Skip to content
Manic Microbes

Worked examples

Four cells, read line by line.

A plant, a predator, a parasite and a sentinel that can tell them apart — all four shipped with the simulator and quoted here exactly as they are written. Between them they use most of what the machine can do, and none of them contains a single instruction the engine treats as special.

Two things will look wrong if nobody warns you first: numbers are written as templates rather than as values, and labels are base pairs rather than addresses. The language page explains both, and it is worth five minutes before you start.

01The producerships in the box

The vegetable

Eats waste and an oxidant out of the water, photosynthesises them into sugar, burns the sugar, puts the waste back, and divides when it can afford to.

genomes/ancestor.mm · 227 bytes

This is the first thing that was alive in Manic Microbes, and it is still the ancestor most runs start from. It is a photo-autotroph: it makes its own food out of light and what is dissolved around it, and it needs nothing else alive in the world to survive.

Nothing in it is clever and nothing in it is optimal. The point is that it closes the matter loop and persists, so that everything else has something to be selected against.

01.1 The driver

genomes/ancestor.mm
        EXPRESS #build
        EXPRESS #feed
        EXPRESS #grow
        EXPRESS #divide
        HALT

Five instructions at the top of the genome, and they are the whole of the cell's behaviour. Each EXPRESS is an associative call: it takes a bit pattern and finds the gene in this genome whose promoter is closest to it, then calls that gene.

It is worth being precise about why that matters. If these were ordinary calls to fixed addresses, then a mutation that deleted a gene would leave a caller jumping into nothing, and a mutation that inserted a byte would shift every target. Because the binding is by similarity, a damaged promoter binds the next-best gene instead of breaking, and duplicating a gene and nudging its promoter gives you a second copy expressed under slightly different conditions.

HALT gives back the rest of the tick's instruction budget and refunds part of what it cost. The instruction pointer does not reset between ticks — it picks up where it stopped — so the cell works its way round this list continuously rather than starting over each tick.

01.2 Building a body

genomes/ancestor.mm
        GENE    #build
        IMM     40              ; param
        IMM     1               ; nucleus
        IMM     1               ; slot 1
        BUILD
        IMM     60
        IMM     3               ; chloroplast
        IMM     3
        BUILD
        IMM     50
        IMM     2               ; mitochondrion
        IMM     2
        BUILD
        RET

The machine is a stack machine, so operands are pushed before the instruction that consumes them. BUILD takes three: a param, a type from the organelle catalogue, and which of the sixteen slots to put it in. Read each group of four lines as one sentence — build a nucleus of size 40 in slot 1, a chloroplast of size 60 in slot 3, a mitochondrion of size 50 in slot 2.

The param is not cosmetic. It scales both what the organelle can do and what it costs to build and to keep. A chloroplast of 60 catches more light than one of 40 and charges more upkeep for the privilege, and there is no correct answer to which is better — it depends entirely on how much light there is where the cell happens to be.

This gene runs every tick and is mostly wasted after the first few, because BUILD on a slot that already holds what was asked for still costs the matter. A more efficient ancestor would check OTYPE first. This one is written to be read.

01.3 Feeding

genomes/ancestor.mm
        GENE    #feed
        IMM     40
        IMM     11              ; carbon dioxide, the input to photosynthesis
        EAT
        DROP
        IMM     20
        IMM     14              ; and its oxidant
        EAT
        DROP
        IMM     16
        IMM     4               ; carbon, to build a body out of
        EAT
        DROP
        RET

Three ingredients, taken straight out of the water in the square the cell is standing on. EAT takes an amount and a chemical index and returns how much it actually got — which is why each one is followed by DROP, discarding a number the cell has no use for.

The amounts are deliberately larger than one tick's throughput. EAT is clamped to what is actually there and to what the cell can still hold, so asking for too much costs nothing but the instruction. Asking for too little would cost a meal.

Chemical 11 is carbon dioxide, the waste that photosynthesis runs on. Chemical 14 stands in for dissolved oxygen. Chemical 4 is carbon, which is what a body is physically made of — and because matter is exactly conserved, every gram of it in this cell came out of the water and will go back when it dies.

01.4 Taking out the rubbish

