Battle Drones: A 12-Iteration AI-Coded RTS, with Multiplayer Over Sound

Simon Willison built a browser RTS in Claude Code over 321 commits, barely reading any code.
Using Claude Code, Simon Willison took a simple prompt through 12 major versions and 321 commits to create Battle Drones, an RTS playable in mobile browsers. The project includes code-generated 3D models, random maps, six AI personalities, agent battles, and sound-wave multiplayer. The key turning point was v4's "Make it a LOT more fun," which ran thousands of simulated matches in Ultracode mode to redo balance, cutting the stalemate rate from 14% to 0.9%. Technically, deterministic simulation underpins replays and multiplayer, requiring replacements for Math.sin/cos to eliminate cross-browser floating-point differences. The author remains reserved about vibe coding, believing the project isn't yet a serious indie game, but sees a viable path.
Title
Battle Drones: A 12-Iteration AI-Coded RTS, with Multiplayer Over Sound
Meta Description
Simon Willison built the browser RTS Battle Drones with 321 commits and 12 versions: from not fun to "a LOT more fun," then 3D, agent battles, and sound-wave-based multiplayer. This article covers the full iteration path and engineering lessons.
Article Content
With 321 commits and 12 major versions, Simon Willison took a "Red Alert on your phone" from nothing to a playable browser real-time strategy game called Battle Drones. What's unusual isn't the game itself—it's that he barely read a line of code, yet the game now has 3D models, random maps, AI battles, and even multiplayer synchronization between two devices using sound waves.

