The opponent shows up, and the death loop dies
"still very weak and slow opponent. it also spawns at places where it is impossible to react to my serve. so i win like always. in the cases i dont win there is a bug. when trying to serve after i got hurt i get hurt again and again until i die". The death loop was G.serveNum. Tennis's pointTo is the only thing that ever reset it, and the match bypasses pointTo entirely — so the first fault of the match armed "second serve" permanently, and every missed serve after it was a double fault, a point, and blood, repeating to death. Exactly the spiral a rattled player serves into. matchReady(), the match's own point boundary, resets it now; a regression pins it. The receiver starts every point on its mark: matchReady drops it onto the exact receiver position the tennis branch computes for O, deuce/ad mirrored, instead of a random spawn x or wherever the last rally left it. An opponent that cannot reach the serve is not weak, it is absent. And the base opponent is a player now: matchSpeedBase 1.4 (the duel's 2.8m/s lumber was tuned for one sudden-death point), matchFlub 0.08 (0.2 gives away a fifth of all returns). Measured with the same autopilot that previously won seven straight games: it now loses the match. Possibly too hot — the two dials are named, Oliver's thumb decides. 40 tests, 15 seeds clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea6e50f8f8
commit
f67411e330
6 files changed
+83
-14
No files matched your search
@@ -81,7 +81,7 @@ globalThis.ResizeObserver = class { observe() {} disconnect() {} };
|
||||
globalThis.getComputedStyle = () => ({ paddingTop: '0' });
|
||||
|
||||
// ---- game modules (real code) ----------------------------------------------
|
||||
const { G, P, score, ball, setupPoint } = await import('./src/state.js');
|
||||
const { G, P, O, score, ball, setupPoint } = await import('./src/state.js');
|
||||
const { update, forceZombies, splatPoint, restartRun, flickTarget } = await import('./src/gameplay.js');
|
||||
const { startDuel, resolveInterlude, startBossFight, endBossFight, startDrill: _startDrill, endDrill, startMatch: _startMatch, endMatch } = await import('./src/beats.js');
|
||||
// the drill's first-sight modal freezes the world (that is what modals do) — dismiss it the way a
|
||||
@@ -557,11 +557,36 @@ test('a match ball never wounds the body: the score is the only way through', ()
|
||||
assert.equal(zb.hp, zb.hpMax, 'and unwounded — "killing by smashing" is out of the match');
|
||||
});
|
||||
|
||||
test('THE DEATH LOOP: a fault before a lost point must not arm second-serve forever', () => {
|
||||
// The match bypasses tennis's pointTo — the only thing that ever reset G.serveNum — so the first
|
||||
// fault of the match made EVERY later missed serve a double fault: a point, blood, and repeat
|
||||
// until dead. Oliver hit it: "when trying to serve after i got hurt i get hurt again and again
|
||||
// until i die".
|
||||
startMatch();
|
||||
G.serveNum = 2; // a fault has burned the first serve
|
||||
resolveInterlude('O'); // the point is lost (double fault, passing shot, whatever)
|
||||
assert.equal(G.serveNum, 1, 'the NEXT point starts on a first serve');
|
||||
resolveInterlude('P');
|
||||
assert.equal(G.serveNum, 1, '...whoever won it');
|
||||
});
|
||||
|
||||
test('every point starts with the receiver on its mark', () => {
|
||||
startMatch();
|
||||
const rz = oppOf();
|
||||
rz.x = 6; rz.z = 12; // stranded mid-court by the last rally
|
||||
resolveInterlude('P');
|
||||
assert.ok(Math.abs(rz.x) < 3 && rz.z <= 1.5,
|
||||
'reset to the receiver spot, not wherever the rally left it: x=' + rz.x.toFixed(1) + ' z=' + rz.z.toFixed(1));
|
||||
assert.equal(rz.x, O.x, 'on the exact mark the tennis branch computed for the receiver');
|
||||
});
|
||||
|
||||
test('the ladder escalates in speed and reliability, not in hp', () => {
|
||||
// pure arithmetic on the knobs racketAI reads — pinned so a future tuning pass cannot silently
|
||||
// flatten the ladder again
|
||||
assert.ok(TUNE.matchSpeedBase > 1, 'opponent one is already quicker than the duel lumber');
|
||||
assert.ok(TUNE.matchSpeedPer > 0, 'each opponent is faster');
|
||||
assert.ok(TUNE.matchFlubKeep < 1, 'and whiffs less');
|
||||
assert.ok(TUNE.matchFlub < TUNE.racketFlub, 'the match whiffs less than the duel from the start');
|
||||
assert.ok(TUNE.matchFlubKeep < 1, 'and less again per rung');
|
||||
});
|
||||
|
||||
test('a game won heals, so a clean player can go the distance', () => {
|
||||
|
||||
Reference in new issue
Block a user