use epkard::*; #[derive(Serialize, Deserialize)] struct State { has_key: bool, } #[derive(Clone, Serialize, Deserialize)] enum Room { Start, Side, Exit, } impl Node for Room { type State = State; fn next<F>(self, rt: &mut Runtime<Self, F>) -> Control<Self> where F: Frontend, { rt.clear(); match self { Room::Start => { rt.println("You are in a room."); rt.wait()?; let next_room = rt.multiple_choice_named( "Where do you want to go?", vec![ ("The door with light behind it", Room::Exit), ("The door with no light behind it", Room::Side), ], )?; next(next_room) } Room::Side => { rt.println(if rt.has_key { "There is nothing here." } else { "There is a key on the floor." }); rt.wait()?; let pick_up_key = rt.multiple_choice_named( "What do you want to do?", Some(("Pick up the key", true)) .filter(|_| !rt.has_key) .into_iter() .chain(Some(("Go back through the door", false))), )?; if pick_up_key { rt.has_key = true; next(Room::Side) } else { next(Room::Start) } } Room::Exit => { rt.println("There is another door with a bright light behind it."); rt.wait()?; let try_to_leave = rt.multiple_choice_named( "Where do you want to go?", vec![ ("Through the door ahead", true), ("Back through the door you came in", false), ], )?; if try_to_leave { if rt.has_key { rt.println("The door is locked. You unlock the door with your key."); rt.wait()?; rt.println("You escaped! You win!"); rt.wait()?; exit() } else { rt.println("The door is locked."); rt.wait()?; next(Room::Exit) } } else { next(Room::Start) } } } } } #[derive(Clone)] struct Inventory; impl Node for Inventory { type State = State; fn next<F>(self, rt: &mut Runtime<Self, F>) -> Control<Self> where F: Frontend, { if rt.has_key { rt.println("You have a key"); } else { rt.println("You have nothing"); } exit() } } fn main() { run( Room::Start, &mut State { has_key: false }, &mut CliFrontend::new(), ) .command("save", |rt| { match rt.save("rooms.yaml") { Ok(_) => rt.println("Save complete"), Err(e) => rt.println(format!("Error: {}", e)), } Continue }) .command("load", |rt| { match rt.load("rooms.yaml") { Ok(_) => rt.println("Load complete"), Err(e) => rt.println(format!("Error: {}", e)), } Skip }) .command("inv, inventory", |rt| rt.push_node(Inventory)); }