diff --git a/src/builder.rs b/src/builder.rs index be3c77b..c20b4b6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -24,60 +24,59 @@ pub enum MazeBuilderError { GenerationError(String), } -/** -A builder pattern for creating hexagonal mazes. - -This struct provides a fluent interface for configuring and building hexagonal mazes. -It offers flexibility in specifying the maze size, random seed, and generation algorithm. - -# Examples - -Basic usage: -``` -use hexlab::prelude::*; - -let maze = MazeBuilder::new() - .with_radius(5) - .build() - .expect("Failed to create maze"); - -// A radius of 5 creates 61 hexagonal tiles -assert!(!maze.is_empty()); -assert_eq!(maze.len(), 91); -``` - -Using a seed for reproducible results: -``` -use hexlab::prelude::*; - -let maze1 = MazeBuilder::new() - .with_radius(3) - .with_seed(12345) - .build() - .expect("Failed to create maze"); - -let maze2 = MazeBuilder::new() - .with_radius(3) - .with_seed(12345) - .build() - .expect("Failed to create maze"); - -// Same seed should produce identical mazes -assert_eq!(maze1.len(), maze2.len()); -assert_eq!(maze1, maze2); -``` - -Specifying a custom generator: -``` -use hexlab::prelude::*; - -let maze = MazeBuilder::new() - .with_radius(7) - .with_generator(GeneratorType::RecursiveBacktracking) - .build() - .expect("Failed to create maze"); -``` -*/ +/// A builder pattern for creating hexagonal mazes. +/// +/// This struct provides a fluent interface for configuring and building hexagonal mazes. +/// It offers flexibility in specifying the maze size, random seed, generation algorithm, +/// and starting position. +/// +/// # Examples +/// +/// Basic usage: +/// ``` +/// use hexlab::prelude::*; +/// +/// let maze = MazeBuilder::new() +/// .with_radius(5) +/// .build() +/// .expect("Failed to create maze"); +/// +/// // A radius of 5 creates 61 hexagonal tiles +/// assert!(!maze.is_empty()); +/// assert_eq!(maze.len(), 91); +/// ``` +/// +/// Using a seed for reproducible results: +/// ``` +/// use hexlab::prelude::*; +/// +/// let maze1 = MazeBuilder::new() +/// .with_radius(3) +/// .with_seed(12345) +/// .build() +/// .expect("Failed to create maze"); +/// +/// let maze2 = MazeBuilder::new() +/// .with_radius(3) +/// .with_seed(12345) +/// .build() +/// .expect("Failed to create maze"); +/// +/// // Same seed should produce identical mazes +/// assert_eq!(maze1.len(), maze2.len()); +/// assert_eq!(maze1, maze2); +/// ``` +/// +/// Specifying a custom generator: +/// ``` +/// use hexlab::prelude::*; +/// +/// let maze = MazeBuilder::new() +/// .with_radius(7) +/// .with_generator(GeneratorType::RecursiveBacktracking) +/// .build() +/// .expect("Failed to create maze"); +/// ``` #[allow(clippy::module_name_repetitions)] #[derive(Default)] pub struct MazeBuilder { @@ -88,7 +87,7 @@ pub struct MazeBuilder { } impl MazeBuilder { - /// Creates a new [`MazeBuilder`] instance. + /// Creates a new [`MazeBuilder`] instance with default settings. #[inline] #[must_use] pub fn new() -> Self { @@ -97,9 +96,14 @@ impl MazeBuilder { /// Sets the radius for the hexagonal maze. /// + /// The radius determines the size of the maze, specifically the number of tiles + /// from the center (0,0) to the edge of the hexagon, not including the center tile. + /// For example, a radius of 3 would create a maze with 3 tiles from center to edge, + /// resulting in a total diameter of 7 tiles (3 + 1 + 3). + /// /// # Arguments /// - /// * `radius` - The size of the maze (number of tiles along one edge). + /// - `radius` - The number of tiles from the center to the edge of the hexagon. #[inline] #[must_use] pub const fn with_radius(mut self, radius: u32) -> Self { @@ -109,9 +113,11 @@ impl MazeBuilder { /// Sets the random seed for maze generation. /// + /// Using the same seed will produce identical mazes, allowing for reproducible results. + /// /// # Arguments /// - /// * `seed` - The random seed value. + /// - `seed` - The random seed value. #[inline] #[must_use] pub const fn with_seed(mut self, seed: u64) -> Self { @@ -125,14 +131,18 @@ impl MazeBuilder { /// /// # Arguments /// - /// * `generator_type` - The maze generation algorithm to use. + /// - `generator_type` - The maze generation algorithm to use. #[inline] #[must_use] pub const fn with_generator(mut self, generator_type: GeneratorType) -> Self { self.generator_type = generator_type; self } - + /// Sets the starting position for maze generation. + /// + /// # Arguments + /// + /// - `pos` - The hexagonal coordinates for the starting position. #[inline] #[must_use] pub const fn with_start_position(mut self, pos: Hex) -> Self { @@ -140,33 +150,31 @@ impl MazeBuilder { self } - /** - Builds the hexagonal maze based on the configured parameters. - - # Errors - - Returns [`MazeBuilderError::NoRadius`] if no radius is specified. - Returns [`MazeBuilderError::InvalidStartPosition`] if the start position is outside maze bounds. - - # Examples - - ``` - use hexlab::prelude::*; - - // Should fail without radius - let result = MazeBuilder::new().build(); - assert!(result.is_err()); - - // Should succeed with radius - let result = MazeBuilder::new() - .with_radius(3) - .build(); - assert!(result.is_ok()); - - let maze = result.unwrap(); - assert!(!maze.is_empty()); - ``` - */ + /// Builds the hexagonal maze based on the configured parameters. + /// + /// # Errors + /// + /// Returns [`MazeBuilderError::NoRadius`] if no radius is specified. + /// Returns [`MazeBuilderError::InvalidStartPosition`] if the start position is outside maze bounds. + /// + /// # Examples + /// + /// ``` + /// use hexlab::prelude::*; + /// + /// // Should fail without radius + /// let result = MazeBuilder::new().build(); + /// assert!(result.is_err()); + /// + /// // Should succeed with radius + /// let result = MazeBuilder::new() + /// .with_radius(3) + /// .build(); + /// assert!(result.is_ok()); + /// + /// let maze = result.unwrap(); + /// assert!(!maze.is_empty()); + /// ``` pub fn build(self) -> Result { let radius = self.radius.ok_or(MazeBuilderError::NoRadius)?; let mut maze = create_hex_maze(radius); diff --git a/src/hex_maze.rs b/src/hex_maze.rs index e3a7b28..8186e69 100644 --- a/src/hex_maze.rs +++ b/src/hex_maze.rs @@ -8,7 +8,10 @@ use hexx::{EdgeDirection, Hex}; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; -/// Represents a hexagonal maze with tiles and walls +/// Represents a hexagonal maze with tiles and walls. +/// +/// This struct stores the layout of a hexagonal maze, including the positions +/// of tiles and their associated walls. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "bevy", derive(Component))] @@ -25,44 +28,67 @@ impl HexMaze { } /// Adds a new tile at the specified coordinates + /// + /// # Arguments + /// + /// - `coords` - The hexagonal coordinates where the tile should be added. pub fn add_tile(&mut self, coords: Hex) { let tile = HexTile::new(coords); self.0.insert(coords, tile); } - /// Adds a wall in the specified direction at the given coordinates + /// Adds a wall in the specified direction at the given coordinates. + /// + /// # Arguments + /// + /// - `coord` - The hexagonal coordinates of the tile. + /// - `direction` - The direction in which to add the wall. pub fn add_wall(&mut self, coord: Hex, direction: EdgeDirection) { if let Some(tile) = self.0.get_mut(&coord) { tile.walls.add(direction); } } - /// Returns a reference to the tile at the specified coordinates + /// Returns a reference to the tile at the specified coordinates. + /// + /// # Arguments + /// + /// - `coord` - The hexagonal coordinates of the tile to retrieve. #[inline] #[must_use] pub fn get_tile(&self, coord: &Hex) -> Option<&HexTile> { self.0.get(coord) } - /// Returns a reference to the walls at the specified coordinates + /// Returns an optional reference to the walls at the specified coordinates. + /// + /// # Arguments + /// + /// - `coord` - The hexagonal coordinates of the tile whose walls to retrieve. pub fn get_walls(&self, coord: &Hex) -> Option<&Walls> { self.0.get(coord).map(HexTile::walls) } - /// Returns the number of tiles in the maze + /// Returns the number of tiles in the maze. #[inline] #[must_use] pub fn len(&self) -> usize { self.0.len() } - /// Returns true if the maze is empty + /// Returns `true` if the maze contains no tiles. #[inline] #[must_use] pub fn is_empty(&self) -> bool { self.0.is_empty() } + /// Removes a wall from a tile in the specified direction. + /// + /// # Arguments + /// + /// - `coord` - The hexagonal coordinates of the tile. + /// - `direction` - The direction of the wall to remove. pub fn remove_tile_wall(&mut self, coord: &Hex, direction: EdgeDirection) { if let Some(tile) = self.0.get_mut(coord) { tile.walls.remove(direction); diff --git a/src/hex_tile.rs b/src/hex_tile.rs index 93fd99d..8ccef70 100644 --- a/src/hex_tile.rs +++ b/src/hex_tile.rs @@ -7,6 +7,8 @@ use hexx::HexLayout; use std::fmt::Display; /// Represents a single hexagonal tile in the maze +/// +/// Each tile has a position and a set of walls defining its boundaries. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "bevy", derive(Component))] @@ -18,7 +20,11 @@ pub struct HexTile { } impl HexTile { - /// Creates a new tile with pos and default walls + /// Creates a new tile with the given position and default walls. + /// + /// # Arguments + /// + /// - `pos` - The hexagonal coordinates of the tile. #[must_use] pub fn new(pos: Hex) -> Self { Self { @@ -40,7 +46,11 @@ impl HexTile { pub const fn pos(&self) -> Hex { self.pos } - + /// Converts the tile's position to a 2D vector based on the given layout. + /// + /// # Arguments + /// + /// - `layout` - The hexagonal layout used for conversion. #[cfg(feature = "bevy_reflect")] #[inline] #[must_use] @@ -48,6 +58,11 @@ impl HexTile { layout.hex_to_world_pos(self.pos) } + /// Converts the tile's position to a 3D vector based on the given layout. + /// + /// # Arguments + /// + /// - `layout` - The hexagonal layout used for conversion. #[cfg(feature = "bevy_reflect")] #[inline] #[must_use] diff --git a/src/walls.rs b/src/walls.rs index e03fa63..102735b 100644 --- a/src/walls.rs +++ b/src/walls.rs @@ -2,48 +2,31 @@ use bevy::prelude::*; use hexx::EdgeDirection; -/** -A bit-flag representation of walls in a hexagonal tile. - -`Walls` uses an efficient bit-flag system to track the presence or absence of walls -along each edge of a hexagonal tile. Each of the six possible walls is represented -by a single bit in an 8-bit integer, allowing for fast operations and minimal memory usage. - -# Examples - -Creating and manipulating walls: -``` -use hexlab::prelude::*; - -// Create a hexagon with all walls -let walls = Walls::new(); -assert!(walls.is_closed()); - -// Create a hexagon with no walls -let mut walls = Walls::empty(); -assert!(walls.is_empty()); - -// Add specific walls -walls.add(EdgeDirection::FLAT_NORTH); -walls.add(EdgeDirection::FLAT_SOUTH); -assert_eq!(walls.count(), 2); -``` - -Using walls in game logic: - -``` -use hexlab::prelude::*; -let mut walls = Walls::empty(); - -// Add walls to create a corner -walls.add(EdgeDirection::FLAT_NORTH); -walls.add(EdgeDirection::FLAT_SOUTH_EAST); - -// Check if a specific direction has a wall -assert!(walls.contains(EdgeDirection::FLAT_NORTH)); -assert!(!walls.contains(EdgeDirection::FLAT_SOUTH)); -``` -*/ +/// A bit-flag representation of walls in a hexagonal tile. +/// +/// `Walls` uses an efficient bit-flag system to track the presence or absence of walls +/// along each edge of a hexagonal tile. Each of the six possible walls is represented +/// by a single bit in an 8-bit integer, allowing for fast operations and minimal memory usage. +/// +/// # Examples +/// +/// Creating and manipulating walls: +/// ``` +/// use hexlab::prelude::*; +/// +/// // Create a hexagon with all walls +/// let walls = Walls::new(); +/// assert!(walls.is_closed()); +/// +/// // Create a hexagon with no walls +/// let mut walls = Walls::empty(); +/// assert!(walls.is_empty()); +/// +/// // Add specific walls +/// walls.add(EdgeDirection::FLAT_NORTH); +/// walls.add(EdgeDirection::FLAT_SOUTH); +/// assert_eq!(walls.count(), 2); +/// ``` #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "bevy", derive(Component))] @@ -52,89 +35,34 @@ assert!(!walls.contains(EdgeDirection::FLAT_SOUTH)); pub struct Walls(u8); impl Walls { - /** - Creates a new set of walls with all edges closed. - - This is the default state where all six edges of the hexagon have walls. - - # Examples - - ``` - use hexlab::prelude::*; - - let walls = Walls::new(); - assert!(walls.is_closed()); - assert_eq!(walls.count(), 6); - ``` - */ + /// Creates a new set of walls with all edges closed. + /// + /// This is the default state where all six edges of the hexagon have walls. #[inline] #[must_use] pub fn new() -> Self { Self::default() } - /** - Creates a new set of walls with no edges (completely open). - - # Examples - - ``` - use hexlab::prelude::*; - - let walls = Walls::empty(); - assert!(walls.is_empty()); - assert_eq!(walls.count(), 0); - ``` - */ + /// Creates a new set of walls with no edges (completely open). #[inline] #[must_use] pub const fn empty() -> Self { Self(0) } - /** - Checks if the walls are currently empty - - Returns `true` if all directions have no walls set. - # Examples - - ``` - use hexlab::prelude::*; - - let walls = Walls::empty(); - assert!(walls.is_empty()); - - let walls = Walls::new(); - assert!(!walls.is_empty()); - ``` - */ + /// Checks if the walls are currently empty (no walls present). #[inline] #[must_use] pub const fn is_empty(&self) -> bool { self.0 == 0 } - /** - Adds a wall in the specified direction - - This method uses bitwise operations to efficiently set the wall flag - for the given direction. Multiple walls can be added to the same hexagon. - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::empty(); - walls.add(EdgeDirection::FLAT_NORTH); - assert!(walls.contains(EdgeDirection::FLAT_NORTH)); - assert!(!walls.contains(EdgeDirection::FLAT_SOUTH)); - - walls.add(EdgeDirection::FLAT_SOUTH); - assert!(walls.contains(EdgeDirection::FLAT_SOUTH)); - assert_eq!(walls.count(), 2); - ``` - */ + /// Adds a wall in the specified direction. + /// + /// # Arguments + /// + /// 0 `direction` - The direction in which to add the wall. #[inline] pub fn add(&mut self, direction: T) where @@ -143,25 +71,11 @@ impl Walls { self.0 |= direction.into().0; } - /** - Removes a wall in the specified direction - - Returns `true` if a wall was actually removed, `false` if there was no wall - in the specified direction. - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::new(); - assert!(walls.remove(EdgeDirection::FLAT_NORTH)); - assert!(!walls.contains(EdgeDirection::FLAT_NORTH)); - - // Removing a non-existent wall returns false - assert!(!walls.remove(EdgeDirection::FLAT_NORTH)); - ``` - */ + /// Removes a wall in the specified direction. + /// + /// # Arguments + /// + /// - `direction` - The direction from which to remove the wall. #[inline] pub fn remove(&mut self, direction: T) -> bool where @@ -174,23 +88,11 @@ impl Walls { was_removed } - /** - Returns true if there is a wall in the specified direction - - Uses efficient bitwise operations to check for the presence of a wall. - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::empty(); - - walls.add(EdgeDirection::FLAT_NORTH); - assert!(walls.contains(EdgeDirection::FLAT_NORTH)); - assert!(!walls.contains(EdgeDirection::FLAT_SOUTH)); - ``` - */ + /// Checks if there is a wall in the specified direction. + /// + /// # Arguments + /// + /// - `other` - The direction to check for a wall. #[inline] pub fn contains(&self, other: T) -> bool where @@ -199,98 +101,39 @@ impl Walls { self.0 & other.into().0 != 0 } - /** - Returns the raw bit representation of the walls - - This method provides access to the underlying bit flags for advanced usage. - The bits are ordered according to the `EdgeDirection` indices. - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::new(); - - assert_eq!(walls.as_bits(), 0b111111); - ``` - */ + /// Returns the raw bit representation of the walls #[inline] #[must_use] pub const fn as_bits(&self) -> u8 { self.0 } - /** - Returns the total number of walls present - - Efficiently counts the number of set bits in the internal representation. - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::empty(); - - assert_eq!(walls.count(), 0); - - walls.add(EdgeDirection::FLAT_NORTH); - walls.add(EdgeDirection::FLAT_SOUTH); - assert_eq!(walls.count(), 2); - ``` - */ + /// Returns the total number of walls present #[inline] #[must_use] pub fn count(&self) -> u8 { u8::try_from(self.0.count_ones()).unwrap_or_default() } - /** - Returns all possible directions as a `Walls` value - - This represents a hexagon with walls in all six directions. - - # Examples - - ``` - use hexlab::prelude::*; - - let all_walls = Walls::all_directions(); - - assert_eq!(all_walls.count(), 6); - assert!(all_walls.is_closed()); - ``` - */ + /// Returns a `Walls` value representing all possible directions. #[inline] #[must_use] pub const fn all_directions() -> Self { Self(0b11_1111) } - /** - Toggles a wall in the specified direction. - - If a wall exists in the given direction, it will be removed. - If no wall exists, one will be added. - Returns the previous state (`true` if a wall was present). - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::empty(); - - assert!(!walls.toggle(EdgeDirection::FLAT_NORTH)); // Returns false, wall was not present - assert!(walls.contains(EdgeDirection::FLAT_NORTH)); // Wall is now present - - let mut walls = Walls::new(); - - assert!(walls.toggle(EdgeDirection::FLAT_NORTH)); // Returns true, wall was present - assert!(!walls.contains(EdgeDirection::FLAT_NORTH)); // Wall is now removed - ``` - */ + /// Toggles a wall in the specified direction. + /// + /// If a wall exists in the given direction, it will be removed. + /// If no wall exists, one will be added. + /// + /// # Arguments + /// + /// - `direction` - The direction in which to toggle the wall. + /// + /// # Returns + /// + /// The previous state (`true` if a wall was present before toggling, `false` otherwise). pub fn toggle(&mut self, direction: T) -> bool where T: Into + Copy, @@ -304,54 +147,55 @@ impl Walls { is_present } - /** - Checks if walls are present in all six directions. - - Returns `true` if the hexagon has all possible walls, making it completely enclosed. - - # Examples - - ``` - use hexlab::prelude::*; - - let walls = Walls::new(); - assert!(walls.is_closed()); - - let mut walls = Walls::empty(); - assert!(!walls.is_closed()); - // Add all walls manually - for direction in EdgeDirection::iter() { - walls.add(direction); - } - assert!(walls.is_closed()); - ``` - */ + /// Checks if walls are present in all six directions. + /// + /// # Returns + /// + /// `true` if the hexagon has all possible walls, making it completely enclosed. + /// + /// # Deprecated + /// + /// This method is deprecated since version 0.3.1. Use `is_enclosed()` instead. #[inline] #[must_use] + #[deprecated(since = "0.3.1", note = "use `walls::Walls::is_enclosed()`")] pub fn is_closed(&self) -> bool { + self.is_enclosed() + } + + /// Checks if walls are present in all six directions. + /// + /// # Returns + /// + /// `true` if the hexagon has all possible walls, making it completely enclosed. + #[inline] + #[must_use] + pub fn is_enclosed(&self) -> bool { self.count() == 6 } - /** - Sets walls for multiple directions at once. - - This method efficiently adds multiple walls in a single operation while - preserving any existing walls not specified in the input. - - # Examples - - ``` - use hexlab::prelude::*; - - let mut walls = Walls::empty(); - walls.add(EdgeDirection::FLAT_NORTH); - - walls.fill([EdgeDirection::FLAT_SOUTH, EdgeDirection::FLAT_SOUTH_EAST]); - - assert!(walls.contains(EdgeDirection::FLAT_SOUTH)); - assert_eq!(walls.count(), 3); - ``` - */ + /// Sets walls for multiple directions at once. + /// + /// This method efficiently adds multiple walls in a single operation while + /// preserving any existing walls not specified in the input. + /// + /// # Arguments + /// + /// - `other` - The walls to add, specified as a `Walls` instance or any type + /// that can be converted into `Walls`. + /// + /// + /// # Examples + /// + /// ``` + /// use hexlab::prelude::*; + /// + /// let mut walls = Walls::empty(); + /// walls.fill([EdgeDirection::FLAT_NORTH ,EdgeDirection::FLAT_SOUTH, EdgeDirection::FLAT_SOUTH_EAST]); + /// + /// assert!(walls.contains(EdgeDirection::FLAT_SOUTH)); + /// assert_eq!(walls.count(), 3); + /// ``` #[inline] pub fn fill(&mut self, other: T) where