genomes/ancestor.mm
        GENE    #grow
        IMM     255
        IMM     13              ; peroxide, out
        EMIT
        DROP
        IMM     8
        IMM     8               ; surplus sugar back to the water
        EMIT
        DROP
        RET

This nine-line gene is the most important one in the file, and it is the entire difference between this ancestor and its sibling `ancestor_sloppy.mm`.

Respiration exhales a reactive byproduct — chemical 13, peroxide — and above a threshold it damages the membrane. A cell that lets it accumulate takes damage, ages badly and dies. A cell that dumps it into the water lives, and here is the part that makes it interesting: peroxide is unstable, so out in the water it decomposes back into carbon dioxide, which is food again.

So the tidy ancestor is not merely surviving. It is running a slightly larger loop than the sloppy one, at the cost of two instructions. When the M2 acceptance test seeds both and asks which takes over the population, this is the difference it is measuring — and nothing in the engine knows that one of these cells is the tidy one.

01.5 Dividing, but only if it can afford to

genomes/ancestor.mm
        GENE    #divide
        ONE
        ZERO
        OGET                    ; membrane slot 0, reading 1: energy
        IMM     100
        CMP                     ; -1 if poor, 0 or 1 if it can afford to divide
        ONE
        ADD                     ; 0 if poor, non-zero if not
        JMPZ    lean            ; too poor — skip the whole copy, do not sleep through it
        GLEN
        SETLN
        GLEN
        BUD
        DROP
        ZERO
        SETPA
        ZERO
        SETPB
loop:
        COPYB
        LOOPLN  loop
        SPLIT
lean:
        RET

The first eight lines are a guard, and they are a nice piece of stack arithmetic. OGET reads an output from an organelle: reading 1 from slot 0 — the membrane, which is always the cell's own self-sensor — gives its current energy. CMP leaves the sign of the subtraction, so −1 if the cell has less than 100, 0 or 1 if it has enough. Adding one turns that into zero-or-not, and JMPZ jumps only on zero.

A cell that starts a division it cannot finish has spent the matter and the energy and gets no daughter. The guard costs eight instructions and is worth every one of them. A poor cell jumps to lean: and returns, skipping the copy rather than sleeping through it — this genome would rather spend what is left of the tick on the next gene than hand it back.

The rest is the replication loop, and it is the only place reproduction happens. There is no divide() in the engine. The cell asks how long it is, sets that as a counter, allocates a daughter buffer, points a read pointer at its own byte zero and a write pointer at the daughter's, and then copies one byte at a time until the counter runs out. COPYB moves the byte and decrements the counter; LOOPLN jumps back while the counter is not zero. Two instructions, and everything alive here descends from something that ran them.

Copy errors happen inside that loop. Each byte has a chance of coming out wrong that depends on the nucleus's fidelity setting and the energy spent on it — high fidelity costs more. So the mutation rate of this lineage is written in its own genome and paid for out of its own budget.

What it demonstrates

That a working organism is small. Two hundred and twenty-seven bytes, five genes, no sensors, no motility and no idea that anything else exists — and it will fill a slide.

In the primordial soup, sixteen of these become 861 cells inside two thousand ticks, and the first lineage to replicate without help does so at tick 500. By then it has already split: a second species diverges at tick 197 and a third at 1,424, and the run ends with all three alive. None of that is in the file. It is what happens when something that copies itself imperfectly is put somewhere it can afford to.

02The consumerships in the box

The hunter

The same body as the vegetable, plus a spike that damages what it touches and a lysosome that digests what the spike leaves behind.

genomes/predator.mm · 334 bytes

There is no predation in this engine. There is no attack instruction, no targeting, no damage type and no code path that knows one cell is eating another. There is a spike, which damages whatever it is in contact with; damage, which kills; death, which deposits the body as carrion; and a lysosome, which digests carrion. Predation is what those four things look like from far enough away.

This genome ships next to `hunter.mm`, which is the same idea with only half of it discovered. The hunter builds a spike and no lysosome, so it kills without being able to eat — and since carrion is a public good, anything standing nearby with a stomach gets the meal. A hunter with no lysosome pays for its neighbours' lunch.

02.1 A bigger nucleus, and why it needs one

