clan/
class/
data/
doc/ideas/
doc/mobprogs/
gods/
log/
player/
time/
/*
 *  The unique portions SunderMud code as well as the integration efforts
 *  for code from other sources is based on the efforts of:
 *
 *  Lotherius (elfren@aros.net)
 *
 *  This code can only be used under the terms of the DikuMud, Merc,
 *  and ROM licenses. The same requirements apply to the changes that
 *  have been made.
 *
 * All other copyrights remain in place and in force.
*/


/***************************************************************************
 *  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.                                                  *
 ***************************************************************************/

#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		);

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

char *	const	where_name	[] =
{
    "<used as light>     ",
    "<worn on finger>    ",
    "<worn on finger>    ",
    "<worn around neck>  ",
    "<worn around neck>  ",
    "<worn on body>      ",
    "<worn on head>      ",
    "<worn on legs>      ",
    "<worn on feet>      ",
    "<worn on hands>     ",
    "<worn on arms>      ",
    "<worn as shield>    ",
    "<worn about body>   ",
    "<worn about waist>  ",
    "<worn around wrist> ",
    "<worn around wrist> ",
    "<wielded>           ",
    "<held>              ",
	"<second wield>      ",
	"<worn with pride>   ",
	"<worn on face>      ",
	"<worn on ears>      ",
	"<floating nearby>   "
};


/* for do_count */
int max_on = 0;



/*
 * 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 ) );



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)     )   strcat( buf, "{x({BInvis{x) "     );
    if ( IS_AFFECTED(ch, AFF_DETECT_EVIL)
         && IS_OBJ_STAT(obj, ITEM_EVIL)   )   strcat( buf, "{x({rRed Aura{x) "  );
    if ( is_affected(ch, skill_lookup("detect good"))
         && IS_OBJ_STAT(obj, ITEM_BLESS)   )   strcat( buf, "{x({gGreen Aura{x) "  );
    if ( IS_AFFECTED(ch, AFF_DETECT_MAGIC)
         && IS_OBJ_STAT(obj, ITEM_MAGIC)  )   strcat( buf, "{x({MMagical{x) "   );
    if ( IS_OBJ_STAT(obj, ITEM_GLOW)      )   strcat( buf, "{x({YGlowing{x) "   );
    if ( IS_OBJ_STAT(obj, ITEM_HUM)       )   strcat( buf, "{x({YHumming{x) "   );

    if ( fShort )
    {
	if ( obj->short_descr != NULL )
	    strcat( buf, obj->short_descr );
    }
    else
    {
	if ( obj->description != NULL )
	    strcat( buf, obj->description );
    }

	if (strlen(buf)<=0)
	    strcat(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 )
{
    char buf[MAX_STRING_LENGTH];
    char **prgpstrShow;
    int *prgnShow;
    char *pstrShow;
    OBJ_DATA *obj;
    int nShow;
    int iShow;
    int count;
    bool fCombine;

    if ( ch->desc == NULL )
	return;

    /*
     * Alloc space for output lines.
     */
    count = 0;
    for ( obj = list; obj != NULL; obj = obj->next_content )
	count++;
    prgpstrShow	= alloc_mem( count * sizeof(char *) );
    prgnShow    = alloc_mem( count * sizeof(int)    );
    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 ) )
	{
	    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 ( IS_NPC(ch) || IS_SET(ch->comm, COMM_COMBINE) )
	{
	    if ( prgnShow[iShow] != 1 )
	    {
		sprintf( buf, "(%2d) ", prgnShow[iShow] );
		send_to_char( buf, ch );
	    }
	    else
	    {
		send_to_char( "     ", ch );
	    }
	}
	send_to_char( prgpstrShow[iShow], ch );
	send_to_char( "\n\r", ch );
	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 );
    }

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

    return;
}



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

    buf[0] = '\0';
	if (!LongLook)
	{
    if ( IS_AFFECTED(victim, AFF_INVISIBLE)   ) strcat( buf, "{x({bInvis{x) "      );
	if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_WIZINVIS) ) strcat ( buf, "{x({mWizi{x) "   );
	if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_CLOAK) ) strcat ( buf, "{x({mCloak{x) "   );
    if ( IS_AFFECTED(victim, AFF_HIDE)        ) strcat( buf, "{x({BHide{x) "       );
    if ( IS_AFFECTED(victim, AFF_CHARM)       ) strcat( buf, "{x({gCharmed{x) "    );
    if ( IS_AFFECTED(victim, AFF_PASS_DOOR)   ) strcat( buf, "{x({CTranslucent{x) ");
    if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) ) strcat( buf, "{x({RPink Aura{x) "  );
    if ( IS_EVIL(victim)
    &&   IS_AFFECTED(ch, AFF_DETECT_EVIL)     ) strcat( buf, "{x({rRed Aura{x) " );
    if ( IS_GOOD(victim)
    &&   is_affected(ch, skill_lookup("detect good"))     ) strcat( buf, "{x({gGreen Aura{x) " );
    if ( IS_AFFECTED(victim, AFF_SANCTUARY)   ) strcat( buf, "{m({WWhite Aura{m){x " );

/* Zeran - immolation not coded yet
	if ( is_affected(ch, skill_lookup("immolation"))) strcat(buf, "{g({RFlames{g){x ");
*/
	}

    if ( victim->position == victim->start_pos && victim->long_descr[0] != '\0' )
    {
		if (!LongLook)
		strcat( buf, victim->long_descr );
		else if (victim->short_descr[0] != '\0')
			{
			strcat (buf, victim->short_descr );
			strcat (buf, "\n\r");
			}
		else /*assumed poly....seems to be the only instance of this*/
			{
			strcat (buf, victim->poly_name);
			strcat (buf, "\n\r");
			}
	send_to_char( buf, ch );
	return;
    }
	if (LongLook)
		if (!IS_NPC(victim) &&( !IS_AFFECTED(victim, AFF_POLY) 
			|| !str_cmp(victim->poly_name, victim->short_descr) ) )
		strcat (buf,"{y");
    strcat( buf, PERSMASK( victim, ch ) );
    if ( !IS_NPC(victim) && !IS_SET(ch->comm, COMM_BRIEF) && (!LongLook) 
		&& (!IS_AFFECTED(victim, AFF_POLY)) )
	strcat( buf, victim->pcdata->title );
	if (!LongLook)
	{	
    switch ( victim->position )
    {
    case POS_DEAD:     strcat( buf, " is DEAD!!" );              break;
    case POS_MORTAL:   strcat( buf, " is {Rmortally wounded.{w" );   break;
    case POS_INCAP:    strcat( buf, " is {Rincapacitated.{w" );      break;
    case POS_STUNNED:  strcat( buf, " is lying here stunned." ); break;
    case POS_SLEEPING: strcat( buf, " is sleeping here." );      break;
    case POS_RESTING:  strcat( buf, " is resting here." );       break;
    case POS_SITTING:  strcat( buf, " is sitting here." );	 break;
    case POS_STANDING: strcat( buf, " is here." );               break;
    case POS_FIGHTING:
	strcat( buf, " is here, fighting " );
	if ( victim->fighting == NULL )
	    strcat( buf, "thin air??" );
	else if ( victim->fighting == ch )
	    strcat( buf, "YOU!" );
	else if ( victim->in_room == victim->fighting->in_room )
	{
	    strcat( buf, PERSMASK( victim->fighting, ch ) );
	    strcat( buf, "." );
	}
	else
	    strcat( buf, "someone who left??" );
	break;
    }
	}

	strcat (buf, "{x" );
	strcat (buf, "\n\r");
    buf[0] = UPPER(buf[0]);
    send_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;

    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;

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

    if (percent >= 100) 
	strcat( buf, " is in {Gexcellent condition{w.\n\r");
    else if (percent >= 90) 
	strcat( buf, " has a {gfew scratches.{w\n\r");
    else if (percent >= 75) 
	strcat( buf," has some {Msmall wounds and bruises{w.\n\r");
    else if (percent >=  50) 
	strcat( buf, " has {yquite a few wounds.{w\n\r");
    else if (percent >= 30)
	strcat( buf, " has some {Ybig nasty wounds and scratches.{w\n\r");
    else if (percent >= 15)
	strcat ( buf, " looks {Wpretty hurt.{w\n\r");
    else if (percent >= 0 )
	strcat (buf, " is in{R awful condition.{w\n\r");
    else
	strcat(buf, " is {Rbleeding to death{w.\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;
	    }
	    send_to_char( where_name[iWear], ch );
	    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 );
    }

    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 )
	&&        IS_AFFECTED(rch, AFF_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 thing!\n\r", ch ); 
	return FALSE; 
    }

    return TRUE;
}

