The World Vol 9 · The Village
ch 91 / 105
Chapter 91

Nothing Waits for a Thought

An answer longer than a hundred milliseconds

The World has run at ten ticks a second since its first volume. Ten ticks in one second means one tick is a tenth of a second, and a hundred milliseconds is the whole budget every part of this world has ever had to work inside. The ground gets its share of it. Every plant standing on the ground gets its share. Every animal walking on the plants gets a share, and inside that share it casts nine rays, fills twenty-four numbers, is asked what it wants and does it. All of that finishes with room to spare, and it finishes with room to spare because everything in it is arithmetic on numbers that are already in memory.

A language model works nothing like that. Asking one for anything is a request to another process, over a socket, which comes back when it comes back. The measurement this volume opened on put a stopwatch on three kinds of that request at this world's own pace, and not one of the three fitted inside a tick; the dearest of them was tens of ticks long. Those are figures about one machine on one afternoon and yours will differ. The ordering will not, and the ordering is all this page needs. A tick is a hundred milliseconds and a thought is seconds, so the two of them can never be in the same call stack. Everything in this volume is a consequence of arranging that properly, and this chapter is the arrangement.

Start from what a villager has to satisfy, because it has not changed since the fifth volume and it is one method wide. Every creature in this world is steered through beast.Mind, which takes one reading of the world and returns one entry of the action table. Twenty-four numbers in, one action out, nothing else crossing, and no way for the thing on the far side to reach the valley, spend anything, or take longer than the caller has. The people founded in the last chapter answer that method with a struct of settings instead of an evolved network, and the valley never found out.

Pick is called from inside a tick. It is called once per creature per tick, in the middle of the creature phase, with the world's index open and everybody else's turn still to come. There is no version of this where Pick opens a socket. What there is instead is a place to put an answer that was worked out somewhere else, and a rule for what to do on the overwhelming majority of ticks where there is no such answer waiting.

So three things get built here, and the first two are small enough to read in one sitting. A mailbox: one slot a villager, carrying at most one already-made decision. A habit: a plain policy in Go that produces an action every tick, never fails, and asks nothing of anybody. And a console, which is a program that founds the village, ticks the world, stands one more body up for whoever is at the keyboard, and reads one command a line. By the last page there are three people keeping a sensible day in The Hollow with no model anywhere near them, and a number saying how much of that day the habit ran. That number is the floor every later measurement in this volume is taken against.

One slot with three waiting decisions

A decision is a small thing. It is a verb out of the table, the body it is about, how many grams it is about, and the tick somebody settled on it. Four numbers, and none of them is a pointer:

▣ Build · stage 1 — a decision, written down as numbers
// internal/village/mail.go

// Intent is one decision somebody has already made, written down as a
// value: which entry of the action table, the body it is about, how
// many grams it is about, and the world tick it was decided at.
//
// Every field is a number, and that is the whole of the type. Nothing
// in here is a pointer, because the side that decides and the side
// that acts run at the same time as each other: a pointer would let
// the deciding side go on editing a decision the acting side is
// already holding, and neither of them would ever find out.
// ...
type Intent struct {
	Act   beast.Act    // which entry of the table
	Whom  sim.EntityID // the body it is about, or 0 for nobody
	Grams float64      // how many grams it is about, or 0
	At    int          // the world tick it was decided at
}

At is the field that will look unnecessary and is not. A decision made on one tick is carried out on a later one, and the difference between those two numbers is a real quantity that somebody is going to want. Writing it down when the decision is made costs one integer. Working it out afterwards is impossible, because by then the only clock anybody has says now.

Now the slot. Go has one obvious thing to reach for here, and reaching for it is right: a channel is the language's own answer to "one goroutine has something another goroutine wants". What is not obvious is the three decisions that go with it, and every one of the three is about waiting.

▣ Build · stage 2 — the mailbox, and the two selects that never block
// internal/village/mail.go

// Box is a mailbox: one slot, holding at most one Intent, with three
// properties that are all about waiting and none about carrying.
//
// It holds VALUES. What crosses is a copy, so once an intent is in the
// slot nobody can change it, including whoever wrote it.
//
// A send REPLACES. Two intents cannot queue, because the second one
// was decided later about a world the first one no longer describes.
// Keeping the older one and making the newer one wait would be keeping
// the worse of the two on purpose.
//
// A receive GIVES UP. The tick side asks whether there is anything
// here and carries on either way, so nothing about a tick's cost
// depends on whether anybody has finished thinking.
//
// A Box nobody opened is an empty mailbox rather than a crash: the
// slot is a nil channel, both selects below fall to their default, and
// a villager with no mailbox keeps to its habit forever.
// ...
type Box struct {
	slot chan Intent
	// ...
}

// NewBox opens a mailbox: one slot, and both ends give up rather than
// wait for the other.
func NewBox() Box { return Box{slot: make(chan Intent, 1)} }
// Send puts an intent in the slot, throwing away whatever was there,
// and never waits for anybody.
//
// The two selects are one operation in two halves. The first empties
// the slot if it has anything in it; the second fills it. Both give up
// at once, so a Send costs the same whether the slot was full, empty,
// or filled by somebody else between the two halves. In that last case
// this intent is the one dropped, which is what replacement means from
// the other side of the slot.
func (b Box) Send(i Intent) {
	// ...
	select {
	case <-b.slot:
	default:
	}
	select {
	case b.slot <- i:
	default:
	}
}

// Take empties the slot if there is anything in it and gives up at
// once if there is not. It is the only read there is: nothing peeks,
// because a slot that can be looked at without being emptied is a slot
// two ticks can act on.
func (b Box) Take() (Intent, bool) {
	select {
	case i := <-b.slot:
		return i, true
	default:
		return Intent{}, false
	}
}
$ go run ./cmd/slot -mode box
slot: one slot, three properties, and neither end ever waits

  the slot       one intent, 32 bytes of it, held by value
  a send         throws away what is there, fills the slot, returns
  a receive      empties the slot if it is full, returns either way

  what happens                                      slot   what came out
  a mailbox nobody has written to yet                  0   -
  send: walk, decided at tick 100                      1   -
  send: hand to creature 2, decided at tick 140        1   -
  take                                                 0   hand to creature 2, decided at tick 140
  take                                                 0   nothing

  the intent decided at tick 100 is gone and nothing reported it.
  Two sends and one take is not a lost message: the second decision
  was made 40 ticks after the first, about a world the first one had
  stopped describing, and a queue would have handed over the worse
  of the two and then handed over the better one a tick later.

  a decision crosses as a value, so posting one is copying it
  posted                   hand to creature 2, decided at tick 300
  the poster then edits    take from creature 3, decided at tick 900
  taken out of the slot    hand to creature 2, decided at tick 300

  the same two moves through a slot that carries a pointer
  posted                   hand to creature 2, decided at tick 300
  the poster then edits    take from creature 3, decided at tick 900
  taken out of the slot    take from creature 3, decided at tick 900
  the decision changed after it was posted. What crossed was 8 bytes
  of address, both sides are looking at the one intent, and neither of
  them can find out that the other one moved it

  a mailbox nobody opened is an empty mailbox and not a stop
  sent, then taken         nothing
  the slot is a channel nobody made, so both selects fall to their
  default and a villager with no mailbox keeps to its habit

  a thousand receives on an empty slot, which is what a tick does
  receives                 0 of 1000 found anything, and not one of them waited

