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:
1 parent
dbfd085493
commit
a5a681f9f2
5 files changed
+47
-57
No files matched your search
+8
-22
@@ -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
|
||||
|
||||
+14
-14
@@ -917,22 +917,22 @@ export const leagueOf = lg => LEAGUES[Math.min(LEAGUES.length, Math.max(1, lg |
|
||||
export const leagueOfRung = n => LEAGUES.find(l => n <= l.band[1]) || LEAGUES[LEAGUES.length - 1];
|
||||
|
||||
// The tournament, PER LEAGUE. Same shape CUP_ROUNDS always had (name/band/need) — round one is a
|
||||
// single game so a run opens fast, and the drawn body's pool still scales with `need`
|
||||
// (matchOpponent). The rounds ride ON the cup object (beats.startMatch stamps them), so every
|
||||
// consumer reads cup.rounds and the full-ladder constant is gone.
|
||||
// A league band is 3-4 rungs, so the draw is WITHOUT REPLACEMENT: every non-final round carries
|
||||
// the whole sub-band and the run deals each body at most once (cup.played / buildBracket's used
|
||||
// set), the final is always the band's top rung — "only the finale is settled", still. A 4-rung
|
||||
// league is four rounds (a shuffle of three challengers), a 3-rung league is three.
|
||||
// single game so a run opens fast, and the body's pool still scales with `need` (matchOpponent).
|
||||
// The rounds ride ON the cup object (beats.startMatch stamps them).
|
||||
// EASY TO HARD, DETERMINISTIC (2026-08-29, Oliver: "warum sollten wir noch mischen?"): each round
|
||||
// is exactly one position of the band, ascending, the final the band's top. The shuffle was the
|
||||
// deleted draw screen's ceremony — without the screen it only ever risked pairing the strongest
|
||||
// challenger with the shortest round, inverting the curve the whole game is tuned around. The
|
||||
// setup's league panel is now, incidentally, an exact preview of the tournament order.
|
||||
export const cupRoundsFor = lg => {
|
||||
const [lo, hi] = leagueOf(lg).band;
|
||||
const open = [];
|
||||
for (let r = lo; r < hi; r++) open.push(r);
|
||||
const names = open.length >= 3 ? ['ROUND ONE', 'QUARTER-FINAL', 'SEMI-FINAL']
|
||||
: ['ROUND ONE', 'SEMI-FINAL'];
|
||||
return open.map((_, i) => ({ name: names[i] || 'ROUND ' + (i + 1), band: open.slice(),
|
||||
need: i ? 2 : 1 }))
|
||||
.concat([{ name: 'THE FINAL', band: [hi], need: 2 }]);
|
||||
const names = hi - lo >= 3 ? ['ROUND ONE', 'QUARTER-FINAL', 'SEMI-FINAL']
|
||||
: ['ROUND ONE', 'SEMI-FINAL'];
|
||||
const rounds = [];
|
||||
for (let r = lo; r < hi; r++)
|
||||
rounds.push({ name: names[rounds.length] || 'ROUND ' + (rounds.length + 1),
|
||||
band: [r], need: rounds.length ? 2 : 1 });
|
||||
return rounds.concat([{ name: 'THE FINAL', band: [hi], need: 2 }]);
|
||||
};
|
||||
|
||||
export const TOURS = [
|
||||
|
||||
Reference in new issue
Block a user