Fair play

HOW VERIFICATION WORKS

A HORDE run is meant to be a fact you can check rather than a score you have to trust. This page explains the machinery, and then it explains, in detail, everything that machinery does not yet do.

Deterministic sim · liveDaily seed rail · liveInput log recorded · liveServer re-simulation · not liveVerified ladder · not live
Last reviewed 19 August 2026
READ THIS FIRST

Nothing on the ladder today has been verified by anyone. No run is re-simulated, no input log ever leaves your browser, and no prize has ever been paid. Today’s board is a practice board with client-reported scores, and it is labelled that way in the game, in the API response and here. The rest of this page describes a substrate that is genuinely built, and a verification service that is genuinely not.

01A fixed 60 Hz simulation

The game advances in fixed steps of exactly one sixtieth of a second. That step size never changes: not on a 144 Hz monitor, not on a laptop struggling at 30 fps, not on a phone. Drawing the frame and stepping the world are two separate jobs, and only the second one decides what happens.

This is the foundation for everything else. A simulation that advances by “however long the last frame took” produces a slightly different world on every machine, and no amount of seeding rescues it. A fixed step means the same inputs applied at the same tick numbers produce the same night, on any hardware. Pausing stops the clock entirely rather than slowing it, so a pause cannot be used to buy reaction time.

02The daily seed

One number decides the night. It is published by /api/seedwhich anyone can open, and it rolls at 00:00 UTC. There are two ways we can derive it, they give different guarantees, and this page reads the live endpoint rather than telling you which one is running.

Checking /api/seed

Open mode. The seed is HORDE-YYYY-MM-DD put through an FNV-1a hash and reduced to a value between 0 and 999,999. Nothing private goes into it, so you can compute tonight’s seed yourself and confirm the number we serve is the number the date produces. The weakness is the mirror image of that strength: anyone can compute any future night and practise it before staking on it. That is acceptable for free play and it is not acceptable for a wager, so staked tables do not open in this mode.

Committed mode. A server-side salt joins the date, so future nights are no longer guessable. On its own that would just move the trust to us, a hidden input means we could pick a night after seeing who turned up. So the salt is committed to in advance: we publish sha256(salt | day) for tomorrow, tonight, before anyone plays it. When a night is retired we release the salt, and anyone can recompute that hash and check it against what we published a day earlier. A commitment that matches proves we did not choose the night after seeing the field. This is the same shape a provably-fair casino game uses, and the chain is what does the work, not our word.

Either way there is no per-player seed, so there is no favoured player to hand a gentler night to.

A run can also be pointed at any seed with ?seed= in the URL, which is how a ghost challenge sends your rival the exact night you just died on.

03Five separate random streams

The seed does not feed one generator. It feeds four independent ones, each started from the seed mixed with a different constant:

The five random streams, how each is seeded, and what it decides
StreamSeeded fromDecidesAdvanced by
World / spawnsseedwave timing and position, elites, big skeletons, dropsthe simulation clock
Draftsseed ⊕ 0x9e3779b9which three upgrade cards you are offeredeach level-up
Combat varianceseed ⊕ 0x51ed270bper-hit damage rollseach hit you land
Environmentseed ⊕ 0x7f4a7c15bone eruptions, dawn shrines, ambient eventsthe simulation clock

Why four and not one. A random stream is a sequence, and every draw moves it forward. If a single stream fed everything, then the number of times you swung your sword would change which skeletons spawned next, two players on the same seed would drift apart within seconds and “same seed” would be a slogan rather than a property.

Splitting them fixes the parts of the night that must be identical for a fair comparison. Spawns and the environment are driven by the clock, so they land at the same second of the night for every player on that seedno matter how either of you plays. Drafts stay in the same order but arrive when you level, so a faster killer sees the same cards sooner. Combat variance follows your own hits, where it belongs.

04The input log

While you play, the game records what you did, not what happened. Every tick it builds a small number, a bitmask, out of the controls you are holding:

Input mask bits and the event values recorded above them
ValueMeaning
bit 0 to 3movement: up, down, left, right
bit 4dash
bit 5DAWNBURST ultimate
bit 6attack
64 to 66draft card chosen (first, second or third of the three offered)
67draft rerolled
68draft skipped
70 to 74hero chosen, written at tick 0
76 to 78draft card banished

Delta-encoded means nothing is written on a tick where your input did not change. A pair of numbers, the tick, and the new mask, is appended only at the moment something changes. Holding right for three seconds costs two numbers rather than a hundred and eighty. A full fifteen-minute run is a few kilobytes.

