Stop calling "passed you" while the ball is still on its way to him
Oliver's v366 log: a LOST "passed you" with no swing. The match gave the CPU the point the moment its ball crossed 0.3 m behind the baseline — a line from when the player stood inside it. Since step 1 he waits up to 2.2 m behind the line for deep balls, and a ball going by ~1.5 m beside him only enters his reach just in front of him, so the point was called before it was ever playable. In the match "past you" now means past his reach. The swing log's hits also say whether the timing was early or late. v367. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5bbde720ad
commit
dfdb699f9d
4 files changed
+73
-4
No files matched your search
@@ -1397,6 +1397,46 @@ test('THE SWING LOG writes in the match too: a whiff, a hit with its tap, and wh
|
||||
} finally { TUNE.autoAssist = assist; }
|
||||
});
|
||||
|
||||
test('a deep ball the player waits for BEHIND his baseline is still his to hit — not "passed you"', () => {
|
||||
// Oliver's v366 log vs THE BRUTE: "LOST passed you" with no swing. The match called the point the
|
||||
// moment its ball crossed 0.3 m behind the baseline — but since step 1 the player waits up to
|
||||
// rallyBehind behind it for a deep, kicking ball, so the ball was taken away on its way to him.
|
||||
const flub = TUNE.matchFlub; TUNE.matchFlub = 0;
|
||||
const assist = TUNE.autoAssist; TUNE.autoAssist = 1.15;
|
||||
try {
|
||||
startMatch(); G.interlude.introT = 0;
|
||||
const zb = oppOf(); zb.swingCool = 999;
|
||||
G.phase = 'rally'; G.wasServe = false; G.missLog.length = 0;
|
||||
Object.assign(P, { x: 0, z: COURT.L + 1.8, swingT: -1, tgt: null, vx: 0, vz: 0 });
|
||||
TUNE.autoAssist = 0; TUNE.matchAssist = 0; // he holds his deep mark: the ball comes to him
|
||||
const v = solveShot(0, 1, 1, 1.25, COURT.L - 2.2, 27, TUNE.gravity * 1.6); // deep, a little wide, heavy topspin
|
||||
Object.assign(ball, { active: true, scored: false, lastHit: 'O', bounces: 0, rx: null, spin: 1.15, soft: false,
|
||||
x: 0, y: 1, z: 1, vx: v.vx, vy: v.vy, vz: v.vz, g: TUNE.gravity * 1.6 });
|
||||
let crossed = false, lift = -1;
|
||||
for (let i = 0; i < 3 * 60 && ball.active && ball.lastHit === 'O'; i++) {
|
||||
if (lift < 0 && ringCue()?.gold) lift = i + 6;
|
||||
if (i === lift) keyPressed('Space', 0.1);
|
||||
update(DT);
|
||||
if (ball.z > COURT.L + 0.3) crossed = true;
|
||||
}
|
||||
assert.ok(crossed, 'the ball really did cross the old line');
|
||||
assert.equal(ball.lastHit, 'P', 'and he returned it: ' + JSON.stringify(G.missLog.map(e => e.result + ' ' + e.reason)));
|
||||
// ...while a ball that truly gets past him is still called, and says whether he swung
|
||||
TUNE.autoAssist = assist; TUNE.matchAssist = 1.15;
|
||||
freshSplatter(); startMatch(); G.interlude.introT = 0;
|
||||
oppOf().swingCool = 999;
|
||||
G.phase = 'rally'; G.wasServe = false; G.missLog.length = 0;
|
||||
Object.assign(P, { x: 0, z: 23, swingT: -1 });
|
||||
const w = solveShot(0, 1, 1, 3.9, COURT.L - 3, 28); // wide, past him
|
||||
Object.assign(ball, { active: true, scored: false, lastHit: 'O', bounces: 0, rx: null, spin: 1, soft: false,
|
||||
x: 0, y: 1, z: 1, vx: w.vx, vy: w.vy, vz: w.vz, g: TUNE.gravity });
|
||||
TUNE.autoAssist = 0; TUNE.matchAssist = 0; // a statue: it must go by
|
||||
for (let i = 0; i < 3 * 60 && G.phase === 'rally'; i++) update(DT);
|
||||
const lost = G.missLog.find(e => e.result === 'LOST');
|
||||
assert.ok(lost && /never swung, it came within/.test(lost.reason), 'the verdict says how close it came: ' + (lost && lost.reason));
|
||||
} finally { TUNE.matchFlub = flub; TUNE.autoAssist = assist; TUNE.matchAssist = 1.15; }
|
||||
});
|
||||
|
||||
test('rally depth: deep by default, mistiming lands it SHORTER, never longer', () => {
|
||||
// the only out a rally ball may find is wide — depth must never put one past the baseline
|
||||
startMatch(); G.interlude.introT = 0;
|
||||
|
||||
Reference in new issue
Block a user