Use spatial hash by default when checking GridPoint for entities #253
Owner
```
❯ best, most correct, or performant way to check for another entity at (x, y) on a grid?
∴ Thinking…
The user is asking about the best way to check for an entity at a specific (x, y) position on a grid in McRogueFace. Let me look at the available APIs.
From my memory, I know that GridPoint has an entities property. Let me check the current API to give the most accurate answer.
● The most direct way is via the GridPoint API:
cell = grid.at(x, y)
entities_here = cell.entities # list of entities at this cell
This returns the entities whose grid_pos matches (x, y). Let me verify the current implementation to confirm performance characteristics.
● Search(pattern: "entities")
⎿ Found 42 lines (ctrl+o to expand)
● Search(pattern: "GridPoint.*entities\|get_entities\|entities_at")
⎿ Found 0 lines
● Read(src/UIGridPoint.cpp)
⎿ Read 50 lines
● Search(pattern: "spatial_hash")
⎿ Found 1 file (ctrl+o to expand)
● Search(pattern: "spatial_hash|SpatialHash")
⎿ Found 2 lines (ctrl+o to expand)
● Read(src/UIGrid.cpp)
⎿ Read 50 lines
● Search(pattern: "class SpatialHash")
⎿ Found 31 lines (ctrl+o to expand)
● Here's the summary of your three options, from best to worst:
1. grid.entities_in_radius() — Best for exact cell lookup (O(k))
entities = grid.entities_in_radius((x, y), 0.5)
This uses the spatial hash (bucket size 32), so it only checks entities in the relevant bucket — not the entire entity list. Complexity is O(k) where k is the number of
nearby entities. For an exact-cell check, a radius of 0.5 will match entities at integer position (x, y) without bleeding into adjacent cells.
2. grid.at(x, y).entities — Simplest, but O(n)
cell = grid.at(x, y)
entities_here = cell.entities
Readable and obvious, but the implementation (UIGridPoint.cpp:109) does a linear scan of the entire grid.entities list, comparing every entity's position against
(target_x, target_y). Fine for small entity counts, but scales poorly.
3. Manual iteration — Most flexible, same O(n)
at_pos = [e for e in grid.entities if int(e.pos[0]) == x and int(e.pos[1]) == y]
Same linear scan but in Python, so strictly slower than option 2 (which at least does the loop in C++).
---
Recommendation: Use grid.entities_in_radius((x, y), 0.5) for performance-sensitive code (pathfinding, collision checks). Use grid.at(x, y).entities when readability
matters more than speed and entity counts are small.
✻ Sautéed for 35s
❯ any reason why the implementation of GridPoint.entities shouldn't use the spatial hash internally?
● No, there's no good reason. It should. Let me check if there's any subtle difference that might matter.
● Read(src/SpatialHash.h)
⎿ Read 72 lines
● Read(src/SpatialHash.cpp)
⎿ Read 126 lines
● No reason at all. The spatial hash is already maintained by the grid — GridPoint.entities just ignores it and does a brute-force linear scan instead. It's purely a
historical artifact (#114 predates #115).
The only minor consideration is that queryRadius does a circular distance check, but for an exact cell match you'd want equality. A small dedicated method like
queryCell(int x, int y) on SpatialHash would be ideal — just a single bucket lookup plus position match, no radius math. But even using the existing queryRadius(x + 0.5f,
y + 0.5f, 0.5f) would be a big improvement over the O(n) scan.
```
Bugfix
priority:tier1-active
labels
Labels
No labels
Alpha Release Requirement
Bugfix
Demo Target
Documentation
Major Feature
Minor Feature
priority:tier1-active
priority:tier2-foundation
priority:tier3-future
priority:tier4-deferred
Refactoring & Cleanup
system:animation
system:documentation
system:grid
system:input
system:performance
system:procgen
system:python-binding
system:rendering
system:ui-hierarchy
Tiny Feature
workflow:blocked
workflow:needs-benchmark
workflow:needs-documentation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
john/McRogueFace#253
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?