The mobile joystick is quantised into the same eight directions before it reaches the mask, so a touch run and a keyboard run produce the same kind of log and are checked the same way.

Because the draft picks, rerolls, skips, banishes and the hero choice are recorded in the same stream as movement, the log is a complete account of every decision you made, in order, with exact timing. Nothing about the run is left to be reconstructed from memory or from a screenshot.

05Why that adds up to a proof

Put the three pieces together and a run stops being an opinion. A fixed step, a known seed and a complete input log mean the night is a function of two inputs:

run result = simulate( seed, input log )

Hand a server the seed and the log and it can play the run back with no player present, and it must arrive at the same survival time, the same kill count and the same level. If it does not, the claim is rejected. That is the whole design.

The useful part is what it does not require. There is no need to detect cheating, no heuristic guessing at suspicious mouse movement, no appeal to our judgement about who looked legitimate. A score the simulation cannot produce simply cannot be reproducedand a run that reproduces is paid whether or not anyone believes it.

06What is actually live today

  • A deterministic fixed-step simulation at 60 Hz, running in your browser.
  • Four independent seeded random streams, split as described above.
  • The daily seed rail: a public endpoint, a date-derived number, a rollover at 00:00 UTC.
  • A delta-encoded input log capturing every movement change, dash, ultimate, attack, hero pick, draft pick, reroll, skip and banish for the whole run.
  • Seed replay by URL, so any night can be fought again by anyone.
  • Wallet signing of a plain-text claim, which identifies a claimant and moves no funds.

07What we cannot yet prove

This is the important section, and it is deliberately the longest.

EIGHT THINGS THAT ARE NOT TRUE YET
  1. Nothing re-simulates your run. Verification is a design, not a running service. There is no server anywhere that replays a HORDE run.
  2. Your input log never leaves your browser. It is built in memory as you play and thrown away when the tab closes. The only thing sent to us at the end of a run is a summary, seed, seconds survived, kills, level, and optionally a display name.
  3. The ladder is therefore client-reported and can be faked. A plausibility cap of roughly four kills per second is the only guard standing between the board and a fabricated number.
  4. A wallet signature proves a claim, not a run. It shows that the submitter controls that address. It says nothing whatsoever about whether the run happened.
  5. Cross-engine determinism is not pinned. The simulation uses floating-point arithmetic, and we have not published a test showing that two different browser engines produce a bit-identical result from identical inputs. The verifier will re-run the same code server-side to keep that surface small, but the tolerance question has to be answered in public before money depends on the answer.
  6. Logs are not version-stamped. Replaying a run six months from now requires the exact build of the simulation that produced it. Today’s logs do not carry that stamp, so an old log could not be trusted against a newer build.
  7. No third-party audit exists of the verification pipeline, for the straightforward reason that the pipeline does not exist. Internal adversarial review is not the same thing and we will not present it as such.
  8. There is no prize pool and no custody wallet. Nothing holds player funds. Nothing has been paid out to anybody, ever.

08What must be true before a token moves

The checklist that gates staked play. Every line is currently unchecked.

  • Input logs uploaded with the run, under enforced size and rate limits.
  • A server-side re-simulation that matches the client simulation exactly, run on every staked result.
  • A pinned, versioned simulation build, with the version stamped into every log.
  • Submissions signed and bound to both the seed and the wallet claiming them.
  • A published custody wallet address whose balance anyone can read.
  • Published disconnect rules and a published dispute process, both in force before the first table opens.
  • 18+ verification and regional gating.
  • Outside review of the verification service by somebody who does not work on it.
When a line here becomes true, it moves to the “live today” list above and this page changes on the same day. If you ever find this page claiming something the product does not do, that is a bug worth shouting about.

09Check us, right now

  • Open /api/seed and compare the number against the one printed in the corner of the game.
  • Open /api/ladder and read the response: it returns verified: false and says the board is client-reported.
  • View source on the game page and find the fixed tick, the four generators and the point where the input log is appended. It is all client-side JavaScript; none of it is hidden.
  • Play the same seed twice and watch the first wave, the first eruption and the first shrine land at the same second both times.
  • Send a friend a ?seed= link and confirm they get your night, not their own.
FOUND A HOLE?

If you can break the determinism, forge a log that reproduces, or defeat the design described above, tell us. Before there is money riding on it is exactly when we want to hear it, contact details are on the terms page.

DAWN IS NOT COMING TO SAVE YOU
Fifteen minutes, one seed, no wallet needed.
PLAY THE GAME → ← Back to the landing page