cpmccoy
← All devlogs
11 min read

MechAssault v2: feature complete

Nine weeks, 8,568 commits and more than 3,500 sub-agents, almost all of it hands off: the browser remake of MechAssault 2: Lone Wolf is feature complete, with five maps, 30 'Mechs, BattleArmor that neurohacks, AI armies and peer-to-peer multiplayer. Plus a first look at Flashpoint: Wild Space.

Project: MechAssault v2TypeScriptThree.jsWebGPUWebRTCAI AgentsReverse Engineering

Five weeks ago, MechAssault v2 was one map, a Blood Asp and a lot of promise. A week after that it was holding its own side by side with the original.

Today it's feature complete. Everything below is running in a browser tab. Agents built nearly all of it, and for most of those nine weeks I wasn't even watching.

Base War on Deliverance with both armies out. A Blood Asp charges its antimatter PPCs in the middle of Red's tank line as a Blue Raven closes in, Blue's VTOLs make rocket runs overhead, and the Raven circles in to point blank.

What's in it

  • Two modes. Base War, where each side tries to destroy the other's generator, and Team Destruction, where the first team to the kill limit wins.
  • Five maps. Deliverance, RushHour, GoCommando, BoggedDown and NoMansLand, each with its own bays, turrets and music.
  • Everything with a seat. All 30 'Mechs, the tank, the VTOL, turrets, the BattleArmor suit, GoCommando's Elementals and the power armour, plus the pilot on foot who climbs between them.
  • BattleArmor that fights like it should. The claw, wall climbing, riding a VTOL's wing, the mortar, and the neurohack: jump on an enemy 'Mech's back, win the button race, and the 'Mech is yours.
  • AI armies. Each side fields AI 'Mechs, a squad of Rommel, Manticore and Partisan tanks, and VTOLs that fly attack runs.
  • Multiplayer. Two to four players, peer to peer, joined with a room code. No server of mine in the middle.
  • A front end. A live hangar menu, Quick Battle, an Options screen, and the original's scoreboard with Restart and Main menu at the end of every match.

BattleArmor and the neurohack

The BattleArmor suit is what set MechAssault 2 apart, and the neurohack is its signature move: a soldier in powered armour jumps on a 'Mech's back, hacks it, and drives it away.

The neurohack. A Blue Owens is shelling Red's power plant when a Red BattleArmor suit lands on its back and claws on. The jacking plate comes up: six prompts, six right presses, the dial fills, and the suit kicks off as the Owens goes quiet. For the recording the suit is dropped in rather than jetted up, and the camera is a chase camera added for the shot. The plate's 'system breached!' text doesn't draw yet.
Then the 'Mech is yours. The pilot climbs out of the suit, runs round to the Owens's front leg and climbs aboard, and the Owens powers up under its new driver. One gap is plain to see: the boarding ladder hangs a few steps off to the side of the crouched 'Mech.

The neurohack is a button race. Clawed onto an enemy 'Mech's back, the suit's jacking plate flashes a button, sometimes two, three or four at once, and you have a fraction of a second to press exactly those. Right presses fill the dial. Wrong presses and missed prompts drain it. Six right presses win, and the 'Mech stands empty for you to climb into. Lose, and the 'Mech bucks you off and your claw locks for five seconds.

None of those numbers are guesses. The rule file behind the hack traces every one of them to the instruction in the original Xbox executable that reads it: the points required, the points per press, the penalty for a miss, how long each prompt shows and how many buttons it can ask for. 120 of the project's 150 rule files cite the executable that way. The rest come from the original game's data or from playing it.

The suit does more than hack. Its claw hits a 'Mech or a tank for 400, it can hang under a VTOL's wing and ride it, its mortar charges and lobs rounds in an arc, and in the air it can claw onto a wall and climb:

Climbing Red's power plant: jet up, claw onto the wall, tap the jets, claw on higher. Four holds, then a long burn over the parapet onto the roof. The jet gauge refills while the suit hangs.

Base War at full strength

In October, Base War was 'Mechs against 'Mechs. Now each side fields the whole army: AI 'Mechs, a tank squad rolling out toward the enemy generator, and VTOLs lifting off from their own half to make rocket passes at anything in sight. Everything takes fire from everything, scores, burns out and comes back.

This is the one big thing the original doesn't have. Its multiplayer maps field no AI at all: every bay 'Mech on Deliverance has its AI switched off. I wanted a match to feel like a battle even with one player, so the armies are the port's addition. They still run on the original's own numbers, though: every 'Mech template carries its own engage radius, view and preferred range, and the AI pilots fight by them. The Manticore and Partisan come from the campaign.

A Blue VTOL swings round over the hill and comes in low, straight at the Blood Asp, taking fire from Red's tanks as it passes overhead.

And this is what a 'Mech's death looks like now:

A point-blank antimatter volley and a tank's beam bring down the Raven. It topples onto its back in flames, holds for two seconds, then goes up: the shock pinches the ground in toward the blast as it passes outward, streaks of light fan out, and burning debris rains across the flats. The Blood Asp's weapons are boosted for the clip with a capture key; at stock level, five takes never finished the Raven off.

Five maps

Deliverance was the only playable map in the first post. Now there are five, and each one is the original level: its terrain, buildings, lights, water, bays, turrets and music.

  • Deliverance

    Deliverance

  • RushHour

    RushHour

  • GoCommando

    GoCommando

  • BoggedDown

    BoggedDown

  • NoMansLand

    NoMansLand

All five, from the Red side: Deliverance's swamp, RushHour's towers, GoCommando's waterfront, BoggedDown's foggy river and NoMansLand's valley at night.

