Lucas WintherandClaude Opus 5.5 34c655c1a4 feat: Module 11, Conditions (NOUN ON NOUN IS ..., checked per object at use; NEAR as the Expansion Drop)
Adds course/11-conditions: lesson, scenarios, nine test_11 tests in both
tracks, the cumulative reference (Module 10's plus conditions) and the NEAR
drop. The engine learns a condition role, rules carry conditions, and
Level.hasProperty and conversion evaluate content's condition checks against
the board whenever a rule is used. Resolution pairs only rules with the same
conditions. Catalog, harness contract, research notes and the diff-tracks
generator follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 13:00:26 +01:00
2026-10-29 00:07:14 +01:00

Systemic Design Course

A free, hands-on course on systemic game design. You learn by rebuilding the rules machinery of two games, then extending it:

  • Part I: Hearthstone (cards, zones, triggers, death phases, auras, text assembly)
  • Part II: Baba Is You (rules as pushable text, parsing, movement, win/lose; Module 11 adds conditions, BABA ON KEY IS WIN)
  • Part III: SpellGrid, a small original game that combines both systems
  • Module 13: Break your own engine, an optional closing module on testing what the tests miss: mutation testing, invariants, metamorphic relations, undo and replay, and a level solver

Every module follows the same beats: Observe, Predict, Spec, Build, Name it, Expansion Drop, Stress it, Further reading. The Expansion Drop is the test of your design: you add new content without touching the engine. Stress it is optional: edge cases and stretch exercises that push the design past what the module's tests check.

Two paths

  • Designer path: read the lessons and scenarios, predict outcomes, and reason about the design.
  • Builder path: also make the tests pass in your own engine.

Mentor path

Prefer a Socratic partner? Install the mentor skill and let your AI agent guide you without writing your code.

Two tracks

Builder path exercises exist in Rust and TypeScript. Both tracks have identical test names, matching the scenarios in each module's scenarios.md.

Quick start

From the course repository:

node --version        # Node 22 or later for the course tooling (CI uses 24)
npm run test:tools    # tooling tests
npm run check         # test names agree across Rust, TS and scenarios

Create your workspace from the template for your track (Module 00, "Before Module 1: choose your track", has the details). Copy the whole directory with cp -r so the hidden .course.json comes along:

cp -r workspace-template/rust ~/my-engine     # or workspace-template/ts
cd ~/my-engine && git init && git add -A && git commit -m "start from template" && cd -
node tools/start-module.mjs 01 ~/my-engine

start-module copies a module's tests for your track (from your workspace's .course.json) and refuses to start a module if you have not yet taken the previous one. Module 00 uses the naive-engine/ project and is not started this way, and Module 13 has no tests to start.

Other tools: tools/coupling-audit.mjs <workspace> (engine code must not name specific cards or nouns), tools/expansion-check.mjs <workspace> <baseRef> (an Expansion Drop must change content only), tools/verify-references.mjs [NN] (reference solutions pass the tests; --expansion also checks every Expansion Drop solution), tools/play-spellgrid.mjs <rust|ts> [l1..l10] (play the Module 10 capstone, SpellGrid, on the command line with the reference engine), tools/solve-spellgrid.mjs [l1..l10|level.json] (search a SpellGrid level for its shortest solution by brute force; --never-rule "X IS Y" asks whether it can be solved without a given rule; see Module 13), tools/verify-levels.mjs [level ...] (checks every claim in course/10-spellgrid/levels/proofs.json with the solver: each level's shortest solution, and that it can't be solved without its idea; npm run verify:levels), tools/diff-tracks.mjs [--seeds N] [--seed S] [--module NN] [--dir D] [--keep] (differential fuzzer: plays random SpellGrid levels and scripts on the Rust and the TypeScript reference CLIs and fails on the first seed where they print different text or one of them crashes; npm run diff:tracks).

Licence

MIT, for both prose and code. See LICENSE. The course is and stays free.

Disclaimer

Not affiliated with Blizzard or Hempuli. See the disclaimer (also the Disclaimer page of the course website).

S
Description
No description provided
Readme MIT
1.7 MiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 50.2%
TypeScript 42.2%
JavaScript 7.1%
Astro 0.4%
MDX 0.1%