From 28692ec50cc3f22c591837a8cfd1cfdb3fe53f58 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Fri, 10 Dec 2021 16:34:11 -0500 Subject: [PATCH] Refactor entity (Enemy, Item, Equipment) spawning --- src/map_builders.rs | 15 ++++++++++++--- src/map_builders/bsp_dungeon.rs | 17 +++++++++++------ src/map_builders/bsp_interior.rs | 22 +++++++++++++--------- src/map_builders/cellular_automata.rs | 23 +++++++++++++++++------ src/map_builders/dla.rs | 23 +++++++++++++++++------ src/map_builders/drunkard.rs | 23 +++++++++++++++++------ src/map_builders/maze.rs | 14 +++++++------- src/map_builders/simple_map.rs | 23 ++++++++++++----------- src/map_builders/voronoi.rs | 23 +++++++++++++++++------ src/map_builders/waveform_collapse.rs | 25 ++++++++++++++++++------- src/spawner.rs | 27 ++++++++++++++++++--------- 11 files changed, 159 insertions(+), 76 deletions(-) diff --git a/src/map_builders.rs b/src/map_builders.rs index 4831ac9..ed65c63 100644 --- a/src/map_builders.rs +++ b/src/map_builders.rs @@ -10,7 +10,7 @@ mod simple_map; mod voronoi; mod waveform_collapse; -use crate::{Map, Position}; +use crate::{spawner, Map, Position}; use bsp_dungeon::BspDungeonBuilder; use bsp_interior::BspInteriorBuilder; use cellular_automata::CellularAutomataBuilder; @@ -29,8 +29,14 @@ pub trait MapBuilder { fn get_starting_position(&self) -> Position; fn get_snapshot_history(&self) -> Vec; fn build_map(&mut self); - fn spawn_entities(&mut self, ecs: &mut World); fn take_snapshot(&mut self); + fn get_spawn_list(&self) -> &Vec<(usize, String)>; + + fn spawn_entities(&mut self, ecs: &mut World) { + for entity in self.get_spawn_list().iter() { + spawner::spawn_entity(ecs, &(&entity.0, &entity.1)); + } + } } pub fn random_builder(new_depth: i32) -> Box { @@ -60,5 +66,8 @@ pub fn random_builder(new_depth: i32) -> Box { // // result - Box::new(PrefabBuilder::new(new_depth)) + Box::new(PrefabBuilder::new( + new_depth, + Some(Box::new(CellularAutomataBuilder::new(new_depth))), + )) } diff --git a/src/map_builders/bsp_dungeon.rs b/src/map_builders/bsp_dungeon.rs index edf8727..5e5449a 100644 --- a/src/map_builders/bsp_dungeon.rs +++ b/src/map_builders/bsp_dungeon.rs @@ -12,6 +12,7 @@ pub struct BspDungeonBuilder { rooms: Vec, history: Vec, rects: Vec, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for BspDungeonBuilder { @@ -31,12 +32,6 @@ impl MapBuilder for BspDungeonBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for room in self.rooms.iter().skip(1) { - spawner::spawn_room(ecs, room, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -47,6 +42,10 @@ impl MapBuilder for BspDungeonBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl BspDungeonBuilder { @@ -58,6 +57,7 @@ impl BspDungeonBuilder { rooms: Vec::new(), history: Vec::new(), rects: Vec::new(), + spawn_list: Vec::new(), } } @@ -113,6 +113,11 @@ impl BspDungeonBuilder { self.map.tiles[stairs_idx] = TileType::DownStairs; self.starting_position = Position::from(self.rooms[0].center()); + + // Spawn some entities + for room in self.rooms.iter().skip(1) { + spawner::spawn_room(&self.map, &mut rng, room, self.depth, &mut self.spawn_list); + } } fn add_subrects(&mut self, rect: Rect) { diff --git a/src/map_builders/bsp_interior.rs b/src/map_builders/bsp_interior.rs index 2105d55..adb2a56 100644 --- a/src/map_builders/bsp_interior.rs +++ b/src/map_builders/bsp_interior.rs @@ -13,6 +13,7 @@ pub struct BspInteriorBuilder { rooms: Vec, history: Vec, rects: Vec, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for BspInteriorBuilder { @@ -32,12 +33,6 @@ impl MapBuilder for BspInteriorBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for room in self.rooms.iter().skip(1) { - spawner::spawn_room(ecs, room, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -47,17 +42,22 @@ impl MapBuilder for BspInteriorBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl BspInteriorBuilder { pub fn new(new_depth: i32) -> BspInteriorBuilder { BspInteriorBuilder { map: Map::new(new_depth), - starting_position: Position { x: 0, y: 0 }, + starting_position: Position::default(), depth: new_depth, rooms: Vec::new(), history: Vec::new(), rects: Vec::new(), + spawn_list: Vec::new(), } } @@ -113,8 +113,12 @@ impl BspInteriorBuilder { let stairs_idx = self.map.xy_idx(stairs.0, stairs.1); self.map.tiles[stairs_idx] = TileType::DownStairs; - let start = self.rooms[0].center(); - self.starting_position = start.into(); + self.starting_position = Position::from(self.rooms[0].center()); + + // Spawn some entities + for room in self.rooms.iter().skip(1) { + spawner::spawn_room(&self.map, &mut rng, room, self.depth, &mut self.spawn_list); + } } fn add_subrects(&mut self, rect: Rect, rng: &mut RandomNumberGenerator) { diff --git a/src/map_builders/cellular_automata.rs b/src/map_builders/cellular_automata.rs index faadf1d..e057a02 100644 --- a/src/map_builders/cellular_automata.rs +++ b/src/map_builders/cellular_automata.rs @@ -13,6 +13,7 @@ pub struct CellularAutomataBuilder { depth: i32, history: Vec, noise_areas: HashMap>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for CellularAutomataBuilder { @@ -32,12 +33,6 @@ impl MapBuilder for CellularAutomataBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -48,6 +43,10 @@ impl MapBuilder for CellularAutomataBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl CellularAutomataBuilder { @@ -58,6 +57,7 @@ impl CellularAutomataBuilder { depth: new_depth, history: Vec::new(), noise_areas: HashMap::new(), + spawn_list: Vec::new(), } } @@ -151,5 +151,16 @@ impl CellularAutomataBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region( + &self.map, + &mut rng, + area.1, + self.depth, + &mut self.spawn_list, + ); + } } } diff --git a/src/map_builders/dla.rs b/src/map_builders/dla.rs index 53af715..9d1871a 100644 --- a/src/map_builders/dla.rs +++ b/src/map_builders/dla.rs @@ -25,6 +25,7 @@ pub struct DLABuilder { brush_size: i32, symmetry: Symmetry, floor_percent: f32, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for DLABuilder { @@ -44,12 +45,6 @@ impl MapBuilder for DLABuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -59,6 +54,10 @@ impl MapBuilder for DLABuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl DLABuilder { @@ -73,6 +72,7 @@ impl DLABuilder { brush_size: 1, symmetry: Symmetry::None, floor_percent: 0.25, + spawn_list: Vec::new(), } } @@ -280,5 +280,16 @@ impl DLABuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region( + &self.map, + &mut rng, + area.1, + self.depth, + &mut self.spawn_list, + ); + } } } diff --git a/src/map_builders/drunkard.rs b/src/map_builders/drunkard.rs index aef7bc2..1da5090 100644 --- a/src/map_builders/drunkard.rs +++ b/src/map_builders/drunkard.rs @@ -29,6 +29,7 @@ pub struct DrunkardsWalkBuilder { history: Vec, noise_areas: HashMap>, settings: DrunkardSettings, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for DrunkardsWalkBuilder { @@ -48,12 +49,6 @@ impl MapBuilder for DrunkardsWalkBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -63,6 +58,10 @@ impl MapBuilder for DrunkardsWalkBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl DrunkardsWalkBuilder { @@ -74,6 +73,7 @@ impl DrunkardsWalkBuilder { history: Vec::new(), noise_areas: HashMap::new(), settings, + spawn_list: Vec::new(), } } @@ -265,5 +265,16 @@ impl DrunkardsWalkBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region( + &self.map, + &mut rng, + area.1, + self.depth, + &mut self.spawn_list, + ); + } } } diff --git a/src/map_builders/maze.rs b/src/map_builders/maze.rs index f1fc4b0..bc3d6f9 100644 --- a/src/map_builders/maze.rs +++ b/src/map_builders/maze.rs @@ -12,6 +12,7 @@ pub struct MazeBuilder { depth: i32, history: Vec, noise_areas: HashMap>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for MazeBuilder { @@ -31,12 +32,6 @@ impl MapBuilder for MazeBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -46,16 +41,21 @@ impl MapBuilder for MazeBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl MazeBuilder { pub fn new(new_depth: i32) -> MazeBuilder { MazeBuilder { map: Map::new(new_depth), - starting_position: Position { x: 0, y: 0 }, + starting_position: Position::default(), depth: new_depth, history: Vec::new(), noise_areas: HashMap::new(), + spawn_list: Vec::new(), } } diff --git a/src/map_builders/simple_map.rs b/src/map_builders/simple_map.rs index 1cc034c..1b7a198 100644 --- a/src/map_builders/simple_map.rs +++ b/src/map_builders/simple_map.rs @@ -10,6 +10,7 @@ pub struct SimpleMapBuilder { depth: i32, rooms: Vec, history: Vec, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for SimpleMapBuilder { @@ -29,12 +30,6 @@ impl MapBuilder for SimpleMapBuilder { self.rooms_and_corridors(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for room in self.rooms.iter().skip(1) { - spawner::spawn_room(ecs, room, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -44,6 +39,10 @@ impl MapBuilder for SimpleMapBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl SimpleMapBuilder { @@ -54,6 +53,7 @@ impl SimpleMapBuilder { depth: new_depth, rooms: Vec::new(), history: Vec::new(), + spawn_list: Vec::new(), } } @@ -104,10 +104,11 @@ impl SimpleMapBuilder { let stairs_idx = self.map.xy_idx(stairs_position.0, stairs_position.1); self.map.tiles[stairs_idx] = TileType::DownStairs; - let start_pos = self.rooms[0].center(); - self.starting_position = Position { - x: start_pos.0, - y: start_pos.1, - }; + self.starting_position = Position::from(self.rooms[0].center()); + + // Spawn some entities + for room in self.rooms.iter().skip(1) { + spawner::spawn_room(&self.map, &mut rng, room, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/voronoi.rs b/src/map_builders/voronoi.rs index c5978aa..e3942ec 100644 --- a/src/map_builders/voronoi.rs +++ b/src/map_builders/voronoi.rs @@ -23,6 +23,7 @@ pub struct VoronoiCellBuilder { noise_areas: HashMap>, n_seeds: usize, distance_algorithm: DistanceAlgorithm, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for VoronoiCellBuilder { @@ -42,12 +43,6 @@ impl MapBuilder for VoronoiCellBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -57,6 +52,10 @@ impl MapBuilder for VoronoiCellBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl VoronoiCellBuilder { @@ -69,6 +68,7 @@ impl VoronoiCellBuilder { noise_areas: HashMap::new(), n_seeds: 64, distance_algorithm: DistanceAlgorithm::Pythagoras, + spawn_list: Vec::new(), } } @@ -183,5 +183,16 @@ impl VoronoiCellBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region( + &self.map, + &mut rng, + area.1, + self.depth, + &mut self.spawn_list, + ); + } } } diff --git a/src/map_builders/waveform_collapse.rs b/src/map_builders/waveform_collapse.rs index 0e1add0..1274eef 100644 --- a/src/map_builders/waveform_collapse.rs +++ b/src/map_builders/waveform_collapse.rs @@ -21,6 +21,7 @@ pub struct WaveformCollapseBuilder { history: Vec, noise_areas: HashMap>, derive_from: Option>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for WaveformCollapseBuilder { @@ -40,12 +41,6 @@ impl MapBuilder for WaveformCollapseBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -55,6 +50,10 @@ impl MapBuilder for WaveformCollapseBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl WaveformCollapseBuilder { @@ -68,11 +67,12 @@ impl WaveformCollapseBuilder { ) -> WaveformCollapseBuilder { WaveformCollapseBuilder { map: Map::new(new_depth), - starting_position: Position { x: 0, y: 0 }, + starting_position: Position::default(), depth: new_depth, history: Vec::new(), noise_areas: HashMap::new(), derive_from, + spawn_list: Vec::new(), } } @@ -141,6 +141,17 @@ impl WaveformCollapseBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region( + &self.map, + &mut rng, + area.1, + self.depth, + &mut self.spawn_list, + ); + } } fn render_tile_gallery(&mut self, constraints: &[MapChunk], chunk_size: i32) { diff --git a/src/spawner.rs b/src/spawner.rs index 34dd491..ff33813 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -56,12 +56,17 @@ fn room_table(map_depth: i32) -> RandomTable { /// fills a room with stuff! #[allow(clippy::map_entry)] -pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) { +pub fn spawn_room( + map: &Map, + rng: &mut RandomNumberGenerator, + room: &Rect, + map_depth: i32, + spawn_list: &mut Vec<(usize, String)>, +) { let mut possible_targets: Vec = Vec::new(); // Borrow scope - to keep access to the map separated { - let map = ecs.fetch::(); for y in room.y1 + 1..room.y2 { for x in room.x1 + 1..room.x2 { let idx = map.xy_idx(x, y); @@ -72,41 +77,45 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) { } } - spawn_region(ecs, &possible_targets, map_depth); + spawn_region(map, rng, &possible_targets, map_depth, spawn_list); } -pub fn spawn_region(ecs: &mut World, area: &[usize], map_depth: i32) { +pub fn spawn_region( + map: &Map, + rng: &mut RandomNumberGenerator, + area: &[usize], + map_depth: i32, + spawn_list: &mut Vec<(usize, String)>, +) { let spawn_table = room_table(map_depth); let mut spawn_points: HashMap = HashMap::new(); let mut areas: Vec = Vec::from(area); // Scope to keep the borrow checker happy { - let mut rng = ecs.write_resource::(); let num_spawns = i32::min( areas.len() as i32, rng.roll_dice(1, MAX_MONSTERS + 3) + (map_depth - 1) - 3, ); - if num_spawns == 0 { return; } for _i in 0..num_spawns { let array_index = if areas.len() == 1 { - 0usize + 0_usize } else { (rng.roll_dice(1, areas.len() as i32) - 1) as usize }; let map_idx = areas[array_index]; - spawn_points.insert(map_idx, spawn_table.roll(&mut rng)); + spawn_points.insert(map_idx, spawn_table.roll(rng)); areas.remove(array_index); } } // Actually spawn the monsters for spawn in spawn_points.iter() { - spawn_entity(ecs, &spawn); + spawn_list.push((*spawn.0, spawn.1.to_string())); } }