1
0
Fork 0

use search helpers more, improve image naming with hash of event

This commit is contained in:
Sean Sube 2024-05-13 20:08:19 -05:00
parent eb12d460b9
commit 4d90cbef33
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
6 changed files with 61 additions and 59 deletions

View File

@ -20,6 +20,8 @@ OPPOSITE_DIRECTIONS = {
def duplicate_name_parser(existing_names: List[str]): def duplicate_name_parser(existing_names: List[str]):
def name_parser(name: str, **kwargs): def name_parser(name: str, **kwargs):
logger.debug(f"validating name: {name}")
if name in existing_names: if name in existing_names:
raise ValueError(f'"{name}" has already been used.') raise ValueError(f'"{name}" has already been used.')

View File

@ -12,6 +12,7 @@ from adventure.context import (
set_dungeon_master, set_dungeon_master,
) )
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
logger = getLogger(__name__) logger = getLogger(__name__)
@ -47,19 +48,23 @@ def action_explore(direction: str) -> str:
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 current_world.rooms]
new_room = generate_room( try:
dungeon_master, current_world.theme, existing_rooms=existing_rooms new_room = generate_room(
) dungeon_master, current_world.theme, existing_rooms=existing_rooms
current_world.rooms.append(new_room) )
current_world.rooms.append(new_room)
# link the rooms together # link the rooms together
current_room.portals[direction] = new_room.name current_room.portals[direction] = new_room.name
new_room.portals[OPPOSITE_DIRECTIONS[direction]] = current_room.name new_room.portals[OPPOSITE_DIRECTIONS[direction]] = current_room.name
broadcast( broadcast(
f"{current_actor.name} explores {direction} of {current_room.name} and finds a new room: {new_room.name}" f"{current_actor.name} explores {direction} of {current_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:
logger.exception("error generating room")
return f"You cannot explore {direction} from here, there is no room in that direction."
def action_search(unused: bool) -> str: def action_search(unused: bool) -> str:
@ -71,22 +76,26 @@ def action_search(unused: bool) -> str:
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." 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]
new_item = generate_item( try:
dungeon_master, new_item = generate_item(
action_world.theme, dungeon_master,
existing_items=existing_items, action_world.theme,
dest_room=action_room.name, existing_items=existing_items,
) dest_room=action_room.name,
action_room.items.append(new_item) )
action_room.items.append(new_item)
broadcast( broadcast(
f"{action_actor.name} searches {action_room.name} and finds a new item: {new_item.name}" f"{action_actor.name} searches {action_room.name} and finds a new item: {new_item.name}"
) )
return f"You search the room and find a new item: {new_item.name}" return f"You search the room and find a new item: {new_item.name}"
except Exception:
logger.exception("error generating item")
return "You find nothing hidden in the room."
def action_use(item: str, target: str) -> str: def action_use(item: str, target: str) -> str:
@ -115,9 +124,7 @@ def action_use(item: str, target: str) -> str:
target_actor = action_actor target_actor = action_actor
target = action_actor.name target = action_actor.name
else: else:
target_actor = next( target_actor = find_actor_in_room(action_room, target)
(actor for actor in action_room.actors if actor.name == target), None
)
if not target_actor: if not target_actor:
return f"The {target} character is not in the room." return f"The {target} character is not in the room."

View File

@ -12,6 +12,7 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
import websocket # NOTE: websocket-client (https://github.com/websocket-client/websocket-client) import websocket # NOTE: websocket-client (https://github.com/websocket-client/websocket-client)
from fnvhash import fnv1a_32
from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2 import Environment, FileSystemLoader, select_autoescape
from PIL import Image from PIL import Image
@ -225,7 +226,8 @@ def prompt_from_event(event: GameEvent) -> str | None:
if event.item: if event.item:
return f"{event.actor.name} uses the {event.item.name}. {event.item.description}. {event.actor.description}. {event.room.description}." return f"{event.actor.name} uses the {event.item.name}. {event.item.description}. {event.actor.description}. {event.room.description}."
return f"{event.actor.name} {event.action}. {event.actor.description}. {event.room.description}." action_name = event.action.removeprefix("action_")
return f"{event.actor.name} uses {action_name}. {event.actor.description}. {event.room.description}."
if isinstance(event, ReplyEvent): if isinstance(event, ReplyEvent):
return event.text return event.text
@ -262,18 +264,24 @@ def sanitize_name(name: str) -> str:
return valid_name.lower() return valid_name.lower()
def fast_hash(text: str) -> str:
return hex(fnv1a_32(text.encode("utf-8")))
def get_image_prefix(event: GameEvent | WorldEntity) -> str: def get_image_prefix(event: GameEvent | WorldEntity) -> str:
if isinstance(event, ActionEvent): if isinstance(event, ActionEvent):
return sanitize_name(f"event-action-{event.actor.name}-{event.action}") return sanitize_name(f"event-action-{event.actor.name}-{event.action}")
if isinstance(event, ReplyEvent): if isinstance(event, ReplyEvent):
return sanitize_name(f"event-reply-{event.actor.name}") return sanitize_name(f"event-reply-{event.actor.name}-{fast_hash(event.text)}")
if isinstance(event, ResultEvent): if isinstance(event, ResultEvent):
return sanitize_name(f"event-result-{event.actor.name}") return sanitize_name(
f"event-result-{event.actor.name}-{fast_hash(event.result)}"
)
if isinstance(event, StatusEvent): if isinstance(event, StatusEvent):
return "status" return sanitize_name(f"event-status-{fast_hash(event.text)}")
if isinstance(event, WorldEntity): if isinstance(event, WorldEntity):
return sanitize_name(f"entity-{event.__class__.__name__.lower()}-{event.name}") return sanitize_name(f"entity-{event.__class__.__name__.lower()}-{event.name}")

View File

@ -35,6 +35,7 @@ from adventure.player import (
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
logger = getLogger(__name__) logger = getLogger(__name__)
@ -214,33 +215,23 @@ def render_input(data):
logger.error(f"failed to find event {event_id}") logger.error(f"failed to find event {event_id}")
elif "actor" in data: elif "actor" in data:
actor_name = data["actor"] actor_name = data["actor"]
actor = next( actor = find_actor(world, actor_name)
(a for r in world.rooms for a in r.actors if a.name == actor_name), None
)
if actor: if actor:
render_entity(actor) render_entity(actor)
else: else:
logger.error(f"failed to find actor {actor_name}") logger.error(f"failed to find actor {actor_name}")
elif "room" in data: elif "room" in data:
room_name = data["room"] room_name = data["room"]
room = next((r for r in world.rooms if r.name == room_name), None) room = find_room(world, room_name)
if room: if room:
render_entity(room) render_entity(room)
else: else:
logger.error(f"failed to find room {room_name}") logger.error(f"failed to find room {room_name}")
elif "item" in data: elif "item" in data:
item_name = data["item"] item_name = data["item"]
item = None item = find_item(
for room in world.rooms: world, item_name, include_actor_inventory=True, include_room_inventory=True
item = next((i for i in room.items if i.name == item_name), None) )
if item:
break
for actor in room.actors:
item = next((i for i in actor.items if i.name == item_name), None)
if item:
break
if item: if item:
render_entity(item) render_entity(item)
else: else:

View File

@ -4,6 +4,7 @@ from adventure.context import (
get_current_context, get_current_context,
get_dungeon_master, get_dungeon_master,
) )
from adventure.search import find_actor_in_room, find_item_in_room
def action_attack(target: str) -> str: def action_attack(target: str) -> str:
@ -17,12 +18,8 @@ def action_attack(target: str) -> str:
_, action_room, action_actor = get_current_context() _, action_room, action_actor = get_current_context()
# make sure the target is in the room # make sure the target is in the room
target_actor = next( target_actor = find_actor_in_room(action_room, target)
(actor for actor in action_room.actors if actor.name == target), None target_item = find_item_in_room(action_room, target)
)
target_item = next(
(item for item in action_room.items if item.name == target), None
)
dungeon_master = get_dungeon_master() dungeon_master = get_dungeon_master()
if target_actor: if target_actor:
@ -73,12 +70,8 @@ def action_cast(target: str, spell: str) -> str:
_, action_room, action_actor = get_current_context() _, action_room, action_actor = get_current_context()
# make sure the target is in the room # make sure the target is in the room
target_actor = next( target_actor = find_actor_in_room(action_room, target)
(actor for actor in action_room.actors if actor.name == target), None target_item = find_item_in_room(action_room, target)
)
target_item = next(
(item for item in action_room.items if item.name == target), None
)
if not target_actor and not target_item: if not target_actor and not target_item:
return f"{target} is not in the {action_room.name}." return f"{target} is not in the {action_room.name}."

View File

@ -1,4 +1,5 @@
from adventure.context import get_current_context from adventure.context import get_current_context
from adventure.search import find_item_in_actor
def action_cook(item: str) -> str: def action_cook(item: str) -> str:
@ -10,7 +11,7 @@ def action_cook(item: str) -> str:
""" """
_, _, action_actor = get_current_context() _, _, action_actor = get_current_context()
target_item = next((i for i in action_actor.items if i.name == item), None) 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."
@ -38,7 +39,7 @@ def action_eat(item: str) -> str:
""" """
_, _, action_actor = get_current_context() _, _, action_actor = get_current_context()
target_item = next((i for i in action_actor.items if i.name == item), None) 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."