Per-entity FOV memory moves from std::vector<UIGridPointState> (two-bool
visible/discovered pairs) to a 3-state DiscreteMap (0=UNKNOWN, 1=DISCOVERED,
2=VISIBLE), exposed as entity.perspective_map. The invariant
visible-subset-of-discovered becomes structural (single value per cell), and
the map is a live, serializable, first-class object rather than an implicit
internal array.
Changes:
- New DiscreteMap C++ class with shared ownership; PyDiscreteMapObject now
holds shared_ptr<DiscreteMap>. UIEntity holds the same shared_ptr.
- New mcrfpy.Perspective IntEnum (UNKNOWN/DISCOVERED/VISIBLE), modelled on
PyInputState.
- entity.perspective_map: lazy-allocated on first access with a grid;
setter validates size against grid and raises ValueError on mismatch;
None clears (next access lazy-reallocates fresh).
- updateVisibility() now demotes 2->1 then promotes visible cells to 2.
- entity.at(x, y) returns grid.at(x, y) when VISIBLE, else None.
- Fog-of-war rendering in UIGridView and UIGrid reads the 3-state map.
- Removed: UIEntity::gridstate, ensureGridstate(), entity.gridstate getter,
UIGridPointState struct + PyUIGridPointStateType.
- Obsolete tests deleted (test_gridpointstate_point,
issue_265_gridpointstate_dangle); 4 new tests cover lazy allocation,
identity, serialization round-trip, size validation, and the
visible-subset-of-discovered invariant.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BREAKING CHANGE: Constructor keyword argument renamed from `click` to
`on_click` for all UIDrawable types (Frame, Caption, Sprite, Grid, Line,
Circle, Arc).
Before: Frame(pos=(0,0), size=(100,100), click=handler)
After: Frame(pos=(0,0), size=(100,100), on_click=handler)
The property name was already `on_click` - this makes the constructor
kwarg match, completing the callback naming standardization from #139.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- grid_demo.py: Updated for new layer-based rendering
- Screenshots: Refreshed demo screenshots
- API docs: Regenerated with latest method signatures
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>