Add templates for different maze styles transitional_engine
authorunC0Rr
Wed, 18 Sep 2024 13:42:26 +0200
branchtransitional_engine
changeset 16035 0caa3dfb3ba2
parent 16034 09beeec033ba
child 16036 7b8d96fc8799
Add templates for different maze styles
hedgewars/uLand.pas
rust/landgen/src/maze.rs
rust/landgen/src/outline_template_based/outline.rs
rust/landgen/src/outline_template_based/template_based.rs
rust/lib-hwengine-future/src/lib.rs
rust/mapgen/src/lib.rs
rust/mapgen/src/template/maze.rs
share/hedgewars/Data/CMakeLists.txt
share/hedgewars/Data/maze_templates.yaml
--- a/hedgewars/uLand.pas	Mon Sep 16 16:57:11 2024 +0200
+++ b/hedgewars/uLand.pas	Wed Sep 18 13:42:26 2024 +0200
@@ -363,7 +363,7 @@
         SelectTemplate:= 'small'
     else
         begin
-        if cTemplateFilter = 0 then
+        if (cTemplateFilter = 0) and (cMapGen <> mgMaze) then
             begin
             l:= getRandom(GroupedTemplatesCount);
             repeat
@@ -373,19 +373,32 @@
             end
             else getRandom(1);
 
-            case cTemplateFilter of
-            0: OutError('Error selecting TemplateFilter. Ask unC0Rr about what you did wrong', true);
-            1: SelectTemplate:= 'small';
-            2: SelectTemplate:= 'medium';
-            3: SelectTemplate:= 'large';
-            4: SelectTemplate:= 'cavern';
-            5: SelectTemplate:= 'wacky';
-    // For lua only!
-            6: begin
-               SelectTemplate:= 'small';
-               GetRandom(2) // burn 1
-               end
-            end
+            case cMapGen of
+                mgMaze:
+                    case cTemplateFilter of
+                    0: SelectTemplate:= 'small_tunnels';
+                    1: SelectTemplate:= 'medium_tunnels';
+                    2: SelectTemplate:= 'large_tunnels';
+                    3: SelectTemplate:= 'small_islands';
+                    4: SelectTemplate:= 'medium_islands';
+                    5: SelectTemplate:= 'large_islands';
+                    else OutError('Error selecting TemplateFilter', true);
+                    end
+              else              
+                    case cTemplateFilter of
+                    1: SelectTemplate:= 'small';
+                    2: SelectTemplate:= 'medium';
+                    3: SelectTemplate:= 'large';
+                    4: SelectTemplate:= 'cavern';
+                    5: SelectTemplate:= 'wacky';
+                    // For lua only!
+                    6: begin
+                       SelectTemplate:= 'small';
+                       GetRandom(2) // burn 1
+                       end
+                    else OutError('Error selecting TemplateFilter', true);
+                    end
+              end
         end;
 
     WriteLnToConsole('Using template filter '+SelectTemplate);
--- a/rust/landgen/src/maze.rs	Mon Sep 16 16:57:11 2024 +0200
+++ b/rust/landgen/src/maze.rs	Wed Sep 18 13:42:26 2024 +0200
@@ -3,6 +3,7 @@
 use integral_geometry::{Point, Polygon, Rect, Size};
 use land2d::Land2D;
 
+#[derive(Clone)]
 pub struct MazeTemplate {
     pub width: usize,
     pub height: usize,
@@ -15,7 +16,7 @@
 struct Maze {
     inverted: bool,
     braidness: u32,
-    off_y: i32,
+    off: Point,
     num_cells: Size,
     num_edges: Size,
     seen_cells: Size,
@@ -109,10 +110,13 @@
             );
         }
 
+        let off_x = ((size.width - num_cells.width * cell_size) / 2) as i32;
+        let off_y = ((size.height - num_cells.height * cell_size) / 2) as i32;
+
         Self {
             inverted,
             braidness,
-            off_y: ((size.height - num_cells.height * cell_size) / 2) as i32,
+            off: Point::new(off_x, off_y),
             num_cells,
             num_edges,
             seen_cells,
@@ -214,8 +218,8 @@
             }
         });
         let new_point = Point::new(
-            (p.x - 1) * self.cell_size as i32 + x as i32,
-            (p.y - 1) * self.cell_size as i32 + y as i32 + self.off_y,
+            (p.x - 1) * self.cell_size as i32 + x as i32 + self.off.x,
+            (p.y - 1) * self.cell_size as i32 + y as i32 + self.off.y,
         );
 
         let nv = polygon.len();
@@ -297,20 +301,6 @@
 
         let mut fill_points = vec![];
 
