A sheepdog cannot push a sheep. It has never touched one. What it has is a distance: come inside the sheep’s flight zone and the sheep moves off, stay outside it and you are a feature of the landscape. Everything else in the sport — the wide outrun, the balance point, the whistle that means get out, widen, move off them — is consequence.
So this is a mechanic about one quantity, standing distance, and the interesting thing about that quantity is that it does not behave like a dial.
What is actually being simulated
src/get-out.mjs is twenty sheep, one dog and a pen, with no renderer in it.
Each sheep carries a position, a velocity and a single scalar called fright,
and four things act on it:
- the dog, but only inside the flight zone
r_a= 17 m, repelling radially with an acceleration that falls linearly to nothing at the edge; - its neighbours, shoving apart inside a personal space of
r_s= 1.9 m; - cohesion, a constant pull toward the centre of mass of its nine nearest neighbours, which is what makes a flock an object rather than a crowd;
- alarm, which is not a force. A sheep takes on 86% of the highest fright among those nine neighbours, caught at 7 per second. Fright sets its speed cap, from 0.45 m/s grazing to 3.6 m/s flat out, against the dog’s 5.2.
That last one is doing more work than it looks. Without it the front of a pressed flock stands grazing while the back piles into it, and nothing moves. With it the flock behaves like one animal: press the near rim and the far rim is running 0.6 s later, which is 23 m/s of apparent propagation — four times the dog’s own top speed, and not a wave but a cascade, which is why the number moves when the integrator’s step moves.
The handler in shepherd() is the published collect-or-drive rule: gather any
sheep further than r_s·N^(2/3) from the bunch before driving the bunch, and
drive from a point on the line from the goal through the flock, held at a
standoff behind the flock’s trailing edge. The player’s pointer and that
controller go through the same hole in step(), so “run it for me” is not a
different game being played.
Before believing any of it, scripts/measure.mjs checks what a wrong model gets
wrong:
| check | result |
|---|---|
| same seed, same trial | 38.520000 s twice |
| deepest a sheep ever got into a fence | 0.000 mm |
| furthest any sheep got outside the paddock | 0.000 mm |
| any sheep over its own speed cap | 0.000 mm/s |
| penned, at steps of 1/25, 1/50, 1/100, 1/200 s | 13, 14, 15, 13 of 16 |
A trial is chaotic — twenty sheep, a noise term, a feedback loop — so the step is checked against the statistic rather than the trajectory, and every number below is a median or a rate over 32 seeds for the same reason.
The lever, and the cliff at the end of it
Hold a standoff behind a flock in an open paddock and walk it down the field for thirty seconds:
| standoff | flock driven (m/s) | sheep inside the zone | opened up |
|---|---|---|---|
| no dog at all | 0.014 | 0.0 | — |
| 3.4 m behind the rim | 1.606 | 13.5 | 33% |
| 6.8 m | 1.486 | 14.2 | 0% |
| 9.4 m | 0.979 | 12.8 | 0% |
| 11.9 m | 0.370 | 4.6 | 0% |
| 13.6 m | 0.108 | 1.4 | 0% |
| 15.3 m | 0.029 | 0.3 | 0% |
| 17.0 m | 0.014 | 0.0 | 0% |
| 20.4 m | 0.014 | 0.0 | 0% |
Between 9.4 m and 15.3 m — six metres, a third of the zone’s radius — the dog goes from moving a flock at a brisk walk to moving it at the speed a paddock with nothing in it moves. There is no gentle version. A dog a few metres too far off is not pressing lightly; it is not pressing, and no amount of patience converts one into the other. That is the whole reason a handler needs a command for get out: the mistake it corrects is not rudeness, it is standing on the wrong side of a cliff edge you cannot see.
The other half of the same fact: position is the instruction, and the instruction expires.
| dog planted this deep inside the rim | flock shifted in 20 s |
|---|---|
| 1 m | 0.55 m |
| 3 m | 0.55 m |
| 6 m | 1.79 m |
| 10 m | 5.00 m |
Stand in exactly the right place and do nothing and you are worth about half a metre: the rear sheep steps out of the zone and the lever disconnects itself. To shift a flock by standing still you have to stand ten metres inside the rim — which is to say, among them, which is the move that opens them up. A standoff is something held, not somewhere arrived at.
Pressure, not pushing
Put the dog at a bearing off the straight-behind line, hold it there motionless, and ask which way the flock leaves:
| dog bearing off straight-behind | flock moved in 20 s | mean lean | mean |error| |
|---|---|---|---|
| 0° | 4.2 m | −0.95° | 9.0° |
| 20° | 4.2 m | 1.88° | 11.2° |
| 40° | 4.2 m | 3.42° | 9.7° |
| 60° | 4.2 m | 4.20° | 10.9° |
| 80° | 4.1 m | 3.99° | 13.4° |
| 100° | 4.1 m | 4.20° | 14.3° |
| 130° | 4.1 m | 2.05° | 16.4° |
Over 130° of bearing there is no systematic lean at all — 2.68° across the lot — and individual trials scatter about 12° either side, because twenty sheep and a noise term do not walk a ruled line. The dog is standing still in every one of those runs. Its position is the entire instruction. Nothing it does is transmitted to a sheep by contact, by chasing, or by being faster.
Which is the thing to feel in the demo: you do not drive the flock by going where you want it to go. You steer by moving around the line that runs from the gate, through the bunch, out the back — and the flock turns by the angle you stepped, not by the distance you travelled.
Press or wait
The same run, 32 seeds, the standoff swept:
| standoff | penned inside 150 s | median time when it works | expected time | flock opened up |
|---|---|---|---|---|
| 1.7 m behind the rim | 69% | 34.1 s | 70.7 s | 53% |
| 3.4 m | 75% | 32.2 s | 62.4 s | 53% |
| 5.1 m | 78% | 31.7 s | 59.1 s | 50% |
| 6.8 m | 78% | 33.4 s | 59.9 s | 47% |
| 9.4 m | 91% | 42.3 s | 57.0 s | 38% |
| 11.9 m | 72% | 93.3 s | 113.5 s | 34% |
| 13.6 m | 9% | 143.1 s | 149.3 s | 34% |
| 17.0 m | 0% | — | 150.0 s | 34% |
The fastest standoff and the best standoff are not the same standoff. Crowding in at 5.1 m pens in 31.7 s when it works, and opens the flock into pieces on half of all attempts. Holding 9.4 m is a third slower per success and wins on expectation, because its failures are rarer. And the cost of pressing is never simply a slower run: it is a flock in two halves, one of which is now behind you, and the clock does not stop while you fetch it.
On the other side of the optimum there is no slope to feel your way down. 11.9 m still works, badly. 13.6 m is 9%. 17.0 m is not a cautious dog; it is no dog.
The outrun, measured rather than admired
The sport is named after the dog’s opening move — the wide arc out and around, so the first the sheep know of it is a dog already standing in the right place. The controller can be told to refuse any line whose middle passes through the bunch, or to walk straight at wherever it needs to be:
| approach | penned | median time | shoved the wrong way on the lift | opened up |
|---|---|---|---|---|
| runs wide | 91% | 42.3 s | 0.47 m | 38% |
| walks straight at them | 91% | 42.1 s | 1.45 m | 41% |
A metre on the lift, and nothing measurable on the outcome. This model will not pay for the outrun, because a flock with this much cohesion closes back up behind a dog that barges through it, and the barging dog arrives at the balance point a little sooner. Reported because it was measured and not because it was wanted: in here, standing in the right place is worth an order of magnitude more than getting there tidily, and I would rather publish the table than the story.
(Both of those dogs are still holding a standoff once they arrive. The outrun is about the approach; everything else on this page is about the station, and the station is what the model cares about.)
What one dog can hold
| sheep | bunch radius | inside the zone while driving | fright of the far sheep | penned | median time |
|---|---|---|---|---|---|
| 6 | 3.5 m | 68% | 0.67 | 100% | 24.0 s |
| 12 | 5.9 m | 66% | 0.57 | 100% | 26.7 s |
| 20 | 7.4 m | 61% | 0.50 | 81% | 38.7 s |
| 30 | 10.6 m | 6% | 0.07 | 13% | 131.9 s |
| 45 | 12.8 m | 3% | 0.04 | 0% | — |
| 65 | 14.7 m | 2% | 0.00 | 0% | — |
Between 20 and 30 sheep the share of the flock the dog can touch at once falls
off a shelf, from 61% to 6%, and the run goes with it. The geometry is simple
enough to do on paper: standing a standoff s behind a bunch of radius r, the
far side of that bunch is inside the zone only while 2r + s·r_a < r_a, which at
the working standoff means r < 3.8 m — true of six sheep and of nothing
bigger. Every flock above that size is being held together by alarm passing
between sheep rather than by the dog, and alarm loses 14% of itself at every
hop. Enough hops and the far rim never hears. The ceiling on one dog is not a
head count and not a stamina budget; it is a distance.
The wings are not scenery
| wing length | penned | mean sheep in at the bell |
|---|---|---|
| 0 m | 19% | 6.3 |
| 3 m | 69% | 16.9 |
| 6 m | 81% | 16.3 |
| 9 m | 88% | 17.5 |
| 13 m | 94% | 18.8 |
A flock pressed at a flat wall slides along it, and the gate is the one part of the wall it is not sliding toward. Three metres of flare either side of the opening takes the pen from 6 sheep in to 17. At the mouth the controller drops its standoff to a third of the usual: the last ones in are pressed, not steered, which is the one moment in the run where getting close is correct.
Reusing it
src/get-out.mjs is framework-free and has no DOM in it. create() builds a
trial, step(state, dt, point) advances it with the dog running at point,
shepherd(state, opts) returns where a handler would be going and why, and
run(opts) plays a whole headless trial for sweeps. clusters() and spread()
are the honest readouts — whether the flock is one object, and how wide.
The piece the rest of a game would want is the sheep themselves: a flight zone plus neighbour shove plus cohesion plus caught alarm is four terms, and it gives a crowd that parts around a threat, re-closes behind it, carries panic faster than anything in it can run, and has a size above which no single threat can move it. Swap the dog for a torch, a siren or a player character and almost none of that changes.
Known edges: the flight zone is a hard circle rather than a cone, so these sheep have eyes in the back of their heads; a real one has a blind spot behind it that is exactly where a handler likes to be. There is no lie-down, so the dog cannot switch its own pressure off without walking out of range. And the paddock is flat and empty — no hedge to hold one side for you, which in a real trial is half the craft.