/* changes your scroll */
void do_scroll(CHAR_DATA *ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    char buf[100];
    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);
	else
	{
	    sprintf(buf,"You currently display %d lines per page.\n\r",
		    ch->lines + 2);
	    send_to_char(buf,ch);
	}
	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;
    }

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

/* RT does socials */
void do_socials(CHAR_DATA *ch, char *argument)
{
    char buf[MAX_STRING_LENGTH];
    int iSocial;
    int col;
     
    col = 0;
   
    for (iSocial = 0; social_table[iSocial].name[0] != '\0'; iSocial++)
    {
	sprintf(buf,"%-12s",social_table[iSocial].name);
	send_to_char(buf,ch);
	if (++col % 6 == 0)
	    send_to_char("\n\r",ch);
    }

    if ( col % 6 != 0)
	send_to_char("\n\r",ch);
    return;
}


 
/* RT Commands to replace news, motd, imotd, etc from ROM */

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

void do_imotd(CHAR_DATA *ch, char *argument)
{  
    do_help(ch,"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,"wizlist");
}

/* RT this following section holds all the auto commands from ROM, as well as
   replacements for config */

void do_autolist(CHAR_DATA *ch, char *argument)
{
    /* lists most player flags */
    if (IS_NPC(ch))
      return;

    send_to_char("   action     status\n\r",ch);
    send_to_char("---------------------\n\r",ch);
 
    send_to_char("autoassist     ",ch);
    if (IS_SET(ch->act,PLR_AUTOASSIST))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch); 

    send_to_char("autoexit       ",ch);
    if (IS_SET(ch->act,PLR_AUTOEXIT))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);

    send_to_char("autogold       ",ch);
    if (IS_SET(ch->act,PLR_AUTOGOLD))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);

    send_to_char("autoloot       ",ch);
    if (IS_SET(ch->act,PLR_AUTOLOOT))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);

    send_to_char("autosac        ",ch);
    if (IS_SET(ch->act,PLR_AUTOSAC))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);

    send_to_char("autosplit      ",ch);
    if (IS_SET(ch->act,PLR_AUTOSPLIT))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);
    
	send_to_char("autotitle      ",ch);
    if (IS_SET(ch->act,PLR_AUTOTITLE))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);
	
	send_to_char("autosave       ",ch);
    if (IS_SET(ch->act,PLR_AUTOSAVE))
        send_to_char("ON\n\r",ch);
    else
        send_to_char("OFF\n\r",ch);

    send_to_char("prompt         ",ch);
    if (IS_SET(ch->comm,COMM_PROMPT))
	send_to_char("ON\n\r",ch);
    else
	send_to_char("OFF\n\r",ch);

    send_to_char("combine items  ",ch);
    if (IS_SET(ch->comm,COMM_COMBINE))
	send_to_char("ON\n\r",ch);
    else
	send_to_char("OFF\n\r",ch);

    if (!IS_SET(ch->act,PLR_CANLOOT))
	send_to_char("Your corpse is safe from thieves.\n\r",ch);
    else 
        send_to_char("Your corpse may be looted.\n\r",ch);

    if (IS_SET(ch->act,PLR_NOSUMMON))
	send_to_char("You cannot be summoned.\n\r",ch);
    else
	send_to_char("You can be summoned.\n\r",ch);
   
    if (IS_SET(ch->act,PLR_NOFOLLOW))
	send_to_char("You do not welcome followers.\n\r",ch);
    else
	send_to_char("You accept followers.\n\r",ch);
}

void do_autoassist(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
    
    if (IS_SET(ch->act,PLR_AUTOASSIST))
    {
      send_to_char("Autoassist removed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOASSIST);
    }
    else
    {
      send_to_char("You will now assist when needed.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOASSIST);
    }
}

void do_autoexit(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_AUTOEXIT))
    {
      send_to_char("Exits will no longer be displayed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOEXIT);
    }
    else
    {
      send_to_char("Exits will now be displayed.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOEXIT);
    }
}

void do_autogold(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_AUTOGOLD))
    {
      send_to_char("Autogold removed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOGOLD);
    }
    else
    {
      send_to_char("Automatic gold looting set.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOGOLD);
    }
}

void do_autoloot(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_AUTOLOOT))
    {
      send_to_char("Autolooting removed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOLOOT);
    }
    else
    {
      send_to_char("Automatic corpse looting set.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOLOOT);
    }
}

void do_autotitle (CHAR_DATA *ch, char *argument)
	{
	if (IS_NPC(ch))
		return;
	
	if (IS_SET (ch->act,PLR_AUTOTITLE))
    {
      send_to_char("Autotitle removed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOTITLE);
    }
    else
    {
      send_to_char("Automatic title set.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOTITLE);
    }
	}

void do_autosac(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_AUTOSAC))
    {
      send_to_char("Autosacrificing removed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOSAC);
    }
    else
    {
      send_to_char("Automatic corpse sacrificing set.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOSAC);
    }
}
void do_autosave(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_AUTOSAVE))
    {
      send_to_char("Autosave message will no longer be shown.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOSAVE);
    }
    else
    {
      send_to_char("Autosave message turned on.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOSAVE);
    }
}
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);
    }
    else
    {
      send_to_char("AFK Set..\n\r",ch);
      SET_BIT(ch->act,PLR_AFK);
    }
}
    

void do_autosplit(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_AUTOSPLIT))
    {
      send_to_char("Autosplitting removed.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_AUTOSPLIT);
    }
    else
    {
      send_to_char("Automatic gold splitting set.\n\r",ch);
      SET_BIT(ch->act,PLR_AUTOSPLIT);
    }
}

void do_brief(CHAR_DATA *ch, char *argument)
{
    if (IS_SET(ch->comm,COMM_BRIEF))
    {
      send_to_char("Full descriptions activated.\n\r",ch);
      REMOVE_BIT(ch->comm,COMM_BRIEF);
    }
    else
    {
      send_to_char("Short descriptions activated.\n\r",ch);
      SET_BIT(ch->comm,COMM_BRIEF);
    }
}

void do_fullfight(CHAR_DATA *ch, char *argument)
{
    if (IS_SET(ch->comm,COMM_FULLFIGHT))
    {
	send_to_char("Full Battle Descriptions Removed.\n\r",ch);
	REMOVE_BIT(ch->comm,COMM_FULLFIGHT);
    }
    else
    {
	send_to_char("Full Battle Descriptions Activated.\n\r",ch);
	SET_BIT(ch->comm,COMM_FULLFIGHT);
    }
}

