1
0
Fork 0

use action context managers, sort modules

This commit is contained in:
Sean Sube 2024-05-18 17:29:40 -05:00
parent 03c324ef60
commit 36f29dcffa
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
21 changed files with 478 additions and 452 deletions

View File

@ -56,4 +56,4 @@ lint-fix:
style: lint-fix style: lint-fix
typecheck: typecheck:
mypy feedme mypy adventure

0
adventure/__init__.py Normal file
View File

View File

@ -3,8 +3,13 @@ from logging import getLogger
from packit.utils import could_be_json from packit.utils import could_be_json
from adventure.context import broadcast, get_actor_agent_for_name, get_current_context from adventure.context import (
from adventure.search import ( action_context,
broadcast,
get_actor_agent_for_name,
world_context,
)
from adventure.utils.search import (
find_actor_in_room, find_actor_in_room,
find_item_in_actor, find_item_in_actor,
find_item_in_room, find_item_in_room,
@ -22,7 +27,8 @@ def action_look(target: str) -> str:
Args: Args:
target: The name of the target to look at. target: The name of the target to look at.
""" """
_, action_room, action_actor = get_current_context()
with action_context() as (action_room, action_actor):
broadcast(f"{action_actor.name} looks at {target}") broadcast(f"{action_actor.name} looks at {target}")
if target.lower() == action_room.name.lower(): if target.lower() == action_room.name.lower():
@ -60,8 +66,8 @@ def action_move(direction: str) -> str:
Args: Args:
direction: The direction to move in. direction: The direction to move in.
""" """
action_world, action_room, action_actor = get_current_context()
with world_context() as (action_world, action_room, action_actor):
destination_name = action_room.portals.get(direction.lower()) destination_name = action_room.portals.get(direction.lower())
if not destination_name: if not destination_name:
return f"You cannot move {direction} from here." return f"You cannot move {direction} from here."
@ -84,16 +90,15 @@ def action_take(item_name: str) -> str:
Args: Args:
item_name: The name of the item to take. item_name: The name of the item to take.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
item = find_item_in_room(action_room, item_name) item = find_item_in_room(action_room, item_name)
if item: if not item:
return "The {item_name} item is not in the room."
broadcast(f"{action_actor.name} takes the {item_name} item") broadcast(f"{action_actor.name} takes the {item_name} item")
action_room.items.remove(item) action_room.items.remove(item)
action_actor.items.append(item) action_actor.items.append(item)
return "You take the {item_name} item and put it in your inventory." return "You take the {item_name} item and put it in your inventory."
else:
return "The {item_name} item is not in the room."
def action_ask(character: str, question: str) -> str: def action_ask(character: str, question: str) -> str:
@ -105,8 +110,7 @@ def action_ask(character: str, question: str) -> str:
question: The question to ask them. question: The question to ask them.
""" """
# capture references to the current actor and room, because they will be overwritten # capture references to the current actor and room, because they will be overwritten
_world, _room, action_actor = get_current_context() with action_context() as (_, action_actor):
# sanity checks # sanity checks
question_actor, question_agent = get_actor_agent_for_name(character) question_actor, question_agent = get_actor_agent_for_name(character)
if question_actor == action_actor: if question_actor == action_actor:
@ -143,8 +147,8 @@ def action_tell(character: str, message: str) -> str:
message: The message to tell them. message: The message to tell them.
""" """
# capture references to the current actor and room, because they will be overwritten # capture references to the current actor and room, because they will be overwritten
_world, _room, action_actor = get_current_context()
with action_context() as (_, action_actor):
# sanity checks # sanity checks
question_actor, question_agent = get_actor_agent_for_name(character) question_actor, question_agent = get_actor_agent_for_name(character)
if question_actor == action_actor: if question_actor == action_actor:
@ -180,8 +184,7 @@ def action_give(character: str, item_name: str) -> str:
character: The name of the character to give the item to. character: The name of the character to give the item to.
item_name: The name of the item to give. item_name: The name of the item to give.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
destination_actor = find_actor_in_room(action_room, character) destination_actor = find_actor_in_room(action_room, character)
if not destination_actor: if not destination_actor:
return f"The {character} character is not in the room." return f"The {character} character is not in the room."
@ -205,8 +208,7 @@ def action_drop(item_name: str) -> str:
item_name: The name of the item to drop. item_name: The name of the item to drop.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
item = find_item_in_actor(action_actor, item_name) item = find_item_in_actor(action_actor, item_name)
if not item: if not item:
return f"You do not have the {item_name} item in your inventory." return f"You do not have the {item_name} item in your inventory."

View File

@ -33,14 +33,14 @@ from adventure.player import (
remove_player, remove_player,
set_player, set_player,
) )
from adventure.render_comfy import render_event from adventure.render.comfy import render_event
logger = getLogger(__name__) logger = getLogger(__name__)
client = None client = None
bot_config: DiscordBotConfig = DEFAULT_CONFIG.bot.discord bot_config: DiscordBotConfig = DEFAULT_CONFIG.bot.discord
active_tasks = set() active_tasks = set()
event_messages: Dict[str, str | GameEvent] = {} event_messages: Dict[int, str | GameEvent] = {}
event_queue: Queue[GameEvent] = Queue() event_queue: Queue[GameEvent] = Queue()
@ -81,13 +81,13 @@ class AdventureClient(Client):
channel = message.channel channel = message.channel
user_name = author.name # include nick user_name = author.name # include nick
if message.content.startswith("!adventure"):
world = get_current_world() world = get_current_world()
if world: if world:
active_world = f"Active world: {world.name} (theme: {world.theme})" active_world = f"Active world: {world.name} (theme: {world.theme})"
else: else:
active_world = "No active world" active_world = "No active world"
if message.content.startswith("!adventure"):
await message.channel.send(f"Hello! Welcome to Adventure! {active_world}") await message.channel.send(f"Hello! Welcome to Adventure! {active_world}")
return return
@ -215,7 +215,14 @@ def stop_bot():
global client global client
if client: if client:
client.close() close_task = client.loop.create_task(client.close())
active_tasks.add(close_task)
def on_close_task_done(future):
logger.info("discord client closed")
active_tasks.discard(future)
close_task.add_done_callback(on_close_task_done)
client = None client = None
@ -299,7 +306,7 @@ async def broadcast_event(message: str | GameEvent):
event_messages[event_message.id] = message event_messages[event_message.id] = message
def embed_from_event(event: GameEvent) -> Embed: def embed_from_event(event: GameEvent) -> Embed | None:
if isinstance(event, GenerateEvent): if isinstance(event, GenerateEvent):
return embed_from_generate(event) return embed_from_generate(event)
elif isinstance(event, ResultEvent): elif isinstance(event, ResultEvent):

View File

@ -37,14 +37,21 @@ game_systems: List[GameSystem] = []
# TODO: where should this one go? # TODO: where should this one go?
actor_agents: Dict[str, Tuple[Actor, Agent]] = {} actor_agents: Dict[str, Tuple[Actor, Agent]] = {}
STRING_EVENT_TYPE = "message"
def get_event_name(event: GameEvent | Type[GameEvent]):
return f"event:{event.type}"
def broadcast(message: str | GameEvent): def broadcast(message: str | GameEvent):
if isinstance(message, GameEvent): if isinstance(message, GameEvent):
logger.debug(f"broadcasting {message.type}") event_name = get_event_name(message)
event_emitter.emit(message.type, message) logger.debug(f"broadcasting {event_name}")
event_emitter.emit(event_name, message)
else: else:
logger.warning("broadcasting a string message is deprecated") logger.warning("broadcasting a string message is deprecated")
event_emitter.emit("message", message) event_emitter.emit(STRING_EVENT_TYPE, message)
def is_union(type_: Type | UnionType): def is_union(type_: Type | UnionType):
@ -62,10 +69,13 @@ def subscribe(
return return
if event_type is str:
event_name = STRING_EVENT_TYPE
else:
event_name = get_event_name(event_type)
logger.debug(f"subscribing {callback.__name__} to {event_type}") logger.debug(f"subscribing {callback.__name__} to {event_type}")
event_emitter.on( event_emitter.on(event_name, callback)
event_type.type, callback
) # TODO: should this use str or __name__?
def has_dungeon_master(): def has_dungeon_master():
@ -74,11 +84,17 @@ def has_dungeon_master():
# region context manager # region context manager
@contextmanager @contextmanager
def with_action_context(): def action_context():
room, actor = get_action_context() room, actor = get_action_context()
yield room, actor yield room, actor
@contextmanager
def world_context():
world, room, actor = get_world_context()
yield world, room, actor
# endregion # endregion
@ -94,7 +110,7 @@ def get_action_context() -> Tuple[Room, Actor]:
return (current_room, current_actor) return (current_room, current_actor)
def get_current_context() -> Tuple[World, Room, Actor]: def get_world_context() -> Tuple[World, Room, Actor]:
if not current_world: if not current_world:
raise ValueError( raise ValueError(
"The current world must be set before calling action functions" "The current world must be set before calling action functions"

View File

@ -246,19 +246,19 @@ def main():
threads = [] threads = []
if args.render: if args.render:
from adventure.render_comfy import launch_render, render_generated from adventure.render.comfy import launch_render, render_generated
threads.extend(launch_render(config.render)) threads.extend(launch_render(config.render))
if args.render_generated: if args.render_generated:
subscribe(GenerateEvent, render_generated) subscribe(GenerateEvent, render_generated)
if args.discord: if args.discord:
from adventure.bot_discord import launch_bot from adventure.bot.discord import launch_bot
threads.extend(launch_bot(config.bot.discord)) threads.extend(launch_bot(config.bot.discord))
if args.server: if args.server:
from adventure.server_socket import launch_server, server_system from adventure.server.websocket import launch_server
threads.extend(launch_server(config.server.websocket)) threads.extend(launch_server(config.server.websocket))
@ -300,6 +300,8 @@ def main():
# make sure the server system runs after any updates # make sure the server system runs after any updates
if args.server: if args.server:
from adventure.server.websocket import server_system
extra_systems.append(GameSystem(simulate=server_system)) extra_systems.append(GameSystem(simulate=server_system))
# load or generate the world # load or generate the world

View File

@ -4,16 +4,17 @@ from typing import Callable, List
from packit.agent import Agent, agent_easy_connect from packit.agent import Agent, agent_easy_connect
from adventure.context import ( from adventure.context import (
action_context,
broadcast, broadcast,
get_agent_for_actor, get_agent_for_actor,
get_current_context,
get_dungeon_master, get_dungeon_master,
has_dungeon_master, has_dungeon_master,
set_dungeon_master, set_dungeon_master,
world_context,
) )
from adventure.generate import OPPOSITE_DIRECTIONS, generate_item, generate_room from adventure.generate import OPPOSITE_DIRECTIONS, generate_item, generate_room
from adventure.search import find_actor_in_room
from adventure.utils.effect import apply_effect from adventure.utils.effect import apply_effect
from adventure.utils.search import find_actor_in_room
from adventure.utils.world import describe_actor, describe_entity from adventure.utils.world import describe_actor, describe_entity
logger = getLogger(__name__) logger = getLogger(__name__)
@ -39,29 +40,26 @@ def action_explore(direction: str) -> str:
direction: The direction to explore: north, south, east, or west. direction: The direction to explore: north, south, east, or west.
""" """
current_world, current_room, current_actor = get_current_context() with world_context() as (action_world, action_room, action_actor):
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()
if not current_world: if direction in action_room.portals:
raise ValueError("No world found") dest_room = action_room.portals[direction]
if direction in current_room.portals:
dest_room = current_room.portals[direction]
return f"You cannot explore {direction} from here, that direction already leads to {dest_room}. Please use the move action to go there." return f"You cannot explore {direction} from here, that direction already leads to {dest_room}. Please use the move action to go there."
existing_rooms = [room.name for room in current_world.rooms] existing_rooms = [room.name for room in action_world.rooms]
try: try:
new_room = generate_room( new_room = generate_room(
dungeon_master, current_world.theme, existing_rooms=existing_rooms dungeon_master, action_world.theme, existing_rooms=existing_rooms
) )
current_world.rooms.append(new_room) action_world.rooms.append(new_room)
# link the rooms together # link the rooms together
current_room.portals[direction] = new_room.name action_room.portals[direction] = new_room.name
new_room.portals[OPPOSITE_DIRECTIONS[direction]] = current_room.name new_room.portals[OPPOSITE_DIRECTIONS[direction]] = action_room.name
broadcast( broadcast(
f"{current_actor.name} explores {direction} of {current_room.name} and finds a new room: {new_room.name}" f"{action_actor.name} explores {direction} of {action_room.name} and finds a new room: {new_room.name}"
) )
return f"You explore {direction} and find a new room: {new_room.name}" return f"You explore {direction} and find a new room: {new_room.name}"
except Exception: except Exception:
@ -74,11 +72,13 @@ def action_search(unused: bool) -> str:
Search the room for hidden items. Search the room for hidden items.
""" """
action_world, action_room, action_actor = get_current_context() with world_context() as (action_world, action_room, action_actor):
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()
if len(action_room.items) > 2: if len(action_room.items) > 2:
return "You find nothing hidden in the room. There is no room for more items." return (
"You find nothing hidden in the room. There is no room for more items."
)
existing_items = [item.name for item in action_room.items] existing_items = [item.name for item in action_room.items]
@ -108,7 +108,7 @@ def action_use(item: str, target: str) -> str:
item: The name of the item to use. item: The name of the item to use.
target: The name of the character to use the item on, or "self" to use the item on yourself. target: The name of the character to use the item on, or "self" to use the item on yourself.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()
action_item = next( action_item = next(
@ -167,7 +167,7 @@ def action_use(item: str, target: str) -> str:
# make sure both agents remember the outcome # make sure both agents remember the outcome
target_agent = get_agent_for_actor(target_actor) target_agent = get_agent_for_actor(target_actor)
if target_agent: if target_agent and target_agent.memory:
target_agent.memory.append(outcome) target_agent.memory.append(outcome)
return outcome return outcome

View File

@ -8,7 +8,7 @@ from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
from packit.agent import Agent from packit.agent import Agent
from packit.utils import could_be_json from packit.utils import could_be_json
from adventure.context import get_current_context from adventure.context import action_context
from adventure.models.event import PromptEvent from adventure.models.event import PromptEvent
logger = getLogger(__name__) logger = getLogger(__name__)
@ -183,7 +183,7 @@ class RemotePlayer(BasePlayer):
formatted_prompt = prompt.format(**kwargs) formatted_prompt = prompt.format(**kwargs)
self.memory.append(HumanMessage(content=formatted_prompt)) self.memory.append(HumanMessage(content=formatted_prompt))
_, current_room, current_actor = get_current_context() with action_context() as (current_room, current_actor):
prompt_event = PromptEvent( prompt_event = PromptEvent(
prompt=formatted_prompt, room=current_room, actor=current_actor prompt=formatted_prompt, room=current_room, actor=current_actor
) )

View File

@ -1,6 +1,6 @@
from random import randint from random import randint
from adventure.context import broadcast, get_current_context, get_dungeon_master from adventure.context import broadcast, get_dungeon_master, world_context
from adventure.generate import generate_item from adventure.generate import generate_item
from adventure.models.base import dataclass from adventure.models.base import dataclass
from adventure.models.entity import Item from adventure.models.entity import Item
@ -26,8 +26,7 @@ def action_craft(item_name: str) -> str:
Args: Args:
item_name: The name of the item to craft. item_name: The name of the item to craft.
""" """
action_world, _, action_actor = get_current_context() with world_context() as (action_world, _, action_actor):
if item_name not in recipes: if item_name not in recipes:
return f"There is no recipe to craft a {item_name}." return f"There is no recipe to craft a {item_name}."
@ -42,9 +41,13 @@ def action_craft(item_name: str) -> str:
inventory_items = {item.name for item in action_actor.items} inventory_items = {item.name for item in action_actor.items}
# Check for sufficient ingredients # Check for sufficient ingredients
missing_items = [item for item in recipe.ingredients if item not in inventory_items] missing_items = [
item for item in recipe.ingredients if item not in inventory_items
]
if missing_items: if missing_items:
return f"You are missing {' and '.join(missing_items)} to craft {item_name}." return (
f"You are missing {' and '.join(missing_items)} to craft {item_name}."
)
# Deduct the ingredients from inventory # Deduct the ingredients from inventory
for ingredient in recipe.ingredients: for ingredient in recipe.ingredients:

View File

@ -1,5 +1,5 @@
from adventure.context import broadcast, get_current_context from adventure.context import action_context, broadcast
from adventure.search import find_item_in_actor from adventure.utils.search import find_item_in_actor
def action_read(item_name: str) -> str: def action_read(item_name: str) -> str:
@ -9,8 +9,7 @@ def action_read(item_name: str) -> str:
Args: Args:
item_name: The name of the item to read. item_name: The name of the item to read.
""" """
_, _, action_actor = get_current_context() with action_context() as (_, action_actor):
item = find_item_in_actor(action_actor, item_name) item = find_item_in_actor(action_actor, item_name)
if not item: if not item:
return f"You do not have a {item_name} to read." return f"You do not have a {item_name} to read."
@ -18,5 +17,5 @@ def action_read(item_name: str) -> str:
if "text" in item.attributes: if "text" in item.attributes:
broadcast(f"{action_actor.name} reads {item_name}") broadcast(f"{action_actor.name} reads {item_name}")
return str(item.attributes["text"]) return str(item.attributes["text"])
else:
return f"The {item_name} has nothing to read." return f"The {item_name} has nothing to read."

View File

@ -1,7 +1,7 @@
from random import randint from random import randint
from adventure.context import broadcast, get_current_context, get_dungeon_master from adventure.context import action_context, broadcast, get_dungeon_master
from adventure.search import find_actor_in_room from adventure.utils.search import find_actor_in_room
def action_cast(spell: str, target: str) -> str: def action_cast(spell: str, target: str) -> str:
@ -12,8 +12,7 @@ def action_cast(spell: str, target: str) -> str:
spell: The name of the spell to cast. spell: The name of the spell to cast.
target: The target of the spell. target: The target of the spell.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
target_actor = find_actor_in_room(action_room, target) target_actor = find_actor_in_room(action_room, target)
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()

View File

@ -1,7 +1,7 @@
from random import randint from random import randint
from adventure.context import broadcast, get_current_context, get_dungeon_master from adventure.context import action_context, broadcast, get_dungeon_master
from adventure.search import find_item_in_room from adventure.utils.search import find_item_in_room
def action_climb(target: str) -> str: def action_climb(target: str) -> str:
@ -11,8 +11,7 @@ def action_climb(target: str) -> str:
Args: Args:
target: The object or feature to climb. target: The object or feature to climb.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()
# Assume 'climbable' is an attribute that marks climbable targets # Assume 'climbable' is an attribute that marks climbable targets
climbable_feature = find_item_in_room(action_room, target) climbable_feature = find_item_in_room(action_room, target)
@ -31,7 +30,9 @@ def action_climb(target: str) -> str:
) )
return f"You successfully climb the {target}." return f"You successfully climb the {target}."
else: else:
broadcast(f"{action_actor.name} fails to climb the {target}. {flavor_text}") broadcast(
f"{action_actor.name} fails to climb the {target}. {flavor_text}"
)
return f"You fail to climb the {target}." return f"You fail to climb the {target}."
else: else:
return f"The {target} is not climbable." return f"The {target} is not climbable."

View File

@ -36,9 +36,9 @@ from adventure.player import (
remove_player, remove_player,
set_player, set_player,
) )
from adventure.render_comfy import render_entity, render_event from adventure.render.comfy import render_entity, render_event
from adventure.search import find_actor, find_item, find_room
from adventure.state import snapshot_world, world_json from adventure.state import snapshot_world, world_json
from adventure.utils.search import find_actor, find_item, find_room
logger = getLogger(__name__) logger = getLogger(__name__)
@ -233,7 +233,7 @@ def render_input(data):
elif "item" in data: elif "item" in data:
item_name = data["item"] item_name = data["item"]
item = find_item( item = find_item(
world, item_name, include_actor_inventory=True, include_room_inventory=True world, item_name, include_actor_inventory=True, include_item_inventory=True
) )
if item: if item:
render_entity(item) render_entity(item)

View File

@ -1,10 +1,10 @@
from adventure.context import ( from adventure.context import (
action_context,
broadcast, broadcast,
get_agent_for_actor, get_agent_for_actor,
get_current_context,
get_dungeon_master, get_dungeon_master,
) )
from adventure.search import find_actor_in_room, find_item_in_room from adventure.utils.search import find_actor_in_room, find_item_in_room
from adventure.utils.world import describe_entity from adventure.utils.world import describe_entity
@ -16,8 +16,7 @@ def action_attack(target: str) -> str:
target: The name of the character or item to attack. target: The name of the character or item to attack.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
# make sure the target is in the room # make sure the target is in the room
target_actor = find_actor_in_room(action_room, target) target_actor = find_actor_in_room(action_room, target)
target_item = find_item_in_room(action_room, target) target_item = find_item_in_room(action_room, target)
@ -45,7 +44,8 @@ def action_attack(target: str) -> str:
) )
broadcast(description) broadcast(description)
return description return description
elif target_item:
if target_item:
outcome = dungeon_master( outcome = dungeon_master(
f"{action_actor.name} attacks {target} in the {action_room.name}. {describe_entity(action_room)}." f"{action_actor.name} attacks {target} in the {action_room.name}. {describe_entity(action_room)}."
f"{describe_entity(action_actor)}. {describe_entity(target_item)}." f"{describe_entity(action_actor)}. {describe_entity(target_item)}."
@ -55,7 +55,7 @@ def action_attack(target: str) -> str:
description = f"{action_actor.name} attacks the {target} in the {action_room.name}. {outcome}" description = f"{action_actor.name} attacks the {target} in the {action_room.name}. {outcome}"
broadcast(description) broadcast(description)
return description return description
else:
return f"{target} is not in the {action_room.name}." return f"{target} is not in the {action_room.name}."
@ -68,8 +68,7 @@ def action_cast(target: str, spell: str) -> str:
spell: The name of the spell to cast. spell: The name of the spell to cast.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
# make sure the target is in the room # make sure the target is in the room
target_actor = find_actor_in_room(action_room, target) target_actor = find_actor_in_room(action_room, target)
target_item = find_item_in_room(action_room, target) target_item = find_item_in_room(action_room, target)

View File

@ -1,5 +1,5 @@
from adventure.context import get_current_context from adventure.context import action_context
from adventure.search import find_item_in_actor from adventure.utils.search import find_item_in_actor
def action_cook(item: str) -> str: def action_cook(item: str) -> str:
@ -9,8 +9,7 @@ def action_cook(item: str) -> str:
Args: Args:
item: The name of the item to cook. item: The name of the item to cook.
""" """
_, _, action_actor = get_current_context() with action_context() as (_, action_actor):
target_item = find_item_in_actor(action_actor, item) target_item = find_item_in_actor(action_actor, item)
if target_item is None: if target_item is None:
return "You don't have the item to cook." return "You don't have the item to cook."
@ -37,8 +36,7 @@ def action_eat(item: str) -> str:
Args: Args:
item: The name of the item to eat. item: The name of the item to eat.
""" """
_, _, action_actor = get_current_context() with action_context() as (_, action_actor):
target_item = find_item_in_actor(action_actor, item) target_item = find_item_in_actor(action_actor, item)
if target_item is None: if target_item is None:
return "You don't have the item to eat." return "You don't have the item to eat."

View File

@ -1,4 +1,4 @@
from adventure.context import get_current_context, get_dungeon_master from adventure.context import action_context, get_dungeon_master
from adventure.utils.world import describe_entity from adventure.utils.world import describe_entity
@ -7,7 +7,7 @@ def action_wash(unused: bool) -> str:
Wash yourself. Wash yourself.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
hygiene = action_actor.attributes.get("hygiene", "clean") hygiene = action_actor.attributes.get("hygiene", "clean")
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()

View File

@ -1,4 +1,4 @@
from adventure.context import get_current_context, get_dungeon_master from adventure.context import action_context, get_dungeon_master
from adventure.utils.world import describe_entity from adventure.utils.world import describe_entity
@ -7,8 +7,7 @@ def action_sleep(unused: bool) -> str:
Sleep until you are rested. Sleep until you are rested.
""" """
_, action_room, action_actor = get_current_context() with action_context() as (action_room, action_actor):
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()
outcome = dungeon_master( outcome = dungeon_master(
f"{action_actor.name} sleeps in the {action_room.name}. {describe_entity(action_room)}. {describe_entity(action_actor)}" f"{action_actor.name} sleeps in the {action_room.name}. {describe_entity(action_room)}. {describe_entity(action_actor)}"

View File

@ -146,6 +146,7 @@ def simulate_world(
) )
logger.debug(f"{actor.name} step result: {result}") logger.debug(f"{actor.name} step result: {result}")
if agent.memory:
agent.memory.append(result) agent.memory.append(result)
result_event = ResultEvent(result=result, room=room, actor=actor) result_event = ResultEvent(result=result, room=room, actor=actor)

View File

@ -54,7 +54,7 @@ def snapshot_world(world: World, step: int):
json_memory = {} json_memory = {}
for actor, agent in get_all_actor_agents(): for actor, agent in get_all_actor_agents():
json_memory[actor.name] = list(agent.memory) json_memory[actor.name] = list(agent.memory or [])
return { return {
"world": json_world, "world": json_world,