RushHour's towers are more than scenery. Shoot one enough and it comes down:

An Atlas pours autocannon fire into one of RushHour's spired towers until it dies: its lights go out, its face sheds chunks, and what's left sinks into its own dust cloud. The rubble it leaves behind is still smaller than the original's.
BoggedDown, one of the two new maps. A Wendigo wades the murky river toward the concrete fortresses in the fog, its arm crackling with arcs as it charges and looses bolt after bolt.

Picking a map works the way the original does too. The level select's map pictures, titles and one-line blurbs ("Who knows what this swamp holds?") are the original's own.

Multiplayer, with no server

The original game had Xbox Live. This one has WebRTC.

One player's browser hosts the match and runs the game. Everyone else's browser sends its inputs and gets snapshots back, predicts its own 'Mech so the controls answer at once, and quietly corrects itself whenever the host saw something different. The host shares a twelve-character room code, or an invite code for networks where the room code can't get through, and the players meet in the briefing room, pick a team and ready up.

Two players, side by side. The host opens a room and gets a code. The second player types it in, lands in the briefing room on Blue, switches to Red and readies up, and the host's Launch Game lights.
Then both are in the same Base War match on Deliverance, each browser following its own Cougar. The joiner circles the host, the host side-steps, and the joiner jets up over the host's head, and each screen shows the other player doing it. Both pages ran on one machine for the recording, linked over real WebRTC, so the link here is instant. Over the internet the other player shows up a moment later.

Two decisions made it work:

  • Not lockstep. The JavaScript spec lets Math.sin, Math.cos and friends return slightly different results on different browsers. In a lockstep game, one last-bit difference desyncs the whole match, so the host is the only source of truth.
  • Tested under bad conditions. A headless harness runs several players at once over a fake link with lag and packet loss injected, so "it felt fine on my machine" was never the test.

The front end

The original's front end is a 640x480 form over still art. This one keeps its words and adds a 'Mech:

A Mad Cat stands in the game's own renderer, powers up as the title gives way to the menu, and the camera glides to a new framing for each screen. Quick Battle drops straight into Base War; Battle steps through the maps.

Around it: an Options screen with music, speech and effects volume (also reachable mid-match), the original's scoreboard at the end of every match with Restart and Main menu, and a What's New page that says what changed in plain words.

Under the hood

  • The game runs on its own thread. In a 12-AI fight on RushHour, the game's own simulation was taking 24 ms of every frame on the same thread that draws. The simulation and physics now run in a Web Worker and hand each frame a packed snapshot of the world, so a busy scene draws smoother.
  • WebGPU first, WebGL2 when it isn't there. Both backends draw the same game, and the build tells you which one it used.
  • A performance readout. F2 shows the frame rate, the slowest frames, where each frame's time goes and, in a match, each player's round trip. Shift+F2 copies a report to paste into a bug.

By the numbers

Measured the same way as the last two posts:

Oct 3Oct 12Nov 9
Game code~30,000 lines~45,900 lines~69,100 lines
Source files241369549
Test code~86,000 lines~125,000 lines~157,500 lines

How it got built

Every change went through the same loop: an implementer agent builds it, an adversarial reviewer agent tries to break it, a fixer agent repairs what broke, and the pipeline decides whether it lands. By November 7 the project had run more than 3,500 sub-agents:

RoleSub-agents
Implementers925
Adversarial reviewers1,266
Fixers1,380

There are more reviewers than implementers, and more fixers than either. That's the loop doing its job: most of the work was finding what was wrong and fixing it.

In all, 805 issues went from the ledger to main, 355 of them since the side-by-side post. The orchestrator handed the project from session to session through the ledger the whole way, the same way the first post described.

Mostly hands off

I didn't write the code, and most of the time I wasn't even watching it get written.

The first four days were setup: 76 messages from me to get the ledger, the roles and the first orchestrator going. After that the orchestrators ran it. From September 12 to November 7 I sent 234 messages, about four a day, with a median of 22 words. Over the same stretch, 7,931 commits landed.

September 12 to November 7
Hours in which code landed1,065
Hours in which I said anything83
Days I said nothing at all12, with 1,116 commits landing on them
Longest silencefive days, Nov 2 to Nov 7: 145 commits and 15 issues merged

In more than nine of every ten hours that code landed, I hadn't said a word. What I did send was mostly playtest notes, the things I noticed when I played the latest build, and decisions only I could make, like putting AI on both teams so a match would feel like a battle. Over the whole project, setup included, everything I typed comes to about 16,000 words.

What's not in it

The campaign. It's on the menu, marked WIP. It went on hold when Deliverance became the focus back in October, and the missions are a project of their own.

And there's still no public build, so this is a write-up, not a link.

What I take from it

v1 was a game built on guesses, and it became its own thing. v2 had the original to check against at every step, and it ended up looking and playing like it.

The agents wrote nearly all of it, mostly while I was doing something else. What made the difference wasn't a smarter model. It was giving them something true to work from: the original game, a ledger that outlived every session, and a reviewer whose only job was to prove them wrong.

Sneak peek: Flashpoint: Wild Space

Flashpoint: Wild Space is Flashpoint, my 2D space strategy game, rebuilt in 3D as an MMO.

A dark green and red fighter seen from above, astern, the left side and three-quarter front, with its three engines marked in orange and six weapon mounts in blue
One of the ships from four sides, with its engines (orange) and weapon mounts (blue) marked.
The night side of a planet dotted with city lights, a thin bright atmosphere along its edge, beside a blazing teal star
A world's night side, lit up, beside its star.

More soon.