use std::fmt::{Debug, Formatter}; use utilz::test_per_file; use texttale::{story, ExpectTextTale, StoryElement, TextTale}; ////////////////////////////////////////////// Player ////////////////////////////////////////////// struct Player { name: String, age: u8, gender: String, race: String, tale: T, } impl Player { fn new(tale: T) -> Self { Self { name: "Link".to_owned(), gender: "unspecified".to_owned(), age: 18, race: "Hylian".to_owned(), tale, } } } impl Debug for Player { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("Player") .field("name", &self.name) .field("age", &self.age) .field("gender", &self.gender) .field("race", &self.race) .finish() } } ///////////////////////////////////////////// bootstrap //////////////////////////////////////////// story! { self cmd, bootstrap by Player; "Welcome to the texttale library. help: ....... Print this help menu. character: .. Configure your character for this texttale. begin: ...... Start off on your journey with the given character. "; "help" => { StoryElement::PrintHelp } "character" => { self.character(); StoryElement::PrintHelp } "begin" => { self.steady_state(); StoryElement::Return } } ///////////////////////////////////////////// character //////////////////////////////////////////// story! { self cmd, character by Player; "Craft your character. help: .... Print this help menu. name: .... Set your character's name. age: ..... Set your character's age. gender: .. Set your character's gender. race: .... Set your character's race. print: ... Print your character. save: .... Commit changes to the configuration and return to previous menu. "; "name" => { self.name = cmd[1..].to_vec().join(" "); StoryElement::Continue } "gender" => { self.gender = cmd[1..].to_vec().join(" "); StoryElement::Continue } "race" => { self.race = cmd[1..].to_vec().join(" "); StoryElement::Continue } "age" => { if cmd.len() != 2 { writeln!(self.tale, "USAGE: age [age]").unwrap(); } else { match cmd[1].parse::() { Ok(age) => { self.age = age; }, Err(err) => { writeln!(self.tale, "invalid age: {}", err).unwrap(); }, }; } StoryElement::Continue } "print" => { let debug = format!("{:#?}", self); writeln!(self.tale, "{}", debug).unwrap(); StoryElement::Continue } "save" => { StoryElement::Return } } /////////////////////////////////////////// steady_state /////////////////////////////////////////// story! { self cmd, steady_state by Player; "Welcome to adventure mode. It's quite boring, but this simple quest is enough to test the texttale library. help: ....... Print this help menu. character: .. Configure your character for this texttale. end: ........ Unceremoniously end this adventure. "; "help" => { StoryElement::PrintHelp } "character" => { self.character(); StoryElement::PrintHelp } "end" => { StoryElement::Return } } /////////////////////////////////////////////// main /////////////////////////////////////////////// fn tell_tale(_file: &str, _line: u32, script: &str) { let tale = ExpectTextTale::new(script, "> ").expect("could parse script"); let mut player = Player::new(tale); player.bootstrap(); } test_per_file! { tell_tale { empty_00 => "scripts/00.empty", motd_01 => "scripts/01.motd", help_02 => "scripts/02.help", character_03 => "scripts/03.character", begin_04 => "scripts/04.begin", } }