kingslayer 0.5.5

A text adventure dungeon crawler game written in Rust
Documentation
use rayon::prelude::*;

use serde::{Deserialize, Serialize};

use super::{Closeable, DoorLock, Durability, Entity, Lockable, Opening};
use crate::{
    dice_roll,
    types::{Action, CmdResult},
};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Pathway {
    directions: Vec<String>,
    target: String,
    #[serde(default)]
    desc: String,
    #[serde(default)]
    inspect: String,
    opening: Option<Opening>,
    lock: Option<DoorLock>,
    #[serde(default)]
    durability: Durability,
}

impl Pathway {
    pub fn long_desc(&self) -> String {
        if let Some(opening) = self.opening {
            match opening {
                Opening::Open => format!("{} The way is open.", self.desc),
                Opening::Closed => format!("{} The way is shut.", self.desc),
            }
        } else {
            self.desc.to_owned()
        }
    }

    pub fn any_direction(&self, dir_name: &str) -> bool {
        if cfg!(target_arch = "wasm32") {
            self.directions
                .iter()
                .map(|direction| direction.split_whitespace().collect())
                .any(|direction: Vec<&str>| {
                    dir_name
                        .par_split_whitespace()
                        .all(|ref word| direction.contains(word))
                })
        } else {
            self.directions
                .par_iter()
                .map(|direction| direction.par_split_whitespace().collect())
                .any(|direction: Vec<&str>| {
                    dir_name
                        .par_split_whitespace()
                        .all(|ref word| direction.contains(word))
                })
        }
    }
}

impl Entity for Pathway {
    fn name(&self) -> &str {
        &self.target
    }

    fn desc(&self) -> &str {
        &self.desc
    }

    fn inspect(&self) -> &str {
        &self.inspect
    }
}

impl Closeable for Pathway {
    fn open(&mut self) -> CmdResult {
        if let Some(opening) = self.opening {
            if opening.is_closed() {
                self.opening = Some(Opening::Open);
                CmdResult::new(Action::Active, "Opened.")
            } else {
                CmdResult::new(Action::Passive, String::from("The way is already open."))
            }
        } else {
            CmdResult::new(Action::Passive, String::from("The way is already open."))
        }
    }

    fn close(&mut self) -> CmdResult {
        if let Some(opening) = self.opening {
            if opening.is_open() {
                self.opening = Some(Opening::Closed);
                CmdResult::new(Action::Active, "Closed.")
            } else {
                CmdResult::new(Action::Passive, String::from("The way cannot be closed."))
            }
        } else {
            CmdResult::new(Action::Passive, String::from("The way cannot be closed."))
        }
    }

    fn is_closed(&self) -> bool {
        if let Some(opening) = self.opening {
            opening.is_closed()
        } else {
            false
        }
    }
}

impl Lockable for Pathway {
    fn unlock(&mut self) -> CmdResult {
        if let Some(lock) = &self.lock {
            if lock.is_locked() {
                if dice_roll(1, 20) > 10 {
                    self.lock = Some(DoorLock::Unlocked);
                    CmdResult::new(Action::Active, "Unlocked.")
                } else {
                    CmdResult::new(
                        Action::Active,
                        "You failed to pick the lock. This is harder than it looks.",
                    )
                }
            } else {
                CmdResult::new(
                    Action::Passive,
                    String::from("The way is already unlocked."),
                )
            }
        } else {
            CmdResult::new(
                Action::Passive,
                String::from("The way is already unlocked."),
            )
        }
    }

    fn lock(&mut self) -> CmdResult {
        CmdResult::new(Action::Passive, "TODO: lock it")
    }

    fn is_locked(&self) -> bool {
        if let Some(lock) = &self.lock {
            lock.is_locked()
        } else {
            false
        }
    }
}