From 22df96cc1d9eb8d789f048300b6a9a76e28e7c94 Mon Sep 17 00:00:00 2001 From: Oliver Rieger Date: Tue, 11 Aug 2026 18:01:33 +0200 Subject: [PATCH] The umpire reads a list, and the bibs come out to meet it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- PROJECT.md | 79 ++++++++++++++++- assets/audio/drill_blue.m4a | Bin 0 -> 7150 bytes assets/audio/drill_call.m4a | Bin 0 -> 10242 bytes assets/audio/drill_green.m4a | Bin 0 -> 6961 bytes assets/audio/drill_red.m4a | Bin 0 -> 6769 bytes assets/audio/drill_yellow.m4a | Bin 0 -> 6981 bytes index.html | 3 +- src/audio.js | 36 +++++++- src/beats.js | 37 +++++++- src/config.js | 18 ++++ src/drill.js | 162 ++++++++++++++++++++++++++++++++++ src/gameplay.js | 31 ++++++- src/main.js | 13 ++- src/render.js | 76 +++++++++++++++- src/state.js | 2 + src/zombies.js | 9 +- test.js | 109 ++++++++++++++++++++++- 17 files changed, 556 insertions(+), 19 deletions(-) create mode 100644 assets/audio/drill_blue.m4a create mode 100644 assets/audio/drill_call.m4a create mode 100644 assets/audio/drill_green.m4a create mode 100644 assets/audio/drill_red.m4a create mode 100644 assets/audio/drill_yellow.m4a create mode 100644 src/drill.js diff --git a/PROJECT.md b/PROJECT.md index 1676cb9..87a6126 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -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 — diff --git a/assets/audio/drill_blue.m4a b/assets/audio/drill_blue.m4a new file mode 100644 index 0000000000000000000000000000000000000000..eba42bad59588097090f7a2c79b4b7f88f49c0a0 GIT binary patch literal 7150 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 XM`mdtQYS&y@u@)=H_u$zL4fsN9CwZJ literal 0 HcmV?d00001 diff --git a/assets/audio/drill_yellow.m4a b/assets/audio/drill_yellow.m4a new file mode 100644 index 0000000000000000000000000000000000000000..df2c67370eee2ae68a5431c74e804a9b0d101264 GIT binary patch literal 6981 zcmeHKXIN9)(%vDVNUstgNI(LJbdVy&ByR+axxemT=E-EJep{{&{f%+px_A)(5pe(N0aKtI{M~pPh{r*F5BheXN`v?#s579BfqDj115m+U zf+(Qn3Rr_Xs9YZSwnPu6ahaGQlU6MVfq&cyc#koG(a~HM|CWbgkyIM!HfVzaS_GLC zxO#Iz6tWI?HAyGTogPKvPA?r5NG5T&awBdocq|Chf&*8pt#Xgl`z^nKsgd3E)T@kv{TKK)op)J>}3B*wGt#U`iYE0?1r?YYgs)ORX74lDiSG()SVpqy9y%ftNs z#Sk_}96F5vl=jmBfOi-dp;po}y@|KxtzcZyi^&Hc`lz zP*EsL)$}qnB=+CD+Af8{_`lJ4o>x@RVYMxelLLLAb^AL-r39V{F)h5i75-3U{dEG5 zG2aZ}d-=&Y6bm4nbv@TPu2PR5(P z`h%waqE*c=KVQ+DFluTn0T`UCd=7WFd|BxGl(lr^P2?`&-c#6oXXHfb=A8)0eN0fI zLv7u1NHxxhH@?B6`;KSF5=$iPoXuU!8I-zJp;M9d>nowvZLiYJ_>uiSKITr<m-5~ta;8TN zX(^kcdHBxh80!?Na71qi_el3%Ye~_s%0G+gvg-Q?SQ{_SIcDv=xshLyeLN&UH=tpr z>BofK=J}iF#$J1AA&Sp3_}f~wyrY)(>1~>6nY`dRi7R_mCfXem%6nt+u>x>M26k&FNbVgMd;TW-RWC=f@)y|Ejt8 z#6-}|{%8Fxe8DPU?!tOQc!b|bPHTx))XNFA+fOP|F}RY57u}Q7$(=wugZGv>A#&jI zHauFIUxu+U=Z4oEZ4nGm`Y3e5H2}yC@uHHGG)TK|J=S_vnU`XHJ~;r&00&9KKU9U= zJi;{Nk@`X~ELNOxw&6))OugFOj=h8P2h2|e|pnh3TwYQTf8!vHbzm#PHtkC`bJ%ND;-__Rpvm7 zDhxkmH!)K)qAt^_M8Lcs*2LQKK*Wd@vF)ux!y|Y1JmBFQWrp8~u-?aZbBMQSMMWI4n+L73O^pK{k@ouT-L_IKey82%I3jIf ztkmc&rRxU7H~ffd8ExObOXNvKc=F1m$J|Y2i@Yr{7)sfe4)YO6GsIi=I4wh3z7>jo zfy8MDz_8GOi{)D45)XvJchjCxJp5>rnQh*2=RYoWQJ6EfDo@HU3Sv~ea55jL11Im9 zQ~f4|-fuL;7@FPP==70w0{7IKE_n=7-WlStEykBpazM1@{kDwc);!Ct)qV|y`$J!5 zQ0Hv3`gIhruk9|Ji0XPd^Um~Lq@P=RP?;gZt<~&n@3*1ha{)`e+e>c6%gJw!&v|M- z8Ze)3O@+%2%U=!s8FpemWz%cr z<)kt%emyw`@buq&hv#*l*@`{iFu*)8Khb(He&#@2RFI1cNCvy3&vaR?xH5q8`o7JEb;G&ey-%&sWiZhM%Ww zUCzr{QNHdp?Tt8A(xRBb3@5zi%V>tSrSvUk+`fS88i9!CdU0c3!W7Ns-So@&Li3zK z{n4}u)#?)p`||2%r?dQ>x)n%Avj_0)3l~er*Xev7X+M;Uf1xa=kM&WxYOpKq+g13e z@kdGcx2665TAdnz6ySU0Q*>bF34Q17!)G!M6MM|`j+FypH=9C)Ct@D*6~zjDsBri8 z%5pu=oHAc52pKv+N$!iYgAU*86oUrFsauWc>})j`o)g=a`#vlvFYT7WtrGp>!|8^n z!yO(M+?J30dTRT+P0DU9NBHwv1S7#G%SN`q*c~Nf4=vI|W5oqwJSymB91`221nH>n zX)C)DRz5vF?Phr$VY?K$d?B{6H)Q5r%@x|z>#Xi_9kYN=J;d3&`@P+W{-qbo+-cI! zO1u^HuIylUkF~Xi?2UyxblH0PE#7z9?DKStq3u`m{cTuX?wcPa!S*FQTE|rljmJ4l z5zQu8pDsC|lsb?^&1Z>?vzCpRc}y3+!Qnfh-hDkm$)jSAi`HE}v)F?MFWw3q(hen& zflc;IM@oYq9|%E@QEaY+e-fcOKW(CDw8alDiU?$z9ym!#^riHFKFsvYdK4s+$-=cm z_MIMk@BaOEgfn1rhrEO2;IlpTidjl&?i1NA`c$Ju?W0UgqQpZezKRDB5SKzNDn&LA zHn-efe`$+zTw*rDdupfA<4{Vj+wR8WgC}wZSwrj$v)j)Rb5@E96OrmF2T~eq^0IF~ z?LgcwaQT?sajA0})p~E-Q{@pMVSN9J)(Oa#o7K zBLbP#H_3@QB$Ix$nA|Hg^M&*ZiQZ&VS1UojM!uY`#CTirNG>He-+A5U8IgOA34H+T z&GjP3Td!G!z~R3B2?qs(GDR)b0onV@vhz*PZWWtV9b_)(9ujo+h~ahPCD}@qPC5J4 zsA>W@fLOdxB6oDMr_GsdxnHSeF?hx{4G@%v~1 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 1dd7f1b..97ed074 100644 --- a/index.html +++ b/index.html @@ -373,6 +373,7 @@

+