genomes/predator.mm
        GENE    #build
        IMM     56              ; nucleus: 448 bytes, room for 342 and some drift
        IMM     1
        IMM     1
        BUILD
        IMM     55
        IMM     3               ; chloroplast — smaller than the ancestor's, because the
        IMM     3               ; upkeep has to leave room for the spike
        BUILD
        IMM     50
        IMM     2               ; mitochondrion
        IMM     2
        BUILD
        RET

Nucleus capacity is the param times eight bytes, and a genome that will not fit in its nucleus is truncated at the next division. This genome is 342 bytes against the ancestor's 230. At the ancestor's param of 40 the nucleus holds 320 bytes — so every daughter would be cut off mid-file, losing the tail of the divide gene, and the lineage would divide once into something sterile and stop.

So the param goes to 56. That is not a workaround, it is the mechanism working: genome bloat costs a bigger nucleus, a bigger nucleus costs upkeep, and a lineage that grows its genome without earning the difference is outcompeted by one that did not. There is no rule against long genomes anywhere in the engine. There is just a bill.

Notice the chloroplast has gone the other way — 55, down from the ancestor's 60. The upkeep budget has to make room for the spike, so being a predator here means being a slightly worse plant. That trade is not encoded anywhere either; it is what happens when everything costs something out of one account.

02.2 A weapon its own children can survive

genomes/predator.mm
        GENE    #arm
        IMM     80
        IMM     12              ; spike
        IMM     5
        BUILD
        IMM     4
        IMM     2
        SHL                     ; 16 — see above; 512 sterilises the lineage
        ZERO                    ; control 0 — signed extension
        IMM     5
        OSET
        RET

BUILD puts a spike in slot 5, and then OSET sets its control input. OSET takes a value, which control input to write, and which slot — so this writes 16 to control 0 of slot 5, which is the spike's extension.

The 16 is computed rather than written, and that is a deliberate piece of genome craft: an immediate's template is only as long as the number needs, so a small IMM and a shift is shorter and more mutable than spelling the number out. A mutation to the shift count moves the extension by a factor of two; a mutation to the IMM moves it a little. The genome has two dials of different coarseness on the same number.

The number itself is the interesting part, and it started out at 512. A spike damages what it touches, and it has no idea what it is touching — the engine filters victims by “not me”, “occupied” and “within reach”, and that is the whole list. There is no kin check and there must not be one, because a special case for “my own offspring” is exactly the sort of flag that would stop this being emergence. A daughter is born inside her mother's reach, and this genome has no cilia, so neither of them can leave.

One founder in the primordial soup, 2,400 ticks, sweeping only the extension: 4 → 55 cells, 16 → 11, 32 → 3, 64 → 1, 128 → 1, 512 → 1. Everything else was ruled out by measurement rather than argument — not the divide guard, not the energy budget, not the copy loop, not the want of prey. It divides perfectly well. The daughters die.

Those numbers are much smaller than the ones this page used to carry, and the shape of the curve is the part that survived: every doubling of the extension costs most of what is left, and past sixty-four the lineage does not get a second generation at all. The engine's whole tempo was halved between the two measurements. Which is the argument for re-running a sweep rather than quoting one — the conclusion held and every figure in it moved.

So the finding this genome exists to carry is that an armed cell which cannot tell kin from prey, and cannot move away from either, has to carry a weapon its own children can survive. Sixteen is one point of damage a tick — a prey cell with a membrane of twenty-four takes about twenty-four ticks of unbroken contact to kill, which is a real weapon and a slow one. Half extension is not a weapon at all. It is a sterility switch.

02.3 The stomach

genomes/predator.mm
        GENE    #digest
        IMM     70
        IMM     11              ; lysosome
        IMM     6
        BUILD
        IMM     255
        IMM     2
        SHL                     ; 1020, near full throttle
        ZERO                    ; control 0 — digestion rate
        IMM     6
        OSET
        RET

Ten lines, and they are the whole difference between this genome and `hunter.mm`. A lysosome in slot 6, opened nearly all the way.

Carrion is chemical 15, and it is deliberately not flagged as structural — a cell cannot build a body out of it directly. It has to be digested into something usable first, and a lysosome is the only thing that does that. This is what makes scavenging a distinct trade rather than a free bonus for standing near a corpse, and it is why the spike alone is a bad deal.

