Entity.gridstate as DiscreteMap reference #294

Open
opened 2026-03-08 20:19:11 +00:00 by john · 1 comment
Owner

Summary

Replace the current entity gridstate implementation (flat arrays with ensureGridstate() resize logic) with a DiscreteMap reference. Entity perspective knowledge becomes a first-class, swappable, serializable object rather than an implicit internal array.

Current problems

  1. ensureGridstate() silently destroys exploration data — moving between grids of different sizes wipes all discovery with no callback or save mechanism
  2. Same-size grids retain stale data — silently reuses the previous grid's perspective data
  3. entity.gridstate returns detached copies (SimpleNamespace snapshots), forcing O(w×h) Python iteration for save/restore — violates the principle that grid-shaped iteration stays on the C++ side
  4. No identity — the gridstate has no association with which grid it belongs to

Proposed API

# Entity's perspective is a DiscreteMap (3 states: unknown=0, discovered=1, visible=2)
perspective = entity.perspective_map  # returns DiscreteMap reference

# Save before leaving a grid
saved = perspective.to_bytes()  # from DiscreteMap serialization issue

# Assign a grid's perspective entity with existing memory
grid.perspective = (entity, saved_discretemap)
# Or with None to create a fresh (all-unknown) DiscreteMap:
grid.perspective = (entity, None)

# Assigning with wrong-sized DiscreteMap raises ValueError
grid.perspective = (entity, wrong_size_map)  # ValueError

# Simple assignment still works — creates fresh DiscreteMap
grid.perspective = entity  # equivalent to (entity, None)

Engine behavior on grid transitions

When an entity is removed from a grid (or the grid's perspective entity changes):

  • The engine disables perspective on affected GridLayers
  • The DiscreteMap remains valid and accessible — game code can save it
  • The engine does NOT automatically cache per-grid states (game devs manage this if needed)

Game-side multi-grid memory pattern

# Game code manages the grid↔memory mapping
player_memory = {}  # grid_id -> bytes

def enter_grid(player, new_grid):
    # Save current
    if player.perspective_map:
        player_memory[current_grid.id] = player.perspective_map.to_bytes()
    # Restore or create fresh
    saved = player_memory.get(new_grid.id)
    if saved:
        dmap = mcrfpy.DiscreteMap(new_grid.width, new_grid.height, 3, data=saved)
        new_grid.perspective = (player, dmap)
    else:
        new_grid.perspective = (player, None)

The engine provides correct primitives; game code composes them for its specific needs.

Dependencies

  • DiscreteMap serialization issue (to_bytes / from_bytes)
  • #252 Grid/GridView overhaul (broader architectural context)

Scope

Could be implemented incrementally on the current Entity/Grid, or as part of #252. The DiscreteMap serialization issue is a prerequisite.

## Summary Replace the current entity gridstate implementation (flat arrays with `ensureGridstate()` resize logic) with a `DiscreteMap` reference. Entity perspective knowledge becomes a first-class, swappable, serializable object rather than an implicit internal array. ## Current problems 1. **`ensureGridstate()` silently destroys exploration data** — moving between grids of different sizes wipes all discovery with no callback or save mechanism 2. **Same-size grids retain stale data** — silently reuses the previous grid's perspective data 3. **`entity.gridstate` returns detached copies** (SimpleNamespace snapshots), forcing O(w×h) Python iteration for save/restore — violates the principle that grid-shaped iteration stays on the C++ side 4. **No identity** — the gridstate has no association with which grid it belongs to ## Proposed API ```python # Entity's perspective is a DiscreteMap (3 states: unknown=0, discovered=1, visible=2) perspective = entity.perspective_map # returns DiscreteMap reference # Save before leaving a grid saved = perspective.to_bytes() # from DiscreteMap serialization issue # Assign a grid's perspective entity with existing memory grid.perspective = (entity, saved_discretemap) # Or with None to create a fresh (all-unknown) DiscreteMap: grid.perspective = (entity, None) # Assigning with wrong-sized DiscreteMap raises ValueError grid.perspective = (entity, wrong_size_map) # ValueError # Simple assignment still works — creates fresh DiscreteMap grid.perspective = entity # equivalent to (entity, None) ``` ### Engine behavior on grid transitions When an entity is removed from a grid (or the grid's perspective entity changes): - The engine disables perspective on affected GridLayers - The DiscreteMap remains valid and accessible — game code can save it - The engine does NOT automatically cache per-grid states (game devs manage this if needed) ### Game-side multi-grid memory pattern ```python # Game code manages the grid↔memory mapping player_memory = {} # grid_id -> bytes def enter_grid(player, new_grid): # Save current if player.perspective_map: player_memory[current_grid.id] = player.perspective_map.to_bytes() # Restore or create fresh saved = player_memory.get(new_grid.id) if saved: dmap = mcrfpy.DiscreteMap(new_grid.width, new_grid.height, 3, data=saved) new_grid.perspective = (player, dmap) else: new_grid.perspective = (player, None) ``` The engine provides correct primitives; game code composes them for its specific needs. ## Dependencies - DiscreteMap serialization issue (to_bytes / from_bytes) - #252 Grid/GridView overhaul (broader architectural context) ## Scope Could be implemented incrementally on the current Entity/Grid, or as part of #252. The DiscreteMap serialization issue is a prerequisite.
Author
Owner

Roadmap context

This issue is part of the Grid & Entity Overhaul Roadmap (docs/GRID_ENTITY_OVERHAUL_ROADMAP.md), placed in Phase 4 (after #252 Grid/GridView split).

The behavior system's seek/flee behaviors (#300) will initially use the current DijkstraMap type, then migrate to DiscreteMap when this issue lands. The DiscreteMap will also serve as the entity's perspective map for FOV-based TARGET triggers in the behavior system.

## Roadmap context This issue is part of the Grid & Entity Overhaul Roadmap (`docs/GRID_ENTITY_OVERHAUL_ROADMAP.md`), placed in **Phase 4** (after #252 Grid/GridView split). The behavior system's seek/flee behaviors (#300) will initially use the current `DijkstraMap` type, then migrate to `DiscreteMap` when this issue lands. The `DiscreteMap` will also serve as the entity's perspective map for FOV-based TARGET triggers in the behavior system.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Depends on
Reference
john/McRogueFace#294
No description provided.