Pyom.1.00a/
Pyom.1.00a/pysrc/miniboa/
"""
#**************************************************************************
 *  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(&current_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