diff --git a/src/map_builders.rs b/src/map_builders.rs index 787451b..4e6c844 100644 --- a/src/map_builders.rs +++ b/src/map_builders.rs @@ -6,6 +6,7 @@ mod common; mod cull_unreachable; mod distant_exit; mod dla; +mod door_placement; mod drunkard; mod maze; mod prefab_builder; @@ -34,6 +35,7 @@ use cellular_automata::CellularAutomataBuilder; use cull_unreachable::CullUnreachable; use distant_exit::DistantExit; use dla::DLABuilder; +use door_placement::DoorPlacement; use drunkard::DrunkardsWalkBuilder; use maze::MazeBuilder; use prefab_builder::PrefabBuilder; @@ -305,17 +307,8 @@ pub fn random_builder(new_depth: i32, rng: &mut RandomNumberGenerator) -> Builde )); } + builder.with(DoorPlacement::new()); builder.with(PrefabBuilder::vaults()); - // builder - // .start_with(SimpleMapBuilder::new()) - // .with(RoomDrawer::new()) - // .with(RoomSorter::new(RoomSort::LeftMost)) - // .with(StraightLineCorridors::new()) - // .with(RoomBasedSpawner::new()) - // .with(CorridorSpawner::new()) - // .with(RoomBasedStairs::new()) - // .with(RoomBasedStartingPosition::new()); - builder } diff --git a/src/map_builders/door_placement.rs b/src/map_builders/door_placement.rs new file mode 100644 index 0000000..68b8477 --- /dev/null +++ b/src/map_builders/door_placement.rs @@ -0,0 +1,71 @@ +use rltk::RandomNumberGenerator; + +use super::{BuilderMap, MetaMapBuilder}; +use crate::TileType; + +pub struct DoorPlacement {} + +impl MetaMapBuilder for DoorPlacement { + #[allow(dead_code)] + fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { + self.doors(rng, build_data); + } +} + +impl DoorPlacement { + #[allow(dead_code)] + pub fn new() -> Box { + Box::new(DoorPlacement {}) + } + + fn doors(&mut self, _rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { + if let Some(halls_original) = &build_data.corridors { + let halls = halls_original.clone(); + for hall in halls.iter() { + // We aren't interested in tiny corridors + if hall.len() > 2 { + if self.door_possible(build_data, hall[0]) { + build_data.spawn_list.push((hall[0], "Door".to_string())); + } + } + } + } else { + // There are no corridors - scan for possible places + let tiles = build_data.map.tiles.clone(); + for (i, tile) in tiles.iter().enumerate() { + if *tile == TileType::Floor && self.door_possible(build_data, i) { + build_data.spawn_list.push((i, "Door".to_string())); + } + } + } + } + + fn door_possible(&self, build_data: &mut BuilderMap, idx: usize) -> bool { + let width = build_data.map.width as usize; + let height = build_data.map.height as usize; + let x = idx % width; + let y = idx / width; + + // Check for east-west door possibility + if build_data.map.tiles[idx] == TileType::Floor + && (x > 1 && build_data.map.tiles[idx - 1] == TileType::Floor) + && (x < width - 2 && build_data.map.tiles[idx + 1] == TileType::Floor) + && (y > 1 && build_data.map.tiles[idx - width] == TileType::Wall) + && (y < height - 2 && build_data.map.tiles[idx + width] == TileType::Wall) + { + return true; + } + + // Check for north-south door possibility + if build_data.map.tiles[idx] == TileType::Floor + && (x > 1 && build_data.map.tiles[idx - 1] == TileType::Wall) + && (x < width - 2 && build_data.map.tiles[idx + 1] == TileType::Wall) + && (y > 1 && build_data.map.tiles[idx - width] == TileType::Floor) + && (y < height - 2 && build_data.map.tiles[idx + width] == TileType::Floor) + { + return true; + } + + false + } +} diff --git a/src/spawner.rs b/src/spawner.rs index fbf5661..e8c36bf 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -142,6 +142,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) { "Rations" => rations(ecs, x, y), "Magic Mapping Scroll" => magic_mapping_scroll(ecs, x, y), "Bear Trap" => bear_trap(ecs, x, y), + "Door" => door(ecs, x, y), _ => {} } } @@ -376,3 +377,17 @@ fn bear_trap(ecs: &mut World, x: i32, y: i32) { .marked::>() .build(); } + +fn door(ecs: &mut World, x: i32, y: i32) { + ecs.create_entity() + .with(Position { x, y }) + .with(Renderable { + glyph: rltk::to_cp437('+'), + fg: RGB::named(rltk::CHOCOLATE), + bg: RGB::named(rltk::BLACK), + render_order: 2, + }) + .with(Name::from("Door")) + .marked::>() + .build(); +}