Read the middle two blocks together, because they are the same two moves run twice. Post a decision, then edit the copy you still have. Through a slot carrying values the posted decision does not move: what went in was a copy of thirty-two bytes and your edits land on your own. Through a slot carrying pointers, eight bytes of address crossed, both ends are looking at the one struct, and the decision the tick eventually acts on is the one the deciding side happened to have finished editing by then. Nothing reports it. There is no error, no panic, no line in a log; the villager does something nobody chose.

That bug is easy to write and hard to see, and the reason is that it is invisible in a single-threaded test. Post, edit, take, and you can see it happen in a straight line, as the run above does. Post from a goroutine that is still working while the tick side reads, and the same bug is a race whose symptom is one wrong action every few thousand ticks. The type is what stops it, and the type stops it everywhere at once.

The last two blocks of that run are about the degenerate cases, and both of them are deliberate. A Box nobody opened has a nil channel in it, and a send or a receive on a nil channel blocks forever; inside a select with a default, neither of them ever gets the chance. So the zero value of a mailbox is an empty mailbox that quietly refuses everything, and a villager holding one keeps to its habit for the rest of its life. That is the right failure for this world: it is one villager going quiet, and not a tick that never returns.

A thousand receives on an empty slot found nothing a thousand times, and the run says the thing that matters about them: not one of them waited. That is the operation a tick performs. It is what a villager's Pick does before anything else, on every one of the ten ticks a second this world runs at, whether or not there is a worker on the far side and whether or not that worker is halfway through anything.

▣ Build · stage 3 — the tick side of the seam, which is nine lines
// internal/village/mail.go

// Mind is what answers beast.Mind for a villager: a mailbox and a
// habit, and nothing else at all. It holds no database handle, no
// client, no valley and no clock.
//
// Pick is the tick side of the seam. Neither of its two paths can
// wait: Take gives up at once, and Habit is a value rather than an
// interface, so there is no nil here to check and no failure to
// handle. A villager always has an answer.
type Mind struct {
	Box   Box
	Habit Habit

	// What the tick side did, kept for a bench to print.
	Took Intent // the last intent taken out of the slot
	Read int    // ticks that found one there
	Ran  int    // ticks that found nothing and ran the habit
}

// Pick takes whatever is in the slot, and finding nothing, runs the
// habit.
func (m *Mind) Pick(row *beast.Senses) beast.Act {
	if i, ok := m.Box.Take(); ok {
		m.Took, m.Read = i, m.Read+1
		return i.Act
	}
	m.Ran++
	return m.Habit.Pick(row)
}
$ go test ./internal/village/ -run 'TestASendReplacesWhatIsInTheSlot|TestATakeOnAnEmptySlotGivesUpAtOnce|TestAnIntentCrossesAsAValueAndNotAsAPointer|TestAMailboxNobodyOpenedIsAnEmptyMailbox|TestAnEmptySlotRunsTheHabitAndAFullOneDoesNot' -v
=== RUN   TestASendReplacesWhatIsInTheSlot
--- PASS: TestASendReplacesWhatIsInTheSlot (0.00s)
=== RUN   TestATakeOnAnEmptySlotGivesUpAtOnce
--- PASS: TestATakeOnAnEmptySlotGivesUpAtOnce (0.00s)
=== RUN   TestAnIntentCrossesAsAValueAndNotAsAPointer
--- PASS: TestAnIntentCrossesAsAValueAndNotAsAPointer (0.00s)
=== RUN   TestAMailboxNobodyOpenedIsAnEmptyMailbox
--- PASS: TestAMailboxNobodyOpenedIsAnEmptyMailbox (0.00s)
=== RUN   TestAnEmptySlotRunsTheHabitAndAFullOneDoesNot
--- PASS: TestAnEmptySlotRunsTheHabitAndAFullOneDoesNot (0.00s)
PASS
ok  	theworld/internal/village	0.003s

Habit is a struct value on that type and not an interface, and the difference is the whole of why Pick has no error path. An interface field can be nil, so a Pick written around one has to decide what to do about that, and whatever it decides is a branch somebody has to test. A value cannot be nil. The zero value of this one answers every reading of the world with a rest, which is a real answer and a legal action, so the worst thing an unfilled Mind can do is stand still.

The second test in that list is the one that cannot be written any other way. TestATakeOnAnEmptySlotGivesUpAtOnce asks an empty slot for an intent a thousand times and asserts that it got nothing each time. If the receive waited, the test would not fail: it would never finish, and the package's test binary would hang until the toolchain killed it ten minutes later. That is the only way to test "does not block" without putting a clock in a test, and a clock in a test is a test that fails on a loaded machine.

The rule underneath, finished

The errand the last chapter drove three people with is a policy of about thirty lines that reads the fan, walks toward the nearest body it can see, and puts a parcel in their hands when it gets close enough. It has one drive in it, and a field on the struct called Hungry that names what to do when that drive has nothing to say. Nothing ever filled that field. A giver standing next to a neighbour with a full store hands over grain until there is nothing left to hand over, and then rests, and then dies of it, on ground with plants standing in plain sight.

The rule that fills it is a total order over a handful of drives, asked in one fixed order, where the first drive with something to say wins and the last one always has something to say. Four drives is enough for a village to keep a day:

▣ Build · stage 4 — four drives, one order, no way out of the bottom
// internal/village/habit.go

