The Brick Gulf: all three wars, one front
The TODO's oldest confession says combined arms on one map
“got muddy” and was split into three games. Today the
split un-splits — deliberately, as a fourth theater
(-combined-arms): planes flown with the air game's flight
model, warships fought with the naval theater's gunnery, armor fought
with the land theater's facet armor, all in one round on one map
designed for exactly this.
Why it got muddy, in numbers
Each arm was tuned to its own scale: naval hulls spot at 4–9 km and shoot to 13 km on a 9 km ocean; tanks fight at 1–3 km on a 3.6 km steppe that was cut down from 6 km because forces wandered an empty map without finding each other. You cannot average those numbers into one battlefield — a map flat and small enough for tanks starves naval gunnery, and an ocean big enough for battleships turns armor into a commute.
So the Brick Gulf doesn't average them. It interlocks two full-scale battlefields along an authored coastline: the land theater's steppe (same noise, same forests, same towns) west of a meandering coast, the naval theater's deep sea and low islands east of it, and one front line running through both. Four zones sit on that line, equidistant from either team: Kilnfeld and Crossbrick for the armor, Fort Brick for the fleets, and Brickhaven — the harbor at the head of a bay that bites into the front's center — capturable by a tank platoon in the streets or a destroyer alongside the quay. The Sky Ring floats over the Gulf mouth and pays a multiplier on your side's zone ticks instead of points: air superiority always matters, and never invalidates the surface war.
The trick that makes ships and tanks touch: warship fire against the shore isn't a 13 km artillery tax. Fog of war is server-side — an unspotted tank is never even sent to the enemy's client — so a cruiser can only aim at armor somebody on her team can see. A fighter orbiting the steppe is the fleet's rangefinder; killing the spotter is air defense of the tank front. Spotting is the currency the arms trade.
The engine already knew how
The satisfying part: because the theaters were built on shared
machinery with per-hull-type dispatch — a warship is a
GroundVehicle with Naval=true, a tank with
Land=true — the mixed roster mostly just
worked. Ship AA already shot at planes; planes already spotted for
both surface games; strafing already resolved through the facet armor
model. The new code is geography and orchestration: where the ports
and depots are, which patrols to field, one unified spotting pass, and
a handful of cross-arm rules — a tank dart into a beached
destroyer resolves through the naval belt-and-citadel model (a
Paladin's sabot laughs at 16 mm of destroyer plating), warship HE gets
a ground burst that armor sheds by the land HE rule, and a Warden's
wire-guided missile covers the whole Gulf.
What the probe caught
The balance probe (ARMADA_BALANCE=1) runs a full bot
round for ten simulated minutes and counts everything. Its first run
never finished — the strike-wing maintainer counted its planes
by requested airframe, the career gate silently clamps a
bot's ungated jet back to the trainer, and the wing spawned pilots
forever. A stack dump found the loop; wings are now counted by role.
With that fixed, one tick of the whole combined world costs
0.29 ms — twenty-seven times under budget.
The second run found a doctrine bug: the land platoon assigner's default objective is “zone 0”, which on this map is the far-western town — both armies marched past each other to camp it while the front's center sat empty. Then the fix overcorrected: everyone piled into Crossbrick, it sat contested all round, and ten minutes of war scored 0 to 16 (domination pays nothing for a town both sides are dying in). The doctrine that finally flowed: the line fights for Crossbrick, the flankers split to Kilnfeld and the Brickhaven quay. Same probe, ten minutes later: 276 to 454, first enemy spotted at 6 seconds, both fronts flipping.
The confession
The browser playtest joined as each arm in turn, and the tank's fighting-compartment panel — ammo nature, smoke, artillery, overdrive chips — wasn't there. The dispatch logic was right. The panel was being hidden sixty times a second: the naval and land panels share one DOM node, and the frame loop called “hide the naval panel” unconditionally after the land panel had just been filled in. Here's the confession: we ran the same check against the shipped land theater, and it has the same bug. The crew panel land players were designed to fight with has been invisible since the theater launched, and nobody — including us — noticed until a combined-arms playtest put a ship's working panel next to a tank's missing one. One exclusive decision now picks whichever hull's labels you're crewing, and the land theater got its panel back as a side effect.
Where it stands
go run ./cmd/server -combined-arms serves the Gulf: pick
a fighter, a warship, or a tank from one spawn screen (each keeps its
own unlock ladder), and the round is first to 1,400 over fifteen
minutes. Terrain is parity-checked in all four theaters, the air
game's golden bytes are untouched, and the smoke tests now include an
armada round. The logistics layer shipped right behind it: truck
columns that steer themselves from the HQ to the forward depot with
the land AI's obstacle feeler (this map has no roads), a freighter
sealift that sails only while your side holds Brickhaven — threading
the Breakwater gauntlet, sinkable by anything — and Fort
Brick's garrison: a dormant ruin of flak and one plotted-fire
battery that stands up, at full strength, under the flag of whoever
takes zone D. Capture the water, inherit the fort. The map was drawn
before the mode was built — the design doc
has the annotated chart, and the terrain in the game is that chart,
bit for bit.