summaryrefslogtreecommitdiff
path: root/trunk/src/examples/adventureEngine.py
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/examples/adventureEngine.py')
-rw-r--r--trunk/src/examples/adventureEngine.py648
1 files changed, 0 insertions, 648 deletions
diff --git a/trunk/src/examples/adventureEngine.py b/trunk/src/examples/adventureEngine.py
deleted file mode 100644
index be09770..0000000
--- a/trunk/src/examples/adventureEngine.py
+++ /dev/null
@@ -1,648 +0,0 @@
-# adventureEngine.py
-# Copyright 2005-2006, Paul McGuire
-#
-# Updated 2012 - latest pyparsing API
-#
-
-from pyparsing import *
-import random
-import string
-
-def aOrAn( item ):
- if item.desc[0] in "aeiou":
- return "an " + item.desc
- else:
- return "a " + item.desc
-
-def enumerateItems(l):
- if len(l) == 0: return "nothing"
- out = []
- if len(l) > 1:
- out.append(', '.join(aOrAn(item) for item in l[:-1]))
- out.append('and')
- out.append(aOrAn(l[-1]))
- return " ".join(out)
-
-def enumerateDoors(l):
- if len(l) == 0: return ""
- out = []
- if len(l) > 1:
- out.append(', '.join(l[:-1]))
- out.append("and")
- out.append(l[-1])
- return " ".join(out)
-
-class Room(object):
- def __init__(self, desc):
- self.desc = desc
- self.inv = []
- self.gameOver = False
- self.doors = [None,None,None,None]
-
- def __getattr__(self,attr):
- return \
- {
- "n":self.doors[0],
- "s":self.doors[1],
- "e":self.doors[2],
- "w":self.doors[3],
- }[attr]
-
- def enter(self,player):
- if self.gameOver:
- player.gameOver = True
-
- def addItem(self, it):
- self.inv.append(it)
-
- def removeItem(self,it):
- self.inv.remove(it)
-
- def describe(self):
- print(self.desc)
- visibleItems = [ it for it in self.inv if it.isVisible ]
- if random.random() > 0.5:
- if len(visibleItems) > 1:
- is_form = "are"
- else:
- is_form = "is"
- print("There %s %s here." % (is_form, enumerateItems(visibleItems)))
- else:
- print("You see %s." % (enumerateItems(visibleItems)))
-
-
-class Exit(Room):
- def __init__(self):
- super(Exit,self).__init__("")
-
- def enter(self,player):
- player.gameOver = True
-
-
-
-class Item(object):
- items = {}
- def __init__(self, desc):
- self.desc = desc
- self.isDeadly = False
- self.isFragile = False
- self.isBroken = False
- self.isTakeable = True
- self.isVisible = True
- self.isOpenable = False
- self.useAction = None
- self.usableConditionTest = None
- self.cantTakeMessage = "You can't take that!"
- Item.items[desc] = self
-
- def __str__(self):
- return self.desc
-
- def breakItem(self):
- if not self.isBroken:
- print("<Crash!>")
- self.desc = "broken " + self.desc
- self.isBroken = True
-
- def isUsable(self, player, target):
- if self.usableConditionTest:
- return self.usableConditionTest( player, target )
- else:
- return False
-
- def useItem(self, player, target):
- if self.useAction:
- self.useAction(player, self, target)
-
-class OpenableItem(Item):
- def __init__(self, desc, contents=None):
- super(OpenableItem,self).__init__(desc)
- self.isOpenable = True
- self.isOpened = False
- if contents is not None:
- if isinstance(contents, Item):
- self.contents = [contents,]
- else:
- self.contents = contents
- else:
- self.contents = []
-
- def openItem(self, player):
- if not self.isOpened:
- self.isOpened = not self.isOpened
- if self.contents is not None:
- for item in self.contents:
- player.room.addItem( item )
- self.contents = []
- self.desc = "open " + self.desc
-
- def closeItem(self, player):
- if self.isOpened:
- self.isOpened = not self.isOpened
- if self.desc.startswith("open "):
- self.desc = self.desc[5:]
-
-
-class Command(object):
- "Base class for commands"
- def __init__(self, verb, verbProg):
- self.verb = verb
- self.verbProg = verbProg
-
- @staticmethod
- def helpDescription():
- return ""
-
- def _doCommand(self, player):
- pass
-
- def __call__(self, player ):
- print(self.verbProg.capitalize()+"...")
- self._doCommand(player)
-
-
-class MoveCommand(Command):
- def __init__(self, quals):
- super(MoveCommand,self).__init__("MOVE", "moving")
- self.direction = quals.direction[0]
-
- @staticmethod
- def helpDescription():
- return """MOVE or GO - go NORTH, SOUTH, EAST, or WEST
- (can abbreviate as 'GO N' and 'GO W', or even just 'E' and 'S')"""
-
- def _doCommand(self, player):
- rm = player.room
- nextRoom = rm.doors[
- {
- "N":0,
- "S":1,
- "E":2,
- "W":3,
- }[self.direction]
- ]
- if nextRoom:
- player.moveTo( nextRoom )
- else:
- print("Can't go that way.")
-
-
-class TakeCommand(Command):
- def __init__(self, quals):
- super(TakeCommand,self).__init__("TAKE", "taking")
- self.subject = quals.item
-
- @staticmethod
- def helpDescription():
- return "TAKE or PICKUP or PICK UP - pick up an object (but some are deadly)"
-
- def _doCommand(self, player):
- rm = player.room
- subj = Item.items[self.subject]
- if subj in rm.inv and subj.isVisible:
- if subj.isTakeable:
- rm.removeItem(subj)
- player.take(subj)
- else:
- print(subj.cantTakeMessage)
- else:
- print("There is no %s here." % subj)
-
-
-class DropCommand(Command):
- def __init__(self, quals):
- super(DropCommand,self).__init__("DROP", "dropping")
- self.subject = quals.item
-
- @staticmethod
- def helpDescription():
- return "DROP or LEAVE - drop an object (but fragile items may break)"
-
- def _doCommand(self, player):
- rm = player.room
- subj = Item.items[self.subject]
- if subj in player.inv:
- rm.addItem(subj)
- player.drop(subj)
- else:
- print("You don't have %s." % (aOrAn(subj)))
-
-class InventoryCommand(Command):
- def __init__(self, quals):
- super(InventoryCommand,self).__init__("INV", "taking inventory")
-
- @staticmethod
- def helpDescription():
- return "INVENTORY or INV or I - lists what items you have"
-
- def _doCommand(self, player):
- print("You have %s." % enumerateItems( player.inv ))
-
-class LookCommand(Command):
- def __init__(self, quals):
- super(LookCommand,self).__init__("LOOK", "looking")
-
- @staticmethod
- def helpDescription():
- return "LOOK or L - describes the current room and any objects in it"
-
- def _doCommand(self, player):
- player.room.describe()
-
-class DoorsCommand(Command):
- def __init__(self, quals):
- super(DoorsCommand,self).__init__("DOORS", "looking for doors")
-
- @staticmethod
- def helpDescription():
- return "DOORS - display what doors are visible from this room"
-
- def _doCommand(self, player):
- rm = player.room
- numDoors = sum([1 for r in rm.doors if r is not None])
- if numDoors == 0:
- reply = "There are no doors in any direction."
- else:
- if numDoors == 1:
- reply = "There is a door to the "
- else:
- reply = "There are doors to the "
- doorNames = [ {0:"north", 1:"south", 2:"east", 3:"west"}[i]
- for i,d in enumerate(rm.doors) if d is not None ]
- #~ print doorNames
- reply += enumerateDoors( doorNames )
- reply += "."
- print(reply)
-
-class UseCommand(Command):
- def __init__(self, quals):
- super(UseCommand,self).__init__("USE", "using")
- self.subject = Item.items[quals.usedObj]
- if quals.targetObj:
- self.target = Item.items[quals.targetObj]
- else:
- self.target = None
-
- @staticmethod
- def helpDescription():
- return "USE or U - use an object, optionally IN or ON another object"
-
- def _doCommand(self, player):
- rm = player.room
- availItems = rm.inv + player.inv
- if self.subject in availItems:
- if self.subject.isUsable( player, self.target ):
- self.subject.useItem( player, self.target )
- else:
- print("You can't use that here.")
- else:
- print("There is no %s here to use." % self.subject)
-
-class OpenCommand(Command):
- def __init__(self, quals):
- super(OpenCommand,self).__init__("OPEN", "opening")
- self.subject = Item.items[quals.item]
-
- @staticmethod
- def helpDescription():
- return "OPEN or O - open an object"
-
- def _doCommand(self, player):
- rm = player.room
- availItems = rm.inv+player.inv
- if self.subject in availItems:
- if self.subject.isOpenable:
- if not self.subject.isOpened:
- self.subject.openItem( player )
- else:
- print("It's already open.")
- else:
- print("You can't open that.")
- else:
- print("There is no %s here to open." % self.subject)
-
-class CloseCommand(Command):
- def __init__(self, quals):
- super(CloseCommand,self).__init__("CLOSE", "closing")
- self.subject = Item.items[quals.item]
-
- @staticmethod
- def helpDescription():
- return "CLOSE or CL - close an object"
-
- def _doCommand(self, player):
- rm = player.room
- availItems = rm.inv+player.inv
- if self.subject in availItems:
- if self.subject.isOpenable:
- if self.subject.isOpened:
- self.subject.closeItem( player )
- else:
- print("You can't close that, it's not open.")
- else:
- print("You can't close that.")
- else:
- print("There is no %s here to close." % self.subject)
-
-class QuitCommand(Command):
- def __init__(self, quals):
- super(QuitCommand,self).__init__("QUIT", "quitting")
-
- @staticmethod
- def helpDescription():
- return "QUIT or Q - ends the game"
-
- def _doCommand(self, player):
- print("Ok....")
- player.gameOver = True
-
-class HelpCommand(Command):
- def __init__(self, quals):
- super(HelpCommand,self).__init__("HELP", "helping")
-
- @staticmethod
- def helpDescription():
- return "HELP or H or ? - displays this help message"
-
- def _doCommand(self, player):
- print("Enter any of the following commands (not case sensitive):")
- for cmd in [
- InventoryCommand,
- DropCommand,
- TakeCommand,
- UseCommand,
- OpenCommand,
- CloseCommand,
- MoveCommand,
- LookCommand,
- DoorsCommand,
- QuitCommand,
- HelpCommand,
- ]:
- print(" - %s" % cmd.helpDescription())
- print()
-
-class AppParseException(ParseException):
- pass
-
-class Parser(object):
- def __init__(self):
- self.bnf = self.makeBNF()
-
- def makeBNF(self):
- invVerb = oneOf("INV INVENTORY I", caseless=True)
- dropVerb = oneOf("DROP LEAVE", caseless=True)
- takeVerb = oneOf("TAKE PICKUP", caseless=True) | \
- (CaselessLiteral("PICK") + CaselessLiteral("UP") )
- moveVerb = oneOf("MOVE GO", caseless=True) | empty
- useVerb = oneOf("USE U", caseless=True)
- openVerb = oneOf("OPEN O", caseless=True)
- closeVerb = oneOf("CLOSE CL", caseless=True)
- quitVerb = oneOf("QUIT Q", caseless=True)
- lookVerb = oneOf("LOOK L", caseless=True)
- doorsVerb = CaselessLiteral("DOORS")
- helpVerb = oneOf("H HELP ?",caseless=True)
-
- itemRef = OneOrMore(Word(alphas)).setParseAction( self.validateItemName )
- nDir = oneOf("N NORTH",caseless=True).setParseAction(replaceWith("N"))
- sDir = oneOf("S SOUTH",caseless=True).setParseAction(replaceWith("S"))
- eDir = oneOf("E EAST",caseless=True).setParseAction(replaceWith("E"))
- wDir = oneOf("W WEST",caseless=True).setParseAction(replaceWith("W"))
- moveDirection = nDir | sDir | eDir | wDir
-
- invCommand = invVerb
- dropCommand = dropVerb + itemRef("item")
- takeCommand = takeVerb + itemRef("item")
- useCommand = useVerb + itemRef("usedObj") + \
- Optional(oneOf("IN ON",caseless=True)) + \
- Optional(itemRef,default=None)("targetObj")
- openCommand = openVerb + itemRef("item")
- closeCommand = closeVerb + itemRef("item")
- moveCommand = moveVerb + moveDirection("direction")
- quitCommand = quitVerb
- lookCommand = lookVerb
- doorsCommand = doorsVerb
- helpCommand = helpVerb
-
- # attach command classes to expressions
- invCommand.setParseAction(InventoryCommand)
- dropCommand.setParseAction(DropCommand)
- takeCommand.setParseAction(TakeCommand)
- useCommand.setParseAction(UseCommand)
- openCommand.setParseAction(OpenCommand)
- closeCommand.setParseAction(CloseCommand)
- moveCommand.setParseAction(MoveCommand)
- quitCommand.setParseAction(QuitCommand)
- lookCommand.setParseAction(LookCommand)
- doorsCommand.setParseAction(DoorsCommand)
- helpCommand.setParseAction(HelpCommand)
-
- # define parser using all command expressions
- return ( invCommand |
- useCommand |
- openCommand |
- closeCommand |
- dropCommand |
- takeCommand |
- moveCommand |
- lookCommand |
- doorsCommand |
- helpCommand |
- quitCommand )("command") + LineEnd()
-
- def validateItemName(self,s,l,t):
- iname = " ".join(t)
- if iname not in Item.items:
- raise AppParseException(s,l,"No such item '%s'." % iname)
- return iname
-
- def parseCmd(self, cmdstr):
- try:
- ret = self.bnf.parseString(cmdstr)
- return ret
- except AppParseException as pe:
- print(pe.msg)
- except ParseException as pe:
- print(random.choice([ "Sorry, I don't understand that.",
- "Huh?",
- "Excuse me?",
- "???",
- "What?" ] ))
-
-class Player(object):
- def __init__(self, name):
- self.name = name
- self.gameOver = False
- self.inv = []
-
- def moveTo(self, rm):
- self.room = rm
- rm.enter(self)
- if self.gameOver:
- if rm.desc:
- rm.describe()
- print("Game over!")
- else:
- rm.describe()
-
- def take(self,it):
- if it.isDeadly:
- print("Aaaagh!...., the %s killed me!" % it)
- self.gameOver = True
- else:
- self.inv.append(it)
-
- def drop(self,it):
- self.inv.remove(it)
- if it.isFragile:
- it.breakItem()
-
-
-def createRooms( rm ):
- """
- create rooms, using multiline string showing map layout
- string contains symbols for the following:
- A-Z, a-z indicate rooms, and rooms will be stored in a dictionary by
- reference letter
- -, | symbols indicate connection between rooms
- <, >, ^, . symbols indicate one-way connection between rooms
- """
- # start with empty dictionary of rooms
- ret = {}
-
- # look for room symbols, and initialize dictionary
- # - exit room is always marked 'Z'
- for c in rm:
- if c in string.ascii_letters:
- if c != "Z":
- ret[c] = Room(c)
- else:
- ret[c] = Exit()
-
- # scan through input string looking for connections between rooms
- rows = rm.split("\n")
- for row,line in enumerate(rows):
- for col,c in enumerate(line):
- if c in string.ascii_letters:
- room = ret[c]
- n = None
- s = None
- e = None
- w = None
-
- # look in neighboring cells for connection symbols (must take
- # care to guard that neighboring cells exist before testing
- # contents)
- if col > 0 and line[col-1] in "<-":
- other = line[col-2]
- w = ret[other]
- if col < len(line)-1 and line[col+1] in "->":
- other = line[col+2]
- e = ret[other]
- if row > 1 and col < len(rows[row-1]) and rows[row-1][col] in '|^':
- other = rows[row-2][col]
- n = ret[other]
- if row < len(rows)-1 and col < len(rows[row+1]) and rows[row+1][col] in '|.':
- other = rows[row+2][col]
- s = ret[other]
-
- # set connections to neighboring rooms
- room.doors=[n,s,e,w]
-
- return ret
-
-# put items in rooms
-def putItemInRoom(i,r):
- if isinstance(r,str):
- r = rooms[r]
- r.addItem( Item.items[i] )
-
-def playGame(p,startRoom):
- # create parser
- parser = Parser()
- p.moveTo( startRoom )
- while not p.gameOver:
- cmdstr = input(">> ")
- cmd = parser.parseCmd(cmdstr)
- if cmd is not None:
- cmd.command( p )
- print()
- print("You ended the game with:")
- for i in p.inv:
- print(" -", aOrAn(i))
-
-
-#====================
-# start game definition
-roomMap = """
- d-Z
- |
- f-c-e
- . |
- q<b
- |
- A
-"""
-rooms = createRooms( roomMap )
-rooms["A"].desc = "You are standing on the front porch of a wooden shack."
-rooms["b"].desc = "You are in a garden."
-rooms["c"].desc = "You are in a kitchen."
-rooms["d"].desc = "You are on the back porch."
-rooms["e"].desc = "You are in a library."
-rooms["f"].desc = "You are on the patio."
-rooms["q"].desc = "You are sinking in quicksand. You're dead..."
-rooms["q"].gameOver = True
-
-# define global variables for referencing rooms
-frontPorch = rooms["A"]
-garden = rooms["b"]
-kitchen = rooms["c"]
-backPorch = rooms["d"]
-library = rooms["e"]
-patio = rooms["f"]
-
-# create items
-itemNames = """sword.diamond.apple.flower.coin.shovel.book.mirror.telescope.gold bar""".split(".")
-for itemName in itemNames:
- Item( itemName )
-Item.items["apple"].isDeadly = True
-Item.items["mirror"].isFragile = True
-Item.items["coin"].isVisible = False
-Item.items["shovel"].usableConditionTest = ( lambda p,t: p.room is garden )
-def useShovel(p,subj,target):
- coin = Item.items["coin"]
- if not coin.isVisible and coin in p.room.inv:
- coin.isVisible = True
-Item.items["shovel"].useAction = useShovel
-
-Item.items["telescope"].isTakeable = False
-def useTelescope(p,subj,target):
- print("You don't see anything.")
-Item.items["telescope"].useAction = useTelescope
-
-OpenableItem("treasure chest", Item.items["gold bar"])
-Item.items["chest"] = Item.items["treasure chest"]
-Item.items["chest"].isTakeable = False
-Item.items["chest"].cantTakeMessage = "It's too heavy!"
-
-OpenableItem("mailbox")
-Item.items["mailbox"].isTakeable = False
-Item.items["mailbox"].cantTakeMessage = "It's nailed to the wall!"
-
-putItemInRoom("mailbox", frontPorch)
-putItemInRoom("shovel", frontPorch)
-putItemInRoom("coin", garden)
-putItemInRoom("flower", garden)
-putItemInRoom("apple", library)
-putItemInRoom("mirror", library)
-putItemInRoom("telescope", library)
-putItemInRoom("book", kitchen)
-putItemInRoom("diamond", backPorch)
-putItemInRoom("treasure chest", patio)
-
-# create player
-plyr = Player("Bob")
-plyr.take( Item.items["sword"] )
-
-# start game
-playGame( plyr, frontPorch )