1
0
Fork 0
taleweave-ai/adventure/utils/search.py

228 lines
5.5 KiB
Python

from typing import Any, Generator
from adventure.models.entity import (
Actor,
EntityReference,
Item,
Portal,
Room,
World,
WorldEntity,
)
from .string import normalize_name
def find_room(world: World, room_name: str) -> Room | None:
for room in world.rooms:
if normalize_name(room.name) == normalize_name(room_name):
return room
return None
def find_portal(world: World, portal_name: str) -> Portal | None:
for room in world.rooms:
for portal in room.portals:
if normalize_name(portal.name) == normalize_name(portal_name):
return portal
return None
def find_actor(world: World, actor_name: str) -> Actor | None:
for room in world.rooms:
actor = find_actor_in_room(room, actor_name)
if actor:
return actor
return None
def find_actor_in_room(room: Room, actor_name: str) -> Actor | None:
for actor in room.actors:
if normalize_name(actor.name) == normalize_name(actor_name):
return actor
return None
# TODO: allow item or str
def find_item(
world: World,
item_name: str,
include_actor_inventory=False,
include_item_inventory=False,
) -> Item | None:
for room in world.rooms:
item = find_item_in_room(
room, item_name, include_actor_inventory, include_item_inventory
)
if item:
return item
return None
def find_item_in_actor(
actor: Actor, item_name: str, include_item_inventory=False
) -> Item | None:
return find_item_in_container(actor, item_name, include_item_inventory)
def find_item_in_container(
container: Actor | Item, item_name: str, include_item_inventory=False
) -> Item | None:
for item in container.items:
if normalize_name(item.name) == normalize_name(item_name):
return item
if include_item_inventory:
item = find_item_in_container(item, item_name, include_item_inventory)
if item:
return item
return None
def find_item_in_room(
room: Room,
item_name: str,
include_actor_inventory=False,
include_item_inventory=False,
) -> Item | None:
for item in room.items:
if normalize_name(item.name) == normalize_name(item_name):
return item
if include_item_inventory:
item = find_item_in_container(item, item_name, include_item_inventory)
if item:
return item
if include_actor_inventory:
for actor in room.actors:
item = find_item_in_actor(actor, item_name, include_item_inventory)
if item:
return item
return None
def find_room_with_actor(world: World, actor: Actor) -> Room | None:
for room in world.rooms:
for room_actor in room.actors:
if normalize_name(actor.name) == normalize_name(room_actor.name):
return room
return None
def find_containing_room(world: World, entity: Room | Actor | Item) -> Room | None:
if isinstance(entity, Room):
return entity
for room in world.rooms:
if entity in room.actors or entity in room.items:
return room
return None
def find_entity_reference(
world: World, reference: EntityReference
) -> WorldEntity | None:
"""
Resolve an entity reference to an entity in the world.
"""
if reference.room:
return find_room(world, reference.room)
if reference.actor:
return find_actor(world, reference.actor)
if reference.item:
return find_item(world, reference.item)
if reference.portal:
return find_portal(world, reference.portal)
return None
def list_rooms(world: World) -> Generator[Room, Any, None]:
for room in world.rooms:
yield room
def list_portals(world: World) -> Generator[Portal, Any, None]:
for room in world.rooms:
for portal in room.portals:
yield portal
def list_actors(world: World) -> Generator[Actor, Any, None]:
for room in world.rooms:
for actor in room.actors:
yield actor
def list_items(
world: World, include_actor_inventory=True, include_item_inventory=True
) -> Generator[Item, Any, None]:
for room in world.rooms:
for item in room.items:
yield item
if include_item_inventory:
yield from list_items_in_container(item)
if include_actor_inventory:
for actor in room.actors:
for item in actor.items:
yield item
def list_actors_in_room(room: Room) -> Generator[Actor, Any, None]:
for actor in room.actors:
yield actor
def list_items_in_actor(
actor: Actor, include_item_inventory=True
) -> Generator[Item, Any, None]:
for item in actor.items:
yield item
if include_item_inventory:
yield from list_items_in_container(item)
def list_items_in_container(
container: Item, include_item_inventory=True
) -> Generator[Item, Any, None]:
for item in container.items:
yield item
if include_item_inventory:
yield from list_items_in_container(item)
def list_items_in_room(
room: Room,
include_actor_inventory=True,
include_item_inventory=True,
) -> Generator[Item, Any, None]:
for item in room.items:
yield item
if include_item_inventory:
yield from list_items_in_container(item)
if include_actor_inventory:
for actor in room.actors:
for item in actor.items:
yield item