clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

Document derived gate state in Crate Works bible

Dami committed 006d6ca
commit
006d6caf41dde8f4aee048359f6e45fa0617cad8
parent
8639457902c9e3e8a400514a56958972aab86467
author
Dami <dami.etoile@gmail.com>
1 file changed, +18 -9
Mdocs/worlds/crate-works.md27++++++++++++++++++---------
M docs/worlds/crate-works.md +18 -9
@@ -288,11 +288,19 @@ shows the authoring hazard: an adjacent plate makes the gate trivial.
288288 289289 ### Undo, reset, sharing, and solver requirements290290 291-- **Snapshot.** Each gate entity stores `open: boolean` in `state.objects`.292- A jam depends on history (the gate was open last turn and is occupied now),293- so it can't be derived from positions alone. Plates hold no state. Undo294- restores `open` from the snapshot like any other field. Reset recomputes295- from the initial layout.291+- **Snapshot: no stored gate bit** (superseded, and reconciled 2026-09-24292+ with the accepted `add-channel-linked-gates` and293+ `add-declarative-mechanic-state-contract`, design D25). An earlier draft of294+ this section stored `open: boolean` per gate, on the theory that a jam295+ depends on history. It doesn't: a closed gate blocks entry, so **anything296+ standing in a gate cell means the gate is being held open.** Gate state is297+ therefore derived from the current board at end of turn:298+ `pressed(channel)` = any occupant on any plate of that channel;299+ `open` = `pressed(channel)` **or** the gate cell is occupied;300+ `jammed` = occupied **and not** pressed.301+ That covers the start-of-level and transform-back cases too (D25: "state is302+ recomputed, and the jam rule applies if occupied"). Plates hold no state303+ either. Undo and reset restore positions and nouns, and gate state follows.296304 - **Authoring.** Object records need an optional `channel` field, and the297305 `object()` helper needs a 5th argument or an options bag. Today `object()`298306 only takes `(noun, x, y, id)`, so the drafts spread the record by hand. The
@@ -300,9 +308,10 @@ shows the authoring hazard: an adjacent plate makes the gate trivial.
300308 channel has plates but no gates, or the reverse.301309 - **Sharing.** `channel` must survive `exportPack`, `packLink`, and install.302310 It's plain data, with no code.303-- **Solver.** The state hash has to include `open` for every gate. Otherwise304- two states that look identical but differ in a jam get merged and the305- search gives wrong answers. The prototype adds one character per gate to306- the key.311+- **Solver.** Because gate state is a pure function of positions and nouns,312+ **the state key needs nothing extra.** Two states that look identical *are*313+ identical. (The prototype's per-gate key character is superseded. It was314+ only needed while gates carried a hidden bit.) The D1 to D3 drafts remain315+ useful as regression fixtures for the engine's derived semantics.307316 - **Events.** `settled()` should report `gates: [{ id, from, to, cause:308317 'pressed' | 'released' | 'jammed' }]` so juice and audio can react.