def reload(self, p, cons, oDO, oIDO): '''Reloads the specified room, or the room containing the player if none is given. First moves all objects out of the room into nulspace, then re-imports the room module, calls `load()` in the new module, then finally moves any creatures including players back to the new room.''' room = None if len(p.words) < 2: room = self.location elif len(p.words) == 2: room = gametools.load_room(p.words[1]) if room == None: return "Error, room '%s' doesn't seem to exist!" % p.words[1] else: return "Usage: 'reload' [room path]\n\t<room path> is optional, if none is given will reload the current room." alive = [x for x in room.contents if isinstance(x, Creature) ] # all Creatures incl NPCs & players if room.detach(room.path) == False: return "Error while detaching room %s!" % room.path mod = importlib.reload(room.mod) newroom = mod.load( ) # TODO: store and re-use parameters of original load() call? newroom.mod = mod for c in alive: c.move_to(newroom, force_move=True) cons.write( 'You make a magical gesture and scene around you suddenly changes.' ) self.emit( '&nD%s makes a magical gesture, and you sense something has changed.' % self.id) del room # XXX unclear if this will do anything return True
def apparate(self, p, cons, oDO, oIDO): if cons.user != self: return "I don't quite get what you mean." if len(p.words) < 2: cons.write( "Usage: 'apparate <id>', where id is the entry of a Room in Thing.ID_dict[] or a path to it's module" ) return True id = " ".join(p.words[1:]) try: room = Thing.ID_dict[id] except KeyError: room = gametools.load_room(id) if room == None: return "There seems to be no place with id (or path) '%s'!" % id if isinstance(room, Room) == False: cons.write("You cannot apparate to %s; that is not a place!" % room.names[0]) return True self.emit( "&nD%s performs a magical incantation, and vanishes!" % self.id, [self]) self.move_to(room) self.emit("&nD%s arrives suddenly, as if by magic!" % self.id, [self]) self.perceive( "You perform a magical incantation and are suddenly in a new place!" ) room.report_arrival(self, silent=True) return True
def move_around(self): """The NPC leaves the room, taking a random exit""" try: exit_list = list(self.location.exits) exit = random.choice(exit_list) except (AttributeError, IndexError): dbg.debug('NPC %s sees no exits, returning from move_around()' % self.id) return dbg.debug("Trying to move to the %s exit!" % (exit)) current_room = self.location new_room_string = self.location.exits[exit] new_room = gametools.load_room(new_room_string) if new_room.monster_safe: dbg.debug('Can\'t go to %s; monster safe room!' % new_room_string) return if new_room_string in self.forbidden_rooms: dbg.debug('Can\'t go to %s: forbidden to %s!' % (new_room_string, self)) self.emit("&nD%s goes %s." % (self.id, exit)) self.move_to(new_room) self.emit("&nI%s arrives." % self.id) dbg.debug( "Creature %s moved to new room %s" % (self.names[0], new_room_string), 1) return
def heartbeat(self): dbg.debug('self.last_cons is %s' % self.last_cons, 2) try: dbg.debug('contents[0] of cave is %s' % self.contents[0].id, 2) contents_question = True except IndexError: contents_question = False dbg.debug('Nothing in the CaveEntry', 2) dbg.debug("%s, %s" % (contents_question, self.in_entry_user), 2) if self.in_entry_user < 1 and contents_question: self.in_entry_user += 1 dbg.debug(str(self.in_entry_user), 2) elif self.in_entry_user > 0 and contents_question: for i in self.contents: if isinstance(i, Player): i.perceive( 'You step back from the cave mouth into the gloomy forest.' ) i.emit( "&nD%s steps back from the cave mouth into the gloomy forest." % i.id) dbg.debug('extracting %s!' % i, 2) going_to_loc = gametools.load_room(self.escape_room) i.move_to(going_to_loc) going_to_loc.report_arrival(i) self.in_entry_user = 0
def go_to(self, p, cons, oDO, oIDO): words = p.words user = cons.user sExit = words[1] if sExit in list(self.exits): try: destPath = self.exits[ sExit] # filename of the destination room module dest = gametools.load_room(destPath) except KeyError: dbg.debug( "KeyError: exit '%s' maps to '%s' which is not an object in the game!" % (sExit, self.exits[sExit]), 0) cons.write("There was an internal error with the exit. ") return True if cons.user.move_to(dest): loc = user.location verb = words[0] conjugated = "goes" if verb == "go" else verb + 's' cons.write("You %s to the %s." % (verb, sExit)) self.emit("&nD%s %s to the %s." % (user.id, conjugated, sExit)) loc.report_arrival(user) return True else: return "For some reason you are unable to go to the %s." % sExit else: # user did not specify a valid exit return "I don't see how to go %s!" % sExit
def enter(self, p, cons, oDO, oIDO): (sV, sDO, sPrep, sIDO) = p.diagram_sentence(p.words) if sDO == 'waterfall': if cons.user.wizardry_element != 'water': cons.user.perceive( 'You try to enter the waterfall, but get swept back by the rushing current.' ) cons.user.emit( '&nD%s dives into the waterfall, but gets swept back by the rushing current.' ) return True dest = gametools.load_room('domains.school.school.water_lounge') if dest == None: cons.user.perceive( "You try to enter the waterfall, but an error occurs! Please report it." ) dbg.debug('Error! dest() of waterfall returned None on load!') return True cons.user.perceive( 'You dive into the waterfall, and find yourself somewhere quite different.' ) cons.user.emit( '&nD%s dives into the waterfall and dissapears from view.') cons.user.move_to(dest) dest.report_arrival(cons.user) return True return "Did you mean to enter the waterfall?"
def dive(self, p, cons, oDO, oIDO): cons.user.perceive( 'You dive under the lake and find yourself in a different environment.' ) cons.user.emit('&nd%s dives underwater and disappears from sight.' % cons.user) loc = gametools.load_room(self.underwater_loc) cons.user.move_to(loc) thing.Thing.game.events.schedule(thing.Thing.game.time + 15, loc.force_surface, cons.user) return True
def enter(self, p, cons, oDO, oIDO): if not self.opened: return "You must open the door before you can pass through it." dest = gametools.load_room(self.destination) if cons.user.move_to(dest): cons.write( 'With a sense of making a momentous decision, you step through the doorway.' ) dest.report_arrival(cons.user) self.emit('&nD%s walks through the doorway to the path of %s.' % (cons.user.id, self.names[0])) return True
def force_surface(self, user): if user not in self.contents: if isinstance(user.location, LakeRoom_underwater): user.location.force_surface(user) return if user.wizardry_element == 'water': #if the user is already a water wizard, then they don't have to re-surface return user.perceive('You find that you are out of air and must resurface.') user.emit('&nD%s swims upward and disappears from sight.' % user) loc = gametools.load_room(self.surface_loc) user.move_to(loc) user.emit('&nD%s surfaces.' % user)
def _restore_objs_from_IDs(self): """Update object references stored as ID strings to directly reference the objects, using Thing.ID_dict.""" if isinstance(self.location, str): self.location = Thing.ID_dict[ self. location] # XXX will this work correctly for the room if it isn't loaded yet? if self.contents != None: self.contents = [ Thing.ID_dict[id] for id in self.contents if isinstance(id, str) ] if hasattr(self, 'set_start_loc'): self.set_start_loc = gametools.load_room(self.set_start_loc)
def __init__(self, path): NPC.__init__(self, 'goblin', path, Thing.ID_dict['nulspace'].game) self.set_description( 'old mean goblin', 'This goblin is standing straight in front of the passage west. He is holding a piece of paper in his hand.' ) self.add_adjectives('old', 'horrid', 'mean') self.add_script( '''Listen. If you intend to walk straight past here invisible, I tell you that you will not get away with it. I am the only one who can let you past and I'm not going to let you get past. And to pass you must acquire a gem--an emerald, I think--and give it to me. If you do not give me the emerald, however, but keep it, you will be severely punished.''' ) self.pit = gametools.load_room('domains.school.dungeon.pit') self.root_room = gametools.load_room( 'domains.school.dungeon.root_room') self.roots = gametools.clone('domains.school.dungeon.roots') self.complete_players = [] self.approached = [] self.complete_message = [] self.talk_counter = 0 Thing.game.register_heartbeat(self)
def heartbeat(self): # If waiting on something, then return if self.waiting: return # If checking status, continue if self.checking_done: self.check() return # If giving a class, continue if self.giving_class: self.give_class() return # If checking homework, continue if self.unchecked_homework: i = self.unchecked_homework[0] if i == self: del self.unchecked_homework[0] elif i.wizardry_element == None: self.emit( 'Prof. Sun says: %s, you have come to the wrong class. Your class starts later. Goodbye.' % i) self.emit('&nD%s vanishes!' % i.id) dest = gametools.load_room('domains.school.school.library') i.move_to(dest) dest.report_arrival(i) else: self.emit('Prof. Sun says: %s, you are good to go.' % i.proper_name) del self.unchecked_homework[0] if not self.unchecked_homework: self.emit('Prof. Sun says: Okay, we are good to go.') self.begin_class() return # Otherwise, check to see if there are any players in the room players = [ x for x in self.location.contents if isinstance(x, creature.Creature) and x not in self.graduates and x != self ] if not players: return # If there are players, check their homework self.emit( 'The tall, wise elf says: Hello. I am Prof. Sun. Welcome to my class.\nI will begin by checking your homework.' ) self.unchecked_homework = players
def die(self, message=None): #What to do when 0 health self.emit("&nD%s dies!" % self.id, [self]) corpse = gametools.clone('corpse', self) self.location.insert(corpse) for i in self.contents: i.move_to(corpse) if hasattr(self, 'cons'): self.move_to(gametools.load_room(self.start_loc_id) if self.start_loc_id else gametools.load_room(gametools.DEFAULT_START_LOC)) #Moves to a location for deletion. TODO: Make nulspace delete anything inside it. else: self.move_to(Thing.ID_dict['nulspace']) self.dead = True if message: self.emit(message)
def enter(self, p, cons, oDO, oIDO): if oDO == self: cons.user.wizardry_element = 'fire' cons.user.perceive('You steel yourself and step through the flaming portal. Oddly, the ' 'roaring flames do not burn, but instead the fire fills you with a ' 'tingling warmth. The flames surround you and suddenly disappear as ' 'if your body had extinguished--no, ABSORBED--the fire. You suddenly ' 'realize you are in a different place...') lounge = gametools.load_room('domains.school.school.fire_lounge') if lounge and cons.user.move_to(lounge): self.emit('&nD%s enters the fiery portal, and disappears in a burst of flame!', cons.user.id) else: cons.user.perceive('...and just as quickly, you feel yourself return! But something has changed...') return True return "Did you mean to enter the portal?"
def __init__(self, path): super().__init__("Silemon", path, pref_id="DeepPocketSignUpWizard") self.set_description( "Silemon Deplintere", "Silemon Deplintere is an older wizard and is wearing a blue cape. He is standing uniformly in front of you." ) self.deep_pockets = [] for i in Thing.ID_dict: if isinstance(i, DeepPocket): self.deep_pockets.append(i) self.serving_customer = False self.vault_room = gametools.load_room( 'domains.wizardry.deep_pocket.vaults') self.in_process = False self.said_nos = []
def lay(self, p, cons, oDO, oIDO): (sV, sDO, sPrep, sIDO) = p.diagram_sentence(p.words) if sV == 'sleep': cons.user.move_to(self) cons.write('You lie down on the bed and fall fast asleep.') self.emit('&nD%s lies down on the bed and falls asleep.' % cons.user.id) cons.user.move_to(gametools.load_room(self.dreamland)) Thing.game.events.schedule(70, self.wake_up, cons) return True if sV == 'lay' and sIDO == 'bed': cons.user.move_to(self) cons.write('You lay down on the bed and relax.') return True return "Did you mean to lay down on the bed?"
def enter(self, p, cons, oDO, oIDO): dest = gametools.load_room(self.dest) if self.dest == gametools.DEFAULT_START_LOC: scroll = gametools.clone('domains.school.scroll') scroll.move_to(cons.user) thing.Thing.game.register_heartbeat(scroll) cons.user.set_start_loc(dest) if cons.user.move_to(dest) == False: return "Error! You attempt to enter the mirror but encounter a glitch in the space-time continuum. Please report an error." label = "" # construct a label, e.g. "swarthy young male gnome" if self.adj1: label += self.adj1 + " " cons.user.adj1 = self.adj1 cons.user.add_adjectives(self.adj1) elif cons.user.adj1: label += cons.user.adj1 + " " else: label = "nondescript" + " " if self.adj2: label += self.adj2 + " " cons.user.adj2 = self.adj2 cons.user.add_adjectives(self.adj2) elif cons.user.adj2: label += cons.user.adj2 + " " if self.gender: label += self.gender + " " cons.user.add_adjectives(self.gender) cons.user.gender = self.gender elif cons.user.gender: label += cons.user.gender + " " if self.species: label += self.species cons.user.species = self.species cons.user.add_names(self.species) elif cons.user.species: label += cons.user.species + " " cons.user.set_description(label, "A " + label) cons.user.perceive( "As if in a dream, you approach the mirror and enter it, the glass parting like gauze " "to let you through. Somehow you feel more sharply defined, more real! You notice your surroundings " "have changed...\n") dest.report_arrival(cons.user) return True
def load(): roomPath = gametools.findGamePath(__file__) exists = room.check_loaded(roomPath) if exists: return exists lair = gametools.load_room('domains.school.cave.lair') cave = cave_mod.CaveRoom('cave', roomPath, lair) cave.indoor = True cave.set_description( 'terrifying dark cave', 'This is one of the most scary caves you have ever been in. You are anxiously looking around to see if there are any monsters.' ) cave.add_adjectives('scary', 'dark', 'terrifying') cave.add_exit('west', 'domains.school.cave.lair') cave.add_exit('east', 'domains.school.forest.forest3') thing.Thing.game.register_heartbeat(cave) cave.attach_monster(lair.monster) return cave
def enter(self, p, cons, oDO, oIDO): if oDO != self: return "What do you intend to enter?" if cons.user.wizardry_element == 'fire': if self.dest == 'domains.school.school.fire_lounge': cons.user.perceive("You stealthily pass through the fireplace and find yourself in another room.") else: cons.user.perceive("You pass through the fireplace into the Great Hall.") self.emit('&d%s passes through the fireplace to a room on the other side. ' % cons.user, ignore = [cons.user]) dest = gametools.load_room(self.dest) if not dest: return "Whoops! There isn't actually a room on the other side!" cons.user.move_to(dest) dest.report_arrival(cons.user) return True else: cons.user.perceive('You burn yourself in the flames of the fire, and it pushes you away.') cons.user.health -= 2 return True
def enter(self, p, cons, oDO, oIDO): if self.state == "closed": cons.user.perceive( 'You try to enter the doorway, but something blocks your path.' ) return True cons.user.wizardry_element = 'water' cons.user.perceive( 'As you swim through the doorway, you start to feel a buildup of pressue. ' 'Somehow, however, it doesn\'t seem unconfortable. Then, all of the sudden, ' 'you begin to feel as if you have given in to--no, ' 'ABSORBED the pressure. You suddenly realize you are in a different place...' ) lounge = gametools.load_room('domains.school.school.water_lounge') if lounge and cons.user.move_to(lounge): self.emit( '&nD%s swims through the doorway, and dissapears on the other side.' % cons.user) else: cons.user.perceive( '...and just as quickly, you feel yourself return! But something has changed...' ) return True
def create_new_player(self, name, cons): user = Player(name, None, cons) cons.user = user adjective = random.choice( ('tall', 'short', 'dark', 'pale', 'swarthy', 'thin', 'heavyset')) species = random.choice(('human', 'elf', 'dwarf', 'gnome')) user.set_description(adjective + ' ' + species, 'A player named %s' % name) user.set_max_weight_carried(750000) user.set_max_volume_carried(2000) start_room = gametools.load_room('domains.school.school.great_hall') start_room.insert(user) scroll = gametools.clone('domains.school.scroll') scroll.move_to(user) self.register_heartbeat(scroll) user.set_start_loc = start_room user.perceive( "\nWelcome to Firlefile Sorcery School!\n\n" "Type 'look' to examine your surroundings or an object, " "'inventory' to see what you are carrying, " "'quit' to end the game, and 'help' for more information.") return user
def load_player(self, filename, cons, oldplayer=None): """Unpickle a single player and his/her inventory from a saved file. Objects in the player's inventory (and their contents, recursively) are treated as new objects, and will often be duplicates of existing objects already in the game. Thus after unpickling each object we need to add it to Thing.ID_dict with a new and unique ID.""" if not filename.endswith('.OADplayer'): filename += '.OADplayer' try: f = open(filename, 'r+b') except FileNotFoundError: cons.write("Error, couldn't find file named %s" % filename) raise gametools.PlayerLoadError try: # l is the list of objects (player + recursive inventory). Note that # unpickling calls init() which creates new entries in ID_dict for objects in l, # using the uniquified IDs - guaranteed to succeed without further changing ID l = pickle.load(f) f.close() except pickle.PickleError: cons.write( "Encountered error while pickling to file %s, player not loaded." % filename) f.close() raise gametools.PlayerLoadError except EOFError: cons.write( "The file you are trying to load appears to be corrupt.") raise gametools.PlayerLoadError newplayer = l[0] # first object pickled is the player if oldplayer: # TODO: move below code for deleting player to Player.__del__() # Unlink player object from room; delete player along with recursive inventory eraselist = [oldplayer] for o in eraselist: if o.contents: eraselist += o.contents if o.location.extract(o): dbg.debug( "Error deleting player or inventory during load_game(): object %s contained in %s " % (o, o.location)) if o in self.heartbeat_users: self.deregister_heartbeat(o) del Thing.ID_dict[o.id] # o.__del__() # XXX probably doesn't truly delete the object; needs more research cons.user = None newplayer.cons = cons # custom pickling code for Player doesn't save console cons.user = newplayer # update backref from cons cons.change_players = True loc_str = newplayer.location newplayer.location = gametools.load_room(loc_str) if newplayer.location == None: dbg.debug( "Saved location '%s' for player %s no longer exists; using default location" % (loc_str, newplayer), 0) cons.write( "Somehow you can't quite remember where you were, but you now find yourself back in the Great Hall." ) newplayer.location = gametools.load_room( 'domains.school.school.great_hall') # Now fix up location & contents[] to list object refs, not ID strings for o in l: o._restore_objs_from_IDs() # Now de-uniquify all IDs, replace object.id and ID_dict{} entry for o in l: del Thing.ID_dict[o.id] (head, sep, tail) = o.id.partition('-saveplayer') o.id = o._add_ID( head) # if object with ID == head exists, will create a new ID room = newplayer.location room.insert(newplayer) # insert() does some necessary bookkeeping cons.write("Restored game state from file %s" % filename) room.report_arrival(newplayer, silent=True) room.emit("&nI%s suddenly appears, as if by sorcery!" % newplayer.id, [newplayer])
def surface(self, p, cons, oDO, oIDO): cons.user.perceive('You swim upwards and resurface.') cons.user.emit('&nD%s swims upwards and disappears from sight.') loc = gametools.load_room(self.surface_loc) cons.user.move_to(loc) return True
def _handle_login(self, cmd): state = self.login_state if state == 'AWAITING_USERNAME': if len(cmd.split()) != 1: self.cons.write("Usernames must be a single word with no spaces.<br>" "Please enter your username:"******"Welcome back, %s!<br>Please enter your password: "******"No player named "+self.names[0]+" found. " "Would you like to create a new player? (yes/no)<br>") self.login_state = 'AWAITING_CREATE_CONFIRM' return elif state == 'AWAITING_CREATE_CONFIRM': if cmd == "yes": self.cons.write("Welcome, %s!<br>Please create a password:"******"no": self.cons.write("Okay, please enter your username: "******"Please answer yes or no: ") return elif state == 'AWAITING_NEW_PASSWORD': passwd = cmd # XXX ignoring for now. # TODO secure password authentication goes here self.id = self._add_ID(self.names[0]) self.proper_name = self.names[0].capitalize() dbg.debug("Creating player id %s with default name %s" % (self.id, self.names[0]), 0) start_room = gametools.load_room(gametools.NEW_PLAYER_START_LOC) start_room.insert(self) self.perceive("\nWelcome to Firlefile Sorcery School!\n\n" "Type 'look' to examine your surroundings or an object, " "'inventory' to see what you are carrying, " "'quit' to end the game, and 'help' for more information.") self.login_state = None return elif state == 'AWAITING_PASSWORD': passwd = cmd # XXX ignoring for now. # TODO secure password authentication goes here filename = os.path.join(gametools.PLAYER_DIR, self.names[0]) + '.OADplayer' try: newuser = self.game.load_player(filename, self.cons) dbg.debug("Loaded player id %s with default name %s" % (newuser.id, newuser.names[0]), 0) newuser.login_state = None self.login_state = None self.game.deregister_heartbeat(self) del Thing.ID_dict[self.id] except gametools.PlayerLoadError: self.cons.write("Error loading data for player %s from file %s. <br>" "Please try again.<br>Please enter your username: "******"AWAITING_USERNAME" return
def take(self, p, cons, oDO, oIDO): if oDO != self and oIDO != self: return "I don't understand what you're trying to take!" cons.write(self.trap_message) cons.user.move_to(gametools.load_room(self.trap_location)) return True