Files
systemic-game-design-course/course/10-spellgrid/expansion
Lucas WintherandClaude Fable 5.2 8467c7929e fix(puzzle): an object steps once per movement phase; negated conversion is settled per object
Bug 1 (modules 08-10): a YOU object pulled by an earlier mover took a second step of its own. Level movement now keeps the ids that stepped in a committed plan this phase; such a YOU object starts no move, and Planner try_move answers no for it. Regression: test_08x_pulled_you_moves_once (Module 8 Expansion Drop).

Bug 2 (modules 09-10): convert honoured negation only per rule, so ALL IS ROCK beat BABA IS NOT ROCK. A target Y is now skipped for an object if any active negated rule IS NOT Y names it. Module 9 and 10 references (and their drop solutions) now carry ALL, the Module 7 Expansion Drop. Regression: test_09_negated_conversion_beats_group.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 09:18:00 +01:00
..
2026-10-29 05:01:27 +01:00

Module 10 Expansion Drop: BATTLECRY IS DOUBLE

The lesson's Expansion Drop beat explains the task. This file holds the scenario, the test locations and the check.

  • Word: BATTLECRY, a noun that names a trigger, as DEATHRATTLE does. With it, BATTLECRY IS DOUBLE written on the grid makes every Battlecry trigger twice, like Brann Bronzebeard ("Your Battlecries trigger twice.", Module 4).
  • Card: Town Crier, a SpellGrid card that is already in course/10-spellgrid/cards/, the module's own cards ("game": "spellgrid"): a 1-cost 1/1 minion, noun CRIER, "Battlecry: Deal 1 damage to the enemy hero."
  • Tests: tests/rust/test_10x.rs and tests/ts/test_10x.test.ts. Copy the one for your track into your workspace's tests/.
  • Reference answer, two data files and no code:
    • solution/words.json: the Module 10 reference's src/content/words.json with one entry added, { "name": "BATTLECRY", "role": "noun" }.
    • solution/seams.json: the Module 10 reference's src/content/seams.json with one entry added to triggerWords, "BATTLECRY": "battlecry".
    • Nothing under src/engine/ changes, and neither does the harness. The seam compiles any trigger word joined to any multiplier word; Module 4's one activations routine already multiplies Battlecries.
  • Check: commit your workspace before you start, then run node tools/expansion-check.mjs <your-workspace> <that-commit> from the course repository. It fails if any file under src/engine/ changed.

Scenario

test_10x_battlecry_is_double

  • Setup: newSpellGrid with a level 5 wide and 3 high holding BATTLECRY (0,0) IS (1,0) DOUBLE (2,0), no cards on the grid, and hand ["Town Crier"].
  • Assertions 1: activeRules() contains "BATTLECRY IS DOUBLE".
  • Action: clearLog(), then play("Town Crier", 0, 2), returning crier.
  • Assertions 2:
    • The log holds exactly two Triggered { source: crier, trigger: "battlecry" }.
    • health(hero(1)) is 28: two Battlecries of 1 damage each.
    • kindsAt(0,2) is ["crier"]: the minion entered the grid as its card's noun.

Before the drop the lexicon doesn't know BATTLECRY, so the text spells no rule, and the first assertion fails. (Without that assertion the Battlecry would trigger once and the hero would have 29 Health.)