140 lines
4.4 KiB
Python
140 lines
4.4 KiB
Python
"""This module defines the basic interpreter system."""
|
|
|
|
import fnmatch
|
|
|
|
from typing import Optional, List, Set, Tuple, cast
|
|
|
|
from .things import Thing, Container, Place, Player
|
|
from .base import VerbCallFrame, PyooVerbNotFound, PyooObjectNotFound
|
|
|
|
|
|
class Interpreter:
|
|
"""Base interpreter class.
|
|
|
|
Manages a collection of objects, and invoking verbs on them.
|
|
"""
|
|
def __init__(self, contents: Optional[List[Thing]] = None):
|
|
"""Initialize an interpreter.
|
|
|
|
Arguments:
|
|
contents (optional list of things): The initial contents to populate the interpreter with.
|
|
|
|
"""
|
|
if contents is None:
|
|
contents = []
|
|
self.contents: Set[Thing] = set(contents)
|
|
for cont in self.contents:
|
|
cont.interpreter = self
|
|
self.content_cache: List[Tuple[str, Thing]] = []
|
|
self.update()
|
|
|
|
def add_player(self, player_object: Player) -> None:
|
|
"""Add a player to the interpreter."""
|
|
self.contents.add(player_object)
|
|
player_object.interpreter = self
|
|
self.update()
|
|
|
|
def remove_player(self, player_object: Player) -> None:
|
|
"""Remove a player from the interpreter."""
|
|
self.contents.remove(player_object)
|
|
self.update()
|
|
|
|
def update(self) -> None:
|
|
"""Do any updates required when objects are added or removed."""
|
|
self.update_caches()
|
|
|
|
def update_caches(self) -> None:
|
|
"""Update the caches for objects contained in the interpreter, as well as updating all of the caches
|
|
on contained containers.
|
|
"""
|
|
self.content_cache = []
|
|
for obj in self.contents:
|
|
for name in obj.names:
|
|
self.content_cache.append((name, obj))
|
|
try:
|
|
cast(Container, obj).update_caches()
|
|
except AttributeError:
|
|
pass
|
|
|
|
def handle_move(self, newroom: Place, player: Player) -> None:
|
|
"""Move a player to a new contained room."""
|
|
if player.location:
|
|
player.location.handle_exit(player)
|
|
newroom.handle_enter(player)
|
|
|
|
def lookup_global_object(self, objstr: str) -> List[Tuple[str, Thing]]:
|
|
"""Find an object within the soup by objstr."""
|
|
return [x for x in self.content_cache if fnmatch.fnmatch(objstr, x[0])]
|
|
|
|
def lookup_object(self, player: Player, objstr: str) -> Optional[Thing]:
|
|
"""Find an object relative to a player
|
|
|
|
This first checks the player's inventory, and then the container which contains the
|
|
player.
|
|
"""
|
|
m: Optional[List[Tuple[str, Thing]]] = None
|
|
try:
|
|
m = player.get_name_matches(objstr)
|
|
except PyooObjectNotFound:
|
|
m = None
|
|
if not m and player.location:
|
|
m = player.location.get_name_matches(objstr)
|
|
if m:
|
|
return m[0][1]
|
|
else:
|
|
return None
|
|
|
|
def interpret(self, command: str, player: Player) -> None:
|
|
"""Interpret a player's command by splitting it into components and finding matching verbs."""
|
|
# FIXME make this better to support mulitple word objstrs and prepstr
|
|
if not command:
|
|
return
|
|
|
|
cmd_comps = command.split()
|
|
verbstr = cmd_comps[0]
|
|
dobjstr = ""
|
|
prepstr = ""
|
|
iobjstr = ""
|
|
argstr = ""
|
|
|
|
try:
|
|
argstr = " ".join(cmd_comps[1:])
|
|
except IndexError:
|
|
pass
|
|
|
|
try:
|
|
dobjstr = cmd_comps[1]
|
|
prepstr = cmd_comps[2]
|
|
iobjstr = cmd_comps[3]
|
|
except IndexError:
|
|
pass
|
|
|
|
try:
|
|
cmdmatches = player.get_command_matches(command)
|
|
except PyooVerbNotFound:
|
|
if player.location:
|
|
cmdmatches = player.location.get_command_matches(command)
|
|
else:
|
|
raise PyooVerbNotFound
|
|
cmd = cmdmatches[0]
|
|
# glob = cmd[0]
|
|
# comps = cmd[1]
|
|
verb = cmd[2]
|
|
this = cmd[3]
|
|
|
|
dobj = None
|
|
if verb.callspec[0] == "this":
|
|
dobj = this
|
|
elif verb.callspec[0] == "that":
|
|
# lookup object
|
|
dobj = self.lookup_object(player, dobjstr)
|
|
|
|
iobj = None
|
|
if verb.callspec[2] == "this":
|
|
iobj = this
|
|
elif verb.callspec[2] == "that":
|
|
# lookp object
|
|
iobj = self.lookup_object(player, iobjstr)
|
|
|
|
return verb(VerbCallFrame(self, player, verbstr, dobj, dobjstr, prepstr, iobj, iobjstr, argstr))
|