--- a/rust/landgen/src/wavefront_collapse/generator.rs Tue Feb 14 08:52:20 2023 +0100
+++ b/rust/landgen/src/wavefront_collapse/generator.rs Wed Feb 15 12:36:24 2023 +0100
@@ -36,9 +36,18 @@
}
#[derive(Clone)]
+pub struct NonStrictEdgesDescription {
+ pub top: Option<EdgeDescription>,
+ pub right: Option<EdgeDescription>,
+ pub bottom: Option<EdgeDescription>,
+ pub left: Option<EdgeDescription>,
+}
+
+#[derive(Clone)]
pub struct TemplateDescription {
pub size: Size,
pub tiles: Vec<TileDescription>,
+ pub edges: NonStrictEdgesDescription,
pub wrap: bool,
}
@@ -107,34 +116,19 @@
}
}
- let edges: Vec<Edge<String>> = [
- &tile_description.edges.top,
- &tile_description.edges.right,
- &tile_description.edges.bottom,
- &tile_description.edges.left,
- ]
- .iter()
- .map(|descr| {
- let edge = Edge::new(descr.name.clone(), descr.symmetrical.unwrap_or_default());
-
- if descr.reversed.unwrap_or_default() {
- edge.reversed()
- } else {
- edge
- }
- })
- .collect();
-
- let [top_edge, right_edge, bottom_edge, left_edge] = edges.as_slice() else {
- unreachable!()
- };
+ let [top_edge, right_edge, bottom_edge, left_edge]: [Edge<String>; 4] = [
+ (&tile_description.edges.top).into(),
+ (&tile_description.edges.right).into(),
+ (&tile_description.edges.bottom).into(),
+ (&tile_description.edges.left).into(),
+ ];
let tile = TileImage::<T, String>::new(
tiles_image,
- top_edge.clone(),
- right_edge.clone(),
- bottom_edge.clone(),
- left_edge.clone(),
+ top_edge,
+ right_edge,
+ bottom_edge,
+ left_edge,
);
result.push(tile.clone());
@@ -178,25 +172,72 @@
result
}
-}
-impl LandGenerator for WavefrontCollapseLandGenerator {
- fn generate_land<T: Copy + PartialEq + Default, I: Iterator<Item = u32>>(
+ pub fn build_rules<T: Copy + PartialEq + Default>(
&self,
- parameters: &LandGenerationParameters<T>,
- random_numbers: &mut I,
- ) -> land2d::Land2D<T> {
- let tiles = self.load_template(parameters);
+ tiles: &[TileImage<T, String>],
+ ) -> Vec<CollapseRule> {
+ let [grid_top_edge, grid_right_edge, grid_bottom_edge, grid_left_edge]: [Option<
+ Edge<String>,
+ >; 4] = [
+ self.template.edges.top.as_ref(),
+ self.template.edges.right.as_ref(),
+ self.template.edges.bottom.as_ref(),
+ self.template.edges.left.as_ref(),
+ ]
+ .map(|opt| opt.map(|d| d.into()));
let mut rules = Vec::<CollapseRule>::new();
- let default_connection = HashSet::from_iter(vec![Tile::Outside, Tile::Empty].into_iter());
+ let default_connection = HashSet::from_iter(vec![Tile::Empty].into_iter());
for (i, tile) in tiles.iter().enumerate() {
let mut right = default_connection.clone();
let mut bottom = default_connection.clone();
let mut left = default_connection.clone();
let mut top = default_connection.clone();
+ // compatibility with grid edges
+ if grid_top_edge
+ .as_ref()
+ .map(|e| e.is_compatible(tile.top_edge()))
+ .unwrap_or(true)
+ {
+ top.insert(Tile::Outside);
+ }
+ if grid_right_edge
+ .as_ref()
+ .map(|e| e.is_compatible(tile.right_edge()))
+ .unwrap_or(true)
+ {
+ right.insert(Tile::Outside);
+ }
+ if grid_bottom_edge
+ .as_ref()
+ .map(|e| e.is_compatible(tile.bottom_edge()))
+ .unwrap_or(true)
+ {
+ bottom.insert(Tile::Outside);
+ }
+ if grid_left_edge
+ .as_ref()
+ .map(|e| e.is_compatible(tile.left_edge()))
+ .unwrap_or(true)
+ {
+ left.insert(Tile::Outside);
+ }
+
+ // compatibility with itself
+ if tile.left_edge().is_compatible(tile.right_edge()) {
+ left.insert(Tile::Numbered(i));
+ right.insert(Tile::Numbered(i));
+ }
+
+ if tile.top_edge().is_compatible(tile.bottom_edge()) {
+ top.insert(Tile::Numbered(i));
+ bottom.insert(Tile::Numbered(i));
+ }
+
+ // compatibility with previously defined tiles
for p in 0..i {
if tiles[p].left_edge().is_compatible(tile.right_edge()) {
rules[p].left.insert(Tile::Numbered(i));
@@ -228,6 +269,19 @@
});
}
+ rules
+ }
+}
+
+impl LandGenerator for WavefrontCollapseLandGenerator {
+ fn generate_land<T: Copy + PartialEq + Default, I: Iterator<Item = u32>>(
+ &self,
+ parameters: &LandGenerationParameters<T>,
+ random_numbers: &mut I,
+ ) -> land2d::Land2D<T> {
+ let tiles = self.load_template(parameters);
+ let rules = self.build_rules(&tiles);
+
let mut wfc = WavefrontCollapse::new(self.template.wrap);
wfc.set_rules(rules);
@@ -244,6 +298,7 @@
wfc.generate_map(&wfc_size, |_| {}, random_numbers);
+ // render tiles into resulting land array
let mut result = land2d::Land2D::new(&self.template.size, parameters.zero);
let offset_y = result.height() - result.play_height();
let offset_x = (result.width() - result.play_width()) / 2;
@@ -272,3 +327,15 @@
result
}
}
+
+impl From<&EdgeDescription> for Edge<String> {
+ fn from(val: &EdgeDescription) -> Self {
+ let edge = Edge::new(val.name.clone(), val.symmetrical.unwrap_or_default());
+
+ if val.reversed.unwrap_or_default() {
+ edge.reversed()
+ } else {
+ edge
+ }
+ }
+}
--- a/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Tue Feb 14 08:52:20 2023 +0100
+++ b/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Wed Feb 15 12:36:24 2023 +0100
@@ -70,17 +70,15 @@
let x = if self.wrap {
if x == usize::MAX {
self.grid.width() - 1
+ } else if x == self.grid.width() {
+ 0
} else {
- if x == self.grid.width() {
- 0
- } else {
- x
- }
+ x
}
} else {
x
};
-
+
self.grid.get(y, x).copied().unwrap_or_default()
}
--- a/rust/mapgen/src/lib.rs Tue Feb 14 08:52:20 2023 +0100
+++ b/rust/mapgen/src/lib.rs Wed Feb 15 12:36:24 2023 +0100
@@ -248,7 +248,7 @@
#[cfg(test)]
mod tests {
- use crate::{MapGenerator, TemplateType, OutlineTemplate};
+ use crate::{MapGenerator, OutlineTemplate, TemplateType};
use rand::thread_rng;
#[test]
--- a/rust/mapgen/src/template/wavefront_collapse.rs Tue Feb 14 08:52:20 2023 +0100
+++ b/rust/mapgen/src/template/wavefront_collapse.rs Wed Feb 15 12:36:24 2023 +0100
@@ -42,6 +42,16 @@
#[derive(Deserialize)]
pub struct TileDescriptionHelper(#[serde(with = "TileDesc")] TileDescription);
+#[derive(Deserialize)]
+pub struct EdgeDescriptionHelper(#[serde(with = "EdgeDesc")] EdgeDescription);
+
+#[derive(Deserialize)]
+pub struct NonStrictEdgesDesc {
+ pub top: Option<EdgeDescriptionHelper>,
+ pub right: Option<EdgeDescriptionHelper>,
+ pub bottom: Option<EdgeDescriptionHelper>,
+ pub left: Option<EdgeDescriptionHelper>,
+}
#[derive(Deserialize)]
pub struct TemplateDesc {
@@ -52,6 +62,7 @@
pub put_girders: bool,
pub max_hedgehogs: u8,
pub wrap: bool,
+ pub edges: Option<NonStrictEdgesDesc>,
pub tiles: Vec<TileDescriptionHelper>,
}
@@ -63,6 +74,18 @@
impl From<&TemplateDesc> for TemplateDescription {
fn from(desc: &TemplateDesc) -> Self {
+ let [top, right, bottom, left] = if let Some(edges) = &desc.edges {
+ [
+ edges.top.as_ref(),
+ edges.right.as_ref(),
+ edges.bottom.as_ref(),
+ edges.left.as_ref(),
+ ]
+ .map(|e| e.map(|EdgeDescriptionHelper(e)| e.clone()))
+ } else {
+ [None, None, None, None]
+ };
+
Self {
size: Size::new(desc.width, desc.height),
tiles: desc
@@ -71,6 +94,12 @@
.map(|TileDescriptionHelper(t)| t.clone())
.collect(),
wrap: desc.wrap,
+ edges: NonStrictEdgesDescription {
+ top,
+ right,
+ bottom,
+ left,
+ },
}
}
}
--- a/share/hedgewars/Data/wfc_templates.yaml Tue Feb 14 08:52:20 2023 +0100
+++ b/share/hedgewars/Data/wfc_templates.yaml Wed Feb 15 12:36:24 2023 +0100
@@ -1,8 +1,8 @@
+---
# Templates for wavefront collapse map generator in hedgewars
templates:
- # 00
- -
+ - &template_00
width: 3960
height: 1920
can_invert: false
@@ -10,7 +10,11 @@
put_girders: true
max_hedgehogs: 40
wrap: true
- tiles:
+ edges:
+ bottom:
+ name: "ff"
+ symmetrical: true
+ tiles: &template_00_tiles
- name: "120_bar.png"
edges:
top:
@@ -127,12 +131,54 @@
can_rotate180: false
can_rotate270: false
+ - &template_01
+ width: 3960
+ height: 1920
+ can_invert: false
+ is_negative: false
+ put_girders: true
+ max_hedgehogs: 40
+ wrap: false
+ edges: &open_edges
+ top:
+ name: "ee"
+ symmetrical: true
+ right:
+ name: "ee"
+ symmetrical: true
+ bottom:
+ name: "ff"
+ symmetrical: true
+ left:
+ name: "ee"
+ symmetrical: true
+ tiles: *template_00_tiles
+ - &template_02
+ width: 1200
+ height: 600
+ can_invert: false
+ is_negative: false
+ put_girders: true
+ max_hedgehogs: 24
+ wrap: false
+ edges: *open_edges
+ tiles: *template_00_tiles
+ - &template_03
+ width: 720
+ height: 7920
+ can_invert: false
+ is_negative: false
+ put_girders: true
+ max_hedgehogs: 64
+ wrap: false
+ edges: *open_edges
+ tiles: *template_00_tiles
template_types:
- small: [0]
- medium: [0]
- large: [0]
+ small: [2]
+ medium: [1]
+ large: [1]
cavern: [0]
- wacky: [0]
+ wacky: [3]