ackmud/
ackmud/area/imc/
ackmud/npcs/a/
ackmud/npcs/c/
ackmud/npcs/d/
ackmud/npcs/e/
ackmud/npcs/f/
ackmud/npcs/h/
ackmud/npcs/i/
ackmud/npcs/k/
ackmud/npcs/l/
ackmud/npcs/n/
ackmud/npcs/o/
ackmud/npcs/p/
ackmud/npcs/r/
ackmud/npcs/s/
ackmud/npcs/w/
ackmud/player/c/
ackmud/player/s/
ackmud/player/z/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *       _/          _/_/_/     _/    _/     _/    ACK! MUD is modified    *
 *      _/_/        _/          _/  _/       _/    Merc2.0/2.1/2.2 code    *
 *     _/  _/      _/           _/_/         _/    (c)Stephen Dooley 1994  *
 *    _/_/_/_/      _/          _/  _/             "This mud has not been  *
 *   _/      _/      _/_/_/     _/    _/     _/      tested on animals."   *
 *                                                                         *
 *                                                                         *
 *  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.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "merc.h"
#include "tables.h"
#include <math.h>


extern  bool     deathmatch;


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>              ",
    "<worn on face>      ",
    "<worn as earring>   ",
    "<clutched>          ",
    "<dual wielded>      "
};



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

    sprintf( buf, "%s", colour_string( ch, "objects" ) );
    if ( IS_OBJ_STAT(obj, ITEM_INVIS)     )   safe_strcat(MAX_STRING_LENGTH, buf, "(Invis) "     );
    
    if ( ( IS_AFFECTED(ch, AFF_DETECT_EVIL) || item_has_apply( ch, ITEM_APPLY_DET_EVIL ) )
	 && IS_OBJ_STAT(obj, ITEM_EVIL)   )   safe_strcat(MAX_STRING_LENGTH, buf, "(Red Aura) "  );
    
    if ( ( IS_AFFECTED(ch, AFF_DETECT_MAGIC)|| item_has_apply( ch, ITEM_APPLY_DET_MAG) )
	 && IS_OBJ_STAT(obj, ITEM_MAGIC)  )   safe_strcat(MAX_STRING_LENGTH, buf, "(Magical) "   );
    
    if ( IS_OBJ_STAT(obj, ITEM_GLOW)      )   safe_strcat(MAX_STRING_LENGTH, buf, "(Glowing) "   );
    
    if ( IS_OBJ_STAT(obj, ITEM_HUM)       )   safe_strcat(MAX_STRING_LENGTH, buf, "(Humming) "   );

    if ( fShort )
    {
	if ( obj->short_descr != NULL )
	    safe_strcat(MAX_STRING_LENGTH, buf, obj->short_descr );
    }
    else
    {
	if ( obj->description != NULL )
	    safe_strcat(MAX_STRING_LENGTH, buf, obj->description );
    }
    safe_strcat( MAX_STRING_LENGTH, buf, colour_string( ch, "normal" ) );
    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;
    buf[0] = '\0';


    /*
     * Alloc space for output lines.
     */
    count = 0;
    for ( obj = list; obj != NULL; obj = obj->next_in_carry_list )
	count++;
    prgpstrShow = qgetmem( count * sizeof(char *) );
    prgnShow    = qgetmem( count * sizeof(int)    );
    nShow       = 0;

    /*
     * Format the list of objects.
     */
    for ( obj = list; obj != NULL; obj = obj->next_in_carry_list )
    { 
	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->act, PLR_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->act, PLR_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->act, PLR_COMBINE) )
	    send_to_char( "     ", ch );
	send_to_char( "Nothing.\n\r", ch );
    }

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

    return;
}

void show_room_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;
    buf[0] = '\0';


    /*
     * Alloc space for output lines.
     */
    count = 0;
    for ( obj = list; obj != NULL; obj = obj->next_in_room )
	count++;
    prgpstrShow = qgetmem( count * sizeof(char *) );
    prgnShow    = qgetmem( count * sizeof(int)    );
    nShow       = 0;

    /*
     * Format the list of objects.
     */
    for ( obj = list; obj != NULL; obj = obj->next_in_room )
    { 
	if ( obj->wear_loc == WEAR_NONE && can_see_obj( ch, obj ) && str_cmp( obj->description, "" ) )
	{
	    pstrShow = format_obj_to_char( obj, ch, fShort );
	    fCombine = FALSE;

	    if ( IS_NPC(ch) || IS_SET(ch->act, PLR_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->act, PLR_COMBINE) ) && str_cmp( prgpstrShow[iShow], "" ) )
	{
	    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->act, PLR_COMBINE) )
	    send_to_char( "     ", ch );
	send_to_char( "Nothing.\n\r", ch );
    }

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

    return;
}




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


    sprintf( buf, "%s", colour_string( ch, "mobiles" ) );
    buf2[0] = '\0';

 
/* This is temporary....
 * Zen  WOLF
 *
 */   
    if ( !IS_NPC( victim ) && IS_WOLF( victim ) )
    {
      if ( IS_SHIFTED( victim ) )
      {
        send_to_char( "A large wolf scampers before you.@@N\n\r", ch );
        return;
      }
      else
      if ( IS_RAGED( victim ) )
      {
        send_to_char( "A @@bWEREWOLF in @@rFULL RAGE stands before you!\n\r", ch );
        return;
      }
    }


    if ( !IS_NPC( victim ) )
    {
	  /* Then show what race they are (about time this added ;) */
	  sprintf( buf2, "(%s) ", race_table[victim->race].race_name );    
	  safe_strcat(MAX_STRING_LENGTH, buf, buf2 );
    }
    
    if ( IS_NPC( victim ) )
    {
       if ( IS_SET( victim->act, ACT_UNDEAD ) &&
	  ( IS_AFFECTED( ch, AFF_DETECT_UNDEAD ) || item_has_apply( ch, ITEM_APPLY_DET_UNDEAD ) ) )
	  safe_strcat(MAX_STRING_LENGTH, buf, "(UnDead) " );
    
       if ( IS_SET( victim->act, ACT_INTELLIGENT ) )
	  safe_strcat( MAX_STRING_LENGTH, buf, "(Int) ");
    
    }
    
    
    if ( IS_AFFECTED(victim, AFF_INVISIBLE)   ) safe_strcat(MAX_STRING_LENGTH, buf, "(Invis) "      );
    
    if ( IS_AFFECTED(victim, AFF_HIDE) || item_has_apply( victim, ITEM_APPLY_HIDE ) )
     safe_strcat(MAX_STRING_LENGTH, buf, "(Hide) "       );
    
    if ( IS_AFFECTED(victim, AFF_CHARM)       ) safe_strcat(MAX_STRING_LENGTH, buf, "(Charm) "    );
    
    if ( IS_AFFECTED(victim, AFF_PASS_DOOR) || item_has_apply( victim, ITEM_APPLY_PASS_DOOR) )
	 safe_strcat(MAX_STRING_LENGTH, buf, "(Clear) ");
    
    if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) ) safe_strcat(MAX_STRING_LENGTH, buf, "(Pink) "  );
    
    if ( IS_EVIL(victim)
    &&   (IS_AFFECTED(ch, AFF_DETECT_EVIL)|| item_has_apply( ch, ITEM_APPLY_DET_EVIL) ) )
	  safe_strcat(MAX_STRING_LENGTH, buf, "(Red) "   );
    
    if ( IS_AFFECTED(victim, AFF_SANCTUARY) || item_has_apply( victim, ITEM_APPLY_SANC )  )
	 safe_strcat(MAX_STRING_LENGTH, buf, "(White) " );
    
    if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER ) )
						safe_strcat(MAX_STRING_LENGTH, buf, "(KILLER) "     );
    
    if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_THIEF  ) )
						safe_strcat(MAX_STRING_LENGTH, buf, "(THIEF) "      );

	/* strcat to buf *linkdead* if not connected? */
    if ( !IS_NPC(victim)  )
      if ( (victim->desc) != NULL
	   && victim->desc->connected != CON_PLAYING )
       safe_strcat( MAX_STRING_LENGTH, buf, "(LINKDEAD)" );

    if ( !IS_NPC( victim ) && IS_SET( victim->pcdata->pflags, PFLAG_RULER ) )    
      safe_strcat( MSL, buf, 
       get_ruler_title( victim->pcdata->ruler_rank, victim->login_sex ) );
    if ( victim->position == POS_STANDING && victim->long_descr[0] != '\0' )
    {
	safe_strcat(MAX_STRING_LENGTH, buf, victim->long_descr );
	safe_strcat(MAX_STRING_LENGTH, buf, colour_string( ch, "normal" ) );

    if (  ( IS_AFFECTED( victim, AFF_CLOAK_FLAMING ) )
       || ( IS_AFFECTED( victim, AFF_CLOAK_ABSORPTION ) ) 
	 || ( IS_AFFECTED( victim, AFF_CLOAK_REFLECTION ) )  )
    {
      safe_strcat( MAX_STRING_LENGTH, buf, "  @@NCLOAK:" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_FLAMING ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@eFLAMING@@N" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_ABSORPTION ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@lABSORB@@N" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_REFLECTION ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@mREFLECT@@N" );
      safe_strcat( MAX_STRING_LENGTH, buf, "\n\r" );
    }

    if ( victim->first_shield != NULL )
    {
      MAGIC_SHIELD * this_shield;
      safe_strcat( MSL, buf, "   @@WSHIELD: @@N" );
      for ( this_shield = victim->first_shield; this_shield != NULL; this_shield = this_shield->next )
        safe_strcat( MSL, buf, this_shield->name );
      safe_strcat( MSL, buf, "\n\r" );
    }

	send_to_char( buf, ch );
	return;
    }

    safe_strcat(MAX_STRING_LENGTH, buf, PERS( victim, ch ) );
    if ( !IS_NPC(victim) && !IS_SET(ch->act, PLR_BRIEF) )
	safe_strcat(MAX_STRING_LENGTH, buf, victim->pcdata->title );

    switch ( victim->position )
    {
    case POS_DEAD:     safe_strcat(MAX_STRING_LENGTH, buf, " is DEAD!!" );              break;
    case POS_MORTAL:   safe_strcat(MAX_STRING_LENGTH, buf, " is mortally wounded." );   break;
    case POS_INCAP:    safe_strcat(MAX_STRING_LENGTH, buf, " is incapacitated." );      break;
    case POS_STUNNED:  safe_strcat(MAX_STRING_LENGTH, buf, " is lying here stunned." ); break;
    case POS_SLEEPING: safe_strcat(MAX_STRING_LENGTH, buf, " is sleeping here." );      break;
    case POS_RESTING:  
      if ( victim->sitting != NULL 
	 && victim->sitting->in_room == victim->in_room )
      {
	 char sit[MAX_INPUT_LENGTH];
	 sprintf( sit, " is here, resting on %s.", victim->sitting->short_descr );
	 safe_strcat( MAX_STRING_LENGTH, buf, sit );
      }
      else
	safe_strcat(MAX_STRING_LENGTH, buf, " is resting here." );       
      break;
    case POS_STANDING: 
         {
           safe_strcat(MAX_STRING_LENGTH, buf, " is here" );
           if (  !IS_NPC( victim )
              && ( victim->stance > 0 ) 
              && ( victim->stance != STANCE_AMBUSH ) )
           {
             char stance_buf[MSL];
             sprintf( stance_buf, " in the Stance of the %s.", stance_app[victim->stance].name );
             safe_strcat( MSL, buf, stance_buf );
           }
           else              
             safe_strcat( MSL, buf, "." );
           break;
         }
    case POS_WRITING:  safe_strcat(MAX_STRING_LENGTH, buf, " is writing a note." );     break;
    case POS_BUILDING: safe_strcat(MAX_STRING_LENGTH, buf, " is BUILDING!!" );          break;
    case POS_FIGHTING:
	safe_strcat(MAX_STRING_LENGTH, buf, " is here, fighting " );
	if ( victim->fighting == NULL )
	    safe_strcat(MAX_STRING_LENGTH, buf, "thin air??" );
	else if ( victim->fighting == ch )
	    safe_strcat(MAX_STRING_LENGTH, buf, "YOU!" );
	else if ( victim->in_room == victim->fighting->in_room )
	{
	    safe_strcat(MAX_STRING_LENGTH, buf, PERS( victim->fighting, ch ) );
	    safe_strcat(MAX_STRING_LENGTH, buf, "." );
	}
	else
	    safe_strcat(MAX_STRING_LENGTH, buf, "somone who left??" );
	break;
    }

    
    /* buf[0] = UPPER(buf[0]); */
    safe_strcat( MAX_STRING_LENGTH, buf, colour_string( ch, "normal" ) );
    safe_strcat(MAX_STRING_LENGTH, buf, "\n\r" );

    if (  ( IS_AFFECTED( victim, AFF_CLOAK_FLAMING ) )
       || ( IS_AFFECTED( victim, AFF_CLOAK_ADEPT ) ) 
	 || ( IS_AFFECTED( victim, AFF_CLOAK_REGEN ) )  
       || ( IS_AFFECTED( victim, AFF_CLOAK_ABSORPTION ) ) 
	 || ( IS_AFFECTED( victim, AFF_CLOAK_REFLECTION ) )  )
    {
      safe_strcat( MAX_STRING_LENGTH, buf, "  @@NCLOAK:" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_FLAMING ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@eFLAMING@@N" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_ABSORPTION ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@lABSORB@@N" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_REFLECTION ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@mREFLECT@@N" );
      
      if ( IS_AFFECTED( victim, AFF_CLOAK_ADEPT ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@WADEPT@@N" );
      if ( IS_AFFECTED( victim, AFF_CLOAK_REGEN ) )
	safe_strcat( MAX_STRING_LENGTH, buf, " @@rREGEN@@N" );
      
      safe_strcat( MAX_STRING_LENGTH, buf, "\n\r" );
   
    }
    if ( victim->first_shield != NULL )
    {
      MAGIC_SHIELD * this_shield;
      safe_strcat( MSL, buf, "   @@WSHIELD: @@N" );
      for ( this_shield = victim->first_shield; this_shield != NULL; this_shield = this_shield->next )
        safe_strcat( MSL, buf, this_shield->name );
      safe_strcat( MSL, buf, "\n\r" );
    }

    if ( victim->riding != NULL )
    {
      sprintf( buf2, "  riding %s.\n\r", victim->riding->short_descr );
      safe_strcat( MSL, buf, buf2 );
    }

    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 pct;
    bool found;
    buf[0] = '\0';


    if ( can_see( victim, ch ) )
    {
     
	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 )
	pct = ( 100 * victim->hit ) / victim->max_hit;
    else
	pct = -1;

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

	 if ( pct >= 100 ) safe_strcat(MAX_STRING_LENGTH, buf, " is in pristine condition.\n\r" );
    else if ( pct >=  90 ) safe_strcat(MAX_STRING_LENGTH, buf, " is slightly scratched.\n\r" );
    else if ( pct >=  80 ) safe_strcat(MAX_STRING_LENGTH, buf, " has some light bruising.\n\r" );
    else if ( pct >=  70 ) safe_strcat(MAX_STRING_LENGTH, buf, " has some shallow cuts.\n\r" );
    else if ( pct >=  60 ) safe_strcat(MAX_STRING_LENGTH, buf, " has several weeping wounds.\n\r" );
    else if ( pct >=  50 ) safe_strcat(MAX_STRING_LENGTH, buf, " looks like a traffic accident.\n\r" );
    else if ( pct >=  40 ) safe_strcat(MAX_STRING_LENGTH, buf, " is bleeding slowly into a puddle.\n\r" );
    else if ( pct >=  30 ) safe_strcat(MAX_STRING_LENGTH, buf, " is spraying blood all over.\n\r" );
    else if ( pct >=  20 ) safe_strcat(MAX_STRING_LENGTH, buf, " is having trouble living.\n\r" );
    else if ( pct >=  10 ) safe_strcat(MAX_STRING_LENGTH, buf, " looks ready to kick the bucket.\n\r"        );
    else                   safe_strcat(MAX_STRING_LENGTH, buf, " is DYING.\n\r" );

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

    found = FALSE;

    if ( !IS_NPC( victim ) && IS_WOLF( victim )
       && ( IS_SHIFTED( victim ) || IS_RAGED( victim )  )  )
    {
    }
    else
    {
      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] )
      {
	send_to_char( "\n\rYou peek at the inventory:\n\r", ch );
	show_list_to_char( victim->first_carry, ch, TRUE, TRUE );
      }
    }
    return;
}


void show_char_to_char( CHAR_DATA *list, CHAR_DATA *ch )
{
    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 )
	    continue;

        if (  ( rch->rider != NULL ) 
           && ( rch->rider != ch ) )
          continue;  /* show under the rider */

	if ( can_see( ch, rch ) )
	{
	    show_char_to_char_0( rch, ch );
	}
	else if ( room_is_dark( ch->in_room )
	&&        (IS_AFFECTED(rch, AFF_INFRARED )|| item_has_apply( rch, ITEM_APPLY_INFRA)) )
	{
	    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;
}



void do_look( CHAR_DATA *ch, char *argument )
{
    char buf  [MAX_STRING_LENGTH];
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char out  [MAX_STRING_LENGTH];
    CHAR_DATA *ppl;
    ROOM_INDEX_DATA *room;
    EXIT_DATA *pexit;
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    char pdesc[MSL];
    int door;
    bool found;
    buf[0] = '\0';
    out[0] = '\0';

    if ( !IS_NPC( ch ) && 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->first_person, ch );
	return;
    }

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || !str_cmp( arg1, "auto" ) )
    {
	/* 'look' or 'look auto' */
	sprintf( out, "%s%s%s\n\r", colour_string( ch, "rooms" ),
		 ch->in_room->name, colour_string( ch, "normal" ) );
	
	send_to_char( out, ch );
	
	if (  IS_SWITCHED( ch )  || ( !IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOEXIT)  ) )
	    do_exits( ch, "auto" );

	if ( arg1[0] == '\0'
	|| (  IS_SWITCHED( ch )  ||  ( !IS_NPC(ch) && !IS_SET(ch->act, PLR_BRIEF)  ) )  )
	{
	    sprintf( out, "%s%s%s\n\r", colour_string( ch, "rooms" ),
		     ch->in_room->description, colour_string( ch, "normal" ) );
	    send_to_char( out, ch );
	}
	
	/* Show any room-affects */
	if (  ( ch->in_room->affected_by != 0 ) 
	 && ( ( is_affected( ch, skill_lookup( "detect magic" ) ) )  
	    || ( item_has_apply( ch, ITEM_APPLY_DET_MAG ) )  ) )
        {
	   sprintf( out, "%s", colour_string( ch, "rooms" ) );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_SHADE ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA menacing @@ddark shadow@@N hangs in the sky above you.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_ENCAPS ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA barely visible @@renergy web@@N is blocking all exits here.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_FIRE_RUNE ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA mystical @@eFire @@NRune@@N hangs in the air above you.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_SHOCK_RUNE ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA mystical @@lShock@@N Rune@@N hangs in the air above you.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_POISON_RUNE ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA mystical @@dPoison@@N Rune hangs in the air above you.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_HEAL_REGEN ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA majestic @@mHealing Light@@N encompasses the room.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_HEAL_STEAL ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA menacing @@dWithering shadow@@N enfolds the room.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_MANA_REGEN ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA powerful @@eMana Flare@@N empowers the room.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_MANA_STEAL ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA mind sapping @@dMana Drain@@N enfolds the room.\n\r" );
	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_HOLD ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NThe magical bars of a @@rCage@@N surround the room.\n\r" );         

	   if ( IS_SET( ch->in_room->affected_by, ROOM_BV_SOUL_NET ) )
	      safe_strcat( MAX_STRING_LENGTH,  out, "@@NA demonic @@dSoul Net@@N enshrouds the room.\n\r" );
		   
	   
	   
	   safe_strcat( MAX_STRING_LENGTH,  out, colour_string( ch, "normal" ) );
	   send_to_char( out, ch );
        }

        if ( !IS_NPC( ch ) && ( IS_VAMP( ch ) || IS_WOLF( ch ) )  )
          if ( ch->in_room->first_mark_list != NULL )
          {
            MARK_LIST_MEMBER	*marks;
            sh_int	num_marks = 0;
            
            for ( marks = ch->in_room->first_mark_list; marks != NULL; marks = marks->next )
              
              if (  ( ( marks->mark->type == WOLF ) && IS_WOLF( ch ) )
                 || ( ( marks->mark->type == VAMP ) && IS_VAMP( ch ) )  )
               num_marks++;
            if ( num_marks > 0 )
            {
              char  marksbuf[MSL];

              if ( IS_WOLF( ch ) )
              {
                sprintf( marksbuf, "@@aThis room has @@W%d @@a%s@@W.@@N\n\r", num_marks, ( num_marks > 1 ) ? "scents" : "scent" );
              }
              else if ( IS_VAMP( ch ) )
              {
                sprintf( marksbuf, "@@mThis room has @@W%d @@eBlood%s@@N.\n\r", num_marks, ( num_marks > 1) ? "Signs" : "Sign" );
              }
              send_to_char( marksbuf, ch );
            }
 
          }
    
	
	
	show_room_list_to_char( ch->in_room->first_content, ch, FALSE, FALSE );
	show_char_to_char( ch->in_room->first_person,   ch );
	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_PORTAL:
	   if ( obj->value[1] == 0 )
	   {
	      act( "You don't seem to be able to look in $p.", ch, obj, NULL, TO_CHAR );
	      return;
	   }
	   
	   if ( ( room = get_room_index( obj->value[0] ) ) == NULL )
	   {
	      send_to_char( "You see nothing but blackness!\n\r", ch );
	      return;
	   }
	   
	   act( "$n looks into $p.", ch, obj, NULL, TO_ROOM );
	   
	   if ( !IS_NPC(ch)
	      &&   !IS_SET(ch->act, PLR_HOLYLIGHT)
	      &&   room_is_dark( ch->in_room ) )
	   {
	      act( "$p comes out into a dark place.  You see nothing!\n\r", ch, obj, NULL, TO_CHAR );
	      return;
	   }
	   
	   sprintf( buf, "You look in $p and see: %s%s.%s", colour_string( ch, "rooms" ), 
	      room->name, colour_string( ch, "normal" ) );
	   act( buf, ch, obj, NULL, TO_CHAR );
	   
	   found = FALSE;
	   if ( room->first_person != NULL )
	   {
	      send_to_char( "You see the following beings:\n\r", ch );
	      for ( ppl = room->first_person; ppl != NULL; ppl = ppl->next_in_room )
	      {
		 if ( can_see( ch, ppl ) )
		 {
		    found = TRUE;
		    sprintf( buf, "%s%s%s\n\r", colour_string( ch, "mobiles" ),
		       (IS_NPC(ppl) ? ppl->short_descr : ppl->name ),
		       colour_string( ch, "normal" ) );
		    send_to_char( buf, ch );
		 }
	      }
	   }
	   if ( !found )
	      act( "You see no beings through $p.", ch, obj, NULL, TO_CHAR );
	   
	   if ( room->first_content != NULL )
	   {
	      send_to_char( "Some objects are visible:\n\r", ch );
	      show_room_list_to_char( room->first_content, ch, TRUE, FALSE );
	   }
	   else
	      act( "You see no objects through $p.", ch, obj, NULL, TO_CHAR );   
	   
	   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_SPELL_MATRIX:
	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->first_in_carry_list, ch, TRUE, TRUE );
	    break;
	}
	return;
    }

    if ( !str_cmp( arg1, "board" ) || !str_cmp( arg2, "board" ) )
    {
	/*int bnum;*/
	
	if ( ( obj = get_obj_here( ch, "board" ) ) == NULL )
	{
	    send_to_char( "You do not see that here.\n\r", ch );
	    return;

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

    for ( obj = ch->first_carry; obj != NULL; obj = obj->next_in_carry_list)
    {
	if ( can_see_obj( ch, obj ) )
	{
	    sprintf( pdesc, "\n\r%s",  get_extra_descr( arg1, obj->first_exdesc ) );
	    if ( str_cmp( pdesc, "\n\r(null)" ) )
	    {
              send_to_char( pdesc, ch );
              act( "$L$n closely examines $p.", ch, obj, NULL, TO_ROOM );
		return;
	    }

	    sprintf( pdesc, "\n\r%s",  get_extra_descr( arg1, obj->pIndexData->first_exdesc ) );

	    if ( str_cmp( pdesc, "\n\r(null)" ) )
	    {
              send_to_char( pdesc, ch );
              act( "$L$n closely examines $p.", ch, obj, NULL, TO_ROOM );
		return;
	    }
	}

	if ( is_name( arg1, obj->name ) )
	{
	    send_to_char( obj->description, ch );
	    return;
	}
    }
     
    for ( obj = ch->in_room->first_content; obj != NULL; obj = obj->next_in_room)
    {
	if ( can_see_obj( ch, obj ) )
	{
	    sprintf( pdesc, "\n\r%s",  get_extra_descr( arg1, obj->first_exdesc ) );

	    if ( str_cmp( pdesc, "\n\r(null)" ) )
	    {
              send_to_char( pdesc, ch );
              act( "$L$n closely examines $p.", ch, obj, NULL, TO_ROOM );
		return;
	    }

	    sprintf( pdesc, "\n\r%s",  get_extra_descr( arg1, obj->pIndexData->first_exdesc ) );
	    if ( str_cmp( pdesc, "\n\r(null)" ) )
	    {
              send_to_char( pdesc, ch );
              act( "$L$n closely examines $p.", ch, obj, NULL, TO_ROOM );
		return;
	    }
	}

	if ( is_name( arg1, obj->name ) )
	{
          send_to_char( obj->description, ch );
          act( "$L$n closely examines $p.", ch, obj, NULL, TO_ROOM );
		return;
	}
    }

    sprintf( pdesc, "\n\r%s",  get_extra_descr( arg1, ch->in_room->first_exdesc ) );
    if ( str_cmp( pdesc, "\n\r(null)" ) )
    {
      send_to_char( pdesc, ch );
      act( "$L$n closely examines the $t.", ch, arg1, NULL, TO_ROOM );
      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 )
    {
	send_to_char( "Nothing special there.\n\r", ch );
	return;
    }

    if (  ( pexit->description != NULL    )
       && ( pexit->description[0] != '\0' )
       && (  ( !str_cmp( pexit->keyword, ""      ) )
          || (  ( str_cmp( pexit->keyword, ""    ) )
             && ( !str_cmp( pexit->keyword, arg1 ) ) )  )  )
	send_to_char( pexit->description, ch );
    else
	send_to_char( "Nothing special there.\n\r", ch );

    if (  ( pexit->keyword    != NULL )
       && ( pexit->keyword[0] != '\0' )
       && ( pexit->keyword[0] != ' ' )
       && ( !str_cmp( pexit->keyword, arg1 ) )  )
    {
	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) )
	{
	    act( "The $d is open.",   ch, NULL, pexit->keyword, TO_CHAR );
	}
    }

    return;
}



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

    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:
	    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 );
	}
    if ( ch->position > POS_RESTING )
      trigger_handler( ch, obj, TRIGGER_EXAMINE );
    }

    return;
}



