#	gadgets.py			6/01/98 JJS##	This module defines a number of handy (or at least cool) gadgets.##	Use this module with:  import gadgets##----------------------------------------------------------------------# standard modulesimport randomimport stringimport typesimport re as regeximport copy# PUB modulesimport pubfrom pubcore import *import pubverbsimport pubobjs#----------------------------------------------------------------------#	ScriptPlayer: executes a script, which is a list of strings.#	The strings are stored in the "script" attribute.##		Each string may be one of:#			DELAY delay#			DO command#			text to be announced to the room#class ScriptPlayer(pubobjs.Actor):	def __init__(self,pNames):		pubobjs.Actor.__init__(self,pNames)		self.script = []		self.curItem = 0		pub.scheduler.AddEvent(3,Event(self,'object.Play()'))	def Play(self):		if not self.script: return		item = self.script[self.curItem]		self.curItem = self.curItem + 1		if self.curItem >= len(self.script): self.curItem = 0		firstword = string.split(item)[0]		delay = 1		if firstword == "DELAY":			delay = toInt(string.split(item)[1])		elif firstword == "DO":			command = item[3:]			self.DoCommandString(command)		else:			self.Announce(item)		pub.scheduler.AddEvent(delay, Event(self,'object.Play()'))#----------------------------------------------------------------------#	Transceiver: when on, transmits to all others#		(makes a pub.transceiverList variable)#class Transceiver(pubobjs.Switch):	def __init__(self,pNames):		pubobjs.Switch.__init__(self,pNames)		# add to the global radio list		try:			pub.transceiverList.append(self)		except:			pub.transceiverList = [self]		self.prefix = "On the transceiver: "		self.effectOnCode = "self.listening = 1"		self.effectOffCode = "self.listening = 0"		self.effectOn = '<The dirobj> is now on.'		self.effectOff = '<The dirobj> is now off.'		self.oeffectOn = '<The actor> activates <the dirobj>.'		self.oeffectOff = '<The actor> deactivates <the dirobj>.'		self.getOnOn = FALSE		self.offOnDrop = FALSE			def Tell(self,pWhat):		# we have to be careful not to tell other transceivers,		# or we'd get a positive feedback loop!		for rcvr in pub.transceiverList:			if rcvr.listening and rcvr != self:				for item in rcvr.GetRoom().contents:					if item.listening and item not in pub.transceiverList:						item.Tell(self.prefix + pWhat)#----------------------------------------------------------------------#	Button#class Button(pubobjs.Thing):	def __init__(self,pNames):		pubobjs.Thing.__init__(self,pNames)		self.useCode = ''		self.defverb = pubverbs.push		self.salient = 0		self.object = None		def Use(self,pByWhom):		if self.object: object = self.object		else: object = self.container		if self.useCode: exec self.useCode#----------------------------------------------------------------------#	Elevator#class Elevator(pubobjs.Room):	def __init__(self,pNames):		pubobjs.Room.__init__(self,pNames)		self.floors = []		# list of accessible floors		self.inlink = {}		# Exit from floor to elevator		self.currentFloor = None	# current floor		self.inNames = 'elevator'	# names to call entrance links		self.outlink = pubobjs.Exit('out,exit')		# Exit from elevator to floor		self.ContainNoCheck(self.outlink)		self.closedDesc = 'The elevator doors are closed.'		self.openDesc = 'The elevator doors are open.'		self.open = FALSE		self.busytill = 0	def LinkFloor(self,pRoom,pNames = ''):		if pRoom in self.floors: return				# make a link to the elevator		self.floors.append(pRoom)		self.inlink[pRoom] = pubobjs.Exit(self.inNames)		self.inlink[pRoom].dest = self		self.inlink[pRoom].open = FALSE		pRoom.ContainNoCheck(self.inlink[pRoom])				# make a button inside the elevator		if pNames:			button = Button( pNames )		else:			button = Button( string.join(pRoom.synonyms,',') )		self.ContainNoCheck(button)		button.useCode = "object.HandleButton(self)"		button.floor = pRoom		# make a button on the floor itself		button = Button( 'button' )		button.useCode = "object.HandleButton(self)"		button.floor = pRoom		button.object = self		pRoom.ContainNoCheck(button)			def HandleButton(self, pButton):		if self.busytill < pub.scheduler.minutes:			t = pub.scheduler.minutes + 1		else:			t = self.busytill + 1		if self.open:			pub.scheduler.AddAbsEvent(t, Event(self,'object.CloseDoors()'))			t = t + 2		if self.currentFloor != pButton.floor:			pub.scheduler.AddAbsEvent(t, \					Event(self,'object.MoveByName("'+pButton.floor.name+'")') )			t = t+1		pub.scheduler.AddAbsEvent(t, Event(self,'object.OpenDoors()'))		t = t+5		pub.scheduler.AddAbsEvent(t, Event(self,'object.Idle()'))		self.busytill = t		return	def CloseDoors(self):		self.Tell('The elevator doors close.')		self.outlink.dest.Tell('The elevator doors close.')		if self.currentFloor:			self.inlink[self.currentFloor].desc = self.closedDesc			self.inlink[self.currentFloor].open = FALSE		self.outlink.desc = self.closedDesc		self.outlink.dest = None		self.outlink.open = FALSE		self.open = FALSE		def MoveByName(self,pName):		f = filter(lambda x,a=pName: x.name==a, self.floors)		self.MoveToFloor(f[0])		def MoveToFloor(self,pRoom):		if pRoom not in self.floors:			print "Error: invalid floor specified in Elevator.MoveToFloor()"			return		if self.open: self.CloseDoors()		self.currentFloor = pRoom		self.Tell('The elevator has arrived at '+pRoom.GetName()+'.')		def OpenDoors(self):		if not self.currentFloor:			print "Error: can't open Elevator doors without a current floor."			return		self.inlink[self.currentFloor].desc = self.openDesc		self.inlink[self.currentFloor].dest = self		self.inlink[self.currentFloor].open = TRUE		self.outlink.desc = self.openDesc		self.outlink.dest = self.currentFloor		self.outlink.open = TRUE		self.open = TRUE		self.Tell('The elevator doors open.')		self.outlink.dest.Tell('The elevator doors open.')	def Idle(self):		# if not in use, close the doors		if self.open and self.busytill <= pub.scheduler.minutes:			self.CloseDoors()	def GetDesc(self,pLooker=None):		out = pubobjs.Room.GetDesc(self,pLooker)		out = out + "\nYou see the following buttons: "		for floor in self.floors:			out = out + "\n     " + floor.GetName()			if floor == self.currentFloor:				out = out + " (current floor)"		return out#----------------------------------------------------------------------#	Window#class Window(pubobjs.Thing):	def __init__(self, pNames):		pubobjs.Thing.__init__(self,pNames)		self.prefix = "Through "+self(the)+", you see:"		self.dest = None		self.noview = "There's nothing much to see."			def GetDesc(self, pLooker=None):		if not self.dest or self.dest == pub.universe:			return self.noview		return self.prefix + self.dest.GetDesc(pLooker)	#----------------------------------------------------------------------#	Vehicle#class Vehicle(pubobjs.Room):	def __init__(self,pNames):		pubobjs.Room.__init__(self,pNames)		# create the window, to view the outside from within		self.window = Window("window,windows,out")		self.window.MoveTo(self)		self.window.salient = 0		# create the exit from the inside		self.exit = pubobjs.Exit("out,exit,outside,leave")		self.exit.MoveTo(self)		# set good notes etc.		self.note = self(A) + " is parked here."		self.dests = {}		self.route = pub.universe		self.leave = self(The) + " gets underway."		self.oleave = self(The) + " departs."		self.arrive = self(The) + " has arrived."		self.oarrive = self(A) + " has arrived."		self.goingTo = None		self.defverb = pubverbs.use		self.size = 400		self.opostsucc = '<The actor> enters <the dirobj>.'	def MoveTo(self, pWhere):		# when being moved, have to also change the window and exit dest		self.window.dest = pWhere		self.exit.dest = pWhere		return BaseThing.MoveTo(self, pWhere)	def TravelToNamed(self,pStr):		if not self.dests.has_key(pStr):			return CANCEL		self.TravelTo(self.dests[pStr])		return OK		def TravelTo(self, pWhere):		self.Leave()		self.goingTo = pWhere		pub.scheduler.AddEvent(10, Event(self,"object.Arrive()") )		def Leave(self):		# cleanly move to self.route		# close the window and exit		self.exit.open = FALSE		self.window.dest = None		# announce the departure		self.Tell( self.leave )		self.container.Tell( self.oleave )		# move to the enroute room		self.MoveTo(self.route)		def Arrive(self):		# cleanly move to self.goingTo		self.MoveTo(self.goingTo)		self.exit.open = 1		# announce the arrival		self.Tell( self.arrive )		self.container.Tell( self.oarrive )	def Use(self,pByWhom):	# Use for this means enter it		pByWhom.MoveTo(self)		return OK	def PreObj(self,cmd):		if cmd.verb == pubverbs.go or cmd.verb == pubverbs.use:			if not self.exit.open:				cmd.Tell( "The door is closed." )				return CANCEL			if self.size < cmd.actor.size or not self.CanContain(cmd.actor):				cmd.Tell("You don't fit!")				return CANCEL			if pubobjs.Thing.PreObj(self,cmd):				cmd.Tell("You enter <dirobj>.", "<The actor> enters <the dirobj>.")				return OK			return CANCEL					# in any other case, return inherited method		return pubobjs.Room.PreObj(self,cmd)	def PostObj(self,cmd):		if cmd.verb == pubverbs.go or cmd.verb == pubverbs.use:				cmd.Tell('', self.opostsucc)			cmd.Tell(self.GetDesc(cmd.actor))			return CANCEL	# so that no further output is printed		# any other condition, return OK for normal output		return OK		#----------------------------------------------------------------------#	Driver#class Driver(pubobjs.NPC):	def HearSpeech(self, pSpeaker, pSpeech):		car = self.container		if not hasattr(car,'dests') or not hasattr(car,'TravelToNamed'):			return CANCEL		for destname in car.dests.keys():			if string.count(string.lower(pSpeech),destname):				self.DoCommandString("nod")				if not car.TravelToNamed(destname):					self.DoCommandString("say dern thing won't work!")					return CANCEL				return OK		self.DoCommandString("say Where do you want to go?")				#----------------------------------------------------------------------#	Camera	- a gadget that takes pictures (just "use" it)#class Camera(pubobjs.Thing):	def Use(self, pByWhom):		# create a picture of the current scene		scene = pByWhom.container		pic = pubobjs.Thing("photo of "+scene()+",photo,picture,pic")		pic.desc = "The photograph depicts:\n" + scene.GetDesc(pByWhom)		# and give it to the user		pByWhom.ContainNoCheck(pic)		return OK	def PostObj(self, cmd):		if cmd.verb == pubverbs.use:			cmd.Tell("You snap a picture.", \				"<The actor> snaps a picture.")			return CANCEL		return pubobjs.Thing.PostObj(self,cmd)