2021-01-14 11:18:31 +00:00
|
|
|
//! Different metrics for the map
|
|
|
|
//! Can be used to meausre the quality of the map or the quality of the generator.
|
|
|
|
//! To meause the quality of the generator; generate lots of maps, measure them
|
|
|
|
//! and the provide generator score as an average.
|
2022-03-12 20:31:30 +00:00
|
|
|
//!
|
2021-01-14 11:18:31 +00:00
|
|
|
|
|
|
|
use super::dijkstra::DijkstraMap;
|
2022-03-12 20:31:30 +00:00
|
|
|
use super::map::Map;
|
2021-01-14 11:18:31 +00:00
|
|
|
|
|
|
|
/// This metric calculates the percentage of walkable cells (Floor).
|
2022-03-12 20:31:30 +00:00
|
|
|
/// If this number is very low (like < 10%) then it means that the map
|
2021-01-14 11:18:31 +00:00
|
|
|
/// is probably to degenerated and shouldn't be used
|
2022-03-14 02:14:59 +00:00
|
|
|
pub fn density<D: Clone + Default>(map: &Map<D>) -> f32 {
|
2022-03-12 20:31:30 +00:00
|
|
|
let floor_count = map.tiles.iter().filter(|&t| t.is_walkable()).count();
|
2021-01-14 11:18:31 +00:00
|
|
|
floor_count as f32 / map.tiles.len() as f32
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculate the length of the shortes path from the starting point
|
|
|
|
/// to the exit.
|
|
|
|
/// If this path is very short, then the map is probably degenerated.
|
2022-03-14 02:14:59 +00:00
|
|
|
pub fn path_length<D: Clone + Default>(map: &Map<D>) -> f32 {
|
2021-01-14 11:18:31 +00:00
|
|
|
if map.starting_point.is_none() {
|
2022-03-12 20:31:30 +00:00
|
|
|
return 0.0;
|
2021-01-14 11:18:31 +00:00
|
|
|
}
|
2022-03-12 20:31:30 +00:00
|
|
|
|
2021-01-14 11:18:31 +00:00
|
|
|
match map.exit_point {
|
|
|
|
None => 0.0,
|
|
|
|
Some(exit) => {
|
|
|
|
let dijkstra = DijkstraMap::new(map);
|
|
|
|
dijkstra.tiles[map.xy_idx(exit.x, exit.y)]
|
2022-03-12 20:31:30 +00:00
|
|
|
}
|
2021-01-14 11:18:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ------------------------------------------------------------------------------------------------
|
|
|
|
/// Module unit tests
|
|
|
|
/// ------------------------------------------------------------------------------------------------
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2022-03-12 15:45:42 +00:00
|
|
|
use crate::{geometry::Point, map::NoData};
|
2021-01-14 11:18:31 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_density_no_floor() {
|
2022-03-12 15:45:42 +00:00
|
|
|
let map = Map::<NoData>::new(10, 10);
|
2021-01-14 11:18:31 +00:00
|
|
|
let score = density(&map);
|
|
|
|
assert_eq!(score, 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_density() {
|
|
|
|
let map_str = "
|
|
|
|
##########
|
|
|
|
# ## #
|
|
|
|
##########
|
|
|
|
";
|
2022-03-12 15:45:42 +00:00
|
|
|
let map = Map::<NoData>::from_string(map_str);
|
2021-01-14 11:18:31 +00:00
|
|
|
let score = density(&map);
|
|
|
|
assert_eq!(score, 0.2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_no_path() {
|
|
|
|
let map_str = "
|
|
|
|
##########
|
|
|
|
# ## #
|
|
|
|
##########
|
|
|
|
";
|
2022-03-12 15:45:42 +00:00
|
|
|
let map = Map::<NoData>::from_string(map_str);
|
2021-01-14 11:18:31 +00:00
|
|
|
let score = path_length(&map);
|
|
|
|
assert_eq!(score, 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_path_length() {
|
|
|
|
let map_str = "
|
|
|
|
##########
|
|
|
|
# ## #
|
|
|
|
# #
|
|
|
|
##########
|
|
|
|
";
|
2022-03-12 15:45:42 +00:00
|
|
|
let mut map = Map::<NoData>::from_string(map_str);
|
2022-03-12 20:31:30 +00:00
|
|
|
map.starting_point = Some(Point::new(1, 1));
|
|
|
|
map.exit_point = Some(Point::new(8, 1));
|
2021-01-14 11:18:31 +00:00
|
|
|
|
|
|
|
let score = path_length(&map);
|
|
|
|
assert!(f32::abs(score - 7.9) <= 0.01);
|
|
|
|
}
|
2022-03-12 20:31:30 +00:00
|
|
|
}
|