/
rogue24b3/
rogue24b3/data/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
*	ROM 2.4 is copyright 1993-1998 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@hypercube.org)				   *
*	    Gabrielle Taylor (gtaylor@hypercube.org)			   *
*	    Brian Moore (zump@rom.org)					   *
*	By using this code, you have agreed to follow the terms of the	   *
*	ROM license, in the file Rom24/doc/rom.license			   *
***************************************************************************/

#include "merc.h"
#include "interp.h"
#include "magic.h"
#include "recycle.h"
#include "tables.h"
#include "lookup.h"
#include "olc.h"
#include "pueblo.h"

extern char roguemud_version[];

/*
 * Someone remind me to fix this later to look better.
 */
char *	const	where_name	[] =
{
	"`n<used as light>     ",
	"`n<worn on finger>    ",
	"`n<worn on finger>    ",
	"`n<worn around neck>  ",
	"`n<worn around neck>  ",
	"`n<worn on torso>     ",
	"`n<worn on head>      ",
	"`n<worn on legs>      ",
	"`n<worn on feet>      ",
	"`n<worn on hands>     ",
	"`n<worn on arms>      ",
	"`n<worn as shield>    ",
	"`n<worn about body>   ",
	"`n<worn about waist>  ",
	"`n<worn around wrist> ",
	"`n<worn around wrist> ",
	"`n<wielded>           ",
	"`n<held>              ",
	"`n<floating nearby>   ",
	"`n<worn on face>      ",
	"`n<worn on back>      ",
	"`n<worn over eyes>    ",
	"`n<worn around ears>  ",
	"`n<left ankle>        ",
	"`n<right ankle>       ",
};


/* for keeping track of the player count */
int max_on = 0;
int boot_high = 0;
/*
 * Local functions.
 */
char *	format_obj_to_char	args( ( OBJ_DATA *obj, CHAR_DATA *ch,
				    bool fShort ) );
void	show_list_to_char	args( ( OBJ_DATA *list, CHAR_DATA *ch,
				    bool fShort, bool fShowNothing ) );
void	show_char_to_char_0	args( ( CHAR_DATA *victim, CHAR_DATA *ch ) );
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 ) );
extern	char *			relation_colors;

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

    buf[0] = '\0';

    if ((fShort && (obj->short_descr == NULL || obj->short_descr[0] == '\0'))
    ||  (obj->description == NULL || obj->description[0] == '\0'))
	return buf;

    if (fShort) {
	if (obj->short_descr != NULL)
	    strcat(buf, obj->short_descr);
    } else {
	if (obj->description != NULL) {
	    if ((ch->on == obj) && (GET_POS(ch) <= POS_SITTING))
		sprintf(buf + strlen(buf), "You are %s on %s.",
			(GET_POS(ch) == POS_RESTING) ? "resting" : "sitting",
			obj->short_descr);
	    else
		strcat(buf, obj->description);
	}
    }

    strcat(buf, "`n");
    if (IS_OBJ_STAT(obj, ITEM_INVIS))		strcat(buf, " (invis)");
    if (IS_AFFECTED(ch, AFF_DETECT_EVIL)
	&& IS_OBJ_STAT(obj, ITEM_EVIL))		strcat(buf, " (Red Aura)");
    if (IS_AFFECTED(ch, AFF_DETECT_GOOD)
	&&  IS_OBJ_STAT(obj,ITEM_BLESS))	strcat(buf," (Blue Aura)");
    if (IS_AFFECTED(ch, AFF_DETECT_MAGIC)
	&& IS_OBJ_STAT(obj, ITEM_MAGIC))	strcat(buf, " (`cmagical`n)");
    if (IS_AFFECTED(ch, AFF_DETECT_MAGIC)
	&& IS_OBJ_STAT(obj, ITEM_MUSIC))	strcat(buf, " (`mmusical`n)");
    if (IS_OBJ_STAT(obj, ITEM_GLOW))		strcat(buf, " (glowing)");
    if (IS_OBJ_STAT(obj, ITEM_HUM))		strcat(buf, " (humming)");

    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];
    BUFFER *output;
    char **prgpstrShow;
    int *prgnShow;
    char *pstrShow;
    OBJ_DATA *obj;
    int nShow;
    int iShow;
    int count;
    bool fCombine;

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

    count = 0;
    for ( obj = list; obj != NULL; obj = obj->next_content )
	count++;

    if (count == 0)
	return; // why go on?

    if (count > 5000)   {
	send_to_char("That is WAY too much junk! Drop some of it!\n\r",ch);
	return;
    }
    output = new_buf();
    alloc_mem(prgpstrShow, char *, count);
    alloc_mem(prgnShow, int, count);
    nShow	= 0;

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

	    fCombine = FALSE;

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

	    /*
	     * Couldn't combine, or didn't want to.
	     */
	    if ( !fCombine )
	    {
		prgpstrShow [nShow] = str_dup( pstrShow );
		prgnShow    [nShow] = 1;
		nShow++;
	    }
	}
    }

    /*
     * Output the formatted list.
     */
    for ( iShow = 0; iShow < nShow; iShow++ )
    {
	if (prgpstrShow[iShow][0] == '\0')
	{
	    free_string(prgpstrShow[iShow]);
	    continue;
	}

	add_buf(output, "`g");
	if (IS_NPC(ch) || IS_SET(ch->comm, COMM_COMBINE))
	{
	    if (prgnShow[iShow] != 1)
	    {
		sprintf(buf, "(%2d) ", prgnShow[iShow]);
		add_buf(output,buf);
	    }
	}
	add_buf(output,prgpstrShow[iShow]);
	add_buf(output,"`n\n\r");
	free_string( prgpstrShow[iShow] );
    }

    if ( fShowNothing && nShow == 0 )
    {
	if ( IS_NPC(ch) || IS_SET(ch->comm, COMM_COMBINE) )
	    send_to_char( "     ", ch );
	send_to_char( "Nothing.\n\r", ch );
    }
    page_to_char(buf_string(output),ch);

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



