Your score is not your score
The browser sends keystrokes. The server plays the run itself and keeps its own number.
A leaderboard in a browser game is a leaderboard of whoever opened the console first. The usual patch is obfuscation, which buys a week.
We do not accept a score from the client at all. Not signed, not encrypted, not in any form. What the browser sends is the input trace: a list of frame numbers and what you pressed on each one.
[{ frame: 12, type: "flap" }, { frame: 47, type: "flap" }, { frame: 180, type: "bank" }]The server loads the same simulation module the browser runs, feeds it the same day seed and your trace, and plays the minute out. Whatever number falls out of that is your score. If you put a score in the request body, it is read and ignored.
This only works if the maths is identical
Replaying inputs gives the same result only when the simulation is deterministic down to the bit. Three rules make that true here.
- The step is exactly 1/60 of a second, driven by an accumulator. Frame delta time never reaches the simulation.
- Positions and velocities are integers in fixed point, 4096 units to one world unit. No float accumulates drift across 3,600 frames.
- Math.random does not appear anywhere in the simulation. Columns, market modes and the whale wall all come out of the day seed through mulberry32.
Even the sine that drives the whale wall is a 256 entry integer table, rounded at build time. Two engines that disagree about the last bit of Math.sin still agree about the table.
Every run carries a checksum the client computes as it plays. When the server replays the trace it computes its own. The test suite asserts the two match across full sixty second runs, which is how we catch a drift bug before players do.
The remaining hole is hands
Nothing here stops someone from writing a bot that plays well. So the run also carries flags: twenty or more columns crossed dead centre frame by frame, or flap intervals with almost no variance, and the run is recorded and kept out of the table.
We set the metronome check to need at least twenty flaps before it says anything. On eight flaps a steady rhythm is a coincidence, and a false flag costs an honest player more than a missed bot costs us.
Every number here comes out of sim/constants.ts, the one file the game reads its balance from.