CI / Tool tests and sync-check (push) Successful in 16s
CI / Verify references (all modules, Rust and TS) (push) Successful in 2m4s
CI / Verify Expansion Drop solutions (all modules, Rust and TS) (push) Successful in 2m1s
CI / Coupling audit on references (push) Successful in 5s
CI / Differential fuzzing of the Rust and TS references (300 seeds) (push) Successful in 53s
CI / Mutation check (tools/mutants.json against the highest TS reference) (push) Successful in 34s
CI / Verify the SpellGrid level proofs (solver) (push) Successful in 5m25s
CI / Site build (push) Successful in 15s
CI / Naive engine tests (Module 0) (push) Successful in 20s
I1: run-scenario and both SpellGrid CLIs check moves first and treat any other engine error as fatal (same text in both tracks); trigger blocks close on error (try/finally, catch_unwind in Rust); unknown summons rejected. I2, I3, M1-M7, T3, T9a-c, T10a-b. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
4.8 KiB
Markdown
54 lines
4.8 KiB
Markdown
# 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; Module 12 adds combat, Taunt and the end of a turn)
|
|
- **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. After Module 10, the [designer capstone](course/10-spellgrid/designer-capstone.md) has you design three SpellGrid cards and a word as data, predict what they do, and run your predictions with `tools/run-scenario.mjs`, on the course's reference engine.
|
|
- **Builder path**: also make the tests pass in your own engine.
|
|
|
|
## Mentor path
|
|
|
|
Prefer a Socratic partner? Install the [mentor skill](mentor/README.md) 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:
|
|
|
|
```sh
|
|
node --version # Node 22.15 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:
|
|
|
|
```sh
|
|
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 the rule its proof forbids; `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`), `tools/mutation-check.mjs [name ...]` (applies each mutant in `tools/mutants.json`, a small change (one to three lines) to one of the engine's decisions, nearly all of them about order, to the highest module's TypeScript reference, runs every module's tests, and fails if a mutant survives or no longer applies; see Module 13; `npm run mutation:check`), `tools/run-scenario.mjs <scenario.json>` (plays a designer's scenario, new cards, words and seam words as data with a level and inputs, on the Module 10 TypeScript reference and prints the board, rules, minions, hand, heroes' Health and log tree after each input; an engine error in the middle of a Sequence ends the run with exit code 1, and a run longer than 60 s is stopped; `npm run run:scenario`).
|
|
|
|
## Licence
|
|
|
|
MIT, for both prose and code. See [LICENSE](LICENSE). The course is and stays free.
|
|
|
|
## Disclaimer
|
|
|
|
Not affiliated with Blizzard or Hempuli. See the [disclaimer](site/src/content/docs/disclaimer.md) (also the Disclaimer page of the course website).
|