feat: undo in Module 9 and stackAt from Module 8; Lesson 8 quote matches the reference

Baba.undo() restores the level before the last step or move (board snapshot:
objects in age order with ids, the id counter, and won; rules recompiled).
place clears the history. SpellGrid's undo throws/panics 'not supported'.
stackAt / stack_at lists a tile's kinds oldest first, on Baba and SpellGrid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-11-11 11:20:03 +01:00
1 parent 21fb40c6f5
commit 820b378929
27 files changed
+530 -30

No files matched your search

@@ -12,6 +12,6 @@ The course's own engine as of the end of Module 8. Part I's card engine is uncha
- The rest of `src/engine/`: Part I, unchanged.
- `src/content/movement.rs` (new) and `src/content/mod.rs`: the movement responses, in the order the engine runs them: `OPEN`/`SHUT`, `PUSH`, `STOP`. What a property does when something moves is content, not engine.
- `src/content/words.json`: Module 8 adds `OPEN` and `SHUT`.
- `src/harness.rs`: the adapter the course tests call. Module 8 adds `Baba::move_dir`, `Baba::pos_of`, `Baba::kinds_at`, and re-exports `Dir`.
- `src/harness.rs`: the adapter the course tests call. Module 8 adds `Baba::move_dir`, `Baba::pos_of`, `Baba::kinds_at`, `Baba::stack_at`, and re-exports `Dir`.
Run it with the module's tests: `node tools/verify-references.mjs 08` from the course repository.
@@ -306,6 +306,12 @@ impl Baba {
kinds.sort();
kinds
}
/// The kinds on tile (x, y), as `kinds_at`, but oldest object first.
pub fn stack_at(&self, x: i32, y: i32) -> Vec<String> {
let board = self.level.board();
board.at(x, y).map(|o| o.kind.to_string()).collect()
}
}
fn normalised(rules: &[puzzle::Rule]) -> Vec<String> {
+1 -1
View File
@@ -12,6 +12,6 @@ The course's own engine as of the end of Module 8. Part I's card engine is uncha
- The rest of `src/engine/`: Part I, unchanged.
- `src/content/movement.ts` (new) and `src/content/index.ts`: the movement responses, in the order the engine runs them: `OPEN`/`SHUT`, `PUSH`, `STOP`. What a property does when something moves is content, not engine.
- `src/content/words.json`: Module 8 adds `OPEN` and `SHUT`.
- `src/harness.ts`: the adapter the course tests call. Module 8 adds `move`, `posOf` and `kindsAt` on `Baba`.
- `src/harness.ts`: the adapter the course tests call. Module 8 adds `move`, `posOf`, `kindsAt` and `stackAt` on `Baba`.
Run it with the module's tests: `node tools/verify-references.mjs 08` from the course repository.
@@ -155,6 +155,7 @@ export interface Baba {
move(dir: puzzle.Dir): void; // every YOU object one tile, with what it pushes; then reparse. Movement only.
posOf(id: Id): [number, number] | null; // null once destroyed
kindsAt(x: number, y: number): string[]; // kinds as placed ("baba", "text:ROCK"), sorted
stackAt(x: number, y: number): string[]; // the same tile, oldest object first
}
/** Distinct rules as normalised strings, sorted. */
@@ -178,5 +179,9 @@ export function newBaba(level: puzzle.LevelDef): Baba {
.at(x, y)
.map((o) => puzzle.Kind.format(o.kind))
.sort(),
stackAt: (x, y) =>
lvl.board
.at(x, y)
.map((o) => puzzle.Kind.format(o.kind)),
};
}