From 78eeb86171263030ebf3b2a1da0322e90bd2e419 Mon Sep 17 00:00:00 2001 From: 44r0n7 <44r0n7+gitea@pm.me> Date: Thu, 29 Oct 2026 21:53:56 -0400 Subject: [PATCH] One rule for a piece's direction variant: remove pieceV (t81) --- docs/PROJECT_MAP.md | 1 + docs/agent-log.md | 11 +++++++++++ src/ui/selection.js | 8 ++++---- test/t_piece_variants.js | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 test/t_piece_variants.js diff --git a/docs/PROJECT_MAP.md b/docs/PROJECT_MAP.md index 9dba3b9..e1005f3 100644 --- a/docs/PROJECT_MAP.md +++ b/docs/PROJECT_MAP.md @@ -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_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_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_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. diff --git a/docs/agent-log.md b/docs/agent-log.md index 2975f63..63c9051 100644 --- a/docs/agent-log.md +++ b/docs/agent-log.md @@ -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 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) - Owner: the round-4 bank was a flat, unnatural ramp; fix lake generation properly instead of diff --git a/src/ui/selection.js b/src/ui/selection.js index e183dc8..94196e3 100644 --- a/src/ui/selection.js +++ b/src/ui/selection.js @@ -82,16 +82,16 @@ function setBrush(d) { } // The block variant a piece is placed with: wall material, or direction (a filter's // 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 (P.filter) return filterVariant(pieceCode(P), (GAME.pieceDir[P.id] || 0) << 7); - return GAME.pieceDir[P.id] || 0; + if (P.filter) return filterVariant(code, dir << 7); + return dir; } // 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). 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 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) : 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; diff --git a/test/t_piece_variants.js b/test/t_piece_variants.js new file mode 100644 index 0000000..c14df89 --- /dev/null +++ b/test/t_piece_variants.js @@ -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();