Who Limits Whom
No population cap
There are three levels of eater in The Hollow now. Plants take light, water and minerals off a cell. Browsers take a quarter of a gram at a time off living tissue. Hunters take fallen mass off a pile, and they have an action nothing else has for putting a pile where they are standing.
An animal's ceiling in this world is what the level below it regrows, and a hunter's is what the browsers do. Nothing anywhere counts animals. If the web will not stand up, the repair is a change to the valley—a rule about the ground, or one of the ground's own numbers—and never a term on an animal.
Every level is written down in the code, and not one line of it says how many of anything the valley is allowed to hold. Search for one and there is nothing to find: no maximum, no cap, no count compared against a threshold, no coefficient with a population on either side of it.
The plants have a density coefficient of their own, written in the terrarium volume, and it stays the plants'. The ground carries one root to a cell and one body to a cell, and those are sentences about ground, not about animals.
Beyond that the arithmetic is a body charging its own store for being a body, a mouth taking what is in front of it, and a parent paying for a child out of what is left over.
That is the constraint the evolution volume set for itself when its valley ate itself flat, and it is still the constraint here. It also makes this page a measurement and not a design. No author gets to decide what the valley carries. The run decides, and the job is to find out what it decided and why.
By the end there is a bench called pyramid. There are two hundred years of a
valley that is empty by its twenty-first and two hundred more of one that is not, with one
number of the ground's between them. A pyramid read off a real run stands the wrong way up.
A year is taken apart into four curves that arrive at four different times. A browser's store is measured at the top of the year and at the bottom of it. A population sits inside a band four animals wide for a hundred and eighty years.
The hunters' measured effect is nothing, and a run over six world seeds says so.
Pricing the two-century run
Two hundred years is 720,000 ticks. Every one of them walks every plant standing in the valley and steps every animal on the roster: nine rays cast, a grown network run forward, an action chosen, priced and applied. What that costs depends on how much is alive, so the honest thing to do is measure a year of the thing that will actually be running before committing to two centuries of it.
// cmd/pyramid/valley.go
//
// pace is the question asked before the long run: what a year of a
// valley with a live population in it costs, on three grounds. Eight
// years of each are run first, because the cost of a tick is set by
// what is standing and walking on the ground and not by how big the
// ground is, and a valley that has not filled yet is cheap for a
// reason that will not last.
func pace(w run) {
for _, g := range [][2]int{{12, 8}, {16, 12}, {48, 32}} {
q := w
q.cols, q.rows, q.years, q.every = g[0], g[1], 8, 1000
q.stood()
for y := 0; y < 8; y++ {
q.year()
}
was, at := q.v.Now, time.Now()
q.year()
took := time.Since(at)
// ... and print the rate
}
}
$ go run ./cmd/pyramid -mode pace
pyramid: one year of a filled valley with both rows walking about in it
12x8: 96 cells, 75 a root can live in, 44 plants at 2918.0 grams,
10 browsers and 0 hunters walking
3600 ticks in 328ms, 10964 ticks a second (measured here; yours will differ)
16x12: 192 cells, 172 a root can live in, 124 plants at 2973.7 grams,
247 browsers and 0 hunters walking
3600 ticks in 3.901s, 923 ticks a second (measured here; yours will differ)
48x32: 1536 cells, 1516 a root can live in, 1361 plants at 43263.7 grams,
2370 browsers and 0 hunters walking
3600 ticks in 37.677s, 96 ticks a second (measured here; yours will differ)
two hundred years is 720000 ticks of whichever of those a run picks
Read the browser column, not the cell count. Every duration and every rate on this page, here and in the four blocks below it, is an eight-core Ryzen 7 3700X talking and will be different on your machine; every tick count beside one is arithmetic and comes out the same anywhere. Between the middle ground and the wide one there are eight times the cells and nine and a half times the animals, and the tick costs about nine times as much, because a plant is a handful of multiplications and an animal is nine rays and a network. At the rate this desk managed, two centuries of the wide ground works out at something over two hours of one core, and that is before anything else on the machine wants a turn; the middle ground priced at about a quarter of an hour and came in comfortably under it. That is the size this chapter runs on, and every figure below stands on a sixteen-by-twelve valley with a hundred and seventy-two cells a root can live in.
The three grounds say the same thing about hunters three times over. Every one was founded with eight of them and every one is carrying none eight years later. The long run is about to say how long it stays that way.
// cmd/pyramid/valley.go — the founding is the one the last three
// chapters used, unchanged to the draw: browsers scattered off stream
// 12, hunters off stream 22 after them, a cell of ground carrying one
// body, wirings that grow their own nodes, births sorted into species,
// and the pool reading a temperament rule rather than the empty one
// that would leave every gene in the genome ornamental.
w.p.Room = true
w.p.Names = gene.NewMint(gene.Wide, beast.Acts)
w.p.Grow = gene.Often
w.p.Sense = gene.Sense{On: true,
Scale: beast.Scale{Wet: w.v.Full, Food: beast.Fauna[0].Bellyful()}}
w.p.Kinds = gene.Sorted
w.p.Temper = gene.Read
$ go run ./cmd/pyramid -mode long -years 200 -every 20 | tail -78 | head -23
pyramid: 16x12 valley, 21 browsers off stream 12 and 8 hunters off stream 22
172 cells a root can live in, the rim walled, a cell of ground carrying one body
year brwsrs hunters stands plants litter bank kills born
1 21 8 90 4654.10 0.95 0.00 0 0
2 7 0 83 6133.75 159.75 387.75 13 44
3 12 0 122 7449.85 157.02 1511.00 13 70
4 22 0 124 7082.59 244.96 2731.25 13 115
5 38 0 123 7289.73 416.80 3663.00 13 187
6 15 0 123 7419.74 800.12 3794.50 13 298
21 0 0 0 0.00 0.00 0.00 13 1727
41 0 0 0 0.00 0.00 0.00 13 1727
61 0 0 0 0.00 0.00 0.00 13 1727
81 0 0 0 0.00 0.00 0.00 13 1727
101 0 0 0 0.00 0.00 0.00 13 1727
121 0 0 0 0.00 0.00 0.00 13 1727
141 0 0 0 0.00 0.00 0.00 13 1727
161 0 0 0 0.00 0.00 0.00 13 1727
181 0 0 0 0.00 0.00 0.00 13 1727
201 0 0 0 0.00 0.00 0.00 13 1727
29 founded, 1727 born, 1756 struck off, 0 still walking after 719550 ticks
the last hunter was struck off on tick 2739
Nine rows of that table are identical and they are the last nine. The hunters go first, all eight inside the second year, and thirteen browsers were killed by the sixteen animals that row ever held. Then the browsers climb through the years the printing skips, take the standing crop down with them, and by the twenty-first year there is nothing on the ground at all: no plant, no animal, no litter, and a seed bank reading nought. A hundred and eighty years of sunlight fall on it after that and the born column never moves off 1,727.
The run cost forty seconds. Two centuries of a valley with nothing in it is very nearly free, and the pacing measurement above priced a quarter of an hour, so almost all of the arithmetic this run was expected to do never happened. That is the cheapest possible way to be told an answer you did not want.
The population column is not the finding, because a run that ends at nought could end there for a dozen reasons. The accounts are, and they are added up over every animal that ever stood on the ground and not over the handful alive at any moment.
$ go run ./cmd/pyramid -mode long -years 200 -every 20 | tail -54 | head -17
the two rows' accounts, added up over every animal that ever lived
browsers hunters
animals that ever lived 1740 16
creature-ticks they were stepped 8749907 7452
energy they were handed to start with 347329.74 8423.24
energy their mouths brought in 3376816.07 532.64
income as a share of rent 530.15 29.29
and where it all went
standing there, at Basal a gram a tick 636952.55 1818.33
the sixth entry, taking mouthfuls 547292.76 80.77
the seventh entry, throwing strikes 0.00 992.81
the legs, by difference 2539900.51 6063.97
the share of it the legs took 68.20% 67.71%
Three of the four spending lines are added up out of their own events: rent is a body's bill times the ticks it stood there, and the two action lines are the table's prices times the number of times each entry was taken. The fourth is worked out by subtraction, because nothing in this world writes down how far an animal walked. What was spent is what went in less what is left in the stores of the living, and the legs are whatever the other three do not account for.
That line is the one to sit with. Two thirds of everything either row ever had went into its legs. Not upkeep, and not the mouth, which is the cheapest thing on the table. Walking. A body is charged its own mass times the square of its speed for every tick it is moving, and a valley of animals that can see food and go to it is a valley of animals that are moving nearly all the time. It works out for the browsers, whose mouths brought in five and a third times what standing still cost them. It does not work out for the hunters, who covered 29 percent of their rent and paid nearly a thousand energy units to throw strikes on top of it.
The ground as competitor
Now count the same run the other way. A pyramid can be read as what is standing on the ground at one moment, and it can be read as what went through each level over the whole of a run, and the two questions have different answers. The bench prints both.
$ go run ./cmd/pyramid -mode long -years 200 -every 20 | tail -36 | head -15
the pyramid, as standing crop: grams alive on the ground at the last tick
grams of the one below
level 0, plants 0.00 -
level 1, browsers 0.00 0.00%
level 2, hunters 0.00 0.00%
lying on the ground as litter 0.00 -
and as throughput: grams that went through each level over the whole run
grams of the one below
level 0, built out of light 1658780.79 -
level 1, off a stand 838436.93 50.55%
level 2, off a pile 133.16 0.02%
burned off the litter by the ground 54469.36 -
The standing crop is four zeroes, which is what a dead valley looks like and says nothing else. The throughput block is where the second row's whole problem is written down in one line, and the line is the last one. Over two centuries the leaves fixed 1,658,780 grams out of light. Browsers' mouths took 838,436 of them off living tissue, which is half of everything the valley ever built. Everything that died—every plant that stopped standing, every animal that ran out of store, every browser a blow emptied—landed on a cell as litter, and of that litter the hunters ate 133 grams and the ground burned 54,469.
The second row's competitor for food is the ground, not the browsers, and it is losing to it by four hundred to one. That is a fact about a number the terrarium volume set long before there was anything alive that could eat a carcass: the share of a litter pile that rots away in a tick. The rotting was written when it was the only road out of a pile, and by four hundred to one it is still the road nearly everything takes.
Numbers first, on one browser carcass. A browser founded in this valley is forty grams, and when its store closes at nothing the whole forty go onto the cell it was standing over. Two things now want that pile.
The ground takes a share. Rotting works on a fraction of what is lying there, multiplied by the warmth: at a decay of 0.01 and full warmth that is a hundredth of forty grams, so 0.4 of a gram on the first tick. It is a share and not a fixed amount, so the bigger the pile the more the ground takes off it, which is exactly the wrong way round for anything hoping to eat a whole body.
A mouth takes a fixed amount. A hunter's bite is 0.375 grams and the sixth entry holds the body for the tick after it, so a mouth standing on a pile and biting every time it can lifts 0.1875 grams a tick and no more, whatever is lying there. Four tenths of a gram a tick against 0.1875: the ground is taking rather more than twice what the mouth is taking, from the first tick, and the mouth never catches up.
Set the two rates equal and there is a decay at which a mouth on a fresh carcass at least draws with the ground: 0.375 divided by two, divided by forty grams, which is 0.0047. Below that a hunter standing on its kill gets more than half of it. The sweep below runs both sides of that number, and the interesting part is what else moves when it does.
Because the same number is the valley's mineral clock. A plant borrows nutrient out of the cell it is rooted in and pays it back when it stops standing and rots. How long a unit spends lying in the litter before the ground hands it back is one over the decay times the warmth, and the year's average warmth is a half. At 0.01 that is two hundred ticks. At 0.04 it is fifty. The valley holds a fixed stock of minerals and nothing arrives from outside, so how fast the plants can build is set by how fast that stock comes round, and a slow ground is a hungry ground.
So one coefficient points two ways at once. Slow it down and the litter lies about long enough to be eaten, and the plants starve. Speed it up and the plants come back, and the second row's dinner is burned before it can get to it.
the ground takes = Decay × warmth × Mass, every tick
a mouth takes = Bite ÷ 2, every tick, standing still
they draw at Decay = Bite ÷ (2 × warmth × Mass)
a mineral waits = 1 ÷ (Decay × warmth) ticks in the litter
terra.Valley.Decay, 0.01 since the terrariumBefore the sweep, one line of the books, because a page that has spent four paragraphs moving grams around owes the reader a total. The ledger closed on that dead valley the way it has closed on every run since the terrarium was sealed, with its residue printed instead of tidied away.
$ go run ./cmd/pyramid -mode long -years 200 -every 20 | tail -20 | head -18
the books in grams
the valley opened with 67.000000 plants founded on the first tick
built out of light 1658780.789860 every gram the leaves ever fixed
creatures stood up 41452.536008 bodies founded and bodies minted
in 1700300.325869
standing 0.000000 living plant tissue
walking 0.000000 living creature bodies
in the air 0.000000 seeds still flying
in the bank 0.000000 seeds waiting in the ground
lying dead 0.000000 litter: plants and carcasses together
burned as upkeep 807260.875722 grams a plant spent on standing there
rotted 54469.356369 grams the litter has burned off
blown away 0.000000 seeds that left over the rim
eaten off a stand 838436.934803 grams a mouth took off living tissue
eaten off the litter 133.158970 grams a mouth took off a pile
out 1700300.325864
difference 0.000005 4.530e-06, which is the last bits of the adding
Five ten-millionths of a gram out over 1.7 million, and six lines reading exactly nought. The rim was walled, so nothing left the valley; every gram it ever had went through something's metabolism and came out as heat. The in the bank nought is the permanent one. A valley whose plants have all been eaten can still come back while there is buried seed to come up, and this one holds none: 838,436 grams went off living tissue into mouths, the standing crop reached nothing, and there was nothing left underground to replace it.
Sweeping the ground's full factor
The repair may not be a term on an animal, and there is no term on an animal that would help anyway: the browsers are not doing anything wrong, they are eating, and the hunters are not doing anything wrong either. What is available is the ground. So take the one coefficient the interlude found pointing two ways, move it across two orders of magnitude with everything else held exactly where it was, and print what the valley did with each setting.
// cmd/pyramid/sweep.go
// Appetites are the rates the ground's own appetite is swept over: the
// share of a litter pile it burns off in a tick at full warmth, from a
// fortieth of the rate this book has run since the terrarium was
// sealed to eight times it.
var Appetites = []float64{0.00025, 0.001, 0.0025, 0.005, 0.01, 0.02, 0.04, 0.08}
// quiet runs one valley all the way through without printing a line of
// it and reads it once at the end. Once, because running a valley
// twice to ask it two questions is two valleys.
func quiet(w run) outcome {
w.stood()
for y := 0; y < w.years; y++ {
w.year()
}
// ... and read the roster, the stands, the bank and the second
// row's account off the finished run
}
$ go run ./cmd/pyramid -mode rot -years 24
pyramid: the ground's own appetite, swept. 16x12 valley, 24 years each,
the same seed and the same founding every time, and the only thing
moved is the share of a pile the ground burns off in a tick
decay a unit browsers hunters stands plants bank rotted hunters'
waits left left left grams grams grams income
0.00025 8000 0 0 92 400.16 291.50 5378.45 81.75%
0.00100 2000 0 0 120 1538.75 1086.50 15417.44 25.34%
0.00250 800 0 0 124 2806.14 2284.50 30889.93 46.85%
0.00500 400 230 0 104 1113.62 634.50 64301.28 45.41%
0.01000 200 0 0 0 0.00 0.00 54469.36 29.29%
0.02000 100 204 0 78 994.23 494.00 43221.61 11.82%
0.04000 50 238 0 123 3762.08 2294.00 80812.26 7.93%
0.08000 25 244 0 122 1889.99 990.00 61026.31 5.46%
a unit waits is how many ticks a mineral spends lying in the litter
before the ground hands it back, at the year's average warmth
687600 ticks in 3m59.126s, 2875 ticks a second (measured here; yours will differ)
Read the top of the table first, because it is the half most readers miss. At the slowest setting a mineral waits eight thousand ticks in the litter, which is more than two years, and the valley is holding four hundred grams of plant on ninety-two stands. Those are starved plants: the minerals they need are lying on the ground beside them where the roots cannot reach. No browser survives twenty-four years of it. Speed the ground up and the plants come back: 1,538 grams, 2,806 grams, and at fifty ticks of waiting, 3,762 grams on a hundred and twenty-three stands with two hundred and thirty-eight browsers standing on it.
Now the last column, which is the second row's income against what standing still cost it. It is the highest at the slowest ground, exactly as the interlude predicted: at a decay of 0.00025 a carcass lies about for years and the hunters cover 82 percent of their rent off it. It falls as the ground speeds up and reads 5.46 percent at the fastest. And it never once reaches a hundred. Across a three-hundred-and-twenty-fold sweep of the only coefficient that touches this, in the one valley where the litter lasts long enough to be eaten, the second row still cannot pay for the walking it does to get there—and the hunters left column reads nought on every row of the table.
Two things have to be said about that sweep before anything is built on it, and both of them are about how much it is entitled to prove. It is one world seed. The 0.01 row, nought across its browsers, its stands, its crop and its bank, is the valley from the last section, and the 0.005 row above it carries two hundred and thirty browsers while the 0.02 row below carries two hundred and four: a setting between two survivors that kills everything is noise, not a threshold. What the sweep establishes is the two ends and the direction, and the ends are not subtle. What it does not establish is a safe value, and there is not one.
So run the two centuries again on a ground that hands its minerals back in fifty ticks instead of two hundred. Same seed, same terrain, same twenty-one browsers off stream 12 and eight hunters off stream 22, same wirings, same temperament rule, same one body to a cell. One number of the valley's, four times what the terrarium set it to.
$ go run ./cmd/pyramid -mode long -decay 0.04 -years 200 -every 20 | tail -78 | head -23
pyramid: 16x12 valley, 21 browsers off stream 12 and 8 hunters off stream 22
172 cells a root can live in, the rim walled, a cell of ground carrying one body
year brwsrs hunters stands plants litter bank kills born
1 21 8 90 5848.60 0.00 0.00 0 0
2 11 0 87 5907.79 0.68 390.00 9 45
3 23 0 122 7775.71 40.31 1573.75 10 84
4 25 0 124 7687.49 1.85 2781.00 10 122
5 19 0 124 7484.66 37.11 3844.75 10 195
6 43 0 124 7187.01 64.14 4102.50 10 252
21 236 0 124 3812.23 0.42 2265.00 10 1643
41 235 0 124 3766.69 0.44 2295.50 10 1773
61 236 0 123 3856.61 0.47 2280.50 10 1902
81 238 0 124 3647.93 0.85 2285.00 10 1965
101 238 0 123 3547.24 0.36 2240.00 10 1970
121 238 0 123 3547.44 0.34 2180.00 10 1972
141 234 0 124 3598.73 0.36 2207.00 10 1979
161 237 0 124 3568.07 0.35 2200.00 10 1993
181 237 0 123 3595.20 0.41 2239.00 10 1995
201 237 0 124 3574.86 0.36 2254.00 10 1996
29 founded, 1996 born, 1788 struck off, 237 still walking after 719550 ticks
the last hunter was struck off on tick 2319
Ten readings, from the twenty-first year to the two hundred and first: 236, 235, 236, 238, 238, 238, 234, 237, 237, 237. A hundred and eighty years inside a band four animals wide. The stands beside them read 123 or 124 every time and the standing crop sits between 3,547 and 3,857 grams, and the seed bank between 2,180 and 2,295. Nobody chose two hundred and thirty-seven. There is no maximum in this program, no count compared with a limit, no coefficient anywhere near an animal. There is a hundred and seventy-two cells of ground, a stock of minerals that comes round every fifty ticks, and a year, and the valley walked to the number those three produce and stayed there for two centuries.
The hunters are still gone by the third year. Ten browsers were killed and the last hunter was struck off on tick 2,319, which is 1,418 ticks after the founding. A full store on that row covers 2,500 ticks of standing perfectly still, so between them the sixteen animals that row ever held managed less life than doing nothing whatever would have bought the eight it opened with.
$ go run ./cmd/pyramid -mode long -decay 0.04 -years 200 -every 20 | tail -36 | head -15
the pyramid, as standing crop: grams alive on the ground at the last tick
grams of the one below
level 0, plants 3574.86 -
level 1, browsers 7362.39 205.95%
level 2, hunters 0.00 0.00%
lying on the ground as litter 0.36 -
and as throughput: grams that went through each level over the whole run
grams of the one below
level 0, built out of light 26774527.41 -
level 1, off a stand 16266639.15 60.75%
level 2, off a pile 28.32 0.00%
burned off the litter by the ground 267699.59 -
That is the pyramid, and the top block of it is standing on its point. Seven thousand three hundred grams of living animal are walking about on a valley holding three thousand five hundred grams of living plant. There is twice as much eater as there is food, at every moment, for a hundred and eighty years, and the arrangement is stable.
Nothing is wrong with the arithmetic, and the bottom block says why. Over the two centuries the leaves built 26,774,527 grams and the browsers ate 16,266,639 of them, which is 61 percent of everything the valley ever made. The plants are not a store, they are a flow: the standing crop is replaced seven and a half thousand times over the run, while a browser's body is minted once and stands for years. A pyramid of standing crop measures how much of each level is sitting still, and a level that turns over fast can feed a level that turns over slowly out of a much smaller standing amount. Count the throughput instead and the pyramid comes back the right way up, and it is very steep: 61 percent from the plants to the browsers, and 28 grams out of sixteen million from the browsers to the hunters, against 267,699 grams the ground burned off the litter in the same two centuries. The valley has a second consumer of everything that dies and it is not an animal.
$ go run ./cmd/pyramid -mode long -decay 0.04 -years 200 -every 20 | tail -20 | head -18
the books in grams
the valley opened with 67.000000 plants founded on the first tick
built out of light 26774527.414535 every gram the leaves ever fixed
creatures stood up 68390.517236 bodies founded and bodies minted
in 26842984.931770
standing 3574.855477 living plant tissue
walking 7362.394694 living creature bodies
in the air 0.000000 seeds still flying
in the bank 2254.000000 seeds waiting in the ground
lying dead 0.358570 litter: plants and carcasses together
burned as upkeep 10295426.259999 grams a plant spent on standing there
rotted 267699.591178 grams the litter has burned off
blown away 0.000000 seeds that left over the rim
eaten off a stand 16266639.148102 grams a mouth took off living tissue
eaten off the litter 28.320770 grams a mouth took off a pile
out 26842984.928791
difference 0.002980 2.980e-03, which is the last bits of the adding
Twenty-six million eight hundred and forty-two thousand grams in and the same out, three thousandths of a gram apart after several hundred million additions taken in two orders. The ledger has exactly the lines the scavenging chapter left it with. Predation put ten browser bodies onto the litter earlier than starving would have, and that is the whole of what a strike contributes to this table, because a strike moves no grams at all.
The first two centuries came in at 40.063 seconds and 17,961 ticks a second; the second
at 6m23.21s and 1,878 ticks a second. That is two long valleys where this volume is
allotted one, and the first is not really a second one: it costs forty seconds because
the valley it runs is dead by its twenty-first year and a bare grid is nearly free to
tick. The one that costs what a long valley costs is the second, and it is the one every
figure in this chapter is read off. Both are 719,550 ticks and the tick counts are
arithmetic, compared like every other number here. These two durations, and the pacing
line on every other block of this chapter, are an eight-core
Ryzen 7 3700X talking and will be different on your machine. The gap between them is
not the machine: one of those valleys had two hundred and thirty-seven animals and a
hundred and twenty-four plants to step on every tick of a hundred and eighty years, and
the other had a bare grid. Each run writes an archive of every birth and every death
into a directory of its own and takes it away again; -log gives the file a
name and leaves it there.
The folded year
A census once a decade says where a valley settled and nothing about how it gets through a year. For that the run has to be sampled every tick, and one year of one valley is a single noisy reading of a thing that happens two hundred times. So fold: take a reading on every tick for eight years and put each one in the bin for its own place in the calendar. Every tick that ever happened at the two hundredth tick of spring goes in one bin, and the average of that bin is what the two hundredth tick of spring looks like here.
// cmd/pyramid/season.go
// tape is one year of the valley averaged over however many years it
// was folded out of: every tick of every year goes into the bin for
// its own place in the calendar, so a curve that climbs and falls with
// the season survives and a valley that is drifting up or down over
// the whole span does not.
type tape struct {
sum [][]float64
n []int
}
func (t *tape) add(phase int, v []float64) {
for i, x := range v {
t.sum[i][phase] += x
}
t.n[phase]++
}
// ... and the bin is the tick's place in the calendar, which is the
// tick modulo the length of a year and never the tick modulo anything
// else.
phase := v.Now % terra.Year
$ go run ./cmd/pyramid -mode year -decay 0.04 -from 40 -span 8 | tail -66 | head -32
pyramid: 16x12 valley, 21 browsers off stream 12 and 8 hunters off stream 22,
every tick of years 41 to 48 folded onto one calendar year
tick season warmth plants litter browsers store born gone
0 spring 0.1464 0.00 124.05 234.88 193.24 0.1528 0.0972
150 spring 0.2500 73.85 41.21 234.62 244.87 0.2083 0.1250
300 spring 0.3706 1541.64 8.09 235.00 300.17 0.2639 0.1667
450 spring 0.5000 3780.82 4.45 235.75 309.36 0.3194 0.1528
600 spring 0.6294 5662.97 0.49 236.12 313.33 0.3194 0.1250
750 spring 0.7500 7197.06 9.35 236.00 315.01 0.3194 0.1389
900 summer 0.8536 8065.51 1.13 236.50 317.42 0.2500 0.1389
1050 summer 0.9330 5487.67 0.77 236.50 320.48 0.1944 0.1389
1200 summer 0.9830 1494.86 2.34 236.75 320.06 0.1806 0.0833
1350 summer 1.0000 17.31 3.52 236.88 315.06 0.1528 0.1389
1500 summer 0.9830 39.35 0.96 236.62 308.26 0.1944 0.1389
1650 summer 0.9330 717.64 0.55 236.88 306.98 0.1944 0.1667
1800 autumn 0.8536 918.62 3.84 236.62 304.62 0.1806 0.2083
1950 autumn 0.7500 4508.06 0.11 237.00 319.84 0.1806 0.2083
2100 autumn 0.6294 690.62 20.64 237.00 318.00 0.1389 0.2083
2250 autumn 0.5000 335.46 8.16 236.62 307.82 0.1111 0.2083
2400 autumn 0.3706 56.09 7.86 236.38 296.13 0.0694 0.2222
2550 autumn 0.2500 43.21 2.93 236.25 283.26 0.0139 0.1806
2700 winter 0.1464 32.37 10.95 235.75 270.80 0.0000 0.1528
2850 winter 0.0670 17.72 360.66 235.62 258.03 0.0000 0.1250
3000 winter 0.0170 10.51 287.42 235.50 245.15 0.0000 0.1389
3150 winter 0.0000 6.76 287.11 235.25 232.33 0.0000 0.0972
3300 winter 0.0170 0.00 277.58 235.25 219.29 0.0000 0.1111
3450 winter 0.0670 0.00 227.15 235.00 206.38 0.0556 0.1111
born and gone are creatures a hundred ticks, smoothed over a season
the second row has no column here: over every tick of these 8 years
the most hunters standing anywhere in the valley at once was 0.00
Four curves, four different years. The warmth column is a pure function of the calendar and is here as the check: it bottoms at tick 3150 and tops at 1350, which is midwinter and midsummer, and any table where it does not is a table binned on the wrong thing. The plants swing from nothing to 8,065 grams and back to nothing, and they do it twice, with a crash at midsummer and a second peak in the autumn. The browsers' stores swing from 193 to 320 and back. And the browser count runs from 234.62 to 237.00, which is a range of two and a half animals in a population of two hundred and thirty-six.
That last one is the trap this table exists to spring. Read the population column on its own and the season does nothing whatever: the valley carries the same number of animals in the deepest week of winter as it does at midsummer, to within one percent. The season is doing all of its work on the two columns beside that one, and the population is the slow sum of what those two get up to.
$ go run ./cmd/pyramid -mode year -decay 0.04 -from 40 -span 8 | tail -33 | head -8
where each curve's year bottoms out, over a season's smoothing
tick season at the low over the year share
warmth 3151 winter 0.00 0.50 0.0029
standing plants 3347 winter 0.00 1725.08 0.0000
litter 1592 summer 0.78 84.91 0.0091
a browser's store 3570 winter 197.89 284.74 0.6950
browsers walking 95 spring 234.65 236.04 0.9941
The share column is each curve's low against its own average over the year, and it separates the four cleanly. The standing crop's low is nought against an average of 1,725 grams, so it is not a curve that dips in winter, it is a curve that goes away. A browser's store falls to 70 percent of its average. The population falls to 99.4 percent of its average. Three orders of magnitude between the first of those and the last, on three quantities that are all describing the same eight years.
Now the timing, which is the part a census can never give. Four curves that all go round once a year do not go round together, and how far apart they are is a measurement: shift one of them round the calendar until it agrees best with another, and the shift that wins is the lag. The bench does that by turning each curve into a number of standard deviations from its own average, so grams and animals and energy units can be multiplied together, and then walking every one of the 3,600 possible shifts.
$ go run ./cmd/pyramid -mode year -decay 0.04 -from 40 -span 8 | tail -9 | head -7
how far behind the warmth each curve's year runs
ticks of a season agrees
the plants behind the warmth -429 -0.48 0.8758
the stores behind the plants 331 0.37 0.7865
the browsers behind the stores 211 0.23 0.9751
the deaths behind the stores 586 0.65 0.6657
The first line checks the climate and not the animals, and it passes. The plants come out 429 ticks ahead of the warmth, and the valley's calendar has the warmth running an eighth of a turn behind the light, which is 450 ticks. A plant's income is light landing on a crown, so the standing crop keeps the sun's calendar and not the thermometer's, and the measurement says so to within twenty-one ticks of a 3,600-tick year.
The next two are the chain this chapter is about. The stores follow the plants by 331 ticks, a little over a third of a season: an animal standing in a valley that has begun growing does not fill up that afternoon, it fills up over the following weeks. The population follows the stores by 211 ticks, and the agreement of 0.9751 is the highest of the four, which is the point. A full store is what pays for a child, and a child appears about two hundred ticks after the store that bought it. The fourth line is the weakest of the four at 0.6657, and it is the one to read with the table in front of you and not on its own: deaths run at 0.2222 a hundred ticks in the autumn, at 0.0833 in the summer, and the falling half of the store curve is where they happen.
So the year is a machine with two halves. Spring and early summer add animals: births peak at 0.3194 a hundred ticks and deaths sit near their low. Autumn and winter take them away: births are exactly 0.0000 for five consecutive readings, covering ticks 2,700 to 3,300, and deaths are at their highest through the whole of the autumn. The number the valley holds is the number where those two halves come out equal over a year.
$ go run ./cmd/pyramid -mode year -decay 0.04 -from 40 -span 8 | tail -24 | head -14
the winter arithmetic, on the 234 browsers the valley is carrying
grams of body, averaged over the row 31.6181
energy one gram of it charges a tick 0.002674
so a body standing still charges a tick 0.084545
grams one of its mouthfuls takes 0.8032
the store's best tick of the year 1117
what it is holding there 320.87
the store's worst tick of the year 3570
what it is holding there 197.89
what the lean half of the year took off it 122.98
ticks of standing still the best store buys 3795
ticks of standing still the worst store buys 2341
ticks of the year with under a mouthful each 1792
Those first four lines are the animal two hundred years of this valley produced, and it is a different animal from the one it was founded with. A founding browser is forty grams and charges itself four thousandths of an energy unit a gram; these average 31.6 grams and 0.002674, and their mouths take three times the founding quarter of a gram. Smaller, cheaper to keep, bigger bite. Nothing anywhere told them to be, and nothing anywhere compared two of them.
The last line is the chapter's claim arriving as a number. For 1,792 ticks of a 3,600-tick year—very nearly half of it—there is less than one mouthful of standing plant on the ground for each animal walking about on it. At the opening of summer there are 8,065 grams standing, which is ten thousand mouthfuls for two hundred and thirty-six animals. On the last two readings of the winter there are none at all. The average over the year is 1,725 grams, about nine mouthfuls each, and that average describes no week that actually happens.
A valley that carried what its average year could feed would carry several times two hundred and thirty-seven browsers. It carries what gets through the lean stretch, and the arithmetic of getting through is on the two lines above: a store that buys 3,795 ticks of standing still at the top of the year and 2,341 at the bottom, against a lean stretch 1,792 ticks long. That is the margin the population is sitting on. Put more animals on the ground and the summer crop is divided further, the peak store is lower, the lean stretch is longer because a mouthful each is harder to find, and the margin closes. No line of the program counts to 237. The worst part of the year does the counting.
Here is the mistake, and it is the one that is easiest to make and hardest to see, because the table it produces looks entirely reasonable. The fold puts each tick into a bin. The obvious bin is how far into the run this tick is, modulo a year, because that is the number lying about in the loop:
phase := (v.Now - w.opened) % terra.Year // ticks since the run opened
// instead of
phase := v.Now % terra.Year // the tick's place in the calendar
Both are a year long. Both wrap. Both give twenty-four bins that fill evenly. The bench takes a flag so the two can be run against each other instead of argued about.
$ go run ./cmd/pyramid -mode year -decay 0.04 -from 40 -span 8 -since | tail -63 | head -7
tick season warmth plants litter browsers store born gone
0 spring 0.8542 8083.47 1.09 236.50 317.45 0.2500 0.1389
150 spring 0.9334 5456.54 0.76 236.50 320.50 0.1944 0.1389
300 spring 0.9832 1468.27 2.25 236.75 320.06 0.1806 0.0833
450 spring 1.0000 16.72 3.38 236.88 315.00 0.1528 0.1389
600 spring 0.9827 41.01 0.92 236.62 308.23 0.1944 0.1389
750 spring 0.9326 716.44 0.53 236.88 307.03 0.1944 0.1667
The warmth column is the tell and it is loud. The fourth line of that table says the valley is at full warmth, 1.0000, in the middle of spring. Warmth in this world is one reading off one angle and the angle is the tick's place in the year; there is no run, no seed and no population that can put the year's hottest tick anywhere but the middle of summer. So the bin is wrong, and the bins are wrong by however far the run's opening tick is from the start of a year.
That distance is not zero and it never has been. Every valley in this book stands up half a season into the calendar and then grows for another half season before anybody is founded on it, so the first tick of these runs is tick 901 and the fold is shifted by 901 ticks, which is a quarter of the year and one. Everything the table then says about seasons is off by a season.
$ go run ./cmd/pyramid -mode year -decay 0.04 -from 40 -span 8 -since | tail -33 | head -8
where each curve's year bottoms out, over a season's smoothing
tick season at the low over the year share
warmth 2250 autumn 0.00 0.50 0.0029
standing plants 2446 autumn 0.00 1725.08 0.0000
litter 691 spring 0.78 84.91 0.0091
a browser's store 2669 autumn 197.89 284.74 0.6950
browsers walking 2794 winter 234.65 236.04 0.9941
Read down the season column and this run claims that The Hollow is coldest in the autumn and that its plants disappear then too. Every value in the table is right. Every label is wrong, and a page built on it would have spent four paragraphs explaining an autumn bottleneck that does not exist.
The reasoning from symptom to cause is one step once the warmth column is in the table, and putting it there was the only defence. Warmth is the one quantity on the page that depends on nothing but the calendar: no creature, no seed, no run history. So it is the one quantity whose answer is known before the run, and a column that is known before the run is a column that can catch a binning mistake that every other column would have hidden. The general form carries a long way past valleys. When you fold data onto a cycle, fold something you already know the answer for alongside it, and check that one first.
One detail of the two tables says exactly how much damage this kind of mistake does. The lag block at the foot of both runs is byte for byte the same. Shifting every curve by the same 901 ticks cannot change how far apart two of them are, so every relative answer on the page survived and every absolute one was destroyed. A bug that ruins half your conclusions and leaves the other half perfect is the kind you ship.
Removing the hunters
One question is left and it is the one the whole trophic web was built for. Eight hunters were founded into that valley, they killed ten browsers, and they were gone by the third year of two hundred. Did they do anything? The obvious way to find out is to found the same valley without them and hold the two runs side by side.
Two runs that differ by ten deaths in the first two years are two different worlds by the fifth, and every number after that is a fact about which world you are in. So the comparison has to be made over enough foundings that the noise between one world and another can be seen for what it is. Six world seeds, both arms, twenty-four years apiece.
$ go run ./cmd/pyramid -mode pair -years 24 -decay 0.04
pyramid: the same valley with the second row in it and without it,
6 world seeds, 24 years each, the ground's appetite at 0.04
with the hunters with none
seed browsers plants kills browsers plants kills
5 238 3762.08 10 1 7755.10 0
7 171 3225.21 10 276 1115.38 0
11 245 2810.57 11 0 0.00 0
13 217 941.03 14 0 8172.13 0
17 0 0.00 13 245 1751.36 0
19 0 0.00 14 277 1358.22 0
mean 145.2 1789.82 133.2 3358.70
1031400 ticks in 7m7.499s, 2413 ticks a second (measured here; yours will differ)
Four of the six valleys with hunters in them were still standing at the end of the twenty-fourth year and four of the six without them were, and they are not the same four. Seed 5 carries 238 browsers with the hunters and one without. Seed 17 carries none with them and 245 without. The means come out at 145.2 against 133.2, on a column whose individual readings run from nought to 277.
There is nothing there. Taking the second row out of this valley moves the browser population less than changing the world seed does, and which valleys come through is decided by the seed. The chapter set out to find the browsers worse off without their hunters, and the honest report is that after six foundings there is no measurement in either direction. It is not a surprising result once the accounts are in front of you: sixteen animals, five thousand eight hundred and eighty-two creature-ticks between them, ten kills, and then a hundred and ninety-seven years of a valley that never saw one again. A level that lasts two years out of two hundred is not a level, and nothing that lives that briefly can be read in a curve.
What the sweep does establish is as useful as the thing it failed to establish. Seeds 17 and 19 finish the first arm with no browsers and no standing plant at all, and seed 11 finishes the second the same way; seed 13 comes out of it with 8,172 grams of green valley and nothing left to eat it, and seed 5 with one animal. Four of the twelve foundings tried here lost their browsers outright inside twenty-four years and a fifth came out of it with a single animal, and three of the four took the plants down with them. The two hundred years earlier on this page happened, and they are not a promise: a page that showed you only that run would have been telling you something this table says is untrue.
Regrowth sets the animal count
Take the animals out and there is a general result here about where the numbers in a system with no numbers in it come from. Three of them turned up on this page and each came from somewhere different.
The plants' number came from a clock. A hundred and twenty-three or a hundred and twenty-four stands, every reading for two centuries. The valley holds a fixed stock of minerals, a plant borrows some to build with and pays them back into the litter when it stops standing, and how long they lie there before the ground hands them back is one over a coefficient. Slow that clock and the stock spends its life on the ground where no root can reach it, and the run says so in grams: four hundred of standing plant at the slowest setting against 3,762 at fifty ticks of waiting. The number of plants is the number the mineral cycle can keep supplied.
The browsers' number came from the worst part of the year. Not the average, and the run separates the two by a factor of several: an average year on that ground has nine mouthfuls standing for each animal and the year it is an average of has 1,792 ticks with under one. Anything that has to survive a cycle is sized by the bad part of the cycle, and the bad part is always further from the average than a mean makes it look. Anybody sizing a battery, a buffer or a reservoir does this arithmetic, and falls into the same trap: the mean is easy to measure and describes no moment that happens.
The hunters' number came from a race they were never in. A hunter can only eat what has already stopped moving, and everything that stops moving in this valley has a second customer that arrives first, takes a share of the pile and not a fixed amount, and never stops. Twenty-eight grams to the animals and 267,699 to the ground over two centuries. No coefficient on the hunters could have fixed that, and the one coefficient that touches it is doing a job for the plants that the plants cannot do without.
The last of those is what the whole page comes down to. There is exactly one number in this valley that decides whether the second row can eat, and it is the same number that decides whether the first row has anything to eat, and it points opposite ways for the two of them. Systems where one parameter serves two purposes are common and they are where tuning goes to die: there is no setting that is right, only a setting that is wrong in the direction you can afford. This valley can afford to starve its hunters and cannot afford to starve its plants, and the sweep is what makes that a decision instead of an accident.
- Given a valley holding 3,574 grams of standing plant and 7,362 grams of living animal at the same tick, explain how the second number can be twice the first without anything running out.
- Work out, from a decay of 0.02 and a browser carcass of forty grams, how many grams the ground takes off that pile on its first tick at full warmth, and say whether a mouth taking 0.1875 grams a tick is ahead or behind.
- Say why the standing plants come out 429 ticks ahead of the warmth rather than behind it, using the valley's own three weather readings.
- The browser population varies by less than one percent over a year and its stores vary by thirty. Say which of the two a page should quote when it claims a season limits a population, and why the other one is nearly useless for that claim.
- Name the column of the folded year that catches a binning mistake, say what makes it able to, and describe what the table looks like when the mistake is present.
- Given the six-seed sweep, say what would have had to be different about the hunters' lifespans before a two-arm comparison could have measured anything at all.
Exercise 1 — find the ground that feeds a hunter. The interlude worked out the decay at which a mouth on a fresh carcass draws with the ground. Predict what the sweep's income column does on either side of it, then check it, then say why the row still cannot live.
The draw is at 0.375 divided by two, divided by forty grams, which is 0.0047. The sweep straddles it with 0.0025 and 0.005, and the income column reads 46.85 and 45.41 percent on those two rows: within a point and a half of each other, and both of them the best readings in the table apart from the very slowest ground's 81.75 percent. The prediction holds in direction and the effect is real.
And it is not enough, by a factor of more than two. The reason is on the accounts block of the long run and not in the interlude: 75 percent of everything the second row ever had went into its legs. Winning the race for a pile only matters to an animal that is standing on one, and a hunter spends nearly all of its life walking to the next one. A pile does not grow back where it stands, which is the whole difference between the two rows: a browser can stand next to one plant and let the plant regrow under it, and nothing regrows under a hunter.
Exercise 2 — fold a year the valley never had. Run the seasonal fold over one year instead of eight and work out which of the page's conclusions survive it and which do not.
Try -span 1 and read the plants column. Eight years folded gives a
curve that climbs, crashes at midsummer, makes a second peak and goes to nothing;
one year gives you whichever afternoon that particular year had, and the midsummer
crash may be twice as deep or half as deep because it is one crash and not eight.
The conclusions that survive are the ones about quantities that barely move between
years: the warmth column exactly, the population column nearly, the store curve's
rise and fall roughly. The one that does not survive is the timing of the plant crash,
and that is the input to two of the four lag measurements.
Averaging a cycle over many turns is the cheapest noise reduction there is, and it costs one long run instead of one experiment per turn. What it cannot do is tell you whether the turns were alike, so read a single year alongside the fold at least once to see how much you smoothed away.
Exercise 3 — put the pyramid back on its base. The standing crop pyramid is upside down. Work out, from the two blocks the long run prints, how many times the standing plant tissue is replaced over the run, and use it to say what would have to change about the plants for the pyramid to stand the right way up.
The throughput block says the leaves built 26,774,527 grams over two centuries and the standing crop block says 3,574.86 grams are standing at the end. Divide and the standing crop was replaced about 7,490 times, which is roughly thirty-seven times a year. A browser body is minted once and stands for years. So the plants are moving grams through a very small standing amount very fast, and the animals are holding grams still.
For the pyramid to stand up, the plants would have to hold more of what they build
instead of turning it over: bigger, longer-lived, slower plants, which in this
valley means the tree rows getting the ground and not the herb rows. The
terrarium volume's own census is where to look for that, and it is a fact about
which species hold the cells and not about the animals. Put v.Census()
on the long run's yearly line and read which rows are holding the ground: an
upside-down pyramid of standing crop is a statement about turnover times, and it is
ordinary anywhere the producers are small and quick.
Two centuries of this valley took six minutes and twenty-three seconds and produced a hundred and eighty years of census, a folded year, a swept coefficient and one honest nothing. All of it went into a directory the bench made and deleted, and the only copies left are the numbers on this page. The valley kept a running archive of every birth and every death while it did all that, a whole genome to a line, in a file whose only way of answering a question is to be read from the beginning. Asking it what the mean generation time was over those two centuries means walking every record ever written. Asking it twice means walking them twice. A world that never resets keeps a history that only grows, and the thing this one is kept in cannot be asked anything about it.