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>
This commit is contained in:
2026-10-24 22:18:50 -04:00
co-authored by Claude Opus 5.5
parent d3fc1d2cbc
commit f57bdd6084
9 changed files with 160 additions and 11 deletions
+8 -7
View File
@@ -216,25 +216,25 @@ Starter furnace designs and the milestone list shown in the notebook.
- functions: smelterBlueprint
- variables: STARTER_DESIGNS, MILESTONES
### src/sim/world.js (98 lines)
### src/sim/world.js (101 lines)
World state: the per-cell typed arrays, alloc(), ambient temperature by depth, waking.
- functions: emit, bagCap, discover, alloc, depthU, depthY, computeAmbient, fillNoise, wakeXY, wakeHeatXY, wakeIdx, wakeHeatIdx
- variables: W, H, N, CW, CH, NCH, mat, temp, life, flags, stamp, part, mach, digp, noiseB, airS, netId, isPow, occ, surfY, dirtY, graniteY, basaltY, magmaY, roofY, AMB, worldSeed, surfBase, underD, shallowD, lapse, BW, BH, NB, blockP, blockV, ents, bgm, flyers, ghostBlocks, ghostMolds, awake, hot, hotLvl, powderArea, tick, tickStamp, machines, molds, nets, pcells, powerDirty, beltL, beltR, tubeLists, brokenMachines, ghostMachines, ghostBlocked, EV, bot, bag, bagTotal, player, seen, ledger, stats
- variables: W, H, N, CW, CH, NCH, mat, temp, life, flags, stamp, part, mach, digp, noiseB, airS, netId, isPow, occ, surfY, dirtY, graniteY, basaltY, magmaY, roofY, AMB, worldSeed, surfBase, underD, shallowD, lapse, BW, BH, NB, blockP, blockV, ents, bgm, flyers, ghostBlocks, ghostMolds, awake, hot, hotLvl, powderArea, roofDirty, tick, tickStamp, machines, molds, nets, pcells, powerDirty, beltL, beltR, tubeLists, brokenMachines, ghostMachines, ghostBlocked, EV, bot, bag, bagTotal, player, seen, ledger, stats
### src/sim/fog.js (52 lines)
Exploration only: never changes grains or the random stream.
- functions: fogAlloc, fogMark, fogSeen, fogInit, fogLook, fogRevealAround, fogRevealAll
- variables: FOG, FOG_SENSE, FOG_SENSE_FADE, fog, FW, FH
### src/sim/cells.js (206 lines)
### src/sim/cells.js (207 lines)
Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove).
- functions: setCell, swapCells, move, enter, powder, passable, liquid, gas, wakeBotPowder, simMove
- variables: SORTP, SORTP_FUEL, LSTEP, LFILM
### src/sim/heat.js (246 lines)
### src/sim/heat.js (265 lines)
Heat: conduction, melting and freezing, reactions, fire and air, steel.
- functions: curAir, airflowAt, alloyMix, airy, hasO2, condPair, heatPass, heatChunk, neighborDir, react, char, quench, burningNear, burn, steelCheck
- variables: POROUS, SOIL, HOTLIQ, ALLOY
- variables: POROUS, SOIL, HOTLIQ, REACT_MIN, ALLOY
### src/sim/machines.js (148 lines)
Machines: the power network, footprints, placing and removing machines.
@@ -316,9 +316,9 @@ The bot: movement and collision with the world.
- functions: botBlocked, botOverlapSolid, botSlide, botStep
- variables: SLIDE_MAX, SLIDE_STEP
### src/sim/ledger.js (43 lines)
### src/sim/ledger.js (54 lines)
Milestone checks (the ledger) and the sky roof line used for cooling.
- functions: checkLedger, updateRoof
- functions: checkLedger, updateRoof, updateDirtyRoof, scanRoof
### src/sim/weather.js (87 lines)
Weather: clouds from steam, rain and snow, and the world water count.
@@ -475,6 +475,7 @@ The frame loop and boot.
- `test/t_physics.js`: Sand and other powders, molten metal and gases: heaps, sorting, sinking, setting, rising and fading. Water has its own suite (t_water.js). Tall worlds keep geothermal heat out of the way.
- `test/t_pipes.js`: Pipes, pumps and outlets move liquids; the Grinder grinds waste rock for trace ore.
- `test/t_racks.js`: Rack intake, FIFO storage, gate, removal and saved-state validation.
- `test/t_sim_optimizations.js`: Optimized paths must match the full roof scan and the original heat loop exactly.
- `test/t_smooth.py`: The smooth look: the WebGL pass compiles, draws, falls back cleanly, and the thermal lens still works.
- `test/t_stone.js`: Uses for waste rock and sand: glass bricks from a fan furnace, the Saw, the silo and builders' orders.
- `test/t_water.js`: Water conservation, settling, ledge pouring, boundaries, pipes and phase changes. Tall worlds keep geothermal heat out of the ponds.
+17
View File
@@ -4,6 +4,23 @@ What agents have done, newest first. Add an entry for every piece of work: the d
note or request it was for, what changed, the files touched, the tests run, and anything left
open or not verified. Keep each entry short; the git history has the details.
## 2026-10-24: t21 phase 3: speed-ups that change nothing (Claude Code, Codex)
- Profiled a Huge world (6144x2048) headless and in the browser. After a load every area is
awake: 8-15 ms/tick for the first 600 ticks, settling to about 0.7 ms/tick after 3 minutes. In
the browser, drawing is cheap; the full roof scan every 20 ticks was the largest single item.
- Kept: `updateDirtyRoof()` (`src/sim/ledger.js`) rescans only area columns marked by
`wakeXY`/`wakeHeatXY`/`simMove`/`heatChunk` (`roofDirty`); `updateRoof()` is still the full scan
for setup code. Quiet Huge world 4.60 -> 1.88 ms per scan, digging 4.67 -> 3.48.
`heatChunk` skips `react()` for solids and powders below their first reaction threshold
(`REACT_MIN`). Huge, ms/tick: digging 2.54 -> 2.34, quiet 1.39 -> 1.18.
- Reverted (no consistent gain): inlining `condPair`, one shared part rule for `enter`/`passable`.
- `test/t_sim_optimizations.js`: the dirty roof matches a full scan; `heatChunk` matches the
reference loop in `test/fixtures/heat-chunk.js` byte for byte, random state included (catches a
reaction added to `react()` but not to `REACT_MIN`).
- Every suite's output identical before and after apart from timings; seeds 777 and 4242
generate the same worlds. `run_all.py --browser` ALL PASSED.
## 2026-10-24: t21: piles near the bot sort quickly (Claude Code, Codex)
- Owner: "a pile should sort when the player is nearby. the sorting shouldnt take long anyway."