/*
 * Thanks to Zrin for auto-exit part.
 */
void do_exits( CHAR_DATA *ch, char *argument )
{
    extern char * const compass_name[];
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    EXIT_DATA *pexit;
    bool found;
    bool fAuto;
    int door;

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


    fAuto  = !str_cmp( argument, "auto" );

    if ( !check_blind( ch ) )
	return;

    strcpy( buf, fAuto ? "[Exits:" : "Obvious exits:\n\r" );

    found = FALSE;
    for ( door = 0; door <= 5; door++ )
    {
      /* check for players that are blind (irl) */
        if ( !IS_NPC( ch ) && IS_SET( ch->pcdata->pflags, PFLAG_BLIND_PLAYER ) )
        {
          if (  ( pexit = ch->in_room->exit[door] ) != NULL
	     &&   pexit->to_room != NULL )
          {
            found = TRUE;
            if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
            {
               sprintf( buf2, " closed %s", ( !str_cmp( pexit->keyword, "" ) 
                                            ? compass_name[door] 
                                            : pexit->keyword )  );
            }
            else
            {
               sprintf( buf2, " %s", ( !str_cmp( pexit->keyword, "" ) 
                                     ? compass_name[door] 
                                     : pexit->keyword )  );
            }
	    safe_strcat( MAX_STRING_LENGTH, buf, buf2 );
            continue;
          }
        }


	/* Check for thieves with find_doors... */
	if ( !IS_NPC( ch ) )
	   if ( ( pexit = ch->in_room->exit[door] ) != NULL
	   &&  pexit->to_room != NULL
	   && IS_SET( pexit->exit_info, EX_CLOSED )
	   && !IS_SET( pexit->exit_info, EX_NODETECT ) 
	   && ( ch->pcdata->learned[gsn_find_doors] > number_percent() ) 
           && ( !str_cmp( pexit->keyword, "" ) )  )
	   {
	       found = TRUE;
	       if ( fAuto )
		  sprintf( buf2, " (%s)", compass_name[door] );
	       else
		  sprintf( buf2, "%-5s - Door.\n\r",
		     capitalize( compass_name[door] ) );
		    
	       safe_strcat( MAX_STRING_LENGTH, buf, buf2 );
	       continue;
	    }
	
	if ( ( pexit = ch->in_room->exit[door] ) != NULL
	&&   pexit->to_room != NULL
	&&   !IS_SET(pexit->exit_info, EX_CLOSED) 
        &&   ( !str_cmp( pexit->keyword, "" ) )  )
	{
	    found = TRUE;
	    if ( fAuto )
	    {
		safe_strcat(MAX_STRING_LENGTH, buf, " " );
		safe_strcat(MAX_STRING_LENGTH, buf, compass_name[door] );
	    }
	    else
	    {
		sprintf( buf + strlen(buf), "%-5s - %s\n\r",
		    capitalize( compass_name[door] ),
		    room_is_dark( pexit->to_room )
			?  "Too dark to tell"
			: pexit->to_room->name
		    );
	    }
	}
    }

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

    if ( fAuto )
	safe_strcat(MAX_STRING_LENGTH, buf, "]\n\r" );

    send_to_char( buf, ch );
    return;
}



