← BRLabs Research / Computational Life source ↗

Primordial soup

Random byte programs collide, execute over each other, and split apart again. No fitness function, no selection, no goal. Watch for the moment the noise stops being noise.

New to this? The controls ship on a suggested setup, just press Run and watch the Fertile programs number. Every control and metric is explained below, and hovering any of them shows a one-line note.

The soupโ€”
1× scroll to zoom · drag to pan · hover a program to read it
program โ€” byte โ€” value โ€”
Hover over the soup to read a program.

Ten instructions, and two data heads, h0 and h1: that move independently along the tape. Instructions and data share that tape, so a running program is rewriting the same bytes it is being read from.

>move h0 one cell right
.copy the byte under h0 to h1
<move h0 one cell left
,copy the byte under h1 to h0
}move h1 one cell right
[skip past the matching ] if the byte under h0 is zero
{move h1 one cell left
]jump back to the matching [ if that byte is not zero
+add 1 to the byte under h0
0zero, the value that ends loops
−subtract 1 from the byte under h0
·any other byte, does nothing
Epoch0
Fertile programsโ€”
Living speciesโ€”
Top code k-merโ€”
Instruction densityโ€”
Byte entropyโ€”
k-mer entropyโ€”
Speedโ€”
Fertility over timeโ€”
━ fertile fraction, programs that reproduce
Dominant code sequence
โ€”
No self-replication detected.
Species: lineages by opcode sequence tracking off
gen
carriers
gen at zero
hover a row to light up its members, click to keep it lit while you scroll up
Turn on tracking to catalogue every self-replicating lineage as it appears. A lineage is a distinct sequence of opcodes; inert bytes between them are ignored.
New here? Start with the suggested settings and press Run
The 30-second version
The grid is a soup of thousands of tiny programs, each a string of random bytes drawn as a row of pixels. Every epoch, pairs are picked at random, run over each other, rewriting each other's bytes, and split back. Nothing is selecting for anything. Watch the Fertile programs number: while it sits near zero the soup is just noise; when it climbs, programs that copy themselves have appeared on their own, and life is spreading. Press Run and leave it, the shipped settings (second head at 64) are tuned to reach that moment in a minute or two.
Want the original?
Set Second head starts at back to 0 for the paper's canonical setup, where emergence is far rarer in a soup this small. Every knob below is explained in the two sections that follow.
The panel: what each number means
Epoch
The soup's clock. One epoch pairs a batch of programs at random, runs each pair, and splits them back. Also called a generation.
Fertile programs
The headline. The share of sampled programs that made a copy of themselves when paired with random partners, the direct measure of life, and the one thing here that detects a replicator it has never seen. A random soup scores a few percent by chance, so treat anything under ~5% as noise.
Living species
How many distinct self-replicating lineages are alive right now. A lineage is one sequence of opcodes, ignoring the inert bytes between them. Needs track lineages on.
Top code k-mer
The most common run of five opcodes in the soup at this instant. Meaningless while the soup is random; once a replicator dominates, its signature shows up here.
Instruction density
The fraction of bytes that are one of the ten instructions rather than inert data. Random noise sits near 4%; functional programs are denser, so this rises as structure forms.
Byte entropy
Disorder of the byte values, 0โ€“8 bits. Pure noise sits near the maximum of 8; it falls as the soup fills with copies of one successful program.
k-mer entropy
Disorder measured over five-opcode sequences instead of single bytes. It drops sharply the moment one code sequence starts to sweep, usually the earliest visible sign of emergence, before the fertility number moves.
Speed
Epochs computed per second. About your machine, not the biology.
Fertility over time
The pink trace plots the fertility number as the run goes, so you can see the phase change, the jump from flat noise to a rising curve, rather than just its current value.
The controls: what each one does
Seed
The random-number seed. Same seed + same settings = a byte-identical world on every machine, so a run is reproducible from this one number. Change it to draw a different soup.
Programs
The population size, how many tapes live in the soup. More programs means more encounters per epoch, so a rare replicator turns up sooner, but each epoch is slower.
Tape edge
What happens when a head walks off the end. wrap: circular tape. invalidate: the program ends. saturate: the head sticks at the edge.
Mutation rate
Chance per byte, per epoch, that a byte is replaced with a fresh random value, applied from outside the programs. At 0 there is no external mutation; every variation comes only from programs rewriting one another. Even a small value (the range is 0 to 0.01) changes the outcome dramatically.
Second head starts at
Where the second data head begins on the 128-byte pair. 0 is the paper's canonical, hard setup. Offsetting it (64 = the partner's first byte, the shipped default) lets copying begin immediately, so emergence becomes common.
Unmatched bracket
What a loop [ or ] with no partner does. ends program is the paper's spec; no-op ignores it and keeps running.
Plant replicator
Inject a known, hand-built replicator instead of waiting for one to emerge, a way to watch what a working one does. demo A and demo B are two different hand-found replicators.
Track lineages
Turns on the species catalogue and its columns (scan every, species at, dead after). It runs a full-soup census, which costs a little speed.

Fertile programs is the measurement that assumes nothing: it samples the soup, pairs each program with random partners, and counts the ones that come out of the encounter having made a copy of themselves. It detects life it has never seen before, which is the whole point, since a spontaneously emerged replicator has a shape nobody chose. The sample is 64 programs, so the reading moves in steps of ~1.6%, and a purely random soup already scores a few percent by accident; treat anything under ~5% as noise.

Species tracking groups programs by their sequence of opcodes, the active instructions, ignoring the inert filler between them. Two programs with the same opcode spine are the same species even if their junk bytes differ. Every figure in that table is an exact count taken by a full scan of the soup, so there is no statistical noise, only temporal resolution: everything is measured as of the last scan, every N generations as you set it. % original is how many members still carry the founder's exact 64 bytes, versus the cloud of variants that drift away from it while the species stays alive.

Nothing here mutates by design: with the mutation rate at zero, all variation comes from programs rewriting themselves as they run. Every byte in the soup is one pixel. Given the same seed and settings this runs identically on every machine, the simulation is integer-only and fully deterministic, so a seed reproduces a world exactly. Results are bit-identical to soup.js in Node. The two replicators offered under "plant" are hand-found, not emergent, a way to watch what a working replicator does without waiting for one to arise.