103 lines
2.8 KiB
Python
103 lines
2.8 KiB
Python
from functools import partial
|
|
from logging import getLogger
|
|
from typing import List
|
|
|
|
from packit.agent import Agent
|
|
from packit.loops import loop_retry
|
|
from packit.results import enum_result
|
|
|
|
from taleweave.context import get_dungeon_master
|
|
from taleweave.game_system import GameSystem
|
|
from taleweave.models.base import dataclass
|
|
from taleweave.models.entity import Room, World, WorldEntity
|
|
from taleweave.systems.generic.logic import load_logic
|
|
from taleweave.utils.string import or_list
|
|
|
|
logger = getLogger(__name__)
|
|
|
|
|
|
LOGIC_FILES = [
|
|
"./taleweave/systems/environment/weather/logic.yaml",
|
|
]
|
|
|
|
|
|
@dataclass
|
|
class TimeOfDay:
|
|
name: str
|
|
start: int
|
|
end: int
|
|
|
|
|
|
GAME_START_HOUR = 8
|
|
TURNS_PER_DAY = 24
|
|
|
|
TIMES_OF_DAY: List[TimeOfDay] = [
|
|
TimeOfDay("night", 0, 4),
|
|
TimeOfDay("morning", 5, 7),
|
|
TimeOfDay("day", 8, 18),
|
|
TimeOfDay("evening", 20, 22),
|
|
TimeOfDay("night", 23, 24),
|
|
]
|
|
|
|
|
|
def get_time_of_day(turn: int) -> TimeOfDay:
|
|
hour = (turn + GAME_START_HOUR) % TURNS_PER_DAY
|
|
for time in TIMES_OF_DAY:
|
|
if time.start <= hour <= time.end:
|
|
return time
|
|
return TIMES_OF_DAY[0]
|
|
|
|
|
|
def initialize_weather(world: World):
|
|
time_of_day = get_time_of_day(0)
|
|
for room in world.rooms:
|
|
logger.info(f"initializing weather for {room.name}")
|
|
room.attributes["time"] = time_of_day.name
|
|
|
|
if "environment" not in room.attributes:
|
|
dungeon_master = get_dungeon_master()
|
|
generate_room_weather(dungeon_master, world.theme, room)
|
|
|
|
|
|
def generate_room_weather(agent: Agent, theme: str, entity: Room) -> None:
|
|
environment_options = ["indoor", "outdoor"]
|
|
environment_result = partial(enum_result, enum=environment_options)
|
|
environment = loop_retry(
|
|
agent,
|
|
"Is this room indoors or outdoors?"
|
|
"Reply with a single word: {environment_list}.\n\n"
|
|
"{description}",
|
|
context={
|
|
"environment_list": or_list(environment_options),
|
|
"description": entity.description,
|
|
},
|
|
result_parser=environment_result,
|
|
)
|
|
entity.attributes["environment"] = environment
|
|
logger.info(f"generated environment for {entity.name}: {environment}")
|
|
|
|
|
|
def generate_weather(agent: Agent, world: World, entity: WorldEntity) -> None:
|
|
if isinstance(entity, Room):
|
|
if "environment" not in entity.attributes:
|
|
generate_room_weather(agent, world.theme, entity)
|
|
|
|
|
|
def simulate_weather(world: World, turn: int, data: None = None):
|
|
time_of_day = get_time_of_day(turn)
|
|
for room in world.rooms:
|
|
room.attributes["time"] = time_of_day.name
|
|
|
|
|
|
def init():
|
|
logic_systems = [load_logic(filename) for filename in LOGIC_FILES]
|
|
return [
|
|
*logic_systems,
|
|
GameSystem(
|
|
"weather",
|
|
generate=generate_weather,
|
|
initialize=initialize_weather,
|
|
simulate=simulate_weather,
|
|
),
|
|
]
|