"""Components for representing Characters.
"""
from __future__ import annotations
import enum
from typing import Any
from neighborly.components.traits import Trait
from neighborly.datetime import SimDate
from neighborly.ecs import Component, GameObject
[docs]class LifeStage(enum.IntEnum):
"""An enumeration of all the various life stages aging characters pass through."""
CHILD = 0
ADOLESCENT = 1
YOUNG_ADULT = 2
ADULT = 3
SENIOR = 4
[docs]class Sex(enum.IntEnum):
"""The characters current sex."""
MALE = enum.auto()
FEMALE = enum.auto()
NOT_SPECIFIED = enum.auto()
[docs]class Species(Component):
"""Configuration information about a character's species."""
__slots__ = (
"adolescent_age",
"young_adult_age",
"adult_age",
"senior_age",
"lifespan",
"can_physically_age",
)
def __init__(
self,
adolescent_age: int,
young_adult_age: int,
adult_age: int,
senior_age: int,
lifespan: int,
can_physically_age: bool,
) -> None:
super().__init__()
self.adolescent_age = adolescent_age
self.young_adult_age = young_adult_age
self.adult_age = adult_age
self.senior_age = senior_age
self.lifespan = lifespan
self.can_physically_age = can_physically_age
[docs] def to_dict(self) -> dict[str, Any]:
return {}
[docs]class Character(Component):
"""A character within the story world."""
__slots__ = ("_first_name", "_last_name", "_sex", "_age", "_life_stage", "species")
_first_name: str
"""The character's first name."""
_last_name: str
"""The character's last name or family name."""
_age: float
"""the character's current age."""
_sex: Sex
"""The physical sex of the character."""
_life_stage: LifeStage
"""The character's current life stage."""
species: GameObject
"""The character's species"""
def __init__(
self, first_name: str, last_name: str, sex: Sex, species: GameObject
) -> None:
super().__init__()
self._first_name = first_name
self._last_name = last_name
self._sex = sex
self._age = 0
self._life_stage = LifeStage.CHILD
self.species = species
@property
def first_name(self) -> str:
"""The character's first name."""
return self._first_name
@first_name.setter
def first_name(self, value: str) -> None:
"""Set the character's first name."""
self._first_name = value
self.gameobject.name = self.full_name
@property
def last_name(self) -> str:
"""The character's last name."""
return self._last_name
@last_name.setter
def last_name(self, value: str) -> None:
"""Set the character's last name."""
self._last_name = value
self.gameobject.name = self.full_name
@property
def full_name(self) -> str:
"""The combined full name of the character."""
return f"{self._first_name} {self._last_name}"
@property
def age(self) -> float:
"""Get the character's age."""
return self._age
@age.setter
def age(self, value: float) -> None:
"""Set the character's age."""
self._age = value
@property
def sex(self) -> Sex:
"""Get the characters sex."""
return self._sex
@property
def life_stage(self) -> LifeStage:
"""Get the character's life stage."""
return self._life_stage
@life_stage.setter
def life_stage(self, value: LifeStage) -> None:
"""Set the character's life stage."""
self._life_stage = value
[docs] def to_dict(self) -> dict[str, Any]:
return {
"first_name": self._first_name,
"last_name": self._last_name,
"sex": self.sex.name,
"age": int(self.age),
"life_stage": self.life_stage.name,
"species": self.species.get_component(Trait).definition_id,
}
def __repr__(self) -> str:
return (
f"{self.__class__.__name__}(name={self.full_name}, sex={self.sex}, "
f"age={self.age}({self.life_stage}), species={self.species.name})"
)
def __str__(self) -> str:
return self.full_name
[docs]class Pregnant(Component):
"""Tags a character as pregnant and tracks relevant information."""
__slots__ = "partner", "due_date"
partner: GameObject
"""The GameObject ID of the character that impregnated this character."""
due_date: SimDate
"""The date the baby is due."""
def __init__(self, partner: GameObject, due_date: SimDate) -> None:
super().__init__()
self.partner = partner
self.due_date = due_date.copy()
def __str__(self) -> str:
return f"{type(self).__name__}(partner={self.partner.name})"
def __repr__(self) -> str:
return f"{type(self).__name__}(partner={self.partner.name})"
[docs] def to_dict(self) -> dict[str, Any]:
return {
**super().to_dict(),
"partner": self.partner.uid,
"due_date": str(self.due_date),
}