Gore opens in the gore, the theme comes back, and every mode gets a board

Splatter gore no longer makes you win a game of tennis first — the mode you
pick is the mode you get, with the man you came to play already turned. The
transition itself is untouched and still reachable; it just isn't a toll booth.

The menu theme could only ever be started, never brought back, so the first
run of a session silenced it for good while the court's ambience followed you
into the menu. Starting a bed now un-ducks it too.

Three world boards instead of one: kills, opponents felled, and games taken
off the CPU, each with its own name prompt and its own row per player.

...and the gore economy stops paying a barrel for every game won past game 16,
while the shamblers, the mix and the ball machines keep escalating past the
point they all used to stop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-15 13:53:42 +02:00
1 parent 9cc3ac54b3
commit 3cf3e029a4
11 files changed
+440 -88

No files matched your search

+98 -1
View File
@@ -20,7 +20,9 @@ anything, so if you add a `return` for an awkward deal, check the body still run
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-15 (the batch below: six new opponent families and an 18-rung ladder, the
Last updated 2026-08-15 (two sessions: the finetuning pass — gore opens in the gore, the menu theme
comes back, one world board per mode, and the barrel economy cut — over the batch below: six new
opponent families and an 18-rung ladder, the
tournament DRAW screen, three netplay fixes off Oliver's cellular report, the night court, and
camera flashes in the stand). **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
@@ -412,6 +414,101 @@ zombie (now an occasional opponent, `TUNE.racketEvery`, not the every-game fixtu
`RETURNED`, `DOUBLE KILL`) is a footnote to something you already watched happen. Sharing the loud
FACE with the milestone cards is right; sharing their SIZE made every footnote read as a milestone.
## Session log: gore opens in the gore, the theme comes back, three boards (2026-08-15, same day)
Oliver's finetuning pass on the batch below.
### THE GORE MODE STARTS IN THE GORE
*"the splatter gore should not have the normal tennis intro anymore, we should just start right in
splatter mode."* The prologue was a game of real tennis you had to WIN before the mode you picked
would begin — a reveal the first time, a toll booth every time after.
`gameplay.startGore()` is the direct door: it lands on the same state the transition's last beat
lands on (extracted as `enterSplatter`, so the two doors can never drift), sets `everTransitioned`
so the cinematic cannot fire behind it, and spawns the turned opponent as your first body — he is
the man you came to play and the mode's premise is that he is already one of them. **The transition
is NOT deleted**: it is still what `forceZombies` / `T.forceZombies()` plays, and it is still the
best thing in the game to look at. It just no longer stands between the menu and the mode. The mode
poster stopped promising a match that turns, because there is no longer one.
`main.intoSplatter` — the back room's "get me into splatter" hack — now calls `startGore()` too,
which deletes its 900 hidden `update()` calls. That loop fast-forwarded the whole eight-second
cinematic inside a single frame, firing every sound it makes at once.
### THE MENU THEME COMES BACK, AND THE COURT STAYS ON THE COURT
*"after some games — or returning to the main menu via the close button — it does not play the
background music anymore but you sometimes still hear the court background noise."*
Two halves of one bug, and both are `loopBed`'s early return. **It no-ops once a file is playing**,
so `menuMusic()` could only ever START the theme and never bring it back from the duck `start()`
put it under — the menu was silent for the rest of the session from the first run onward, and
quitting was the reliable way in because the death summary is the only path that ever called
`menuDuck(false)`. Meanwhile nothing ducked the court's own two beds at all, so the ambience
followed you onto the silent menu.
`menuMusic()` is now the one call that means "we are in the menus": it starts the theme, un-ducks
it, and ducks both court beds. `ambient()` and `zombieMusic()` un-duck themselves for the same
reason — the SECOND run would otherwise have been played in the silence the menu left them in.
**The rule, for anything added here later: a bed's start function must also un-duck it, because
starting it is a no-op the second time and ducking it is not.** `audio.bedTest` exposes the duck
set to the suite (same idea as `netTest`), which is what makes this testable at all — the beds
never load headless, but the INTENT is the thing that was wrong.
### THREE WORLD BOARDS
*"the world rank is still about the splatter gore which is not the only thing — we need something
similar for the other modes."*
`stats.BOARDS` is the only place that knows what each board ranks, and the server does not know at
all: it sorts `k` then `g` within a mode and nothing crosses.
| board | ranks | second column |
|---|---|---|
| SPLATTER | kills in a run | games survived |
| TENNIS (arcade + cup) | opponents felled | games |
| CLASSIC | games taken off the CPU | games played |
Classic needed a number worth ranking — every win is exactly two sets, so a board of 2s is a wall
of ties. `G.classicWon` counts the games YOU took and rides in the record's `s` slot, which held
sets until now and which **nothing has ever displayed** (the sets line on the death screen is
gore's; `read()` has never looked at `s`). The name prompt is per-mode too, gated on the board's
own number rather than on kills — the old `run.kills > 0` test silently barred classic (no kills)
from ever reaching it.
Server: rows carry `m`, `GET /api/scores?m=g|z|c` filters, POST keeps one row per name **per
board** and trims `KEEP` **per board** so a busy mode cannot evict a quiet one. Name ownership
stays GLOBAL — one person owns their name on all three, or a stranger could take it on classic
while you hold it on gore. Rows written before the split carry no `m` and are gore rows, which is
the same convention the client has used since the stats screen split, so there is no migration.
### THE GORE MODE GETS HARD AGAIN
*"in splatter gore it now gets too easy to just play through. Maybe we should reduce the barrels
again — pretty early in the game every won game gives a barrel. The splatter gore should be
unbelievably hard towards the end."*
He is right and the arithmetic said so. `barrelEvery 3 / barrelRamp 8` drove the gap to **one** at
game 16 and left it there, so the entire back half of a run paid out a weapon for every game won —
while every difficulty ramp in the file reached its ceiling around game 25 and stopped. A run got
richer after game 25 and never more dangerous.
- **Barrels: 5 / 14, and a new `barrelFloor` of 3.** The ramp survives (the late game does need
more inventory than the early one), it is just slower and it STOPS. `gameplay.barrelGap()` is the
curve, exported and pinned by a test, because this is exactly the kind of one-liner that quietly
becomes an income again.
- **`zSpeedMax` 2.9 → 3.6** — shamblers keep gaining speed to ~game 28 instead of 22.
- **`nastyMax` 0.75 → 1.0** — by game 34 there are no ordinary shamblers left in the mix at all.
- **Ball machines scale**: `machCap()` is 2 + one per `machMaxPer` games, capped at `machMaxCap`.
The one kind of late pressure that does not crowd the ground — they hold position and shoot, so
the court stays readable while the number of things that can reach you goes up.
The body COUNT ceiling (`zMaxCap`) is untouched and stays untouched: it is a readability limit on a
270 px screen, not a difficulty dial. What escalates now is what the bodies ARE and how fast they
arrive. **Feel-pending: these are dials, and the end of a long run is the one part of this game
that cannot be judged from the numbers.**
## Session log: the roster doubles, the draw is made on screen, and netplay stops locking (2026-08-15)
Oliver's seven-item batch. All of it is on STAGING and pending his phone verdict; items 3-5 in