Faces cut into loose piles collapse outward instead of draining column by column (t93)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 22:06:48 -04:00
co-authored by Claude Opus 5.5
parent 6ac5f463aa
commit 84dd8b8d0a
11 changed files with 271 additions and 9 deletions
+15
View File
@@ -555,6 +555,21 @@ above, including:
keeps its chunk awake to retry. Burning fuel beds keep their tuned settling behavior.
Grain stamps, sealed corners, transport barriers and per-chunk random streams still apply.
- **Vacuum-cut loose faces spread while falling (t93 reopened, 2026-10-28).** The owner
reports that stone-only and mixed faces still stand after vacuuming into settled piles.
Sticky-step retries alone do not address the descending column formed by always choosing
straight down first. A falling grain on an exposed vertical face, backed by supported
powder, prefers an open outward diagonal. With at least 12 grains of backing above it
and unmoved support below that backing, it spills across up to eight clear grains and
falls up to eight clear grains. This is a local pressure approximation: the falling
outer column must drain quickly enough to let the body of the pile release. Shallow
faces keep the one-grain step, preserving small heaps and conveyor feeds. Check the
whole horizontal/downward path for occupancy, parts and cleats, including other chunks.
Keep one stamped move per tick and the existing eight-grain worker write halo.
Resting heaps do not enter this path; world generation keeps its recorded settling rules
and seed layouts.
## Ideas not built yet
- **Concrete**, as a stronger wall material from rubble.
+5 -2
View File
@@ -254,10 +254,10 @@ 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 (240 lines)
### src/sim/cells.js (272 lines)
Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove).
- functions: setCell, swapCells, swapCellData, move, enter, enterFree, powder, passable, liquid, liquidSearch, gas, wakeBotPowder, simMove, moveChunk
- variables: SORTP, SORTP_FUEL, LSTEP, LFILM, CORNER_SEAL
- variables: SORTP, SORTP_FUEL, LSTEP, LFILM, CORNER_SEAL, POWDER_FAN
### src/sim/heat.js (266 lines)
Heat: conduction, melting and freezing, reactions, fire and air, steel.
@@ -630,6 +630,7 @@ The frame loop and boot.
- `test/harness.js`: Loads the simulation (the src/sim/ files listed in src/manifest.json, joined in order into one script, the same way build.py joins them) so scenarios can drive it headlessly in Node. Errors point at the real file and line (sim/pipes.js:42), not at the joined script.
- `test/light-cases.js`: Lighting behaviour checks executed by the GPU browser harness.
- `test/light-readback.js`: Read float source channels, including transmittance, from the WGSL light pass.
- `test/pile-cut.js`: Shared Node/browser reproduction: vacuum the foot of settled 60-grain heaps, one stroke per tick.
- `test/play.py`: Play-test in a real browser: mouse, keyboard and a mocked gamepad drive the game; save and continue. Screenshots go to shots/play/ (or the folder given as the first argument). Pixel look unless the second argument is 'smooth'.
- `test/run_all.py`: Run the test suites and report.
- `test/t_bar_stacking.js`: Resting bars snap into pairs of grains and tip off narrow supports.
@@ -668,6 +669,8 @@ The frame loop and boot.
- `test/t_smooth.py`: The smooth look: the WebGPU pass compiles and draws, 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_threads.js`: Shared allocation, checkerboard independence, and real worker-count determinism.
- `test/t_vacuum_collapse.js`: Real nozzle cuts into settled heaps, inline and through the real Node worker pool.
- `test/t_vacuum_collapse.py`: Vacuum cuts in the real pixel frame loop with active browser workers and hardware graphics.
- `test/t_water.js`: Water conservation, settling, ledge pouring, boundaries, pipes and phase changes. Tall worlds keep geothermal heat out of the ponds.
- `test/t_weather.js`: Weather: no more springs; steam rises into clouds and rains back; showers; snow when it is freezing.
- `test/t_world.js`: Trees from acorns, charcoal, brick, density, water/lava/snow/ice, full-bag refunds, drill reach, ballistic blowing, snowy mountains.
+8
View File
@@ -78,6 +78,14 @@ checks waking within eight ticks separately from the probabilistic consumption o
gamepad and world sizes. Screenshots go to
`shots/play/`. Pixel look by default; `python3 test/play.py shots/play smooth` uses the smooth
look.
- `test/t_vacuum_collapse.py` cuts settled stone and mixed heaps with one normal-width
vacuum stroke per simulation tick in the real frame loop. It uses the shared
`test/pile-cut.js` fixture, requires actual helper dispatch (forced for this small world),
checks both faces within 180 ticks, and saves time-series pixel screenshots in `shots/`.
`test/t_vacuum_collapse.js` uses the same cuts inline and with Node helpers, including
bot-near/far, grain conservation, equal material bytes and forced-awake resting stability.
It also checks a broad 120-grain wall within 600 ticks and a spill stopped by cleats
across chunk edges, where the source chunk's one-grain barrier flag is clear.
- `test/t_smooth.py` checks WebGPU smooth shapes, seams, joins, fog and the thermal lens.
- `test/t_gpu_golden.py` compares 28 cropped frozen reference PNGs (384x288, under
`test/fixtures/golden/`) against WebGPU: renderer, joins, sky and four light scenes,
+53
View File
@@ -5,6 +5,59 @@ note or request it was for, what changed, the files touched, the tests run, and
open or not verified. Keep each entry short; the git history has the details.
## 2026-10-28: t93 reopened, vacuum-cut faces drain in columns (Codex)
- Read AGENTS, the t93 task/log and 807217b; inspected both new owner screenshots.
The remaining reproduced cause is straight-down movement taking priority over outward
fall: an exposed edge stays a descending column, blocking the next column's diagonal
exits. This is a movement/scan-order bottleneck, not lost wakes in this reproduction.
`setCell` wakes the cut; worker wakes merge each checkerboard pass. A radius-6 vacuum,
one call per tick into a settled 60-grain RSTONE heap, leaves a 39-grain cliff; after
120 ticks it is still 18, with exactly the same series when all chunks are forced awake.
RSTONE already has STICK=1. Inline and actual Node helpers agree, bot near or far.
- Added outward downward movement only for a falling exposed vertical face backed by
supported powder. Retain one downward step per tick, occupancy, parts, barriers and
burning-grain guard. Resting heaps do not enter this path. `POWDER_FAN` goes to workers
and is disabled during the existing legacy worldgen settle to preserve all seed hashes.
Rejected a horizontal-step experiment (forced-awake creep) and a broad falling-edge
rule (spread free-falling blocks too far); no old test expectation was changed.
- New shared `test/pile-cut.js`: two 60-grain triangular heaps, 600 settling ticks,
stone and stone/copper ore/iron ore/dirt, then actual radius-6 vacuum strokes.
New Node suite passes 40 checks: cuts inline/2 helpers, near/far bot, conservation,
exact inline/helper material bytes, initially stable heaps and 600 forced-awake
stable ticks afterward. Browser suite uses isolated HTTP, real NVIDIA Blackwell GPU,
real frame loop and two helpers with confirmed dispatch (small fixture forces dispatch).
Verdict is recorded at exactly tick 180. Control with face spreading disabled:
cliff stone/mixed 33/32 at cut end, 14/13 at 120, 8/5 at 180; browser assertion fails.
Fixed browser reaches <=2 by 120 and passes at 180. Earlier Node red run fails eight
collapse checks (its mixed fixture included clay); existing clay collapse checks pass.
- Full `python3 test/run_all.py --browser`: ALL PASSED, 34 headless + 9 browser suites,
including collapse 17, threads 12, vacuum 40, gameplay 361 and browser vacuum 1.
Log: `/tmp/t93b-all-browser.log`. No existing test was weakened. Browser regression
is included in the suite runner. Original seed hashes and liquid-sinking checks pass.
- Saved and inspected `shots/t93b-before.png` (control at cut end) and
`shots/t93b-after.png` (fixed after 180 ticks): vertical cut faces become slopes.
Fixed series: `shots/t93b-time-{0,60,120,180}.png`; matching control series:
`shots/t93b-control-time-{0,60,120,180}.png`. Browser control log:
`/tmp/t93b-browser-matching-control.log`. Small initial browser passes stayed inline
despite a pool existing; final regression requires actual `simPool.activeMax > 0`.
- Requested idle profile, real GPU, no concurrent tests:
`python3 tools/perf.py --scenes settled,heat --looks pixel --zooms 6 --compare tools/perf-after-t88.json`.
Rule-disabled control -> final total ms/tick: settled 1.9855 -> 2.0226 (+1.9%),
heat 2.7027 -> 2.7734 (+2.6%). Against historical t88: +12.0%/+5.7%.
Movement ms/tick 0.9639 -> 0.9818 / 1.3481 -> 1.3885; unchanged heat work also
varies 0.9412 -> 0.9593 / 1.2724 -> 1.3019. End awake counts identical, 425/494.
These timings show small run-to-run differences, not exact equality; historical settled
time remains over the profiler's 10% comparison threshold. Evidence:
`/tmp/t93b-idle-control.json`, `/tmp/t93b-idle-final.json`, `/tmp/t93b-idle-summary.log`.
An earlier control profile overlapped headless checks and was excluded from this comparison.
- Files: `src/sim/cells.js`, `src/sim/workers.js`, `src/sim/worldgen.js`,
`test/pile-cut.js`, `test/t_vacuum_collapse.js`, `test/t_vacuum_collapse.py`,
`test/run_all.py`, `docs/DESIGN.md`, `docs/TESTING.md`, generated project map,
t93 task and this log. No commit. Owner playtesting of their larger worlds remains open.
## 2026-10-28: t92 keep pass-through, restore original loose-grain behaviour (Codex)
- Read the 7293787 then dadf62a t92 history and original drill in 90f2d3f. Restored the