""" Origin data models - character backstory and starting conditions. Origins are saved to the character and referenced by the AI DM throughout the game to create personalized narrative experiences, quest hooks, and story-driven interactions. """ from dataclasses import dataclass, field from typing import Dict, List, Any @dataclass class StartingLocation: """ Represents where a character begins their journey. Attributes: id: Unique location identifier name: Display name of the location region: Larger geographical area this location belongs to description: Brief description of the location """ id: str name: str region: str description: str def to_dict(self) -> Dict[str, Any]: """Serialize to dictionary.""" return { "id": self.id, "name": self.name, "region": self.region, "description": self.description, } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'StartingLocation': """Deserialize from dictionary.""" return cls( id=data["id"], name=data["name"], region=data["region"], description=data["description"], ) @dataclass class StartingBonus: """ Represents mechanical benefits from an origin choice. Attributes: trait: Name of the trait/ability granted description: What the trait represents narratively effect: Mechanical game effect (stat bonuses, special abilities, etc.) """ trait: str description: str effect: str def to_dict(self) -> Dict[str, Any]: """Serialize to dictionary.""" return { "trait": self.trait, "description": self.description, "effect": self.effect, } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'StartingBonus': """Deserialize from dictionary.""" return cls( trait=data["trait"], description=data["description"], effect=data["effect"], ) @dataclass class Origin: """ Represents a character's backstory and starting conditions. Origins are permanent character attributes that the AI DM uses to create personalized narratives, generate relevant quest hooks, and tailor NPC interactions throughout the game. Attributes: id: Unique origin identifier (e.g., "soul_revenant") name: Display name (e.g., "Soul Revenant") description: Full backstory text that explains the origin starting_location: Where the character begins their journey narrative_hooks: List of story elements the AI can reference starting_bonus: Mechanical benefits from this origin """ id: str name: str description: str starting_location: StartingLocation narrative_hooks: List[str] = field(default_factory=list) starting_bonus: StartingBonus = None def to_dict(self) -> Dict[str, Any]: """ Serialize origin to dictionary for JSON storage. Returns: Dictionary containing all origin data """ return { "id": self.id, "name": self.name, "description": self.description, "starting_location": self.starting_location.to_dict(), "narrative_hooks": self.narrative_hooks, "starting_bonus": self.starting_bonus.to_dict() if self.starting_bonus else None, } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'Origin': """ Deserialize origin from dictionary. Args: data: Dictionary containing origin data Returns: Origin instance """ starting_location = StartingLocation.from_dict(data["starting_location"]) starting_bonus = None if data.get("starting_bonus"): starting_bonus = StartingBonus.from_dict(data["starting_bonus"]) return cls( id=data["id"], name=data["name"], description=data["description"], starting_location=starting_location, narrative_hooks=data.get("narrative_hooks", []), starting_bonus=starting_bonus, ) def __repr__(self) -> str: """String representation of the origin.""" return f"Origin({self.name}, starts at {self.starting_location.name})"