void do_compact(CHAR_DATA *ch, char *argument)
{
    if (IS_SET(ch->comm,COMM_COMPACT))
    {
      send_to_char("Compact mode removed.\n\r",ch);
      REMOVE_BIT(ch->comm,COMM_COMPACT);
    }
    else
    {
      send_to_char("Compact mode set.\n\r",ch);
      SET_BIT(ch->comm,COMM_COMPACT);
    }
}

void do_prompt(CHAR_DATA *ch, char *argument)
{
	char word[MAX_INPUT_LENGTH];	
	if (strlen(argument) != 0) 
		{
		one_argument (argument, word);
		if (!str_cmp(word, "default"))
			{
			free_string (ch->pcdata->prompt);
			ch->pcdata->prompt = strdup ("{G({W%h/%Hhp %m/%Mmn %v/%Vmv{G){x");
			return;
			}
		else
			{
			smash_tilde(argument);
			free_string (ch->pcdata->prompt);
			ch->pcdata->prompt = strdup (argument);
			return;
			}
		}
	
	 if (IS_SET(ch->comm,COMM_PROMPT))
    {
      send_to_char("You will no longer see prompts.\n\r",ch);
      REMOVE_BIT(ch->comm,COMM_PROMPT);
    }
    else
    {
      send_to_char("You will now see prompts.\n\r",ch);
      SET_BIT(ch->comm,COMM_PROMPT);
    }
}

void do_combine(CHAR_DATA *ch, char *argument)
{
    if (IS_SET(ch->comm,COMM_COMBINE))
    {
      send_to_char("Long inventory selected.\n\r",ch);
      REMOVE_BIT(ch->comm,COMM_COMBINE);
    }
    else
    {
      send_to_char("Combined inventory selected.\n\r",ch);
      SET_BIT(ch->comm,COMM_COMBINE);
    }
}

void do_noloot(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_CANLOOT))
    {
      send_to_char("Your corpse is now safe from thieves.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_CANLOOT);
    }
    else
    {
      send_to_char("Your corpse may now be looted.\n\r",ch);
      SET_BIT(ch->act,PLR_CANLOOT);
    }
}

void do_nofollow(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch))
      return;
 
    if (IS_SET(ch->act,PLR_NOFOLLOW))
    {
      send_to_char("You now accept followers.\n\r",ch);
      REMOVE_BIT(ch->act,PLR_NOFOLLOW);
    }
    else
    {
      send_to_char("You no longer accept followers.\n\r",ch);
      SET_BIT(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.\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
    {
      if (IS_SET(ch->act,PLR_NOSUMMON))
      {
        send_to_char("You are no longer immune to summon.\n\r",ch);
        REMOVE_BIT(ch->act,PLR_NOSUMMON);
      }
      else
      {
        send_to_char("You are now immune to summoning.\n\r",ch);
        SET_BIT(ch->act,PLR_NOSUMMON);
      }
    }
}

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];
    EXIT_DATA *pexit;
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    char *pdesc;
    int door;
    int number,count;

    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 ) )
	return;


    if ( !IS_NPC(ch)
    &&   !IS_SET(ch->act, PLR_HOLYLIGHT)
    &&   room_is_dark( ch->in_room ) )
    {
	send_to_char( "It is pitch black ... \n\r", ch );
	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" ) )
    {
	/* 'look' or 'look auto'  room color added by elfren */
	if (ch->level >= AVATAR) /*Zeran: show vnum of room if IMM*/
		{
		char buf2[64];
		sprintf (buf2, "{cRoom [%d]{x ", ch->in_room->vnum);
		send_to_char (buf2,ch);
		}
        send_to_char( "{c", ch ) ;
	send_to_char( ch->in_room->name, ch );
	send_to_char( "{w\n\r", ch );

	if ( arg1[0] == '\0'
	|| ( !IS_NPC(ch) && !IS_SET(ch->comm, COMM_BRIEF) ) )
	{
	    send_to_char( "  ",ch);
	    send_to_char( ch->in_room->description, ch );
	}

        if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOEXIT) )
	{
	    send_to_char("\n\r{B",ch);
            do_exits( ch, "auto" );
	    send_to_char("{w",ch);
	}

	show_list_to_char( ch->in_room->contents, ch, FALSE, FALSE );
	send_to_char ("\n\r",ch);
	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, 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;
	    }

	    sprintf( 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, 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 );
			show_obj_cond (ch, obj);
		    return;
	    	}
	    	else continue;

 	    pdesc = get_extra_descr( arg3, obj->pIndexData->extra_descr );
 	    if ( pdesc != NULL )
 	    	if (++count == number)
 	    	{	
		    send_to_char( pdesc, ch );
			show_obj_cond (ch, obj);
		    return;
	     	}
		else continue;

	    if ( is_name( arg3, obj->name ) )
	    	if (++count == number)
	    	{
	    	    send_to_char( obj->description, ch );
	    	    send_to_char( "\n\r",ch);
				show_obj_cond (ch, obj);
	    	   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 );
			show_obj_cond (ch, obj);
		    return;
	    	}

	    pdesc = get_extra_descr( arg3, obj->pIndexData->extra_descr );
	    if ( pdesc != NULL )
	    	if (++count == number)
	    	{
		    send_to_char( pdesc, ch );
			show_obj_cond (ch, obj);
		    return;
	    	}

	if ( is_name( arg3, obj->name ) )
	    if (++count == number)
	    {
	    	send_to_char( obj->description, ch );
	    	send_to_char("\n\r",ch);
			show_obj_cond (ch, obj);
	    	return;
	    }
    }
    }
    
    if (count > 0 && count != number)
    {
    	if (count == 1)
    	    sprintf(buf,"You only see one %s here.\n\r",arg3);
    	else
    	    sprintf(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 )
    {
	send_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' )
		{
		send_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;
	int door;
	char doors[6][30];
	bool anything=FALSE;

	sprintf (doors[0], "{c[North]\n\r{x");
	sprintf (doors[1], "{c[East]\n\r{x");
	sprintf (doors[2], "{c[South]\n\r{x");
	sprintf (doors[3], "{c[West]\n\r{x");
	sprintf (doors[4], "{c[Up]\n\r{x");
	sprintf (doors[5], "{c[Down]\n\r{x");
	
	for (door=0;door<=5;door++)
		{
	    /* 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) )
				{
				send_to_char(doors[door], ch);	
				show_char_to_char(pexit->u1.to_room->people, 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;
	}


/* RT added back for the hell of it */
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;
    }

    obj =  get_obj_list(ch,argument,ch->carrying);

    if (obj== NULL)
    {
        send_to_char("You don't have that item.\n\r",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;

        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;
	}

        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, arg ) ) != NULL )
    {
	switch ( obj->item_type )
	{
	default:
/*	    spell_identify( skill_lookup("lore"), ch->level, ch, obj);*/
	    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 );
	    sprintf( buf, "in %s", arg );
	    do_look( ch, buf );
	}
    }

    return;
}



/*
 * Thanks to Zrin for auto-exit part.
 */