void show_char_to_char_0( CHAR_DATA *victim, CHAR_DATA *ch )
{
    char buf[MAX_STRING_LENGTH],message[MAX_STRING_LENGTH];
    char relation = relation_colors[ch->GetRelation(victim)];
    buf[0] = '\0';

    if (IS_NPC(victim) && ch->questmob > 0 &&
	victim->pIndexData->vnum == ch->questmob)
       strcat( buf, "`r[TARGET]`n ");

    if ( victim->position == POS_STANDING && victim->long_descr[0] != '\0' )
    {
	sprintf(message, "`%c%s`n", relation, victim->long_descr);
	strcat( buf, message);
	send_to_char( buf, ch );
	return;
    }

    sprintf(buf, "`%c%s", relation, PERS(victim, ch));
    if (!IS_NPC(victim) && !IS_SET(ch->comm, COMM_BRIEF) 
    &&  victim->position == POS_STANDING && ch->on == NULL)
	strcat(buf, victim->pcdata->title );
    strcat(buf, "`y");
    if (IS_AFFECTED(victim, AFF_INVISIBLE))	strcat(buf, " (invisible)");
    if (victim->invis_level >= LEVEL_HERO)	strcat(buf, " (wizi)");
    if (IS_AFFECTED(victim, AFF_HIDE))		strcat(buf, " (hidden)");
    if (!IS_NPC(victim) && !victim->desc)	strcat(buf, " (linkless)");
    if (PLR_FLAGGED(victim, PLR_WRITING))	strcat(buf, " `n(`rwriting`n)");
    if (IS_AFFECTED(victim, AFF_CHARM))		strcat(buf, " `m(charmed)`n");
    if (IS_AFFECTED(victim, AFF_PASS_DOOR))	strcat(buf, " `c(translucent)`n");
    if (IS_AFFECTED(victim, AFF_FAERIE_FIRE))	strcat(buf, " `M(pink aura`n)");
    if (IS_EVIL(victim)
    &&  IS_AFFECTED(ch, AFF_DETECT_EVIL))	strcat(buf, " `R(red aura)`n");
    if (IS_GOOD(victim)
    &&  IS_AFFECTED(ch, AFF_DETECT_GOOD))	strcat(buf, " `Y(gold aura)`n");
    if (IS_AFFECTED(victim, AFF_SANCTUARY))	strcat(buf, " `W(glowing)`n");
    if (IS_SET(victim->comm,COMM_AFK))		strcat(buf, " `c[AFK]`n");
    if (PLR_FLAGGED(victim, PLR_KILLER))	strcat(buf, " `R(KILLER)`n");
    if (PLR_FLAGGED(victim, PLR_THIEF))		strcat(buf, " `B(THIEF)`n");

    switch ( victim->position )
    {
    case POS_DEAD:     strcat( buf, " is DEAD!!" );              break;
    case POS_MORTAL:   strcat( buf, " is mortally wounded." );   break;
    case POS_INCAP:    strcat( buf, " is incapacitated." );      break;
    case POS_STUNNED:  strcat( buf, " is lying here stunned." ); break;
    case POS_SLEEPING: 
	if (victim->on != NULL)
	{
	    if (IS_SET(victim->on->value[2],SLEEP_AT))
  	    {
		sprintf(message," is sleeping at %s.",
		    victim->on->short_descr);
		strcat(buf,message);
	    }
	    else if (IS_SET(victim->on->value[2],SLEEP_ON))
	    {
		sprintf(message," is sleeping on %s.",
		    victim->on->short_descr); 
		strcat(buf,message);
	    }
	    else
	    {
		sprintf(message, " is sleeping in %s.",
		    victim->on->short_descr);
		strcat(buf,message);
	    }
	}
	else 
	    strcat(buf," is sleeping here.");
	break;
    case POS_RESTING:  
        if (victim->on != NULL)
	{
            if (IS_SET(victim->on->value[2],REST_AT))
            {
                sprintf(message," is resting at %s.",
                    victim->on->short_descr);
                strcat(buf,message);
            }
            else if (IS_SET(victim->on->value[2],REST_ON))
            {
                sprintf(message," is resting on %s.",
                    victim->on->short_descr);
                strcat(buf,message);
            }
            else 
            {
                sprintf(message, " is resting in %s.",
                    victim->on->short_descr);
                strcat(buf,message);
            }
	}
        else
	    strcat( buf, " is resting here." );       
	break;
    case POS_SITTING:  
        if (victim->on != NULL)
        {
            if (IS_SET(victim->on->value[2],SIT_AT))
            {
                sprintf(message," is sitting at %s.",
                    victim->on->short_descr);
                strcat(buf,message);
            }
            else if (IS_SET(victim->on->value[2],SIT_ON))
            {
                sprintf(message," is sitting on %s.",
                    victim->on->short_descr);
                strcat(buf,message);
            }
            else
            {
                sprintf(message, " is sitting in %s.",
                    victim->on->short_descr);
                strcat(buf,message);
            }
        }
        else
	    strcat(buf, " is sitting here.");
	break;
    case POS_STANDING: 
	if (victim->on != NULL)
	{
	    if (IS_SET(victim->on->value[2],STAND_AT))
	    {
		sprintf(message," is standing at %s.",
		    victim->on->short_descr);
		strcat(buf,message);
	    }
	    else if (IS_SET(victim->on->value[2],STAND_ON))
	    {
		sprintf(message," is standing on %s.",
		   victim->on->short_descr);
		strcat(buf,message);
	    }
	    else
	    {
		sprintf(message," is standing in %s.",
		    victim->on->short_descr);
		strcat(buf,message);
	    }
	}
	else
	    strcat( buf, " is here." );               
	break;
    case POS_FIGHTING:
	strcat( buf, " is here, fighting " );
	if ( victim->fighting == NULL )
	    strcat( buf, "thin air??" );
	else if ( victim->fighting == ch )
	    strcat( buf, "YOU!" );
	else if ( victim->in_room == victim->fighting->in_room )
	{
	    strcat( buf, PERS( victim->fighting, ch ) );
	    strcat( buf, "." );
	}
	else
	    strcat( buf, "someone who left??" );
	break;
    }

    strcat( buf, "`n\n\r" );
    buf[0] = UPPER(buf[0]);
    send_to_char( buf, ch );
    return;
}



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

    if ( can_see( victim, ch ) )
    {
	if ((!IS_IMMORTAL(ch) && IS_IMMORTAL(victim)) && (ch != victim))
	{
		send_to_char("You cannot behold such a creature.\n\r",ch);
		return;
	} else if (ch == victim)
	    act( "$n looks at $mself.",ch,NULL,NULL,TO_ROOM);
	else
	{
	    act( "$n looks at you.", ch, NULL, victim, TO_VICT    );
	    act( "$n looks at $N.",  ch, NULL, victim, TO_NOTVICT );
	}
    }

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

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

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

    if (percent >= 100) 
	strcat( buf, " is in excellent condition.\n\r");
    else if (percent >= 90) 
	strcat( buf, " has a few scratches.\n\r");
    else if (percent >= 75) 
	strcat( buf," has some small wounds and bruises.\n\r");
    else if (percent >=  50) 
	strcat( buf, " has quite a few wounds.\n\r");
    else if (percent >= 30)
	strcat( buf, " has some big nasty wounds and scratches.\n\r");
    else if (percent >= 15)
	strcat ( buf, " looks pretty hurt.\n\r");
    else if (percent >= 0 )
	strcat (buf, " is in awful condition.\n\r");
    else
	strcat(buf, " is bleeding to death.\n\r");

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

    found = FALSE;
    for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
    {
	if ( ( obj = get_eq_char( victim, iWear ) ) != NULL
	&&   can_see_obj( ch, obj ) )
	{
	    if ( !found )
	    {
		send_to_char( "\n\r", ch );
		act( "$N is using:", ch, NULL, victim, TO_CHAR );
		found = TRUE;
	    }
	    send_to_char( where_name[iWear], ch );
	    send_to_char( format_obj_to_char( obj, ch, TRUE ), ch );
	    send_to_char( "\n\r", ch );
	}
    }

    if (!IS_STAFF(ch)
    &&  !IS_NPC(ch) && victim != ch
    &&  number_percent() < get_skill(ch, gsn_peek)) {
	send_to_char("\n\rYou peek at the inventory:\n\r", ch);
	check_improve(ch, gsn_peek, TRUE, 4);
	show_list_to_char(victim->carrying, ch, TRUE, TRUE);
    } else if (IS_STAFF(ch)) {
		send_to_char("\n\rYou peek at the inventory:\n\r",ch);
		show_list_to_char(victim->carrying, 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 ( get_trust(ch) < rch->invis_level)
	    continue;

	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)) {
	    send_to_char( "`rYou see glowing red eyes watching YOU!`n\n\r", ch );
	}
    }
    return;
} 

