Files
systemic-game-design-course/course/05-assemble/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:17:21 +01:00
2026-10-29 03:17:21 +01:00
2026-10-29 03:17:21 +01:00
2026-10-29 03:17:21 +01:00
2026-10-29 03:17:21 +01:00
2026-10-29 03:17:21 +01:00
2026-10-29 03:17:21 +01:00

Module 5 reference engine (TypeScript)

The course's own engine as of the end of Module 5. Every card is now data: a JSON file in the course's card format (course/schema/card.schema.json), and the functions that were card effects in Modules 2–4 are gone. One interpreter turns effects into actions. Assemble builds a new card by replacing half of one card's text with the same half of another's. Module 4'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): the card data. It is a copy of course/cards/, the single source: tools/verify-references.mjs stages it next to the package, and tools/start-module.mjs copies it into a learner's workspace.
  • src/engine/: generic machinery. Names no cards.
    • card.ts: the card format as TypeScript types (CardDef, Clause, Effect, Target, Aura), and the library. Registering a definition compiles its clauses into triggers, auras and a spell's effects, and marks whether Assemble may offer it (minions with text that were not themselves assembled). TriggerOn gains endOfTurn, which card data may name (Drakkari Enchanter's aura does); the course has no turns, so nothing fires it.
    • effect.ts: the interpreter: one effect plus its context in, actions out. The only code that knows what dealDamage, draw, summon, assemble, buffHand, ... mean.
    • assemble.ts: assemble(base, donor, half) (list surgery on text at split; throws AssembleError if the text is unchanged), and the assemble effect, which asks the chooser for a base from the filtered pool, a donor and a half.
    • queue.ts: as in Module 4, plus two actions (assemble, buff). An ability's effects are interpreted and performed one at a time, in printed order.
    • world.ts: as in Module 4, plus card registration, cost, the chooser, and buff.
    • aura.ts, death.ts, event.ts: unchanged from Module 4.
  • src/content/index.ts: imports every .json file in cards/ with Vite's import.meta.glob. No card is named in TypeScript any more.
  • src/harness.ts: the adapter the course tests call. Module 5 adds registerCards, assemble, cost and setChooser.

Run it with the module's tests: node tools/verify-references.mjs 05 from the course repository. npm test in this directory alone fails: there is no cards/ here.