GridData.observe(origin=...) mutates the grid's shared FOV buffer #402
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#402
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 implementing
GridData.observe()/mcrfpy.VisibilityMaskfor the simulation-harness observation seam (seesrc/PyGridDataMethods.cpp:PyGridData::py_observe,src/PyVisibilityMask.{h,cpp}).observe()is documented as producing an inert, side-effect-free snapshot ("the returned dict holds no live references and is unaffected by later grid or entity changes"). But when called with anorigin, it calls straight intoGridData::computeFOV()(src/GridData.cpp:138), exactly the same code path used bycompute_fov()/is_in_fov()and by entity FOV updates (UIEntity.cpp:112,:1311,GridLayers.cpp:301). There is exactly one TCOD FOV map perGridData, andcomputeFOV()overwrites it in place.So a nominally read-only projection has a real side effect: if a background observer (an NPC, an AI perception query, a simulation harness taking a snapshot from some other position) calls
grid.observe(origin=npc_pos), it silently clobbers whatever FOV state the player/renderer had just computed for that grid. The nextis_in_fov()call or FOV-driven render reads the observer's FOV, not the player's.This is currently only documented, not fixed —
py_observe's MCRF_NOTE says: "observe(origin=...) recomputes the grid's FOV state exactly as compute_fov() does -- it is the same shared per-grid TCOD FOV buffer. observe() with no origin touches no FOV state at all."Suggested fix shapes (pick one, or propose better):
GridDataa scratch/second TCOD FOV map used only byobserve(), leaving the "live" FOV map (used bycompute_fov()/rendering) untouched.computeFOV()insideobserve()and restore it afterward.Either way,
observe(origin=...)should become genuinely side-effect-free, matching what its docstring already promises.Type label: filing as Minor Feature rather than Bugfix — the current behavior matches its own documentation (it's a documented caveat, not an unnoticed bug), and fixing it requires adding real capacity (a second FOV buffer or save/restore), not correcting a wrong computation.