{"slug": "battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven", "title": "Battle Drones: What 12 Iterations of 'Make It More Fun' Reveals About Agent-Driven Game Development", "summary": "Simon Willison built Battle Drones, a browser-based real-time strategy game, entirely through coding agents, accumulating 321 commits without writing any code himself. The project relied on Claude Code's \"Ultracode\" mode, a JavaScript runtime that orchestrates networks of subagents, and included an overnight run of 1,200 simulated playtests to rebalance gameplay. To support replay and multiplayer, the agents replaced JavaScript's built-in trigonometric functions with custom implementations that guarantee bit-identical results across browsers, and the game adds an agent-vs-agent mode where two LLMs command opposing armies.", "body_md": "Simon Willison built a full Command & Conquer-style RTS game by telling Claude Code to \"make it more fun.\" The result is Battle Drones, a browser-based real-time strategy game with 3D models, fog of war, AI opponents, and audio-based multiplayer. It took 321 commits by coding agents, zero lines of code written by Willison himself, and a single overnight run that executed 1,200 simulated playtests to rebalance gameplay.\n\nThis is not a toy demo. The game runs offline as a PWA, costs nothing to host, and supports multiplayer between devices using audio modem signals. The plumbing underneath exposes how dynamic workflow orchestration, deterministic simulation engines, and agent-vs-agent testing actually work in production.\n\nClaude Code's \"Ultracode\" mode is a JavaScript runtime that coordinates networks of subagents. When Willison prompted \"Make it a LOT more fun,\" Claude didn't just tweak parameters. It spun up a workflow that:\n\nThe workflow ran overnight. Willison woke up to release notes written by the agent itself, detailing new \"call-down powers\" (orbital strikes, EMP blasts), objective-based gameplay (uplink relays, supply drops), and adaptive music that responds to combat intensity.\n\nThis is not prompt chaining. Ultracode generates JavaScript that orchestrates subagents, each with its own context and tool access. The parent workflow decides when to spawn a subagent, what data to pass, and how to merge results. The model writes the orchestration logic, not the human.\n\nBattle Drones supports replay and multiplayer, both of which require deterministic simulation. Every frame must produce identical results given identical inputs. This broke when Claude initially used JavaScript's built-in `Math.sin()` and `Math.cos()`.\n\nDifferent browsers return slightly different floating-point results for trigonometric functions. Chrome and Safari diverge after enough iterations, causing replay desync. Claude replaced the standard library with custom implementations that guarantee bit-identical results across platforms.\n\nThe same determinism requirement applies to multiplayer. Two devices must simulate the same game state from the same input stream. The audio modem sends compressed command deltas (unit selections, movement orders, building placements), not full state snapshots. Each device reconstructs the game state independently. If simulation diverges, multiplayer breaks.\n\nThis is why the codebase avoids:\n\nThe random map generator uses seeded RNG so maps can be shared and replayed. Every match can be exported as JSON and fed back into the replay tool.\n\nBattle Drones includes an \"Agent vs. Agent\" mode where two LLMs control opposing armies. The prompt design is visible at the `/agent-battles` endpoint. Each turn, the LLM receives:\n\nThe LLM responds with a JSON array of commands. The game executes them, advances the simulation, and queries the next LLM. A separate debug tool shows the underlying prompt and response for each turn, exposing how models reason about strategy.\n\nThe prompt includes constraints:\n\nThis forces the LLM to play within the same information constraints as a human. The replay system records the full prompt/response chain, so you can watch GPT-6 Luna vs. Claude Haiku 5.5 and see exactly what each model was thinking.\n\nThe audio-based multiplayer is a stateless modem protocol. Two devices within microphone range exchange game state deltas using high-frequency chirps. The protocol:\n\nThis works because the simulation is deterministic. Both devices start from the same seed and apply the same command stream. No WebSockets, no relay server, no ongoing hosting cost.\n\nWillison later added a WebSocket relay server (deployed on Fly.io for $2.19/month) after the high-pitched modem sounds caused headaches. The relay is stateless: it forwards messages between two connected clients and forgets everything when they disconnect. No game state is stored server-side.\n\nThe relay uses a simple room-based protocol:\n\n```\n// Client connects and joins a room\nws.send(JSON.stringify({ type: 'join', room: 'abc123' }));\n\n// Server forwards messages to the other client in the same room\nws.send(JSON.stringify({ type: 'game_command', payload: {...} }));\n```\n\nThe server never validates or interprets game commands. It's a dumb pipe. This keeps the deployment simple and the cost predictable.\n\nEvery 3D model in Battle Drones is constructed in TypeScript using Three.js. No external modeling tools, no asset files. Claude generated procedural geometry for buildings, vehicles, and terrain features.\n\nExample: the Goliath mech is a walking base that can be airlifted by two Condor aircraft. It has eye lasers, arm cannons, shoulder-mounted mortars, and machine guns. As it takes damage, it loses weapons in a specific order (mortars first, then lasers, guns last). All of this is defined in code.\n\nThe model browser at `/models` shows every unit in the game. You can rotate them, inspect their geometry, and see the TypeScript that generated them.\n\nThis approach has trade-offs:\n\n| Aspect | Code-Generated Models | Asset Files | \n|---|---|---|\n| Iteration speed | Fast (just prompt) | Slow (export, import, test) | \n| File size | Larger (code + runtime) | Smaller (optimized meshes) | \n| Visual fidelity | Limited by procedural generation | High (artist-controlled) | \n| Consistency | Guaranteed (same code, same output) | Variable (manual export) | \n| Version control | Clean diffs | Binary blobs | \n\nFor a vibe-coded game, code-generated models win. For a production game with a dedicated art team, asset files win.\n\nThe project exposes several failure modes:\n\n**Non-deterministic simulation drift.** Even after replacing `Math.sin()`, subtle differences in floating-point arithmetic can accumulate. The replay system includes a checksum validation step that detects drift and logs the divergence point.\n\n**Audio modem reliability.** Background noise, microphone quality, and speaker volume all affect decode success rate. The protocol includes error correction, but high packet loss makes multiplayer unplayable. The WebSocket relay is a fallback.\n\n**Agent hallucination in battles.** LLMs sometimes issue invalid commands (e.g., trying to build a structure outside their base range). The game engine silently ignores these, but the LLM doesn't receive feedback. This can cause the agent to repeat the same invalid action.\n\n**Ultracode token burn.** The \"make it more fun\" prompt consumed most of Willison's weekly Claude token budget. Dynamic workflows are expensive. You need to know when the cost is justified.\n\n**No observability into subagent coordination.** Ultracode workflows are opaque. You see the final result, but not the intermediate steps. There's no trace of which subagents ran, what data they processed, or how they coordinated. This makes debugging hard.\n\nThe game is a single-page application with no backend:\n\nThe entire game is TypeScript compiled to JavaScript. Willison has reviewed almost none of the code. He playtested extensively but didn't write a single line.\n\n**Use agent-driven development when:**\n\n**Avoid it when:**\n\nThe \"make it more fun\" prompt worked because the agent could measure success (win rate distribution, game duration) and iterate autonomously. This pattern generalizes to any problem where you can define success metrics and let the agent optimize.\n\nThe lack of observability into Ultracode workflows is the biggest operational risk. You don't know what the subagents did, only that they produced a result. For production systems, you need trace logs, metrics, and the ability to replay workflows step-by-step.", "url": "https://wpnews.pro/news/battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven", "canonical_source": "https://dev.to/mech_app_ai/battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven-game-development-2j82", "published_at": "2026-10-22 00:08:24+00:00", "updated_at": "2026-10-22 00:10:36.081319+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "artificial-intelligence"], "entities": ["Simon Willison", "Claude Code", "Battle Drones", "Ultracode", "Fly.io", "GPT-6 Luna", "Claude Haiku 5.5"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven", "markdown": "https://wpnews.pro/news/battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven.md", "text": "https://wpnews.pro/news/battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven.txt", "jsonld": "https://wpnews.pro/news/battle-drones-what-12-iterations-of-make-it-more-fun-reveals-about-agent-driven.jsonld"}}