diff --git a/src/map_builders/mod.rs b/src/map_builders/mod.rs index 999d604..54e92b3 100644 --- a/src/map_builders/mod.rs +++ b/src/map_builders/mod.rs @@ -32,24 +32,30 @@ pub trait MapBuilder { } pub fn random_builder(new_depth: i32) -> Box { - // let mut rng = rltk::RandomNumberGenerator::new(); - // match rng.roll_dice(1, 16) { - // 1 => Box::new(BspDungeonBuilder::new(new_depth)), - // 2 => Box::new(BspInteriorBuilder::new(new_depth)), - // 3 => Box::new(CellularAutomataBuilder::new(new_depth)), - // 4 => Box::new(DrunkardsWalkBuilder::open_area(new_depth)), - // 5 => Box::new(DrunkardsWalkBuilder::open_halls(new_depth)), - // 6 => Box::new(DrunkardsWalkBuilder::winding_passages(new_depth)), - // 7 => Box::new(DrunkardsWalkBuilder::fat_passages(new_depth)), - // 8 => Box::new(DrunkardsWalkBuilder::fearful_symmetry(new_depth)), - // 9 => Box::new(MazeBuilder::new(new_depth)), - // 10 => Box::new(DLABuilder::walk_inwards(new_depth)), - // 11 => Box::new(DLABuilder::walk_outwards(new_depth)), - // 12 => Box::new(DLABuilder::central_attractor(new_depth)), - // 13 => Box::new(DLABuilder::insectoid(new_depth)), - // 14 => Box::new(VoronoiCellBuilder::pythagoras(new_depth)), - // 15 => Box::new(VoronoiCellBuilder::manhattan(new_depth)), - // _ => Box::new(SimpleMapBuilder::new(new_depth)), - // } - Box::new(WaveformCollapseBuilder::new(new_depth)) + let mut rng = rltk::RandomNumberGenerator::new(); + let mut result: Box = match rng.roll_dice(1, 17) { + 1 => Box::new(BspDungeonBuilder::new(new_depth)), + 2 => Box::new(BspInteriorBuilder::new(new_depth)), + 3 => Box::new(CellularAutomataBuilder::new(new_depth)), + 4 => Box::new(DrunkardsWalkBuilder::open_area(new_depth)), + 5 => Box::new(DrunkardsWalkBuilder::open_halls(new_depth)), + 6 => Box::new(DrunkardsWalkBuilder::winding_passages(new_depth)), + 7 => Box::new(DrunkardsWalkBuilder::fat_passages(new_depth)), + 8 => Box::new(DrunkardsWalkBuilder::fearful_symmetry(new_depth)), + 9 => Box::new(MazeBuilder::new(new_depth)), + 10 => Box::new(DLABuilder::walk_inwards(new_depth)), + 11 => Box::new(DLABuilder::walk_outwards(new_depth)), + 12 => Box::new(DLABuilder::central_attractor(new_depth)), + 13 => Box::new(DLABuilder::insectoid(new_depth)), + 14 => Box::new(VoronoiCellBuilder::pythagoras(new_depth)), + 15 => Box::new(VoronoiCellBuilder::manhattan(new_depth)), + 16 => Box::new(WaveformCollapseBuilder::test_map(new_depth)), + _ => Box::new(SimpleMapBuilder::new(new_depth)), + }; + + if rng.roll_dice(1, 3) == 1 { + result = Box::new(WaveformCollapseBuilder::derived_map(new_depth, result)); + } + + result } diff --git a/src/map_builders/waveform_collapse/constraints.rs b/src/map_builders/waveform_collapse/constraints.rs index 136e9ec..c91ca94 100644 --- a/src/map_builders/waveform_collapse/constraints.rs +++ b/src/map_builders/waveform_collapse/constraints.rs @@ -212,9 +212,10 @@ pub fn patterns_to_constraints(patterns: Vec>, chunk_size: i32) -> c.compatible_with[direction].push(j); } if !has_any { - // There's no exits on this side, we don't care what goes there - for compat in c.compatible_with.iter_mut() { - compat.push(j); + // There's no exits on this side, let's match only if + // the other edge also has no exits + if potential.exits[opposite].iter().filter(|a| !**a).count() == 0 { + c.compatible_with[direction].push(j); } } } diff --git a/src/map_builders/waveform_collapse/mod.rs b/src/map_builders/waveform_collapse/mod.rs index d148ee7..dea554a 100644 --- a/src/map_builders/waveform_collapse/mod.rs +++ b/src/map_builders/waveform_collapse/mod.rs @@ -16,12 +16,20 @@ use solver::*; use specs::prelude::*; use std::collections::HashMap; +#[derive(PartialEq, Copy, Clone)] +pub enum WaveformMode { + TestMap, + Derived, +} + pub struct WaveformCollapseBuilder { map: Map, starting_position: Position, depth: i32, history: Vec, noise_areas: HashMap>, + mode: WaveformMode, + derive_from: Option>, } impl MapBuilder for WaveformCollapseBuilder { @@ -40,7 +48,7 @@ impl MapBuilder for WaveformCollapseBuilder { } fn get_starting_position(&self) -> Position { - self.starting_position.clone() + self.starting_position } fn get_snapshot_history(&self) -> Vec { @@ -59,25 +67,64 @@ impl MapBuilder for WaveformCollapseBuilder { } impl WaveformCollapseBuilder { - pub fn new(new_depth: i32) -> WaveformCollapseBuilder { + /// Generic constructor for waveform collapse. + /// # Arguments + /// * new_depth - the new map depth + /// * derive_from - either None, or a boxed MapBuilder, as output by `random_builder` + pub fn new( + new_depth: i32, + mode: WaveformMode, + derive_from: Option>, + ) -> WaveformCollapseBuilder { WaveformCollapseBuilder { map: Map::new(new_depth), starting_position: Position { x: 0, y: 0 }, depth: new_depth, history: Vec::new(), noise_areas: HashMap::new(), + mode, + derive_from, } } + /// Creates a Wave Function Collapse builder using the baked-in WFC test map. + /// # Arguments + /// * new_depth - the new map depth + pub fn test_map(new_depth: i32) -> WaveformCollapseBuilder { + WaveformCollapseBuilder::new(new_depth, WaveformMode::TestMap, None) + } + + /// Derives a map from a pre-existing map builder. + /// # Arguments + /// * new_depth - the new map depth + /// * derive_from - either None, or a boxed MapBuilder, as output by `random_builder` + pub fn derived_map(new_depth: i32, builder: Box) -> WaveformCollapseBuilder { + WaveformCollapseBuilder::new(new_depth, WaveformMode::Derived, Some(builder)) + } + fn build(&mut self) { + if self.mode == WaveformMode::TestMap { + self.map = load_rex_map( + self.depth, + &rltk::XpFile::from_resource("../resources/wfc-demo1.xp").unwrap(), + ); + self.take_snapshot(); + + return; + } + let mut rng = RandomNumberGenerator::new(); - const CHUNK_SIZE: i32 = 7; + const CHUNK_SIZE: i32 = 8; - self.map = load_rex_map( - self.depth, - &rltk::XpFile::from_resource("../resources/wfc-demo2.xp").unwrap(), - ); + let prebuilder = &mut self.derive_from.as_mut().unwrap(); + prebuilder.build_map(); + self.map = prebuilder.get_map(); + for t in self.map.tiles.iter_mut() { + if *t == TileType::DownStairs { + *t = TileType::Floor + } + } self.take_snapshot(); let patterns = build_patterns(&self.map, CHUNK_SIZE, true, true); @@ -104,10 +151,12 @@ impl WaveformCollapseBuilder { let mut start_idx = self .map .xy_idx(self.starting_position.x, self.starting_position.y); - // while self.map.tiles[start_idx] != TileType::Floor { - // self.starting_position.x -= 1; - // start_idx = self.map.xy_idx(self.starting_position.x, self.starting_position.y); - // } + while self.map.tiles[start_idx] != TileType::Floor { + self.starting_position.x -= 1; + start_idx = self + .map + .xy_idx(self.starting_position.x, self.starting_position.y); + } self.take_snapshot(); // Find all tiles we can reach from the starting point @@ -122,7 +171,7 @@ impl WaveformCollapseBuilder { self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng); } - fn render_tile_gallery(&mut self, constraints: &Vec, chunk_size: i32) { + fn render_tile_gallery(&mut self, constraints: &[MapChunk], chunk_size: i32) { self.map = Map::new(0); let mut counter = 0; let mut x = 1; diff --git a/src/map_builders/waveform_collapse/solver.rs b/src/map_builders/waveform_collapse/solver.rs index fcefabd..4380c5a 100644 --- a/src/map_builders/waveform_collapse/solver.rs +++ b/src/map_builders/waveform_collapse/solver.rs @@ -41,28 +41,28 @@ impl Solver { if chunk_x > 0 { let left_idx = self.chunk_idx(chunk_x - 1, chunk_y); - if let Some(_) = self.chunks[left_idx] { + if self.chunks[left_idx].is_some() { neighbors += 1; } } if chunk_x < self.chunks_x - 1 { let right_idx = self.chunk_idx(chunk_x + 1, chunk_y); - if let Some(_) = self.chunks[right_idx] { + if self.chunks[right_idx].is_some() { neighbors += 1; } } if chunk_y > 0 { let up_idx = self.chunk_idx(chunk_x, chunk_y - 1); - if let Some(_) = self.chunks[up_idx] { + if self.chunks[up_idx].is_some() { neighbors += 1; } } if chunk_y < self.chunks_y - 1 { let down_idx = self.chunk_idx(chunk_x, chunk_y + 1); - if let Some(_) = self.chunks[down_idx] { + if self.chunks[down_idx].is_some() { neighbors += 1; } } diff --git a/src/rex_assets.rs b/src/rex_assets.rs index 52327fe..b76b12c 100644 --- a/src/rex_assets.rs +++ b/src/rex_assets.rs @@ -2,7 +2,6 @@ use rltk::rex::XpFile; rltk::embedded_resource!(SMALL_DUNGEON, "../resources/SmallDungeon_80x50.xp"); rltk::embedded_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp"); -rltk::embedded_resource!(WFC_DEMO_IMAGE2, "../resources/wfc-demo2.xp"); pub struct RexAssets { pub menu: XpFile, @@ -12,7 +11,6 @@ impl RexAssets { pub fn new() -> RexAssets { rltk::link_resource!(SMALL_DUNGEON, "../resources/SmallDungeon_80x50.xp"); rltk::link_resource!(WFC_DEMO_IMAGE1, "../resources/wfc-demo1.xp"); - rltk::link_resource!(WFC_DEMO_IMAGE2, "../resources/wfc-demo2.xp"); RexAssets { menu: XpFile::from_resource("../resources/SmallDungeon_80x50.xp").unwrap(),