It also means the predator does not need to kill in order to eat. A lysosome pays off next to anything that died, however it died. Predation and scavenging are the same organelle pointed at different opportunities, and the engine does not distinguish them because there is nothing to distinguish.

What it demonstrates

That a trophic level is an accounting outcome rather than a category. Nothing marks this cell as a predator. It has a spike and a stomach and pays for both, and the analysis layer calls it a predator afterwards because of what it is observed doing.

It also demonstrates the cost. Run it alone in the soup and sixteen become 164 cells in two thousand ticks, where sixteen ancestors become 861. Carrying a weapon and a stomach is expensive, and it only pays where there is something worth eating.

03The parasiteships in the box

The virus

Finds a neighbour, guesses its receptor key, opens a channel into it, and overwrites its genome with a copy of its own.

genomes/parasite.mm · 346 bytes

There is no virus in this engine either, and there is a specific design decision behind that. Writing a byte into your own nucleus and writing a byte into someone else's are the same instruction — INJECT takes a junction index, and one reserved index means yourself. Self-modifying code and other-modifying code are not two mechanisms.

Which means a parasite is not a feature. It is what you get when a cell forms a soft junction and points the copy loop down it. This genome does exactly that, and the loop that does the infecting is the replication loop from the ancestor with one instruction swapped.

03.1 The body it needs

genomes/parasite.mm
        GENE    #build
        IMM     48              ; nucleus: 384 bytes, room for 351 and some drift
        IMM     1
        IMM     1
        BUILD
        IMM     60              ; a chloroplast, to pay its way while it hunts
        IMM     3
        IMM     3
        BUILD
        IMM     50
        IMM     2
        IMM     2
        BUILD
        IMM     12              ; a touch sensor, to notice something to infect
        IMM     9
        IMM     5
        BUILD
        IMM     12              ; and a port for the junction to sit in
        IMM     10
        IMM     6
        BUILD
        RET

Two organelles the other two genomes did not need. A touch sensor in slot 5, which reports how many things the cell is in contact with and gives a handle for each, and a junction port in slot 6, which is the socket a junction actually occupies.

It also keeps a full-sized chloroplast. This is a parasite that still makes its own living while it looks for a host, which is the honest way to start — a lineage that has given up its own metabolism cannot survive the gap between victims. Real parasites shed those genes later, once the host is reliable enough to depend on, and there is nothing stopping that happening here: a mutation that breaks the chloroplast is neutral while hosts are plentiful and fatal when they are not.

03.2 Three states, and a guess at the key

genomes/parasite.mm
        GENE    #infect
        ZERO                    ; junction port, output 0 — how many junctions do I have
        IMM     6
        OGET
        JMPNZ   connected
        ZERO                    ; touch sensor, output 0 — how many contacts
        IMM     5
        OGET
        JMPZ    idle            ; nothing to work with — skip the attempt entirely
        RAND
        IMM     127
        AND                     ; one guess at its receptor key, 0-127
        ZERO                    ; kind 0 — soft, a channel rather than a strut
        ONE                     ; touch sensor, output 1 — the handle it reported
        IMM     5
        OGET
        JOIN
        DROP                    ; one bit comes back, and one bit is all it is worth
idle:
        RET

The cell has no memory of what it was doing, so it works out which state it is in by asking its organelles. Already joined to something? Go and write. Touching something but not joined? Try to get in. Neither? Return, and let the next gene have the rest of the tick.

This is what a genome does instead of keeping state, and it is more robust than the alternative — a cell whose junction was broken by something else does not get stuck believing it still has one.

Every cell has a seven-bit receptor key, and guessing it wrong costs energy rather than being refused outright — consent here is economic. So a parasite has two options, and this one takes the crude version: RAND masked to 0–127 is a single guess, thrown at whatever it happens to be touching. On average that is sixty-four attempts, each costing a tick. The alternative is to specialise on whichever key is common in the population, which is cheaper and leaves you helpless the moment the hosts change theirs.

The DROP is the important line and it is easy to miss. A failed JOIN returns one bit — it did not work — and deliberately not the distance to the true key. If it returned the distance, the key would be hill-climbable in about seven probes and parasitism would be free. Making the probe uninformative is what keeps the arms race an arms race.

