grid.step() turn manager does not check entity occupancy for movement collision #415
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#415
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?
Found while building the mcrogueface-007 demo body node (robot_sim_stack, SIM_SPEC_v2.md §13.6), which wanted
Trigger.BLOCKEDto be reachable as "a genuine actuation failure... a collision with another moving entity."Traced the turn manager (
PyGridData::py_step,src/PyGridDataMethods.cpp:1000-1040) and the per-behavior executors (src/EntityBehavior.cpp): for WAYPOINT/PATH/PATROL/LOOP,BehaviorResult::BLOCKEDis produced only whenisCellWalkable()fails (staticgrid.walkable_plane,EntityBehavior.cpp:44) orTCODPath::compute()finds no route.BehaviorResult::MOVEDnever checks whether the target cell is currently occupied by another entity —grid->spatial_hash.queryCell(...)is consulted only after a BLOCKED result already happened for a terrain reason, purely to name a blocker for the callback payload, not to decide BLOCKED in the first place.Net effect: two entities can walk through/onto one another with no collision, no BLOCKED trigger, and no signal at all. This is a plausible gap for anyone building a turn-based game on
grid.step()and expecting entities to be mutually solid.Not a blocker for mcrogueface-007 — that demo produces a legible BLOCKED via an unreachable target (walled-off pocket) instead, which satisfies the same "deterministic, fully explained, reconstructible" requirement without needing this. Filing so the gap is tracked rather than silently rediscovered later.
Possible fix shape (not designed in detail here): in the
BehaviorResult::MOVEDcase inPyGridData::py_step, checkgrid->spatial_hash.queryCell(target_cell)for a live entity before committing the move, and re-route that case through the existing BLOCKED path (including the blocker lookup that already exists) instead of unconditionally moving.