♻️ refactor
parent
1ddb5ffe18
commit
576cf0b4e5
209
src/main.rs
209
src/main.rs
|
@ -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,80 +109,97 @@ 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)]
|
||||||
struct StateRoom1 {
|
struct StateRoom1 {
|
||||||
|
@ -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."),
|
||||||
Quit,
|
Response::Quit,
|
||||||
]
|
],
|
||||||
}
|
PlayerAction::Help => just (print_help ()),
|
||||||
PlayerAction::Help => {
|
PlayerAction::Nonsense => vec! [
|
||||||
just (print_help ())
|
|
||||||
},
|
|
||||||
PlayerAction::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 ("I couldn't understand that. Try `help` or `hint`."),
|
||||||
line_response ("`hint` may contain spoilers. `help` will not."),
|
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::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."))
|
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)),
|
|
||||||
("look at table", Look (ItemName::Table)),
|
|
||||||
("look table", Look (ItemName::Table)),
|
|
||||||
("LOOK TABLE", Look (ItemName::Table)),
|
|
||||||
("wait", Wait),
|
|
||||||
("help", Help),
|
("help", Help),
|
||||||
("hint", Hint),
|
("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 () {
|
].into_iter () {
|
||||||
let actual = super::parse_input (input);
|
let actual = super::parse_input (input);
|
||||||
assert_eq! (actual, expected);
|
assert_eq! (actual, expected);
|
||||||
|
|
Loading…
Reference in New Issue