Files
MaidEngine/docs/superpowers/specs/2026-04-05-room-system-design.md
2026-04-05 22:58:30 -04:00

2.6 KiB

Room System Design

Overview

A room system for battle maps where rooms are defined as groups of tiles, walls exist on tile borders (not as tiles), and openings are explicitly marked doorways between rooms. Tiles outside rooms are impassable void.

Data Model

Room (Resource)

  • id: int — unique room identifier
  • tiles: Array[Vector2i] — tile coordinates belonging to this room

MapLayout (Resource)

  • rooms: Array[Room] — all rooms on the map
  • openings: Array — list of tile-coordinate pairs ([Vector2i, Vector2i]) representing bidirectional doorways between adjacent tiles in different rooms

Derived Wall Computation

A wall exists on a tile edge when:

  1. One side is a room tile and the other is void (not in any room), OR
  2. The two sides belong to different rooms AND the edge is not in the openings list

MapLayout API

  • get_walls() -> Array — computes all wall edge segments from room and opening data
  • is_passable(from: Vector2i, to: Vector2i) -> bool — returns whether movement is allowed between two adjacent tiles (false if wall, false if either tile is void)
  • is_tile_valid(tile: Vector2i) -> bool — returns whether a tile belongs to any room
  • get_room_at(tile: Vector2i) -> Room — returns the room a tile belongs to, or null

Integration with Movement

  • CombatMap holds a reference to the MapLayout
  • Before allowing a unit to move from tile A to tile B, the movement system calls MapLayout.is_passable(a, b)
  • If there is a wall on that edge (and no opening), movement is blocked
  • Tiles not belonging to any room are impassable — is_tile_valid() returns false for void tiles
  • Future pathfinding uses the same is_passable check as its neighbor filter

Wall Rendering

  • CombatMap iterates over computed wall edges from MapLayout.get_walls()
  • Each wall edge is defined by two adjacent tile coordinates — the wall is drawn on the border between them
  • Openings have no wall drawn
  • Initial implementation uses simple Line2D segments or sprite strips on tile edges
  • Can be replaced with proper art assets later

Design Decisions

  • Rooms are the primary data, walls are derived — single source of truth, no sync issues
  • Openings are explicit — all room boundaries are walls by default; doorways are punched explicitly as tile-coordinate pairs
  • Openings are always bidirectional
  • No room metadata beyond ID — tile ownership stays tile-level per existing system
  • Void tiles are impassable — no hallway/corridor concept; all walkable tiles belong to a room
  • Room data is independent of rendering — clean for future map editor serialization