What a "vibe-coded" RTS can look like
Battle Drones started from a remarkably plain request: build a Command & Conquer-style RTS playable on a phone, with two teams of drones (air and ground) competing for territory and resources. The project began in July using Claude Fable 5, later upgraded to Opus 5.5, and was almost entirely built in Claude Code for Web.
The final feature list is substantial: 9 building types, 7 ground vehicles, 6 air vehicles, 3 infantry types, all as code-built 3D models; fog of war, anti-air/anti-ground weapon distinctions, six maps across five biomes, a random map generator, campaign mode, survival mode, area weapons, supply crates, dynamic music that responds to the battle, six AI personalities, AI-vs-AI spectator mode, a giant "Goliath" mech, variant rules, daily challenges, achievements, and an LLM-vs-LLM agent battle mode.
One point the author stresses repeatedly: this isn't the kind of demo that "looks like a game but is boring to play." By his own admission, this one is genuinely fun.
From v1 to v12: key turning points in the evolution
v1–v3: It runs, but it isn't fun
The first version was built on the Phaser 2D framework. The author handed Claude an OpenAI API key and had it call an image-generation API to produce sprite art. The result was a prototype you could recognize as an RTS—building systems, unit commands, and a basic AI—but the visuals were rough and it was no fun to play.
By October, after upgrading to Opus 5.5, a single prompt—"substantially improve this game, make both the visuals and gameplay good, redraw assets with the latest image API, add new units, new buildings, and more varied terrain"—produced five distinct maps and a fully redrawn set of sprites. The visuals finally looked like a real game, but the author's assessment remained sober: still not fun; you get bored after a few minutes.
v4: "Make it a LOT more fun"
This is the most interesting step in the whole project. The author had long held the view that coding agents can produce "game-like things" but not genuinely addictive experiences. He decided to give the model a chance and typed the prompt on his phone that would later be quoted repeatedly:
This game isn't fun enough yet. Make it a LOT more fun.
This time he ran it in Claude Code's Ultracode mode—according to the official docs, it orchestrates a large number of sub-agents in parallel via a JavaScript script. He started it in the evening and only got a playable result the next morning.
The outcome exceeded expectations. Claude wrote its own release notes, and the core of them was numerical: across 1,200 AI-vs-AI test matches on Normal difficulty, the share of games still undecided after 25 minutes dropped from 14% to 0.9%; the share of factions trailing by more than 800 scrap that came back to win rose from 24% to 46%. In other words, the game went from "easily dragged into a stalemate" to "the momentum swings back and forth." According to the author, much of the time was spent because Claude ran thousands of simulated matches to tune balance.
Ultracode mode is a high-intensity execution mode offered by Claude Code. Its core mechanism is to orchestrate tasks via JavaScript scripts, decomposing a large goal and distributing it to many sub-agents for parallel execution. Unlike conventional serial conversational coding, it lets the model launch multiple independent work units within a single task—handling sub-problems like numerical tuning, test simulation, and asset generation separately—then aggregate the results. This mode is particularly well suited to tasks that require large amounts of repeated experimentation, such as running thousands of AI-vs-AI matches to gather balance data—serial execution would take days, while parallel orchestration can compress it into a single night. The cost is significantly higher token consumption, and it requires the model to have strong task-decomposition and result-integration capabilities.
v5–v9: Going 3D and a map with a design intent
One prompt—"port this game to 3D using three.js, and make all buildings and vehicles 3D models"—meant another overnight run. By the next morning, all 3D models had been built directly in TypeScript code by Claude.
The author later felt somewhat guilty about this: several consecutive versions were just instructions like "make it look better" or "make it more polished." So v8 produced his longest prompt—designing a map where the relay point can only be captured by airdropping infantry onto an island with Vulture transports. That tropical map, named Archipelago, uses limited harvestable resources and island relay points reachable only by air to force tactical play around air superiority and transport.
v10: The Goliath mech and agent battles
The giant mech's design was a series of brainstorming prompts: first diverge on ideas, then settle on its role as a mobile base—able to receive scrap, build within three tiles around it, and produce infantry; then design a system where weapons fail progressively as it takes damage (mortars first, then lasers, with machine guns always available); and finally decide that it takes two Vultures to lift one Goliath. The result, in the author's words, is "really cool."
The same version also added agent battles: two LLMs obtain information within the fog of war through a tool interface and command troops against each other. The project includes full battle replays, such as a snow-terrain match between Claude Haiku 5.5 and GPT-6 Luna, along with a debugging tool that lets you inspect the underlying model responses. The author hopes to turn it into a league leaderboard someday.
v11–v12: Random maps and sound-wave multiplayer
v11 came about casually: the author noticed his weekly Claude quota was only 75% used with 45 minutes until reset, so he casually asked the model to build a random map generator within the time limit. The resulting maps are rotationally symmetric, support seed reuse, and incorporate river bridges, rocks, forests, scrap, and crystals into generation.
v12 is the most technically novel part—multiplayer over sound. Two devices simply need to be close enough for their microphones to hear each other to synchronize game state. The idea grew out of his earlier Chirp Pong experiment: Claude first built a "radio probe" tool to measure the available bandwidth between the two ends, and after confirming feasibility, implemented a complete acoustic modem system. The author has tested it between a laptop, an iPhone, and an iPad, with good results.
Why sound instead of a server? His reasoning is straightforward: he likes static HTML with zero running costs and doesn't want to maintain a server long-term for a game that someone might want to play at any moment.
An acoustic modem is a communication method that encodes digital data into sound-wave signals, transmits them through the air, and decodes them at the receiving end via microphone. Its basic principle is similar to a traditional telephone dial-up modem: a bitstream is mapped onto audio carriers of different frequencies or phases, and the receiver reconstructs the data through spectral analysis. In a browser environment, you can generate and play audio with the Web Audio API, capture microphone input with getUserMedia, and then demodulate by identifying frequency components via fast Fourier transform. The practical challenges are ambient noise, echo, differences in the frequency response of device speakers and microphones, and sampling offset caused by clock desynchronization between the two ends. Usable bandwidth is typically only a few hundred to a few thousand bits per second, so it is suitable only for transmitting compact streams of action commands rather than full game state.
A few engineering lessons worth noting
Deterministic simulation is the foundation for replays and multiplayer
For replays and multiplayer synchronization to work, the simulation engine must be deterministic. Midway through the project, a subtle issue appeared: different browsers (such as Chrome and Safari) produce extremely tiny differences in the return values of Math.sin() and Math.cos(), enough to make replays desynchronize. Claude's solution was to replace these native math functions with custom implementations.
Deterministic simulation means that, given the same initial state and the same input sequence, the simulation engine produces exactly identical results on any device. It is the prerequisite for replay systems and lockstep multiplayer synchronization: replays only need to store the initial state and the input command stream, and re-simulate on playback; in multiplayer, each side exchanges only action commands and simulates locally, staying in sync as long as the results match. The difficulty of implementing deterministic simulation lies in eliminating all sources of nondeterminism, including random number generators (use a fixed-seed pseudorandom algorithm), the order of floating-point operations, and subtle differences in how different browser engines implement math library functions. Once a single frame drifts, the error accumulates over frames, eventually causing replay desynchronization or divergence in state between multiplayer peers.
Static HTML + WebGL is an underrated game platform
Three.js (and earlier Phaser) are platforms the current models are very familiar with. A side benefit is that Battle Drones unexpectedly became an offline-capable PWA—the author didn't ask for it, but on a plane he discovered his phone had cached it and could play it directly.
PWA (Progressive Web App) refers to a class of web applications enhanced with Service Workers and a Web App Manifest, which can be installed to a device's home screen, run offline, and offer an experience close to native apps. The Service Worker acts as a programmable proxy between the browser and the network, intercepting requests and caching resources locally so the page can still load from cache when offline. For games, this means you can play offline after a single visit, with no app store distribution and no server running continuously. Combined with WebGL's hardware-accelerated rendering, a purely static HTML page can already host a 3D real-time game, with essentially zero deployment cost—just host the static files.
Models can directly generate 3D models and music
Opus 5.5's ability to build 3D models in Three.js was described by the author as "spectacular." Likewise, there are no audio files in the project at all—the soundtrack is entirely code-generated, changes with the map, and intensifies when combat heats up.
Tools are practically free
The radio probe page, model viewer, agent battle debugger, and a batch of tools Claude Code built for itself were all prompted along the way. The author says he hasn't even had time to explore them one by one.
Self-doubt about "vibe coding"
The author's attitude is not one of fervor. He explicitly says he won't submit Battle Drones to events like Steam Next Fest—around the same time, a Hacker News post was discussing players calling for Steam to add a "no AI" filter because such events are flooded with sloppy work. He believes his project's "effort level is still far from enough" to be considered a serious indie game.
But he also believes the path has emerged: this game is fun, looks good, and has a feature he considers a first for RTS—sound-based multiplayer. At the end of the post, he admits he still feels guilty about building software this way: in a field where he has almost no experience, he doesn't feel he "deserves" to make something like this.
This sense of contradiction may be more worth recording than the technical details. Tools lower the barrier to output, but taste, judgment, and the willingness to keep iterating still determine how far the final product can go. As he himself says: he'd love to see what someone with better taste and a strong obsession could build with this toolkit.
One-line Summary
Simon Willison built a browser RTS in Claude Code over 321 commits, barely reading any code.
Paragraph Summary
Using Claude Code, Simon Willison took a simple prompt through 12 major versions and 321 commits to create Battle Drones, an RTS playable in mobile browsers. The project includes code-generated 3D models, random maps, six AI personalities, agent battles, and sound-wave multiplayer. The key turning point was v4's "Make it a LOT more fun," which ran thousands of simulated matches in Ultracode mode to redo balance, cutting the stalemate rate from 14% to 0.9%. Technically, deterministic simulation underpins replays and multiplayer, requiring replacements for Math.sin/cos to eliminate cross-browser floating-point differences. The author remains reserved about vibe coding, believing the project isn't yet a serious indie game, but sees a viable path.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.