Strengthen final-league placement and returns

This commit is contained in:
wuwi committed 2026-09-04 09:11:12 +02:00
1 parent bfc70d7388
commit e3faeb0a3a
5 files changed
+101 -8

No files matched your search

+10 -4
View File
@@ -1444,11 +1444,13 @@ function trySwing(ch, isAI, qCap = TUNE.aiQualityMax) {
// finger is usually still down at contact, and the vector under it NOW is the aim the player
// means — the released flickAim only carries it when the ball arrives after the finger lifted.
const flick = isAI ? null : (G.swipe || takeFlickAim());
// SMART AIM (G.diff.smart, classic difficulty): with this probability the CPU plays the OPEN
// SMART AIM (classic difficulty or the solo match foe): with this probability the CPU plays the OPEN
// COURT — the corner away from where you stand — instead of rolling a random lane. Random aim
// sends a third of everything straight back to your racket; hunting the open corner is what
// makes a hard CPU feel like it is PLAYING you. ax is an absolute court lane (see doHit).
const smart = isAI && G.diff && Math.random() < (G.diff.smart || 0);
const smartChance = G.diff ? (G.diff.smart || 0) : G.match && !G.net ? (ch.foe?.smart || 0) : 0;
// Keep the old random sequence for classic and for foes without smart aim.
const smart = isAI && (G.diff || smartChance) && Math.random() < smartChance;
const aim = isAI
? { ax: smart ? (P.x > 0.6 ? -1 : P.x < -0.6 ? 1 : (Math.random() < 0.5 ? -1 : 1))
: [ -1, 0, 1 ][Math.floor(Math.random() * 3)],
@@ -1545,8 +1547,12 @@ function racketAI(rz, dt) {
// body had actually learned. The champion's near-zero flub is exactly what this opens.
+ (G.match && G.match.surprised ? TUNE.surpFlub * learnK(rz) : 0);
if (Math.random() < flub) rz.swingCool = 0.5; // whiff — it hesitates (rarer per rung of the ladder)
else { rz.swingT = TUNE.swingWindup + TUNE.swingWindow / 2;
trySwing(rz, true, TUNE.racketQMax + TUNE.duelQBonus * duelSkill()); rz.swingT = -1; rz.swingCool = 0.3; }
else {
const qCap = G.match && !G.net ? (rz.foe?.qMax ?? TUNE.racketQMax)
: TUNE.racketQMax + TUNE.duelQBonus * duelSkill();
rz.swingT = TUNE.swingWindup + TUNE.swingWindow / 2;
trySwing(rz, true, qCap); rz.swingT = -1; rz.swingCool = 0.3;
}
// the lean is SPENT at the racket, either way — matchReady clears it when a point ends unmet
if (G.match) G.match.surprised = G.match.expected = false;
}