bool check_blind( CHAR_DATA *ch )
{

    if (PLR_FLAGGED(ch, 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;
}

#define TOG_ON	0
#define TOG_OFF	1

#define PLR_TOG_CHK(ch,flag) ((TOGGLE_BIT(PLR_FLAGS(ch), (flag))) & (flag))
#define CHN_TOG_CHK(ch,flag) ((TOGGLE_BIT(CHN_FLAGS(ch), (flag))) & (flag))

ACMD(do_gen_tog) {
	Flags	result;

	char *tog_messages[][2] = {
		{"You are now safe from summoning by other players.\n\r",
		 "You may now be summoned by other players.\n\r"},
		{"Nohassle enabled.\n\r",
		 "Nohassle disabled.\n\r"},
		{"Brief mode on.\n\r",
		 "Brief mode off.\n\r"},
		{"Compact mode on.\n\r",
		 "Compact mode off.\n\r"},
		{"You are now deaf to tells.\n\r",
		 "You can now hear tells.\n\r"},
		{"You are now deaf to music.\n\r",
		 "You can now hear music.\n\r"},
		{"You are now deaf to shouts.\n\r",
		 "You can now hear shouts.\n\r"},
		{"You are now deaf to chat.\n\r",
		 "You can now hear chat.\n\r"},
		{"You are now deaf to congratulation messages.\n\r",
		 "You can now hear congratulation messages.\n\r"},
		{"You are now deaf to quests.\n\r",
		 "You can now hear quests.\n\r"},
		{"Holylight mode on.\n\r",
		 "Holylight mode off.\n\r"},
		{"Autoexits enabled.\n\r",
		 "Autoexits disabled.\n\r"},
		{"You will no longer receive game broadcasts.\n\r",
		 "You will now receive game broadcasts.\n\r"},
		{"You will now see color.\n\r",
		 "You will no longer see color.\n\r"},
		{"You will now hear MSP sounds.\n\r",
		 "You are now deaf to MSP sounds.\n\r"},
		{"You are now deaf to clan chat.\n\r",
		 "You can now hear clan chat.\n\r"},
		{"UNUSED SCMD #16\n\r",
		 "UNUSED SCMD #16\n\r"},
		{"Combined inventory on.\n\r",
		 "Combined inventory off.\n\r"},
		{"Your corpse may now be looted.\n\r",
		 "Your corpse is now safe from thieves.\n\r"},
		{"You no longer accept followers.\n\r",
		 "You now accept followers.\n\r"},
		{"You will no longer see pueblo enhancements.\n\r",
		 "You will now see pueblo enhancements.\n\r"},
		{"Autoassist on.\n\r",
		 "Autoassist off.\n\r"},
		{"Autodamage on.\n\r",
		 "Autodamage off.\n\r"},
		{"Autogold on.\n\r",
		 "Autogold off.\n\r"},
		{"Autoloot on.\n\r",
		 "Autoloot off.\n\r"},
		{"Autosacrifice on.\n\r",
		 "Autosacrifice off.\n\r"},
		{"Autospliting on.\n\r",
		 "Autospliting off.\n\r"},
		{"Automapping enabled.\n\r",
		 "Automapping disabled.\n\r"},
		{"You will now see affects in score.\n\r",
		 "You will no longer see affects in score.\n\r"},
		{"Quiet mode on.\n\r",
		 "Quiet mode off.\n\r"}
	};

	if (IS_NPC(ch))
		return;

	switch (subcmd) {
		case SCMD_NOSUMMON:	result = PLR_TOG_CHK(ch, PLR_NOSUMMON);	break;
		case SCMD_NOHASSLE:	result = PLR_TOG_CHK(ch, PLR_NOHASSLE);	break;
		case SCMD_BRIEF:	result = CHN_TOG_CHK(ch, COMM_BRIEF);	break;
		case SCMD_COMPACT:	result = CHN_TOG_CHK(ch, COMM_COMPACT);	break;
		case SCMD_NOTELL:	result = CHN_TOG_CHK(ch, COMM_NOTELL);	break;
		case SCMD_NOMUSIC:	result = CHN_TOG_CHK(ch, COMM_NOMUSIC);	break;
		case SCMD_NOSHOUT:	result = CHN_TOG_CHK(ch, COMM_NOSHOUT);	break;
		case SCMD_NOCHAT:	result = CHN_TOG_CHK(ch, COMM_NOGOSSIP);	break;
		case SCMD_NOGRATS:	result = CHN_TOG_CHK(ch, COMM_NOGRATS);	break;
		case SCMD_NOQUEST:	result = CHN_TOG_CHK(ch, COMM_NOQUEST);	break;
		case SCMD_HOLYLIGHT:	result = PLR_TOG_CHK(ch, PLR_HOLYLIGHT);	break;
		case SCMD_AUTOEXIT:	result = PLR_TOG_CHK(ch, PLR_AUTOEXIT);	break;
		case SCMD_NOINFO:	result = CHN_TOG_CHK(ch, COMM_NOINFO);	break;
		case SCMD_COLOR:	result = PLR_TOG_CHK(ch, PLR_COLOUR);	break;
		case SCMD_MSP:		result = PLR_TOG_CHK(ch, PLR_MSP);	break;
		case SCMD_NOCLAN:	result = CHN_TOG_CHK(ch, COMM_NOCLAN);	break;
		case SCMD_UNUSED16:	result = FALSE;	break;
		case SCMD_COMBINE:	result = CHN_TOG_CHK(ch, COMM_COMBINE);	break;
		case SCMD_NOLOOT:	result = PLR_TOG_CHK(ch, PLR_CANLOOT);	break;
		case SCMD_NOFOLLOW:	result = PLR_TOG_CHK(ch, PLR_NOFOLLOW);	break;
		case SCMD_NOPUEBLO:	result = CHN_TOG_CHK(ch, COMM_NOPUEBLO);	break;
		case SCMD_AUTOASSIST:	result = PLR_TOG_CHK(ch, PLR_AUTOASSIST);	break;
		case SCMD_AUTODAMAGE:	result = PLR_TOG_CHK(ch, PLR_AUTODAMAGE);	break;
		case SCMD_AUTOGOLD:	result = PLR_TOG_CHK(ch, PLR_AUTOGOLD);	break;
		case SCMD_AUTOLOOT:	result = PLR_TOG_CHK(ch, PLR_AUTOLOOT);	break;
		case SCMD_AUTOSAC:	result = PLR_TOG_CHK(ch, PLR_AUTOSAC);	break;
		case SCMD_AUTOSPLIT:	result = PLR_TOG_CHK(ch, PLR_AUTOSPLIT);	break;
		case SCMD_AUTOMAP:	result = PLR_TOG_CHK(ch, PLR_AUTOMAP);	break;
		case SCMD_SHOW:		result = CHN_TOG_CHK(ch, COMM_SHOW_AFFECTS);	break;
		case SCMD_QUIET:	result = CHN_TOG_CHK(ch, COMM_QUIET);	break;
		default: mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Unkown subcmd %d in do_gen_toggle", subcmd); return;
	}

	if (result)	send_to_char(tog_messages[subcmd][TOG_ON], ch);
	else		send_to_char(tog_messages[subcmd][TOG_OFF], ch);
	return;
}

/* Lore skill by The Mage */
ACMD(do_lore) {
  char object_name[MAX_INPUT_LENGTH + 100];

  OBJ_DATA *obj;
  argument = one_argument(argument, object_name);
  if ((obj = get_obj_carry(ch, object_name, ch)) == NULL)
  {
	send_to_char( "You are not carrying that.\n\r", ch );
	return;
  }

  send_to_char("You ponder the item.\n\r",ch);
  if (number_percent() < get_skill(ch,gsn_lore) && ch->level >= obj->level)
  {
    ch->Send(
	"Object '%s' is type %s, extra flags %s.\n\rWeight is %d, value is %d, level is %d.\n\r",
	obj->name, item_name(obj->item_type),
	extra_bit_name(obj->extra_flags),
	obj->weight / 10,
	obj->cost, obj->level);

    switch (obj->item_type)
    {
      case ITEM_SCROLL: 
      case ITEM_POTION:
      case ITEM_PILL:
	ch->Send("Some level spells of:");

	if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL )
	  {
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[1]].name, ch );
	    send_to_char( "'", ch );
	  }

	if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL )
	  {
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[2]].name, ch );
	    send_to_char( "'", ch );
	  }

	if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	  {
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[3]].name, ch );
	    send_to_char( "'", ch );
	  }

	if (obj->value[4] >= 0 && obj->value[4] < MAX_SKILL)
	  {
	    send_to_char(" '",ch);
	    send_to_char(skill_table[obj->value[4]].name,ch);
	    send_to_char("'",ch);
	  }

	send_to_char( ".\n\r", ch );
	break;

      case ITEM_WAND: 
      case ITEM_STAFF: 
	ch->Send("Has some charges of some level");
      
	if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	  {
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[3]].name, ch );
	    send_to_char( "'", ch );
	  }

	send_to_char( ".\n\r", ch );
	break;

      case ITEM_DRINK_CON:
        ch->Send("It holds %s-colored %s.\n\r",
		liq_table[obj->value[2]].liq_color,
		liq_table[obj->value[2]].liq_name);
        break;

      case ITEM_CONTAINER:
	ch->Send("Capacity: %d#  Maximum weight: %d#  flags: %s\n\r",
		obj->value[0], obj->value[3], cont_bit_name(obj->value[1]));
	if (obj->value[4] != 100)
	  {
	    ch->Send("Weight multiplier: %d%%\n\r",
		    obj->value[4]);
	  }
	break;
		
      case ITEM_WEAPON:
 	send_to_char("Weapon type is ",ch);
	switch (obj->value[0])
	  {
	  case(WEAPON_EXOTIC) : send_to_char("exotic.\n\r",ch);	break;
	  case(WEAPON_SWORD)  : send_to_char("sword.\n\r",ch);	break;	
	  case(WEAPON_DAGGER) : send_to_char("dagger.\n\r",ch);	break;
	  case(WEAPON_SPEAR)	: send_to_char("spear/staff.\n\r",ch);	break;
	  case(WEAPON_MACE) 	: send_to_char("mace/club.\n\r",ch);	break;
	  case(WEAPON_AXE)	: send_to_char("axe.\n\r",ch);		break;
	  case(WEAPON_FLAIL)	: send_to_char("flail.\n\r",ch);	break;
	  case(WEAPON_WHIP)	: send_to_char("whip.\n\r",ch);		break;
	  case(WEAPON_POLEARM): send_to_char("polearm.\n\r",ch);	break;
	  case(WEAPON_QUARTERSTAFF): send_to_char("quarterstaff.\n\r",ch); break;
	  default		: send_to_char("unknown.\n\r",ch);	break;
	  }
	if (obj->pIndexData->new_format)
	  ch->Send("Damage is %dd%d (average %d).\n\r",
		  obj->value[1],obj->value[2],
		  (1 + obj->value[2]) * obj->value[1] / 2);
	else
	  ch->Send("Damage is %d to %d (average %d).\n\r",
		   obj->value[1], obj->value[2],
		   ( obj->value[1] + obj->value[2] ) / 2 );
        if (obj->value[4])  /* weapon flags */
	  {
            ch->Send("Weapons flags: %s\n\r",weapon_bit_name(obj->value[4]));
	  }
	break;

      case ITEM_ARMOR:
	ch->Send( 
		 "Armor class is %d pierce, %d bash, %d slash, and %d vs. magic.\n\r", 
		 obj->value[0], obj->value[1], obj->value[2], obj->value[3] );
	break;
      }
  }
  return;
}

/* changes your scroll */
ACMD(do_scroll) {
    char arg[MAX_INPUT_LENGTH];
    char buf[100];
    int lines;

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

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

    lines = atoi(arg);

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

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

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

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

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


ACMD(do_gen_ps) {
    switch (subcmd) {
	case SCMD_MOTD:		do_help(ch, "motd",  0);		break;
	case SCMD_IMOTD:	do_help(ch, "imotd", 0);		break;
	case SCMD_RULES:	do_help(ch, "rules", 0);		break;
	case SCMD_POLICY:	do_help(ch, "policy",0);		break;
	case SCMD_STORY:	do_help(ch, "story", 0);		break;
	case SCMD_VERSION:	send_to_char(roguemud_version, ch);	break;
	case SCMD_CLEAR:	send_to_char("\033[H\033[J", ch);	break;
    }
}

ACMD(do_autolist) {
    /* lists most player flags */
    if (IS_NPC(ch))
      return;

    ch->Send(
	"Action         Status\n\r"
	"`m---------------------`n\n\r"
	"autoassist     %-3s\r\n"
	"autodamage     %-3s\r\n"
	"automapper     %-3s\r\n"
	"autoexit       %-3s\r\n"
	"autogold       %-3s\r\n"
	"autoloot       %-3s\r\n"
	"autosac        %-3s\r\n"
	"autosplit      %-3s\r\n"
	"compact mode   %-3s\r\n"
	"combine items  %-3s\r\n",
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOASSIST)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTODAMAGE)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOMAP)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOEXIT)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOGOLD)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOLOOT)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOSAC)),
	ONOFF(PLR_FLAGGED(ch, PLR_AUTOSPLIT)),
	ONOFF(COMM_FLAGGED(ch, COMM_COMPACT)),
	ONOFF(COMM_FLAGGED(ch, COMM_COMBINE)));
}

ACMD(do_autoall) {
    if (!IS_NPC(ch)) {
	SET_BIT(ch->act,PLR_AUTOASSIST);
	SET_BIT(ch->act,PLR_AUTODAMAGE);
	SET_BIT(ch->act,PLR_AUTOEXIT);
	SET_BIT(ch->act,PLR_AUTOGOLD);
	SET_BIT(ch->act,PLR_AUTOLOOT);
	SET_BIT(ch->act,PLR_AUTOSAC);
	SET_BIT(ch->act,PLR_AUTOSPLIT);
	SET_BIT(ch->act,PLR_COLOUR);
	if (!PLR_FLAGGED(ch, PLR_PUEBLO))
		SET_BIT(ch->act, PLR_AUTOMAP);
	send_to_char("All AUTOs activated.. have a nice day.\n\r",ch);
    } else {
	send_to_char("Your a mob dufus.. You get no such luxury.\n\r",ch);
	return;
    }
}

