← Dev Log
Building a Cannon Fodder style browser game with AI in ten days

Building a Cannon Fodder style browser game with AI in ten days

building with AIClaude Codebrowser gameCannon Foddergame developmentAI harness

This dev log is about Inselnova: one island, sea wars and alliance politics in a world that never resets. Play free →

TL;DR: On a Saturday night I typed one prompt into Claude Code asking for a Cannon Fodder prototype, and by Sunday lunchtime it was deployed on Render. Ten days later it’s Boots & Bullets, a top-down squad shooter with 50 campaign missions, a zombie horde mode, two-player multiplayer and its own analytics, at bootsandbullets.com. The point was to see whether the way I work on Inselnova transfers to a game that looks nothing like it, with none of Inselnova’s tooling to lean on. It does, but the harness had to be built again from nothing, and about half the ten days went on that.

Play it here, free, in the browser: bootsandbullets.com

One prompt on a Saturday night

Inselnova has an AI harness that has grown since February. Skills, hooks, gates, tests, a release process, a hundred small rules that each came out of a bug. I’ve never had to build it twice, so I didn’t know whether it was the method or just the scar tissue of one project. A second game, as far from an island strategy game as I could get, was the cheapest way to find out.

The prompt went in at ten on Saturday 30 August, typos included:

i want you to build me a prototype of the old classic game cannon fodder

you will setup..

docs/
game/

it will be using a slim nodejs server
it will use svg or sprites, if you can find some sprites that'll be better
it'll have a basic map specified in a data directory as some sort of ascii file
i will be able to move a group of army guys in a herd
they won't overlap with each other
they won't be able to walk through map elements like trees
i will control with my mouse
i will click to move
when i click on an enemy they will move within radius and shoot them
the enemy will try and shoot me
our group can get shot
when all of them are shot then the game restarts
if i kill the last person the game says well done and option to restart
the game should be fluid and the screen will scroll around
it will take up most of the screen
the soilders will be small, and feel fast to move around

the map will include trees, a river, some huts, a pick up crate, some enemies to shoot

--

you will first RESEARCH the game
the mechanics
the movement
see if there are any established clones out there you can get ideas from

break down the code into like.. troops.ts enemies.ts map.ts

etc..

I went to bed.

By seven the next morning there was a first commit. Three prompts later I’d asked what the original had that this didn’t, then for a level generator, an intro screen and better graphics. By half ten on Sunday it was on a Render URL. That evening I renamed it Boots & Bullets, because Cannon Fodder is someone else’s name.

The other nine days were polish, and polish is where all the work is.

What it is now

It’s a demo. That stops me building feature after feature and gets it in front of people sooner. It’s also a desktop browser game, not a phone one, which opens a door Inselnova never had: Steam. Nobody wishlists a slow browser strategy game. A chaotic little shooter with a horde mode might be different.

Campaign missions50, across three zones (Jungle, Desert, the Frozen North)
Difficultythree rungs, but 22 separate levers underneath them
Multiplayertwo players over a shared link, four skirmish grounds
ChallengesThe Herd, 300 zombies on screen, score is how long you last
Attract modethe intro backdrop is two AI sides fighting each other, live, plus a chicken that pecks
EconomyWar Bonds, spent in an Armoury on guns, throwables and call-ins
CharacterMajor Trumper, an officer who is certain, wrong, and nowhere near the fighting
Analyticsits own package, one dependency, counting people rather than events

The Boots & Bullets front screen, with two AI sides fighting behind the menu The front screen. The battle behind the buttons is live, green against blue on one map, and the chicken is a third side that pecks. The score across the top is real.

Three hundred zombies crossing open ground towards the squad in The Herd The Herd. Three hundred of them on screen at once, from three sides and never the south, so you can always run.

The Herd is the first of what I want to be a lot of challenge maps, and they’re there for two reasons. One is video. Inselnova is nearly impossible to make a video of. I’ve seen strategy games try, and the footage is never really in the game, and I think players feel cheated when they arrive and it looks nothing like the clip. Three hundred zombies pouring at six men is a clip. The other reason is that it made me and the AI optimise for a lot of things on screen at once, which the campaign never forced.

