♻️ refactor

main
_ 2021-10-24 23:00:47 +00:00
parent 1ddb5ffe18
commit 576cf0b4e5
1 changed files with 111 additions and 108 deletions

View File

@ -72,8 +72,13 @@ fn just <T> (t: T) -> Vec <T> {
enum PlayerAction { enum PlayerAction {
Quit, Quit,
Help, Help,
Hint,
Nonsense, Nonsense,
RoomSpecific (PlayerActionRoomSpecific),
}
#[derive (Debug, PartialEq)]
enum PlayerActionRoomSpecific {
Hint,
Wait, Wait,
Look (ItemName), Look (ItemName),
LookAround, LookAround,
@ -104,79 +109,96 @@ fn _item_name_display (x: ItemName) -> &'static str {
} }
fn parse_input (s: &str) -> PlayerAction { fn parse_input (s: &str) -> PlayerAction {
use PlayerAction::*;
use PlayerActionRoomSpecific::*;
let s = s.to_lowercase (); let s = s.to_lowercase ();
if s == "quit" || s == "quit game" { if s == "quit" || s == "quit game" {
return PlayerAction::Quit; Quit
} }
else if s == "help" || s == "help me" {
if s == "look" || s == "look around" { Help
return PlayerAction::LookAround;
} }
else if s == "look" || s == "look around" {
if let Some (rest) = s.strip_prefix ("look at the ") { RoomSpecific (LookAround)
return PlayerAction::Look (parse_item_name (rest));
} }
else if let Some (rest) = s.strip_prefix ("look at the ") {
if let Some (rest) = s.strip_prefix ("look at ") { RoomSpecific (Look (parse_item_name (rest)))
return PlayerAction::Look (parse_item_name (rest));
} }
else if let Some (rest) = s.strip_prefix ("look at ") {
if let Some (rest) = s.strip_prefix ("look ") { RoomSpecific (Look (parse_item_name (rest)))
return PlayerAction::Look (parse_item_name (rest));
} }
else if let Some (rest) = s.strip_prefix ("look ") {
if let Some (rest) = s.strip_prefix ("examine ") { RoomSpecific (Look (parse_item_name (rest)))
return PlayerAction::Look (parse_item_name (rest));
} }
else if let Some (rest) = s.strip_prefix ("examine ") {
if let Some (rest) = s.strip_prefix ("use the ") { RoomSpecific (Look (parse_item_name (rest)))
return PlayerAction::Use (parse_item_name (rest));
} }
else if let Some (rest) = s.strip_prefix ("use the ") {
if let Some (rest) = s.strip_prefix ("use ") { RoomSpecific (Use (parse_item_name (rest)))
return PlayerAction::Use (parse_item_name (rest));
} }
else if let Some (rest) = s.strip_prefix ("use ") {
if s == "do nothing" { RoomSpecific (Use (parse_item_name (rest)))
return PlayerAction::Wait;
} }
if s == "wait" { else if
return PlayerAction::Wait; s == "do nothing" ||
s == "wait"
{
RoomSpecific (Wait)
} }
else if s == "hint" {
if s == "help" { RoomSpecific (Hint)
return PlayerAction::Help;
} }
if s == "hint" { else {
return PlayerAction::Hint; Nonsense
} }
PlayerAction::Nonsense
} }
fn parse_item_name (s: &str) -> ItemName { fn parse_item_name (s: &str) -> ItemName {
if s == "door" { if s == "door" {
return ItemName::Door; ItemName::Door
} }
else if s == "emergency exit" {
if s == "emergency exit" { ItemName::EmergencyExit
return ItemName::EmergencyExit;
} }
else if s == "keypad" {
if s == "keypad" { ItemName::Keypad
return ItemName::Keypad;
} }
else if s == "note" {
if s == "note" { ItemName::Note
return ItemName::Note;
} }
else if s == "table" {
if s == "table" { ItemName::Table
return ItemName::Table;
} }
else {
ItemName::Nonsense
}
}
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
}
} }
#[derive (Clone, Default)] #[derive (Clone, Default)]
@ -199,55 +221,41 @@ enum Response {
FailedDetectionCheck, FailedDetectionCheck,
} }
macro_rules! require_detection {
($condition:expr $(,)?) => {
if ! $condition {
return vec! [
Response::FailedDetectionCheck,
undetected_item (),
];
}
};
}
#[derive (Clone, Default)] #[derive (Clone, Default)]
struct State { struct State {
current_room: RoomName,
room_1: StateRoom1, room_1: StateRoom1,
} }
impl State { impl State {
fn step (&mut self, input: &str) -> Vec <Response> { fn step (&mut self, input: &str) -> Vec <Response> {
self.room_1 (input)
}
fn room_1 (&mut self, input: &str) -> Vec <Response> {
use Response::*;
let action = parse_input (input); let action = parse_input (input);
match action { match action {
PlayerAction::Quit => { PlayerAction::Quit => vec! [
vec! [ line_response ("Bye."),
line_response ("Bye."), Response::Quit,
Quit, ],
] PlayerAction::Help => just (print_help ()),
} PlayerAction::Nonsense => vec! [
PlayerAction::Help => { line_response ("I couldn't understand that. Try `help` or `hint`."),
just (print_help ()) line_response ("`hint` may contain spoilers. `help` will not."),
}, ],
PlayerAction::Hint => { PlayerAction::RoomSpecific (x) => self.room_1 (x),
}
}
fn room_1 (&mut self, action: PlayerActionRoomSpecific) -> Vec <Response> {
use PlayerActionRoomSpecific::*;
match action {
Hint => {
just (line_response ("Hint for this room: Try using the `help` command.")) just (line_response ("Hint for this room: Try using the `help` command."))
}, },
PlayerAction::Nonsense => { Wait => {
vec! [
line_response ("I couldn't understand that. Try `help` or `hint`."),
line_response ("`hint` may contain spoilers. `help` will not."),
]
},
PlayerAction::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.")) 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! [ 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."), 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 output
} }
PlayerAction::Look (item_name) => { Look (item_name) => {
match item_name { match item_name {
ItemName::Door => { ItemName::Door => {
self.room_1.detected_keypad = true; self.room_1.detected_keypad = true;
@ -299,18 +307,14 @@ impl State {
}, },
ItemName::Table => { ItemName::Table => {
self.room_1.detected_note = true; self.room_1.detected_note = true;
vec! [ just (line_response ("You look at the TABLE. Your instincts tell you that it is period-accurate. Upon the TABLE sits a NOTE."))
Response::Print ("You look at the TABLE. Your instincts tell you that it is period-accurate. Upon the TABLE sits a NOTE.".into ()),
]
}, },
_ => { _ => {
vec! [ just (undetected_item ())
undetected_item (),
]
}, },
} }
}, },
PlayerAction::Use (item_name) => { Use (item_name) => {
match item_name { match item_name {
ItemName::Door => { ItemName::Door => {
let mut output = vec! [ let mut output = vec! [
@ -319,18 +323,18 @@ impl State {
if ! self.room_1.detected_keypad { if ! self.room_1.detected_keypad {
self.room_1.detected_keypad = true; 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 output
}, },
ItemName::EmergencyExit => { ItemName::EmergencyExit => {
vec! [ 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::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::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::JokeEnding,
Response::Quit, 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.")) just (line_response ("You can't think of any way to USE the TABLE that would be better than LOOKing at it."))
}, },
_ => { _ => {
vec! [ just (undetected_item ())
undetected_item (),
]
}, },
} }
}, },
@ -426,17 +428,18 @@ mod test {
use super::{ use super::{
ItemName, ItemName,
PlayerAction::*, PlayerAction::*,
PlayerActionRoomSpecific::*,
}; };
for (input, expected) in [ for (input, expected) in [
("", Nonsense), ("", Nonsense),
("look at the table", Look (ItemName::Table)), ("help", Help),
("look at table", Look (ItemName::Table)), ("look at the table", RoomSpecific (Look (ItemName::Table))),
("look table", Look (ItemName::Table)), ("look at table", RoomSpecific (Look (ItemName::Table))),
("LOOK TABLE", Look (ItemName::Table)), ("look table", RoomSpecific (Look (ItemName::Table))),
("wait", Wait), ("LOOK TABLE", RoomSpecific (Look (ItemName::Table))),
("help", Help), ("wait", RoomSpecific (Wait)),
("hint", Hint), ("hint", RoomSpecific (Hint)),
].into_iter () { ].into_iter () {
let actual = super::parse_input (input); let actual = super::parse_input (input);
assert_eq! (actual, expected); assert_eq! (actual, expected);