diff --git a/Cargo.lock b/Cargo.lock index 185f51d..110e324 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2350,7 +2350,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "hexlab" -version = "0.6.0" +version = "0.6.1" dependencies = [ "bevy", "bevy_reflect", diff --git a/Cargo.toml b/Cargo.toml index 603250a..16d20e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hexlab" authors = ["Kristofers Solo "] -version = "0.6.0" +version = "0.6.1" edition = "2021" description = "A hexagonal maze generation and manipulation library" repository = "https://github.com/kristoferssolo/hexlab" diff --git a/src/pathfinding.rs b/src/pathfinding.rs index 5c66c15..4ec7099 100644 --- a/src/pathfinding.rs +++ b/src/pathfinding.rs @@ -1,19 +1,70 @@ +//! Maze pathfinding implementation for hexagonal grids. +//! +//! This module provides functionality for finding paths through a hexagonal maze +//! using the A* pathfinding algorithm. The maze is represented as a collection of +//! hexagonal cells, where each cell may have walls on any of its six edges. +//! +//! # Examples +//! +//! ``` +//! use hexlab::prelude::*; +//! +//! let maze = MazeBuilder::new() +//! .with_radius(3) +//! .with_seed(12345) +//! .build() +//! .expect("Failed to create maze"); +//! assert!(maze.find_path(Hex::ZERO, Hex::new(-1, 3)).is_some()); +//! ``` +//! +//! # Implementation Details +//! +//! The pathfinding algorithm uses Manhattan distance as a heuristic and considers +//! walls between cells when determining valid paths. Each step between adjacent +//! cells has a cost of 1. use hexx::{EdgeDirection, Hex}; use pathfinding::prelude::*; use crate::Maze; impl Maze { + #[must_use] + /// Finds the shortest path between two hexagonal positions in the maze using A* pathfinding. + /// + /// This function calculates the optimal path while taking into account walls between cells. + /// The path cost between adjacent cells is always 1, and Manhattan distance is used as the + /// heuristic for pathfinding. + /// + /// # Arguments + /// + /// * `from` - The starting hexagonal position + /// * `to` - The target hexagonal position + /// + /// # Returns + /// + /// * `Some(Vec)` - A vector of hexagonal positions representing the path from start to target + /// * `None` - If no valid path exists between the positions + /// + /// # Examples + /// + /// ``` + /// use hexlab::prelude::*; + /// + /// let maze = MazeBuilder::new() + /// .with_radius(3) + /// .with_seed(12345) + /// .build() + /// .expect("Failed to create maze"); + /// assert!(maze.find_path(Hex::ZERO, Hex::new(-1, 3)).is_some()); + /// ``` pub fn find_path(&self, from: Hex, to: Hex) -> Option> { let successors = |pos: &Hex| { { EdgeDirection::ALL_DIRECTIONS.iter().filter_map(|&dir| { let neighbor = pos.neighbor(dir); if let Some(current_tile) = self.get(pos) { - if let Some(_) = self.get(&neighbor) { - if !current_tile.walls.contains(dir) { - return Some((neighbor, 1)); // Cost of 1 for each step - } + if self.get(&neighbor).is_some() && !current_tile.walls.contains(dir) { + return Some((neighbor, 1)); // Cost of 1 for each step } } None @@ -25,7 +76,7 @@ impl Maze { let heuristic = |pos: &Hex| { // Manhatan distance let diff = *pos - to; - (diff.x.abs() + diff.y.abs() + diff.z().abs()) as u32 / 2 + (diff.x.abs() + diff.y.abs() + diff.z().abs()) / 2 }; astar(&from, successors, heuristic, |pos| *pos == to).map(|(path, _)| path)