fix(pathfinding): correct BinaryHeap ordering and movement threshold

- Fix PathNode and ChunkPathNode Ord impl to use correct min-heap ordering
  (self.f_score.cmp vs other.f_score.cmp) - was causing zig-zag paths
- Fix movement threshold formula to use tile_weight directly
  (walk_speed * tile_weight / 50) instead of inverted multiplier
- Update comments to reflect 'higher = slower to traverse' semantics
This commit is contained in:
2026-03-19 20:27:36 +00:00
parent c4890fa23e
commit a97e2908ed
+9 -12
View File
@@ -155,10 +155,9 @@ struct PathNode {
impl Ord for PathNode {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other
.f_score
.cmp(&self.f_score)
.then_with(|| other.g_score.cmp(&self.g_score))
self.f_score
.cmp(&other.f_score)
.then_with(|| self.g_score.cmp(&other.g_score))
}
}
@@ -508,8 +507,7 @@ pub fn movement(mut query: Query<(&mut Ambulatory, &mut Transform)>, tilemap: Re
if ambulatory.walk_speed > 0. {
let tile_weight = get_tile_weight(&tilemap, current_pos.as_ivec3());
let speed_multiplier = (tile_weight as f32) / 50.0;
let threshold = (ambulatory.walk_speed * speed_multiplier) as u32;
let threshold = (ambulatory.walk_speed as i32 * tile_weight as i32 / 50) as u32;
if ambulatory.step_recovery <= threshold {
ambulatory.step_recovery += 1;
@@ -557,7 +555,7 @@ fn is_standable_tile(tilemap: &TileMap, pos: IVec3) -> bool {
tilemap.is_standable(pos)
}
/// Get the A* weight for a tile position. Lower is better (faster to traverse).
/// Get the A* weight for a tile position. Higher = slower to traverse.
/// Returns 100 (default) if tile not found.
#[inline]
fn get_tile_weight(tilemap: &TileMap, pos: IVec3) -> u8 {
@@ -566,7 +564,7 @@ fn get_tile_weight(tilemap: &TileMap, pos: IVec3) -> u8 {
/// Calculate movement cost including tile weight.
/// Base costs: cardinal=10, diagonal=14, vertical~50.
/// Tile weight adds: (weight - 50) / 5 to make heavier tiles more costly.
/// Tile weight adds: (weight - 50) / 5 to make higher-weight tiles more costly.
fn calculate_movement_cost(move_dir: IVec3, tile_weight: u8) -> i32 {
let base_cost = match (
move_dir.x.abs() / ITILE_SIZE,
@@ -851,10 +849,9 @@ impl PartialEq for ChunkPathNode {
impl Ord for ChunkPathNode {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other
.f_score
.cmp(&self.f_score)
.then_with(|| other.g_score.cmp(&self.g_score))
self.f_score
.cmp(&other.f_score)
.then_with(|| self.g_score.cmp(&other.g_score))
}
}