Skip to content

Rewritten astar.rs#58

Merged
CLOEI merged 2 commits into
CLOEI:mainfrom
badewen:refactor/pathfinder
Apr 21, 2026
Merged

Rewritten astar.rs#58
CLOEI merged 2 commits into
CLOEI:mainfrom
badewen:refactor/pathfinder

Conversation

@badewen

@badewen badewen commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Now it should be generic enough to be reused in other project :)

Summary by CodeRabbit

  • Refactor
    • Redesigned pathfinding system with a stateless architecture replacing the previous stateful implementation.
    • Simplified bot movement to use 4-directional pathfinding with uniform per-step costs.
    • Updated path computation to return empty results when no valid path exists instead of always returning a result.
    • Changed bot coordinate handling from signed to unsigned integers for improved safety.

@coderabbitai

coderabbitai Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The codebase refactors A\* pathfinding from a stateful struct with grid caching to a stateless function accepting a passability callback. Bot core integrates the new API, changes walk/path signatures from i32 to u32, and restructures auto-collect targeting by tile grouping.

Changes

Cohort / File(s) Summary
A\ Algorithm Refactoring*
src/astar.rs
Removed AStar struct with grid state and caching. Introduced stateless find_path function taking origin, target, and is_passable_cb callback. Simplified movement from 8-directional with diagonal corner-cutting to uniform 4-directional moves. Replaced Node with parent-tracked PathNode and changed heap ordering to use OpenEntry { f, h, pos }. Path reconstruction now backtracks via parent pointers instead of came_from map.
Bot Integration & Type Migration
src/bot/core.rs
Removed astar field; integrated new stateless find_path API via callback pattern. Changed walk and compute_path signatures: coordinates now u32 (was i32), compute_path returns Option<Vec<...>> (was Vec). Added is_tile_passable callback incorporating TileType, TileFlags, and WorldTilePermission checks. Restructured auto-collect targeting from sorted Vec to HashMap grouped by tile coordinates, with reachability determined via compute_path calls.

Sequence Diagram

sequenceDiagram
    participant Bot as Bot Core
    participant AStar as A* Pathfinding
    participant Callback as Tile Passability<br/>Callback
    participant World as World/Tile System

    Bot->>Bot: compute_path(goal_x, goal_y)
    Bot->>AStar: find_path(ox, oy, tx, ty, is_passable_cb)
    
    AStar->>AStar: Initialize open list with start
    loop While open list not empty
        AStar->>AStar: Pop lowest f-cost node
        alt At goal
            AStar->>AStar: Reconstruct path via parent pointers
            AStar->>Bot: Return Some(path)
        else Expand neighbors (4-directional)
            AStar->>Callback: is_passable_cb(nx, ny, direction)
            Callback->>World: Check tile type & flags
            Callback->>World: Check world permissions
            Callback->>AStar: Return bool
            alt Passable & unvisited
                AStar->>AStar: Add to open list (f, h, pos)
            end
        end
    end
    
    alt Open list exhausted
        AStar->>Bot: Return None
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A star once lived in cached state,
With grids and bounds—oh what a weight!
Now stateless calls with callbacks bright,
Four directions feel so right,
Manhattan hops through cleaner flight! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Rewritten astar.rs' is vague and does not clearly convey the main purpose of the changes. While it references the modified file, it lacks specificity about the actual improvement—making the A* pathfinder more generic and reusable. Consider a more descriptive title such as 'Make A* pathfinder generic and reusable' or 'Refactor A* to support stateless, generic pathfinding' to better communicate the intent and benefit of the rewrite.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/bot/core.rs (2)

2916-2955: Minor: Typo in comment.

Line 2945: "Onw way" should be "One way".

