Update Proposal: Next Gen Grid Entity System

John McCardle 2025-12-02 03:14:30 +00:00
parent bca1ee8f52
commit 49f2aa8d2f
1 changed files with 436 additions and 436 deletions

@ -1,436 +1,436 @@
# Proposal: Next-Generation Grid & Entity System # Proposal: Next-Generation Grid & Entity System
**Status:** Design Phase **Status:** Design Phase
**Complexity:** Major architectural overhaul **Complexity:** Major architectural overhaul
**Impact:** Grid System, Entity Management, Performance **Impact:** Grid System, Entity Management, Performance
**Related Pages:** **Related Pages:**
- [[Grid-System]] - Current grid architecture - [[Grid-System]] - Current grid architecture
- [[Entity-Management]] - Current entity usage - [[Entity-Management]] - Current entity usage
- [[Grid-Rendering-Pipeline]] - Current rendering architecture - [[Grid-Rendering-Pipeline]] - Current rendering architecture
**Source Documents:** **Source Documents:**
- `NEXT_GEN_GRIDS_ENTITIES_SHORTCOMINGS.md` - Analysis of current limitations - `NEXT_GEN_GRIDS_ENTITIES_SHORTCOMINGS.md` - Analysis of current limitations
- `NEXT_GEN_GRIDS_ENTITIES_PROPOSAL.md` - Detailed technical proposal - `NEXT_GEN_GRIDS_ENTITIES_PROPOSAL.md` - Detailed technical proposal
- `NEXT_GEN_GRIDS_ENTITIES_IDEATION.md` - Use cases and ideation - `NEXT_GEN_GRIDS_ENTITIES_IDEATION.md` - Use cases and ideation
**Related Issues:** **Related Issues:**
- [#115](../../issues/115) - SpatialHash for 10,000+ entities - [#115](../../issues/115) - SpatialHash for 10,000+ entities
- [#116](../../issues/116) - Dirty flag system - [#116](../../issues/116) - Dirty flag system
- [#113](../../issues/113) - Batch operations - [#113](../../issues/113) - Batch operations
- [#117](../../issues/117) - Memory pool - [#117](../../issues/117) - Memory pool
- [#123](../../issues/123) - Subgrid system - [#123](../../issues/123) - Subgrid system
- [#124](../../issues/124) - Grid Point Animation - [#124](../../issues/124) - Grid Point Animation
--- ---
## Executive Summary ## Executive Summary
The current UIEntity/UIGrid system has fundamental architectural limitations preventing implementation of modern roguelike features. This proposal outlines a comprehensive redesign supporting: The current UIEntity/UIGrid system has fundamental architectural limitations preventing implementation of modern roguelike features. This proposal outlines a comprehensive redesign supporting:
- **Flexible entity content** - Entities containing any UIDrawable (Frame, Caption, Grid, Sprite) - **Flexible entity content** - Entities containing any UIDrawable (Frame, Caption, Grid, Sprite)
- **Multi-tile entities** - 2x2, 3x3, or arbitrary-sized creatures and structures - **Multi-tile entities** - 2x2, 3x3, or arbitrary-sized creatures and structures
- **Custom layer system** - Weather effects, particle layers, UI overlays - **Custom layer system** - Weather effects, particle layers, UI overlays
- **Spatial optimization** - O(1) entity queries via spatial hashing - **Spatial optimization** - O(1) entity queries via spatial hashing
- **Memory efficiency** - Optional gridstate, chunk-based loading - **Memory efficiency** - Optional gridstate, chunk-based loading
**Key Insight:** Maintain entity as grid-specific *container* (no inheritance from UIDrawable), but allow flexible *content* (any UIDrawable). **Key Insight:** Maintain entity as grid-specific *container* (no inheritance from UIDrawable), but allow flexible *content* (any UIDrawable).
--- ---
## Current Limitations ## Current Limitations
### 1. Entity Type Rigidity ### 1. Entity Type Rigidity
**Problem:** **Problem:**
- UIEntity hardcoded to contain only UISprite - UIEntity hardcoded to contain only UISprite
- Cannot place Frames, Captions, or Grids on grids - Cannot place Frames, Captions, or Grids on grids
- Blocks speech bubbles, nested grids, complex UI - Blocks speech bubbles, nested grids, complex UI
**Current Code:** **Current Code:**
```cpp ```cpp
class UIEntity { class UIEntity {
UISprite sprite; // Hardcoded! UISprite sprite; // Hardcoded!
// Should be: std::shared_ptr<UIDrawable> content; // Should be: std::shared_ptr<UIDrawable> content;
} }
``` ```
### 2. Single-Tile Limitation ### 2. Single-Tile Limitation
**Problem:** **Problem:**
- Entity position is single point - Entity position is single point
- No concept of dimensions or occupied tiles - No concept of dimensions or occupied tiles
- Blocks large enemies (2x2 dragons), multi-tile structures (castle doors) - Blocks large enemies (2x2 dragons), multi-tile structures (castle doors)
**Missing:** **Missing:**
- `width`/`height` properties - `width`/`height` properties
- Spatial occupancy tracking - Spatial occupancy tracking
- Collision detection for multi-tile entities - Collision detection for multi-tile entities
### 3. Fixed Layer System ### 3. Fixed Layer System
**Problem:** **Problem:**
- Grid has three hardcoded layers: tiles, entities, visibility - Grid has three hardcoded layers: tiles, entities, visibility
- No custom layers - No custom layers
- Blocks cloud layer, particle effects, weather overlays - Blocks cloud layer, particle effects, weather overlays
### 4. Performance Issues ### 4. Performance Issues
**Problem:** **Problem:**
- Linear O(n) iteration through all entities - Linear O(n) iteration through all entities
- No spatial indexing - No spatial indexing
- Full grid re-render every frame - Full grid re-render every frame
**Current Code:** **Current Code:**
```cpp ```cpp
// O(n) iteration every frame // O(n) iteration every frame
for (auto e : *entities) { for (auto e : *entities) {
if (in_viewport(e)) render(e); if (in_viewport(e)) render(e);
} }
``` ```
### 5. Memory Inefficiency ### 5. Memory Inefficiency
**Problem:** **Problem:**
- Every entity maintains full gridstate vector (width × height) - Every entity maintains full gridstate vector (width × height)
- Decorative entities (clouds) waste memory on visibility data - Decorative entities (clouds) waste memory on visibility data
- Cannot unload distant chunks - Cannot unload distant chunks
--- ---
## Proposed Architecture ## Proposed Architecture
### Core Change 1: Flexible Entity Content ### Core Change 1: Flexible Entity Content
```cpp ```cpp
class UIEntity { // No inheritance - grid-specific container class UIEntity { // No inheritance - grid-specific container
private: private:
std::shared_ptr<UIDrawable> content; // Any drawable! std::shared_ptr<UIDrawable> content; // Any drawable!
sf::Vector2f gridPosition; // Position in grid coords sf::Vector2f gridPosition; // Position in grid coords
sf::Vector2i dimensions; // Size in tiles (default 1x1) sf::Vector2i dimensions; // Size in tiles (default 1x1)
std::set<sf::Vector2i> occupiedTiles; // Cached occupied positions std::set<sf::Vector2i> occupiedTiles; // Cached occupied positions
std::vector<UIGridPointState> gridstate; // Optional perspective data std::vector<UIGridPointState> gridstate; // Optional perspective data
public: public:
void setContent(std::shared_ptr<UIDrawable> drawable); void setContent(std::shared_ptr<UIDrawable> drawable);
void renderAt(sf::RenderTarget& target, sf::Vector2f pixelPos); void renderAt(sf::RenderTarget& target, sf::Vector2f pixelPos);
bool occupies(int x, int y) const; bool occupies(int x, int y) const;
}; };
``` ```
**Python API:** **Python API:**
```python ```python
# Entity with sprite (backward compatible) # Entity with sprite (backward compatible)
enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5) enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5)
# Entity with frame (NEW - speech bubble) # Entity with frame (NEW - speech bubble)
speech_frame = mcrfpy.Frame(size=(100, 50)) speech_frame = mcrfpy.Frame(size=(100, 50))
speech_caption = mcrfpy.Caption(text="Hello!") speech_caption = mcrfpy.Caption(text="Hello!")
speech_frame.append(speech_caption) speech_frame.append(speech_caption)
speech_entity = mcrfpy.Entity(grid_pos=(player.x, player.y - 2)) speech_entity = mcrfpy.Entity(grid_pos=(player.x, player.y - 2))
speech_entity.content = speech_frame speech_entity.content = speech_frame
# Entity with nested grid (NEW - mini-map) # Entity with nested grid (NEW - mini-map)
minimap_grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100)) minimap_grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100))
minimap_entity = mcrfpy.Entity(grid_pos=(5, 5)) minimap_entity = mcrfpy.Entity(grid_pos=(5, 5))
minimap_entity.content = minimap_grid minimap_entity.content = minimap_grid
``` ```
### Core Change 2: Multi-Tile Entities ### Core Change 2: Multi-Tile Entities
```cpp ```cpp
class GridOccupancyMap { class GridOccupancyMap {
private: private:
std::unordered_map<int, std::set<std::shared_ptr<UIEntity>>> spatialHash; std::unordered_map<int, std::set<std::shared_ptr<UIEntity>>> spatialHash;
int cellSize = 16; int cellSize = 16;
public: public:
void addEntity(std::shared_ptr<UIEntity> entity); void addEntity(std::shared_ptr<UIEntity> entity);
void removeEntity(std::shared_ptr<UIEntity> entity); void removeEntity(std::shared_ptr<UIEntity> entity);
std::vector<std::shared_ptr<UIEntity>> getEntitiesAt(int x, int y); // O(1) std::vector<std::shared_ptr<UIEntity>> getEntitiesAt(int x, int y); // O(1)
std::vector<std::shared_ptr<UIEntity>> getEntitiesInRect(sf::IntRect rect); std::vector<std::shared_ptr<UIEntity>> getEntitiesInRect(sf::IntRect rect);
}; };
``` ```
**Python API:** **Python API:**
```python ```python
# Large enemy (2x2 tiles) # Large enemy (2x2 tiles)
dragon = mcrfpy.Entity( dragon = mcrfpy.Entity(
grid_pos=(20, 20), grid_pos=(20, 20),
sprite_index=10, sprite_index=10,
dimensions=(2, 2) # NEW: multi-tile support dimensions=(2, 2) # NEW: multi-tile support
) )
# Check what tiles dragon occupies # Check what tiles dragon occupies
occupied = dragon.occupied_tiles # [(20, 20), (21, 20), (20, 21), (21, 21)] occupied = dragon.occupied_tiles # [(20, 20), (21, 20), (20, 21), (21, 21)]
# Collision detection accounts for size # Collision detection accounts for size
if grid.can_move_to(dragon, new_x, new_y): if grid.can_move_to(dragon, new_x, new_y):
dragon.x = new_x dragon.x = new_x
dragon.y = new_y dragon.y = new_y
``` ```
### Core Change 3: Flexible Layer System ### Core Change 3: Flexible Layer System
```cpp ```cpp
class GridLayer { class GridLayer {
public: public:
enum class Type { TILE, ENTITY, EFFECT, OVERLAY, CUSTOM }; enum class Type { TILE, ENTITY, EFFECT, OVERLAY, CUSTOM };
private: private:
Type type; Type type;
std::string name; std::string name;
int zOrder; int zOrder;
float opacity = 1.0f; float opacity = 1.0f;
bool visible = true; bool visible = true;
std::shared_ptr<EntityCollection> entities; // For ENTITY layers std::shared_ptr<EntityCollection> entities; // For ENTITY layers
public: public:
virtual void render(UIGrid* grid, sf::RenderTarget& target); virtual void render(UIGrid* grid, sf::RenderTarget& target);
}; };
class UIGrid : public UIDrawable { class UIGrid : public UIDrawable {
private: private:
std::map<std::string, std::shared_ptr<GridLayer>> layers; std::map<std::string, std::shared_ptr<GridLayer>> layers;
std::vector<std::shared_ptr<GridLayer>> sortedLayers; // By zOrder std::vector<std::shared_ptr<GridLayer>> sortedLayers; // By zOrder
public: public:
std::shared_ptr<GridLayer> addLayer(const std::string& name, std::shared_ptr<GridLayer> addLayer(const std::string& name,
GridLayer::Type type, int zOrder); GridLayer::Type type, int zOrder);
}; };
``` ```
**Python API:** **Python API:**
```python ```python
# Create custom layers # Create custom layers
grid.add_layer("clouds", mcrfpy.LayerType.EFFECT, z_order=100) grid.add_layer("clouds", mcrfpy.LayerType.EFFECT, z_order=100)
grid.add_layer("particles", mcrfpy.LayerType.EFFECT, z_order=50) grid.add_layer("particles", mcrfpy.LayerType.EFFECT, z_order=50)
grid.add_layer("units", mcrfpy.LayerType.ENTITY, z_order=10) grid.add_layer("units", mcrfpy.LayerType.ENTITY, z_order=10)
# Add entities to specific layers # Add entities to specific layers
cloud = mcrfpy.Entity(grid_pos=(15, 15), sprite_index=20) cloud = mcrfpy.Entity(grid_pos=(15, 15), sprite_index=20)
grid.get_layer("clouds").entities.append(cloud) grid.get_layer("clouds").entities.append(cloud)
# Layer control # Layer control
grid.get_layer("clouds").opacity = 0.5 grid.get_layer("clouds").opacity = 0.5
grid.get_layer("clouds").visible = False grid.get_layer("clouds").visible = False
``` ```
### Core Change 4: Spatial Optimization ### Core Change 4: Spatial Optimization
**SpatialHash Implementation:** **SpatialHash Implementation:**
```cpp ```cpp
int hashPosition(int x, int y) const { int hashPosition(int x, int y) const {
return (x / cellSize) * 1000000 + (y / cellSize); return (x / cellSize) * 1000000 + (y / cellSize);
} }
std::vector<std::shared_ptr<UIEntity>> getEntitiesInRect(sf::IntRect rect) { std::vector<std::shared_ptr<UIEntity>> getEntitiesInRect(sf::IntRect rect) {
std::set<std::shared_ptr<UIEntity>> result; std::set<std::shared_ptr<UIEntity>> result;
// Only check relevant hash cells // Only check relevant hash cells
for (int y = rect.top; y < rect.top + rect.height; y += cellSize) { for (int y = rect.top; y < rect.top + rect.height; y += cellSize) {
for (int x = rect.left; x < rect.left + rect.width; x += cellSize) { for (int x = rect.left; x < rect.left + rect.width; x += cellSize) {
int hash = hashPosition(x, y); int hash = hashPosition(x, y);
if (spatialHash.count(hash)) { if (spatialHash.count(hash)) {
result.insert(spatialHash[hash].begin(), spatialHash[hash].end()); result.insert(spatialHash[hash].begin(), spatialHash[hash].end());
} }
} }
} }
return std::vector<std::shared_ptr<UIEntity>>(result.begin(), result.end()); return std::vector<std::shared_ptr<UIEntity>>(result.begin(), result.end());
} }
``` ```
**Performance Impact:** **Performance Impact:**
- Current: O(n) for entity queries - Current: O(n) for entity queries
- Proposed: O(1) average case - Proposed: O(1) average case
**Benchmark Targets:** **Benchmark Targets:**
- 10,000 entities with 50 visible: <1ms per frame - 10,000 entities with 50 visible: <1ms per frame
- Entity collision detection: O(k) where k = entities in same hash cell - Entity collision detection: O(k) where k = entities in same hash cell
--- ---
## Migration Path ## Migration Path
### Phase 1: Performance Foundation (Issues #115, #116, #117) ### Phase 1: Performance Foundation (Issues #115, #116, #117)
**Backward compatible improvements:** **Backward compatible improvements:**
1. Add SpatialHash to existing UIGrid 1. Add SpatialHash to existing UIGrid
2. Implement dirty flag system 2. Implement dirty flag system
3. Add memory pool for entities 3. Add memory pool for entities
**No breaking changes to Python API.** **No breaking changes to Python API.**
### Phase 2: Multi-Tile Support (Issue #123) ### Phase 2: Multi-Tile Support (Issue #123)
**Add to existing UIEntity:** **Add to existing UIEntity:**
```cpp ```cpp
// Add to UIEntity class // Add to UIEntity class
sf::Vector2i dimensions = {1, 1}; // Default 1x1 (backward compatible) sf::Vector2i dimensions = {1, 1}; // Default 1x1 (backward compatible)
std::set<sf::Vector2i> occupiedTiles; std::set<sf::Vector2i> occupiedTiles;
void updateOccupiedTiles(); void updateOccupiedTiles();
bool occupies(int x, int y) const; bool occupies(int x, int y) const;
``` ```
**Python API additions:** **Python API additions:**
```python ```python
# Backward compatible - existing code works unchanged # Backward compatible - existing code works unchanged
enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5) enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5)
# New code can specify dimensions # New code can specify dimensions
dragon = mcrfpy.Entity(grid_pos=(20, 20), sprite_index=10, dimensions=(2, 2)) dragon = mcrfpy.Entity(grid_pos=(20, 20), sprite_index=10, dimensions=(2, 2))
``` ```
### Phase 3: Flexible Content (Issue #124) ### Phase 3: Flexible Content (Issue #124)
**Replace UIEntity::sprite with content:** **Replace UIEntity::sprite with content:**
```cpp ```cpp
// Deprecate: UISprite sprite; // Deprecate: UISprite sprite;
// Add: std::shared_ptr<UIDrawable> content; // Add: std::shared_ptr<UIDrawable> content;
// Backward compatibility shim: // Backward compatibility shim:
PyObject* get_sprite() { PyObject* get_sprite() {
auto sprite = std::dynamic_pointer_cast<UISprite>(content); auto sprite = std::dynamic_pointer_cast<UISprite>(content);
if (!sprite) { if (!sprite) {
// Legacy: entity still has sprite member // Legacy: entity still has sprite member
return legacy_sprite_accessor(); return legacy_sprite_accessor();
} }
return RET_PY_INSTANCE(sprite); return RET_PY_INSTANCE(sprite);
} }
``` ```
**Migration period:** 1-2 releases with deprecation warnings. **Migration period:** 1-2 releases with deprecation warnings.
### Phase 4: Layer System ### Phase 4: Layer System
**Add GridLayer system alongside existing architecture:** **Add GridLayer system alongside existing architecture:**
```cpp ```cpp
// Existing entities automatically added to default "entities" layer // Existing entities automatically added to default "entities" layer
// New layer API available for advanced use // New layer API available for advanced use
``` ```
**Backward compatible - existing code works unchanged.** **Backward compatible - existing code works unchanged.**
--- ---
## Use Cases Enabled ## Use Cases Enabled
### Speech Bubbles ### Speech Bubbles
```python ```python
speech = mcrfpy.Frame(size=(100, 40)) speech = mcrfpy.Frame(size=(100, 40))
speech.append(mcrfpy.Caption(text="Hello adventurer!")) speech.append(mcrfpy.Caption(text="Hello adventurer!"))
bubble = mcrfpy.Entity(grid_pos=(npc.x, npc.y - 1)) bubble = mcrfpy.Entity(grid_pos=(npc.x, npc.y - 1))
bubble.content = speech bubble.content = speech
grid.entities.append(bubble) grid.entities.append(bubble)
``` ```
### Large Enemies ### Large Enemies
```python ```python
dragon = mcrfpy.Entity(grid_pos=(25, 25), sprite_index=DRAGON, dimensions=(3, 3)) dragon = mcrfpy.Entity(grid_pos=(25, 25), sprite_index=DRAGON, dimensions=(3, 3))
# Pathfinding accounts for size # Pathfinding accounts for size
if grid.can_large_entity_move_to(dragon, new_x, new_y): if grid.can_large_entity_move_to(dragon, new_x, new_y):
dragon.move_to(new_x, new_y) dragon.move_to(new_x, new_y)
``` ```
### Weather Effects ### Weather Effects
```python ```python
grid.add_layer("rain", mcrfpy.LayerType.EFFECT, z_order=200) grid.add_layer("rain", mcrfpy.LayerType.EFFECT, z_order=200)
rain_layer = grid.get_layer("rain") rain_layer = grid.get_layer("rain")
for i in range(100): for i in range(100):
raindrop = mcrfpy.Entity( raindrop = mcrfpy.Entity(
grid_pos=(random.randint(0, 49), random.randint(0, 49)), grid_pos=(random.randint(0, 49), random.randint(0, 49)),
sprite_index=RAINDROP sprite_index=RAINDROP
) )
rain_layer.entities.append(raindrop) rain_layer.entities.append(raindrop)
``` ```
### Nested Mini-Map ### Nested Mini-Map
```python ```python
minimap = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100)) minimap = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100))
# ... populate minimap ... # ... populate minimap ...
minimap_entity = mcrfpy.Entity(grid_pos=(0, 0)) minimap_entity = mcrfpy.Entity(grid_pos=(0, 0))
minimap_entity.content = minimap minimap_entity.content = minimap
hud_layer.entities.append(minimap_entity) hud_layer.entities.append(minimap_entity)
``` ```
--- ---
## Performance Expectations ## Performance Expectations
### Before (Current System) ### Before (Current System)
- 1,000 entities: 60 FPS - 1,000 entities: 60 FPS
- 10,000 entities: 15 FPS (unacceptable) - 10,000 entities: 15 FPS (unacceptable)
- Entity query: O(n) = slow - Entity query: O(n) = slow
### After (Proposed System) ### After (Proposed System)
- 1,000 entities: 60 FPS - 1,000 entities: 60 FPS
- 10,000 entities: 60 FPS (with spatial hash + culling) - 10,000 entities: 60 FPS (with spatial hash + culling)
- Entity query: O(1) average case - Entity query: O(1) average case
### Memory Impact ### Memory Impact
- Per-entity overhead: +24 bytes (dimensions, occupied tiles set) - Per-entity overhead: +24 bytes (dimensions, occupied tiles set)
- Spatial hash: ~8KB for 1000 entities (negligible) - Spatial hash: ~8KB for 1000 entities (negligible)
- Optional gridstate: Save width × height × sizeof(UIGridPointState) per decorative entity - Optional gridstate: Save width × height × sizeof(UIGridPointState) per decorative entity
--- ---
## Open Questions ## Open Questions
1. **Backward Compatibility Timeline** 1. **Backward Compatibility Timeline**
- How many releases should deprecation period last? - How many releases should deprecation period last?
- Support for legacy `entity.sprite` accessor? - Support for legacy `entity.sprite` accessor?
2. **Layer API Design** 2. **Layer API Design**
- Should layers have separate render textures? - Should layers have separate render textures?
- Layer blending modes (multiply, add, alpha)? - Layer blending modes (multiply, add, alpha)?
3. **Multi-Tile Pathfinding** 3. **Multi-Tile Pathfinding**
- Should large entities use separate TCOD maps? - Should large entities use separate TCOD maps?
- How to handle partially-blocked paths? - How to handle partially-blocked paths?
4. **Content Delegation** 4. **Content Delegation**
- Should entity forward all UIDrawable methods to content? - Should entity forward all UIDrawable methods to content?
- Or keep explicit `entity.content.method()` pattern? - Or keep explicit `entity.content.method()` pattern?
--- ---
## Implementation Complexity ## Implementation Complexity
**Estimated Effort:** **Estimated Effort:**
- Phase 1 (SpatialHash, dirty flags): 40-60 hours - Phase 1 (SpatialHash, dirty flags): 40-60 hours
- Phase 2 (Multi-tile): 20-30 hours - Phase 2 (Multi-tile): 20-30 hours
- Phase 3 (Flexible content): 30-40 hours - Phase 3 (Flexible content): 30-40 hours
- Phase 4 (Layers): 40-50 hours - Phase 4 (Layers): 40-50 hours
**Total:** 130-180 hours (3-4 months part-time) **Total:** 130-180 hours (3-4 months part-time)
**Risk Areas:** **Risk Areas:**
- Backward compatibility testing - Backward compatibility testing
- Python binding complexity for flexible content - Python binding complexity for flexible content
- Performance regression testing - Performance regression testing
- Documentation updates - Documentation updates
--- ---
## Decision Needed ## Decision Needed
**Should this proposal move forward?** **Should this proposal move forward?**
- ✅ Addresses major architectural limitations - ✅ Addresses major architectural limitations
- ✅ Enables modern roguelike features - ✅ Enables modern roguelike features
- ✅ Clear migration path with backward compatibility - ✅ Clear migration path with backward compatibility
- ⚠️ Significant implementation effort - ⚠️ Significant implementation effort
- ⚠️ Risk of introducing bugs in core systems - ⚠️ Risk of introducing bugs in core systems
**Alternative:** Focus on incremental improvements (SpatialHash, dirty flags) without architectural redesign. **Alternative:** Focus on incremental improvements (SpatialHash, dirty flags) without architectural redesign.
--- ---
**Navigation:** **Navigation:**
- [[Home]] - Documentation hub - [[Home]] - Documentation hub
- [[Grid-System]] - Current architecture - [[Grid-System]] - Current architecture
- [[Design-Proposals]] - All design proposals - [[Design-Proposals]] - All design proposals