// Habit is the utility rule: what a villager does on every tick
// nothing has told it to do anything else, which in this world is
// nearly all of them.
//
// It is four drives asked in one fixed order, and the first one with
// something to say wins:
//
//	1  hunger  below Feed, with a plant in sight            eat
//	2  errand  Trade is on, the store is on the far side
//	           of Deal, and a body is in sight              hand or take
//	3  forage  below Fill, with a plant in sight            eat
//	4  idle    none of the above                            Idle
//
// The order is the whole design. It is not a score with weights on it
// and there is nothing to tune: drive 1 sits above drive 2 because a
// villager that hands its store away while it is starving is a
// villager that starves, and drive 3 sits below drive 2 because a full
// store is worth less than a neighbour who needs something.
// ...
type Habit struct {
	Feed  float64    // eat below this share of a full store
	Deal  float64    // trade while the store is on the far side of this share
	Fill  float64    // stop topping up at this share
	Trade bool       // whether drive 2 is asked at all
	Idle  beast.Act  // the last resort, and the zero value of it is a rest
	Eat   beast.Hunt // drives 1 and 3
	Give  Errand     // drive 2
}

// Pick asks the four drives in order and hands back one entry of the
// table.
func (h Habit) Pick(row *beast.Senses) beast.Act {
	store := row[beast.StoreAt]
	switch {
	case store < h.Feed && sighted(row, beast.Plant):
		return h.Eat.Pick(row)
	case h.trading(store) && sighted(row, beast.Creature):
		return h.Give.Pick(row)
	case store < h.Fill && sighted(row, beast.Plant):
		return h.Eat.Pick(row)
	}
	return h.Idle
}
$ go run ./cmd/slot -mode rule
slot: the rule that runs on every tick nothing has been posted

  the settings   feed below 25%, trade past 40%, top up below 90%
  the row        24 numbers, of which this rule reads 19: the fan and the store
  this one       a giver, eating within 0.5000 cells and handing within 1.4142,
                 over a sight span of 12 cells and a fan of 9 rays

  the four drives, asked in this order, first one with something to say wins
   1 hunger   below 25% of a full store, with a plant in sight
   2 errand   past 40% of one the trading way, with a body in sight
   3 forage   below 90% of one, with a plant in sight
   4 idle     none of the above, and there is no condition on this one

  one reading at a time: nine rays, one store, and the answer
   store  what the fan met                   drive    the answer
     10%  a plant ahead, a person beside it  hunger   bite
     30%  a plant ahead, a person beside it  forage   bite
     60%  a plant ahead, a person beside it  errand   hand
     95%  a plant ahead, a person beside it  errand   hand
     60%  a plant ahead, nobody about        forage   bite
     95%  a plant ahead, nobody about        idle     turn right
     10%  a plant well off to the left       hunger   turn left
     10%  a plant ahead and six cells off    hunger   walk
     10%  nothing at all                     idle     turn right

  and every way the fan can come back: 9 rays, 5 things a ray can meet
  readings handed to the rule                   5859375
  readings it answered                          5859375
  readings it did not                                 0

  which drive answered, and with what
  drive      readings        walk   turn left  turn right        bite        hand
  hunger      1690981      433470      563695      563608      130208           0
  errand      3381962      658564     1127322     1127326           0      468750
  forage       242461       58942       80862       80811       21846           0
  idle         543971           0           0      543971           0           0
  it named 5 of the 9 entries in the table, and never named these 4:
  rest, sprint, strike, take

  not one of those 5859375 readings came back without an entry of the table,
  and it is the last arm of the switch that says so: nothing is asked of
  the row there, so there is no way out of the bottom of this rule. The
  two fallback fields inside the drives were never reached either, because
  the order asks each drive only where its own fallback cannot fire

The nine hand-made readings in the middle are the order working. The same fan, the same neighbour standing in the same place, and one number moved: a tenth of a store and the villager eats, three tenths and it eats, six tenths and it hands over. The first two rows are answered by different drives and come back with the same action, and that is not redundancy. Drive 1 is need and drive 3 is opportunity, and they sit on either side of the errand because a person who is hungry feeds themselves first and a person who is comfortable helps somebody else first. Change nothing but which side of drive 2 the eating sits on and you have written a different person.

The bottom half is the claim this rule has to be able to make. There are nine rays and five things a ray can come back with, so there are 1,953,125 ways the fan can be filled in; at three store levels that is 5,859,375 readings, and the bench hands the rule every one of them with the distances shuffled a different way each time so the search for the nearest ray is asked every question it can be asked. Every reading came back with an entry of the table. Nothing failed, because there is nothing in this function that can fail: no error return, no allocation, no index computed from a number the world supplied, and a final arm on the switch with no condition attached to it.

The two fallback fields are worth one more sentence, because they are the reason this is a finish and not a rewrite. Eat carries a field for what to do with no plant in sight and Give carries the Hungry field that started this section, and both of them are still nil. The order is what makes them unreachable: the eating drives are asked only when a plant is in the row, and the errand is asked only when a body is in the row and the store is on the trading side of the threshold, which are exactly the two conditions those fallbacks exist to handle. A field nothing fills is a defect when something can reach it, and a fact about the caller when nothing can.

