use crate::error::WumpError;
use crate::map::dodecahedron::{Dodecahedron, Payload, Polyhedron, Vertex};
pub use crate::map::dodecahedron::{VertexKey, VertexMap};
use crate::map::room::{initialize_room_map, RoomMap};
use crate::Args;
use anyhow::Result;
pub use room::Room;
use slotmap::{SecondaryMap, SlotMap};
use std::any::Any;
mod dodecahedron;
mod room;
impl Payload for () {
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Debug, Default)]
pub struct WumpusMap {
room_map: RoomMap,
vertex_map: VertexMap<()>,
vertices: Vec<VertexKey>,
}
impl WumpusMap {
pub fn new() -> Self {
let mut vertex_map = SlotMap::with_key();
let polyhedron = Dodecahedron::create(&mut vertex_map);
let mut room_map = SecondaryMap::new();
initialize_room_map(polyhedron.as_slice(), &mut room_map);
let vertices = polyhedron.as_slice().to_vec();
Self {
vertex_map,
room_map,
vertices,
}
}
pub fn try_get_vertex(&self, key: &VertexKey) -> Result<&Vertex<()>> {
Ok(self
.vertex_map
.get(*key)
.ok_or(WumpError::UnknownVertexKey(key.clone()))?)
}
pub fn get_vertex(&self, key: &VertexKey) -> &Vertex<()> {
self.try_get_vertex(key).unwrap()
}
pub fn len(&self) -> usize {
self.vertices.len()
}
pub fn as_slice(&self) -> &[VertexKey] {
&self.vertices
}
pub fn _rooms(&self) -> Vec<Room> {
self.vertices
.iter()
.map(|&key| self.room_map[key].clone())
.collect()
}
pub fn _get_neighboring_rooms(&self, key: &VertexKey) -> Vec<Room> {
self.try_get_neighboring_rooms(key).unwrap()
}
pub fn try_get_neighboring_rooms(&self, key: &VertexKey) -> Result<Vec<Room>> {
let vertex = self.try_get_vertex(key)?;
Ok(vertex
.neighbors()
.iter()
.map(|v| self.try_get_room(v).cloned())
.collect::<Result<Vec<_>>>()?)
}
pub fn get_room(&self, key: &VertexKey) -> &Room {
self.try_get_room(key).unwrap()
}
pub fn try_get_room(&self, key: &VertexKey) -> Result<&Room> {
Ok(self
.room_map
.get(*key)
.ok_or(WumpError::UnknownVertexKey(key.clone()))?)
}
pub fn get_room_from_room_number(&self, room_number: usize) -> Result<&Room> {
if let Some(vertex) = self.vertices.get(room_number - 1) {
self.try_get_room(vertex)
} else {
Err(WumpError::UnknownRoom(room_number))?
}
}
}
pub fn generate_map(_config: &Args) -> WumpusMap {
WumpusMap::new()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_wumpus_map() {
let wumpus_map = WumpusMap::new();
let vertex_map = &wumpus_map.vertex_map;
let room_map = &wumpus_map.room_map;
assert_eq!(vertex_map.len(), 20);
assert_eq!(room_map.len(), 20);
}
}