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]>
67 lines
1.9 KiB
Rust
67 lines
1.9 KiB
Rust
// The SpellGrid command line, played from a script (the reference's own check; not a course test).
|
|
use std::cell::RefCell;
|
|
use std::io::{Cursor, Write};
|
|
use std::rc::Rc;
|
|
|
|
use engine::cli::{run, Outcome};
|
|
|
|
/// Collects what the CLI prints.
|
|
#[derive(Clone, Default)]
|
|
struct Screen(Rc<RefCell<Vec<u8>>>);
|
|
|
|
impl Write for Screen {
|
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
|
self.0.borrow_mut().extend_from_slice(buf);
|
|
Ok(buf.len())
|
|
}
|
|
fn flush(&mut self) -> std::io::Result<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn play(level: &str, input: &[&str]) -> (Outcome, String) {
|
|
let screen = Screen::default();
|
|
let input = Box::new(Cursor::new(input.join("\n") + "\n"));
|
|
let outcome = run(level, input, Box::new(screen.clone()));
|
|
let out = String::from_utf8(screen.0.borrow().clone()).unwrap();
|
|
(outcome, out)
|
|
}
|
|
|
|
#[test]
|
|
fn cli_wins_level_1() {
|
|
let input = ["w", "w", "c Whirlwind", "s", "s", "a", "s", "s", "d", "d"];
|
|
let (outcome, out) = play(include_str!("../levels/l1-double-tap.json"), &input);
|
|
assert_eq!(outcome, Outcome::Won);
|
|
assert!(out.contains("DEA IS DOU"));
|
|
assert!(out.contains("You win!"));
|
|
}
|
|
|
|
#[test]
|
|
fn cli_wins_level_2_with_choices_and_play() {
|
|
let input = [
|
|
"c Graft",
|
|
"Ember Moth",
|
|
"Rune Scribe",
|
|
"bottom",
|
|
"c Ember Moth (Assembled) 4 3",
|
|
"a",
|
|
"a",
|
|
];
|
|
let (outcome, out) = play(include_str!("../levels/l2-spliced-corpse.json"), &input);
|
|
assert_eq!(outcome, Outcome::Won);
|
|
assert!(out.contains("Choose the base"));
|
|
assert!(out.contains("Hand: Ember Moth (Assembled)"));
|
|
}
|
|
|
|
#[test]
|
|
fn cli_reports_errors_and_quits() {
|
|
let input = ["c Spark", "x", "q"];
|
|
let (outcome, out) = play(
|
|
include_str!("../levels/l3-simultaneous-paradox.json"),
|
|
&input,
|
|
);
|
|
assert_eq!(outcome, Outcome::Quit);
|
|
assert!(out.contains("\"Spark\" is not in the hand"));
|
|
assert!(out.contains("Commands:"));
|
|
}
|