fix(issue-6): prevent A* diagonal corner-cutting through blocked cells (#19)
* fix(issue-6): prevent A* diagonal corner-cutting through blocked cells The A* neighbor loop previously checked only whether the destination cell was free. For diagonal moves this allows agents to clip through the corner of a blocked cell — the two orthogonal neighbours (e.g. N and E for a NE move) were never validated. Fix: after confirming the diagonal destination is free, additionally check both orthogonal intermediary cells. If either is blocked, the diagonal expansion is skipped and the agent must route around the obstacle. Adds three unit tests covering: - a path that would clip a single corner (rejected after fix) - a path through open space (diagonals still used freely) - a path around a multi-cell wall segment (no cells in the wall visited) * chore: remove unused imports from diagonal corner test (lint cleanup) * test(navigation): add expanded diagonal corner-cutting tests (issue #6) Additional tests for astar diagonal corner-cutting prevention: - All 4 diagonal directions (NE, NW, SE, SW): block orthogonal neighbour, verify path avoids the blocked cell in each direction - Both orthogonal sides blocked: verify no diagonal move is taken from start - L-shaped wall: verify agent navigates around entire L without clipping any segment - Dense grid stress test: maze-like layout verifying valid path found and no waypoint lands on a blocked cell --------- Co-authored-by: Neo (subagent) <neo@openclaw.local>
This commit is contained in:
committed by
GitHub
parent
533bcd9b3f
commit
941612ab2d
@@ -300,6 +300,15 @@ export function astar(
|
||||
}
|
||||
const nextIndex = nextRow * GRID_COLS + nextColumn;
|
||||
if (visited[nextIndex] || grid[nextIndex]) continue;
|
||||
|
||||
// For diagonal moves, require both orthogonal neighbours to be free so
|
||||
// agents cannot clip through the corner of a blocked cell (issue #6).
|
||||
// E.g. moving NE (dc=+1, dr=-1) requires N (dc=0, dr=-1) and E (dc=+1, dr=0) to be clear.
|
||||
if (columnOffset !== 0 && rowOffset !== 0) {
|
||||
const orthogonalA = (currentRow + rowOffset) * GRID_COLS + currentColumn;
|
||||
const orthogonalB = currentRow * GRID_COLS + (currentColumn + columnOffset);
|
||||
if (grid[orthogonalA] || grid[orthogonalB]) continue;
|
||||
}
|
||||
const nextCost = gCost[current] + cost;
|
||||
if (nextCost < gCost[nextIndex]) {
|
||||
gCost[nextIndex] = nextCost;
|
||||
|
||||
Reference in New Issue
Block a user