add weather and time-of-day system
This commit is contained in:
parent
a30e762498
commit
dd999a89eb
|
@ -113,7 +113,7 @@ python3 -m adventure.main \
|
||||||
--discord=true \
|
--discord=true \
|
||||||
--server=true \
|
--server=true \
|
||||||
--rooms 3 \
|
--rooms 3 \
|
||||||
--steps 30 \
|
--turns 30 \
|
||||||
--optional-actions=true \
|
--optional-actions=true \
|
||||||
--actions adventure.sim_systems:init_actions \
|
--actions adventure.sim_systems:init_actions \
|
||||||
--systems adventure.sim_systems:init_logic
|
--systems adventure.sim_systems:init_logic
|
||||||
|
|
|
@ -29,6 +29,7 @@ logger = getLogger(__name__)
|
||||||
QUEST_SYSTEM = "quest"
|
QUEST_SYSTEM = "quest"
|
||||||
|
|
||||||
|
|
||||||
|
# region models
|
||||||
@dataclass
|
@dataclass
|
||||||
class QuestGoalContains:
|
class QuestGoalContains:
|
||||||
"""
|
"""
|
||||||
|
@ -82,7 +83,47 @@ class QuestData:
|
||||||
completed: Dict[str, List[Quest]]
|
completed: Dict[str, List[Quest]]
|
||||||
|
|
||||||
|
|
||||||
# region quest completion
|
# endregion
|
||||||
|
|
||||||
|
|
||||||
|
# region state helpers
|
||||||
|
def complete_quest(quests: QuestData, character: Character, quest: Quest) -> None:
|
||||||
|
"""
|
||||||
|
Complete the given quest for the given character.
|
||||||
|
"""
|
||||||
|
if quest in quests.available.get(character.name, []):
|
||||||
|
quests.available[character.name].remove(quest)
|
||||||
|
|
||||||
|
if quest == quests.active.get(character.name, None):
|
||||||
|
del quests.active[character.name]
|
||||||
|
|
||||||
|
if character.name not in quests.completed:
|
||||||
|
quests.completed[character.name] = []
|
||||||
|
|
||||||
|
quests.completed[character.name].append(quest)
|
||||||
|
|
||||||
|
|
||||||
|
def get_quests_for_character(quests: QuestData, character: Character) -> List[Quest]:
|
||||||
|
"""
|
||||||
|
Get all quests for the given character.
|
||||||
|
"""
|
||||||
|
return quests.available.get(character.name, [])
|
||||||
|
|
||||||
|
|
||||||
|
def set_active_quest(quests: QuestData, character: Character, quest: Quest) -> None:
|
||||||
|
"""
|
||||||
|
Set the active quest for the given character.
|
||||||
|
"""
|
||||||
|
quests.active[character.name] = quest
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_quest(quests: QuestData, character: Character) -> Quest | None:
|
||||||
|
"""
|
||||||
|
Get the active quest for the given character.
|
||||||
|
"""
|
||||||
|
return quests.active.get(character.name)
|
||||||
|
|
||||||
|
|
||||||
def is_quest_complete(world: World, quest: Quest) -> bool:
|
def is_quest_complete(world: World, quest: Quest) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if the given quest is complete.
|
Check if the given quest is complete.
|
||||||
|
@ -121,47 +162,7 @@ def is_quest_complete(world: World, quest: Quest) -> bool:
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
|
|
||||||
# region state management
|
# region game system callbacks
|
||||||
def get_quests_for_character(quests: QuestData, character: Character) -> List[Quest]:
|
|
||||||
"""
|
|
||||||
Get all quests for the given character.
|
|
||||||
"""
|
|
||||||
return quests.available.get(character.name, [])
|
|
||||||
|
|
||||||
|
|
||||||
def set_active_quest(quests: QuestData, character: Character, quest: Quest) -> None:
|
|
||||||
"""
|
|
||||||
Set the active quest for the given character.
|
|
||||||
"""
|
|
||||||
quests.active[character.name] = quest
|
|
||||||
|
|
||||||
|
|
||||||
def get_active_quest(quests: QuestData, character: Character) -> Quest | None:
|
|
||||||
"""
|
|
||||||
Get the active quest for the given character.
|
|
||||||
"""
|
|
||||||
return quests.active.get(character.name)
|
|
||||||
|
|
||||||
|
|
||||||
def complete_quest(quests: QuestData, character: Character, quest: Quest) -> None:
|
|
||||||
"""
|
|
||||||
Complete the given quest for the given character.
|
|
||||||
"""
|
|
||||||
if quest in quests.available.get(character.name, []):
|
|
||||||
quests.available[character.name].remove(quest)
|
|
||||||
|
|
||||||
if quest == quests.active.get(character.name, None):
|
|
||||||
del quests.active[character.name]
|
|
||||||
|
|
||||||
if character.name not in quests.completed:
|
|
||||||
quests.completed[character.name] = []
|
|
||||||
|
|
||||||
quests.completed[character.name].append(quest)
|
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
|
||||||
|
|
||||||
|
|
||||||
def initialize_quests(world: World) -> QuestData:
|
def initialize_quests(world: World) -> QuestData:
|
||||||
"""
|
"""
|
||||||
Initialize quests for the world.
|
Initialize quests for the world.
|
||||||
|
@ -214,6 +215,10 @@ def simulate_quests(world: World, turn: int, data: QuestData | None = None) -> N
|
||||||
complete_quest(quests, character, active_quest)
|
complete_quest(quests, character, active_quest)
|
||||||
|
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
|
||||||
|
# region I/O
|
||||||
def load_quest_data(file: str) -> QuestData:
|
def load_quest_data(file: str) -> QuestData:
|
||||||
logger.info(f"loading quest data from {file}")
|
logger.info(f"loading quest data from {file}")
|
||||||
return load_system_data(QuestData, file)
|
return load_system_data(QuestData, file)
|
||||||
|
@ -224,6 +229,9 @@ def save_quest_data(file: str, data: QuestData) -> None:
|
||||||
return save_system_data(QuestData, file, data)
|
return save_system_data(QuestData, file, data)
|
||||||
|
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
|
||||||
def init() -> List[GameSystem]:
|
def init() -> List[GameSystem]:
|
||||||
return [
|
return [
|
||||||
GameSystem(
|
GameSystem(
|
||||||
|
|
|
@ -3,12 +3,6 @@ from .language_actions import action_read
|
||||||
from .magic_actions import action_cast
|
from .magic_actions import action_cast
|
||||||
from .movement_actions import action_climb
|
from .movement_actions import action_climb
|
||||||
|
|
||||||
from taleweave.systems.logic import load_logic
|
|
||||||
|
|
||||||
LOGIC_FILES = [
|
|
||||||
"./adventure/systems/rpg/weather_logic.yaml",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def init_actions():
|
def init_actions():
|
||||||
return [
|
return [
|
||||||
|
@ -24,4 +18,4 @@ def init_actions():
|
||||||
|
|
||||||
|
|
||||||
def init_logic():
|
def init_logic():
|
||||||
return [load_logic(filename) for filename in LOGIC_FILES]
|
return []
|
||||||
|
|
|
@ -5,11 +5,11 @@ from .sleeping_actions import action_sleep
|
||||||
from taleweave.systems.logic import load_logic
|
from taleweave.systems.logic import load_logic
|
||||||
|
|
||||||
LOGIC_FILES = [
|
LOGIC_FILES = [
|
||||||
"./adventure/systems/sim/environment_logic.yaml",
|
"./taleweave/systems/sim/environment_logic.yaml",
|
||||||
"./adventure/systems/sim/hunger_logic.yaml",
|
"./taleweave/systems/sim/hunger_logic.yaml",
|
||||||
"./adventure/systems/sim/hygiene_logic.yaml",
|
"./taleweave/systems/sim/hygiene_logic.yaml",
|
||||||
"./adventure/systems/sim/mood_logic.yaml",
|
"./taleweave/systems/sim/mood_logic.yaml",
|
||||||
"./adventure/systems/sim/sleeping_logic.yaml",
|
"./taleweave/systems/sim/sleeping_logic.yaml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
from typing import List
|
||||||
|
from taleweave.models.base import dataclass
|
||||||
|
from taleweave.models.entity import World
|
||||||
|
from taleweave.systems.logic import load_logic
|
||||||
|
from taleweave.game_system import GameSystem
|
||||||
|
|
||||||
|
LOGIC_FILES = [
|
||||||
|
"./taleweave/systems/weather/weather_logic.yaml",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TimeOfDay:
|
||||||
|
name: str
|
||||||
|
start: int
|
||||||
|
end: int
|
||||||
|
|
||||||
|
|
||||||
|
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 % TURNS_PER_DAY
|
||||||
|
for time in TIMES_OF_DAY:
|
||||||
|
if time.start <= hour <= time.end:
|
||||||
|
return time
|
||||||
|
return TIMES_OF_DAY[0]
|
||||||
|
|
||||||
|
|
||||||
|
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_systems():
|
||||||
|
return [GameSystem("weather", simulate=simulate_weather)]
|
||||||
|
|
||||||
|
|
||||||
|
def init_logic():
|
||||||
|
return [load_logic(filename) for filename in LOGIC_FILES]
|
|
@ -4,51 +4,60 @@ rules:
|
||||||
match:
|
match:
|
||||||
type: room
|
type: room
|
||||||
outdoor: true
|
outdoor: true
|
||||||
weather: sunny
|
weather: clear
|
||||||
chance: 0.1
|
chance: 0.1
|
||||||
set:
|
set:
|
||||||
weather: cloudy
|
weather: clouds
|
||||||
|
|
||||||
- group: weather
|
- group: weather
|
||||||
match:
|
match:
|
||||||
type: room
|
type: room
|
||||||
outdoor: true
|
outdoor: true
|
||||||
weather: cloudy
|
weather: clouds
|
||||||
chance: 0.1
|
chance: 0.1
|
||||||
set:
|
set:
|
||||||
weather: rainy
|
weather: rain
|
||||||
|
|
||||||
- group: weather
|
- group: weather
|
||||||
match:
|
match:
|
||||||
type: room
|
type: room
|
||||||
outdoor: true
|
outdoor: true
|
||||||
weather: rainy
|
weather: rain
|
||||||
chance: 0.1
|
chance: 0.1
|
||||||
set:
|
set:
|
||||||
weather: sunny
|
weather: clear
|
||||||
|
|
||||||
- group: weather
|
- group: weather
|
||||||
match:
|
match:
|
||||||
type: room
|
type: room
|
||||||
outdoor: true
|
outdoor: true
|
||||||
weather: cloudy
|
weather: clouds
|
||||||
chance: 0.1
|
chance: 0.1
|
||||||
set:
|
set:
|
||||||
weather: sunny
|
weather: clear
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
- match:
|
- match:
|
||||||
type: room
|
type: room
|
||||||
weather: sunny
|
weather: clear
|
||||||
|
rule: |
|
||||||
|
"time" not in attributes or attributes&.time in ["morning", "day"]
|
||||||
backstory: The sun is shining brightly.
|
backstory: The sun is shining brightly.
|
||||||
description: The sun is shining brightly.
|
description: The sun is shining brightly.
|
||||||
- match:
|
- match:
|
||||||
type: room
|
type: room
|
||||||
weather: cloudy
|
weather: clear
|
||||||
|
rule: |
|
||||||
|
"time" in attributes and attributes&.time in ["evening", "night"]
|
||||||
|
backstory: The moon is shining brightly.
|
||||||
|
description: The moon is shining brightly.
|
||||||
|
- match:
|
||||||
|
type: room
|
||||||
|
weather: clouds
|
||||||
backstory: The sky is overcast.
|
backstory: The sky is overcast.
|
||||||
description: The sky is overcast.
|
description: The sky is overcast.
|
||||||
- match:
|
- match:
|
||||||
type: room
|
type: room
|
||||||
weather: rainy
|
weather: rain
|
||||||
backstory: Rain is falling from the sky.
|
backstory: Rain is falling from the cloudy sky.
|
||||||
description: Rain is falling from the sky.
|
description: Rain is falling from the cloudy sky.
|
Loading…
Reference in New Issue