void do_exits( CHAR_DATA *ch, char *argument )
{
    extern char * const dir_name[];
    char buf[MAX_STRING_LENGTH];
	char buf2[128];
    EXIT_DATA *pexit;
    bool found;
    bool fAuto; 
	bool Hlight=FALSE;
    int door;
	
    buf[0] = '\0';
	buf[2] = '\0';
    fAuto  = !str_cmp( argument, "auto" );

    if ( !check_blind( ch ) )
	return;

	if (IS_SET(ch->act, PLR_XINFO))
		Hlight=TRUE;
	if (Hlight && fAuto)
		strcpy (buf, "Exits:  [ flags ]\n\r");
	else	
		strcpy( buf, fAuto ? "[Exits:" : "Obvious exits:\n\r" );

    found = FALSE;
    for ( door = 0; door <= 5; door++ )
    {
	if ( ( pexit = ch->in_room->exit[door] ) != NULL
	&&   pexit->u1.to_room != NULL
	&&   can_see_room(ch,pexit->u1.to_room))
	{
	if  ( Hlight && fAuto)
		{
		found = TRUE;
		sprintf (buf2, "%5s", dir_name[door] );
		strcat (buf2, "   [ ");
		if (IS_SET(pexit->exit_info, EX_ISDOOR))
			strcat (buf2, "door ");
		if (IS_SET(pexit->exit_info, EX_CLOSED))
			strcat (buf2, "closed ");
		if (IS_SET(pexit->exit_info, EX_LOCKED))
			strcat (buf2, "locked ");
		if (IS_SET(pexit->exit_info, EX_PICKPROOF))
			strcat (buf2, "pickproof ");
		if (IS_SET(pexit->exit_info, EX_HIDDEN))
			strcat (buf2, "hidden ");
		if (IS_SET(pexit->exit_info, EX_NO_PASS))
			strcat (buf2, "no_pass");
		strcat (buf2, "]\n\r");
		strcat (buf, buf2);
		}
	else if (!IS_SET(pexit->exit_info, EX_CLOSED) )
		{
	    found = TRUE;
	    if ( fAuto )
	    	{
			strcat( buf, " " );
			strcat( buf, dir_name[door] );
	    	}
	    else
	    	{
			sprintf( buf + strlen(buf), "%-5s - %s\n\r",
			    capitalize( dir_name[door] ),
			    room_is_dark( pexit->u1.to_room )
				?  "Too dark to tell"
				: pexit->u1.to_room->name );
	    	}
		}
	}
	
    }

    if ( !found )
	strcat( buf, fAuto ? " none" : "None.\n\r" );

	if ( fAuto && Hlight)
		strcat (buf, "\n\r");
    if ( fAuto && !Hlight )
		strcat( buf, "]\n\r" );

    send_to_char( buf, ch );
    return;
}

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

    if (IS_NPC(ch))
    {
	sprintf(buf,"You have %ld gold.\n\r",ch->gold);
	send_to_char(buf,ch);
	return;
    }

    sprintf(buf, "You have {Y%ld {wgold, and {c%d{w experience ({W%d{w exp to level).\n\r",
	ch->gold, ch->exp,
	(ch->level + 1) * exp_per_level(ch,ch->pcdata->points) - ch->exp);

    send_to_char(buf,ch);

    return;
}


char *	const	day_name	[] =
{
    "the Moon", "the Bull", "Deception", "Thunder", "Freedom",
    "the Great Gods", "the Sun"
};

char *	const	month_name	[] =
{
    "Winter", "Winter Wolf", "Frost Giant", "the Old Forces",
    "Grand Struggle", "Spring", "Nature", "Futility", "the Dragon",
    "Sun", "Heat", "Battle", "Dark Shades", "Shadows",
    "Long Shadows", "Ancient Darkness", "Great Evil"
};

