diff --git a/src/main.rs b/src/main.rs index 74ba053..55ac026 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,8 +72,13 @@ fn just (t: T) -> Vec { enum PlayerAction { Quit, Help, - Hint, Nonsense, + RoomSpecific (PlayerActionRoomSpecific), +} + +#[derive (Debug, PartialEq)] +enum PlayerActionRoomSpecific { + Hint, Wait, Look (ItemName), LookAround, @@ -104,79 +109,96 @@ fn _item_name_display (x: ItemName) -> &'static str { } fn parse_input (s: &str) -> PlayerAction { + use PlayerAction::*; + use PlayerActionRoomSpecific::*; + let s = s.to_lowercase (); if s == "quit" || s == "quit game" { - return PlayerAction::Quit; + Quit } - - if s == "look" || s == "look around" { - return PlayerAction::LookAround; + else if s == "help" || s == "help me" { + Help } - - if let Some (rest) = s.strip_prefix ("look at the ") { - return PlayerAction::Look (parse_item_name (rest)); + else if s == "look" || s == "look around" { + RoomSpecific (LookAround) } - - if let Some (rest) = s.strip_prefix ("look at ") { - return PlayerAction::Look (parse_item_name (rest)); + else if let Some (rest) = s.strip_prefix ("look at the ") { + RoomSpecific (Look (parse_item_name (rest))) } - - if let Some (rest) = s.strip_prefix ("look ") { - return PlayerAction::Look (parse_item_name (rest)); + else if let Some (rest) = s.strip_prefix ("look at ") { + RoomSpecific (Look (parse_item_name (rest))) } - - if let Some (rest) = s.strip_prefix ("examine ") { - return PlayerAction::Look (parse_item_name (rest)); + else if let Some (rest) = s.strip_prefix ("look ") { + RoomSpecific (Look (parse_item_name (rest))) } - - if let Some (rest) = s.strip_prefix ("use the ") { - return PlayerAction::Use (parse_item_name (rest)); + else if let Some (rest) = s.strip_prefix ("examine ") { + RoomSpecific (Look (parse_item_name (rest))) } - - if let Some (rest) = s.strip_prefix ("use ") { - return PlayerAction::Use (parse_item_name (rest)); + else if let Some (rest) = s.strip_prefix ("use the ") { + RoomSpecific (Use (parse_item_name (rest))) } - - if s == "do nothing" { - return PlayerAction::Wait; + else if let Some (rest) = s.strip_prefix ("use ") { + RoomSpecific (Use (parse_item_name (rest))) } - if s == "wait" { - return PlayerAction::Wait; + else if + s == "do nothing" || + s == "wait" + { + RoomSpecific (Wait) } - - if s == "help" { - return PlayerAction::Help; + else if s == "hint" { + RoomSpecific (Hint) } - if s == "hint" { - return PlayerAction::Hint; + else { + Nonsense } - - PlayerAction::Nonsense } fn parse_item_name (s: &str) -> ItemName { if s == "door" { - return ItemName::Door; + ItemName::Door } - - if s == "emergency exit" { - return ItemName::EmergencyExit; + else if s == "emergency exit" { + ItemName::EmergencyExit } - - if s == "keypad" { - return ItemName::Keypad; + else if s == "keypad" { + ItemName::Keypad } - - if s == "note" { - return ItemName::Note; + else if s == "note" { + ItemName::Note } - - if s == "table" { - return ItemName::Table; + else if s == "table" { + ItemName::Table + } + else { + ItemName::Nonsense + } +} + +macro_rules! require_detection { + ($condition:expr $(,)?) => { + if ! $condition { + return vec! [ + Response::FailedDetectionCheck, + undetected_item (), + ]; + } + }; +} + +#[derive (Clone)] +enum RoomName { + /// Starting room with the dead-simple note and keypad puzzle. + Room1, + /// Duplicate of starting room so I can change things around a little. + Room2, +} + +impl Default for RoomName { + fn default () -> Self { + Self::Room1 } - - ItemName::Nonsense } #[derive (Clone, Default)] @@ -199,55 +221,41 @@ enum Response { FailedDetectionCheck, } -macro_rules! require_detection { - ($condition:expr $(,)?) => { - if ! $condition { - return vec! [ - Response::FailedDetectionCheck, - undetected_item (), - ]; - } - }; -} - #[derive (Clone, Default)] struct State { + current_room: RoomName, room_1: StateRoom1, } impl State { fn step (&mut self, input: &str) -> Vec { - self.room_1 (input) - } - - fn room_1 (&mut self, input: &str) -> Vec { - use Response::*; - let action = parse_input (input); match action { - PlayerAction::Quit => { - vec! [ - line_response ("Bye."), - Quit, - ] - } - PlayerAction::Help => { - just (print_help ()) - }, - PlayerAction::Hint => { + PlayerAction::Quit => vec! [ + line_response ("Bye."), + Response::Quit, + ], + PlayerAction::Help => just (print_help ()), + PlayerAction::Nonsense => vec! [ + line_response ("I couldn't understand that. Try `help` or `hint`."), + line_response ("`hint` may contain spoilers. `help` will not."), + ], + PlayerAction::RoomSpecific (x) => self.room_1 (x), + } + } + + fn room_1 (&mut self, action: PlayerActionRoomSpecific) -> Vec { + use PlayerActionRoomSpecific::*; + + match action { + Hint => { just (line_response ("Hint for this room: Try using the `help` command.")) }, - PlayerAction::Nonsense => { - vec! [ - line_response ("I couldn't understand that. Try `help` or `hint`."), - line_response ("`hint` may contain spoilers. `help` will not."), - ] - }, - PlayerAction::Wait => { + Wait => { just (line_response ("You wait around a bit. You can hear humming from the electrical lights, and the distant rumble of the building's HVAC system. The room smells faintly of fresh paint. Nothing has changed.")) }, - PlayerAction::LookAround => { + LookAround => { let mut output = vec! [ line_response ("You are in a small room. In one corner is a TABLE. Obvious exits are a DOOR, and an EMERGENCY EXIT."), ]; @@ -261,7 +269,7 @@ impl State { output } - PlayerAction::Look (item_name) => { + Look (item_name) => { match item_name { ItemName::Door => { self.room_1.detected_keypad = true; @@ -299,18 +307,14 @@ impl State { }, ItemName::Table => { self.room_1.detected_note = true; - vec! [ - Response::Print ("You look at the TABLE. Your instincts tell you that it is period-accurate. Upon the TABLE sits a NOTE.".into ()), - ] + just (line_response ("You look at the TABLE. Your instincts tell you that it is period-accurate. Upon the TABLE sits a NOTE.")) }, _ => { - vec! [ - undetected_item (), - ] + just (undetected_item ()) }, } }, - PlayerAction::Use (item_name) => { + Use (item_name) => { match item_name { ItemName::Door => { let mut output = vec! [ @@ -319,18 +323,18 @@ impl State { if ! self.room_1.detected_keypad { self.room_1.detected_keypad = true; - output.push (Response::Print ("You notice an electronic KEYPAD on the DOOR.".into ())); + output.push (line_response ("You notice an electronic KEYPAD on the DOOR.")); } output }, ItemName::EmergencyExit => { vec! [ - Response::Print ("You push on the emergency exit. An alarm starts sounding. Your ADVENTURE GAME ENTHUSIAST friend is going to be very mad at you.".into ()), + line_response ("You push on the emergency exit. An alarm starts sounding. Your ADVENTURE GAME ENTHUSIAST friend is going to be very mad at you."), Response::Sleep (5000), - Response::Print ("The alarm is still sounding. You are getting embarrassed, but you have committed to this path of action.".into ()), + line_response ("The alarm is still sounding. You are getting embarrassed, but you have committed to this path of action."), Response::Sleep (5000), - Response::Print ("The emergency exit unlocks, and you walk out of the game. Bye.".into ()), + line_response ("The emergency exit unlocks, and you walk out of the game. Bye."), Response::JokeEnding, Response::Quit, ] @@ -353,9 +357,7 @@ impl State { just (line_response ("You can't think of any way to USE the TABLE that would be better than LOOKing at it.")) }, _ => { - vec! [ - undetected_item (), - ] + just (undetected_item ()) }, } }, @@ -426,17 +428,18 @@ mod test { use super::{ ItemName, PlayerAction::*, + PlayerActionRoomSpecific::*, }; for (input, expected) in [ - ("", Nonsense), - ("look at the table", Look (ItemName::Table)), - ("look at table", Look (ItemName::Table)), - ("look table", Look (ItemName::Table)), - ("LOOK TABLE", Look (ItemName::Table)), - ("wait", Wait), - ("help", Help), - ("hint", Hint), + ("", Nonsense), + ("help", Help), + ("look at the table", RoomSpecific (Look (ItemName::Table))), + ("look at table", RoomSpecific (Look (ItemName::Table))), + ("look table", RoomSpecific (Look (ItemName::Table))), + ("LOOK TABLE", RoomSpecific (Look (ItemName::Table))), + ("wait", RoomSpecific (Wait)), + ("hint", RoomSpecific (Hint)), ].into_iter () { let actual = super::parse_input (input); assert_eq! (actual, expected);