ACMD(do_display) {
    char arg[MSL];
    char buf[MSL];
    int i, x;

      const char *def_prompts[][2] = {
	{ "Stock Rom",	"`c<%hhp %mm %vmv>`n " },
	{ "Colorized Stock Rogue", "`R%h`rhp `M%m`mma `G%v`gmv`c>`n "},
	{ "Standard", "`R%h`rhp `M%m`mma `G%v`gmv `yexp: %X`n> "},
	{ "Non Magic Featured", "`R%h`w(`R%H`w)`Whitp `G%v`w(`G%V`w)`Wmove`n> %b"},
	{ "Full Featured", "`R%h`w(`R%H`w)`Whitp `M%m`w(`M%M`w)`Wmana `G%v`w(`G%V`w)`Wmove`n> %b`n"},
	{ "\n", "\n" }
	};

	argument = one_argument(argument, arg);

	if (!arg || !*arg) {
		send_to_char("The following pre-set prompts are availible...\n\r", ch);
	for (i = 0; *def_prompts[i][0] != '\n'; i++) {
			sprintf(buf,"  %d. %-25s  %s\r\n", i,def_prompts[i][0],def_prompts[i][1]);
		send_to_char(buf,ch);
	}
		send_to_char(   "Usage: display <number>\r\n"
			"To create your own prompt, use \"prompt <str>\".\r\n", ch);
	} else if (!isdigit(*arg))
		send_to_char(   "Usage: display <number>\r\n"
			"Type \"display\" without arguments for a list of preset prompts.\r\n",ch);
	else {
		i = atoi(arg);
		if (i < 0) {
			send_to_char("The number cannot be negative.\r\n", ch);
		} else {
			for (x = 0; *def_prompts[x][0] != '\n'; x++);
			if (i >= x) {
				sprintf(buf,"The range for the prompt number is 0-%d.\r\n", x-1);
				send_to_char(buf,ch);
			} else {
				free_string(ch->prompt);
				ch->prompt = str_dup(def_prompts[i][1]);
				sprintf(buf, "Set your prompt to the %s preset prompt.\r\n",def_prompts[i][0]);
				send_to_char(buf,ch);
			}
		}
	}
}

ACMD(do_prompt) {
   char buf[MAX_STRING_LENGTH];
 
   if ( argument[0] == '\0' )
   {
	if (ch->prompt != NULL)
	{
		sprintf(buf,"Your current prompt is: %s\n\r",ch->prompt);
		send_to_char(buf,ch);
	}
       return;
   }
 
   if( !strcmp( argument, "all" ) )
      strcpy( buf, "`c%h(%H)hp %mm %vmv>`n " );
   else
   {
      if ( strlen(argument) > 50 )
         argument[50] = '\0';
      strcpy( buf, argument );
      smash_tilde( buf );
      if (str_suffix("%c",buf))
	strcat(buf," ");
	
   }
 
   free_string( ch->prompt );
   ch->prompt = str_dup( buf );
   sprintf(buf,"Prompt set to %s\n\r",ch->prompt );
   send_to_char(buf,ch);
   return;
}

extern char *dirs[];

void do_auto_exits(CHAR_DATA *ch, ROOM_INDEX_DATA *room) {
    SInt8 door;
    EXIT_DATA *pexit;
    SInt32 buflen = 0;
    char buf[MAX_STRING_LENGTH];

    if (room == NULL)
	return;

    buf[0] = '\0';

    for (door = 0; door < MAX_DIR; door++) {
	if ((pexit = room->exit[door]) != NULL
	&& pexit->u1.to_room != NULL
	&& can_see_room(ch, pexit->u1.to_room)
	&& can_see_ex_hidden(ch, pexit)) {
	    buflen += sprintf(buf + buflen, "`%s%c ",
		(EXIT_FLAGGED(pexit, EX_HIDDEN)) ? "g" : "c",
		(EXIT_FLAGGED(pexit, EX_CLOSED)) ?
		LOWER(*dir_name[door]) : UPPER(*dir_name[door])
	    );
	}
    }
    ch->Send("`c[ Exits: %s]`n\n\r", *buf ? buf : "None! ");
}

void show_obj_to_char(OBJ_DATA *obj, CHAR_DATA *ch, int mode) {
    int found;
    char buf[MAX_STRING_LENGTH];

    *buf = '\0';
    strcpy(buf, "`g");
    if ((mode == 0) && *obj->description) {
	if ((ch->on == obj) && (GET_POS(ch) <= POS_SITTING))
	    sprintf(buf + strlen(buf), "You are %s on %s.",
		(ch->position == POS_RESTING) ? "resting" : "sitting",
		obj->short_descr);
	else
	    strcat(buf, obj->description);
    } else if (*obj->short_descr && ((mode == 1)
    || (mode == 2) || (mode == 3) || (mode == 4)))
	strcat(buf, obj->short_descr);
    else if (mode == 5) {
	if (obj->item_type == ITEM_NOTE) {
	    if (*obj->note_descr) {
		strcpy(buf, "There is something written upon it:\n\r\n\r");
		strcat(buf, obj->note_descr);
		page_to_char(buf, ch);
	    } else
		ch->Send("It's blank.\n\r");
	    return;
	} else if (obj->item_type == ITEM_DRINK_CON)
	    strcpy(buf, "It looks like a drink container.");
	else
	    strcpy(buf, "You see nothing special...");
    }
    if (mode != 3) {
	if (IS_OBJ_STAT(obj, ITEM_INVIS))	strcat(buf, " (invis)");
	if (IS_AFFECTED(ch, AFF_DETECT_EVIL)
	&& IS_OBJ_STAT(obj, ITEM_EVIL))
						strcat(buf, " (Red Aura)");
	if (IS_AFFECTED(ch, AFF_DETECT_GOOD)
	&& IS_OBJ_STAT(obj,ITEM_BLESS))
						strcat(buf," (Blue Aura)");
	if (IS_AFFECTED(ch, AFF_DETECT_MAGIC)
	&& IS_OBJ_STAT(obj, ITEM_MAGIC))
						strcat(buf, " (`cmagical`n)");
	if (IS_AFFECTED(ch, AFF_DETECT_MAGIC)
	&& IS_OBJ_STAT(obj, ITEM_MUSIC))
						strcat(buf, " (`mmusical`n)");
	if (IS_OBJ_STAT(obj, ITEM_GLOW))	strcat(buf, " (glowing)");
	if (IS_OBJ_STAT(obj, ITEM_HUM))		strcat(buf, " (humming)");
    }
    strcat(buf, "\n\r");
    page_to_char(buf, ch);
}

void look_at_target(CHAR_DATA *ch, char *arg) {
    bool found = FALSE;
    char *desc, *number;
    int bits, j, msg = 1;
    CHAR_DATA *found_char = NULL;
    OBJ_DATA *obj = NULL, *found_obj = NULL;

    if (!ch->desc)
	return;
    else if (!*arg)
	ch->Send("Look at what?\n\r", ch);
    else {
	bits = generic_find(arg, FIND_OBJ_INV | FIND_OBJ_ROOM | FIND_OBJ_EQ |
		FIND_CHAR_ROOM, ch, &found_char, &found_obj);

	if (found_char) {
	    show_char_to_char_1(found_char, ch);
	    if (ch != found_char) {
		if (can_see(found_char, ch))
		    act("$n looks at you.", ch, 0, found_char, TO_VICT);
		act("$n looks at $N.", ch, 0, found_char, TO_NOTVICT);
	    }
	    return;
	}

	if ((desc = get_extra_descr(arg, IN_ROOM(ch)->extra_descr)) != NULL) {
	    page_to_char(desc, ch);
	    return;
	}
	for (obj = ch->carrying; obj != NULL; obj = obj->next_content) {
	    if ((desc = get_extra_descr(arg, obj->extra_descr)) != NULL) {
		page_to_char(desc, ch);
		found = TRUE;
	    }
	}
	for (obj = IN_ROOM(ch)->contents; obj != NULL; obj = obj->next_content) {
	    if (found)
		break;
	    if ((desc = get_extra_descr(arg, obj->extra_descr)) != NULL) {
		page_to_char(desc, ch);
		found = TRUE;
	    }
	}

	if (bits) {
	    if (!found)		show_obj_to_char(found_obj, ch, 5);
	    else		show_obj_to_char(found_obj, ch, 6);
	} else if (!found)
		ch->Send("You do not see that here.\n\r");
    }
}

void look_out(CHAR_DATA *ch) {
    OBJ_DATA *viewport, *vehicle;
    OBJ_DATA *find_vehicle_by_vnum(int vnum);

    if (!(viewport = get_obj_list_type(ITEM_V_WINDOW, IN_ROOM(ch)->contents))) {
	ch->Send("There is no window to see out of.\n\r");
	return;
    }

    vehicle = find_vehicle_by_vnum(viewport->value[0]);
    if (!vehicle || IN_ROOM(vehicle) == NULL) {
	ch->Send("All you can see is an infinite blackness.\n\r");
	return;
    }
    look_at_rnum(ch, IN_ROOM(vehicle), FALSE);
    return;
}

void look_in_obj(CHAR_DATA *ch, char *arg) {
    int amt, bits;
    OBJ_DATA *obj = NULL;
    CHAR_DATA *dummy = NULL;

    if (!*arg)
	ch->Send("Look in what?\n\r");
    else if (!(bits = generic_find(arg, FIND_OBJ_INV | FIND_OBJ_ROOM | FIND_OBJ_EQ, ch, &dummy, &obj)))
	ch->Send("There doesn't seem to be %s %s here.\r\n", AN(arg), arg);
    else {
	switch (obj->item_type) {
	    default:
		ch->Send("There is nothing inside of that!\n\r");
		break;
	    case ITEM_DRINK_CON:
		if (obj->value[1] <= 0) {
		    ch->Send("It is empty.\n\r");
		    break;
		}
		ch->Send("It's %sfilled with a %s liquid.\n\r",
			obj->value[1] < obj->value[0] / 4 ? "less than half-" :
			obj->value[1] < 3 * obj->value[0] / 4 ? "about half-" :
			"more than half-", liq_table[obj->value[2]].liq_color);
		break;
	    case ITEM_CONTAINER:
	    case ITEM_CORPSE_PC:
	    case ITEM_CORPSE_NPC:
		if (IS_SET(obj->value[1], CONT_CLOSED)) {
		    ch->Send("It is closed.\n\r");
		    break;
		}
		act("$p holds:", ch, obj, 0, TO_CHAR);
		show_list_to_char(obj->contains, ch, TRUE, TRUE);
		break;
	}
    }
}