That arms race has a cost on both sides, which is what makes it interesting rather than a one-way ratchet — and the bill the host pays for changing its key is set out with the junction mechanics rather than here.

03.3 The infection loop

genomes/parasite.mm
connected:
        GLEN
        SETLN                   ; LN = my own length
        ZERO
        SETPA                   ; read from my byte 0
        ZERO
        SETPB                   ; write to its byte 0
pump:
        ZERO
        INJECT                  ; its nucleus[PB] = my genome[PA]; PA++, PB++, LN--
        DROP
        LOOPLN  pump
        ZERO
        LEAVE                   ; it is me now; let go and find another
        RET

Compare this to the ancestor's replication loop and the point of the whole design becomes obvious. Both ask how long they are, set that as a counter, point a read pointer at their own byte zero and a write pointer at byte zero of the destination, and then copy one byte at a time until the counter empties. The ancestor's destination is a daughter buffer it allocated with BUD. This one's destination is somebody else's nucleus, reached down a junction.

One instruction is different. COPYB becomes INJECT, and both advance the same pointers and decrement the same counter, for exactly that reason — a copy loop should read the same whether the target is self or a neighbour. Anything else would have made horizontal gene transfer a special case, and it must not be one.

The target keeps running the whole time. It is not paused, not trapped, not notified. Its instruction pointer wraps modulo its genome length, so there is no invalid state to land in — it simply continues executing code that is being replaced underneath it, and what it does while half-rewritten depends on which half it is currently in.

LEAVE at the end is what makes this reproduction rather than vandalism. The host is now running a copy of the parasite's genome, which includes this gene, so it will go looking for a host of its own. The lineage grew by one without dividing once.

What it demonstrates — and how the answer changed

That the mechanism is real and costs what it should. Alone in the soup this genome sustains a population perfectly well, paying its way with its chloroplast and infecting on the side.

For a long time this page reported that it loses. Against an older build it did, comprehensively — the ancestor eliminated it a few thousand ticks in, and the arithmetic was the explanation: converting a host takes as many injections as the parasite has bytes, which at sixteen instructions a tick is some seventy ticks of doing nothing else, plus however many failed key guesses came first. Division is simply faster than that.

Then it was close. Over five seeds of a twenty-thousand-tick arena match the parasite took three, seed 1 finishing 618 to 577 in its favour and two going the other way by a narrower margin — a coexistence rather than a knockout.

Re-run against the current engine, it is not close any more, and it has gone the other way entirely: the parasite takes all five seeds, by roughly two to one, and neither side is ever eliminated. Seed 1 finishes 651 to 373. The narrowest of the five is 659 to 354. The genome has not changed a byte across any of this.

So this result has now reversed once and then widened, and nothing in either file moved — the balance of the world underneath them did. Which is the argument for re-measuring rather than quoting, and the reason this page keeps saying so: a result with a date on it is a result. A result without one is folklore.

04The discriminatorships in the box

The sentinel

The same hunter, plus a badge, a touch sensor and one gene of opinion — and it puts the spike away when the thing in front of it is wearing what it is wearing.

genomes/sentinel.mm · 450 bytes

This is the predator with the other half discovered, and shipping the pair is the point. The predator holds its spike out permanently and so kills its own daughters, which is why its weapon had to be turned down to a sixty-fourth of full extension before it could breed at all.

This one asks a question first. Every cycle: is the nearest thing wearing what I am wearing? If it is, the spike goes away. If it is not, the spike goes all the way out — to the setting that sterilised the other genome. A weapon you can put away is a weapon you can afford to make sharp.

It is the longest genome in the library and it carries an extra organelle drawing upkeep every tick. It wins anyway, and by a lot.

04.1 Eight genes instead of four

genomes/sentinel.mm
        EXPRESS #build
        EXPRESS #dress
        EXPRESS #arm
        EXPRESS #digest
        EXPRESS #watch
        EXPRESS #feed
        EXPRESS #grow
        EXPRESS #divide
        HALT

The vegetable's driver is four lines. This is eight, and the two that are new are the whole subject: dress puts the colours on, and watch decides every cycle whether the weapon should be out.