void do_score( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int i;
    int day;
    char rankbuf[32];
	int trust;

    if (IS_NPC(ch))
	{
	send_to_char("You are an NPC. Use the 'OLDSCORE' Command.",ch);
	return;
	}
  
    send_to_char("{Y-------------------------------------------------------------------------{x",ch);
    send_to_char ( "\n\r",ch);

    sprintf(buf,"{BSTR\t[{W%2d/%2d{B]\t\t{YLEVEL\t[{W%11d{Y]\t{GHP\t[{W%7d/%7d{G]{x\n\r",
        ch->perm_stat[STAT_STR],
        get_curr_stat(ch,STAT_STR),
        ch->level,
        ch->hit,
        ch->max_hit);
    send_to_char(buf,ch);		

    sprintf(buf,"{BINT\t[{W%2d/%2d{B]\t\t{YRACE\t[{W%11s{Y]\t{GMANA\t[{W%7d/%7d{G]{x\n\r",
        ch->perm_stat[STAT_INT],
        get_curr_stat(ch,STAT_INT),
        race_table[ch->race].name,
        ch->mana,
        ch->max_mana);
    send_to_char(buf,ch);	

    sprintf(buf,"{BWIS\t[{W%2d/%2d{B]\t\t{YSEX\t[{W%11s{Y]\t{GMOVE\t[{W%7d/%7d{G]{x\n\r",
        ch->perm_stat[STAT_WIS],
        get_curr_stat(ch,STAT_WIS),
        ch->sex == 0 ? "sexless" : ch->sex == 1 ? "male" : "female",
        ch->move,
        ch->max_move);
    send_to_char(buf,ch);	

    sprintf(buf,"{BDEX\t[{W%2d/%2d{B]\t\t{YCLASS\t[{W%11s{Y]\t{GPRAC\t[{W%15d{G]{x\n\r",
        ch->perm_stat[STAT_DEX],
        get_curr_stat(ch,STAT_DEX),
        IS_NPC(ch) ? "mobile" : class_table[ch->class].name,
        ch->practice);
    send_to_char(buf,ch);

    sprintf(buf,"{BCON\t[{W%2d/%2d{B]\t\t{YAGE\t[{W%3d/%-4dHrs{Y]\t{GTRAIN\t[{W%15d{G]{x\n\r",
        ch->perm_stat[STAT_CON],
        get_curr_stat(ch,STAT_CON),
        get_age(ch),
        ( ch->played + (int) (current_time - ch->logon) ) / 3600,
        ch->train);
    send_to_char(buf,ch);

    sprintf(buf,"{BHITR\t[{W%5d{B]\t\t{YNXT LVL\t[{W%11d{Y]\t{GRATE\t[{W%15d{G]{x\n\r",
        GET_HITROLL(ch),
        ((ch->level + 1) * exp_per_level(ch,ch->pcdata->points) - ch->exp),
        ch->pcdata->battle_rating);
    send_to_char(buf,ch);

    sprintf(buf,"{BDAMR\t[{W%5d{B]\t\t{YXP\t[{W%11d{Y]\t{GWEIGHT\t[{W%7d/%7d{G]{x\n\r",
        GET_DAMROLL(ch),
        ch->exp,
        ch->carry_weight,
        can_carry_w(ch));
    send_to_char(buf,ch);

    sprintf(buf,"{BWIMPY\t[{W%5d{B]\t\t{YGOLD\t[{W%11ld{Y]\t{GITEMS\t[{W%7d/%7d{G]{x\n\r",
        ch->wimpy,
		ch->gold,
        ch->carry_number,
        can_carry_n(ch));
    send_to_char(buf,ch);

	send_to_char("{Y-------------------------------------------------------------------------{x\n\r",ch);
   	if (!IS_NPC(ch)) 
		{
		trust = get_trust(ch);
		if ( trust > ch->level )
			{
			sprintf( buf, "{BTRUST\t [{W%3d{B]{x\n\r",
			     trust);
			send_to_char( buf, ch );
    		}
		}
    day=ch->startday+1;
    sprintf(buf,"{BBORN\t[{W%d{B, month of {W%s {Bin the Year of Dark Times {W%d{B]{x\n\r",
        day,
        month_name[ch->startmonth],
        ch->startyear);
    send_to_char(buf,ch);

    clan_rank_name (ch, rankbuf);
        sprintf(buf,"{BCLAN\t[{W%-25s{B]\t{GRANK\t[{W%-7s{G]{x\n\r",
        ch->pcdata->clan_name,
        rankbuf);
    send_to_char(buf,ch);


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

    switch ( ch->position )
    {
    case POS_DEAD:     
    send_to_char( "{YYou are {&{RDEAD!!{x\n\r",       ch );
	break;
    case POS_MORTAL:
    send_to_char( "You are {4{Rmortally wounded{x.\n\r",  ch );
	break;
    case POS_INCAP:
    send_to_char( "You are {yincapacitated{x.\n\r", ch );
	break;
    case POS_STUNNED:
    send_to_char( "You are {ystunned{x.\n\r",       ch );
	break;
    case POS_SLEEPING:
    send_to_char( "You are {csleeping{x.\n\r",      ch );
	break;
    case POS_RESTING:
    send_to_char( "You are resting.\n\r",       ch );
	break;
    case POS_STANDING:
    send_to_char( "You are standing.\n\r",      ch );
	break;
    case POS_FIGHTING:
    send_to_char( "You are {Rfighting{x.\n\r",      ch );
	break;
    }


    /* print AC values */
    if (ch->level >= 25)
    {	
    sprintf( buf,"{CArmor{W: {Gpierce{W: {B%d  {Gbash{W: {B%d  {Gslash{W: {B%d  {Gexotic{W: {B%d{x\n\r",
		 GET_AC(ch,AC_PIERCE),
		 GET_AC(ch,AC_BASH),
		 GET_AC(ch,AC_SLASH),
		 GET_AC(ch,AC_EXOTIC));
    	send_to_char(buf,ch);
    }

    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;
	}
	
    send_to_char("You are ", ch);

	if      (GET_AC(ch,i) >=  101 ) 
	    sprintf(buf,"hopelessly vulnerable to %s.\n\r",temp);
	else if (GET_AC(ch,i) >= 25) 
	    sprintf(buf,"defenseless against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -50)
	    sprintf(buf,"barely protected from %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -125)
	    sprintf(buf,"slighty armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -200)
	    sprintf(buf,"somewhat armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -275)
	    sprintf(buf,"armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -350)
	    sprintf(buf,"well-armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -425)
	    sprintf(buf,"very well-armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -500)
        sprintf(buf,"{Bheavily armored against {W%s{x.\n\r",temp);
	else if (GET_AC(ch,i) >= -575)
        sprintf(buf,"{Gsuperbly armored against {W%s{x.\n\r",temp);
	else if (GET_AC(ch,i) >= -650)
        sprintf(buf,"{Calmost invulnerable to {W%s{x.\n\r",temp);
	else
        sprintf(buf,"{Ydivinely armored against {W%s{x.\n\r",temp);

	send_to_char(buf,ch);
    }


    /* RT wizinvis and holy light */
    if ( IS_IMMORTAL(ch))
    {
      send_to_char("Holy Light: ",ch);
      if (IS_SET(ch->act,PLR_HOLYLIGHT))
        send_to_char("on   ",ch);
      else
        send_to_char("off  ",ch);
 
      if (IS_SET(ch->act,PLR_WIZINVIS))
      {
        sprintf( buf, "Invisible: level %d   ",ch->invis_level);
        send_to_char(buf,ch);
      }
      
	  if (IS_SET(ch->act,PLR_CLOAK))
      {
        sprintf( buf, "Cloak: level %d",ch->cloak_level);
        send_to_char(buf,ch);
      }
		
      send_to_char("\n\r",ch);
    }

    if ( ch->level >= 10 )
    {
    sprintf( buf, "{YAlignment: {W%d{x.  ", ch->alignment );
	send_to_char( buf, ch );
    }

    send_to_char( "You are ", ch );
         if ( ch->alignment >  900 ) send_to_char( "{Wangelic{x.\n\r", ch );
    else if ( ch->alignment >  700 ) send_to_char( "{Wsaintly{x.\n\r", ch );
    else if ( ch->alignment >  350 ) send_to_char( "{Cgood{x.\n\r",    ch );
    else if ( ch->alignment >  100 ) send_to_char( "{Ckind{x.\n\r",    ch );
    else if ( ch->alignment > -100 ) send_to_char( "neutral{x.\n\r", ch );
    else if ( ch->alignment > -350 ) send_to_char( "{rmean{x.\n\r",    ch );
    else if ( ch->alignment > -700 ) send_to_char( "{revil{x.\n\r",    ch );
    else if ( ch->alignment > -900 ) send_to_char( "{Rdemonic{x.\n\r", ch );
    else                             send_to_char( "{Rsatanic{x.\n\r", ch );

    return;

}

void do_oldscore( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int i;
    int day;
	int trust;
	char rankbuf[32];

    send_to_char( "{Y--------------------------{BYour Character Information{Y---------------------------{w",ch);
    send_to_char ( "\n\r",ch);
	sprintf(buf, "You are %s%s{w, level {c%d{w, {y%d{w years old ({W%d hours{w).\n\r",
	ch->name,
	IS_NPC(ch) ? "" : ch->pcdata->title,
	ch->level, get_age(ch),
        ( ch->played + (int) (current_time - ch->logon) ) / 3600);
    send_to_char( buf, ch );

	day = ch->startday + 1;
	sprintf(buf,"You were born on day %d of the month of %s in year {W%d.\n\r",
		day,
		month_name[ch->startmonth],
		ch->startyear);
    send_to_char( buf,ch);

   	if (!IS_NPC(ch)) 
		{
		trust = get_trust(ch);
		if ( trust > ch->level )
			{
			sprintf( buf, "You are trusted at level %d.\n\r",
			     trust);
			send_to_char( buf, ch );
    		}
		}

    sprintf(buf, "Race: {B%s{w  Sex: {B%s{w  Class:  {B%s{w\n\r",
	race_table[ch->race].name,
	ch->sex == 0 ? "sexless" : ch->sex == 1 ? "male" : "female",
 	IS_NPC(ch) ? "mobile" : class_table[ch->class].name);
    send_to_char(buf,ch);

	if (ch->pcdata != NULL) /*force mob to do score? seg faults on pcdata*/
	{	
	clan_rank_name (ch, rankbuf);
	sprintf(buf, "Clan: %s   Rank: {y%s{x\n\r", ch->pcdata->clan_name, rankbuf);
	send_to_char(buf,ch); 
	}

    sprintf( buf,
	"You have {B%d{w/{W%d{w hit, {B%d{w/{W%d{w mana, {B%d{w/{W%d{w movement.\n\r",
	ch->hit,  ch->max_hit,
	ch->mana, ch->max_mana,
	ch->move, ch->max_move);
    send_to_char( buf, ch );

    sprintf( buf,
	"You have {R%d{w practices and {R%d{w training sessions.\n\r",
	ch->practice, ch->train);
    send_to_char( buf, ch );

    sprintf( buf,
	"You are carrying {B%d{w/{W%d{w items with weight {B%d{w/{W%d{w pounds.\n\r",
	ch->carry_number, can_carry_n(ch),
	ch->carry_weight, can_carry_w(ch) );
    send_to_char( buf, ch );

    sprintf( buf,
	"Str: %d({Y%d{x)  Int: %d({Y%d{x)  Wis: %d({Y%d{x)  Dex: %d({Y%d{x)  Con: %d({Y%d{x)\n\r",
	ch->perm_stat[STAT_STR],
	get_curr_stat(ch,STAT_STR),
	ch->perm_stat[STAT_INT],
	get_curr_stat(ch,STAT_INT),
	ch->perm_stat[STAT_WIS],
	get_curr_stat(ch,STAT_WIS),
	ch->perm_stat[STAT_DEX],
	get_curr_stat(ch,STAT_DEX),
	ch->perm_stat[STAT_CON],
	get_curr_stat(ch,STAT_CON) );
    send_to_char( buf, ch );

    sprintf( buf,
	"You have scored {W%d{w exp, and have {Y%ld{w gold coins.\n\r",
	ch->exp,  ch->gold );
    send_to_char( buf, ch );

    /* RT shows exp to level */
    if (!IS_NPC(ch) && ch->level < LEVEL_HERO)
    {
      sprintf (buf, 
	"You need {C%d{w exp to level.\n\r",
	((ch->level + 1) * exp_per_level(ch,ch->pcdata->points) - ch->exp));
      send_to_char( buf, ch );
     }

    sprintf( buf, "Wimpy set to {B%d{w hit points.\n\r", ch->wimpy );
    send_to_char( buf, ch );

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

    switch ( ch->position )
    {
    case POS_DEAD:     
	send_to_char( "{YYou are {RDEAD!!{w\n\r",		ch );
	break;
    case POS_MORTAL:
	send_to_char( "You are {Rmortally wounded{w.\n\r",	ch );
	break;
    case POS_INCAP:
	send_to_char( "You are incapacitated.\n\r",	ch );
	break;
    case POS_STUNNED:
	send_to_char( "You are stunned.\n\r",		ch );
	break;
    case POS_SLEEPING:
	send_to_char( "You are sleeping.\n\r",		ch );
	break;
    case POS_RESTING:
	send_to_char( "You are resting.\n\r",		ch );
	break;
    case POS_STANDING:
	send_to_char( "You are standing.\n\r",		ch );
	break;
    case POS_FIGHTING:
	send_to_char( "You are fighting.\n\r",		ch );
	break;
    }


    /* print AC values */
    if (ch->level >= 25)
    {	
	sprintf( buf,"Armor: pierce: {B%d{w  bash: {B%d{w  slash: {B%d{w  magic: {B%d{w\n\r",
		 GET_AC(ch,AC_PIERCE),
		 GET_AC(ch,AC_BASH),
		 GET_AC(ch,AC_SLASH),
		 GET_AC(ch,AC_EXOTIC));
    	send_to_char(buf,ch);
    }

    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;
	}
	
	send_to_char("You are ", ch);

	if      (GET_AC(ch,i) >=  101 ) 
	    sprintf(buf,"hopelessly vulnerable to %s.\n\r",temp);
	else if (GET_AC(ch,i) >= 25) 
	    sprintf(buf,"defenseless against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -50)
	    sprintf(buf,"barely protected from %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -125)
	    sprintf(buf,"slighty armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -200)
	    sprintf(buf,"somewhat armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -275)
	    sprintf(buf,"armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -350)
	    sprintf(buf,"well-armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -425)
	    sprintf(buf,"very well-armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -500)
	    sprintf(buf,"heavily armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -575)
	    sprintf(buf,"superbly armored against %s.\n\r",temp);
	else if (GET_AC(ch,i) >= -650)
	    sprintf(buf,"almost invulnerable to %s.\n\r",temp);
	else
	    sprintf(buf,"divinely armored against %s.\n\r",temp);

	send_to_char(buf,ch);
    }


    /* RT wizinvis and holy light */
    if ( IS_IMMORTAL(ch))
    {
      send_to_char("Holy Light: ",ch);
      if (IS_SET(ch->act,PLR_HOLYLIGHT))
        send_to_char("on",ch);
      else
        send_to_char("off",ch);
 
      if (IS_SET(ch->act,PLR_WIZINVIS))
      {
        sprintf( buf, "  Invisible: level %d",ch->invis_level);
        send_to_char(buf,ch);
      }
      
	  if (IS_SET(ch->act,PLR_CLOAK))
      {
        sprintf( buf, "  Cloak: level %d",ch->cloak_level);
        send_to_char(buf,ch);
      }
		
      send_to_char("\n\r",ch);
    }

    if ( ch->level >= 15 )
    {
	sprintf( buf, "Hitroll: %d  Damroll: %d.\n\r",
	    GET_HITROLL(ch), GET_DAMROLL(ch) );
	send_to_char( buf, ch );
    }
    
    if ( ch->level >= 10 )
    {
	sprintf( buf, "Alignment: %d.  ", ch->alignment );
	send_to_char( buf, ch );
    }

    send_to_char( "You are ", ch );
         if ( ch->alignment >  900 ) send_to_char( "angelic.\n\r", ch );
    else if ( ch->alignment >  700 ) send_to_char( "saintly.\n\r", ch );
    else if ( ch->alignment >  350 ) send_to_char( "good.\n\r",    ch );
    else if ( ch->alignment >  100 ) send_to_char( "kind.\n\r",    ch );
    else if ( ch->alignment > -100 ) send_to_char( "neutral.\n\r", ch );
    else if ( ch->alignment > -350 ) send_to_char( "mean.\n\r",    ch );
    else if ( ch->alignment > -700 ) send_to_char( "evil.\n\r",    ch );
    else if ( ch->alignment > -900 ) send_to_char( "demonic.\n\r", ch );
    else                             send_to_char( "satanic.\n\r", ch );

    return;
}

void do_affect (CHAR_DATA *ch, char *argument)
	{
	AFFECT_DATA *paf;
    char buf[MAX_STRING_LENGTH];
	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 )
			{
			sprintf( buf, "Spell: '%s'", skill_table[paf->type].name );
	    
			send_to_char( buf, ch );

	   		 if ( ch->level >= 20 )
	   			 {
				sprintf( buf,
			    " modifies %s by %d for %d hours",
			    affect_loc_name( paf->location ),
			    paf->modifier,
			    paf->duration );
				send_to_char( buf, ch );
	   			 }

	   		 send_to_char( ".\n\r", ch );
			}
    	}
	/* 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;
				sprintf( buf, "Object Spell: bits [%s]", affect_bit_name(paf->bitvector) );
				send_to_char( buf, ch );
				sprintf( buf,
				    " modifies %s by %d for %d hours\n\r",
				    affect_loc_name( paf->location ),
				    paf->modifier,
				    paf->duration );
				send_to_char( buf, ch );
				}
			}
		if (!tmp->enchanted)
		for (paf = tmp->pIndexData->affected ; paf != NULL; paf = paf->next)
			{
			if (paf->bitvector)
				{
				noaffect=FALSE;
				sprintf( buf, "Object Spell: bits [%s]", affect_bit_name(paf->bitvector) );
				send_to_char( buf, ch );
				sprintf( buf,
				    " modifies %s by %d for %d hours\n\r",
				    affect_loc_name( paf->location ),
				    paf->modifier,
				    paf->duration );
				send_to_char( buf, ch );
				} /* end for */
			} /* end if equipped loop */
			} /*end carrying for loop */
		}
			
	if (noaffect)	
		send_to_char ("Nothing.\n\r",ch);
    return;
}

void do_time( CHAR_DATA *ch, char *argument )
{
    extern char str_boot_time[];
    char buf[MAX_STRING_LENGTH];
    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";

    sprintf( buf,
    "It is %d o'clock %s, Day of %s, %d%s the Month of %s.\n\rThe year is %d.\n\rSunderMud started up at %s\rThe system time is %s (Mountain Time)\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,
	str_boot_time,
	(char *) ctime( &current_time )
	);

    send_to_char( buf, ch );


    return;
}



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

    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) 
    {
	sprintf( buf, "The sky is %s and a warm breeze blows from the south.\n\r",
	    sky_look[weather_info.sky]);
    }
    else
    {
	sprintf( buf, "The sky is %s and a cold northern wind chills you.\n\r",
	    sky_look_winter[weather_info.sky]);
    }



/*

    sprintf( buf, "The sky is %s and %s.\n\r",
	sky_look[weather_info.sky],
	weather_info.change >= 0
	? "a warm southerly breeze blows"
	: "a cold northern gust blows"
	);
*/

    send_to_char( buf, ch );
    return;
}



void do_help( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;
    char argall[MAX_INPUT_LENGTH],argone[MAX_INPUT_LENGTH];

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

    /* this parts handles help a b so that it returns help 'a b' */
    argall[0] = '\0';
    while (argument[0] != '\0' )
    {
	argument = one_argument(argument,argone);
	if (argall[0] != '\0')
	    strcat(argall," ");
	strcat(argall,argone);
    }

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

	if ( is_name( argall, pHelp->keyword ) )
	{
	    if ( pHelp->level >= 0 && str_cmp( argall, "imotd" ) )
	    {
		send_to_char( pHelp->keyword, ch );
		send_to_char( "\n\r", ch );
	    }

	    /*
	     * Strip leading '.' to allow initial blanks.
	     */
	    if ( pHelp->text[0] == '.' )
		page_to_char( pHelp->text+1, ch );
	    else
		page_to_char( pHelp->text  , ch );
	    return;
	}
    }

    send_to_char( "No help on that word.\n\r", ch );
    return;
}


/* whois command */
void do_whois (CHAR_DATA *ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    char output[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    bool found = FALSE;

    one_argument(argument,arg);
  
    if (arg[0] == '\0')
    {
	send_to_char("You must provide a name.\n\r",ch);
	return;
    }

    output[0] = '\0';

    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(arg,wch->name))
	{
	    found = TRUE;
	    
	    /* a little formatting */
	    sprintf(buf, "[{Y%2d %s{w] %s%s%s%s\n\r",
                wch->level,
                wch->level <= HERO ? pc_race_table[wch->race].who_name
                    : wch->pcdata->immtitle,
		IS_SET(wch->act,PLR_KILLER) ? "(KILLER) " : "",
		IS_SET(wch->act,PLR_THIEF) ? "(THIEF) " : "",
		wch->name, IS_NPC(wch) ? "" : wch->pcdata->title);
	    strcat(output,buf);
            if(wch->pcdata->email && wch->pcdata->email[0] != '\0')
            {
                sprintf(buf, "{W%s's email is: {C%s\n\r",
                   wch->name,
                   wch->pcdata->email);
                strcat(output,buf);
            }

            sprintf(buf,"  {Y[{WPkill Wins: {G%d{Y] [{WPkill Losses: {R%d{Y]{x\n\r",
                wch->pcdata->pkill_wins,
                wch->pcdata->pkill_losses); 
            strcat(output,buf); 

	}
    }

    if (!found)
    {
	send_to_char("No one of that name is playing.\n\r",ch);
	return;
    }

    page_to_char(output,ch);
}


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

/* Newer 'who' command by Zeran */

void do_who( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
	char clanbuf[40];
	char form[MAX_STRING_LENGTH];
    char output[4 * MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    int iClass;
    int iRace;
    int iLevelLower;
    int iLevelUpper;
    int nNumber;
	int immMatch=0;
	int mortMatch=0;
    bool rgfClass[MAX_CLASS];
    bool rgfRace[MAX_PC_RACE];
    bool fClassRestrict;
    bool fRaceRestrict;
    bool fImmortalOnly;
	bool fClanOnly;
	struct who_slot *table[61]; /*want 1 to 100, not 0 to 99*/ 
	int counter;

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

    /*
     * Set default arguments.
     */
    iLevelLower    = 0;
    iLevelUpper    = MAX_LEVEL;
    fClassRestrict = FALSE;
    fRaceRestrict = FALSE;
    fImmortalOnly  = FALSE;
	fClanOnly		=FALSE;
    for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
	rgfClass[iClass] = FALSE;
    for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	rgfRace[iRace] = 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.
	     */
	    if ( arg[0] == 'i' )
	    {
		fImmortalOnly = TRUE;
	    }
		else if (!str_cmp(arg, "clan"))
			{
			if (ch->pcdata->clan_num == -1)
				{
				send_to_char ("'who clan' is only available to players in clans.\n\r",ch);
				return;
				}
			fClanOnly=TRUE;
			}
	    else
	    {
		iClass = class_lookup(arg);
		if (iClass == -1)
		{
		    iRace = race_lookup(arg);

		    if (iRace == 0 || iRace >= MAX_PC_RACE)
		    {
			send_to_char( 
			    "That's not a valid race or class.\n\r",ch);
			return;
		    }
		    else
		    {
			fRaceRestrict = TRUE;
			rgfRace[iRace] = TRUE;
		    }
		}
		else
		{
			send_to_char ("Sorry, who list by class has been removed.\n\r",ch);
			return;
		}
	    }
	}
    }
	/* 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 ) )
	    continue;

	if ( wch->level < iLevelLower
	||   wch->level > iLevelUpper
	|| ( fImmortalOnly  && wch->level < LEVEL_HERO )
	|| ( fClassRestrict && !rgfClass[wch->class] ) 
	|| ( fRaceRestrict && !rgfRace[wch->race])
	|| ( fClanOnly && wch->pcdata->clan_num != ch->pcdata->clan_num))
	    continue;

	if (wch->level >= LEVEL_IMMORTAL)
		immMatch++;
	else
		mortMatch++;	
	
	if (table[wch->level] == NULL) /*empty list*/
		{
		table[wch->level] = (struct who_slot *)malloc(sizeof(struct who_slot)); 
		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 = (struct who_slot *)malloc(sizeof(struct who_slot)); 
		tmp->next->ch = wch;
		tmp->next->next=NULL;
		}
	} /* end form table...fun, fun, fun! :) */

    /*
     * Now show matching chars.
     */
    buf[0] = '\0';
    output[0] = '\0';

	strcat(output,"\n\r{B--------------------------{xThe {WGuardians{x of SunderMud{B--------------------------{x\n\r");
   
	 for ( counter=60;counter>=1;counter--) /*outside list loop*/
    {
	CHAR_DATA *wch;
	struct who_slot *tmp=table[counter];

	if (counter == 51)
		{
		strcat(output,"{B-------------------------------------------------------------------------------{x\n\r");
		strcat(output,"{G---------------------------{xThe {WPlayers{x of SunderMud{G----------------------------{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 */
		{
		log_string ("Got null table->ch, argh.");
		continue;
		}
		
	strcpy (form, "{x[{Y%2d {W%s{x] %s%s%s%s%s %s");
		 	
	if ((!IS_NPC(wch))&&(wch->pcdata->clan!=NULL))
		{
		sprintf(clanbuf, "%s", wch->pcdata->clan->name);	
		}
	else sprintf (clanbuf, "%s", "");

        sprintf( 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))
		strcat (buf, " {r({cWizi{r){x");
	if (IS_SET(wch->act, PLR_CLOAK))
		strcat (buf, " {r({cCloak{r){x");
	
	if (!IS_NPC(wch) && (wch->desc!=NULL) && wch->desc->editor)
		strcat (buf, " {M(OLC){x ");
	strcat (buf, "\n\r");
	if ( (strlen(output) + strlen(buf)) > (4*MAX_STRING_LENGTH+1) )
		{ /*stop overruning outbuf, find better solution later*/
		page_to_char (output,ch);
		output[0]='\0';
		}
	strcat(output,buf);
	} /*end inner list loop*/
    } /*end countdown loop*/

	strcat(output,"{G-------------------------------------------------------------------------------{x\n\r");
    sprintf( buf2, "\n\r{yGuardians found: {r%d{x \n\r{yPlayers found:   {c%d{x\n\r",
					 immMatch, mortMatch );
    strcat(output,buf2);
    page_to_char( output, ch );
    return;
}

