diff --git a/Cargo.lock b/Cargo.lock index 3822a55..c4f52a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2014,21 +2014,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.31" @@ -2036,7 +2021,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -2045,17 +2029,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.31" @@ -2086,12 +2059,6 @@ dependencies = [ "syn", ] -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - [[package]] name = "futures-task" version = "0.3.31" @@ -2110,13 +2077,9 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", @@ -2375,7 +2338,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "hexlab" -version = "0.5.2" +version = "0.5.3" dependencies = [ "bevy", "bevy_reflect", @@ -3570,21 +3533,21 @@ checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" [[package]] name = "rstest" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" dependencies = [ - "futures", "futures-timer", + "futures-util", "rstest_macros", "rustc_version", ] [[package]] name = "rstest_macros" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" dependencies = [ "cfg-if", "glob", diff --git a/Cargo.toml b/Cargo.toml index 6a4368e..0673bff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hexlab" authors = ["Kristofers Solo "] -version = "0.5.2" +version = "0.5.3" edition = "2021" description = "A hexagonal maze generation and manipulation library" repository = "https://github.com/kristoferssolo/hexlab" @@ -36,7 +36,7 @@ features = ["glam"] [dev-dependencies] claims = "0.8" -rstest = "0.23" +rstest = "0.24" [features] default = [] diff --git a/src/builder.rs b/src/builder.rs index c1a4deb..51bc41f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -211,18 +211,18 @@ mod test { #[case(100, 30301)] fn create_hex_maze_various_radii(#[case] radius: u16, #[case] expected_size: usize) { let maze = create_hex_maze(radius); - assert_eq!(maze.len(), expected_size); + assert_eq!(maze.count(), expected_size); } #[test] fn create_hex_maze_large_radius() { let large_radius = 1000; let maze = create_hex_maze(large_radius); - assert_gt!(maze.len(), 0); + assert_gt!(maze.count(), 0); // Calculate expected size for this radius let expected_size = 3 * (large_radius as usize).pow(2) + 3 * large_radius as usize + 1; - assert_eq!(maze.len(), expected_size); + assert_eq!(maze.count(), expected_size); } #[test] diff --git a/src/errors.rs b/src/errors.rs index 6b6d803..be24eb0 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,6 +1,8 @@ -use hexx::Hex; +use hexx::{EdgeDirection, Hex}; use thiserror::Error; +use crate::Tile; + #[derive(Debug, Error, PartialEq, Eq)] pub enum MazeBuilderError { /// Occurs when attempting to build a maze without specifying a radius. @@ -18,6 +20,22 @@ pub enum MazeBuilderError { #[derive(Debug, Error, PartialEq, Eq)] pub enum MazeError { + /// Error when attempting to access or modify a tile at a non-existent coordinate. #[error("Invalid coordinate: {0:?}")] InvalidCoordinate(Hex), + + /// Error when a tile's internal position doesn't match its insertion coordinate. + #[error("Tile position ({tile_pos:?}) does not match insertion coordinates ({insert_pos:?})")] + PositionMismatch { tile_pos: Hex, insert_pos: Hex }, + + /// Error when attempting to insert a tile at an already occupied position. + #[error("A tile {old_tile:?} already exists at position {pos:?}")] + TileAlreadyExists { pos: Hex, old_tile: Tile }, + + /// Error when a wall operation fails at the specified coordinate and direction. + #[error("Cannot add wall at {coord:?} in direction {direction:?}")] + WallOperationFailed { + coord: Hex, + direction: EdgeDirection, + }, } diff --git a/src/generator/backtrack.rs b/src/generator/backtrack.rs index 1f3c0d1..d56bf0e 100644 --- a/src/generator/backtrack.rs +++ b/src/generator/backtrack.rs @@ -106,6 +106,10 @@ mod test { } } } - assert_eq!(connected.len(), maze.len(), "All tiles should be connected"); + assert_eq!( + connected.len(), + maze.count(), + "All tiles should be connected" + ); } } diff --git a/src/maze.rs b/src/maze.rs index 6510f05..2695cf5 100644 --- a/src/maze.rs +++ b/src/maze.rs @@ -69,14 +69,7 @@ impl Maze { self.0.insert(coords, tile) } - /// Adds a new tile at the specified coordinates. - /// - /// If the map did not have this key present, [`None`] is returned. - /// - /// If the map did have this key present, the value is updated, and the old - /// value is returned. - /// - /// It is recommended to use [`insert`]. + /// Adds a new tile at the specified coordinates. It is recommended to use [`insert`]. /// /// [`insert`]: Maze::insert /// @@ -85,21 +78,50 @@ impl Maze { /// - `coords` - The hexagonal coordinates where the tile should be added. /// - `tile` - The tile to insert to. /// + /// # Errors + /// + /// Returns [`MazeError::PositionMismatch`] if the tile's position doesn't match the insertion coordinates. + /// Returns [`MazeError::TileAlreadyExists`] if a tile already exists at the specified coordinates. + /// /// # Examples /// /// ``` /// use hexlab::prelude::*; /// /// let mut maze = Maze::new(); - /// let coord = Hex::ZERO; - /// let tile1 = Tile::new(coord); - /// let tile2 = Tile::new(Hex::new(1, 1)); /// - /// assert_eq!(maze.insert_with_tile(coord, tile1.clone()), None); - /// assert_eq!(maze.insert_with_tile(coord, tile2), Some(tile1)); + /// assert_eq!( + /// maze.insert_with_tile(Hex::new(2, 2), Tile::new(Hex::ZERO)), + /// Err(MazeError::PositionMismatch { + /// tile_pos: Hex::ZERO, + /// insert_pos: Hex::new(2, 2) + /// }) + /// ); + /// let tile = Tile::new(Hex::ZERO); + /// assert_eq!(maze.insert_with_tile(Hex::ZERO, tile.clone()), Ok(tile.clone())); + /// assert_eq!( + /// maze.insert_with_tile(Hex::ZERO, tile.clone()), + /// Err(MazeError::TileAlreadyExists { + /// pos: Hex::ZERO, + /// old_tile: tile + /// }) + /// ); /// ``` - pub fn insert_with_tile(&mut self, coords: Hex, tile: Tile) -> Option { - self.0.insert(coords, tile) + pub fn insert_with_tile(&mut self, coords: Hex, tile: Tile) -> Result { + if tile.pos != coords { + return Err(MazeError::PositionMismatch { + tile_pos: tile.pos, + insert_pos: coords, + }); + } + self.0 + .insert(coords, tile.clone()) + .map_or(Ok(tile), |old_tile| { + Err(MazeError::TileAlreadyExists { + pos: coords, + old_tile, + }) + }) } /// Returns a reference to the tile at the specified coordinates. @@ -190,17 +212,17 @@ impl Maze { /// use hexlab::prelude::*; /// /// let mut maze = Maze::new(); - /// assert_eq!(maze.len(), 0); + /// assert_eq!(maze.count(), 0); /// /// maze.insert(Hex::new(0, 0)); - /// assert_eq!(maze.len(), 1); + /// assert_eq!(maze.count(), 1); /// /// maze.insert(Hex::new(1, -1)); - /// assert_eq!(maze.len(), 2); + /// assert_eq!(maze.count(), 2); /// ``` #[inline] #[must_use] - pub fn len(&self) -> usize { + pub fn count(&self) -> usize { self.0.len() } diff --git a/tests/builder.rs b/tests/builder.rs index d26aa3c..7f4ba70 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -10,7 +10,7 @@ use rstest::rstest; #[case(5, 91)] fn maze_size(#[case] radius: u16, #[case] expected_size: usize) { let maze = assert_ok!(MazeBuilder::new().with_radius(radius).build()); - assert_eq!(maze.len(), expected_size); + assert_eq!(maze.count(), expected_size); } #[test] @@ -126,5 +126,5 @@ fn generate_maze_with_different_types(#[case] generator: GeneratorType) { .with_generator(generator) .build()); - assert_gt!(maze.len(), 0); + assert_gt!(maze.count(), 0); } diff --git a/tests/generator.rs b/tests/generator.rs index 25f2190..f7954bf 100644 --- a/tests/generator.rs +++ b/tests/generator.rs @@ -19,11 +19,11 @@ fn generator_type( } } } - let initial_size = maze.len(); + let initial_size = maze.count(); generator.generate(&mut maze, start_pos, seed); - assert_eq!(maze.len(), initial_size, "Maze size should not change"); + assert_eq!(maze.count(), initial_size, "Maze size should not change"); // Check maze connectivity let start = start_pos.unwrap_or(Hex::ZERO); @@ -42,7 +42,7 @@ fn generator_type( } } } - assert_eq!(visited.len(), maze.len(), "All tiles should be connected"); + assert_eq!(visited.len(), maze.count(), "All tiles should be connected"); // Check that each tile has at least one open wall for &pos in maze.keys() { diff --git a/tests/maze.rs b/tests/maze.rs index cd1b06f..d6edd33 100644 --- a/tests/maze.rs +++ b/tests/maze.rs @@ -7,7 +7,7 @@ fn hex_maze_creation_and_basic_operations() { let center = Hex::ZERO; maze.insert(center); - assert_eq!(maze.len(), 1); + assert_eq!(maze.count(), 1); assert!(!maze.is_empty()); let tile = maze.get(¢er); @@ -47,7 +47,7 @@ fn hex_maze_multiple_tiles() { maze.insert(tile); } - assert_eq!(maze.len(), tiles.len()); + assert_eq!(maze.count(), tiles.len()); for &tile in &tiles { assert!(maze.get(&tile).is_some());