Zeus: Master of Olympus, running in a browser
Zeus: Master of Olympus, playable in a browser, with new content and a difficulty + rewards system that reads your city.
Zeus: Master of Olympus is a city builder Sierra shipped in 2000. eZeus is Maurycy Liebner's open-source reimplementation of it in C++. This post talks about how a factory of AI agents 1) brought eZeus to WebAssembly so it runs in a browser and 2) expanded the game itself, with new content and a difficulty + rewards system 3) Learnings/Takeaways
Disclaimer: My writer agent wrote the first draft of this post. I wanted to be upfront as it matters for how you read the rest. Secondly, this work has no affiliation with Activision or Sierra. Nothing from this effort is up for sale. The engine is eZeus by Maurycy Liebner, GPL, and everything above sits on top of it. Nothing is hosted anywhere to click into, so playing it means owning a copy of the original.
Motivation
I have been nostalgic for quite a few games (from the early 2000s) to be playable on the iPad. Long flights, by nature, are painful -- thought I would use this opportunity to get Zeus, a game I cherish from my childhood, to be playable on the iPad.
I kicked off my first prompt from a lounge at SFO, and by the end of the flight I had it running offline on the iPad.
How it works
What had to change in the engine before a browser can drive it, and how the agents doing the work are organized.

Since I wanted it playable in the browser, everything gets built to WASM. That was not straightforward. The main loop is inverted, so the browser drives the engine now rather than the engine owning the loop, through emscripten_set_main_loop_arg at its native 20fps clamp. Threads came out entirely, because they want SharedArrayBuffer, which wants COOP and COEP headers, and that chain is the fastest way to lose iPad Safari.
A codebase from 2000 also still calls fopen on paths it expects to find, so the filesystem is built in memory at boot and the save directory is mounted to IndexedDB. The map generator is dropped under Emscripten, which upstream already excludes everywhere but Linux.
The engine compiles to a 13MB wasm binary, 4MB gzipped. First load was 490MB of textures, audio and campaign data, now 86MB: gzip at stage time, audio deferred to what the menu needs, and textures repacked to WebP q90 for 61% because gzip saved 0% on them. A reload takes about half a second from IndexedDB with wifi off.
Within an hour I had a scaffold running. That was the easy part. Most of the time went into the factory around it, the infrastructure to build and iterate quickly on a set of ideas before choosing what to promote and what to discard.
First boot

Agent factory
How the work is split up, and what it costs to run.
I spent some time setting up an "agent factory" with defined roles, after the initial scaffold. Work arrives as a 1p brief naming the exact files to touch. Reading the codebase is the expensive part of any task, so one agent spent a session mapping where things live. I didn't want to spend a lot of $s on this project so I had optimized my factory for token efficiency. Briefs quote that map now.
Nothing merges on an agent's word, because an agent grading its own diff grades generously. A harness compiles it, plays the game through the change in a real browser, screenshots what happened and I read that next to the diff.

46 agent transcripts, 1.26B tokens, 96% cache reads.
The art pipeline
Generating the picture turned out to be the cheap part. Fitting it to a twenty-five-year-old art style and a binary format that predates it is the work.

A new sprite sits next to art drawn in 2000 and cannot read as pasted on, so every prompt carries a fixed style block. For ex, Oracle's button plate was sampled from the eleven icons already shipped.
The model is FLUX.2 klein, four billion parameters quantized to 8 bit, driven through mflux at 768x768. It loads, renders a single image and exits, with a guard that refuses to start when memory is tight. Running the model locally means no per-image cost.
Here are a few examples:

Expanding the game
I always wanted more from Zeus. The rewards and the challenges never went far enough, and that is the part I went after first.
Zeus has no intrinsic reward economy: a kill pays no drachmas, and neither does a finished god quest. The shipped paks carry dated events and a table of which one triggers which. Year five brings an invasion because someone typed year five into an editor before the game shipped, and the payout at the far end is a fixed pile chosen the same day. The event fires the same whether your city is a fortress or on fire.
Meet the Oracle

The Oracle is a system that watches your city and decides what it can handle. Every month it reads the place: how big the army is, what sits in the treasury, how much food is in store, whether people are rioting. That read becomes a single number, and the number decides which monster turns up, how much warning you get, and how long the quiet lasts before the next one.
The reward is picked the same way, against whatever the city is short of. In one run a city was sitting on twelve thousand drachmas with an empty granary, so the Oracle promised wheat instead of money. The stronger the city, the smaller the gift, which is what stops a strong city running away with it.

The rest is new content:
- The Akademia, a 3x3 culture building with twelve employees and heavy appeal. I picked a shape with nothing novel in the simulation on purpose, to find out what the twelve-file checklist really costs.
- An eighth housing tier above vanilla's seventh, the Philosopher's Villa, gated on four culture venues and wine in the house. Common housing refuses wine below level 6, so a block of hovels cannot drain the vendors elite housing needs.
- Orpheus, a ninth hero and the only one who ignores the slayer table. He sets a monster passive on reaching it, then walks back onto patrol. No attack, no corpse.
- The Nemean Lion, an eighteenth monster, Hercules its slayer.
- A sidebar category for the Oracle.

Separately, I decided to add a feature flag system. All of the new capabilities sit behind feature flags, under one rule: flags gate creation, never existence. For ex, turning a flag off stops you building an Akademia and can never make one that already exists disappear.
Learnings
Building got cheap. Deciding what was good did not.
The overall process of developing on an unknown domain and codebase dramatically sped up; however, the cost moved rather than disappeared. For ex, I learnt a little more about how the build process works only to find a bug in the system -- a build with nothing to compile took 224 seconds every time, because docker's --rm threw away emscripten's port cache, so make rebuilt 676 unchanged objects. It is 0.97s now, which took a few cycles to debug.
Separately, generating forty images costs nothing; however, looking at them costs time.
The bigger lever was intuition about which agent to point at what, and which model sits behind it. Fable holds the map of the codebase and writes the briefs. Sonnet takes table-driven work where the brief names the exact lines. Opus takes anything where a wrong guess is expensive, which here means the save format and multi-file C++. Getting that split right moved more than any individual prompt did.
So, what's next
What I want next is a shared map -- cities built by different people on one world, trading with each other, async so nobody waits on anyone's turn. I would start with two players, because two is where the hard problems already show up: whose clock is authoritative, what happens when one city is a fortress and the other is starving, how a trade route survives one side going quiet for a week. The Oracle already reads a single city every month; reading a neighborhood of them is the same idea with more inputs.
That said, this was quite the learning experience for someone who has never built games.