sunder2.1a/clan/
sunder2.1a/class/
sunder2.1a/class/bak/
sunder2.1a/doc/ideas/
sunder2.1a/gods/
sunder2.1a/i3/
sunder2.1a/log/
sunder2.1a/msgbase/
sunder2.1a/player/
sunder2.1a/src/o/
sunder2.1a/time/
 /***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik Strfeldt, 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.                                                  *
 ***************************************************************************/
/**********************************************************
 *************** S U N D E R M U D *** 2 . 0 **************
 **********************************************************
 * The unique portions of the SunderMud code as well as   *
 * the integration efforts for code from other sources is *
 * based primarily on the efforts of:                     *
 *                                                        *
 * Lotherius <aelfwyne@operamail.com> (Alvin W. Brinson)  *
 *    and many others, see "help sundermud" in the mud.   *
 **********************************************************/

#include "everything.h"
#include "magic.h"

/* command procedures needed */
DECLARE_DO_FUN ( do_exits );
DECLARE_DO_FUN ( do_look );
DECLARE_DO_FUN ( do_help );
DECLARE_DO_FUN ( do_scan );
DECLARE_DO_FUN ( do_copy );
DECLARE_DO_FUN ( do_darkcolors );
DECLARE_DO_FUN ( do_nodarkgrey );
DECLARE_DO_FUN ( do_noflashy   );
DECLARE_DO_FUN ( do_colour     );
DECLARE_DO_FUN ( do_cursor     );
DECLARE_DO_FUN ( do_bank       );
DECLARE_DO_FUN ( do_borrow     );

struct who_slot
{
     CHAR_DATA          *ch;
     struct who_slot    *next;
};

// With two hands only, you can:
// wield & hold, wield and dual, hold & hold, but not wield/hold/light wield/dual/light, etc...
//

/*
 * Local functions.
 */
char    *format_obj_to_char    args ( ( OBJ_DATA * obj, CHAR_DATA * ch, bool fShort ) );
void     show_list_to_char     args ( ( OBJ_DATA * list, CHAR_DATA * ch, bool fShort, bool fShowNothing ) );
void     show_char_to_char_0   args ( ( CHAR_DATA * victim, CHAR_DATA * ch, bool LongLook ) );
void     show_char_to_char_1   args ( ( CHAR_DATA * victim, CHAR_DATA * ch ) );
void     show_char_to_char     args ( ( CHAR_DATA * list, CHAR_DATA * ch, bool LongLook ) );
bool     check_blind           args ( ( CHAR_DATA * ch ) );
void     real_consider 	       args ( ( CHAR_DATA *ch, CHAR_DATA *victim ) );

char *format_obj_to_char ( OBJ_DATA * obj, CHAR_DATA * ch, bool fShort )
{
     static char         buf[MAX_STRING_LENGTH];

     buf[0] = '\0';
     if ( IS_OBJ_STAT ( obj, ITEM_INVIS ) )
          SLCAT ( buf, "{x({BInvis{x) " );
     if ( CAN_DETECT ( ch, DET_EVIL )
          && IS_OBJ_STAT ( obj, ITEM_EVIL ) )
          SLCAT ( buf, "{x({rRed Aura{x) " );
     if ( is_affected ( ch, skill_lookup ( "detect good" ) )
          && IS_OBJ_STAT ( obj, ITEM_BLESS ) )
          SLCAT ( buf, "{x({gGreen Aura{x) " );
     if ( CAN_DETECT ( ch, DET_MAGIC )
          && IS_OBJ_STAT ( obj, ITEM_MAGIC ) )
          SLCAT ( buf, "{x({MMagical{x) " );
     if ( IS_OBJ_STAT ( obj, ITEM_GLOW ) )
          SLCAT ( buf, "{x({YGlowing{x) " );
     if ( IS_OBJ_STAT ( obj, ITEM_HUM ) )
          SLCAT ( buf, "{x({YHumming{x) " );

     if ( fShort )
     {
          if ( obj->short_descr != NULL )
          {
               SLCAT ( buf, obj->short_descr );
               SLCAT ( buf, " {c({w" );
               SLCAT ( buf, obj_cond ( obj ) );
               SLCAT ( buf, "{c){w" );
          }
     }
     else
     {
          if ( obj->description != NULL )
               SLCAT ( buf, obj->description );
     }

     if ( strlen ( buf ) <= 0 )
          SLCAT ( buf, "This object has no description. Please inform the IMP." );
     return buf;
}

/*
 * Show a list to a character.
 * Can coalesce duplicated items.
 */
void show_list_to_char ( OBJ_DATA * list, CHAR_DATA * ch, bool fShort, bool fShowNothing )
{

     BUFFER		*outbuf;
     char              **prgpstrShow;
     int                *prgnShow;
     char               *pstrShow;
     OBJ_DATA           *obj;
     int                 nShow;
     int                 iShow;
     int                 count;
     bool                fCombine;

     if ( ch->desc == NULL )
          return;
     outbuf = buffer_new(1000);
     /*
      * Alloc space for output lines.
      */

     count = 0;
     for ( obj = list; obj != NULL; obj = obj->next_content ) count++;
     prgpstrShow = alloc_mem ( count * sizeof ( char * ), "show_list_to_char" );
     prgnShow = alloc_mem ( count * sizeof ( int ), "show_list_to_char" );
     nShow = 0;

	 /*
	  * Format the list of objects.
	  */
     for ( obj = list; obj != NULL; obj = obj->next_content )
     {
          if ( obj->wear_loc == WEAR_NONE
               && can_see_obj ( ch, obj )
               && !IS_SET ( obj->extra_flags, ITEM_NODISP ) )
          {
               pstrShow = format_obj_to_char ( obj, ch, fShort );
               fCombine = FALSE;

               if ( IS_NPC ( ch ) || IS_SET ( ch->comm, COMM_COMBINE ) )
               {   /* Look for duplicates, case sensitive.
                    * Matches tend to be near end so run loop backwords.
                    */
                    for ( iShow = nShow - 1; iShow >= 0; iShow-- )
                    {
                         if ( !strcmp ( prgpstrShow[iShow], pstrShow ) )
                         {
                              prgnShow[iShow]++;
                              fCombine = TRUE;
                              break;
                         }
                    }
               }
               /*
                * Couldn't combine, or didn't want to.
                */
               if ( !fCombine )
               {
                    prgpstrShow[nShow] = str_dup ( pstrShow );
                    prgnShow[nShow] = 1;
                    nShow++;
               }
          }
     }

	 /*
	  * Output the formatted list.
	  */
     for ( iShow = 0; iShow < nShow; iShow++ )
     {

          if (prgpstrShow[iShow][0] == '\0')
          {
               free_string(prgpstrShow[iShow]);
               continue;
          }

          if ( IS_NPC ( ch ) || IS_SET ( ch->comm, COMM_COMBINE ) )
          {
               if ( prgnShow[iShow] != 1 )
               {
                    bprintf ( outbuf, "(%2d) ", prgnShow[iShow] );
               }
               else
               {
                    bprintf ( outbuf, "     " );
               }
          }
          bprintf (outbuf, prgpstrShow[iShow]);
          bprintf (outbuf, "\n\r" );
          free_string ( prgpstrShow[iShow] );
     }

     if ( fShowNothing && nShow == 0 )
     {
          if ( IS_NPC ( ch ) || IS_SET ( ch->comm, COMM_COMBINE ) )
               send_to_char ( "     ", ch );
          send_to_char ( "Nothing.\n\r", ch );
     }
     else if ( nShow != 0 )      // Can't page nothing, or we'll get gibberish.
          page_to_char(outbuf->data, ch);

     /*
      * Clean up.
      */
     free_mem ( prgpstrShow, count * sizeof ( char * ), "show_list_to_char" );
     free_mem ( prgnShow, count * sizeof ( int ), "show_list_to_char" );

     buffer_free(outbuf);

     return;
}