void do_count ( CHAR_DATA *ch, char *argument )
{
    int count;
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    count = 0;

    for ( d = descriptor_list; d != NULL; d = d->next )
        if ( d->connected == CON_PLAYING && can_see( ch, d->character ) )
	    count++;

    max_on = UMAX(count,max_on);

    if (max_on == count)
        sprintf(buf,"There are %d characters on, the most so far today.\n\r",
	    count);
    else
	sprintf(buf,"There are %d characters on, the most on today was %d.\n\r",
	    count,max_on);

    send_to_char(buf,ch);
}

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( "You are using:\n\r", ch );
    found = FALSE;
    for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
    {
	if ( ( obj = get_eq_char( ch, iWear ) ) == NULL )
	    continue;

	send_to_char( where_name[iWear], ch );
	if ( can_see_obj( ch, obj ) )
	{
	    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;
}



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 )
    {
	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 )
    {
	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 = obj1->value[0] + obj1->value[1] + obj1->value[2];
	    value2 = obj2->value[0] + obj2->value[1] + obj2->value[2];
	    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 to use helpfile.
 */

void do_areas( CHAR_DATA *ch, char *argument )
{
    do_help( ch, "areas" );
    return;
}


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

void do_where (CHAR_DATA *ch, char *argument)
	{
	char buf[MAX_STRING_LENGTH];
	if ( ch->in_room->area->name != NULL
		&& ch->in_room->area->name[0] != '\0' )
		sprintf (buf, "You are currently in: {%s\n\r", ch->in_room->area->name);
	else
		sprintf (buf, "You are in an unnamed area, inform the IMPs asap.\n\r");
	send_to_char (buf, ch);
	return;
	}

/* Old where command removed...too abusive */
/* void do_where( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    DESCRIPTOR_DATA *d;
    bool found;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Players near you:\n\r", ch );
	found = FALSE;
	for ( d = descriptor_list; d; d = d->next )
	{
	    if ( d->connected == CON_PLAYING
	    && ( victim = d->character ) != NULL
	    &&   !IS_NPC(victim)
	    &&   victim->in_room != NULL
	    &&   victim->in_room->area == ch->in_room->area
	    &&   can_see( ch, victim ) )
	    {
		found = TRUE;
		sprintf( buf, "%-28s %s\n\r",
		    victim->name, victim->in_room->name );
		send_to_char( buf, ch );
	    }
	}
	if ( !found )
	    send_to_char( "None\n\r", ch );
    }
    else
    {
	found = FALSE;
	for ( victim = char_list; victim != NULL; victim = victim->next )
	{
	    if ( victim->in_room != NULL
	    &&   victim->in_room->area == ch->in_room->area
	    &&   !IS_AFFECTED(victim, AFF_HIDE)
	    &&   !IS_AFFECTED(victim, AFF_SNEAK)
	    &&   can_see( ch, victim )
	    &&   is_name( arg, victim->name ) )
	    {
		found = TRUE;
		sprintf( buf, "%-28s %s\n\r",
		    PERS(victim, ch), victim->in_room->name );
		send_to_char( buf, ch );
		break;
	    }
	}
	if ( !found )
	    act( "You didn't find any $T.", ch, NULL, arg, TO_CHAR );
    }

    return;
} */


void do_consider( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char *msg = '\0';
    char *buf = '\0';
    int diff;
    int hpdiff;

    one_argument( argument, arg );

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

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They're not here.\n\r", ch );
	return;
    }

    if (is_safe(ch,victim))
    {
	send_to_char("Don't even think about it.\n\r",ch);
	return;
    }

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

         if ( diff <= -10 ) msg = "$N is not even worthy of your attention.";
    else if ( diff <=  -5 ) msg = "You could kill $N even on a bad day.";
    else if ( diff <=  -2 ) msg = "$N shouldn't be too hard.";
    else if ( diff <=   1 ) msg = "The {Yperfect match{w!";
    else if ( diff <=   4 ) msg = "With some luck & skill you could kill $N.";
    else if ( diff <=   9 ) msg = "Maybe you should purchase life insurance first.";
    else                    msg = "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 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];

    if ( IS_NPC(ch) )
    {
	bug( "Set_title: NPC.", 0 );
	return;
    }

    if ( title[0] != '.' && title[0] != ',' && title[0] != '!' && title[0] != '?' )
    {
	buf[0] = ' ';
	strcpy( buf+1, title );
    }
    else
    {
	strcpy( 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 ( strlen(argument) > 45 )
	argument[45] = '\0';

    smash_tilde( argument );
    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';

    smash_tilde( argument );
    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';

    smash_tilde( argument );
    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';
	smash_tilde( argument );
	if ( argument[0] == '+' )
	{
	    if ( ch->description != NULL )
		strcat( 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") ) 
    {
        string_append (ch, &ch->description );
        return;
    }

	strcat( buf, argument );
	strcat( 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];

    sprintf( buf,
	"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   );

    send_to_char( buf, ch );

    sprintf( buf, "$n says 'I have %d/%d hp %d/%d mana %d/%d mv %d xp.'",
	ch->hit,  ch->max_hit,
	ch->mana, ch->max_mana,
	ch->move, ch->max_move,
	ch->exp   );

    act( buf, ch, NULL, NULL, TO_ROOM );

    return;
}



void do_practice( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int sn;

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	int col;

	col    = 0;
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name == NULL )
		break;
/*	    if (ch->level < skill_table[sn].skill_level[ch->class] ) */
	    if (skill_available(sn, ch) == FALSE )
		continue;
	    sprintf( buf, "%-18s %3d%%  ",
		skill_table[sn].name, ch->pcdata->learned[sn] );
	    send_to_char( buf, ch );
	    if ( ++col % 3 == 0 )
		send_to_char( "\n\r", ch );
	}

	if ( col % 3 != 0 )
	    send_to_char( "\n\r", ch );

	sprintf( buf, "You have %d practice sessions left.\n\r",
	    ch->practice );
	send_to_char( buf, 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_PRACTICE) )
		break;
	}

	if ( mob == NULL )
	{
	    send_to_char( "You can't do that here.\n\r", ch );
	    return;
	}

	if ( ch->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) == FALSE )
	     || skill_table[sn].rating[ch->class] <0 ) ) )
	{
	    send_to_char( "You can't practice that.\n\r", ch );
	    return;
	}

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

	if ( ch->pcdata->learned[sn] >= adept )
	{
	    sprintf( buf, "You can only learn more about %s through experience.\n\r",
		skill_table[sn].name );
	    send_to_char( buf, ch );
	}
	else
	{
	    ch->practice--;
	    ch->pcdata->learned[sn] += 
		(int_app[get_curr_stat(ch,STAT_INT)].learn) / 4 ;
		/* only learn 1/4 of previous */
	    if ( ch->pcdata->learned[sn] < adept )
	    {
		act( "You practice $T.",
		    ch, NULL, skill_table[sn].name, TO_CHAR );
		act( "$n practices $T.",
		    ch, NULL, skill_table[sn].name, TO_ROOM );
	    }
	    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 buf[MAX_STRING_LENGTH];
    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;
    }

    ch->wimpy	= wimpy;
    sprintf( buf, "Wimpy set to %d hit points.\n\r", wimpy );
    send_to_char( buf, ch );
    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 ) )
    {
	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)
	{
	if (IS_SET(ch->act, PLR_XINFO))
		{
		send_to_char ("Xinfo is now off.\n\r",ch);
		ch->act -= PLR_XINFO;
		}
	else
		{
		send_to_char ("Xinfo is now on.\n\r",ch);
		ch->act += PLR_XINFO;
		}
	return;
	}

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;
	} 

/* RT configure command SMASHED */