void list_scanned_chars(CHAR_DATA *list, CHAR_DATA *ch, int distance, int door) {
    CHAR_DATA *i;
    char relation;
    const char *how_far[] = {
	"close by",
	"nearby",
	"to the",
	"far off",
	"far in the distance"};
    UInt32 count = 0, one_sent = 0;

    for (i = list; i != NULL; i = i->next_in_room) {
	if (can_see(ch, i))
	    count++;
    }

    if (!count)
	return;

    for (i = list; i != NULL; i = i->next_in_room) {
	relation = relation_colors[ch->GetRelation(i)];

	if (!one_sent)
	    ch->Send("You see `%c%s", relation, RealName(i));
	else
	    ch->Send("`%c%s", relation, GetName(i));

	if (--count > 1)	ch->Send("`n, ");
	else if (count == 1)	ch->Send(" `nand ");
	else			ch->Send(" `n%s %s.\n\r", how_far[distance], dir_name[door]);
	one_sent++;
    }
}

void look_in_direction(CHAR_DATA *ch, SInt32 dir, SInt32 maxDist) {
    int distance;
    ROOM_INDEX_DATA *room = IN_ROOM(ch);

    if (EXIT(ch, dir)) {
	ch->Send(EXIT(ch, dir)->GetDesc("You see nothing special.\n\r"));
	if (EXIT(ch, dir)->keyword != NULL
	&&  EXIT(ch, dir)->keyword[0] != '\0'
	&&  EXIT(ch, dir)->keyword[0] != ' ') {
	    if (EXIT_FLAGGED(EXIT(ch, dir), EX_CLOSED))
		act("The $T is closed.\n\r", ch, 0, fname(EXIT(ch, dir)->keyword), TO_CHAR);
	    else
		act("The $T is open\n\r", ch, 0, fname(EXIT(ch, dir)->keyword), TO_CHAR);
	}
	room = CAN_GO2(room, dir) ? EXIT2(room, dir)->u1.to_room : NULL;

	for (distance = 0; (room != NULL) && (distance < maxDist); distance++) {
	    list_scanned_chars(room->people, ch, distance, dir);
	    room = CAN_GO2(room, dir) ? EXIT2(room, dir)->u1.to_room : NULL;
	}
    } else
	ch->Send("Nothing special there...\n\r");
}

void look_at_rnum(CHAR_DATA *ch, ROOM_INDEX_DATA *room, int ignore_brief) {
    void map_room(CHAR_DATA *ch, char *argument, ROOM_INDEX_DATA *room);

    if (!ch->desc || room == NULL)
	return;

    if (!check_blind(ch))
	return;

    if (room_is_dark(room) && !PLR_FLAGGED(ch, PLR_HOLYLIGHT)) {
	ch->Send("It is pitch black...\n\r");
	show_char_to_char(room->people, ch);
	return;
    }

    if (*room->p_image && !COMM_FLAGGED(ch, COMM_NOPUEBLO))
	image_to_char(ch, room->p_image);

    if (PLR_FLAGGED(ch, PLR_AUTOMAP))
	map_room(ch, "SRoom", room);
    else {
	ch->Send("`c");
	if (PLR_FLAGGED(ch, PLR_HOLYLIGHT)) {
	    ch->Send("[%5d] %s `c[%s] [%s]",
		room->vnum, room->name,
		flag_string(room_flags, room->room_flags),
		flag_string(sector_flags, room->sector_type));
	} else
	    ch->Send(room->name);

	ch->Send("`n\n\r");

	if (!COMM_FLAGGED(ch, COMM_BRIEF) || ignore_brief)
	    ch->Send("  %s", room->description);
    }

    if (PLR_FLAGGED(ch, PLR_AUTOEXIT))
	do_auto_exits(ch, room);

    show_list_to_char(room->contents, ch, FALSE, FALSE);
    show_char_to_char(room->people, ch);
    return;
}

void look_at_room(CHAR_DATA *ch, int ignore_brief) {
    if (IN_ROOM(ch) == NULL)
	char_to_room(ch, get_room_index(1));

    look_at_rnum(ch, IN_ROOM(ch), ignore_brief);
}

ACMD(do_look) {
    int look_type;

    if (!ch->desc)
	return;

    if (ch->position < POS_SLEEPING)
	ch->Send("You can't see anything but stars!\n\r");
    else if (AFF_FLAGGED(ch, AFF_BLIND))
	ch->Send("You can't see a damned thing, your blind!\n\r");
    else if (room_is_dark(IN_ROOM(ch)) && !PLR_FLAGGED(ch, PLR_HOLYLIGHT)) {
	ch->Send("It is pitch black...\n\r");
	show_char_to_char(ch->in_room->people, ch);
    } else {
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];

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

	if (!*arg1)
		look_at_room(ch, 1);
	else if (is_abbrev(arg1, "in"))
		look_in_obj(ch, arg2);
	else if (is_abbrev(arg1, "out"))
		look_out(ch);
	else if (is_abbrev(arg1, "at"))
		look_at_target(ch, arg2);
	else if ((look_type = search_block(arg1, dir_name, FALSE)) >= 0)
		look_in_direction(ch, look_type, 5);
	else
		look_at_target(ch, arg1);
    }
}

/* RT added back for the hell of it */
ACMD(do_read) {
    do_function(ch, &do_look, argument, 0);
}

ACMD(do_examine) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

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

    do_function(ch, &do_look, arg, 0);

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	switch ( obj->item_type )
	{
	default:
	    break;
	
	case ITEM_JUKEBOX:
	    do_function(ch, &do_play, "list", 0);
	    break;

	case ITEM_MONEY:
	    if (obj->value[0] == 0)
	    {
	        if (obj->value[1] == 0)
		    sprintf(buf,"Odd...there's no coins in the pile.\n\r");
		else if (obj->value[1] == 1)
		    sprintf(buf,"Wow. One gold coin.\n\r");
		else
		    sprintf(buf,"There are %d gold coins in the pile.\n\r",
			obj->value[1]);
	    }
	    else if (obj->value[1] == 0)
	    {
		if (obj->value[0] == 1)
		    sprintf(buf,"Wow. One silver coin.\n\r");
		else
		    sprintf(buf,"There are %d silver coins in the pile.\n\r",
			obj->value[0]);
	    }
	    else
		sprintf(buf,
		    "There are %d gold and %d silver coins in the pile.\n\r",
		    obj->value[1],obj->value[0]);
	    send_to_char(buf,ch);
	    break;

	case ITEM_DRINK_CON:
	case ITEM_CONTAINER:
	case ITEM_CORPSE_NPC:
	case ITEM_CORPSE_PC:
	    sprintf(buf,"in %s",argument);
	    do_function(ch, &do_look, buf, 0);
	}
    }

    return;
}



/*
 * Thanks to Zrin for auto-exit part.
 */
ACMD(do_exits) {
    int door;
    bool found;
    EXIT_DATA *pexit;
    char buf[MAX_STRING_LENGTH];

    if (!check_blind(ch))
	return;

    if (IS_IMMORTAL(ch))
	sprintf(buf,"Obvious exits from room %d:\n\r",ch->in_room->vnum);
    else
	sprintf(buf,"Obvious exits:\n\r");

    found = FALSE;
    for ( door = 0; door <= 5; door++ )
    {
	if ((pexit = ch->in_room->exit[door]) != NULL
	&&   pexit->u1.to_room != NULL
	&&   can_see_room(ch,pexit->u1.to_room) 
	&&   can_see_ex_hidden(ch,ch->in_room->exit[door]))
	{
	    found = TRUE;
	    sprintf( buf + strlen(buf), "%-5s - %s",
		    capitalize( dir_name[door] ),
		    room_is_dark( pexit->u1.to_room )
			?  "Too dark to tell"
			: pexit->u1.to_room->name);
		if (IS_IMMORTAL(ch))
		    sprintf(buf + strlen(buf), 
			" (room %d)\n\r",pexit->u1.to_room->vnum);
		else
		    sprintf(buf + strlen(buf), "\n\r");
	}
    }

    if (!found)
	strcat(buf, "None.\n\r");

    send_to_char(buf, ch);
    return;
}

ACMD(do_worth) {
    char buf[MAX_STRING_LENGTH];

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

    sprintf(buf, 
    "You have %ld gold, %ld silver, and %d experience (%d exp to level).\n\r",
	ch->gold, ch->silver,ch->exp,
	exp_per_level(ch, ch->pcdata->points) *
	(IS_REAL_HERO(ch) ? (ch->level+ch->hero_level+1) : (ch->level+1))
	- ch->exp);
    send_to_char(buf,ch);

    return;
}

