// Optimized paths must match the full roof scan and the original heat loop exactly. const fs = require('fs'); const { load, suite, flatWorld } = require('./harness'); const { run } = load(); const { check, done } = suite(); run(fs.readFileSync(__dirname + '/fixtures/heat-chunk.js', 'utf8')); // Partial areas and changes at area boundaries, including material appearing in empty sky. flatWorld(run, 99, 97, 80); run('RS = 123; bot.x = 45; bot.y = 30;'); run(` const originalWeatherTick = weatherTick; weatherTick = function () { if (tick % 20 === 1) { const roof = roofY.slice(); updateRoof(); if (!roof.every((v, x) => v === roofY[x])) globalThis.__roofMiss = (globalThis.__roofMiss || 0) + 1; } originalWeatherTick(); }; `); for (let k = 0; k < 200; k++) run(` setCell((12 + ${k} % 60) * W + (${k} * 31 % W), ${k} % 3 ? WATER : EMPTY, 18, 0); simTick(); `); check('scheduled roof matches a full scan at area edges', !run('globalThis.__roofMiss'), run('globalThis.__roofMiss')); run('weatherTick = originalWeatherTick;'); // Every material, threshold neighbours, fractional temperatures, burning, cold neighbours, // alternating heat scales, and partial areas exercise both random calls and Float32 stores. const snapshot = () => run(`JSON.stringify({ arrays: [mat, temp, life, flags, hot, hotLvl, part, digp, seen].map(a => Array.from(new Uint8Array(a.buffer))), RS, stats, EV, brokenMachines })`); const setup = () => { flatWorld(run, 67, 65, 60); run(`{ RS = 456; seen.fill(0); EV.length = 0; stats.ignitions = 0; brokenMachines = []; const ts = [-30, -0.5, 0, 0.5, 18, 97, 100, 260, 380, 600, 880, 1085, 1300, 1530, 1900]; for (let i = 0; i < N; i++) { const m = (i * 37) % NMAT; mat[i] = m; temp[i] = ts[i % ts.length] + ((i % 3) - 1) * 0.001; life[i] = i % 256; flags[i] = i % 23 === 0 && FUEL[m] ? F_BURN : 0; } hot.fill(6); hot[0] = 0; hotLvl.fill(2); updateRoof(); }`); }; for (const scale of [1, 4]) { setup(); run(`for (let c = 1; c < NCH; c++) referenceHeatChunk(c, ${scale});`); const expected = snapshot(); setup(); run(`for (let c = 1; c < NCH; c++) heatChunk(c, ${scale});`); check('heat matches original bytes and random state at scale ' + scale, snapshot() === expected); } setup(); run('const optimizedHeatChunk=heatChunk;heatChunk=referenceHeatChunk;heatPass();'); const passExpected=snapshot(); run('heatChunk=optimizedHeatChunk;'); setup();run('heatPass();'); check('four-pass heat matches the unoptimized oracle byte for byte',snapshot()===passExpected); done();