--- a/rust/landgen/Cargo.toml Sat Jan 18 16:57:26 2025 +0100
+++ b/rust/landgen/Cargo.toml Tue Jan 21 22:10:55 2025 +0100
@@ -8,7 +8,6 @@
integral-geometry = { path = "../integral-geometry" }
land2d = { path = "../land2d" }
vec2d = { path = "../vec2d" }
-itertools = "0.14"
png = "0.17"
rand = "0.8"
--- a/rust/landgen/src/wavefront_collapse/generator.rs Sat Jan 18 16:57:26 2025 +0100
+++ b/rust/landgen/src/wavefront_collapse/generator.rs Tue Jan 21 22:10:55 2025 +0100
@@ -9,14 +9,14 @@
use std::io::{BufReader, Result};
use std::path::{Path, PathBuf};
-#[derive(Clone)]
+#[derive(Debug, Clone)]
pub struct EdgeDescription {
pub name: String,
pub reversed: Option<bool>,
pub symmetrical: Option<bool>,
}
-#[derive(Clone)]
+#[derive(Debug, Clone)]
pub struct EdgesDescription {
pub top: EdgeDescription,
pub right: EdgeDescription,
@@ -24,7 +24,7 @@
pub left: EdgeDescription,
}
-#[derive(Clone)]
+#[derive(Debug, Clone)]
pub struct TileDescription {
pub name: String,
pub edges: EdgesDescription,
@@ -36,19 +36,26 @@
pub can_rotate270: Option<bool>,
}
-#[derive(Clone)]
-pub struct NonStrictEdgesDescription {
- pub top: Option<EdgeDescription>,
- pub right: Option<EdgeDescription>,
- pub bottom: Option<EdgeDescription>,
- pub left: Option<EdgeDescription>,
+#[derive(Debug, Clone)]
+pub struct ComplexEdgeDescription {
+ pub begin: Option<EdgeDescription>,
+ pub fill: Option<EdgeDescription>,
+ pub end: Option<EdgeDescription>,
}
-#[derive(Clone)]
+#[derive(Debug, Clone)]
+pub struct NonStrictComplexEdgesDescription {
+ pub top: Option<ComplexEdgeDescription>,
+ pub right: Option<ComplexEdgeDescription>,
+ pub bottom: Option<ComplexEdgeDescription>,
+ pub left: Option<ComplexEdgeDescription>,
+}
+
+#[derive(Debug, Clone)]
pub struct TemplateDescription {
pub size: Size,
pub tiles: Vec<TileDescription>,
- pub edges: NonStrictEdgesDescription,
+ pub edges: NonStrictComplexEdgesDescription,
pub wrap: bool,
}
@@ -79,7 +86,7 @@
.as_path(),
)?;
let decoder = Decoder::new(BufReader::new(file));
- let mut reader = decoder.read_info().unwrap();
+ let mut reader = decoder.read_info()?;
let info = reader.info();
let mut tiles_image = vec2d::Vec2D::new(
@@ -88,7 +95,7 @@
);
let mut buf = vec![0; reader.output_buffer_size()];
- let info = reader.next_frame(&mut buf).unwrap();
+ let info = reader.next_frame(&mut buf)?;
let bytes = &buf[..info.buffer_size()];
let mut tiles_image_pixels = tiles_image.as_mut_slice().iter_mut();
@@ -183,14 +190,14 @@
probability_distribution_factor: i32,
) -> Vec<CollapseRule> {
let [grid_top_edge, grid_right_edge, grid_bottom_edge, grid_left_edge]: [Option<
- Edge<String>,
+ [Option<Edge<String>>; 3],
>; 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()));
+ .map(|opt| opt.map(|d| [&d.begin, &d.fill, &d.end].map(|e| e.as_ref().map(Into::into))));
let mut rules = Vec::<CollapseRule>::new();
@@ -201,34 +208,32 @@
let mut left = default_connection.clone();
let mut top = default_connection.clone();
+ let iteration = [
+ (&grid_top_edge, tile.top_edge(), &mut top),
+ (&grid_right_edge, tile.right_edge(), &mut right),
+ (&grid_bottom_edge, tile.bottom_edge(), &mut bottom),
+ (&grid_left_edge, tile.left_edge(), &mut left),
+ ];
+
// 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);
+ for (edge, tile_edge, set) in iteration {
+ for (is_compatible, tile) in edge
+ .as_ref()
+ .map(|e| {
+ e.clone().map(|ed| {
+ ed.as_ref()
+ .map(|e| e.is_compatible(tile_edge))
+ .unwrap_or(true)
+ })
+ })
+ .unwrap_or([true, true, true])
+ .into_iter()
+ .zip([Tile::OutsideBegin, Tile::OutsideFill, Tile::OutsideEnd].into_iter())
+ {
+ if is_compatible {
+ set.insert(tile);
+ }
+ }
}
// compatibility with itself
@@ -244,21 +249,25 @@
// compatibility with previously defined tiles
for p in 0..i {
+ // Check left edge
if tiles[p].left_edge().is_compatible(tile.right_edge()) {
rules[p].left.insert(Tile::Numbered(i));
right.insert(Tile::Numbered(p));
}
+ // Check right edge
if tiles[p].right_edge().is_compatible(tile.left_edge()) {
rules[p].right.insert(Tile::Numbered(i));
left.insert(Tile::Numbered(p));
}
+ // Check top edge
if tiles[p].top_edge().is_compatible(tile.bottom_edge()) {
rules[p].top.insert(Tile::Numbered(i));
bottom.insert(Tile::Numbered(p));
}
+ // Check bottom edge
if tiles[p].bottom_edge().is_compatible(tile.top_edge()) {
rules[p].bottom.insert(Tile::Numbered(i));
top.insert(Tile::Numbered(p));
--- a/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Sat Jan 18 16:57:26 2025 +0100
+++ b/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Tue Jan 21 22:10:55 2025 +0100
@@ -8,16 +8,12 @@
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum Tile {
Empty,
- Outside,
+ OutsideBegin,
+ OutsideFill,
+ OutsideEnd,
Numbered(usize),
}
-impl Default for Tile {
- fn default() -> Self {
- Tile::Outside
- }
-}
-
#[derive(Debug)]
pub struct CollapseRule {
pub weight: u32,
@@ -83,11 +79,38 @@
x
};
- self.grid.get(y, x).copied().unwrap_or_default()
+ self.grid.get(y, x).copied().unwrap_or_else(|| {
+ let x_out = x >= self.grid.width();
+
+ if x_out {
+ let y_at_begin = y == 0;
+ let y_at_end = y.wrapping_add(1) == self.grid.height();
+ if y_at_begin {
+ Tile::OutsideBegin
+ } else if y_at_end {
+ Tile::OutsideEnd
+ } else {
+ Tile::OutsideFill
+ }
+ } else {
+ // if not x, then it is y
+
+ let x_at_begin = x == 0;
+ let x_at_end = x.wrapping_add(1) == self.grid.width();
+
+ if x_at_begin {
+ Tile::OutsideBegin
+ } else if x_at_end {
+ Tile::OutsideEnd
+ } else {
+ Tile::OutsideFill
+ }
+ }
+ })
}
fn collapse_step(&mut self, random_numbers: &mut impl Rng) -> bool {
- let mut tiles_to_collapse = (usize::max_value(), Vec::new());
+ let mut tiles_to_collapse = (usize::MAX, Vec::new());
// Iterate through the tiles in the land
for x in 0..self.grid.width() {
@@ -96,8 +119,8 @@
if let Tile::Empty = current_tile {
// calc entropy
- let right_tile = self.get_tile(y, x + 1);
- let bottom_tile = self.get_tile(y + 1, x);
+ let right_tile = self.get_tile(y, x.wrapping_add(1));
+ let bottom_tile = self.get_tile(y.wrapping_add(1), x);
let left_tile = self.get_tile(y, x.wrapping_sub(1));
let top_tile = self.get_tile(y.wrapping_sub(1), x);
--- a/rust/mapgen/Cargo.toml Sat Jan 18 16:57:26 2025 +0100
+++ b/rust/mapgen/Cargo.toml Tue Jan 21 22:10:55 2025 +0100
@@ -2,7 +2,7 @@
name = "mapgen"
version = "0.1.0"
authors = ["Hedgewars Project"]
-edition = "2018"
+edition = "2021"
[dependencies]
vec2d = { path = "../vec2d" }
@@ -13,6 +13,6 @@
rand = "0.8"
serde = "1.0"
-serde_yaml = "0.8"
+serde_yaml = "0.9"
serde_derive = "1.0"
-png = "0.13"
\ No newline at end of file
+png = "0.13"
--- a/rust/mapgen/src/template/wavefront_collapse.rs Sat Jan 18 16:57:26 2025 +0100
+++ b/rust/mapgen/src/template/wavefront_collapse.rs Tue Jan 21 22:10:55 2025 +0100
@@ -5,7 +5,7 @@
use std::collections::hash_map::HashMap;
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
#[serde(remote = "EdgeDescription")]
pub struct EdgeDesc {
pub name: String,
@@ -13,7 +13,7 @@
pub symmetrical: Option<bool>,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
#[serde(remote = "EdgesDescription")]
pub struct EdgesDesc {
#[serde(with = "EdgeDesc")]
@@ -26,7 +26,7 @@
pub left: EdgeDescription,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
#[serde(remote = "TileDescription")]
pub struct TileDesc {
pub name: String,
@@ -40,20 +40,26 @@
pub can_rotate270: Option<bool>,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
pub struct TileDescriptionHelper(#[serde(with = "TileDesc")] TileDescription);
-#[derive(Deserialize)]
+#[derive(Debug, 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(Debug, Deserialize)]
+pub struct ComplexEdgeDesc {
+ pub begin: Option<EdgeDescriptionHelper>,
+ pub fill: Option<EdgeDescriptionHelper>,
+ pub end: Option<EdgeDescriptionHelper>,
+}
+#[derive(Debug, Deserialize)]
+pub struct NonStrictComplexEdgesDesc {
+ pub top: Option<ComplexEdgeDesc>,
+ pub right: Option<ComplexEdgeDesc>,
+ pub bottom: Option<ComplexEdgeDesc>,
+ pub left: Option<ComplexEdgeDesc>,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
pub struct TemplateDesc {
pub width: usize,
pub height: usize,
@@ -62,11 +68,11 @@
pub put_girders: bool,
pub max_hedgehogs: u8,
pub wrap: bool,
- pub edges: Option<NonStrictEdgesDesc>,
+ pub edges: Option<NonStrictComplexEdgesDesc>,
pub tiles: Vec<TileDescriptionHelper>,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
pub struct TemplateCollectionDesc {
pub templates: Vec<TemplateDesc>,
pub template_types: HashMap<String, Vec<usize>>,
@@ -74,14 +80,14 @@
impl From<&TemplateDesc> for TemplateDescription {
fn from(desc: &TemplateDesc) -> Self {
- let [top, right, bottom, left] = if let Some(edges) = &desc.edges {
+ let [top, right, bottom, left]:[Option<ComplexEdgeDescription>; 4] = if let Some(edges) = &desc.edges {
[
- edges.top.as_ref(),
- edges.right.as_ref(),
- edges.bottom.as_ref(),
- edges.left.as_ref(),
+ &edges.top,
+ &edges.right,
+ &edges.bottom,
+ &edges.left,
]
- .map(|e| e.map(|EdgeDescriptionHelper(e)| e.clone()))
+ .map(|e| e.as_ref().map(Into::into))
} else {
[None, None, None, None]
};
@@ -94,7 +100,7 @@
.map(|TileDescriptionHelper(t)| t.clone())
.collect(),
wrap: desc.wrap,
- edges: NonStrictEdgesDescription {
+ edges: NonStrictComplexEdgesDescription {
top,
right,
bottom,
@@ -103,3 +109,13 @@
}
}
}
+
+impl From<&ComplexEdgeDesc> for ComplexEdgeDescription {
+ fn from(value: &ComplexEdgeDesc) -> Self {
+ Self {
+ begin: value.begin.as_ref().map(|EdgeDescriptionHelper(e)| e.clone()),
+ fill: value.fill.as_ref().map(|EdgeDescriptionHelper(e)| e.clone()),
+ end: value.end.as_ref().map(|EdgeDescriptionHelper(e)| e.clone()),
+ }
+ }
+}
--- a/share/hedgewars/Data/wfc_templates.yaml Sat Jan 18 16:57:26 2025 +0100
+++ b/share/hedgewars/Data/wfc_templates.yaml Tue Jan 21 22:10:55 2025 +0100
@@ -12,9 +12,34 @@
wrap: true
edges:
bottom:
- name: "ff"
- symmetrical: true
+ fill:
+ name: "ff"
+ symmetrical: true
+ top:
+ fill:
+ name: "ff"
+ symmetrical: true
tiles: &template_00_tiles
+ - name: "120_filled.png"
+ edges:
+ top:
+ name: "ff"
+ symmetrical: true
+ right:
+ name: "ff"
+ symmetrical: true
+ bottom:
+ name: "ff"
+ symmetrical: true
+ left:
+ name: "ff"
+ symmetrical: true
+ is_negative: true
+ can_mirror: false
+ can_flip: false
+ can_rotate90: false
+ can_rotate180: false
+ can_rotate270: false
- name: "120_bar.png"
edges:
top:
@@ -33,7 +58,27 @@
can_flip: false
can_rotate90: true
can_rotate180: true
- can_rotate270: true
+ can_rotate270: true
+ - name: "120_filled.png"
+ edges:
+ top:
+ name: "ee"
+ symmetrical: true
+ right:
+ name: "ee"
+ symmetrical: true
+ bottom:
+ name: "ee"
+ symmetrical: true
+ left:
+ name: "ee"
+ symmetrical: true
+ is_negative: false
+ can_mirror: false
+ can_flip: false
+ can_rotate90: false
+ can_rotate180: false
+ can_rotate270: false
- name: "120_corner.png"
edges:
top:
@@ -72,46 +117,6 @@
can_rotate90: true
can_rotate180: true
can_rotate270: true
- - name: "120_filled.png"
- edges:
- top:
- name: "ff"
- symmetrical: true
- right:
- name: "ff"
- symmetrical: true
- bottom:
- name: "ff"
- symmetrical: true
- left:
- name: "ff"
- symmetrical: true
- is_negative: true
- can_mirror: false
- can_flip: false
- can_rotate90: false
- can_rotate180: false
- can_rotate270: false
- - name: "120_filled.png"
- edges:
- top:
- name: "ee"
- symmetrical: true
- right:
- name: "ee"
- symmetrical: true
- bottom:
- name: "ee"
- symmetrical: true
- left:
- name: "ee"
- symmetrical: true
- is_negative: false
- can_mirror: false
- can_flip: false
- can_rotate90: false
- can_rotate180: false
- can_rotate270: false
- name: "120_two_corners.png"
edges:
top:
@@ -141,17 +146,44 @@
wrap: false
edges: &open_edges
top:
- name: "ee"
- symmetrical: true
+ begin:
+ name: "ee"
+ symmetrical: true
+ fill:
+ name: "ee"
+ symmetrical: true
+ end:
+ name: "ee"
+ symmetrical: true
right:
- name: "ee"
- symmetrical: true
+ begin:
+ name: "ee"
+ symmetrical: true
+ fill:
+ name: "ee"
+ symmetrical: true
+ end:
+ name: "ee"
+ symmetrical: true
bottom:
- name: "ff"
- symmetrical: true
+ begin:
+ name: "fe"
+ reversed: true
+ fill:
+ name: "ff"
+ symmetrical: true
+ end:
+ name: "fe"
left:
- name: "ee"
- symmetrical: true
+ begin:
+ name: "ee"
+ symmetrical: true
+ fill:
+ name: "ee"
+ symmetrical: true
+ end:
+ name: "ee"
+ symmetrical: true
tiles: *template_00_tiles
- &template_02