Ecru GamesDevlog › Exponential cost, linear benefit

Exponential cost, linear benefit

A player wrote: "giving the factory 350 million and still not getting a 1k upgrade, it goes 122, 123." He was right, and the arithmetic behind him was worse than he knew. This is the same balance failure found in four separate systems of one game, with the numbers from real saves.

Ecru Games developer

Cotton Tycoon is an incremental game about a textile business. Almost everything in it can be upgraded, and almost every upgrade price is a familiar exponential: base price times some step to the power of the level. That curve is standard and it works, right up until you check what it is buying.

In one evening I found the same root cause in four unrelated systems. In each one the cost curved upward and the thing it purchased did not.

SystemCostBenefitResult at level 31
Storage1.20n1.12nUnit of capacity: 54 lira → 737 lira
Factory1.55nlinear4.10 billion lira buys +3.2%
Order demandscaled to storage (exponential)production is linearOne order wants 16.5 minutes of output in a 12-minute window
Offline earningsfull expensesincome cut to a thirdNet result is always zero

The storage row is the one that shows the trap cleanly. Both sides are exponential, and the base differs by only eight percentage points. At level 5 nobody could tell. At level 31 a unit of storage costs fourteen times what it did, which means that buying cotton on the open market is cheaper than building somewhere to put it.

Why nobody notices in time

This class of bug is invisible during design and invisible during testing, because you test the first ten levels. Everything is proportionate there. The gap opens later, quietly, in the part of the game only a fraction of players reach, and those players do not describe it as a curve problem. They describe it as "the upgrades feel fake" or "money has nowhere to go", and it is easy to answer the wrong complaint.

The check that would have caught all four: when you write a cost curve, write down the base of the benefit curve next to it and evaluate both at levels 30 and 50. A difference of five percentage points in the base is a factor of four by level 30 and a factor of twenty by level 50.

Softening the cost, and why that was only half

The first fix kept the exponential where it was doing useful work and handed the rest to a polynomial. Below the knee the price is bit-for-bit identical to what it was, so no existing player sees a change in the range they are playing. Above it the curve stops running away: level 31 went from 4.1 billion to 30 million, level 50 from 17 trillion to 209 million.

That fixed the price. It did not fix what the price was buying, and a few weeks later the same complaint came back from a player at a much higher level. The production rate itself had been linear since the day it was written. Here is what one percent of line speed actually cost:

Factory levelOne level givesCostPer 1% of speed
10+9.6%207 K lira21 K lira
56+1.8%140 M lira79 M lira
120+0.83%1.02 B lira1.23 B lira
468+0.21%35 B lira164 B lira

So the benefit curve got the same treatment as the cost curve: linear below the knee, polynomial above it. Measured against real saves, a level 9 factory is unchanged to the digit, level 30 gains 13%, level 56 gains 75%, level 124 triples and level 468 multiplies by 7.8.

One thing this does not fix, and cannot: the percentage a single level adds keeps shrinking, because one level's share is the curve divided by the level count. If you want a constant percentage you need fewer, larger levels, which is a different design with its own migration problem for existing saves.

The bill did not read the new curve. Electricity demand was computed from installed buildings, so a knee that got more output from the same machines nearly tripled demand on one save, from 33,997 kW against a supply of 43,223, to 95,862. The patch meant to make upgrades feel worthwhile would have pushed that farm into a brownout and lowered its production. Before you grow a production number, grep for everyone who reads it. One of them is issuing an invoice.

A cap is a curve too

The third shape of this problem is a ceiling that was written as a constant. A facility that multiplies output had its cap raised in two steps, at level 20 and level 30, and then stopped forever. One player had taken that building to level 21: earned a multiplier of 6.76, received 3.00. More than half of the money spent bought nothing at all, and because that building was the only multiplier on the fabric line, their complaint of "I cannot increase fabric production" was literally accurate.

Worse, some of those ceilings lived inside the formula rather than in the shared cap table, so the panel never printed "maximum" and the purchase was never refused. The money left the account and nothing moved. A player who had read the documentation reported it: "no matter how much I upgrade, the current value does not increase."

Caps now scale with the player instead of with a table. They are identical at the two levels the old steps named, they do not bind at all below level 10, and they no longer stop.

If a card promises something, the loop has to run it

A repeatable upgrade advertised "+10% output, every time". The code added ten percentage points per purchase rather than compounding them, so the twelfth purchase delivered +4.5%. This is not a balance disagreement. It is the interface announcing a number that the simulation never executes.

The same failure in another place: an offer card multiplied a bonus by a hard-coded 6 and 4, written when both multipliers were linear. After one of them was capped, that card would have told a player with 1,141 prestige points "+61,104% production" where the true figure was +0%, because their production was already at the ceiling. Cards now ask the real formula by borrowing the level, calling the function the simulation calls and putting it back.

Two exponents that cancel look like a flat line

The last shape is the sneakiest, because a suppression that is working can still be wrong. Levelling was already dampened by a square root, and it still felt like it was accelerating. A player said so in the chat: "I'm 295 already" seventeen minutes after being 287.

Payout across 109 saves grows as roughly L4.15. The square root turns that into L2.07. A level costs about L2. The two exponents cancel almost exactly, so the level rate never falls: across 89 saves the levels per delivery were flat from level 34 to level 527. What changed was not the rate but the frequency, as three delivery channels started overlapping.

The right question was never "did the suppression stop the runaway". It was does the rate fall as the level rises, and the answer was no.

A fix is measured by what it does not do

Every one of these changes was checked against real saves for the case where nothing should happen, and that half of the table matters more than the other half:

If a rebalance changes the numbers for a new player, it is not a fix for late-game inflation. It is a nerf that happens to include one.

Play Cotton Tycoon