ACMD(do_score) {
    CHAR_DATA *vict;
    bool other = FALSE;
    int  tempP=0, tempM=0, tempT=0;
    char buf[MAX_STRING_LENGTH], arg[MIL];

    argument = one_argument(argument, arg);

    if (arg[0] == '\0')
	vict = ch;
    else if (IS_IMMORTAL(ch)) {
	if ((vict = get_char_world(ch, arg)) == NULL) {
		send_to_char("No such player.\r\n",ch);
		return;
	}
	if (get_trust(vict) >= get_trust(ch))
		vict = ch;
    } else 
	vict = ch;
    if (vict == NULL)	return;
    if (vict != ch)	other = TRUE;

    if (AFF_FLAGGED(vict, AFF_SHAPESHIFT))
	sprintf(buf, "%s morphed into: %s", other ? "$N is" : "You are",
	vict->morph);
    else {
	sprintf(buf,
		"%s %s%s%s, %slevel %d",
		other ? "$E is" : "You are",
		IS_NPC(vict) ? vict->short_descr : GET_CNAME(vict),
		IS_NPC(vict) ? "" : vict->lname,
		IS_NPC(vict) ? "" : vict->pcdata->title,
		IS_REAL_HERO(vict) ? "hero " : "",
		IS_REAL_HERO(vict) ? vict->hero_level : vict->level);
	if (get_trust(vict) != vict->level)
		sprintf(buf + strlen(buf), " (trust %d)", get_trust(vict));
	strcat(buf, ".");
    }
    act(buf, ch, NULL, vict, TO_CHAR);

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

    if (!IS_NPC(vict)) {
	ch->Send("%s (%d hours).\n\r",
	other_age(vict->createtime),
	(vict->played + (int) (current_time - vict->logon)) / 3600);
    }

    ch->Send(
	"You have %d/%d hit, %d/%d mana, and %d/%d moves.\n\r",
	vict->hit,  vict->max_hit,
	vict->mana, vict->max_mana,
	vict->move, vict->max_move);

    ch->Send(
	"You have %ld gold coins, %ld silver coins (0 gold in bank).\n\r",
	vict->gold, vict->silver);

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

    sprintf(buf,
	"You have scored %d exp (%d exp to level).\n\r",
	vict->exp,
	!IS_NPC(vict) ? ((IS_REAL_HERO(vict) ? (vict->level+vict->hero_level+1) :
	(vict->level+1)) * exp_per_level(vict, vict->pcdata->points) - vict->exp) : 0);
    send_to_char(buf, ch);

    /* Print Kill/Death Ratios */
    if (!IS_NPC(vict)) {
	tempP = vict->pkill;
	tempM = vict->mkill;
	tempT = tempP + tempM;
	ch->Send(
	"You have killed %d beings (%d (%d%%) players, %d (%d%%) mobs).\r\n",
		tempP + tempM, tempP, tempT ? (tempP * 100)/tempT : 0,
		tempM, tempT ? (tempM * 100)/tempT : 0);

	tempP = vict->pdeath;
	tempM = vict->mdeath;
	tempT = tempP + tempM;
	ch->Send(
	"You have been killed by %d beings (%d (%d%%) players, %d (%d%%) mobs).\r\n",
		tempP + tempM, tempP, tempT ? (tempP * 100)/tempT : 0,
		tempM, tempT ? (tempM * 100)/tempT : 0);
    }

    if (GET_COND(vict, COND_DRUNK) >= 10)
	send_to_char("You are drunk.\n\r",ch);
    if (GET_COND(vict, COND_HANGOVER) > 0)
	send_to_char("You are aching with a hangover.\n\r", ch);
    if (GET_COND(vict, COND_THIRST) == 0)
	send_to_char("You are thirsty.\n\r",ch);
    if (GET_COND(vict, COND_THIRST) == 0)
	send_to_char("You are hungry.\n\r",ch);

    switch (vict->position)
    {
    case POS_DEAD:
	send_to_char("You are DEAD!!\n\r",ch);
	break;
    case POS_MORTAL:
	send_to_char("You are mortally wounded.\n\r",ch);
	break;
    case POS_INCAP:
	send_to_char("You are incapacitated.\n\r",ch);
	break;
    case POS_STUNNED:
	send_to_char("You are stunned.\n\r",ch);
	break;
    case POS_SLEEPING:
	send_to_char("You are sleeping.\n\r",ch);
	break;
    case POS_RESTING:
	send_to_char("You are resting.\n\r",ch);
	break;
    case POS_SITTING:
	send_to_char("You are sitting.\n\r",ch);
	break;
    case POS_STANDING:
	send_to_char("You are standing.\n\r",ch);
	break;
    case POS_FIGHTING:
	if (ch->fighting)
		ch->Send("You are fighting %s.\n\r", PERS(ch->fighting, ch));
	else
		send_to_char("You are fighting thin air.\n\r",ch);
	break;
    default:
	ch->position = POS_STANDING;
	send_to_char("You have no idea how, but this is a bug.\n\r",ch);
	break;
    }

    if (COMM_FLAGGED(ch, COMM_SHOW_AFFECTS) && (vict == ch))
	do_function(ch, &do_affects, "", 0);
}

char *get_align_desc(int align) {
	if (align > 900)	return "angelic";
	else if (align > 700)	return "saintly";
	else if (align > 350)	return "good";
	else if (align > 100)	return "kind";
	else if (align > -100)	return "neutral";
	else if (align > -350)	return "mean";
	else if (align > -700)	return "evil";
	else if (align > -900)	return "demonic";
	else			return "satanic";
}

ACMD(do_attributes) {
    int i;
    CHAR_DATA *vict;
    char buf[MAX_STRING_LENGTH], arg[MIL];
    static char * const he_she[] = { "It",  "He",  "She" };

	argument = one_argument(argument, arg);
	if (arg[0] == '\0')
		vict = ch;
	else if (IS_IMMORTAL(ch)) {
		vict = get_char_world(ch, arg);
		if (!vict) {
			send_to_char("No such player.\r\n",ch);
			return;
		}
		if (get_trust(vict) >= get_trust(ch))
			vict = ch;
	} else
		vict = ch;
    if (!vict) // Sanity crazy! Sense no make!
	return;

    ch->Send(
	"Character attributes for %s\r\n"
	"Str: %2d (%2d)  Int: %2d (%2d)  Wis: %2d (%2d)\r\n"
	"Dex: %2d (%2d)  Con: %2d (%2d)  Cha: %2d (%2d)\r\n"
	"Hitroll: %3d  Damroll: %3d\r\n"
	"%s %s of %s alignment",
	IS_NPC(vict) ? vict->short_descr : vict->name,
	vict->perm_stat[STAT_STR], get_curr_stat(vict,STAT_STR),
	vict->perm_stat[STAT_INT], get_curr_stat(vict,STAT_INT),
	vict->perm_stat[STAT_WIS], get_curr_stat(vict,STAT_WIS),
	vict->perm_stat[STAT_DEX], get_curr_stat(vict,STAT_DEX),
	vict->perm_stat[STAT_CON], get_curr_stat(vict,STAT_CON),
	vict->perm_stat[STAT_CHA], get_curr_stat(vict,STAT_CHA),
	GET_HITROLL(vict), GET_DAMROLL(vict),
	(ch == vict) ? "You" : he_she[vict->sex],
	(ch == vict) ? "are" : "is",
	get_align_desc(vict->alignment));

    if (ch->level >= 10)
	ch->Send(" (%d)", vict->alignment);
    send_to_char(".\r\n", ch);

    for (i = 0; i < 4; i++)
    {
	char * temp;
	switch(i)
	{
	    case(AC_PIERCE):    temp = "piercing";      break;
	    case(AC_BASH):      temp = "bashing";       break;
	    case(AC_SLASH):     temp = "slashing";      break;
	    case(AC_EXOTIC):    temp = "magic";         break;
	    default:            temp = "error";         break;
	}
	if (ch == vict)
		send_to_char("You are ", ch);
	else
		ch->Send("%s is ", he_she[vict->sex]);

	if (GET_AC(vict,i) >= 101)
	    sprintf(buf,"hopelessly vulnerable to %s",temp);
	else if (GET_AC(vict,i) >= 80)
	    sprintf(buf,"defenseless against %s",temp);
	else if (GET_AC(vict,i) >= 60)
	    sprintf(buf,"barely protected from %s",temp);
	else if (GET_AC(vict,i) >= 40)
	    sprintf(buf,"slightly armored against %s",temp);
	else if (GET_AC(vict,i) >= 20)
	    sprintf(buf,"somewhat armored against %s",temp);
	else if (GET_AC(vict,i) >= 0)
	    sprintf(buf,"armored against %s",temp);
	else if (GET_AC(vict,i) >= -20)
	    sprintf(buf,"well-armored against %s",temp);
	else if (GET_AC(vict,i) >= -40)
	    sprintf(buf,"very well-armored against %s",temp);
	else if (GET_AC(vict,i) >= -60)
	    sprintf(buf,"heavily armored against %s",temp);
	else if (GET_AC(vict,i) >= -80)
	    sprintf(buf,"superbly armored against %s",temp);
	else if (GET_AC(vict,i) >= -100)
	    sprintf(buf,"almost invulnerable to %s",temp);
	else
	    sprintf(buf,"divinely armored against %s",temp);

	if (ch->level >= 25)
		sprintf(buf + strlen(buf), " (%d)", GET_AC(vict, i));
	strcat(buf, ".\r\n");
	send_to_char(buf,ch);
    }

}

ACMD(do_affects) {
    AFFECT_DATA *paf, *paf_last = NULL;
    char buf[MAX_STRING_LENGTH];
    
    if ( ch->affected != NULL )
    {
	send_to_char( "You are affected by the following spells:\n\r", ch );
	for ( paf = ch->affected; paf != NULL; paf = paf->next )
	{
	    if (paf_last != NULL && paf->type == paf_last->type)
		if (ch->level >= 20)
		    sprintf( buf, "                      ");
		else
		    continue;
	    else
	    	sprintf( buf, "Spell: %-15s", skill_table[paf->type].name );

	    send_to_char( buf, ch );

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

	    send_to_char( "\n\r", ch );
	    paf_last = paf;
	}
    }
    else 
	send_to_char("You are not affected by any spells.\n\r",ch);

    return;
}

