Oliver's insight, and it retires a whole subsystem: "we don't need colors at
all! we already have different zombie types.. so the sequence is the zombies
themselves".
The bib and then the ground disc were both inventions bolted on to give a
body an identity it already had. A brute does not look like a runner, the
game is built on reading those silhouettes at speed, and the strip can show
the body's own walk frame instead of a swatch — no legend, no mapping, no new
art ever. It also deletes the accessibility problem outright rather than
deferring it, because a silhouette is not a hue. DRILL_COLS, drawColourRing,
drawBib, PIP_FACES, blip(), drillRingR and drillTones are all gone.
Two rules keep a type unambiguous: the plain shambler is never in the
alphabet (it is what the eaters are, so "not the puzzle" needs no marking),
and one of each type is on court at a time.
The new failure mode this created is instructive. Types move at different
speeds and drill bodies hold their lane, so one in a lane you are not in
walks the whole court and off the back untouched — stranding the sequence
asking for a body that no longer existed, i.e. the un-winnable state the mode
exists to prevent, reintroduced by a change that looked cosmetic. A batch
body crossing your baseline counts as caught now ("GOT PAST YOU"), which is
also just better design, and the speed spread is narrowed to 1.35..0.70 so a
batch stays coherent. Their real difference is HP and that is untouched: a
runner is one shot, a roller is seven.
Verified: 14400 frames of simulation, zero frames where the sequence named a
body that was not on court.
29 tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"remove the mob boy - make the normal zombies rarer and not so close to the
color gang".
sendBoy refuses during a drill, guarded at the function rather than at the
call sites — same shape as its existing G.interlude guard, so every present
and future caller inherits it. He is one more body crossing the lanes you are
reading colours down, and unlike everything else out there he is neither the
puzzle nor the threat. Measured: 0 boy-frames in 90 seconds. Gore no longer
gets mopped in this mode; the existing 40/30 caps are what bound it.
The eaters are rarer — every 12s falling to 5s, capped at 3 on court. At the
old rate they were a second crowd rather than an interruption, and a threat
you break off to deal with only works if breaking off is occasional. 8
arrivals in 90s where the old numbers gave ~13.
And they enter wide of the colour gang: best-of-9 lane sampling against the
bibbed bodies, the same trick the batch uses. Narrowest clearance measured
across 8 spawns was 0.91 m. They still converge on you afterwards — that is
what they are for — this only decides where they walk in, so they stop
screening the bodies you are trying to read.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"the colored zombies should also explode like they did before and make the
normal splash sound on destruction.. no bleeps please.. can we make the color
as a color circle the walk on? the sign they're holding is not nice. also
remove the ball slicing in this mode.. this leads to unwanted hits".
The silent deaths were my bug: the hook in killZombie did drillKill(zb) and
then RETURNED, and everything below that return is the death — decal, pile,
36-particle burst, splat, headshot crack. It resolves after the splice and
without returning now. Both halves are load-bearing and each was a bug in
turn: splice first or a freshly drawn combination names the corpse; don't
return, or the body simply vanishes.
The colour is a disc on the court the body walks on, drawn before the sprite.
The bib was a flat quad pinned to a walking sprite — UI stuck onto a
character, covering the art it sat on. On the ground it takes the court's own
perspective, measures 12.4px across at the spawn line against a chest patch's
few, and hides none of the sprite. A hard dark rim plus a bright inner line
is what keeps it from reading as another gore decal.
No slicing in the drill: a cut ball leaves the corpse and strikes whatever it
finds next, which in a mode where the wrong body is the failure is the game
choosing your target for you, badly.
And the mode has no sound of its own now, deliberately. The umpire reading
the list was vetoed, the arpeggio that replaced him was vetoed. blip() is
deleted. A kill bursts and splats like every other kill in this game; the
strip carries the list.
28 tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"make the game that it is actually winable meaning that all required colors
are visible on the far side before when a color combination is shown.. for
now no colors that are not in the current combination but occasional zombies
which don't have a color and are converging to the player trying to eat him".
Two rules define the file now. Every colour on court is IN the current
combination — no coloured decoys, so the strip can never name a body that is
not there. And a combination is only shown once its bodies are all on the far
side, which is free because the batch is BORN there: it is a property of the
construction rather than a check that could be wrong.
The pressure moved to the eaters: plain unbibbed shamblers on their own
clock, deliberately not flagged `drill` so they keep the gore mode's homing
and converge on you while the bibbed batch walks its lanes. Killing one is
never a fault; letting one reach you is the ordinary caught. The puzzle plays
fair and the danger arrives separately, which is a better trade than a puzzle
that cheats.
The batch is the round: kill the last of it and the next walks in on the same
frame with its combination already called.
One real bug, caught by the new test: killZombie resolved the drill BEFORE
splicing the body, so a combination drawn on the spot could name the corpse —
a round asking for a colour that is not on court, i.e. exactly the unwinnable
state this pass exists to prevent. Splice first, resolve second.
28 tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"what are the dice dots for?" -> "drop them", and "the dodge swipe should not
reset to the middle when firing".
The pips were colourblind redundancy so the mode did not rest on hue alone,
but they were noise to everyone who can separate the colours and they shrank
to nothing on a body at distance — exactly where the channel had to work.
Gone from the bib and the chip. Recorded in PROJECT.md as a known gap rather
than pretended away: if the mode ships, the answer is bibs that differ by
shape at sprite scale, not dots.
The dodge one was never a drill bug. The auto-assist recovered toward HOME.P
including its x, so firing walked you back to the centre line: measured, a
step out to 1.94 m was dragged to 0.77 m over one ball's flight — most of a
dodge, handed back for free, which is the welded-in-place complaint the
sidestep exists to answer arriving slowly instead of all at once. Splatter
recovers in DEPTH ONLY now and holds whatever lane you stepped to. Tennis
keeps the full recovery: recovering to centre is the real sport's footwork
and there is no sidestep there to protect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Oliver: "daniel announcing is maximum annoying" / "don't let the rush in
position just let them coming from the back in steady speed.. try to space
them not too close" / "when one combination is done just let the new one in..
in a continuous stream that increases in speed and difficulty" / "the rounds
can stay, they should be continuous".
The round survives as the unit. Every seam around it is deleted: no walk-on
to a mark, no announcement beat, no between-rounds pause, no deal. Bodies
walk in from the far baseline forever and a round is drawn from whoever is on
court — finish one and the next is drawn in the same frame, off the same
rolling population. The bodies you were ignoring a second ago are the ones
being called now.
- Daniel is gone from this mode. Each colour has a pitch; a round announces
itself as a four-note figure in half a second (blip()). drillTones 0 mutes
it. The recordings stay in assets.
- PLACEMENTS is deleted with the marks — nothing rushes anywhere and nothing
stops, so there are no shapes to place.
- A DRILL BODY HOLDS ITS LANE. updateZombies homes bodies onto the player's x
past the net, so they arrived spread and bunched into a knot right in front
of you; spawn spacing cannot survive that. Their lane is the puzzle here.
- One ramp on TIME SURVIVED drives speed, spawn gap and round length. Speed
is stamped per body at spawn, so the ramp reads as newcomers outpacing the
ones already walking, not the court accelerating under you.
- The empty-court watchdog is gone and nothing replaced it: with a stream
there is no state to be stuck in. One line covers every case.
27 tests, rewritten around the stream.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"the drill mode immediately goes into some horrible audio loop" — on a phone,
never on desktop, and that is the tell. Three of the four defects can only
happen on a phone, and every one of them is a rule voice() had followed for
months that my new function quietly broke.
- A SUSPENDED AudioContext HAS A FROZEN CLOCK. Scheduling four clips at
currentTime +0/+0.9/+1.7/+2.4 while the context is suspended puts all of
them in the past by the time it starts, so they fire on one instant through
a 1.3s reverb tail. Resume first, re-read the clock after the decode.
- A second call layered instead of replacing. voiceSeq SET voiceUntil and
never checked it. It stops the outstanding list now.
- ...and cancelling a list has to give back the time it booked, or the
replacement queues behind a list that will never play. Measured at 6.6s of
silence before the call the player is waiting on.
- The amplifier was in drill.js: the empty-court net redealt on the spot,
making the repair rate the frame rate — and every deal calls the umpire. It
goes through the ordinary between-rounds beat now.
Verified by tagging each decoded buffer with its source file and counting
start() calls: one drill_call, three colours, spaced, zero overlapping voice
lines. The earlier "clean" reading counted fetches, which proves nothing —
VOICE[] caches, so a repeat play never fetches again.
27 tests; the new one empties the court every frame for six seconds and
asserts at most one umpire call per beat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Oliver played it: "the auto aim just mean no skills involved at all. this
should just go away.. there is no penalty at the moment.. make some
variations of the position on the court and the color".
The first two notes are one finding. With the shot locked to the called body
it was unmissable, so the fault could never fire — there was no penalty
because there was no way to earn one. Both snaps are deleted. What replaced
them is one line: aimTie is 0 during a drill. That is not auto-aim, it is
removing the guess — the ordinary magnet lets a nearer body inside the same
cone steal a shot aimed past it, which is right for a crowd you are mowing
down and exactly wrong where hitting the wrong body IS the failure. An
unaimed tap now lands on grass.
And the variation:
- six colours (purple, white) with the court dealt three to five of them, so
which colours turn up and how many decoys there are are live questions. At
four out of four every round dealt every colour and only the order moved.
- PLACEMENTS: fan, cluster, column, stagger, wing — weighted, mirrored per
round, lanes shuffled against the bib order. column stacks bodies in one
lane, and the ball hits the first thing it touches, so feet matter.
- pips are dice faces now, shared by bib and HUD chip. A row of five dots has
to be counted; a die is recognised.
Measured over 30 deals: all five shapes, counts even, all six colours, and
the first target screened by another body in ~10% of rounds. Verified end to
end in the browser that FAULT and DOUBLE FAULT both fire.
26 tests, including a named regression for the auto-aim staying gone.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The late game is repetitive because the optimal move never changes: kill the
nearest thing, now. This is the first swing at a mode where it does — a
coaching drill where the umpire CALLS a colour sequence aloud while bibbed
bodies take their marks, and you must put them down in that order while they
walk at you. Uncalled colours are decoys you have to ignore. Two faults is a
double fault and the round is theirs.
Back room only (DRILL TEST, or #drill): this is a feel-test for one question —
tense, or just noisy? — so it keeps its own round count and touches neither
tennis scoring nor the run.
- voiceSeq: voice() drops a line that would start while the umpire is still
talking, which is fatal for a list. Decode first, queue at accumulated
offsets, and the anti-overlap rule is satisfied instead of fought.
- Four colours with PIPS as well as hue — red/green alone makes the mode
unplayable for ~8% of men.
- drawBib is a ponytail-marked overlay that knowingly breaks the sprite rule;
it is the thing to delete if the mode survives.
- BOTH target pickers snap (flickTarget and zombieTarget). Snapping only the
slingshot left fifteen tap-serves in a row scoring nothing.
- Contact costs the point, not the run — permadeath stays in the gore mode.
- startDrill disarms the ordinary schedule; updateDrill redeals and logs an
INVARIANT if anything empties its court.
Eight new tests (24 total) pin the ownership contract both ways, the call
beat, the win, the double fault, the un-winnable-round guard and the death.
PROJECT.md carries the four open questions for the playtest.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The gun, beacon, flamer and rocket fell silent the moment they cleared the court:
firing and steering were both gated on phase 'rally', and every beat raised by the
kill that empties the court (a point, a won game, the mop-up) parks the phase in
'over'. A burst is its own control mode for its whole len, like a horde — its own
clock is the only thing that ends it. Not fixed by forcing the phase back to rally:
a parked 'over' beat that never expires is how pendingHorde gets stranded.
The countdown moved off the tile's bottom edge (the rounded frame, and the bottom of
the screen) into the tile: the armed slot's well drains as a gold wash, clipped to
its own rounded path, under the icon and labels.
16 tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
THEY KEEP COMING is a 2.4s 'over' beat again (warnHorde in beats.js) instead of a
flash raised on the same frame the wave lands, and the chapter boss walks on behind
an overlay — his name in red over ENTERED THE COURT — held for 3s by the new
self-dismissing modal clock (m.hold) rather than announced on a routine-set card.
startHorde returns a bool: if the court has been taken when the warning expires the
pendingHorde latch is re-armed rather than the set losing the horde it paid for. The
warning ticks on its own clock, not on the 'over' beat, so a beat that moves the
phase underneath it can't strand it (the mgT lock, again).
Three tests, 15 total.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>