One rule for a piece's direction variant: remove pieceV (t81)

This commit is contained in:
2026-10-29 21:53:56 -04:00
parent daeb3b2238
commit 78eeb86171
4 changed files with 49 additions and 4 deletions
+1
View File
@@ -671,6 +671,7 @@ The frame loop and boot.
- `test/t_nozzle.js`: Blowing aims within the nozzle's reach, with room for the brush and settling. - `test/t_nozzle.js`: Blowing aims within the nozzle's reach, with room for the brush and settling.
- `test/t_perf.js`: Profiling fixtures start in the same state after previous scenes and warm-up ticks. - `test/t_perf.js`: Profiling fixtures start in the same state after previous scenes and warm-up ticks.
- `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_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_piece_variants.js`: The build plan and direct variant queries share one direction/material rule.
- `test/t_pile_collapse.js`: Tall loose faces release together; supported heaps stop moving, including when revisited. - `test/t_pile_collapse.js`: Tall loose faces release together; supported heaps stop moving, including when revisited.
- `test/t_pipes.js`: Pipes, pumps and outlets move liquids; the Grinder grinds waste rock for trace ore. - `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_racks.js`: Rack intake, FIFO storage, gate, removal and saved-state validation.
+11
View File
@@ -4,6 +4,17 @@ 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 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. open or not verified. Keep each entry short; the git history has the details.
## 2026-10-29: t81 shared piece direction variants (Codex)
- `pieceV` accepts a direction and resolved code; `dragPlan` calls it for previews and
placement. Default queries keep the selected direction. No world generation changes.
- Files: src/ui/selection.js, test/t_piece_variants.js, docs/PROJECT_MAP.md, tasks/t81*.
- New checks: 29 failures before, all 72 pass after. All 41 headless suites pass;
all 40 existing suite outputs match before/after, ignoring timing lines (empty
/tmp/t81-determinism.diff). Pixel test/play.py passes with no console errors; inspected
shots/t81-play/04-{blocks,diagonal-screws}.png. Sandbox WebGPU was unavailable;
host GPU rerun passed. Nothing left open; t81 ready for owner review.
## 2026-10-29: t96 rebuilt: lakes are bowls filled to their spill level (Claude) ## 2026-10-29: t96 rebuilt: lakes are bowls filled to their spill level (Claude)
- Owner: the round-4 bank was a flat, unnatural ramp; fix lake generation properly instead of - Owner: the round-4 bank was a flat, unnatural ramp; fix lake generation properly instead of
+4 -4
View File
@@ -82,16 +82,16 @@ function setBrush(d) {
} }
// The block variant a piece is placed with: wall material, or direction (a filter's // The block variant a piece is placed with: wall material, or direction (a filter's
// materials and mode travel separately, as GAME.filterCfg) // materials and mode travel separately, as GAME.filterCfg)
function pieceV(P) { function pieceV(P, dir = GAME.pieceDir[P.id] || 0, code = pieceCode(P)) {
if (isWall(P.code)) return GAME.wallMat; if (isWall(P.code)) return GAME.wallMat;
if (P.filter) return filterVariant(pieceCode(P), (GAME.pieceDir[P.id] || 0) << 7); if (P.filter) return filterVariant(code, dir << 7);
return GAME.pieceDir[P.id] || 0; return dir;
} }
// One drag for the build tool and its preview: code, direction, variant, blocks, and the planned // One drag for the build tool and its preview: code, direction, variant, blocks, and the planned
// blocks the join rule sees. A line that joins one block up or down snaps there (joinSnap). // blocks the join rule sees. A line that joins one block up or down snaps there (joinSnap).
function dragPlan(P, a, b, shift) { function dragPlan(P, a, b, shift) {
const code = pieceCode(P, b), dd = a ? dragDirFor(P, a, b) : -1, dir = dd >= 0 ? dd : (GAME.pieceDir[P.id] || 0); const code = pieceCode(P, b), dd = a ? dragDirFor(P, a, b) : -1, dir = dd >= 0 ? dd : (GAME.pieceDir[P.id] || 0);
const v = isWall(P.code) ? GAME.wallMat : P.filter ? filterVariant(code, dir << 7) : dir; const v = pieceV(P, dir, code);
let cells = !a ? [[b.bx, b.by]] : shift && !lineOnly(code) ? blockRect(a.bx, a.by, b.bx, b.by) let cells = !a ? [[b.bx, b.by]] : shift && !lineOnly(code) ? blockRect(a.bx, a.by, b.bx, b.by)
: blockLine(a.bx, a.by, b.bx, b.by, isWall(code) || isSlopeBelt(code) || code === BP_SCREW); : blockLine(a.bx, a.by, b.bx, b.by, isWall(code) || isSlopeBelt(code) || code === BP_SCREW);
const snap = lineOnly(code) ? joinSnap(code, v, cells) : 0; const snap = lineOnly(code) ? joinSnap(code, v, cells) : 0;
+33
View File
@@ -0,0 +1,33 @@
// The build plan and direct variant queries share one direction/material rule.
const { load, suite, flatWorld } = require('./harness');
const fs = require('fs');
const { run } = load(), { check, done } = suite();
flatWorld(run, 256, 224, 208);
run(fs.readFileSync('src/ui/selection.js', 'utf8'));
run(fs.readFileSync('src/ui/actions.js', 'utf8'));
run(`globalThis.GAME = { pieceDir: {}, pieceShape: {}, wallMat: RSTONE };
globalThis.aimBlock = () => ({ bx: 20, by: 20 });`);
for (const id of ['wall', 'belt', 'filter', 'screw', 'gate', 'pump']) {
const dirs = run(`PIECE_BY_ID.${id}.dirs?.length || 1`);
for (let dir = 0; dir < dirs; dir++) {
run(`GAME.pieceDir.${id} = ${(dir + 1) % dirs};`);
const expected = id === 'wall' ? run('RSTONE') : id === 'filter' ? dir << 7 : dir;
check(`${id} explicit direction ${dir} gives its stored variant`,
run(`pieceV(PIECE_BY_ID.${id}, ${dir})`) === expected);
}
}
for (const id of ['wall', 'belt', 'filter', 'screw', 'gate', 'pump']) {
for (const [dx, dy] of [[0, 0], [4, 0], [-4, 0], [0, 4], [0, -4], [4, -4], [4, 4], [-4, 4], [-4, -4]]) {
run(`GAME.pieceDir.${id} = 0; GAME.drag = { bx: 20, by: 20 };`);
// The endpoint intentionally differs from aimBlock(), including opposite filter slopes.
check(`${id} plan ${dx},${dy} keeps the direction and variant rule`, run(`(() => {
const P = PIECE_BY_ID.${id}, b = { bx: ${20 + dx}, by: ${20 + dy} };
const plan = dragPlan(P, GAME.drag, b, false);
const code = pieceCode(P, b), dd = dragDirFor(P, GAME.drag, b), dir = dd >= 0 ? dd : 0;
const expected = isWall(P.code) ? GAME.wallMat : P.filter ? filterVariant(code, dir << 7) : dir;
return plan.code === code && plan.dir === dir && plan.v === expected &&
pieceV(P, dir, code) === expected && [...plan.planned.values()].every(([c, v]) => c === code && v === expected);
})()`));
}
}
done();