Files
systemic-game-design-course/course/07-rule-resolution/reference/ts
Lucas WintherandClaude Opus 5.5 06a1b34c5d feat: Module 11 becomes 13; diff-tracks fuzzer; align the two reference tracks
- Rename course/11-break-your-engine to 13-break-your-engine and update every
  link and mention; start-module explains that Module 13 has no tests to start.
- tools/diff-tracks.mjs (npm run diff:tracks): stages both references of a
  module, generates a seeded random SpellGrid level and script per seed, pipes
  it to the Rust and TypeScript CLIs and diffs their output; crashes on one or
  both sides fail. stagePlay takes a module number.
- register_assembled: the TypeScript track compared only the text of an
  existing Assembled card, so a base re-registered with a new cost (or a
  different split) silently rewrote the earlier card. It now compares every
  field the engine reads, as Rust does (Modules 5-10).
  New test_05_assemble_never_rewrites_an_earlier_card.
- SpellGrid CLIs: coordinates and chooser numbers are 1-9 plain digits in both
  tracks (Rust accepted signs, TypeScript accepted "+2", "0x2", "1e0"); Rust
  quotes card names verbatim instead of with Debug escapes; Rust joins the
  minion list with "; " instead of rewriting ", ". Two new CLI tests per track.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 10:08:56 +01:00
..
2026-10-29 03:47:48 +01:00
2026-10-29 03:47:48 +01:00
2026-10-29 03:47:48 +01:00
2026-10-29 03:47:48 +01:00
2026-10-29 03:47:48 +01:00

Module 7 reference engine (TypeScript)

The course's own engine as of the end of Module 7. Part I's card engine is unchanged, and all of its tests still pass. The Part II engine in src/engine/puzzle/ now reads IS NOT and resolves the parsed rules into the rules in force. Module 6's reference was the starting point, so a diff between the two shows what this module adds.

  • cards/ (at the package root; not in this directory): Part I's card data, a copy of course/cards/ staged by tools/verify-references.mjs. Part II doesn't read it.
  • src/engine/puzzle/: the Part II engine. It names no noun: the engine's own words are the operators IS, AND, NOT, the meta-noun TEXT and the property PUSH of the base rule TEXT IS PUSH.
    • grid.ts: the level format, object kinds and the board. Module 7 adds Board.get.
    • word.ts: the lexicon and the lexer. Module 7 adds Selects: which objects a noun names as a subject (its own things by default, every text object for TEXT, or every non-text object), read from the word list's optional "selects" field, and Lexicon.names.
    • parse.ts: the parser. Module 7 adds NOT: before a complement it negates that complement (Rule.negated); before a subject it ends the run of subjects without that subject. Each rule also records its complement's role, so a conversion (X IS <noun>) can be told apart.
    • resolve.ts (new): the resolution pass. Negation first (X IS NOT Y cancels every X IS Y and stays in force), then the identity lock (a surviving X IS X cancels X IS Y for nouns Y).
    • level.ts: a level in play. Every change to the board parses, then resolves. hasProperty answers for one object from the rules in force.
    • index.ts: the module's exports.
  • The rest of src/engine/: Part I, unchanged.
  • src/content/words.json: unchanged from Module 6.
  • src/harness.ts: the adapter the course tests call. Module 7 adds activeRules and hasProperty on Baba; rules() now lists negated rules too ("BABA IS NOT YOU").

Run it with the module's tests: node tools/verify-references.mjs 07 from the course repository.