Proposal: spatial queries & pathfinding — Query.nearest/within, Grid.*, Path.a_star #24
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#24
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #2. ECS-native spatial helpers plus grid/path algorithms, deterministic fixed-point.
Proposed surface
Query.count([Prop]),Query.first([Prop]) -> entity,Query.nearest(from, [Prop]) -> entity,Query.within(center, radius, [Prop]) -> listGrid.line(a, b)(Bresenham — thert_lineprimitive from #2 already exists),Grid.flood_fill(x, y),Grid.line_of_sight(a, b)over the tilemapPath.a_star(cost_map, from, to) -> listWork required
Query.nearest/withinwant a runtime spatial index to be efficient;Grid.*/Path.*need Map access wiring and the A* implementation.Blocked on: a runtime spatial index (for Query) + Map/pathfinding plumbing.
Shipped the grid geometry + pathfinding half in
07e5a20— the part that isn't blocked. It's a newGrid.*namespace over theMaptilemap (runtime/native/grid.ludic, ~150 lines of Ludic, C-free, spliced via core.ludic):Grid.line(x0,y0,x1,y1) -> []Cell— Bresenham line cells (the primitive #24 notedrt_linealready had; this returns the cells rather than drawing them)Grid.blocked(x,y,wall) -> bool— the shared passability testGrid.line_of_sight(x0,y0,x1,y1,wall) -> bool— unobstructed straight line over the tilemapGrid.flood(x,y,wall) -> []Cell— 4-connected reachable region (BFS)Grid.a_star(x0,y0,x1,y1,wall) -> []Cell— shortest 4-connected path (A*, Manhattan heuristic), empty if unreachableA cell is passable unless it's out of bounds or holds the caller's
walltile (a char code, e.g.'#'), so any impassable glyph works — and it's all integer/deterministic. ReturnedCellslices are ordinary Ludic slices (len/[i], each cell has.x/.y). Pathfinding lives underGridrather than aPathnamespace, sincePathis already the filesystem-paths library (#10).Verified against Python references — a 1500-case fuzzer over random maps agrees exactly on A* path length (optimal, == BFS), flood-fill count, and line-of-sight.
examples/library/grid.ludicasserts it and is wired intox test(now 61 passed, 0 failed); a Grid docs section + 5 per-symbol pages; coverage/vocabulary/fence checks green; seed reseeded and the C-free bootstrap fixpoint holds.What's covered vs deferred
Grid.line(Bresenham),Grid.flood_fill,Grid.line_of_sightover the tilemapPath.a_star— asGrid.a_star(thePathname is taken)Query.count/first/nearest/within— the ECS spatial-query side, which #24 itself flagged as blocked on a runtime spatial indexClosing this as the grid/pathfinding deliverable; the blocked ECS-query half is tracked in #42.