diff --git a/src/map_builders/bsp_dungeon.rs b/src/map_builders/bsp_dungeon.rs index 27f9ca9..e073624 100644 --- a/src/map_builders/bsp_dungeon.rs +++ b/src/map_builders/bsp_dungeon.rs @@ -1,4 +1,4 @@ -use super::{apply_room_to_map, draw_corridor, BuilderMap, InitialMapBuilder, Map, Rect, TileType}; +use super::{BuilderMap, InitialMapBuilder, Map, Rect, TileType}; use rltk::RandomNumberGenerator; pub struct BspDungeonBuilder { @@ -32,11 +32,9 @@ impl BspDungeonBuilder { let rect = self.get_random_rect(rng); let candidate = self.get_random_sub_rect(rect, rng); - if self.is_possible(candidate, &build_data.map) { - apply_room_to_map(&mut build_data.map, &candidate); + if self.is_possible(candidate, &build_data, &rooms) { rooms.push(candidate); self.add_subrects(rect); - build_data.take_snapshot(); } n_rooms += 1; @@ -81,7 +79,7 @@ impl BspDungeonBuilder { result } - fn is_possible(&self, rect: Rect, map: &Map) -> bool { + fn is_possible(&self, rect: Rect, build_data: &BuilderMap, rooms: &Vec) -> bool { let mut expanded = rect; expanded.x1 -= 2; expanded.x2 += 2; @@ -90,12 +88,18 @@ impl BspDungeonBuilder { let mut can_build = true; + for r in rooms.iter() { + if r.intersect(&rect) { + can_build = false; + } + } + for y in expanded.y1..=expanded.y2 { for x in expanded.x1..=expanded.x2 { - if x > map.width - 2 { + if x > build_data.map.width - 2 { can_build = false; } - if y > map.height - 2 { + if y > build_data.map.height - 2 { can_build = false; } if x < 1 { @@ -105,14 +109,14 @@ impl BspDungeonBuilder { can_build = false; } if can_build { - let idx = map.xy_idx(x, y); - if map.tiles[idx] != TileType::Wall { + let idx = build_data.map.xy_idx(x, y); + if build_data.map.tiles[idx] != TileType::Wall { can_build = false; } } } } - can_build + return can_build; } } diff --git a/src/map_builders/mod.rs b/src/map_builders/mod.rs index 0ddd797..0d23e9f 100644 --- a/src/map_builders/mod.rs +++ b/src/map_builders/mod.rs @@ -46,6 +46,8 @@ mod rooms_corridors_bsp; use rooms_corridors_bsp::BspCorridors; mod room_sorter; use room_sorter::{RoomSort, RoomSorter}; +mod room_draw; +use room_draw::RoomDrawer; // Shared data to be passed around build chain pub struct BuilderMap { @@ -172,6 +174,14 @@ fn random_room_builder(rng: &mut rltk::RandomNumberGenerator, builder: &mut Buil _ => builder.with(RoomSorter::new(RoomSort::CENTRAL)), } + builder.with(RoomDrawer::new()); + + let corridor_roll = rng.roll_dice(1, 2); + match corridor_roll { + 1 => builder.with(DoglegCorridors::new()), + _ => builder.with(BspCorridors::new()), + } + let corridor_roll = rng.roll_dice(1, 2); match corridor_roll { 1 => builder.with(DoglegCorridors::new()), @@ -252,11 +262,9 @@ pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator) -> _ => random_shape_builder(rng, &mut builder), } - /* WFC needs some fixes. - if rng.roll_dice(1, 3) == 1 { - builder.with(WaveFunctionCollapseBuilder::new()); - } - */ + /*if rng.roll_dice(1, 3)==1 { + builder.with(WaveformCollapseBuilder::new()); + }*/ if rng.roll_dice(1, 20) == 1 { builder.with(PrefabBuilder::sectional(prefab_builder::prefab_sections::UNDERGROUND_FORT)); diff --git a/src/map_builders/room_draw.rs b/src/map_builders/room_draw.rs new file mode 100644 index 0000000..7f4c192 --- /dev/null +++ b/src/map_builders/room_draw.rs @@ -0,0 +1,62 @@ +use super::{BuilderMap, MetaMapBuilder, Rect, TileType}; +use rltk::RandomNumberGenerator; + +pub struct RoomDrawer {} + +impl MetaMapBuilder for RoomDrawer { + fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) { + self.build(rng, build_data); + } +} + +impl RoomDrawer { + #[allow(dead_code)] + pub fn new() -> Box { + return Box::new(RoomDrawer {}); + } + + fn rectangle(&mut self, build_data: &mut BuilderMap, room: &Rect) { + for y in room.y1 + 1..=room.y2 { + for x in room.x1 + 1..=room.x2 { + let idx = build_data.map.xy_idx(x, y); + if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize { + build_data.map.tiles[idx] = TileType::Floor; + } + } + } + } + + fn circle(&mut self, build_data: &mut BuilderMap, room: &Rect) { + let radius = i32::min(room.x2 - room.x1, room.y2 - room.y1) as f32 / 2.0; + let center = room.centre(); + let center_pt = rltk::Point::new(center.0, center.1); + for y in room.y1..=room.y2 { + for x in room.x1..=room.x2 { + let idx = build_data.map.xy_idx(x, y); + let distance = rltk::DistanceAlg::Pythagoras.distance2d(center_pt, rltk::Point::new(x, y)); + if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize && distance <= radius + { + build_data.map.tiles[idx] = TileType::Floor; + } + } + } + } + + 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 Drawing require a builder with room structures"); + } + + for room in rooms.iter() { + let room_type = rng.roll_dice(1, 4); + match room_type { + 1 => self.circle(build_data, room), + _ => self.rectangle(build_data, room), + } + build_data.take_snapshot(); + } + } +} diff --git a/src/map_builders/simple_map.rs b/src/map_builders/simple_map.rs index 40d0605..8c54d50 100644 --- a/src/map_builders/simple_map.rs +++ b/src/map_builders/simple_map.rs @@ -35,11 +35,7 @@ impl SimpleMapBuilder { } } if ok { - apply_room_to_map(&mut build_data.map, &new_room); - build_data.take_snapshot(); - rooms.push(new_room); - build_data.take_snapshot(); } } build_data.rooms = Some(rooms); diff --git a/src/spawner.rs b/src/spawner.rs index 295f831..7c90a27 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -170,6 +170,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) { "confusion wand" => confusion_wand(ecs, x, y), // Food "rations" => rations(ecs, x, y), + "apple" => apple(ecs, x, y), // Traps "bear trap" => bear_trap(ecs, x, y), "confusion trap" => confusion_trap(ecs, x, y), @@ -220,7 +221,7 @@ fn item_table(_map_depth: i32) -> RandomTable { } fn food_table(_map_depth: i32) -> RandomTable { - return RandomTable::new().add("rations", 1); + return RandomTable::new().add("rations", 1).add("apple", 1); } fn trap_table(_map_depth: i32) -> RandomTable { @@ -492,6 +493,23 @@ fn rations(ecs: &mut World, x: i32, y: i32) { .build(); } +fn apple(ecs: &mut World, x: i32, y: i32) { + ecs.create_entity() + .with(Position { x, y }) + .with(Renderable { + glyph: rltk::to_cp437('%'), + fg: RGB::named(rltk::GREEN), + bg: RGB::named(rltk::BLACK), + render_order: 2, + }) + .with(Name { name: "apple".to_string(), plural: "apples".to_string() }) + .with(Item {}) + .with(ProvidesNutrition {}) + .with(Consumable {}) + .marked::>() + .build(); +} + // WANDS fn fireball_wand(ecs: &mut World, x: i32, y: i32) {