One rule shaped everything. The game has one runtime dependency, ws for multiplayer, and one asset file, the menu music. Every sprite is plotted into a canvas at boot from code. The terrain is derived from a one-character-per-tile grid. The sound effects are synthesised with WebAudio. The constraint makes the AI draw, and drawing is where it’s weakest.

A village mission: river, plank bridge, thatched huts and enemy soldiers, all plotted from code Village. Every pixel here is drawn by code at boot: the river, the bridge, the huts, the men. No image file is loaded.

Trumper came out of a brief that said “a bit rough, silly, stupid, I like dry comedy like Sean Lock”. The AI turned that into the best rule in the docs:

If a line would work with a drum sting after it, it is the wrong line.

Move as a herd and use the trees. I hid in some trees in 1961. Nobody has found me since, in a sense.

Major Trumper's comms panel over a mission, mid-briefing Trumper on the comms panel. The portrait is one of the four things in the game that was imported rather than plotted, after the plotted face was rejected.

The comms panel he talks from exists because a friend sat down at a Mac and couldn’t work out how to fire. A new game is the first time I’ve had to solve onboarding from zero rather than patch it.

The harness, again

Nothing came across from Inselnova by copying files. I pointed Claude Code at the Inselnova repo and told it to look at what that game had that this one should. That’s how the analytics package, the release command and the changelog format got built, and each time it copied the shape and rejected the size. Inselnova’s release process is described in the new docs as “not one command, it is a department”.

There are 17 skills after ten days. Two of them, /commit and /release, I asked for on the first morning. The other fifteen exist because a session did something wrong, or did the same thing twice, and I told it to write down how to do it properly. If you’re starting a project with an agent, the skills start on day one, and by the end of the first week their shape decides whether the agent is getting faster or slower.

SkillWhat it doesWhy it exists
/commitreviews the tree and commits in the repo’s voice, staging by namemore than one session edits the tree at once, and git add -A shipped another session’s files under my subject
/releaseships main to Render and proves the deploy is livea green dashboard can’t tell a new build from the old instance still serving
/specsplits a raw brief into one file per issue, with questions for me and a ledgerone long spec file meant items in the middle got skimmed and silently missed
/gauntletthe build-and-critique loop against a reference image, objective and metric fixed before round one“make it look more like the original” is an adjective, not a target
/grillone round of that: capture a screen, hand it to a blind subagent, take back the single largest gapthe agent that drew the thing may not judge it in the same session
/stylethe visual vocabulary: which greens, where the light comes from, how thick an outline issettles “does this look like our game” without arguing from taste
/pixel-checkchecks drawing code against the laws: no anti-aliasing, no alpha, no gradientsone soft edge in a dithered frame reads as a different game pasted in
/pixelatemeasures a reference image into plottable pixels and puts our sprite beside it at the same scalesprites were being drawn three times from guesses at the size
/spritesopens a live gallery of every baked sprite, deep-linkablethe only way to look at a sprite without making the game show it to you
/playtestlaunches the real game in a browser and drives itseveral bugs were invisible to every other check
/mapwrites one mission by hand as a data module, from an idea rather than a seedthe generated campaign needed a few places that were designed
/arenaworks on the CPU-vs-CPU mode, proved with a headless soak rather than a screenshotfour of five arena bugs were invisible for the first thirty seconds and obvious in a five-minute run
/multiplayerloads the one rule that decides where code goes across the wire, and the four bugs from not having itfour issues in two briefs were the same mistake made without it
/speakersMajor Trumper’s register, what he may never say, how to add a second voicea line that works with a drum sting after it is the wrong line
/image-promptwrites a prompt for an external image generator that comes back in the game’s stylethe house style is a paragraph, and retyping it drifts
/workthe work packages: capture, start, park, finish, reportthe directory an item sits in is its status, so any session can pick it up
/improveturns this session’s mistakes into rules and compacts what’s already thererun at the end of every piece of work, or the next agent pays for it

