# HG changeset patch # User unC0Rr # Date 1676460984 -3600 # Node ID b0e8cc72bfef31c33c829d795763ba811e03ca9a # Parent 9502611bffc1c7af8e80c5a21d1e25ccd61bc820 Allow defining compatible edges for grid, add few more templates diff -r 9502611bffc1 -r b0e8cc72bfef rust/landgen/src/wavefront_collapse/generator.rs --- 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, + pub right: Option, + pub bottom: Option, + pub left: Option, +} + +#[derive(Clone)] pub struct TemplateDescription { pub size: Size, pub tiles: Vec, + pub edges: NonStrictEdgesDescription, pub wrap: bool, } @@ -107,34 +116,19 @@ } } - let edges: Vec> = [ - &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; 4] = [ + (&tile_description.edges.top).into(), + (&tile_description.edges.right).into(), + (&tile_description.edges.bottom).into(), + (&tile_description.edges.left).into(), + ]; let tile = TileImage::::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>( + pub fn build_rules( &self, - parameters: &LandGenerationParameters, - random_numbers: &mut I, - ) -> land2d::Land2D { - let tiles = self.load_template(parameters); + tiles: &[TileImage], + ) -> Vec { + let [grid_top_edge, grid_right_edge, grid_bottom_edge, grid_left_edge]: [Option< + Edge, + >; 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::::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>( + &self, + parameters: &LandGenerationParameters, + random_numbers: &mut I, + ) -> land2d::Land2D { + 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 { + 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 + } + } +} diff -r 9502611bffc1 -r b0e8cc72bfef rust/landgen/src/wavefront_collapse/wavefront_collapse.rs --- 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() } diff -r 9502611bffc1 -r b0e8cc72bfef rust/mapgen/src/lib.rs --- 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] diff -r 9502611bffc1 -r b0e8cc72bfef rust/mapgen/src/template/wavefront_collapse.rs --- 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, + pub right: Option, + pub bottom: Option, + pub left: Option, +} #[derive(Deserialize)] pub struct TemplateDesc { @@ -52,6 +62,7 @@ pub put_girders: bool, pub max_hedgehogs: u8, pub wrap: bool, + pub edges: Option, pub tiles: Vec, } @@ -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, + }, } } } diff -r 9502611bffc1 -r b0e8cc72bfef share/hedgewars/Data/wfc_templates.yaml --- 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]