Drop BuilderData trait.

This commit is contained in:
Nolan Darilek 2022-03-13 21:14:59 -05:00
parent ffaad6cf48
commit 2202540a43
17 changed files with 61 additions and 78 deletions

View File

@ -2,7 +2,7 @@ use mapgen::{
filter::{ filter::{
AreaStartingPosition, CellularAutomata, CullUnreachable, NoiseGenerator, XStart, YStart, AreaStartingPosition, CellularAutomata, CullUnreachable, NoiseGenerator, XStart, YStart,
}, },
BuilderData, MapBuilder, MapFilter, MapBuilder, MapFilter,
}; };
#[derive(Clone, Default)] #[derive(Clone, Default)]
@ -10,11 +10,9 @@ struct MyData {
value: usize, value: usize,
} }
impl BuilderData for MyData {}
struct IncrementData; struct IncrementData;
impl<D: BuilderData> MapFilter<D> for IncrementData { impl<D: Clone + Default> MapFilter<D> for IncrementData {
fn modify_map(&self, rng: &mut rand::prelude::StdRng, map: &mapgen::Map<D>) -> mapgen::Map<D> { fn modify_map(&self, rng: &mut rand::prelude::StdRng, map: &mapgen::Map<D>) -> mapgen::Map<D> {
let map = map.clone(); let map = map.clone();
map.data.value += 1; map.data.value += 1;
@ -28,7 +26,7 @@ fn main() {
.with(CellularAutomata::new()) .with(CellularAutomata::new())
.with(AreaStartingPosition::new(XStart::CENTER, YStart::CENTER)) .with(AreaStartingPosition::new(XStart::CENTER, YStart::CENTER))
.with(CullUnreachable::new()) .with(CullUnreachable::new())
.with(Box::new(IncrementData)) .with(Box::new(IncrementData::<MyData>))
.build(); .build();
println!("{:}", &map); println!("{:}", &map);

View File

@ -25,7 +25,7 @@
//! --- //! ---
//! //!
use super::map::{BuilderData, Map}; use super::map::Map;
use std::f32::MAX; use std::f32::MAX;
use std::{collections::VecDeque, marker::PhantomData}; use std::{collections::VecDeque, marker::PhantomData};
@ -41,13 +41,13 @@ pub struct DijkstraMap<D> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> DijkstraMap<D> { impl<D: Clone + Default> DijkstraMap<D> {
//! Construct a new Dijkstra map, ready to run. //! Construct a new Dijkstra map, ready to run.
pub fn new(map: &Map<D>) -> DijkstraMap<D> { pub fn new(map: &Map<D>) -> DijkstraMap<D> {
let len = map.width * map.height; let len = map.width * map.height;
let tiles = vec![MAX; len]; let tiles = vec![MAX; len];
let mut d = DijkstraMap { let mut d = DijkstraMap {
tiles: tiles, tiles,
size_x: map.width, size_x: map.width,
size_y: map.height, size_y: map.height,
max_depth: len as f32, max_depth: len as f32,

View File

@ -25,21 +25,21 @@ use std::marker::PhantomData;
use crate::geometry::{Point, Rect}; use crate::geometry::{Point, Rect};
use crate::random::Rng; use crate::random::Rng;
use crate::Map; use crate::Map;
use crate::{BuilderData, MapFilter}; use crate::MapFilter;
use rand::prelude::*; use rand::prelude::*;
pub struct BspInterior<D: BuilderData> { pub struct BspInterior<D> {
min_room_size: usize, min_room_size: usize,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for BspInterior<D> { impl<D: Clone + Default> MapFilter<D> for BspInterior<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(rng, map) self.build(rng, map)
} }
} }
impl<D: BuilderData> BspInterior<D> { impl<D: Clone + Default> BspInterior<D> {
pub fn new() -> Box<BspInterior<D>> { pub fn new() -> Box<BspInterior<D>> {
Box::new(BspInterior { Box::new(BspInterior {
min_room_size: 8, min_room_size: 8,

View File

@ -22,23 +22,22 @@ use std::marker::PhantomData;
use crate::geometry::Rect; use crate::geometry::Rect;
use crate::random::Rng; use crate::random::Rng;
use crate::BuilderData;
use crate::Map; use crate::Map;
use crate::MapFilter; use crate::MapFilter;
use rand::prelude::*; use rand::prelude::*;
pub struct BspRooms<D: BuilderData> { pub struct BspRooms<D> {
max_split: usize, max_split: usize,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for BspRooms<D> { impl<D: Clone + Default> MapFilter<D> for BspRooms<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build_rooms(map, rng) self.build_rooms(map, rng)
} }
} }
impl<D: BuilderData> BspRooms<D> { impl<D: Clone + Default> BspRooms<D> {
pub fn new() -> Box<BspRooms<D>> { pub fn new() -> Box<BspRooms<D>> {
Box::new(BspRooms { Box::new(BspRooms {
max_split: 240, max_split: 240,
@ -152,13 +151,11 @@ impl<D: BuilderData> BspRooms<D> {
if y < 1 { if y < 1 {
can_build = false; can_build = false;
} }
if can_build { if can_build && map.at(x as usize, y as usize).is_walkable() {
if map.at(x as usize, y as usize).is_walkable() {
can_build = false; can_build = false;
} }
} }
} }
}
can_build can_build
} }

View File

@ -23,24 +23,23 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::BuilderData;
use crate::MapFilter; use crate::MapFilter;
use crate::{Map, Tile}; use crate::{Map, Tile};
use rand::prelude::*; use rand::prelude::*;
/// Map filter /// Map filter
pub struct CellularAutomata<D: BuilderData> { pub struct CellularAutomata<D> {
num_iteraction: u32, num_iteraction: u32,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for CellularAutomata<D> { impl<D: Clone + Default> MapFilter<D> for CellularAutomata<D> {
fn modify_map(&self, _rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, _rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(map) self.build(map)
} }
} }
impl<D: BuilderData> CellularAutomata<D> { impl<D: Clone + Default> CellularAutomata<D> {
/// Create generator which will create map with the given dimension. /// Create generator which will create map with the given dimension.
pub fn new() -> Box<CellularAutomata<D>> { pub fn new() -> Box<CellularAutomata<D>> {
Box::new(CellularAutomata { Box::new(CellularAutomata {
@ -60,7 +59,7 @@ impl<D: BuilderData> CellularAutomata<D> {
} }
} }
fn apply_iteration<D: BuilderData>(map: &Map<D>) -> Map<D> { fn apply_iteration<D: Clone + Default>(map: &Map<D>) -> Map<D> {
let mut new_map = map.clone(); let mut new_map = map.clone();
for y in 1..map.height - 1 { for y in 1..map.height - 1 {

View File

@ -8,21 +8,21 @@ use std::marker::PhantomData;
use crate::dijkstra::DijkstraMap; use crate::dijkstra::DijkstraMap;
use crate::MapFilter; use crate::MapFilter;
use crate::{BuilderData, Map, Tile}; use crate::{Map, Tile};
use rand::prelude::StdRng; use rand::prelude::StdRng;
/// Remove unreachable areas from the map. /// Remove unreachable areas from the map.
pub struct CullUnreachable<D: BuilderData> { pub struct CullUnreachable<D> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for CullUnreachable<D> { impl<D: Clone + Default> MapFilter<D> for CullUnreachable<D> {
fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(map) self.build(map)
} }
} }
impl<D: BuilderData> CullUnreachable<D> { impl<D: Clone + Default> CullUnreachable<D> {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new() -> Box<CullUnreachable<D>> { pub fn new() -> Box<CullUnreachable<D>> {
Box::new(CullUnreachable { Box::new(CullUnreachable {

View File

@ -6,7 +6,6 @@
use crate::dijkstra::DijkstraMap; use crate::dijkstra::DijkstraMap;
use crate::geometry::Point; use crate::geometry::Point;
use crate::BuilderData;
use crate::Map; use crate::Map;
use crate::MapFilter; use crate::MapFilter;
use rand::prelude::StdRng; use rand::prelude::StdRng;
@ -14,17 +13,17 @@ use std::f32;
use std::marker::PhantomData; use std::marker::PhantomData;
/// Add exist position to the map based on the distance from the start point. /// Add exist position to the map based on the distance from the start point.
pub struct DistantExit<D: BuilderData> { pub struct DistantExit<D> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for DistantExit<D> { impl<D: Clone + Default> MapFilter<D> for DistantExit<D> {
fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(map) self.build(map)
} }
} }
impl<D: BuilderData> DistantExit<D> { impl<D: Clone + Default> DistantExit<D> {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new() -> Box<DistantExit<D>> { pub fn new() -> Box<DistantExit<D>> {
Box::new(DistantExit { Box::new(DistantExit {

View File

@ -20,7 +20,6 @@ use crate::{
geometry::Point, geometry::Point,
map::{Map, Symmetry, Tile}, map::{Map, Symmetry, Tile},
random::Rng, random::Rng,
BuilderData,
}; };
use rand::prelude::*; use rand::prelude::*;
@ -30,7 +29,7 @@ pub enum DrunkSpawnMode {
Random, Random,
} }
pub struct DrunkardsWalk<D: BuilderData> { pub struct DrunkardsWalk<D> {
spawn_mode: DrunkSpawnMode, spawn_mode: DrunkSpawnMode,
drunken_lifetime: i32, drunken_lifetime: i32,
floor_percent: f32, floor_percent: f32,
@ -39,13 +38,13 @@ pub struct DrunkardsWalk<D: BuilderData> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for DrunkardsWalk<D> { impl<D: Clone + Default> MapFilter<D> for DrunkardsWalk<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(rng, map) self.build(rng, map)
} }
} }
impl<D: BuilderData> DrunkardsWalk<D> { impl<D: Clone + Default> DrunkardsWalk<D> {
pub fn new( pub fn new(
spawn_mode: DrunkSpawnMode, spawn_mode: DrunkSpawnMode,
drunken_lifetime: i32, drunken_lifetime: i32,

View File

@ -17,22 +17,22 @@ use std::marker::PhantomData;
use crate::MapFilter; use crate::MapFilter;
use crate::{ use crate::{
map::{BuilderData, Map, Tile}, map::{Map, Tile},
random::Rng, random::Rng,
}; };
use rand::prelude::*; use rand::prelude::*;
pub struct MazeBuilder<D: BuilderData> { pub struct MazeBuilder<D> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for MazeBuilder<D> { impl<D: Clone + Default> MapFilter<D> for MazeBuilder<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(rng, map) self.build(rng, map)
} }
} }
impl<D: BuilderData> MazeBuilder<D> { impl<D: Clone + Default> MazeBuilder<D> {
pub fn new() -> Box<MazeBuilder<D>> { pub fn new() -> Box<MazeBuilder<D>> {
Box::new(MazeBuilder { Box::new(MazeBuilder {
phantom: PhantomData, phantom: PhantomData,
@ -93,7 +93,7 @@ impl Cell {
} }
} }
struct Grid<'a, D: BuilderData> { struct Grid<'a, D> {
width: i32, width: i32,
height: i32, height: i32,
cells: Vec<Cell>, cells: Vec<Cell>,
@ -103,7 +103,7 @@ struct Grid<'a, D: BuilderData> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<'a, D: BuilderData> Grid<'a, D> { impl<'a, D: Clone + Default> Grid<'a, D> {
fn new(width: i32, height: i32, rng: &mut StdRng) -> Grid<D> { fn new(width: i32, height: i32, rng: &mut StdRng) -> Grid<D> {
let mut grid = Grid { let mut grid = Grid {
width, width,

View File

@ -19,22 +19,22 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::MapFilter; use crate::MapFilter;
use crate::{BuilderData, Map, Tile}; use crate::{Map, Tile};
use rand::prelude::*; use rand::prelude::*;
/// Map noise generator /// Map noise generator
pub struct NoiseGenerator<D: BuilderData> { pub struct NoiseGenerator<D> {
prob: f32, prob: f32,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for NoiseGenerator<D> { impl<D: Clone + Default> MapFilter<D> for NoiseGenerator<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(map, rng) self.build(map, rng)
} }
} }
impl<D: BuilderData> NoiseGenerator<D> { impl<D: Clone + Default> NoiseGenerator<D> {
/// Create noise with custom probability /// Create noise with custom probability
pub fn new(prob: f32) -> Box<NoiseGenerator<D>> { pub fn new(prob: f32) -> Box<NoiseGenerator<D>> {
Box::new(NoiseGenerator { Box::new(NoiseGenerator {

View File

@ -1,23 +1,22 @@
//! Connect nearest rooms on the map with corridors //! Connect nearest rooms on the map with corridors
//! //!
use crate::BuilderData;
use crate::Map; use crate::Map;
use crate::MapFilter; use crate::MapFilter;
use rand::prelude::StdRng; use rand::prelude::StdRng;
use std::collections::HashSet; use std::collections::HashSet;
use std::marker::PhantomData; use std::marker::PhantomData;
pub struct NearestCorridors<D: BuilderData> { pub struct NearestCorridors<D> {
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for NearestCorridors<D> { impl<D: Clone + Default> MapFilter<D> for NearestCorridors<D> {
fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> {
self.corridors(map) self.corridors(map)
} }
} }
impl<D: BuilderData> NearestCorridors<D> { impl<D: Clone + Default> NearestCorridors<D> {
pub fn new() -> Box<NearestCorridors<D>> { pub fn new() -> Box<NearestCorridors<D>> {
Box::new(NearestCorridors { Box::new(NearestCorridors {
phantom: PhantomData, phantom: PhantomData,

View File

@ -22,25 +22,24 @@ use std::marker::PhantomData;
use crate::geometry::Rect; use crate::geometry::Rect;
use crate::random::Rng; use crate::random::Rng;
use crate::BuilderData;
use crate::Map; use crate::Map;
use crate::MapFilter; use crate::MapFilter;
use rand::prelude::*; use rand::prelude::*;
pub struct SimpleRooms<D: BuilderData> { pub struct SimpleRooms<D> {
max_rooms: usize, max_rooms: usize,
min_room_size: usize, min_room_size: usize,
max_room_size: usize, max_room_size: usize,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for SimpleRooms<D> { impl<D: Clone + Default> MapFilter<D> for SimpleRooms<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build_rooms(map, rng) self.build_rooms(map, rng)
} }
} }
impl<D: BuilderData> SimpleRooms<D> { impl<D: Clone + Default> SimpleRooms<D> {
pub fn new() -> Box<SimpleRooms<D>> { pub fn new() -> Box<SimpleRooms<D>> {
Box::new(SimpleRooms { Box::new(SimpleRooms {
max_rooms: 30, max_rooms: 30,

View File

@ -23,7 +23,6 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::geometry::Point; use crate::geometry::Point;
use crate::BuilderData;
use crate::Map; use crate::Map;
use crate::MapFilter; use crate::MapFilter;
use rand::prelude::StdRng; use rand::prelude::StdRng;
@ -43,19 +42,19 @@ pub enum YStart {
} }
/// Add starting position to the map /// Add starting position to the map
pub struct AreaStartingPosition<D: BuilderData> { pub struct AreaStartingPosition<D> {
x: XStart, x: XStart,
y: YStart, y: YStart,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for AreaStartingPosition<D> { impl<D: Clone + Default> MapFilter<D> for AreaStartingPosition<D> {
fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, _: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(map) self.build(map)
} }
} }
impl<D: BuilderData> AreaStartingPosition<D> { impl<D: Clone + Default> AreaStartingPosition<D> {
/// Create new modifier with given region /// Create new modifier with given region
pub fn new(x: XStart, y: YStart) -> Box<AreaStartingPosition<D>> { pub fn new(x: XStart, y: YStart) -> Box<AreaStartingPosition<D>> {
Box::new(AreaStartingPosition { Box::new(AreaStartingPosition {

View File

@ -18,23 +18,23 @@ use std::marker::PhantomData;
use crate::MapFilter; use crate::MapFilter;
use crate::{ use crate::{
geometry::Point, geometry::Point,
map::{BuilderData, Map, Tile}, map::{Map, Tile},
random::Rng, random::Rng,
}; };
use rand::prelude::*; use rand::prelude::*;
pub struct VoronoiHive<D: BuilderData> { pub struct VoronoiHive<D> {
n_seeds: usize, n_seeds: usize,
phantom: PhantomData<D>, phantom: PhantomData<D>,
} }
impl<D: BuilderData> MapFilter<D> for VoronoiHive<D> { impl<D: Clone + Default> MapFilter<D> for VoronoiHive<D> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> { fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D> {
self.build(rng, map) self.build(rng, map)
} }
} }
impl<D: BuilderData> VoronoiHive<D> { impl<D: Clone + Default> VoronoiHive<D> {
pub fn new() -> Box<VoronoiHive<D>> { pub fn new() -> Box<VoronoiHive<D>> {
Box::new(VoronoiHive { Box::new(VoronoiHive {
n_seeds: 64, n_seeds: 64,

View File

@ -34,7 +34,7 @@ pub mod map;
pub mod metric; pub mod metric;
pub use filter::*; pub use filter::*;
pub use map::{BuilderData, Map, NoData, Symmetry, Tile}; pub use map::{Map, NoData, Symmetry, Tile};
pub(crate) mod dijkstra; pub(crate) mod dijkstra;
pub(crate) mod random; pub(crate) mod random;
@ -44,18 +44,18 @@ use std::time::{SystemTime, UNIX_EPOCH};
/// Trait which should be implemented by map modifier. /// Trait which should be implemented by map modifier.
/// Modifier takes initiall map and apply changes to it. /// Modifier takes initiall map and apply changes to it.
pub trait MapFilter<D: BuilderData> { pub trait MapFilter<D: Clone + Default> {
fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D>; fn modify_map(&self, rng: &mut StdRng, map: &Map<D>) -> Map<D>;
} }
/// Used to chain MapBuilder and MapModifiers to create the final map. /// Used to chain MapBuilder and MapModifiers to create the final map.
pub struct MapBuilder<D> { pub struct MapBuilder<D: Clone + Default> {
width: usize, width: usize,
height: usize, height: usize,
modifiers: Vec<Box<dyn MapFilter<D>>>, modifiers: Vec<Box<dyn MapFilter<D>>>,
} }
impl<D: BuilderData> MapBuilder<D> { impl<D: Clone + Default> MapBuilder<D> {
/// Create Map Builder with initial map generator /// Create Map Builder with initial map generator
pub fn new(width: usize, height: usize) -> MapBuilder<D> { pub fn new(width: usize, height: usize) -> MapBuilder<D> {
MapBuilder { MapBuilder {

View File

@ -24,18 +24,13 @@ pub enum Symmetry {
Both, Both,
} }
/// Arbitrary data associated with each map
pub trait BuilderData: Clone + Default {}
/// No build data /// No build data
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct NoData; pub struct NoData;
impl BuilderData for NoData {}
/// Map data /// Map data
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct Map<D> { pub struct Map<D: Clone + Default> {
pub tiles: Vec<Tile>, pub tiles: Vec<Tile>,
pub width: usize, pub width: usize,
pub height: usize, pub height: usize,
@ -72,7 +67,7 @@ impl Tile {
} }
} }
impl<D: BuilderData> Map<D> { impl<D: Clone + Default> Map<D> {
/// Generates an empty map, consisting entirely of solid walls /// Generates an empty map, consisting entirely of solid walls
pub fn new(width: usize, height: usize) -> Map<D> { pub fn new(width: usize, height: usize) -> Map<D> {
let map_tile_count = width * height; let map_tile_count = width * height;
@ -274,7 +269,7 @@ impl<D: BuilderData> Map<D> {
} }
} }
impl<D: BuilderData> fmt::Display for Map<D> { impl<D: Clone + Default> fmt::Display for Map<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for y in 0..self.height { for y in 0..self.height {
let bytes: Vec<u8> = (0..self.width) let bytes: Vec<u8> = (0..self.width)

View File

@ -6,12 +6,11 @@
use super::dijkstra::DijkstraMap; use super::dijkstra::DijkstraMap;
use super::map::Map; use super::map::Map;
use super::BuilderData;
/// This metric calculates the percentage of walkable cells (Floor). /// This metric calculates the percentage of walkable cells (Floor).
/// If this number is very low (like < 10%) then it means that the map /// If this number is very low (like < 10%) then it means that the map
/// is probably to degenerated and shouldn't be used /// is probably to degenerated and shouldn't be used
pub fn density<D>(map: &Map<D>) -> f32 { pub fn density<D: Clone + Default>(map: &Map<D>) -> f32 {
let floor_count = map.tiles.iter().filter(|&t| t.is_walkable()).count(); let floor_count = map.tiles.iter().filter(|&t| t.is_walkable()).count();
floor_count as f32 / map.tiles.len() as f32 floor_count as f32 / map.tiles.len() as f32
} }
@ -19,7 +18,7 @@ pub fn density<D>(map: &Map<D>) -> f32 {
/// Calculate the length of the shortes path from the starting point /// Calculate the length of the shortes path from the starting point
/// to the exit. /// to the exit.
/// If this path is very short, then the map is probably degenerated. /// If this path is very short, then the map is probably degenerated.
pub fn path_length<D: BuilderData>(map: &Map<D>) -> f32 { pub fn path_length<D: Clone + Default>(map: &Map<D>) -> f32 {
if map.starting_point.is_none() { if map.starting_point.is_none() {
return 0.0; return 0.0;
} }