▣ Build · stage 5 — the order, and the numbers no valley makes
// internal/village/habit_test.go
	for _, c := range []struct {
		what  string
		hits  []beast.Hit
		store float64
		drive int
	}{
		{"starving, with both in sight", both, 0.10, 0},
		{"comfortable, with both in sight", both, 0.60, 1},
		{"comfortable, with nobody in sight", plants, 0.60, 2},
		{"between Feed and Deal, with both in sight", both, 0.30, 2},
		{"full, with a plant in sight and nobody near", plants, 0.95, 3},
		{"starving, with nothing in sight", none, 0.10, 3},
	} {
	// ...
$ go test ./internal/village/ -run 'TestTheHabitAsksItsFourDrivesInOneOrder|TestTheHabitAnswersEveryWayTheFanCanComeBack|TestTheHabitAnswersNumbersNoValleyWouldEverProduce|TestAHabitWithEveryDriveOffStandsStill' -v
=== RUN   TestTheHabitAsksItsFourDrivesInOneOrder
--- PASS: TestTheHabitAsksItsFourDrivesInOneOrder (0.00s)
=== RUN   TestTheHabitAnswersEveryWayTheFanCanComeBack
    habit_test.go:99: 1953125 readings, every one answered, 5 entries of the table named
--- PASS: TestTheHabitAnswersEveryWayTheFanCanComeBack (0.25s)
=== RUN   TestTheHabitAnswersNumbersNoValleyWouldEverProduce
    habit_test.go:129: 729 readings of numbers a valley cannot make, every one answered
--- PASS: TestTheHabitAnswersNumbersNoValleyWouldEverProduce (0.00s)
=== RUN   TestAHabitWithEveryDriveOffStandsStill
--- PASS: TestAHabitWithEveryDriveOffStandsStill (0.00s)
PASS
ok  	theworld/internal/village	0.252s

The third of those four is the one people leave out. It fills rows with numbers no valley in this book has ever produced: both infinities, a NaN, and the two ends of what a float64 holds, in the distance slots and in the store slot. None of those is a reading this world makes. All of them are readings this function has to survive, because "never fails" is a claim about the function and not about its callers, and the day somebody hands it a row from somewhere new is the day the claim gets tested for real. It survives them for a plain reason: every number in the row is compared and never indexed by, and a comparison against a NaN is false, so a ray reporting nonsense loses every contest it enters.

One distinction before this rule goes near a world, because it will otherwise get muddled the first time a run prints a refusal. The habit never fails to produce an action. The world can still refuse the action it produced. Walking into open water is refused by the ground rule; handing a parcel to somebody who has drifted a cell too far away is refused by the transfer rule. A refused action costs the tick and is spent standing there, exactly as it does for every animal in this world. Those are two different properties with two different owners, and the rule owning the first one is what keeps the tick's cost fixed.

A decision that arrives thirty ticks late

Now the far side, and the first question is where it hangs off. The daemon that ran a valley unattended for weeks in the seventh volume has a comment on one line of its loop calling that line the one place where no phase is part way through, no view is open and no creature is half stepped. Everything in that loop which is not a tick happens there: the snapshot, the signal check, the stop. The eighth volume hung a between-ticks job on the same line for the same reason. The far side of the seam hangs there too, and it is not in terra.Valley.Phase, not in beast.Roster.Seen, not in Born, and above all not in Pick. Those are all inside a tick.

No run on this page calls a model. There is no server, no container and no socket anywhere in these runs, and that is the point of them: what is being measured is the crossing, so the far side is a goroutine that answers a stated number of ticks after it is asked, and how many ticks is a flag the bench prints. The answers it gives are five verbs written down in a list. Nothing here decides anything, and a bench that pretended to decide would be measuring its own pretending.

▣ Build · stage 6 — the boundary, one worker, and a slot between them
// cmd/slot/late.go
	for t := 0; t < s.ticks; t++ {
		// The boundary. No phase is part way through here, no view is
		// open and no creature is half stepped, so this is where a
		// finished answer is handed over and where the next request is
		// made. Neither of those two things is inside a tick.
		if pending != nil && v.Now >= pending.due {
			close(pending.release)
			// This waits for the hand-over and not for the answer.
			// The answer was finished at the top of this boundary;
			// what is being waited on is one channel operation, and
			// it is here so that this run is the same run on a fast
			// machine and a slow one.
			<-pending.landed
			// ...
		}
		if pending == nil && t%s.every == 0 {
			// ...
			go func(j *job, box village.Box) {
				<-j.release
				box.Send(j.what)
				close(j.landed)
			}(pending, minds[who].Box)
		}

		v.Tick()
		// ...
	}
$ go run ./cmd/slot -mode late
slot: 3 people, one worker, and an answer that takes 30 ticks

  the world      seed 5, 12x8 cells, founded at tick 901
  the run        600 ticks, ungoverned
  the pace       10 ticks a second, so a tick is 100ms
  the worker     one, asked every 40 ticks, answering after 30
  the mailbox    one slot, a send that replaces and a receive that gives up
  the habit      feed below 25%, trade past 40%, top up below 90%

   # villager  posted at  landed at  taken at  ticks old   the intent
   1 Halla           901        931       932         31   hand to creature 2
   2 Ander           941        971       972         31   turn left
   3 Mose            981       1011      1012         31   walk
   4 Halla          1021       1051      1052         31   take from creature 3
   5 Ander          1061       1091      1092         31   rest
   6 Mose           1101       1131      1132         31   hand to creature 1
   7 Halla          1141       1171      1172         31   turn left
   8 Ander          1181       1211      1212         31   walk
   9 Mose           1221       1251      1252         31   take from creature 2
  10 Halla          1261       1291      1292         31   rest
  11 Ander          1301       1331      1332         31   hand to creature 1
  12 Mose           1341       1371      1372         31   turn left
  13 Halla          1381       1411      1412         31   walk
  14 Ander          1421       1451      1452         31   take from creature 1
  15 Mose           1461       1491      1492         31   rest

  what drove each tick
  villager      ticks   from an intent  from the habit
  Halla           600                5             595
  Ander           600                5             595
  Mose            600                5             595
  together       1800               15            1785

  every intent in this run was 31 ticks old when it was carried out:
  30 ticks on the far side of the seam and one more to be taken out of
  the slot. A villager acting on it is acting on a world that has moved
  on 31 ticks since anybody looked at it.

  and no tick in this run waited for anybody: 1785 of the 1800 ticks found
  an empty slot, gave up on it at once and ran the habit instead

  600 ticks in 12ms, 48247 ticks a second (measured here; yours will differ)

The column to read twice is the last number in each row. Every intent in that run was thirty-one ticks old when the villager acted on it: thirty on the far side, and one more to be taken out of the slot. Thirty-one ticks at ten ticks a second is a little over three seconds of world, in which three people and a valley full of plants carried on without waiting for anybody. Halla's first intent was to hand a parcel to creature 2. By the time it was carried out, creature 2 had had thirty-one turns of its own and might be somewhere else.

Every decision a villager makes is a decision about a world that has already moved on. That is the design and not a defect of it. There is no arrangement where it is otherwise: an answer that takes time is an answer about the past, and the only way to make it an answer about the present would be to stop the world while it was worked out, which is the thing this whole chapter exists to avoid. What makes it safe is the field on Intent that looked unnecessary two sections ago. A decision arrives carrying the tick it was made at, so how stale it is is a number the engine holds, and premises that have gone away can be checked against the world before anything is done about them.

The seam: a tick side, a boundary, and one slot between them Three labelled areas run left to right. On the left, the tick, a hundred milliseconds long, containing a receive that gives up and a habit that always answers. In the middle, one slot holding at most one intent. On the right, the far side, which takes as long as it takes. An arrow runs from the far side into the slot, labelled as a send that replaces and never waits; a second arrow runs from the slot into the tick, labelled as a receive that gives up at once. A band along the bottom names what crosses the slot, which is four numbers copied, and what never crosses it, which is a pointer, a handle and a wait. THE ONLY THING THE TWO SIDES SHARE the tick 100 ms, every 100 ms Take: gives up at once empty? run the habit an action, every time one slot at most one intent 32 bytes, by value the far side as long as it takes Send: replaces never waits for a reader started at the boundary WHAT CROSSES, AND WHAT NEVER DOES four numbers, copied the verb, the body, the grams, and the tick it was decided at nothing can edit it afterwards a pointer, a handle, a wait no address, so no edit in flight no valley, no socket, no clock no send and no receive that blocks
Figure 91.1 — the two halves of a villager, and the thirty-two bytes they are allowed to have in common. The left box runs on a fixed budget and the right box has no budget at all, so nothing that joins them may be able to wait. What makes that possible is that the slot is the only join: everything else a decision might have wanted to reach is on one side of it or the other.
∑ Math Interlude — how much of a day is the habit

Take the run above and count. It went for six hundred ticks with three people in it, so eighteen hundred creature-ticks were handed out. Fifteen intents were delivered. Fifteen out of eighteen hundred leaves 1,785, and the run prints all three numbers.

Turn that into a share. 15 divided by 1,800 is 0.00833, which is a third of one per cent. Put the other way round, 1,785 divided by 1,800 is 0.99167, so the habit answered 99.2% of the ticks in that village. The rule built in the last section is not the degraded case that runs when something has gone wrong. It is what a villager does with nearly the whole of its life, and the thing on the far side of the seam is the rare event.

Now the arithmetic that predicts it, so the number can be worked out before a run instead of counted afterwards. One worker serves one villager at a time and takes R ticks over each, so with n villagers, each of them is served once every n times R ticks. Each answer drives exactly one tick, because the slot is emptied by the first receive that finds it. So the share of a villager's ticks that come from the far side is one over n times R:

share = 1 ÷ (n × R)

With three people and thirty ticks an answer, that is 1 divided by 90, which is 0.0111, or 1.1%. The run measured 0.83%, and the gap is the cadence: the bench was told to ask every 40 ticks and the worker only needs 30, so it idles for ten ticks out of every forty. Take the idling away, as the first exercise at the end of this chapter does, and the count goes to 19 out of 1,800, which is 1.06%. The last sliver between that and 1.11% is one request still out on the far side when the run stopped.

The useful thing about that formula is which way its two letters point. Both are on the bottom, so both of them make the share smaller. More people means each one waits longer. A dearer answer means the same. There is no arrangement of a village where a slow far side drives most of the ticks, and that is true before anybody has chosen how many people to found or what to ask them.

nvillagers one worker is serving, taken in turn
Rticks one answer takes on the far side of the seam
sharethe fraction of one villager's ticks that an intent drove
a × ba multiplied by b
a ÷ ba divided by b
⚠ Worked failure — write the send the way sends are usually written

A mailbox is a channel and a channel already has a send. Writing b.slot <- i is one line where the version above is eight, it needs no select and no default, and it does something a reasonable person would call the right thing: it puts the intent in the slot, and if the slot is full it waits until the tick side has taken what is there. Nothing is ever dropped. It compiles, it vets clean, and it is behind a flag so it can be run.

// internal/village/mail.go

// Waiting opens the mailbox as it is usually written the first time:
// one slot and a plain send, which stops the sender until somebody
// takes what is there. Nothing this book ships opens one.
func Waiting() Box { return Box{slot: make(chan Intent), waits: true} }

func (b Box) Send(i Intent) {
	if b.waits {
		b.slot <- i
		return
	}
	// ...
}
$ go run ./cmd/slot -mode late -blocking
slot: 3 people, one worker, and an answer that takes 30 ticks

  the world      seed 5, 12x8 cells, founded at tick 901
  the run        600 ticks, ungoverned
  the pace       10 ticks a second, so a tick is 100ms
  the worker     one, asked every 40 ticks, answering after 30
  the mailbox    one slot, a send that WAITS for a reader
  the habit      feed below 25%, trade past 40%, top up below 90%

fatal error: all goroutines are asleep - deadlock!

The run prints its settings and stops dead. Under that line the runtime prints a dump naming every parked goroutine, which is not quoted here because the numbers in it belong to one process; the two lines that matter say goroutine 1 [chan receive] in the loop and [chan send] in village.Box.Send. The Go runtime noticed that every goroutine in the program was waiting for another one and gave up on the whole process. Not one intent was ever delivered.

Work back from the symptom. The boundary released the worker and then waited for the hand-over, because that is what makes the run reproducible: the answer is finished, so handing it across should be one channel operation and take no time at all. With a replacing send it is exactly that. With a plain send it is a rendezvous, and a rendezvous needs somebody on the other end. The only thing that ever reads that slot is Pick, Pick runs inside v.Tick(), and v.Tick() is the line after the boundary. The reader cannot arrive until the boundary lets go, and the boundary cannot let go until the reader arrives.

The tempting reading of that is "the boundary should not have waited", and it is the wrong one. Rearrange the loop so the boundary does not wait and the deadlock goes away, but the property that caused it does not: a send that waits is a send whose cost depends on somebody else's schedule. The reader of a villager's slot stops arriving the moment that villager stops being stepped, which happens when it starves and is struck off the roster, and there is exactly one worker in this design. One person dying would take the whole village's thinking with it, at some tick nobody can predict, weeks into an unattended run. A deadlock on the first delivery is the cheapest possible version of that bug, and it is only that cheap because the boundary waits.

The cause is one word in the design rather than one line in the code. A send that waits waits for a reader, and nothing anywhere in this world promises that a reader will come back. Replacement is what turns that promise into something the sender never needs.

Somebody to walk over and look at

A village with nobody in it is a village nobody can watch. Everything so far has been read out of a bench's own tables, which is the right way to check arithmetic and a poor way to find out whether a place should hold a body. So there is a second program: cmd/village, which founds the ground, founds the people out of configs/village.json, stands one more body up for whoever is at the keyboard, and then reads one command a line and writes one event a line back. The world ticks while it reads.

It has five verbs and they are closed: look, who, carry, go and wait. It is not a player and not a client. It opens no socket, speaks no protocol, has no window and draws nothing. What it has is a body on the same roster as everybody else, stamped from the same row, paying the same prices for the same actions and starving on the same clock.

And that body reaches the world exactly the way a villager does. Typing go 4 does not move anything: it puts four intents, one a tick, into a mailbox, at the boundary, between two ticks. The tick side takes them or does not. Your own body is driven by the same Mind the villagers are, with the same Take in front of it and the same rule underneath it, and the only difference is which rule:

▣ Build · stage 7 — your own body, on the rule with every drive turned off
// cmd/village/main.go
	c.you = k.Spawn(beast.Centre(cell), v.Now)
	c.you.Store = k.Full / 2
	// Your own body runs the same rule the villagers do, with every
	// drive turned off. The zero value of the last resort is a rest, so
	// a console nobody is typing at stands where it was put.
	c.yours = &village.Mind{Box: village.NewBox()}
	c.you.Mind = c.yours
	r.Add(c.you)
// cmd/village/main.go — the posting, which is at the boundary
func (c *console) walk(n int, act beast.Act, post bool) (took, refused int, why error) {
	was, nos := c.yours.Read, c.nos
	for i := 0; i < n; i++ {
		if post {
			c.yours.Box.Send(village.Intent{Act: act, At: c.v.Now})
			c.posted++
		}
		c.v.Tick()
		c.ran++
		// ...
	}
	// ...
}

village.Mind{Box: village.NewBox()} leaves the habit at its zero value, and the zero value of a habit has every threshold at nothing, no trading, and a last resort of beast.Rest, which happens to be the first entry of the action table. Every drive's condition is a comparison against nought that no store can satisfy, so every reading falls through to the last arm, and a console nobody is typing at stands where it was put. There is no special case in the code for "this body is the operator's". It is the same rule with the numbers turned down.

▣ Build · stage 8 — a walk through Firstlight, driven from a file
# cmd/village/walk-91.txt
# Chapter 91's walk. Nothing in this file is sent to anybody but your
# own body: the villagers are running their own rule the whole time.
who
carry
look
go left 6
look
go 4
who
wait 300
who
carry
$ go run ./cmd/village -script cmd/village/walk-91.txt
village: a console beside the world, reading cmd/village/walk-91.txt

  the world      12x8 cells, tick 901, 12 plants standing at 1517.5 grams
  the village    3 people, each on a mailbox and a habit
  you            creature 4 on 10,5, one more body on the same roster,
                 paying the same prices, on a mailbox and no habit at all
  the pace       ungoverned: as fast as this machine will carry it
  the verbs      look, who, carry, go [left|right] N, wait N
  the fan        . nothing  * a plant  o a body  ~ water  # rock

  tick    901  the world is running; nothing you have not typed is yours
> who
  tick    901  Halla    creature 1 on 8,5, 2.0000 cells off, carrying 200.0000 grams, settled law
  tick    901  Ander    creature 2 on 9,5, 1.0000 cells off, carrying  40.0000 grams, settled law
  tick    901  Mose     creature 3 on 8,6, 2.2361 cells off, carrying 120.0000 grams, settled law
> carry
  tick    901  you are carrying 100.0000 grams, with room for 100.0000 more, out of a full 200.0000
> look
  tick    901  the fan, left to right: # # # # # # # # *
  tick    901  nearest plant    0.7500 cells, on ray 9 of 9
  tick    901  nearest rock     0.5000 cells, on ray 5 of 9
> go left 6
  tick    907  you posted turn left 6 times and 6 of them were taken out of your slot
  tick    907  you are on 10,5 facing west
> look
  tick    907  the fan, left to right: * * o o o o o * *
  tick    907  nearest plant    0.7500 cells, on ray 1 of 9
  tick    907  nearest body     0.7500 cells, on ray 3 of 9
> go 4
  tick    911  you posted walk 4 times and 4 of them were taken out of your slot
  tick    911  you are on 9,5 facing west
> who
  tick    911  Halla    creature 1 on 8,5, 1.0000 cells off, carrying 196.3250 grams, settled law
  tick    911  Ander    creature 2 on 9,5, 0.0000 cells off, carrying  42.7925 grams, settled law
  tick    911  Mose     creature 3 on 8,6, 1.4142 cells off, carrying 121.3250 grams, settled law
> wait 300
  tick   1211  you waited 300 ticks and did nothing with any of them
> who
  tick   1211  Halla    creature 1 on 8,5, 1.0000 cells off, carrying  75.6150 grams, settled law
  tick   1211  Ander    creature 2 on 9,5, 0.0000 cells off, carrying 112.7225 grams, settled law
  tick   1211  Mose     creature 3 on 8,6, 1.4142 cells off, carrying 161.0750 grams, settled law
> carry
  tick   1211  you are carrying 104.3588 grams, with room for 95.6412 more, out of a full 200.0000

  ticks run                                       310
  intents you posted                               10
  of those, taken out of your slot                 10
  of those, refused by the check                    0
  ticks your body found the slot empty            300
  intents anybody posted to a villager              0
  ticks the villagers ran their own rule          930

  310 ticks in 7ms, 46881 ticks a second (measured here; yours will differ)

The first look is a wall. The body was stood up on 10,5 facing east and the whole eastern column of this valley is rock, so eight of the nine rays came back with a rock and the ninth found a plant three quarters of a cell away. Six turns to the left is half a turn, because one turn action swings the heading by a twelfth of a whole one, and the second look is the village: two plants, five rays that ended on a body, two more plants. There are only three people out there and one of you, so more than one of those five rays found the same person. That is what somebody standing there sees, cast by the ray caster every animal in this world has used since the volume that built it.

The interesting part is the three hundred ticks in the middle where nothing was typed. Halla went from 196 grams to 75; Ander went from 42 to 112; Mose went from 121 to 161. Nobody sent any of them anything, and the run says so on its last block: no intent was posted to a villager at all. What took a hundred and twenty grams off Halla and put most of them somewhere else, in half a minute of world, was three copies of the rule from the last section, asking four questions each, ten times a second.

And your own store went up. You arrived carrying a hundred grams, did nothing at all for three hundred ticks, and came away with 104.3588. That figure is net of what three hundred ticks charged your body for standing there, so rather more than four grams arrived. Halla's errand hands a parcel to whoever has the most room inside her reach, and once Ander had filled up past you, that was you. The action table does not know what a person is and has never been told what a console is; it is two bodies and a parcel, and you were standing there.

Which leaves the run the rest of this volume gets measured against. Three people, a live valley, two thousand ticks, and nothing on the far side of any mailbox at all.

▣ Build · stage 9 — the floor, with no model within a mile of it
$ go run ./cmd/slot -mode day -ticks 2000
slot: a day with nothing at all on the far side of the seam

  the world      seed 5, 12x8 cells, tick 901, 12 plants at 1517.5 grams
  the run        2000 ticks, which is 200 seconds of world at 10 ticks a second
  the village    3 people out of configs/village.json
  the mailboxes  opened and never written to: nothing posts anything here
  the habit      feed below 25%, trade past 40%, top up below 90%

  who trades and who does not, worked out from the roll and not written in it
  name      founded holding   the second drive
  Halla            200.0000   hands over
  Mose             120.0000   neither
  Ander             40.0000   takes

  the errand on its own, which is the rule as it was first written:
  one drive, and a fallback field with nothing in it
  name         at first      at last   after the run
  Halla        200.0000      -0.0300   starved on tick 1471
  Ander         40.0000      -0.0800   starved on tick 1476
  Mose         120.0000      78.6350   standing
  1 of 3 standing after 2000 ticks

  the habit, which is four drives asked in one order
  name         at first      at last   after the run
  Halla        200.0000      91.1613   standing
  Ander         40.0000     180.0603   standing
  Mose         120.0000     102.7601   standing
  3 of 3 standing after 2000 ticks

  what the habit asked for over 6000 creature-ticks, and what the check allowed
  action           asked
  walk               233
  turn left          344
  turn right        1114
  bite              3398
  hand               832
  take                79
  together          6000
  the rule was asked 6000 times and answered 6000 times
  refused   158 times: the cell ahead is open water or off the grid
  refused   426 times: no other living creature inside reach
  a refused action costs the tick and is spent standing there, and the
  rule failing and the world refusing are two different things

  what the ground carried, in grams
  standing at the founding                  1517.4652
  taken off standing plants                  901.8115
  standing at the end                        301.0757
  the village burned being alive in it       480.0000
  plants standing at the founding                  12
  plants standing at the end                        5
  the ground is carrying less than it was. 3 people eating for 2000 ticks
  take more off this valley than it grows back, which is a fact about
  12 plants and not about the rule: run it long enough and the last of
  them is eaten and everybody starves whatever they are being driven by

  this is the floor: 3 people, 6000 creature-ticks, every one of them
  answered, no mailbox written to, no worker running, nothing outside
  this process asked for anything, and 3 of 3 still standing

  2000 ticks in 24ms, 82762 ticks a second (measured here; yours will differ)

Two runs over the same ground from the same seed, and the only difference between them is what answers Pick. The errand on its own loses two people inside five hundred ticks of each other: the giver hands everything away and starves at 1471, and the taker starves five ticks later because there is nobody left with a parcel to take. The one who trades with nobody is the one who lives, which is as clear a statement of what a missing drive costs as this world is going to produce. Four drives in one order, and all three are standing at the end with between 91 and 180 grams in the store.

The middle table is the claim that matters for everything after this page. Six thousand creature-ticks were handed out and six thousand actions came back, so the rule was asked on every tick every person got and it answered every time. Five hundred and eighty-four of those actions were refused by the world, and the run keeps the two facts in separate columns on purpose: the check refusing an action is the world's business, and it costs the tick either way. What the rule guarantees is narrower and more useful. There is never a tick where nobody has an answer.

The last block is the honest part. Twelve plants at the founding and five at the end; 902 grams taken off the ground and 480 burned by three bodies standing on it. This valley does not grow enough to keep three people eating forever, and no rule can fix that, because the rule decides what a person does with a tick and not how much grows. The number to hold on to is what happened across those two thousand ticks: three people kept themselves alive, moved 900 grams of tissue about between themselves and the ground, and did not once ask anything outside this process for anything.

Why fast loops and slow loops share values

Take the valley away and what is left is a pattern that turns up wherever a program has a loop with a deadline in it and a job without one. A game's frame. An audio callback. A control loop on a motor. A packet handler. Every one of them is a piece of code that has to finish inside a fixed budget, sitting in the same process as something that cannot promise to finish at all, and the two of them have something to say to each other.

The reflex is to make the join a queue, because a queue is what a join usually is, and then to make the deadline side drain the queue. That works until the day the slow side gets slower than the fast side, and then the queue grows, and everything in it is an answer to a question about a world that no longer exists. The deadline side then spends its budget working through decisions in the order they became stale. A one-slot mailbox is the same join with that failure removed by construction: there is nowhere for a backlog to accumulate, so the deadline side always acts on the newest thing the slow side finished, and the older ones are dropped by the only participant who knows they are old.

The second thing that generalizes is which of the two sides is allowed to fail. Between a fast loop and a slow job, exactly one of them can be made unable to fail, and it has to be the fast one, because the slow one is slow precisely because it is doing something that depends on the outside world. So the deadline side gets a total function with no error return and no dependency, and every uncertainty in the design is pushed across the join. The habit here reads twenty-four numbers and returns; it cannot fail because there is nothing in it that could. That is the property a fallback has to have, and "fallback" is a poor word for it, because the run above says it answers 99.2% of the ticks. It is the normal case, and the far side is the exception.

The third is about what a value costs and what a pointer costs. Sending thirty-two bytes across a channel copies thirty-two bytes. Sending a pointer copies eight, and then hands the receiver a promise that nobody will touch what it points at, which is a promise made in a comment and enforced by nothing. The eight bytes look cheaper and they are, by twenty-four bytes, once per decision, a handful of times a minute. Against that, a value removes a class of bug that does not show up in a test, does not show up in a log, and shows up in production as one wrong action in ten thousand. Anywhere a struct is small and crosses a boundary between two things that run at once, copying it is not the compromise. It is the design, and the size of the struct is a thing to keep small on purpose so it stays available.

And the last one is the sentence this chapter's title is about. A tick that can wait is a tick with no budget. It does not matter what it waits for: a disk, a socket, a lock, a channel with nobody on the other end. The rule this book adopted when it grew a database was that nothing inside a tick opens a transaction, and this page is that rule met a second time with something far slower on the other side of it. The way to keep it is to make waiting unrepresentable at the join, which is what a send that replaces and a receive that gives up amount to. Neither of them has a code path that can block, so no amount of pressure from the far side can produce one.

✓ Checkpoint — one slot, four drives, and the age of a decision
  • Say what happens to the first of two intents posted into one slot before either is taken, and give the reason a queue would be the worse answer here rather than the safer one.
  • A worker posts an intent and then edits the struct it built it from. Say what the tick side sees when the slot carries a value and when it carries a pointer, and which of the two produces an error message.
  • Work out how old, in ticks, a decision is when it is carried out, given that the far side takes R ticks and the receive that finds it runs in the tick after it lands. Then say why Intent.At has to be written when the decision is made and cannot be worked out afterwards.
  • Name the four drives in the order they are asked, and say what changes about a villager if drives 1 and 2 swap places.
  • Explain how a habit whose every field is left at its zero value produces a legal action for every one of the 5,859,375 readings the fan can return.
  • Given one worker, twelve villagers and an answer that takes 30 ticks, work out the share of a villager's ticks that an intent drives, and say which of the two numbers you would change to raise it.
⚡ Exercises — try first, then reveal
Exercise 1 — ask four times as often. The seam run asks for a decision every 40 ticks and the worker answers in 30. Drop the cadence to 10 and predict two things before you run it: how many answers arrive over 600 ticks, and how old each one is when it is carried out.

Nineteen answers instead of fifteen, and every one of them still thirty-one ticks old. Asking four times as often bought four extra decisions and did not make a single one of them arrive sooner:

$ go run ./cmd/slot -mode late -every 10 | tail -20 | head -18
  villager      ticks   from an intent  from the habit
  Halla           600                7             593
  Ander           600                6             594
  Mose            600                6             594
  together       1800               19            1781

  1 request was still on the far side when the run stopped. Its answer
  went into a slot no tick will read again and the villager it was for
  never found out, because a villager that is not told anything keeps
  to its habit. That is the whole of what is lost when this stops.

  every intent in this run was 31 ticks old when it was carried out:
  30 ticks on the far side of the seam and one more to be taken out of
  the slot. A villager acting on it is acting on a world that has moved
  on 31 ticks since anybody looked at it.

  and no tick in this run waited for anybody: 1781 of the 1800 ticks found
  an empty slot, gave up on it at once and ran the habit instead

The reason is that there is one worker, and asking it for something while it is busy is not asking. The cadence stopped being the constraint the moment it went below the answer's own cost: at 40 ticks the worker idles for ten out of every forty, and at 10 it is asked again the instant it is free, so requests go out every 30 ticks and 600 divided by 30 is 20. Nineteen of those came back inside the run and the twentieth was still out when it stopped.

That last one is the interesting line in the block. Its answer was handed into a slot nothing will ever read, and the villager it was for never found out that anybody had been asked. Nothing anywhere is damaged by that, and the reason is the same reason the receive gives up: a villager that is told nothing keeps to its habit. Everything a villager is lives in the roster and in files, and what is in flight is one decision nobody will miss.

Exercise 2 — put hunger above generosity, and then above everything. The giver eats below 25% of a full store and hands over above 40%. Raise the eating threshold to 90%, so it sits above the trading one, and predict what happens to the number of parcels handed over in a two thousand tick run.

Hands go from 832 to 55, and takes go from 79 to none at all:

$ go run ./cmd/slot -mode day -ticks 2000 -feed 0.9 | tail -37 | head -19
  the habit, which is four drives asked in one order
  name         at first      at last   after the run
  Halla        200.0000     169.5403   standing
  Ander         40.0000     157.2588   standing
  Mose         120.0000     145.7315   standing
  3 of 3 standing after 2000 ticks

  what the habit asked for over 6000 creature-ticks, and what the check allowed
  action           asked
  walk               799
  turn left          239
  turn right         366
  bite              4541
  hand                55
  together          6000
  the rule was asked 6000 times and answered 6000 times
  refused   751 times: the cell ahead is open water or off the grid
  a refused action costs the tick and is spent standing there, and the
  rule failing and the world refusing are two different things

Nothing was disabled. Drive 2 is still there, still switched on, still the second thing asked. A villager below 90% of a full store with a plant in sight is answered by drive 1 first, and a villager in this valley is nearly always below 90% of a full store with a plant in sight. Drive 2 now only speaks in the narrow window where somebody is nearly full and standing next to a plant they cannot see, which happened 55 times in six thousand ticks.

Everybody ends the run richer, which is the trap in the result. Three people who never help each other and eat all day do very well for two thousand ticks, and the thing they have stopped doing is the only thing that distinguishes them from the animals in the same roster. A threshold moved by one number turned a village into three browsers, and no test failed.

Exercise 3 — take the third drive out. Drive 3 is the one that tops a store up when there is nothing better to do, and it looks like the most expendable of the four. Set its threshold to nothing so it can never fire, run the day again, and say what you expect the program to print and what you expect it to exit with.

Two of the three starve, and the four-drive rule ends the run with exactly as many people standing as the one-drive errand did:

$ go run ./cmd/slot -mode day -ticks 2000 -fill 0 2>&1 | tail -36 | head -6
  the habit, which is four drives asked in one order
  name         at first      at last   after the run
  Halla        200.0000      -0.0032   starved on tick 2264
  Ander         40.0000      22.4335   standing
  Mose         120.0000      -0.0321   starved on tick 2804
  1 of 3 standing after 2000 ticks

Drive 1 only fires below a quarter of a full store, so with drive 3 gone a villager between a quarter and the trading threshold has nothing to say about a plant standing in front of it and turns on the spot instead. It coasts down to the quarter mark, eats back up above it, coasts down again, and spends the whole run inside the narrowest band its rent allows, until one stretch of turning costs more than the band had in it. The ground is barely touched by comparison: 528.5047 grams eaten against the 901.8115 the full rule ate, on the same twelve plants. Two people starved with food standing all around them.

And the run stops, which is the other half of the exercise. The audit at the bottom asks whether four drives kept more people standing than one drive did, gets 1 against 1, and says so on standard error with a non-zero status:

$ go run ./cmd/slot -mode day -ticks 2000 -fill 0 2>&1 | tail -3
  NO: the habit kept 1 people standing and the errand alone kept 1
slot: 1 thing(s) did not add up
exit status 1

A table of numbers for a person to read is a report. A check has to be able to stop the run it is watching, and the only way to find out whether a particular check can is to give it something to catch. Put the threshold back and the same comparison passes silently, which is what it does on every other run on this page.

So there are three people at Firstlight keeping to a sensible day, a slot each for somebody to tell them otherwise, and a console to walk over and look at them from. What none of them has is any idea that any of it happened. Halla asked to hand a parcel eight hundred and thirty-two times in that last run and could not tell you about one of them; the console's own body was handed grain by a neighbour it will never be able to name. Every tick of that village is computed from the world as it stands and then thrown away. A person who cannot say what happened to them yesterday has nothing for a decision to be made out of, and writing that down is the next thing this village needs.