05 / In development · iPhone

Hold the
Line

The network is the game.

A minimalist WWI strategy game in active development. You don’t control soldiers — you control the logistics that let soldiers fight: which trenches to dig, which routes to repair, where the reserve walks. This is the project where I moved from building apps to building a game: a simulation with its own clock, not a UI with state.

It’s also the least accidental premise on this site. I spent five years at CNA turning contested logistics into playable models — networks, constrained resources, partial information, cascading failure. Hold the Line is that same instinct off the clock, shrunk onto a phone screen, with the modeling discipline intact.

A

A real game loop

The simulation ticks at a fixed 10Hz, decoupled from display refresh. Wall-clock time accumulates into ticks, stalls are clamped, and at most eight ticks run per rendered frame — so a dropped frame produces more ticks, never a shorter one. The 2× speed button changes how many ticks fit in a wall-second and never what happens inside a tick. Twelve systems run in a fixed, documented order, because that order is part of the game’s contract: supply is consumed before combat so a sector fights on what it has left, and positions fall last so a collapse redraws the map before the next tick begins.

B

Same seed, bit-identical run — as a test, not a claim

The engine carries a hand-rolled SplitMix64 random generator and its own state hash, because Swift’s built-ins aren’t stable across processes or releases. Every simulated quantity is an integer. Iteration happens in sorted ID order, never dictionary order. The test suite replays a complete run to collapse and asserts it’s bit-identical — and one test asserts that every mutable field of the world state moves the hash, so a new field can’t silently escape the determinism contract.

C

Rerouting fell out of one decision

Supply consignments carry a destination, never a precomputed path, and they re-run Dijkstra against live edge costs at every node they reach. That single choice is what makes rerouting free: when artillery severs a trench or a route congests, the next hop is simply computed against the new costs. There is no special-case rerouting code to get wrong.

SEVER A ROUTE. TRAFFIC FINDS THE NEXT ONE.

D

Losing ground redraws the puzzle

When a position breaks, it doesn’t lose hit points — the map changes. Its roads sever but keep charging the construction budget, because retreat has a bill. A support position behind it is promoted to the front line, with a frontline garrison and a frontline appetite for supply. And the fallback is chosen geometrically — the nearest held position closer to the rear — not from a lookup table, so it works on irregular maps. There’s a test named for exactly that promise.

E

Playtests are diagnoses

My first playtest verdict is kept verbatim in the repo: “I’m not entirely sure what I was supposed to be testing.” The screenshots showed every system working; the failure was communication, and the root cause was precise — color was encoding both role and danger in one channel, so a calm front position and one under assault looked the same. The fix was a redesign: color now means danger, and only danger.

Balance isn’t feel, either. Soak simulations run to 200,000 ticks across multiple seeds and assert that runs land inside a 4–20-minute band, and an invariant suite checks the structural truths of the world on every single tick.

WHAT IT TAUGHT ME

Game development is systems engineering wearing a costume. The craft is making a dozen interlocking systems legible in one glance on a phone screen — and it’s still in progress: the first milestone passed its gate, and the art, sound, and interface language are being built now.