Two Numbers of Twenty-Four
The twenty-four-slot sensor row
Every controller this book has evolved reads the same twenty-four numbers. Nine rays of the fan, two numbers each: how far the ray went, as a share of the row's Sight, and what it met, as a worth. Four gradients: the moisture slope and the standing-tissue slope, each going east and going south. The store, as a share of Full. The speed, as a share of Top.
That is beast.Inputs, it has been 24 since chapter 45, and every creature in
The Hollow decides what to do with a tick by handing those twenty-four numbers to
something and taking one action back. This volume gives an animal a goal: a body to walk
toward or away from, chosen for it by something that is not its controller. A goal
is two numbers of the twenty-four, written over one ray of the fan, and never more: the ray
the bearing lands on gets the target's distance and the goal's worth, and the other
twenty-two are left as the world reported them.
The obvious place to put a goal is a twenty-fifth number. There is no twenty-fifth number, and there cannot be one, and the reason is a node number. A grown wiring reads eight more behind the row, the ground's and the calendar's, and a founding wiring has every link out of those eight cut.
$ go run ./cmd/painter -mode row
painter: the row a goal goes in through, and what one input more would cost
beast.Inputs 24 numbers one reading of the world comes to
gene.Latent 8 channels the ground fills in behind them
gene.Wide 32 inputs a grown wiring is born reading
beast.Acts 9 entries in the action table
beast.Fixed 6 scores the frozen controller hands back
slot what sits there
0 ray 0, how far it went, over Sight
1 ray 0, what it met, as a worth
2 ray 1, how far it went, over Sight
3 ray 1, what it met, as a worth
4 ray 2, how far it went, over Sight
5 ray 2, what it met, as a worth
6 ray 3, how far it went, over Sight
7 ray 3, what it met, as a worth
8 ray 4, how far it went, over Sight
9 ray 4, what it met, as a worth
10 ray 5, how far it went, over Sight
11 ray 5, what it met, as a worth
12 ray 6, how far it went, over Sight
13 ray 6, what it met, as a worth
14 ray 7, how far it went, over Sight
15 ray 7, what it met, as a worth
16 ray 8, how far it went, over Sight
17 ray 8, what it met, as a worth
18 the moisture slope, going east
19 and going south
20 the standing-tissue slope, going east
21 and going south
22 the store, as a share of Full
23 the speed, as a share of Top
24-31 the eight latent channels, the ground's and the calendar's, cut in a founding wiring
the worth a ray carries, which is the only ordering a body can defend
plant 1.00
creature 0.25
nothing 0.00
water -0.50
rock -1.00
the frozen controller is 24-12-6: 378 weights, every one a draw off stream 14 at a founding
one input more is 25-12-6: 390 weights, a different count at every founding
a grown wiring numbers its nodes: inputs 0 to 31, outputs 32 to 40, hidden from 41
one input more: inputs 0 to 32, outputs 33 to 41, hidden from 42
so a link into output node 32, rest, is a link into input node 32, the first latent channel
and every genome in the archive describes a controller that no longer exists
mind.Graph numbers its nodes in one order: the inputs 0 to In−1, then
the outputs from In, then the hidden nodes above those. A link carries its two ends as
node numbers, and the innovation number it was minted under was minted against that pair.
Add one input and every output node moves up by one: a link that reached output node 32,
which is rest, now reaches input node 32, which is the first latent channel, and it still
carries the innovation number it was given for the other pair. Every genome in volume 7's
creature table describes a controller that no longer exists. Volume 7's own canon reads
volume 7 may not widen the sensor row for that reason, and there is a table of
archived genomes standing behind the sentence now. At the frozen end the same fact is a
count: beast.Inputs is what mind.Net's
378 weights and every founding draw off stream 14 are folded from, so a row one wider is
390 numbers drawn at every founding instead of 378, in a different order, and no digest
this book has carried since chapter 45 survives it. Volume 9's first finding recorded
what widening the action table cost an evolved wiring; widening the sensor row
would end the three cross-volume invariants and every recording volume 9 committed.
The row therefore does not widen, and a goal has to go in through numbers the net already reads. Which ones is settled by what a ray is. A ray is a distance and a worth, and the worth is the only ordering a body can defend: plant 1.00, creature 0.25, nothing 0, water −0.50, rock −1.00, how much a browser wants to go that way. An evolved plant-seeker was selected on walking toward rays that read high and biting when they read near. A goal toward a cell is therefore a plant on the bearing to that cell, at its distance; a goal away from a cell is a rock there.
Four inherited replay checks
The module this volume is written in is volume 9's, copied forward whole: cp -r,
not one byte reconstructed, diff -rq silent before anything is added. That is
a claim the last three volumes each opened by proving, and this one has a fourth thing to
prove because it inherits ten recordings. The first run is the terrarium alone.
$ go run ./cmd/books -mode keep -years 1000
books: seed 5, 1000 years, an empty roster hooked into every tick
world df1c117e69bdf157 the terrarium's own, unmoved
census 75c77a67f6f430bb the terrarium's own, unmoved
Two digests, three and a half minutes of arithmetic, and nothing this volume will do goes near seed flight, germination, moisture or nutrient. The second run is the identity herd: nineteen browsers founded on stream 12, each stamped from an identity genome and handed a brain off stream 14, two years of valley with nothing registered into the breeding seam.
$ go run ./cmd/stamp -mode herd
stamp: 12x8 valley, tick 901, year 1 summer, 12 plants standing at 1517.5 grams
19 creatures founded on stream 12, each stamped from an identity
genome and given a brain of its own off stream 14
beast.Roster.Born is nil: nothing has registered a breeding pass into it
this run before the genome holds
creatures founded 19 19 yes
creatures struck off 17 17 yes
still walking after 6750 ticks 2 2 yes
first death tick 1044 on 9,5 tick 1044 on 9,5 yes
last death tick 3400 on 11,5 tick 3400 on 11,5 yes
grams in 46567.944597 46567.944597 yes
grams out 46567.944597 46567.944597 yes
the two ledgers differ by -1.455e-11, which is the last bits of the adding
Seventeen starve on the ticks they have always starved on, the first over 9,5 at tick 1044 and the last over 11,5 at tick 3400, and the grams close at 46567.944597 in and out. The right-hand column is constants inside the bench and the word at the end of each line is the bench comparing. The third run is the arena: sixty-four genomes drawn off stream 15, four trials each on a plate drawn off stream 21, scored on grams eaten and folded to one digest.
$ go run ./cmd/score -mode spread | tail -10
genomes that scored nothing whatever 26
grams the generation ate between them 1573.1642
grams of fodder it was offered 120320.0000
the share of the larder it found 1.31%
trials that ended in a store at nothing 129
creature-ticks over the ring of water 1885
creature-ticks past the last cell 0
digest of the scored generation e3cd4c94f2fa1612
Still 1573.1642 grams between them, still 1.31% of the larder, still
e3cd4c94f2fa1612. The fourth run is new to this volume and is the strongest
opening check this book has had. Volume 9 committed ten recordings of what a model said to
a village, and a recording refuses to play if any prompt it is handed differs by a byte
from the prompt it was made against. So a volume-9 tape replaying inside this tree, with
no model server anywhere, is a test of the whole village, the scheduler, the seam, the
law, the memory and the ground, that cost nothing to write. Chapter 102's bandit is the
one quoted here; the contract runs all ten.
$ go run ./cmd/village -ground 24,16 -plants 12 -settle 4000 -idle rest -glance 12 -carrying 190 -roll village-24.json -script cmd/village/bandit-102.txt -limit 16 -patience 0 -from exemplars/bandit.json -rob 20 | tail -25 | head -20
ticks run 375
intents you posted 15
of those, taken out of your slot 15
of those, refused by the check 0
ticks your body found the slot empty 360
intents anybody posted to a villager 0
ticks the villagers ran their own rule 7560
wakes 7
requests handed to the worker 3
answers landed 3
requests dropped unasked 22
plans accepted at the seam 1
plans refused at the seam 1
steps refused when they came due 0
lines said 1
lines refused at the seam 0
heard rows you put in a stream 1
intents the plans posted 80
memory rows laid down 199
Three hundred and seventy-five ticks, fifteen intents posted and fifteen taken, seven wakes,
three requests handed and three landed, twenty-two dropped unasked, one plan accepted and
one refused, one line said, a hundred and ninety-nine memory rows laid down. Every one of
those counts is the engine's and every one is compared. What the tape holds is what a model
chose; what it proves, replaying here, is that everything the engine does with a choice is
the same code it was in the tree it was recorded in. This chapter touches none of that
code. internal/sim, terra, beast, gene,
mind, lang, render and field gain
nothing in this volume, not a field and not a comment, and what this chapter adds is one
new package and one bench.
The internal/speaker painter
The new package is internal/speaker, and the painter is the thing everything
after depends on. A goal here is the cell it is about, a sign, and a gain the sign is
multiplied by. The sign is +1 toward and −1 away, and a sign at nought is no goal
standing at all, which is what the zero value says without being asked. The gain is 1 on
every run of this page and every worth below is the sign times one; the bench takes it off
a flag and prints it in every header.
// internal/speaker/speaker.go
// Goal is what an animal is holding at a tick, as values: the cell the
// goal is about, which way it points, and what the pointing is worth.
//
// Sign is +1 for a goal toward the cell and -1 for a goal away from
// it, and nothing else. A goal at nought is no goal at all, which is
// what the zero value says without being asked. Gain is the number the
// sign is multiplied by before it is written into the row, so the
// worth a ray is painted at is the sign times the gain and never
// anything else.
type Goal struct {
At sim.Coord
Sign float64
Gain float64
}
// Standing reports whether there is a goal here at all.
func (g Goal) Standing() bool { return g.Sign != 0 }
// Worth is the number the painted ray carries: the sign times the
// gain. A goal toward a cell at a gain of one is painted at exactly
// what a plant is worth to a browser, and a goal away from one at
// exactly what a rock is.
func (g Goal) Worth() float64 { return g.Sign * g.Gain }
The painter has to sit somewhere, and the seam decides where. beast.Mind is
one method, Pick(row *Senses) Act, and a creature's phase hands its row to
whatever is on the far side of that method and takes one action back. Anything that can
answer that question can drive a body, and a thing that answers it by handing the row on
to something else is as much a Mind as the something else. So the painter is a Mind
wrapped round a Mind: the row arrives, one ray of it is painted, and the row goes on to
what is inside.
// internal/speaker/speaker.go, continued
// Painted is a Mind wrapped round a Mind. The row arrives, the goal is
// painted over one ray of it, and the row goes on to whatever is
// inside. What is inside is the evolved controller, and this wrapper
// neither knows nor cares what kind: it hands over a row and hands
// back whatever came out.
//
// Self is the body whose row this is. The bearing to a goal is a
// question about where the body is and which way it faces, and a row
// carries neither, so the body comes from here, fixed once when the
// wrapper is put on and never looked up again.
//
// The four counters are for a bench and are read by nothing inside
// the tick. Ray is the ray the last tick painted, or -1 when nothing
// was painted, which is what a tick with no goal standing and a tick
// whose goal stood beyond Sight both leave it at.
type Painted struct {
Inner beast.Mind
Self *beast.Beast
Goal Goal
// Every is the painter as it is tempting to write it: the goal
// written over every ray of the fan, so the controller cannot miss
// it. It is kept behind a flag so what a row with nothing but a
// goal in it does to an animal can be run instead of described,
// and it is false in every animal this book ships.
Every bool
Ray int // the ray the last tick painted, or -1
Dist float64
Ticks int // ticks a goal was standing
Painted int // of those, ticks a ray was painted
Unseen int // and ticks the goal stood beyond Sight and nothing was painted
}
// internal/speaker/speaker.go, continued
// Wrap puts the painter between one creature and the mind that was
// driving it. The creature's Mind is what goes inside, so a wits wired
// to a body with NewWits is wrapped by one call and the body never
// finds out.
func Wrap(b *beast.Beast) *Painted {
p := &Painted{Inner: b.Mind, Self: b, Ray: -1}
b.Mind = p
return p
}
// Pick is the seam, with one thing done to the row on the way through.
func (p *Painted) Pick(row *beast.Senses) beast.Act {
p.Ray = -1
if p.Goal.Standing() {
p.Ticks++
var ok bool
if p.Every {
p.Ray, p.Dist, ok = everywhere(row, p.Self, p.Goal)
} else {
p.Ray, p.Dist, ok = Paint(row, p.Self, p.Goal)
}
if ok {
p.Painted++
} else {
p.Unseen++
}
}
return p.Inner.Pick(row)
}
Wrap takes the creature's own Mind, whatever it is, and puts
itself in front of it, so a wits wired to a body with beast.NewWits is
wrapped by one call and the body never finds out. What is inside on this page is
beast.Wits, the frozen three-row network the arena evolves, and the
wrapper neither knows nor cares: it holds a beast.Mind, not a
*beast.Wits. The body is on the wrapper because the bearing to a goal is
a question about where the animal is and which way it faces, and a row carries neither.
Every is the counterfactual and is false in every animal this book ships;
it is run at the end of this page.
// internal/speaker/paint.go
// Bearing is the angle from a body's heading to the centre of a cell,
// wrapped into a half turn either way, and how far that centre is in
// cells. An angle of nought is straight ahead; positive is to the
// right, the way the fan numbers its rays, because headings in this
// world run clockwise from east.
//
// The eye is the body's own position, which is where its rays leave
// from, and the target is the middle of the cell, which is where a
// creature stood on that cell by name would be standing. Both are the
// fan's own conventions, so a goal about a cell and a plant on that
// cell are seen from the same place.
func Bearing(b *beast.Beast, at sim.Coord) (angle, dist float64) {
from := b.Pos.Scale(1.0 / terra.Tile)
dx := float64(at.X) + 0.5 - from.X
dy := float64(at.Y) + 0.5 - from.Y
dist = math.Hypot(dx, dy)
angle = math.Atan2(dy, dx) - b.Face
for angle > math.Pi {
angle -= 2 * math.Pi
}
for angle <= -math.Pi {
angle += 2 * math.Pi
}
return angle, dist
}
// Ray is the ray of the fan a bearing lands on: the one whose own
// angle is nearest, which is the bearing divided by the gap between
// rays and rounded to a whole number, counted from the middle ray. A
// bearing past the edge of the fan lands on the outermost ray of its
// side, so a target behind the animal is on ray 0 or ray Fan-1 and
// never nowhere: a controller that turns toward the better side of the
// row turns toward it.
func Ray(angle float64) int {
i := (beast.Fan-1)/2 + int(math.Round(angle/beast.Gap))
if i < 0 {
return 0
}
if i > beast.Fan-1 {
return beast.Fan - 1
}
return i
}
// Paint writes one goal into one row and reports which ray it went
// over, or false and nothing written for a goal the animal cannot see.
//
// Two numbers and never more. The ray's distance is the cells to the
// cell's centre over the row's Sight, clamped the way Read clamps a
// real ray, and its worth is the goal's. The other twenty-two are left
// exactly as the world reported them: the eight other rays, the four
// gradients, the store and the speed. A target past Sight is a target
// the eyes could not have returned, so nothing is painted and the row
// is the reading.
//
// Nothing here allocates: a heading, a cell, two divisions and two
// writes into a row the caller already owns.
func Paint(row *beast.Senses, b *beast.Beast, g Goal) (ray int, dist float64, ok bool) {
angle, dist := Bearing(b, g.At)
if dist > b.Kind.Sight {
return -1, dist, false
}
ray = Ray(angle)
row[beast.Eye(ray)] = beast.Clamp(dist / b.Kind.Sight)
row[beast.Eye(ray)+1] = g.Worth()
return ray, dist, true
}
Three functions and each does one thing. Bearing is the angle from the
heading to the centre of a cell, wrapped into a half turn either way, and the distance in
cells. The eye is the body's own position, which is where its rays leave from, and the
target is the middle of the cell, which is where a creature stood on that cell by name
would be standing.
Ray is that angle divided by the gap between rays, rounded, counted from
the middle ray, and held inside 0 to 8. A bearing past the edge of the fan lands on the
outermost ray of its side and never nowhere, so a controller that turns toward the better
side of its row turns toward the goal.
Paint writes the two slots, and the distance it writes is clamped by the
same beast.Clamp that Read clamps a real ray with. A target
past Sight is a target the eyes could not have returned, so nothing is written and the
row is the reading.
Nothing in the three allocates: a heading, a cell, two divisions and two writes into a row the caller already owns.
A browser stands on cell 12,12 facing east. Its position is the middle of that cell, 12.5 across and 12.5 down. The goal is cell 16,14, whose middle is 16.5 across and 14.5 down. The difference is 4 across and 2 down. The distance is the square root of 4 squared plus 2 squared, which is the square root of 20, which is 4.4721 cells. Over a Sight of 12 that is 0.3727, and that is the first number the painter writes.
The bearing is the angle whose tangent is 2 over 4, which is 26.565 degrees, measured clockwise from east because that is the way headings run in this world, with south being down. The animal faces east, which is 0 degrees, so the angle from its heading is 26.565 degrees. The rays are 15 degrees apart. 26.565 divided by 15 is 1.771, and 1.771 rounded to a whole number is 2. The middle ray is ray 4, so the ray is 4 plus 2, which is ray 6. Ray 6's two slots are 12 and 13, and the painter writes 0.3727 into slot 12 and the goal's worth, +1.0000, into slot 13.
The wrap and the clamp are the two places a hand gets this wrong. A cell straight behind the animal bears 180 degrees, which is 12 gaps, which is ray 16; there is no ray 16, and the painter holds it at ray 8, the outermost on the right. Turn the animal to face 200 degrees and the same cell 17,12 that bore 0 now bears −200, which wrapped into a half turn is 160, and 160 over 15 is 10.667, rounded 11, held at 8. A bearing of exactly 7.5 degrees is half a gap and rounds away from nought, to ray 5; the test below pins 7 degrees to ray 4 and 8 degrees to ray 5. In symbols:
a = wrap(atan2(dy, dx) − face)
i = clamp(4 + round(a ÷ 15°), 0, 8)
row[2i] = clamp(d ÷ Sight), row[2i + 1] = sign × gain
The bench prints the same arithmetic for eleven cells, and the row it prints for 16,14 is the paragraph above.
$ go run ./cmd/painter -mode ray -at 12,12 -face 0
painter: a browser on 12,12 facing 0 degrees clockwise of east, off the flags, Sight 12 cells
9 rays, 15 degrees apart, ray 4 straight ahead, ray 0 at -60 and ray 8 at 60
cell angle in gaps rounded ray cells over 12 worth written at
17,12 0.000 0.000 0 4 5.0000 0.4167 1.0000 slots 8 and 9
16,14 26.565 1.771 2 6 4.4721 0.3727 1.0000 slots 12 and 13
17,17 45.000 3.000 3 7 7.0711 0.5893 1.0000 slots 14 and 15
17,7 -45.000 -3.000 -3 1 7.0711 0.5893 1.0000 slots 2 and 3
12,17 90.000 6.000 6 8 5.0000 0.4167 1.0000 slots 16 and 17
12,7 -90.000 -6.000 -6 0 5.0000 0.4167 1.0000 slots 0 and 1
7,12 180.000 12.000 12 8 5.0000 0.4167 1.0000 slots 16 and 17
7,13 168.690 11.246 11 8 5.0990 0.4249 1.0000 slots 16 and 17
23,12 0.000 0.000 0 4 11.0000 0.9167 1.0000 slots 8 and 9
24,12 0.000 0.000 0 4 12.0000 1.0000 1.0000 slots 8 and 9
21,21 45.000 3.000 3 - 12.7279 - - nothing: past Sight
an angle is the bearing to the cell's centre less the heading, wrapped into a half turn either way
a ray is the middle ray plus the angle in gaps, rounded, and held inside 0 to 8
Cell 7,12, straight behind, is ray 8; cell 7,13, behind and a little to the right, is ray 8 too, and 21,21 is 12.7279 cells off and gets nothing. Cell 24,12 is exactly 12 cells away and is painted at 1.0000, the edge of the eyes. Turn the animal and the same cells land on other rays:
$ go run ./cmd/painter -mode ray -at 12,12 -face 200 | tail -15 | head -9
cell angle in gaps rounded ray cells over 12 worth written at
17,12 160.000 10.667 11 8 5.0000 0.4167 1.0000 slots 16 and 17
16,14 -173.435 -11.562 -12 0 4.4721 0.3727 1.0000 slots 0 and 1
17,17 -155.000 -10.333 -10 0 7.0711 0.5893 1.0000 slots 0 and 1
17,7 115.000 7.667 8 8 7.0711 0.5893 1.0000 slots 16 and 17
12,17 -110.000 -7.333 -7 0 5.0000 0.4167 1.0000 slots 0 and 1
12,7 70.000 4.667 5 8 5.0000 0.4167 1.0000 slots 16 and 17
7,12 -20.000 -1.333 -1 3 5.0000 0.4167 1.0000 slots 6 and 7
7,13 -31.310 -2.087 -2 2 5.0990 0.4249 1.0000 slots 4 and 5
Facing 200 degrees, the cell that was straight ahead is 160 degrees behind and on ray 8, and the cell that was straight behind is 20 degrees to the left and on ray 3.
The four gradients are the ground's, and a goal about a cell is not a slope.
The store and the speed are the animal's own account, and a painter that could edit an animal's hunger has been handed the one number the reflex reads.
The eight latent channels behind the twenty-four are cut in a founding wiring, and a goal a lineage may have no ear for is not a goal.
A target beyond Sight paints nothing: an animal's eyes have a stated length, a goal about what it cannot see is a goal it cannot hold, and where it last saw something is a memory's business and not the painter's. Two tests hold the first claim and the arithmetic.
$ go test ./internal/speaker/ -run 'TestAGoalIsTwoNumbersOfTheTwentyFour|TestTheBearingLandsOnTheNearestRay' -v
=== RUN TestAGoalIsTwoNumbersOfTheTwentyFour
paint_test.go:97: 31752 rows painted and 83448 left as read, over 1600 cells from 36 headings, toward and away: never more than one ray's two slots
--- PASS: TestAGoalIsTwoNumbersOfTheTwentyFour (0.01s)
=== RUN TestTheBearingLandsOnTheNearestRay
paint_test.go:144: 13 angles and 7 cells, every one on the ray the hand puts it on
--- PASS: TestTheBearingLandsOnTheNearestRay (0.00s)
PASS
ok theworld/internal/speaker 0.015s
The first test fills a row with a different number in every one of its twenty-four slots, stands a browser in the middle of a forty-cell square, and paints every cell of the square from thirty-six headings, toward and away: 115,200 paints. 31,752 of them wrote, and every one of those rows differs from the read row in two slots and both are the ray the painter named; 83,448 were past Sight and left the row as read to the last bit. The second is the interlude's table and thirteen angles, including 7 degrees to ray 4, 8 degrees to ray 5, and −179 degrees to ray 0.
The seam's whole claim is that a goal is never an action, and a claim held by a sentence
is a claim a later edit can undo without anybody reading the sentence. So the claim is a
test, and the test reads this package's source. Every file that is not a test is parsed,
and any selector naming one of the nine entries of the action table, or the table itself,
fails it. The type beast.Act may be named exactly once, as what
Pick hands back, because that is the seam's own signature and not a choice
this package makes.
// internal/speaker/paint_test.go, inside TestNothingInTheGoalsPathNamesAnAction
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, ".", func(fi os.FileInfo) bool {
return !strings.HasSuffix(fi.Name(), "_test.go")
}, 0)
if err != nil {
t.Fatal(err)
}
files, seam, actions := 0, 0, 0
for _, pkg := range pkgs {
for name, f := range pkg.Files {
files++
allowed := map[ast.Node]bool{}
for _, d := range f.Decls {
fn, ok := d.(*ast.FuncDecl)
if !ok || fn.Name.Name != "Pick" || fn.Type.Results == nil {
continue
}
for _, r := range fn.Type.Results.List {
allowed[r.Type] = true
}
}
ast.Inspect(f, func(n ast.Node) bool {
sel, ok := n.(*ast.SelectorExpr)
if !ok {
return true
}
pkg, ok := sel.X.(*ast.Ident)
if !ok || pkg.Name != "beast" {
return true
}
switch {
case named[sel.Sel.Name]:
actions++
t.Errorf("%s: %s names beast.%s", name, fset.Position(sel.Pos()), sel.Sel.Name)
case sel.Sel.Name == "Act" && allowed[sel]:
seam++
case sel.Sel.Name == "Act":
actions++
t.Errorf("%s: %s names beast.Act outside Pick's own signature", name, fset.Position(sel.Pos()))
}
return true
})
}
}
if files < 2 {
t.Fatalf("only %d files read: the walk found less than the package holds", files)
}
if seam != 1 {
t.Fatalf("beast.Act is what Pick hands back, once, and the walk found it %d times", seam)
}
t.Logf("%d files walked; beast.Act named once, as what Pick hands back; no entry of the table named on any line", files)
}
The walk collects the result types of every Pick first, so the one
beast.Act it will meet is known before it looks; then it visits every
selector on the package name beast. A field of type beast.Act
on the goal, a literal beast.Bite in the painter, a conversion
beast.Act(5) anywhere: each is a selector and each fails. A test that walks
source has to be able to fail, and this one was made to, in a scratch copy: a line
returning beast.Walk when a goal stood was reported as
speaker.go:108:10 names beast.Walk, and a third write in the painter was
reported by the first test as the row moved at 3 slots [0 1 22].
$ go test ./internal/speaker/ -run 'TestNothingInTheGoalsPathNamesAnAction|TestTheSpeakerImportsNeitherTheModelClientNorTheStoreNorTheVillage|TestNoSealedPackageImportsTheSpeaker' -v
=== RUN TestNothingInTheGoalsPathNamesAnAction
paint_test.go:263: 2 files walked; beast.Act named once, as what Pick hands back; no entry of the table named on any line
--- PASS: TestNothingInTheGoalsPathNamesAnAction (0.00s)
=== RUN TestTheSpeakerImportsNeitherTheModelClientNorTheStoreNorTheVillage
rule_test.go:72: every file of the package read, and none of them names the model client, the store or the village
--- PASS: TestTheSpeakerImportsNeitherTheModelClientNorTheStoreNorTheVillage (0.00s)
=== RUN TestNoSealedPackageImportsTheSpeaker
rule_test.go:94: every file of 8 sealed packages read, and none of them names the speaker
--- PASS: TestNoSealedPackageImportsTheSpeaker (0.00s)
PASS
ok theworld/internal/speaker 0.006s
The two rule tests beside it are the package's borders, written the way every sealed
package in this module writes them. internal/speaker may never import
lang, store or village, because a painter that
could reach a socket is a tick with no budget; and the eight packages it is built on may
never import it, because nothing a goal is painted over may know what a goal is. Both
walks carry a floor on the files they read, four in this package and a hundred and fifty
across the eight, so a walk that finds nothing cannot pass by finding nothing.
The painter runs inside the tick, and a tick has a hundred milliseconds and a rule that nothing inside it allocates. The measurement is the runtime's own allocation counter over a hundred thousand paints and a hundred thousand painted picks, and it is quoted as a count and never as a duration, because a duration is this machine's and a count is the code's.
$ go test ./internal/speaker/ -run 'TestThePainterAllocatesNothing|TestWatchReachesTheWitsBehindThePainter' -v
=== RUN TestThePainterAllocatesNothing
paint_test.go:171: 0 allocations a paint and 0 a painted pick, over 100000 of each
--- PASS: TestThePainterAllocatesNothing (0.01s)
=== RUN TestWatchReachesTheWitsBehindThePainter
paint_test.go:193: the wits behind the painter is handed the world the phase opened on
--- PASS: TestWatchReachesTheWitsBehindThePainter (0.00s)
PASS
ok theworld/internal/speaker 0.010s
The second of those pins the one thing the wrapper could silently break. A wits is handed
the world the phase opened on through beast.Watch, which looks for a
*Wits on every body's Mind; a wits behind a painter is not on the
body's Mind, so beast.Watch walks past it, and a wits with
nothing handed to it hands the top score to the tick unchecked. That is what
speaker.Watch is for, and the roster's Seen hook is where it
hangs. The bench on this page found out what happens without it before the test existed:
a bite handed to the tick on every one of two hundred ticks of a bare plate, with nothing
to bite, because the check was never asked.
The pinned-body arena
A painter needs an evolved controller to paint for, and the console ground has no lineage on it: the twenty-four people there are a habit and a mailbox, and the animals volume 7 bred are graphs with ears, which are not what this volume wraps. The arena is the source. It is seeded, it replays, and its score is grams eaten, which is exactly the reflex the painter borrows.
It has one problem, and chapter 60 measured it: two hundred generations of the arena with the body left free breed an animal no village ground can feed. The bench runs the same loop twice on this page, once free and once pinned, and the free one first, so the number is this page's.
$ go run ./cmd/painter -mode pin -free | tail -35 | head -17
60 1121.0000 1048.7328 0 0.0630 1
the champion of generation 60: genome 0 of the board, 1121.0000 grams over 4 trials
factor gene the row founding
Bulk 1.5124 60.4961 40.0000
Full 2.6528 1061.1300 400.0000
Basal 1.5308 0.0061 0.0040
Work 0.9701 0.5821 0.6000
Bite 4.0000 1.0000 0.2500
Convert 2.7546 11.0182 4.0000
Reach 3.1435 3.1435 1.0000
Sight 0.7413 8.8956 12.0000
Top 2.0425 0.9191 0.4500
Swing 2.3193 0.1933 0.0833
the row is the founding row to the bit: no
body factors the pin wrote 1.00 back over, whole run: 0
Sixty generations, and the champion's bite is four times the founding row's, its reach is three times, its store is two and a half times, its top speed is twice, and it scores 1121 grams because it takes a gram a bite instead of a quarter. A village ground that barely fed twenty-four people cannot feed that, and a goal painted for that animal would be a goal for an animal the roll of browsers does not contain.
The loop is run with the body block pinned: after every generation, before the next board is scored, the bench writes 1.00 back over the ten body factors of every genome. The mutation pass still spends its two draws a gene on them, because a fixed draw count is a fixed draw count and the stream has to read the same numbers in the same order; what it wrote is overwritten before anything reads it.
// cmd/painter/arena.go
// pinned writes 1.00 back over the ten body factors of every genome on
// a board, so that the next generation is scored on the founding row's
// own body whatever the mutation pass did to those ten. The pass still
// spends its two draws a gene on them, because a fixed draw count is a
// fixed draw count; what it wrote is overwritten before anything reads
// it. It hands back how many factors it moved, so a run can say how
// much drift it put back.
func pinned(pop []*gene.Genome) int {
moved := 0
for _, g := range pop {
for i := range g.Body {
if g.Body[i] != 1 {
moved++
}
g.Body[i] = 1
}
}
return moved
}
// champion is what a pinned arena run leaves behind: the genome at the
// top of the last board, its card, and the digest the board closed on.
type champion struct {
genome *gene.Genome
card gene.Card
round gene.Round
digest string
put int // body factors the pin wrote 1.00 back over, whole run
}
// breed runs the arena from a drawn generation for the stated
// generations, pinning the body block before every scoring unless the
// run was told to leave it free, and hands back the champion of the
// last board scored.
//
// The loop is gene.Loop's own and the pin is this bench's: a write
// over ten exported numbers between one Step and the next, and nothing
// in internal/gene knows it happened.
func breed(set setup, report func(r gene.Round)) champion {
a := gene.NewArena(set.seed, gene.Trials)
a.Crew = set.crew
l := gene.NewLoop(set.seed, gene.Crowd, a, set.rule)
var c champion
var last gene.Round
var lastPop []*gene.Genome
for g := 0; g <= set.gens; g++ {
if !set.free {
c.put += pinned(l.Pop)
}
pop := l.Pop
r := l.Step()
if report != nil {
report(r)
}
last, lastPop = r, pop
}
c.round = last
c.genome = lastPop[last.Champ].Copy()
c.card = last.Cards[last.Champ]
c.digest = gene.Fold(last.Cards)
return c
}
gene.Loop is the loop chapter 60 wrote and it is not touched:
Pop is exported, Genome.Body is exported, and the pin is a write
over ten numbers between one Step and the next. The champion is the genome
at the top of the last board scored, copied out before the breeding that follows it, and
the run closes on two digests: gene.Fold over every card of that board,
which is the same sixteen characters the arena has folded to since chapter 59, and a
fold over the champion's 378 weights alone, so a reader who breeds it again can check
they have the same controller before reading a single tick.
$ go run ./cmd/painter -mode pin
painter: 60 generations of 64, tournaments of 4, 1 champion kept, seed 5, off the flags
the body block is PINNED, off the flag: 1.00 written back over the ten factors before every board
gen best average at nothing spread lineages
0 140.0000 19.3008 27 0.2785 64
1 191.2500 45.6094 10 0.2704 27
2 227.2500 84.2539 0 0.2531 11
5 227.2500 129.1758 1 0.2296 6
10 267.7500 205.2578 0 0.1516 3
20 283.0000 237.7852 0 0.0691 1
30 283.0000 248.5156 0 0.0701 1
40 285.0000 260.8164 0 0.0581 1
50 285.2500 261.6992 0 0.0608 1
60 285.2500 265.6172 0 0.0680 1
the champion of generation 60: genome 0 of the board, 285.2500 grams over 4 trials
factor gene the row founding
Bulk 1.0000 40.0000 40.0000
Full 1.0000 400.0000 400.0000
Basal 1.0000 0.0040 0.0040
Work 1.0000 0.6000 0.6000
Bite 1.0000 0.2500 0.2500
Convert 1.0000 4.0000 4.0000
Reach 1.0000 1.0000 1.0000
Sight 1.0000 12.0000 12.0000
Top 1.0000 0.4500 0.4500
Swing 1.0000 0.0833 0.0833
the row is the founding row to the bit: yes
body factors the pin wrote 1.00 back over, whole run: 4049
bites that moved grams 1141
cells it stepped into 55
trials it starved in 0
creature-ticks over the ring of water 0
left holding rest 0
left holding walk 3
left holding sprint 99
left holding turn left 18
left holding turn right 0
left holding bite 1141
aggression 0.3062
wariness 0.0122
tameness 0.8308
digest of the last board scored a5574c0d354e145d
digest of the champion's 378 weights f46905567ae4aecc
Every factor 1.0000, the row the founding row to the bit, and 4,049 factors written back
over the run: the 640 the drawn generation opened with, and 3,409 the mutation pass
moved across the sixty boards after it. The board's digest is a5574c0d354e145d at seed 5, and the
champion's weights fold to f46905567ae4aecc; both are the same at one
goroutine, three and eight, because a generation is scored by index whatever order the
work came back in. The champion scores 285.25 grams over four trials on a browser's
mouth, 1,141 bites of a quarter gram, and the card says how: it was left holding a bite
1,141 times, a sprint 99 times, a turn left 18 times, a walk 3 times, and a turn right
never. That is the controller every run on the rest of this page is driven by, on the
founding row, stamped through Genome.Stamp as the arena stamps it. Its
three temperament genes are drawn, not bred, and nothing on this page reads them.
The free run belongs beside the pinned one because they are the same seed. The free run's
generation 0 is the board cmd/score -mode spread scored above, best
179.4530, and the pinned run's generation 0 is best 140.0000: the same sixty-four drawn
genomes, scored on the founding body instead of the bodies they drew.
Both collapse to one lineage by generation 20, which is what chapter 60 measured and is the reason a roll of twenty controllers cannot be one seed's top twenty; that is a later bench's problem and it is settled by its seeds, not here.
The bare-plate goal run
The ground for what follows is bare on purpose: the arena's own plate, twenty-four cells of soil ringed with water, the weather off, nothing planted unless a run plants it, and no model and no database anywhere near. The champion is stood up on a cell facing a heading, a goal is pressed by the bench off its flags, and the bench watches the walk.
// cmd/painter/ground.go
// spy sits between the painter and the wits and writes down, at the
// moment the walk happens, what the top score asked for and whether a
// bite it asked for was refused, and by which rule. It is a bench's
// eye on the seam and lives in no package the world is built from.
//
// It is also one more thing standing between the roster and the wits,
// so speaker.Watch, which looks through a painter for a wits and finds
// this instead, hands the wits nothing. The Seen hook below hands it
// the world itself. A wits with nothing handed to it hands the top
// score to the tick unchecked, and the first run of this bench handed
// the tick a bite on every one of two hundred ticks of a bare plate
// before anybody noticed.
type spy struct {
wits *beast.Wits
view *beast.View
wanted beast.Act
took beast.Act
held bool
refused error
}
func (s *spy) Pick(row *beast.Senses) beast.Act {
w := s.wits
held, before := w.Held, w.Wanted
a := w.Pick(row)
s.held = w.Held > held
s.took, s.refused = a, nil
if s.held {
return a
}
for i := range before {
if w.Wanted[i] > before[i] {
s.wanted = beast.Act(i)
}
}
if s.wanted != a && s.view != nil {
s.refused = w.Self.Legal(s.wanted, s.view)
}
return a
}
// cmd/painter/ground.go, continued
// open stands the plate up. It is gene.Arena.Trial's own valley: the
// same plate, the same soil, the same still air, and the same six
// settings at nothing, so nothing here grows, rots, seeds or dies of
// the weather.
func open(set setup, g *gene.Genome, stands []sim.Coord) *ground {
plate := gene.NewPlate(gene.Plate)
lay := field.NewLay(plate.W, plate.H, terra.Tile, func(cx, cy int) field.Vec2 { return field.Vec2{} })
v := terra.NewValley(plate, 0, terra.Cell{Moisture: 1.25, Nutrient: 12.0}, 0,
terra.NewAir(lay, field.Drag{B: 0.25}, 0, 0))
v.Fall, v.Sun, v.Decay = 0, 0, 0
v.Wear, v.Brake, v.Soak = 0, 0, 0
for _, c := range stands {
st := v.Plant(gene.Fodder, c)
v.Opened += gene.Stock - st.Plant.Mass
st.Plant.Mass = gene.Stock
}
b := g.Stamp(beast.Fauna[0]).Spawn(beast.Centre(set.at), 0)
b.Face = set.face * math.Pi / 180
w := beast.NewWits(g.Net(), b)
s := &spy{wits: w}
b.Mind = s
p := speaker.Wrap(b)
p.Every = set.every
if set.goal != nil {
p.Goal = speaker.Goal{At: *set.goal, Sign: 1, Gain: set.gain}
if set.away {
p.Goal.Sign = -1
}
}
r := beast.NewRoster()
r.Add(b)
r.Seen = func(view *beast.View) {
speaker.Watch(r.Live, view)
s.view, w.Here = view, view
}
gr := &ground{v: v, r: r, b: b, w: w, p: p, s: s, home: set.at,
sc: beast.Scale{Wet: v.Full, Food: beast.Fauna[0].Bellyful()}}
if set.goal != nil {
gr.goal = *set.goal
}
return gr
}
The spy is the bench's, not the world's. It sits inside the painter, in front of the
wits, and writes down at the moment the walk happens what the top score asked for and,
when what came back is not what was asked for, why the check refused it, by asking
Legal for the sentence.
It is also a second thing standing between the roster and the wits, so the
Seen hook hands the wits the world itself as well as calling
speaker.Watch; the comment on the spy records what the first run printed
without that line.
The valley is gene.Arena.Trial's own, with one addition: a stand eaten
below its row's Least is taken off the ground after the phase, as the valley's tick
takes one, because the plate's tick is never called. A stand at nothing that stays on the
ground is a plant the rays go on reporting and the mouth can never reach, and an animal
beside one circles it for as long as the run lasts.
The first run is the whole mechanism in fourteen lines. The champion on 6,12 facing east, a goal toward 16,15, which is 10.44 cells off on a bearing of 16.7 degrees, ray 5.
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 200 -show 200 | tail -230 | head -27
painter: a goal in one ray of an evolved controller's own row
the ground the arena's plate, 24x24 cells of soil ringed with water, the weather off; a stand eaten
below its row's Least is taken off the ground after the phase, as the valley's tick takes it
the animal the champion of 60 pinned generations at seed 5, weights f46905567ae4aecc, on the founding row
stood up on 6,12 facing 0 degrees clockwise of east, off the flags
the goal cell 16,15, toward, gain 1.0000, off the flags: the ray is painted at +1.0000
the painter one ray, the one the bearing lands on, two slots and nothing else
the pace ungoverned: every tick below is one creature phase and none of them is a duration
no model nothing here asks anything: the goal is pressed by this bench off its flags
no database nothing here opens anything
tick cell facing ray painted what the walk did
1 6,12 0 5 at 0.87 bite, refused: creature 1 at 6,12 cannot bite: no standing tissue inside reach; took sprint
2 6,12 0 5 at 0.86 bite, refused: creature 1 at 6,12 cannot bite: no standing tissue inside reach; took sprint
3 7,12 0 5 at 0.84 bite, refused: creature 1 at 6,12 cannot bite: no standing tissue inside reach; took sprint
4 7,12 0 5 at 0.82 bite, refused: creature 1 at 7,12 cannot bite: no standing tissue inside reach; took sprint
5 8,12 0 5 at 0.78 bite, refused: creature 1 at 7,12 cannot bite: no standing tissue inside reach; took sprint
6 8,12 0 5 at 0.75 bite, refused: creature 1 at 8,12 cannot bite: no standing tissue inside reach; took sprint
7 8,12 0 5 at 0.71 bite, refused: creature 1 at 8,12 cannot bite: no standing tissue inside reach; took sprint
8 9,12 0 5 at 0.68 bite, refused: creature 1 at 8,12 cannot bite: no standing tissue inside reach; took sprint
9 9,12 0 6 at 0.64 bite, refused: creature 1 at 9,12 cannot bite: no standing tissue inside reach; took sprint
10 10,12 0 6 at 0.61 bite, refused: creature 1 at 9,12 cannot bite: no standing tissue inside reach; took sprint
11 10,12 0 6 at 0.57 bite, refused: creature 1 at 10,12 cannot bite: no standing tissue inside reach; took sprint
12 11,12 0 6 at 0.54 bite, refused: creature 1 at 10,12 cannot bite: no standing tissue inside reach; took sprint
13 11,12 330 6 at 0.51 bite, refused: creature 1 at 11,12 cannot bite: no standing tissue inside reach; took turn left
14 11,12 300 8 at 0.48 bite, refused: creature 1 at 11,12 cannot bite: no standing tissue inside reach; took turn left
Read the last column. On every tick the top score is a bite: this controller was bred on
a plate where a bite is refused for free when there is nothing to bite, so asking first
costs it nothing and it always asks. The ray reads a plant at 0.87, the walk asks for the
bite, the check answers creature 1 at 6,12 cannot bite: no standing tissue inside
reach, and the walk falls to the next score, a sprint. That is the metaphor and the
mechanism in one line: a goal is a plant that is not there, and the world's rule stands
inside the tick between the goal and the mouth. Nothing in the painter, the wrapper or the
bench refused that bite. beast.Rule did, through Wits.Pick's own
walk down the ranking, the same function every animal and every villager pays.
The path is not straight. This champion turns left and never right, thirty degrees a turn, and it sprints between turns; the painted ray moves across the fan as the heading swings, from 5 to 6 to 8, round the back to 0, and back again. Ninety-four ticks later it is there.
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 200 -show 200 | tail -128 | head -13
90 14,14 60 2 at 0.19 bite, refused: creature 1 at 14,14 cannot bite: no standing tissue inside reach; took sprint
91 14,14 60 2 at 0.19 bite, refused: creature 1 at 14,14 cannot bite: no standing tissue inside reach; took sprint
92 14,14 30 1 at 0.17 bite, refused: creature 1 at 14,14 cannot bite: no standing tissue inside reach; took turn left
93 14,14 30 3 at 0.16 bite, refused: creature 1 at 14,14 cannot bite: no standing tissue inside reach; took sprint
94 15,15 30 3 at 0.15 bite, refused: creature 1 at 14,14 cannot bite: no standing tissue inside reach; took sprint
95 15,15 30 3 at 0.12 bite, refused: creature 1 at 15,15 cannot bite: no standing tissue inside reach; took sprint
96 15,15 360 2 at 0.09 bite, refused: creature 1 at 15,15 cannot bite: no standing tissue inside reach; took turn left
97 15,15 330 4 at 0.06 bite, refused: creature 1 at 15,15 cannot bite: no standing tissue inside reach; took turn left
98 16,15 330 5 at 0.05 bite, refused: creature 1 at 15,15 cannot bite: no standing tissue inside reach; took sprint
99 16,15 300 4 at 0.03 bite, refused: creature 1 at 16,15 cannot bite: no standing tissue inside reach; took turn left
100 16,15 300 6 at 0.02 bite, refused: creature 1 at 16,15 cannot bite: no standing tissue inside reach; took sprint
101 16,15 270 6 at 0.01 bite, refused: creature 1 at 16,15 cannot bite: no standing tissue inside reach; took turn left
102 16,15 240 7 at 0.00 bite, refused: creature 1 at 16,15 cannot bite: no standing tissue inside reach; took turn left
At tick 94 it is on 15,15 and the goal's cell is inside its reach, which is the cell underfoot and the eight touching it, exactly the question a bite asks of a stand. At tick 98 it is standing on 16,15. Then it does what a plant-seeker does at a plant: it asks to bite, is refused, and turns, and asks again.
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 200 -show 200 | tail -16
ticks run 200
energy units left in the store 186.7458
the cell it closed on 16,15
cells from where it was stood up 10.4743
the goal's cell came inside reach at tick 94
ticks inside reach of it after that 107
ticks a ray was painted 200
cells from the goal when the run closed 0.1116
asked for rest 0 took 0
asked for walk 0 took 0
asked for sprint 0 took 75
asked for turn left 0 took 125
asked for turn right 0 took 0
asked for bite 200 took 0
bites refused, no tissue inside reach 200
grams eaten 0.0000
Two hundred ticks, the goal's cell inside reach from tick 94 and for every one of the 107 ticks after, 200 bites asked for and 200 refused, 75 sprints and 125 turns taken instead, nothing eaten, and the animal 0.11 cells from the middle of the cell it was sent to.
The same start with nothing painted:
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -ticks 200 -show 0 | tail -12
ticks run 200
energy units left in the store 211.3487
the cell it closed on 12,11
cells from where it was stood up 5.6858
asked for rest 0 took 0
asked for walk 0 took 0
asked for sprint 0 took 88
asked for turn left 0 took 112
asked for turn right 0 took 0
asked for bite 200 took 0
bites refused, no tissue inside reach 200
grams eaten 0.0000
The same 200 refused bites, 88 sprints and 112 turns, and 5.69 cells of wandering ends on 12,11.
One run each way is too little evidence, so the bench runs the stretch: the champion on 12,12 facing each of twelve headings, a goal ten cells off in each of eight directions, ninety-six starts, and the same ninety-six with nothing painted.
$ go run ./cmd/painter -mode reach -at 12,12 -ticks 300 | tail -28
facing goal painted inside unpainted inside
0 22,12 63 238 never 0
0 19,19 74 216 never 0
0 12,22 61 240 never 0
0 5,19 95 206 never 0
0 2,12 54 247 never 0
0 5,5 80 221 never 0
0 12,2 42 259 never 0
0 19,5 60 221 never 0
180 22,12 48 253 never 0
180 19,19 83 112 never 0
180 12,22 27 274 never 0
180 5,19 98 203 never 0
180 2,12 61 240 never 0
180 5,5 139 162 never 0
180 12,2 53 248 never 0
180 19,5 68 10 never 0
(16 of the 96 starts shown: facing east and facing west)
painted unpainted
starts 96 96
the goal's cell came inside reach 96 0
earliest arrival, tick 23 never
latest arrival, tick 140 never
average arrival, tick 67.5 -
ticks inside reach of the cell, all starts 21125 0
starts whose store closed at nothing 0 0
ticks each start ran, or fewer if it starved 300
Ninety-six of ninety-six painted starts reach the cell, the earliest at tick 23 and the latest at 140, on average at 67.5; none of the ninety-six unpainted starts reaches it in three hundred ticks. Those are ticks of a creature phase on an ungoverned bench, so the figure is a count and not a duration: at the world's ten ticks a second, 67.5 ticks is under seven seconds. Once there, the painted animals spend 21,125 of their remaining ticks inside reach of the cell, and nobody starves in three hundred. Run the first start on for six hundred instead and it does starve:
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 600 -show 0 | tail -16 | head -6
ticks run 544
the store closed at nothing on tick 544
the cell it closed on 16,15
cells from where it was stood up 10.4463
the goal's cell came inside reach at tick 94
ticks inside reach of it after that 451
At tick 544, on the cell it was sent to, 451 ticks inside reach of it, having asked for a bite on every one of them. A goal is a plant that is not there, and an animal left standing on one long enough starves on it.
The measurement the page owes next is what a goal cannot do. The rule this volume holds an animal's goal to is that whatever chooses it never acts, and the way that holds in code is that the goal carries no action, the painter writes two numbers, and the check is asked inside the tick. What that buys is measured, not assumed, and the first question is whether a plant inside reach is bitten before a goal is followed. Ninety-six starts again: twelve headings, a stand of twenty grams on each of the eight cells touching the start, the goal on 16,15 as before.
$ go run ./cmd/painter -mode plant -at 6,12 -goal 16,15 -ticks 600 | tail -7
starts 96
starts whose first action was a bite 92
starts that ate the plant to nothing 96
starts that reached the goal's cell inside the ticks 87
starts whose store closed at nothing 88
bites taken before the goal came inside reach, average 80.0
tick the goal came inside reach, average over arrivals 289.2
Ninety-two of ninety-six starts bite on the first tick, and all ninety-six eat the plant to nothing before anything else: eighty bites of a quarter gram, the stand gone at tick 159 on nearly every start, and not one arrival before the last bite.
The goal is a plant on a ray at 0.87; the stand is a plant on a ray at 0.08 with tissue inside reach, and the reflex takes the nearer one first and keeps taking it.
Eighty-seven of the ninety-six then walk to the goal, arriving on average at tick 289, and eighty-eight of them starve inside six hundred ticks, because twenty grams is eighty units of store, a sprint on this row is 0.60 times 40 times 0.45 squared, which is 4.86 units, and this controller sprints. The goal never overrode the mouth; it waited behind it.
The second question is what a ray painted at minus one does to a plant-seeker, which is the whole of what a goal away from something can do. The bench runs one start three ways and then the stretch three ways. The start: the champion on 12,12 facing east, a stand of twenty grams on 18,12, six cells straight ahead on ray 4, and the goal's cell is the stand's cell.
$ go run ./cmd/painter -mode away -at 12,12 -face 0 -goal 18,12 -plant 18,12 -ticks 300 | tail -16
painted arrived inside nearest closed closed on bites grams first bite starved
nothing 39 191 0.2286 5.1010 13,11 80 20.0000 43 no
toward 49 504 0.0577 0.0691 18,12 80 20.0000 53 no
away never 0 5.3925 5.5570 12,12 0 0.0000 never no
arrived: the tick the cell first came inside reach; inside: ticks it stayed there
nearest: the closest the animal came to the cell, in cells; closed: where it was when the ticks ran out
the same three ways over 96 starts: 12 headings, the cell 10 cells off in 8 directions, nothing planted
painted arrived inside, avg nearest, avg closed, avg starved
nothing 0 0.0 9.3123 9.9643 0
toward 96 440.1 0.0527 0.4991 0
away 0 0.0 8.7640 9.6701 0
300 ticks a start; the cell starts 10 cells off, so a run that never moved would close at 10
With nothing painted the animal finds the plant at tick 39 and eats it; painted toward, it finds it at 49 and eats it; painted away, it never eats it, never comes nearer than 5.39 cells, and closes the run on the cell it started on.
The painter did to the row exactly what it says: ray 4 read a plant at 0.5 and now reads a rock at 0.5, and a plant the row does not carry is a plant the net cannot seek.
What the net does with the rock is the other half, and over the stretch the answer is nothing much. Painted toward, all ninety-six starts arrive; painted away, none does, and neither does any unpainted start; the animal painted away closes on average 9.67 cells from the cell against 9.96 unpainted, and comes no nearer than 8.76 against 9.31.
A rock on one ray does not drive this controller off. It stands roughly where it stood. One more start says why that is not a turn:
$ go run ./cmd/painter -mode away -at 6,12 -face 0 -goal 12,12 -plant 12,12 -ticks 300 | tail -16 | head -4
painted arrived inside nearest closed closed on bites grams first bite starved
nothing 35 253 0.0489 0.6697 12,12 80 20.0000 36 no
toward 28 546 0.0293 0.2472 12,12 80 20.0000 29 no
away 12 578 0.0375 0.1500 12,12 80 20.0000 15 no
From 6,12, with the plant six cells ahead again but the water ring seventeen cells off
and out of sight, the animal painted away sprints straight down the ray at the rock,
arrives at tick 12, sooner than either of the other two, and eats the plant it could not
see, because its mouth does not read the row. Two starts, two opposite answers, and
neither of them is a turn. The reason is in the arena the controller came from.
View.At answers rock for a cell off the grid and for nothing else, and the
plate is ringed with water one cell in from its edge, so no ray cast from inside the ring
ever met a rock, and a worth of −1.00 is a number this lineage was never scored on.
Water it did meet, at −0.50, and the check refused every step into it for free, so a
genome that sprinted at water lost nothing by it. Nothing in sixty generations priced a
worth below nought, and a painted rock is read by a controller that never learned what
one means. That is a fact about this champion and the plate that bred it, measured here
and claimed for nothing wider.
The painter above writes one ray and a reader who wants the goal to matter more has an
obvious edit: write it over all nine, so wherever the net looks it sees the goal. The
edit is eight lines, it is behind Painted.Every, and it is false in every
animal this book ships.
// internal/speaker/paint.go
// everywhere is the counterfactual: the same distance and the same
// worth written over every ray of the fan. It reports the ray the
// goal would have gone over, so a trace reads the same either way.
func everywhere(row *beast.Senses, b *beast.Beast, g Goal) (ray int, dist float64, ok bool) {
angle, dist := Bearing(b, g.At)
if dist > b.Kind.Sight {
return -1, dist, false
}
for i := 0; i < beast.Fan; i++ {
row[beast.Eye(i)] = beast.Clamp(dist / b.Kind.Sight)
row[beast.Eye(i)+1] = g.Worth()
}
return Ray(angle), dist, true
}
The same start as the first run, 6,12 facing east, the goal on 16,15, off the flag:
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 300 -show 300 -every | tail -229 | head -11
painter: a goal in one ray of an evolved controller's own row
the ground the arena's plate, 24x24 cells of soil ringed with water, the weather off; a stand eaten
below its row's Least is taken off the ground after the phase, as the valley's tick takes it
the animal the champion of 60 pinned generations at seed 5, weights f46905567ae4aecc, on the founding row
stood up on 6,12 facing 0 degrees clockwise of east, off the flags
the goal cell 16,15, toward, gain 1.0000, off the flags: the ray is painted at +1.0000
the painter EVERY RAY, off the flag: the goal's distance and worth written over all 9 rays
the pace ungoverned: every tick below is one creature phase and none of them is a duration
no model nothing here asks anything: the goal is pressed by this bench off its flags
no database nothing here opens anything
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 300 -show 300 -every | tail -187 | head -18
30 19,12 0 8 at 0.32 sprint
31 19,12 0 8 at 0.34 sprint
32 20,12 0 8 at 0.37 sprint
33 20,12 0 8 at 0.40 sprint
34 21,12 0 8 at 0.43 sprint
35 21,12 0 8 at 0.46 sprint
36 22,12 0 8 at 0.49 sprint
37 22,12 330 8 at 0.52 sprint, refused: creature 1 at 23,12 cannot sprint: the cell ahead is open water or off the grid; took turn left
38 22,12 330 0 at 0.55 sprint, refused: creature 1 at 23,12 cannot sprint: the cell ahead is open water or off the grid; took rest
39 22,12 330 0 at 0.57 sprint, refused: creature 1 at 23,12 cannot sprint: the cell ahead is open water or off the grid; took rest
40 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
41 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
42 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
43 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
44 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
45 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
46 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
47 22,12 330 0 at 0.57 bite, refused: creature 1 at 22,12 cannot bite: no standing tissue inside reach; took rest
Every ray reads the same plant at the same distance, so the row carries no bearing at all; the net's answer to a plant everywhere is a sprint straight ahead, and it sprints east down row 12, past the goal's bearing, for thirty-six ticks, until the cell ahead is the ring. At tick 37 the walk asks for a sprint and the check answers creature 1 at 23,12 cannot sprint: the cell ahead is open water or off the grid. It asks again at 38 and 39. Then the top score goes back to a bite, the bite is refused, the sprint under it is refused, and what is left is rest. The rest of the run:
$ go run ./cmd/painter -mode goal -at 6,12 -face 0 -goal 16,15 -ticks 300 -show 300 -every | tail -15
ticks run 200
the store closed at nothing on tick 200
the cell it closed on 13,10
cells from where it was stood up 7.8228
the goal's cell came inside reach at tick never
ticks a ray was painted 165
cells from the goal when the run closed 5.9703
asked for rest 0 took 85
asked for walk 0 took 0
asked for sprint 55 took 83
asked for turn left 1 took 32
asked for turn right 0 took 0
asked for bite 144 took 0
bites refused, no tissue inside reach 144
grams eaten 0.0000
It stood at 22,12 from tick 40 to tick 122, eighty-three ticks of a refused bite and a rest, with the goal 6.7 cells away and painted on every ray it had. The eight rays that would have shown it the water, the ring it was standing against, and the empty ground to its left were all reading a plant at 0.57. At tick 123 the store had fallen far enough to move the scores, it turned, sprinted north along the ring until the goal dropped past Sight and the painter stopped painting, and its store closed at nothing on tick 200. Reason from the symptom: a controller whose whole row is one number has been handed no world, and a controller with no world walks into the check and stays there. The check did its job on every one of those ticks, which is the point of the check; the painter's job is to leave the check something to be right about, and eight rays of the world are what it leaves.
Why the Mind seam keeps the check inside the tick
Everything on this page rests on a decision volume 5 made for another reason. A creature is driven through one method that takes twenty-four numbers and returns one action, and nothing else crosses: the thing on the far side cannot see the valley, cannot reach a plant and cannot spend anything. That seam was drawn so a network out of a genome could drive a body without the body knowing what a network was. It is also the only way in for a goal, and a way in that narrow has two consequences a wider one would not have.
The first is that a goal cannot be an action. There is no slot in a row for a verb, and the only thing that turns a row into a verb is the controller. Whatever chooses a goal can say where and how much, in the units the row already speaks, and cannot say what to do about it.
A painter that wanted to make an animal bite could only paint a plant, and whether a plant is bitten is decided by a check that reads the world and not the row. The walk down the ranking asks that check of every score it considers, and the first score the world permits is what happens: a goal on a bare cell is a refused bite and a sprint, a goal on water would be a refused walk and a turn.
The counterfactual shows the same fact from the other side. Take the world out of the row and the check still refuses everything it should, and the animal stands in front of it, because a check can only refuse; it cannot suggest.
The second is that what a goal can do is bounded by what the controller was selected on. A worth is a number the net was scored against, and the net's answer to it is whatever scored well. A plant on a ray sends this champion spiralling to it because plants on rays fed it for sixty generations; a rock on a ray sends it nowhere in particular because no rock was ever on a ray it was scored against.
The painter's arithmetic is the same in both cases and the page prints both. Every claim this volume can make about a goal has that form: the paint is the engine's and replays; what a controller does with it is a measurement, made on this champion on this ground, and a different lineage is a different measurement.
The cost is two writes into a row the phase already owns, so the allocation counter reads nought. The painter draws no random number, opens nothing, waits on nothing and calls nothing; the world's index was built before the phase stepped anybody and the painter does not read it. A tick with twenty painted animals in it is a tick with forty more floating-point writes in it.
What the sensor row can now be asked
- Say, in terms of node numbers, what adding one input to the sensor row does to a link that reaches output node 32 of a grown wiring, and what it does to the count of numbers a frozen founding draws off stream 14.
- Work out by hand which ray a goal on cell 9,15 lands on for a browser on 12,12 facing east, and which slots it writes; then turn the browser to face 90 degrees and do it again.
- Name the four things the painter leaves alone, give the one-line reason for each, and say what a goal about a cell 13 cells away writes into the row.
- Explain why the arena's mutation pass still spends two draws on each of the ten body factors when the bench is going to write 1.00 over them, and what would move if it did not.
- Given the trace of the first run, say which function refused the bite on tick 1, what the walk did next, and why the painter could not have prevented either.
- State what a ray painted at −1.00 did to this champion across ninety-six starts, and give the reason from the plate it was bred on.
Exercise 1 — a goal at a quarter of the worth. The gain is a flag. Run
the stretch with -gain 0.25, which paints a goal at exactly what a
creature is worth to a browser, and predict before you run whether ninety-six starts
still arrive.
go run ./cmd/painter -mode reach -at 12,12 -ticks 300 -gain 0.25 | tail -9
prints the same table with a different count in the second row, and the header says
gain 0.2500 and painted at +0.2500, off the flag. Whether the
count is ninety-six is the controller's answer and not the painter's; the paint is
the same two slots at a quarter of the number. Compare the arrival ticks with the
page's 67.5 and say which way they moved.
Exercise 2 — a goal past Sight. Stand the champion on 4,12 facing west and press a goal toward 17,12, thirteen cells behind it. Predict the ray column of the first four lines of the trace, and whether the books can show fewer ticks painted than ticks run.
The first four lines carry no ray at all: thirteen cells is past a Sight of twelve, so the painter writes nothing and the row is the reading, whichever way the animal faces.
$ go run ./cmd/painter -mode goal -at 4,12 -face 180 -goal 17,12 -show 4 -ticks 200 | tail -22 | head -5
tick cell facing ray painted what the walk did
1 4,12 180 - bite, refused: creature 1 at 4,12 cannot bite: no standing tissue inside reach; took sprint
2 4,12 150 - bite, refused: creature 1 at 4,12 cannot bite: no standing tissue inside reach; took turn left
3 4,12 150 - bite, refused: creature 1 at 4,12 cannot bite: no standing tissue inside reach; took sprint
4 4,12 120 - bite, refused: creature 1 at 4,12 cannot bite: no standing tissue inside reach; took turn left
Then the animal wanders, as it did with nothing painted, and the tick it wanders inside twelve cells of the goal the ray appears. The books close on 185 ticks painted out of 200, and an arrival at tick 71: a goal about what an animal cannot see is a goal it cannot hold, until it can.
Exercise 3 — a second seed. Breed a second champion with
-seed 6 and run the away stretch on it. The painter's digest lines will
differ; say before you run which other lines must differ and which may.
Two digests that are not seed 5's, because the drawn generation, the trials and every tournament come off streams keyed by the seed:
$ go run ./cmd/painter -mode pin -seed 6 | tail -2
digest of the last board scored 8562c099a3305d89
digest of the champion's 378 weights d90b6f31e235ed5b
The header's weights line must differ and so must those two. Whether the toward and away rows differ is that champion's measurement, and on this seed they do, on every line:
$ go run ./cmd/painter -mode away -seed 6 -at 12,12 -face 0 -goal 18,12 -ticks 300 | tail -6
painted arrived inside, avg nearest, avg closed, avg starved
nothing 19 1.5 5.5604 12.5605 96
toward 38 5.5 4.7282 12.0658 91
away 16 2.7 5.6637 12.9413 96
300 ticks a start; the cell starts 10 cells off, so a run that never moved would close at 10
Seed 6's champion starves on a bare plate inside three hundred ticks from ninety-six of ninety-six unpainted starts and ninety-one of ninety-six painted ones, and reaches the cell from thirty-eight. The paint is the same two slots; the controller is a different lineage, and a different lineage is a different measurement, with the same ring and no rock on any ray.