The cup climbs: easy to hard, deterministic — the shuffle retires with its screen

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Fable 5 committed 2026-08-29 16:49:36 +02:00
1 parent dbfd085493
commit a5a681f9f2
5 files changed
+47 -57

No files matched your search

+8 -22
View File
@@ -354,13 +354,12 @@ export function watchdog(dt) {
// the match mode ends. Regicide is inherited for free: smashing the ball into the body still wounds
// it, and killing it outright wins the game early (killZombie fires resolveInterlude('P'), which
// lands in matchGameWon via the empty-court check).
// `draw` is an optional pre-settled list of rungs, one per cup round — null (the normal case
// since the bracket screen was deleted, 2026-08-29) means "roll each round as it comes". The
// parameter stays: the suite uses it to pin the validation below.
// `train` (2026-08-28) is a RUNG NUMBER and turns the run into the TRAINING COURT: that one
// opponent, one game at a time, nothing banked. The ladder is parked — d.opp never advances, a
// felled body walks straight back on, and bleeding out costs a modal instead of the run. All of
// it rides the ordinary match machinery behind the d.train flag; see matchGameWon / matchPoint.
// `draw` is DEAD weight kept only for call-site arity — the cup runs easy to hard now
// (cupRoundsFor is deterministic, 2026-08-29) and nothing reads it.
export function startMatch(cup = false, draw = null, train = 0) {
if (G.interlude || G.horde || G.bossFight || G.drill || G.match || G.bench || G.net) return false;
// THE LEAGUES: the profile's league is the world (band, pace tier, court — see PROJECT.md).
@@ -376,7 +375,7 @@ export function startMatch(cup = false, draw = null, train = 0) {
// on (a rung DRAWN from the round's band — cupDraw sets d.opp, so every ladder dial downstream
// scales off the drawn rung untouched), how deep the body's pool is (matchOpponent multiplies
// by the round's `need`), and where a won game goes (cupGameWon). See config.cupRoundsFor.
if (cup) { G.match.cup = { round: 0, g: 0, draw: draw || null, rounds: cupRoundsFor(G.league) }; cupDraw(); }
if (cup) { G.match.cup = { round: 0, g: 0, rounds: cupRoundsFor(G.league) }; cupDraw(); }
G.matchFall = null;
G.hp = G.hpMax = TUNE.matchPlayerHp; // a real match is longer than four mistakes — the gore
// mode's 4 was "too weak" here, felt not calculated
@@ -412,25 +411,12 @@ export function startMatch(cup = false, draw = null, train = 0) {
return true;
}
// The round's rung, drawn from its band. d.opp carries it so matchFoe, the ladder speed dials and
// the felled arithmetic all read the drawn rung with no cup-awareness of their own.
// A PASSED DRAW IS THE DRAW THAT IS PLAYED (it once arrived from the bracket screen; the suite
// still passes one) — this reads it off rather than rolling again.
// Guarded on the band all the same: a saved or hand-passed draw that names a rung this round does
// not contain falls back to an honest roll rather than dealing the champion in round one.
// The round's opponent. No draw and no roll any more: the rounds ARE the band, ascending, so
// this simply reads the round's one position off (cupRoundsFor carries the order). d.opp carries
// it so matchFoe, the ladder speed dials and the felled arithmetic stay cup-unaware.
function cupDraw() {
const cup = G.match.cup, R = cup.rounds[cup.round];
const drawn = cup.draw && cup.draw[cup.round];
// WITHOUT REPLACEMENT: a league band is 3-4 rungs and every non-final round carries the whole
// sub-band, so the run remembers who has already fallen (cup.played) and never deals a body
// twice — a repeat would read as the bracket screen lying. The final's band is one rung and
// sails through untouched.
cup.played = cup.played || [];
const pool = R.band.filter(r => !cup.played.includes(r));
cup.rung = R.band.includes(drawn) && !cup.played.includes(drawn) ? drawn
: (pool.length ? pool : R.band)[Math.floor(Math.random() * (pool.length ? pool : R.band).length)];
cup.played.push(cup.rung);
G.match.opp = cup.rung;
const cup = G.match.cup;
G.match.opp = cup.rung = cup.rounds[cup.round].band[0];
}
// Every point starts like a real one: the server behind his line (setupPoint's tennis branch) and