Note where watch sits — after the body is built and before the cell feeds. The decision is remade every time round the loop rather than latched, because the thing standing next to you changes and a cached answer would be wrong the moment it moved.

04.2 Putting the colours on

genomes/sentinel.mm
        GENE    #dress
        IMM     210
        SETBADGE
        RET

Three instructions, and this is the entire signalling mechanism. SETBADGE writes fifteen bits that anything touching this cell can read, that the engine does absolutely nothing with, and that cost nothing to wear and nothing to forge.

That last part is not a weakness. A badge that could not be forged would be an identity card issued by the physics, and the engine deciding what a family is would be exactly the special case that stops this being emergence. Another lineage is free to wear 210 without meaning it — which is the arms race, and it is supposed to be available.

The badge is also inherited, so a daughter is already wearing this before she has executed a single instruction. She has to be: the ticks in which a newborn is in danger are precisely the ticks before her first cycle has run. Setting it here as well costs two instructions and keeps the marker and the genome from drifting apart.

A founder is the exception, and it is worth knowing before you place two of them touching. She is seeded bare-faced and does not dress until her first cycle completes, so for a few ticks she is a stranger to her own kind.

04.3 The weapon and the eye

genomes/sentinel.mm
        GENE    #arm
        IMM     80
        IMM     12              ; spike
        IMM     5
        BUILD
        IMM     40
        IMM     9               ; touch sensor
        IMM     7
        BUILD
        RET

A spike in slot 5 and a touch sensor in slot 7. The sensor is the only structural difference from the predator and it is not free — another organelle, drawing upkeep every tick, on a lineage that was already the most expensive thing in the library.

What it buys is the right to carry the spike at full extension, and that turns out to be worth far more than it costs. Notice that this gene does not set the extension at all. That decision belongs to the next one, because it is not a property of the body — it is a property of the moment.

04.4 Friend or foe, decided every cycle

genomes/sentinel.mm
        GENE    #watch
        ZERO
        IMM     7               ; touch sensor reading 0: how many are in reach
        OGET
        JMPZ    kin             ; nobody in reach, so nothing to point it at
        IMM     3
        IMM     7               ; reading 3: the nearest one's badge
        OGET
        IMM     24              ; membrane reading 24: my own badge.
                                ; **It has moved twice now.** The membrane's scalars are laid out
                                ; *after* the chemical readings, so widening the table shifts
                                ; every reading past them: 21 originally, 22 when dinitrogen
                                ; landed at ISA 11, 24 when calcium and carbonate landed at
                                ; ISA 12. That is what the version stamp is for, and it is the
                                ; one sharp edge of adding a chemical.
        ZERO                    ; slot 0, the membrane
        OGET
        CMP
        JMPZ    kin
        IMM     128
        IMM     2
        SHL                     ; 512 — half extension, the setting that sterilised predator.mm
        ZERO                    ; control 0 — signed extension
        IMM     5
        OSET
        RET
kin:
        ZERO                    ; sheathed
        ZERO
        IMM     5
        OSET
        RET

Read what the nearest thing is wearing. Read what I am wearing. Compare. CMP leaves zero when they match, so JMPZ is “one of mine — put it away”.

Reading its own badge back rather than comparing against the literal in #dress is the detail that makes the lineage able to move. A mutation that changes the badge changes what this cell wears and what it answers to in the same stroke, so a lineage can drift its colours and still know its own children — and diverge from its cousins as it goes. Hard-coding the number here instead would make every such mutation an instant matricide.

The comment on the 24 is the sharpest illustration on this page of what the version stamp is for, and it is worth reading twice. The membrane's own scalars sit after its chemical readings, so every chemical added to the world shifts them along: that reading was 21 when this genome was written, 22 once inert dinitrogen landed, and 24 once calcium and carbonate did. The bytes did not change. What they mean did. An archived genome replayed under the wrong instruction set is not slightly wrong — it is reading its own oxygen level and calling it a badge.

The first test is the one that is easy to leave out and expensive to leave out. A cell touching nobody reads a badge of zero, which differs from its own — so without it a solitary cell arms permanently and is the predator again, paying the dearest upkeep in the catalogue to menace open water.

