The weather: evening sun, rain and leaves over any court, coming and going (v390)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5.5 committed 2026-10-16 15:52:52 +02:00
1 parent f18680d497
commit af8cd7a513
7 files changed
+202 -1

No files matched your search

+24
View File
@@ -90,6 +90,7 @@ globalThis.getComputedStyle = () => ({ paddingTop: '0' });
const state = await import('./src/state.js');
const { G, P, O, score, ball, setupPoint } = state;
const { ringCue, predictLanding, solveShot, update, forceZombies, startGore, splatPoint, restartRun, leaguePace, duelSkill, tinLadder, deliverTin, peerK: _peerK, legLevel: _legLevel, winLevel: _winLevel, assistK: _assistK, flickTarget, flatCount, swayOf, keyPressed, classicGame, serveApexY, assistK, rallyFeel, barrelGap, machCap, hitServe, cheer, inCourt } = await import('./src/gameplay.js');
const weather = await import('./src/weather.js');
const { startDuel, resolveInterlude, startBossFight, endBossFight, startDrill: _startDrill, endDrill, startMatch: _startMatch, endMatch, FALL_LEN, startNetVs, endNetVs, startStory, startStoryChapter, startHorde, storyUI } = await import('./src/beats.js');
const { mirror, netMsg, netTest, netTick, netAgain } = await import('./src/net.js');
// the drill's first-sight modal freezes the world (that is what modals do) — dismiss it the way a
@@ -1310,6 +1311,29 @@ test('a groundstroke a little off PERFECT is a little worse, not a weak ball (no
} finally { TUNE.autoAssist = assist; }
});
test('THE WEATHER: one soft sky that comes and goes, never snaps, and never sets the sun on the night court', () => {
const { SKY, tickSky } = weather;
Object.assign(SKY, { kind: null, k: 0, target: 0, nextT: 0 });
const dt = 0.1, maxStep = dt / TUNE.skyFade + 1e-9;
let clear = 0, total = 0, seen = new Set(), prev = { ...SKY };
for (let i = 0; i < 2 * 3600 / dt; i++) {
const court = i < 3600 / dt ? 'clay' : 'gloom';
tickSky(dt, court);
assert.ok(SKY.k >= 0 && SKY.k <= 1, 'intensity stays in range');
assert.ok(Math.abs(SKY.k - prev.k) <= maxStep, 'no snap: ' + prev.k + ' -> ' + SKY.k);
if (SKY.kind !== prev.kind) assert.ok(prev.k < 0.02, 'the kind only changes under a clear sky');
if (court === 'gloom' && i > 3600 / dt + 200) assert.ok(!(SKY.kind === 'sun' && SKY.k > 0), 'no sunset at night');
if (SKY.k > 0.05) seen.add(SKY.kind); else clear++;
total++; prev = { ...SKY };
}
assert.deepEqual([...seen].sort(), ['leaves', 'rain', 'sun'], 'all three come round');
assert.ok(clear / total > 0.25 && clear / total < 0.8, 'and sometimes nothing at all: clear ' + (clear / total).toFixed(2));
TUNE.weather = 'rain';
for (let i = 0; i < 40 / dt; i++) tickSky(dt, 'clay');
assert.equal(SKY.kind, 'rain'); assert.equal(SKY.k, 1, '?weather=rain forces it in');
TUNE.weather = 'auto';
});
test('THE BURNING BALL: a perfect strike marks its ball for the flight, and the reply clears it', () => {
// render reads ball.hotT (the white-hot impact frame, the halo, the gold streak); the state is here
const assist = TUNE.autoAssist; TUNE.autoAssist = 1.15;