Determinism and reproducibility

The same seed always produces the same world, down to the byte, on any machine, however many times it is replayed and however many people are watching. That is a strong claim, and it is the foundation everything else on this site rests on: an experiment you cannot re-run is not an experiment.

Implementation Ruleset pre-genesis-candidate-v2 Source: src/el/rng.py, src/el/statehash.py

The problem with an ordinary random generator

A conventional simulation holds a generator, and every random decision advances it. That works until the code changes. Add one new random draw anywhere, and every subsequent draw in the entire run shifts by one. A change to how fire spreads silently changes which organism won a movement contest ten thousand ticks later. Every previous recorded run becomes unreproducible against the new code, and no experiment can be compared against another.

It also means the generator's internal state has to be saved with every checkpoint, and any parallelism has to be carefully ordered, because the answer depends on when a draw happened rather than what it was for.

Counter-based keyed randomness

There is no generator. Every random value in this simulation is a pure function of stable keys, computed on demand:

base = stream(seed, tick, purpose) u = uniform(base, entity_id) # A draw is addressed by what it is for, not by when it happened. # Mixing is SplitMix64: cheap, well distributed, exact under uint64 wraparound.
From el.rng. There is no global mutable state, and therefore no RNG state to checkpoint.

purpose is the important part. Every kind of random decision has its own permanently assigned identifier: movement steps, movement contests, offspring placement, physical mutation, neural mutation, action noise, resource growth, natural ignition, climate forcing, and more. The identifiers are never reused with a different meaning, because that would make historical runs unreproducible.

Emergent Life implementation

The property this buys is stream independence under code change. Adding a new random mechanism to the simulation means claiming a new purpose identifier, and doing so cannot perturb a single existing draw anywhere. This is what allowed phases to add thermal ignition, then climate forcing, then object manipulation, without invalidating any earlier run's reproducibility.

A second consequence: every draw is keyed on an organism's permanent identifier, never on its position in an array. Organisms are compacted in memory whenever one dies, so array positions are reassigned constantly. Keying on position would make the outcome depend on how many organisms happened to die earlier that tick.

Everyone sees the same frozen world

Within a tick, every organism perceives the world as it stood at the start of that tick. Nothing any organism does within a tick is visible to any other organism within the same tick.

This is what makes the tick order-independent. If organisms were processed one at a time against a world that updated as they went, the outcome would depend on the order, and the order depends on memory layout. Where two organisms genuinely contend for the same outcome, for example wanting to move into the same cell, the tie is not broken by whoever was processed first. It is resolved by a deterministic keyed contest with its own purpose identifier.

The state hash

The whole authoritative state is reduced to one SHA-256 digest: every field of the world, every array of the population, and the lineage registry, fed in a fixed order. It is published live in the spectator feed, and it appears at the bottom of the world history page.

Two runs agree if and only if their hashes agree at every tick. That turns a vague claim into a test, and this project uses it as one constantly:

Emergent Life implementation

The controller panel is the case where this mattered most. Reading an organism's decision means running its network forward, and there are two functions that could do that. One is the authoritative decision function, which draws exploration noise from the simulation's own random stream. Calling that from a viewing panel would consume a draw the simulation was going to make. The panel calls the other one, which is pure and draws nothing, and a test asserts that the real decision function produces identical output before and after any amount of inspection.

An invariant that stops the world

Determinism guarantees that a run is repeatable. It does not guarantee that the run is correct. For that there is a separate, executable check: total energy across all seven reservoirs is reconciled every single tick against the previous tick plus what entered minus what dissipated.

If the books do not balance within tolerance, the simulation raises and halts. It does not log a warning and continue. A universe that has quietly started creating or destroying energy is no longer running the physics it claims to be running, and continuing would produce hundreds of thousands of ticks of data that look fine and are not. See energy and metabolism.

Why the ruleset is frozen

A universe runs one physics version for its entire life. The one running now is pre-genesis-candidate-v2, checkpoint schema 13.

The rule this project holds itself to is that any change which would make the state hash evolve differently is the seed of a new universe, not a patch to an existing one. Not because changes are forbidden, but because a world whose rules changed halfway through is a world whose history cannot be replayed, and replayability is the only thing that makes its history evidence rather than anecdote.

This has real costs and they have been paid. A candidate ruleset was frozen, tested for 500,000 ticks, found wanting, and withdrawn rather than patched in place. See RN-001.

What determinism does not give you