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 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. game since the last delivery. That is not the same as winning the duel.
**Build:** make winning the duel the ONLY source of weapons. **The design decision (Oliver, 2026-07-27):** duels must come round on their own after a
- Delete the `tinDue` scheduling in `splatPoint()` and the `deliverTin()` call in while, "damit es immer die chance auf waffen gibt". So the schedule is not the problem — it
`startChangeover()`. Keep the "CHANGEOVER" flash. `G.tinDue` / `TUNE.ballChangeFirst` / is attached to the wrong event. **Move it from delivering tins to calling duels.** The
`ballChangeEvery` / `G.shameGame` all become dead — remove them rather than leaving cadence stays, the reward becomes something you have to earn, and the umpire-restores-order
vestigial state. framing is unchanged.
- Keep `resolveInterlude('P') → deliverTin()`.
**Consequence to check:** duels only trigger when the court is clear and a racket zombie is **Why the duel is rare today:** the trigger at `gameplay.js:~760` requires
the last one standing (`gameplay.js:~760`). If that turns out to be rare, weapons become `zombies.length === 1 && zombies[0].variant === 'r' && !zombies[0].dueled` — the court has to
near-unobtainable. **Measure before shipping:** run a 5-minute simulated session and count be completely empty apart from one never-yet-dueled racket zombie. Racket zombies only appear
duels. If it's under ~1 per two games, tell Oliver rather than silently re-adding a second when you win a game (`splatPoint`) or survive a horde (`endHorde`), and fresh shamblers spawn
source — the design question (how often should duels happen?) is his call. 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 **Build:**
unchanged. Win one; exactly one tin arrives. - 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).
--- ---