diff --git a/demo/src/lib.rs b/demo/src/lib.rs index df221f9..ab93937 100644 --- a/demo/src/lib.rs +++ b/demo/src/lib.rs @@ -1,7 +1,7 @@ use wasm_bindgen::prelude::*; use web_sys; use rand::prelude::*; -use mapgen::{Map, MapBuilder, TileType, geometry::Point}; +use mapgen::{Map, MapBuilder, geometry::Point}; use mapgen::filter::*; use mapgen::metric; @@ -34,7 +34,7 @@ impl World { fn new(width: u32, height: u32, map: Map) -> World { let tiles = (0..map.tiles.len()) - .map(|i| if map.tiles[i] == TileType::Floor {Cell::Floor} else {Cell::Wall}) + .map(|i| if map.tiles[i].is_walkable() {Cell::Floor} else {Cell::Wall}) .collect(); World { width, height, tiles, map } } diff --git a/src/filter/bsp_interior.rs b/src/filter/bsp_interior.rs index a700584..996f01f 100644 --- a/src/filter/bsp_interior.rs +++ b/src/filter/bsp_interior.rs @@ -114,7 +114,7 @@ impl BspInterior { #[cfg(test)] mod tests { use super::*; - use crate::{TileType, Map}; + use crate::{Map}; #[test] fn no_corridors_on_borders() { @@ -122,12 +122,12 @@ mod tests { let gen = BspInterior::new(); let map = gen.modify_map(&mut rng, &Map::new(80, 50)); for i in 0..80 { - assert_eq!(map.at(i, 0), TileType::Wall); - assert_eq!(map.at(i, 49), TileType::Wall); + assert!(map.at(i, 0).is_blocked()); + assert!(map.at(i, 49).is_blocked()); } for j in 0..50 { - assert_eq!(map.at(0, j), TileType::Wall); - assert_eq!(map.at(79, j), TileType::Wall); + assert!(map.at(0, j).is_blocked()); + assert!(map.at(79, j).is_blocked()); } } diff --git a/src/filter/bsp_rooms.rs b/src/filter/bsp_rooms.rs index c459f4a..8028eda 100644 --- a/src/filter/bsp_rooms.rs +++ b/src/filter/bsp_rooms.rs @@ -22,7 +22,7 @@ use rand::prelude::*; use crate::MapFilter; use crate::geometry::Rect; use crate::random::Rng; -use crate::{Map, TileType}; +use crate::Map; pub struct BspRooms { @@ -122,7 +122,7 @@ impl BspRooms { if x < 1 { can_build = false; } if y < 1 { can_build = false; } if can_build { - if map.at(x as usize, y as usize) != TileType::Wall { + if map.at(x as usize, y as usize).is_walkable() { can_build = false; } } @@ -147,12 +147,12 @@ mod tests { let gen = BspRooms::new(); let map = gen.modify_map(&mut rng, &Map::new(80, 50)); for i in 0..80 { - assert_eq!(map.at(i, 0), TileType::Wall); - assert_eq!(map.at(i, 49), TileType::Wall); + assert!(map.at(i, 0).is_blocked()); + assert!(map.at(i, 49).is_blocked()); } for j in 0..50 { - assert_eq!(map.at(0, j), TileType::Wall); - assert_eq!(map.at(79, j), TileType::Wall); + assert!(map.at(0, j).is_blocked()); + assert!(map.at(79, j).is_blocked()); } } diff --git a/src/filter/cellular_automata.rs b/src/filter/cellular_automata.rs index 24728ed..365ab61 100644 --- a/src/filter/cellular_automata.rs +++ b/src/filter/cellular_automata.rs @@ -23,7 +23,7 @@ use rand::prelude::*; use crate::MapFilter; -use crate::{Map, TileType}; +use crate::{Map, Tile}; /// Map filter @@ -65,14 +65,14 @@ fn apply_iteration(map: &Map) -> Map { (x-1, y), (x+1, y), (x-1, y+1), (x, y+1), (x+1, y+1)]; let neighbors = idxs.iter() - .filter(|(x, y)| map.at(*x, *y) == TileType::Wall) + .filter(|(x, y)| map.at(*x, *y).is_blocked()) .count(); if neighbors > 4 || neighbors == 0 { - new_map.set_tile(x, y, TileType::Wall) + new_map.set_tile(x, y, Tile::wall()) } else { - new_map.set_tile(x, y, TileType::Floor); + new_map.set_tile(x, y, Tile::floor()); } } } @@ -91,7 +91,7 @@ mod tests { fn test_iteration_wal() { let map = Map::new(3, 3); let new_map = apply_iteration(&map); - assert_eq!(new_map.at(1, 1), TileType::Wall); + assert!(new_map.at(1, 1).is_blocked()); } @@ -100,11 +100,11 @@ mod tests { let mut map = Map::new(3, 3); for i in 0..3 { for j in 0..2 { - map.set_tile(i, j, TileType::Floor); + map.set_tile(i, j, Tile::floor()); } } let new_map = apply_iteration(&map); - assert_eq!(new_map.at(1, 1), TileType::Floor); + assert!(new_map.at(1, 1).is_walkable()); } } \ No newline at end of file diff --git a/src/filter/cull_unreachable.rs b/src/filter/cull_unreachable.rs index e5b1390..6f8c6e8 100644 --- a/src/filter/cull_unreachable.rs +++ b/src/filter/cull_unreachable.rs @@ -6,7 +6,7 @@ use rand::prelude::StdRng; use crate::MapFilter; -use crate::{Map, TileType}; +use crate::{Map, Tile}; use crate::dijkstra::DijkstraMap; @@ -30,11 +30,11 @@ impl CullUnreachable { let dijkstra_map = DijkstraMap::new(map); for (i, tile) in new_map.tiles.iter_mut().enumerate() { - if *tile == TileType::Floor { + if tile.is_walkable() { let distance_to_start = dijkstra_map.tiles[i]; // We can't get to this tile - so we'll make it a wall if distance_to_start == std::f32::MAX { - *tile = TileType::Wall; + *tile = Tile::wall(); } } } diff --git a/src/filter/drunkard.rs b/src/filter/drunkard.rs index 3c45e05..9c8b341 100644 --- a/src/filter/drunkard.rs +++ b/src/filter/drunkard.rs @@ -16,7 +16,7 @@ use rand::prelude::*; use crate::MapFilter; use crate::{ - map::{Map, Symmetry, TileType}, + map::{Map, Symmetry, Tile}, geometry::Point, random::Rng }; @@ -79,11 +79,11 @@ impl DrunkardsWalk { let mut new_map = map.clone(); // Set a central starting point let starting_position = Point::new( new_map.width / 2, new_map.height / 2 ); - new_map.set_tile(starting_position.x, starting_position.y, TileType::Floor); + new_map.set_tile(starting_position.x, starting_position.y, Tile::floor()); let total_tiles = new_map.width * new_map.height; let desired_floor_tiles = (self.floor_percent * total_tiles as f32) as usize; - let mut floor_tile_count = new_map.tiles.iter().filter(|a| **a == TileType::Floor).count(); + let mut floor_tile_count = new_map.tiles.iter().filter(|a| a.is_walkable()).count(); let mut digger_count = 0; while floor_tile_count < desired_floor_tiles { let mut drunk_x; @@ -106,7 +106,7 @@ impl DrunkardsWalk { let mut drunk_life = self.drunken_lifetime; while drunk_life > 0 { - new_map.set_tile(drunk_x, drunk_y, TileType::Wall); + new_map.set_tile(drunk_x, drunk_y, Tile::wall()); new_map.paint(self.symmetry, self.brush_size, drunk_x, drunk_y); let stagger_direction = rng.roll_dice(1, 4); @@ -121,7 +121,7 @@ impl DrunkardsWalk { } digger_count += 1; - floor_tile_count = new_map.tiles.iter().filter(|a| **a == TileType::Floor).count(); + floor_tile_count = new_map.tiles.iter().filter(|a| a.is_walkable()).count(); } new_map diff --git a/src/filter/maze.rs b/src/filter/maze.rs index 9931d00..eab7d9f 100644 --- a/src/filter/maze.rs +++ b/src/filter/maze.rs @@ -16,7 +16,7 @@ use rand::prelude::*; use crate::MapFilter; use crate::{ - map::{Map, TileType}, + map::{Map, Tile}, random::Rng }; @@ -201,17 +201,17 @@ impl<'a> Grid<'a> { fn copy_to_map(&self, map: &mut Map) { // Clear the map - for i in map.tiles.iter_mut() { *i = TileType::Wall; } + for i in map.tiles.iter_mut() { *i = Tile::wall(); } for cell in self.cells.iter() { let x = (cell.column as usize + 1) * 2; let y = (cell.row as usize + 1) * 2; - map.set_tile(x, y, TileType::Floor); - if !cell.walls[TOP] { map.set_tile(x, y-1, TileType::Floor) } - if !cell.walls[RIGHT] { map.set_tile(x+1, y, TileType::Floor) } - if !cell.walls[BOTTOM] { map.set_tile(x, y+1, TileType::Floor) } - if !cell.walls[LEFT] { map.set_tile(x-1, y, TileType::Floor) } + map.set_tile(x, y, Tile::floor()); + if !cell.walls[TOP] { map.set_tile(x, y-1, Tile::floor()) } + if !cell.walls[RIGHT] { map.set_tile(x+1, y, Tile::floor()) } + if !cell.walls[BOTTOM] { map.set_tile(x, y+1, Tile::floor()) } + if !cell.walls[LEFT] { map.set_tile(x-1, y, Tile::floor()) } } } } \ No newline at end of file diff --git a/src/filter/noise_generator.rs b/src/filter/noise_generator.rs index 1a12745..d7d6a7c 100644 --- a/src/filter/noise_generator.rs +++ b/src/filter/noise_generator.rs @@ -18,7 +18,7 @@ use rand::prelude::*; use crate::MapFilter; -use crate::{Map, TileType}; +use crate::{Map, Tile}; /// Map noise generator @@ -54,8 +54,8 @@ impl NoiseGenerator { for y in 1..new_map.height-1 { for x in 1..new_map.width-1 { let roll = rng.next_u32() % 100; - if roll > p { new_map.set_tile(x, y, TileType::Floor) } - else { new_map.set_tile(x, y, TileType::Wall) } + if roll > p { new_map.set_tile(x, y, Tile::floor()) } + else { new_map.set_tile(x, y, Tile::wall()) } } } diff --git a/src/filter/starting_point.rs b/src/filter/starting_point.rs index a3f9fe7..bed4f69 100644 --- a/src/filter/starting_point.rs +++ b/src/filter/starting_point.rs @@ -6,13 +6,13 @@ //! Example modifier usage: //! ``` //! use rand::prelude::*; -//! use mapgen::{MapFilter, Map, TileType}; +//! use mapgen::{MapFilter, Map, Tile}; //! use mapgen::filter::starting_point::{AreaStartingPosition, XStart, YStart}; //! use mapgen::geometry::Point; //! //! let mut rng = StdRng::seed_from_u64(100); //! let mut map = Map::new(80, 50); -//! map.set_tile(10, 10, TileType::Floor); +//! map.set_tile(10, 10, Tile::floor()); //! let modifier = AreaStartingPosition::new(XStart::LEFT, YStart::TOP); //! let new_map = modifier.modify_map(&mut rng, &map); //! @@ -23,7 +23,7 @@ use rand::prelude::StdRng; use crate::MapFilter; use crate::geometry::Point; -use crate::{Map, TileType}; +use crate::Map; /// Initial x region position @@ -67,7 +67,7 @@ impl AreaStartingPosition { let mut available_floors : Vec<(usize, f32)> = Vec::new(); for (idx, tiletype) in map.tiles.iter().enumerate() { - if *tiletype == TileType::Floor { + if tiletype.is_walkable() { available_floors.push( ( idx, diff --git a/src/filter/voronoi.rs b/src/filter/voronoi.rs index b7777cf..adb650a 100644 --- a/src/filter/voronoi.rs +++ b/src/filter/voronoi.rs @@ -16,7 +16,7 @@ use rand::prelude::*; use crate::MapFilter; use crate::{ - map::{Map, TileType}, + map::{Map, Tile}, random::Rng, geometry::Point, }; @@ -71,7 +71,7 @@ impl VoronoiHive { if voronoi_membership[new_map.xy_idx(x, y+1)] != my_seed { neighbors += 1; } if neighbors < 2 { - new_map.set_tile(x, y, TileType::Floor); + new_map.set_tile(x, y, Tile::floor()); } } } diff --git a/src/lib.rs b/src/lib.rs index b124846..f0ab09e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ //! //! Example //! ``` -//! use mapgen::{MapFilter, MapBuilder, Map, TileType}; +//! use mapgen::{MapFilter, MapBuilder, Map, Tile}; //! use mapgen::filter::{ //! NoiseGenerator, //! CellularAutomata, @@ -33,7 +33,7 @@ pub mod geometry; pub mod map; pub mod metric; -pub use map::{Map, Symmetry, TileType}; +pub use map::{Map, Symmetry, Tile}; pub use filter::*; pub (crate) mod dijkstra; diff --git a/src/map.rs b/src/map.rs index 085057b..27f6eed 100644 --- a/src/map.rs +++ b/src/map.rs @@ -12,8 +12,8 @@ use super::geometry::{Point, Rect, usize_abs}; #[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)] -pub enum TileType { - Wall, Floor +pub struct Tile { + is_blocked: bool, } #[derive(PartialEq, Copy, Clone)] @@ -23,7 +23,7 @@ pub enum Symmetry { None, Horizontal, Vertical, Both } /// Map data #[derive(Default, Clone)] pub struct Map { - pub tiles : Vec, + pub tiles : Vec, pub width : usize, pub height : usize, pub starting_point: Option, @@ -32,13 +32,31 @@ pub struct Map { pub corridors: Vec>, } +impl Tile { + pub fn wall() -> Tile { + Tile { is_blocked: true } + } + + pub fn floor() -> Tile { + Tile { is_blocked: false } + } + + pub fn is_walkable(&self) -> bool { + !self.is_blocked + } + + pub fn is_blocked(&self) -> bool { + self.is_blocked + } +} + impl Map { /// Generates an empty map, consisting entirely of solid walls pub fn new(width: usize, height: usize) -> Map { let map_tile_count = width*height; Map{ - tiles : vec![TileType::Wall; map_tile_count], + tiles : vec![Tile::wall(); map_tile_count], width, height, starting_point: None, @@ -62,7 +80,7 @@ impl Map { let line = lines[i].as_bytes(); for j in 0..line.len() { if line[j] as char == ' ' { - map.set_tile(j, i, TileType::Floor); + map.set_tile(j, i, Tile::floor()); } } } @@ -70,9 +88,9 @@ impl Map { } /// Get TileType at the given location - pub fn at(&self, x: usize, y: usize) -> TileType { + pub fn at(&self, x: usize, y: usize) -> Tile { if x >= self.width || y >= self.height { - TileType::Wall + Tile::wall() } else { let idx = (y as usize) * self.width + (x as usize); self.tiles[idx] @@ -100,11 +118,11 @@ impl Map { // Check if given tile can be accessed fn is_exit_valid(&self, x:usize, y:usize) -> bool { - self.at(x, y) == TileType::Floor + self.at(x, y).is_blocked == false } /// Modify tile at the given location - pub fn set_tile(&mut self, x: usize, y: usize, tile: TileType) { + pub fn set_tile(&mut self, x: usize, y: usize, tile: Tile) { if x < self.width && y < self.height { let idx = self.xy_idx(x as usize, y as usize); self.tiles[idx] = tile; @@ -120,7 +138,7 @@ impl Map { pub fn add_room(&mut self, rect: Rect) { for x in rect.x1..rect.x2 { for y in rect.y1..rect.y2 { - self.set_tile(x as usize, y as usize, TileType::Floor); + self.set_tile(x as usize, y as usize, Tile::floor()); } } self.rooms.push(rect); @@ -142,9 +160,9 @@ impl Map { y -= 1; } - if self.at(x, y) != TileType::Floor { + if self.at(x, y).is_blocked { corridor.push(Point::new(x, y)); - self.set_tile(x, y, TileType::Floor); + self.set_tile(x, y, Tile::floor()); } } } @@ -192,14 +210,14 @@ impl Map { fn apply_paint(&mut self, brush_size: usize, x: usize, y: usize) { match brush_size { 1 => { - self.set_tile(x, y, TileType::Floor); + self.set_tile(x, y, Tile::floor()); } _ => { let half_brush_size = brush_size / 2; for brush_y in y-half_brush_size .. y+half_brush_size { for brush_x in x-half_brush_size .. x+half_brush_size { if brush_x > 1 && brush_x < self.width-1 && brush_y > 1 && brush_y < self.height-1 { - self.set_tile(brush_x, brush_y, TileType::Floor); + self.set_tile(brush_x, brush_y, Tile::floor()); } } } @@ -212,7 +230,7 @@ impl fmt::Display for Map { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for y in 0..self.height { let bytes: Vec = (0..self.width) - .map(|x| if self.at(x, y) == TileType::Wall {'#'} else {' '} as u8) + .map(|x| if self.at(x, y).is_blocked {'#'} else {' '} as u8) .collect(); let line = String::from_utf8(bytes).expect("Can't convert map to string"); let _ = write!(f, "{}\n", line); @@ -233,7 +251,7 @@ mod tests { let map = Map::new(10, 10); for i in 0..10 { for j in 0..10 { - assert_eq!(map.at(i, j), TileType::Wall); + assert!(map.at(i, j).is_blocked); } } } @@ -250,12 +268,12 @@ mod tests { assert_eq!(map.width, 10); assert_eq!(map.height, 3); for i in 0..10 { - assert_eq!(map.at(i, 0), TileType::Wall); - assert_eq!(map.at(i, 2), TileType::Wall); + assert!(map.at(i, 0).is_blocked); + assert!(map.at(i, 2).is_blocked); if i == 0 || i == 9 { - assert_eq!(map.at(i, 1), TileType::Wall); + assert!(map.at(i, 1).is_blocked); } else { - assert_eq!(map.at(i, 1), TileType::Floor); + assert!(map.at(i, 1).is_blocked == false); } } } @@ -281,9 +299,9 @@ mod tests { for x in 0..map.width { for y in 0..map.height { if x == 0 || y == 0 || x == 4 || y == 4 { - assert_eq!(map.at(x, y), TileType::Wall); + assert!(map.at(x, y).is_blocked); } else { - assert_eq!(map.at(x, y), TileType::Floor); + assert!(map.at(x, y).is_blocked == false); } } } diff --git a/src/metric.rs b/src/metric.rs index c4e2033..4736fcb 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -4,7 +4,7 @@ //! and the provide generator score as an average. //! -use super::map::{Map, TileType}; +use super::map::Map; use super::dijkstra::DijkstraMap; @@ -13,7 +13,7 @@ use super::dijkstra::DijkstraMap; /// is probably to degenerated and shouldn't be used pub fn density(map: &Map) -> f32 { let floor_count = map.tiles.iter() - .filter(|&t| *t == TileType::Floor) + .filter(|&t| t.is_walkable()) .count(); floor_count as f32 / map.tiles.len() as f32 }