From ce3d92bfe2edfe84cc3d69e900db64a096e61196 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Fri, 10 Dec 2021 16:35:09 -0500 Subject: [PATCH] Complete section 4.12 --- src/map_builders/prefab_builder.rs | 97 +++++++++++++++---- .../prefab_builder/prefab_sections.rs | 80 +++++++++++++++ 2 files changed, 158 insertions(+), 19 deletions(-) create mode 100644 src/map_builders/prefab_builder/prefab_sections.rs diff --git a/src/map_builders/prefab_builder.rs b/src/map_builders/prefab_builder.rs index d00ee03..7b6cf98 100644 --- a/src/map_builders/prefab_builder.rs +++ b/src/map_builders/prefab_builder.rs @@ -1,4 +1,5 @@ mod prefab_levels; +mod prefab_sections; use super::{remove_unreachable_areas_returning_most_distant, MapBuilder}; use crate::{spawner, Map, Position, TileType, SHOW_MAPGEN_VISUALIZER}; @@ -8,8 +9,15 @@ use specs::prelude::*; #[derive(PartialEq, Clone)] #[allow(dead_code)] pub enum PrefabMode { - RexLevel { template: &'static str }, - Constant { level: prefab_levels::PrefabLevel }, + RexLevel { + template: &'static str, + }, + Constant { + level: prefab_levels::PrefabLevel, + }, + Sectional { + section: prefab_sections::PrefabSection, + }, } pub struct PrefabBuilder { @@ -18,7 +26,8 @@ pub struct PrefabBuilder { depth: i32, history: Vec, mode: PrefabMode, - spawns: Vec<(usize, String)>, + previous_builder: Option>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for PrefabBuilder { @@ -38,12 +47,6 @@ impl MapBuilder for PrefabBuilder { self.build(); } - fn spawn_entities(&mut self, ecs: &mut World) { - for entity in self.spawns.iter() { - spawner::spawn_entity(ecs, &(&entity.0, &entity.1)); - } - } - fn take_snapshot(&mut self) { if SHOW_MAPGEN_VISUALIZER { let mut snapshot = self.map.clone(); @@ -53,27 +56,33 @@ impl MapBuilder for PrefabBuilder { self.history.push(snapshot); } } + + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + &self.spawn_list + } } impl PrefabBuilder { #[allow(dead_code)] - pub fn new(new_depth: i32) -> PrefabBuilder { + pub fn new(new_depth: i32, previous_builder: Option>) -> PrefabBuilder { PrefabBuilder { map: Map::new(new_depth), starting_position: Position { x: 0, y: 0 }, depth: new_depth, history: Vec::new(), - mode: PrefabMode::Constant { - level: prefab_levels::WFC_POPULATED, + mode: PrefabMode::Sectional { + section: prefab_sections::UNDERGROUND_FORT, }, - spawns: Vec::new(), + previous_builder, + spawn_list: Vec::new(), } } fn build(&mut self) { match self.mode { - PrefabMode::RexLevel { template } => self.load_rex_map(&template), + PrefabMode::RexLevel { template } => self.load_rex_map(template), PrefabMode::Constant { level } => self.load_ascii_map(&level), + PrefabMode::Sectional { section } => self.apply_sectional(§ion), } self.take_snapshot(); @@ -121,23 +130,23 @@ impl PrefabBuilder { '>' => self.map.tiles[idx] = TileType::DownStairs, 'g' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Goblin".to_string())); + self.spawn_list.push((idx, "Goblin".to_string())); } 'o' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Orc".to_string())); + self.spawn_list.push((idx, "Orc".to_string())); } '^' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Bear Trap".to_string())); + self.spawn_list.push((idx, "Bear Trap".to_string())); } '%' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Rations".to_string())); + self.spawn_list.push((idx, "Rations".to_string())); } '!' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Health Potion".to_string())); + self.spawn_list.push((idx, "Health Potion".to_string())); } _ => { rltk::console::log(format!("Unknown glyph loading map: {}", (ch as u8) as char)); @@ -195,4 +204,54 @@ impl PrefabBuilder { } } } + + pub fn apply_sectional(&mut self, section: &prefab_sections::PrefabSection) { + use prefab_sections::*; + + let string_vec = Self::read_ascii_to_vec(section.template); + + // Place the new section + let chunk_x = match section.placement.0 { + HorizontalPlacement::Left => 0, + HorizontalPlacement::Center => (self.map.width / 2) - (section.width as i32 / 2), + HorizontalPlacement::Right => (self.map.width - 1) - section.width as i32, + }; + + let chunk_y = match section.placement.1 { + VerticalPlacement::Top => 0, + VerticalPlacement::Center => (self.map.height / 2) - (section.height as i32 / 2), + VerticalPlacement::Bottom => (self.map.height - 1) - section.height as i32, + }; + + // Build the map + let prev_builder = self.previous_builder.as_mut().unwrap(); + prev_builder.build_map(); + self.starting_position = prev_builder.get_starting_position(); + self.map = prev_builder.get_map(); + for e in prev_builder.get_spawn_list().iter() { + let idx = e.0; + let x = idx as i32 % self.map.width; + let y = idx as i32 / self.map.width; + if x < chunk_x + || x > (chunk_x + section.width as i32) + || y < chunk_y + || y > (chunk_y + section.height as i32) + { + self.spawn_list.push((idx, e.1.to_string())) + } + } + self.take_snapshot(); + + let mut i = 0; + for ty in 0..section.height { + for tx in 0..section.width { + if tx < self.map.width as usize && ty < self.map.height as usize { + let idx = self.map.xy_idx(tx as i32 + chunk_x, ty as i32 + chunk_y); + self.char_to_map(string_vec[i], idx); + } + i += 1; + } + } + self.take_snapshot(); + } } diff --git a/src/map_builders/prefab_builder/prefab_sections.rs b/src/map_builders/prefab_builder/prefab_sections.rs new file mode 100644 index 0000000..2466787 --- /dev/null +++ b/src/map_builders/prefab_builder/prefab_sections.rs @@ -0,0 +1,80 @@ +#[allow(dead_code)] +#[derive(PartialEq, Copy, Clone)] +pub enum HorizontalPlacement { + Left, + Center, + Right, +} + +#[allow(dead_code)] +#[derive(PartialEq, Copy, Clone)] +pub enum VerticalPlacement { + Top, + Center, + Bottom, +} + +#[allow(dead_code)] +#[derive(PartialEq, Copy, Clone)] +pub struct PrefabSection { + pub template: &'static str, + pub width: usize, + pub height: usize, + pub placement: (HorizontalPlacement, VerticalPlacement), +} + +#[allow(dead_code)] +pub const UNDERGROUND_FORT: PrefabSection = PrefabSection { + template: RIGHT_FORT, + width: 15, + height: 43, + placement: (HorizontalPlacement::Right, VerticalPlacement::Top), +}; + +#[allow(dead_code)] +// The padding needs to be here! +const RIGHT_FORT: &str = " + # + ####### + # # + # ####### + # g # + # ####### + # # + ### ### + # # + # # + # ## + ^ + ^ + # ## + # # + # # + # # + # # + ### ### + # # + # # + # g # + # # + # # + ### ### + # # + # # + # # + # ## + ^ + ^ + # ## + # # + # # + # # + ### ### + # # + # ####### + # g # + # ####### + # # + ####### + # +";