use super::MapArchitect; use crate::prelude::*; const STAGGER_DISTANCE: usize = 400; const NUM_TILES: usize = (SCREEN_WIDTH * SCREEN_HEIGHT) as usize; const DESIRED_FLOOR: usize = NUM_TILES / 3; pub struct DrunkardsWalkArchitect {} impl MapArchitect for DrunkardsWalkArchitect { fn new(&mut self, rng: &mut RandomNumberGenerator) -> MapBuilder { let mut mb = MapBuilder { map: Map::new(), rooms: Vec::new(), monster_spawns: Vec::new(), player_start: Point::zero(), amulet_start: Point::zero(), theme: super::themes::DungeonTheme::new(), }; mb.fill(TileType::Wall); let center = Point::new(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); self.drunkard(¢er, rng, &mut mb.map); while mb .map .tiles .iter() .filter(|t| **t == TileType::Floor) .count() < DESIRED_FLOOR { self.drunkard( &Point::new(rng.range(0, SCREEN_WIDTH), rng.range(0, SCREEN_HEIGHT)), rng, &mut mb.map, ); let dijkstra_map = DijkstraMap::new( SCREEN_WIDTH, SCREEN_HEIGHT, &[mb.map.point2d_to_index(center)], &mb.map, 1024.0, ); dijkstra_map .map .iter() .enumerate() .filter(|(_, distance)| *distance > &2000.0) .for_each(|(idx, _)| mb.map.tiles[idx] = TileType::Wall); } mb.monster_spawns = mb.spawn_monsters(¢er, rng); mb.player_start = center; mb.amulet_start = mb.find_most_distant(&mb.player_start); mb } } impl DrunkardsWalkArchitect { fn drunkard(&mut self, start: &Point, rng: &mut RandomNumberGenerator, map: &mut Map) { let mut drunkard_pos = start.clone(); let mut distance_staggered = 0; loop { let drunk_idx = map.point2d_to_index(drunkard_pos); map.tiles[drunk_idx] = TileType::Floor; match rng.range(0, 4) { 0 => drunkard_pos.x -= 1, 1 => drunkard_pos.x += 1, 2 => drunkard_pos.y -= 1, _ => drunkard_pos.y += 1, } if !map.in_bounds(drunkard_pos) { break; } distance_staggered += 1; if distance_staggered > STAGGER_DISTANCE { break; } } } }