void show_char_to_char_0 ( CHAR_DATA * victim, CHAR_DATA * ch, bool LongLook )
{
     char       buf[MAX_STRING_LENGTH];
     char       cmdbuf[MSL];
     char	message[MAX_STRING_LENGTH];

     buf[0] = '\0';
     message[0] = '\0';

     if ( !LongLook )
     {
          if ( !IS_NPC ( ch ) )
          {
               if ( IS_NPC ( victim ) && ch->pcdata->questmob > 0 && victim->pIndexData->vnum == ch->pcdata->questmob )
                    SLCAT ( buf, "{Y({RTARGET{Y){x " );
          }
          if ( IS_AFFECTED ( victim, AFF_INVISIBLE ) )    			SLCAT ( buf, "{x({bInvis{x) " );
          if ( !IS_NPC ( victim ) && IS_SET ( victim->act, PLR_WIZINVIS ) ) 	SLCAT ( buf, "{x({mWizi{x) " );
          if ( !IS_NPC ( victim ) && IS_SET ( victim->act, PLR_CLOAK ) ) 	SLCAT ( buf, "{x({mCloak{x) " );
          if ( IS_AFFECTED ( victim, AFF_HIDE ) )    				SLCAT ( buf, "{x({BHide{x) " );
          if ( IS_AFFECTED ( victim, AFF_CHARM ) )    				SLCAT ( buf, "{x({gCharmed{x) " );
          if ( IS_AFFECTED ( victim, AFF_PASS_DOOR ) )    			SLCAT ( buf, "{x({CTranslucent{x) " );
          if ( IS_AFFECTED ( victim, AFF_FAERIE_FIRE ) )    			SLCAT ( buf, "{x({RPink Aura{x) " );
          if ( IS_EVIL ( victim ) && CAN_DETECT ( ch, DET_EVIL ) )              SLCAT ( buf, "{x({rRed Aura{x) " );
          if ( IS_GOOD ( victim )
               && is_affected ( ch, skill_lookup ( "detect good" ) ) )          SLCAT ( buf, "{x({gGreen Aura{x) " );
          if ( IS_PROTECTED ( victim, PROT_SANCTUARY ) )    			SLCAT ( buf, "{m({WWhite Aura{m){x " );
     }
     if ( victim->position == victim->start_pos && victim->long_descr[0] != '\0' )
     {
          SNP ( cmdbuf, "ch_cmc %s", victim->name );
          if ( !LongLook )
          {
               SLCAT ( buf, click_cmd ( ch->desc, victim->long_descr, cmdbuf, "Context Menu" ) );
               if ( ch->desc->mxp ) // This is because ZMUD barfs on linefeeds in a send. Thus it has to be added back.
               {
                    SLCAT ( buf, "\r\n" );
               }
          }
          else if ( victim->short_descr[0] != '\0' )
          {
               SLCAT ( buf, click_cmd ( ch->desc, victim->short_descr, cmdbuf, "Context Menu" ) );
               SLCAT ( buf, "\r\n" );
          }
          else          /*assumed poly....seems to be the only instance of this */
          {
               SLCAT ( buf, click_cmd ( ch->desc, victim->poly_name, cmdbuf, "Context Menu" ) );
               SLCAT ( buf, "\r\n" );
          }
          page_to_char ( buf, ch );
          return;
     }
     if ( LongLook )
          if ( !IS_NPC ( victim ) && ( !IS_AFFECTED ( victim, AFF_POLY )
                                       || !str_cmp ( victim->poly_name, victim->short_descr ) ) )
               SLCAT ( buf, "{y" );
     SLCAT ( buf, PERSMASK ( victim, ch ) );
     if ( !IS_NPC ( victim ) && !IS_SET ( ch->comm, COMM_BRIEF ) && ( !LongLook ) && ( !IS_AFFECTED ( victim, AFF_POLY ) ) )
          SLCAT ( buf, victim->pcdata->title );
     if ( !LongLook )
     {
          switch ( victim->position )
          {
          case POS_DEAD:               SLCAT ( buf, " is DEAD!!" );               	break;
          case POS_MORTAL:             SLCAT ( buf, " is {Rmortally wounded.{w" );      break;
          case POS_INCAP:              SLCAT ( buf, " is {Rincapacitated.{w" );         break;
          case POS_STUNNED:            SLCAT ( buf, " is lying here stunned." );        break;
          case POS_SLEEPING:
               if (victim->on != NULL)
               {
                    if (IS_SET(victim->on->value[2],SLEEP_AT))
                    {
                         SNP(message," is sleeping at %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
                    else if (IS_SET(victim->on->value[2],SLEEP_ON))
                    {
                         SNP(message," is sleeping on %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
                    else
                    {
                         SNP(message, " is sleeping in %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
               }
               else
                    SLCAT ( buf, " is sleeping here." );
               break;
          case POS_RESTING:
               if (victim->on != NULL)
               {
                    if (IS_SET(victim->on->value[2],REST_AT))
                    {
                         SNP(message," is resting at %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
                    else if (IS_SET(victim->on->value[2],REST_ON))
                    {
                         SNP(message," is resting on %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
                    else
                    {
                         SNP(message, " is resting in %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
               }
               else
                    SLCAT ( buf, " is resting here." );
               break;
          case POS_SITTING:
               if (victim->on != NULL)
               {
                    if (IS_SET(victim->on->value[2],SIT_AT))
                    {
                         SNP(message," is sitting at %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
                    else if (IS_SET(victim->on->value[2],SIT_ON))
                    {
                         SNP(message," is sitting on %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
                    else
                    {
                         SNP(message, " is sitting in %s.", victim->on->short_descr);
                         SLCAT(buf,message);
                    }
               }
               else
                    SLCAT ( buf, " is sitting here." );
               break;
          case POS_STANDING:
               SLCAT ( buf, " is here." );
               break;
          case POS_FIGHTING:
               SLCAT ( buf, " is here, fighting " );
               if ( victim->fighting == NULL )
                    SLCAT ( buf, "thin air??" );
               else if ( victim->fighting == ch )
                    SLCAT ( buf, "YOU!" );
               else if ( victim->in_room == victim->fighting->in_room )
               {
                    SLCAT ( buf, PERSMASK ( victim->fighting, ch ) );
                    SLCAT ( buf, "." );
               }
               else
                    SLCAT ( buf, "someone who left??" );
               break;
          }
     }
     SLCAT ( buf, "{x\n\r" );
     buf[0] = UPPER ( buf[0] );
     page_to_char ( buf, ch );
     return;
}

void show_char_to_char_1 ( CHAR_DATA * victim, CHAR_DATA * ch )
{
     char                buf[MAX_STRING_LENGTH];
     OBJ_DATA           *obj;
     int                 iWear;
     int                 percent;
     bool                found;

     buf[0] = '\0';

     if ( can_see ( victim, ch ) )
     {
          if ( ch == victim )
               act ( "$n looks at $mself.", ch, NULL, NULL, TO_ROOM );
          else
          {
               act ( "$n looks at you.", ch, NULL, victim, TO_VICT );
               act ( "$n looks at $N.", ch, NULL, victim, TO_NOTVICT );
          }
     }

     if ( victim->description[0] != '\0' )
     {
          send_to_char ( victim->description, ch );
     }
     else
     {
          act ( "You see nothing special about $M.", ch, NULL, victim, TO_CHAR );
     }

     if ( victim->max_hit > 0 )
          percent = ( 100 * victim->hit ) / victim->max_hit;
     else
          percent = -1;

     SLCPY ( buf, PERSMASK ( victim, ch ) );

     if ( percent >= 100 )          SLCAT ( buf, TXT_COND_A );
     else if ( percent >= 90 )      SLCAT ( buf, TXT_COND_B );
     else if ( percent >= 75 )      SLCAT ( buf, TXT_COND_C );
     else if ( percent >= 50 )      SLCAT ( buf, TXT_COND_D );
     else if ( percent >= 30 )      SLCAT ( buf, TXT_COND_E );
     else if ( percent >= 15 )      SLCAT ( buf, TXT_COND_F );
     else if ( percent >= 0 )       SLCAT ( buf, TXT_COND_G );
     else                           SLCAT ( buf, TXT_COND_H );
     SLCAT ( buf, "\n\r" );

     buf[0] = UPPER ( buf[0] );
     send_to_char ( buf, ch );

     found = FALSE;
     for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
     {
          if ( ( obj = get_eq_char ( victim, iWear ) ) != NULL
               && can_see_obj ( ch, obj ) )
          {
               if ( !found )
               {
                    send_to_char ( "\n\r", ch );
                    act ( "$N is using:", ch, NULL, victim, TO_CHAR );
                    found = TRUE;
               }
               form_to_char ( ch, "{C<{w%-13s{C>{w  ", wear_info[iWear].name );
               send_to_char ( format_obj_to_char ( obj, ch, TRUE ), ch );
               send_to_char ( "\n\r", ch );
          }
     }

     if ( victim != ch && !IS_NPC ( ch ) && ( number_percent (  ) < ch->pcdata->learned[gsn_peek]
                                              || get_trust ( ch ) >= LEVEL_IMMORTAL ) )
     {
          send_to_char ( "\n\rYou peek at the inventory:\n\r", ch );
          check_improve ( ch, gsn_peek, TRUE, 4 );
          show_list_to_char ( victim->carrying, ch, TRUE, TRUE );
     }

     if ( IS_NPC ( victim ) && !IS_NULLSTR ( victim->pIndexData->notes ) && IS_IMMORTAL ( ch ) )
     {
          send_to_char ( "{W[{GComments{W]{w:\n\r  ", ch );
          send_to_char ( victim->pIndexData->notes, ch );
          send_to_char ( "\n\r", ch );
     }

     return;
}

void show_char_to_char ( CHAR_DATA * list, CHAR_DATA * ch, bool LongLook )
{
     CHAR_DATA          *rch;

     for ( rch = list; rch != NULL; rch = rch->next_in_room )
     {
          if ( rch == ch )
               continue;

          if ( !IS_NPC ( rch ) && IS_SET ( rch->act, PLR_WIZINVIS )
               && get_trust ( ch ) < rch->invis_level )
               continue;

          if ( can_see ( ch, rch ) )
          {
               show_char_to_char_0 ( rch, ch, LongLook );
          }
          else if ( room_is_dark ( ch->in_room ) && CAN_DETECT ( rch, DET_INFRARED ) )
          {
               send_to_char ( "You see glowing red eyes watching YOU!\n\r", ch );
          }
     }

     return;
}

bool check_blind ( CHAR_DATA * ch )
{
     if ( !IS_NPC ( ch ) && IS_SET ( ch->act, PLR_HOLYLIGHT ) )
          return TRUE;
     if ( IS_AFFECTED ( ch, AFF_BLIND ) )
     {
          send_to_char ( "You can't see a darned thing!\n\r", ch );
          return FALSE;
     }
     return TRUE;
}

void do_scroll ( CHAR_DATA * ch, char *argument )
{
     char                arg[MAX_INPUT_LENGTH];
     int                 lines;

     one_argument ( argument, arg );
     if ( arg[0] == '\0' )
     {
          if ( ch->lines == 0 )
          {
               send_to_char ( "You do not page long messages.\n\r", ch );
               send_to_char ( "This is not the recommended setting.\n\r", ch);
          }
          else
          {
               form_to_char ( ch, "You currently display %d lines per page.\n\r", ch->lines + 2 );
          }
          return;
     }

     if ( !is_number ( arg ) )
     {
          send_to_char ( "You must provide a number.\n\r", ch );
          return;
     }

     lines = atoi ( arg );

     if ( lines == 0 )
     {
          send_to_char ( "Paging disabled.\n\r", ch );
          ch->lines = 0;
          return;
     }

     if ( lines < 10 || lines > 100 )
     {
          send_to_char ( "You must provide a reasonable number.\n\r", ch );
          return;
     }

     form_to_char ( ch, "Scroll set to %d lines.\n\r", lines );
     ch->lines = lines - 2;
     return;
}

void do_socials ( CHAR_DATA * ch, char *argument )
{
     BUFFER             *buffer;
     int                 iSocial;
     int                 col;

     col = 0;
     buffer = buffer_new (512);
     for ( iSocial = 0; social_table[iSocial].name[0] != '\0'; iSocial++ )
     {
          bprintf ( buffer, "%-12s", social_table[iSocial].name );
          if ( ++col % 6 == 0 )
               bprintf ( buffer, "\n\r" );
     }
     if ( col % 6 != 0 )
          bprintf ( buffer, "\n\r" );
     page_to_char ( buffer->data, ch );
     buffer_free ( buffer );
     return;
}

/* RT Commands to replace news, motd, imotd, etc from ROM */
/* You'll notice nobb notb on some of these. This turns off the SunderMud Help Banners. - Lotherius */

void do_motd ( CHAR_DATA * ch, char *argument )
{
     do_help ( ch, "nobb notb motd" );
}

void do_imotd ( CHAR_DATA * ch, char *argument )
{
     do_help ( ch, "nobb notb imotd" );
}

void do_rules ( CHAR_DATA * ch, char *argument )
{
     do_help ( ch, "rules" );
}

void do_story ( CHAR_DATA * ch, char *argument )
{
     do_help ( ch, "story" );
}

void do_wizlist ( CHAR_DATA * ch, char *argument )
{
     do_help ( ch, "nobb notb wizlist" );
}

// Generic act flag toggle with message.
//
void real_auto ( CHAR_DATA *ch, long flag, char *text )
{
     if ( IS_NPC ( ch ) )
          return;

     if ( IS_SET ( ch->act, flag ) )
     {
          form_to_char ( ch, "%s: Disabled.\n\r", text );
          REMOVE_BIT( ch->act, flag );
     }
     else
     {
          form_to_char ( ch, "%s: Enabled.\n\r", text );
          SET_BIT ( ch->act, flag );
     }
}

void real_acomm ( CHAR_DATA *ch, long flag, char *text )
{
     if ( IS_NPC ( ch ) )
          return;

     if ( IS_SET ( ch->comm, flag ) )
     {
          form_to_char ( ch, "%s: Disabled.\n\r", text );
          REMOVE_BIT( ch->comm, flag );
     }
     else
     {
          form_to_char ( ch, "%s: Enabled.\n\r", text );
          SET_BIT ( ch->comm, flag );
     }
}

void do_autoassist ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOASSIST, "Automatically Assist Group Members" );
}

void do_autoexit ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOEXIT, "View Brief Exits" );
}

void do_autogold ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOGOLD, "Automatically loot gold from corpses" );
}

void do_autoloot ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOLOOT, "Automatically loot items from corpses" );
}

void do_autosac ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOSAC, "Automatically sacrifice corpses" );
}

void do_autosave ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOSAVE, "Notification of AutoSaves" );
}

void do_afk ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( IS_SET ( ch->act, PLR_AFK ) )
     {
          send_to_char ( "AFK removed...\n\r", ch );
          REMOVE_BIT ( ch->act, PLR_AFK );
          if ( ch->pcdata->afk_tell_first != NULL )
               send_to_char( "You have missed tells, type {greplay{x to see them.\n\r",  ch );
     }
     else
     {
          send_to_char ( "AFK Set..\n\r", ch );
          SET_BIT ( ch->act, PLR_AFK );
     }
}

void do_autosplit ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_AUTOSPLIT, "Share Money with Group Members" );

     if ( !IS_SET ( ch->act, PLR_AUTOSPLIT ) )
          sound ("splitoff.wav", ch );
}

void do_brief ( CHAR_DATA * ch, char *argument )
{
     real_acomm ( ch, COMM_BRIEF, "Short Room Descriptions" );
}

void do_fullfight ( CHAR_DATA * ch, char *argument )
{
     real_acomm ( ch, COMM_FULLFIGHT, "Full Battle Descriptions" );
}

void do_compact ( CHAR_DATA * ch, char *argument )
{
     real_acomm ( ch, COMM_COMPACT, "Compact Mode" );
}

void do_prompt ( CHAR_DATA * ch, char *argument )
{
     char       word[MAX_INPUT_LENGTH];

     if ( IS_NPC ( ch ) )
          return;

     if ( strlen ( argument ) != 0 )
     {
          one_argument ( argument, word );
          if ( !str_cmp ( word, "default" ) )
          {
               free_string ( ch->pcdata->prompt );
               ch->pcdata->prompt = str_dup ( "{G({W$h/$Hhp $m/$Mmn $v/$Vmv{G){x" );
          }
          else
          {
               if (strlen(argument) > 85)
               {
                    send_to_char("Prompt too long. Truncated at 85 characters. (Counting color)\n\r", ch);
                    argument[85] = '\0';
               }
               free_string ( ch->pcdata->prompt );
               ch->pcdata->prompt = str_dup ( argument );
          }
          return;
          form_to_char ( ch, "\n\r{wNew Prompt:\n\r%s\n\r", ch->pcdata->prompt );
     }
     else
          real_acomm ( ch, COMM_PROMPT, "Auto-Prompt" );
}

void do_combine ( CHAR_DATA * ch, char *argument )
{
     real_acomm ( ch, COMM_COMBINE, "Combined inventory" );
}

void do_noflashy ( CHAR_DATA * ch, char *argument )
{
     real_acomm ( ch, COMM_NOFLASHY, "Blocking of Flashing or Reverse Video text" );
}

void do_darkcolors ( CHAR_DATA * ch, char *argument )
{
     real_acomm ( ch, COMM_DARKCOLOR, "Automatically dim all colours" );
}

void do_nodarkgrey ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( IS_SET ( ch->comm, COMM_NODARKGREY ) )
     {
          REMOVE_BIT ( ch->comm, COMM_NODARKGREY );
          send_to_char ( "You should now see {Dthe dark grey (aka bright black) colour{w.\n\r", ch );
          send_to_char ( "If part of that sentence was missing, your client won't show dark grey.\n\r", ch );
     }
     else
     {
          send_to_char ( "You now see white instead of dark grey.\n\r", ch );
          SET_BIT ( ch->comm, COMM_NODARKGREY );
     }
}

void do_noloot ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_CANLOOT, "Allow your corpse to be looted by others" );
}

void do_nofollow ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( IS_AFFECTED( ch, AFF_CHARM ) )
     {
          send_to_char ( "You can't decide this for yourself now.\n\r", ch);
          return;
     }
     real_auto ( ch, PLR_NOFOLLOW, "Refuse followers" );

     if ( !IS_SET ( ch->act, PLR_NOFOLLOW ) )
          die_follower ( ch );
}

void do_nosummon ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
     {
          if ( IS_SET ( ch->imm_flags, IMM_SUMMON ) )
          {
               send_to_char ( "You are no longer immune to summon. Careful.\n\r", ch );
               REMOVE_BIT ( ch->imm_flags, IMM_SUMMON );
          }
          else
          {
               send_to_char ( "You are now immune to summoning.\n\r", ch );
               SET_BIT ( ch->imm_flags, IMM_SUMMON );
          }
     }
     else
          real_auto ( ch, PLR_NOSUMMON, "Protection from Summoning" );

     return;
}