About half have an equivalent in Inselnova’s harness under another name. The other half are only here because this is a shooter with hand-plotted pixels. A strategy game never needed a rule about outline thickness.

/work and /spec are the loop the whole ten days ran on. I’d play the game with a briefing.md open and type every problem as I hit it, one thought per paragraph, separated by a line of dashes. At twenty or thirty I’d run /spec. It checks every claim against the code, then fans the one file out into one file per issue, a questions file for the decisions only I can make, and a ledger. The agent works through them one at a time, each fixed with a Playwright check or a headless run before it moves on. The biggest brief became 42 files. The QA ones ran 26 to 35. Thirty-eight packages are finished.

A lot of the pushing happened from my phone. Claude Code’s remote control opens a running session, and I used it to review and nudge, not to start anything. Read what it did, answer its question, tell it to carry on.

The docs outgrew the code. 58,000 lines of TypeScript, 80,000 lines of markdown. Every rule in the rulebook has two lines under it: what breaks without it, and what enforces it. Where the second says “nothing”, that rule will be broken again.

Multiplayer was a little tricky

Multiplayer wasn’t in the plan. The AI told me, more than once, that a two-player mode would turn a week into a month. I did it anyway, because the only way a game this size gets seen is one person making a room and sending the link to a friend. The basics took about an hour and the AI wrote all of it. What it got wrong was one design decision, and finding that took longer than the code did.

The multiplayer lobby: create a public or private game, or join with a code The lobby. A private game gives you a code to send to a friend, which is the whole reason it exists.

I keep a Codex session open about the game. It has no access to the code, which is the point. It’s somewhere to bounce ideas without the answer being shaped by what’s already built. Multiplayer got planned there. Claude Code corrected the plan against the code, dropped the Colyseus dependency in favour of ws and its own rooms, noticed the schema had forgotten to hash the credential, and built it. I tested it on 3 September. The shared link didn’t work, I couldn’t click to shoot, and I couldn’t pick anything up.

Each fix held, but the shape of the problem took two days to name. The server runs the real simulation and the client holds a puppet world that’s told what happened. Every new thing in the game needed a second edit in the network code to make the puppet show it, and every time that was forgotten it failed silently:

  • A barrel exploded on the server and did nothing on the client.
  • A pickup sparkled in the wrong colour.
  • The “+2 GRENADES” label never appeared.
  • Bullets crawled, because their position was copied every fourth tick and held still in between.

A barrel explosion four frames in, the crate beside it untouched The explosion, four frames in. On the server it always happened. On the other player’s screen, for two days, it didn’t.

Claude had also got confused about which player was which, and that went over to the Codex session for a second opinion. On 5 September I asked the question that fixed it:

If a barrel explodes when hit by a bullet in single player, why would that be any different in multiplayer?

Then: is this the industry standard way, will new things work in multiplayer automatically, and no shortcuts. The answer is one sentence at the top of the multiplayer doc. State is corrected, events are replayed, and the client simulates whatever doesn’t decide an outcome. An effect without a replay is now a compile error.

It should have been the design from the first day. Opus 5 did a decent job of everything else on a fresh project. This was the one place it built the wrong thing confidently.

Two things I only found out by measuring

Where the time went. One long session, timed from its own log: a tenth of its tool calls took five times longer than the other nine tenths put together. The slow calls were the same two things, the full browser playtest, over three minutes, run 47 times in a session that made nine commits, and the full check, run over a hundred times. Every run after the first was re-asking a question that had already been answered. The rule now is to run the nine-second check while you work, run the gate once before the commit, and keep its output.

And a rule that prose couldn’t hold. Every session was told, in the project file and in its own memory, to write files with the editing tools and never with a shell heredoc, because the shell eats backslashes and dollar signs silently. It was broken about thirty times in eight days. Every session that broke it said so at the time:

exactly what my notes warn about

