Files
deepgrain-foundry/src/sim/ledger.js
T
44r0n7andClaude Opus 5.5 9937683a2c Faster roof scan and heat pass with identical results (t21)
- The roof is rescanned only in area columns that changed since the last scan: a quiet Huge
  world goes from 4.60 to 1.88 ms per scan (every 20 ticks).
- The heat pass skips react() for solids and powders below their first reaction threshold:
  Huge world digging 2.54 -> 2.34 ms/tick, quiet 1.39 -> 1.18.
- Every suite's output is identical apart from timing lines; seeds make the same worlds.
- test/t_sim_optimizations.js checks the dirty roof against a full scan and the heat loop
  against the reference loop byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 22:18:50 -04:00

55 lines
2.1 KiB
JavaScript

// Milestone checks (the ledger) and the sky roof line used for cooling.
// ---------- Ledger ----------
function checkLedger() {
const done = id => ledger[id];
const mark = id => { if (!ledger[id]) { ledger[id] = tick || 1; emit({ t: 'milestone', id }); } };
if (stats.dug >= 15) mark('dig');
if (seen[FIRE]) { mark('fire'); if (!player.lens) { player.lens = true; } }
if (seen[BRICK] || seen[RBRICK] || seen[BARBR]) mark('brick');
if (seen[CHARCOAL]) mark('charcoal');
if (stats.grown > 0) mark('grow');
if (seen[MCU]) mark('copper');
if (stats.bars > 0) mark('bars');
if (player.bitTier >= 1) mark('bit1');
let anyPower = false, steamOn = false;
for (const mm of machines) if (mm) { if ((mm.type === 'wheel' || mm.type === 'engine') && mm.out > 0.5) anyPower = true; if (mm.type === 'engine' && mm.out > 1) steamOn = true; }
if (anyPower && !POWER_FREE) mark('power');
if (stats.moved >= 300) mark('auto');
if (seen[MGL] || seen[GLASS] || seen[CULLET]) { mark('glass'); player.flask = true; }
if (steamOn && !POWER_FREE) mark('steam');
if (seen[MFE]) mark('iron');
if (player.bitTier >= 2) mark('bit2');
if (seen[MST]) mark('steel');
if (player.bitTier >= 3) mark('bit3');
if (player.tankTier >= 1) mark('tank');
if (depthU(bot.y) > 0.85) mark('deep');
if (stats.sold > 0) mark('sale');
if (ordersDone > 0) mark('order');
if (seen[MBZ] || seen[MBS]) mark('alloy');
if (seen[AGORE] || seen[AUORE] || seen[SILVER] || seen[GOLD]) mark('precious');
if (debt <= 0) mark('claim');
if (earned >= 50000) mark('rich1');
if (earned >= 200000) mark('rich2');
void done;
}
// Topmost non-air cell of each column: air above it can shed heat to the sky.
function updateRoof() {
scanRoof(0, W);
roofDirty.fill(0);
}
function updateDirtyRoof() {
for (let cx = 0; cx < CW; cx++) {
if (!roofDirty[cx]) continue;
scanRoof(cx << 5, Math.min(W, (cx + 1) << 5));
roofDirty[cx] = 0;
}
}
function scanRoof(x0, x1) {
for (let x = x0; x < x1; x++) {
let y = 0;
for (; y < H; y++) { const ph = PH[mat[y * W + x]]; if (ph === PH_SOLID || ph === PH_POWDER || ph === PH_LIQUID) break; }
roofY[x] = y;
}
}