It asks the sensor how many things are in reach. It used to ask what the nearest one was wearing and treat a zero as an empty space, which looks equivalent and is not: somebody wearing nothing also reads zero, and that is every founder the world seeds and every genome in this library but two. So the guard against menacing open water was also a guard against attacking anything that had not chosen a badge, and this cell went through entire runs without ever drawing. Eight of these among eight ancestors over eight thousand ticks went from nought wounds and nought ticks with the spike out to a predator that draws on a stranger and sheathes for its own children. The sensor reading it needed had been there since the motility milestone; the genome was asking the wrong question of something that could already answer the right one.

And the 512 is the joke of the whole file: it is exactly the extension that sterilised the predator. The same number that made a weapon unusable makes this one formidable, because the difference was never the weapon.

What it demonstrates

That recognition is worth paying for, and that nothing in the engine had to know what a friend is. TouchSensor reading 3 reports that the thing in front of you is wearing 210 and says nothing whatever about what 210 means. This genome is the entire opinion that 210-like-me means do not stab.

Head to head against the predator over twenty thousand ticks, the sentinel does not merely win, it clears the slide. On the first two seeds it eliminates the predator outright — at tick 15,640 and at tick 14,172 — and on the third it finishes 590 to 1, while carrying a spike thirty-two times sharper, an extra organelle, and a hundred and sixteen more bytes than its opponent. Seeded into the soup on its own terms it reaches 410 cells by tick 2,000, against the predator's 164.

Two limits, both honest rather than oversights. It reads the nearest neighbour only, so standing between a daughter and a stranger it will arm, and the spike damages everything within reach — including her. And it compares badges rather than identity, so a mimic wearing 210 is safe from it for free. That is not a bug in the gate. That is the next move in the game, and it is available to anything that stumbles onto it.

Why they are the same shape

Reproduction and infection are the same loop.

Set the two side by side with the scaffolding stripped out. The left one makes a daughter. The right one makes a convert. They differ by one instruction, and that is a decision rather than a coincidence.

copying yourself into a daughter

ancestor.mm
        GLEN
        SETLN
        GLEN
        BUD
        DROP
        ZERO
        SETPA
        ZERO
        SETPB
loop:
        COPYB
        LOOPLN  loop
        SPLIT

copying yourself into a neighbour

parasite.mm
        GLEN
        SETLN
        ZERO
        SETPA
        ZERO
        SETPB
pump:
        ZERO
        INJECT
        DROP
        LOOPLN  pump

COPYB and INJECTadvance the same two pointers and decrement the same counter. The only thing that differs is where the write lands: into a buffer the cell allocated for a daughter, or through a junction into another cell’s nucleus.

That is why viruses are emergent here rather than implemented. Nothing in the engine knows the word. There is one interface for reading and writing genome bytes, and whether the target is yourself or somebody else is an argument to it.

Measured, not asserted

What each of them actually does.

Every number here came out of the simulator's own headless runner, re-run against the build that is in the repository today rather than quoted from the last time I looked.

GenomeFileBytesCells at tick 2,000Species
The vegetableancestor.mm2278613
The hunterpredator.mm3341642
The parasiteparasite.mm3466941
The sentinelsentinel.mm4504101

All four in the same world — the primordial soup, sixteen cells seeded, the scenario's own seed. Population at tick 2,000. Re-measured against v0.4.0; the parasite's figure fell by a quarter between releases without a byte of it changing, which is the reason these are re-run rather than carried forward.

Reproduce any of it

Each row is one command, and the same seed gives the same answer on any machine.

$mm-cli run scenarios/soup.ron --genome genomes/ancestor.mm --ticks 2000
$mm-cli match genomes/ancestor.mm genomes/predator.mm

The parasite used to lose, and now it does not

This page reported for a long time that the ancestor eliminated the parasite a few thousand ticks in. Against the current build it does not: over five seeds of a twenty-thousand-tick match the parasite takes all five, by about two to one, and neither side is ever wiped out.

Nothing in either genome explains that — the balancing between the two builds does. It is the clearest argument I have for re-running the numbers instead of quoting them, and for putting a date on anything measured.

Now write a worse one and see what happens to it.

The editor will disassemble anything alive on the slide, let you set a breakpoint on it, and inject an edited genome into a cell while the world is still running.