-        for y in 0..self.num_cells.height {
-            for x in 0..self.num_cells.width {
-                if maze[y][x] {
-                    let half_cell = self.cell_size / 2;
-                    let fill_point = Point::new(
-                        (x * self.cell_size + half_cell) as i32,
-                        (y * self.cell_size + half_cell) as i32 + self.off_y,
-                    );
-                    islands.push(Polygon::new(&[fill_point]));
-                    fill_points.push(fill_point);
-                }
-            }
-        }
-
         for x in 0..self.num_edges.width {
             for y in 0..self.num_cells.height {
                 if self.edge_list[0][y][x] {
@@ -328,12 +318,10 @@
                             polygon.pop();
                         }
 
-                        /*
-                                                for p in &polygon {
-                                                    println!("{} {}", p.x, p.y);
-                                                }
-                                                println!("\ne\n");
-                        */
+                        for p in &polygon {
+                            println!("{} {}", p.x, p.y);
+                        }
+                        println!("\ne\n");
 
                         islands.push(Polygon::new(&polygon));
                     }
@@ -342,6 +330,41 @@
             }
         }
 
+        for x in 0..self.num_cells.width {
+            for y in 0..self.num_cells.height {
+                if maze[y][x] {
+                    let half_cell = self.cell_size / 2;
+                    let fill_point = Point::new(
+                        (x * self.cell_size + half_cell) as i32 + self.off.x,
+                        (y * self.cell_size + half_cell) as i32 + self.off.y,
+                    );
+                    islands.push(Polygon::new(&[fill_point]));
+                    fill_points.push(fill_point);
+
+                    let mut points = vec![(x, y)];
+
+                    while let Some((x, y)) = points.pop() {
+                        if maze[y][x] {
+                            maze[y][x] = false;
+
+                            if x > 0 {
+                                points.push((x - 1, y));
+                            }
+                            if x < self.num_cells.width - 1 {
+                                points.push((x + 1, y));
+                            }
+                            if y > 0 {
+                                points.push((x, y - 1));
+                            }
+                            if y < self.num_cells.height - 1 {
+                                points.push((x, y + 1));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
         (islands, fill_points)
     }
 }
@@ -431,7 +454,7 @@
         );
 
         if !parameters.skip_distort {
-            points.distort(parameters.distance_divisor, random_numbers);
+            points.distort(parameters.distance_divisor, self.maze_template.distortion_limiting_factor, random_numbers);
         }
 
         if !parameters.skip_bezier {
--- a/rust/landgen/src/outline_template_based/outline.rs	Mon Sep 16 16:57:11 2024 +0200
+++ b/rust/landgen/src/outline_template_based/outline.rs	Wed Sep 18 13:42:26 2024 +0200
@@ -278,10 +278,9 @@
     pub fn distort<I: Iterator<Item = u32>>(
         &mut self,
         distance_divisor: u32,
+        distortion_limiting_factor: u32,
         random_numbers: &mut I,
     ) {
-        let distortion_limiting_factor = 100 + random_numbers.next().unwrap() as u32 % 8 * 10;
-
         loop {
             let old_len = self.total_len();
             self.divide_edges(distance_divisor, distortion_limiting_factor, random_numbers);
--- a/rust/landgen/src/outline_template_based/template_based.rs	Mon Sep 16 16:57:11 2024 +0200
+++ b/rust/landgen/src/outline_template_based/template_based.rs	Wed Sep 18 13:42:26 2024 +0200
@@ -54,7 +54,9 @@
         }
 
         if !parameters.skip_distort {
-            points.distort(parameters.distance_divisor, random_numbers);
+            let distortion_limiting_factor = 100 + random_numbers.next().unwrap() % 8 * 10;
+
+            points.distort(parameters.distance_divisor, distortion_limiting_factor, random_numbers);
         }
 
         if !parameters.skip_bezier {
--- a/rust/lib-hwengine-future/src/lib.rs	Mon Sep 16 16:57:11 2024 +0200
+++ b/rust/lib-hwengine-future/src/lib.rs	Wed Sep 18 13:42:26 2024 +0200
@@ -141,17 +141,21 @@
 
     let mut random_numbers_gen = LaggedFibonacciPRNG::new(seed.as_bytes());
 
-    let map_gen = MapGenerator::<MazeTemplate>::new(data_path);
+    let yaml_templates =
+        fs::read_to_string(data_path.join(Path::new("maze_templates.yaml")).as_path())
+            .expect("Error reading map templates file");
+
+    let mut map_gen = MapGenerator::<MazeTemplate>::new(data_path);
+    map_gen.import_yaml_templates(&yaml_templates);
+
     let distance_divisor = feature_size.pow(2) / 8 + 10;
     let params = LandGenerationParameters::new(0u16, 0x8000u16, distance_divisor, false, false);
-    let template = MazeTemplate {
-        width: 4096,
-        height: 2048,
-        cell_size: 225,
-        inverted: false,
-        distortion_limiting_factor: 120,
-        braidness: 10,
-    };
+
+    let template = map_gen
+        .get_template(template_type, &mut random_numbers_gen)
+        .expect("Error reading maze templates file")
+        .clone();
+
     let landgen = map_gen.build_generator(template);
     let collision = landgen.generate_land(&params, &mut random_numbers_gen);
     let size = collision.size().size();
--- a/rust/mapgen/src/lib.rs	Mon Sep 16 16:57:11 2024 +0200
+++ b/rust/mapgen/src/lib.rs	Wed Sep 18 13:42:26 2024 +0200
@@ -189,7 +189,7 @@
             .map(|(size, indices)| {
                 (
                     TemplateType(size),
-                    indices.indices.iter().map(|i| (&templates[*i]).into()).collect(),
+                    indices.iter().map(|i| (&templates[*i]).into()).collect(),
                 )
             })
             .collect();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/mapgen/src/template/maze.rs	Wed Sep 18 13:42:26 2024 +0200
@@ -0,0 +1,33 @@
+use landgen::maze::MazeTemplate;
+use serde_derive::Deserialize;
+
+use std::collections::hash_map::HashMap;
+#[derive(Deserialize)]
+pub struct TemplateDesc {
+    width: usize,
+    height: usize,
+    max_hedgehogs: u8,
+    cell_size: usize,
+    distortion_limiting_factor: u32,
+    braidness: u32,
+    invert: bool,
+}
+
+#[derive(Deserialize)]
+pub struct TemplateCollectionDesc {
+    pub templates: Vec<TemplateDesc>,
+    pub template_types: HashMap<String, Vec<usize>>,
+}
+
+impl From<&TemplateDesc> for MazeTemplate {
+    fn from(desc: &TemplateDesc) -> Self {
+        MazeTemplate {
+            width: desc.width,
+            height: desc.height,
+            cell_size: desc.cell_size,
+            inverted: desc.invert,
+            distortion_limiting_factor: desc.distortion_limiting_factor,
+            braidness: desc.braidness,
+        }
+    }
+}
--- a/share/hedgewars/Data/CMakeLists.txt	Mon Sep 16 16:57:11 2024 +0200
+++ b/share/hedgewars/Data/CMakeLists.txt	Wed Sep 18 13:42:26 2024 +0200
@@ -22,5 +22,6 @@
 
 install(FILES
     map_templates.yaml
+    maze_templates.yaml
     wfc_templates.yaml
     DESTINATION ${SHAREPATH}Data)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/maze_templates.yaml	Wed Sep 18 13:42:26 2024 +0200
@@ -0,0 +1,131 @@
+# Templates for maze map generator in hedgewars
+
+templates:
+  # 00
+  -
+    width: 2048
+    height: 1024
+    max_hedgehogs: 64
+    cell_size: 100
+    distortion_limiting_factor: 140
+    braidness: 12
+    invert: false
+
+  # 01
+  -
+    width: 1536
+    height: 1024
+    max_hedgehogs: 64
+    cell_size: 64
+    distortion_limiting_factor: 160
+    braidness: 8
+    invert: false
+
+  # 02
+  -
+    width: 2048
+    height: 1024
+    max_hedgehogs: 64
+    cell_size: 140
+    distortion_limiting_factor: 140
+    braidness: 12
+    invert: false
+
+  # 03
+  -
+    width: 4096
+    height: 2048
+    max_hedgehogs: 64
+    cell_size: 160
+    distortion_limiting_factor: 180
+    braidness: 16
+    invert: false
+
+  # 04
+  -
+    width: 4096
+    height: 2048
+    max_hedgehogs: 64
+    cell_size: 240
+    distortion_limiting_factor: 220
+    braidness: 20
+    invert: false
+
+  # 05
+  -
+    width: 4096
+    height: 2048
+    max_hedgehogs: 64
+    cell_size: 280
+    distortion_limiting_factor: 220
+    braidness: 20
+    invert: false
+
+  # 06
+  -
+    width: 1024
+    height: 1024
+    max_hedgehogs: 64
+    cell_size: 64
+    distortion_limiting_factor: 150
+    braidness: 3
+    invert: true
+
+  # 07
+  -
+    width: 2048
+    height: 1024
+    max_hedgehogs: 64
+    cell_size: 80
+    distortion_limiting_factor: 150
+    braidness: 5
+    invert: true
+
+  # 08
+  -
+    width: 2048
+    height: 1024
+    max_hedgehogs: 64
+    cell_size: 120
+    distortion_limiting_factor: 150
+    braidness: 5
+    invert: true
+
+  # 09
+  -
+    width: 4096
+    height: 2048
+    max_hedgehogs: 64
+    cell_size: 140
+    distortion_limiting_factor: 200
+    braidness: 10
+    invert: true
+
+  # 10
+  -
+    width: 4096
+    height: 2048
+    max_hedgehogs: 64
+    cell_size: 220
+    distortion_limiting_factor: 250
+    braidness: 10
+    invert: true
+
+  # 11
+  -
+    width: 4096
+    height: 2048
+    max_hedgehogs: 64
+    cell_size: 256
+    distortion_limiting_factor: 280
+    braidness: 10
+    invert: true
+
+template_types:
+  small_tunnels: [0, 1]
+  medium_tunnels: [2, 3]
+  large_tunnels: [4, 5]
+  small_islands: [6, 7]
+  medium_islands: [8, 9]
+  large_islands: [10, 11]
+