One wrote a control character into 65 files at once. Claude Code’s auto mode injects an instruction mid-session, long after the project file was read, telling the model to prefer sed and heredocs. A rule the model has to remember loses to an instruction it has just been handed. So the rule is a hook now, with sixteen tests. The harness is the bit that doesn’t need to be remembered.

Some numbers

From the transcripts. 62 sessions, 635 MB, often three or four open at once on different work items.

Calendar days10 (30 August to 8 September)
Elapsed, first prompt to now207 h
Agent activity, idle gaps removed123 h
Busiest day4 September, 16 h
Commits721
Things I asked for411
Tool calls the models made26,560
Times I interrupted it35
Screenshots I pasted in37
Context compactions16
Plan mode6

That’s 65 tool calls for every request, against about ten on the last job I costed. The difference is the harness. A request here runs a type check, a test file, a headless soak of the campaign, a playtest section, a screenshot diff, and only then reports back.

ToolCalls
Bash18,01867.8%
Edit4,30816.2%
Write1,9787.4%
Read1,5645.9%
Grep1890.7%
Skill1280.5%
Agent1180.4%
everything else2571.0%

Writing and editing files is a quarter of it. Two thirds is running things and reading what came back.

The 123 hours are not me at a keyboard. This was an evening project. I have my normal work in the day, and in the evening I’m usually still doing work things with one set of agents while juggling another set on the game. Most of the 411 requests were typed while playing.

Opus 5 and Fable 5.1

Opus 5 did 77 percent of the turns, Fable 5 and 5.1 the rest, mostly the later polish.

Opus 5 is good on a small project, and this was a small project for the first few days. Once the specs got to twenty and thirty files it started falling short, and the way it falls short is that it doesn’t like reaching the end. It’ll get two thirds through a big spec and stop to ask me a question it could have answered itself, and I have to kick it along. The /goal command helps. You give it the finish line and it won’t let the session stop before it gets there.

Fable 5.1 is fantastic. It specs quickly, it works through the entire thing, and it doesn’t stop to ask. It still has no design taste, but neither does Opus, and Fable is fast and gets the job done. I wish I could have it all the time.

The design taste problem showed up the same way with both. Every time I added something to the game, Opus decided the mission success screen needed to show it too, and that screen turned into a pile of everything the model thought a player might want to know. It’s AI slop, in a UI. A decent slice of the ten days went on removing things the AI had added because it thought they’d be helpful. The win panel now says six things, in my order.

The mission accomplished panel: result, squad, four stats, stars, three buttons The win panel after the cut. Before it, this card also carried a “fastest” ribbon, a second clear ribbon, a lost-men row, accuracy and best-time suffixes, an itemised bond tally, a “not a scratch” line and a promotions roll.

What it cost

I paid $200, the Claude Code Max subscription for the month, shared with Inselnova. Priced on the API:

Tokens
Fresh input418,571
Cache writes165.3 M
Cache reads17.7 B
Output48.8 M

At $5/MTok in and $25/MTok out, with cache reads at a tenth of the input rate, that’s about $11,100. Priced as fresh input it would be $90,500, so long sessions only exist because of caching. Output, meaning every line it wrote, is 11% of the bill. 80% is the model re-reading the conversation.

What I learned

The method transferred. The harness didn’t, not as files, and I no longer think it should. It’s cheaper to point an agent at the old repo and say “look at what that has and decide what this needs” than to port a department.

  • Opus 5 is still good, but it’s annoying to talk to.
  • Fable 5.1 is still fantastic, and I wish I could have it all the time.
  • Harnesses and custom skills take almost no effort to build, and they work. Seventeen in ten days.
  • Ignore the advice the agents give you about scope. Multiplayer took about an hour to get the basics in, and if the game does spread it will be through that invite link. You lead it, not the AI.

There’s more character to add, and a lot I’ve learned about hooking people from Inselnova that isn’t in here yet. I’d rather find out what people think of it now, and whether the Steam door is real. It’s free and it runs in the browser.

bootsandbullets.com