kingslayer 0.5.5

A text adventure dungeon crawler game written in Rust
Documentation
use crate::{
    cli::Cli,
    input::CmdTokens,
    player::Player,
    types::{Action, CmdResult},
    world::World,
};

#[derive(Debug)]
pub struct Parser;

impl Parser {
    fn parse_attack(
        verb: &str,
        words: &CmdTokens,
        world: &mut World,
        player: &mut Player,
    ) -> CmdResult {
        if let Some(obj) = words.obj() {
            if let Some(obj_prep) = words.obj_prep() {
                if words.prep() == Some(&String::from("with")) {
                    let res = world.harm_enemy(obj, player.attack_with(obj_prep));
                    if res.is_active() {
                        player.engage_combat()
                    }
                    res
                } else {
                    CmdResult::no_comprendo()
                }
            } else if player.main_hand().is_some() {
                let res = world.harm_enemy(obj, player.attack_main());
                if res.is_active() {
                    player.engage_combat()
                }
                res
            } else {
                CmdResult::do_what(&format!("{} the {} with", verb, obj))
                    .with_request_input(CmdTokens::new(verb).with_obj(obj).with_prep("with"))
            }
        } else {
            CmdResult::do_what_prep(verb, words.prep(), words.obj_prep())
        }
    }

    fn parse_close(
        verb: &str,
        words: &CmdTokens,
        world: &mut World,
        player: &mut Player,
    ) -> CmdResult {
        if let Some(obj) = words.obj() {
            if let Some(res) = player.close(obj) {
                res
            } else {
                world.close(obj)
            }
        } else {
            CmdResult::do_what(verb)
        }
    }

    fn parse_don(verb: &str, words: &CmdTokens, player: &mut Player) -> CmdResult {
        if let Some(obj) = words.obj() {
            player.don_armor(obj)
        } else {
            CmdResult::do_what(verb)
        }
    }

    fn parse_drop(
        verb: &str,
        words: &CmdTokens,
        world: &mut World,
        player: &mut Player,
    ) -> CmdResult {
        if let Some(obj) = words.obj() {
            world.insert(obj, player.remove(obj))
        } else {
            CmdResult::do_what(verb)
        }
    }

    fn parse_equip(verb: &str, words: &CmdTokens, player: &mut Player) -> CmdResult {
        if let Some(obj) = words.obj() {
            player.equip(obj)
        } else {
            CmdResult::do_what(verb)
        }
    }

    fn parse_hail(words: &CmdTokens, world: &mut World) -> CmdResult {
        if let Some(obj) = words.obj() {
            world.hail(obj)
        } else {
            CmdResult::new(Action::Passive, "Hello, sailor!")
        }
    }

    fn parse_increase(words: &CmdTokens, player: &mut Player) -> CmdResult {
        if let Some(obj) = words.obj() {
            player.increase_ability_score(obj)
        } else {
            CmdResult::do_what(
                "increase?
                    \r(strength, dexterity, constitution, intellect, wisdom, charisma)",
            )
        }
    }

    fn parse_move(verb: &str, words: &CmdTokens, world: &mut World) -> CmdResult {
        if let Some(obj) = words.obj() {
            world.move_room(obj)
        } else {
            CmdResult::new(Action::Passive, format!("Where do you want to {}?", verb))
                .with_request_input(CmdTokens::new(verb))
        }
    }

    fn parse_unlock(verb: &str, words: &CmdTokens, world: &mut World) -> CmdResult {
        if let Some(obj) = words.obj() {
            world.unlock(obj)
        } else {
            CmdResult::do_what(verb)
        }
    }

    fn parse_open(
        verb: &str,
        words: &CmdTokens,
        world: &mut World,
        player: &mut Player,
    ) -> CmdResult {
        if let Some(obj) = words.obj() {
            if let Some(res) = player.open(obj) {
                res
            } else {
                world.open(obj)
            }
        } else {
            CmdResult::do_what(verb)
        }
    }

