use serde::{Deserialize, Serialize};
use crate::{
entity::{Closeable, Element, Enemy, Entity, Item, Lockable, Room},
types::{Action, Attack, CmdResult, Items, Rooms},
};
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct World {
curr_room: String,
rooms: Rooms,
}
impl World {
pub fn get_curr_room(&self) -> &Room {
if let Some(room) = self.rooms.get(&self.curr_room) {
room
} else {
panic!(
"ERROR: {} is not a valid room (The world should be fixed).",
self.curr_room
)
}
}
pub fn get_curr_room_mut(&mut self) -> &mut Room {
if let Some(room) = self.rooms.get_mut(&self.curr_room) {
room
} else {
panic!(
"ERROR: {} is not a valid room (The world should be fixed).",
self.curr_room
)
}
}
fn get_room_mut(&mut self, room_name: &str) -> &mut Room {
if let Some(room) = self.rooms.get_mut(room_name) {
room
} else {
panic!(
"ERROR: {} is not a valid room (The world should be fixed).",
room_name
)
}
}
pub fn look(&self) -> CmdResult {
CmdResult::new(Action::Active, self.get_curr_room().long_desc())
}
pub fn inspect(&self, name: &str) -> Option<CmdResult> {
self.get_curr_room().inspect(name)
}
pub fn any_angry_enemies(&self) -> bool {
for enemy in self.get_curr_room().enemies() {
if enemy.is_angry() {
return true;
}
}
false
}
pub fn move_room(&mut self, direction: &str) -> CmdResult {
if let Some(path) = self.get_curr_room().find_path(direction) {
if path.is_closed() {
CmdResult::new(Action::Active, "The way is shut.")
} else if path.is_locked() {
CmdResult::is_locked(direction)
} else if self.any_angry_enemies() {
CmdResult::new(Action::Passive, "Enemies bar your way.")
} else {
self.curr_room = path.name().to_owned();
self.look()
}
} else {
CmdResult::new(Action::Passive, "You cannot go that way.")
}
}
pub fn unlock(&mut self, name: &str) -> CmdResult {
self.get_curr_room_mut().unlock(name)
}
pub fn open(&mut self, name: &str) -> CmdResult {
self.get_curr_room_mut().open(name)
}
pub fn close(&mut self, name: &str) -> CmdResult {
self.get_curr_room_mut().close(name)
}
pub fn clear_dead_enemies(&mut self) {
self.get_curr_room_mut()
.enemies_mut()
.retain(|e| e.is_alive());
}
pub fn harm_enemy(&mut self, enemy_name: &str, attack: Attack) -> CmdResult {
self.get_curr_room_mut().harm_enemy(enemy_name, attack)
}
pub fn give(&mut self, name: &str) -> Option<Box<Item>> {
self.get_curr_room_mut().remove_item(name)
}
pub fn give_from(
&mut self,
item_name: &str,
container_name: &str,
) -> Result<Box<Item>, CmdResult> {
self.get_curr_room_mut()
.give_from(item_name, container_name)
}
pub fn give_all(&mut self) -> Items {
self.get_curr_room_mut().drain_all()
}
pub fn insert(&mut self, name: &str, item: Option<Box<Item>>) -> CmdResult {
self.get_curr_room_mut().take_item(name, item)
}
pub fn insert_into(
&mut self,
item_name: &str,
container_name: &str,
item: Option<Box<Item>>,
) -> (CmdResult, Option<Box<Item>>) {
self.get_curr_room_mut()
.insert_into(item_name, container_name, item)
}
pub fn hail(&self, ally_name: &str) -> CmdResult {
self.get_curr_room().hail(ally_name)
}
pub fn add_element(&mut self, room: &str, el: Element) {
self.get_room_mut(room).add_element(el);
}
pub fn add_item(&mut self, room: &str, item: Item) {
self.get_room_mut(room).add_item(item);
}
pub fn spawn_enemy(&mut self, room: &str, enemy: Enemy) {
self.get_room_mut(room).spawn_enemy(enemy);
}
}