Files
Code_of_Conquest/api/app/models/origins.py
2025-11-24 23:10:55 -06:00

149 lines
4.4 KiB
Python

"""
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})"