SpellGrid capstone: Part I's card engine and Part II's grid engine joined at three seams (rules -> aura data, hazard victims -> one destroy Sequence, Sequence end -> write text, remove the dead, reparse). Three levels with scripted solutions, a naive-timing test via a harness-only hook that reverses the END_OF_PHASE list, CLIs in both tracks, the BATTLECRY IS DOUBLE Expansion Drop, SpellGrid cards and words in course/cards and the catalog, level schema cards/hand, and tools staging/copying of module levels. Co-Authored-By: Claude Opus 5.5 <[email protected]>
33 lines
1.3 KiB
TypeScript
33 lines
1.3 KiB
TypeScript
// The SpellGrid command line, played from a script (the reference's own check; not a course test).
|
|
import { readFileSync } from "node:fs";
|
|
import { expect, test } from "vitest";
|
|
import { run } from "../src/cli";
|
|
|
|
function play(level: string, input: string[]): { outcome: string; out: string } {
|
|
let out = "";
|
|
const outcome = run(readFileSync(`levels/${level}.json`, "utf8"), () => input.shift(), (s) => (out += s));
|
|
return { outcome, out };
|
|
}
|
|
|
|
test("cli_wins_level_1", () => {
|
|
const { outcome, out } = play("l1-double-tap", ["w", "w", "c Whirlwind", "s", "s", "a", "s", "s", "d", "d"]);
|
|
expect(outcome).toBe("won");
|
|
expect(out).toContain("DEA IS DOU");
|
|
expect(out).toContain("You win!");
|
|
});
|
|
|
|
test("cli_wins_level_2_with_choices_and_play", () => {
|
|
const input = ["c Graft", "Ember Moth", "Rune Scribe", "bottom", "c Ember Moth (Assembled) 4 3", "a", "a"];
|
|
const { outcome, out } = play("l2-spliced-corpse", input);
|
|
expect(outcome).toBe("won");
|
|
expect(out).toContain("Choose the base");
|
|
expect(out).toContain("Hand: Ember Moth (Assembled)");
|
|
});
|
|
|
|
test("cli_reports_errors_and_quits", () => {
|
|
const { outcome, out } = play("l3-simultaneous-paradox", ["c Spark", "x", "q"]);
|
|
expect(outcome).toBe("quit");
|
|
expect(out).toContain('"Spark" is not in the hand');
|
|
expect(out).toContain("Commands:");
|
|
});
|