Sharpen league and Climb difficulty and give Gore a front door

This commit is contained in:
wuwi committed 2026-09-07 09:53:49 +02:00
1 parent e3faeb0a3a
commit ede1f48152
6 files changed
+151 -51

No files matched your search

+14 -8
View File
@@ -275,7 +275,7 @@ function doHit(ch, quality, aim) {
// rungs take it back.
// ...and the RUNG's own pace trait rides on top, inside the cap: full pace is still the ceiling,
// an opponent just gets there sooner or later than the flat curve would (see matchFoe in config).
s *= Math.min(1, (TUNE.matchOppPace + (G.match.opp - 1) * TUNE.matchOppPacePer) * (ch.foe?.pace || 1));
s *= Math.min(1, (TUNE.matchOppPace + matchStep() * TUNE.matchOppPacePer) * (ch.foe?.pace || 1));
}
if (G.match) {
// THE OPPONENT'S WIDTH IS THE THIRD DIAL. Its returns scatter off aimError x (1 - 0.55
@@ -283,7 +283,7 @@ function doHit(ch, quality, aim) {
// balls". Opponent one keeps its returns inside matchWideBase of the centre line; each rung
// earns matchWidePer more width, so the line-painting is the LATE ladder, not the opening one.
if (ch.side !== 'P') {
const wide = (TUNE.matchWideBase + (G.match.opp - 1) * TUNE.matchWidePer) * (ch.foe?.wide || 1);
const wide = (TUNE.matchWideBase + matchStep() * TUNE.matchWidePer) * (ch.foe?.wide || 1);
tx = Math.max(-wide, Math.min(wide, tx));
}
}
@@ -1172,8 +1172,15 @@ function matchFallWillPlay() {
// One definition, because the read boost, the wrong-foot slow and the surprise whiff must all
// answer "how smart is this one" identically or the twist pulls in three directions at once.
const learnK = rz => G.match && !G.net ? Math.min(1, Math.max(0, (G.match.opp - 1) / (LADDER - 1))) : 0;
// The Climb is a repeatable arcade run: less nursery at the bottom. Four extra progression
// steps taper to zero at opponent eight; identities, territory tempo and cup onboarding stay put.
// Share this across movement, intercept planning and returns so all four dials agree.
const matchStep = () => {
const n = G.match.opp - 1;
return n + (!G.net && !G.match.cup && !G.match.train ? 4 * Math.max(0, 1 - n / 7) : 0);
};
const rzChaseSpeed = rz => TUNE.racketSpeed * leaguePace()
* (G.match ? (TUNE.matchSpeedBase + (G.match.opp - 1) * TUNE.matchSpeedPer) * ((rz.foe && rz.foe.speed) || 1)
* (G.match ? (TUNE.matchSpeedBase + matchStep() * TUNE.matchSpeedPer) * ((rz.foe && rz.foe.speed) || 1)
: 1 + TUNE.duelSpeedMax * duelSkill())
* (G.wasServe && ball.lastHit === 'P' ? TUNE.aiReturnDash : 1)
// wrong-footed: a body mid-lean is slow to turn — THE READ's one-ball cost, and it lives HERE
@@ -1456,10 +1463,9 @@ function trySwing(ch, isAI, qCap = TUNE.aiQualityMax) {
: [ -1, 0, 1 ][Math.floor(Math.random() * 3)],
az: Math.random() < 0.25 ? -1 : 0 }
: flick || { ax: axisX(), az: axisZ() * (ch.side === 'P' ? 1 : -1) };
// G.diff (classic difficulty) moves the FLOOR too: a raised qMin is what makes HARD's every
// ball arrive with pace, where a cap alone just trims the best ones. Null outside classic, so
// the racket zombie and the gore opener keep the TUNE floor.
const qMin = G.diff ? G.diff.qMin : TUNE.aiQualityMin;
// A quality floor makes strong opponents sustain pressure, instead of only improving their
// luckiest returns. Classic and solo match traits own their bands; gore keeps its own floor.
const qMin = G.diff ? G.diff.qMin : G.match && !G.net ? (ch.foe?.qMin ?? TUNE.aiQualityMin) : TUNE.aiQualityMin;
if (isAI) q = Math.min(q, qMin + Math.random() * (Math.max(qCap, qMin) - qMin));
if (!isAI && G.mode === 'tennis') {
G.swingSnaps = null; G.rallyNear = null;
@@ -1540,7 +1546,7 @@ function racketAI(rz, dt) {
&& ball.y < CONTACT.maxY && ball.y > CONTACT.minY) {
// ...and the match has its OWN flub base: the duel's 0.2 hands a fifth of all returns away,
// which across a game is an opponent that beats itself.
const flub = (G.match ? TUNE.matchFlub * Math.pow(TUNE.matchFlubKeep, G.match.opp - 1) * (rz.foe?.flub || 1) * wnd.flub
const flub = (G.match ? TUNE.matchFlub * Math.pow(TUNE.matchFlubKeep, matchStep()) * (rz.foe?.flub || 1) * wnd.flub
: TUNE.racketFlub * (1 - TUNE.duelFlubCut * duelSkill()))
// THE READ: a wrong-footed racket reaches the ball late even when the legs got there —
// the surprise ball ADDS whiff on top of the rung's own rate, scaled by how much this