A bowling ball does not knock down ten pins. It cannot get near ten pins.
The pins stand on an equilateral lattice with 12 inches between the centres of any two neighbours. A tenpin is 4.766 inches across its belly. So the clear air between two neighbouring pins is
12 − 4.766 = 7.234 in
and a bowling ball is 8.5 inches across. It is 1.266 inches too wide to
fit between any two pins in the rack, and because the lattice is equilateral,
every adjacent pair is that same 12 inches — there is no wider gap somewhere
else to go through instead. validateGeometry() counts the eighteen adjacent
pairs and refuses a layout where any of them differs, because if that stopped
being true the piece would have no claim at all.
Five of them are behind a door
“Too wide to fit between two pins” is a fact about a gap. The useful question is what it does to the rack, and that is a question about the ball’s configuration space — not where the ball is, but where its centre is allowed to be, which is the set of points at least 6.633 inches from every pin spot and no further than 16.5 inches off the centreline, because the rest of the lane is channel.
cspace() floods that set from in front of the rack, and reachability() then
walks the circle of touching positions around each pin and asks which of them
the flood actually got to. The answer:
| the ball can reach | 1, 2, 3, 4, 6 |
| no route at all | 5, 7, 8, 9, 10 |
The 5 pin is the one that gives the game away. There are plenty of places the ball could legally sit while touching the 5 — directly in front of it, in the notch between the 2 and the 3, with 0.45 inches to spare on either side. It simply cannot get to any of them, because arriving means crossing the 2-3 line, and the 2 and the 3 are 12 inches apart like everything else. Same for the 8 and the 9. The 7 and the 10 are worse: the ball’s centre cannot go past 16.5 inches off the middle, so the only approach is inboard, and the 6 is in the way.
The deepest the ball ever gets with ten standing is 15.9 inches down the
deck, in the slot beside the 4 or the 6 — past the front row and nowhere near
the second. That is the shape the reach loop draws: the same rack, the ball
walked up every board on the lane from 5 to 34, stopping dead in the front row
every single time. The demo shades the whole reachable set underneath it, and
the picture is the argument.
And it is not short of energy
The obvious objection is that none of this should matter, because a bowling ball is enormously more violent than a pin is sturdy. That is true, and it is the point.
A pin topples when its centre of gravity passes outside the edge of its own base. The base is 2.0625 inches across and the centre of gravity sits about 5.5 inches up, so the tilt is
atan( 1.031 / 5.5 ) = 10.62°
which lifts the centre of gravity by 0.0958 of an inch. At 3.5 lb that is 0.0280 ft·lb per pin, 0.280 for all ten. A 15 lb ball at 17 mph arrives with 144.9 ft·lb.
The ball brings 518 times the energy the entire rack needs — 5,184 times what one pin needs — and still leaves pins standing. There is no such thing as a glancing blow that a pin survives; a pin left standing is, very nearly, a pin that was never touched. Whatever a bowler is actually buying with speed and revolutions, it is not energy. It is geometry: the 1.266 inches.
So a strike is a tunnel
Which leaves the thing the ball does have: it can open the door itself.
simulate() is a plan-view rigid-disc carry — a 15 lb disc and ten 3.5 lb
ones, impacts resolved along the line of centres with a coefficient of
restitution, struck pins decelerating and bouncing off the kickback plates.
Run the book pocket, 17.5 board at 6°:
pin 1 0 ms ball bent +8.1° pin away at 19.6 mph
pin 3 44 ms ball bent −6.9° pin away at 15.4 mph
pin 5 107 ms ball bent +7.2° pin away at 11.4 mph
Three pins. The other seven are knocked down by pins. And the ball reaches the 5 — which the geometry above says is unreachable — because by the time it gets to the second row the 1 and the 3 are gone. At 81 ms, as the ball’s centre crossed their row, the clear air between the 1 and the 3 measured 11.26 inches, up from 7.234. The ball needed 8.5. The hole it went through was one it had opened itself, about eighty milliseconds earlier, and it went through with 2.76 inches to spare.
Each of those contacts bends the ball’s line by seven or eight degrees — more, every time, than the 6° of entry angle the whole shot was aimed to produce. Along the line of centres the ball keeps 70.7% of its closing speed and the pin leaves at 1.257 times it, which is the entire mass ratio argument: 15 against 3.5 is not nearly as lopsided as it feels.
What the entry angle is actually buying
Take the angle out and leave everything else alone — same board, same speed,
0° — and the flat loop is what happens. The ball now arrives at the front row
too early. At 85 ms the 1-3 clear air is 6.57 inches: not just short of
the 8.5 the ball needs, but narrower than the 7.234 it started at, because
the pins have been shoved inward rather than thrown clear. So the ball does not
pass through the door. It ploughs through it, paying for the passage in
deflection, and arrives at the 5 late, slow and off line. It carries nine and
leaves the 8 pin — which is the leave a real straight ball at the pocket
famously gives you.
That is what entry angle buys. Not more energy, and not a better hit on the headpin. It buys a door that is already open by the time you get there.
Two more the model lands without being told to:
- on the nose (20 board, 1°) the rack splits sideways round the ball and leaves the 4-6-7-10 — the big four, and exactly what a nose hit does.
- light (15 board) leaves the 2-4-7 side of the rack, because the ball never crosses to it.
How far to trust this
Kept deliberately apart, in the source and here:
Certain. The lattice, the gap, the 1.266 inches, the configuration space
and which pins are sealed off, the toppling angle and its energy, and the
velocity split at a two-body impact. Those are geometry and bookkeeping, and
validateGeometry() asserts the ones the prose leans on — including the
reachable set itself, so that if a constant ever drifts far enough to open a
route to the 5, the build says so instead of the page quietly lying.
Modelled. The carry, all of it. Real pins go airborne, tumble about three axes, and come back off the kickbacks in ways a plan view has no vocabulary for. This is discs on a plane with a restitution and a deceleration, calibrated against leaves the sport recognises rather than against force plates. Believe the shapes — flat 8, nose split, the light-side leaves. Do not believe a strike percentage.
The carry map in the demo shows the honest edge of that. Thirty-nine of its 527
board × angle cells strike, and the boundary is speckled: a deterministic
rigid-body model flips between a strike and a 10 pin on a quarter of a degree.
Nudge the pin spots by a thirty-second of an inch and the pocket does not care
at all — sixty racks out of sixty still strike — but one board off, at 18.5, the
same nudge flips the leave between the 7 and the 7-9 roughly two times in three.
Real bowling’s smooth strike-probability curve is an average over that
sensitivity, which is the thing carrydown and roll-out are both modelling
when they hand the carry to a number.
Where this sits
Two mechanics in this catalog already do the other sixty feet. roll-out
models the ball’s rotation from release to the pins; carrydown models the oil
film it is editing on the way. Both of them stop at the pin deck and turn the
carry into a probability from the pocket error, because the deck is a different
problem. This is that problem, and the answer it gives back to them is that
most of what they call “carry” is the rack hitting itself.
The loops
- strike — the book pocket, 17.5 board at 6°. Three pins touched, ten down.
- flat — the same line with the entry angle taken out. The 8 stands.
- nose — dead on the headpin. The big four.
- reach — ten standing, the ball walked up every board, and the whole reachable configuration space shaded underneath. It never gets past the front row.
Reuse
export/deck-<loop>-<n>.png— 1× frames (87×120, transparent background). Render at integer scales with nearest-neighbour filtering.export/deck-sheet.png— every frame in one strip, in loop order.export/deck@4x.png— prescaled hero, mid-mix at the pocket.
Source
No .aseprite — the canonical source is source/deck.mjs, which is the
geometry, the carry model and the pixel drawing in one file. Nothing is
keyframed: a frame is renderFrame({ shot, t }) evaluated at a time in
milliseconds after first contact, and the pins are wherever the integration put
them. The lane is 39 boards across 41.5 inches, which at 2 px/in is 2.13 px a
board — the reason a pixel drawing of a lane wants to be exactly this wide.
Regenerate everything with:
node source/render.mjs # export/, media/ loops, thumb, demo copy
node scripts/screenshot-demo.mjs # media/ demo shots, and the demo smoke test
(needs site/node_modules installed — the scripts resolve Chromium through
site/scripts/lib/chromium.mjs.)