1
0
Fork 0

add function triggers to logic system

This commit is contained in:
Sean Sube 2024-05-04 17:57:24 -05:00
parent dc00a78b57
commit 4affcb893a
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
5 changed files with 57 additions and 25 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
adventure/custom_actions.py
adventure/custom_*.py
worlds/
__pycache__/
.env

View File

@ -9,6 +9,13 @@ from adventure.models import Actor, Item, Room, World
logger = getLogger(__name__)
OPPOSITE_DIRECTIONS = {
"north": "south",
"south": "north",
"east": "west",
"west": "east",
}
def generate_room(
agent: Agent, world_theme: str, existing_rooms: List[str], callback
@ -147,13 +154,14 @@ def generate_world(
existing_actors: List[str] = []
existing_items: List[str] = []
existing_rooms: List[str] = []
# generate the rooms
rooms = []
for i in range(room_count):
existing_rooms = [room.name for room in rooms]
room = generate_room(agent, theme, existing_rooms, callback=callback)
rooms.append(room)
existing_rooms.append(room.name)
item_count = randint(0, 3)
callback(f"Generating {item_count} items for room: {room.name}")
@ -198,13 +206,6 @@ def generate_world(
actor.items.append(item)
existing_items.append(item.name)
opposite_directions = {
"north": "south",
"south": "north",
"east": "west",
"west": "east",
}
# generate portals to link the rooms together
for room in rooms:
directions = ["north", "south", "east", "west"]
@ -213,7 +214,7 @@ def generate_world(
logger.debug(f"Room {room.name} already has a {direction} portal")
continue
opposite_direction = opposite_directions[direction]
opposite_direction = OPPOSITE_DIRECTIONS[direction]
if randint(0, 1):
dest_room = choice([r for r in rooms if r.name != room.name])
@ -233,7 +234,7 @@ def generate_world(
# create bidirectional links
room.portals[direction] = dest_room.name
dest_room.portals[opposite_directions[direction]] = room.name
dest_room.portals[OPPOSITE_DIRECTIONS[direction]] = room.name
# ensure actors act in a stable order
order = [actor.name for room in rooms for actor in room.actors]

View File

@ -1,4 +1,3 @@
from importlib import import_module
from json import load
from logging.config import dictConfig
from os import environ, path
@ -12,6 +11,7 @@ from packit.toolbox import Toolbox
from packit.utils import logger_with_colors
from adventure.context import set_current_broadcast
from adventure.plugins import load_plugin
# Configure logging
LOG_PATH = "logging.json"
@ -209,6 +209,9 @@ def parse_args():
parser.add_argument(
"--max-rooms", type=int, help="The maximum number of rooms to generate"
)
parser.add_argument(
"--optional-actions", type=bool, help="Whether to include optional actions"
)
parser.add_argument(
"--server", type=str, help="The address on which to run the server"
)
@ -326,6 +329,16 @@ def main():
)
extra_actions.extend(module_actions)
if args.optional_actions:
logger.info("Loading optional actions")
from adventure.optional_actions import init as init_optional_actions
optional_actions = init_optional_actions()
logger.info(
f"Loaded optional actions: {[action.__name__ for action in optional_actions]}"
)
extra_actions.extend(optional_actions)
# load extra systems
def snapshot_system(world: World, step: int) -> None:
logger.debug("Snapshotting world state")
@ -356,12 +369,5 @@ def main():
)
def load_plugin(name):
module_name, function_name = name.rsplit(":", 1)
plugin_module = import_module(module_name)
plugin_entry = getattr(plugin_module, function_name)
return plugin_entry()
if __name__ == "__main__":
main()

12
adventure/plugins.py Normal file
View File

@ -0,0 +1,12 @@
from importlib import import_module
def load_plugin(name: str, override_function: str | None = None):
plugin_entry = get_plugin_function(name, override_function)
return plugin_entry()
def get_plugin_function(name: str, override_function: str | None = None):
module_name, function_name = name.rsplit(":", 1)
plugin_module = import_module(module_name)
return getattr(plugin_module, override_function or function_name)

View File

@ -5,7 +5,8 @@ from typing import Dict, List, Optional
from pydantic import Field
from yaml import Loader, load
from adventure.models import World, dataclass
from adventure.models import Actor, Item, Room, World, dataclass
from adventure.plugins import get_plugin_function
logger = getLogger(__name__)
@ -22,6 +23,7 @@ class LogicRule:
chance: float = 1.0
remove: Optional[List[str]] = None
set: Optional[Dict[str, str]] = None
trigger: Optional[List[str]] = None
@dataclass
@ -32,10 +34,17 @@ class LogicTable:
with open("./worlds/logic.yaml") as file:
logic_rules = LogicTable(**load(file, Loader=Loader))
logic_triggers = {
rule: [get_plugin_function(trigger) for trigger in rule.trigger]
for rule in logic_rules.rules
if rule.trigger
}
def update_attributes(
attributes: Dict[str, str], dataset: LogicTable
entity: Room | Actor | Item,
attributes: Dict[str, str],
dataset: LogicTable,
) -> Dict[str, str]:
for rule in dataset.rules:
if rule.match.items() <= attributes.items():
@ -52,18 +61,22 @@ def update_attributes(
for key in rule.remove or []:
attributes.pop(key, None)
if rule in logic_triggers:
for trigger in logic_triggers[rule]:
attributes = trigger(entity, attributes)
return attributes
def update_logic(world: World, step: int) -> None:
for room in world.rooms:
room.attributes = update_attributes(room.attributes, logic_rules)
room.attributes = update_attributes(room, room.attributes, logic_rules)
for actor in room.actors:
actor.attributes = update_attributes(actor.attributes, logic_rules)
actor.attributes = update_attributes(actor, actor.attributes, logic_rules)
for item in actor.items:
item.attributes = update_attributes(item.attributes, logic_rules)
item.attributes = update_attributes(item, item.attributes, logic_rules)
for item in room.items:
item.attributes = update_attributes(item.attributes, logic_rules)
item.attributes = update_attributes(item, item.attributes, logic_rules)
logger.info("updated world attributes")