void do_score( CHAR_DATA *ch, char *argument )
{
    
    /* Score text has been re-formatted to look a little nicer ;)
     * Affected by now dealt with by command 'affected'
     * Also now added colour
     *  -- Stephen
     */
    
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    int cnt;

    
    sprintf( buf, "@@y%s%s, Race: %s%s, Clan: %s\n\rAge: ",
       IS_NPC(ch)  ? ch->short_descr : ch->name,
       IS_NPC(ch)  ? "" : ch->pcdata->title,
       IS_NPC(ch)  ? "n/a" : race_table[ch->race].race_title,
       IS_VAMP(ch) ? "@@e(Vampire)@@N" : IS_WOLF( ch ) ? "@@r(Werewolf)@@N" : "",
       IS_NPC(ch)  ? "n/a" : clan_table[ch->pcdata->clan].clan_name );
    my_get_age( ch, buf );
    send_to_char( buf, ch );
    sprintf( buf, " (%d hours RL)\n\r", my_get_hours( ch ) );
    send_to_char( buf, ch );
    
    /*
    sprintf( buf, 
       "@@WYou are: @@y%s%s  \n\r@@WAge: @@y%d @@W( @@y%d @@Whrs ) Race: @@y%s  @@WClan: @@y%s.@@g\n\r",
       IS_NPC(ch) ? ch->short_descr : ch->name,
       IS_NPC(ch) ? "" : ch->pcdata->title,    
       get_age(ch),
       (get_age(ch) - 17) * 2, 
       IS_NPC(ch) ? "n/a"  : IS_VAMP(ch) ? "Vampire" : race_table[ch->race].race_title,
       IS_NPC(ch) ? " n/a" : clan_table[ch->pcdata->clan].clan_name );
    send_to_char( buf, ch );
    */               
    
    sprintf( buf,
	"@@c+===============================================================+\n\r");
    send_to_char( buf, ch );

    sprintf( buf,
	"| @@y%4d/%4d @@WHit @@y%4d/%4d @@WMana @@y%4d/%4d @@WMovement @@y%3d @@WPractices@@c |\n\r",
	 ch->hit,  ch->max_hit,
	ch->mana, ch->max_mana,
	ch->move, ch->max_move,
	ch->practice );
    send_to_char( buf, ch );

    if ( IS_NPC( ch ) )
    {
	sprintf( buf,
	"|     @@R[ @@WStr:  @@y%2d  @@WInt:  @@y%2d  @@WWis:  @@y%2d  @@WDex:  @@y%2d  @@WCon:  @@y%2d @@R]      @@c|\n\r",
	get_curr_str( ch ), get_curr_int( ch ),
	get_curr_wis( ch ), get_curr_dex( ch ),
	get_curr_con( ch ) );
	send_to_char( buf, ch );
    
    
    }
    else
    {
    sprintf( buf,
	"|   @@R[ @@WStr:@@y%2d/%2d  @@WInt:@@y%2d/%2d  @@WWis:@@y%2d/%2d  @@WDex:@@y%2d/%2d  @@WCon:@@y%2d/%2d @@R]   @@c|\n\r",
	get_curr_str(ch), ch->pcdata->max_str,
	get_curr_int(ch), ch->pcdata->max_int,
	get_curr_wis(ch), ch->pcdata->max_wis,
	get_curr_dex(ch), ch->pcdata->max_dex,
	get_curr_con(ch), ch->pcdata->max_con );
    send_to_char( buf, ch );
    }
    
    if ( !IS_NPC( ch ) )
    {
       
    buf2[0] = '\0';

       for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
       {   
	  sprintf( buf, "@@c%s", class_table[cnt].who_name );
	  safe_strcat(MAX_STRING_LENGTH, buf2, buf );
	  if ( ch->lvl[cnt] != -1 )
	     sprintf( buf, ":@@W%2d ", ch->lvl[cnt] );
	  else
	     sprintf( buf, "@@c:%s ", " 0" );
	  safe_strcat(MAX_STRING_LENGTH, buf2, buf );
       }
     }
     else
       sprintf( buf2, " @@WLevel: @@y%d", ch->level );

    sprintf( buf, "@@c|%s @@c|\n\r", center_text(buf2, 62) );
    send_to_char( buf, ch );
    buf2[0] = '\0';

    if ( is_remort( ch ) )
    {
	
	for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	{
	   if ( ch->lvl2[cnt] != -1 )
	   {
	      sprintf( buf, "@@m%s:@@W%2d ", 
		 remort_table[cnt].who_name, ch->lvl2[cnt] ); 
	     safe_strcat(MAX_STRING_LENGTH, buf2, buf );

	   }
	}
	sprintf( buf, "@@c|%s @@c|\n\r", center_text(buf2, 62) );
	send_to_char( buf, ch );
     }
    
    if ( ch->adept_level > 0 )
    {
      sprintf( buf, "@@WADEPT@@N: %s ", get_adept_name( ch ) );
      buf2[0] = '\0';
      safe_strcat( MAX_STRING_LENGTH, buf2, buf );
      sprintf( buf, "@@c|%s @@c|\n\r", center_text(buf2, 62) );
      send_to_char( buf, ch );
    }
    
	   
    sprintf( buf,
	"X========= @@WExps: @@y%9d @@c========== @@WGold: @@y%10d @@c=========X\n\r",
	ch->exp,  ch->gold );
    send_to_char( buf, ch );

    if ( get_trust( ch ) != ch->level )
    {
	sprintf( buf, 
	"X================= @@WYou are trusted at level @@y%2d @@c=================X\n\r",
	    get_trust( ch ) );
	send_to_char( buf, ch );
    }
       
    
    
    
    
    sprintf( buf,
	"| @@WYou are carrying @@y%4d/%4d @@Witems, weight @@y%7d/%7d @@Wkg.  @@c|\n\r",
	ch->carry_number, can_carry_n(ch),
	ch->carry_weight, can_carry_w(ch) );
    send_to_char( buf, ch );


    sprintf( buf,
	"|       @@WAutoexit: @@y%s   @@WAutoloot: @@y%s  @@WAutosac: @@y%s       @@c|\n\r",
	 (!IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOEXIT)) ? "*ON* " : "*OFF*",
	(!IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOLOOT)) ? "*ON* " : "*OFF*",
	(!IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOSAC) ) ? "*ON* " : "*OFF*" );
    send_to_char( buf, ch );
    
    
    if ( !IS_NPC( ch ) )
    {
       sprintf( buf, " @@WYou have killed a total of: @@y%d @@WNPCs, and @@y%d @@WPlayers.",
	  ch->pcdata->mkills, ch->pcdata->pkills );
       sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf,62) );
       send_to_char( buf2, ch );

       sprintf( buf, " @@WA total of @@y%d @@WNPCs and @@y%d @@WPlayers have killed you.",
	  ch->pcdata->mkilled, ch->pcdata->pkilled );
       sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62 ) );
       send_to_char( buf2, ch );

       sprintf( buf, " @@WWimpy Set to @@y%d @@WHitPoints.  Page Length is @@y%d @@Wlines.",
	  ch->wimpy, ch->pcdata->pagelen );
       sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
       send_to_char( buf2, ch );

      sprintf( buf, " @@WDrunk: @@y%3s   @@WThirsty: @@y%3s   @@WHungry: @@y%3s",
	  ( ch->pcdata->condition[COND_DRUNK]  > 10 ) ? "Yes" : "No",
	  ( ch->pcdata->condition[COND_THIRST] == 0 ) ? "Yes" : "No",
	  ( ch->pcdata->condition[COND_FULL]   == 0 ) ? "Yes" : "No" );
       sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf,62) );
       send_to_char( buf2, ch );
     
      if ( IS_VAMP( ch ) )
      {
	  sprintf( buf, "@@eBLOODLUST@@W: @@e%d@@W/@@e%d@@N", ch->pcdata->bloodlust, ch->pcdata->bloodlust_max );
	  sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf,62) );
	  send_to_char( buf2, ch );
	  sprintf( buf, "@@dKindred Rank:@@N %d  @@rGeneration:@@N %d   @@mKnowledge Avail:@@N %d", 
	       ch->pcdata->vamp_level, ch->pcdata->generation, ch->pcdata->vamp_pracs );
	  sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
	  send_to_char( buf2, ch );
	  sprintf( buf, "@@WFAMILY: %s", get_family_name( ch ) );
	  sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
	  send_to_char( buf2, ch );

      }  
      else
      if ( IS_WOLF( ch ) )
      {
	  sprintf( buf, "@@eRAGE@@W: @@e%d@@W/@@e%d@@N", ch->pcdata->bloodlust, ch->pcdata->bloodlust_max );
	  sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf,62) );
	  send_to_char( buf2, ch );
	  sprintf( buf, "@@rTribe Rank@@W:@@N %d  @@yTribe Standing@@W:@@N %s   @@GKnowledge Avail:@@N %d", 
	       ch->pcdata->vamp_level, get_tribe_standing_name( ch->pcdata->generation ), ch->pcdata->vamp_pracs );
	  sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
	  send_to_char( buf2, ch );
	  sprintf( buf, "@@bTRIBE: %s", get_tribe_name( ch ) );
	  sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
	  send_to_char( buf2, ch );

       }  
  
    }
    sprintf( buf, "@@aQuest Points@@W: @@y%3d", ch->quest_points );
    sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
    send_to_char( buf2, ch );
    sprintf( buf, "@@WYou have assumed the @@yStance @@Wof the@@N %s.", stance_app[ch->stance].name );
    sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf, 62) );
    send_to_char( buf2, ch );

    switch ( ch->position )
    {
    case POS_DEAD:     
	sprintf( buf, " You are @@yDEAD!!" );
	break;
    case POS_MORTAL:
	sprintf( buf, " You are @@ymortally wounded." ); 
	break;
    case POS_INCAP:
	sprintf( buf, " You are @@yincapaciated." );
	break;
    case POS_STUNNED:
	sprintf( buf, " You are @@ystunned." );
	break;
    case POS_SLEEPING:
	sprintf( buf, " You are @@ysleeping." );
	break;
    case POS_RESTING:
	sprintf( buf, " You are @@yresting." );
	break;
    case POS_STANDING:
	sprintf( buf, " You are @@ystanding." );
	break;
    case POS_FIGHTING:
	sprintf( buf, " You are @@yfighting." );
	break;
    }
    sprintf( buf2, "|@@W%s @@c|\n\r", center_text(buf,62) );
    send_to_char( buf2, ch );

    sprintf( buf, "@@WYou are " );
	 if ( GET_AC(ch) >=  101 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yall skin and bones." );
    else if ( GET_AC(ch) >=   80 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ynaked."              );
    else if ( GET_AC(ch) >=   60 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ybadly armored."      );
    else if ( GET_AC(ch) >=   40 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yslightly armored."   );
    else if ( GET_AC(ch) >=   20 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ysomewhat armored."   );
    else if ( GET_AC(ch) >=    0 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yarmored."            );
    else if ( GET_AC(ch) >= - 20 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ywell armored."       );
    else if ( GET_AC(ch) >= - 40 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ystrongly armored."   );
    else if ( GET_AC(ch) >= - 60 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yheavily armored."    );
    else if ( GET_AC(ch) >= - 80 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ysuperbly armored."   );
    else if ( GET_AC(ch) >= -100 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ydivinely armored."   );
    else                           safe_strcat( MAX_STRING_LENGTH,  buf, "@@yalmost invincible!"  );

    
    sprintf( buf2, " @@WArmor Class: @@y%5d.   %s", GET_AC( ch ), buf );
    sprintf( buf, "@@c|%s @@c|\n\r", center_text(buf2,62) );
    send_to_char( buf, ch );
    
    sprintf( buf, " @@WHitroll: @@y%-5d   @@WDamroll: @@y%-5d", GET_HITROLL(ch), GET_DAMROLL(ch) );
    sprintf( buf2, "@@c|%s @@c|\n\r", center_text(buf,62) );
    send_to_char( buf2, ch );
    
	  
    sprintf( buf, " @@WYou are " );
    
	 if ( ch->alignment >  900 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yangelic." );
    else if ( ch->alignment >  700 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ysaintly." );
    else if ( ch->alignment >  300 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ygood."    );
    else if ( ch->alignment >  100 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ykind."    );
    else if ( ch->alignment > -100 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yneutral." );
    else if ( ch->alignment > -350 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ymean."    );
    else if ( ch->alignment > -700 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@yevil."    );
    else if ( ch->alignment > -900 ) safe_strcat( MAX_STRING_LENGTH,  buf, "@@ydemonic." );
    else                             safe_strcat( MAX_STRING_LENGTH,  buf, "@@ysatanic!" );
    
    sprintf( buf2, " @@WAlignment: @@y%5d.   %s", ch->alignment, buf );
    sprintf( buf, "@@c|%s @@c|\n\r", center_text(buf2,62) );
    send_to_char( buf, ch );



    sprintf( buf,
	"+===============================================================+@@g\n\r");
    send_to_char( buf, ch );
    
   
    return;
}

void do_affected( CHAR_DATA *ch, char *argument )
{
    
    char buf[MAX_STRING_LENGTH];
    AFFECT_DATA *paf;
    buf[0] = '\0';

	send_to_char( 
	"\n\r@@a********************** @@mYou are affected by: @@a*********************@@N\n\r", 
	ch );
	   
	
	if ( ch->first_affect != NULL )
	{
	   for ( paf = ch->first_affect; paf != NULL; paf = paf->next )
	   {
	       sprintf( buf, "Spell: '%s'", skill_table[paf->type].name );
	       send_to_char( buf, ch );

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

                 }
                 else
                  sprintf( buf, " lasts for %d hours", paf->duration  );
		 send_to_char( buf, ch );
	       }

	       send_to_char( ".\n\r", ch );
	   }
    /* Check to see if items have applies... */
	}    

      if ( item_has_apply( ch, ITEM_APPLY_INFRA ) )
       send_to_char( "Spell: 'Infravision' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_INV ) )
       send_to_char( "Spell: 'Invisibilty' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_DET_INV ) )
       send_to_char( "Spell: 'Detect Invisibilty' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_SANC ) )
       send_to_char( "Spell: 'Sanctuary' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_SNEAK ) )
       send_to_char( "Skill: 'Sneak' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_HIDE ) )
       send_to_char( "Skill: 'Hide' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_PROT ) )
       send_to_char( "Spell: 'Protection' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_ENHANCED ) )
       send_to_char( "Skill: 'Enhanced Damage' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_DET_MAG ) )
       send_to_char( "Spell: 'Detect Magic' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_DET_HID ) )
       send_to_char( "Spell: 'Detect Hidden' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_DET_EVIL ) )
       send_to_char( "Spell: 'Detect Evil' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_PASS_DOOR ) )
       send_to_char( "Spell: 'Pass Door' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_DET_POISON ) )
       send_to_char( "Spell: 'Detect Posion' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_FLY ) )
       send_to_char( "Spell: 'Fly' permanent duration.\n\r", ch );
    if ( item_has_apply( ch, ITEM_APPLY_KNOW_ALIGN ) )
       send_to_char( "Spell: 'Know Alignment' permanent duration.\n\r", ch );  
  

    sprintf( buf,
	"*****************************************************************\n\r");
    send_to_char( buf, ch );


    

    return;
}

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

/* 
 * Number of months reduced from 17 (!) to 8
 * This is to bring the time it takes a character to age on mud year
 * down from 200+ rl hrs to 64 rl hrs
 * (Player's age stats were screwed in base merc!)
 */

char *  const   month_name      [] =
{
    "the Frost Giant", "the Old Forces",
    "the Grand Struggle", "Futility", 
    "the Dark Shades", "the Long Shadows", 
    "the Ancient Darkness", "the Great Evil"
};

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\rAck! started up at %s\rThe system time is %s\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],
	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];
    char buf2[MSL];

    static char * const sky_look[4] =
    {
	"cloudless",
	"cloudy",
	"rainy",
	"lit by flashes of lightning"
    };
    buf[0] = '\0';
    buf2[0] = '\0';

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

    if ( IS_SET( ch->in_room->affected_by, ROOM_BV_SHADE ) )
    {
       send_to_char( "You see no weather - a dark shadow masks the sky.\n\r", ch );
       return;
    }
    
    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"
	);
    switch ( weather_info.moon_loc )
    {
      case MOON_DOWN: safe_strcat( MSL, buf, "The moon is not in the sky.\n\r");
                     break;
      case MOON_RISE: sprintf( buf2, "A %s @@yMoon@@N is just rising.\n\r", get_moon_phase_name( ) );
                      safe_strcat( MSL, buf, buf2 );
                      break;
      case MOON_LOW: sprintf( buf2, "A %s @@yMoon@@N is low on the horizon.\n\r", get_moon_phase_name( ) );
                      safe_strcat( MSL, buf, buf2 );
                      break;
      case MOON_PEAK: sprintf( buf2, "A %s @@yMoon@@N is high above you.\n\r", get_moon_phase_name( ) );
                      safe_strcat( MSL, buf, buf2 );
                      break;
      case MOON_FALL: sprintf( buf2, "A %s @@yMoon@@N is falling.\n\r", get_moon_phase_name( ) );
                      safe_strcat( MSL, buf, buf2 );
                      break;

      case MOON_SET: sprintf( buf2, "A %s @@yMoon@@N has just set.\n\r", get_moon_phase_name( ) );
                      safe_strcat( MSL, buf, buf2 );
                      break;

    }

    send_to_char( buf, ch );
    return;
}



void do_help( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;

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

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

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

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

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



/*
 * New 'who' command originally by Alander of Rivers of Mud.
 * Changed a lot since then though :P
 * List comes in 4 parts: Imms, Adepts, remorts then morts
 */

#define SHOW_IMMORT     0
#define SHOW_ADEPT	1
#define SHOW_REMORT     2
#define SHOW_MORTAL     3
#define SHOW_FINISH     4

void do_who( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d; 

    char buf[MAX_STRING_LENGTH*10];
    char buf2[MAX_STRING_LENGTH*4];
    char buf3[MAX_STRING_LENGTH*4];
    char buf4[MAX_STRING_LENGTH*4];
    char fgs[MAX_STRING_LENGTH*4];
    char clan_job[MAX_STRING_LENGTH];
    int iClass;
    int iLevelLower;
    int iLevelUpper;
    int nNumber;
    int nMatch;
    bool rgfClass[MAX_CLASS];
    bool fClassRestrict;
    bool fImmortalOnly;
    bool fadeptonly = FALSE;
    bool fremortonly = FALSE;
    int cnt, slength, excess, nlength;
    int true_cnt=0;
    static int max_players;
    int list;
    int number[3];
    bool idle = FALSE, invis = FALSE,  wanted = FALSE;
    bool cangroup = FALSE;
    int stop_counter = 0;

    /*
     * Set default arguments.
     */
    buf[0] = '\0';
    buf2[0] = '\0';
    buf3[0] = '\0';
    buf4[0] = '\0';

    iLevelLower    = 0;
    iLevelUpper    = MAX_LEVEL;
    fClassRestrict = FALSE;
    fImmortalOnly  = 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
	{
	    int iClass;

	    if ( strlen(arg) < 3 )
	    {
		send_to_char( "Classes must be longer than that.\n\r", ch );
		return;
	    }
	    /*
	     * Look for classes to turn on.
	     */
	    if ( !str_prefix( arg, "group" ) )
	    {
          cangroup = TRUE;
	     break;
	    }
	    if ( !str_prefix( arg, "adept" ) )
	    {
          fadeptonly = TRUE;
	     break;
	    }
	    if ( !str_prefix( arg, "remort" ) )
	    {
          fremortonly = TRUE;
	     break;
	    }


	    arg[3]    = '\0';
	    if ( !str_cmp( arg, "imm" ) )
	    {
		fImmortalOnly = TRUE;
	    }

	  else
	    {
		fClassRestrict = TRUE;
		for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
		{
		    if ( !str_cmp( arg, class_table[iClass].who_name ) )
		    {
			rgfClass[iClass] = TRUE;
			break;
		    }
		}

		if ( ( iClass == MAX_CLASS ) && ( !( cangroup ) )   )
		{
		    send_to_char( "That's not a class.\n\r", ch );
		    return;
		}
	    }
	}
    }

    buf[0] = '\0';
    
    sprintf( buf,    
    "WHO Listing: " mudnamecolor "\n\r" );
	  safe_strcat( MAX_STRING_LENGTH, buf, "@@R+-----------------------------------------------------------------------------+\n\r" );
	  safe_strcat( MAX_STRING_LENGTH, buf, "| @@mSo An Ki Ne Mo@@R                                                              |\n\r" );
	  safe_strcat( MAX_STRING_LENGTH, buf, "| @@bMa Cl Th Wa Ps @@eRace Clan  ABJPW    Player	Title		      @@R(flags) @@R|\n\r" );
	  safe_strcat( MAX_STRING_LENGTH, buf, "|---------------------------------+-------------------------------------------|\n\r" );    
    
    
    for ( list = SHOW_IMMORT; list < SHOW_FINISH; list ++)
    {
       number[list] = 0;
    
       for ( d = first_desc; 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 ( ( list == SHOW_IMMORT && wch->level < LEVEL_HERO )
	  || ( list == SHOW_REMORT && ( !is_remort( wch ) || wch->level >= LEVEL_HERO ) )
	  || ( list == SHOW_MORTAL && ( is_remort( wch ) || wch->level >= LEVEL_HERO ) ) 
        || ( list == SHOW_ADEPT  && ( wch->adept_level < 1 ) )
        || ( list == SHOW_ADEPT  && ( wch->level >= LEVEL_HERO ) ) 
        || ( list == SHOW_REMORT && ( wch->adept_level > 0 ) )   )
	     continue; 

	  if ( wch->level < iLevelLower
	  ||   wch->level > iLevelUpper
	  || ( fImmortalOnly  && wch->level < LEVEL_HERO )
       || ( fadeptonly && ( ( wch->adept_level < 1 ) || wch->level >= LEVEL_HERO ) )
	  || ( fClassRestrict && !rgfClass[wch->class] ) 
       || ( fremortonly && (  !is_remort( wch ) 
					  || ( wch->level >= LEVEL_HERO ) 
					  || ( wch->adept_level > 0 )   )   ) )
	      continue;

/* Multiple grouping restriction checks  Zen */

    {
      bool ch_adept = FALSE, ch_dremort = FALSE, ch_sremort = FALSE, victim_adept = FALSE,
           victim_dremort = FALSE, victim_sremort = FALSE, legal_group = FALSE;
 
    if ( ch->adept_level > 0 )
         ch_adept = TRUE;
    if ( wch->adept_level > 0 )
         victim_adept = TRUE;

    if ( get_psuedo_level( ch ) > 97 )
        ch_dremort = TRUE;
    if ( get_psuedo_level( wch ) > 97 )
        victim_dremort = TRUE;

    if ( get_psuedo_level( ch ) > 80 )
        ch_sremort = TRUE;
    if ( get_psuedo_level( wch ) > 80 )
        victim_sremort = TRUE;


    if ( ch_adept && victim_adept )
    {
      legal_group = TRUE;
    }
    else
    if (  ( ch_adept &&  victim_dremort )
       || ( victim_adept && ch_dremort )  )
    {
      if ( abs(  get_psuedo_level( ch ) - get_psuedo_level( wch )  ) < 9 )
        legal_group = TRUE;
      else
        legal_group = FALSE;
      
    }
    else
    
    if (   ch_dremort || victim_dremort ||  ch_sremort || victim_sremort   )
    {
      if ( abs(  get_psuedo_level( ch ) - get_psuedo_level( wch ) < 8 )  )
        legal_group = TRUE;
   
    }
    
    else
    {
      if ( abs( get_psuedo_level( ch ) - get_psuedo_level( wch )  ) < 21 )
          legal_group = TRUE;
     /*  send_to_char( "No Remorts\n\r", ch );  */

    }

    if ( IS_IMMORTAL( wch )  )
      legal_group = FALSE;

    if ( !legal_group && cangroup )
      continue;
 
   }


	  number[list]++;
       }
    }
    
    /*
     * Now show matching chars.
     */
    nMatch = 0;
    buf3[0] = '\0';
    buf4[0] = '\0';
    
    
    
    for ( list = SHOW_IMMORT; list < SHOW_FINISH; list++ )
    {
       stop_counter = 0;
       if ( number[list] == 0 )
	  continue;
       
       
       switch ( list )
       {
       case SHOW_IMMORT:
	  safe_strcat( MAX_STRING_LENGTH, buf, 
"@@R|---------------------------------|----------@@lImmortals@@R------------------------|@@g\n\r" );
	  break;

       case SHOW_ADEPT:
	  safe_strcat( MAX_STRING_LENGTH, buf, 
"@@R|---------------------------------|------------@@WAdepts@@R-------------------------|@@g\n\r" );
	  break;

       case SHOW_REMORT:
	  safe_strcat( MAX_STRING_LENGTH, buf, 
"@@R|---------------------------------|----------@@mRemortals@@R------------------------|@@g\n\r" );
	  break;
       case SHOW_MORTAL:
	  safe_strcat( MAX_STRING_LENGTH, buf, 
"@@R|---------------------------------|-----------@@cMortals@@R-------------------------|@@g\n\r" );
   
	  break;
       }
    
    true_cnt = 0;

    
    for ( d = first_desc; d != NULL; d = d->next )
    {
	CHAR_DATA *wch;
	char const *class;
	/*
	 * Check for match against restrictions.
	 * Don't use trust as that exposes trusted mortals.
	 */
	 true_cnt++;
	
	if ( d->connected != CON_PLAYING || !can_see( ch, d->character ) )
	    continue;

	wch   = ( d->original != NULL ) ? d->original : d->character;   
	/* Check to see if we're showing the correct character for
	 * each segment of the loop... 
	 */
	if ( ( list == SHOW_IMMORT && wch->level < LEVEL_HERO )
	|| ( list == SHOW_REMORT && ( !is_remort( wch ) || wch->level >= LEVEL_HERO ) )
	|| ( list == SHOW_MORTAL && ( is_remort( wch ) || wch->level >= LEVEL_HERO ) )
      || ( list == SHOW_ADEPT  && ( wch->adept_level < 1 ) ) 
      || ( list == SHOW_ADEPT  && ( wch->level >= LEVEL_HERO ) )  
      || ( list == SHOW_REMORT && ( wch->adept_level > 0 ) )  )
	   continue;

	if ( wch->level < iLevelLower
	||   wch->level > iLevelUpper
	|| ( fImmortalOnly  && wch->level < LEVEL_HERO )
     || ( fadeptonly && ( ( wch->adept_level < 1 ) || wch->level >= LEVEL_HERO ) )
	|| ( fClassRestrict && !rgfClass[wch->class] ) 
     || ( fremortonly && (  !is_remort( wch ) 
					|| ( wch->level >= LEVEL_HERO ) 
					|| ( wch->adept_level > 0 )   )   )  )

	    continue;

/* Multiple grouping restriction checks  Zen */

    {
      bool ch_adept = FALSE, ch_dremort = FALSE, ch_sremort = FALSE, victim_adept = FALSE,
           victim_dremort = FALSE, victim_sremort = FALSE, legal_group = FALSE;
 
    if ( ch->adept_level > 0 )
         ch_adept = TRUE;
    if ( wch->adept_level > 0 )
         victim_adept = TRUE;

    if ( get_psuedo_level( ch ) > 97 )
        ch_dremort = TRUE;
    if ( get_psuedo_level( wch ) > 97 )
        victim_dremort = TRUE;

    if ( get_psuedo_level( ch ) > 80 )
        ch_sremort = TRUE;
    if ( get_psuedo_level( wch ) > 80 )
        victim_sremort = TRUE;


    if ( ch_adept && victim_adept )
    {
      legal_group = TRUE;
    }
    else
    if (  ( ch_adept &&  victim_dremort )
       || ( victim_adept && ch_dremort )  )
    {
      if ( abs(  get_psuedo_level( ch ) - get_psuedo_level( wch )  ) < 9 )
        legal_group = TRUE;
      
    }
    else
    
    if (   ch_dremort || victim_dremort ||  ch_sremort || victim_sremort   )
    {
      if ( abs(  get_psuedo_level( ch ) - get_psuedo_level( wch )  ) < 8 )  
        legal_group = TRUE;
      else
        legal_group = FALSE;
   
    }
    
    else
    {
      if ( abs( get_psuedo_level( ch ) - get_psuedo_level( wch )  ) < 21 )
          legal_group = TRUE;
     /*  send_to_char( "No Remorts\n\r", ch );  */

    }
    if ( IS_IMMORTAL( wch ) )
      legal_group = FALSE;
    if ( !legal_group && cangroup )
      continue;
 
   }



       if ( stop_counter > 45 )
         continue;
       stop_counter++;

	nMatch++; 
	/*
	 * Figure out what to print for class.
	 */
	class = class_table[wch->class].who_name;
	
	if ( str_cmp( wch->pcdata->who_name, "off" ) )
	   class = wch->pcdata->who_name;
	else
	{   
	switch ( wch->level )
	{                                  
	default: break;
	case MAX_LEVEL - 0: class = "@@l-* CREATOR *-@@g "; break;
	case MAX_LEVEL - 1: class = "@@B-= SUPREME =-@@g "; break;
	case MAX_LEVEL - 2: class = "@@a--  DEITY  --@@g "; break;
	case MAX_LEVEL - 3: class = "@@c - IMMORTAL- @@g "; break;
	case MAX_LEVEL - 4: class = "@@W    ADEPT  @@N   "; break;
	}
			    
	}
	
	
	if ( IS_SET( wch->pcdata->pflags, PFLAG_AMBAS ) )
	{
	   sprintf( buf3,           "   AMBASSADOR  " );
	}
	else
	{  
	   if ( wch->level >= ( MAX_LEVEL - 4 ) 
	   ||   str_cmp(wch->pcdata->who_name, "off" ) )
	   {
	      switch( wch->level )
	      {
	      case MAX_LEVEL - 0:
		 sprintf( buf3, "@@l %s@@g", class );
		 break;
	      case MAX_LEVEL - 1:
		 sprintf( buf3, "@@B %s@@g", class );
		 break;
	      case MAX_LEVEL - 2:
		 sprintf( buf3, "@@a %s@@g", class );
		 break;
	      case MAX_LEVEL - 3:
		 sprintf( buf3, "@@c %s@@g", class );
		 break;
	      default:
		 sprintf( buf3, "@@W %s@@g", class );
		 break;
	      }
	   }
	   else
	   {
	      buf4[0] = '\0';
	      buf3[0] = '\0';
	   
	      for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	      {   
		 if ( wch->lvl2[cnt] > 0 )
		{
		 sprintf( buf4, "@@m%3d@@N", wch->lvl2[cnt] );
		 
		}
		else
		{
		 if ( wch->lvl[cnt] <= 0 )
		    sprintf( buf4, "@@d%3d@@N", 0 );
		 else
		    sprintf( buf4, "@@b%3d@@N", wch->lvl[cnt] );
		 }

		 safe_strcat(MAX_STRING_LENGTH, buf3, buf4 );
		
	       }
	     }
	}
	/* Work out what to show for 'flags' column.
	   PKOK, AFK, LEADER, WRITING, BUILDING 
	  ADDED: race and clan (Stephen)*/
	clan_job[0] = '\0';
	if ( IS_SET(wch->pcdata->pflags, PFLAG_CLAN_BOSS ) )
	  safe_strcat( MAX_STRING_LENGTH, clan_job, "*" );
	else if ( IS_SET( wch->pcdata->pflags, PFLAG_CLAN_LEADER ) )
	  safe_strcat( MAX_STRING_LENGTH, clan_job, "L" );
	else if ( IS_SET( wch->pcdata->pflags, PFLAG_CLAN_ARMOURER ) )
	  safe_strcat( MAX_STRING_LENGTH, clan_job, "!" );
	else 
	  safe_strcat( MAX_STRING_LENGTH, clan_job, " ") ;

	sprintf( fgs, "%3s %5s %s%s%s%s%s",
	   race_table[wch->race].race_name,
	   clan_table[wch->pcdata->clan].clan_abbr,
	   IS_SET( wch->pcdata->pflags, PFLAG_AFK  ) ? "A" : " ",
	   wch->position == POS_BUILDING             ? "B" : " ",
	   clan_job,
	   IS_SET( wch->pcdata->pflags, PFLAG_PKOK ) ? "P" : " ",
	   wch->position == POS_WRITING              ? "W" : " " );
	/* Oh look... another hack needed due to change in who format! */
	/* Make sure that the title (and wanted/idle flag) will fit ok */
	/* excess holds number of chars we have to lose ): */
	nlength = strlen( wch->name );
	slength = 1 + my_strlen(wch->pcdata->title) + nlength;
	
	excess = 0;

        idle = FALSE;
        wanted = FALSE;
        invis = FALSE;
        if ( IS_SET(wch->act, PLR_WIZINVIS ) )
        {
           excess += 6;
           invis = TRUE;
        }	
        else
        {
	if ( IS_SET(wch->act, PLR_KILLER ) || IS_SET(wch->act, PLR_THIEF ) )
	{
	   excess += 8;
	   wanted = TRUE;
	}
	
	if ( wch->timer > 5 )
	{
	   excess += 10;
	   idle = TRUE;
	}
	}   
	sprintf( buf4, wch->pcdata->title ); 
	
	if ( slength+excess > 43 )      
	{
	if ( invis )
		sprintf( buf4, "%1.26s", wch->pcdata->title );
	else if ( idle && !wanted )
		 sprintf( buf4, "%1.24s", wch->pcdata->title );
	else if ( !idle && wanted )
		 sprintf( buf4, "%1.28s", wch->pcdata->title );
	else if ( idle && wanted )
		 sprintf( buf4, "%1.18s", wch->pcdata->title );
	else 
		 sprintf( buf4, "%1.31s", wch->pcdata->title );       

	   
	}  
	else                            
	{
	   for ( cnt = slength+excess; cnt < 43; cnt ++ )
	   {
	      strcat( buf4, " " );
	   }
	}
        if ( invis  )
    	{ 
          if ( slength+excess <= 43 )
          {
            sprintf( buf + strlen(buf), "@@R|%s%s%s  %s @@R| %s%s%s%s",
             colour_string( ch, "stats" ),
             buf3,
             colour_string( ch, "stats" ),
             fgs,
             colour_string( ch, "stats" ),
             wch->name,
             buf4,
             IS_SET(wch->act, PLR_WIZINVIS )  ?
                "(WIZI)" : "" );
             sprintf( buf + strlen( buf ), "@@R|@@g\n\r" );
 	   }
          else
	   {
            sprintf( buf + strlen(buf), "@@R|%s%s%s  %s @@R| %s%s%s%s",
            colour_string( ch, "stats" ),
            buf3,
            colour_string( ch, "stats" ),
            fgs,
            colour_string( ch, "stats" ),
            wch->name,
            buf4,
            IS_SET(wch->act, PLR_WIZINVIS ) ?
               " (WIZI) " : "" );
           sprintf( buf + strlen( buf ), "@@R|@@g\n\r" );
	   }
	}
	else 
        {
	sprintf( buf + strlen(buf), "@@R|%s%s%s  %s @@R| %s%s%s%s",
	    colour_string( ch, "stats" ),
	    buf3,
	    colour_string( ch, "stats" ),
	    fgs,
	    colour_string( ch, "stats" ),
	    wch->name,
	    buf4,
	    ( IS_SET(wch->act, PLR_KILLER) || IS_SET(wch->act, PLR_THIEF) ) ? 
	       "(WANTED)" : "" );
	
	
	
	if ( wch->timer > 5 )
	   sprintf( buf + strlen(buf), "[IDLE:%2d] @@R|@@g\n\r", wch->timer );
	else
	   sprintf( buf + strlen( buf ), "@@R|@@g\n\r" );
	}	
    }
    
    safe_strcat( MAX_STRING_LENGTH, buf,    
"@@R|---------------------------------+-------------------------------------------|\n\r" );           
    send_to_char( buf, ch );
    buf[0] = '\0';
    } 
    
    if ( true_cnt > max_players )
       max_players = true_cnt;
    sprintf( buf4, "(%d Player%s)  KEY: (A)fk  (B)uilding  (*)Clan Boss  (P)kok  (W)riting",
	    nMatch, nMatch == 1 ? "" : "s" );
    sprintf( buf2, "@@R|@@G %s @@R|\n\r", center_text( buf4, 75 ) );
    safe_strcat(MAX_STRING_LENGTH, buf, buf2 );
    sprintf( buf4," (L) Clan Leader  (!) Clan Armourer " );
    sprintf( buf2, "@@R|@@G %s @@R|\n\r", center_text( buf4, 75 ) );
    safe_strcat(MAX_STRING_LENGTH, buf, buf2 );

    sprintf( buf4, "There have been a maximum of %d player%s logged on this session",
	    max_players, max_players == 1 ? "" : "s" );
    sprintf( buf2, "@@R|@@G %s @@R|\n\r", center_text( buf4, 75 ) );
    safe_strcat( MAX_STRING_LENGTH, buf, buf2 );
    safe_strcat( MAX_STRING_LENGTH, buf, 
    "@@R+-----------------------------------------------------------------------------+\n\r" );

/* Removed this... out is used once, to add a single color code... D'Oh! to me --Stimpy
    sprintf( out, "%s%s", buf, colour_string( ch, "normal" ) );
*/
  
    send_to_char( buf, ch );
    send_to_char( colour_string( ch, "normal" ), ch );

/* #endif  */

    return;      
}



void do_inventory( CHAR_DATA *ch, char *argument )
{
    if ( !IS_NPC( ch ) && IS_WOLF( ch )
       && ( IS_SHIFTED( ch ) || IS_RAGED( ch )  )   )
    {
      send_to_char( "All your inventory has transformed into fur!!!@@N\n\r", ch );
      return;
    }
 
    send_to_char( "You are carrying:\n\r", ch );
   show_list_to_char( ch->first_carry, ch, TRUE, TRUE );
    return;
}



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

    if ( !IS_NPC( ch ) && IS_WOLF( ch )
       && ( IS_SHIFTED( ch ) || IS_RAGED( ch )  )   )
    {
      send_to_char( "All your inventory has transformed into fur!!!@@N\n\r", ch );
      return;
    }
 
    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;
    if ( !IS_NPC( ch ) && IS_WOLF( ch )
       && ( IS_SHIFTED( ch ) || IS_RAGED( ch )  )   )
    {
      send_to_char( "All your inventory has transformed into fur!!!@@N\n\r", ch );
      return;
    }
 
    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->first_carry; obj2 != NULL; obj2 = obj2->next_in_carry_list )
	{
	    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];
	    value2 = obj2->value[0];
	    break;

	case ITEM_WEAPON:
	    value1 = obj1->value[1] + obj1->value[2];
	    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;
}



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



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;
    buf[0] = '\0';

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Players near you:\n\r", ch );
      sprintf( buf, "In %s %s @@N:\n\r",ch->in_room->area->level_label,
                     ch->in_room->area->name );
      send_to_char( buf, ch );
	found = FALSE;
	for ( d = first_desc; 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 ) 
            && ( !IS_WOLF( victim ) || ( !IS_SHIFTED( victim ) && !IS_RAGED( 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 = first_char; victim != NULL; victim = victim->next )
	{
	    /* &&   victim->in_room->area == ch->in_room->area 
	     * taken out from below to allow global where use
	     * and then put back in... global where no fun at all. ;)
	     * -- Stephen
	     */

	    if ( victim->in_room != NULL
	    &&   ( !IS_AFFECTED(victim, AFF_HIDE) && !item_has_apply( victim, ITEM_APPLY_HIDE ) )
	    &&  ( victim->in_room->area == ch->in_room->area )
	    &&  ( !IS_AFFECTED(victim, AFF_SNEAK) && !item_has_apply( victim, ITEM_APPLY_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';
    char *buf2 = '\0';
    char *buf3 = '\0';
    char *buf4 = '\0';
    float diff;
    int hpdiff;
    int hrdiff;
    int drdiff;
    int acdiff;
            
    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_NPC( victim ) )
       send_to_char( "Remember there are downfalls to PKilling!\n\r", ch );

    /* Stephen - bypass class adjustment if victim == NPC */    
    /* Also, only look at modifiers if victim == NPC */

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

	diff = (get_psuedo_level( victim ) - get_psuedo_level( ch ));    
    /* Additions for difficulty. */
    /* Class:   */
    if ( !IS_NPC( victim ) )
    {
       switch (ch->class)
       {
	  case 0:  diff+=0.3; break;      /* Mage       */
	  case 1:  diff+=0.4; break;      /* Cleric     */
	  case 2:  diff+=0.1; break;      /* Thief      */
	  case 3:  diff+=0  ; break;      /* Warrior    */
	  case 4:  diff-=0.4; break;      /* Psionicist */
	  case 5:  diff+=0.5; break;      /* Conjurer   */
	  case 6:  diff-=0.2; break;      /* Templar    */
	  case 7:  diff+=0.2; break;      /* Ranger     */
       }   
    }

    /* Mod rolls. */
    if ( IS_NPC( victim ) )
    {
       diff+=victim->hr_mod/4;
       diff+=victim->dr_mod/4;
       diff-=victim->ac_mod/30;
    }

    if ( diff >= 10 ) msg = "Death will thank you for your gift.";
    if ( diff <=   9 ) msg = "$N laughs at you mercilessly.";
    if ( diff <=   4 ) msg = "$N says 'Do you feel lucky, punk?'.";
    if ( diff <=   1 ) msg = "The perfect match!";
    if ( diff <=  -2 ) msg = "$N looks like an easy kill.";
    if ( diff <=  -5 ) msg = "$N is no match for you.";
    if ( diff <= -10 ) msg = "You can kill $N naked and weaponless.";
    
    act( msg, ch, NULL, victim, TO_CHAR );
    msg = "";

    /* 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 );
    buf = "";
    
/* LLolth added the following code to make consider show more information */
/* root@vampyre.net */

	drdiff = ( GET_DAMROLL(ch) - GET_DAMROLL(victim) );
	if ( drdiff >= 20 ) buf2 = "You hit alot harder than $E.";
	if ( drdiff <= 10 ) buf2 = "You hit slightly harder than $E.";
	if ( drdiff <= 5 ) buf2 = "$E hits about the same as you.";
	if ( drdiff <= -5 ) buf2 = "$E hits about the same as you.";
	if ( drdiff <= -10 ) buf2 = "$E hits slightly harder than you.";
	if ( drdiff <= -20 ) buf2 = "$E hits alot harder than you.";
    act( buf2, ch, NULL, victim, TO_CHAR );
    buf = "";
    	
	hrdiff = (GET_HITROLL(ch) - GET_HITROLL(victim) );
	if ( hrdiff >= 20 ) buf3 = "You hit alot more often than $E.";
	if ( hrdiff <= 10 ) buf3 = "You hit slightly more often than $E.";
	if ( hrdiff <= 5 ) buf3 = "You and $E hit about equally as often.";
	if ( hrdiff <= -10 ) buf3 = "$E hits slightly more often than you.";
	if ( hrdiff <= -20 ) buf3 = "$E hits alot more often than you.";
	act( buf3, ch, NULL, victim, TO_CHAR );
	buf3 = "";
	
	acdiff = (GET_AC(victim) - GET_AC(ch));
	if ( acdiff >= 100 ) buf4 = "You are Armored like a tank compared to $E.";
	if ( acdiff <= 75 ) buf4 = "You are armored quite a bit better than $E is.";
	if ( acdiff <= 50 ) buf4 = "You are more heavily armored than $E is.";
	if ( acdiff <= 25 ) buf4 = "You are slightly more armored than $E is.";
	if ( acdiff <= 5 ) buf4 = "You and $E are armored pretty equally.";
	if ( acdiff <= -6 ) buf4 = "$E is slightly more armored than you are.";
	if ( acdiff <= -50 ) buf4 = "$E is more heavily armored than you are.";
	if ( acdiff <= -75 ) buf4 = "$E is armored quite a bit better than you are.";
	if ( acdiff <= -100 ) buf4 = "$E is armored like a tank compared to you.";
	
	act( buf4, ch, NULL, victim, TO_CHAR );
	buf = "";
	return;	
}



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

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

    if ( isalpha(title[0]) || isdigit(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 )
{
    /* Changed this to limit title length, and to remove and brackets. -S- */
    
    char buf[MAX_STRING_LENGTH];
    int cnt;
    bool changed;
    buf[0] = '\0';

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	send_to_char( "Change your title to what?\n\r", ch );
	return;
    }
    changed = FALSE;

    for ( cnt = 0; cnt < strlen(argument); cnt++ )
    {
       if ( argument[cnt] == '[' || argument[cnt] == ']' )
       {
	  changed = TRUE;
	  argument[cnt] = ( argument[cnt] == ']' ) ? '>' : '<';
       }
    }

    if ( changed )
       send_to_char( "You used either [ or ] in your title.  They have been removed!\n\r", ch );

    /* my_strlen handles colour codes as zero length */
    if ( my_strlen(argument) > 29 )
    {
	send_to_char( "Title too long.  Please try again.\n\r", ch );
	return;
    }

    smash_tilde( argument );
    set_title( ch, argument );
    sprintf( buf, "You are now: %s%s.\n\r", ch->name, ch->pcdata->title );
    send_to_char( buf, ch );
}



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

    if ( argument[0] != '\0' )
    {
	buf[0] = '\0';
	smash_tilde( argument );
	if ( argument[0] == '+' )
	{
	    if ( ch->description != NULL )
		safe_strcat(MAX_STRING_LENGTH, 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;
	}

	safe_strcat(MAX_STRING_LENGTH, buf, argument );
	safe_strcat(MAX_STRING_LENGTH, 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 report: %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 reports: %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];
    char buf1[MAX_STRING_LENGTH];
    CHAR_DATA *mob;
    int cnt;
    int sn;
    int ack;
    int class;

    /* Now need to check through ch->lvl[] to see if player's level in
     * the required class is enough for him/her to be able to prac the
     * skill/spell.  Eg if char is cle:10 and war:50, we don't want the
     * player to be getting level 50 cleric spells, which would happen
     * if ch->class was used here! -S-
     */
    buf[0] = '\0';
    buf1[0] = '\0';
    
    if ( IS_NPC(ch) )
	return;

    buf1[0] = '\0';

    if ( ch->level < 3 )
    {
	send_to_char(
	    "You must be third level to practice.  Go train instead!\n\r",
	    ch );
	return;
    }
    /* moved check for mob here. -S- */

    for ( mob = ch->in_room->first_person; mob != NULL; mob = mob->next_in_room )
	{
	    if ( IS_NPC(mob) && IS_SET(mob->act, ACT_PRACTICE) )
		break;
	}

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

	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    ok = FALSE;
	    
	    if ( skill_table[sn].name == NULL )
		break;
	    
	    
	    /* Check ch->lvl[] */
	    for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	       if ( ( (( ch->lvl[cnt] >= skill_table[sn].skill_level[cnt] ) && ( skill_table[sn].flag1 == MORTAL ))
		  || ((ch->lvl2[cnt] >= skill_table[sn].skill_level[cnt] ) && ( skill_table[sn].flag1 == REMORT )) )
		  && (skill_table[sn].flag2 != VAMP )  
                  && ( skill_table[sn].flag2 != WOLF )  )
		  ok = TRUE;
	    
	    if ( ok || ch->pcdata->learned[sn] != 0 )
	    {
	       if ( ch->pcdata->learned[sn] == 0 && mob == NULL )
	       {
		  /* Not in prac room.  Only show what has been learnt */
		  continue;
	       } 
	       if ( ch->pcdata->learned[sn] > 0 )
               {
	         sprintf( buf, "@@W%16s-@@y%-7s@@g  ", skill_table[sn].name, 
		    learnt_name( ch->pcdata->learned[sn] ) );
	       
	         safe_strcat( MAX_STRING_LENGTH, buf1, buf );
	         if ( ++col % 3 == 0 )
		    safe_strcat(MAX_STRING_LENGTH, buf1, "\n\r" );
               }
	    }
	}

	if ( col % 3 != 0 )
	    safe_strcat(MAX_STRING_LENGTH, buf1, "\n\r" );

	sprintf( buf, "You have %d practice sessions left.\n\r",
	    ch->practice );
	safe_strcat(MAX_STRING_LENGTH, buf1, buf );
	send_to_char( buf1, ch );
    }
    else
    {
	int adept;
	bool ok;

	if ( !IS_AWAKE(ch) )
	{
	    send_to_char( "In your dreams, or what?\n\r", ch );
	    return;
	}
	for ( mob = ch->in_room->first_person; 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 )
	{
	    send_to_char( "You can't practice that.\n\r", ch );
	    return;
	}
	class = 0; ack = -1;
	ok = FALSE;



      if ( ( skill_table[sn].flag2 == VAMP )|| ( skill_table[sn].flag2 == WOLF ) )
	 {
	   send_to_char( "You can't practice that.\n\r", ch );
	   return;
	 }
      if (  ( skill_table[sn].flag1 == ADEPT ) 
	 && ( ch->adept_level >= skill_table[sn].skill_level[0] )   )
      {
	class = 0;
	ok = TRUE;
      }
      else
      {
	  for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	{
	    if (  ( ch->lvl[cnt] >= skill_table[sn].skill_level[cnt] )
	     && ( skill_table[sn].flag1 == MORTAL ) )
	    {
	    if ( ch->lvl[cnt] > ack ) 
	      {
		ack = ch->lvl[cnt];
		class = cnt;
	      }
	     
	      ok = TRUE;
	  }
	 
	  else 
	  if (  ( ch->lvl2[cnt] >= skill_table[sn].skill_level[cnt] )
	     && ( skill_table[sn].flag1 == REMORT ) )
	    {
	    if ( ch->lvl2[cnt] > ack ) 
	      {
		ack = ch->lvl2[cnt];
		class = cnt;
	      }
	      ok = TRUE;
	  }
	}
      }
	if ( !ok )
	{
	   send_to_char( "You can't practice that.\n\r", ch );
	   return;
	}
	for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	   if ( ch->pcdata->order[cnt] == class )
	      break;       

	adept = IS_NPC(ch) ? 100 : ( 90 - ( cnt * 4 ) );
      if ( skill_table[sn].flag1 == ADEPT )
	adept = 95;

	if ( ch->pcdata->learned[sn] >= adept )
	{
	    sprintf( buf, "You are already know %s as well as is currently possible.\n\r",
		skill_table[sn].name );
	    send_to_char( buf, ch );
	}
	else
	{
	    ch->practice--;
	    ch->pcdata->learned[sn] += int_app[get_curr_int(ch)].learn;
	    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 a master of $T.",
		    ch, NULL, skill_table[sn].name, TO_CHAR );
		act( "$n is now a master of $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;
    if ( deathmatch )
    {
      send_to_char( "Not during a @@eDeath MAtch@@N!!!\n\r", ch );
      return;
    }
    buf[0] = '\0';

    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 )
    {
	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;
    arg1[0] = '\0';
    arg2[0] = '\0';

    /*
     * 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 (  ( ch->pcdata->pwd != '\0' )
       && ( arg1[0] == '\0' || arg2[0] == '\0' )  )
    {
	send_to_char( "Syntax: password <old> <new>.\n\r", ch );
	return;
    }

    if (  ( ch->pcdata->pwd != '\0' )
       && ( 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_socials( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char out[MAX_STRING_LENGTH*2];
    int iSocial;
    int col;
    buf[0] = '\0';
 
    col = 0;
    out[0] = '\0';

    for ( iSocial = 0; social_table[iSocial].name[0] != '\0'; iSocial++ )
    {
	sprintf( buf, "%-12s", social_table[iSocial].name );
	safe_strcat(MAX_STRING_LENGTH, out, buf );
	if ( ++col % 6 == 0 )
	    safe_strcat(MAX_STRING_LENGTH, out, "\n\r" );
    }
 
    if ( col % 6 != 0 )
	safe_strcat(MAX_STRING_LENGTH, out, "\n\r" );
    send_to_char( out, ch );
    return;
}



/*
 * Contributed by Alander.
 */
void do_commands( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH];
    int cmd;
    int col;
 
    buf[0] = '\0';
    
    if ( IS_NPC(ch) )
       return;
    
    
    
    buf1[0] = '\0';
    col = 0;
    for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
    {
	if ( cmd_table[cmd].level <  LEVEL_HERO
	&&   cmd_table[cmd].level <= get_trust( ch ) )
	{
	
	     if ( cmd_table[cmd].level == CLAN_ONLY 
	      && ch->pcdata->clan == 0 )
		 continue;
	     
	     if ( cmd_table[cmd].level == BOSS_ONLY
	      && !IS_SET( ch->act, PLR_CLAN_LEADER ) )
		 continue;
	
	     if ( cmd_table[cmd].level == VAMP_ONLY
	      && !IS_VAMP( ch ) )
		 continue;
	     if ( cmd_table[cmd].level == WOLF_ONLY
	      && !IS_WOLF( ch ) )
		 continue;
	
	    sprintf( buf, "%-12s", cmd_table[cmd].name );
	    safe_strcat(MAX_STRING_LENGTH, buf1, buf );
	    if ( ++col % 6 == 0 )
		safe_strcat(MAX_STRING_LENGTH, buf1, "\n\r" );
	}
    }
 
    if ( col % 6 != 0 )
	safe_strcat(MAX_STRING_LENGTH, buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


struct chan_type {
	     int    bit;
	     int    min_level;
	     char * name;
	     char * on_string;
	     char * off_string;
	     };
	     
struct chan_type channels[] = {
	    { CHANNEL_AUCTION, 0, "auction",
	      "[ +AUCTION  ] You hear biddings.@@N\n\r",
	      "[ -auction  ] You don't hear biddings.\n\r" },
	    { CHANNEL_GOSSIP,  0, "gossip",
	      "[ +GOSSIP   ] You hear general gossip.\n\r",
	      "[ -gossip   ] You don't hear general gossip.\n\r" },
	    { CHANNEL_MUSIC,   0, "music", 
	      "[ +MUSIC    ] You hear people's music quotes.\n\r",
	      "[ -music    ] You don't hear people's music quotes.\n\r" },
	    { CHANNEL_IMMTALK, LEVEL_HERO, "immtalk",
	      "[ +IMMTALK  ] You hear what other immortals have to say.\n\r",
	      "[ -immtalk  ] You don't hear what other immortals have to say.\n\r" },
	    { CHANNEL_NOTIFY,  LEVEL_HERO, "notify",
	      "[ +NOTIFY   ] You hear player information.\n\r",
	      "[ -notify   ] You don't hear player information.\n\r" },
	    { CHANNEL_LOG,0, "log",
	    "[ +LOG      ] You receive LOG_FILE details.\n\r",
	    "[ -log      ] You don't receive LOG_FILE details.\n\r"},
	
	    { CHANNEL_QUEST,   0, "quest",
	    "[  +QUEST   ] You hear roleplaying quests!\n\r",
	    "[  -quest   ] You ignore roleplaying quests.\n\r" },
	
	    { CHANNEL_NEWBIE, 0, "newbie",
	     "[ +NEWBIE   ] You hear newbie's chit-chat.\n\r",
	     "[ -newbie   ] You don't hear newbie's chit-chat.\n\r" },
	    

	    { CHANNEL_QUESTION, 0, "question",
	    "[ +QUESTION ] You hear player's questions & answers.\n\r",
	    "[ -question ] You don't hear player's questions & answers.\n\r"},
	    

	    { CHANNEL_SHOUT,0, "shout",
	    "[ +SHOUT    ] You hear people shouting.\n\r",
	    "[ -shout    ] You don't hear people shouting.\n\r"},
	    

	    { CHANNEL_YELL,0, "yell",
	    "[ +YELL     ] You hear people yelling.\n\r",
	    "[ -yell     ] You don't hear people yelling.\n\r"},
	    

	    { CHANNEL_CLAN,0, "clan",
	    "[ +CLAN     ] You hear clan chit-chat.\n\r",
	    "[ -clan     ] You don't hear clan chit-chat.\n\r"},
	    
            { CHANNEL_GAME,0, "game",
            "[ +GAME     ] You hear players participating in games.\n\r",   
            "[ -game     ] You no longer hear people playing games.\n\r"},  
	
	    { CHANNEL_RACE,0, "race",
	    "[ +RACE     ] You hear your race's chit-chat.\n\r",
	    "[ -race     ] You don't hear your race's chit-chat.\n\r"},
	
	    { CHANNEL_FLAME,0, "flame",
	    "[ +FLAME    ] You hear players flaming each other.\n\r",
	    "[ -flame    ] You don't hear players flaming each other.\n\r"},
	    

	    { CHANNEL_ZZZ,0, "zzz",
	    "[ +ZZZ      ] You hear sleeping players chatting.\n\r",
	    "[ -zzz      ] You don't hear sleeping players chatting.\n\r"},
	    
	
	    { CHANNEL_INFO,0, "info",
	    "[ +INFO     ] You hear information about deaths, etc.\n\r",
	    "[ -info     ] You don't hear information about deaths, etc.\n\r"},
	    
	    { CHANNEL_CREATOR, 85, "creator",
	    "[ +CREATOR  ] You hear Creator's discussing Mud matters.\n\r",
	    "[ -creator  ] You don't hear Creators discussing Mud matters\n\r" },
	    
	    { CHANNEL_ALLCLAN, 85, "allclan",
	    "[ +ALLCLAN  ] You hear ALL clan channels.\n\r",
	    "[ -allclan  ] You don't hear ALL clan channels.\n\r" },
	    
	    { CHANNEL_ALLRACE, 85, "allrace",
	    "[ +ALLRACE  ] You hear ALL race channels.\n\r",
	    "[ -allrace  ] You don't hear ALL race channels.\n\r" },
	    
	    { CHANNEL_HERMIT, 0, "hermit",
	    "[ +HERMIT   ] You are NOT ignoring all channels.\n\r",
	    "[ -hermit   ] YOU ARE IGNORING ALL CHANNELS!\n\r" },
	    
	    { CHANNEL_BEEP,   0, "beep",
	    "[ +BEEP     ] You accept 'beeps' from other players.\n\r",
	    "[ -beep     ] You are ignoring 'beeps' from other players.\n\r" },
	    { CHANNEL_ALLCLAN, 85, "allclan",
	    "[ +ALLCLAN  ] You hear ALL clan channels.\n\r",
	    "[ -allclan  ] You don't hear ALL clan channels.\n\r" },
	    
	    { CHANNEL_FAMILY, 0, "vampyre",
	    "",
	    "" },
	    
	    { CHANNEL_DIPLOMAT, 0, "diplomat",
	    "[ +DIPLOMAT ] You hear diplomatic negotioations.\n\r",
	    "[ -diplomat ] YOU do not hear diplomatic negotiations\n\r" },
	    
	    { CHANNEL_REMORTTALK,   0, "{",
	    "[ +{        ] You hear remorts gossiping amongst themselves.\n\r",
	    "[ -{        ] You are ignoring idle remort chatter.\n\r" },

	    { CHANNEL_CRUSADE,   0, "crusade",
	    "[ +CRUSADE  ] You hear quest information.\n\r",
	    "[ -crusade  ] You are ignoring quest information.\n\r" },

	    { CHANNEL_ADEPT,   0, "adept",
	    "[  +ADEPT   ] You hear Adepts plotting to take over the mud!\n\r",
	    "[  -adept   ] You ignore those bored dudes and dudettes.\n\r" },

	    { CHANNEL_GAME,   0, "game",
	    "[   +GAME   ] You hear non-roleplaying games.\n\r",
	    "[   -game   ] You are ignoring non-roleplaying games.\n\r" },


	    { CHANNEL_OOC,   0, "ooc",
	    "[   +OOC    ] You hear non-roleplaying chit-chat.\n\r",
	    "[   -ooc    ] You ignore those boring non-roleplaying fools!\n\r" },
			    
	    { 0,0, NULL, NULL }
	    };
	   
	    
	      
	      
	    

	      

void do_channels( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buffer[MAX_STRING_LENGTH];
    int a,trust;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
      if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_SILENCE) )
      {
	send_to_char( "You are silenced.\n\r", ch );
	return;
      }

      trust=get_trust(ch);
      buffer[0]='\0';
      safe_strcat( MAX_STRING_LENGTH, buffer, "Channels:\n\r");
	
      for (a=0; channels[a].bit != 0; a++)
      {
	if (trust >= channels[a].min_level)
	{
          char  colbuf[10];
          colbuf[0] = '\0';

	  if ( IS_SET(ch->deaf, channels[a].bit) )
          {
            if ( !IS_NPC( ch ) )
            {
              sprintf( colbuf, "@@%c", ch->pcdata->dimcol );
              safe_strcat( MSL, buffer, colbuf );
            }
	    safe_strcat( MAX_STRING_LENGTH, buffer, channels[a].off_string);
          }
	  else
          {
            if ( !IS_NPC( ch ) )
            {
              sprintf( colbuf, "@@%c", ch->pcdata->hicol );
              safe_strcat( MSL, buffer, colbuf );
            }
	    safe_strcat( MAX_STRING_LENGTH, buffer, channels[a].on_string);
          }
	}
	
 	safe_strcat( MAX_STRING_LENGTH, buffer,"@@N");
      }
      send_to_char( buffer, ch );
    }
    else
    {
	bool fClear;
	int bit;

	     if ( arg[0] == '+' ) fClear = TRUE;
	else if ( arg[0] == '-' ) fClear = FALSE;
	else
	{
	    send_to_char( "Channels -channel or +channel?\n\r", ch );
	    return;
	}

	/* Now check through table to set/unset channel... */
	bit = 0;
	for ( a = 0; channels[a].bit != 0; a++ )
	{
	   if ( channels[a].min_level > get_trust( ch ) )
	      continue;
	   if ( !str_prefix( arg+1, channels[a].name ) )
	   {
	      bit = channels[a].bit;
	      break;
	   }
	}
	if ( bit == 0 )
	{
	   send_to_char( "Set or clear which channel?\n\r", ch );
	   return;
	}

	if ( fClear ) 
	    REMOVE_BIT (ch->deaf, bit);
	else
	    SET_BIT    (ch->deaf, bit);

	send_to_char( "Ok.\n\r", ch );
    }

    return;
}



/*
 * Contributed by Grodyn.
 */
void do_config( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    if ( IS_NPC(ch) )
	return;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "[ Keyword  ] Option\n\r", ch );

	send_to_char( IS_SET( ch->act, PLR_NOSUMMON )
	   ? "[+NOSUMMON ] You may not be summoned.\n\r"
	   : "[-nosummon ] You may be summoned.\n\r"
	   , ch );

	send_to_char( IS_SET( ch->act, PLR_NOVISIT )
	   ? "[+NOVISIT  ] You may not be 'visited'.\n\r"
	   : "[-novisit  ] You may be 'visited'.\n\r"
	   , ch );
	
	send_to_char( IS_SET( ch->act, PLR_COLOUR )
	   ? "[+COLOUR   ] You recieve 'ANSI' colour.\n\r"
	   : "[-colour   ] You don't receive 'ANSI' colour.\n\r"
	   , ch );
	
	send_to_char(  IS_SET(ch->act, PLR_AUTOEXIT)
	    ? "[+AUTOEXIT ] You automatically see exits.\n\r"
	    : "[-autoexit ] You don't automatically see exits.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_AUTOLOOT)
	    ? "[+AUTOLOOT ] You automatically loot corpses.\n\r"
	    : "[-autoloot ] You don't automatically loot corpses.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_AUTOSAC)
	    ? "[+AUTOSAC  ] You automatically sacrifice corpses.\n\r"
	    : "[-autosac  ] You don't automatically sacrifice corpses.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_BLANK)
	    ? "[+BLANK    ] You have a blank line before your prompt.\n\r"
	    : "[-blank    ] You have no blank line before your prompt.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_BRIEF)
	    ? "[+BRIEF    ] You see brief descriptions.\n\r"
	    : "[-brief    ] You see long descriptions.\n\r"
	    , ch );
	 
	send_to_char(  IS_SET(ch->act, PLR_COMBINE)
	    ? "[+COMBINE  ] You see object lists in combined format.\n\r"
	    : "[-combine  ] You see object lists in single format.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_PROMPT)
	    ? "[+PROMPT   ] You have a prompt.\n\r"
	    : "[-prompt   ] You don't have a prompt.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_TELNET_GA)
	    ? "[+TELNETGA ] You receive a telnet GA sequence.\n\r"
	    : "[-telnetga ] You don't receive a telnet GA sequence.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_NO_PRAY)
	    ? "[+NOPRAY   ] You cannot use 'pray'.\n\r"
	    : ""
	    , ch );
	
	send_to_char(  IS_SET(ch->act, PLR_SILENCE)
	    ? "[+SILENCE  ] You are silenced.\n\r"
	    : ""
	    , ch );

	send_to_char( !IS_SET(ch->act, PLR_NO_EMOTE)
	    ? ""
	    : "[-emote    ] You can't emote.\n\r"
	    , ch );

	send_to_char( !IS_SET(ch->act, PLR_NO_TELL)
	    ? ""
	    : "[-tell     ] You can't use 'tell'.\n\r"
	    , ch );
    }
    else
    {
	bool fSet;
	int bit;

	     if ( arg[0] == '+' ) fSet = TRUE;
	else if ( arg[0] == '-' ) fSet = FALSE;
	else
	{
	    send_to_char( "Config -option or +option?\n\r", ch );
	    return;
	}

	     if ( !str_cmp( arg+1, "autoexit" ) ) bit = PLR_AUTOEXIT;
	else if ( !str_cmp( arg+1, "autoloot" ) ) bit = PLR_AUTOLOOT;
	else if ( !str_cmp( arg+1, "autosac"  ) ) bit = PLR_AUTOSAC;
	else if ( !str_cmp( arg+1, "blank"    ) ) bit = PLR_BLANK;
	else if ( !str_cmp( arg+1, "brief"    ) ) bit = PLR_BRIEF;
	else if ( !str_cmp( arg+1, "combine"  ) ) bit = PLR_COMBINE;
	else if ( !str_cmp( arg+1, "prompt"   ) ) bit = PLR_PROMPT;
	else if ( !str_cmp( arg+1, "telnetga" ) ) bit = PLR_TELNET_GA;
	else if ( !str_cmp( arg+1, "nosummon" ) ) bit = PLR_NOSUMMON;
	else if ( !str_cmp( arg+1, "novisit"  ) ) bit = PLR_NOVISIT;
	else if ( !str_cmp( arg+1, "colour"   ) ) bit = PLR_COLOUR;
	else
	{
	    send_to_char( "Config which option?\n\r", ch );
	    return;
	}

	if ( fSet )
	    SET_BIT    (ch->act, bit);
	else
	    REMOVE_BIT (ch->act, bit);

	send_to_char( "Ok.\n\r", ch );
    }

    return;
}

void do_wizlist ( CHAR_DATA *ch, char *argument )
{

    do_help ( ch, "wizlist" );
    return;

}

void do_race_list ( CHAR_DATA *ch, char *argument )
{
   int          iRace;
   char         buf[MAX_STRING_LENGTH];
    
   send_to_char( "    Here follows a list of current races within ACK! Mud:\n\r", ch );
   send_to_char( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r", ch );
   send_to_char( "\n\r", ch );
   if ( IS_IMMORTAL( ch ) )
      send_to_char( "    No.   Room.    Abbr.    Name.   M/C   Classes: (Good->Bad)\n\r", ch );
   else
      send_to_char( "   Abbr.    Name.  M/C  Classes: (Good->Bad)\n\r", ch );
   
   for ( iRace = 0; iRace < MAX_RACE; iRace++ )
   {
      if ( IS_IMMORTAL( ch ) )
      sprintf( buf, "   %3d   %5d    %5s     %8s %2d %s\n\r", 
	 iRace, race_table[iRace].recall,
	 race_table[iRace].race_name,  race_table[iRace].race_title,
	 race_table[iRace].classes, race_table[iRace].comment );

      else      
	 sprintf( buf, "   %5s    %8s    %2d %s\n\r",  
	 race_table[iRace].race_name,  race_table[iRace].race_title,
	 race_table[iRace].classes, race_table[iRace].comment );

      send_to_char( buf, ch );
   }
   send_to_char( "\n\r", ch );
   send_to_char( "M/C = Number of classes available.\n\r", ch );
   send_to_char( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r", ch );
   return;
}

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

   send_to_char( "\n\r    Here follows a list of current clans for " mudnamecolor ":\n\r", ch );
   send_to_char( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r", ch );
   send_to_char( "\n\r", ch );
   if ( IS_IMMORTAL( ch ) )
      send_to_char( "    No.   Room.   Abbr.     Leader    Name.\n\r", ch );
   else
      send_to_char( "   Abbr.          Leader     Name.\n\r", ch );

   for ( iClan = 0; iClan < MAX_CLAN; iClan++ )
   {
      if ( !IS_IMMORTAL(ch) && iClan == 0 )
	continue;       /* Don't list 'none' as a clan :) */
      if ( IS_IMMORTAL( ch ) )
      sprintf( buf, "   %3d   %5d    %s  %12s  %s\n\r", 
	 iClan, clan_table[iClan].clan_room,  clan_table[iClan].clan_abbr,  
	 clan_table[iClan].leader, clan_table[iClan].clan_name );
      else      
	 sprintf( buf, "   %s    %12s  %s\n\r",  
	 clan_table[iClan].clan_abbr, clan_table[iClan].leader, 
	 clan_table[iClan].clan_name  );

      send_to_char( buf, ch );
   }
   send_to_char( "\n\r", ch );
   send_to_char( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r", ch );
   return;
}

void do_spells ( CHAR_DATA *ch, char *argument )
{
    char buf [MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH];
    int sn;
    int col;
    int cnt;
    bool ok;
    buf[0] = '\0';
    
   /* if ( ( !IS_NPC( ch ) &&
	   !class_table[ch->class].fMana )
    ||  IS_NPC ( ch ) )
    */
    if ( IS_NPC( ch ) )
    {  
       send_to_char ( "You do not know how to cast spells!\n\r", ch );
       return;
    }

    buf1[0] = '\0';

    col = 0;
    for ( sn = 0; sn < MAX_SKILL; sn++ )
    {
	ok = FALSE;
	
	if ( skill_table[sn].name == NULL )
	   break;
	for ( cnt = 0; cnt < MAX_CLASS; cnt ++ )
	   if  ( ( ch->lvl[cnt] >= skill_table[sn].skill_level[cnt] )
	       && ( skill_table[sn].skill_level[cnt] < LEVEL_HERO ) )
	      ok = TRUE;
	
	if ( ch->pcdata->learned[sn] == 0 )
	   continue;
	
	if ( skill_table[sn].slot == 0 )
	   continue;
	   
	/*
	if ( skill_table[sn].skill_level[ch->class] > LEVEL_HERO ) 
	   continue; */

	sprintf ( buf, "%18s %3dpts ",
	   skill_table[sn].name, mana_cost( ch, sn ) );
	safe_strcat(MAX_STRING_LENGTH, buf1, buf );
	if ( ++col % 3 == 0 )
	   safe_strcat(MAX_STRING_LENGTH, buf1, "\n\r" );
    }

    if ( col % 3 != 0 )
      safe_strcat(MAX_STRING_LENGTH, buf1, "\n\r" );

    send_to_char ( buf1, ch );
    return;

}

void do_slist ( CHAR_DATA *ch, char *argument )
{
    char buf [MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH];
    int class;
    int foo;
    int sn;
    int col;
    int level;
    bool pSpell;
    bool any;
    bool remort_class;
    bool adept_class;
    buf[0] = '\0';
    buf1[0] = '\0';
    

    if ( IS_NPC ( ch ) )
    {  
       send_to_char ( "You do not need any stinking spells!\n\r", ch );
       return;
    }

    if ( argument[0] == '\0' )
    {
       send_to_char( "USAGE:  <abbrev>.  abbrev = 3-letter class abreviation.\n\r", ch );
       return;
    }

   any = FALSE;  class=-1; remort_class = FALSE; adept_class = FALSE;
   for ( foo = 0; foo <  MAX_CLASS ; foo++ )
      if ( !str_cmp( class_table[foo].who_name, argument ) )
      {
	 any = TRUE; class = foo;
       
      }
      else if ( !str_cmp( remort_table[foo].who_name, argument ) )
      {
	 any = TRUE; class = foo;
       remort_class = TRUE;
      }
      else if ( !str_prefix( "ADEPT", argument ) )
      {
	any = TRUE; adept_class = TRUE; class = 0;
      }
    
   if ( !any ) 
   {
      send_to_char( "That abbreviation not recognized!\n\r", ch );
      return;
   }
    
    buf1[0] = '\0';

    safe_strcat ( MAX_STRING_LENGTH, buf1, "ALL Spells available for the class " );
     if ( adept_class )
     {
       safe_strcat ( MAX_STRING_LENGTH, buf1, "@@W" );
       safe_strcat (MAX_STRING_LENGTH, buf1, "Adept" );
       safe_strcat (MAX_STRING_LENGTH, buf1, "@@N\n\r\n\r" );
     }
     else

     if ( remort_class )
     {
       safe_strcat ( MAX_STRING_LENGTH, buf1, "@@m" );
       safe_strcat (MAX_STRING_LENGTH, buf1, remort_table[class].class_name );
       safe_strcat (MAX_STRING_LENGTH, buf1, "@@N\n\r\n\r" );
     }
     else

     {
       safe_strcat ( MAX_STRING_LENGTH, buf1, "@@b" );
       safe_strcat (MAX_STRING_LENGTH, buf1, class_table[class].class_name );
       safe_strcat (MAX_STRING_LENGTH, buf1, "@@N\n\r\n\r" );
     }


    safe_strcat ( MAX_STRING_LENGTH, buf1, "@@rLv          @@lSpells@@N\n\r\n\r" );

    for ( level = 1; level < LEVEL_IMMORTAL; level++ )
    {

      col = 0;
      pSpell = TRUE;

      for ( sn = 0; sn < MAX_SKILL; sn++ )
      {
	  if ( skill_table[sn].name == NULL )
	    break;
	    if ( ( skill_table[sn].skill_level[class] != level )
	      || ( skill_table[sn].flag2 == VAMP ) 
              || ( skill_table[sn].flag2 == WOLF ) )
	    continue;
	if ( ( adept_class )
	     && ( skill_table[sn].flag1 == ADEPT ) )
	{
	    
	    if (pSpell)
	    {
	 
	      sprintf ( buf, "@@r%2d:@@N", level );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	      pSpell = FALSE;
	    }

	    if ( ++col % 5 == 0 )
	      safe_strcat ( MAX_STRING_LENGTH, buf1, "   " );
	  if ( ch->pcdata->learned[sn] > 0 )
	  {
	      sprintf ( buf, "@@x@@m%18s@@N", skill_table[sn].name );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	  }
	  else
	  {
	      sprintf ( buf, "@@a%18s@@N", skill_table[sn].name );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	  }
	    if ( col % 4 == 0 )
	      safe_strcat ( MAX_STRING_LENGTH, buf1, "\n\r" );
	}
	else 
	if (  ( remort_class )
	   && ( !adept_class )
	   && ( skill_table[sn].flag1 == REMORT ) )
	{
	    
	    if (pSpell)
	    {
	 
	      sprintf ( buf, "@@r%2d:@@N", level );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	      pSpell = FALSE;
	    }

	    if ( ++col % 5 == 0 )
	      safe_strcat ( MAX_STRING_LENGTH, buf1, "   " );
	  if ( ch->pcdata->learned[sn] > 0 )
	  {
	      sprintf ( buf, "@@x@@m%18s@@N", skill_table[sn].name );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	  }
	  else
	  {
	      sprintf ( buf, "@@a%18s@@N", skill_table[sn].name );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	  }
	    if ( col % 4 == 0 )
	      safe_strcat ( MAX_STRING_LENGTH, buf1, "\n\r" );
	}
	else if (  ( !remort_class )
		&& ( !adept_class )
		&& ( skill_table[sn].flag1 == MORTAL ) )
	{
	  if (pSpell)
	    {
	      sprintf ( buf, "@@r%2d:@@N", level );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	      pSpell = FALSE;
	    }

	    if ( ++col % 5 == 0 )
	      safe_strcat ( MAX_STRING_LENGTH, buf1, "   " );

	  
	  if ( ch->pcdata->learned[sn] > 0 )
	  {
	      sprintf ( buf, "@@x@@m%18s@@N", skill_table[sn].name );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	  }
	  else
	  {
	      sprintf ( buf, "@@a%18s@@N", skill_table[sn].name );
	      safe_strcat ( MAX_STRING_LENGTH, buf1, buf );
	  }
	    if ( col % 4 == 0 )
	      safe_strcat ( MAX_STRING_LENGTH, buf1, "\n\r" );

	}
      }

      if ( col % 4 != 0 )
	safe_strcat ( MAX_STRING_LENGTH, buf1, "\n\r" );

    }

    send_to_char( buf1, ch );
    return;

}

/* by passing the conf command - Kahn */

void do_autoexit ( CHAR_DATA *ch, char *argument )
{

    ( IS_SET ( ch->act, PLR_AUTOEXIT )
     ? do_config( ch, "-autoexit" )
     : do_config( ch, "+autoexit" ) );

}

void do_autoloot ( CHAR_DATA *ch, char *argument )
{

    ( IS_SET ( ch->act, PLR_AUTOLOOT )
     ? do_config( ch, "-autoloot" )
     : do_config( ch, "+autoloot" ) );

}

void do_autosac ( CHAR_DATA *ch, char *argument )
{

    ( IS_SET ( ch->act, PLR_AUTOSAC )
     ? do_config( ch, "-autosac" )
     : do_config( ch, "+autosac" ) );

}

void do_blank ( CHAR_DATA *ch, char *argument )
{

    ( IS_SET ( ch->act, PLR_BLANK )
     ? do_config( ch, "-blank" )
     : do_config( ch, "+blank" ) );

}

void do_brief ( CHAR_DATA *ch, char *argument )
{

    ( IS_SET ( ch->act, PLR_BRIEF )
     ? do_config( ch, "-brief" )
     : do_config( ch, "+brief" ) );

}

void do_combine ( CHAR_DATA *ch, char *argument )
{

    ( IS_SET ( ch->act, PLR_COMBINE )
     ? do_config( ch, "-combine" )
     : do_config( ch, "+combine" ) );

}
 
void do_pagelen ( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int lines;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
	lines = 20;
    else
	lines = atoi( arg );

    if ( lines < 1 )
    {
	send_to_char(
		"Negative or Zero values for a page pause is not legal.\n\r",
		     ch );
	return;
    }

    ch->pcdata->pagelen = lines;
    sprintf( buf, "Page pause set to %d lines.\n\r", lines );
    send_to_char( buf, ch );
    return;
}

/* Do_prompt from Morgenes from Aldara Mud */
void do_prompt( CHAR_DATA *ch, char *argument )
{
   char buf[MAX_STRING_LENGTH];
    buf[0] = '\0';

   if ( argument[0] == '\0' )
   {
       ( IS_SET ( ch->act, PLR_PROMPT )
	? do_config( ch, "-prompt" )
	: do_config( ch, "+prompt" ) );
       return;
   }

   if( !strcmp( argument, "all" ) )
      strcpy( buf, "<%hhp %mm %vmv> ");
   else
   {
      if ( strlen(argument) > 200 )
	 argument[200] = '\0';
      strcpy( buf, argument );
      smash_tilde( buf );
   }

   free_string( ch->prompt );
   ch->prompt = str_dup( buf );
   send_to_char( "Ok.\n\r", ch );
   return;
} 

void do_auto( CHAR_DATA *ch, char *argument )
{

    do_config( ch, "" );
    return;

}


void do_players( CHAR_DATA *ch, char *argument )
{
    
    send_to_char( "This command is no longer needed, as 'WHO' carries all details.\n\r", ch );
    return;
}

void do_diagnose( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int pct;

    
    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Diagnose 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 ( can_see( victim, ch ) )
    {
	act( "$n gives you the once-over.", ch, NULL, victim, TO_VICT    );
	act( "$n gives $N the once-over.",  ch, NULL, victim, TO_NOTVICT );
    }
    else
    {
	send_to_char( "They're not here.\n\r", ch );
	return;
    }
    
    if ( victim->max_hit > 0 )
	pct = ( 100 * victim->hit ) / victim->max_hit;
    else
	pct = -1;

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

	 if ( pct >= 100 ) safe_strcat(MAX_STRING_LENGTH, buf, " --  [5] 4  3  2  1   \n\r" );
    else if ( pct >=  80 ) safe_strcat(MAX_STRING_LENGTH, buf, " --   5 [4] 3  2  1   \n\r" );
    else if ( pct >=  60 ) safe_strcat(MAX_STRING_LENGTH, buf, " --   5  4 [3] 2  1   \n\r" );
    else if ( pct >=  40 ) safe_strcat(MAX_STRING_LENGTH, buf, " --   5  4  3 [2] 1   \n\r" );
    else                   safe_strcat(MAX_STRING_LENGTH, buf, " --   5  4  3  2 [1]  \n\r" );
    
    buf[0] = UPPER(buf[0]);
    send_to_char( buf, ch );


    return;
}




void do_heal( CHAR_DATA *ch, char *argument )
{
   /* This function used when a player types heal when in a room with
    * a mob with ACT_HEAL set.  Cost is based on the ch's level.
    * -- Stephen
    */

    CHAR_DATA *mob;
    char buf[MAX_STRING_LENGTH];
    int mult;           /* Multiplier used to calculate costs. */
    buf[0] = '\0';

    /* Check for mob with act->heal */
   for ( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
   {
      if ( IS_NPC(mob) && IS_SET(mob->act, ACT_HEAL) )
	 break;
   }
 
   if ( mob == NULL )
   {
      send_to_char( "You can't do that here.\n\r", ch );
	 return;
   }

   mult = UMAX( 10, ch->level/2 );

   if ( argument[0] == '\0' )
   {
      /* Work out costs of different spells. */
      send_to_char( "Costs for spells:\n\r", ch );
      sprintf( buf, "Sanctuary:          %7d GP.\n\r", (mult*100)  ); 
      send_to_char( buf, ch );
      sprintf( buf, "Heal:               %7d GP.\n\r", (mult*90)  );
      send_to_char( buf, ch );
      sprintf( buf, "Invisibilty:        %7d GP.\n\r", (mult*20)  );
      send_to_char( buf, ch );
      sprintf( buf, "Detect Invisibilty: %7d GP.\n\r", (mult*10)   );
      send_to_char( buf, ch );
      sprintf( buf, "Refresh:            %7d GP.\n\r", (mult*10)   );
      send_to_char( buf, ch );
      sprintf( buf, "Night Vision:       %7d GP.\n\r", (mult*20)  );
      send_to_char( buf, ch );
      sprintf( buf, "Magical Dispel:     %7d GP.\n\r", (mult*200)  );
      send_to_char( buf, ch );
      send_to_char( "Power (50 Mana)     10000   GP.\n\r", ch );
      send_to_char( "Type HEAL [S|H|I|D|R|N|M|P]\n\r", ch );
      send_to_char( "Eg: 'HEAL H' will result in the heal spell being cast.\n\r", ch );
      send_to_char( "\n\r**ALL** Spells will be cast on the buyer ONLY.\n\r", ch );
      return;
   }

   switch ( UPPER( argument[0] ) )
   {
      case 'S':                                /* Sanc */
	 if ( ch->gold < ( mult * 100 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 spell_sanctuary( skill_lookup( "sanc" ), mult, ch, ch, NULL );
	 ch->gold -= ( mult * 100 );
	 break;
      case 'P':                                 /* mana */
	 if ( ch->gold < 5000 )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 ch->gold -= 5000;
	 ch->mana = UMIN( ch->max_mana, ch->mana + 50 );
	 break;
      
      case 'H':                                 /* Heal */
	 if ( ch->gold < ( mult * 90 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 spell_heal( skill_lookup( "heal" ), mult, mob, ch, NULL );
	 ch->gold -= ( mult * 90 );
	 break;
      case 'I':                                 /* invis */
	 if ( ch->gold < ( mult * 20 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 spell_invis( skill_lookup( "invis" ), mult, mob, ch, NULL );
	 ch->gold -= ( mult * 20 );
	 break;
      case 'D':                                 /* detect invis */
	 if ( ch->gold < ( mult * 10 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 spell_detect_invis( skill_lookup( "detect invis" ), mult, mob, ch, NULL );        
	 ch->gold -= ( mult * 10 );
	 break;
      case 'R':                                 /* refresh */
	 if ( ch->gold < ( mult * 10 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 spell_refresh( skill_lookup( "refresh" ), mult, mob, ch, NULL );      
	 ch->gold -= ( mult * 10 ); 
	 break;      
      case 'N':                                 /* Infra */
	 if ( ch->gold < ( mult * 20 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 act( "$N gestures towards $n.", ch, NULL, mob, TO_NOTVICT );
	 act( "$N gestures towards you.", ch, NULL, mob, TO_CHAR );
	 spell_infravision( skill_lookup( "infra" ), mult, ch, ch, NULL );
	 ch->gold -= ( mult * 20 );
	 break;
      case 'M':                                 /* dispel */   
	 if ( ch->gold < ( mult * 200 ) )
	 {
	    send_to_char( "You don't have that much gold right now...\n\r", ch );
	    return;
	 }
	 /* No acts, as they are in spell_dispel_magic.  Doh. */
	 spell_dispel_magic( skill_lookup( "dispel magic" ), mult*5, mob, ch, NULL );
	 ch->gold -= ( mult * 200 );
	 break;
      default:
	 send_to_char( "Are you sure you're reading the instructions right??\n\r", ch );
	 return;
   }
   return;
}

void do_bank( CHAR_DATA *ch, char *argument )
{
    /* Simple banking system.  Allow ch to check balance, make a 
     * deposit or withdrawl some money.
     * -- Stephen
     */
    
    CHAR_DATA *mob;
    char buf[MAX_STRING_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    buf[0] = '\0';

   if ( IS_NPC( ch ) )
   {
      send_to_char( "Banking Services are only available to players!\n\r", ch );
      return;
   }
  
   /* Check for mob with act->heal */
   for ( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
   {
      if ( IS_NPC(mob) && IS_SET(mob->act, ACT_BANKER ) )
	 break;
   }
 
   if ( mob == NULL )
   {
      send_to_char( "You can't do that here.\n\r", ch );
	 return;
   }

   if ( argument[0] == '\0' )
   {
      send_to_char( "                  BANK : Options:\n\r\n\r", ch );
      send_to_char( "          BANK BALANCE : Displays your balance.\n\r", ch );
      send_to_char( " BANK DEPOSIT <amount> : Deposit gold into your account.\n\r", ch );
      send_to_char( "BANK WITHDRAW <amount> : Withdrawl gold from your account.\n\r", ch );
      return;
   }

   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );
   
   /* Now work out what to do... */

   
   if ( !str_cmp( arg1, "balance" ) )
   {
      sprintf( buf, "Your current balance is: %d GP.  The total amount insured against loss is %d GP.\n\r",
         ch->balance,
         get_psuedo_level( ch ) * 100000 );
      send_to_char( buf, ch );
      return;
   }

   if ( !str_cmp( arg1, "deposit" ) )
   {
      int amount; 
      if ( is_number ( arg2 ) )
      {
	 amount = atoi( arg2 );
	 if ( amount < 0 )
	 return;
	 if (amount > ch->gold )
	 {
	    sprintf( buf, "How can you deposit %d GP when you only have %d?\n\r",
	       amount, ch->gold );
	    send_to_char( buf, ch );
	    return;
	 }

	 ch->gold    -= amount;
	 ch->balance += amount;
	 sprintf ( buf, "You deposit %d GP.  Your new balance is %d GP.\n\r",  
	    amount, ch->balance );
	 send_to_char( buf, ch );
	 do_save( ch, "" );
	 return;
      }
   
   }

   if ( !str_cmp( arg1, "withdraw" ) )
   {
      int amount; 
      if ( is_number ( arg2 ) )
      {
	 amount = atoi( arg2 );
       if ( amount < 0 )
	   return;
	 if ( amount > ch->balance )
	 {
	    sprintf( buf, "How can you withdraw %d GP when your balance is %d?\n\r",
	       amount, ch->balance );
	    send_to_char( buf, ch );
	    return;
	 }
         if ( ch->gold + amount > 100000000 )
         {
           send_to_char( "You can't carry that much gold.\n\r", ch );
           return;
         }
	 ch->balance -= amount;
	 ch->gold    += amount;
	 sprintf( buf, "You withdraw %d GP.  Your new balance is %d GP.\n\r",
	    amount, ch->balance );
	 send_to_char( buf, ch );
	 do_save( ch, "" );
	 return;
      }
   }

   send_to_char( "That option not recognised!\n\r", ch );
   return;
}


void do_gain( CHAR_DATA *ch, char *argument )
{
    /* Allow ch to gain a level in a chosen class.     
     * Only can be done at prac/train mob. -S-
     * Now handles remort chars
     */

    CHAR_DATA *mob;
    char buf[MAX_STRING_LENGTH];
    long_int cost = 0;
    int cnt;
    int subpop;
    bool any;
    int  c;     /* The class to gain in */
    int numclasses;  /* Current number of classes person has*/
    int a;           /* Looping var */   
    bool remort = FALSE;
    bool vamp   = FALSE;
    bool adept  = FALSE;
    bool wolf   = FALSE;
    int vamp_cost = 0;
    sh_int	morts_at_seventy = 0;
    sh_int	remorts_at_seventy = 0;
    sh_int	morts_at_eighty = 0;
    sh_int	remorts_at_eighty = 0;
    sh_int	num_remorts = 0;
    bool	allow_remort = FALSE;
    bool	allow_adept = FALSE;

    buf[0] = '\0';


 

   if ( IS_NPC( ch ) )
   {
      send_to_char( "Hahaha, not for NPCs.\n\r", ch );
      return;
   }
  
   /* Check for mob with act->pac/train */
   for ( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
   {
      if ( IS_NPC(mob) && 
	 ( IS_SET(mob->act, ACT_TRAIN ) || IS_SET( mob->act, ACT_PRACTICE ) ) ) 
	 break;
   }
 
   if ( mob == NULL )
   {
      send_to_char( "You can't do that here.\n\r", ch );
	 return;
   }
      for ( cnt = 0; cnt < MAX_CLASS ; cnt++ )
      {
        if ( ch->lvl[cnt] >= 70 )
          morts_at_seventy++;
        if ( ch->lvl[cnt] == 80 )
          morts_at_eighty++;
        if ( ch->lvl2[cnt] >= 70 )
          remorts_at_seventy++;
        if ( ch->lvl2[cnt] == 80 )
          remorts_at_eighty++;
        if ( ch->lvl2[cnt] > -1 )
          num_remorts++;
      }
/* first case.. remort  */
      if (  (  ( morts_at_seventy >= 2 ) 
            && ( is_remort( ch ) == FALSE ) )
         || (  ( morts_at_eighty == 5 )
            && ( remorts_at_seventy == 1 ) 
            && ( num_remorts == 1 ) )     )
      {
        allow_remort = TRUE;
      }

/* second case..can adept */

      if (  ( morts_at_eighty == 5 )
         && ( remorts_at_eighty == 2 )  
         && ( ch->adept_level < 1 )   )
      {
        allow_adept = TRUE;
      }

   if ( argument[0] == '\0' )
   {

      /* Display details... */
      send_to_char( "You can gain levels in:\n\r", ch );
      any = FALSE;
      numclasses =0;
      for ( a=0; a < MAX_CLASS; a++)
       if ( ch->lvl[a] >= 0 ) numclasses++;
	    
      for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	 if ( (ch->lvl[cnt] != -1 || numclasses < race_table[ch->race].classes )
	      && ch->lvl[cnt] < ( LEVEL_HERO -1 ) )
	 {   
	    any = TRUE;
	    cost = exp_to_level( ch, cnt, (ch->pcdata)->index[cnt] );
	    
	    sprintf( buf, "%s : %d Exp.\n\r", class_table[cnt].who_name, cost );
	    send_to_char( buf, ch );
	 }   
	 
      for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	 if ( ch->lvl2[cnt] != -1 && ch->lvl2[cnt] < ( LEVEL_HERO -1 ) )
	 {
	    any = TRUE;
	    cost = exp_to_level( ch, cnt, 5 );  /* 5 means remort */
	    sprintf( buf, "%s : %d Exp.\n\r", remort_table[cnt].who_name, cost );
	    send_to_char( buf, ch );
	 }
	 if ( ( ch->adept_level > 0 ) && ( ch->adept_level < 20 ) )
       {
	 any = TRUE;
	 cost = exp_to_level_adept( ch );
	 sprintf( buf, "@@WAdept@@N: %d Exp.\n\r", cost );
	 send_to_char( buf, ch );
       }
       if ( allow_remort )
       {
         any = TRUE;
        send_to_char( "You can @@mREMORT@@N!!! Type gain <first three letters of the class> you want.\n\r", ch );
       }
       if ( allow_adept )
       {
         any = TRUE;
         send_to_char( "You can @@WADEPT@@N!!! Type gain adept!!\n\r", ch );
       }
	 if ( any )
	    send_to_char( ".\n\r", ch );
	 else
	    send_to_char( "None.\n\r", ch );
       if (   ( IS_VAMP( ch ) )
	   && ( ch->pcdata->vamp_level < ( MAX_VAMP_LEVEL - ( ch->pcdata->generation / 2 ) ) )    ) 
	 if ( IS_VAMP( ch ) )
	   if ( ch->pcdata->vamp_exp >= exp_to_level_vamp( ch->pcdata->vamp_level ) )
	    send_to_char( "@@NYou may gain a @@dVAMPYRE@@N level!!!\n\r", ch );
       if (  ( IS_WOLF( ch ) )
          && ( ch->pcdata->vamp_level < ( ( MAX_WOLF_LEVEL + 2 ) - ( ch->pcdata->generation * 2 ) )  )   )
         if ( IS_WOLF( ch ) )
	   if ( ch->pcdata->vamp_exp >= exp_to_level_wolf( ch->pcdata->vamp_level ) )
	    send_to_char( "@@NYou may gain a @@bWerewolf@@N level!!!\n\r", ch );

	 return;
   }
   
   /* If an argument supplied, make sure it's valid :P */

   any = FALSE;  c=-1;
   for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
     if ( !str_cmp( class_table[cnt].who_name, argument ) )
     {
	any = TRUE; c = cnt;
     }

   for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
     if (  ( !str_cmp( remort_table[cnt].who_name, argument ) )
        && ( ( ch->lvl2[cnt] > 0 ) || ( allow_remort ) )   )
     {
       any = TRUE; remort = TRUE; c = cnt;
     }
   if ( !str_prefix ( "VAMPYRE", argument ) )
   {
     if ( IS_VAMP( ch ) )
     {
       any = TRUE; vamp = TRUE;
     }
   }

   if ( !str_prefix ( "WEREWOLF", argument ) )
   {
     if ( IS_WOLF( ch ) )
     { 
       any = TRUE;
       wolf = TRUE;
     }

   }

   if ( !str_prefix( "ADEPT", argument ) )
   {
     if ( ( ch->adept_level < 0 ) && !allow_adept )
       return;

     any = TRUE;  adept = TRUE;
   }

   if ( !any )
   {
      send_to_char( "That's not a class!\n\r", ch );
      return;
   }

   /* Ok, so now class should be valid.  Check if enough exp */
   if ( wolf )
     vamp_cost = exp_to_level_wolf( ch->pcdata->vamp_level );
   else if ( vamp )
     vamp_cost = exp_to_level_vamp( ch->pcdata->vamp_level );
   else if ( remort )
      cost = exp_to_level( ch, c, 5 );
   else if ( adept )
   {
     if ( ch->adept_level < 1 )
       cost = 0;
     else
      cost = exp_to_level_adept( ch );
   }
   else
      cost = exp_to_level( ch, c, (ch->pcdata->index[c] ) );

   if ( vamp )
   {
     if ( ch->pcdata->vamp_exp < vamp_cost )
     {
       send_to_char( "@@NYou have not yet mastered your current knowledge of the ways of the @@dKINDRED@@N!!\n\r", ch );
       return;
     }
   }
   else if ( wolf )
   {
     if ( ch->pcdata->vamp_exp < vamp_cost )
     {
       send_to_char( "@@NYour @@rtribe@@N does not consider you worthy!@@N!!\n\r", ch );
       return;
     }
   }

   else if ( ch->exp < cost )
   {
      sprintf( buf, "Cost is %d Exp.  You only have %d (%d short).\n\r", 
	 cost, ch->exp, ( cost - ch->exp ) );
      send_to_char( buf, ch );
      return;
   }

   if ( ( wolf ) && ( ch->pcdata->vamp_level < ( MAX_WOLF_LEVEL - ( ch->pcdata->generation * 2 ) ) ) )
     {
       c = ADVANCE_WOLF;
       send_to_char( "@@NYour @@rTribe@@N increases your standing@@N!!!\n\r", ch );
       ch->pcdata->vamp_exp -= vamp_cost;
       advance_level( ch, c, TRUE, remort );
       ch->pcdata->vamp_level += 1;
       do_save( ch, "" );
       return;
     }
     else if ( wolf )
     { 
       send_to_char( "@@NYour @@rTribe @@Ndenies your request@@N.\n\r", ch );
       return;
     }
 

   if ( ( vamp ) && ( ch->pcdata->vamp_level < ( MAX_VAMP_LEVEL - ( ch->pcdata->generation / 2 ) ) ) )
     {
       c = ADVANCE_VAMP;
       send_to_char( "@@NYou gain more power in the ways of the @@dKindred@@N!!!\n\r", ch );
       ch->pcdata->vamp_exp -= vamp_cost;
       advance_level( ch, c, TRUE, remort );
       ch->pcdata->vamp_level += 1;
       do_save( ch, "" );
       return;
     }
     else if ( vamp )
     { 
       send_to_char( "@@NYou have reached the epitome of Rank in the ways of the @@eKindred@@N.\n\r", ch );
       return;
     }
   if ( ( adept ) && ( ch->adept_level < 20 ) ) 
   {
     c = ADVANCE_ADEPT;
     send_to_char( "@@WYou have reached another step on the stairway to Wisdom!!!@@N\n\r", ch );
     ch->exp -= cost;
     advance_level( ch, c , TRUE, FALSE );
     ch->adept_level = UMAX( 1, ch->adept_level + 1);
     sprintf( buf, "%s @@W advances in the way of the Adept!!\n\r", ch->name );
     info( buf, 1);
     free_string( ch->pcdata->who_name );
     ch->pcdata->who_name = str_dup( get_adept_name( ch ) );
     do_save( ch, "" );
     if ( ch->adept_level == 1 )
       ch->exp /= 1000;
     return;
   }
   else if ( adept )
   { 
     send_to_char( "@@aYou peer down upon all the hapless mortals, knowing that you have reached the final step upon the stairway of Wisdom.@@N\n\r", ch );
     return;
   }
   /* Don't bother adapting for remort... dropped num classes yrs ago! */
   if (ch->lvl[c] < 0)
   {
    /* Check to see if max. num of classes has been reached. */
    numclasses=0;
    
    for ( a=0; a < MAX_CLASS; a++)
     if (ch->lvl[a] >= 0) numclasses++;
    
    if ( numclasses >= race_table[ch->race].classes )
    {
     /* Already got max. number of classes */
     send_to_char( "Cannot level in that class, already have maximum number of classes.\n\r",ch);
     return;
    }
    
    ch->lvl[c] = 0;
   }
    
   /* Ok,ok now we know ch has enough exps.  Do the advancement stuff */

   if ( ( remort ? ch->lvl2[c] : ch->lvl[c] ) + 1 >= LEVEL_HERO )
   {
      send_to_char( "If you wish to advance this class, please ask an Immortal.\n\r", ch );
      return;
   }    
   /* Check to see if able to reach new level */
   if ( remort )
      sprintf( buf, "You gain a %s level!\n\r", remort_table[c].class_name );
   else
      sprintf( buf, "You gain a %s level!\n\r", class_table[c].class_name );
   send_to_char( buf, ch );

   /* Use info channel to inform of level gained! */
   
   if ( remort )
      sprintf( buf, "%s advances in the way of the %s.", ch->name, remort_table[c].class_name );
   else   
      sprintf( buf, "%s advances in the way of the %s.", ch->name, class_table[c].class_name );
   info( buf, 1 );

   ch->exp -= cost;
   
   advance_level( ch, c, TRUE, remort );
   if ( remort )
      ch->lvl2[c] = UMAX( 1, ch->lvl2[c] + 1);
   else
      ch->lvl[c] += 1;     /* Incr. the right class */

   
   /* Maintain ch->level as max level of the lot */
   for ( subpop = 0; subpop < MAX_CLASS; subpop++ )
   {
      if ( ch->lvl[subpop] > ch->level )
	 ch->level = ch->lvl[subpop];
      if ( ch->lvl2[subpop] > ch->level )
	 ch->level = ch->lvl2[subpop];
   }
   do_save( ch, "" );
   return;
}


void do_assassinate( CHAR_DATA *ch, char *argument )
{
   char buf[MAX_STRING_LENGTH];
   int  cost;
   CHAR_DATA *mob;
   CHAR_DATA *victim;
    buf[0] = '\0';


     /* Check for mob with act->merc */
   for ( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
   {
      if ( IS_NPC(mob) && 
	 ( IS_SET(mob->act, ACT_MERCENARY ) ) ) 
	 break;
   }
 
   if ( mob == NULL )
   {
      send_to_char( "There doesn't seem to be a mercenary around!\n\r", ch );
      return;
   }

   if ( mob->hunting != NULL || mob->hunt_obj != NULL )
   {
	act( "$N looks to be busy already!", ch, NULL, mob, TO_CHAR );
	return;
   }
   
   cost = ( mob->level * 10000 );

   if ( argument[0] == '\0' )
   {
       sprintf( buf, "$N tells you, 'The cost is %d GP.'", cost );
       act( buf, ch, NULL, mob, TO_CHAR );
       return;
   }

   if ( (victim = get_char_world( ch, argument ) ) == NULL )
   {
      act( "$N tells you, 'I can't locate the victim.  Sorry.'", ch, NULL, mob, TO_CHAR );
       return;
   }

   if ( victim == ch )
     return;


   if ( IS_NPC(victim) )
   {
      act( "$N tells you, 'I only go after REAL players, they're more fun!`",
	    ch, NULL, mob, TO_CHAR );
      return;
    }

   if ( victim->level < 12 )
   {
      act( "$N tells you, 'I'm not interested in small fry.'", ch, NULL, mob, TO_CHAR );
      return;
   }  


   if ( ch->gold < cost )
   {
       act( "$N tells you, 'You can't afford my services!'", ch, NULL, mob, TO_CHAR );
       return;
    }

   
   if ( !set_hunt(mob, ch, victim, NULL, HUNT_WORLD|HUNT_MERC,
					 HUNT_INFORM|HUNT_CR) )
   {
     act( "$N tells you, 'I can't seem to find the target!'", ch, NULL, mob,
	  TO_CHAR );
     return;
   }
/*   if ( !make_hunt( mob, victim ) )
   {
      act( "$N tells you, 'I can't seem to find the target!'", ch, NULL, mob, TO_CHAR );
      return;
   }*/
   

    ch->gold -= cost;
    act( "$n gives $N some gold coins.", ch, NULL, mob, TO_NOTVICT );
    act( "$n says '$N shall die by my hand!`", mob, NULL, victim, TO_ROOM );
    sprintf( buf, "%s employs the services of %s to assassinate %s!!",
	     ch->name, mob->short_descr, victim->name );
    info( buf, 1 );
   return;
}


void do_alias( CHAR_DATA *ch, char *argument )
{
  /* Handle aliases - setting and clearing, as well as listing. */
  
  int cnt;
  int alias_no;
  char buf[MAX_STRING_LENGTH];
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];

    buf[0] = '\0';

  
  if ( IS_NPC( ch ) )
  {
     send_to_char( "Not a chance!\n\r", ch );
     return;
  }
  smash_tilde( argument );
  if ( argument[0] == '\0' )
  {
     send_to_char( "Defined Aliases:\n\r", ch );
     
     for ( cnt = 0; cnt < MAX_ALIASES; cnt++ )
     {
	sprintf( buf, "(%d) [Name:] %12s  [Aliases:] %s\n\r", cnt,
		 ch->pcdata->alias_name[cnt],
		 ch->pcdata->alias[cnt] );
	send_to_char( buf, ch );
     }
     send_to_char( "\n\rTo Set an Alias:\n\r", ch );
     send_to_char( "ALIAS <num> <name> <alias>\n\r", ch );
     send_to_char( "-enter 'CLEAR' as name to clear an alias.\n\r", ch );
     return;
  }
  
   argument=one_argument( argument, arg1 );   /* Number */
   argument=one_argument( argument, arg2 );   /* name   */
   strcpy( arg3, argument );                  /* alias  */

   if ( arg3[0] == '\0' && str_cmp( arg2, "clear" ) )
   {
     send_to_char( "\n\rTo Set an Alias:\n\r", ch );
     send_to_char( "ALIAS <num> <name> <alias>\n\r", ch );
     send_to_char( "-enter 'CLEAR' as name to clear an alias.\n\r", ch );
     return;
   } 

   if ( !is_number( arg1 ) )
   {
      send_to_char( "First argument must be an integer.\n\r", ch );
      return;
   }
   else
      alias_no = atoi( arg1 );
      
   if ( alias_no < 0 || alias_no > (MAX_ALIASES - 1) )
   {
      sprintf( buf, "Valid alias numbers are 0 to %d.\n\r", MAX_ALIASES );
      send_to_char( buf, ch );
      return;
   }
   
   if ( !str_cmp( "clear", arg2 ) )
   {
      free_string( ch->pcdata->alias_name[alias_no] );
      free_string( ch->pcdata->alias[alias_no] );
   
      ch->pcdata->alias_name[alias_no] = str_dup( "<none>" );   
      ch->pcdata->alias[alias_no]      = str_dup( "<none>" );    

      /* Clear the alias (enter <none> for name and alias */
      return;
   }
   
   /* Hopefully, now just set the (new) alias... */
   
   free_string( ch->pcdata->alias_name[alias_no] );
   free_string( ch->pcdata->alias[alias_no] );
   
   ch->pcdata->alias_name[alias_no] = str_dup( arg2 );   
   ch->pcdata->alias[alias_no]      = str_dup( arg3 );    
   return;
}
  

void do_colour( CHAR_DATA *ch, char *argument )
{
   /* Allow users to set which colour they get certain texts in. -S- */
   
   char  buf[MAX_STRING_LENGTH];
   char arg1[MAX_STRING_LENGTH];
   char arg2[MAX_STRING_LENGTH];
   int   col;
   int   cnt;
   int   ansi_number;
   int   colour_number;
    buf[0] = '\0';

      
   if ( IS_NPC(ch) )
      return;
   
   /* First check to see if there is NO argument.  If so, display
    * the current settings for players colour. 
    * In this context, 'colour' means the type of text, eg "say" or "shout"
    *                  'ansi'   means the actual colour
    *                  ->Confusing, right?
    * -S-
    */
    
   if ( IS_NPC( ch ) )
      return;
   col = 0;

   if ( argument[0] == '\0' )
   {
      send_to_char( "@@yPresent Colour Configuration:@@g\n\r\n\r", ch );
      
      for ( cnt = 0; cnt < MAX_COLOUR; cnt++ )
      {
	 sprintf( buf, "@@W%8s: %s%-12s@@N   ",
		  colour_table[cnt].name,
		  ansi_table[ch->pcdata->colour[cnt]].value,
		  ansi_table[ch->pcdata->colour[cnt]].name );
	 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 );
 
      send_to_char( "\n\r@@yAvailable Colours:@@g\n\r", ch );
 
      col = 0;
      
      for ( cnt = 0; cnt < MAX_ANSI; cnt++ )
      {
	 sprintf( buf, "%s%-12s@@N  ", 
	    IS_SET(ch->act, PLR_COLOUR) ? ansi_table[cnt].value : "",
	    ansi_table[cnt].name );
	 send_to_char( buf, ch );
	 if ( ++col % 5 == 0 )
	    send_to_char( "\n\r", ch );
      }
      if ( col % 5 != 0 )
	 send_to_char( "\n\r", ch );
	 
      send_to_char( "\n\rUSAGE: COLOUR <name> <colour>\n\r", ch );
      send_to_char( "Eg:     COLOUR say red\n\r", ch );
      send_to_char( "OR: COLOUR highlighted/dimmed <colour> for emphasized or dimmed text.\n\r", ch );

      send_to_char( "NOTE: The 'stats' info covers who, score, etc.\n\r", ch );
      return;
   }
   
   argument = one_argument( argument, arg1 );  /* The name, eg 'say'   */
   argument = one_argument( argument, arg2 );  /* The colour, eg 'red' */
   
   if ( arg2[0] == '\0' )
   {
      do_colour( ch, "" );              /* Generate message */
      return;
   }
   if ( !str_prefix( arg1, "highlighted" ) )
     colour_number = -2;
   else if ( !str_prefix( arg1, "dimmed" ) )
     colour_number = -3;
   else
   {
      /* Check to see if the name is valid */
     colour_number = -1;
     for ( cnt = 0; cnt < MAX_COLOUR; cnt++ )
       if ( !str_cmp( arg1, colour_table[cnt].name ) )
	colour_number = colour_table[cnt].index;
   }
	
   if ( colour_number == -1 )
   {
      /* list possible choices */
      /* do_colour( ch, "help" ); */
      return;
   }
   
   /* colour (the name) is ok.  Now find the ansi (the colour) */
   ansi_number = -1;
   for ( cnt = 0; cnt < MAX_ANSI; cnt++ )
      if ( !str_cmp( arg2, ansi_table[cnt].name ) )
	 ansi_number = ansi_table[cnt].index;
	 
   if ( ansi_number == -1 )
   {
      /* list possible choice */
      /* do_colour( ch, "help" ); */
      return;
   }
   
   /* Ok now, we have colour_number, which is the index to pcdata->colour[]
    * so we need to set the value of it to the colour.  
    * -S-
    */
    

    if ( colour_number == -2 )
    {
      ch->pcdata->hicol = ansi_table[ansi_number].letter;
      return;
    }
    else
    if ( colour_number == -3 )
    {
      ch->pcdata->dimcol = ansi_table[ansi_number].letter;
      return;
    }

    ch->pcdata->colour[colour_number] = ansi_number;
    send_to_char( "OK.\n\r", ch );
    return;
}

/* A simple, return the char sequence, function -S- */

char * colour_string( CHAR_DATA *ch, char *argument )
{
   int cnt;
   int num;
   
   
   /* if we don't want to send the string, return "" */
   /* argument should be the string to find, eg "say" */
   
   if ( IS_NPC( ch ) || argument[0] == '\0' )
      return( "" );
   
   if ( !IS_SET( ch->act, PLR_COLOUR ) )
      return( "" );
      
   if ( !str_cmp( argument, "normal" ) )
      return( "\x1b[0m" );
   
   /* By here, ch is a PC and wants colour */
   
   num = -1;
   for ( cnt = 0; cnt < MAX_COLOUR; cnt ++ )
     if ( !str_cmp( argument, colour_table[cnt].name ) )
	num = cnt;
	
   if ( num == -1 ) /* bug report? */
   
      return( "" );
   
   return( ansi_table[ch->pcdata->colour[num]].value );

} 

void do_worth( CHAR_DATA *ch, char *argument )
{
	/* Show details regarding cost to level each class, etc */

    bool any;
    char buf[MAX_STRING_LENGTH];        
    int numclasses;
    int a;
    long_int cost;
    int cnt;

    if ( IS_NPC( ch ) )
    {
	send_to_char( "Only for PCs.\n\r", ch );
	return;
    }
	
    send_to_char( "Costs in Exp for you to level:\n\r", ch );
    send_to_char( "Cost is shown first, followed by how much more exp you need.\n\r\n\r", ch );
    send_to_char( "CLASS NAME:        COST:    DIFFERENCE:\n\r\n\r", ch );

    if ( ch->adept_level > 0 )
    {
      
      cost = exp_to_level_adept( ch );
      sprintf( buf," %-14s  %9d %9d.\n\r", get_adept_name( ch ), cost, UMAX( 0, cost-ch->exp) );
      send_to_char( buf, ch );
      return;
    }

      any = FALSE;
      numclasses =0;
      for ( a=0; a < MAX_CLASS; a++)
       if ( ch->lvl[a] >= 0 ) numclasses++;
	    
      for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	 if ( (ch->lvl[cnt] != -1 || numclasses < race_table[ch->race].classes )
	      && ch->lvl[cnt] < LEVEL_HERO -1 )
	 {   
	    any = TRUE;
	    cost  = exp_to_level( ch, cnt, (ch->pcdata)->index[cnt] );
	    
	    
	    sprintf( buf, "%-14s  %9d %9d.\n\r", class_table[cnt].who_name, 
		     cost, UMAX( 0, cost-ch->exp) );
	    send_to_char( buf, ch );
	 }   
	 
      /* Check for remort classes */
      for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
	 if ( ch->lvl2[cnt] != -1 && ch->lvl2[cnt] < LEVEL_HERO - 1 )
	 {
	    any = TRUE;
	    cost = exp_to_level( ch, cnt, 5 );  /* Pass 5 for remort */
	    sprintf( buf, "%-14s  %9d %9d.\n\r", remort_table[cnt].who_name,
		     cost, UMAX( 0, cost- ch->exp ) );
	    send_to_char( buf, ch );
	 }
	 
	 if ( any )
	    send_to_char( "\n\r", ch );
	 else
	    send_to_char( "None to show!!\n\r", ch );

	 return;
   }
 
void do_whois( CHAR_DATA *ch, char *argument )
{
   /* Show ch some details about the 'victim'
    * Make sure ch can see victim!
    * -S-
    */

   CHAR_DATA *victim;
   char buf[MAX_STRING_LENGTH];

   if ( ( victim = get_char_world( ch, argument ) ) == NULL )
   {
      send_to_char( "No such player found.\n\r", ch );
      return;
   }
 
   if ( !can_see( ch, victim ) )
   {
      send_to_char( "No such player found.\n\r", ch );
      return;
   }

   if ( IS_NPC( victim ) )
   {
      send_to_char( "Not on NPCs.\n\r", ch );
      return;
   }

   /* Ok, so now show the details! */
   sprintf( buf, "-=-=-=-=-=-=-=-=-=-=- %9s -=-=-=-=-=-=-=-=-=-=-\n\r", victim->name );
   if ( IS_IMMORTAL( victim ) )
   {
      sprintf( buf+strlen(buf), " [ %3s ]\n\r", victim->pcdata->who_name );
   }
   else if ( victim->adept_level > 0 )
   {
     sprintf( buf+strlen(buf), " %s \n\r", get_adept_name( victim ) );
   }
   else
   {
   sprintf( buf+strlen(buf), "Levels: [ Mag:%2d  Cle:%2d  Thi:%2d  War:%2d  Psi:%2d ]\n\r",
      victim->lvl[0] > 0 ? victim->lvl[0] : 0,
      victim->lvl[1] > 0 ? victim->lvl[1] : 0,
      victim->lvl[2] > 0 ? victim->lvl[2] : 0,
      victim->lvl[3] > 0 ? victim->lvl[3] : 0,
      victim->lvl[4] > 0 ? victim->lvl[4] : 0);
   
   if ( is_remort( victim ) )

   sprintf( buf+strlen(buf), "Levels: [ Sor:%2d  Ass:%2d  Kni:%2d  Nec:%2d  Mon:%2d ]\n\r",
      victim->lvl2[0] > 0 ? victim->lvl2[0] : 0,
      victim->lvl2[1] > 0 ? victim->lvl2[1] : 0,
      victim->lvl2[2] > 0 ? victim->lvl2[2] : 0,
      victim->lvl2[3] > 0 ? victim->lvl2[3] : 0,
      victim->lvl2[4] > 0 ? victim->lvl2[4] : 0);
   }
   sprintf( buf+strlen(buf), "Sex: %s.  Race: %s.  Clan: %s.\n\r", 
      ( victim->sex == SEX_MALE ) ? "Male" :
      ( victim->sex == SEX_FEMALE ) ? "Female" : "None",
      race_table[victim->race].race_name,
      clan_table[victim->pcdata->clan].clan_name );
   
 /*  if (victim->pcdata->pflags != 0)
    sprintf( buf+strlen(buf), "Player is %s\n\r",bit_table_lookup(tab_player_flags,victim->pcdata->pflags));
	 taken out to not show vamps :P */
     if (IS_SET( victim->pcdata->pflags, PFLAG_PKOK ) )
      sprintf(buf+strlen(buf), "Player is @@ePKOK@@N\n\r");
   sprintf( buf+strlen(buf), "Players Killed: %d.  Times killed by players: %d.\n\r",
      victim->pcdata->pkills, victim->pcdata->pkilled );

   sprintf( buf+strlen(buf), "Mobs killed: %d.  Times killed by mobs: %d.\n\r", 
      victim->pcdata->mkills, victim->pcdata->mkilled );

     if ( IS_IMMORTAL( victim ) )
     {
        sprintf( buf+strlen(buf), "%s is an Immortal.\r\n", victim->name );
     }
   /* Description here, or email address? */
 
   sprintf( buf+strlen(buf), "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r");
   send_to_char(buf,ch);
   return;
}

void do_shelp( CHAR_DATA *ch, char * argument )
{
   /* Like help, except for spells and skills. */
   int sn;
   char buf[MAX_STRING_LENGTH];
   HELP_DATA *pHelp;
   bool found = FALSE;
    buf[0] = '\0';

   if ( argument[0] == '\0' )
   {
      do_help( ch, "shelp_summary" );   
      return;
   }
      
   if ( ( sn = skill_lookup( argument ) ) < 0 )
   {
      sprintf( buf, "No sHelp found for argument:%s\n\r", argument );
      send_to_char( buf, ch );
      return;
   }
   sprintf( buf, "shelp_%s", skill_table[sn].name );
   
   /* Search help texts for 'shelp_<name>' as keyword.... */
   for ( pHelp = first_help; pHelp != NULL; pHelp = pHelp->next )
      if ( !str_cmp( buf, pHelp->keyword ) )
      {
	 found = TRUE;
	 send_to_char( pHelp->text, ch );
	 break;
      }
      
   if ( !found )
      send_to_char( "Couldn't find a sHelp for that skill/spell.\n\r", ch );   
      
   return;
}     

void do_afk( CHAR_DATA *ch, char *argument )
{
    int value;
    
    if ( IS_NPC( ch ) )
       return;
    
    value = table_lookup( tab_player_flags, "AFK" );
    
    if ( IS_SET( ch->pcdata->pflags, value ) )
    {
       REMOVE_BIT( ch->pcdata->pflags, value );
       send_to_char( "AFK flag turned off.\n\r", ch );
    }
    else
    {
       SET_BIT( ch->pcdata->pflags, value );
       send_to_char( "AFK flag turned on.\n\r", ch );
    }
    return;
}  

void do_gold( CHAR_DATA *ch, char *argument )
{
   char buf[MAX_STRING_LENGTH];
   
   sprintf( buf, "You are carrying %d gold coin%s.\n\r",
      ch->gold, ch->gold == 1 ? "" : "s" );
   send_to_char( buf, ch );
   
   return;
}

void do_colist( CHAR_DATA *ch, char *argument )
{
   int col, n;
   char buf[MAX_STRING_LENGTH];
   
   if IS_NPC( ch )
      return;
   
   send_to_char( "@@WColour Codes: @@yTo use colour codes within a string, use the following\n\r", ch );
   send_to_char( "characters in sequence: @ @ <letter>.  Do not leave any spaces when you use\n\r", ch );
   send_to_char( "the codes.  (Spaces are left above so that the characters are not interpreted\n\r", ch );
   send_to_char( "as colours when you see this text!)@@g\n\r\n\r", ch );
   
   n = 0;
   
   for ( col = 0; col < MAX_ANSI; col++ )
   {
      sprintf( buf, "%c - %s%-14s@@N    ", 
	 ansi_table[col].letter, 
	 IS_SET( ch->act, PLR_COLOUR ) ? ansi_table[col].value : "", 
	 ansi_table[col].name );
      send_to_char( buf, ch );
      if ( ++n % 3 == 0 )
	 send_to_char( "\n\r", ch );
   }
   if ( n % 3 != 0 )
      send_to_char( "\n\r", ch );
   
   send_to_char( "\n\r", ch );
   return;
}
   
char *  get_family_name     ( CHAR_DATA *ch ) 
{
 
    switch ( ch->pcdata->vamp_bloodline )
      {
	default : return "Renegade!";
	case 1  : return "@@WNOT SET@@N" ;
	case 2  : return "@@WNOT SET@@N" ;
	case 3  : return "@@WNOT SET@@N" ;
	case 4  : return "@@WNOT SET@@N";
      }

}

char *  get_tribe_name     ( CHAR_DATA *ch ) 
{
    switch ( ch->pcdata->vamp_bloodline )
      {
	default : return "Renegade!";
	case 1  : return "@@WNOT SET@@N";
	case 2  : return "@@WNOT SET@@N";
	case 3  : return "@@WNOT SET@@N";
	case 4  : return "@@WNOT SET@@N";
      }

}

void do_loot ( CHAR_DATA *ch, char *argument )
{

    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *corpse;
    OBJ_DATA *obj = NULL;
    int counter, num;

    one_argument( argument, arg );

    if ( IS_NPC( ch ) )
    {
        send_to_char( "NPC's cannot loot corpses.\n\r", ch );
        return;
    }

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

    if ( !str_cmp( arg, "all" ) || !str_prefix( "all." , arg ) )
    {
        send_to_char( "You can't do that.\n\r", ch );
        return;
    }

    corpse = get_obj_room( ch, arg, ch->in_room->first_content );
    if ( corpse == NULL )
    {
        act( "I see no $T here.", ch, NULL, arg, TO_CHAR );
        return;
    }

    if ( corpse->item_type == ITEM_CORPSE_NPC )
    {
        send_to_char( "Just go ahead and take it.\n\r", ch );
        return;
    }

    if ( corpse->item_type != ITEM_CORPSE_PC )
    {
        send_to_char( "You cannot loot that.\n\r", ch );
        return;
    } 
    /* begin checking for lootability */
   
    if ( ( ch->pcdata->clan == 0 )
      && ( !IS_SET(ch->pcdata->pflags, PFLAG_PKOK)  )
      && ( !IS_VAMP( ch ) && !IS_WOLF( ch )  )  )
    {
        send_to_char( "You cannot loot corpses.\n\r", ch );
        return;
    }

    if ( corpse->value[3] == 0 )
    {
        send_to_char( "You cannot loot this corpse.\n\r", ch );
        return;
    }

    if (  ( ch->pcdata->clan == corpse->value[2] )
       || (  ( IS_SET( ch->pcdata->pflags, PFLAG_PKOK )  )
          && ( corpse->value[0] == 1 )  )  
       || (  ( IS_WOLF( ch ) || IS_VAMP( ch )  )  
          && ( corpse->value[0] == 1 )   )   )
    {
        counter = number_range( 1, 100 );

        if ( counter >= 40 )
        {
            if ( corpse->first_in_carry_list == NULL )
            {
                send_to_char( "There isn't anything in the corpse.\n\r", ch);
                return;
            }

            num = 0;
            for (obj = corpse->first_in_carry_list;
                 obj != NULL;
                 obj = obj->next_in_carry_list) {
              ++num;
            }

            counter = number_range( 1, num );
 
            obj = corpse->first_in_carry_list;
            for (num = 1; num < counter; ++num) {
              obj = obj->next_in_carry_list;
            }

            if ( !IS_SET( obj->extra_flags, ITEM_NOLOOT ) )
	    {
	        get_obj( ch, obj, corpse );
      
                /* just incase... */
               if ( ch->level > 1 )
                {
                   do_save( ch, "" );
                }
            }
            else 
	    {
		send_to_char( "You failed to loot the corpse.\n\r", ch );
		return;
	    }

            corpse->value[3] = corpse->value[3] - 1; 
            return;
        }
        else
        {
            send_to_char( "You failed to loot the corpse.\n\r", ch );
            return;
        }
     }
     
     send_to_char( "You cannot loot this corpse.\n\r", ch );
  return;
}