# HG changeset patch # User unC0Rr # Date 1738075785 -3600 # Node ID 5d302b12d837b6698f3c6c70215022720ac34371 # Parent a4cbc692643939cbf30ed3912b79909ab193041d - Update landgen to use the latest rand crate - Change Size width and height from usize to u32 for portability - Implement backtracking in wfc generator diff -r a4cbc6926439 -r 5d302b12d837 rust/integral-geometry/src/lib.rs --- a/rust/integral-geometry/src/lib.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/integral-geometry/src/lib.rs Tue Jan 28 15:49:45 2025 +0100 @@ -113,20 +113,20 @@ #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Size { - pub width: usize, - pub height: usize, + pub width: u32, + pub height: u32, } impl Size { pub const EMPTY: Self = Self::square(0); #[inline] - pub const fn new(width: usize, height: usize) -> Self { + pub const fn new(width: u32, height: u32) -> Self { Self { width, height } } #[inline] - pub const fn square(size: usize) -> Self { + pub const fn square(size: u32) -> Self { Self { width: size, height: size, @@ -134,12 +134,12 @@ } #[inline] - pub const fn area(&self) -> usize { + pub const fn area(&self) -> u32 { self.width * self.height } #[inline] - pub const fn linear_index(&self, x: usize, y: usize) -> usize { + pub const fn linear_index(&self, x: u32, y: u32) -> u32 { y * self.width + x } @@ -194,7 +194,7 @@ impl PotSize { #[inline] - const fn new_impl(width: usize, height: usize) -> Self { + const fn new_impl(width: u32, height: u32) -> Self { debug_assert!(width.is_power_of_two() && height.is_power_of_two()); Self { size: Size::new(width, height), @@ -202,7 +202,7 @@ } #[inline] - pub const fn new(width: usize, height: usize) -> Option { + pub const fn new(width: u32, height: u32) -> Option { if width.is_power_of_two() && height.is_power_of_two() { Some(Self::new_impl(width, height)) } else { @@ -214,16 +214,16 @@ self.size } - pub const fn width(&self) -> usize { + pub const fn width(&self) -> u32 { self.size.width } - pub const fn height(&self) -> usize { + pub const fn height(&self) -> u32 { self.size.height } #[inline] - pub const fn square(size: usize) -> Option { + pub const fn square(size: u32) -> Option { if size.is_power_of_two() { Some(Self::new_impl(size, size)) } else { @@ -232,12 +232,12 @@ } #[inline] - pub const fn area(&self) -> usize { + pub const fn area(&self) -> u32 { self.size.area() } #[inline] - pub const fn linear_index(&self, x: usize, y: usize) -> usize { + pub const fn linear_index(&self, x: u32, y: u32) -> u32 { self.size.linear_index(x, y) } @@ -289,18 +289,18 @@ } #[inline] - pub fn contains_x>(&self, x: T) -> bool { + pub fn contains_x>(&self, x: T) -> bool { (self.size.width & x.into()) == 0 } #[inline] - pub fn contains_y>(&self, y: T) -> bool { + pub fn contains_y>(&self, y: T) -> bool { (self.size.height & y.into()) == 0 } #[inline] pub fn contains(&self, point: Point) -> bool { - self.contains_x(point.x as usize) && self.contains_y(point.y as usize) + self.contains_x(point.x as u32) && self.contains_y(point.y as u32) } #[inline] @@ -439,7 +439,7 @@ ) } - pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self { + pub fn from_size_coords(x: i32, y: i32, width: u32, height: u32) -> Self { Self::from_size(Point::new(x, y), Size::new(width, height)) } @@ -448,13 +448,13 @@ } #[inline] - pub const fn width(&self) -> usize { - (self.right() - self.left() + 1) as usize + pub const fn width(&self) -> u32 { + (self.right() - self.left() + 1) as u32 } #[inline] - pub const fn height(&self) -> usize { - (self.bottom() - self.top() + 1) as usize + pub const fn height(&self) -> u32 { + (self.bottom() - self.top() + 1) as u32 } #[inline] @@ -463,7 +463,7 @@ } #[inline] - pub const fn area(&self) -> usize { + pub const fn area(&self) -> u32 { self.size().area() } @@ -504,7 +504,10 @@ #[inline] pub fn with_margin(&self, margin: i32) -> Self { - let offset = Point::new(min(margin, self.width() as i32 / 2), min(margin, self.height() as i32 / 2)); + let offset = Point::new( + min(margin, self.width() as i32 / 2), + min(margin, self.height() as i32 / 2), + ); Self::new(self.top_left() + offset, self.bottom_right() - offset) } @@ -566,7 +569,7 @@ } #[inline] - pub fn quotient(self, x: usize, y: usize) -> Point { + pub fn quotient(self, x: u32, y: u32) -> Point { self.top_left() + Point::new((x % self.width()) as i32, (y % self.height()) as i32) } } diff -r a4cbc6926439 -r 5d302b12d837 rust/land2d/src/lib.rs --- a/rust/land2d/src/lib.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/land2d/src/lib.rs Tue Jan 28 15:49:45 2025 +0100 @@ -48,12 +48,12 @@ } #[inline] - pub fn play_width(&self) -> usize { + pub fn play_width(&self) -> u32 { self.play_box.width() } #[inline] - pub fn play_height(&self) -> usize { + pub fn play_height(&self) -> u32 { self.play_box.height() } @@ -69,12 +69,12 @@ #[inline] pub fn is_valid_x(&self, x: i32) -> bool { - self.mask.contains_x(x as usize) + self.mask.contains_x(x as u32) } #[inline] pub fn is_valid_y(&self, y: i32) -> bool { - self.mask.contains_y(y as usize) + self.mask.contains_y(y as u32) } #[inline] @@ -150,7 +150,7 @@ dir: isize, ) { let yd = y as isize + dir; - if mask.contains_y(yd as usize) { + if mask.contains_y(yd as u32) { stack.push((xl, xr, yd as usize, dir)); } } @@ -331,7 +331,7 @@ #[test] fn basics() { - let l: Land2D = Land2D::new(Size::new(30, 50), 0); + let l: Land2D = Land2D::new(&Size::new(30, 50), 0); assert_eq!(l.play_width(), 30); assert_eq!(l.play_height(), 50); @@ -348,7 +348,7 @@ #[test] fn fill() { - let mut l: Land2D = Land2D::new(Size::square(128), 0); + let mut l: Land2D = Land2D::new(&Size::square(128), 0); l.draw_line(Line::new(Point::new(0, 0), Point::new(32, 96)), 1); l.draw_line(Line::new(Point::new(32, 96), Point::new(64, 32)), 1); diff -r a4cbc6926439 -r 5d302b12d837 rust/landgen/Cargo.toml --- a/rust/landgen/Cargo.toml Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/landgen/Cargo.toml Tue Jan 28 15:49:45 2025 +0100 @@ -9,7 +9,7 @@ land2d = { path = "../land2d" } vec2d = { path = "../vec2d" } png = "0.17" -rand = "0.8" +rand = "0.9" [dev-dependencies] criterion = "0.5" diff -r a4cbc6926439 -r 5d302b12d837 rust/landgen/src/maze.rs --- a/rust/landgen/src/maze.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/landgen/src/maze.rs Tue Jan 28 15:49:45 2025 +0100 @@ -3,12 +3,13 @@ use integral_geometry::{Point, Polygon, Rect, Size}; use land2d::Land2D; use rand::Rng; +use vec2d::Vec2D; #[derive(Clone)] pub struct MazeTemplate { - pub width: usize, - pub height: usize, - pub cell_size: usize, + pub width: u32, + pub height: u32, + pub cell_size: u32, pub inverted: bool, pub distortion_limiting_factor: u32, pub braidness: u32, @@ -21,10 +22,10 @@ num_cells: Size, num_edges: Size, seen_cells: Size, - cell_size: usize, - seen_list: Vec>>, - walls: Vec>>, - edge_list: Vec>>, + cell_size: u32, + seen_list: Vec2D>, + walls: Vec>, + edge_list: Vec>, last_cell: Vec, came_from: Vec>, came_from_pos: Vec, @@ -80,7 +81,7 @@ impl Maze { pub fn new( size: &Size, - cell_size: usize, + cell_size: u32, num_steps: usize, inverted: bool, braidness: u32, @@ -96,17 +97,17 @@ let mut last_cell = vec![Point::diag(0); num_steps]; let came_from_pos = vec![0; num_steps]; - let came_from = vec![vec![Point::diag(0); num_steps]; num_cells.area()]; + let came_from = vec![vec![Point::diag(0); num_steps]; num_cells.area() as usize]; - let seen_list = vec![vec![None as Option; seen_cells.width]; seen_cells.height]; - let walls = vec![vec![vec![true; seen_cells.width]; seen_cells.height]; 2]; - let edge_list = vec![vec![vec![false; num_cells.width]; num_cells.height]; 2]; + let seen_list = Vec2D::new(&seen_cells, None); + let walls = vec![Vec2D::new(&seen_cells, true); 2]; + let edge_list = vec![Vec2D::new(&num_cells, false); 2]; for current_step in 0..num_steps { - let x = random_numbers.gen_range(0..seen_cells.width - 1) / num_steps; + let x = random_numbers.random_range(0..seen_cells.width as i32 - 1) / num_steps as i32; last_cell[current_step] = Point::new( - (x + current_step * seen_cells.width / num_steps) as i32, - random_numbers.gen_range(0..seen_cells.height) as i32, + x + current_step as i32 * seen_cells.width as i32 / num_steps as i32, + random_numbers.random_range(..seen_cells.height) as i32, ); } @@ -141,7 +142,7 @@ let p = self.last_cell[current_step]; self.seen_list[p.y as usize][p.x as usize] = Some(current_step); - let next_dir_clockwise = random_numbers.gen(); + let next_dir_clockwise = random_numbers.random(); for _ in 0..5 { let sp = p + dir.0; @@ -158,7 +159,7 @@ match when_seen { Some(a) if a == current_step => { // try another direction - if !self.inverted && random_numbers.gen_range(0..self.braidness) == 0 { + if !self.inverted && random_numbers.random_range(..self.braidness) == 0 { if dir.0.x == -1 && p.x > 0 { self.walls[dir.orientation()][p.y as usize][p.x as usize - 1] = false; @@ -261,46 +262,46 @@ pub fn to_islands(mut self) -> (Vec, Vec) { let mut islands: Vec = vec![]; let mut polygon: Vec = vec![]; - let mut maze = vec![vec![false; self.num_cells.width]; self.num_cells.height]; + let mut maze = Vec2D::new(&self.num_cells, false); - for x in 0..self.seen_cells.width { - for y in 0..self.seen_cells.height { + for x in 0..self.seen_cells.width as usize { + for y in 0..self.seen_cells.height as usize { if self.seen_list[y][x].is_some() { maze[y * 2 + 1][x * 2 + 1] = true; } } - for y in 0..self.seen_cells.height - 1 { + for y in 0..self.seen_cells.height as usize - 1 { if !self.walls[0][y][x] { maze[y * 2 + 2][x * 2 + 1] = true; } } } - for x in 0..self.seen_cells.width - 1 { - for y in 0..self.seen_cells.height { + for x in 0..self.seen_cells.width as usize - 1 { + for y in 0..self.seen_cells.height as usize { if !self.walls[1][y][x] { maze[y * 2 + 1][x * 2 + 2] = true; } } } - for x in 0..self.num_edges.width { - for y in 0..self.num_cells.height { + for x in 0..self.num_edges.width as usize { + for y in 0..self.num_cells.height as usize { self.edge_list[0][y][x] = maze[y][x] != maze[y][x + 1]; } } - for x in 0..self.num_cells.width { - for y in 0..self.num_edges.height { + for x in 0..self.num_cells.width as usize { + for y in 0..self.num_edges.height as usize { self.edge_list[1][y][x] = maze[y][x] != maze[y + 1][x]; } } let mut fill_points = vec![]; - for x in 0..self.num_edges.width { - for y in 0..self.num_cells.height { + for x in 0..self.num_edges.width as usize { + for y in 0..self.num_cells.height as usize { if self.edge_list[0][y][x] { self.edge_list[0][y][x] = false; self.add_vertex(Point::new(x as i32 + 1, y as i32 + 1), &mut polygon); @@ -328,13 +329,13 @@ } } - for x in 0..self.num_cells.width { - for y in 0..self.num_cells.height { + for x in 0..self.num_cells.width as usize { + for y in 0..self.num_cells.height as usize { 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, + (x as u32 * self.cell_size + half_cell) as i32 + self.off.x, + (y as u32 * self.cell_size + half_cell) as i32 + self.off.y, ); islands.push(Polygon::new(&[fill_point])); fill_points.push(fill_point); @@ -348,13 +349,13 @@ if x > 0 { points.push((x - 1, y)); } - if x < self.num_cells.width - 1 { + if x < self.num_cells.width as usize - 1 { points.push((x + 1, y)); } if y > 0 { points.push((x, y - 1)); } - if y < self.num_cells.height - 1 { + if y < self.num_cells.height as usize - 1 { points.push((x, y + 1)); } } @@ -371,7 +372,7 @@ maze_template: MazeTemplate, } -fn prev_odd(num: usize) -> usize { +fn prev_odd(num: u32) -> u32 { if num & 1 == 0 { num - 1 } else { @@ -409,7 +410,7 @@ for current_step in 0..num_steps { if !step_done[current_step] { - let dir = Direction::new(random_numbers.gen()); + let dir = Direction::new(random_numbers.random_range(..4)); step_done[current_step] = maze.see_cell(current_step, dir, random_numbers); done = false; } diff -r a4cbc6926439 -r 5d302b12d837 rust/landgen/src/outline_template_based/outline.rs --- a/rust/landgen/src/outline_template_based/outline.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/landgen/src/outline_template_based/outline.rs Tue Jan 28 15:49:45 2025 +0100 @@ -27,7 +27,7 @@ .map(|i| { i.iter() .map(|rect| { - let (rnd_a, rnd_b) = random_numbers.gen(); + let (rnd_a, rnd_b) = random_numbers.random(); play_box.top_left() + rect.quotient(rnd_a, rnd_b) }) .collect::>() @@ -241,8 +241,9 @@ Some(mid_point) } else { // select distance within [-dist_right; dist_left], keeping min_distance in mind - let d = random_numbers - .gen_range(-(dist_right as i32) + min_distance..=dist_left as i32 - min_distance); + let d = random_numbers.random_range( + -(dist_right as i32) + min_distance..=dist_left as i32 - min_distance, + ); Some(mid_point + normal * d / normal_len as i32) } diff -r a4cbc6926439 -r 5d302b12d837 rust/landgen/src/outline_template_based/template_based.rs --- a/rust/landgen/src/outline_template_based/template_based.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/landgen/src/outline_template_based/template_based.rs Tue Jan 28 15:49:45 2025 +0100 @@ -20,7 +20,7 @@ random_numbers: &mut impl Rng, ) -> Land2D { let do_invert = self.outline_template.is_negative - && (!self.outline_template.can_invert || random_numbers.gen()); + && (!self.outline_template.can_invert || random_numbers.random()); let (basic, zero) = if do_invert { (parameters.zero, parameters.basic) } else { @@ -37,17 +37,17 @@ ); // mirror - if self.outline_template.can_mirror && random_numbers.gen() { + if self.outline_template.can_mirror && random_numbers.random() { points.mirror(); } // flip - if self.outline_template.can_flip && random_numbers.gen() { + if self.outline_template.can_flip && random_numbers.random() { points.flip(); } if !parameters.skip_distort { - let distortion_limiting_factor = 100 + random_numbers.gen_range(0..8) * 10; + let distortion_limiting_factor = 100 + random_numbers.random_range(0..8) * 10; points.distort( parameters.distance_divisor, diff -r a4cbc6926439 -r 5d302b12d837 rust/landgen/src/wavefront_collapse/generator.rs --- a/rust/landgen/src/wavefront_collapse/generator.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/landgen/src/wavefront_collapse/generator.rs Tue Jan 28 15:49:45 2025 +0100 @@ -91,10 +91,8 @@ let mut reader = decoder.read_info()?; let info = reader.info(); - let mut tiles_image = vec2d::Vec2D::new( - &Size::new(info.width as usize, info.height as usize), - parameters.zero, - ); + let mut tiles_image = + vec2d::Vec2D::new(&Size::new(info.width, info.height), parameters.zero); let mut buf = vec![0; reader.output_buffer_size()]; let info = reader.next_frame(&mut buf)?; @@ -325,19 +323,20 @@ // 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; + let offset_y = result.height() - result.play_height() as usize; + let offset_x = (result.width() - result.play_width() as usize) / 2; - for row in 0..wfc_size.height { - for column in 0..wfc_size.width { + for row in 0..wfc_size.height as usize { + for column in 0..wfc_size.width as usize { if let Some(Tile::Numbered(tile_index)) = wfc.grid().get(row, column) { let tile = &tiles[*tile_index]; - for tile_row in 0..tile.size().height { - for tile_column in 0..tile.size().width { + for tile_row in 0..tile.size().height as usize { + for tile_column in 0..tile.size().width as usize { result.map( - (row * tile.size().height + tile_row + offset_y) as i32, - (column * tile.size().width + tile_column + offset_x) as i32, + (row * tile.size().height as usize + tile_row + offset_y) as i32, + (column * tile.size().width as usize + tile_column + offset_x) + as i32, |p| { *p = *tile.get(tile_row, tile_column).unwrap_or(¶meters.zero) diff -r a4cbc6926439 -r 5d302b12d837 rust/landgen/src/wavefront_collapse/wavefront_collapse.rs --- a/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Tue Jan 28 15:49:45 2025 +0100 @@ -1,6 +1,6 @@ use integral_geometry::Size; -use rand::distributions::Distribution; -use rand::distributions::WeightedIndex; +use rand::distr::{weighted::WeightedIndex, Distribution}; +use rand::prelude::IndexedRandom; use rand::Rng; use std::collections::HashSet; use vec2d::Vec2D; @@ -59,7 +59,19 @@ seed_fn(&mut self.grid); - while self.collapse_step(random_numbers) {} + let mut backtracks = 0usize; + while let Some(b) = self.collapse_step(random_numbers) { + backtracks += b; + + if backtracks >= 1000 { + println!("[WFC] Too much backtracking, stopping generation!"); + break; + } + } + + if backtracks > 0 { + println!("[WFC] Had to backtrack {} times...", backtracks); + } } pub fn set_rules(&mut self, rules: Vec) { @@ -109,7 +121,7 @@ }) } - fn collapse_step(&mut self, random_numbers: &mut impl Rng) -> bool { + fn collapse_step(&mut self, random_numbers: &mut impl Rng) -> Option { let mut tiles_to_collapse = (usize::MAX, Vec::new()); // Iterate through the tiles in the land @@ -118,11 +130,16 @@ let current_tile = self.get_tile(y, x); if let Tile::Empty = current_tile { + let neighbors = [ + (y, x.wrapping_add(1)), + (y.wrapping_add(1), x), + (y, x.wrapping_sub(1)), + (y.wrapping_sub(1), x), + ]; + // calc entropy - 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); + let [right_tile, bottom_tile, left_tile, top_tile] = + neighbors.map(|(y, x)| self.get_tile(y, x)); let possibilities: Vec<(u32, Tile)> = self .rules @@ -146,7 +163,8 @@ let weights = possibilities.iter().map(|(weight, _)| *weight); let distribution = WeightedIndex::new(weights).unwrap(); - let entry = (y, x, possibilities[distribution.sample(random_numbers)]); + let entry = + (y, x, possibilities[distribution.sample(random_numbers)].1); if entropy < tiles_to_collapse.0 { tiles_to_collapse = (entropy, vec![entry]) @@ -155,12 +173,26 @@ } } } else { - /*println!("We're here: {}, {}", x, y); + /* + println!("We're here: {}, {}", x, y); println!( "Neighbour tiles are: {:?} {:?} {:?} {:?}", right_tile, bottom_tile, left_tile, top_tile ); - println!("Rules are: {:?}", self.rules);*/ + println!("Rules are: {:?}", self.rules); + */ + + let entries = neighbors + .iter() + .filter(|(y, x)| self.grid.get(*y, *x).is_some()) + .map(|(y, x)| (*y, *x, Tile::Empty)) + .collect::>(); + + if entropy < tiles_to_collapse.0 { + tiles_to_collapse = (entropy, entries); + } else { + tiles_to_collapse.1.extend(entries); + } //todo!("no collapse possible - what to do?") } @@ -168,23 +200,28 @@ } } - let tiles_to_collapse = tiles_to_collapse.1; - let possibilities_number = tiles_to_collapse.len(); + if tiles_to_collapse.0 == 0 { + // cannot collapse, we're clearing some tiles - if possibilities_number > 0 { - let weights = tiles_to_collapse.iter().map(|(_, _, (weight, _))| *weight); - let distribution = WeightedIndex::new(weights).unwrap(); - - let (y, x, (_, tile)) = tiles_to_collapse[distribution.sample(random_numbers)]; + for (y, x, tile) in tiles_to_collapse.1 { + *self + .grid + .get_mut(y, x) + .expect("correct iteration over grid") = tile; + } - *self - .grid - .get_mut(y, x) - .expect("correct iteration over grid") = tile; + Some(1) + } else { + if let Some(&(y, x, tile)) = tiles_to_collapse.1.as_slice().choose(random_numbers) { + *self + .grid + .get_mut(y, x) + .expect("correct iteration over grid") = tile; - true - } else { - false + Some(0) + } else { + None + } } } diff -r a4cbc6926439 -r 5d302b12d837 rust/lib-hwengine-future/src/lib.rs --- a/rust/lib-hwengine-future/src/lib.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/lib-hwengine-future/src/lib.rs Tue Jan 28 15:49:45 2025 +0100 @@ -39,8 +39,8 @@ #[no_mangle] pub extern "C" fn create_empty_game_field(width: u32, height: u32) -> *mut GameField { let game_field = Box::new(GameField { - collision: land2d::Land2D::new(&Size::new(width as usize, height as usize), 0), - pixels: land2d::Land2D::new(&Size::new(width as usize, height as usize), 0), + collision: land2d::Land2D::new(&Size::new(width, height), 0), + pixels: land2d::Land2D::new(&Size::new(width, height), 0), landgen_parameters: None, }); diff -r a4cbc6926439 -r 5d302b12d837 rust/mapgen/src/lib.rs --- a/rust/mapgen/src/lib.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/mapgen/src/lib.rs Tue Jan 28 15:49:45 2025 +0100 @@ -19,10 +19,10 @@ }, LandGenerationParameters, LandGenerator, }; -use rand::{seq::SliceRandom, Rng}; +use rand::Rng; +use rand::prelude::IndexedRandom; use std::{borrow::Borrow, collections::hash_map::HashMap}; -use rand::prelude::IndexedRandom; use vec2d::Vec2D; #[derive(PartialEq, Eq, Hash, Clone, Debug)] @@ -68,7 +68,7 @@ if let Some(land_sprite) = theme.land_texture() { for (row_index, (land_row, tex_row)) in land.rows().zip(texture.rows_mut()).enumerate() { - let sprite_row = land_sprite.get_row(row_index % land_sprite.height()); + let sprite_row = land_sprite.get_row(row_index % land_sprite.height() as usize); let mut x_offset = 0; while sprite_row.len() < land.width() - x_offset { let copy_range = x_offset..x_offset + sprite_row.len(); @@ -79,7 +79,7 @@ sprite_row, ); - x_offset += land_sprite.width() + x_offset += land_sprite.width() as usize } if x_offset < land.width() { @@ -107,8 +107,10 @@ &mut offsets, border_width, |x, y| { - border_sprite - .get_pixel(x % border_sprite.width(), border_sprite.height() - 1 - y) + border_sprite.get_pixel( + x % border_sprite.width() as usize, + border_sprite.height() as usize - 1 - y, + ) }, ); @@ -119,7 +121,7 @@ land.rows().zip(texture.rows_mut()), &mut offsets, border_width, - |x, y| border_sprite.get_pixel(x % border_sprite.width(), y), + |x, y| border_sprite.get_pixel(x % border_sprite.width() as usize, y), ); } @@ -169,7 +171,10 @@ .map(|(size, indices)| { ( TemplateType(size), - indices.iter().map(|i| templates[*i].to_template(&desc.tiles, &desc.edges)).collect(), + indices + .iter() + .map(|i| templates[*i].to_template(&desc.tiles, &desc.edges)) + .collect(), ) }) .collect(); diff -r a4cbc6926439 -r 5d302b12d837 rust/mapgen/src/template/maze.rs --- a/rust/mapgen/src/template/maze.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/mapgen/src/template/maze.rs Tue Jan 28 15:49:45 2025 +0100 @@ -4,10 +4,10 @@ use std::collections::hash_map::HashMap; #[derive(Deserialize)] pub struct TemplateDesc { - width: usize, - height: usize, + width: u32, + height: u32, max_hedgehogs: u8, - cell_size: usize, + cell_size: u32, distortion_limiting_factor: u32, braidness: u32, invert: bool, diff -r a4cbc6926439 -r 5d302b12d837 rust/mapgen/src/template/outline.rs --- a/rust/mapgen/src/template/outline.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/mapgen/src/template/outline.rs Tue Jan 28 15:49:45 2025 +0100 @@ -21,8 +21,8 @@ #[derive(Deserialize, Clone)] pub struct TemplateDesc { - width: usize, - height: usize, + width: u32, + height: u32, can_flip: bool, can_invert: bool, can_mirror: bool, @@ -55,10 +55,7 @@ .map(|v| { v.iter() .map(|r| { - Rect::from_size( - Point::new(r.x as i32, r.y as i32), - Size::new(r.w as usize, r.h as usize), - ) + Rect::from_size(Point::new(r.x as i32, r.y as i32), Size::new(r.w, r.h)) }) .collect() }) @@ -70,10 +67,7 @@ .map(|v| { v.iter() .map(|r| { - Rect::from_size( - Point::new(r.x as i32, r.y as i32), - Size::new(r.w as usize, r.h as usize), - ) + Rect::from_size(Point::new(r.x as i32, r.y as i32), Size::new(r.w, r.h)) }) .collect() }) diff -r a4cbc6926439 -r 5d302b12d837 rust/mapgen/src/template/wavefront_collapse.rs --- a/rust/mapgen/src/template/wavefront_collapse.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/mapgen/src/template/wavefront_collapse.rs Tue Jan 28 15:49:45 2025 +0100 @@ -33,8 +33,8 @@ #[derive(Debug, Deserialize)] pub struct TemplateDesc { - pub width: usize, - pub height: usize, + pub width: u32, + pub height: u32, pub can_invert: Option, pub is_negative: Option, pub put_girders: Option, @@ -53,7 +53,11 @@ } impl TemplateDesc { - pub fn to_template(&self, tiles: &HashMap>, edges: &HashMap) -> TemplateDescription { + pub fn to_template( + &self, + tiles: &HashMap>, + edges: &HashMap, + ) -> TemplateDescription { let [top, right, bottom, left]: [Option; 4] = if let Some(edges_name) = &self.edges { let edges = edges.get(edges_name).expect("missing template edges"); @@ -63,7 +67,11 @@ [None, None, None, None] }; - let tiles = self.tiles.iter().flat_map(|t| tiles.get(t).expect("missing template tiles")).collect::>(); + let tiles = self + .tiles + .iter() + .flat_map(|t| tiles.get(t).expect("missing template tiles")) + .collect::>(); TemplateDescription { size: Size::new(self.width, self.height), diff -r a4cbc6926439 -r 5d302b12d837 rust/mapgen/src/theme.rs --- a/rust/mapgen/src/theme.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/mapgen/src/theme.rs Tue Jan 28 15:49:45 2025 +0100 @@ -22,12 +22,12 @@ } #[inline] - pub fn width(&self) -> usize { + pub fn width(&self) -> u32 { self.size().width } #[inline] - pub fn height(&self) -> usize { + pub fn height(&self) -> u32 { self.size().height } @@ -61,7 +61,7 @@ let size = self.size(); assert!(size.is_power_of_two()); let tile_width_shift = size.width.trailing_zeros() as usize + 2; - let mut pixels = vec![0u32; size.area()]; + let mut pixels = vec![0u32; size.area() as usize]; for (y, row) in self.pixels.rows().enumerate() { for (x, v) in row.iter().enumerate() { @@ -95,12 +95,12 @@ } #[inline] - pub fn width(&self) -> usize { + pub fn width(&self) -> u32 { self.size().width } #[inline] - pub fn height(&self) -> usize { + pub fn height(&self) -> u32 { self.size().height } @@ -237,7 +237,7 @@ info.color_type ))); } - let size = Size::new(info.width as usize, info.height as usize); + let size = Size::new(info.width, info.height); let mut pixels: Vec2D = Vec2D::new(&size, 0); reader.next_frame(slice_u32_to_u8_mut(pixels.as_mut_slice()))?; diff -r a4cbc6926439 -r 5d302b12d837 rust/vec2d/src/lib.rs --- a/rust/vec2d/src/lib.rs Tue Jan 28 10:37:46 2025 +0100 +++ b/rust/vec2d/src/lib.rs Tue Jan 28 15:49:45 2025 +0100 @@ -4,7 +4,7 @@ slice::SliceIndex, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Vec2D { data: Vec, size: Size, @@ -30,19 +30,19 @@ let pos = row * self.width(); - &mut self.data[pos..pos + self.size.width] + &mut self.data[pos..pos + self.size.width as usize] } } impl Vec2D { #[inline] pub fn width(&self) -> usize { - self.size.width + self.size.width as usize } #[inline] pub fn height(&self) -> usize { - self.size.height + self.size.height as usize } #[inline] @@ -55,7 +55,7 @@ pub fn new(size: &Size, value: T) -> Self { Self { size: *size, - data: vec![value; size.area()], + data: vec![value; size.area() as usize], } } @@ -85,7 +85,10 @@ column: usize, ) -> Option<&mut >::Output> { if row < self.height() && column < self.width() { - Some(unsafe { self.data.get_unchecked_mut(row * self.size.width + column) }) + Some(unsafe { + self.data + .get_unchecked_mut(row * self.size.width as usize + column) + }) } else { None } @@ -106,7 +109,8 @@ row: usize, column: usize, ) -> &mut >::Output { - self.data.get_unchecked_mut(row * self.size.width + column) + self.data + .get_unchecked_mut(row * self.size.width as usize + column) } #[inline] @@ -146,7 +150,7 @@ impl Vec2D { pub fn from_iter>(iter: I, size: &Size) -> Option> { let data: Vec = iter.into_iter().collect(); - if size.width * size.height == data.len() { + if size.width as usize * size.height as usize == data.len() { Some(Vec2D { data, size: *size }) } else { None @@ -160,7 +164,7 @@ #[test] fn basics() { - let mut v: Vec2D = Vec2D::new(Size::new(2, 3), 0xff); + let mut v: Vec2D = Vec2D::new(&Size::new(2, 3), 0xff); assert_eq!(v.width(), 2); assert_eq!(v.height(), 3); @@ -173,7 +177,7 @@ assert_eq!(v[2][0], 0xff); assert_eq!(v[2][1], 0); - v.get_mut(2, 1).map(|v| *v = 1); + v.get_mut(2, 1).into_iter().for_each(|v| *v = 1); assert_eq!(v[2][1], 1); assert_eq!(v.get_mut(2, 2), None);