CITIES OF THE AEGEAN
an ancient Greek city builder

Full granaries, starving citizens

29 July 2026 · Devlog · Reading time about 8 minutes

Four separate bugs in one food system, each of which produced the same symptom: a city dying of hunger with more than a thousand units of food in storage.

Cities of the Aegean simulates food the way the Impressions city builders did. Farms produce it, carts haul it to granaries, market vendors carry it out to houses, and houses eat from their own pantry. Nothing is teleported. Every unit of grain is somewhere specific, being carried by someone specific, and that is the whole appeal of the genre.

It is also why the failure mode is so counter-intuitive. In a game where food is a global number, you cannot starve while the number is high. In a game where food has a location, you can starve two hundred tiles from a full granary, and the player has no idea why.

Farms, granaries and agoras in a city builder game, with cart drivers hauling the harvest along the roads into the city
Every unit of food in this picture is in a specific place, being carried by a specific person. That is the appeal of the genre and the source of all four bugs.

We hit that four times, for four unrelated reasons.

1. The fast-forward famine

The first one only happened when players used the speed controls.

Cities were dying with 1,500 food banked, and only at triple speed. At normal speed the same city was fine. That is a strange bug report to receive and a very good one to get, because a symptom that depends on the speed multiplier narrows the search enormously.

The cause was that periodic checks — dispatch a vendor, send a cart, re-evaluate coverage — were gated on tick counts rather than on elapsed game time. Something scheduled for "every 60 ticks" fires at a fixed real-world rate. But at triple speed, three times as many game days pass between those firings. Vendors were being dispatched five times less often per game day, while the citizens went on eating at the normal per-day rate.

The fix was mechanical: route every periodic check through a single day-gate helper that triggers on accumulated game time. The rule that came out of it is now written down for future work. If you add anything that happens every N of something, N is measured in game days, never ticks.

2. The ledger that lied

The City Ledger has a Food section, and it was reporting nonsense.

A city of about 6,000 citizens, with 4,700 food in store and the number climbing, was being told it was running a deficit of 34 food per day. Both the stock and the flow were visible on the same screen and they contradicted each other.

The ledger computed consumption as population multiplied by the daily ration. The simulation did not. In the simulation a house eats the smaller of its pantry and its ration, because a household with an empty pantry eats nothing at all. It just accrues hunger.

In this city, 39% of the population had empty pantries. The ledger was charging those people for a meal they never got, and the size of the phantom deficit was exactly the size of the distribution failure.

The interesting part is what we did with that. The obvious fix was to clamp the ledger to the pantry so the number matched reality. But throwing away the demand figure would have discarded useful information, so the ledger now shows both: Needed per day, which is what the population would eat if everyone were served, and Eaten per day, which is what actually went into mouths.

The gap between the two rows is the distribution failure, stated numerically. And it points the player at their markets instead of at their farms, which is where the actual problem is. A warning that reads "you need more food" sends people off to build farms they do not need.

3. The market throughput ceiling nobody could raise

This is the one that changed how we think about the game.

Olive groves and an olive press in a Greek city building game, the oil chain that feeds house evolution and export trade
Olive groves and a press. Oil is the first good that houses want for its own sake, and the first that a broken supply chain visibly starves them of.

Markets in Cities of the Aegean are called agoras. An agora sends runners to granaries and storehouses to stock itself, then sends vendors out along the roads to deliver to houses. We measured what one agora could actually sustain and got 3.7 food per day, which supports a few hundred citizens at most. That felt low.

So we raised the carrying capacities. The amount a supply runner could fetch. The amount the agora could hold. Nothing changed. Not a little — nothing.

When you raise a limit and throughput does not move, that limit was not binding. We instrumented it and the numbers were unambiguous: supply runs were averaging 32 units against a cap of 60, and agora stock was sitting at 14 against a cap of 110. Both caps had metres of headroom. The constraint was somewhere else entirely.

It was concurrency. Each agora had a single runner slot shared across every commodity it stocked — food, olive oil, wine. Whenever the slot was occupied by a run hauling oil, the bread stall could not restock. And because the round trip to a granary takes real game time, that slot was busy a lot. 38% of all supply runs were fetching oil and wine, and the food shelf was empty 81% of the time.

The round trip was the ration. That was the insight. The agora's throughput was not set by how much a runner could carry, but by how often a runner could be walking at all.

Giving each commodity its own runner slot took the same agora from 3.7 to between 6 and 7 food per day — roughly 380 citizens, or six fully grown estates. And we deliberately stopped there rather than pushing it higher.

A market that serves 380 people means a city of 4,000 needs ten markets, spread through its districts. That is not a limitation. That is the game.

Market coverage pressure is what makes city layout matter. Remove it and you have a game where you build farms and watch a number rise.

4. The death spiral, and the valve we added for it

The last one was not a bug. It was a design failure, which is worse.

Play-testing kept producing cities that oscillated to death. A district loses market coverage. Its houses run out of food. Hungry citizens abandon their homes, so the population falls. The population falling means fewer workers, so the farms and the markets lose staff. Understaffed markets serve even fewer houses. Meanwhile immigration is frozen, because the game will not admit settlers into a city that is visibly starving.

The city cannot recover, because every path out of the hole requires the workers it just lost. And the whole time, the granaries are full. There is grain a two-minute walk away and the simulation has no way for a hungry family to go and get it.

So we gave them one. A house whose pantry has been empty for several days now sends out its own runner to the nearest granary holding enough stock, and brings back a few days' rations. The countdown to abandoning the home pauses while that runner is out. Nobody walks away from a home while there is reachable food.

The problem with a valve like this is obvious the moment you build it: if subsistence is free, why would anyone build markets? A city of foragers would be perfectly viable and the entire market layer becomes optional.

So foraging has teeth. A pantry filled by the household's own runner is flagged, and that flag blocks the house from growing until a real vendor next serves it, so a market-less city stays huts forever. Worse, neglect accumulates the whole time a house is living on its own runs. Past a threshold, a homestead or better stops counting as supported and begins to decline: it loses rank, it loses capacity, and it loses the taxes it was paying.

Subsistence keeps your citizens alive. It costs you your city's rank.

That detail had to live on its own counter rather than on the hunger clock, which took a couple of attempts to get right. The hunger clock resets on any delivery, including a forager's, and it gates the starvation mechanic. Bleeding decline pressure through it would have re-armed exactly the spiral the valve exists to prevent.

What the player sees now, when a district loses its market, is strain rather than collapse. Runners on the roads, hunger bubbles, stalled growth, houses quietly slipping a rank, immigration flickering. All of it legible, all of it recoverable, and all of it pointing at the thing that is actually wrong.

The thread running through all four

Every one of these produced the same screen: a full granary and a starving city. The causes were a scheduling bug, a reporting bug, a concurrency bottleneck and a missing feedback valve, and they have nothing to do with one another.

What they share is that the simulation was right and the player could not see why. The food was where the simulation said it was. It just could not get where it needed to go, and nothing on screen explained the difference between having food and delivering it.

Most of the work in a game like this turns out to be that. Not making the simulation correct, but making a correct simulation legible enough that failing at it feels like your fault.

If you want the player-facing version of all this, the beginner's guide covers what to build and in what order.

All of the above, running in a browser tab.

Found a city

The tutorial is free with no time limit. No download, no account.