def reject(self, character): """ Reject an honour combat. """ character_id = character.id if character_id not in self.preparing: return # stop the call call_id = self.preparing[character_id]["call_id"] call_id.cancel() # remove characters from the preparing queue opponent_id = self.preparing[character_id]["opponent"] character = search_object("#%s" % character_id) if character: character[0].msg({"match_rejected": character_id}) del self.preparing[character_id] opponent = search_object("#%s" % opponent_id) if opponent: opponent[0].msg({"match_rejected": character_id}) del self.preparing[opponent_id] self.remove_by_id(character_id)
def at_initial_setup(): """ Build up the default world and set default locations. """ try: # load world data import_local_data() print("Import local data.") # load game settings GAME_SETTINGS.reset() print("Reset game settings.") # build world builder.build_all() print("Builder build all.") # set limbo's desc limbo_obj = search.search_object("#2", exact=True) if limbo_obj: limbo_obj[0].db.desc = LIMBO_DESC limbo_obj[0].position = None print("Set limbo object.") # set default locations builder.reset_default_locations() print("Set default locations.") superuser = search.search_object("#1", exact=True) if superuser: superuser = superuser[0] # move the superuser to the start location start_location = search.search_object(settings.START_LOCATION, exact=True) if start_location: start_location = start_location[0] superuser.move_to(start_location, quiet=True) # set superuser's data superuser.set_data_key(GAME_SETTINGS.get("default_player_character_key")) superuser.set_level(1) superuser.set_nickname("superuser") print("Set supervisor.") except Exception, e: ostring = "Can't set initial data: %s" % e print(ostring) print(traceback.format_exc())
def remove_by_id(self, character_id): """ Remove a character from the queue. """ character = search_object("#%s" % character_id) if character: self.remove(character[0])
def MailTo(self, caller, prompt, user_input): target = search.search_object(user_input, typeclass="typeclasses.characters.Character") if len(target) == 0: caller.msg("SYSTEM: That didn't match a player. Confirm the player's name and try again.") elif len(target) > 1: caller.msg("SYSTEM: That matched several players. Maybe try an alias?") else: caller.ndb.mailtarget = target[0] get_input(self.caller, "SYSTEM: What is the subject of this mail?", self.MailSubject) return True
def at_initial_setup(): """ Build up the default world and set default locations. """ try: # load world data importer.import_all() # reload skill modules MudderySkill.load_skill_modules() # build world builder.build_all() # set limbo's desc limbo_obj = search.search_object("#2", exact=True) if limbo_obj: limbo_obj[0].db.desc = LIMBO_DESC # set default locations builder.reset_default_locations() superuser = search.search_object("#1", exact=True) if superuser: superuser = superuser[0] # move the superuser to the start location start_location = search.search_object(settings.START_LOCATION, exact=True) if start_location: start_location = start_location[0] superuser.move_to(start_location, quiet=True) # set superuser's data superuser.set_data_key(settings.DEFAULT_PLAYER_CHARACTER_KEY) superuser.set_level(1) superuser.set_nickname("superuser") except Exception, e: ostring = "Can't build world: %s" % e print(ostring) print(traceback.format_exc())
def fight(self, opponents): """ Create a combat. """ confirmed0 = opponents[0] in self.preparing and self.preparing[opponents[0]]["confirmed"] confirmed1 = opponents[1] in self.preparing and self.preparing[opponents[1]]["confirmed"] if not confirmed0 and not confirmed1: self.remove_by_id(opponents[0]) self.remove_by_id(opponents[1]) opponent0 = search_object("#%s" % opponents[0]) opponent0[0].msg({"match_rejected": opponents[0], "left_combat_queue": ""}) opponent1 = search_object("#%s" % opponents[1]) opponent1[0].msg({"match_rejected": opponents[1], "left_combat_queue": ""}) elif not confirmed0: # opponents 0 not confirmed self.remove_by_id(opponents[0]) if opponents[1] in self.preparing: del self.preparing[opponents[1]] opponent0 = search_object("#%s" % opponents[0]) opponent0[0].msg({"match_rejected": opponents[0], "left_combat_queue": ""}) opponent1 = search_object("#%s" % opponents[1]) opponent1[0].msg({"match_rejected": opponents[0]}) elif not confirmed1: # opponents 1 not confirmed self.remove_by_id(opponents[1]) if opponents[0] in self.preparing: del self.preparing[opponents[0]] opponent1 = search_object("#%s" % opponents[1]) opponent1[0].msg({"match_rejected": opponents[1], "left_combat_queue": ""}) opponent0 = search_object("#%s" % opponents[0]) opponent0[0].msg({"match_rejected": opponents[1]}) elif confirmed0 and confirmed1: # all confirmed opponent0 = search_object("#%s" % opponents[0]) opponent1 = search_object("#%s" % opponents[1]) # create a new combat handler chandler = create_script(settings.HONOUR_COMBAT_HANDLER) # set combat team and desc chandler.set_combat({1:[opponent0[0]], 2:[opponent1[0]]}, _("Fight of Honour"), settings.AUTO_COMBAT_TIMEOUT) self.remove_by_id(opponents[0]) self.remove_by_id(opponents[1])
def delete_object(obj_dbref): # helper function for deleting a single object obj = search.search_object(obj_dbref) if not obj: ostring = "Can not find object %s." % obj_dbref print(ostring) # do the deletion okay = obj[0].delete() if not okay: ostring = "Can not delete %s." % obj_dbref print(ostring)
def func(self): target = search.search_object(self.args.split('=')[0], typeclass="typeclasses.characters.Character") if len(target) == 1: prefix = "From {0} on {1}/{2}: ".format(self.caller.key,datetime.now().month,datetime.now().day) target[0].db.notifications.append(prefix + self.args.split('=',1)[1]) self.caller.msg("SYSTEM: Added notification to " + target[0].key + "'s queue.") if target[0].has_player: target[0].msg("SYSTEM: You have pending notifications.") else: if len(target) > 1: self.caller.msg("SYSTEM: That matched more than one player.") else: self.caller.msg("SYSTEM: That did not match a player.")
def open_wall(self): """ This method is called by the push button command once the puzzle is solved. It opens the wall and sets a timer for it to reset itself. """ # this will make it into a proper exit (this returns a list) eloc = search.search_object(self.db.destination) if not eloc: self.caller.msg("The exit leads nowhere, there's just more stone behind it ...") else: self.destination = eloc[0] self.exit_open = True # start a 45 second timer before closing again utils.delay(45, self.reset)
def func(self): target = search.search_object(self.args, typeclass="typeclasses.characters.Character") if len(target) == 1: target[0].db.approved = 1 self.caller.msg("SYSTEM: You have approved " + target[0].key + " for play.") if target[0].has_player: target[0].msg("SYSTEM: You have been approved for play by " + self.caller.key) else: now = datetime.now() target[0].db.notifications.append("{0}/{1}: Approved for play by {2}.".format(now.month, now.day, self.caller.key)) else: if len(target) > 1: self.caller.msg("SYSTEM: " + self.args + " matched several Characters.") else: self.caller.msg("SYSTEM: " + self.args + " didn't match a Character.")
def open_wall(self): """ This method is called by the push button command once the puzzle is solved. It opens the wall and sets a timer for it to reset itself. """ # this will make it into a proper exit (this returns a list) eloc = search.search_object(self.db.destination) if not eloc: self.caller.msg( "The exit leads nowhere, there's just more stone behind it ..." ) else: self.destination = eloc[0] self.exit_open = True # start a 45 second timer before closing again utils.delay(45, self.reset)
def func(self): if not self.args: get_input(self.caller, "SYSTEM: Who are you sending mail to?", self.MailTo) else: target = search.search_object(self.args.split('/')[0], typeclass="typeclasses.characters.Character") title = self.args.split('/')[1].split('=')[0] message = self.args.split('/')[1].split('=',1)[1] if len(target) == 0: caller.msg("SYSTEM: That didn't match a player. Confirm the player's name and try again.") elif len(target) > 1: caller.msg("SYSTEM: That matched several players. Maybe try an alias?") else: target = target[0] temp = [ self.caller.key, title, message, datetime.now() ] target.db.mailsystem.append(temp) self.caller.msg("Sent your mail to {0}".format(target.key)) msg = "{0}/{1}: New mail from {2} about {3}.".format(temp[3].month, temp[3].day, self.caller.key, temp[1]) target.db.notifications.append(msg) if target.has_player: target.msg("SYSTEM: You have pending notifications.")
def func(self): target = search.search_object(self.args.split('=')[0], typeclass="typeclasses.characters.Character") if len(target) == 1: target = target[0] if self.args.split('=')[1].isdigit(): if self.cmdstring == '@assets': target.db.assets += int(self.args.split('=')[1]) else: target.db.firebirds += int(self.args.split('=')[1]) self.caller.msg("SYSTEM: Added {0} to {1}'s {2}.".format(self.args.split('=')[1], target.key, str(self.cmdstring).strip('@'))) if target.has_player: target.msg("SYSTEM: {0} added {1} to your {2}.".format(self.caller.key, self.args.split('=')[1], str(self.cmdstring).strip('@'))) else: target.db.notifications.append("{0}/{1}: {2} added {3} to your {4}.".format(datetime.now().month, datetime.now().day, self.caller.key, self.args.split('=')[1], str(self.cmdstring).strip('@'))) else: self.caller.msg("SYSTEM: Amount argument must be a digit.") else: if len(target) > 1: self.caller.msg("SYSTEM: That matched more than one character.") else: self.caller.msg("SYSTEM: That didn't match any characters.")
def character_death(victim, killer=None, weapon_name=None): # send an appropriate global death message if not killer: msg_global(f"{victim.name} has died of mysterious causes.") elif not weapon_name: msg_global(f"{victim.name} has been slain by {killer.name}.") else: msg_global(f"{victim.name} has been slain by {killer.name}'s {weapon_name}.") # award xp to the killer if killer is not None and killer.is_typeclass("typeclasses.characters.Character"): killer.msg(f"You killed {victim.name}!") xp = calculate_kill_xp(killer.db.xp, victim.db.xp) gain_xp(killer, xp) # victim drops everything it was holding before leaving room for obj in victim.contents: if obj.worth: # only drop things with value # TODO: possible destroy chance? victim.execute_cmd(f"drop {obj.key}") else: # nuke worthless objects obj.delete() # victim goes to the void the_void = search_object("Void")[0] if the_void: victim.location.msg_contents( f"{victim.name} disappears in a cloud of greasy black smoke.", exclude=[victim]) victim.move_to(the_void, quiet=True) # reduce victim xp/level set_xp(victim, int(victim.db.xp / 2)) # clear/reset various stats reset_victim_state(victim) # starting gold! give_starting_gold(victim)
def _obj_search(*args, **kwargs): "Helper function to search for an object" query = "".join(args) session = kwargs.get("session", None) return_list = kwargs.pop("return_list", False) account = None if session: account = session.account targets = search.search_object(query) if return_list: retlist = [] if account: for target in targets: if target.access(account, target, 'control'): retlist.append(target) else: retlist = targets return retlist else: # single-match if not targets: raise ValueError("$obj: Query '{}' gave no matches.".format(query)) if len(targets) > 1: raise ValueError( "$obj: Query '{query}' gave {nmatches} matches. Limit your " "query or use $objlist instead.".format(query=query, nmatches=len(targets))) target = targets[0] if account: if not target.access(account, target, 'control'): raise ValueError( "$obj: Obj {target}(#{dbref} cannot be added - " "Account {account} does not have 'control' access.".format( target=target.key, dbref=target.id, account=account)) return target
def reborn(self): """ Reborn after being killed. """ # Reborn at its home. home = None if not home: home_key = self.system.location if home_key: rooms = utils.search_obj_data_key(home_key) if rooms: home = rooms[0] if not home: rooms = search.search_object(settings.DEFAULT_HOME) if rooms: home = rooms[0] if home: self.move_to(home, quiet=True) # Recover properties. self.recover()
def _obj_search(*args, **kwargs): "Helper function to search for an object" query = "".join(args) session = kwargs.get("session", None) return_list = kwargs.pop("return_list", False) account = None if session: account = session.account targets = search.search_object(query) if return_list: retlist = [] if account: for target in targets: if target.access(account, target, 'control'): retlist.append(target) else: retlist = targets return retlist else: # single-match if not targets: raise ValueError("$obj: Query '{}' gave no matches.".format(query)) if len(targets) > 1: raise ValueError("$obj: Query '{query}' gave {nmatches} matches. Limit your " "query or use $objlist instead.".format( query=query, nmatches=len(targets))) target = targets[0] if account: if not target.access(account, target, 'control'): raise ValueError("$obj: Obj {target}(#{dbref} cannot be added - " "Account {account} does not have 'control' access.".format( target=target.key, dbref=target.id, account=account)) return target
def at_initial_setup(): # Search by dbref to find the #1 superuser char1 = search_object('#1', use_dbref=True)[0] room = search_object('#2', use_dbref=True)[0] room.key = 'default_home' room.db.desc = ( "This is the room where objects travel to when their home location isn\'t " "explicity set in the source code or by a builder, " "and the object\'s current location is destroyed. " "Character typeclasses are not allowed to enter this room in a move_to check." ) # Black Hole black_hole = create_object(typeclass='rooms.rooms.Room', key='black_hole') black_hole.db.desc = ( "The room where all objects go to die. It is the default home for " "objects that are considered worthless. Any object entering this room is " "automatically deleted via the at_object_receive method.") black_hole.tags.add('black_hole', category='rooms') # Statis Chamber statis_chamber = create_object(typeclass='rooms.rooms.Room', key='statis_chamber') statis_chamber.db.desc = ( "This room holds objects indefinitely. It is the default home for " "objects that are of significant value, unique, or otherwise should " "not be destroyed for any reason.") statis_chamber.tags.add('statis_chamber', category='rooms') # Trash Bin trash_bin = create_object(typeclass='rooms.rooms.Room', key='trash_bin') trash_bin.db.desc = ( "This room holds objects for 90 days, before being sent to black_hole. " "It is the default home for objects of some value and the destination " "of said objects when discarded by players.") trash_bin.tags.add('trash_bin', category='rooms') # Superuser's equipment generation must take place after the item rooms are generated. # The inventory container requires trash_bin to exist. char1.equip.generate_equipment() # Create the superuser's home room. rm3 = create_object(typeclass='rooms.rooms.Room', key='Main Office') char1.home = rm3 rm3.tags.add('main_office', category='ooc_room') char1.move_to(rm3, quiet=True, move_hooks=False) # Create the Common Room. This is where all portals will lead when entering public OOC areas. rm4 = create_object(typeclass='rooms.rooms.Room', key='Common Room') rm4.tags.add('common_room', category='ooc_room') rm4.tags.add(category='public_ooc') # Connect the main office and common room with exits. exit_rm3_rm4 = create_object(typeclass='travel.exits.Exit', key='a mahogany door', aliases=[ 'door', ], location=rm3, destination=rm4, tags=[ ('door', 'exits'), ]) exit_rm3_rm4.attributes.add('card_dir', 'n') exit_rm3_rm4.tags.add(category='ooc_exit') exit_rm4_rm3 = create_object(typeclass='travel.exits.Exit', key='a mahogany door', aliases=[ 'door', ], location=rm4, destination=rm3, tags=[ ('door', 'exits'), ]) exit_rm4_rm3.attributes.add('card_dir', 's') exit_rm4_rm3.tags.add(category='ooc_exit')
def create_character(new_player, nickname, permissions=None, character_key=None, level=1, typeclass=None, location=None, home=None): """ Helper function, creates a character based on a player's name. """ if not character_key: character_key = GAME_SETTINGS.get("default_player_character_key") if not typeclass: typeclass = settings.BASE_PLAYER_CHARACTER_TYPECLASS if not permissions: permissions = settings.PERMISSION_ACCOUNT_DEFAULT if not home: default_home_key = GAME_SETTINGS.get("default_player_home_key") if default_home_key: rooms = utils.search_obj_data_key(default_home_key) if rooms: home = rooms[0] if not home: rooms = search.search_object(settings.DEFAULT_HOME) if rooms: home = rooms[0] if not location: location = home try: start_location_key = GAME_SETTINGS.get("start_location_key") if start_location_key: rooms = utils.search_obj_data_key(start_location_key) location = rooms[0] except: pass new_character = create.create_object(typeclass, key=new_player.key, location=location, home=home, permissions=permissions) # set character info new_character.set_data_key(character_key, level) new_character.after_creation() # set playable character list new_player.db._playable_characters.append(new_character) # allow only the character itself and the player to puppet this character (and Immortals). new_character.locks.add( "puppet:id(%i) or pid(%i) or perm(Immortals) or pperm(Immortals)" % (new_character.id, new_player.id)) # If no description is set, set a default description if not new_character.db.desc: new_character.db.desc = "This is a Player." # Add nickname if not nickname: nickname = character_key new_character.set_nickname(nickname) # We need to set this to have @ic auto-connect to this character new_player.db._last_puppet = new_character return new_character
def match(self): """ Match opponents according to character's scores. The longer a character in the queue, the score is higher. The nearer of two character's rank, the score is higher. """ if len(self.queue) < 2: return time_now = time.time() candidates = [] count = 0 max = self.max_candidates for id in self.queue: if count >= max: break if id in self.preparing: continue characters = search_object("#%s" % id) if not characters or characters[0].is_in_combat(): continue candidates.append(id) count += 1 max_score = 0 opponents = () for i in xrange(len(candidates) - 1): for j in xrange(i + 1, len(candidates)): score_A = time_now - self.waiting_time[candidates[i]] score_B = time_now - self.waiting_time[candidates[j]] honour_A = HONOURS_MAPPER.get_honour_by_id(candidates[i], 0) honour_B = HONOURS_MAPPER.get_honour_by_id(candidates[j], 0) score_C = self.max_honour_diff - math.fabs(honour_A - honour_B) if score_A <= self.min_waiting_time or score_B <= self.min_waiting_time or score_C <= 0: break score = score_A + score_B + score_C if score > max_score: max_score = score opponents = candidates[i], candidates[j] if opponents: self.preparing[opponents[0]] = {"time": time.time(), "opponent": opponents[1], "confirmed": False} self.preparing[opponents[1]] = {"time": time.time(), "opponent": opponents[0], "confirmed": False} character_A = search_object("#%s" % opponents[0]) character_B = search_object("#%s" % opponents[1]) if character_A: character_A[0].msg({"prepare_match": self.preparing_time}) if character_B: character_B[0].msg({"prepare_match": self.preparing_time}) call_id = reactor.callLater(self.preparing_time, self.fight, opponents) self.preparing[opponents[0]]["call_id"] = call_id self.preparing[opponents[1]]["call_id"] = call_id self.ave_samples.append(time_now - self.waiting_time[opponents[0]]) self.ave_samples.append(time_now - self.waiting_time[opponents[1]]) while len(self.ave_samples) > self.ave_samples_number: self.ave_samples.popleft() self.ave_waiting = float(sum(self.ave_samples)) / len(self.ave_samples)
def fight(self, opponents): """ Create a combat. """ confirmed0 = opponents[0] in self.preparing and self.preparing[ opponents[0]]["confirmed"] confirmed1 = opponents[1] in self.preparing and self.preparing[ opponents[1]]["confirmed"] if not confirmed0 and not confirmed1: self.remove_by_id(opponents[0]) self.remove_by_id(opponents[1]) opponent0 = search_object("#%s" % opponents[0]) opponent0[0].msg({ "match_rejected": opponents[0], "left_combat_queue": "" }) opponent1 = search_object("#%s" % opponents[1]) opponent1[0].msg({ "match_rejected": opponents[1], "left_combat_queue": "" }) elif not confirmed0: # opponents 0 not confirmed self.remove_by_id(opponents[0]) if opponents[1] in self.preparing: del self.preparing[opponents[1]] opponent0 = search_object("#%s" % opponents[0]) opponent0[0].msg({ "match_rejected": opponents[0], "left_combat_queue": "" }) opponent1 = search_object("#%s" % opponents[1]) opponent1[0].msg({"match_rejected": opponents[0]}) elif not confirmed1: # opponents 1 not confirmed self.remove_by_id(opponents[1]) if opponents[0] in self.preparing: del self.preparing[opponents[0]] opponent1 = search_object("#%s" % opponents[1]) opponent1[0].msg({ "match_rejected": opponents[1], "left_combat_queue": "" }) opponent0 = search_object("#%s" % opponents[0]) opponent0[0].msg({"match_rejected": opponents[1]}) elif confirmed0 and confirmed1: # all confirmed opponent0 = search_object("#%s" % opponents[0]) opponent1 = search_object("#%s" % opponents[1]) # create a new combat handler chandler = create_script(settings.HONOUR_COMBAT_HANDLER) # set combat team and desc chandler.set_combat(combat_type=CombatType.HONOUR, teams={ 1: [opponent0[0]], 2: [opponent1[0]] }, desc=_("Fight of Honour"), timeout=0) self.remove_by_id(opponents[0]) self.remove_by_id(opponents[1])