diff --git a/src/map_builders.rs b/src/map_builders.rs index 0d210c3..1aaf747 100644 --- a/src/map_builders.rs +++ b/src/map_builders.rs @@ -12,6 +12,8 @@ mod prefab_builder; mod room_based_spawner; mod room_based_stairs; mod room_based_starting_position; +mod room_corner_rounding; +mod room_exploder; mod simple_map; mod voronoi; mod voronoi_spawning; @@ -31,6 +33,8 @@ use prefab_builder::PrefabBuilder; use room_based_spawner::RoomBasedSpawner; use room_based_stairs::RoomBasedStairs; use room_based_starting_position::RoomBasedStartingPosition; +use room_corner_rounding::RoomCornerRounder; +use room_exploder::RoomExploder; use simple_map::SimpleMapBuilder; use specs::prelude::*; use voronoi::VoronoiCellBuilder; diff --git a/src/map_builders/room_corner_rounding.rs b/src/map_builders/room_corner_rounding.rs new file mode 100644 index 0000000..e48f248 --- /dev/null +++ b/src/map_builders/room_corner_rounding.rs @@ -0,0 +1,60 @@ +use crate::map_builders::{BuilderMap, MetaMapBuilder}; +use crate::{Rect, TileType}; +use rltk::RandomNumberGenerator; + +pub struct RoomCornerRounder {} + +impl MetaMapBuilder for RoomCornerRounder { + fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { + self.build(rng, build_data); + } +} + +impl RoomCornerRounder { + #[allow(dead_code)] + pub fn new() -> Box { + Box::new(RoomCornerRounder {}) + } + + fn fill_if_corner(&mut self, x: i32, y: i32, build_data: &mut BuilderMap) { + let w = build_data.map.width; + let h = build_data.map.height; + let idx = build_data.map.xy_idx(x, y); + let mut neighbor_walls = 0; + + if x > 0 && build_data.map.tiles[idx - 1] == TileType::Wall { + neighbor_walls += 1; + } + if y > 0 && build_data.map.tiles[idx - w as usize] == TileType::Wall { + neighbor_walls += 1; + } + if x < w - 2 && build_data.map.tiles[idx + 1] == TileType::Wall { + neighbor_walls += 1; + } + if y < h - 2 && build_data.map.tiles[idx + w as usize] == TileType::Wall { + neighbor_walls += 1; + } + + if neighbor_walls == 2 { + build_data.map.tiles[idx] = TileType::Wall; + } + } + + fn build(&mut self, _rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { + let rooms: Vec; + if let Some(rooms_builder) = &build_data.rooms { + rooms = rooms_builder.clone(); + } else { + panic!("Room Rounding requires a builder with room structures"); + } + + for room in rooms.iter() { + self.fill_if_corner(room.x1 + 1, room.y1 + 1, build_data); + self.fill_if_corner(room.x2, room.y1 + 1, build_data); + self.fill_if_corner(room.x1 + 1, room.y2, build_data); + self.fill_if_corner(room.x2, room.y2, build_data); + + build_data.take_snapshot(); + } + } +} diff --git a/src/map_builders/room_exploder.rs b/src/map_builders/room_exploder.rs new file mode 100644 index 0000000..3db8a7f --- /dev/null +++ b/src/map_builders/room_exploder.rs @@ -0,0 +1,88 @@ +use crate::map_builders::common::{paint, Symmetry}; +use crate::map_builders::{BuilderMap, MetaMapBuilder}; +use crate::{Rect, TileType}; +use rltk::RandomNumberGenerator; + +pub struct RoomExploder {} + +impl MetaMapBuilder for RoomExploder { + fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { + self.build(rng, build_data); + } +} + +impl RoomExploder { + #[allow(dead_code)] + pub fn new() -> Box { + Box::new(RoomExploder {}) + } + + fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { + let rooms: Vec; + if let Some(rooms_builder) = &build_data.rooms { + rooms = rooms_builder.clone(); + } else { + panic!("Room Explosions require a builder with room structures"); + } + + for room in rooms.iter() { + let start = room.center(); + let n_diggers = rng.roll_dice(1, 20) - 5; + + if n_diggers > 0 { + for _i in 0..n_diggers { + let mut drunk_x = start.0; + let mut drunk_y = start.1; + + let mut drunk_life = 20; + let mut did_something = false; + + while drunk_life > 0 { + let drunk_idx = build_data.map.xy_idx(drunk_x, drunk_y); + if build_data.map.tiles[drunk_idx] == TileType::Wall { + did_something = true; + } + + paint(&mut build_data.map, Symmetry::None, 1, drunk_x, drunk_y); + build_data.map.tiles[drunk_idx] = TileType::DownStairs; + + match rng.roll_dice(1, 4) { + 1 => { + if drunk_x > 2 { + drunk_x -= 1; + } + } + 2 => { + if drunk_x < build_data.map.width - 2 { + drunk_x += 1; + } + } + 3 => { + if drunk_y > 2 { + drunk_y -= 1; + } + } + _ => { + if drunk_y < build_data.map.height - 2 { + drunk_y += 1; + } + } + } + + drunk_life -= 1; + } + + if did_something { + build_data.take_snapshot(); + } + + for t in build_data.map.tiles.iter_mut() { + if *t == TileType::DownStairs { + *t = TileType::Floor; + } + } + } + } + } + } +}