void do_killer ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( IS_SET ( ch->act, PLR_KILLER ) )
     {
          send_to_char ( "Once a Killer, Always a Killer.\n\r", ch );
          return;
     }

     if ( argument[0] == '\0' )
     {
          send_to_char ( "To declare yourself a KILLER, you must use your password with the killer command.\n\r", ch );
          send_to_char ( "{R{&Warning: {x{RRead HELP PKILL first. Killer flags are PERMANENT!{x\n\r", ch );
          return;
     }
     if ( str_cmp ( crypt ( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
     {
          send_to_char ( "Declaring you a KILLER.\n\r", ch );
          SET_BIT ( ch->act, PLR_KILLER );
          save_char_obj ( ch );
     }
     else
          send_to_char ( "Invalid argument, nothing done.\n\r", ch );
     return;
}

/* New config command */
/* Why RT hated it, I dunno, but I like it. */

void do_config ( CHAR_DATA * ch, char *argument )
{
     BUFFER *buffer;
     bool    haveargs = FALSE;

     if ( IS_NPC ( ch ) )
          return;
     if ( argument[0] != '\0' )
          haveargs = TRUE;

     if (!haveargs)
     {
          buffer = buffer_new (1024);

          bprintf ( buffer, "{G[{W---{G] {wConfig Item        {G[{W---{G] {wChannel\n\r");
          bprintf ( buffer, "{C+{c--------------------------------------------{C+\n\r");
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wautoassist        {G[{W%3s{G]{w gossip\n\r",
                    ( IS_SET (ch->act, PLR_AUTOASSIST) ? "YES" : " NO" ),
                    ( !IS_SET ( ch->comm, COMM_NOGOSSIP ) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wautoexit          {G[{W%3s{G]{w auction\n\r",
                    ( !IS_SET (ch->act, PLR_AUTOEXIT) ? "YES" : "NO" ),
                    ( !IS_SET (ch->comm, COMM_NOAUCTION ) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wautoloot          {G[{W%3s{G]{w music (channel)\n\r",
                    ( IS_SET (ch->act, PLR_AUTOLOOT) ? "YES" : " NO" ),
                    ( !IS_SET (ch->comm, COMM_NOMUSIC) ? "YES" : " NO" ));
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wautosac           {G[{W%3s{G]{w question/answer\n\r",
                    ( IS_SET (ch->act, PLR_AUTOSAC) ? "YES" : " NO" ),
                    ( !IS_SET (ch->comm, COMM_NOQUESTION) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wautogold          {G[{W%3s{G]{w beep\n\r",
                    ( IS_SET (ch->act, PLR_AUTOGOLD) ? "YES" : " NO" ),
                    ( !IS_SET (ch->comm, COMM_BEEP) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wautosplit         {G[{W%3s{G]{w deaf (shout)\n\r",
                    ( IS_SET (ch->act, PLR_AUTOSPLIT) ? "YES" : " NO" ),
                    ( !IS_SET (ch->comm, COMM_DEAF) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wnoloot            {G[{W---{G]{w\n\r",
                    ( !IS_SET (ch->act, PLR_CANLOOT) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wnosummon          {G[{W%3s{G]{w {R*{wcompact\n\r",
                    ( IS_SET (ch->act, PLR_NOSUMMON) ? "YES" : " NO" ),
                    ( IS_SET (ch->comm, COMM_COMPACT) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wnofollow          {G[{W%3s{G]{w {R*{wbrief\n\r",
                    ( IS_SET (ch->act, PLR_NOFOLLOW) ? "YES" : " NO" ),
                    ( IS_SET (ch->comm, COMM_BRIEF) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wfullfight         {G[{W%3s{G]{w {R*{wcombine\n\r",
                    ( IS_SET (ch->comm, COMM_FULLFIGHT) ? "YES" : " NO" ),
                    ( IS_SET (ch->comm, COMM_COMBINE) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w scroll             {G[{W%3s{G]{w {R*{wcursor\n\r",
                    ( ( ch->lines > 0 ) ? itos(ch->lines+2) : " NO"),
                    ( IS_SET (ch->act, PLR_CURSOR) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w killer             {G[{W%3s{G]{w thief\n\r",
                    ( IS_SET (ch->act, PLR_KILLER) ? "YES" : " NO" ),
                    ( IS_SET (ch->act, PLR_THIEF) ? "YES" : " NO" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wcolor             {G[{W%3s{G]{w sound\n\r",
                    ch->desc->ansi ? "YES" : " NO" ,
                    ch->desc->msp ? "YES" : " NO" );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wdarken            {G[{W%3s{G]{w {R*{wdarkgrey\n\r",
                    ( IS_SET (ch->comm, COMM_DARKCOLOR) ? "YES" : " NO" ),
                    ( IS_SET (ch->comm, COMM_NODARKGREY ) ? "NO" : "YES" ) );
          bprintf ( buffer, "{G[{W%3s{G]{w {R*{wflashing          {G[{W%3s{G]{w MXP Mud eXtension\n\r",
                    ( IS_SET (ch->comm, COMM_NOFLASHY ) ? "NO" : "YES" ),
                    ch->desc->mxp ? "YES" : " NO" );
          bprintf ( buffer, "{C+{c--------------------------------------------{C+\n\r");
          bprintf ( buffer, "{CUse config to toggle items marked with {R*{C.\n\r");
          bprintf ( buffer, "Set notify options under the \"notify\" command.\n\r");
          page_to_char(buffer->data, ch);
          buffer_free ( buffer );
     }
     /* End of ( !haveargs ) */
     else
     {
          if ( strstr (argument, "autoassist" ) != NULL )
               do_autoassist ( ch, "" );
          else if ( strstr (argument, "autoexit" ) != NULL)
               do_autoexit ( ch, "" );
          else if ( strstr (argument, "autoloot" ) != NULL )
               do_autoloot ( ch, "" );
          else if ( strstr (argument, "autogold" ) != NULL )
               do_autogold ( ch, "" );
          else if ( strstr (argument, "autosac" ) != NULL )
               do_autosac ( ch, "" );
          else if ( strstr (argument, "autosplit" ) != NULL )
               do_autosplit ( ch, "" );
          else if ( strstr (argument, "noloot" ) != NULL )
               do_noloot( ch, "" );
          else if ( strstr (argument, "nosummon" ) != NULL )
               do_nosummon ( ch, "" );
          else if ( strstr (argument, "nofollow" ) != NULL )
               do_nofollow ( ch, "" );
          else if ( strstr (argument, "fullfight" ) != NULL )
               do_fullfight ( ch, "" );
          else if ( strstr (argument, "color" ) != NULL )
               do_colour ( ch, "" );
          else if ( strstr (argument, "compact" ) != NULL )
               do_compact ( ch, "" );
          else if ( strstr (argument, "brief" ) != NULL )
               do_brief ( ch, "" );
          else if ( strstr (argument, "combine" ) != NULL )
               do_combine ( ch, "" );
          else if ( strstr (argument, "cursor" ) != NULL )
               do_cursor ( ch, "" );
          else if ( strstr (argument, "darken" ) != NULL )
               do_darkcolors ( ch, "" );
          else if ( strstr (argument, "darkgrey" ) != NULL )
               do_nodarkgrey ( ch, "" );
          else if ( strstr (argument, "flashing" ) != NULL )
               do_noflashy ( ch, "" );
          else
               send_to_char ( "Invalid Config Option.\n\r", ch );
     }
     return;
}

void do_look ( CHAR_DATA * ch, char *argument )
{
     char                buf[MAX_STRING_LENGTH];
     char                arg1[MAX_INPUT_LENGTH];
     char                arg2[MAX_INPUT_LENGTH];
     char                arg3[MAX_INPUT_LENGTH];
     char                outbuf[MAX_STRING_LENGTH * 4];
     EXIT_DATA          *pexit;
     CHAR_DATA          *victim;
     OBJ_DATA           *obj;
     char               *pdesc;
     int                 door;
     int                 number, count;

     buf[0] = '\0';
     outbuf[0] = '\0';

     if ( ch->desc == NULL )
          return;
     if ( ch->position < POS_SLEEPING )
     {
          send_to_char ( "You can't see anything but stars!\n\r", ch );
          return;
     }
     if ( ch->position == POS_SLEEPING )
     {
          send_to_char ( "You can't see anything, you're sleeping!\n\r", ch );
          return;
     }
     if ( !check_blind ( ch ) ) // check_blind should give hte error msg here.
          return;
     if ( !IS_NPC ( ch ) && !IS_SET ( ch->act, PLR_HOLYLIGHT ) && room_is_dark ( ch->in_room ) )
     {
          SNP ( buf, "It is pitch black ... \n\r" );
          page_to_char ( buf, ch );
          buf[0] = '\0';	/* reset to NULL */
          show_char_to_char ( ch->in_room->people, ch, FALSE );
          return;
     }

     argument = one_argument ( argument, arg1 );
     argument = one_argument ( argument, arg2 );
     number = number_argument ( arg1, arg3 );
     count = 0;

     if ( arg1[0] == '\0' || !str_cmp ( arg1, "auto" ) )
     {
          SNP ( buf, "{c" );
          SLCAT ( outbuf, buf );
          if ( ch->desc->mxp )
          {
               SNP ( buf, MXP_SECURE "<RName>" );
               SLCAT ( outbuf, buf );
          }
          SNP ( buf, "%s",
                IS_RENTED(ch->in_room->lease) && !IS_NULLSTR(ch->in_room->lease->lease_name) ?
                ch->in_room->lease->lease_name : ch->in_room->name );
          SLCAT ( outbuf, buf );
          if ( ch->desc->mxp )
          {
               SNP ( buf, MXP_SECURE "</RName>" MXP_LLOCK );
               SLCAT ( outbuf, buf );
          }
          if ( ch->level >= AVATAR )       /*Zeran: show vnum of room if IMM */
          {
               char                buf2[64];
               SNP ( buf2, " {W[{C%d{W]{x", ch->in_room->vnum );
               SLCAT ( outbuf, buf2 );
          }
          SLCAT ( outbuf, "{w\n\r" );

          if ( arg1[0] == '\0'
               || ( !IS_NPC ( ch ) &&
                    !IS_SET ( ch->comm, COMM_BRIEF ) ) )
          {
               SLCAT ( outbuf, "  " );
               if ( ch->desc->mxp )
               {
                    SNP ( buf, MXP_LSECURE "<RDesc>" ); // Lock secure since room desc is multi-line
                    SLCAT ( outbuf, buf );
               }
               SNP ( buf, "%s",
                     IS_RENTED(ch->in_room->lease) && !IS_NULLSTR(ch->in_room->lease->lease_descr) ?
                     ch->in_room->lease->lease_descr : ch->in_room->description );
               SLCAT ( outbuf, buf );
               if ( ch->desc->mxp )
               {
                    SNP ( buf, MXP_SECURE "</RDesc>" MXP_LLOCK ); // Reset locked
                    SLCAT ( outbuf, buf );
               }
          }

          if ( !IS_NPC ( ch ) && IS_SET ( ch->act, PLR_AUTOEXIT ) )
          {
               SLCAT ( outbuf, "\n\r" );
               page_to_char ( outbuf, ch );
               outbuf[0] = '\0';	/* reset to NULL */
               do_exits ( ch, "auto" );
               send_to_char ( "{w", ch );
          }
          else if ( !IS_NPC ( ch ) )
          {
               SLCAT ( outbuf, "\n\r" );
               page_to_char ( outbuf, ch );
               outbuf[0] = '\0';   /* reset to NULL */
               do_exits ( ch, "" );
               send_to_char ( "{w", ch );
          }
          {
               page_to_char ( outbuf, ch );
          }
          outbuf[0] = '\0';	/* reset to NULL */
          show_list_to_char ( ch->in_room->contents, ch, FALSE, FALSE );
          show_char_to_char ( ch->in_room->people, ch, FALSE );
          return;
     }

     if ( !str_cmp ( arg1, "i" ) || !str_cmp ( arg1, "in" ) )
     {
		  /* 'look in' */
          if ( arg2[0] == '\0' )
          {
               send_to_char ( "Look in what?\n\r", ch );
               return;
          }

          if ( ( obj = get_obj_here ( ch, NULL, arg2 ) ) == NULL )
          {
               send_to_char ( "You do not see that here.\n\r", ch );
               return;
          }

          switch ( obj->item_type )
          {
          default:
               send_to_char ( "That is not a container.\n\r", ch );
               break;

          case ITEM_DRINK_CON:
               if ( obj->value[1] <= 0 )
               {
                    send_to_char ( "It is empty.\n\r", ch );
                    break;
               }

               SNP ( buf, "It's %s full of a %s liquid.\n\r",
                     obj->value[1] < obj->value[0] / 4 ? "less than"
                     : obj->value[1] < 3 * obj->value[0] / 4
                     ? "about" : "more than", liq_table[obj->value[2]].liq_color );

               send_to_char ( buf, ch );
               break;
          case ITEM_CONTAINER:
          case ITEM_CORPSE_NPC:
          case ITEM_CORPSE_PC:
               if ( IS_SET ( obj->value[1], CONT_CLOSED ) )
               {
                    send_to_char ( "It is closed.\n\r", ch );
                    break;
               }
               act ( "$p contains:", ch, obj, NULL, TO_CHAR );
               show_list_to_char ( obj->contains, ch, TRUE, TRUE );
               break;
          }
          return;
     }

     if ( ( victim = get_char_room ( ch, NULL, arg1 ) ) != NULL )
     {
          show_char_to_char_1 ( victim, ch );
          return;
     }

     for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
     {
          if ( can_see_obj ( ch, obj ) )
          {
               pdesc = get_extra_descr ( arg3, obj->extra_descr );
               if ( pdesc != NULL )
               {
                    if ( ++count == number )
                    {
                         send_to_char ( pdesc, ch );
                         SNP ( buf, "Condition: %s\n\r", obj_cond ( obj ) );
                         send_to_char ( buf, ch );
                         return;
                    }
               }

               pdesc = get_extra_descr ( arg3, obj->pIndexData->extra_descr );
               if ( pdesc != NULL )
               {
                    if ( ++count == number )
                    {
                         send_to_char ( pdesc, ch );
                         SNP ( buf, "Condition: %s\n\r", obj_cond ( obj ) );
                         send_to_char ( buf, ch );
                         return;
                    }
               }

               if ( is_name ( arg3, obj->name ) || is_name_abbv ( arg3, obj->name ) )
                    if ( ++count == number )
                    {
                         send_to_char ( obj->description, ch );
                         send_to_char ( "\n\r", ch );
                         SNP ( buf, "Condition: %s\n\r", obj_cond ( obj ) );
                         send_to_char ( buf, ch );
                         if ( !IS_NULLSTR (obj->pIndexData->notes ) && IS_IMMORTAL ( ch ) )
                         {
                              SNP ( buf, "{W[{GComments{W]{w:\n\r  %s\n\r",
                                    obj->pIndexData->notes );
                              send_to_char ( buf, ch );
                         }
                         return;
                    }
          }
     }

     for ( obj = ch->in_room->contents; obj != NULL; obj = obj->next_content )
     {
          if ( can_see_obj ( ch, obj ) )
          {
               pdesc = get_extra_descr ( arg3, obj->extra_descr );
               if ( pdesc != NULL )
                    if ( ++count == number )
                    {
                         send_to_char ( pdesc, ch );
                         SNP ( buf, "Condition: %s\n\r", obj_cond ( obj ) );
                         send_to_char ( buf, ch );
                         return;
                    }

               pdesc = get_extra_descr ( arg3, obj->pIndexData->extra_descr );
               if ( pdesc != NULL )
                    if ( ++count == number )
                    {
                         send_to_char ( pdesc, ch );
                         SNP ( buf, "Condition: %s\n\r", obj_cond ( obj ) );
                         send_to_char ( buf, ch );
                         return;
                    }
               if ( is_name ( arg3, obj->name ) || is_name_abbv ( arg3, obj->name ) )
                    if ( ++count == number )
                    {
                         send_to_char ( obj->description, ch );
                         send_to_char ( "\n\r", ch );
                         SNP ( buf, "Condition: %s\n\r", obj_cond ( obj ) );
                         send_to_char ( buf, ch );
                         if ( !IS_NULLSTR (obj->pIndexData->notes ) && IS_IMMORTAL ( ch ) )
                         {
                              SNP ( buf, "{W[{GComments{W]{w:\n\r  %s\n\r",
                                    obj->pIndexData->notes );
                              send_to_char ( buf, ch );
                         }
                         return;
                    }
          }
     }

     if ( count > 0 && count != number )
     {
          if ( count == 1 )
               SNP ( buf, "You only see one %s here.\n\r", arg3 );
          else
               SNP ( buf, "You only see %d %s's here.\n\r", count, arg3 );

          send_to_char ( buf, ch );
          return;
     }

     pdesc = get_extra_descr ( arg1, ch->in_room->extra_descr );
     if ( pdesc != NULL )
     {
          page_to_char ( pdesc, ch );
          return;
     }

     if ( !str_cmp ( arg1, "n" ) || !str_cmp ( arg1, "north" ) ) door = 0;
     else if ( !str_cmp ( arg1, "e" ) || !str_cmp ( arg1, "east" ) ) door = 1;
     else if ( !str_cmp ( arg1, "s" ) || !str_cmp ( arg1, "south" ) ) door = 2;
     else if ( !str_cmp ( arg1, "w" ) || !str_cmp ( arg1, "west" ) ) door = 3;
     else if ( !str_cmp ( arg1, "u" ) || !str_cmp ( arg1, "up" ) ) door = 4;
     else if ( !str_cmp ( arg1, "d" ) || !str_cmp ( arg1, "down" ) ) door = 5;
     else
     {
          send_to_char ( "You do not see that here.\n\r", ch );
          return;
     }

	 /* 'look direction' */
     if ( ( pexit = ch->in_room->exit[door] ) == NULL )	/* no exit */
     {
          send_to_char ( "Nothing special there.\n\r", ch );
          return;
     }

     if ( IS_SET ( pexit->exit_info, EX_CLOSED ) && IS_SET ( pexit->exit_info, EX_HIDDEN ) )	/* closed hidden door */
     {
          send_to_char ( "Nothing special there.\n\r", ch );
          return;
     }

     if ( pexit->description != NULL && pexit->description[0] != '\0' )
     {
          page_to_char ( pexit->description, ch );
     }

     if ( pexit->keyword != NULL && pexit->keyword[0] != '\0' && pexit->keyword[0] != ' ' )
     {
          if ( IS_SET ( pexit->exit_info, EX_CLOSED ) )
          {
               act ( "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR );
          }
          else if ( IS_SET ( pexit->exit_info, EX_ISDOOR ) &&
                    pexit->u1.to_room->people != NULL )
          {
               act ( "The $d is open.", ch, NULL, pexit->keyword, TO_CHAR );
               send_to_char ( "You see:\n\r", ch );
               show_char_to_char ( pexit->u1.to_room->people, ch, TRUE );
          }
          else if ( pexit->u1.to_room->people != NULL )
          {
               send_to_char ( "You see:\n\r", ch );
               show_char_to_char ( pexit->u1.to_room->people, ch, TRUE );
          }
          else
               send_to_char ( "You see nothing of interest in that direction.\n\r", ch );
     }
     else
     {
          if ( IS_SET ( pexit->exit_info, EX_CLOSED ) )
          {
               act ( "The door is closed.", ch, NULL, pexit->keyword,
                     TO_CHAR );
          }
          else if ( IS_SET ( pexit->exit_info, EX_ISDOOR ) &&
                    pexit->u1.to_room->people != NULL )
          {
               act ( "The door is open.", ch, NULL, pexit->keyword, TO_CHAR );
               send_to_char ( "You see:\n\r", ch );
               show_char_to_char ( pexit->u1.to_room->people, ch, TRUE );
          }
          else if ( pexit->u1.to_room->people != NULL )
          {
               send_to_char ( "You see:\n\r", ch );
               show_char_to_char ( pexit->u1.to_room->people, ch, TRUE );
          }
          else
               send_to_char ( "You see nothing of interest in that direction.\n\r", ch );
     }
     return;
}

void do_scan ( CHAR_DATA * ch, char *argument )
{
     EXIT_DATA          *pexit;
     CHAR_DATA		*rch;
     int                 door;
     char                doors[6][30];
     bool		 thisdir = FALSE;
     bool                anything = FALSE;

     SNP ( doors[0], "{c[North]\n\r{x" );
     SNP ( doors[1], "{c[East]\n\r{x" );
     SNP ( doors[2], "{c[South]\n\r{x" );
     SNP ( doors[3], "{c[West]\n\r{x" );
     SNP ( doors[4], "{c[Up]\n\r{x" );
     SNP ( doors[5], "{c[Down]\n\r{x" );

     if ( !check_blind( ch ) )
          return;

     for ( door = 0; door <= 5; door++ )
     {
          thisdir = FALSE;
		  /* scan direction */
          if ( ( pexit = ch->in_room->exit[door] ) != NULL
               && pexit->u1.to_room != NULL
               && can_see_room ( ch, pexit->u1.to_room ) )
          {
               if ( !IS_SET ( pexit->exit_info, EX_CLOSED ) && ( pexit->u1.to_room->people != NULL ) )
               {
                    rch = pexit->u1.to_room->people;

                    for ( ; rch != NULL; rch = rch->next_in_room )
                    {
                         if (ch == rch)
                              continue;

                         if ( (!IS_NPC(rch)) && (IS_SET(rch->act, PLR_WIZINVIS))
                              && (get_trust( ch ) < rch->invis_level))
                              continue;
                         if ( (!IS_NPC(rch)) && (IS_SET(rch->act, PLR_CLOAK))
                              && (get_trust( ch ) < rch->cloak_level))
                              continue;
                         /* This will show the door only once for each direction */
                         if (!thisdir)
                              send_to_char(doors[door], ch);
                         thisdir = TRUE;
                         if (room_is_dark(rch->in_room))
                              send_to_char ("You see a pair of {rglowing red eyes{x!\n\r", ch);
                         else
                              show_char_to_char ( rch, ch, TRUE );
                         anything = TRUE;
                    }

               }
               else if ( IS_SET ( pexit->exit_info, EX_CLOSED ) && !IS_SET ( pexit->exit_info, EX_HIDDEN ) )
               {
                    send_to_char ( doors[door], ch );
                    if ( ( pexit->description ) &&
                         ( pexit->description[0] != '\0' ) )
                         send_to_char ( pexit->description, ch );
                    else
                         send_to_char ( "a door\n\r", ch );
               }
          }
     }
     if ( anything )
          return;
     send_to_char ( "You see nobody around you.\n\r", ch );
     return;
}

void do_read ( CHAR_DATA * ch, char *argument )
{
     do_look ( ch, argument );
}

void do_lore ( CHAR_DATA * ch, char *argument )
{
     char                arg[MAX_INPUT_LENGTH];
     int                 chance;
     OBJ_DATA           *obj;

     one_argument ( argument, arg );

     if ( arg[0] == '\0' )
     {
          send_to_char ( "Lore what?\n\r", ch );
          return;
     }

     if ( ( obj = get_obj_carry ( ch, arg, NULL ) ) == NULL )
     {
          send_to_char ( "You don't appear to have that item.\n\r", ch );
          return;
     }
     chance = ch->pcdata->learned[gsn_lore];
     if ( chance < 1 )
     {
          send_to_char ( "You don't have any idea where to begin to look for information.", ch );
          return;
     }
     if ( ch->move < 100 )
     {
          send_to_char ( "You are too tired to look up information on this object\n\r", ch );
          return;
     }
     ch->move -= 100;

     WAIT_STATE ( ch, skill_table[gsn_lore].beats );

	 /*modifiers */

     chance = chance + ( get_curr_stat ( ch, STAT_INT ) - 20 ) * 5;
     if ( number_percent (  ) > chance )
     {
          send_to_char ( "Lore failed.\n\r", ch );
          check_improve ( ch, gsn_lore, FALSE, 1 );
          return;
     }
     send_to_char ( "You manage to find some information.\n\r", ch );
     check_improve ( ch, gsn_lore, TRUE, 1 );
     spell_identify ( skill_lookup ( "lore" ), ch->level, ch, obj );
}

void do_examine ( CHAR_DATA * ch, char *argument )
{
     char                buf[MAX_STRING_LENGTH];
     char                arg[MAX_INPUT_LENGTH];
     OBJ_DATA           *obj;

     one_argument ( argument, arg );

     if ( arg[0] == '\0' )
     {
          send_to_char ( "Examine what?\n\r", ch );
          return;
     }

     do_look ( ch, arg );

     if ( ( obj = get_obj_here ( ch, NULL, arg ) ) != NULL )
     {
          switch ( obj->item_type )
          {
          default:
               break;
          case ITEM_DRINK_CON:
          case ITEM_CONTAINER:
          case ITEM_CORPSE_NPC:
          case ITEM_CORPSE_PC:
               send_to_char ( "When you look inside, you see:\n\r", ch );
               SNP ( buf, "in %s", arg );
               do_look ( ch, buf );
          }
     }

     return;
}

/*
 * auto-exit changed form and function on Sunder. Sorry Zrin.
 */
void do_exits ( CHAR_DATA * ch, char *argument )
{
     extern char *const  dir_name[];
     char                buf[MAX_STRING_LENGTH];
     char                buf2[128];
     char	         buf3[MAX_STRING_LENGTH];
     EXIT_DATA          *pexit;
     bool                found;
     bool                fAuto;
     bool                Hlight = FALSE;
     int                 door;

     // fAuto = do brief view of exits, else do long view.
     fAuto = !str_cmp ( argument, "auto" );

     if ( !check_blind ( ch ) )
          return;

     // If immortal and brief(?) view, show flags & comments.
     if ( fAuto && IS_IMMORTAL ( ch ) )
     {
          if ( !IS_NULLSTR ( ch->in_room->notes ) )
          {
               SNP ( buf, "{W[{GComments{W]{w:\n\r  %s\n\r", ch->in_room->notes );
               page_to_char ( buf, ch );
          }
          SNP ( buf, "{gRoom flags: {w[{C%s{w]\n\r",
                flag_string ( room_flags, ch->in_room->room_flags ) );
          page_to_char ( buf, ch );
     }

     // Guarantee zeroed strings
     buf[0] = '\0';
     buf[2] = '\0';

     // If "extra info" is toggled, turn on Hlight (who chose this variable, it is too similar to holy light?)
     if ( IS_SET ( ch->act, PLR_XINFO ) )
          Hlight = TRUE;

     // Show appropriate headers.
     if ( Hlight && fAuto )
          SLCPY ( buf, "{gExits:  {w[ {Cflags {w]\n\r" );
     else
          SLCPY ( buf, fAuto ? "{gPaths: {w[{C" : "{gObvious paths:\n\r" );

     found = FALSE;
     // Cycle through all possible doors.
     for ( door = 0; door <= 5; door++ )
     {
          // If the door exists and the player can see destination room, display it.
          if ( ( pexit = ch->in_room->exit[door] ) != NULL
               && pexit->u1.to_room != NULL && can_see_room ( ch, pexit->u1.to_room ) )
          {
               // If "extra info" and "brief view" show door flags.
               if ( Hlight && fAuto )
               {
                    found = TRUE;
                    if (ch->desc->mxp)
                         SNP ( buf2, MXP_SECURE "<Ex>%5s</Ex>" MXP_LLOCK, dir_name[door] );
                    else
                         SNP ( buf2, "%5s", dir_name[door] );
                    SLCAT ( buf2, "   {w[{C " );
                    if ( IS_SET ( pexit->exit_info, EX_ISDOOR ) )
                         SLCAT ( buf2, "door " );
                    if ( IS_SET ( pexit->exit_info, EX_CLOSED ) )
                         SLCAT ( buf2, "closed " );
                    if ( IS_SET ( pexit->exit_info, EX_LOCKED ) )
                         SLCAT ( buf2, "locked " );
                    if ( IS_SET ( pexit->exit_info, EX_PICKPROOF ) )
                         SLCAT ( buf2, "pickproof " );
                    if ( IS_SET ( pexit->exit_info, EX_HIDDEN ) )
                         SLCAT ( buf2, "hidden " );
                    if ( IS_SET ( pexit->exit_info, EX_NO_PASS ) )
                         SLCAT ( buf2, "no_pass" );
                    SLCAT ( buf2, "{w]\n\r" );
                    SLCAT ( buf, buf2 );
               }
               // end hlight && fauto
               else if ( !IS_SET ( pexit->exit_info, EX_CLOSED ) )
               {
                    // If the door isn't closed
                    found = TRUE;
                    // If "brief" view, open door.
                    if ( fAuto )
                    {
                         if ( ch->desc->mxp )
                              SLCAT ( buf, MXP_SECURE " <Ex>" );
                         else
                              SLCAT ( buf, " " );
                         SLCAT ( buf, dir_name[door] );
                         if ( ch->desc->mxp )
                              SLCAT ( buf, MXP_SECURE "</Ex>" MXP_LLOCK );
                    }
                    // If non-brief view, open door.
                    else
                    {
						 /* Okay. Open door, can see DESCR or ROOM_NAME if NULL */
						 /* Always see descr, builder should consider darkness */
                         if ( !IS_NULLSTR ( pexit->description ) )
                              SNP( buf3, pexit->description );
                         else
                         {
                              if (room_is_dark (pexit->u1.to_room) )
                                   SNP( buf3, "{bToo dark to tell");
                              else
                              {
                                   SNP ( buf3, "%s",
                                         IS_RENTED(pexit->u1.to_room->lease)
                                         && !IS_NULLSTR(pexit->u1.to_room->lease->lease_name) ?
                                         pexit->u1.to_room->lease->lease_name
                                         : !IS_NULLSTR ( pexit->u1.to_room->name )
                                         ? pexit->u1.to_room->name : "Somewhere" );
                              }
                              SLCAT(buf3, "\n\r");
                         }
                         if ( ch->desc->mxp )
                              snprintf ( buf + strlen ( buf ), sizeof ( buf )-1, MXP_SECURE "{C <Ex>%-5s</Ex>" MXP_LLOCK "  {w- %s",
                                         capitalize ( dir_name[door] ), buf3);
                         else
                              snprintf ( buf + strlen ( buf ), sizeof ( buf )-1, "{C %-5s  {w- %s",
                                         capitalize ( dir_name[door] ), buf3);
                    }
                    // end of non-brief open door.
               }
               // End of the door isn't closed.
               else if ( IS_SET ( pexit->exit_info, EX_CLOSED ) && !IS_SET ( pexit->exit_info, EX_HIDDEN ) )
               {
                    // If the door is closed, and isn't hidden.
                    found = TRUE;
                    if ( fAuto  )
                    {
                         SLCAT ( buf, " {M<{c" );
                         if ( ch->desc->mxp )
                              SLCAT ( buf, MXP_SECURE "<Ex>" );
                         SLCAT (buf, dir_name[door] );
                         if ( ch->desc->mxp )
                              SLCAT ( buf, MXP_SECURE "</Ex>" MXP_LLOCK );
                         SLCAT (buf, "{M>{C" );
                    }
                    else
                    {
						 /* Okay. CLOSED door, can see DESCR or Nothing */
                         if ( pexit->description != NULL && pexit->description[0] != '\0' )
                              SNP( buf3, pexit->description );
                         else
                         {
                              if ( pexit->keyword != NULL
                                   &&   pexit->keyword[0] != '\0' &&   pexit->keyword[0] != ' ' )
                              {
                                   SNP( buf3, "{cYou can't see through the %s.{w\n\r", pexit->keyword );
                              }
                              else
                                   SNP( buf3, "{cYou can't see through this door.{w\n\r" );
                         }
                         if ( ch->desc->mxp )
                              snprintf ( buf + strlen ( buf ), sizeof ( buf ) -1, MXP_SECURE "{M<{c<Ex>%-5s</Ex>" MXP_LLOCK "{M> {w- %s",
                                         capitalize ( dir_name[door] ), buf3 );
                         else
                              snprintf ( buf + strlen ( buf ), sizeof ( buf ) -1, "{M<{c%-5s{M> {w- %s",
                                         capitalize ( dir_name[door] ), buf3 );
                    }
               }
               // End of door closed and isn't hidden
          }
          // End of a real, visible, door found.
     }
     // End of cycling the doors.
     //
     if ( !found )
          SLCAT ( buf, fAuto ? " none" : "None.\n\r" );

     if ( fAuto && Hlight )
          SLCAT ( buf, "{x\n\r" );
     if ( fAuto && !Hlight )
          SLCAT ( buf, "{w ]{x\n\r" );

     page_to_char ( buf, ch );
     return;
}

/* Gotta love how simple things can be sometimes - Lotherius */
void do_worth ( CHAR_DATA * ch, char *argument )
{
     form_to_char ( ch, "You have ${Y%ld{w gold.\n\r", ch->gold );
     do_bank ( ch, "" );
     do_borrow ( ch, "auto" );
     return;
}

// This calculates an arbitrary "Score" for the character.
// Subject to much tweaking. -- Lotherius
//
int score_calc ( CHAR_DATA *ch )
{
     int score;
     if ( IS_NPC ( ch ) ) // Just in case as usual
          return 0;
     score = ( ( ch->level*3 - ch->pcdata->mob_losses ) +
               ( ch->pcdata->pkill_wins - ch->pcdata->pkill_losses ) +
               ( ch->pcdata->battle_rating + (ch->pcdata->mob_rating/2) ) +
               ( ch->pcdata->questearned / 5000 ) );
     return score;
}

/*
 * Structure for a custom score default
 */

struct cscore_type
{
     char               *text;
};

const struct cscore_type cscore_table[MAX_CSCORE] =
{
     {
          "{/You are #n #t, level #l, #a years old (#A hours).{/"
               "Race: #r  Sex: #s  Class:  #s{/"
               "You have #h/#H hit, #m/#M mana, #v/#V movement.{/"
               "You have #p practices.{/"
               "You are carrying #x/#X items with weight #y/#Y pounds.{/"
               "Str: @S(@s)  Int: @I(@i)  Wis: @W(@w)  Dex: @D(@d)  Con: @C(@c){/"
               "You have scored #e exp, and have #g gold coins.{/"
               "You need #E exp to level.{/"
               "Wimpy set to #W hit points.{/"
               "You are #P.{/"
               "Your alignment is @a.{/"
     },
     {
          "{/You are {W#n #t{w, level {C#l{w, {C#a{w years old ({C#A{w hours).{/"
               "Race: {C#r{w  Sex: {C#s{w  Class:  {C#s{w{/"
               "You have {C#h{w/{C#H{w hit, {C#m{w/{C#M{w mana, {C#v{w/{C#V{w movement.{/"
               "You have {C#p{w practices.{/"
               "You are carrying {C#x{w/{C#X{w items with weight {C#y{w/{C#Y{w pounds.{/"
               "Str: {C@S{w({C@s{w)  Int: {C@I{w({C@i{w)  Wis: {C@W{w({C@w{w)  Dex: {C@D{w({C@d{w)  Con: {C@C{w({C@c{w){/"
               "You have scored {C#e{w exp, and have {C#g{w gold coins.{/"
               "You need {C#E{w exp to level.{/"
               "Wimpy set to {C#W{w hit points.{/"
               "You are {C#P{w.{/"
               "Your alignment is {C@a{w.{/"
     },
     {
          "{/Your stats:{/"
               "STR: @s/@S{/"
               "INT: @i/@I{/"
               "WIS: @w/@W{/"
               "DEX: @d/@D{/"
               "CON: @c/@C{/"
     }
};

void do_cscore ( CHAR_DATA *ch, char *argument )
{
     char *outbuf = NULL;
     int i;

     if ( argument[0] == '\0' || !is_number ( argument ) )
     {
          send_to_char ( "Syntax: cscore <number>\n\r  <number> is the text you wish to view.\n\r", ch );
          send_to_char ( "Warning: cscore is currently experimental code. Please report any flaws\n\r"
                         "to the IMMs and be aware that usefulness is currently limited in ways that\n\r"
                         "it will not always be.\n\r", ch );
          return;
     }

     i = atoi(argument);

     if ( !ENTRE ( 0, i, MAX_CSCORE+1 ) )
     {
          send_to_char ( "Value out of range. (Yes this is not a very informative message. The code is\n\rstill experimental. So there.)", ch );
          return;
     }

     i--; // Start at base 0;

     outbuf = csc_translate ( ch, cscore_table[i].text, NULL, NULL, NULL );
     page_to_char ( outbuf, ch );
     return;
}

void do_score ( CHAR_DATA *ch, char *argument )
{
     BUFFER    *buffer;
     int        day;

     if ( IS_NPC ( ch ) )
     {
          send_to_char ( "You are an NPC. Bye.", ch );
          return;
     }

     buffer = buffer_new(1024);

     bprintf(buffer, "\n\r{C+{c----------------------------{C[ {W%11s {C]{c----------------------------{C+\n\r",
             ch->name );
     bprintf ( buffer, "{wIncarnation: {D[{W%8s{D]           {wRace: {D[{W%8s{D]      {wClass: {D[{W%8s{D]\n\r",
               IS_IMMORTAL (ch) ? "Immortal" : (ch->pcdata->mortal ? "Mortal" : "Demi-God"),
               race_table[ch->race].name,
               class_table[ch->pcdata->pclass].name );
     day = ch->pcdata->startday + 1;
     bprintf ( buffer, "        {wAge: {D[{W%7d{D]        {wBirthday: {D[{WDay %d of %s, %d{D]\n\r",
               get_age ( ch ), day, month_name[ch->pcdata->startmonth], ch->pcdata->startyear );
     if ( ch->pcdata->clan )
     {
          bprintf ( buffer, "       {wRank: {D[{W%15s{D] {wof Clan: {D[{W%s{D]\n\r",
                    ch->sex == 2 ? ch->pcdata->clan->franks[ch->pcdata->clrank] :
                    ch->pcdata->clan->mranks[ch->pcdata->clrank],
                    ch->pcdata->clan->clan_name );
     }
     bprintf ( buffer, "      {wLevel: {D[{W%7d{D]      {wExperience: {D[{W%7d{D]     {wTo Level: {D[{W%7d{D]\n\r",
               ch->level, ch->exp,
               ( ch->level + 1 ) * exp_per_level ( ch, ch->pcdata->points ) - ch->exp );
     bprintf ( buffer, "   {wQuestPts: {D[{W%7d{D]      {w QP Earned: {D[{W%7d{D]\n\r",
               ch->pcdata->questpoints, ch->pcdata->questearned );

     bprintf ( buffer, "          {C+{c------------------{C[{W    Ratings   {C]{c------------------{C+\n\r" );
     bprintf ( buffer, "  {wMob Kills: {D[{W%7d{D]     {w Mob Deaths: {D[{W%7d{D]     {w  Rating: {D[{W%7ld{D]\n\r",
               ch->pcdata->mob_wins, ch->pcdata->mob_losses, ch->pcdata->mob_rating );
     bprintf ( buffer, " {wPKill Wins: {D[{W%7d{D]    {wPKill Losses: {D[{W%7d{D]       {wRating: {D[{W%7d{D]\n\r",
               ch->pcdata->pkill_wins, ch->pcdata->pkill_losses, ch->pcdata->battle_rating );
     bprintf ( buffer, "                         {wOverall Score: {D[{W%7d{D]\n\r",
               score_calc ( ch ) );
     bprintf (buffer, "{C+{c-----------------------------------------------------------------------{C+{x\n\r");

     if ( ch->pcdata->account->status <= ACCT_VERIFIED && ch->level <=5 )
          bprintf ( buffer, "For more information, use these commands: armor, stats, affects, info\n\r"
                    "  This message will go away after level 5.\n\r" );

     page_to_char ( buffer->data, ch );
     buffer_free ( buffer );
     return;
}

void do_stats ( CHAR_DATA * ch, char *argument )
{
     BUFFER *buffer;

     if ( IS_NPC ( ch ) )
          return;

     buffer = buffer_new ( 1024 );

     bprintf(buffer, "\n\r{C+{c----------------------------{C[ {W%11s {C]{c----------------------------{C+\n\r",
             ch->name );

     bprintf ( buffer, "    {wStrength: {D[{W%2d{D/{W%2d{D]{w      Hit+: {D[{W%4d{D]{w   Dam+: {D[{W%4d{D]{w"
               "   Weight: {D[{W%4d{D]{w\n\r                          Wield: {D[{W%4d{D]{w\n\r",
               get_curr_stat ( ch, STAT_STR ),
               ch->perm_stat[STAT_STR],
               str_app[get_curr_stat(ch, STAT_STR)].tohit,
               str_app[get_curr_stat(ch, STAT_STR)].todam,
               str_app[get_curr_stat(ch, STAT_STR)].carry,
               str_app[get_curr_stat(ch, STAT_STR)].wield );
     bprintf ( buffer, "{w   Dexterity: {D[{W%2d{D/{W%2d{D]{w   Defense: {D[{W%4d{D]{w\n\r",
               get_curr_stat ( ch, STAT_DEX ),
               ch->perm_stat[STAT_DEX],
               dex_app[get_curr_stat(ch, STAT_DEX)].defensive );
     bprintf ( buffer, "{wConstitution: {D[{W%2d{D/{W%2d{D]{w  HP Bonus: {D[{W%4d{D]{w  Shock  {D[{W%4d{D]{w\n\r",
               get_curr_stat ( ch, STAT_CON ),
               ch->perm_stat[STAT_CON],
               con_app[get_curr_stat(ch, STAT_CON)].hitp,
               con_app[get_curr_stat(ch, STAT_CON)].shock );
     bprintf ( buffer, "{wIntelligence: {D[{W%2d{D/{W%2d{D] {wInt Learn: {D[{W%4d{D]{w  Mag+   {D[{W%4d{D]{w\n\r",
               get_curr_stat ( ch, STAT_INT ),
               ch->perm_stat[STAT_INT],
               int_app[get_curr_stat(ch, STAT_INT)].learn,
               int_app[get_curr_stat(ch, STAT_INT)].mspell );
     bprintf ( buffer, "{w      Wisdom: {D[{W%2d{D/{W%2d{D]  {wPractice: {D[{W%4d{D]{w Cleric+ {D[{W%4d{D]{w\n\r",
               get_curr_stat ( ch, STAT_WIS ),
               ch->perm_stat[STAT_WIS],
               wis_app[get_curr_stat(ch, STAT_WIS)].practice,
               wis_app[get_curr_stat(ch, STAT_WIS)].cspell );
     bprintf (buffer, "{C+{c-----------------------------------------------------------------------{C+{x\n\r");

     page_to_char ( buffer->data, ch );
     buffer_free ( buffer );
     return;
}

void do_info ( CHAR_DATA * ch, char *argument )
{
     BUFFER    *buffer;
     char	buf2[MIL];
     char       message[MIL];
     int        trust;

     if ( IS_NPC ( ch ) )
     {
          send_to_char ( "You are an NPC. Bye.", ch );
          return;
     }

     buffer = buffer_new(1024);

     if ( ch->alignment > 900 )
          SNP ( buf2, "{Wangelic" );
     else if ( ch->alignment > 700 )
          SNP (buf2, "{Wsaintly" );
     else if ( ch->alignment > 350 )
          SNP (buf2, "{Cgood" );
     else if ( ch->alignment > 100 )
          SNP (buf2, "{Ckind" );
     else if ( ch->alignment > -100 )
          SNP (buf2, "{wneutral" );
     else if ( ch->alignment > -350 )
          SNP (buf2, "{rmean" );
     else if ( ch->alignment > -700 )
          SNP (buf2, "{revil" );
     else if ( ch->alignment > -900 )
          SNP (buf2, "{Rdemonic" );
     else
          SNP (buf2, "{Rsatanic" );

     bprintf ( buffer, "{wYou are a %s{w %s %s %s, and ",
               buf2,
               ch->sex == 0 ? "sexless" : ch->sex == 1 ? "male" : "female",
               race_table[ch->race].name,
               class_table[ch->pcdata->pclass].name );

     bprintf ( buffer, "have played for {W%d {whours.\n\r",
               ( ch->played + ( int ) ( current_time - ch->logon ) ) / 3600 );

     switch ( ch->position )
     {
     case POS_DEAD:
          SNP ( buf2, "{RDEAD!!");
          break;
     case POS_MORTAL:
          SNP ( buf2, "{RMortally Wounded!!!!");
          break;
     case POS_INCAP:
          SNP ( buf2, "{yincapacitated!!!");
          break;
     case POS_STUNNED:
          SNP ( buf2, "{ystunned!!");
          break;
     case POS_SLEEPING:
          SNP ( buf2, "{csleeping");
          if (ch->on != NULL)
          {
               if (IS_SET(ch->on->value[2],SLEEP_AT))
               {
                    SNP(message," at %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
               else if (IS_SET(ch->on->value[2],SLEEP_ON))
               {
                    SNP(message," %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
               else
               {
                    SNP(message, " in %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
          }
          break;
     case POS_SITTING:
          SNP ( buf2, "{csitting");
          if (ch->on != NULL)
          {
               if (IS_SET(ch->on->value[2],SIT_AT))
               {
                    SNP(message," at %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
               else if (IS_SET(ch->on->value[2],SIT_ON))
               {
                    SNP(message," on %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
               else
               {
                    SNP(message, " in %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
          }
          break;
     case POS_RESTING:
          SNP( buf2, "{cresting");
          if (ch->on != NULL)
          {
               if (IS_SET(ch->on->value[2],REST_AT))
               {
                    SNP(message," at %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
               else if (IS_SET(ch->on->value[2],REST_ON))
               {
                    SNP(message," on %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
               else
               {
                    SNP(message, " in %s.",
                        ch->on->short_descr);
                    SLCAT(buf2,message);
               }
          }
          break;
     case POS_STANDING:
          SNP( buf2, "{wstanding.");
          break;
     case POS_FIGHTING:
          SNP( buf2, "{RFighting ");
          if ( ch->fighting == NULL )
               SLCAT ( buf2, "thin air??" );
          else if ( ch->fighting == ch )
               SLCAT ( buf2, "YOURSELF!!" );
          else if ( ch->in_room == ch->fighting->in_room )
               SLCAT ( buf2, PERSMASK ( ch->fighting, ch ) );
          else
               SLCAT ( buf2, "someone who left??" );
          break;
     default:
          SNP( buf2, "under the Influence of a Bug.");
          break;
     }

     bprintf ( buffer, "You are currently %s{w\n\r", buf2 );

     trust = get_trust ( ch );
     if ( trust > ch->level )
          bprintf ( buffer, "It seems you've tricked the Gods into trusting you at level {G%d{w.\n\r", trust );

     if ( ch->pcdata->condition[COND_DRUNK] > 10 )
          bprintf ( buffer, "You are {Bd{yr{cu{Mn{rk{W.{w\n\r" );
     if ( ch->pcdata->condition[COND_THIRST] == 0 )
          bprintf ( buffer, "You are {Rthirsty{w.\n\r" );
     if ( ch->pcdata->condition[COND_FULL] == 0 )
          bprintf ( buffer, "You are {Rhungry{w.\n\r", ch );

     bprintf ( buffer, "You are speaking in the {Y%s{x language.\n\r", ch->speaking );

	 /* AC moved to Armor command */
	 /* RT wizinvis and holy light */
     if ( IS_IMMORTAL ( ch ) )
     {
          bprintf (buffer, "Holy Light: %s",
                   IS_SET (ch->act, PLR_HOLYLIGHT) ?
                   "on   " : "off  " );
          if ( IS_SET ( ch->act, PLR_WIZINVIS ) )
               bprintf ( buffer, "Invisible: level %d   ", ch->invis_level );
          if ( IS_SET ( ch->act, PLR_CLOAK ) )
               bprintf ( buffer, "Cloak: level %d", ch->cloak_level );

          bprintf ( buffer, "\n\r" );
     }

     page_to_char ( buffer->data, ch );
     buffer_free ( buffer );
     return;

}

// Modified to give something useful in the new armor system... - Lotherius
void do_armor (CHAR_DATA *ch, char *argument )
{
     OBJ_DATA  *obj;
     int 	i;
     int 	armor[4];

     // Zero the values
     for ( i = 0; i < 4; i++ )
          armor[i] = 0;

     // Add up the totals
     for ( i = 0; i < MAX_WEAR; i++ )
     {
          if ( ( obj = get_eq_char ( ch, i ) ) == NULL )
               continue;
          armor[0] += c_base_ac ( obj, AC_PIERCE );
          armor[1] += c_base_ac ( obj, AC_BASH   );
          armor[2] += c_base_ac ( obj, AC_SLASH  );
          armor[3] += c_base_ac ( obj, AC_EXOTIC );
     }

     if ( ch->level >= 25 )
          form_to_char ( ch, "{cYour Armor{W:\n\r {cPierce{W: {C%d  {cBash{W: {C%d  {cslash{W: {C%d  {cexotic{W: {C%d{x\n\r",
                         armor[0], armor[1], armor[2], armor[3] );
     if ( ch->armor > 0 )
          form_to_char ( ch, " {cMagical Bonii{W: {C%d{w\n\r", ch->armor );

     for ( i = 0; i < 4; i++ )
     {
          char               *temp;
          switch ( i )
          {
          case ( AC_PIERCE ):
               temp = "piercing";
               break;
          case ( AC_BASH ):
               temp = "bashing";
               break;
          case ( AC_SLASH ):
               temp = "slashing";
               break;
          case ( AC_EXOTIC ):
               temp = "magic";
               break;
          default:
               temp = "error";
               break;
          }

          // With 15 hittable body parts, theoretical max armor should be 1500
          // This is of course with the assumption that a location's armor does not
          // exceed 100 (it shouldn't) without magical bonii. If ALL locations had
          // 100 AC *AND* there were magical bonii, then the total could exceed 1500.
          //
          if ( armor[i] + ch->armor <= 10 )
               form_to_char ( ch, "{wYou are hopelessly vulnerable to {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 25 )
               form_to_char ( ch, "{wYou are defenseless against {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 50 )
               form_to_char ( ch, "{wYou are barely protected from {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 125 )
               form_to_char ( ch, "{wYou are slighty armored against {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 200 )
               form_to_char ( ch, "{wYou are somewhat armored against {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 300 )
               form_to_char ( ch, "{wYou are armored against {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 450 )
               form_to_char ( ch, "{wYou are well-armored against {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 700 )
               form_to_char ( ch, "{wYou are very well-armored against {W%s.\n\r", temp );
          else if ( armor[i] + ch->armor <= 1000 )
               form_to_char ( ch, "{wYou are heavily armored against {W%s{x.\n\r", temp );
          else if ( armor[i] + ch->armor <= 1300 )
               form_to_char ( ch, "{wYou are superbly armored against {W%s{x.\n\r", temp );
          else if ( armor[i] + ch->armor <= 1500 )
               form_to_char ( ch, "{wYou are almost invulnerable to {W%s{x.\n\r", temp );
          else
               form_to_char ( ch, "{wYou are divinely armored against {W%s{x.\n\r", temp );
     }
     return;
}

void do_affect ( CHAR_DATA * ch, char *argument )
{
     AFFECT_DATA        *paf;
     OBJ_DATA           *tmp;
     bool                noaffect = TRUE;

     send_to_char ( "You are affected by:\n\r", ch );
     if ( ch->affected != NULL )
     {
          noaffect = FALSE;
          for ( paf = ch->affected; paf != NULL; paf = paf->next )
          {
               form_to_char ( ch, "Spell:   [{G%15s{w] ",
                              skill_table[paf->type].name );

               if (paf->location != APPLY_NONE)
                    form_to_char ( ch, "modifies %s by %d ",
                                   affect_loc_name (paf->location), paf->modifier );
               if (paf->duration >= 0)
                    form_to_char ( ch, "for %d hours.\n\r", paf->duration );
               else
                    form_to_char ( ch, "forever.\n\r" );
          }
     }
	 /* now, loop through object affects */
     for ( tmp = ch->carrying; tmp != NULL; tmp = tmp->next_content )
     {
          if ( tmp->wear_loc != WEAR_NONE )
          {
               for ( paf = tmp->affected; paf != NULL; paf = paf->next )
               {
                    if ( paf->bitvector )	/* check for spell vs just normal bonus affect */
                    {
                         noaffect = FALSE;
                         switch (paf->where)
                         {
                         case TO_AFFECTS:
                              form_to_char ( ch, "Affect:  [{G%15s{w] ", affect_bit_name ( paf->bitvector ) );
                              break;
                         case TO_DETECTIONS:
                              form_to_char ( ch, "Detect:  [{G%15s{w] ", detect_bit_name ( paf->bitvector ) );
                              break;
                         case TO_PROTECTIONS:
                              form_to_char ( ch, "Protect: [{G%15s{w] ", protect_bit_name ( paf->bitvector ) );
                              break;
                         }
                         if (paf->location != APPLY_NONE)
                              form_to_char ( ch, "modifies %s by %d ",
                                             affect_loc_name (paf->location), paf->modifier );
                         if (paf->duration >= 0)
                              form_to_char ( ch, "for %d hours.\n\r", paf->duration );
                         else
                              form_to_char ( ch, "until removed.\n\r" );
                    }
               }
               if ( !tmp->enchanted )
               {
                    for ( paf = tmp->pIndexData->affected; paf != NULL; paf = paf->next )
                    {
                         if ( paf->bitvector )
                         {
                              noaffect = FALSE;
                              switch (paf->where)
                              {
                              case TO_AFFECTS:
                                   form_to_char ( ch, "Affect:  [{G%15s{w] ", affect_bit_name ( paf->bitvector ) );
                                   break;
                              case TO_DETECTIONS:
                                   form_to_char ( ch, "Detect:  [{G%15s{w] ", detect_bit_name ( paf->bitvector ) );
                                   break;
                              case TO_PROTECTIONS:
                                   form_to_char ( ch, "Protect: [{G%15s{w] ", protect_bit_name ( paf->bitvector ) );
                                   break;
                              }
                              if (paf->location != APPLY_NONE)
                                   form_to_char ( ch, "modifies %s by %d ",
                                                  affect_loc_name (paf->location), paf->modifier );
                              if (paf->duration >= 0)
                                   form_to_char ( ch, "for %d hours.\n\r", paf->duration );
                              else
                                   form_to_char ( ch, "until removed.\n\r" );
                         }
                         /* end for */
                    }
                    /* end if equipped loop */
               }
               /* End if enchanted */
          }
          /*end carrying for loop */
     }

     if ( noaffect )
          send_to_char ( "Nothing.\n\r", ch );
     return;
}

void do_time ( CHAR_DATA * ch, char *argument )
{
     char               *suf;
     int                 day;

     day = time_info.day + 1;

     if ( day > 4 && day < 20 )
          suf = "th";
     else if ( day % 10 == 1 )
          suf = "st";
     else if ( day % 10 == 2 )
          suf = "nd";
     else if ( day % 10 == 3 )
          suf = "rd";
     else
          suf = "th";
     form_to_char ( ch, "{W[{Y%d{W:{Y00 {C%s{W] {WThe Day of %s, {C%d%s the Month of %s {win year {C%d{w.\n\r",
                    ( time_info.hour % 12 == 0 ) ? 12 : time_info.hour % 12,
                    time_info.hour >= 12 ? "pm" : "am",
                    day_name[day % 7], day, suf,
                    month_name[time_info.month],
                    time_info.year );
     return;
}

void do_version ( CHAR_DATA * ch, char *argument )
{
     extern char         str_boot_time[];
     form_to_char ( ch, "{w" TXT_MUDVERSION " Compiled : " TXT_COMPILE ".\n\r"
                    "{W" TXT_MUDNAME " {wlast rebooted at %s"
                    "The current system time is %s\n\r",
                    str_boot_time,
                    ( char * ) ctime ( &current_time ) );
     return;
}

/* Outputs a formatted Calendar to the user. */

void do_calendar ( CHAR_DATA * ch, char *argument )
{
     int counter, i;

     form_to_char ( ch, "\n\r               [{CThe Month of {Y%s{C, year {Y%d{w]\n\r\n\r", month_name[time_info.month],
                    time_info.year );

     for ( i = 0; i <= 6 ; i++ )
          form_to_char ( ch, " [{W%11s{w]", capitalize(day_name[i]) );
     send_to_char ( "\n\r\n\r", ch );

     counter = 0;
     for ( i = 0; i <= 34 ; i++ )
     {
          if ( counter > 6 )
          {
               counter = 0;
               send_to_char ( "\n\r", ch );
          }
          if ( i != time_info.day )
               form_to_char ( ch, " [{c%11d{w]", i+1 );
          else
               form_to_char ( ch, " {C[{G%11d{C]{w", i+1 );
          counter ++;
     }
     send_to_char ( "\n\r\n\r", ch );

     if ( time_info.month == 0 )
          form_to_char ( ch, "Last Month: [{M%s{w]  {C::  ", month_name[16] );
     else
          form_to_char ( ch, "Last Month: [{M%s{w]  {C::  ", month_name[time_info.month-1] );

     if ( time_info.month == 16 )
          form_to_char ( ch, "{wNext Month: [{M%s{w]\n\r\n\r", month_name[0] );
     else
          form_to_char ( ch, "{wNext Month: [{M%s{w]\n\r\n\r", month_name[time_info.month+1] );
     return;
}

void do_weather ( CHAR_DATA * ch, char *argument )
{
     static char        *const sky_look[4] =
     {
          "cloudless",
               "cloudy",
               "rainy",
               "lit by flashes of lightning"
     };

     static char        *const sky_look_winter[4] =
     {
          "crystal clear",
               "cloudy",
               "icy",
               "snowing heavily"
     };

     if ( !IS_OUTSIDE ( ch ) )
     {
          send_to_char ( "You can't see the weather indoors.\n\r", ch );
          return;
     }

     if ( weather_info.change >= 0 )
     {
          form_to_char ( ch, "The sky is %s and a warm breeze blows from the south.\n\r",
                         sky_look[weather_info.sky] );
     }
     else
     {
          form_to_char ( ch, "The sky is %s and a cold northern wind chills you.\n\r",
                         sky_look_winter[weather_info.sky] );
     }
     return;
}

void do_help ( CHAR_DATA * ch, char *argument )
{
     HELP_DATA          *pHelp;
     char                argall[MAX_INPUT_LENGTH], argone[MAX_INPUT_LENGTH];
     BUFFER		*outbuf;
     bool		 found = FALSE;
     bool		 topbanner = TRUE;
     bool		 bottombanner = TRUE;

     outbuf = buffer_new(1000);

     if ( argument[0] == '\0' )
          argument = "summary";

     /* this parts handles help a b so that it returns help 'a b' */
     argall[0] = '\0';

     /* Specifying notb or nobb as an argument will turn off banners */

     while ( argument[0] != '\0' )
     {
          argument = one_argument ( argument, argone );
          if (!strcmp(argone, "notb") )
          {
               topbanner = FALSE;
               continue;
          }
          if (!strcmp(argone, "nobb") )
          {
               bottombanner = FALSE;
               continue;
          }

          if ( argall[0] != '\0' )
               SLCAT ( argall, " " );
          SLCAT ( argall, argone );
     }

     /* gotta check this again just in case something goofed */
     if ( argall[0] == '\0' )
          SLCAT (argall, "summary");

     for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next )
     {
          if ( pHelp->level > get_trust ( ch ) )
               continue;

          if ( is_name ( argall, pHelp->keyword ) )
          {
               if (topbanner)
                    bprintf(outbuf,
                            "\n\r{C={c=========================================={C[ {WSunderMud {R][ {C]{c={w\n\r\n\r");
               if ( pHelp->level >= 0 && str_cmp ( argall, "imotd" ) )
               {
                    bprintf ( outbuf, "{G%s\n\r{w", pHelp->keyword );
               }

               /*
                * Strip leading '.' to allow initial blanks.
                * Must use buffer_strcat to prevent conversion of % signs in helpfiles.
                */
               if ( pHelp->text[0] == '.' )
                    buffer_strcat ( outbuf, pHelp->text + 1 );
               else
                    buffer_strcat ( outbuf, pHelp->text );
               found = TRUE;
          }
     }

     if (bottombanner && found)
          bprintf ( outbuf,"{c={C[ {WHelp {C]{c==================================================={x\n\r" );

     if (!found)
          send_to_char ( "No help on that word.\n\r", ch );
     else
     {
          /* Only page if in a mode that prompts pages correctly. */
          if ( ch->desc->connected == CON_PLAYING )
               page_to_char ( outbuf->data, ch );
          else
               send_to_char ( outbuf->data, ch );
     }

     buffer_free(outbuf);

     return;
}

/* whois command */
void do_whois ( CHAR_DATA * ch, char *argument )
{
     BUFFER             *outbuf;
     DESCRIPTOR_DATA    *d;
     bool                found = FALSE;

     if (argument[0] == '\0')
     {
          argument = str_dup (ch->name);
     }

     outbuf = buffer_new(1000);

     for ( d = descriptor_list; d != NULL; d = d->next )
     {
          CHAR_DATA          *wch;

          if ( d->connected != CON_PLAYING || !can_see ( ch, d->character ) )
               continue;
          wch = ( d->original != NULL ) ? d->original : d->character;
          if ( !can_see ( ch, wch ) )
               continue;
          if ( !str_prefix ( argument, wch->name ) )
          {
               found = TRUE;
               bprintf ( outbuf, "   %s%s%s%s{x\n\r",
                         IS_SET ( wch->act,
                                  PLR_KILLER ) ? "{r({RKILLER{r){w " : "",
                         IS_SET ( wch->act,
                                  PLR_THIEF ) ? "{y({RTHIEF{y){w " : "",
                         wch->name, wch->pcdata->title );
               bprintf(outbuf, "  {c___________________________________________\n\r");
               bprintf ( outbuf, "  {c[{CLevel:         {G%4d{c] [{G%19s{c]\n\r",
                         wch->level,
                         wch->level <= HERO ? pc_race_table[wch->race].who_name :
                         wch->pcdata->immtitle );
               bprintf ( outbuf, "  {c[{CClan: {G%13s{c] [{CRank:{G %13s{c]\n\r",
                         (wch->pcdata->clan) ? wch->pcdata->clan->clan_short : "Clanless",
                         (wch->pcdata->clan) ? (wch->sex == 2 ? wch->pcdata->clan->franks[wch->pcdata->clrank] :
                                                wch->pcdata->clan->mranks[wch->pcdata->clrank] ) : "Clanless" );
               bprintf ( outbuf,
                         "  {c[{CPkill Wins:  {G%6d{c] [{CPkill Lost:  {R%6d{c]{x\n\r",
                         wch->pcdata->pkill_wins,
                         wch->pcdata->pkill_losses );
               bprintf ( outbuf, "  {c[{CMob Kills:  {G%7ld{c] [{CDeaths:     {R%7ld{c]{x\n\r",
                         wch->pcdata->mob_wins,
                         wch->pcdata->mob_losses );
               bprintf ( outbuf, "  {c[{CPK Rating:    {G%5d{c] [{CMob Rating:   {G%5ld{c]\n\r",
                         wch->pcdata->battle_rating, wch->pcdata->mob_rating );
               bprintf ( outbuf, "  {c[{CQP Total:   {G%7ld{c] [{CQP Earned   {G%7ld{c]\n\r",
                         wch->pcdata->questpoints, wch->pcdata->questearned );
               bprintf ( outbuf, "  {c[{CAge: {G%14d{c] {c[{CHours: {G%12d{c]\n\r",
                         get_age(wch),
                         ( wch->played + ( int ) ( current_time - wch->logon ) ) / 3600 );
               bprintf ( outbuf, "  {c[{CScore:      {G%7d{c] [                   ]\n\r",
                         score_calc ( wch ) );
               bprintf( outbuf, "  {c[_________________________________________]{x\n\r");
               if ( IS_IMMORTAL(wch) )
                    bprintf( outbuf, "   {W%s is a {RStaff Member.{w\n\r", wch->name );
               else if ( wch->pcdata->mortal )
                    bprintf( outbuf, "   {R%s is a mortal.{w\n\r", wch->name );
               else
                    bprintf( outbuf, "   {Y%s is a Demi-God.{w\n\r", wch->name );

               if ( wch->pcdata->email &&
                    wch->pcdata->email[0] != '\0' )
               {
                    bprintf ( outbuf, "   {W%s's email is: {C%s{x\n\r",
                              wch->name, wch->pcdata->email );
               }
          }
     }
     if ( !found )
     {
          send_to_char ( "No one of that name is playing.\n\r", ch );
          buffer_free(outbuf);
          return;
     }
     page_to_char ( outbuf->data, ch );
     buffer_free (outbuf);
}

/*
 * New 'who' command originally by Alander of Rivers of Mud.
 */

/* Newer 'who' command by Zeran */

/* 6/24/02 - Malloc here replaced with alloc_mem  - lotherius */

void do_who ( CHAR_DATA * ch, char *argument )
{
     char                buf[MAX_STRING_LENGTH];
     char                clanbuf[40];
     char                form[MAX_STRING_LENGTH];
     BUFFER		*output;
     DESCRIPTOR_DATA    *d;
     int                 iClass;
     int                 iRace = 0;
     int                 iLevelLower;
     int                 iLevelUpper;
     int                 nNumber;
     int                 immMatch = 0;
     int                 mortMatch = 0;
     bool                rgfClass[MAX_CLASS];
     bool                fClassRestrict;
     bool                fRaceRestrict;
     bool                fImmortalOnly;
     bool                fClanOnly, fMortal, fDemi, fHelper;
     struct who_slot    *table[111];	/*want 1 to 110, not 0 to 109 */
     int                 counter;

     for ( counter = 1; counter <= 110; counter++ )	/* init table */
          table[counter] = NULL;

     /*
      * Set default arguments.
      */

     iLevelLower = 0;
     iLevelUpper = MAX_LEVEL;
     fClassRestrict = FALSE;
     fRaceRestrict = FALSE;
     fImmortalOnly = FALSE;
     fClanOnly = FALSE;
     fMortal = FALSE;
     fDemi = FALSE;
     fHelper = FALSE;
     for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
          rgfClass[iClass] = FALSE;

	 /*
	  * Parse arguments.
	  */
     nNumber = 0;
     for ( ;; )
     {
          char                arg[MAX_STRING_LENGTH];

          argument = one_argument ( argument, arg );
          if ( arg[0] == '\0' )
               break;

          if ( is_number ( arg ) )
          {
               switch ( ++nNumber )
               {
               case 1:
                    iLevelLower = atoi ( arg );
                    break;
               case 2:
                    iLevelUpper = atoi ( arg );
                    break;
               default:
                    send_to_char ( "Only two level numbers allowed.\n\r", ch );
                    return;
               }
          }
          else
          {

			   /*
				* Look for classes to turn on.
				* And other flags.
				*/
               if ( arg[0] == 'i' )
               {
                    fImmortalOnly = TRUE;
               }
               else if ( !str_cmp ( arg, "clan" ) )
               {
                    if ( ch->pcdata->clan && !strcmp(ch->pcdata->clan->clan_short, "Loner" ) )
                    {
                         send_to_char ( "'who clan' is only available to players in clans.\n\r", ch );
                         return;
                    }
                    fClanOnly = TRUE;
               }
               else if ( !str_cmp ( arg, "mortal" ) || !str_cmp ( arg, "mort") )
               {
                    fMortal = TRUE;
               }
               else if ( !str_cmp ( arg, "demigod") || !str_cmp ( arg, "demi-god") || !str_cmp (arg, "demi") )
               {
                    fDemi = TRUE;
               }
               else if ( !str_cmp ( arg, "helper") )
               {
                    fHelper=TRUE;
               }
               else
               {
                    iClass = class_lookup ( arg );
                    if ( iClass == -1 )
                    {
                         iRace = pcrace_lookup ( arg );

                         if ( iRace == 0 )
                         {
                              send_to_char ( "That's not a valid race or class.\n\r", ch );
                              return;
                         }
                         else
                         {
                              fRaceRestrict = TRUE;
                         }
                    }
                    else
                    {
                         send_to_char
                              ( "Sorry, who list by class has been removed.\n\r",  ch );
                         return;
                    }
               }
          }
     }

     output = buffer_new(1000);

	 /* Zeran - form table */
     for ( d = descriptor_list; d != NULL; d = d->next )
     {
          CHAR_DATA          *wch;

		  /*
		   * Check for match against restrictions.
		   * Don't use trust as that exposes trusted mortals.
		   */
          wch = ( d->original != NULL ) ? d->original : d->character;
          if ( d->connected != CON_PLAYING || !can_see ( ch, wch ) )
          {
               if ( ( d->connected < CON_NOTE_TO ) ||
                    ( d->connected > CON_NOTE_FINISH ) )
                    continue;
          }

          if ( wch->level < iLevelLower
               || wch->level > iLevelUpper
               || ( fImmortalOnly && wch->level < LEVEL_HERO )
               || ( fClassRestrict && !rgfClass[wch->pcdata->pclass] )
               || ( fRaceRestrict && ( wch->pcdata->pcrace != iRace ) )
               || ( fMortal && !wch->pcdata->mortal )
               || ( fHelper && (wch->pcdata->account->status != ACCT_HELPER) )
               || ( fDemi && wch->pcdata->mortal && IS_IMMORTAL(wch) )
               || ( fClanOnly && !is_same_clan (wch, ch) ) )
               continue;

          if ( wch->level >= LEVEL_IMMORTAL )
               immMatch++;
          else
               mortMatch++;

          if ( table[wch->level] == NULL )	/*empty list */
          {
               table[wch->level] = alloc_mem ( sizeof ( struct who_slot ), "do_who" );
               table[wch->level]->ch = wch;
               table[wch->level]->next = NULL;
          }
          else			/* non-empty list */
          {
               struct who_slot    *tmp = table[wch->level];
               for ( ; tmp->next != NULL; tmp = tmp->next );	/*get to end of list */
               tmp->next = alloc_mem ( sizeof ( struct who_slot ), "do_who" );
               tmp->next->ch = wch;
               tmp->next->next = NULL;
          }
     }
     /* end form table...fun, fun, fun! :) */

	 /*
	  * Now show matching chars.
	  */

     bprintf ( output,
               "\n\r{C+{c--------------------------------{C[ {WThe Staff {C]{c--------------------------------{C+{x\n\r" );

     for ( counter = 110; counter >= 1; counter-- )	/*outside list loop */
     {
          CHAR_DATA          *wch;
          struct who_slot    *tmp = table[counter];
          struct who_slot    *free_tmp = NULL;

          if ( counter == 101 )
          {
               bprintf ( output,
                         "{C+{c-----------------------------------------------------------------------------{C+{x\n\r\n\r" );
               bprintf ( output,
                         "{C+{c-------------------------------{C[ {WThe Players {C]{c-------------------------------{C+{x\n\r" );
          }

          if ( tmp == NULL )	/* no one at this level */
               continue;
		  /* now, follow each chain to end */
          for ( ; tmp != NULL; tmp = tmp->next )
          {
               wch = tmp->ch;
               if ( wch == NULL )	/* got a problem */
               {
                    bugf ( "Got null table->ch, argh." );
                    continue;
               }
			   /* free the old struct who_slot */
               if ( free_tmp )
                    free_mem ( free_tmp, sizeof ( struct who_slot), "do_who" );
               SLCPY ( form, "{x[{Y%2d {W%s{x] %s%s%s%s%s %s" );

               if ( ( !IS_NPC ( wch ) ) &&
                    ( wch->pcdata->clan != NULL ) )
               {
                    SNP ( clanbuf, "%s",
                          wch->pcdata->clan->clan_name );
               }
               else
                    SNP ( clanbuf, "%s", "" );
               SNP ( buf, form,
                     wch->level,
                     wch->level <= HERO ? pc_race_table[wch->race].who_name : wch->pcdata->immtitle,
                     IS_SET ( wch->act, PLR_AFK ) ? "{r(AFK){x " : "",
                     IS_SET ( wch->act, PLR_KILLER ) ? "{r(KILLER){x " : "",
                     IS_SET ( wch->act, PLR_THIEF ) ? "{b(THIEF) {x" : "",
                     wch->name, IS_NPC ( wch ) ? "" : wch->pcdata->title, clanbuf );
               if ( IS_SET ( wch->act, PLR_WIZINVIS ) )
                    SLCAT ( buf, " {r({cWizi{r){x" );
               if ( IS_SET ( wch->act, PLR_CLOAK ) )
                    SLCAT ( buf, " {r({cCloak{r){x" );

               if ( !IS_NPC ( wch ) && ( wch->desc != NULL ) &&
                    wch->desc->editor )
                    SLCAT ( buf, " {M(OLC){x " );

			   /* hmm
				if ( (d->connected >= CON_NOTE_TO) || (d->connected <= CON_NOTE_FINISH) )
				SLCAT (buf, " {g(NOTE{x ");
				*/
               SLCAT ( buf, "\n\r" );

               bprintf ( output, buf );
			   /* set the free_tmp pointer in order to call free(free_tmp) near top
				* of loop */
               free_tmp = tmp;
          }
          /*end inner list loop */
		  /* free up the last who_slot from this level hash */
          if ( free_tmp )
               free_mem ( free_tmp, sizeof ( struct who_slot), "do_who" );
     }
     /*end countdown loop */

     bprintf( output, "{C+{c-----------------------------------------------------------------------------{C+{x\n\r" );

     bprintf ( output, "\n\r{yGuardians found: {r%d{x \n\r{yPlayers found:   {c%d{x\n\r", immMatch, mortMatch );
     page_to_char(output->data, ch);
     buffer_free(output);

     return;
}

/* For an accurate max_on, count must be called during each character's logon. */
void do_count ( CHAR_DATA * ch, char *argument )
{
     int                 count;
     DESCRIPTOR_DATA    *d;

     count = 0;

     /* Let's make sure we get a good count! */
     for ( d = descriptor_list; d != NULL; d = d->next )
     {
          if ( d->connected == CON_PLAYING && can_see ( ch, d->character ) )
               count++;
          if ( d->connected >= CON_NOTE_TO && can_see ( ch, d->character ) )
               count++;
     }

     max_on = UMAX ( count, max_on );
     if ( max_on == count )
          form_to_char ( ch, "There are %d characters on, the most on since reboot.\r\n\r\n", count );
     else
          form_to_char ( ch, "There are %d characters on, the most on since reboot was %d.\r\n\r\n", count, max_on );
     return;
}

void do_inventory ( CHAR_DATA * ch, char *argument )
{
     send_to_char ( "You are carrying:\n\r", ch );
     show_list_to_char ( ch->carrying, ch, TRUE, TRUE );
     return;
}

void do_equipment ( CHAR_DATA * ch, char *argument )
{
     OBJ_DATA           *obj;
     int                 iWear;
     bool                found;

     send_to_char ( "{C<{wLocation     {C> <{wAC Pier/Slas/Bash/Mag{C> {wItem Used:\n\r", ch );
     send_to_char ( "{c--------------- ----------------------- ----------{w\n\r", ch );
     found = FALSE;
     for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
     {
          if ( ( obj = get_eq_char ( ch, iWear ) ) == NULL )
               continue;

          form_to_char ( ch, "{C<{w%-13s{C>{w ", wear_info[iWear].name );

          if ( can_see_obj ( ch, obj ) )
          {
               if ( wear_info[iWear].has_ac == FALSE )
                    send_to_char ( "                        ", ch );
               else
                    form_to_char ( ch, "{C<{w%3d{C> <{w%3d{C> <{w%3d{C> <{w%3d{C>{w ",
                                   c_base_ac ( obj, AC_PIERCE ),
                                   c_base_ac ( obj, AC_BASH   ),
                                   c_base_ac ( obj, AC_SLASH  ),
                                   c_base_ac ( obj, AC_EXOTIC ) );
               send_to_char ( format_obj_to_char ( obj, ch, TRUE ), ch );
               send_to_char ( "\n\r", ch );
          }
          else
          {
               send_to_char ( "                        something.\n\r", ch );
          }
          found = TRUE;
     }
     if ( !found )
          send_to_char ( "Nothing.\n\r", ch );
     return;
}

// Compare needs fixed for new AC ...
//
void do_compare ( CHAR_DATA * ch, char *argument )
{
     char                arg1[MAX_INPUT_LENGTH];
     char                arg2[MAX_INPUT_LENGTH];
     OBJ_DATA           *obj1;
     OBJ_DATA           *obj2;
     int                 value1;
     int                 value2;
     char               *msg;

     argument = one_argument ( argument, arg1 );
     argument = one_argument ( argument, arg2 );
     if ( arg1[0] == '\0' )
     {
          send_to_char ( "Compare what to what?\n\r", ch );
          return;
     }

     if ( ( obj1 = get_obj_carry ( ch, arg1, NULL ) ) == NULL )
     {
          send_to_char ( "You do not have that item.\n\r", ch );
          return;
     }

     if ( arg2[0] == '\0' )
     {
          for ( obj2 = ch->carrying; obj2 != NULL; obj2 = obj2->next_content )
          {
               if ( obj2->wear_loc != WEAR_NONE
                    && can_see_obj ( ch, obj2 )
                    && obj1->item_type == obj2->item_type
                    && ( obj1->wear_flags & obj2->
                         wear_flags & ~ITEM_TAKE ) != 0 )
                    break;
          }

          if ( obj2 == NULL )
          {
               send_to_char ( "You aren't wearing anything comparable.\n\r", ch );
               return;
          }
     }

     else if ( ( obj2 = get_obj_carry ( ch, arg2, NULL ) ) == NULL )
     {
          send_to_char ( "You do not have that item.\n\r", ch );
          return;
     }

     msg = NULL;
     value1 = 0;
     value2 = 0;

     if ( obj1 == obj2 )
     {
          msg = "You compare $p to itself.  It looks about the same.";
     }
     else if ( obj1->item_type != obj2->item_type )
     {
          msg = "You can't compare $p and $P.";
     }
     else
     {
          switch ( obj1->item_type )
          {
          default:
               msg = "You can't compare $p and $P.";
               break;

          case ITEM_ARMOR:
               value1 = c_base_ac(obj1, AC_PIERCE) + c_base_ac(obj1, AC_BASH)
                    + c_base_ac(obj1, AC_SLASH ) + c_base_ac(obj1, AC_EXOTIC);
               value2 = c_base_ac(obj2, AC_PIERCE) + c_base_ac(obj2, AC_BASH)
                    + c_base_ac(obj2, AC_SLASH ) + c_base_ac(obj2, AC_EXOTIC);
               break;
          case 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];
               break;
          }
     }

     if ( msg == NULL )
     {
          if ( value1 == value2 )
               msg = "$p and $P look about the same.";
          else if ( value1 > value2 )
               msg = "$p looks better than $P.";
          else
               msg = "$p looks worse than $P.";
     }

     act ( msg, ch, obj1, obj2, TO_CHAR );
     return;
}

/*
 * new do_areas by Lotherius
 */

void do_areas ( CHAR_DATA * ch, char *argument )
{
     BUFFER    *buffer;
     AREA_DATA *pArea;
     int        i,x,y;

     if (argument[0] != '\0')
     {
          send_to_char("No options are currently available for the Area List.\n\r",ch);
          return;
     }

     buffer = buffer_new ( 1024 );
     x = MAX_VNUM;
     y = 0;

     bprintf ( buffer, "{c-{C[ {WAreas {C]{c-----------------------------------------------------------{C-{w\n\r" );

     bprintf ( buffer, "[{B Level {w] [{WName                        {w] [{YZone{w] [{GCredits             {w]\n\r" );
     for ( i = area_first->vnum; i <= area_last->vnum; i++ )
     {
          for ( pArea = area_first; pArea; pArea = pArea->next )
               if ( pArea->lvnum < x && pArea->lvnum > y )
                    x = pArea->lvnum;
          y = x;
          x = MAX_VNUM;
          for ( pArea = area_first; pArea; pArea = pArea->next )
               if ( y == pArea->lvnum )
               {
                    if ( pArea->zone > -1 )
                         bprintf ( buffer, "[{B%3d %3d{w] [{W%-28s{w] [{Y%3d {w] [{G%-20s{w]\n\r",
                                   pArea->llev,
                                   pArea->hlev,
                                   pArea->name,
                                   pArea->zone,
                                   pArea->credits );
               }
     }

     bprintf ( buffer, "{c---------------------------------------------------------------------{C-{w\n\r" );
     page_to_char ( buffer->data, ch );
     buffer_free ( buffer );
     return;
}

void do_credits ( CHAR_DATA * ch, char *argument )
{
     do_help ( ch, "diku" );
     return;
}

void do_where ( CHAR_DATA * ch, char *argument )
{
     if ( ch->in_room->area->name != NULL && ch->in_room->area->name[0] != '\0' )
          form_to_char ( ch, "You are currently in: {W%s{x\n\r", ch->in_room->area->name );
     else
          send_to_char ( "You are in an unnamed area, inform the IMPs asap.\n\r", ch );
     form_to_char ( ch, "This area is designed for levels {Y%d{w to {Y%d{w, ", ch->in_room->area->llev, ch->in_room->area->hlev );
     form_to_char ( ch, "and was originally built by: {C%s{w\n\r", ch->in_room->area->credits );

     return;
}

void do_consider ( CHAR_DATA * ch, char *argument )
{
     char                arg[MAX_INPUT_LENGTH];
     CHAR_DATA          *victim;

     one_argument ( argument, arg );

     if ( arg[0] == '\0' && ch->fighting != NULL )
     {
          SNP( arg, ch->fighting->name );
     }

     if ( arg[0] == '\0' )
     {
          send_to_char ( "Consider killing whom?\n\r", ch );
          return;
     }

     if ( !str_cmp ( arg, "all" ) )
     {
          bool found = FALSE;
          for ( victim = ch->in_room->people; victim != NULL; victim = victim->next_in_room )
          {
               if ( can_see ( ch, victim ) && ch != victim )
               {
                    found = TRUE;
                    real_consider ( ch, victim );
               }
          }
          if ( !found )
               send_to_char ( "You can't seem to find anyone here besides yourself.\n\r", ch );
     }
     else
     {
          if ( ( victim = get_char_room ( ch, NULL, arg ) ) == NULL )
          {
               send_to_char ( "They're not here.\n\r", ch );
               return;
          }
          else
               real_consider ( ch, victim );
     }
     return;
}

void real_consider ( CHAR_DATA *ch, CHAR_DATA *victim )
{
     char               *msg = '\0';
     char               *buf = '\0';
     int                 diff;
     int                 hpdiff;

     if ( is_safe ( ch, victim, TRUE ) )
          return;

     diff = victim->level - ch->level;

     if ( diff <= -10 )          msg = "$N: $E is not even worthy of your attention.";
     else if ( diff <= -5 )      msg = "$N: You could kill $M even on a bad day.";
     else if ( diff <= -2 )      msg = "$N: $E shouldn't be too hard.";
     else if ( diff <= 1 )       msg = "$N: The {Yperfect match{w!";
     else if ( diff <= 4 )       msg = "$N: With some luck & skill you could kill $M.";
     else if ( diff <= 9 )       msg = "$N: Maybe you should purchase life insurance first.";
     else                        msg = "$N: Would you like to borrow a pick & shovel?";

     act ( msg, ch, NULL, victim, TO_CHAR );

     /* additions by king@tinuviel.cs.wcu.edu */
     hpdiff = ( ch->hit - victim->hit );

     if ( ( ( diff >= 0 ) && ( hpdiff <= 0 ) ) || ( ( diff <= 0 ) && ( hpdiff >= 0 ) ) )
     {
          send_to_char ( "Also,", ch );
     }
     else
     {
          send_to_char ( "However,", ch );
     }
     if ( hpdiff >= 101 )          buf = " you are currently much healthier than $E.";
     if ( hpdiff <= 100 )          buf = " you are currently healthier than $E.";
     if ( hpdiff <= 50 )           buf = " you are currently slightly healthier than $E.";
     if ( hpdiff <= 25 )           buf = " you are a teensy bit healthier than $E.";
     if ( hpdiff == 0 )		   buf = " $E and you are just as healthy.";
     if ( hpdiff <= 0 )            buf = " $E is a teensy bit healthier than you.";
     if ( hpdiff <= -25 )          buf = " $E is slightly healthier than you.";
     if ( hpdiff <= -50 )          buf = " $E is healthier than you.";
     if ( hpdiff <= -100 )         buf = " $E is much healthier than you.";
     act ( buf, ch, NULL, victim, TO_CHAR );
     return;
}

void set_title ( CHAR_DATA * ch, char *title )
{
     char                buf[MAX_STRING_LENGTH];

     /* Silly mob, titles are for PC's */
     if ( IS_NPC ( ch ) )
          return;

     if ( title[0] != '.' && title[0] != ',' && title[0] != '!' && title[0] != '?' )
     {
          SLCPY ( buf, " " );
          SLCAT ( buf, title );
     }
     else
     {
          SLCPY ( buf, title );
     }

     free_string ( ch->pcdata->title );
     ch->pcdata->title = str_dup ( buf );
     return;
}

void do_title ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( argument[0] == '\0' )
     {
          send_to_char ( "Change your title to what?\n\r", ch );
          return;
     }
     if ( cstrlen ( argument ) > 45 )
     {
          send_to_char ( "Maximum of 45 characters allowed in your title, not counting colour.\n\r", ch );
          return;
     }
     if ( strlen ( argument ) > 85 )
     {
          send_to_char ( "Maximum of 85 characters allowed in your title, counting colour codes.\n\r", ch );
          return;
     }
     set_title ( ch, argument );
     send_to_char ( "Ok.\n\r", ch );
}

void do_immtitle ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( argument[0] == '\0' )
     {
          send_to_char ( "Change your immtitle to what?\n\r", ch );
          return;
     }
     if ( strlen ( argument ) > 15 )
          argument[15] = '\0';

     free_string ( ch->pcdata->immtitle );
     ch->pcdata->immtitle = str_dup ( argument );
     send_to_char ( "ImmTitle set.\n\r", ch );
}

void do_email ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;
     if ( argument[0] == '\0' )
     {
          send_to_char ( "Change your email to what?\n\r", ch );
          return;
     }
     if ( strlen ( argument ) > 50 )
          argument[50] = '\0';
     free_string ( ch->pcdata->email );
     ch->pcdata->email = str_dup ( argument );
     send_to_char ( "Email set.\n\r", ch );
}

void do_description ( CHAR_DATA * ch, char *argument )
{
     char                buf[MAX_STRING_LENGTH];

     if ( argument[0] != '\0' )
     {
          buf[0] = '\0';

          if ( argument[0] == '+' )
          {
               if ( ch->description != NULL )
                    SLCAT ( buf, ch->description );
               argument++;
               while ( isspace ( *argument ) )
                    argument++;
          }

          if ( strlen ( buf ) + strlen ( argument ) >= MAX_STRING_LENGTH - 2 )
          {
               send_to_char ( "Description too long.\n\r", ch );
               return;
          }

          if ( !str_prefix ( argument, "edit" ) )
          {
               if ( IS_NPC ( ch ) )
               {
                    if ( ch->desc )
                         send_to_char ( "You must use the non-interactive editor.", ch );
                    return;
               }
               ch->pcdata->mode = MODE_DESCEDIT;
               string_append ( ch, &ch->description );
               return;
          }

          SLCAT ( buf, argument );
          SLCAT ( buf, "\n\r" );
          free_string ( ch->description );
          ch->description = str_dup ( buf );
     }

     send_to_char ( "Your description is:\n\r", ch );
     send_to_char ( ch->description ? ch->description : "(None).\n\r", ch );
     return;
}

void do_report ( CHAR_DATA * ch, char *argument )
{
     char                buf[MAX_INPUT_LENGTH];
     form_to_char ( ch, "You say 'I have %d/%d hp %d/%d mana %d/%d mv %d xp.'\n\r",
                    ch->hit, ch->max_hit,
                    ch->mana, ch->max_mana,
                    ch->move, ch->max_move, ch->exp );
     SNP ( buf, "{g$n says '{GI have %d/%d hp %d/%d mana %d/%d mv %d xp.{g'",
           ch->hit, ch->max_hit, ch->mana, ch->max_mana,
           ch->move, ch->max_move, ch->exp );
     act ( buf, ch, NULL, NULL, TO_ROOM );
     return;
}

void do_practice ( CHAR_DATA * ch, char *argument )
{
     if ( IS_NPC ( ch ) )
          return;

     if ( argument[0] == '\0' )
     {
          show_current_prac ( ch );
     }
     else
     {
          CHAR_DATA          *mob;
          bool		      doall = FALSE; /* practice everything? */
          int                 adept, sn;

          if ( !IS_AWAKE ( ch ) )
          {
               send_to_char ( "In your dreams, or what?\n\r", ch );
               return;
          }
          for ( mob = ch->in_room->people; mob != NULL; mob = mob->next_in_room )
          {
               if ( IS_NPC ( mob ) && IS_SET ( mob->act, ACT_PRACTICE ) )
                    break;
          }
          if ( mob == NULL )
          {
               send_to_char ( "You can't do that here.\n\r", ch );
               return;
          }
          if ( ch->pcdata->practice <= 0 )
          {
               send_to_char ( "You have no practice sessions left.\n\r", ch );
               return;
          }

          if ( !str_cmp ( argument, "all" ) )
               doall = TRUE;

          adept = class_table[ch->pcdata->pclass].skill_adept;
          if ( !doall )
          {
               if ( ( sn = skill_lookup ( argument ) ) < 0 ||
                    ( ( ( skill_available ( sn, ch, SKILL_PRAC, NULL ) == FALSE ) ) ) )
               {
                    send_to_char ( "You can't practice that.\n\r", ch );
                    return;
               }

               if ( ch->pcdata->learned[sn] >= adept )
               {
                    form_to_char ( ch, "You can only learn more about %s through experience.\n\r", skill_table[sn].name );
                    return;
               }
               else
               {
                    ch->pcdata->practice--;
                    ch->pcdata->learned[sn] += ( int_app[get_curr_stat ( ch, STAT_INT )].learn ) / 3;
                    if ( ch->pcdata->learned[sn] < adept )
                    {
                         //act ( "You practice $T.", ch, NULL, skill_table[sn].name, TO_CHAR );
                         form_to_char ( ch, "You practice %s.   ", skill_table[sn].name );
                         act ( "$n practices $T.", ch, NULL, skill_table[sn].name, TO_ROOM );
                         form_to_char ( ch, "Practiced %s to %d%%.\n\r", skill_table[sn].name, ch->pcdata->learned[sn] );
                    }
                    else
                    {
                         ch->pcdata->learned[sn] = adept;
                         act ( "You are now learned at $T.", ch, NULL, skill_table[sn].name, TO_CHAR );
                         act ( "$n is now learned at $T.",   ch, NULL, skill_table[sn].name, TO_ROOM );
                    }
               }
          }
          // end of single prac
          else
          {
               bool found = FALSE;

               form_to_char ( ch, "Practicing everything to at least %d%%.\n\rYou have %d practices.\n\r",
                              (adept-10), ch->pcdata->practice );

               for ( sn = 0; sn < MAX_SKILL; sn++ ) /* Loop through all skills */
               {
                    if ( skill_table[sn].name == NULL )
                         break;
                    if ( skill_available ( sn, ch, SKILL_AVAIL, NULL ) == FALSE )
                         continue;

                    while ( ( ch->pcdata->learned[sn] < (adept-10) )
                            && ch->pcdata->practice > 0 )
                    {
                         found = TRUE;

                         ch->pcdata->practice--;
                         ch->pcdata->learned[sn] += ( int_app[get_curr_stat ( ch, STAT_INT)].learn ) / 3;
                         if ( ch->pcdata->learned[sn] < adept )
                         {
                              act ( "You practice $T.", ch, NULL, skill_table[sn].name, TO_CHAR );
                              form_to_char ( ch, "Practiced %s to %d%%.\n\r", skill_table[sn].name, ch->pcdata->learned[sn] );
                         }
                         else
                         {
                              ch->pcdata->learned[sn] = adept;
                              act ( "You are now learned at $T.", ch, NULL, skill_table[sn].name, TO_CHAR );
                         }
                    }
                    // End of while loop
                    if ( ch->pcdata->practice <= 0 )
                    {
                         send_to_char ( "You have no more practice sessions.\n\r", ch );
                         return;
                    }
               }
               /* end of for loop */
               if ( !found )
                    form_to_char ( ch, "Couldn't find any skills below %d%%.\n\r", (adept-10) );
               else
                    form_to_char ( ch, "You now have %d practice sessions.\n\r", ch->pcdata->practice );

          }
          // end of all prac
     }
     return;
}

void do_learn ( CHAR_DATA * ch, char *argument )
{
     int                 sn;

     if ( IS_NPC ( ch ) )
          return;

     if ( argument[0] == '\0' )
     {
          show_current_prac ( ch );
     }
     else
     {
          CHAR_DATA          *mob;
          int                 adept;
          if ( !IS_AWAKE ( ch ) )
          {
               send_to_char ( "In your dreams, or what?\n\r", ch );
               return;
          }
          for ( mob = ch->in_room->people; mob != NULL; mob = mob->next_in_room )
          {
               if ( IS_NPC ( mob ) && IS_SET ( mob->act, ACT_SKILLMASTER ) )
                    break;
          }
          if ( mob == NULL )
          {
               send_to_char ( "You can't do that here.\n\r", ch );
               return;
          }
          /* Zeran - handle "learn list" case here */
          if ( !str_cmp ( argument, "list" ) )
          {
               show_skillmaster_skills ( ch, mob );
               return;
          }
          if ( ch->pcdata->practice <= 0 )
          {
               send_to_char ( "You have no practice sessions left.\n\r", ch );
               return;
          }
          if ( ( sn = skill_lookup ( argument ) ) < 0 || ( !IS_NPC ( ch )
                                                           && ( ( skill_available ( sn, ch, SKILL_LEARN, mob ) == FALSE ))))
          {
               send_to_char ( "You can't learn that.\n\r", ch );
               return;
          }

          adept = IS_NPC ( ch ) ? 100 : class_table[ch->pcdata->pclass].skill_adept;

          if ( ch->pcdata->learned[sn] >= adept )
          {
               form_to_char ( ch, "You can only learn more about %s through experience.\n\r",
                              skill_table[sn].name );
          }
          else
          {
               ch->pcdata->practice--;
               ch->pcdata->learned[sn] += ( int_app[get_curr_stat ( ch, STAT_INT )].learn ) / 3;

               if ( ch->pcdata->learned[sn] <= adept )
               {
                    act ( "$N teaches you more about $t.", ch, skill_table[sn].name, mob, TO_CHAR );
                    act ( "$N teaches $n more about $t.",  ch, skill_table[sn].name, mob, TO_ROOM );
                    form_to_char ( ch, "Learned %s to %d%%.\n\r", skill_table[sn].name, ch->pcdata->learned[sn] );
               }
               else
               {
                    ch->pcdata->learned[sn] = adept;
                    act ( "You are now learned at $T.", ch, NULL, skill_table[sn].name, TO_CHAR );
                    act ( "$n is now learned at $T.",   ch, NULL, skill_table[sn].name, TO_ROOM );
               }
          }
     }
     return;
}

/*
 * 'Wimpy' originally by Dionysos.
 */
void do_wimpy ( CHAR_DATA * ch, char *argument )
{
     char                arg[MAX_INPUT_LENGTH];
     int                 wimpy;

     one_argument ( argument, arg );

     if ( arg[0] == '\0' )
          wimpy = ch->max_hit / 5;
     else
          wimpy = atoi ( arg );

     if ( wimpy < 0 )
     {
          send_to_char ( "Your courage exceeds your wisdom.\n\r", ch );
          return;
     }

     if ( wimpy > ch->max_hit / 2 )
     {
          send_to_char ( "Such cowardice ill becomes you.\n\r", ch );
          return;
     }
     if ( wimpy == 0 )
          form_to_char ( ch, "You won't try to flee even if you're dead.\n\r" );
     else
          form_to_char ( ch, "You will now attempt to flee under %d hit points.\n\r", wimpy );
     ch->wimpy = wimpy;
     return;
}

void do_password ( CHAR_DATA * ch, char *argument )
{
     char                arg1[MAX_INPUT_LENGTH];
     char                arg2[MAX_INPUT_LENGTH];
     char               *pArg;
     char               *pwdnew;
     char               *p;
     char                cEnd;

     if ( IS_NPC ( ch ) )
          return;
     /*
      * Can't use one_argument here because it smashes case.
      * So we just steal all its code.  Bleagh.
      */
     pArg = arg1;
     while ( isspace ( *argument ) )
          argument++;

     cEnd = ' ';
     if ( *argument == '\'' || *argument == '"' )
          cEnd = *argument++;

     while ( *argument != '\0' )
     {
          if ( *argument == cEnd )
          {
               argument++;
               break;
          }
          *pArg++ = *argument++;
     }
     *pArg = '\0';

     pArg = arg2;
     while ( isspace ( *argument ) )
          argument++;

     cEnd = ' ';
     if ( *argument == '\'' || *argument == '"' )
          cEnd = *argument++;

     while ( *argument != '\0' )
     {
          if ( *argument == cEnd )
          {
               argument++;
               break;
          }
          *pArg++ = *argument++;
     }
     *pArg = '\0';

     if ( arg1[0] == '\0' || arg2[0] == '\0' )
     {
          send_to_char ( "Syntax: password <old> <new>.\n\r", ch );
          return;
     }

     if ( strcmp
          ( crypt ( arg1, ch->pcdata->pwd ), ch->pcdata->pwd ) )
     {
          if ( ( !strcmp ( arg1, "null" ) ) && ( ch->pcdata->pwd[0] == '\0' ) )
          {
               send_to_char ( "Fixing null password. Remember to report this error.\n\r", ch );
          }
          else
          {
               WAIT_STATE ( ch, 40 );
               send_to_char ( "Wrong password.  Wait 10 seconds.\n\r", ch );
               return;
          }
     }

     if ( strlen ( arg2 ) < 5 )
     {
          send_to_char ( "New password must be at least five characters long.\n\r", ch );
          return;
     }

     /*
      * No tilde allowed because of player file format.
      */
     pwdnew = crypt ( arg2, ch->name );
     for ( p = pwdnew; *p != '\0'; p++ )
     {
          if ( *p == '~' )
          {
               send_to_char ( "New password not acceptable, try again.\n\r", ch );
               return;
          }
     }

     free_string ( ch->pcdata->pwd );
     ch->pcdata->pwd = str_dup ( pwdnew );
     save_char_obj ( ch );
     send_to_char ( "Ok.\n\r", ch );
     return;
}

void do_xinfo ( CHAR_DATA * ch, char *argument )
{
     real_auto ( ch, PLR_XINFO, "View Xinfo" );
}

bool is_outside ( CHAR_DATA * ch )
{
     if ( IS_SET ( ch->in_room->room_flags, ROOM_INDOORS ) )
          return FALSE;
     if ( IS_SET ( ch->in_room->sector_type, SECT_INSIDE ) )
          return FALSE;
     return TRUE;
}

void do_verify ( CHAR_DATA *ch, char *argument )
{
     FILE *fp;
     char buf[MSL];
     char cmdbuf[MSL];
     int  vcode;

     if ( IS_NPC ( ch ) )
          return;

     /* Need to handle changing account id's, but not now. */

     if (ch->pcdata->account->status >= ACCT_VERIFIED)
     {
          send_to_char ( "You've already been verified!\n\r", ch );
          return;
     }

     if (argument[0] != '\0')
     {
          if (!is_number (argument) )
          {
               send_to_char ("{RVerify Failed. Please copy the code exactly from the email.{w\n\r", ch);
               return;
          }

          if ( atoi(argument) == ch->pcdata->account->vcode )
          {
               send_to_char ("{GWelcome to VERIFIED status!{w\n\r", ch );
               if (ch->pcdata->account->heroes >= mud.fordemi )
               {
                    send_to_char ( "Since you have 2 Mortal Heroes{w, you may now create\n\r"
                                   "{YDEMI-GOD{w characters. Congratulations!\n\r", ch);
                    ch->pcdata->account->status = ACCT_VERIFIED_DEMISTAT;
               }
               else
               {
                    send_to_char ( "You will need a total of 2 Mortal Heroes before you will be able"
                                   "to create DEMI-GOD characters.\n\r", ch);
                    ch->pcdata->account->status = ACCT_VERIFIED;
               }
               log_string ( "%s:%s Verify Succeeded.", ch->name, ch->pcdata->account->acc_name );
               fwrite_accounts ( ); /* Must always save accounts to avoid loss of data! */
               return;
          }
          send_to_char ("{RVerify Failed. Please copy the code exactly from the email.{w\n\r", ch);
          return;
     }

     if ( ch->pcdata->account->vcode > 0 )
     {
          send_to_char ("You've already requested a validation code!\n\r", ch );
          send_to_char ("If for some reason you didn't receive the email,\n\r"
                        "try again after the next system reboot.\n\r", ch );
          return;
     }

     /* We don't need to be TOO fancy. */
     vcode = number_range (1, 128000);
     /* Not saved! */
     ch->pcdata->account->vcode = vcode;

     send_to_char( "Sending your {GVerification Code{w to the email you provided.\n\r", ch );
     send_to_char( "\n\rYou will need to enter this code to the mud as soon as possible,\n\r", ch );
     send_to_char( "or you will need to request a new code if the mud has rebooted.\n\r", ch );

     if ( ( fp = fopen ( "temptomail", "w+" ) ) == NULL )
     {
          bugf ( "Failed openning temptomail for writing." );
          send_to_char( "Something went wrong. Mail not sent.\n\r", ch );
          return;
     }

     SNP (buf, "Someone has requested a verification code for " TXT_MUDNAME " be sent to this\n"
          "email address. If this was not you, you can safely ignore this message.\n\n"
          "To verify your " TXT_MUDNAME " account, enter the following command exactly as\n"
          "shown into " TXT_MUDNAME ":\n\rverify %d\n\n"
          "Once you have done this, your account will be fully verified.\n"
          "If you do not enter this validation code before the next system reboot,\n"
          "however, you will need to re-request your validation code.\n"
          "Thank you for verifying your email address,\n"
          "\nThe " TXT_MUDNAME " Staff", vcode );
     fprintf ( fp, buf );
     fclose ( fp );

     SNP ( cmdbuf, "cat temptomail | /usr/bin/mail -s \"" TXT_MUDNAME " Verification Request\" %s",
           ch->pcdata->account->acc_name );

     if ( system ( cmdbuf ) == 1 )
     {
          bugf ("Failed to execute command on do_verify: %s", cmdbuf );
          send_to_char ("Failed to execute mail on verify.\n\r", ch);
     }
     else
     {
          log_string ( "Verification %d sent to %s.", vcode, ch->pcdata->account->acc_name );
          send_to_char ("\n\rVerification code sent. Check your email.\n\r", ch );
     }
     return;
}