clone

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

main
miau-is-true / docs / design-backbone.md
design-backbone.md 15.0K rendered
1# Dynamic-rule Sokoban engine: design backbone23This document is a vocabulary and execution contract for a grid puzzle engine4that combines Sokoban-style pushing with Baba Is You-style rules that are5physical, editable objects. It separates observations about the reference6games from recommendations for this engine so that a mod author can tell7which behavior is compatibility-oriented and which behavior is ours to choose.89## Design thesis1011The core puzzle loop is: inspect a board, form or break a rule, observe the12new affordances, then make a deliberately ordered sequence of movement and13pushes. The board contains both the objects affected by rules and the words14that define the rules. A rule is therefore state, level geometry, and puzzle15clue at the same time.1617This is a direct synthesis of two proven constraints:1819* Sokoban's single verb is constrained pushing. The player can walk and push20 but cannot pull, so a push can permanently remove future options. The creator21 Hiroyuki Imabayashi describes the 1981 prototype as a puzzle in which a bad22 box placement can make further progress impossible ([creator interview](https://sokoboxes.com/articles/my-conversation-with-mr-hiroyuki-imabayashi/)).23* Baba Is You makes the rules themselves pushable blocks. Teikari's GDC slides24 describe the basic rule as object + verb + quality, with rules being25 re-detected after words move ([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 8–14).2627Recommendation: make every turn replayable and undoable from the beginning.28This preserves Sokoban's meaningful irreversible pushes while allowing players29to explore a dynamic rule system without paying a restart tax.3031## Vocabulary inventory3233The engine should distinguish *surface words* (what a module places and the34player reads) from *semantic capabilities* (what the simulation executes).35This avoids making the parser and renderer depend on JavaScript class names.3637### Tier 0: board invariants3839These are the smallest shared concepts and should be stable in the public mod40API.4142| Term | Meaning | Required invariant |43| --- | --- | --- |44| `cell` | One integer grid coordinate | A cell can hold zero or more entities and terrain layers. |45| `entity` | A runtime instance with identity and position | Identity survives movement; two entities may share a cell. |46| `kind` | Whether an entity is a physical `object` or pushable `word` | Rule matching uses an object's noun or a word's text, never an instance ID. |47| `noun` | Semantic type of a physical object, such as `MIAU`, `WALL`, or `ROCK` | Rules target nouns, so every object of the same noun gains the same derived properties. |48| `layer` | Terrain, actor, item, text, or effect ordering | Rendering order must not silently change collision order. |49| `direction` | Facing or movement vector | Cardinal movement is the baseline; diagonal support is an explicit extension. |50| `occupancy` | Entities currently in a cell | Never encode occupancy as a single sprite slot: stacked words and objects are valid. |51| `property` | A capability or tag attached by active rules | Properties are recomputed from the current rule set, not permanently mutated. |52| `goal` | A predicate over state that ends or advances a level | A goal may be an object property (`WIN`) or a mod-defined predicate. |53| `turn` | One accepted player intent plus all resulting resolution | Undo restores the complete pre-turn snapshot, including rules and effects. |5455The stacked-word invariant is evidence-based: Teikari says the shipped system56had to be rewritten to account for words sharing a cell and to test possible57permutations ([Game Developer interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 68–71).5859### Tier 1: nouns, operators, and properties6061The initial built-in lexicon should be small enough to teach in a few levels.62Words are data records, not reserved identifiers; a mod can add synonyms or a63new word that maps to an existing semantic capability.6465**Nouns (things that can be targeted):**6667`YOU`'s subject kinds such as `BABA` and `FENN`; board kinds such as `WALL`,68`ROCK`, `FLAG`, `WATER`, `LAVA`, `GRASS`; and meta kinds `TEXT`, `LEVEL`,69`ALL`, `EMPTY`, `WORD`. `ALL` and `EMPTY` are selectors rather than ordinary70spawnable kinds and need explicit scope rules.7172**Core relation verbs:**7374`IS` assigns properties or transforms one kind into another; `HAS` emits or75creates a kind when the subject is destroyed; `MAKE` is an optional explicit76spawn relation. Start with `IS` and `HAS`; keep `MAKE` out until a concrete77level needs its semantics.7879**Core properties / capabilities:**8081`YOU` makes every matching entity player-controlled; `PUSH` allows an entity to82be pushed; `PULL` makes it drag an adjacent entity when it moves; `STOP` blocks83movement; `OPEN` and `SHUT` form a paired interaction; `SINK` consumes both84participants; `WIN` satisfies the level goal on contact; `DEFEAT` resets or85removes the controlled entity; `HOT` and `MELT` form a paired interaction;86`FLOAT` chooses a collision layer; `MOVE` supplies autonomous movement; `SHIFT`87transfers entities on contact.8889**Connectives and modifiers:**9091`AND` bundles adjacent nouns or properties; `NOT` negates a term; `ON`, `NEAR`,92`FACING`, and `LONELY` constrain a rule by spatial context. A parser must retain93the exact token sequence and source coordinates so diagnostics and editor94highlighting can explain why a rule is active.9596These categories follow Teikari's documented progression: three-part rules,97then `AND` and `ON`, then parameterized conditionals such as `NEAR` and98`FACING`, then `LONELY`, `NOT`, letters, and stacked rules ([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 15–21).99100### Tier 2: derived systems101102These are useful after the core loop is stable:103104* **Rule text:** words have their own kind and can be targeted by `TEXT`,105 transformed, destroyed, or made controllable.106* **Plural and wildcard selectors:** `ALL IS YOU` expands to all eligible107 kinds; expansion must be a deterministic snapshot for the turn.108* **Conditional predicates:** a rule can query the subject's neighbors,109 supporting cell, facing vector, or count. Predicates should be pure queries.110* **Creation and destruction:** `HAS`, `SINK`, `DEFEAT`, `MELT`, and `OPEN /111 SHUT` are effect relationships, not movement properties.112* **Meta-board entities:** the level map, level-select map, or UI may become113 simulation entities, but only in an opt-in extension tier.114115Teikari's implementation uses multiple passes: find candidate straight-line116sentences, filter word-type order, validate syntax, convert to rule records,117then apply expansion and disabling. It accepts only left-to-right and118top-to-bottom straight lines and discards lines shorter than three words119([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 10–14).120That is a good default grammar because it is predictable to read and easy to121debug.122123## Turn pipeline and precedence124125The following order is the recommended engine contract. It makes each phase126observable for debugging and deterministic for mods.1271281. **Accept intent.** Read one cardinal input (`up`, `down`, `left`, `right`),129 `wait`, `undo`, or `reset`. Reject input while a level transition is being130 committed.1312. **Snapshot.** Save the entire state, including entity identities, positions,132 directions, text stacks, active rules, RNG seed, and pending effects.1333. **Resolve movement intent.** Determine controlled entities from the active134 `YOU` rules. For each requested move, compute the push chain in a stable135 order. A blocked chain fails atomically; a legal chain moves as one action.1364. **Apply movement and pushes.** Move entities from back to front. A push137 cannot pull an entity unless `PULL` independently creates that behavior.138 Resolve simultaneous controlled entities with a documented ordering key139 (for example entity ID), then expose collision groups to mods.1405. **Re-scan rules if relevant state changed.** If any text moved, was created,141 destroyed, transformed, or stacked, parse the board again. The reference142 implementation tracks whether words changed and only rewrites rules when143 needed ([Game Developer interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 46–52).1446. **Compile semantic rules.** Validate syntax, expand `AND` / `ALL`, apply145 negation and disablement, and replace the active rule table atomically.146 Contradictions must be deterministic: a negative rule such as `BABA IS NOT147 YOU` suppresses the positive `BABA IS YOU` rule, as in the reference game.1487. **Resolve interactions.** Run paired effects (`OPEN`/`SHUT`, `SINK`,149 `DEFEAT`, `MELT`) using a fixed priority list. Recommended initial order:150 structural destruction and transformations, then defeat, then win. A mod151 can register a priority but cannot create a cycle.1528. **Run autonomous behavior.** Apply `MOVE`, `SHIFT`, and similar behaviors as153 a new deterministic substep, then re-run rule and interaction phases if154 they changed text or occupancy. Cap cascading substeps and report a cycle.1559. **Evaluate goals.** Evaluate `WIN` and mod goals against the settled state.156 A surviving object with both `YOU` and `WIN` satisfies the goal by itself;157 a `YOU` object and a distinct `WIN` object satisfy it when they share a158 cell. Evaluate this after `SINK` and `DEFEAT` removals. If both win and159 defeat occur in a turn, use the explicit goal policy (the recommended160 default is defeat before win unless the level opts into “reaching win ends161 immediately”). This self-win behavior is supported by Hempuli's patch note162 for `EMPTY IS YOU AND WIN AND DEFEAT` ([official patch notes](https://www.hempuli.com/blog/index.php?page=8)).16310. **Commit presentation.** Emit a replay event list, sound/effect cues, and164 text highlighting. Rendering and particles must not mutate simulation165 state.166167This pipeline is an engine recommendation inferred from the source's168multi-pass rule detection and from Sokoban's need to reason about pushes as169irreversible state changes. It is not a claim that the commercial games use170this exact sequence.171172## Puzzle pedagogy173174Use a vocabulary curriculum, not a feature dump. Teach one new noun or175property in a low-pressure board; immediately give a second level where the176same word combines with an older word; then make the player manipulate the177word tile itself. Keep the number of initially active rules low. Teikari says178levels were cut when the intended interaction could be bypassed, required too179many supporting rules, or became overwhelming with many active rules180([Game Developer interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 59–64).181182Preserve a visible escape route from difficulty spikes. Teikari grouped areas183by introduced words and used “Extra” markers to signal unusually difficult184levels, while acknowledging that sequential numbering worked against returning185later ([same interview](https://www.gamedeveloper.com/design/designing-i-baba-is-you-i-s-delightfully-innovative-rule-writing-system), lines 82–87).186For this engine, a mod should be able to mark levels as `required`, `optional`,187or `challenge`, and the campaign should unlock around a hard puzzle.188189Sokoban pedagogy depends on the player learning which pushes are unsafe. A190crate in a non-goal corner is a simple deadlock; more complex deadlocks arise191from wall corridors, frozen crate groups, and goal ordering. Deadlock research192exists because these states make Sokoban difficult even for non-optimal solving193([Cazenave, “Towards deadlock free Sokoban”](https://www.lamsade.dauphine.fr/~cazenave/papers/sokoban.pdf)).194Make deadlocks legible through undo, restart, and optional post-failure hints;195do not silently auto-solve or remove every consequence.196197For a design tool, validate levels with at least: reachability of controlled198entities, a goal witness or solver result, detection of static dead squares,199and a report of active rules at level start. Unique-solution or minimum-push200claims are optional metadata, not a requirement for a fun level.201202## CommonJS mod boundary203204The first playable release accepts trusted local CommonJS modules containing a205manifest, levels, noun vocabulary, and an emoji palette. Its concrete shape and206limits are in the [modding guide](modding.md). A later engine milestone should207add pure hooks through a narrow, versioned contract such as:208209```js210module.exports = {211 manifest: { id: 'garden-01', name: 'Garden', version: '2.0.0' },212 vocabulary: { nouns: [], verbs: [], properties: [] },213 levels: [{ id: 'intro', width: 9, height: 7, cells: [] }],214 systems: {215 onTurnStart(ctx) {},216 onCollision(ctx) {},217 onGoalCheck(ctx) { return false }218 }219}220```221222The host owns parsing, snapshots, input, rendering, replay, and persistence.223Mods may register words, level data, serializers, pure predicates, and named224effect handlers. They should not access DOM nodes, mutate the active rule table225in place, replace the scheduler, use wall-clock time, or depend on object226iteration order. The host passes a capability-scoped context with read-only227queries and queued commands (`spawn`, `destroy`, `setDirection`, `emitEffect`).228229This boundary is a recommendation for deterministic, shareable content. It is230also a practical security boundary: CommonJS is code, so untrusted mods need a231worker or restricted loader with explicit resource and API limits.232233## Explicit non-goals and open decisions234235The first engine should not promise full commercial Baba compatibility, natural236language parsing, diagonal movement, continuous time, physics simulation,237network multiplayer, arbitrary UI-as-level semantics, or unrestricted code238execution in mods. Those features multiply ambiguity before the basic turn239contract is proven.240241Open decisions to settle with executable examples: whether entities can occupy242multiple layers in one cell; whether `YOU` entities move simultaneously or in243ID order; whether win precedes defeat; whether a failed push still consumes a244turn; how `ALL`, `EMPTY`, and `TEXT` select targets; whether rule scan uses245nearest valid sentence or all overlapping valid sentences; and whether effects246are allowed to trigger recursive rule scans. Each decision should become a247small fixture level and a replay test before the mod API is frozen.248249The GDC talk explicitly cautions that a perfectly robust parser would require250removing some desirable complexity; Teikari kept unstable but fitting elements251and limited player access to the worst cases, while treating `IF` as not worth252the implementation pain at that stage ([GDC talk PDF](https://media.gdcvault.com/gdc2020/presentations/Reading%20the%20rules_Teikari_Arvi.pdf), pp. 19–21).253That is a useful product constraint: keep the grammar deliberately small and254make quirky extensions opt-in and testable.255256## Sources257258- Hempuli, [official Baba Is You patch notes](https://www.hempuli.com/blog/index.php?page=8), documenting the `EMPTY IS YOU AND WIN AND DEFEAT` win-condition fix.