The umpire reads a list, and the bibs come out to meet it
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>
This commit is contained in:
1 parent
c659b6882f
commit
22df96cc1d
17 files changed
+556
-19
No files matched your search
+76
-3
@@ -10,7 +10,7 @@ detail of any individual change, read the git log.
|
||||
the state-machine contracts that have historically produced the show-stoppers. The Dockerfile runs
|
||||
it as a build stage, so a red suite cannot deploy — but finding out from Coolify is the slow way.
|
||||
|
||||
Last updated 2026-08-11 (the horde's breather restored, the boss walk-on overlay; beats.js
|
||||
Last updated 2026-08-11 (the coaching drill lands as a back-room prototype; the horde's breather restored, the boss walk-on overlay; beats.js
|
||||
extraction, this file renamed, tests gate the build). **Start with "How to work on this", "OPEN — leftovers" and "LATER —
|
||||
shipping it"** (all three just above the CLOSED sections) — the first tells you how Oliver's feedback
|
||||
should be handled, the second is everything known to be outstanding in the game, the third is the
|
||||
@@ -57,8 +57,10 @@ the primary target.
|
||||
`config.js` TUNE (live T panel) + structural constants + `UI` palette · `state.js` the `G` object +
|
||||
P/O/ball/score + `setupPoint`/`sendBoy` · `gameplay.js` ballistics/swings/serve/rules/AI/`update()` +
|
||||
transition + `splatPoint` + ball-boy routines · `beats.js` **the beat machinery: every mode
|
||||
transition (duel/horde/boss/changeover/`proceedAfterClear`) — ONE MODE OWNS THE COURT, and each
|
||||
`start*` enforces that itself; a new mode starts there and refuses there** · `zombies.js`
|
||||
transition (duel/horde/boss/changeover/drill/`proceedAfterClear`) — ONE MODE OWNS THE COURT, and
|
||||
each `start*` enforces that itself; a new mode starts there and refuses there** · `drill.js` the
|
||||
coaching drill's own clock, bodies and rules (its transitions live in beats.js like every other
|
||||
mode's) · `zombies.js`
|
||||
zombie/gore/particle state + `updateZombies` · `render.js` camera/palette-lerp/sprites/all drawing ·
|
||||
`input.js` keys/touch/flick · `audio.js` sfx + recorded umpire (`assets/audio/*`, macOS
|
||||
`say -v Daniel`) · `panel.js` the T panel · `main.js` boot, loop, scoreboard test-mode taps,
|
||||
@@ -431,6 +433,77 @@ WELL drains instead: a gold wash across the whole tile, emptying leftward, clipp
|
||||
rounded path (`panel` leaves it as the current path) and drawn under the icon and labels. Measured
|
||||
lit vs empty on the live tile: rgb(88,125,68) against rgb(31,84,49).
|
||||
|
||||
## Session log: THE COACHING DRILL — the cognitive mode, as a prototype (2026-08-11, same day)
|
||||
|
||||
Oliver and his team-mate decided the game needs **a different angle alongside the gore mode**, after
|
||||
he reported the late game going repetitive: *"something that requires some immediate strategy other
|
||||
than saving specific weapons for a boss I was killed by last time"*. Three modes planned — classic
|
||||
tennis, **splatter tennis** (this), splatter tennis GORE (what exists). What went in today is the
|
||||
middle one's feel-test, not the mode: **back room only** (`DRILL TEST`, or `#drill`), no menu entry,
|
||||
nothing wired to tennis scoring.
|
||||
|
||||
**Why the late game is flat, for the record** (diagnosed before proposing anything, per the
|
||||
meta-lesson). The optimal move never changes: kill the nearest thing, now. Every interruption is on
|
||||
a fixed metronome (duel/3, machine/4, horde/6, boss/10, barrel/every game past 16), the director's
|
||||
dials all bottom out by ~game 25, nothing is scarce once the rack is full — and **the zombie side's
|
||||
score is unreachable by construction**: contact is a radius around the player and bodies home on his
|
||||
x, so anything that could cross the baseline eats him first. The crossing branch in `updateZombies`
|
||||
(and the `ump_unsportsmanlike` line with it) is very nearly dead code. Oliver caught that himself —
|
||||
the first design direction proposed this session was built on it and had to be thrown away.
|
||||
|
||||
**The mode.** The umpire CALLS a colour sequence aloud while bibbed bodies jog on and take their
|
||||
marks; then they come for you and you put them down in the called order. Colours never called are
|
||||
DECOYS — bodies walking at you that you are required to ignore. Two faults = double fault = the
|
||||
round is theirs. Settled in discussion: **audio-first, and shown as a pattern too.**
|
||||
|
||||
- **`voiceSeq` in audio.js** is what makes the call possible at all. `voice()` DROPS a line that
|
||||
would start while the umpire is still talking (one man, one microphone) — correct for unrelated
|
||||
triggers, fatal for a list. It decodes every clip FIRST, then queues them all at accumulated
|
||||
offsets, so the anti-overlap rule is satisfied by construction rather than fought. Five new
|
||||
recordings (`say -v Daniel -r 168` -> `afconvert`, the existing pipeline).
|
||||
- **Four colours, not six**, and every bib carries PIPS as well as a hue: ~8% of men cannot separate
|
||||
red from green, and a mode whose entire input is "which colour is that" owes them a second
|
||||
channel. The same pips appear on the HUD strip, so the two readouts teach each other.
|
||||
- **The bib is a DRAWN OVERLAY and it knowingly breaks the sprite rule** (`ponytail:` marked in
|
||||
`drawBib`). Six bib sheets x every walk frame is a week of art to answer a question a trapezoid
|
||||
answers today. If the mode survives its playtest, `drawBib` is the thing to DELETE and replace
|
||||
with a real bib sprite per colour, drawn like a wound skin. Shoulders wider than waist — the first
|
||||
cut flared the other way and every body was wearing a sandwich board.
|
||||
- **TWO functions pick a target, and snapping only one of them was the bug.** `flickTarget` (the
|
||||
slingshot) and `zombieTarget` (the plain tap) are separate paths; with only the first snapped,
|
||||
fifteen tap-serves in a row scored zero and the round just ran out. Both snap now. Anything that
|
||||
changes how a shot chooses a body has to touch both — same shape as the "three of five weapons
|
||||
silently no-oped on the racket zombie" bug.
|
||||
- **Contact costs the POINT, not the run** — a deliberate contract change, hooked in `killPlayer`
|
||||
(the single death path for both damage channels, which is why one hook covers every way in).
|
||||
Permadeath stays settled in the gore mode: a memory game where one lapse deletes a thirty-minute
|
||||
run punishes the exact skill it is trying to teach.
|
||||
- **The empty-court net** in `updateDrill`: a live round with nothing bibbed on court means something
|
||||
outside the drill emptied it (seen once while wiring up, not reproducible afterwards). Unrepaired
|
||||
that is a dead mode — no targets, no clock, nothing to tap. It redeals and logs `INVARIANT`, the
|
||||
same contract `watchdog` uses. `startDrill` also DISARMS the ordinary schedule (`pendingHorde`,
|
||||
`hordeWarn`, `bossDue`, `duelDue`): taking the court is not enough if someone else's arming latch
|
||||
is still loaded behind you.
|
||||
- **Eight new tests** (24 total) pin the ownership contract both ways, the call beat, the clean win,
|
||||
the double fault, the un-winnable-round guard and the softer death.
|
||||
|
||||
**Open, and every one of them is Oliver's call after he plays it:**
|
||||
1. **A ball that carries through the lane can complete two steps at once** — measured: one serve
|
||||
killed bib 1 and then bib 2 standing behind it, banking two correct steps in one shot. Had the
|
||||
second body been out of order that is an instant fault the player could not have intended. Either
|
||||
the lane is part of the puzzle (it is the same occlusion that makes footwork matter) or the pierce
|
||||
has to stop on a drill kill. Do not patch it silently — it is a design fork, not a bug.
|
||||
2. **The tap now aims itself completely.** With `zombieTarget` snapped, a bare tap is a legal shot at
|
||||
the called body, so the mode currently has NO aiming skill in it at all — only order and tempo.
|
||||
That is probably right for a cognitive mode played one-thumbed, and occlusion is the only thing
|
||||
left that makes standing position matter. Worth a deliberate look rather than an accident.
|
||||
3. Difficulty climbs on sequence LENGTH today (`drillSeq` 3 -> `drillSeqMax` 4, +1 every 3 rounds)
|
||||
and is deliberately capped low: a longer list is a memory test and memory tests fatigue. The dial
|
||||
with real headroom is the GEOMETRY — how often the called order fights the order they reach you
|
||||
in, and how often the target is behind someone. Unbuilt.
|
||||
4. Nothing is wired to tennis scoring, the menu or the run, and the mode has no ending. That is the
|
||||
next job IF the answer to "tense or noisy?" comes back tense.
|
||||
|
||||
## Session log: beats.js, the rename, and the build gate (2026-08-11, same day)
|
||||
|
||||
Oliver's structural question ("framework? smaller files?") answered with a deliberate NO on both —
|
||||
|
||||
Reference in new issue
Block a user