The Fitness Function Comes Out
Fitness moves into the creature
Four pages of arena made every decision by reading one column: which genomes entered a tournament, which of the four won it, which genome crossed into the next generation untouched, and which of two animals supplied a gene. A creature makes a child when its store closes a tick at or above the price of that child.
The price is the child's own body priced back through the same conversion a mouthful came in at, plus the store the child opens with. The grams of the child come out of the parent's store energy, so nothing in the world receives free flesh.
The arena's number is useful because it is clean, but it is still outside the world. A valley that only changes when a separate score says who may breed is an arena with weather painted on it. The food web needs reproduction to happen inside the tick that earned it.
The birth rule runs after action, digestion and burial. That order gives the parent a full tick to earn the store it spends, prevents a dead creature from breeding, and records one event stream instead of two competing books.
The page proves one birth and one failed birth, then turns the score column off for six years. Population, plant mass and lineage counts become consequences of the tick rather than inputs to a selection loop.
Birth cost from food value
A birth has to cost something. Free, every creature would breed on every tick it was alive and the roster would double every hundred ticks. So there is a price, and the first question is where the number comes from.
Any number picked here is a term of a fitness function. Set the price at three hundred and the valley now prefers animals that can reach three hundred, which is a statement about what a good animal is, written by a person, exactly as the arena's score was. The price has to come out of the world's own arithmetic or a score has been smuggled back in under another name.
It does come out of the world's arithmetic, and the exchange rate was fixed by the grazing
chapter. A bite turns grams into energy at the animal's Convert: a quarter of
a gram at a conversion of four is one unit in the store. Run that the other way and it
says what a gram of body costs to build. A child of forty grams, at a conversion of four,
is one hundred and sixty units, and there is no choice anywhere in that sentence.
The second half of the price is the store the child opens with, and this valley hands over half a full one. A newborn with nothing in it starves before it has walked anywhere, and a newborn with a full store could pay for a child of its own before it had ever found food, which would let a lineage spend one animal's meal four generations deep.
// internal/gene/birth.go
// Opening is the share of a full store a newborn is handed. Half is a
// working store and not a starving one: the child can pay its own
// upkeep for as long as it takes to find its first mouthful, and it
// cannot pay for a child of its own until it has fed itself.
const Opening = 0.5
// Costs is what a child of this row costs the parent that makes it, in
// energy units out of the store.
//
// Two pieces, and neither of them is a price anybody chose. The first
// is the body: a child of Bulk grams, built at the same Convert a
// mouthful of tissue came in at, which is a bite run backwards. The
// second is the store the child opens with, handed over as energy and
// staying energy. Nothing is manufactured either way: the grams come
// out of energy the parent ate for, and the store is energy moved from
// one animal to another.
func Costs(k beast.Kind) float64 { return k.Bulk*k.Convert + k.Full*Opening }
// Ready reports whether this creature closed a tick with enough in the
// store to pay for a child of its own row. It is the threshold the
// breeding pass reads and the one a second parent has to clear too, and
// it is the whole of what this valley checks before making an animal.
func Ready(b *beast.Beast) bool { return b.Store >= Costs(*b.Kind) }
$ go run ./cmd/kin -mode price
kin: what a child of the founding row costs, in energy units
the row a founder is stamped out of
grams of body 40.0000 Bulk
energy a gram of tissue is worth 4.0000 Convert
energy the store holds when full 400.0000 Full
energy the standing body costs a tick 0.1600 Bulk x Basal
the price of a child of that row
the body, at the bite's own rate 160.0000 40 x 4.0
the store the child opens with 200.0000 400 / 2
a child costs 360.0000 of a store of 400
what paying it leaves behind
left in the parent's store 40.0000
ticks that covers a standing body 250.0
grams of tissue that would refill it 90.0000
bites of that, at 0.2500 grams each 360.0
ticks of eating, one bite every two 720.0
what a birth spends, whatever any of the numbers say
who the second parent is 1 stream 18
which parent each gene came from 396 stream 17
the copy's mistakes 790 stream 16
where the child is set down 2 stream 20
a birth costs 1189
Three hundred and sixty of a store that holds four hundred is the whole reproductive biology of this valley. An animal has to get to ninety percent of full, and paying leaves it forty units, which is two hundred and fifty ticks of standing still and far fewer of walking about. Filling the store back up means ninety grams of standing plant, and a bite occupies two ticks, so that is seven hundred and twenty ticks of eating without one wasted. A browser buys a child with a fifth of a year of perfect feeding and spends the next two hundred and fifty ticks two bad decisions from stopping.
Work the founding row's number by hand, because a reader who can do this can price any creature the ranges allow. The child is forty grams of tissue, and tissue is worth four energy units a gram to this animal, the same number the mouth uses: a bite of a quarter of a gram lands one unit in the store. So the body is
body = Bulk × Convert = 40 × 4.0 = 160 energy units
and the grams that come out of it are real grams. They were plant tissue, they went through a mouth, they were counted as energy, and the same conversion turns some of that energy back into standing mass.
The second half is the store the child opens with, and it stays energy throughout:
open = Full ÷ 2 = 400 ÷ 2 = 200 energy units
Add them and a child of the founding row costs
price = Bulk × Convert + Full ÷ 2 = 160 + 200 = 360
out of a store that tops out at 400. Two rows are involved, and they are different
rows. The parent is asked the question against its own, because that is the
only one available before a child exists; but the child is made first and charged
second, so what leaves the store is worked out of the child's Bulk,
Convert and Full. A child whose body gene came out seven percent
larger costs
price = 42.9896 × 4.0 + 200 = 371.9584
which is more than a parent standing at 360.2200 can carry, and that birth does not happen. The run further down this page is that exact refusal, and it is the first thing that ever happened in the valley it comes from.
One consequence to carry into the long run at the bottom of the page. A creature with a
smaller Bulk is cheaper to keep standing, since upkeep is Bulk ×
Basal a tick, and cheaper to make a child of, since the body half of the price is
Bulk × Convert. One gene, two bills. Nothing in the code knows that.
Births run after burial
A creature phase does four things in a fixed order: it builds one reading of the world, casts every fan against that reading, steps the roster from the first animal to the last, and buries whatever stopped standing. All of them share the reading, so an animal stepped ninth sees exactly the world an animal stepped first saw.
There is one place in that order a new animal can go, and it is after all four. Put a newborn on the roster in the middle of the stepping loop and the index every other creature is reading stops describing the valley they are standing in; it is addressed by cell, so the next fan cast asks it about a coordinate and gets an answer that was true one animal ago. The genome chapter cut the seam for exactly this and left it empty: one function field on the roster, called once a phase after the burial, with nothing in this book registered into it until now.
// internal/beast/roster.go — the closing lines of Roster.Phase
if !r.Hasty && len(died) > 0 {
r.bury(v, died)
}
if r.Born != nil {
r.Born(v)
}
return died, refused
}
What registers into it lives in internal/gene, and it has to. The creature
package spent its one allowed addition on that field, so beast.Beast has
nowhere to put four hundred numbers. What it does have is identities, handed out by the
roster, so the genomes live in a pool keyed by one, on the side of the module where every
random draw in this volume already happens.
// internal/gene/birth.go, continued
// Pool is every genome the valley is running and the pass that makes
// new ones. It owns the four generators a birth spends, the map from a
// living body to the genome it was stamped out of, the pedigree, and
// the log.
type Pool struct {
Roster *beast.Roster
Rates Rates
Sex float64 // the share of births that have two parents
Founders int // creatures this pool was handed rather than made
Minted float64 // grams of body it has built out of store energy
Made int // births that went ahead
Refused int // births whose genome cost more than the store held
Log []Event
genes map[sim.EntityID]*Genome
kin map[sim.EntityID]Kin
mate *rand.Rand
mix *rand.Rand
mut *rand.Rand
place *rand.Rand
near []*beast.Beast
}
// Breed is the pass that goes into beast.Roster.Born, and it is the one
// step this volume adds to the creature phase.
//
// The roster is walked once, in roster order, and at most one child is
// made per parent per tick. The length is taken before the walk starts:
// a creature born on this tick goes on the end of the list, is not
// asked for a child of its own, and is not stepped until the next phase
// builds a view that contains it.
func (p *Pool) Breed(v *terra.Valley) {
live := p.Roster.Live
n := len(live)
for i := 0; i < n; i++ {
b := live[i]
g, ok := p.genes[b.ID]
if !ok || !Ready(b) {
continue
}
p.Asked++
mate := p.suitor(b, live[:n], i)
p.Picks++
with := g
if mate != nil {
with = p.genes[mate.ID]
}
kid, x := Cross(g, with, p.Sex, p.mix)
p.Mixes += x.Draws
m := p.Rates.Mutate(kid, p.mut)
p.Moves += m.Draws
at := p.where(b, v)
p.Places += 2
row := kid.Stamp(beast.Fauna[0])
e := Event{Tick: v.Now, Parent: b.ID, Grams: row.Bulk,
Fill: row.Full * Opening, Price: Costs(row),
Store: b.Store, At: b.Cell()}
if mate != nil {
e.Mate = mate.ID
}
// The genome is made before the price is known, because the
// price is the child's and not the parent's. A parent that
// cannot carry what it has just described refuses, and every
// number the refusal spent is spent.
if b.Store < e.Price {
p.Refused++
p.Log = append(p.Log, e)
continue
}
b.Store -= e.Price
c := row.Spawn(at, v.Now)
c.Store = row.Full * Opening
beast.NewWits(kid.Net(), c)
p.Roster.Add(c)
// ... the pedigree, the log, and the grams this minted ...
}
}
Four operators arrive in that loop in the order the arena's own breeding loops spend
them: the second parent off stream 18, the crossing off 17, the mutation pass off 16,
the placement off 20. Every one is spent for every creature the pass asks, including
those that find nobody to breed with and those that turn out unable to pay. That is the
discipline the copying page opened the volume with, arriving at the last operator in it:
a birth is 1 + (1 + G) + 2G + 2 numbers on a genome of G
genes, which is 1,189 here, and nothing any of them said can move the count.
A pass registered into a phase where nothing can afford a child has to cost that phase nothing, and the claim has a run. Take the twelve-by-eight valley the creature chapters act on, open every store at a hundred, and give it three hundred ticks. A bite occupies two ticks and lands one unit, so three hundred ticks hold a hundred and fifty bites at most and a store opening at a hundred cannot pass two hundred and fifty. The threshold is three hundred and sixty; the arithmetic settles it before the run does.
$ go run ./cmd/kin -mode quiet -store 100 -ticks 300
kin: 300 ticks, 24 creatures opening with 100.0000 in the store
a bite takes two ticks and is worth 1.0000, so 300 ticks hold at most 150
of them and a store opening at 100.0000 cannot pass 250.0000, while a child
costs 360.0000: nothing in this run can afford one
digest draws
beast.Roster.Born is nil 25e785e6484f6d12 0
the breeding pass registered into it 25e785e6484f6d12 0
the two lines agree, so a pass with nobody able to pay costs this
valley nothing at all: the phase runs the phase it always ran
The digest folds the ground, every standing plant, and every creature's identity, place, heading, store and grams eaten, and the two runs agree to the character. The draws column is why: the pass reads the threshold before it reaches for a generator, so a creature that cannot pay costs it a comparison and not a number.
The other half of the check is the herd the genome chapter left walking: same seed, same nineteen founders on stream 12, same brain apiece off stream 14, same two years, and the seam left unclaimed.
$ go run ./cmd/kin -mode herd -breed=false
kin: 12x8 valley, tick 901, year 1 summer, 12 plants standing at 1517.5 grams
19 creatures founded on stream 12, each stamped from an identity
genome, given a brain off stream 14 and a store of 400.0000
beast.Roster.Born is nil: nothing has registered a breeding pass into it
this run with nothing born holds
creatures founded 19 19 yes
creatures born 0 0 yes
creatures struck off 17 17 yes
still walking after 6750 ticks 2 2 yes
first death tick 1044 on 9,5 tick 1044 on 9,5 yes
last death tick 3400 on 11,5 tick 3400 on 11,5 yes
grams in 46567.944597 46567.944597 yes
grams out 46567.944597 46567.944597 yes
the two ledgers differ by -1.455e-11, which is the last bits of the adding
the pass spent 0 numbers and minted 0.000000 grams of body
The right-hand column is not a transcription of the left. Those are constants compiled into the bench, and the word at the end of each row is a comparison the program made. A page that adds a step to the creature phase owes the reader that table, because everything the volume measured before it was measured inside a valley that has to go on behaving exactly as it did.
The breeding test
Two things in that loop have not been built yet, and both are decisions the arena never had to make. It found a second parent by holding a second tournament, because an arena has no ground and no neighbours; a valley has both. And it never had to put a child anywhere.
The mate first. A creature looks inside a box six cells east or west and six north or south, and takes anybody in it that is over the breeding threshold. The candidates are gathered in roster order, one number off stream 18 picks among them, and that number is drawn whether or not there is anybody to spend it on. One consequence nobody had to write down: a creature earlier in the roster that has already made a child this tick has already paid for it, so its store is under the threshold, so it cannot also be somebody else's mate on the same phase.
// internal/gene/birth.go, continued
// suitor is the second parent: one number off stream 18, spent whether
// or not there is anybody to spend it on.
func (p *Pool) suitor(b *beast.Beast, live []*beast.Beast, self int) *beast.Beast {
p.near = p.near[:0]
at := b.Cell()
for j, o := range live {
if j == self {
continue
}
if _, ok := p.genes[o.ID]; !ok {
continue
}
c := o.Cell()
if c.X-at.X > Near || at.X-c.X > Near || c.Y-at.Y > Near || at.Y-c.Y > Near {
continue
}
if !Ready(o) {
continue
}
p.near = append(p.near, o)
}
who := p.mate.Float64()
if len(p.near) == 0 {
return nil
}
return p.near[int(who*float64(len(p.near)))]
}
// where is the cell a child is set down on: one angle and one distance
// of up to a whole cell, off stream 20, in that order.
//
// A child whose drawn place is open water, or off the grid altogether,
// is set down on its parent's own cell instead. There is no second
// draw: a redraw would make the count of numbers a birth spends depend
// on where the first one landed, which is the one thing this volume's
// streams may not do.
func (p *Pool) where(b *beast.Beast, v *terra.Valley) field.Vec2 {
turn := p.place.Float64() * 2 * math.Pi
away := p.place.Float64() * terra.Tile
at := field.Vec2{X: b.Pos.X + math.Cos(turn)*away, Y: b.Pos.Y + math.Sin(turn)*away}
c := sim.Coord{
X: int(math.Floor(at.X / terra.Tile)),
Y: int(math.Floor(at.Y / terra.Tile)),
}
if !v.Bed.In(c) || v.Bed.Kind(c) == sim.Water {
return b.Pos
}
return at
}
The box is a box and not a circle because a box is four comparisons and a circle is a square root, and the whole pass runs inside the fifty milliseconds the creature phase is budgeted. The cost is that the corners of the search reach a little further than the sides, which nothing in this valley can tell apart. The placement is one angle and one distance of up to a cell, so a newborn is always on its parent's cell or a neighbouring one, and the water case is the mate draw's rule again: spend the numbers, take what they give, never ask twice.
Now let a valley run until it has answered the question eight times. The ground is wider than the creature chapters use, forty-eight cells by thirty-two, founded with enough seedlings to feed a population, and every founder opens with two hundred units, under the price of a child. Nothing here breeds on anything but food it found.
$ go run ./cmd/kin -mode birth -ground wide | head -18
kin: 48x32 valley, tick 901, year 1 summer, 147 plants standing at 25725.8 grams
57 creatures founded on stream 12, each stamped from an identity
genome, given a brain off stream 14 and a store of 200.0000
beast.Roster.Born is the pool's breeding pass
a creature breeds when its store closes a tick at or above 360.0000
the first eight times this valley was asked for a child
tick parent mate the store the child what happened
1503 18 none 360.2200 371.9584 REFUSED, and every draw spent
1503 55 none 360.2200 360.0000 born, creature 58
1504 18 none 360.0600 360.0000 born, creature 59
1506 45 none 360.1850 360.0000 born, creature 60
1506 50 none 360.1850 360.0000 born, creature 61
1509 38 none 360.1500 360.0000 born, creature 62
1526 56 none 360.5050 360.0000 born, creature 63
1536 31 none 360.5225 360.0000 born, creature 64
Six hundred and two ticks after the herd was stood up, five animals crossed the threshold
within six ticks of each other, and the first thing that ever happened in this valley
was a refusal. The mate column reads none down all eight rows, which is what
a box six cells wide finds among fifty-seven animals on fifteen hundred cells of ground:
neighbours are rare, and neighbours over the threshold at the same instant are rarer. The
store column is nearly the same number eight times over, because a creature is asked on
the first tick it closes above the line and not a tick later.
$ go run ./cmd/kin -mode birth -ground wide | tail -53 | head -15
the first of them that was refused, on tick 1503, on cell 33,6
the parent of record 18
the second parent none in reach
ticks the parent had been standing 602
in its store when it was asked 360.2200
grams of body the genome described 42.9896
that body, at the child's own Convert 171.9584
the store the child opens with 200.0000
the child it made came to 371.9584
a child of the founding row would cost 360.0000
the store is short by 11.7384
nothing went on the roster, no gram was minted, and every one of the
1189 numbers the birth spent is spent
Creature 18 cleared its own row's threshold at 360.2200 and then described a child of 42.9896 grams. The mutation pass had moved the body gene up by about seven percent, and seven percent of forty grams is three more grams to build, which at a conversion of four is 11.9584 more energy than the parent's own row would have asked for. It was 11.7384 short. The genome went in the bin, the log kept the refusal, and every one of the 1,189 numbers stays spent, so the next animal in roster order reads exactly what it would have read if creature 18 had never crossed the line.
Charge the parent's own row for it instead, as the eligibility test does, and a lineage builds animals it cannot afford, generation after generation, with the ledger nodding along. One tick later creature 18 was asked again, made a child that came to exactly 360.0000, and paid for it.
$ go run ./cmd/kin -mode birth -ground wide | tail -37
the first of them that went ahead, on tick 1503, on cell 3,1
the parent of record 55
the second parent none in reach
ticks the parent had been standing 602
in its store when it was asked 360.2200
grams of body the genome described 40.0000
that body, at the child's own Convert 160.0000
the store the child opens with 200.0000
the child it made came to 360.0000
a child of the founding row would cost 360.0000
the child 58
generations from a founder 1
left in the parent's store 0.2200
ticks that leaves it, standing still 1.4
grams of body minted out of the store 40.0000
i gene parent child the row the child's
0 Bulk 1.0000 1.0000 40.0000 40.0000
1 Full 1.0000 1.0000 400.0000 400.0000
2 Basal 1.0000 1.0000 0.0040 0.0040
3 Work 1.0000 1.0000 0.6000 0.6000
4 Bite 1.0000 1.0000 0.2500 0.2500
5 Convert 1.0000 1.0000 4.0000 4.0000
6 Reach 1.0000 1.0000 1.0000 1.0000
7 Sight 1.0000 1.0000 12.0000 12.0000
8 Top 1.0000 1.0000 0.4500 0.4500
9 Swing 1.0000 1.0000 0.0833 0.0833
the two genomes are furthest apart at weight 71, by 2.5388
the parent stopped on tick 1505 and the child was still standing
8 creatures have been asked for a child: 7 made one and 1 could not pay
the pass has spent 9512 numbers on 8 asks, which is 1189 apiece:
8 off stream 18, 3168 off 17, 6320 off 16 and 16 off 20
the roster is holding 35 creatures and Stood reads 2560.0000 grams:
2280.0000 of it founded and 280.0000 of it minted out of a store
Read the two lines under the table first. This child's ten body factors all came through the copy untouched, so it stamps the founding row to the digit and costs the founding row's price; the copy moved a controller weight by 2.5388, a replacement and not a nudge, so what walked away is the parent's body running a slightly different brain. And the parent stopped on tick 1505. It paid 360.0000 out of 360.2200 and kept 0.2200, against a standing body costing 0.1600 a tick, so it had one and a bit ticks left the moment the child was set down. It spent everything it had on an animal that was still standing when the run stopped, which is the only kind of success this valley can record.
The last four lines are the bookkeeping the rest of the page hangs on. Eight asks at 1,189 numbers apiece is 9,512, split across four streams in the ratio the price mode predicted, the refusal costing exactly what the seven births cost. And the roster's opening-stock line reads 2,560 grams: 2,280 of it is fifty-seven founders at forty grams, and the other 280 is seven newborns, which is a very different kind of gram.
Five properties of the pass break silently if they break at all, so they are tests.
$ go test ./internal/gene/ -run 'ABirthSpends|AChildIsMinted|TheOpeningStock|ANewbornIsNot|NobodyOverThe' -v
=== RUN TestABirthSpendsTheSameNumbersWhetherOrNotItHappens
--- PASS: TestABirthSpendsTheSameNumbersWhetherOrNotItHappens (0.02s)
=== RUN TestAChildIsMintedOutOfItsParentsStore
--- PASS: TestAChildIsMintedOutOfItsParentsStore (0.00s)
=== RUN TestTheOpeningStockIsStoodLessWhatWasMinted
--- PASS: TestTheOpeningStockIsStoodLessWhatWasMinted (0.01s)
=== RUN TestANewbornIsNotSteppedOnTheTickItIsBorn
--- PASS: TestANewbornIsNotSteppedOnTheTickItIsBorn (0.00s)
=== RUN TestNobodyOverTheThresholdSpendsNoNumbers
--- PASS: TestNobodyOverTheThresholdSpendsNoNumbers (0.00s)
PASS
ok theworld/internal/gene 0.029s
The first runs four hundred phases over a plate where both kinds of ask happen and demands the total come to the count of asks times 1,189, with stream 18 read once an ask and stream 20 twice. The second charges one full store for one child and checks every part of the arithmetic: the store fell by the price, the price is the child's grams at the child's conversion plus its opening store, the grams that appeared are the child's own bulk, and the pool minted exactly those. The fourth is the phase-order claim: a phase that opened on six creatures hands out six creature-ticks however many are standing when it closes, and every newborn on the roster carries an empty ledger. The fifth is the seam's promise, with nobody over the threshold and every generator left where it was.
Six years without arena scoring
The twelve-by-eight valley the creature chapters use cannot carry a population, and it is honest to say so before showing one that can. Run the same nineteen founders with the pass registered and they produce twenty-six births, the first store runs out on tick 919 and the last on tick 5488, and by the end of the second year the roster is empty. That valley holds twelve plants; nineteen browsers and their children eat it flat, and the grams close at 47857.648836 in and out with 1043.149050 of them minted into bodies that are now litter.
So here is a wider one. Forty-eight by thirty-two, a hundred and forty-seven plants standing when the herd arrives, fifty-seven founders off the same stream 12 the whole book founds creatures on, each stamped from an identity genome with a brain off stream 14, and six years of valley. On the machine this was written on, an eight-core Ryzen 7 3700X running Go 1.26 on Linux, it takes about thirty-two seconds; yours will differ and the numbers will not.
$ go run ./cmd/kin -mode long -ground wide -years 6 -every 2 | head -21
kin: 48x32 valley, tick 901, year 1 summer, 147 plants standing at 25725.8 grams
57 creatures founded on stream 12, each stamped from an identity
genome, given a brain off stream 14 and a store of 200.0000
beast.Roster.Born is the pool's breeding pass
a creature breeds when its store closes a tick at or above 360.0000,
and nothing anywhere in this valley is keeping a score
tick season alive born refused gone lines deepest eaten standing
2251 autumn 23 19 2 53 17 2 2900.5328 13377.57
4051 spring 14 32 5 75 7 4 5019.5255 46304.96
5851 autumn 12 45 5 90 5 6 7062.8849 43082.01
7651 spring 15 59 8 101 4 6 9402.5391 68421.44
9451 autumn 18 81 16 120 4 8 12274.2626 58857.75
11251 spring 16 101 18 142 3 9 15084.1379 64667.83
13051 autumn 16 123 20 164 2 11 17848.9590 62907.87
14851 spring 18 140 22 179 2 13 20519.6220 59604.56
16651 autumn 21 162 27 198 1 17 23665.0645 64502.22
18451 spring 56 228 37 229 1 22 32425.1057 58860.61
20251 autumn 198 536 80 395 1 26 67350.3742 54484.88
22051 spring 174 804 127 687 1 30 95651.6381 64423.47
Read the alive column first and the run looks like a long, dull failure. The
population falls from fifty-seven to twenty-three inside a year and then sits between
twelve and twenty-one for three and a half years, births and deaths arriving at almost the
same rate. That flat stretch is a handful of animals that can feed themselves barely
replacing themselves, while everything descended from a founder that could not goes into
the litter.
Then read the lines column beside it, which counts how many of the fifty-seven
founders still have a descendant walking. Seventeen at the end of the first year. Seven,
five, four, four, three, two, two, and one at tick 16651. That is the collapse the
selection page measured with a tournament, arriving here with no tournament, no score, no
board and no elite place.
And then read the last three rows. Twenty-one alive at tick 16651, fifty-six at 18451, a
hundred and ninety-eight at 20251. The line that outlasted the other fifty-six found
something, and the population goes up ninefold inside a single year while the standing
plant mass falls from sixty-four thousand grams to fifty-four thousand. Nothing told it to and
nothing measured it. The eaten column nearly triples over the same stretch,
which is the only sense in which anything here was ever scored: it ate more.
$ go run ./cmd/kin -mode long -ground wide -years 6 -every 2 | tail -62 | head -38
57 founded, 804 born, 687 struck off, 174 still walking after 21150 ticks
805988 creature-ticks handed out, and 804 of the roster's places were
filled by something no founding put there
931 creatures closed a tick over the threshold and were asked for a child
804 of them made one and 127 described a child they could not pay for
40 of the births had a second parent and 764 had nobody in reach over it
the pass spent 1106959 numbers: 931 off 18, 368676 off 17, 735490 off 16 and 1862 off 20,
which is 1189 for every one of the 931 creatures it asked
the last founder was struck off on tick 7124 and it was creature 37
the 174 still walking come from 1 of the 57 lineages the valley was founded with
the deepest living creature stands 30 generations from a founder
generations from a founder alive
0 to 4 0
5 to 9 2
10 to 14 10
15 to 19 70
20 to 24 74
25 to 29 17
30 to 34 1
the ten body factors of the 174 still walking, against 1.00 in every founder
i gene lowest mean highest the row now
0 Bulk 0.2743 0.6198 0.9836 24.7909
1 Full 0.6105 0.8589 1.0000 343.5612
2 Basal 0.2985 0.9637 2.4147 0.0039
3 Work 0.9251 1.0932 3.0825 0.6559
4 Bite 0.9452 1.9051 2.7994 0.4763
5 Convert 0.7810 0.9451 1.0296 3.7806
6 Reach 0.8005 1.0303 3.8710 1.0303
7 Sight 0.9286 1.1281 1.8091 13.5377
8 Top 0.7350 0.9633 2.6853 0.4335
9 Swing 0.6997 1.2065 3.5928 0.1005
how far apart the living genomes are 0.0755
One line in that block is the page's whole claim. The last creature the valley was founded with was struck off on tick 7124, a third of the way through the run, and the valley did not notice. Nearly fifteen thousand ticks later a hundred and seventy-four animals are standing on it, not one of them within five generations of anything anybody stood up and the deepest of them thirty generations out, and not one of them has ever been measured against anything. No board, no ranking. A store, a price, and a bill every tick.
The body table underneath says what the ledger did over nine hundred and thirty-one
asks. Every founder
opened at 1.00 on all ten factors, so every mean that is not 1.00 is a change
nothing asked for. Bulk is at 0.6198, a twenty-five gram browser instead of a
forty gram one, and that one gene pays two separate bills: a smaller body costs less to
keep standing, and a smaller body is cheaper to build a child out of. Full
came down to 0.8589 for the second of those alone, since half of a smaller store is a
smaller half to hand over. And Bite nearly doubled, to 0.4763 grams a
mouthful against the founding row's quarter gram, so an animal needing ninety grams to
breed gets them in half the bites.
Cheaper to keep, cheaper to reproduce and faster to fill: three genes, all pointing the
same way, none of them named anywhere in the code. The columns either side of the mean say
this is a population and not a clone. Reach runs from 0.8005 to 3.8710 and
Swing from 0.6997 to 3.5928, and both extremes are eating well enough to
still be standing. The population sits 0.0755 apart gene by gene, and every bit of that
was made by mutation, because the body block of every founder was identical.
Why birth cost replaces score
Strip the creatures out and there are two mechanisms here, and only one of them has anything to do with reproduction.
The first is the difference between a measurement taken from outside a system and a consequence of the system's own accounts. A benchmark computes a number that has no effect on the candidate: the candidate cannot feel it, cannot spend it, and would behave identically if it were never computed at all. The store is the opposite in every one of those respects. It falls when the animal turns and falls further when it sprints, it rises only when the animal finds tissue, it ends the animal when it reaches nothing, and it is now the only thing that can make another animal. There is nothing left for a fitness function to do, because continuing is the fitness function, evaluated ten times a second by the same arithmetic that prices a mouthful.
The second generalises past valleys. Selection needs a differential, and a differential can come from a comparison or from a cost. The arena's was a comparison: put four candidates side by side, read a column, keep the best. This valley's is a cost: the world charges for everything and whatever cannot pay stops. A comparison needs somebody to write down what is being compared, and that person's opinion becomes the only thing the search can ever find. A cost needs the world's own prices, and those were already there: the bite's conversion, the body's upkeep, the square law on movement. Every one of them was written down before there was such a thing as a genome, for reasons that had nothing to do with evolution, and that is exactly what makes them trustworthy as a selection rule.
The loss is real. A score gives you a curve, and a curve going up is a thing a person can watch. This valley prints a population, a count of surviving lines, and the ten factors of whatever is standing, and none of those is progress towards anything, because there is no towards. A world with no score cannot tell you it is doing well, and never being lied to by a metric costs you never being reassured by one.
Birth records in the books
The volume that built this valley closed on one rule: the grams have to add up both ways, every gram that ever entered against every place a gram can now be, printed to six decimal places with the residue shown instead of rounded off. Three of those lines belonged to the creature phase: the bodies the run stood up, the bodies still walking, and the grams a mouth took and a store spent. Births add a fourth, and it is the only line in the ledger that describes a gram appearing in the middle of a run.
Those grams were never manufactured. They came out of the parent's store, which was
filled by grams off standing plants the audit already counted as eaten and
treated as gone. So the ledger gains one line saying that some of what was counted as
spent came back as body, and the total does not move.
$ go run ./cmd/kin -mode long -ground wide -years 6 -every 2 | tail -23
the books in grams
the valley opened with 131.000000 plants founded on the first tick
built out of light 4145056.531219 every gram the leaves ever fixed
creatures stood up 2280.000000 bodies the run opened with
built out of a store 26435.644165 grams a parent minted into a child
in 4173903.175383
standing 64423.473365 living plant tissue
walking 4313.612763 living creature bodies
in the air 0.000000 seeds still flying
in the bank 46393.500000 seeds waiting in the ground
lying dead 4207.857671 litter: plants and carcasses together
burned as upkeep 3902449.694159 grams a plant spent on standing there
rotted 54762.399309 grams the litter has burned off
blown away 1701.000000 seeds that left over the rim
eaten 95651.638122 grams a mouth took and a store spent
out 4173903.175389
difference -0.000005 -5.313e-06, which is the last bits of the adding
the opening stock, counted a second way
57 creatures founded at 40 grams a body is 2280.000000 grams
the line the audit read 2280.000000 grams
difference 0.000000 grams
Four million one hundred and seventy-three thousand grams in and the same out, differing
by five millionths of a gram, which is what several million additions taken in two orders
cost. The residue is printed instead of rounded away for the reason the terrarium
printed its own: 0.000000 and -5.313e-06 mean the same thing,
and only the second one says plainly that it is a rounding and not a rule.
creatures stood up reads 2,280 grams, fifty-seven bodies at forty.
built out of a store reads 26,435.644165, the eight hundred and four newborns
at whatever each of them weighed. Both numbers come out of one place, and getting them out
of that one place is where the interesting mistake lives.
// internal/gene/birth.go — inside type Pool struct
// Ancient is the grams audit as it was first written: every body
// on the roster charged to the opening stock, as though every
// animal alive had been standing there since the first tick. It is
// kept behind a flag so what a forgotten correction does to a
// ledger can be run instead of described, and it is false in every
// pool this book ships.
Ancient bool
The call that puts a creature on the roster charges the body to Stood,
the opening-stock line. That was right for the whole volume before this one: the only
road onto a roster was to be founded, and a founding creature is opening stock exactly
as a founding plant is. A born body was made out of energy in the middle of the run, and
the audit already counted the grams behind that energy on the way in. So the pool keeps
its own count of what it minted, and the opening stock the ledger reads is
Stood less that count. Take the correction out and run the same six
years.
$ go run ./cmd/kin -mode long -ground wide -years 6 -every 2 -ancient | tail -23
the books in grams
the valley opened with 131.000000 plants founded on the first tick
built out of light 4145056.531219 every gram the leaves ever fixed
creatures stood up 28715.644165 bodies the run opened with
built out of a store 0.000000 grams a parent minted into a child
in 4173903.175383
standing 64423.473365 living plant tissue
walking 4313.612763 living creature bodies
in the air 0.000000 seeds still flying
in the bank 46393.500000 seeds waiting in the ground
lying dead 4207.857671 litter: plants and carcasses together
burned as upkeep 3902449.694159 grams a plant spent on standing there
rotted 54762.399309 grams the litter has burned off
blown away 1701.000000 seeds that left over the rim
eaten 95651.638122 grams a mouth took and a store spent
out 4173903.175389
difference -0.000005 -5.313e-06, which is the last bits of the adding
the opening stock, counted a second way
57 creatures founded at 40 grams a body is 2280.000000 grams
the line the audit read 28715.644165 grams
difference -26435.644165 grams
The in total is the same number. The out total is the same
number. The difference is -5.313e-06, the same rounding, to the same digit.
Every one of the nine lines on the outgoing side is unchanged. This ledger closes exactly
as well as the one above it, and it says that The Hollow was founded with
28,715.644165 grams of creature, which at forty grams a body is more than seven hundred
animals stood up on the first tick, when fifty-seven were. It also says, on the line
right underneath, that no parent has ever minted a gram into a child, in a run that made
eight hundred and four of them.
The bottom block is what catches it, and it is the instrument the volume before this one used on the carcasses. A total that balances is not a total that is right, because a number missing from one column and its mirror image in another balance perfectly. So the opening stock is counted a second time from another direction: the bench knows how many founders it stood up, the founding row says a body is forty grams, and fifty-seven times forty is 2,280. The corrected run's two lines agree to the gram. The uncorrected run's are 26,435.644165 grams apart, which is the entire minting of the run sitting in a column labelled bodies the run opened with.
The reasoning from symptom to cause has no bug at the end of it. Roster.Add
does what it says and always did, and every gram it charged was really on a body. What
changed is that a second road onto the roster opened, and a line meaning founding
stock quietly began to mean every body that ever stood up, which are the
same set right up until the tick something is born. The currency is right, the arithmetic
is right, the total is right, and one of the labels has stopped being true.
- Given a creature's ten body factors You can work out what a child of it costs, name which two halves the price is made of, and say which of them stays energy and which becomes grams.
- You can say why the eligibility test reads the parent's row and the charge reads the child's, and describe what a lineage could do if both read the parent's.
- You can count the numbers one birth spends off each of the four streams, and explain why a refused birth and a birth with no mate in reach spend every one of them.
- You can name the four steps of the creature phase this pass runs after, and say what would go wrong with the index if a newborn were added anywhere earlier.
- Shown a grams ledger whose difference column reads zero, You can name the second count that would catch an opening-stock line holding bodies nobody founded.
- Looking at the body factors of a population nothing ever scored, You can say why one gene falling makes two separate bills cheaper, and which two.
Exercise 1 — a store that opens full. The wide valley founds
every creature with two hundred units, under the price of a child. Predict what
happens when they open with four hundred instead, then check with
go run ./cmd/kin -mode long -ground wide -store 400 -years 2 -every 2.
Every founder is over the threshold before it has eaten anything, so the first row of the table reads 82 born and 100 gone by tick 2251, against 19 born and 53 gone when the store opens at two hundred. Four times the births in the same thirteen hundred and fifty ticks, and four times the funerals with them: a parent that pays 360 out of 400 is left with two hundred and fifty ticks of standing still, and most of these had not shown they could find a plant.
Now compare where the two runs are after two years. This one has made 129 children, buried 169 animals and has 17 walking; the page's run made 59, buried 101 and has 15. Twice the reproduction to arrive in the same place, because a free generation is a generation of copies of animals that mostly could not eat. The founding store is the one arbitrary number in this valley, and putting it under the price is what makes the first birth mean something.
Exercise 2 — a valley that hardly ever finds a mate. Only 40
of the 804 births in the long run had a second parent. Work out from the mate rule why
the number is so small, then try the obvious fix, a quarter of the ground with the
same herd and the same seedlings:
go run ./cmd/kin -mode long -ground wide -cols 24 -rows 16 -years 6 -every 2.
A second parent has to be inside a box thirteen cells on a side and over the threshold on the same tick. In fifteen hundred cells holding twenty animals a creature has, on average, a fraction of a neighbour inside that box, and a neighbour only counts on the handful of ticks in its life when its own store is above three hundred and sixty. Both conditions are rare and nearly independent, so their product is very rare indeed.
Crowding the ground looks like the fix and is not. On a quarter of the cells the same founding draws land 52 animals instead of 57, the valley holds 125 plants instead of 147, and the herd eats the larder out from under itself: the last founder goes on tick 5647, the roster is empty by tick 11251, and the whole run manages 37 births of which exactly one had a second parent. Density is what the mate rule wants and food is what density costs, and on this ground the second one runs out first. The population in the page's own run finds one mate in five years and the other thirty-nine in the year it grows past a hundred and fifty animals on the wide ground, which is density bought with food instead of with fences.
Exercise 3 — put the price back in a person's hands. Change
Costs to charge a flat 300 for every child, whatever the child is, and run
the same six years. Predict the refused column before you look, then say
what the valley did.
One line does it: func Costs(k beast.Kind) float64 { return 300 }. The
refused column reads 0 on every row of the table, and it has to: the
eligibility test and the charge both call Costs, so once they hand back
the same constant, a creature that is allowed to try can always pay. A whole
behaviour of the valley, and the failure box's entire subject, is deleted by making
a number simpler.
What the valley does is die. The threshold is now 60 units below the founding row's,
so animals breed earlier and on a thinner margin, and thinner margins are graves:
the run makes 51 births against the page's 804, loses its last founder on tick 3709
against 7124, and has an empty roster by tick 11251, having eaten 5322.3918 grams
where the real price ate 95651.6381. The flat price is a small, reasonable, tidy-looking
sentence somebody wrote, and the valley rearranged itself against it in three years.
Put Costs back and the price goes back to being an exchange rate the
world was already using for something else.
Six years is long enough to watch a founding generation disappear and short enough that the last two rows of the table are still climbing when the run stops. A hundred and seventy-four animals and rising, the standing plant mass falling, one lineage out of fifty-seven holding the whole valley, and nothing in any of that has been asked to stop. A herd that keeps growing on ground that does not is a story with an ending, and in a world with no score to read off, the only way to find out what the ending is means leaving the thing running and counting what is left.