# Data Model All identifiers and code are in English. ## Enums ```python class Gender(IntEnum): MALE = 0 FEMALE = 1 NONBINARY = 2 class PartnerType(IntEnum): MARRIAGE = 0 AFFAIR = 1 POLITICAL = 2 ILLEGITIMATE = 3 class StageType(IntEnum): CHILD = 0 TEEN = 1 YOUNG_ADULT = 2 ADULT = 3 SENIOR = 4 class Event(IntEnum): # Category 1 — Death DEATH_ILLNESS = 10 DEATH_ACCIDENT = 11 DEATH_COMBAT = 12 DEATH_OLD_AGE = 13 DEATH_CHILDBIRTH = 14 # mother dies during birth # Category 2 — Partnership PARTNER_MARRIAGE = 20 PARTNER_AFFAIR = 21 PARTNER_ENGAGEMENT = 22 PARTNER_POLITICAL = 23 PARTNER_CHILDHOOD_PROMISE = 24 # Category 3 — Offspring CHILD_BORN = 30 CHILD_TWINS = 31 CHILD_TRIPLETS = 32 CHILD_STILLBORN = 33 CHILD_ADOPT = 34 # only path to offspring for NONBINARY; from YOUNG_ADULT onwards # Category 4 — Daily Life DAILY_FRIENDSHIP = 40 DAILY_FAMILY = 41 DAILY_TEMP_CHAR = 42 # Category 5 — Travel TRAVEL_NEAR = 50 TRAVEL_FAR = 51 TRAVEL_PILGRIMAGE = 52 # Category 6 — Learning LEARN_APPRENTICESHIP = 60 LEARN_MENTOR = 61 LEARN_SELF = 62 # Category 7 — Conflict (personal) CONFLICT_PERSONAL = 70 CONFLICT_FIGHT = 71 CONFLICT_FEUD = 72 # Category 8 — Discovery DISCOVER_OBJECT = 80 DISCOVER_SPELL = 81 DISCOVER_WONDER = 82 DISCOVER_KNOWLEDGE = 83 # Category 9 — Local Conflict LOCAL_REBELLION = 90 LOCAL_PLAGUE = 91 LOCAL_DISASTER = 92 LOCAL_CRISIS = 93 # Category 10 — Intrigue INTRIGUE_POLITICAL = 100 INTRIGUE_EXILE = 101 INTRIGUE_CONSPIRACY = 102 # Category 11 — Illness / Injury ILLNESS_WEAK = 110 ILLNESS_SEVERE = 111 ILLNESS_CHRONIC = 112 INJURY_ACCIDENT = 113 INJURY_COMBAT = 114 ``` `event_type // 10` → category, `event_type % 10` → subtype within category. ## Person ```python Person { id: str name: str gender: Gender birth_year: int # absolute, set when person is created via parent event death_year: int | None # birth_year + age_at_death alive: bool appearance: dict profession: str | None # set by a LEARN event home: str is_ancestor: bool # True only for Person 1 parent_id: str | None # previous active node; None = joined from outside generation: int partners: PartnerEntry[] events: str[] # event IDs in chronological order acquaintances: str[] # IDs from person_pool only (not family tree) stages: Stage[] } PartnerEntry { person_id: str type: PartnerType children_ids: str[] # all children from this union } ``` ## Stage ```python Stage { type: StageType age: { from: int, to: int } # relative to person events: str[] # event IDs } ``` ### Stage Age Ranges | Stage | Age | |-------------|----------------| | Child | 0–12 | | Teen | 12–16 | | Young Adult | 16–32 | | Adult | 32–50 | | Senior | 50–X (LLM decides) | ## EventEntry ```python EventEntry { id: str type: Event # e.g. Event.ILLNESS_SEVERE age: int # age of person at time of event # absolute_year: @property -> person.birth_year + self.age location: str | None # None = takes place at person.home location_is_temp: bool # True = travel destination, False = known location participants: str[] # person_ids or pool_ids result: dict # predetermined simulation outcome context: dict # extra info passed to LLM prompt follow_bonus: Event[] # event types made more likely after this event # e.g. after TRAVEL_FAR -> [DISCOVER_OBJECT, DISCOVER_WONDER] } ``` ## FamilyTree & person_pool ```python FamilyTree { persons: dict[str, Person] # all family tree persons person_pool: dict[str, Person] # temporary chars with no tree membership # e.g. random villager # distant cousin -> lives in persons, not here world: World current_generation: int active_node: str # person_id of currently narrated person } World { start_year: int # randomly generated, max 4 digits, no calendar system stated name: str epoch_flavor: str # setting keywords passed to LLM } ```