Browse Source

Finish Voronoi chapter.

Herbert Wolverson 4 years ago
parent
commit
503c633ba9

+ 0 - 2
book/src/SUMMARY.md

@@ -35,6 +35,4 @@
     - [Diffusion-limited aggregation maps](./chapter_30.md)
     - [Add symmetry and brushes to the library](./chapter_31.md)
     - [Voronoi Hive Maps](./chapter_32.md)
-    - Noise
-    - Quantum Waveform Collapse
 [Contributors](./contributors.md)

BIN
book/src/c32-s1.gif


BIN
book/src/c32-s2.gif


File diff suppressed because it is too large
+ 251 - 0
book/src/chapter_32.md


+ 2 - 2
chapter-32-voronoi/src/map_builders/common.rs

@@ -38,13 +38,13 @@ pub fn apply_vertical_tunnel(map : &mut Map, y1:i32, y2:i32, x:i32) {
 pub fn remove_unreachable_areas_returning_most_distant(map : &mut Map, start_idx : usize) -> usize {
     map.populate_blocked();
     let map_starts : Vec<i32> = vec![start_idx as i32];
-    let dijkstra_map = rltk::DijkstraMap::new(map.width, map.height, &map_starts , map, 300.0);
+    let dijkstra_map = rltk::DijkstraMap::new(map.width, map.height, &map_starts , map, 400.0);
     let mut exit_tile = (0, 0.0f32);
     for (i, tile) in map.tiles.iter_mut().enumerate() {
         if *tile == TileType::Floor {
             let distance_to_start = dijkstra_map.map[i];
             // We can't get to this tile - so we'll make it a wall
-            if distance_to_start > 300.0 {
+            if distance_to_start == std::f32::MAX {
                 *tile = TileType::Wall;
             } else {
                 // If it is further away than our current exit candidate, move the exit

+ 4 - 4
chapter-32-voronoi/src/map_builders/mod.rs

@@ -29,9 +29,8 @@ pub trait MapBuilder {
 }
 
 pub fn random_builder(new_depth: i32) -> Box<dyn MapBuilder> {
-    /*
     let mut rng = rltk::RandomNumberGenerator::new();
-    let builder = rng.roll_dice(1, 14);
+    let builder = rng.roll_dice(1, 16);
     match builder {
         1 => Box::new(BspDungeonBuilder::new(new_depth)),
         2 => Box::new(BspInteriorBuilder::new(new_depth)),
@@ -46,8 +45,9 @@ pub fn random_builder(new_depth: i32) -> Box<dyn MapBuilder> {
         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(VoronoiCellBuilder::new(new_depth))
+    }
 }
 

+ 56 - 11
chapter-32-voronoi/src/map_builders/voronoi.rs

@@ -1,17 +1,21 @@
 use super::{MapBuilder, Map,  
     TileType, Position, spawner, SHOW_MAPGEN_VISUALIZER,
-    remove_unreachable_areas_returning_most_distant, generate_voronoi_spawn_regions,
-    draw_corridor};
+    remove_unreachable_areas_returning_most_distant, generate_voronoi_spawn_regions};
 use rltk::RandomNumberGenerator;
 use specs::prelude::*;
 use std::collections::HashMap;
 
+#[derive(PartialEq, Copy, Clone)]
+pub enum DistanceAlgorithm { Pythagoras, Manhattan, Chebyshev }
+
 pub struct VoronoiCellBuilder {
     map : Map,
     starting_position : Position,
     depth: i32,
     history: Vec<Map>,
     noise_areas : HashMap<i32, Vec<usize>>,
+    n_seeds: usize,
+    distance_algorithm: DistanceAlgorithm
 }
 
 impl MapBuilder for VoronoiCellBuilder {
@@ -55,20 +59,44 @@ impl VoronoiCellBuilder {
             starting_position : Position{ x: 0, y : 0 },
             depth : new_depth,
             history: Vec::new(),
-            noise_areas : HashMap::new()
+            noise_areas : HashMap::new(),
+            n_seeds: 64,
+            distance_algorithm: DistanceAlgorithm::Pythagoras
         }
     }
 
+    pub fn pythagoras(new_depth : i32) -> VoronoiCellBuilder {
+        VoronoiCellBuilder{
+            map : Map::new(new_depth),
+            starting_position : Position{ x: 0, y : 0 },
+            depth : new_depth,
+            history: Vec::new(),
+            noise_areas : HashMap::new(),
+            n_seeds: 64,
+            distance_algorithm: DistanceAlgorithm::Pythagoras
+        }
+    }
+
+    pub fn manhattan(new_depth : i32) -> VoronoiCellBuilder {
+        VoronoiCellBuilder{
+            map : Map::new(new_depth),
+            starting_position : Position{ x: 0, y : 0 },
+            depth : new_depth,
+            history: Vec::new(),
+            noise_areas : HashMap::new(),
+            n_seeds: 64,
+            distance_algorithm: DistanceAlgorithm::Manhattan
+        }
+    }
 
     #[allow(clippy::map_entry)]
     fn build(&mut self) {
         let mut rng = RandomNumberGenerator::new();
 
         // Make a Voronoi diagram. We'll do this the hard way to learn about the technique!
-        let n_seeds = 64;
         let mut voronoi_seeds : Vec<(usize, rltk::Point)> = Vec::new();
 
-        while voronoi_seeds.len() < n_seeds {
+        while voronoi_seeds.len() < self.n_seeds {
             let vx = rng.roll_dice(1, self.map.width-1);
             let vy = rng.roll_dice(1, self.map.height-1);
             let vidx = self.map.xy_idx(vx, vy);
@@ -78,17 +106,34 @@ impl VoronoiCellBuilder {
             }
         }
 
-        let mut voroni_distance = vec![(0, 0.0f32) ; n_seeds];
+        let mut voroni_distance = vec![(0, 0.0f32) ; self.n_seeds];
         let mut voronoi_membership : Vec<i32> = vec![0 ; self.map.width as usize * self.map.height as usize];
         for (i, vid) in voronoi_membership.iter_mut().enumerate() {
             let x = i as i32 % self.map.width;
             let y = i as i32 / self.map.width;
 
             for (seed, pos) in voronoi_seeds.iter().enumerate() {
-                let distance = rltk::DistanceAlg::PythagorasSquared.distance2d(
-                    rltk::Point::new(x, y), 
-                    pos.1
-                );
+                let distance;
+                match self.distance_algorithm {           
+                    DistanceAlgorithm::Pythagoras => {
+                        distance = rltk::DistanceAlg::PythagorasSquared.distance2d(
+                            rltk::Point::new(x, y), 
+                            pos.1
+                        );
+                    }
+                    DistanceAlgorithm::Manhattan => {
+                        distance = rltk::DistanceAlg::Manhattan.distance2d(
+                            rltk::Point::new(x, y), 
+                            pos.1
+                        );
+                    }
+                    DistanceAlgorithm::Chebyshev => {
+                        distance = rltk::DistanceAlg::Chebyshev.distance2d(
+                            rltk::Point::new(x, y), 
+                            pos.1
+                        );
+                    }
+                }
                 voroni_distance[seed] = (seed, distance);
             }
 
@@ -131,7 +176,7 @@ impl VoronoiCellBuilder {
         self.map.tiles[exit_tile] = TileType::DownStairs;
         self.take_snapshot();
 
-        // Now we build a noise map for use in spawning entities later
+        // Now we build a noise map for use in spawning entities later        
         self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng);
     }    
 }

+ 1 - 0
wasmbuild.bat

@@ -30,6 +30,7 @@ CALL :Stage chapter-28-drunkards-walk
 CALL :Stage chapter-29-mazes
 CALL :Stage chapter-30-dla
 CALL :Stage chapter-31-symmetry
+CALL :Stage chapter-32-voronoi
 
 REM Publish or perish
 cd book\book\wasm