What 7helm Is Made Of
Change the drag constant in my arcade game by one part in a hundred million and twelve recorded runs stop matching. That strictness is the foundation the replays, the scoreboard, the co-op and the releases all stand on.
Change the drag constant in 7helm by one part in a hundred million and twelve of thirteen recorded runs stop matching. I know because that is the test. Before the player's ship was rebuilt to make room for a second pilot, thirteen scripted runs were fingerprinted at full precision every ten seconds, one for every mode. Each step of the rebuild had to leave all thirteen identical to the last bit. There are fifteen of them now, and they run on every change.
Nearly everything else in the game stands on that strictness. The replays do, and the scoreboard, the daily challenge, the co-op, and the way a release reaches players.
I introduced 7helm in September as a thing you fly. This is the other half: what it is built from, what is live, and where it is still rough.
The game as it plays today
It is a twin-stick space arcade that runs in a browser, on a phone or a desktop, with nothing to install and no account. You move with one hand and aim with the other. Red hunters arrive in waves, and the wave number tells you what is coming. Every third wave is a crossfire. Every fourth is marksmen who lead their shots. Every fifth is a swarm. A pilot who has seen wave five twice knows what wave ten is.
The enemies run on one rule. They are allowed to get very good, but only at things you can see and answer. Every shot and every lunge shows a ring before it happens. Their rounds never get faster. There is a floor under how quickly they can react.
PLAY drops you into a public skirmish. If nobody else is flying, it is single-player and says so. If someone is, they are simply there too. A room code gets you a private room with friends, up to four pilots, each in their own colour. There is a daily challenge, the same sky for everyone that day, with its own board. Behind a door marked ARCADE LABS are the experiments: the Fall, where twelve ships share a field while a front closes in; a tower-defence siege across seven stations from the Moon out to Titan; a duel.
Here is half a minute of it, flown by the game's own test pilots.
A simulation with no browser in it
The first version was one file of 5,300 lines that drew, listened, and decided what happened, all at once. It felt right and it could not have carried a second player.
The fix was to move everything that decides what happens into a library that is forbidden from knowing a browser exists. The build checks for it. That library is told two things: how the match was set up, and what each pilot intends this tick. It speaks to the outside through one narrow port, for sound, sparks and shake, and it never reads anything back.
Making that true surfaced five leaks. The simulation had been reading the frame rate, because drawing borrowed from the same random numbers. It read the screen size, so the same seed made a different world on a different device. Three of the player's verbs were written straight into the world by key handlers, so a recording of intentions lost them. One branch looked at the browser's saved settings. One shuffle used a random generator that differs between the two places the code runs.
None of those shows up when one person plays on one machine. Every one of them makes a recorded run drift from its replay.
Once a run could be recorded and replayed to the same state, the replay started finding bugs that playing never had. In the Fall, ships could not actually hit each other; the check sat below a line that skipped it. Three rounds of tuning had been done against that. Choosing a mode from the pause menu quietly set the enemy population to zero, forever. The first replay ever run against the live client disagreed with it on the very first tick and named the field.
A scoreboard that replays your run
There is one board and everyone shares it. When a run ends, the game sends the recording of your controls, and the server plays the whole run again by itself. The board posts what that replay reaches. A run that does not replay does not count.
That only works if the simulation reaches the same bits on every engine that runs it: Chrome, every browser on an iPhone, the scoreboard's verifier, and the game server. Arithmetic is pinned to the last bit by the floating-point standard. Sine, cosine and arctangent are not, and those engines do round them differently. The first real run I replayed outside a browser reached the same outcome and had drifted by tick 600, five seconds in.
So the game carries its own versions of those three functions, written in nothing but add, subtract, multiply, divide and compare, and the build refuses any code in the simulation that calls the ordinary ones. There was no public board until that was done. A board that cannot check its rows would have rejected fair runs or accepted invented ones.
The daily challenge came almost free after that. One seed per day gives everyone the same sky, and the same replay check keeps its board straight.
Who owns the truth
Putting a second pilot in the world meant deciding who owns the truth. A player's phone cannot, since it could rewrite the world and the room would die when they left. So there is a server, running the same simulation library compiled for a server, and it is the authority.
The first networked build was tested on two real phones and felt wrong at once. Your own ship skipped, the picture flickered, and sounds played twice. The cause was one thing. A snapshot from the server describes the past, so accepting it pulled your ship back by however many of your inputs were still in flight, and the phone then lived those ticks again, audibly.
The repair is the standard one, and it has three parts. Every input carries a number, and every snapshot says which of your inputs it already includes. On each snapshot the phone takes the server's world and silently replays the inputs the server has not seen yet. Whatever still moves is eased into place over about ninety milliseconds instead of jumping.
I measured it on a simulated network, and the measurement is part of the test suite. At 100 milliseconds of delay, the average jump in your own ship on each snapshot went from 10.8 world units to zero. At 200 it went from 15.8 to 0.6.
The same simulation is small enough that the server is one of the cheapest machines AWS rents, about eight dollars a month. A two-pilot room steps in roughly 36 millionths of a second, which is about 230 rooms on one core. The server program is twelve megabytes and uses about six of memory.
I work with Kubernetes and I left it out of this path on purpose. A room lives in one process's memory. A scheduler moving that process ends every room on it. A game server wants to stay where it is.
I considered the other way to network a deterministic game, where every player's machine computes the same thing in lockstep and only inputs are exchanged. It is tempting when the simulation is already exact. It stops working the moment anything arrives late, and something always does.
One artifact, built once
The release path has one idea: the thing I tested is the thing players get. The site is built once into a single folder. Staging receives that folder. Production receives the same bytes, copied and never rebuilt. Every build carries its version and commit in the corner of the screen, and a build made from uncommitted work cannot be deployed at all.
The site used to be copied over the live files, so for a minute a player could load a mix of old and new. Now every release is written to its own folder in production and never overwritten. A single pointer says which folder everyone gets. A preview key lets one browser see the next folder on the real domain before anyone else does. Moving the pointer is the release. Moving it back is the rollback, and in rehearsal that took 32 seconds.
That covers the site, and only the site. The scoreboard and the game server are still replaced in place, which means a release today ends every room that is flying. Giving the server two slots, so rooms finish on the one they opened on, is designed and not built. It needs a slightly larger machine, about three dollars a month more.
One person runs this. The point of all of it is that I stop thinking about upgrades.
What you hear
Every sound in 7helm was made in ChipForge, the synthesis engine I wrote in Python. There are no samples and no recordings in it. Every waveform is computed from numpy arrays, the same way the Napkin Films scores are.
The effects came first, seven short clips: a shot, a hit, a crack, a boost, a death, a spawn, a tick. On a phone they sounded harsh, and the question was whether to keep them. I liked them once I could separate the sounds from how they had been treated. The problem turned out to be how they were rendered, not what they were. Distortion on the crack, the hit and the death came out entirely. Attacks of a fifth of a millisecond became one or two, which is the difference between a click and a hit. Peaks came down. The noise bursts were rolled off where harshness lives, between three and eight kilohertz, and each clip got a short room so it stopped sounding dry and cheap. The note I wrote for myself at the time was that ugly should mean heavy, not fizzy.
Then the mix. Your own gun is the quietest thing in it, at 0.30 against 1.15 for a kill. It fires eight times a second and tells you nothing you did not already know, and a loud gun is how an arcade mix goes deaf. Everything else plays from where it happened: full level within 260 units of your ship, falling off with distance out to 2,200, and silent past that. Left and right come from where it is. In the larger maps you hear a shooter before it reaches the edge of the screen, and you hear which side it is on.
The music is three pieces in one family, sharing the same pad, strings, chiptune engine and orchestral voices. They grew out of a fourth. The first score was a single 96-second loop in A minor at 100 beats a minute, built from three threads I wanted to hear separately: a low chiptune pulse, a classical body of strings and a cathedral pad that borrows a G sharp at its cadences, and a half-time EDM pulse under both. It had a fourth layer, a melodic lead, which I cut. It was weak and slightly out of tune against the other three.
My brief for the next round was short: something different for the Fall and for the front screen, and a skirmish score that was longer, had more notes, and was still beautiful.
The title piece is in D major at 72 beats a minute, built as a ground bass with variations, the Baroque device behind Pachelbel's Canon and Purcell's grounds. One eight-bar bass line, D, C sharp, B, A, G, F sharp, E, A, repeats underneath seven variations. The melody over it is my own. The pad and the bass begin alone. Strings enter and a cello states the theme. The chiptune engine arrives with a celeste answering high. The violin takes the theme over a cello countermelody, then breaks it into eighth notes. A horn carries it at the fullest point, and a harp settles it home. It runs a little over three minutes and plays only on the front screen.
Title, the front screen
The skirmish piece starts with the original 96 seconds, note for note, and then keeps going for about four minutes. A cello enters under the old theme, a horn answers it, the harmony lifts into the relative major, and then the drums stop for a breath. The theme comes back on violin, builds to a horn climax, and ends with the motif once more on celeste before it thins back into the opening so it can loop.
Skirmish, at full intensity
The Fall is in D minor at 108, over the lament bass: four notes, D, C, B flat, A, falling down the scale and repeating. Baroque composers used that figure for grief and for descent, and a mode where every ship falls one by one until one is left seemed to want it literally. It opens on a heartbeat kick and a low horn call. In the middle the lament goes chromatic, D, C sharp, C, B, B flat, A, the bass under Dido's lament in Purcell's opera, with the drive taken out. Then the ground comes back at full force with horns on the theme.
The Fall, at full intensity
What makes it behave like a score rather than a playlist is that the game never changes which notes play. Each piece is rendered as four layers, a bed, the chiptune engine, the pulse and the solo voices, and exported as two mixes of the same length, one calm and one tense. About three times a second the game reads the fight: how close the nearest threat is, how much hull you have left, whether the Fall's front is closing. It smooths that into a single number and blends the two mixes by it. Because every layer's level moves in a straight line between calm and tense, two files reproduce the four-layer mix exactly, in half the memory. When you go from the front screen into a run, or from a run into the Fall, one piece crossfades into the next over two and a half seconds. Music has its own volume, separate from the effects, and a visitor who leaves within two seconds downloads none of it.
What it keeps
No accounts, no cookies, no scripts from anyone else. Nothing leaves the game's own domain. It records how a run went: which mode, how long, how it ended, how many pilots. It never records who, never an address, and never any text a player typed, because there is nowhere to type any. What ties your runs together is a random id your own browser made up, and you can delete everything held against it. The privacy page lists every field, and a field goes on that page before the game is allowed to send it.
Bots fill empty seats in some modes, and they wear a mark a player cannot type. A bot shown as a person would be an invented row on a board whose whole purpose is that its rows are checked.
Where it is rough
When PLAY went public, the first version dropped people into the Fall. That was a mistake, corrected the same day once I played it for real. PLAY had only ever meant the default mode, now shared. It had never meant a different game with different rules.
Co-op is currently easier than flying alone. Two test pilots reach wave 12 where one reaches wave 9, and the knobs for that have not been turned yet. A test pilot with perfect aim cleared four waves in 29 seconds without being touched, which tells me the ceiling is low. Names on the board are three initials, and a design for something more is written and not decided.
It was built in small pieces, with agents doing much of the typing while I did the deciding and the flying. The fifteen recorded runs are what made that safe. An agent can change a great deal in an hour, and a test that fails on one part in a hundred million tells me within seconds whether any of it changed how the game plays.
The name, said aloud, is sevenhelm. A helm is where the steersman stands, and steersman is the old word that cybernetics was named for. I did not plan for the game and the essays to meet there.
If you play it, tell me which wave ends you.