ACMD(do_toggle) {
	char buf[MSL];

	if (IS_NPC(ch))
		return;

	if (ch->wimpy == 0)
		strcpy(buf, "OFF");
	else
		sprintf(buf, "%-4d", ch->wimpy);

	ch->Send(
		"`y[`GGeneral Config`y]`n\r\n"
		"     Brief Mode: %-3s    "" Summon Protect: %-3s    ""   Compact Mode: %-3s\r\n"
		"    Corpse Safe: %-3s    ""      AutoExits: %-3s    ""      Followers: %-3s\r\n"
		"     ANSI Color: %-3s    ""         Pueblo: %-3s    ""      MSP Sound: %-3s\r\n"
		"`y[`GChannels      `y]`n\r\n"
		"           Chat: %-3s    ""          Music: %-3s    ""          Grats: %-3s\r\n"
		"           Info: %-3s    ""          Shout: %-3s    ""           Tell: %-3s\r\n"
		"          QTalk: %-3s    ""           Clan: %-3s\r\n"
		"`y[`GGame Specifics`y]`n\r\n"
		"            AFK: %-3s    ""     Wimp Level: %-3s\r\n",
		ONOFF(COMM_FLAGGED(ch, COMM_BRIEF)),
		ONOFF(PLR_FLAGGED(ch, PLR_NOSUMMON)),
		ONOFF(COMM_FLAGGED(ch, COMM_COMPACT)),
		YESNO(!PLR_FLAGGED(ch, PLR_CANLOOT)),
		ONOFF(PLR_FLAGGED(ch, PLR_AUTOEXIT)),
		YESNO(!PLR_FLAGGED(ch, PLR_NOFOLLOW)),
		ONOFF(PLR_FLAGGED(ch, PLR_COLOUR)),
		ONOFF(PLR_FLAGGED(ch, PLR_PUEBLO)),
		ONOFF(PLR_FLAGGED(ch, PLR_MSP)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOGOSSIP)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOMUSIC)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOGRATS)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOINFO)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOSHOUT)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOTELL)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOQUEST)),
		ONOFF(!COMM_FLAGGED(ch, COMM_NOCLAN)),
		ONOFF(COMM_FLAGGED(ch, COMM_AFK)), buf);

    if (IS_IMMORTAL(ch)) {
	char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
	static char * const syslog_desc	[] = { "OFF", "BRF", "NRM", "CMP" };
	sh_int tp = ((PLR_FLAGGED(ch, PLR_LOG1) ? 1 : 0) +
		(PLR_FLAGGED(ch, PLR_LOG2) ? 2 : 0));
	if (ch->invis_level)
		sprintf(buf1, "%d", ch->invis_level);
	else
		sprintf(buf1, "OFF");
	if (ch->incog_level)
		sprintf(buf2, "%d", ch->incog_level);
	else
		sprintf(buf2, "OFF");

	ch->Send(
		"`y[`GStaff Config  `y]`n\n\r"
		"        Immtalk: %-3s    ""      Holylight: %-3s    ""         Syslog: %-3s\n\r"
		"       Nohassle: %-3s    ""       WizInvis: %-3s    ""      Incognito: %-3s\n\r",
		ONOFF(!COMM_FLAGGED(ch, COMM_NOWIZ)),
		ONOFF(PLR_FLAGGED(ch, PLR_HOLYLIGHT)),
		syslog_desc[tp],
		ONOFF(PLR_FLAGGED(ch, PLR_NOHASSLE)),
		buf1, buf2);
    }
    return;
}

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

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

ACMD(do_time) {
    extern char str_boot_time[];
    char buf[MAX_STRING_LENGTH];
    char *suf, *str_current_time;
    int day;

    day     = time_info.day + 1;
    str_current_time = (char *) ctime( &current_time );
    *(str_current_time+strlen(str_current_time)-1) = '\0';

         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.\n\r"
	"%d%s Day of %s, Month of %s.\n\r",
	(time_info.hour % 12 == 0) ? 12 : time_info.hour %12,
	time_info.hour >= 12 ? "pm" : "am",
	day, suf,
	day_name[day % 7],
	month_name[time_info.month]);
    send_to_char(buf,ch);
    sprintf(buf,"Rogue started up at %s.\n\r"
		"The system time is %s.\n\r",
	str_boot_time, str_current_time);
    send_to_char( buf, ch );
    return;
}



ACMD(do_weather) {
    char buf[MAX_STRING_LENGTH];

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

    if ( !IS_OUTSIDE(ch) )
    {
	send_to_char( "You can't see the weather indoors.\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"
	);
    send_to_char( buf, ch );
    return;
}

ACMD(do_help) {
    HELP_DATA *pHelp;
    BUFFER *output;
    bool found = FALSE;
    char argall[MAX_INPUT_LENGTH],argone[MAX_INPUT_LENGTH];
    int level;

    output = new_buf();

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

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

    for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next )
    {
    	level = (pHelp->level < 0) ? -1 * pHelp->level - 1 : pHelp->level;

	if (level > get_trust( ch ) )
	    continue;

	if ( is_name( argall, pHelp->keyword ) )
	{
	    /* add seperator if found */
	    if (found)
		add_buf(output,
    "\n\r============================================================\n\r\n\r");
	    if ( pHelp->level >= 0 && str_cmp( argall, "imotd" ) )
	    {
		add_buf(output,pHelp->keyword);
		add_buf(output,"\n\r");
	    }

	    /*
	     * Strip leading '.' to allow initial blanks.
	     */
	    if ( pHelp->text[0] == '.' )
		add_buf(output,pHelp->text+1);
	    else
		add_buf(output,pHelp->text);
	    found = TRUE;
	    /* small hack :) */
	    if (ch->desc != NULL && ch->desc->connected != CON_PLAYING 
	    &&  		    ch->desc->connected != CON_GEN_GROUPS)
		break;
	}
    }

    if (!found) {
    	send_to_char( "No help on that word.\n\r", ch );
	mudlogf(CMP, LVL_STAFF, TRUE, "%s tried to get help on: %s",ch->name, argall);
    } else
	page_to_char(buf_string(output),ch);
    free_buf(output);
}


/*
 * New 'who' command originally by Alander of Rivers of Mud,
 * Modified by Mendanbar/Kerrigan of StarCraft MUD.
 */
char *WHO_USAGE =
	"Usage: who [minlev[-maxlev]] [-n name] [-r races] [-c classes] [-wzsp]\n\r"
	"\n\r"
	"Races:\n\r"
	" (H)uman, (E)lf, (D)warf, (G)iant\n\r"
	"\n\r"
	"Classes:\n\r"
	" (M)age, (C)leric, (T)hief, (W)arrior, (R)anger, (D)ruid, (P)sionic, (B)ard\n\r"
	"\n\r"
	"Switches:\n\r"
	" -w = who is in the current room\n\r"
	" -z = who is in the current zone\n\r"
	" -s = only show staff\n\r"
	" -p = only show players\n\r";

ACMD(do_who) {
    DESCRIPTOR_DATA *d;
    char	mode;
    char	arg[MAX_INPUT_LENGTH],
		buf[MAX_STRING_LENGTH],
		staff_buf[MAX_STRING_LENGTH],
		player_buf[MAX_STRING_LENGTH],
		name_search[MAX_INPUT_LENGTH];
    SInt32	low = 0, high = MAX_LEVEL,
		iRace = 0, iClass = 0,
		staff = 0, players = 0, i = 0;
    bool	who_room = FALSE, who_zone = FALSE,
		no_staff = FALSE, no_players = FALSE,
		who_race = FALSE, who_class = FALSE,
		showrace[MAX_PC_RACE], showclass[MAX_CLASS];

    name_search[0] = '\0';
    for (iRace = 0; iRace < MAX_PC_RACE; iRace++)
	showrace[iRace] = FALSE;
    for (iClass = 0; iClass < MAX_CLASS; iClass++)
	showclass[iClass] = FALSE;
 
    /*
     * Parse arguments.
     */
    while (*argument) {
	argument = one_argument(argument, arg);
	if (isdigit(*arg)) {
		sscanf(arg, "%d-%d", &low, &high);
	} else if (*arg == '-') {
		mode = *(arg + 1);
		switch (mode) {
			case 'z':
				who_zone = TRUE;
				break;
			case 'l':
				argument = one_argument(argument, arg);
				sscanf(arg, "%d-%d", &low, &high);
				break;
			case 'n':
				argument = one_argument(argument, name_search);
				break;
			case 'w':
				who_room = TRUE;
				break;
			case 's':
				no_players = TRUE;
				break;
			case 'p':
				no_staff = TRUE;
				break;
			case 'r':
				argument = one_argument(argument, arg);
				who_race = TRUE;
				for (i = 0; i < strlen(arg); i++) {
					iRace = find_race_bitvector(arg[i]);
					showrace[iRace] = TRUE;
				}
				break;
			case 'c':
				argument = one_argument(argument, arg);
				who_class = TRUE;
				for (i = 0; i < strlen(arg); i++) {
					iClass = find_class_bitvector(arg[i]);
					showclass[iClass] = TRUE;
				}
				break;
			case 'h':
			default:
				send_to_char(WHO_USAGE, ch);
				return;
		}
	} else {
		send_to_char(WHO_USAGE, ch);
		return;
	}
    }

    /*
     * Now show matching chars.
     */

        strcpy(staff_buf,       "Staff currently online\r\n"
                                "----------------------\r\n");
        strcpy(player_buf,      "Players currently online\r\n"
                                "------------------------\r\n");

  for (i = MAX_LEVEL; i >= 0; i--) {
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *wch;
        char const *pClass;

        /*
         * Check for match against restrictions.
         * Don't use trust as that exposes trusted mortals.
         */
	if (STATE(d) != CON_PLAYING)			continue;
	if (!(wch = Original(d)))			continue;
	if (!can_see(ch, wch))				continue;
	if (wch->level != i)				continue;
	if ((wch->level < low) || (wch->level > high))	continue;
	if ((no_staff && IS_STAFF(wch)) || (no_players && !IS_STAFF(wch)))
		continue;
	if (*name_search && str_cmp(RealName(wch), name_search) && !strstr(wch->pcdata->title, name_search))
		continue;
	if (who_zone && IN_ROOM(ch)->area != IN_ROOM(wch)->area)
		continue;
	if (who_room && (IN_ROOM(ch) != IN_ROOM(wch)))
		continue;
	if (who_race && !showrace[wch->race])
		continue;
	if (who_class && !showclass[wch->Class])
		continue;

	pClass = class_table[wch->Class].who_name;

	if (wch->level >= LEVEL_IMMORTAL) {
		if (wch->pcdata->immtitle[0] != '\0')
			pClass = wch->pcdata->immtitle;
		else
			pClass = get_cat(GET_CATEGORY(wch));
	}
	/*
	 * Format it up.
	 */
	*buf = '\0';

        if (IS_STAFF(wch)) {
	        sprintf(buf, "`y %s`y %s%s%s`n",
			pClass, wch->name, wch->lname, wch->pcdata->title);
	staff++;
	} else if (IS_REAL_HERO(wch)) {
		sprintf(buf, "`n[%3d %3s %3s] `%c%s%s%s`n",
			wch->hero_level,
			pc_race_table[wch->race].who_name,
			"`YHRO`n", relation_colors[ch->GetRelation(wch)],
			wch->name, wch->lname, wch->pcdata->title);
	players++;
	} else {
		sprintf(buf, "`n[%3d %3s %3s] `%c%s%s%s`n",
			wch->level,
			pc_race_table[wch->race].who_name,
			class_table[wch->Class].who_name,
			relation_colors[ch->GetRelation(wch)],wch->name,
			wch->lname, wch->pcdata->title);
	players++;
	}
	if (IS_AFFECTED(wch, AFF_INVISIBLE))	strcat(buf, " `n(`winvis`n)");
	if (wch->invis_level > 0) sprintf(buf + strlen(buf), " `n(`ww%d`n)",wch->invis_level);
	if (wch->incog_level > 0) sprintf(buf + strlen(buf), " `w(`yi%d`w)`n",wch->incog_level);
	if (PLR_FLAGGED(wch, PLR_WRITING))	strcat(buf, " `n(`rwriting`n)");
	if (IS_SET(wch->act, PLR_KILLER))	strcat(buf, " `R(KILLER)`n");
	if (IS_SET(wch->act, PLR_THIEF))	strcat(buf, " `B(THIEF)`n");
	if (is_clan(wch))
		sprintf(buf + strlen(buf), " `n<%s`n>",clan_table[wch->clan].who_name);
	if (IS_SET(wch->comm, COMM_AFK)) strcat(buf, " `c[AFK]`n");
		strcat(buf, "`n\r\n");

	if (IS_STAFF(wch))      strcat(staff_buf, buf);
	else                    strcat(player_buf, buf);
    }
  }
	*buf = '\0';
        if (staff) {
                strcat(buf, staff_buf);
                strcat(buf, "\r\n");
        }
        if (players) {
                strcat(buf, player_buf);
                strcat(buf, "\r\n");
        }

	if ((staff + players) == 0) {
        strcat(buf, "No staff or players are currently visible to you.\r\n");
        }
        if (staff)
		sprintf(buf + strlen(buf), "There %s %d visible staff%s", (staff == 1 ? "is" : "are"), staff, players ? " and there" : ".");
        if (players)
	sprintf(buf + strlen(buf), "%s %s %d visible player%s.", staff ? "" : "There", (players == 1 ? "is" : "are"), players, (players == 1 ? "" : "s"));
        strcat(buf, "\r\n");
        if ((staff + players) > boot_high)
                boot_high = staff+players;

	sprintf(buf + strlen(buf), "There is a boot time high of %d player%s.\r\n", boot_high, (boot_high == 1 ? "" : "s"));
	page_to_char(buf, ch);
	return;
}

