import whrandom import busparse import string # declare some constants the = 1 a = 2 The = 101 A = 102 # function to capitalize a string def cap(s): return string.upper(s[0]) + s[1:] # base type of any object class Thing: # initialization method def __init__(self,pName): self.name = string.split(pName,',')[0] # main name self.synonyms = string.split(string.lower(pName),',') self.size = 10 # size (100=human) self.container = None # its location self.desc = '' # description self.listening = 0 # wants Tell() calls? self.salient = 1 # show in room contents list? # add names to the parser's list of nouns for n in self.synonyms: if n not in busparse.nouns: busparse.nouns.append(n) # get name def GetName(self, article=0): if not article: return self.name if article==the: if hasattr(self,'the'): return self.the + ' ' + self.name return 'the ' + self.name if article==a: if hasattr(self,'a'): return self.a + ' ' + self.name return 'a ' + self.name if article==The: if hasattr(self,'the'): return cap(self.the) + ' ' + self.name return 'The ' + self.name if article==A: if hasattr(self,'A'): return cap(self.a) + ' ' + self.name return 'A ' + self.name return self.name # check for a name match def NameMatch(self, pName): return pName in self.synonyms # get note (for when listing the contents of a room) def GetNote(self): if not self.salient: return '' r = whrandom.randint(0,2) if r == 0: return 'You see ' + self.GetName(a) + ' lying here.' if r == 1: return self.GetName(A) + ' is lying here.' if r == 2: return 'There is '+ self.GetName(a) + ' here.' # get description def GetDesc(self,pDepth=0): if self.desc != '': return self.desc return "It looks like an ordinary " + self.GetName() + "." # let the object hear something def Tell(self, pWhat): # by default, do nothing return # use the object def Use(self, pByWhom): # for a standard Thing, attempt to pick it up pByWhom.dirobj = self.GetName() pByWhom.cmdGET() # end of class Thing # base type of any object which can contain another class Container (Thing): # initialization method def __init__(self,pName): Thing.__init__(self,pName) self.contents = [] # return true if this object can contain another def CanContain(self,pThing): return pThing.size < self.size; # move the given object to the contents of this one def ContainNoCheck(self,pThing): if pThing.container != None: # remove from previous container pThing.container.contents.remove(pThing) pThing.container = self self.contents.append(pThing) def GetDesc(self): if not self.contents: return Thing.GetDesc(self) return Thing.GetDesc(self) + '\n' + self.GetContentsDesc() def GetContentsDesc(self): if not self.contents: return self.GetName(The)+' is empty.' out = 'It looks like ' + self.GetName(the) + ' contains:\n' for item in self.contents: out = out + '\n - ' + item.GetName(a) return out # end of class Container # base class of any room or location class Room(Container): def __init__(self,pName): Container.__init__(self,pName) self.light = 75 # where 0=pitch black, 100=sunlight self.size = 5000 def GetDesc(self, pDontNote=None): if self.light < 20: return "It's too dark to see.\n" out = Thing.GetDesc(self) + '\n' for item in self.contents: if item != pDontNote and item.salient: out = out + '\n ' + item.GetNote() return out + '\n' def Tell( self, pWhat, pExcept=[]): whom = filter(lambda x,n=pExcept: x.listening and x not in n, self.contents) for i in whom: i.Tell(pWhat) # class for exits -- things which connect one room to another class Exit(Thing): def __init__(self,pName): Thing.__init__(self,pName) self.dest = None # by default, no destination self.salient = 0 # and not salient self.size = 300 # and as big as 3 people # move someone through the exit, if possible def Transport(self,pWhom): if not self.dest: Tell(pWhom,self.GetName()+" leads nowhere.") return if self.size < pWhom.size or not self.dest.CanContain(pWhom): Tell(pWhom,"You don't fit!") # perform the move pWhom.Announce(pWhom.GetName()+" exits to "+self.GetName(the)+".") pWhom.Tell("You head "+self.GetName()+".") self.dest.ContainNoCheck(pWhom) pWhom.Announce(pWhom.GetName()+" enters the room.") pWhom.Tell(self.dest.GetDesc(pWhom)) def Use(self, pByWhom): self.Transport(pByWhom) # base class of any person, monster, or other chanacter class Actor(Container): def __init__(self,pName): Container.__init__(self,pName) self.size = 100 # human-sized self.listening = 1 # wants Tell() calls self.par = busparse.Parser() # my very own command interpreter self.commanding = None # whom we're bossing around def GetNote(self): return self.GetName() + " is here." def Use(self, pByWhom): # for an Actor, being used means being given commands pByWhom.commanding = self def Act(self): # by default, no action return def Announce(self, pWhat): if self.container: self.container.Tell( pWhat, [self] ) # given the name of a noun, return the visible object def FindNoun(self,pName): if not pName: return None if pName == 'self' or pName == 'me': return self if pName == 'here' or pName == 'room': return self.container l = filter(lambda x,a=pName: x.NameMatch(a),self.contents) if not l: l = filter(lambda x,a=pName: x.NameMatch(a),self.container.contents) if l: return l[0] return None def DoCommand(self,cmd): par = self.par # just for convenience below... while cmd: cmd = par.Parse(cmd) if par.verb == 'look': self.cmdLOOK() elif par.verb == 'get' or par.verb=='take': self.cmdGET() elif par.verb == 'drop': self.cmdDROP() elif par.verb == 'inv' or par.verb == 'i': self.cmdINV() elif par.verb == 'put': self.cmdPUT(); elif par.verb == 'use': self.cmdUSE(); if self.commanding: self.commanding.DoCommand(cmd) self.commanding = None cmd = '' elif par.verb == 'go': i = self.FindNoun(self.par.dirobj) if i: i.Transport(self) else: self.Tell("Unknown command.") def cmdLOOK(self): atwhat = None if self.par.dirobj: atwhat = self.FindNoun(self.par.dirobj) elif self.par.atobj: atwhat= self.FindNoun(self.par.atobj) elif self.par.inobj: atwhat= self.FindNoun(self.par.inobj) if not atwhat: self.Tell('Look in what?!?') if not hasattr(atwhat,'GetContentsDesc'): self.Tell(atwhat.GetName(The)+' is not a container.') else: self.Tell(atwhat.GetContentsDesc()) return else: # no object; describe the room if self.container != None: self.Tell(self.container.GetDesc(self)) else: self.Tell('You are in the Void.') return if atwhat: self.Tell(atwhat.GetDesc()) else: self.Tell('Look at what?!?') def cmdGET(self): pWhat = None if self.par.inobj: pWhere = self.FindNoun(self.par.inobj) if pWhere: l = filter(lambda x,a=self.par.dirobj: x.NameMatch(a),pWhere.contents) if l: pWhat = l[0] if not pWhat: pWhat = self.FindNoun(self.par.dirobj) if pWhat: if pWhat.container == self: self.Tell("You've already got that.") return if not self.CanContain(pWhat): self.Tell("You can't carry that.") return self.ContainNoCheck(pWhat) self.Tell('You get the ' + pWhat.GetName() + '.') self.Announce(self.GetName() + " gets " + pWhat.GetName(a) + ".") else: self.Tell('Get what?!?') def cmdDROP(self): pWhat = self.FindNoun(self.par.dirobj) if pWhat: if pWhat.container != self: self.Tell("You aren't carrying that.") return if not self.container.CanContain(pWhat): self.Tell("You can't drop that here.") return self.container.ContainNoCheck(pWhat) self.Tell('You drop the ' + pWhat.GetName() + '.') self.Announce(self.GetName() + " drops " + pWhat.GetName(a) + ".") else: self.Tell('Get what?!?') def cmdPUT(self): pWhat = self.FindNoun(self.par.dirobj) if not pWhat: self.Tell('Put what?!?') return pWhere = self.FindNoun(self.par.inobj) if not pWhere: self.Tell('Put it where?!?') return if pWhat.container == pWhere: self.Tell(pWhat.GetName() + ' is already in ' + pWhere.GetName(the)) return if not pWhere.CanContain(pWhat): self.Tell("You can't put that in " + pWhere.GetName(the) + ".") return pWhere.ContainNoCheck(pWhat) self.Tell('You put the ' + pWhat.GetName() + ' in the ' + pWhere.GetName() + '.') self.Announce(self.GetName() + " puts " + pWhat.GetName(a) + ' into ' + pWhere.GetName(a) + '.') def cmdUSE(self): pWhat = self.FindNoun(self.par.dirobj) if not pWhat: self.Tell('Use what?!?') return pWhat.Use(self) def cmdINV(self): if not self.contents: self.Tell('You are empty-handed.') else: self.Tell('You are carrying:') for item in self.contents: self.Tell(' - ' + item.GetName(a) ) # end of class Actor # class of the player -- i.e., the Actor interfaced to the terminal class Player(Actor): def Tell(self, pWhat): print pWhat def Act(self): cmd = string.lower(raw_input('>')) self.DoCommand(cmd) # end of class Player # class parrot -- puts whatever it hears to the terminal class Parrot(Actor): def Tell(self,pWhat): print '[' + self.GetName() + ' hears] ' + pWhat # create some sample objects rock = Thing("rock,stone") bag = Container("bag,sack") bag.size = 20 me = Player("Everyman") Bert = Actor("Bert,Herbert,Albert") bird = Parrot("bird,parrot,squawker") bird.size = 15 here = Room("Empty Room") here.desc = "You're in an empty room. An exit lies north." here.ContainNoCheck(bag) here.ContainNoCheck(me) here.ContainNoCheck(Bert) here.ContainNoCheck(bird) there = Room("Outside") there.ContainNoCheck(rock) here2there = Exit('north,n,out,outside,exit') here.ContainNoCheck(here2there) here2there.dest = there there2here = Exit('south,s,in') there2here.dest = here there.ContainNoCheck(there2here) def test(): while 1: me.Act()