    fn parse_put(
        words: &CmdTokens,
        verb: &str,
        world: &mut World,
        player: &mut Player,
    ) -> CmdResult {
        if let Some(prep) = words.prep() {
            match prep {
                "in" | "inside" => {
                    if let Some(obj) = words.obj() {
                        if let Some(obj_prep) = words.obj_prep() {
                            if player.has(obj_prep) {
                                player.insert_into(obj, obj_prep)
                            } else {
                                let (res, rejected_item) =
                                    world.insert_into(obj, obj_prep, player.remove(obj));
                                if let Some(item) = rejected_item {
                                    player.take_back(item);
                                }
                                res
                            }
                        } else {
                            CmdResult::do_what(&format!("place in the {}", obj)).with_request_input(
                                CmdTokens::new("place").with_obj(obj).with_prep("in"),
                            )
                        }
                    } else {
                        CmdResult::do_what(verb)
                    }
                }
                "on" => {
                    if let Some(obj_prep) = words.obj_prep() {
                        player.don_armor(obj_prep)
                    } else {
                        CmdResult::do_what(&format!("{} on", verb))
                    }
                }
                _ => CmdResult::no_comprendo(),
            }
        } else if let Some(obj) = words.obj() {
            CmdResult::do_what(&format!("{} the {} in", verb, obj))
                .with_request_input(CmdTokens::new("put").with_obj(obj).with_prep("in"))
        } else {
            CmdResult::do_what_prep(verb, words.prep(), words.obj_prep())
        }
    }

    fn parse_take(
        verb: &str,
        words: &CmdTokens,
        world: &mut World,
        player: &mut Player,
    ) -> CmdResult {
        if let Some(obj) = words.obj() {
            if let Some(prep) = words.prep() {
                if prep == "from" || prep == "out" || prep == "in" {
                    if let Some(obj_prep) = words.obj_prep() {
                        if player.has(obj_prep) {
                            player.take_from_self(obj, obj_prep)
                        } else {
                            player.take_item_from(world.give_from(obj, obj_prep))
                        }
                    } else {
                        CmdResult::do_what(&format!("{} the {} from", verb, obj))
                            .with_request_input(
                                CmdTokens::new("take").with_obj(obj).with_prep("from"),
                            )
                    }
                } else {
                    CmdResult::no_comprendo()
                }
            } else if obj == "all" || obj.len() >= 4 && obj.starts_with("all ") {
                player.take_all(world.give_all())
            } else {
                player.take(obj, world.give(obj))
            }
        } else {
            CmdResult::do_what_prep(verb, words.prep(), words.obj_prep())
        }
    }

    fn parse_x(verb: &str, words: &CmdTokens, world: &mut World, player: &mut Player) -> CmdResult {
        if let Some(obj) = words.obj() {
            if let Some(s) = player.inspect(obj) {
                s
            } else if let Some(s) = world.inspect(obj) {
                s
            } else {
                CmdResult::no_item_here(obj)
            }
        } else {
            CmdResult::do_what(verb)
        }
    }

    pub fn parse(words: &CmdTokens, world: &mut World, player: &mut Player) -> CmdResult {
        if let (Some(verb), Some(short_verb)) = words.short_verb() {
            match short_verb {
                "north" | "south" | "east" | "west" | "northeast" | "northwest" | "southeast"
                | "southwest" | "up" | "down" => world.move_room(verb),
                "enter" | "go" | "move" | "exit" => Parser::parse_move(verb, words, world),
                "c" | "stat" | "stats" => player.info(),
                "i" | "invent" => player.print_inventory(),
                "l" | "look" => world.look(),
                "attack" | "cut" | "hit" | "kill" | "slay" => {
                    Parser::parse_attack(verb, words, world, player)
                }
                "heal" | "rest" | "sleep" => player.rest(),
                "hail" | "talk" | "hi" | "hello" | "greet" => Parser::parse_hail(words, world),
                "cast" | "use" => {
                    CmdResult::new(Action::Passive, String::from("TODO: cast something"))
                }
                "close" => Parser::parse_close(verb, words, world, player),
                "don" | "wear" => Parser::parse_don(verb, words, player),
                "draw" | "equip" | "hold" => Parser::parse_equip(verb, words, player),
                "drop" | "remove" | "throw" => Parser::parse_drop(verb, words, world, player),
                "examin" | "inspec" | "read" | "search" | "x" => {
                    Parser::parse_x(verb, words, world, player)
                }
                "get" | "take" => Parser::parse_take(verb, words, world, player),
                "increa" => Parser::parse_increase(words, player),
                "lock" => CmdResult::new(Action::Passive, String::from("TODO: lock something")),
                "open" => Parser::parse_open(verb, words, world, player),
                "insert" | "place" | "put" => Parser::parse_put(words, verb, world, player),
                "unlock" | "pick" => Parser::parse_unlock(verb, words, world),
                "wait" | "z" => Player::wait(),
                "help" => Cli::help(),
                _ => CmdResult::new(
                    Action::Failed,
                    format!("I do not know the word \"{}\".", verb),
                ),
            }
        } else {
            CmdResult::no_comprendo()
        }
    }
}