ACMD(do_count) {
    int count;
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    count = 0;

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

    max_on = UMAX(count,max_on);

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

    send_to_char(buf,ch);
}

ACMD(do_inventory) {
    send_to_char( "You are carrying:\n\r", ch );
    show_list_to_char( ch->carrying, ch, TRUE, TRUE );
    return;
}



ACMD(do_equipment) {
    OBJ_DATA *obj;
    int iWear;
    bool found;

    send_to_char( "You are using:\n\r", ch );
    found = FALSE;
    for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
    {
	if ( ( obj = get_eq_char( ch, iWear ) ) == NULL )
	    continue;

	send_to_char( where_name[iWear], ch );
	if ( can_see_obj( ch, obj ) )
	{
	    send_to_char( format_obj_to_char( obj, ch, TRUE ), ch );
	    send_to_char( "\n\r", ch );
	}
	else
	{
	    send_to_char( "something.\n\r", ch );
	}
	found = TRUE;
    }

    if ( !found )
	send_to_char( "Nothing.\n\r", ch );

    return;
}



ACMD(do_compare) {
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj1;
    OBJ_DATA *obj2;
    int value1;
    int value2;
    char *msg;

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

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

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

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

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

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

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

	case ITEM_ARMOR:
	    value1 = obj1->value[0] + obj1->value[1] + obj1->value[2];
	    value2 = obj2->value[0] + obj2->value[1] + obj2->value[2];
	    break;

	case ITEM_WEAPON:
	    if (obj1->pIndexData->new_format)
		value1 = (1 + obj1->value[2]) * obj1->value[1];
	    else
	    	value1 = obj1->value[1] + obj1->value[2];

	    if (obj2->pIndexData->new_format)
		value2 = (1 + obj2->value[2]) * obj2->value[1];
	    else
	    	value2 = obj2->value[1] + obj2->value[2];
	    break;
	}
    }

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

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



ACMD(do_credits) {
    do_function(ch, &do_help, "diku", 0);
    return;
}



ACMD(do_where) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    DESCRIPTOR_DATA *d;
    bool found;

    one_argument( argument, arg );

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

    return;
}




ACMD(do_consider) {
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char *msg;
    int diff;

    one_argument( argument, arg );

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

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

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

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

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

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



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

    if (IS_NPC(ch))
    {
	mudlogf(BRF, LVL_CODER, TRUE, "SYSERR: set_title: trying to set NPC title.");
	return;
    }

    if ( title[0] != '.' && title[0] != ',' && title[0] != '!' && title[0] != '?' )
    {
	buf[0] = ' ';
	strcpy( buf+1, title );
    }
    else
    {
	strcpy( buf, title );
    }

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



ACMD(do_title) {
    int i,color = 0, realsize = 0;

    if ( IS_NPC(ch) )
	return;

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

    smash_tilde( argument );

    for ( i = 0; i < strlen(argument); i++ )
    {
        if ( argument[i] == '`' )
            color++;
    }
    color *= 2;
    realsize = strlen(argument) - color;

    if ( realsize > 45 )
    {
	send_to_char("Title string too long. Try again.\n\r",ch);
	return;
    }
    set_title( ch, argument );
    send_to_char( "Ok.\n\r", ch );
}


ACMD(do_report) {
    char buf[MAX_INPUT_LENGTH];

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

    send_to_char( buf, ch );

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

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

    return;
}



ACMD(do_practice) {
    char buf[MAX_STRING_LENGTH];
    int sn;

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	int col = 0;
	BUFFER *output = new_buf();

	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name == NULL )
		break;
	    if ( ch->level < skill_table[sn].skill_level[ch->Class] 
	      || ch->pcdata->learned[sn] < 1 /* skill is not known */)
		continue;

	    sprintf( buf, "%-18s %3d%%  ",
		skill_table[sn].name, ch->pcdata->learned[sn] );
	    add_buf(output, buf);
	    if ( ++col % 3 == 0 )
		add_buf(output, "\n\r");
	}

	if ( col % 3 != 0 )
	    add_buf(output, "\n\r");

	sprintf(buf, "You have %d practice sessions left.\n\r",
	    ch->practice);
	add_buf(output, buf);
	page_to_char(buf_string(output), ch);
	free_buf(output);
	return;
    }
    else
    {
	CHAR_DATA *mob;
	int adept;

	if ( !IS_AWAKE(ch) )
	{
	    send_to_char( "In your dreams, or what?\n\r", ch );
	    return;
	}

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

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

	if ( ch->practice <= 0 )
	{
	    send_to_char( "You have no practice sessions left.\n\r", ch );
	    return;
	}

	if ( ( sn = find_spell( ch,argument ) ) < 0
	|| ( !IS_NPC(ch)
	&&   (ch->level < skill_table[sn].skill_level[ch->Class] 
 	||    ch->pcdata->learned[sn] < 1 /* skill is not known */
	||    skill_table[sn].rating[ch->Class] == 0)))
	{
	    send_to_char( "You can't practice that.\n\r", ch );
	    return;
	}

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

	if ( ch->pcdata->learned[sn] >= adept )
	{
	    sprintf( buf, "You are already learned at %s.\n\r",
		skill_table[sn].name );
	    send_to_char( buf, ch );
	}
	else
	{
	    ch->practice--;
	    ch->pcdata->learned[sn] += 
		int_app[get_curr_stat(ch,STAT_INT)].learn / 
	        skill_table[sn].rating[ch->Class];
	    if ( ch->pcdata->learned[sn] < adept )
	    {
		act( "You practice $T.",
		    ch, NULL, skill_table[sn].name, TO_CHAR );
		act( "$n practices $T.",
		    ch, NULL, skill_table[sn].name, TO_ROOM );
	    }
	    else
	    {
		ch->pcdata->learned[sn] = adept;
		act( "You are now learned at $T.",
		    ch, NULL, skill_table[sn].name, TO_CHAR );
		act( "$n is now learned at $T.",
		    ch, NULL, skill_table[sn].name, TO_ROOM );
	    }
	}
    }
    return;
}



/*
 * 'Wimpy' originally by Dionysos.
 */
ACMD(do_wimpy) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int wimpy;

    one_argument( argument, arg );

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

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

    if ( wimpy > ch->max_hit/2 )
    {
	send_to_char( "Such cowardice ill becomes you.\n\r", ch );
	return;
    }

    ch->wimpy	= wimpy;
    sprintf( buf, "Wimpy set to %d hit points.\n\r", wimpy );
    send_to_char( buf, ch );
    return;
}



ACMD(do_password) {
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char *pArg;
    char *pwdnew;
    char *p;
    char cEnd;

    if ( IS_NPC(ch) )
	return;

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

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

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

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

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

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

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

    if ( strcmp( crypt( arg1, ch->pcdata->pwd ), ch->pcdata->pwd ) )
    {
	WAIT_STATE( ch, 40 );
	send_to_char( "Wrong password.  Wait 10 seconds.\n\r", ch );
	return;
    }

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

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

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