""" #************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ #************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #*********** * Ported to Python by Davion of MudBytes.net * Using Miniboa https://code.google.com/p/miniboa/ * Now using Python 3 version https://code.google.com/p/miniboa-py3/ ************/ """ from collections import OrderedDict from merc import * from nanny import con_playing, con_gen_groups from handler import * from act_move import dir_name from db import get_extra_descr from const import skill_table, guild_table, pc_race_table, int_app from tables import clan_table from fight import is_safe where_name = ["<used as light> ", "<worn on finger> ", "<worn on finger> ", "<worn around neck> ", "<worn around neck> ", "<worn on torso> ", "<worn on head> ", "<worn on legs> ", "<worn on feet> ", "<worn on hands> ", "<worn on arms> ", "<worn as shield> ", "<worn about body> ", "<worn about waist> ", "<worn around wrist> ", "<worn around wrist> ", "<wielded> ", "<held> ", "<floating nearby> "] # for keeping track of the player count */ max_on = 0 def format_obj_to_char(obj, ch, fShort): buf = '' if (fShort and not obj.short_descr) or not obj.description: return buf if IS_OBJ_STAT(obj, ITEM_INVIS): buf += "(Invis) " if IS_AFFECTED(ch, AFF_DETECT_EVIL) \ and IS_OBJ_STAT(obj, ITEM_EVIL): buf += "(Red Aura) " if IS_AFFECTED(ch, AFF_DETECT_GOOD) \ and IS_OBJ_STAT(obj, ITEM_BLESS): buf += "(Blue Aura) " if IS_AFFECTED(ch, AFF_DETECT_MAGIC) \ and IS_OBJ_STAT(obj, ITEM_MAGIC): buf += "(Magical) " if IS_OBJ_STAT(obj, ITEM_GLOW): buf += "(Glowing) " if IS_OBJ_STAT(obj, ITEM_HUM): buf += "(Humming) " if fShort: if obj.short_descr: buf += obj.short_descr else: if obj.description: buf += obj.description return buf # * Show a list to a character. # * Can coalesce duplicated items. def show_list_to_char(clist, ch, fShort, fShowNothing): if not ch.desc: return objects = OrderedDict() for obj in clist: if obj.wear_loc == WEAR_NONE and ch.can_see_obj(obj): frmt = format_obj_to_char(obj, ch, fShort) if frmt not in objects: objects[frmt] = 1 else: objects[frmt] += 1 if not objects and fShowNothing: if IS_NPC(ch) or IS_SET(ch.comm, COMM_COMBINE): ch.send(" ") ch.send("Nothing.\n") #* Output the formatted list. for desc, count in objects.items(): if IS_NPC(ch) or IS_SET(ch.comm, COMM_COMBINE) and count > 1: ch.send("(%2d) %s\n" % (count, desc)) else: for i in range(count): ch.send(" %s\n" % desc) def show_char_to_char_0(victim, ch): buf = '' if IS_SET(victim.comm, COMM_AFK): buf += "[AFK] " if IS_AFFECTED(victim, AFF_INVISIBLE): buf += "(Invis) " if victim.invis_level >= LEVEL_HERO: buf += "(Wizi) " if IS_AFFECTED(victim, AFF_HIDE): buf += "(Hide) " if IS_AFFECTED(victim, AFF_CHARM): buf += "(Charmed) " if IS_AFFECTED(victim, AFF_PASS_DOOR): buf += "(Translucent) " if IS_AFFECTED(victim, AFF_FAERIE_FIRE): buf += "(Pink Aura) " if IS_EVIL(victim) and IS_AFFECTED(ch, AFF_DETECT_EVIL): buf += "(Red Aura) " if IS_GOOD(victim) and IS_AFFECTED(ch, AFF_DETECT_GOOD): buf += "(Golden Aura) " if IS_AFFECTED(victim, AFF_SANCTUARY): buf += "(White Aura) " if not IS_NPC(victim) and IS_SET(victim.act, PLR_KILLER): buf += "(KILLER) " if not IS_NPC(victim) and IS_SET(victim.act, PLR_THIEF): buf += "(THIEF) " if victim.position == victim.start_pos and victim.long_descr: buf += victim.long_descr ch.send(buf) return buf += PERS(victim, ch) if not IS_NPC(victim) and not IS_SET(ch.comm, COMM_BRIEF) \ and victim.position == POS_STANDING and not ch.on: buf += victim.pcdata.title if victim.position == POS_DEAD: buf += " is DEAD!!" elif victim.position == POS_MORTAL: buf += " is mortally wounded." elif victim.position == POS_INCAP: buf += " is incapacitated." elif victim.position == POS_STUNNED: buf += " is lying here stunned." elif victim.position == POS_SLEEPING: if victim.on: if IS_SET(victim.on.value[2], SLEEP_AT): buf += " is sleeping at %s." % (victim.on.short_descr) elif IS_SET(victim.on.value[2], SLEEP_ON): buf += " is sleeping on %s." % (victim.on.short_descr) else: buf += " is sleeping in %s." % (victim.on.short_descr) else: buf += " is sleeping here." elif victim.position == POS_RESTING: if victim.on: if IS_SET(victim.on.value[2], REST_AT): buf += " is resting at %s." % victim.on.short_descr elif IS_SET(victim.on.value[2], REST_ON): buf += " is resting on %s." % victim.on.short_descr else: buf += " is resting in %s." % victim.on.short_descr else: buf += " is resting here." elif victim.position == POS_SITTING: if victim.on: if IS_SET(victim.on.value[2], SIT_AT): buf += " is sitting at %s." % victim.on.short_descr elif IS_SET(victim.on.value[2], SIT_ON): buf += " is sitting on %s." % victim.on.short_descr else: buf += " is sitting in %s." % victim.on.short_descr else: buf += " is sitting here." elif victim.position == POS_STANDING: if victim.on: if IS_SET(victim.on.value[2], STAND_AT): buf += " is standing at %s." % victim.on.short_descr elif IS_SET(victim.on.value[2], STAND_ON): buf += " is standing on %s." % victim.on.short_descr else: buf += " is standing in %s." % victim.on.short_descr else: buf += " is here." elif victim.position == POS_FIGHTING: buf += " is here, fighting " if not victim.fighting: buf += "thin air??" elif victim.fighting == ch: buf += "YOU!" elif victim.in_room == victim.fighting.in_room: buf += "%s." % PERS(victim.fighting, ch) else: buf += "someone who left??" buf = buf.capitalize() ch.send(buf + "\n") return def show_char_to_char_1(victim, ch): if victim.can_see(ch): if ch == victim: act("$n looks at $mself.", ch, None, None, TO_ROOM) else: act("$n looks at you.", ch, None, victim, TO_VICT) act("$n looks at $N.", ch, None, victim, TO_NOTVICT) if victim.description: ch.send(victim.description + "\n") else: act("You see nothing special about $M.", ch, None, victim, TO_CHAR) if victim.max_hit > 0: percent = (100 * victim.hit) // victim.max_hit else: percent = -1 buf = PERS(victim, ch) if percent >= 100: buf += " is in excellent condition.\n" elif percent >= 90: buf += " has a few scratches.\n" elif percent >= 75: buf += " has some small wounds and bruises.\n" elif percent >= 50: buf += " has quite a few wounds.\n" elif percent >= 30: buf += " has some big nasty wounds and scratches.\n" elif percent >= 15: buf += " looks pretty hurt.\n" elif percent >= 0: buf += " is in awful condition.\n" else: buf += " is bleeding to death.\n" buf = buf.capitalize() ch.send(buf) found = False for iWear in range(MAX_WEAR): obj = victim.get_eq(iWear) if obj and ch.can_see_obj(obj): if not found: act("$N is using:", ch, None, victim, TO_CHAR) found = True ch.send(where_name[iWear]) ch.send(format_obj_to_char(obj, ch, True) + "\n") if victim != ch and not IS_NPC(ch) \ and random.randint(1, 99) < ch.get_skill("peek"): ch.send("\nYou peek at the inventory:\n") check_improve(ch, 'peek', True, 4) show_list_to_char(victim.carrying, ch, True, True) return def show_char_to_char(list, ch): for rch in list: if rch == ch: continue if ch.get_trust() < rch.invis_level: continue if ch.can_see(rch): show_char_to_char_0(rch, ch) ch.send("\n") elif ch.in_room.is_dark() and IS_AFFECTED(rch, AFF_INFRARED): ch.send("You see glowing red eyes watching YOU!\n") def check_blind(ch): if not IS_NPC(ch) and IS_SET(ch.act, PLR_HOLYLIGHT): return True if IS_AFFECTED(ch, AFF_BLIND): ch.send("You can't see a thing!\n") return False return True # changes your scroll */ def do_scroll(self, argument): ch = self argument, arg = read_word(argument) if not arg: if ch.lines == 0: ch.send("You do not page long messages.\n") else: ch.send("You currently display %d lines per page.\n" % ( ch.lines + 2)) return if not arg.isdigit(): ch.send("You must provide a number.\n") return lines = int(arg) if lines == 0: ch.send("Paging disabled.\n") ch.lines = 0 return if lines < 10 or lines > 100: ch.send("You must provide a reasonable number.\n") return ch.send("Scroll set to %d lines.\n" % lines) ch.lines = lines - 2 # RT does socials */ def do_socials(self, argument): ch = self for col, social in enumerate(social_list): ch.send("%-12s" % social.name) if col % 6 == 0: ch.send("\n") if len(social_list) % 6 != 0: ch.send("\n") return # RT Commands to replace news, motd, imotd, etc from ROM */ def do_motd(self, argument): ch = self ch.do_help("motd") def do_imotd(self, argument): ch = self ch.do_help("imotd") def do_rules(self, argument): ch = self ch.do_help("rules") def do_story(self, argument): ch = self ch.do_help("story") def do_wizlist(self, argument): ch = self ch.do_help("wizlist") # RT this following section holds all the auto commands from ROM, as well as # replacements for config */ def do_autolist(self, argument): ch = self # lists most player flags */ if IS_NPC(ch): return ch.send(" action status\n") ch.send("---------------------\n") ch.send("autoassist ") if IS_SET(ch.act, PLR_AUTOASSIST): ch.send("ON\n") else: ch.send("OFF\n") ch.send("autoexit ") if IS_SET(ch.act, PLR_AUTOEXIT): ch.send("ON\n") else: ch.send("OFF\n") ch.send("autogold ") if IS_SET(ch.act, PLR_AUTOGOLD): ch.send("ON\n") else: ch.send("OFF\n") ch.send("autoloot ") if IS_SET(ch.act, PLR_AUTOLOOT): ch.send("ON\n") else: ch.send("OFF\n") ch.send("autosac ") if IS_SET(ch.act, PLR_AUTOSAC): ch.send("ON\n") else: ch.send("OFF\n") ch.send("autosplit ") if IS_SET(ch.act, PLR_AUTOSPLIT): ch.send("ON\n") else: ch.send("OFF\n") ch.send("compact mode ") if IS_SET(ch.comm, COMM_COMPACT): ch.send("ON\n") else: ch.send("OFF\n") ch.send("prompt ") if IS_SET(ch.comm, COMM_PROMPT): ch.send("ON\n") else: ch.send("OFF\n") ch.send("combine items ") if IS_SET(ch.comm, COMM_COMBINE): ch.send("ON\n") else: ch.send("OFF\n") if not IS_SET(ch.act, PLR_CANLOOT): ch.send("Your corpse is safe from thieves.\n") else: ch.send("Your corpse may be looted.\n") if IS_SET(ch.act, PLR_NOSUMMON): ch.send("You cannot be summoned.\n") else: ch.send("You can be summoned.\n") if IS_SET(ch.act, PLR_NOFOLLOW): ch.send("You do not welcome followers.\n") else: ch.send("You accept followers.\n") def do_autoassist(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_AUTOASSIST): ch.send("Autoassist removed.\n") ch.act = REMOVE_BIT(ch.act, PLR_AUTOASSIST) else: ch.send("You will now assist when needed.\n") ch.act = SET_BIT(ch.act, PLR_AUTOASSIST) def do_autoexit(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_AUTOEXIT): ch.send("Exits will no longer be displayed.\n") ch.act = REMOVE_BIT(ch.act, PLR_AUTOEXIT) else: ch.send("Exits will now be displayed.\n") ch.act = SET_BIT(ch.act, PLR_AUTOEXIT) def do_autogold(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_AUTOGOLD): ch.send("Autogold removed.\n") ch.act = REMOVE_BIT(ch.act, PLR_AUTOGOLD) else: ch.send("Automatic gold looting set.\n") ch.act = SET_BIT(ch.act, PLR_AUTOGOLD) def do_autoloot(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_AUTOLOOT): ch.send("Autolooting removed.\n") ch.act = REMOVE_BIT(ch.act, PLR_AUTOLOOT) else: ch.send("Automatic corpse looting set.\n") ch.act = SET_BIT(ch.act, PLR_AUTOLOOT) def do_autosac(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_AUTOSAC): ch.send("Autosacrificing removed.\n") ch.act = REMOVE_BIT(ch.act, PLR_AUTOSAC) else: ch.send("Automatic corpse sacrificing set.\n") ch.act = SET_BIT(ch.act, PLR_AUTOSAC) def do_autosplit(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_AUTOSPLIT): ch.send("Autosplitting removed.\n") ch.act = REMOVE_BIT(ch.act, PLR_AUTOSPLIT) else: ch.send("Automatic gold splitting set.\n") ch.act = SET_BIT(ch.act, PLR_AUTOSPLIT) def do_brief(self, argument): ch = self if IS_SET(ch.comm, COMM_BRIEF): ch.send("Full descriptions activated.\n") ch.comm = REMOVE_BIT(ch.comm, COMM_BRIEF) else: ch.send("Short descriptions activated.\n") ch.comm = SET_BIT(ch.comm, COMM_BRIEF) def do_compact(self, argument): ch = self if IS_SET(ch.comm, COMM_COMPACT): ch.send("Compact mode removed.\n") ch.comm = REMOVE_BIT(ch.comm, COMM_COMPACT) else: ch.send("Compact mode set.\n") ch.comm = SET_BIT(ch.comm, COMM_COMPACT) def do_show(self, argument): ch = self if IS_SET(ch.comm, COMM_SHOW_AFFECTS): ch.send("Affects will no longer be shown in score.\n") ch.comm = REMOVE_BIT(ch.comm, COMM_SHOW_AFFECTS) else: ch.send("Affects will now be shown in score.\n") ch.comm = SET_BIT(ch.comm, COMM_SHOW_AFFECTS) def do_prompt(self, argument): ch = self if not argument: if IS_SET(ch.comm, COMM_PROMPT): ch.send("You will no longer see prompts.\n") ch.comm = REMOVE_BIT(ch.comm, COMM_PROMPT) else: ch.send("You will now see prompts.\n") ch.comm = SET_BIT(ch.comm, COMM_PROMPT) return if argument.lower() == "all": buf = "<%hhp %mm %vmv> " else: if len(argument) > 50: argument = argument[:50] buf = argument if buf.endswith("%c"): buf += " " ch.prompt = buf ch.send("Prompt set to %s\n" % ch.prompt) return def do_combine(self, argument): ch = self if IS_SET(ch.comm, COMM_COMBINE): ch.send("Long inventory selected.\n") ch.comm = REMOVE_BIT(ch.comm, COMM_COMBINE) else: ch.send("Combined inventory selected.\n") ch.comm = SET_BIT(ch.comm, COMM_COMBINE) def do_noloot(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_CANLOOT): ch.send("Your corpse is now safe from thieves.\n") ch.act = REMOVE_BIT(ch.act, PLR_CANLOOT) else: ch.send("Your corpse may now be looted.\n") ch.act = SET_BIT(ch.act, PLR_CANLOOT) def do_nofollow(self, argument): ch = self if IS_NPC(ch): return if IS_SET(ch.act, PLR_NOFOLLOW): ch.send("You now accept followers.\n") ch.act = REMOVE_BIT(ch.act, PLR_NOFOLLOW) else: ch.send("You no longer accept followers.\n") ch.act = SET_BIT(ch.act, PLR_NOFOLLOW) die_follower(ch) def do_nosummon(self, argument): ch = self if IS_NPC(ch): if IS_SET(ch.imm_flags, IMM_SUMMON): ch.send("You are no longer immune to summon.\n") ch.imm_flags = REMOVE_BIT(ch.imm_flags, IMM_SUMMON) else: ch.send("You are now immune to summoning.\n") ch.imm_flags = SET_BIT(ch.imm_flags, IMM_SUMMON) else: if IS_SET(ch.act, PLR_NOSUMMON): ch.send("You are no longer immune to summon.\n") ch.act = REMOVE_BIT(ch.act, PLR_NOSUMMON) else: ch.send("You are now immune to summoning.\n") ch.act = SET_BIT(ch.act, PLR_NOSUMMON) def do_look(ch, argument): if not ch.desc: return if ch.position < POS_SLEEPING: ch.send("You can't see anything but stars!\n") return if ch.position == POS_SLEEPING: ch.send("You can't see anything, you're sleeping!\n") return if not check_blind(ch): return if not IS_NPC(ch) and not IS_SET(ch.act, PLR_HOLYLIGHT) \ and ch.in_room.is_dark(): ch.send("It is pitch black ... \n") show_char_to_char(ch.in_room.people, ch) return argument, arg1 = read_word(argument) argument, arg2 = read_word(argument) number, arg3 = number_argument(arg1) count = 0 if not arg1 or arg1 == "auto": # 'look' or 'look auto' */ ch.send(ch.in_room.name) if IS_IMMORTAL(ch) and (IS_NPC(ch) or IS_SET(ch.act, PLR_HOLYLIGHT)): ch.send(" [Room %d]" % ch.in_room.vnum) ch.send("\n") if not arg1 or (not IS_NPC(ch) and not IS_SET(ch.comm, COMM_BRIEF)): ch.send(" %s" % ch.in_room.description) if not IS_NPC(ch) and IS_SET(ch.act, PLR_AUTOEXIT): ch.send("\n") ch.do_exits("auto") show_list_to_char(ch.in_room.contents, ch, False, False) show_char_to_char(ch.in_room.people, ch) return if arg1 == "i" or arg1 == "in" or arg1 == "on": # 'look in' */ if not arg2: ch.send("Look in what?\n") return obj = ch.get_obj_here(arg2) if not obj: ch.send("You do not see that here.\n") return item_type = obj.item_type if item_type == ITEM_DRINK_CON: if obj.value[1] <= 0: ch.send("It is empty.\n") return if obj.value[1] < obj.value[0] // 4: amnt = "less than half-" elif obj.value[1] < 3 * obj.value[0] // 4: amnt = "abount half-" else: amnt = "more than half-" ch.send("It's %sfilled with a %s liquid.\n" % ( amnt, liq_table[obj.value[2]].liq_color)) elif item_type == ITEM_CONTAINER or item_type == ITEM_CORPSE_NPC \ or item_type == ITEM_CORPSE_PC: if IS_SET(obj.value[1], CONT_CLOSED): ch.send("It is closed.\n") return act("$p holds:", ch, obj, None, TO_CHAR) show_list_to_char(obj.contains, ch, True, True) return else: ch.send("That is not a container.\n") return victim = ch.get_char_room(arg1) if victim: show_char_to_char_1(victim, ch) return obj_list = ch.carrying obj_list.extend(ch.in_room.contents) for obj in obj_list: if ch.can_see_obj(obj): #player can see object */ pdesc = get_extra_descr(arg3, obj.extra_descr) if pdesc: count += 1 if count == number: ch.send(pdesc) return else: continue pdesc = get_extra_descr(arg3, obj.pIndexData.extra_descr) if pdesc: count += 1 if count == number: ch.send(pdesc) return else: continue if arg3.lower() in obj.name.lower: count += 1 if count == number: ch.send("%s\n" % obj.description) return pdesc = get_extra_descr(arg3, ch.in_room.extra_descr) if pdesc: count += 1 if count == number: ch.send(pdesc) return if count > 0 and count != number: if count == 1: ch.send("You only see one %s here.\n" % arg3) else: ch.send("You only see %d of those here.\n" % count) return if "north".startswith(arg1): door = 0 elif "east".startswith(arg1): door = 1 elif "south".startswith(arg1): door = 2 elif "west".startswith(arg1): door = 3 elif "up".startswith(arg1): door = 4 elif "down".startswith(arg1): door = 5 else: ch.send("You do not see that here.\n") return # 'look direction' */ if door not in ch.in_room.exit or not ch.in_room.exit[door]: ch.send("Nothing special there.\n") return pexit = ch.in_room.exit[door] if pexit.description: ch.send(pexit.description) else: ch.send("Nothing special there.\n") if pexit.keyword and pexit.keyword.strip(): if IS_SET(pexit.exit_info, EX_CLOSED): act("The $d is closed.", ch, None, pexit.keyword, TO_CHAR) elif IS_SET(pexit.exit_info, EX_ISDOOR): act("The $d is open.", ch, None, pexit.keyword, TO_CHAR) return # RT added back for the hell of it */ def do_read(self, argument): ch = self ch.do_look(argument) def do_examine(self, argument): ch = self argument, arg = read_word(argument) if not arg: ch.send("Examine what?\n") return ch.do_look(arg) buf = "" obj = ch.get_obj_here(arg) if obj: if obj.item_type == ITEM_JUKEBOX: ch.do_play("list") elif obj.item_type == ITEM_MONEY: if obj.value[0] == 0: if obj.value[1] == 0: buf = "Odd...there's no coins in the pile.\n" elif obj.value[1] == 1: buf = "Wow. One gold coin.\n" else: buf = "There are %d gold coins in the pile.\n" % obj.value[1] elif obj.value[1] == 0: if obj.value[0] == 1: buf = "Wow. One silver coin.\n" else: buf = "There are %d silver coins in the pile.\n" % obj.value[0] else: buf = "There are %d gold and %d silver coins in the pile.\n" % (obj.value[1], obj.value[0]) ch.send(buf) elif obj.item_type == ITEM_DRINK_CON \ or obj.item_type == ITEM_CONTAINER \ or obj.item_type == ITEM_CORPSE_NPC \ or obj.item_type == ITEM_CORPSE_PC: ch.do_look("in %s" % argument) # * Thanks to Zrin for auto-exit part. def do_exits(self, argument): ch = self fAuto = argument == "auto" buf = '' if not check_blind(ch): return if fAuto: buf += "[Exits:" elif IS_IMMORTAL(ch): buf += "Obvious exits from room %d:\n" % ch.in_room.vnum else: buf += "Obvious exits:\n" found = False for door, pexit in enumerate(ch.in_room.exit): if pexit and pexit.to_room and ch.can_see_room(pexit.to_room) \ and not IS_SET(pexit.exit_info, EX_CLOSED): found = True if fAuto: buf += " %s" % dir_name[door] else: buf += "%-5s - %s" % (dir_name[door].capitalize(), "Too dark to tell" if pexit.to_room.is_dark() else pexit.to_room.name) if IS_IMMORTAL(ch): buf += " (room %d)\n" % pexit.to_room.vnum else: buf += "\n" if not found: buf += " none" if fAuto else "None.\n" if fAuto: buf += "]\n" ch.send(buf) return def do_worth(self, argument): ch = self if IS_NPC(ch): ch.send("You have %ld gold and %ld silver.\n" % (ch.gold, ch.silver)) ch.send(buf) return ch.send("You have %ld gold, %ld silver, and %d experience (%d exp to level).\n" % ( ch.gold, ch.silver, ch.exp, (ch.level + 1) * ch.exp_per_level(ch.pcdata.points) - ch.exp)) def do_score(self, argument): ch = self ch.send("You are %s%s, level %d, %d years old (%d hours).\n" % (ch.name, "" if IS_NPC(ch) else ch.pcdata.title, ch.level, ch.get_age(), (ch.played + (int)(current_time - ch.logon)) // 3600)) if ch.get_trust() != ch.level: ch.send("You are trusted at level %d.\n" % ch.get_trust()) ch.send("Race: %s Sex: %s Class: %s\n" % (ch.race.name, "sexless" if ch.sex == 0 else "male" if ch.sex == 1 else "female", "mobile" if IS_NPC(ch) else ch.guild.name)) ch.send("You have %d/%d hit, %d/%d mana, %d/%d movement.\n" % (ch.hit, ch.max_hit, ch.mana, ch.max_mana, ch.move, ch.max_move)) ch.send("You have %d practices and %d training sessions.\n" % (ch.practice, ch.train)) ch.send("You are carrying %d/%d items with weight %ld/%d pounds.\n" % (ch.carry_number, ch.can_carry_n(), get_carry_weight(ch) // 10, ch.can_carry_w() // 10)) ch.send("Str: %d(%d) Int: %d(%d) Wis: %d(%d) Dex: %d(%d) Con: %d(%d)\n" % ( ch.perm_stat[STAT_STR], ch.get_curr_stat(STAT_STR), ch.perm_stat[STAT_INT], ch.get_curr_stat(STAT_INT), ch.perm_stat[STAT_WIS], ch.get_curr_stat(STAT_WIS), ch.perm_stat[STAT_DEX], ch.get_curr_stat(STAT_DEX), ch.perm_stat[STAT_CON], ch.get_curr_stat(STAT_CON))) ch.send("You have scored %d exp, and have %ld gold and %ld silver coins.\n" %(ch.exp, ch.gold, ch.silver)) # RT shows exp to level */ if not IS_NPC(ch) and ch.level < LEVEL_HERO: ch.send("You need %d exp to level.\n" % ((ch.level + 1) * ch.exp_per_level(ch.pcdata.points) - ch.exp)) ch.send("Wimpy set to %d hit points.\n" % ch.wimpy) if not IS_NPC(ch) and ch.pcdata.condition[COND_DRUNK] > 10: ch.send("You are drunk.\n") if not IS_NPC(ch) and ch.pcdata.condition[COND_THIRST] == 0: ch.send("You are thirsty.\n") if not IS_NPC(ch) and ch.pcdata.condition[COND_HUNGER] == 0: ch.send("You are hungry.\n") if ch.position == POS_DEAD: ch.send("You are DEAD!!\n") elif ch.position == POS_MORTAL: ch.send("You are mortally wounded.\n") elif ch.position == POS_INCAP: ch.send("You are incapacitated.\n") elif ch.position == POS_STUNNED: ch.send("You are stunned.\n") elif ch.position == POS_SLEEPING: ch.send("You are sleeping.\n") elif ch.position == POS_RESTING: ch.send("You are resting.\n") elif ch.position == POS_SITTING: ch.send("You are sitting.\n") elif ch.position == POS_STANDING: ch.send("You are standing.\n") elif ch.position == POS_FIGHTING: ch.send("You are fighting.\n") # print AC values */ if ch.level >= 25: ch.send("Armor: pierce: %d bash: %d slash: %d magic: %d\n" % ( GET_AC(ch, AC_PIERCE), GET_AC(ch, AC_BASH), GET_AC(ch, AC_SLASH), GET_AC(ch, AC_EXOTIC))) for i in range(4): temp = '' if i == AC_PIERCE: temp = "piercing" elif i == AC_BASH: temp = "bashing" elif i == AC_SLASH: temp = "slashing" elif i == AC_EXOTIC: temp = "magic" else: temp = "error" ch.send("You are ") if GET_AC(ch, i) >= 101: ch.send("hopelessly vulnerable to %s.\n" % temp) elif GET_AC(ch, i) >= 80: ch.send("defenseless against %s.\n" % temp) elif GET_AC(ch, i) >= 60: ch.send("barely protected from %s.\n" % temp) elif GET_AC(ch, i) >= 40: ch.send("slightly armored against %s.\n" % temp) elif GET_AC(ch, i) >= 20: ch.send("somewhat armored against %s.\n" % temp) elif GET_AC(ch, i) >= 0: ch.send("armored against %s.\n" % temp) elif GET_AC(ch, i) >= -20: ch.send("well-armored against %s.\n" % temp) elif GET_AC(ch, i) >= -40: ch.send("very well-armored against %s.\n" % temp) elif GET_AC(ch, i) >= -60: ch.send("heavily armored against %s.\n" % temp) elif GET_AC(ch, i) >= -80: ch.send("superbly armored against %s.\n" % temp) elif GET_AC(ch, i) >= -100: ch.send("almost invulnerable to %s.\n" % temp) else: ch.send("divinely armored against %s.\n" % temp) # RT wizinvis and holy light */ if IS_IMMORTAL(ch): ch.send("Holy Light: ") if IS_SET(ch.act, PLR_HOLYLIGHT): ch.send("on") else: ch.send("off") if ch.invis_level: ch.send(" Invisible: level %d" % ch.invis_level) if ch.incog_level: ch.send(" Incognito: level %d" % ch.incog_level) ch.send("\n") if ch.level >= 15: ch.send("Hitroll: %d Damroll: %d.\n" % (GET_HITROLL(ch), GET_DAMROLL(ch))) if ch.level >= 10: ch.send("Alignment: %d. " % ch.alignment) ch.send("You are ") if ch.alignment > 900: ch.send("angelic.\n") elif ch.alignment > 700: ch.send("saintly.\n") elif ch.alignment > 350: ch.send("good.\n") elif ch.alignment > 100: ch.send("kind.\n") elif ch.alignment > -100: ch.send("neutral.\n") elif ch.alignment > -350: ch.send("mean.\n") elif ch.alignment > -700: ch.send("evil.\n") elif ch.alignment > -900: ch.send("demonic.\n") else: ch.send("satanic.\n") if IS_SET(ch.comm, COMM_SHOW_AFFECTS): ch.do_affects("") def do_affects(self, argument): ch = self paf_last = None if ch.affected: ch.send("You are affected by the following spells:\n") for paf in ch.affected: if paf_last and paf.type == paf_last.type: if ch.level >= 20: ch.send(" ") else: continue else: ch.send("Spell: %-15s" % paf.type) if ch.level >= 20: ch.send(": modifies %s by %d " % (affect_loc_name(paf.location), paf.modifier)) if paf.duration == -1: ch.send("permanently") else: ch.send("for %d hours" % paf.duration) ch.send("\n") paf_last = paf else: ch.send("You are not affected by any spells.\n") day_name = ["the Moon", "the Bull", "Deception", "Thunder", "Freedom", "the Great Gods", "the Sun"] month_name = ["Winter", "the Winter Wolf", "the Frost Giant", "the Old Forces", "the Grand Struggle", "the Spring", "Nature", "Futility", "the Dragon", "the Sun", "the Heat", "the Battle", "the Dark Shades", "the Shadows", "the Long Shadows", "the Ancient Darkness", "the Great Evil"] def do_time(self, argument): ch = self day = time_info.day + 1 suf = '' if day > 4 and day < 20: suf = "th" elif day % 10 == 1: suf = "st" elif day % 10 == 2: suf = "nd" elif day % 10 == 3: suf = "rd" else: suf = "th" ch.send("It is %d o'clock %s, Day of %s, %d%s the Month of %s.\n" % ( 12 if (time_info.hour % 12 == 0) else time_info.hour % 12, "pm" if time_info.hour >= 12 else "am", day_name[day % 7], day, suf, month_name[time_info.month])) #ch.send("ROM started up at %s\nThe system time is %s.\n", str_boot_time, (char *) ctime(¤t_time) return def do_weather(self, argument): ch = self sky_look = ["cloudless", "cloudy", "rainy", "lit by flashes of lightning"] if not IS_OUTSIDE(ch): ch.send("You can't see the weather indoors.\n") return ch.send("The sky is %s and %s.\n" % (sky_look[weather_info.sky], "a warm southerly breeze blows" if weather_info.change >= 0 else "a cold northern gust blows")) return def do_help(self, argument): ch = self if not argument: argument = "summary" found = [h for h in help_list if h.level <= self.get_trust() and argument.lower() in h.keyword.lower()] for pHelp in found: if ch.desc.is_connected(con_playing): self.send("\n============================================================\n") ch.send(pHelp.keyword) ch.send("\n") text = pHelp.text if pHelp.text[0] == '.': text = pHelp.text[1:] ch.send(text + "\n") # small hack :) */ if ch.desc and ch.desc.connected != con_playing and ch.desc.connected != con_gen_groups: break if not found: self.send("No help on that word.\n") # whois command */ def do_whois(self, argument): ch = self found = False argument, arg = read_word(argument) if not arg: ch.send("You must provide a name.\n") return for d in descriptor_list[:]: if not d.is_connected(con_playing) or not ch.can_see(d.character): continue wch = CH(d) if not ch.can_see(wch): continue if wch.name.lower().startswith(arg): found = True # work out the printing */ guild = wch.guild.who_name if wch.level == MAX_LEVEL - 0: guild = "IMP" elif wch.level == MAX_LEVEL - 1: guild = "CRE" elif wch.level == MAX_LEVEL - 2: guild = "SUP" elif wch.level == MAX_LEVEL - 3: guild = "DEI" elif wch.level == MAX_LEVEL - 4: guild = "GOD" elif wch.level == MAX_LEVEL - 5: guild = "IMM" elif wch.level == MAX_LEVEL - 6: guild = "DEM" elif wch.level == MAX_LEVEL - 7: guild = "ANG" elif wch.level == MAX_LEVEL - 8: guild = "AVA" # a little formatting */ ch.send("[%2d %6s %s] %s%s%s%s%s%s%s%s\n" % ( wch.level, (pc_race_table[wch.race.name].who_name if wch.race.name in pc_race_table else " "), guild, ("(Incog) " if wch.incog_level >= LEVEL_HERO else ""), ("(Wizi) " if wch.invis_level >= LEVEL_HERO else ""), wch.clan.who_name, ("[AFK] " if IS_SET(wch.comm, COMM_AFK) else ""), ("(KILLER) " if IS_SET(wch.act, PLR_KILLER) else ""), ("(THIEF) " if IS_SET(wch.act, PLR_THIEF) else ""), wch.name, ("" if IS_NPC(wch) else wch.pcdata.title))) if not found: ch.send("No one of that name is playing.\n") return # # * New 'who' command originally by Alander of Rivers of Mud. def do_who(self, argument): ch = self fClassRestrict = False fClanRestrict = False fClan = False fRaceRestrict = False fImmortalOnly = False #* Set default arguments. iLevelLower = 0 iLevelUpper = MAX_LEVEL rgfClass = {k:False for k, g in guild_table.items()} rgfRace = {k:False for k, r in pc_race_table.items()} rgfClan = {k:False for k, r in clan_table.items()} #* Parse arguments. nNumber = 0 while True: argument, arg = read_word(argument) if not arg: break if arg.isdigit(): nNumber += 1 if nNumber == 1: iLevelLower = int(arg) elif nNumber == 2: iLevelUpper = int(arg) else: ch.send("Only two level numbers allowed.\n") return else: # Look for classes to turn on. if "immortals".startswith(arg): fImmortalOnly = True else: if arg not in guild_table: if arg not in pc_race_table: if "clan".startswith(arg): fClan = True else: if arg in clan_table: fClanRestrict = True rgfClan[arg] = clan_table[arg] else: ch.send("That's not a valid race, class, or clan.\n") return else: fRaceRestrict = True rgfRace[arg] = pc_race_table[arg] else: fClassRestrict = True rgfClass[arg] = guild_table[arg] # Now show matching chars. nMatch = 0 for d in descriptor_list: #* Check for match against restrictions. #* Don't use trust as that exposes trusted mortals. if not d.is_connected(con_playing) or not ch.can_see(d.character): continue wch = CH(d) if not ch.can_see(wch): continue if wch.level < iLevelLower or wch.level > iLevelUpper \ or (fImmortalOnly and wch.level < LEVEL_IMMORTAL) \ or (fClassRestrict and not rgfClass[wch.guild.name]) \ or (fRaceRestrict and not rgfRace[wch.race.name]) \ or (fClan and not wch.is_clan()) or (fClanRestrict and not rgfClan[wch.clan.name]): continue nMatch += 1 # # Figure out what to print for class. guild = wch.guild.who_name if wch.level == MAX_LEVEL - 0: guild = "IMP" elif wch.level == MAX_LEVEL - 1: guild = "CRE" elif wch.level == MAX_LEVEL - 2: guild = "SUP" elif wch.level == MAX_LEVEL - 3: guild = "DEI" elif wch.level == MAX_LEVEL - 4: guild = "GOD" elif wch.level == MAX_LEVEL - 5: guild = "IMM" elif wch.level == MAX_LEVEL - 6: guild = "DEM" elif wch.level == MAX_LEVEL - 7: guild = "ANG" elif wch.level == MAX_LEVEL - 8: guild = "AVA" # a little formatting */ ch.send("[%2d %6s %s] %s%s%s%s%s%s%s%s\n" % ( wch.level, pc_race_table[wch.race.name].who_name if wch.race.name in pc_race_table else " ", guild, "(Incog) " if wch.incog_level >= LEVEL_HERO else "", "(Wizi) " if wch.invis_level >= LEVEL_HERO else "", wch.clan.who_name, "[AFK] " if IS_SET(wch.comm, COMM_AFK) else "", "(KILLER) " if IS_SET(wch.act, PLR_KILLER) else "", "(THIEF) " if IS_SET(wch.act, PLR_THIEF) else "", wch.name, "" if IS_NPC(wch) else wch.pcdata.title)) ch.send("\nPlayers found: %d\n" % nMatch) return max_on = 0 def do_count(self, argument): global max_on ch = self count = len([d for d in descriptor_list if d.is_connected(con_playing) and ch.can_see(CH(d))]) max_on = max(count, max_on) if max_on == count: ch.send("There are %d characters on, the most so far today.\n" % count) else: ch.send("There are %d characters on, the most on today was %d.\n" % (count, max_on)) def do_inventory(self, argument): ch = self ch.send("You are carrying:\n") show_list_to_char(ch.carrying, ch, True, True) return def do_equipment(self, argument): ch = self ch.send("You are using:\n") found = False for iWear in range(MAX_WEAR): obj = ch.get_eq(iWear) if not obj: continue ch.send(where_name[iWear]) if ch.can_see_obj(obj): ch.send(format_obj_to_char(obj, ch, True) + "\n") else: ch.send("something.\n") found = True if not found: ch.send("Nothing.\n") def do_compare(self, argument): ch = self argument, arg1 = read_word(argument) argument, arg2 = read_word(argument) if not arg1: ch.send("Compare what to what?\n") return obj1 = ch.get_obj_carry(arg1, ch) if not obj1: ch.send("You do not have that item.\n") return obj2 = None if not arg2: for obj2 in ch.carrying: if obj2.wear_loc != WEAR_NONE and ch.can_see_obj(obj2) and obj1.item_type == obj2.item_type \ and (obj1.wear_flags & obj2.wear_flags & ~ITEM_TAKE) != 0: break if not obj2: ch.send("You aren't wearing anything comparable.\n") return else: obj2 = ch.get_obj_carry(arg2, ch) if not obj2: ch.send("You do not have that item.\n") return msg = None value1 = 0 value2 = 0 if obj1 is obj2: msg = "You compare $p to itself. It looks about the same." elif obj1.item_type != obj2.item_type: msg = "You can't compare $p and $P." else: if obj1.item_type == ITEM_ARMOR: value1 = obj1.value[0] + obj1.value[1] + obj1.value[2] value2 = obj2.value[0] + obj2.value[1] + obj2.value[2] elif obj1.item_type == ITEM_WEAPON: if obj1.pIndexData.new_format: value1 = (1 + obj1.value[2]) * obj1.value[1] else: value1 = obj1.value[1] + obj1.value[2] if obj2.pIndexData.new_format: value2 = (1 + obj2.value[2]) * obj2.value[1] else: value2 = obj2.value[1] + obj2.value[2] else: msg = "You can't compare $p and $P." if msg == None: if value1 == value2: msg = "$p and $P look about the same." elif value1 > value2: msg = "$p looks better than $P." else: msg = "$p looks worse than $P." act(msg, ch, obj1, obj2, TO_CHAR) return def do_credits(self, argument): ch = self ch.do_help("diku") return def do_where(self, argument): ch = self argument, arg = read_word(argument) if not arg: ch.send("Players near you:\n") found = False for d in descriptor_list: victim = CH(d) if d.is_connected(con_playing) \ and victim \ and not IS_NPC(victim) \ and victim.in_room \ and not IS_SET(victim.in_room.room_flags,ROOM_NOWHERE) \ and (ch.is_room_owner(victim.in_room) or not victim.in_room.is_private()) \ and victim.in_room.area == ch.in_room.area \ and ch.can_see(victim): found = True ch.send("%-28s %s\n" % (victim.name, victim.in_room.name)) if not found: ch.send("None\n") else: found = False for victim in char_list[:]: if victim.in_room \ and victim.in_room.area == ch.in_room.area \ and not IS_AFFECTED(victim, AFF_HIDE) \ and not IS_AFFECTED(victim, AFF_SNEAK) \ and ch.can_see(victim) \ and arg in victim.name.lower(): found = True ch.send("%-28s %s\n" % (PERS(victim, ch), victim.in_room.name)) break if not found: act("You didn't find any $T.", ch, None, arg, TO_CHAR) return def do_consider(self, argument): ch = self argument, arg = read_word(argument) if not arg: ch.send("Consider killing whom?\n") return victim = ch.get_char_room(arg) if not victim: ch.send("They're not here.\n") return if is_safe(ch,victim): ch.send("Don't even think about it.\n") return diff = victim.level - ch.level if diff <= -10: msg = "You can kill $N naked and weaponless." elif diff <= -5: msg = "$N is no match for you." elif diff <= -2: msg = "$N looks like an easy kill." elif diff <= 1: msg = "The perfect match!" elif diff <= 4: msg = "$N says 'Do you feel lucky, punk?'." elif diff <= 9: msg = "$N laughs at you mercilessly." else: msg = "Death will thank you for your gift." act(msg, ch, None, victim, TO_CHAR) return def set_title(ch, title): if IS_NPC(ch): print ("BUG: Set_title: NPC.") return buf = '' if title[0] != '.' and title[0] != ',' and title[0] != '!' and title[0] != '?': buf += ' ' + title else: buf = title ch.pcdata.title = buf def do_title(self, argument): ch = self if IS_NPC(ch): return if not argument: ch.send("Change your title to what?\n") return if len(argument) > 45: argument = argument[:45] set_title(ch, argument) ch.send("Ok.\n") def do_description(self, argument): ch = self if not argument: if argument[0] == '-': if not ch.description: ch.send("No lines left to remove.\n") return buf = ch.description.split('\n') buf.pop() ch.description = '\n'.join(buf) if len(buf) > 1: ch.send("Your description is:\n") ch.send(ch.description if ch.description else "(None).\n") return else: ch.description = "" ch.send("Description cleared.\n") return if argument[0] == '+': argument = argument[1:].lstrip() if len(argument) + len(ch.description) >= 1024: ch.send("Description too long.\n") return ch.description += argument + "\n" ch.send("Your description is:\n") ch.send(ch.description if ch.description else "(None).\n") return def do_report(self, argument): ch = self ch.send("You say 'I have %d/%d hp %d/%d mana %d/%d mv %d xp.'\n" % ( ch.hit, ch.max_hit, ch.mana, ch.max_mana, ch.move, ch.max_move, ch.exp )) buf = "$n says 'I have %d/%d hp %d/%d mana %d/%d mv %d xp.'" % ( ch.hit, ch.max_hit, ch.mana, ch.max_mana, ch.move, ch.max_move, ch.exp ) act(buf, ch, None, None, TO_ROOM) return def do_practice(self, argument): ch = self if IS_NPC(ch): return if not argument: col = 0 for sn, skill in skill_table.items(): if ch.level < skill.skill_level[ch.guild.name] \ or sn not in ch.pcdata.learned or ch.pcdata.learned[sn] < 1: # skill is not known */) continue ch.send("%-18s %3d%% " % (skill.name, ch.pcdata.learned[sn])) col += 1 if col % 3 == 0: ch.send("\n") if col % 3 != 0: ch.send("\n") ch.send("You have %d practice sessions left.\n" % ch.practice) else: if not IS_AWAKE(ch): ch.send("In your dreams, or what?\n") return mob = None prac_mobs = [mob for mob in ch.in_room.people if IS_NPC(mob) and IS_SET(mob.act, ACT_PRACTICE)][:1] if not prac_mobs: ch.send("You can't do that here.\n") return else: mob = prac_mobs[0] if ch.practice <= 0: ch.send("You have no practice sessions left.\n") return skill = prefix_lookup(skill_table, argument) if not skill or not IS_NPC(ch) \ and (ch.level < skill.skill_level[ch.guild.name] or ch.pcdata.learned[skill.name] < 1 \ or skill.rating[ch.guild.name] == 0): ch.send("You can't practice that.\n") return adept = 100 if IS_NPC(ch) else ch.guild.skill_adept if ch.pcdata.learned[skill.name] >= adept: ch.send("You are already learned at %s.\n" % skill.name) else: ch.practice -= 1 ch.pcdata.learned[skill.name] += int_app[ch.get_curr_stat(STAT_INT)].learn // skill.rating[ch.guild.name] if ch.pcdata.learned[skill.name] < adept: act("You practice $T.", ch, None, skill.name, TO_CHAR) act("$n practices $T.", ch, None, skill.name, TO_ROOM) else: ch.pcdata.learned[skill.name] = adept act("You are now learned at $T.", ch, None, skill.name, TO_CHAR) act("$n is now learned at $T.", ch, None, skill.name, TO_ROOM) return # * 'Wimpy' originally by Dionysos. def do_wimpy(self, argument): ch = self argument, arg = read_word(argument) if not arg: wimpy = ch.max_hit // 5 else: wimpy = int(arg) if wimpy < 0: ch.send("Your courage exceeds your wisdom.\n") return if wimpy > ch.max_hit // 2: ch.send("Such cowardice ill becomes you.\n") return ch.wimpy = wimpy ch.send("Wimpy set to %d hit points.\n" % wimpy) return def do_password(self, argument): ch = self if IS_NPC(ch): return #* Can't use read_word here because it smashes case. #* So we just steal all its code. Bleagh. # -- It actually doesn't now because it loads areas too. Davion. argument, arg1 = read_word(argument, False) argument, arg2 = read_word(argument, False) if not arg1 or not arg2: ch.send("Syntax: password <old> <new>.\n") return if ENCRYPT_PASSWORD: arg1 = hashlib.sha512(arg1).hexdigest() arg2 = hashlib.sha512(arg2).hexdigest() if arg1 == ch.pcdata.pwd: WAIT_STATE(ch, 40) ch.send("Wrong password. Wait 10 seconds.\n") return if len(arg2) < 5: ch.send("New password must be at least five characters long.\n") return #* No tilde allowed because of player file format. # Also now not true. Davion ch.pcdata.pwd = arg2 save_char_obj(ch) ch.send("Ok.\n") return