from __future__ import annotations from dataclasses import dataclass, field TILE_LAYERS = ("subfloor", "flooring", "room", "roof") @dataclass(frozen=True) class TileLayerDef: id: str layer: str texture: str | None = None color: tuple[int, int, int] = (255, 0, 255) walkable: bool = True blocks_los: bool = False deconstruct_item_id: str | None = None # item yielded by a careful (right-click) deconstruction is_helm: bool = False # standing here lets a character steer the embedded map it's part of staircase_direction: str | None = None # "up" or "down" - see Tile.staircase_direction extra: dict = field(default_factory=dict) @dataclass class TileLayerInstance: """A layer's actual per-cell state (as opposed to its static def).""" def_id: str integrity: float = 100.0 @dataclass class Tile: subfloor: TileLayerInstance | None = None flooring: TileLayerInstance | None = None room: TileLayerInstance | None = None roof: TileLayerInstance | None = None def get_layer(self, layer: str) -> TileLayerInstance | None: return getattr(self, layer) def set_layer(self, layer: str, instance: TileLayerInstance | None) -> None: setattr(self, layer, instance) def layer_id(self, layer: str) -> str | None: instance = self.get_layer(layer) return instance.def_id if instance is not None else None def is_walkable(self, registry) -> bool: for layer in ("room", "flooring"): layer_def = registry.get_tile_layer_def(layer, self.layer_id(layer)) if layer_def is not None and not layer_def.walkable: return False return True def staircase_direction(self, registry) -> str | None: """'up'/'down' if either layer here is a staircase/ladder, else None.""" for layer in ("room", "flooring"): layer_def = registry.get_tile_layer_def(layer, self.layer_id(layer)) if layer_def is not None and layer_def.staircase_direction is not None: return layer_def.staircase_direction return None