add function triggers to logic system
This commit is contained in:
parent
dc00a78b57
commit
4affcb893a
|
@ -1,4 +1,4 @@
|
|||
adventure/custom_actions.py
|
||||
adventure/custom_*.py
|
||||
worlds/
|
||||
__pycache__/
|
||||
.env
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
|
@ -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")
|
||||
|
||||
|
|
Loading…
Reference in New Issue