Initial commit with a mostly working engine.
Basic commands are being parsed. I think the only weird part is the 'use' command because it needs to possibly target two things. A tiny test example is provided in __main__, this will probably be broken out later. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
247
agame/trigger.py
Normal file
247
agame/trigger.py
Normal file
@@ -0,0 +1,247 @@
|
||||
import abc
|
||||
import re
|
||||
from typing import Match, Pattern, TYPE_CHECKING
|
||||
from agame.util import search_item_name
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from agame.game import Game
|
||||
|
||||
|
||||
# Triggers:
|
||||
# get/take/grab/pick up [a[n]/the] x
|
||||
# use [a[n]/the] x [with/on [a[n]/the] y]
|
||||
# put [a[n]/the] x on/in [a[n]/the] y
|
||||
# look [[at] [a[n]/the] x]
|
||||
# open x
|
||||
# close x
|
||||
# go/(go to)/leave/exit x
|
||||
# give [a[n]/the] x to [a[n]/the] y
|
||||
# push [a[n]/the] x
|
||||
# pull [a[n]/the] x
|
||||
# (put down)/drop [a[n]/the] x
|
||||
__all__ = (
|
||||
"Trigger",
|
||||
"GetTrigger",
|
||||
"UseTrigger",
|
||||
"PutTrigger",
|
||||
"LookTrigger",
|
||||
"OpenTrigger",
|
||||
"CloseTrigger",
|
||||
"GoTrigger",
|
||||
"GET",
|
||||
"USE",
|
||||
"PUT",
|
||||
"LOOK",
|
||||
"OPEN",
|
||||
"CLOSE",
|
||||
"GO",
|
||||
)
|
||||
GET = "get"
|
||||
USE = "use"
|
||||
PUT = "put"
|
||||
LOOK = "look"
|
||||
OPEN = "open"
|
||||
CLOSE = "close"
|
||||
GO = "go"
|
||||
|
||||
|
||||
class Trigger(metaclass=abc.ABCMeta):
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def pattern() -> Pattern:
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
pass
|
||||
|
||||
|
||||
class GetTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>get|take|grab|pick[ ]*up)
|
||||
(([ ]+(an?|the))?[ ]+(?P<item>.+))?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
if not item_name:
|
||||
otrigger = match["trigger"].lower().capitalize()
|
||||
game.say(f"{otrigger} what?")
|
||||
return
|
||||
item = game.room.search_item_name(item_name.lower())
|
||||
if item and GET in item.triggers:
|
||||
actions = item.triggers[GET]
|
||||
# if there are any actions, do them. else do the default action
|
||||
game.do_actions(actions)
|
||||
else:
|
||||
game.say("Can't get that.")
|
||||
|
||||
|
||||
class UseTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
# TODO(low) - wouldn't it be cool to specify "use" actions?
|
||||
# e.g. you have a gun item and you want to be allowed to use "shoot" in order to
|
||||
# use the gun.
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>use)
|
||||
(([ ]+(an?|the))?[ ]+(?P<item>.+?)
|
||||
([ ]+(with|on)([ ]+(an?|the))?[ ]+(?P<target>.+))?)?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
if not item_name:
|
||||
game.say("Use what?")
|
||||
return
|
||||
target_name = match["target"]
|
||||
|
||||
# Get the item from inventory or room
|
||||
item = game.room.search_item_name(item_name) or search_item_name(
|
||||
game.inventory.values(), item_name.lower()
|
||||
)
|
||||
if not item:
|
||||
game.say(f"I'm not sure what you mean by {item_name}.")
|
||||
return
|
||||
|
||||
target = None
|
||||
if target_name:
|
||||
# Get the target from inventory or room
|
||||
target = game.room.search_item_name(target_name) or search_item_name(
|
||||
game.inventory.values(), target_name.lower()
|
||||
)
|
||||
if not target:
|
||||
game.say(f"I'm not sure what you mean by {target_name}.")
|
||||
# Check if the target can be used on something
|
||||
elif target.id in item.use_actions:
|
||||
game.do_actions(item.use_actions[target.id])
|
||||
else:
|
||||
game.say("I'm not sure how to do that.")
|
||||
elif USE in item.triggers:
|
||||
# Check if the item can be used by itself
|
||||
game.do_actions(item.triggers[USE])
|
||||
elif item.use_actions:
|
||||
# This item can be used with *something*, but we don't know what.
|
||||
game.say(f"Use (({item_name})) with what?")
|
||||
else:
|
||||
# This can't be used.
|
||||
game.say("I can't really use that.")
|
||||
|
||||
|
||||
class PutTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>put)
|
||||
([ ]+((an?|the)[ ]+)?(?P<item>.+?)
|
||||
((on|in)[ ]+)?((an?|the)[ ]+)?[ ]+(?P<target>.+))?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
|
||||
|
||||
class LookTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>look)
|
||||
([ ]+(at[ ]+)?((an?|the)[ ]+)?(?P<item>.+?))?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
if not item_name:
|
||||
game.print_room()
|
||||
return
|
||||
item = game.room.search_item_name(item_name.lower())
|
||||
if item and LOOK in item.triggers:
|
||||
actions = item.triggers[LOOK]
|
||||
game.do_actions(actions)
|
||||
else:
|
||||
game.say("Can't see that.")
|
||||
|
||||
|
||||
class OpenTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>open)
|
||||
(((an?|the)[ ]+)?[ ]+(?P<item>.+?))?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
if not item_name:
|
||||
game.say("Open what?")
|
||||
return
|
||||
item = game.room.search_item_name(item_name.lower())
|
||||
if item and OPEN in item.triggers:
|
||||
actions = item.triggers[OPEN]
|
||||
game.do_actions(actions)
|
||||
else:
|
||||
game.say("Can't open that.")
|
||||
|
||||
|
||||
class CloseTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>close)
|
||||
(((an?|the)[ ]+)?[ ]+(?P<item>.+?))?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
if not item_name:
|
||||
game.say("Close what?")
|
||||
return
|
||||
item = game.room.search_item_name(item_name.lower())
|
||||
if item and CLOSE in item.triggers:
|
||||
actions = item.triggers[CLOSE]
|
||||
game.do_actions(actions)
|
||||
else:
|
||||
game.say("Can't close that.")
|
||||
|
||||
|
||||
class GoTrigger(Trigger):
|
||||
@staticmethod
|
||||
def pattern() -> Pattern:
|
||||
return re.compile(
|
||||
r"""
|
||||
(?P<trigger>go|go[ ]*to|leave|exit)
|
||||
(((an?|the)[ ]+)?[ ]+(?P<item>.+?))?
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
def trigger(self, game: "Game", match: Match):
|
||||
item_name = match["item"]
|
||||
if not item_name:
|
||||
otrigger = match["trigger"].lower().capitalize()
|
||||
game.say(f"{otrigger} where?")
|
||||
return
|
||||
item = game.room.search_item_name(item_name.lower())
|
||||
if item and GO in item.triggers:
|
||||
actions = item.triggers[GO]
|
||||
game.do_actions(actions)
|
||||
Reference in New Issue
Block a user