Stop calling three different things "the ladder"

Oliver: "the talk about ladder and rung is extremely confusing." It was, and it
was my vocabulary, not his reading. "Ladder" had come to mean three unrelated
things in this codebase — the sequence of opponents in zombie tennis, the
sequence of WOUND STAGES on one body, and the name of a stats screen — and
"rung" meant a position in whichever of those you happened to be reading about.

One word per thing now:

  the OPPONENTS   who you play, in order, one game each (config.OPPONENTS,
                  matchFoe(n), zb.foe). Never "rungs".
  WOUND STAGES    healthy -> arm off -> headless, on one body. Unchanged, and
                  now the only thing allowed to be called a progression.
  a FAMILY        the sprite set a body wears (config.ZFAMS).

Renames: LADDER_TRAITS -> OPPONENTS, matchRung -> matchFoe, zb.rung -> zb.foe,
and the stats screen THE LADDER -> OPPONENTS FELLED, which is what it lists.

The 'L0'..'L9' record keys are deliberately NOT renamed: they are written into
saved run records, and renaming them would orphan every match anyone has
played. A comment says so where they are built.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-12 13:11:55 +02:00
1 parent e2487b784a
commit df454c5d92
6 files changed
+40 -37

No files matched your search

+7 -7
View File
@@ -7,7 +7,7 @@
// (beats <-> gameplay and beats <-> zombies are runtime-only import cycles, same pattern as
// input <-> gameplay: the imported bindings are only touched inside functions, never at load.)
import { TUNE, UI, bossArt, matchRung, BENCH, ZFAMS, COURT, HOME } from './config.js';
import { TUNE, UI, bossArt, matchFoe, BENCH, ZFAMS, COURT, HOME } from './config.js';
import { G, P, O, ball, score, setupPoint, sendBoy } from './state.js';
import { voice, zombieDuck, aww } from './audio.js';
import { zombies, pellets, extras, shots, spawnRacketZombie, spawnChapterBoss, spawnZombie, explode, killPlayer } from './zombies.js';
@@ -344,12 +344,12 @@ function matchOpponent() {
spawnRacketZombie();
const zb = zombies.find(z => z.variant === 'r');
zb.dueled = true; // wakes racketAI, same as a fresh duel
// WHO THIS ONE IS. The rung carries a name off the chapter roster and a set of dial scalings —
// pure data, read where the dials are already read (see matchRung in config). It rides on the
// BODY so that killZombie can file the kill under it without asking G what rung we were on.
zb.rung = matchRung(G.match.opp);
zb.fam = zb.rung.fam; // ...and the body that rung wears (config.ZFAMS)
G.card = { title: zb.rung.name, sub1: zb.rung.line, color: UI.hot, t: 2.4 };
// WHO THIS ONE IS. The opponent carries a name off the chapter roster and a set of dial scalings —
// pure data, read where the dials are already read (see matchFoe in config). It rides on the BODY
// so killZombie can file the kill under it without asking G which opponent we were on.
zb.foe = matchFoe(G.match.opp);
zb.fam = zb.foe.fam; // ...and the body it wears (config.ZFAMS)
G.card = { title: zb.foe.name, sub1: zb.foe.line, color: UI.hot, t: 2.4 };
zb.hp = zb.hpMax = TUNE.matchOppHp; // a FLAT pool: with regicide gone the body is pure
// scoreboard (a quarter per point), so a deeper pool would
// change nothing — the ladder escalates in racketAI instead