use search helpers more, improve image naming with hash of event
This commit is contained in:
parent
eb12d460b9
commit
4d90cbef33
|
@ -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.')
|
||||||
|
|
||||||
|
|
|
@ -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."
|
||||||
|
|
||||||
|
|
|
@ -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}")
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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}."
|
||||||
|
|
|
@ -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."
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue