- SpellGrid cards move to course/10-spellgrid/cards; start-module and verify-references stage course/cards plus module-local cards up to the module, so M5-M9 workspaces get exactly the pre-M10 card set. - cast() rejects a chosen-target spell without a target (checkCast/checkPlay); new test_10_targeted_spell_needs_target. - Rust CLI pre-validates instead of swapping the global panic hook. - Catalog: CRIER noun; DEATHRATTLE/BATTLECRY note on lexicon vs catalog role. - Lesson: design note on mid-movement reparse. Co-Authored-By: Claude Opus 5.5 <[email protected]>
21 lines
2.9 KiB
Markdown
21 lines
2.9 KiB
Markdown
# Module 10 reference engine (TypeScript)
|
||
|
||
The course's own engine as of the end of Module 10: Part I's card engine and Part II's grid engine, joined by SpellGrid. Every test from Modules 1–9 still passes. Module 9's reference was the starting point, so a diff between the two shows what this module adds.
|
||
|
||
- `cards/` and `levels/` (at the package root; not in this directory): copies of `course/cards/` plus `course/10-spellgrid/cards/` (SpellGrid's own cards, which only Module 10 on receives), and of `course/10-spellgrid/levels/`, staged by `tools/verify-references.mjs`.
|
||
- `src/engine/spellgrid.ts` (new): the only file that imports both engines. `SpellGrid` keeps a `World` and a `puzzle.Level` in step through the three seams: `ruleAuras` (rules in force → auras), the destroy function (hazard victims → one `destroy` Sequence → the Death Creation Step), and `sequence` (after each Sequence: write `TextSpawned` text, take dead minions off the grid, reparse). It also keeps one id space: a minion's id is its grid object's id.
|
||
- Part I (`src/engine/`, outside `puzzle/`):
|
||
- `queue.ts`: `END_OF_PHASE` (`["deathCreation", "auraUpdate"]`) is the list of steps at the end of the outermost Phase, read from the world. The `spawnText` action records a `TextSpawned` event.
|
||
- `world.ts`: `setRuleAuras`/`ruleAuras` (auras that no minion carries), `setEndOfPhase`/`endOfPhase`, `entityCount`.
|
||
- `aura.ts`: an Aura Update adds the rule auras for both players; `activations` applies a `triggerCap`.
|
||
- `card.ts`: the `triggerCap` aura (not in the card format: only SpellGrid makes it).
|
||
- `effect.ts`: `spawnText` is an action, not an error. `event.ts`: `TextSpawned`.
|
||
- Part II (`src/engine/puzzle/`):
|
||
- `level.ts`: `Destroy` and `removeAll`. `step` and `moveYou` take an optional `Destroy`, which movement, conversion (`X IS NOT X`) and hazards hand their victims to. `reparse` is public.
|
||
- `grid.ts`: `Board.reserveId`, and `cards`/`hand` in `LevelDef` (read only by SpellGrid).
|
||
- `src/content/seams.json` and `seams()` (new): which nouns name a trigger (`DEATHRATTLE`) and which properties multiply one (`DOUBLE`, twice, `stacking: "max"`). `words.json` adds the SpellGrid nouns, `DEATHRATTLE` and `DOUBLE`. `index.ts` now reads `cards/` with `node:fs`, so the command line, which runs without Vite, reads the same cards.
|
||
- `src/harness.ts`: Module 10 adds `newSpellGrid` and the `SpellGrid` interface, including the test hook `withNaiveAuraTiming()`, which reverses `END_OF_PHASE` for one game.
|
||
- `src/cli.ts` (new): the command line, `npx tsx src/cli.ts levels/l1-double-tap.json` from a staged workspace (it needs `cards/` and `levels/`). `w a s d` move, `c <card> [x y]` casts a spell (at the minion on that tile) or plays a minion (onto that empty tile), `q` quits. `tests/cli.test.ts` plays it from a script; it is the reference's own check, not a course test.
|
||
|
||
Run it with the module's tests: `node tools/verify-references.mjs 10` from the course repository.
|