clige_rs/
lib.rs

1//! Main library for the engine.
2//! Exports all necessary modules and adds useful utilities
3
4pub mod error;
5pub mod game;
6
7pub use error::*;
8pub use game::*;
9
10fn clear_console() {
11    print!("{}c", 27 as char);
12}
13
14fn lose_screen(score: i32) {
15    color_print::cprintln!(
16        "\
17You've <red, bold>lost!</> You scored: <yellow, bold>{}",
18        score
19    );
20}
21
22fn win_screen(score: i32) {
23    color_print::cprintln!(
24        "\
25You've <green, bold>won!</> You scored: <yellow, bold>{}",
26        score
27    );
28}
29
30fn draw_input_hint() {
31    color_print::cprintln!(
32        "\
33What do you want to do?
34Type <cyan, bold>action <<id>></>. To view possible actions, type <red, bold>help."
35    );
36}
37
38fn draw_actions_hint() {
39    color_print::cprintln!(
40        "\
41Available actions: <cyan, bold>
42attack
43throw
44equip
45eat
46enter"
47    );
48}
49
50/// Reads line from `stdin`, then tries to parse it into action.
51/// If the action provided isn't valid, it reads another line.
52/// ### Panics
53/// Function panics if it can't open `stdin`.
54fn get_user_input() -> (Action, i32) {
55    loop {
56        let mut input = String::new();
57
58        std::io::stdin()
59            .read_line(&mut input)
60            .expect("Can't open stdin.");
61
62        match parse_input(&input) {
63            Ok((Action::Help, _)) => draw_actions_hint(),
64            Ok(action) => break action,
65            Err(e) => println!("Error occured: {}. Please try again.", e),
66        }
67    }
68}
69
70/// This function tries to parse `input` into pair of action and target.
71/// If the action is `help`, it doesn't read the target, returning `0`.
72///
73/// Function skips any tokens after succesfully parsing.
74fn parse_input(input: &str) -> Result<(Action, i32), String> {
75    let mut tokens = input.split_ascii_whitespace();
76    match tokens.next() {
77        Some("help") => Ok((Action::Help, 0)),
78        Some(token) => {
79            let action = action_of_str(token)?;
80            let id: i32 = match tokens.next() {
81                Some(s) => match s.parse() {
82                    Ok(n) => n,
83                    _ => return Err(format!("Invalid target: {}", s)),
84                },
85                None => return Err(format!("Provide a target")),
86            };
87            Ok((action, id))
88        }
89        None => Err(format!("Provide an action")),
90    }
91}
92
93/// Parses `str` into `Action`.
94fn action_of_str(s: &str) -> Result<Action, String> {
95    match s {
96        "attack" => Ok(Action::Attack),
97        "equip" => Ok(Action::Equip),
98        "throw" => Ok(Action::Throw),
99        "eat" => Ok(Action::Eat),
100        "enter" => Ok(Action::Enter),
101        "help" => Ok(Action::Help),
102        _ => Err(color_print::cformat!("Unknown action: <red, bold>{}</>", s)),
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn parse_test() {
112        assert_eq!(parse_input("attack 4").unwrap(), (Action::Attack, 4));
113        assert_eq!(
114            parse_input("test").unwrap_err(),
115            color_print::cformat!("Unknown action: <red, bold>test</>")
116        );
117    }
118}