
Chasing a gold economy that tells the truth

The long, humbling story of teaching Dota Captain's match engine that gold is a finite, earned, map-gated resource, one broken scoreboard at a time.
There is one part of this project I have rewritten more than any other, and it is not close. Early on, gold and XP in my match engine basically appeared out of nowhere. I would open a simulated game to check something unrelated and find a support sitting on the same net worth as the hard carry, or a hero who had died nine times somehow leading the scoreboard in gold. Every single time, the feeling was the same. That cannot happen in real Dota. I have spent weeks chasing an economy that tells the truth, and I want to be honest about how messy that road has been, because it is still an approximation and I am still getting parts of it wrong.
Gold does not come from nowhere
The core idea I kept failing to respect is simple, and any Dota player already knows it in their bones. Gold is finite. It is earned, and it is gated by map control. There is only so much on the map at any moment, and getting it means being alive, being where the farm is, and taking last hits before the other team does. My earliest sim did not model any of that. Numbers just ticked upward for everyone, so the scoreboard read like a game nobody actually played.
The first real pass at this, back in 0.3.0, was a major overhaul of XP and gold pacing so that XPM, GPM, and lane income tracked closer to real games. That helped the overall shape, but it was still treating gold as a rising tide that lifted every hero more or less equally. It made the totals look plausible from a distance while the individual stories underneath stayed wrong.
I benchmark all of this against real match data from OpenDota, which is the closest thing I have to ground truth. That is worth saying plainly. The sim is not real Dota and never will be. It is a model I keep nudging toward what the real distributions say, and OpenDota is the ruler I hold it up against.
Not every hero farms the same
Once the totals looked reasonable, the individual heroes still did not. The thing that bugged me most was off-meta cores keeping pace on net worth without earning it. In real Dota, a hero's farm identity matters enormously. Some cores are built to sit in a lane and convert it into gold. Others rely on kills and tempo and simply do not out-farm a dedicated carry from creeps alone.
In 0.4.2 I taught the sim to respect that. Cores with low or medium farm reliance now earn less from the lane, so an off-meta farm hero can no longer quietly keep up on net worth without actually getting kills. If you want to be rich on a hero that is not a natural farmer, you have to go make plays. That is how it works in a real game, and now the scoreboard reflects the choice.
This is the transferable idea underneath the change. Farm is not free real estate you get for picking a core. It is a role. A hero's kit and its reliance on the lane decide how much of the map's gold it can realistically claim, and everything else has to be earned through fights and space.
Stopping the scoreboard from lying
A few of the ugliest bugs were about totals that inflated beyond what heroes had actually earned. In 0.4.9 I stopped team net worth on the scoreboard from ballooning above the sum of what the individual heroes made. I also changed how gold accrues between fights, so it ticks up gradually the way passive farm does instead of jumping in one suspicious spike. And I made sure position 4 supports stay poorer than offlaners, because the roaming support being richer than the offlane core is exactly the kind of thing that made me distrust my own tool.
In 0.5.6 I went after how gold turns into strength. Before, net worth converted into fight power in item-tier steps, which meant a hero could sit at an awkward breakpoint and feel wrong. Now net worth scales strength continuously, so a gold lead converts smoothly into being stronger in a fight rather than lurching upward when an imaginary item completes.
The same version added two ideas I care about. Three greedy cores in one draft now share a limited farm pool, so a triple-carry lineup earns less overall and spikes later, which is the real tradeoff of that draft. And map control earns passive gold that tapers off once a lead is already decisive, because in a real game a crushing lead stops compounding infinitely once the other team just stops contesting.
Kills, deaths, and denies finally mean something
The 0.6.0 update was the big one, and it was mostly about making death and dominance actually cost something. Kills now grant XP the way Dota does, a bounty of 100 plus 13 percent of the victim's total XP, so the team getting the kills genuinely out-levels the team that keeps dying. Heroes also got a creep score now, real last hits, where cores last-hit the most and supports far less, and a team starved of map control simply farms fewer creeps.
Denying finally matters too, which I am oddly proud of. A hero who wins their lane denies creeps to starve the loser's XP, so a stomped lane falls a step behind. I kept it bounded on purpose, a nudge and not a death sentence, because a lost lane in real Dota is a disadvantage, not an automatic loss. And dying now costs net worth, not just respawn time. A dead hero earns none of the farm they would have gotten, and that gold flows to teammates still farming. So a core that feeds is not just wasting its own time, it is falling behind its own team while the enemy pulls ahead.
Kill gold got shaped like Dota as well. The killer of a higher-level or streaking hero earns a bigger share, and assist gold scales with the victim's net worth and a comeback factor. That last part matters because it means killing the fed enemy carry pays out more than farming ten creeps, which is the whole reason you group up and hunt in the first place.
Supports, levels, and knowing when to stop
The carry-to-support gap was one of the last things I fixed in 0.6.0. Supports now earn a realistic amount of gold, inside the bands I see for real high-MMR games on OpenDota, and critically that gold is drawn off the farming cores rather than conjured up. That closes the carry-to-support ratio toward what real games actually show, instead of everyone drifting rich together.
I also had a long-running problem where heroes over-leveled. My carries were maxing out at level 30 in games where a real pub carry would not. So I pulled the XP economy down toward the real median, and now a 50-minute carry lands around level 27 or 28 instead of hitting the cap. It is a small number on a scoreboard, but getting it wrong made every late game feel slightly fake.
Finally, I taught decided games to behave like decided games. A losing team keeps farming safe corners late while the leader groups up to close, so the net-worth gap stops ballooning to cartoonish extremes. Comebacks stay possible but bounded. I want to be clear that none of this is finished. The engine is an approximation, I benchmark it against real data and it still misses, and I will almost certainly rewrite parts of this economy again. But it lies to me a lot less than it used to, and for a scoreboard, that is most of the job.