POLISH-PLAN: schedule the DUEL, not the tin

Oliver's call: duels have to come round on their own so there is always a shot
at a weapon. So the game-count schedule isn't the bug — it's attached to the
wrong event. Item 5 now moves it from delivering tins to calling duels: same
cadence, same umpire-restores-order framing, but the weapon has to be earned.

Fires off proceedAfterClear(), which is the one moment the court is guaranteed
empty (the wave was just cleared by hand and nothing has respawned). Clearing
is already mandatory before play advances, so the schedule can't stall — a
wall-clock timer would need its own wait-for-a-safe-moment logic and could fire
mid-swarm. The existing opportunistic trigger stays as a bonus path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-07-27 04:53:00 +03:00
1 parent 64b297ce54
commit 5faaa99467
1 file changed
+41 -13
+41 -13
View File
@@ -181,21 +181,49 @@ oder nicht."
Note path 2 has a partial gate already: `G.shameGame` withholds the tin if *they* took a
game since the last delivery. That is not the same as winning the duel.
**Build:** make winning the duel the ONLY source of weapons.
- Delete the `tinDue` scheduling in `splatPoint()` and the `deliverTin()` call in
`startChangeover()`. Keep the "CHANGEOVER" flash. `G.tinDue` / `TUNE.ballChangeFirst` /
`ballChangeEvery` / `G.shameGame` all become dead — remove them rather than leaving
vestigial state.
- Keep `resolveInterlude('P') → deliverTin()`.
**The design decision (Oliver, 2026-07-27):** duels must come round on their own after a
while, "damit es immer die chance auf waffen gibt". So the schedule is not the problem — it
is attached to the wrong event. **Move it from delivering tins to calling duels.** The
cadence stays, the reward becomes something you have to earn, and the umpire-restores-order
framing is unchanged.
**Consequence to check:** duels only trigger when the court is clear and a racket zombie is
the last one standing (`gameplay.js:~760`). If that turns out to be rare, weapons become
near-unobtainable. **Measure before shipping:** run a 5-minute simulated session and count
duels. If it's under ~1 per two games, tell Oliver rather than silently re-adding a second
source — the design question (how often should duels happen?) is his call.
**Why the duel is rare today:** the trigger at `gameplay.js:~760` requires
`zombies.length === 1 && zombies[0].variant === 'r' && !zombies[0].dueled` — the court has to
be completely empty apart from one never-yet-dueled racket zombie. Racket zombies only appear
when you win a game (`splatPoint`) or survive a horde (`endHorde`), and fresh shamblers spawn
again the moment a clear finishes. So it fires by luck.
**Acceptance:** simulate a full game where the player loses the duel; `G.bombs` etc. must be
unchanged. Win one; exactly one tin arrives.
**Build:**
- Rename the schedule to what it now schedules: `TUNE.ballChangeFirst`/`ballChangeEvery` →
`duelFirst`/`duelEvery`, `G.tinDue` → `G.duelDue`. Keep the same arithmetic in
`splatPoint()`. Suggested start: first duel after game 2, then every 3.
- Delete the `deliverTin()` call in `startChangeover()` (keep the "CHANGEOVER" flash).
`G.shameGame` — which withheld a tin if they took a game — has nothing left to gate;
remove it rather than leaving vestigial state.
- Keep `resolveInterlude('P') → deliverTin()` as the only weapon source.
- **Fire the scheduled duel off the existing clear beat.** `proceedAfterClear()`
(`gameplay.js:290`) already runs at the one moment the court is guaranteed empty — the
player just cleared the wave by hand, and no new shamblers have spawned yet. That is the
natural slot. There: if `G.duelDue`, consume it, ensure a racket zombie exists
(`spawnRacketZombie()` if none, and clear `dueled` on the existing one so a veteran can be
challenged again), and start the interlude instead of the changeover/game beat. The
changeover follows after the duel resolves.
- Leave the existing opportunistic trigger in place. The schedule is a floor, not a ceiling —
a lucky clear can still produce a bonus duel, which is pure upside for weapon supply.
**Why this slot and not a timer:** clearing the wave is already mandatory before play
advances (`G.clearing`, a settled feel decision Oliver was emphatic about), so the schedule
can never stall. A wall-clock timer would need its own "wait for a safe moment" logic and
could fire mid-swarm.
**Acceptance:**
- Simulate ~10 games. A duel must occur at game 2, 5, 8 … regardless of how the waves fall.
- Lose a duel → `G.bombs`/`triples`/`flames`/`guns` unchanged, and the next duel still
arrives on schedule.
- Win one → exactly one tin, and the item-8 modal names it.
- No path reaches `deliverTin()` except `resolveInterlude('P')`
(`grep -n "deliverTin" *.js` should show the definition, that one call, and the `window.T`
test export — nothing else).
---