from __future__ import annotations from dataclasses import dataclass, field from typing import Dict @dataclass class AbilityScores: STR: int = 0 DEX: int = 0 INT: int = 0 WIS: int = 0 CON: int = 0 LUK: int = 0 CHA: int = 0 @dataclass(frozen=True) class Race: id: str name: str description: str alignment: int = 0 ability_scores: AbilityScores = field(default_factory=AbilityScores) tags: list[str] = field(default_factory=list) # e.g., {"playable"}, {"hostile","goblinoid"} @property def is_playable(self) -> bool: return "playable" in self.tags @staticmethod def from_yaml(data: Dict[str, object]) -> "Race": # basic validation with helpful errors required = ["id", "name", "description", "alignment", "ability_mods"] missing = [k for k in required if k not in data] if missing: raise ValueError(f"Spell missing required fields: {missing}") mods = data.get("ability_mods", {}) or {} abs = AbilityScores( STR=int(mods.get("STR", 0)), DEX=int(mods.get("DEX", 0)), INT=int(mods.get("INT", 0)), WIS=int(mods.get("WIS", 0)), CON=int(mods.get("CON", 0)), LUK=int(mods.get("LUK", 0)), CHA=int(mods.get("CHA", 0)), ) tags = list(data.get("tags", [])) return Race( id=str(data["id"]), name=str(data["name"]), description=str(data["description"]), ability_scores=abs, tags=tags )