♻️ 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 {
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
}
}
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)]
@ -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 <Response> {
self.room_1 (input)
}
fn room_1 (&mut self, input: &str) -> Vec <Response> {
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 <Response> {
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);