Skip to content

Add stepwise A* search for visualizing pathfinding progress#25

Merged
migus88 merged 1 commit into
masterfrom
feature/stepwise-search-visualization
Jun 24, 2026
Merged

Add stepwise A* search for visualizing pathfinding progress#25
migus88 merged 1 commit into
masterfrom
feature/stepwise-search-visualization

Conversation

@migus88

@migus88 migus88 commented Jun 24, 2026

Copy link
Copy Markdown
Owner

What

Adds a stepwise (tick-by-tick) variant of the A* search for displaying how the pathfinder works — an educational/visualization facility that does not replace or change GetPath.

Pathfinder.BeginStepwiseSearch(agent, from, to) returns a disposable Pathfinder.StepwiseSearch. Each Tick() performs a single cell expansion and returns an immutable SearchStep snapshot containing:

  • the accumulated searched area — every discovered cell tagged Open (frontier) or Closed (expanded), each with its A* g/h/f scores,
  • Current (the cell expanded this tick), OpenCount/ClosedCount, and
  • the path once the destination is reached.

RunToCompletion() advances to the end in one call.

using var search = pathfinder.BeginStepwiseSearch(agent, from, to);
while (!search.IsComplete)
{
    var step = search.Tick();
    Render(step.Searched); // open vs closed cells, with scores
}

Why this design

The request asked for a Tick-style API that shows the flow without changing how the pathfinder works today and without duplicating code — and floated "a separate class that inherits from Pathfinder".

  • No subclassing. Pathfinder is sealed and its algorithm internals are private; inheriting would force unsealing it and exposing unsafe pointer internals as protected. Instead the driver is a public nested Pathfinder.StepwiseSearch, which reuses every private helper directly.
  • No duplicated logic. A single A* iteration is factored into a shared private ExpandNext, called by both the batch GetPath loop and the stepwise search — so they run identical expansion logic and find the same path. ExpandNext is AggressiveInlining, keeping GetPath's hot path unchanged (a pure, behavior-preserving refactor; the existing 100 tests still pass).
  • Correctness over speed, as requested for this path: the session pins the cell buffer (GCHandle) for the search lifetime so the open set's raw pointers stay valid across ticks — hence it is IDisposable and locks the instance to one active session (InvalidOperationException on a second). Snapshots own plain arrays (no pooling) so they survive across ticks.

The visualized Path is the raw A* path (no smoothing), following PathResult's origin-excluded convention.

New public types

Pathfinder.StepwiseSearch, SearchStep, SearchNode, SearchState, SearchNodeState.

Verification

  • dotnet build src/mpath-source/Migs.MPath.sln0 errors.
  • dotnet test …/Migs.MPath.Tests.csproj115 passed (100 existing + 15 new stepwise tests covering path equivalence with GetPath, monotonic accumulation, open/closed partitioning, failure on unreachable targets, origin==destination, idempotent/disposed ticks, the single-session guard, and argument validation).

Docs

  • New docs/api/ pages: StepwiseSearch, SearchStep, SearchNode, SearchState (+ index).
  • New guide docs/guides/visualizing-search.md (+ docs/README.md index).
  • docs/api/Pathfinder.md, README.md, and CLAUDE.md updated for the new public surface and architecture.

🤖 Generated with Claude Code

Adds Pathfinder.BeginStepwiseSearch, an educational/visualization API that
runs the same A* search as GetPath but one expansion at a time. Each Tick()
returns an immutable SearchStep snapshot with the accumulated searched area
(open frontier + closed/expanded cells, each with its A* g/h/f scores) and,
on success, the path.

The single A* iteration is factored into a shared ExpandNext helper so the
batch GetPath and the stepwise search run identical logic (no duplication),
and GetPath's hot path is unchanged (ExpandNext is AggressiveInlining). The
stepwise driver is a public nested Pathfinder.StepwiseSearch (IDisposable)
that reuses the private algorithm internals rather than subclassing —
Pathfinder is sealed and its internals are private. It pins the cell buffer
for the search lifetime, so it must be disposed and locks the instance to a
single active session.

New public types: Pathfinder.StepwiseSearch, SearchStep, SearchNode,
SearchState, SearchNodeState.

Verified: dotnet build (0 errors) and the full test suite (115 passed,
incl. 15 new stepwise tests). Docs added under docs/api and
docs/guides/visualizing-search.md; README and CLAUDE.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@migus88 migus88 merged commit c75c288 into master Jun 24, 2026
1 check passed
@migus88 migus88 deleted the feature/stepwise-search-visualization branch June 24, 2026 21:22
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.

1 participant