Files
systemic-game-design-course/course/06-parser/scenarios.md
T
Lucas WintherandClaude Opus 5.5 68fe9834c3 feat: module 06 parser
First Part II module. The cumulative reference adds a second engine
(src/engine/puzzle: grid, lexer, parser) beside Part I's; nouns and
properties are data in src/content/words.json, and the engine names only
IS/AND/NOT/TEXT and the base rule TEXT IS PUSH. Rules are recompiled from
the board on every change; rules() is a sorted set. Adds the M6 scenarios
and tests (rows, columns, shared IS, AND distribution, stacked text, base
rule), the HOT word as a data-only Expansion Drop, the lesson with the
Part II bridge, and the Rust LevelDef shape in harness.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 03:33:53 +01:00

3.5 KiB

Module 6 scenarios: Grid, lexer and parser

Each heading is a test name. The Rust test lives in tests/rust/test_06.rs and the TypeScript test in tests/ts/test_06.test.ts; both state exactly what is written here.

Part II has its own harness object, Baba, made by newBaba(level) from a level in the format of course/schema/level.schema.json: a width, a height and a list of objects, each {kind, x, y}. x grows right and y grows down. A kind is either an object ("baba") or a word of text ("text:BABA"). place(kind, x, y) adds one more object to the level and returns its id. Several objects may share a tile.

rules() returns every rule the board currently spells, as normalised strings such as "BABA IS YOU", sorted, each distinct rule once. The base rule "TEXT IS PUSH" is always in it, although no text spells it. Duplicates are a real thing in the game (stacked text "will attempt to produce all possible rules", and a rule spelled twice can duplicate objects, see docs/research/baba-is-you.md §e), so the engine may hold the same rule more than once, but rules() is the set of distinct rules and no test counts duplicates.

Words used: the nouns BABA, ROCK, FLAG; the properties YOU, WIN, PUSH, STOP; the operators IS and AND; the meta-noun TEXT (only through the base rule). Rules read left to right in a row and top to bottom in a column. A test writes a sentence as its words with their tiles: BABA (0,0) IS (1,0) YOU (2,0) is three text objects, text:BABA at x 0, y 0, and so on.

test_06_horizontal_rule

  • Setup: newBaba with a level 5 wide and 3 high whose objects are, in this order: BABA (0,0) IS (1,0) YOU (2,0); an object baba at (3,2); YOU (0,2) IS (1,2) FLAG (2,2).
  • Action: none. The rules come from the level's objects.
  • Assertions:
    • rules() is exactly ["BABA IS YOU", "TEXT IS PUSH"].
    • Row 2 spells nothing: YOU IS FLAG has a property where a noun must start the sentence, and the parser never reads right to left (FLAG IS YOU). The baba object is not text and plays no part in parsing.

test_06_crossword_shared_is

  • Setup: newBaba with an empty level 3 wide and 3 high. Place BABA (0,1), IS (1,1), YOU (2,1), then FLAG (1,0).
  • Assertions 1: rules() is exactly ["BABA IS YOU", "TEXT IS PUSH"]. FLAG above IS is half a sentence.
  • Action: place WIN (1,2).
  • Assertions 2: rules() is exactly ["BABA IS YOU", "FLAG IS WIN", "TEXT IS PUSH"]. The IS at (1,1) is in a row sentence and a column sentence at once, and the rules were recompiled when the board changed.

test_06_and_distributes

  • Setup: newBaba with an empty level 7 wide and 1 high. Place BABA (0,0) AND (1,0) ROCK (2,0) IS (3,0) PUSH (4,0) AND (5,0) STOP (6,0).
  • Assertions: rules() is exactly ["BABA IS PUSH", "BABA IS STOP", "ROCK IS PUSH", "ROCK IS STOP", "TEXT IS PUSH"]. AND distributes over both sides: two subjects times two complements is four rules.

test_06_stacked_text_all_combinations

  • Setup: newBaba with an empty level 3 wide and 1 high. Place text:BABA at (0,0), then text:ROCK also at (0,0), then IS (1,0) and YOU (2,0).
  • Assertions: rules() is exactly ["BABA IS YOU", "ROCK IS YOU", "TEXT IS PUSH"]. Both stacked words start a sentence: the parser produces every rule the stack allows.

test_06_default_text_is_push

  • Setup: newBaba with a level 3 wide and 3 high whose only object is a baba at (1,1).
  • Assertions: rules() is exactly ["TEXT IS PUSH"]. No text spells it: it is a base rule of the game.