📝 Fix typo
-                    5 => { // Onw way
+                    5 => { // One way
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bot/core.rs` around lines 2916 - 2955, In is_tile_passable (function) fix
the comment typo "Onw way" to "One way" near the collision_type 5 branch; locate
the match arm for item_info.collision_type == 5 inside is_tile_passable in
src/bot/core.rs and update the inline comment to read "One way" so the code
comment is correct and clear.

2305-2320: Minor: Redundant type casts.

node is already (u32, u32) from compute_path, so casting node.0 as u32 and node.1 as u32 is unnecessary.

🔧 Remove redundant casts
 for node in nodes {
-    let nx = node.0 as u32;
-    let ny = node.1 as u32;
+    let (nx, ny) = node;
     let cx = (self.pos_x / 32.0) as u32;
     let cy = (self.pos_y / 32.0) as u32;
     if nx == cx && ny == cy {
         continue;
     }

     // TODO: Optimize this.
     //  I think the impact is tolerable
     if self.compute_path(nx, ny).is_none() {
         self.pathfind_recalc = true;
         break;
     }

     self.walk(nx, ny);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bot/core.rs` around lines 2305 - 2320, The variables nx and ny are
redundantly cast to u32 even though node is already (u32, u32); update the block
to use the tuple values directly (e.g., let (nx, ny) = node;) or assign nx =
node.0 and ny = node.1 without "as u32", keep the existing comparisons against
cx/cy (which come from pos_x/pos_y) and the subsequent calls to
self.compute_path(nx, ny) and self.walk(nx, ny) unchanged so behavior stays the
same.
src/astar.rs (1)

1-3: Unnecessary vec import.

The vec! macro is available in the Rust prelude and doesn't need to be explicitly imported.

🔧 Remove redundant import
 use std::{
-    cmp::Ordering, collections::{BinaryHeap, HashMap}, vec
+    cmp::Ordering, collections::{BinaryHeap, HashMap},
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/astar.rs` around lines 1 - 3, The use statement in src/astar.rs
unnecessarily imports the vec symbol (vec macro) from the prelude; remove vec
from the grouped import so the line becomes: use std::{cmp::Ordering,
collections::{BinaryHeap, HashMap}} (or otherwise drop only the vec token), then
run cargo check to ensure no other changes are needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/bot/core.rs`:
- Around line 2607-2610: Movement offset x/y is being applied twice: it's added
when computing cx/cy from self.pos_x/pos_y and then added again when calling
self.walk; update the call to self.walk to pass cx and cy (converted to u32)
directly (e.g., self.walk(cx as u32, cy as u32)), keep the negative check on
cx/cy as-is, and remove the extra + x and + y in the walk invocation so the bot
moves the intended single offset.

---

Nitpick comments:
In `@src/astar.rs`:
- Around line 1-3: The use statement in src/astar.rs unnecessarily imports the
vec symbol (vec macro) from the prelude; remove vec from the grouped import so
the line becomes: use std::{cmp::Ordering, collections::{BinaryHeap, HashMap}}
(or otherwise drop only the vec token), then run cargo check to ensure no other
changes are needed.

In `@src/bot/core.rs`:
- Around line 2916-2955: In is_tile_passable (function) fix the comment typo
"Onw way" to "One way" near the collision_type 5 branch; locate the match arm
for item_info.collision_type == 5 inside is_tile_passable in src/bot/core.rs and
update the inline comment to read "One way" so the code comment is correct and
clear.
- Around line 2305-2320: The variables nx and ny are redundantly cast to u32
even though node is already (u32, u32); update the block to use the tuple values
directly (e.g., let (nx, ny) = node;) or assign nx = node.0 and ny = node.1
without "as u32", keep the existing comparisons against cx/cy (which come from
pos_x/pos_y) and the subsequent calls to self.compute_path(nx, ny) and
self.walk(nx, ny) unchanged so behavior stays the same.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 458e9b96-6c2f-4c2a-b6a2-1d83b17bd49f

📥 Commits

Reviewing files that changed from the base of the PR and between 8381974 and f554fdf.

📒 Files selected for processing (2)
  • src/astar.rs
  • src/bot/core.rs

Comment thread src/bot/core.rs
Comment on lines +2607 to +2610
let cx = ((self.pos_x / 32.0).round() as i32) + x;
let cy = ((self.pos_y / 32.0).round() as i32) + y;
if cx < 0 || cy < 0 { return; }
self.walk((cx + x) as u32, (cy + y) as u32);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Bug: Movement offset applied twice.

The offset x is added to compute cx, then added again in the walk() call. Same for y. This causes the bot to move twice the intended distance.

🐛 Proposed fix
 BotCommand::Move { x, y } => {
     let cx = ((self.pos_x / 32.0).round() as i32) + x;
     let cy = ((self.pos_y / 32.0).round() as i32) + y;
     if cx < 0 || cy < 0 { return; }
-    self.walk((cx + x) as u32, (cy + y) as u32);
+    self.walk(cx as u32, cy as u32);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let cx = ((self.pos_x / 32.0).round() as i32) + x;
let cy = ((self.pos_y / 32.0).round() as i32) + y;
if cx < 0 || cy < 0 { return; }
self.walk((cx + x) as u32, (cy + y) as u32);
let cx = ((self.pos_x / 32.0).round() as i32) + x;
let cy = ((self.pos_y / 32.0).round() as i32) + y;
if cx < 0 || cy < 0 { return; }
self.walk(cx as u32, cy as u32);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bot/core.rs` around lines 2607 - 2610, Movement offset x/y is being
applied twice: it's added when computing cx/cy from self.pos_x/pos_y and then
added again when calling self.walk; update the call to self.walk to pass cx and
cy (converted to u32) directly (e.g., self.walk(cx as u32, cy as u32)), keep the
negative check on cx/cy as-is, and remove the extra + x and + y in the walk
invocation so the bot moves the intended single offset.

@CLOEI

CLOEI commented Apr 21, 2026

Copy link
Copy Markdown
Owner

Nicely done! thank you for your hardwork!

@CLOEI CLOEI merged commit 77cf2b7 into CLOEI:main Apr 21, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants