/
roa/
roa/lib/boards/
roa/lib/config/
roa/lib/edits/
roa/lib/help/
roa/lib/misc/
roa/lib/plrobjs/
roa/lib/quests/
roa/lib/socials/
roa/lib/www/
roa/lib/www/LEDSign/
roa/lib/www/LEDSign/fonts/
roa/lib/www/LEDSign/scripts/
roa/src/s_inc/
roa/src/sclient/
roa/src/sclient/binary/
roa/src/sclient/text/
roa/src/util/
/************************************************************************
	Realms of Aurealis 		James Rhone aka Vall of RoA

info.c				Commands of an informative nature for
				players such as do_who, do_score, etc.
				Most generic 'informational' things that
				a character has access to can be found
				here.

		******** Heavily modified and expanded ********
		*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
		******** Heavily modified and expanded ********
		        All rights reserved henceforth. 

    Please note that no guarantees are associated with any code from
Realms of Aurealis.  All code which has been released to the general
public has been done so with an 'as is' pretense.  RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license.   *** Read, Learn, Understand, Improve ***
*************************************************************************/
#include "conf.h"
#include "sysdep.h"

#include "structures.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "acmd.h"
#include "handler.h"
#include "db.h"
#include "magic.h"
#include "mudlimits.h"
#include "screen.h"
#include "quest.h"
#include "affect.h"
#include "lists.h"
#include "shaman.h"
#include "plshop.h"
#include "global.h"
#include "boards.h"
#include "htown.h"
#include "darkenelf.h"
#include "thief.h"

/* extern variables */
extern struct htown_data 	htowns[];
extern int 		exp_table[NUM_CLASSES][MAX_LEVELS];
extern char 		*affected_bits[];
extern char 		*affected2_bits[];
extern char 		*trap_types[];
extern char 		*genders[];
extern char 		*material_types[];
extern char 		*song_names_cap[];
extern char		*dirs[];
extern char		*sh_dirs[];
extern char		*where[];
extern char		*wv_bits[];
extern char		*armor_where[];
extern char		*color_liquid[];
extern char		*fullness[];
extern char		*class_abbrevs[];
extern char		*room_bits[];
extern char		*room_bits2[];
extern struct str_app_type str_app[];
extern char *time_format_1(time_t dt);
extern char *time_format_2(time_t dt);

// external functions
extern chdata *get_mount_in_room(chdata *ch);
extern chdata *get_mounter(chdata *ch);
extern void clear_who_list(void);
extern int num_remorts(chdata *ch);
extern int IdListMember(IdList * member, long idnum);
extern void uptime_to_buf(char *buf);
extern void date_to_buf(char *buf);

// internal vars
int	num_of_cmds;

// internal functionns
void list_obj_to_char(obdata *list, chdata *ch, int mode, BOOL show);

// following modes are for show_object and list_object functions
#define O_ROOM_MODE	0
#define O_INV_MODE	1
#define O_CONTAINS_MODE	2
#define O_EXAM_COMP  	3
#define O_EXAM_MIN 	4

#define CHAR_LIST	0
#define CHAR_LOOK	1
#define CHAR_LOOK_INV	2

#define CHAR_LIST_LONG  0
#define CHAR_LIST_SHORT 1

// can_see changed froma very confusing macro to function call
int can_see(chdata *ch, chdata *vict)
{
  int l_ok      = FALSE;
  int light_ok  = FALSE;
  int invis_ok  = FALSE;

  // if foggy room and not fog caster, no can see 3/2/98 -jtrhone
  if (!IS_IMMORTAL(ch) && spell_affects_room(ch->in_room, SPELL_WALLOFFOG) &&
      !char_spell_affects_room(ch, SPELL_WALLOFFOG, ch->in_room))
    return FALSE;

  if (!IS_IMMORTAL(ch) && spell_affects_room(ch->in_room, SPELL_OCCLUSION) &&
      !char_spell_affects_room(ch, SPELL_OCCLUSION, ch->in_room))
    return FALSE;

  if (!IS_IMMORTAL(ch) && spell_affects_room(vict->in_room, SPELL_WALLOFFOG) &&
      !char_spell_affects_room(ch, SPELL_WALLOFFOG, vict->in_room))
    return FALSE;

  if (!IS_IMMORTAL(ch) && spell_affects_room(vict->in_room, SPELL_OCCLUSION) &&
      !char_spell_affects_room(ch, SPELL_OCCLUSION, vict->in_room))
    return FALSE;

  if (!IS_IMMORTAL(ch) && ROOM_FLAGGED2(ch->in_room, WALLOFFOG))
    return FALSE;

  if (!IS_IMMORTAL(ch) && IS_AFFECTED(ch, AFF_BLIND))
    return FALSE;

  if (ch == vict)
    return TRUE;

  if (IdListMember(vict->concealed, GET_IDNUM(ch)))	// 03/22/98 -callahan
    return FALSE;

  // no matter what, can see an NPC
  if (IS_IMMORTAL(ch) && IS_NPC(vict))
    return TRUE;

  if ((IS_PC(vict) && GET_LEVEL(ch) >= GET_INVIS_LEV(vict)) || IS_NPC(vict))
    l_ok = TRUE;

  if (IS_IMMORTAL(ch) && PRF_FLAGGED(ch, PRF_HOLYLIGHT) && l_ok)
    return TRUE;

  if (!IS_AFFECTED(vict, AFF_INVISIBLE) || IS_AFFECTED(ch, AFF_DETECT_INVISIBLE))
    invis_ok = TRUE;

  // Added for reveal. 03/22/98 -callahan
  if (!l_ok && IdListMember(vict->revealed, GET_IDNUM(ch)))
    l_ok = TRUE;

  if (!invis_ok && IdListMember(vict->revealed, GET_IDNUM(ch)))
    invis_ok = TRUE;

  if (IS_LIGHT(ch->in_room) || IS_AFFECTED(ch, AFF_INFRARED) || IS_DROW(ch))
    light_ok = TRUE;

  return (l_ok && invis_ok && light_ok);
}

// scan an extra descrip llist, if keyword matches, return description
char	*find_exdesc(char *word, exdescdata *list)
{
   exdescdata *i;
   for (i = list; i; i = i->next)
      if (isname(word, i->keyword))
	 return(i->description);
   return(NULL);
}

// for short eq listings, if the object is below a certain
// condition, tack an asterisk on the end... 12/15/97 -jtrhone
void damage_asterisk(obdata *o, char *buf)
{
  float condition;

  if (MAX_OBJ_HITS(o) <= 0)
    return;
  else
  {
    condition = ((float) OBJ_HITS(o) / (float) MAX_OBJ_HITS(o) * 100.0);
    if (condition <= 25.0)
      strcat(buf, "%B%1*%0");
    else
    if (condition <= 50.0)
      strcat(buf, "%1*%0");
    else
    if (condition <= 75.0)
      strcat(buf, "%B%3*%0");
  }
}

// stick misc obj info into a buf given the buf and object
void objstuff_to_buf(obdata *o, char *buf)
{
  float condition;

  sprintf(buf, "\n\rIt looks to be made of %s.\n\r", material_types[MADE_OF(o)]);
  if (MAX_OBJ_HITS(o) <= -1)
    strcat(buf, "It looks to be in excellent condition.");
  else
  if (!MAX_OBJ_HITS(o))
    strcat(buf, "Its condition is indeterminable.");
  else
  {
    strcat(buf, "It looks to be in ");
    condition = ((float) OBJ_HITS(o) / (float) MAX_OBJ_HITS(o) * 100.0);
    if (condition <= 0.0)
      strcat(buf, "a state of disrepair.");
    else
    if (condition <= 25.0)
      strcat(buf, "poor condition.");
    else
    if (condition <= 50.0)
      strcat(buf, "fair condition.");
    else
    if (condition <= 75.0)
      strcat(buf, "pretty good condition.");
    else
    if (condition <= 100.0)
      strcat(buf, "excellent condition.");
  }

  // updated to show poison on weapon...  4/19/98 -jtrhone
  if (o->poisoned)
    strcat(buf, "\n\rIt appears to have been tainted with %2poison%0.");
}

// show a single object to a character
// use asterisk if damaged yellow/red based on damage 12/15/97 -jtrhone
void	show_obj_to_char(obdata *object, chdata *ch, int mode, int num)
{
  char trpbuf[MAX_INPUT_LENGTH];

  *buf = '\0';

  if ((mode == O_ROOM_MODE && object->description) ||
      (mode == O_INV_MODE && object->shdesc) || 
      (mode == O_CONTAINS_MODE && object->shdesc))
  { 
    if (num > 1)
      sprintf(buf, "[%%6%d%%0] ", num);

    switch (mode) {
      case O_ROOM_MODE:
        str_cat(buf, object->description, MAX_STRING_LENGTH, "show_obj_to_char");
        break;
      case O_INV_MODE:
      case O_CONTAINS_MODE:
        str_cat(buf, object->shdesc, MAX_STRING_LENGTH, "show_obj_to_char");
        if (OBJ_LIGHT(object) && LIT(object))
          str_cat(buf, " (%Blight%0)", MAX_STRING_LENGTH, "show_obj_to_char"); 
        break;
    }
  }

  if (mode == O_EXAM_COMP) 
  {
    // hey now, we throw them to the board viewer
    if (ITEM_TYPE(object) == ITEM_BOARD && board_interaction(ch, "", get_command("look")))
      return;
    else
    if (ITEM_TYPE(object) == ITEM_NOTE) 
    {
      if (object->actdesc) 
      {
	 sprintf(buf, "There is something written upon it:\n\r%s\n\r", object->actdesc);
	 page_string(ch->desc, buf, TRUE);
      } 
      else
	act("$p is blank.", FALSE, ch, object, NULL, TO_CHAR);

      return;
    } 
    else 
    if (object->actdesc && str_cmp(object->actdesc, "(null)") && str_cmp(object->actdesc, "(def)"))
      str_cpy(buf, object->actdesc, MAX_STRING_LENGTH, "show_obj_to_char");
    else
    if (ITEM_TYPE(object) == ITEM_DRINKCON)
      strcpy(buf, "It looks like a drink container.");
    else
      sprintf(buf, "It looks like %s.", object->shdesc);
  }

  if (OBJ_FLAGGED(object, ITEM_INVISIBLE))
    str_cat(buf, "(invis)", MAX_STRING_LENGTH, "show_obj_to_char");
  if (OBJ_FLAGGED(object, ITEM_EVIL) && IS_AFFECTED(ch, AFF_DETECT_EVIL)) 
    str_cat(buf, "..%1red aura%0!", MAX_STRING_LENGTH, "show_obj_to_char");
  if (OBJ_FLAGGED(object, ITEM_MAGIC) && IS_AFFECTED(ch, AFF_DETECT_MAGIC)) 
    str_cat(buf, "..%4blue aura%0!", MAX_STRING_LENGTH, "show_obj_to_char");
  if (OBJ_FLAGGED(object, ITEM_GLOW)) 
    str_cat(buf, " (%BGlowing%0)", MAX_STRING_LENGTH, "show_obj_to_char");

  if (ITEM_TYPE(object) == ITEM_CONTAINER && TRAPS(object))
  {
    traps_to_buf(ch, trpbuf, TRAPS(object));
    str_cat(buf, trpbuf, MAX_STRING_LENGTH, "show_obj_to_char");
  }

  if (mode == O_EXAM_COMP)
  {
    objstuff_to_buf(object, buf1);
    str_cat(buf, buf1, MAX_STRING_LENGTH, "show_obj_to_char");
    *buf1 = '\0';
  }
  else
    damage_asterisk(object, buf);

  str_cat(buf, "\n\r", MAX_STRING_LENGTH, "show_obj_to_char");
  page_string(ch->desc, buf, 1);
}

// show a list of objects to a character -roa
void	list_obj_to_char(obdata *list, chdata *ch, int mode, BOOL show)
{
  obdata *i, *ob;
  BOOL found = FALSE;
  int count = 0;
  int vnum = 0;

  for (i = list ; i ; i = i->next_content)
    i->viewed = FALSE;

  if (mode == O_ROOM_MODE || mode == O_INV_MODE || mode == O_CONTAINS_MODE)
  {
    // updated obj grouping to show individual objs if descs differ
    // mainly for working with ranger markings  3/27/98 -jtrhone
    for (i=list ;i ; i=i->next_content)
     if ((GET_OBJ_VNUM(i) <= 0 || 
          str_cmp(i->description, obj_proto[GET_OBJ_RNUM(i)].description)) && 
         CAN_SEE_OBJ(ch, i))
     {
       found = TRUE;
       show_obj_to_char(i, ch, mode, 1);
     }
     else
     if (!i->viewed && CAN_SEE_OBJ(ch, i))
     {
       found = TRUE;
       vnum = GET_OBJ_VNUM(i);
       i->viewed = TRUE;
       for (count = 1, ob = i ; ob ; ob = ob->next_content)
	if (!ob->viewed && GET_OBJ_VNUM(ob) == vnum)
        {
	  count++;
	  ob->viewed = TRUE;
        }

       show_obj_to_char(i, ch, mode, count);      
     }   
  }
  else
  for (i=list ;i ; i=i->next_content)
    if (CAN_SEE_OBJ(ch, i)) 
   {
     show_obj_to_char(i, ch, mode, count);
     found = TRUE;
   }

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

// send char diagnoses to another character, used during combat usually
void	diag_char_to_char(chdata *i, chdata *ch)
{
  int	percent, num;
  char *diags[21] =
  {
    " is in excellent condition.\n\r",			// 100%
    " is in good condition.\n\r",			// 95%
    " has a scratch or two.\n\r",			// 90%
    " has a few scratches.\n\r",			// 85%
    " has a couple small wounds.\n\r",			// 80%
    " has small wounds and bruises.\n\r",		// 75%
    " has quite a few wounds.\n\r",			// 70%
    " has numerous wounds and bruises.\n\r",		// 65%
    " has large nasty wounds and scratches.\n\r",	// 60%
    " has terrible looking wounds.\n\r",		// 55%
    " looks pretty hurt.\n\r",				// 50%
    " looks very hurt.\n\r",				// 45%
    " is in bad condition%0.\n\r",			// 40%
    " is in terrible condition%0.\n\r",			// 35%
    " is in %1awful condition%0.\n\r",			// 30%
    " is in %1awful condition%0.\n\r",			// 25%
    " is %1bleeding%0 severely.\n\r",			// 20%
    " is %1bleeding awfully%0 from large wounds.\n\r",	// 15%
    " is %1bleeding awfully%0 from gaping wounds.\n\r",	// 10%
    " can no longer hold back the flow of %1blood%0.\n\r",	// 5%
    " %4awaits the onset of death%0.\n\r"			// 0%
  };

  if (!can_see(ch, i))
    return;

  if (GET_MAX_HIT(i) > 0)
    percent = (100 * GET_HIT(i)) / GET_MAX_HIT(i);
  else
    percent = -1; 

  strcpy(buf, GET_NAME(i));
  CCAP(buf);

  num = 20 - (percent / 5);
  num = MAX(0, num);
  num = MIN(20, num);
  strcat(buf, diags[num]);
  S2C();
}

// for some auras, illuminate, sanct, and stuff
void char_auras_to_buf(chdata *i, char *buf)
{
  if (IS_AFFECTED2(i, AFF2_ILLUMINATE))
    strcat(buf, "(%B%3Illum%0)");

  if (IS_AFFECTED(i, AFF_SANCTUARY))
    strcat(buf, "(%BGlowing%0)");
  else
  if (IS_AFFECTED2(i, AFF2_CROW))
    strcat(buf, "(%BProtected%0)");
}

// stick a bunch of (FLAGS) into buf based on char affs
// note, this CATs onto the buffer
void char_affs_to_buf(chdata *i, char *buf)
{
  if (PLR_FLAGGED(i, PLR_AFK))
    strcat(buf, "(%BAFK%0)");

  char_auras_to_buf(i, buf);

  if (PLR_FLAGGED(i, PLR_RITUAL))
    strcat(buf, "(%4Ritual%0)");

  if (IN_ARENA(i))
    strcat(buf, "(%B%6ARENA%0)");

  if (IS_AFFECTED(i, AFF_INVISIBLE))
     strcat(buf, "(invisible)");

  if (IS_PC(i) && !i->desc)
     strcat(buf, "(soulless)");

  if (PLR_FLAGGED(i, PLR_MAILING))
     strcat(buf, "(mailing)");

  if (PLR_FLAGGED(i, PLR_WRITING))
     strcat(buf, "(posting)");

  if (PLR_FLAGGED(i, PLR_BUILDING))
     strcat(buf, "(%B%1OLC%0)");
}

void char_pos_to_buf(chdata *ch, chdata *i, char *buf)
{
  chdata *mount = NULL;

  switch (GET_POS(i)) {
  case POS_STUNNED  :
    strcat(buf, " is lying here, stunned.");
    break;
  case POS_INCAP    :
    strcat(buf, " is lying here, incapacitated.");
    break;
  case POS_MORTALLYW:
    strcat(buf, " is lying here, mortally wounded.");
    break;
  case POS_DEAD     :
    strcat(buf, " is lying here, dead..");
    break;
  case POS_STANDING :
    strcat(buf, " is standing here.");
    break;
  case POS_SITTING  :
    strcat(buf, " is sitting here.");
    break;
  case POS_RESTING  :
    strcat(buf, " is resting here.");
    break;
  case POS_SLEEPING :
    strcat(buf, " is sleeping here.");
    break;
  case POS_FIGHTING :
    if (FIGHTING(i)) 
    {
      strcat(buf, " is here, fighting ");
      if (FIGHTING(i) == ch)
	  strcat(buf, "YOU!");
      else 
      {
	 if (SAME_ROOM(i, FIGHTING(i)))
	   strcat(buf, GET_NAME(i->specials.fighting));
	 else
	   strcat(buf, "someone who has already left");
	 strcat(buf, ".");
       }
    } 
    else 
      strcat(buf, " is here struggling with thin air.");
    break;

  case POS_MOUNTED:
    if ((mount = get_mount_in_room(i)))
      sprintf(buf, "%s is here, mounted on %s.",buf, GET_NAME(mount));
    else
      strcat(buf, " is here, riding on a thin sheet of air.");
    break;

  case POS_FLOATING:
    strcat(buf, " is floating here.");
    break;

  default :
    strcat(buf, " is somewhat not not really here.");
    break;
 }
}

// stick a bunch of (FLAGS) into buf, based on misc char info 
void char_misc_to_buf(chdata *ch, chdata *i, char *buf)
{
  if (IS_AFFECTED(ch, AFF_DETECT_ALIGN)) 
  {
    if (IS_EVIL(i))
       strcat(buf, "(%1Evil%0)");
    else
    if (IS_NEUTRAL(i))
       strcat(buf, "(%7%BNeutral%0)");
    else
    if (IS_GOOD(i))
       strcat(buf, "(%6Good%0)");
  }

  if (IS_AFFECTED(ch, AFF_DETECT_EVIL) && IS_EVIL(i))
    strcat(buf, "(%1Red Aura%0)");

  if ((IS_IMMORTAL(ch) || affected_by_spell(ch, SPELL_VIEW_HIDDEN) || 
                          affected_by_spell(ch, SPELL_FOREST_SIGHT)) && IS_AFFECTED(i, AFF_HIDE))
    strcat(buf, "(%4hid%0)");
}

void show_char_to_char_list(chdata *i, chdata *ch)
{
  chdata *mounter;

  if (!PRF_FLAGGED(ch, PRF_HOLYLIGHT))
   if ((IS_AFFECTED(i, AFF_HIDE) && !affected_by_spell(ch, SPELL_VIEW_HIDDEN) &&
                                    !affected_by_spell(ch, SPELL_FOREST_SIGHT)) || !can_see(ch, i))
   {
         if (IS_AFFECTED(ch, AFF_SENSE_LIFE))
            send_to_char("You sense a hidden life form in the room.\n\r", ch);
         return;
   }

  if (IS_MOUNTED(i))  /* is here carrying NAME */
  {
    if (!(mounter = get_mounter(i)))
    {
      REMOVE_BIT(CHAR_FLAGS(i), CH_MOUNTED);
      i->npc_specials.mounter_id = -1;
      return;
    }

    if (mounter != ch)
      sprintf(buf, "$N is here, mounted by %s.",GET_NAME(mounter));
    else
      sprintf(buf, "$N is here, mounted by you.");
    act(buf, FALSE, ch, 0, i, TO_CHAR);
    return;
  }

  // no long description or out of default position
  if (!i->player.long_descr || (IS_NPC(i) && GET_POS(i) != i->npc_specials.default_pos) ||
	(IS_PC(i) && GET_POS(i) != POS_STANDING)) 
  {
    if (IS_PC(i))
    {
      if (!INCOG(i) || IS_IMMORTAL(ch))
	sprintf(buf, "A %s %s %s named %s", genders[(int)GET_SEX(i)], 
                rcarray[(int)GET_RACE(i)].racial_string, 
                clarray[(int)GET_CLASS(i)].class_name, i->player.name);
	else
	sprintf(buf, "A %s %s named %s", genders[(int)GET_SEX(i)], 
                rcarray[(int)GET_RACE(i)].race_name, i->player.name);
    }
    else 
    {
      str_cpy(buf, i->player.short_descr, MAX_STRING_LENGTH, "show_char_to_char_list");
      CCAP(buf);
    }

    char_pos_to_buf(ch, i, buf);
    char_affs_to_buf(i, buf);
    char_misc_to_buf(ch, i, buf);
    str_cat(buf, "\n\r", MAX_STRING_LENGTH, "show_char_to_char_list");
    S2C();
  } 
  else 	// send the DEFAULT char_to_char list 
  { 
    *buf = '\0';
    if (IS_AFFECTED(i, AFF_INVISIBLE))
      strcpy(buf, "%6*%0");

    char_misc_to_buf(ch, i, buf);
    char_auras_to_buf(i, buf);
    str_cat(buf, i->player.long_descr, MAX_STRING_LENGTH, "show_char_to-char_list");
    S2C();
  } 
}

// when one character actually looks at another
// updated eq listing for new slots and wvector 5/28/98 -jtrhone
void show_char_to_char_look(chdata *i, chdata *ch)
{
  chdata *mounter;
  BOOL found;
  int j;
  obdata *tmp_obj;
  char cstr[MAX_INPUT_LENGTH];
  extern chdata *get_char_by_id(long id);

  if (i->player.description)
    send_to_char(i->player.description, ch);
  else 
  {
    if (!IS_IMMORTAL(ch))
      act("You see nothing special about $m.", FALSE, i, 0, ch, TO_VICT);
    else
      act("$m lacks a description, please remedy this situation.", FALSE, i, 0, ch, TO_VICT);
  }

  if (IS_MOUNTED(i))
  {
    if (!(mounter = get_mounter(i))) 
    {
      REMOVE_BIT(CHAR_FLAGS(i), CH_MOUNTED);
      i->npc_specials.mounter_id = -1;   /* reset */
      return;
    }
    if (mounter != ch)
      sprintf(buf, "%s is mounted by %s.\n\r", GET_NAME(i), GET_NAME(mounter));
    else
      sprintf(buf, "%s is mounted by you.\n\r", GET_NAME(i));
    CCAP(buf);
    S2C();
  }

  if (SPC_FLAGGED(i,SPC_HUNTER))
    act("$N has the ability to hunt prey, be warned.",TRUE, ch, 0, i, TO_CHAR);

  if (MOB_FLAGGED(i, MOB_HELPER))
    act("$N aids $S comrades in battle, be warned.",TRUE,ch,0,i,TO_CHAR);

  if (IS_HELD(i))
    act("$N seems to be %4held%0 in place!",TRUE, ch, 0, i, TO_CHAR);

  if (IS_NPC(i) && SUMMONED(i) && (mounter = get_char_by_id(SUMMONER(i))))
  {
    sprintf(buf, "%s belongs to %s.\n\r",GET_NAME(i), 
	    (ch == mounter) ? "you" : GET_NAME(mounter));
    CCAP(buf);
    S2C();
  }

  if (IS_PC(i) && SINGING(i))
  {
    sprintf(buf, "%s is singing %%B%%6%s%%0.\n\r", GET_NAME(i), song_names_cap[SINGING(i)]);
    CCAP(buf);
    S2C();
  }
  if (IS_PC(i) && PLAYING(i))
  {
    sprintf(buf, "%s is playing %%B%%6%s%%0.\n\r", GET_NAME(i), song_names_cap[PLAYING(i)]);
    CCAP(buf);
    S2C();
  }

  diag_char_to_char(i, ch);  /* show character condition */

  strcpy(buf, "Visible Specials: ");
  char_affs_to_buf(i, buf);
  str_cat(buf, "\n\r", MAX_STRING_LENGTH, "show_char_to-char_look");
  S2C();

  found = FALSE;
  for (j = 0; j < MAX_WEAR; j++) 
    if (EQ(i, j) && CAN_SEE_OBJ(ch, EQ(i, j))) 
      found = TRUE;

  // updated for new slots...5/28/98 -jtrhone
  if (found) 
  {
    act("\n\r$n is using:", FALSE, i, 0, ch, TO_VICT);
    for (j = 0; j < MAX_WEAR; j++) 
    if (EQ(i, j) && CAN_SEE_OBJ(ch, EQ(i, j))) 
    {
       if (WV_FLAGS(EQ(i, j)))
         sprintbit(WV_FLAGS(EQ(i,j)), wv_bits, buf2);
       else
         strcpy(buf2, "");

       sprintf(cstr, "%s %s%s%s", wv_bits[j], *buf2 ? "(" : "" , buf2, *buf2 ? ")" : "" );
       sprintf(buf, "%%B%-35.35s%%0: %s\n\r", cstr,  EQ(i, j)->shdesc);
       S2C();
    }
  }

  if (IS_THIEF(ch) && (ch != i) && !IS_IMMORTAL(i)) 
  {
    found = FALSE;
    send_to_char("\n\rYou attempt to peek at the inventory:\n\r", ch);
    for (tmp_obj = i->carrying; tmp_obj; tmp_obj = tmp_obj->next_content) 
      if (CAN_SEE_OBJ(ch, tmp_obj) && (number(0, 60) < GET_LEVEL(ch))) 
      {
	show_obj_to_char(tmp_obj, ch, O_INV_MODE, 1);
	found = TRUE;
      }

    if (!found)
      send_to_char("You can't see anything.\n\r", ch);
  }
}

// show a character to another character
void show_char_to_char(chdata *i, chdata *ch, int mode)
{
  if (mode == CHAR_LIST) 
    show_char_to_char_list(i, ch);
  else
  if (mode == CHAR_LOOK)
    show_char_to_char_look(i, ch);
  else
  if (mode == CHAR_LOOK_INV) 
  {
    act("$n is carrying:", FALSE, i, 0, ch, TO_VICT);
    list_obj_to_char(i->carrying, ch, O_INV_MODE, TRUE);
  }
}

// show a list of characters to another character (uses next_in_room)
// valid modes are CHAR_LIST_LONG and CHAR_LIST_SHORT
void	list_char_to_char(chdata *list, chdata *ch, int mode)
{
  chdata *i;

  for (i = list; i; i = i->next_in_room)
  if (ch != i) 
  {
    if (mode == CHAR_LIST_LONG) 
    { 
      if ((can_see(ch, i) && (IS_IMMORTAL(ch) || IS_AFFECTED(ch, AFF_SENSE_LIFE) || 
          affected_by_spell(ch, SPELL_VIEW_HIDDEN) || affected_by_spell(ch, SPELL_FOREST_SIGHT) || 
          !IS_AFFECTED(i, AFF_HIDE))))
        show_char_to_char(i, ch, CHAR_LIST);
      else 
      if ((IS_DARK(ch->in_room)) && (IS_AFFECTED(i, AFF_INFRARED) || IS_DROW(i)))
	send_to_char("You see a pair of %B%1glowing red%0 eyes looking your way.\n\r", ch);
    }
    else 
    if (mode == CHAR_LIST_SHORT)	// usually do_scan
    { 
      if ((can_see(ch, i) && (IS_IMMORTAL(ch) || IS_AFFECTED(ch, AFF_SENSE_LIFE) || 
	  affected_by_spell(ch, SPELL_VIEW_HIDDEN) || affected_by_spell(ch, SPELL_FOREST_SIGHT) || 
          !IS_AFFECTED(i, AFF_HIDE)))) 
      {
	if (IS_PC(i))
	  sprintf(buf, "%s %s", i->player.name, GET_TITLE(i));
	else 
	{
	  str_cpy(buf, i->player.short_descr, MAX_STRING_LENGTH, "list_char_to_char");
	  CCAP(buf);  
        }
        str_cat(buf, "\n\r", MAX_STRING_LENGTH, "list_char_to_char");
        S2C();
      }
    }
  }
}

// send one liners for now to char related to room_affects
void list_room_affects_to_char(chdata *ch)
{
  struct room_affect_type *raf;
  extern BOOL room_align_probs(chdata *ch, int bitv);

  for (raf = world[ch->in_room].room_affects; raf; raf = raf->next)
    switch (raf->spell) {
      case SPELL_NATURES_CALTROPS:
        send_to_char("Long, wickedly-pointed wooden spikes protrude from the ground.\r\n", ch);
        break;
      case SPELL_ROCK_TO_MUD:
        send_to_char("The ground here is extremely muddy.\r\n", ch);
        break;
      case SPELL_FIRESTORM:	// 04/23/98 -callahan
	send_to_char("A deadly %B%1storm of fire%0 blazes through the area.\n\r",ch);
	break;
      case SPELL_SILENCE:
	send_to_char("An aura of %Bholy silence%0 saturates the area.\n\r",ch);
	break;
      case SPELL_FIREWALL:
	send_to_char("A %B%1wall of fire%0 rages through the area.\n\r",ch);
	break;
      case SPELL_ICEWALL:
	send_to_char("A %B%6shower of ice%0 falls over the area.\n\r",ch);
	break;
      case SPELL_TYPHOON:
	send_to_char("A deadly %1typhoon%0 rages through the area.\n\r",ch);
	break;
      case SPELL_VOID:
	send_to_char("A %4temporal void%0 shimmers here.\n\r",ch);
	break;
      case SPELL_GASCLOUD:
	send_to_char("A %2gaseous cloud%0 hangs here.\n\r",ch);
	break;
      case SPELL_BLINDWALL:
	send_to_char("A %4strange darkness%0 looms here.\n\r",ch);
	break;
      case SPELL_CONFUSION:
	break;
      case SKILL_NOTRACK:
	break;
      case SPELL_SHOWEROFLIFE:
	send_to_char("A %B%6shower of life%0 falls gently around the area.\n\r",ch);
	break;
      case SPELL_CURSED_GROUNDS:
	send_to_char("An uncomfortable feeling surrounds this area.\n\r",ch);
	break;
      case SPELL_ABSOLUTE_WARD:
        if (raf->caster != ch)
	  send_to_char("You feel unwelcome in this area.\n\r",ch);
	break;
      case SPELL_CIRCLE_OF_WARDING:
        if (raf->caster != ch && room_align_probs(ch, raf->bitvector))
	  send_to_char("You feel unwelcome in this area.\n\r",ch);
	break;
      case SPELL_WALLOFFOG:
      case SPELL_OCCLUSION:
        if (raf->caster != ch)
	  send_to_char("A wall of fog hangs heavy over this area.\n\r",ch);
	break;
      default: break;
    }
}

// show the auras of areas of return... 3/27/98 -jtrhone
void list_areas_of_return(rmdata *rm, chdata *ch)
{
  char buf[MAX_STRING_LENGTH];
  struct room_affect_type *raf;

  for (*buf = '\0', raf = rm->room_affects; raf; raf=raf->next)
    if (raf->spell == SPELL_AREA_OF_RETURN && raf->caster && raf->caster != ch)
    {
      sprintf(buf, "An aura of %s hangs here.\n\r", GET_NAME(raf->caster));
      S2C();
    }
    else
    if (raf->spell == SPELL_PROJECT && raf->caster && raf->caster != ch)
      show_char_to_char_list(raf->caster, ch);
}

// make sure not in void AND all descrips are there -roa
void do_look_at_room(chdata *ch, int cmd, int subcmd)
{
  int rm;
  extern char *terrain_types[];

  if (INVALID_ROOM(ch->in_room) || ZONE_FREED(world[ch->in_room].zone))
  {
    send_to_char("You see %4utter darkness%0.\n\r",ch);
    return;
  }

  if (GET_POS(ch) < POS_SLEEPING)
  {
     send_to_char("You can't see anything but stars!\n\r", ch);
     return;
  }

  if (GET_POS(ch) == POS_SLEEPING)
  {
     send_to_char("You can't see anything, you're sleeping!\n\r", ch);
     return;
  }

  if (IS_AFFECTED(ch, AFF_BLIND))
  {
     send_to_char("You can't see a damned thing, you're blinded!\n\r", ch);
     return;
  }

  // if foggy room and not fog caster, no can see 3/2/98 -jtrhone
  if (!IS_IMMORTAL(ch) && spell_affects_room(ch->in_room, SPELL_WALLOFFOG) &&
      !char_spell_affects_room(ch, SPELL_WALLOFFOG, ch->in_room))
  {
     send_to_char("%BYou can't see anything but fog!%0\n\r", ch);
     return;
  }

  if (!IS_IMMORTAL(ch) && spell_affects_room(ch->in_room, SPELL_OCCLUSION) &&
      !char_spell_affects_room(ch, SPELL_OCCLUSION, ch->in_room))
  {
     send_to_char("%BYou can't see anything but fog!%0\n\r", ch);
     return;
  }

  if (!IS_IMMORTAL(ch) && ROOM_FLAGGED2(ch->in_room, WALLOFFOG))
  {
     send_to_char("%BYou can't see anything but fog!%0\n\r", ch);
     return;
  }

  if (IS_DARK(ch->in_room) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT) && IS_PC(ch) && !IS_DROW(ch)) 
  {
     send_to_char("It is pitch %4black...%0\n\r", ch);
     list_char_to_char(world[ch->in_room].people, ch, CHAR_LIST_LONG);   
     return;
  }

  if (world[ch->in_room].name && *world[ch->in_room].name)
    str_cpy(buf2, world[ch->in_room].name, MAX_STRING_LENGTH, "do_look_at_room");
  else
    strcpy(buf2, "%1WARNING:%0 This room has no name... notify builder.");

  // Added terrain type in look.... 07/10/98 -callahan
  if (RoomFlags(ch)) {
    sprintbit((long) world[ch->in_room].room_flags, room_bits, buf);
    sprinttype(world[InRoom(ch)].terrain_type, terrain_types, buf1);
    sprintf(buf2, "%s (#%d - %%6%s%%0)\n\r[ %%6%s%%0 ]\n\r",
            buf2, world[ch->in_room].number, buf1, buf);
    sprintbit((long) world[ch->in_room].room_flags2, room_bits2, buf);
    sprintf(buf2, "%s[ %%6%s%%0 ]", buf2, buf);
  }

  // updated not to reference hard wired command #  4/21/98 -jtrhone
  if (!PRF_FLAGGED(ch, PRF_BRIEF) || CMD_IS(cmd, "look"))
    sprintf(buf2 + strlen(buf2), "\n\r%s",
	  (world[ch->in_room].description && *world[ch->in_room].description)?
	   world[ch->in_room].description :
	   "%1WARNING:%0 This room has no description... notify builder!\n\r");
  else
    str_cat(buf2, "\n\r", MAX_STRING_LENGTH, "do_look_at_room");
  send_to_char(buf2, ch);

  if (PLR_FLAGGED(ch, PLR_LINE))
    send_to_char("%B-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%0\n\r",ch);

  list_obj_to_char(world[ch->in_room].contents, ch, O_ROOM_MODE, FALSE);
  list_char_to_char(world[ch->in_room].people, ch, CHAR_LIST_LONG);

  // show auras of areas of return... for each AREA_OF_RETURN spell in this room
  // 3/27/98 -jtrhone
  if (world[ch->in_room].room_affects)
    list_areas_of_return(&world[ch->in_room], ch);

  if (subcmd >= 0 && world[ch->in_room].trans_present > 0 &&
      (rm = real_room(world[ch->in_room].trans_present)) >= 0)
  {
    if (TRANS_SHDESC(&world[rm]))
      sprintf(buf, "%s is here.\n\r", TRANS_SHDESC(&world[rm]));
    else
      sprintf(buf, "%s is here.\n\r", world[rm].name);
    S2C();
  }

  list_room_affects_to_char(ch);

  if ((IS_NPC(ch) || PRF_FLAGGED(ch, PRF_AUTOX)) && !IS_AFFECTED(ch, AFF_BLIND))
    do_exits(ch, "", 0, 0);
}

void do_look_outside_transport(chdata *ch)
{
  int room_in;

  if ((room_in = real_room(world[ch->in_room].location)) < 0)
  {
    send_to_char("You look outside and see %4l i m b o%0.\n\r",ch);
    return;
  }
  send_to_char("%BYou look outside and see:%0 \n\r",ch);
  send_to_char(world[room_in].name, ch);
  send_to_char("\n\r",ch);
  if(!PRF_FLAGGED(ch, PRF_BRIEF))
    send_to_char(world[room_in].description, ch);
  if(PLR_FLAGGED(ch, PLR_LINE))
    send_to_char("%B-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
		 "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%0\n\r",ch);

  list_char_to_char(world[room_in].people, ch, CHAR_LIST_LONG);

  // show auras of areas of return... for each AREA_OF_RETURN spell in this room
  // 3/27/98 -jtrhone
  if (world[room_in].room_affects)
    list_areas_of_return(&world[room_in], ch);
}

// char looks in something
void do_look_in(chdata *ch, char *arg2)
{
  obdata *tmp_obj = NULL;
  chdata *tmp_char = NULL;
  int bits, temp;

  if (!*arg2)
  {
    send_to_char("Look in what?\n\r",ch);
    return;
  }

  if ((bits = generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_ROOM | 
        FIND_OBJ_EQUIP, ch, &tmp_char, &tmp_obj)))
  { 
    if (ITEM_TYPE(tmp_obj) == ITEM_DRINKCON || ITEM_TYPE(tmp_obj) == ITEM_FOUNTAIN)
    {
      if (tmp_obj->value[1] <= 0 || tmp_obj->value[0] <= 0)
	act("It is empty.", FALSE, ch, 0, 0, TO_CHAR);
      else 
      {
	temp = ((tmp_obj->value[1] * 3) / tmp_obj->value[0]);
	sprintf(buf, "It's %sfull of a %s liquid.\n\r", fullness[temp], 
		color_liquid[tmp_obj->value[2]]);
	S2C();
      }
    } 
    else 
    if (ITEM_TYPE(tmp_obj) == ITEM_CONTAINER) 
    {
      if (!IS_SET(tmp_obj->value[1], CONT_CLOSED)) 
      {
	send_to_char(fname(tmp_obj->name), ch);
	switch (bits) {
	case FIND_OBJ_INV:
	  send_to_char(" (carried):\n\r", ch);
	  break;
	case FIND_OBJ_ROOM:
	  send_to_char(" (here):\n\r", ch);
	  break;
	case FIND_OBJ_EQUIP :
	  send_to_char(" (used):\n\r", ch);
	  break;
	}
	list_obj_to_char(tmp_obj->contains, ch, O_CONTAINS_MODE, TRUE);
      } 
      else
	send_to_char("It is closed.\n\r", ch);
    } 
    else 
      send_to_char("That is not a container.\n\r", ch);
  } 
  else 
   send_to_char("You do not see that item here.\n\r", ch);

  return;
}

// one char looks at another
void do_look_at_char(chdata *ch, chdata *tmp_char)
{
   show_char_to_char(tmp_char, ch, CHAR_LOOK);
   if (ch != tmp_char) 
   {
     if (can_see(tmp_char, ch))
       act("$n looks at you.", TRUE, ch, 0, tmp_char, TO_VICT);
     act("$n looks at $N.", TRUE, ch, 0, tmp_char, TO_NOTVICT);
   }
}

// updated to show traps... 4/14/98 -jtrhone
void do_look_dir(chdata *ch, int rl_dir)
{
  char trpbuf[MAX_INPUT_LENGTH];
  rmdirdata *d = EXIT(ch, rl_dir);
  rmdata *r;

  if (d->exit_descr)
    send_to_char(d->exit_descr, ch);
  else
    send_to_char("It's hard to tell what lies in that direction.\n\r", ch);

  if (EXIT_CLOSED(d) && d->keyword)
  {
    sprintf(buf, "The %s is closed.\n\r", fname(d->keyword));
    S2C();
  } 
  else 
  if (EXIT_ISDOOR(d) && d->keyword)
  {
    sprintf(buf, "The %s is open.\n\r", fname(d->keyword));
    S2C();
  }

  // send em trap info if its visible...
  if (TRAPS(d) && (IS_IMMORTAL(ch) || TRAPFLAGGED(TRAPS(d), TRF_REVEALED)))
  {
    traps_to_buf(ch, trpbuf, TRAPS(d));
    sprintf(buf, "Visible exit specials: %s\n\r", trpbuf);
    S2C();
  }

  // if there is a visible snare in the room beyond... show em
  if (!EXIT_ISDOOR(d) || EXIT_OPEN(d)) 
  {
    if (!INVALID_ROOM(d->to_room))
    {
      r = &world[d->to_room];
      if (TRAPS(r) && (IS_IMMORTAL(ch) || TRAPFLAGGED(TRAPS(r), TRF_REVEALED)))
      {
        sprintf(buf, "You see a %s in the area beyond.\n\r", trap_types[TRAPTYPE(TRAPS(r))]);
        S2C();
      }
    }
  }
}

// ignore BOARD extras  12/30/97 -jtrhone
int do_look_extras_eq(chdata *ch, char *arg2)
{
  char *tmp_desc = NULL;
  int j;
  int found = FALSE;

  for (j = 0; j < MAX_WEAR && !found; j++) 
    if (EQ(ch, j) && CAN_SEE_OBJ(ch, EQ(ch, j)) && ITEM_TYPE(EQ(ch, j)) != ITEM_BOARD) 
      if ((tmp_desc = find_exdesc(arg2, EQ(ch, j)->exdesc)))
      {
	found = TRUE;
	str_cpy(buf2, tmp_desc, MAX_STRING_LENGTH, "do_look_extras_eq");
	objstuff_to_buf(EQ(ch, j), buf1);
	str_cat(buf2, buf1, MAX_STRING_LENGTH, "do_look_extras_eq");
	*buf1 = '\0';
	page_string(ch->desc, buf2, TRUE);
      }
  return found;
}

// ignore BOARD extras  12/30/97 -jtrhone
int do_look_extras_inv(chdata *ch, char *arg2)
{
  char *tmp_desc = NULL;
  int found = FALSE;
  obdata *tmp_obj;

  for (tmp_obj = ch->carrying; tmp_obj && !found; tmp_obj = tmp_obj->next_content) 
    if (CAN_SEE_OBJ(ch, tmp_obj) && ITEM_TYPE(tmp_obj) != ITEM_BOARD)
      if ((tmp_desc = find_exdesc(arg2, tmp_obj->exdesc)))
      {
	found = TRUE;
	str_cpy(buf2, tmp_desc, MAX_STRING_LENGTH, "do_look_extras_inv");
	objstuff_to_buf(tmp_obj, buf1);
	str_cat(buf2, buf1, MAX_STRING_LENGTH, "do_look_extras_inv");
	*buf1 = '\0';
	page_string(ch->desc, buf2, TRUE);
      }

  return found;
}

// modified to work with new board design
// return FALSE regardless of extras if it's a board  12/30/97  -jtrhone
int do_look_extras_obj_room(chdata *ch, char *arg2)
{
  char *tmp_desc = NULL;
  int found = FALSE;
  obdata *tmp_obj;

  for (tmp_obj = world[ch->in_room].contents; tmp_obj && !found; tmp_obj = tmp_obj->next_content) 
    if (CAN_SEE_OBJ(ch, tmp_obj) && ITEM_TYPE(tmp_obj) != ITEM_BOARD)
      if ((tmp_desc = find_exdesc(arg2,tmp_obj->exdesc)))
      {
	found = TRUE;
	str_cpy(buf2, tmp_desc, MAX_STRING_LENGTH, "do_look_extras_obj_room");
	objstuff_to_buf(tmp_obj, buf1);
	str_cat(buf2, buf1, MAX_STRING_LENGTH, "do_look_extras_obj_room");
	*buf1 = '\0';
	page_string(ch->desc, buf2, TRUE);
      }

  return found;
}

void do_look_at(chdata *ch, char *arg2, int dirnum)
{
  obdata *found_obj = NULL;
  chdata *tmp_char = NULL;
  int bits, rl_dir;
  BOOL found = FALSE;
  char *tmp_desc = NULL;

  if (!*arg2)
  {
    send_to_char("Look at what?\n\r",ch);
    return;
  }

  bits = generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_ROOM | FIND_OBJ_EQUIP | 
		      FIND_CHAR_ROOM, ch, &tmp_char, &found_obj);

  if (tmp_char) 
  {
    do_look_at_char(ch, tmp_char);
    return;
  } 

  // is it an extra description in the room? 
  if ((tmp_desc = find_exdesc(arg2,world[ch->in_room].exdesc)))
  {
    page_string(ch->desc, tmp_desc, 0);
    return; 
  }

  if (dirnum >= 3)
    rl_dir = dirnum - 3;  

  // prevent secret dirs from being seen 4/10/98 -jtrhone
  if (dirnum >= 3 && EXIT(ch, rl_dir) && !EXIT_FLAGGED(EXIT(ch, rl_dir), EX_SECRET)) 
  {
    found = TRUE;
    do_look_dir(ch, rl_dir);
  }

  if (!found)
    found = do_look_extras_eq(ch, arg2);

  if (!found)
    found = do_look_extras_inv(ch, arg2);

  if (!found)
    found = do_look_extras_obj_room(ch, arg2);

  if (bits) 	// there was an object 
  { 
    if (!found)	// no extra found, show completely
      show_obj_to_char(found_obj, ch, O_EXAM_COMP, 1); 
    else
      show_obj_to_char(found_obj, ch, O_EXAM_MIN, 1); 
  }
  else 
  if (!found)
    send_to_char("You do not see that here.\n\r", ch);
}

ACMD(do_look)
{
  static char arg2[MAX_INPUT_LENGTH];
  int	keyword_no, dirnum;
  char *argu = argument;
  int room_in;
  static char	*keywords[] = {
     "in",
     "at",
     "",
     "north",
     "east",
     "south",
     "west",
     "up",
     "down",
     "neast",
     "seast",
     "swest",
     "nwest",
     "\n"};

  if (IN_NOWHERE(ch)) return;

  if (!ch->desc || PLR_FLAGGED(ch, PLR_BUILDING))
     return;

  skip_spaces(&argu);

  if (GET_POS(ch) < POS_SLEEPING)
     send_to_char("You can't see anything but stars!\n\r", ch);
  else 
  if (GET_POS(ch) == POS_SLEEPING)
     send_to_char("You can't see anything, you're sleeping!\n\r", ch);
  else
  if (IS_AFFECTED(ch, AFF_BLIND))
     send_to_char("You can't see a damned thing, you're blinded!\n\r", ch);
  else
  if (ROOM_FLAGGED2(ch->in_room, TRANSPORT) && *argu && is_abbrev(argu, "outside"))
  {    
    do_look_outside_transport(ch);
    return;
  }
  else
  if (world[ch->in_room].trans_present && *argu &&
     (room_in = real_room(world[ch->in_room].trans_present)) >= 0 &&
      TRANS_KEYWORDS(&world[room_in]) && 
      isname(argu, TRANS_KEYWORDS(&world[room_in])))
  {
     if (TRANS_LDESC(&world[room_in]))  
       send_to_char(TRANS_LDESC(&world[room_in]), ch);
     else
       send_to_char("You see a bunch of wierd stuff sorta.\n\r",ch);
     return;
  }
  else 
  if (IS_DARK(ch->in_room) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT) && IS_PC(ch) && 
      !IS_DROW(ch)) 
  {
     send_to_char("It is pitch %4black...%0\n\r", ch);
     list_char_to_char(world[ch->in_room].people, ch, CHAR_LIST_LONG);   
  }
  else 
  {
    half_chop(argu, arg, arg2);
    keyword_no = search_block(arg, keywords, FALSE); /* Partial Match */

    // set up direction if they looked in a direction
    dirnum = 1;
    if ((keyword_no == -1 || (keyword_no >= 3 && keyword_no <= 12)) && *arg) 
    {
       if (keyword_no >= 3) 
         dirnum = keyword_no;
       keyword_no = 1; 
       str_cpy(arg2, arg, MAX_INPUT_LENGTH, "do_look"); 
    }

    switch (keyword_no) 
    {
      case 0 :     /* look 'in'	*/
	do_look_in(ch, arg2);
        break;

      case 1 :     /* look 'at'	*/
	do_look_at(ch, arg2, dirnum);
	break;

      case 2 :    /* look '' */
        do_look_at_room(ch, cmd, subcmd);
        break;

      default:
        send_to_char("What do you want to look at?\n\r", ch);
        break;
    }
  }
}

// modified to work with new board design 12/30/97 -jtrhone
ACMD(do_read)
{
  if (board_in_room(ch->in_room) && board_interaction(ch, argument, get_command("read")))
    return;
  
  sprintf(buf1, "at %s", argument);
  do_look(ch, buf1, 15, 0);
}

ACMD(do_examine)
{
  char	name[100], buf[100];
  int	bits;
  chdata *tmp_char;
  obdata *tmp_object;

  sprintf(buf, "at %s", argument);
  do_look(ch, buf, 15, 0);

  one_argument(argument, name);

  if (!*name) {
     send_to_char("Examine what?\n\r", ch);
     return;
  }

  bits = generic_find(name, FIND_OBJ_INV | FIND_OBJ_ROOM | FIND_OBJ_EQUIP, ch, &tmp_char, &tmp_object);

  if (tmp_object)
      if ((ITEM_TYPE(tmp_object) == ITEM_DRINKCON) || 
          (ITEM_TYPE(tmp_object) == ITEM_FOUNTAIN) || 
          (ITEM_TYPE(tmp_object) == ITEM_CONTAINER)) 
      {
	 send_to_char("When you look inside, you see:\n\r", ch);
	 sprintf(buf, "in %s", argument);
	 do_look(ch, buf, 15, 0);
      }
}

void get_exit_prompt(chdata *ch, char *str)
{
  int	door;

  *str = '\0';
  sprintf(str, "[ ");

  for(door = 0; door < NUM_OF_DIRS; door++) 
    if(EXIT(ch, door) && EXIT(ch, door)->to_room != NOWHERE) 
      if (EXIT_OPEN(EXIT(ch, door)) && !EXIT_FLAGGED(EXIT(ch, door), EX_SECRET))
        sprintf(str + strlen(str), "%s", sh_dirs[door]);
  strcat(str, "]");
}

ACMD(do_exits)
{
  rmdirdata *d;
  int	door;
  char *p_closed = "(closed)";
  char *p_closed_and_locked = "(closed locked)";
  char *p_null = "";
  char *p;

  *buf = '\0';

  if (IS_AFFECTED(ch, AFF_BLIND)) {
    send_to_char("You can't see a damned thing, you're blind!\r\n", ch);
    return;
  }

  if (PRF_FLAGGED(ch, PRF_SHORTX))
    sprintf(buf, "[ ");

  for (door = 0; door < NUM_OF_DIRS; door++) 
  {
    *buf2 = '\0';
    if (!(d = EXIT(ch, door)))
      continue;

    if (!INVALID_ROOM(d->to_room))
    {
      if (IS_IMMORTAL(ch) && !PRF_FLAGGED(ch, PRF_SHORTX)) 
      {
        if (EXIT_CLOSED(d) && EXIT_LOCKED(d)) 
          p = p_closed_and_locked;
        else 
	{
          if (EXIT_CLOSED(d))
            p = p_closed;
          else 
	    p = p_null; 
        }
	sprintf(buf2, "%-9s - [%5d] %s %s%s\n\r", dirs[door], world[d->to_room].number, 
                world[d->to_room].name ?   world[d->to_room].name : "An eerie %4darkness%0", p,
                EXIT_SECRET(d) ? " (secret)" : "");
      }
      else 
      {
        if (PRF_FLAGGED(ch, PRF_SHORTX) && EXIT_OPEN(d) && !EXIT_SECRET(d))
    	    sprintf(buf2, "%s", sh_dirs[door]);
	else 
	if (!PRF_FLAGGED(ch, PRF_SHORTX))
	{
         if (EXIT_OPEN(d) && !EXIT_SECRET(d))
	 {
	  sprintf(buf2, "%-9s - ", dirs[door]);
	  if (IS_DARK(d->to_room) && !CAN_SEE_IN_DARK(ch))
	    str_cat(buf2, "An eerie %4darkness%0\n\r", MAX_STRING_LENGTH, "do_exits");
          else
	  if (spell_affects_room(d->to_room, SPELL_WALLOFFOG))
	    str_cat(buf2, "An eerie %Bfog%0\n\r", MAX_STRING_LENGTH, "do_exits");
	  else 
	  if (spell_affects_room(d->to_room, SPELL_OCCLUSION))
	    str_cat(buf2, "An eerie %Bfog%0\n\r", MAX_STRING_LENGTH, "do_exits");
	  else 
	  if (ROOM_FLAGGED2(d->to_room, WALLOFFOG))
	    str_cat(buf2, "An eerie %Bfog%0\n\r", MAX_STRING_LENGTH, "do_exits");
	  else 
	    sprintf(buf2+strlen(buf2), "%s\n\r", world[d->to_room].name ? 
		world[d->to_room].name : "An eerie %4darkness%0"); 
         }
	}
      }
      CCAP(buf2);
      str_cat(buf, buf2, MAX_STRING_LENGTH, "do_exits");
    }
  }

  if (PRF_FLAGGED(ch, PRF_SHORTX))
  {
    str_cat(buf, "]", MAX_STRING_LENGTH, "do_exits");
    sprintf(buf2, "Obvious exits: %s\n\r",buf);
    send_to_char(buf2, ch);
  }
  else 
  {
    send_to_char("Obvious exits:\n\r", ch);
    if (*buf)
      S2C();
    else
      send_to_char(" None.\r\n", ch);
  }
}

void room_affects_to_buf(char *buf, int room)
{
  struct room_affect_type *raf = world[room].room_affects;

  for (*buf = '\0'; raf; raf = raf->next)
    switch (raf->spell) {
      case SPELL_SILENCE:
	strcat(buf, "%B(Silenced)%0");
	break;
      case SPELL_FIRESTORM:	// 04/23/98 -callahan
      case SPELL_FIREWALL:
	strcat(buf, "%B%1(Fire)%0");
	break;
      case SPELL_ICEWALL:
	strcat(buf, "%B%6(Ice)%0");
	break;
      case SPELL_TYPHOON:
	strcat(buf, "%1(Storm)%0");
	break;
      case SPELL_VOID:
	strcat(buf, "%4(Void)%0");
	break;
      case SPELL_GASCLOUD:
	strcat(buf, "%2(Gas)%0");
	break;
      case SPELL_BLINDWALL:
	strcat(buf, "%4(Darkness)%0");
	break;
      case SPELL_CONFUSION:
	break;
      case SKILL_NOTRACK:
	break;
      case SPELL_SHOWEROFLIFE:
	strcat(buf, "%B(Rain)%0");
	break;
      case SPELL_CURSED_GROUNDS:  // no notification...
	break;
      case SPELL_ABSOLUTE_WARD:  
	strcat(buf, "%4(Ward)%0");
	break;
      case SPELL_CIRCLE_OF_WARDING:  
	strcat(buf, "%4(Ward)%0");
	break;
      case SPELL_WALLOFFOG:  
      case SPELL_OCCLUSION:  
	strcat(buf, "%B(Fog)%0");
	break;
      default: break;
    }
}

/* Added scan command..basically same as do_exits JRhone */
ACMD(do_scan)  
{
   int	door;
   char	*exits[] = 
    {
      "North",
      "East ",
      "South",
      "West ",
      "Up   ",
      "Down ",
      "NorthEast ",
      "SouthEast ",
      "SouthWest ",
      "NorthWest ",
   };
   char rmtrpbuf[MAX_INPUT_LENGTH];
   char extrpbuf[MAX_INPUT_LENGTH];


  if (affected_by_spell(ch, SPELL_BLINDNESS))
  {
    send_to_char("You're blind, you can't see a damn thing!\n\r",ch);
    return;
  }

  // if foggy room and not fog caster, no can see 3/2/98 -jtrhone
  if (!IS_IMMORTAL(ch) && spell_affects_room(ch->in_room, SPELL_WALLOFFOG) &&
      !char_spell_affects_room(ch, SPELL_WALLOFFOG, ch->in_room))
  {
     send_to_char("%BYou can't see anything but fog!%0\n\r", ch);
     return;
  }

  if (!IS_IMMORTAL(ch) && spell_affects_room(ch->in_room, SPELL_OCCLUSION) &&
      !char_spell_affects_room(ch, SPELL_OCCLUSION, ch->in_room))
  {
     send_to_char("%BYou can't see anything but fog!%0\n\r", ch);
     return;
  }

  if (!IS_IMMORTAL(ch) && ROOM_FLAGGED2(ch->in_room, WALLOFFOG))
  {
     send_to_char("%BYou can't see anything but fog!%0\n\r", ch);
     return;
  }

  if ( IS_DARK(ch->in_room) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT) && IS_PC(ch) && !IS_DROW(ch)) 
  {
    send_to_char("It is pitch %4black...%0\n\r", ch);
    return;
  }

   send_to_char("You %5scan%0 the surrounding area.\n\r", ch);
   for (door = 0; door <= 9; door++) 
   {
      if (!EXIT(ch, door))
        continue;

      if (!IS_IMMORTAL(ch) && EXIT_FLAGGED(EXIT(ch, door), EX_SECRET))
        continue;

      *buf = '\0';
      if (CAN_GO(ch, door))
	if (IS_IMMORTAL(ch))
	{
          traps_to_buf(ch, rmtrpbuf, TRAPS(&world[EXIT(ch, door)->to_room]));
          traps_to_buf(ch, extrpbuf, TRAPS(EXIT(ch, door)));
	  room_affects_to_buf(buf2, EXIT(ch, door)->to_room);
	  sprintf(buf, "%%6%-9s%%0: %s %s%s\n\r",exits[door], rmtrpbuf, extrpbuf, buf2);
          S2C();
          list_char_to_char(world[EXIT(ch, door)->to_room].people, ch, CHAR_LIST_SHORT);

          // show auras of areas of return... for each AREA_OF_RETURN spell in this room
          // 3/27/98 -jtrhone
          if (world[EXIT(ch, door)->to_room].room_affects)
            list_areas_of_return(&world[EXIT(ch, door)->to_room], ch);
        }     
	else 
	if (IS_DARK(EXIT(ch, door)->to_room) && !PRF_FLAGGED(ch, PRF_HOLYLIGHT)) 
	{ 
	  sprintf(buf, "%%6%-9s%%0 - An eerie %%4darkness%%0\n\r",exits[door]);
          S2C();
        }
        else
	if (spell_affects_room(EXIT(ch, door)->to_room, SPELL_WALLOFFOG) && 
            !PRF_FLAGGED(ch, PRF_HOLYLIGHT)) 
	{ 
	  sprintf(buf, "%%6%-9s%%0 - An eerie %%Bfog%%0\n\r",exits[door]);
          S2C();
        }
        else
	if (spell_affects_room(EXIT(ch, door)->to_room, SPELL_OCCLUSION) && 
            !PRF_FLAGGED(ch, PRF_HOLYLIGHT)) 
	{ 
	  sprintf(buf, "%%6%-9s%%0 - An eerie %%Bfog%%0\n\r",exits[door]);
          S2C();
        }
        else
	if (ROOM_FLAGGED2(EXIT(ch, door)->to_room, WALLOFFOG))
	{ 
	  sprintf(buf, "%%6%-9s%%0 - An eerie %%Bfog%%0\n\r",exits[door]);
          S2C();
        }
	else 
	{
          traps_to_buf(ch, rmtrpbuf, TRAPS(&world[EXIT(ch, door)->to_room]));
          traps_to_buf(ch, extrpbuf, TRAPS(EXIT(ch, door)));
	  room_affects_to_buf(buf2, EXIT(ch, door)->to_room);
	  sprintf(buf, "%%6%-9s%%0: %s %s%s\n\r", exits[door], rmtrpbuf, extrpbuf, buf2);
          S2C();
          list_char_to_char(world[EXIT(ch, door)->to_room].people, ch, CHAR_LIST_SHORT);

          // show auras of areas of return... for each AREA_OF_RETURN spell in this room
          // 3/27/98 -jtrhone
          if (world[EXIT(ch, door)->to_room].room_affects)
            list_areas_of_return(&world[EXIT(ch, door)->to_room], ch);
        }
   } 
}

// command will just diplay gold on hand and in bank so
// you dont have to type score and/or go to a teller machine -jtrhone
// changed to use runtime currency names  11/28/97 -jtrhone
// command name changed to "bank" in interpreter  11/28/97 -jtrhone
ACMD(do_gold)
{
  if (IS_NPC(ch)) return;

  sprintf(buf, "%s on hand: %d\n\r", currency_name_plural, GET_GOLD(ch));
  CAP(buf); S2C();

  sprintf(buf, "%s in bank: %d\n\r", currency_name_plural, GET_BANK_GOLD(ch));
  CAP(buf); S2C();

  if (PLSHOPS(ch))
    do_plshopbank(ch, "", 0, 0);
}

// create a save vs bar based on amt  5/30/98 -jtrhone
void get_sv_bar(int sv, char *barfinal)
{
  int i, num = 0;
  static char bar[MAX_INPUT_LENGTH];

  num = sv / 10;

  if (num <= 3)
    strcpy(bar, "%B%1");
  else
  if (num <= 7)
    strcpy(bar, "%B%3");
  else
    strcpy(bar, "%B%2");

  for (i = 0; i < num && i < 10; i++)
    strcat(bar, ">");

  strcat(bar, "%0");

  for (; i < 10; i++)
    strcat(bar, " ");

  sprintf(barfinal, "%%B%%4{%%0%s%%B%%4}%%0", bar);
}

// create an affect bar based on amt  5/30/98 -jtrhone
void get_aff_bar(int num, char *barfinal)
{
  int i;
  static char bar[MAX_INPUT_LENGTH];

  if (num <= 3)
    strcpy(bar, "%B%1");
  else
  if (num <= 7)
    strcpy(bar, "%B%3");
  else
    strcpy(bar, "%B%2");

  for (i = 0; i < num && i < 24; i++)
    strcat(bar, ">");

  strcat(bar, "%0");

  for (; i < 24; i++)
    strcat(bar, " ");

  sprintf(barfinal, "%%B%%4{%%0%s%%B%%4}%%0", bar);
}

// affect show screen, split up from normal score list
// updated to use bars... and show sv_vs_*  5/30/98 -jtrhone
// added EQ affects in a little list there like... 6/4/98 -jtrhone
ACMD(do_affects)
{
  struct affected_type *aff;
  char bar[MAX_INPUT_LENGTH];
  int bitv1 = 0, bitv2 = 0, i;
  char tmp1[MAX_INPUT_LENGTH], tmp2[MAX_INPUT_LENGTH];
  obdata *o;
  
  strcpy(buf, "%B%6Saves:%0\n\r%B-=-=-=-%0\n\r");
  get_sv_bar(SAVING_THROW(ch, SV_HEAT), bar);
  sprintf(buf+strlen(buf), "Save vs %%B%%1heat%%0  : %s\n\r", bar);
  get_sv_bar(SAVING_THROW(ch, SV_COLD), bar);
  sprintf(buf+strlen(buf), "Save vs %%B%%6cold%%0  : %s\n\r", bar);
  get_sv_bar(SAVING_THROW(ch, SV_MAGIC), bar);
  sprintf(buf+strlen(buf), "Save vs %%B%%5magic%%0 : %s\n\r", bar);
  get_sv_bar(SAVING_THROW(ch, SV_POISON), bar);
  sprintf(buf+strlen(buf), "Save vs %%B%%2poison%%0: %s\n\r", bar);
  get_sv_bar(SAVING_THROW(ch, SV_BREATH), bar);
  sprintf(buf+strlen(buf), "Save vs %%B%%3breath%%0: %s\n\n\r", bar);
  S2C();

  if (ch->affected) 
  {
    send_to_char("%B%6Affections:%0\n\r",ch);
    send_to_char(  "%B-=-=-=-=-=-%0\n\r",ch);
    for (*buf='\0', aff = ch->affected; aff; aff = aff->next) 
    {
      get_aff_bar(aff->duration+1, bar);
      sprintf(buf+strlen(buf), "%%B%-20.20s%%0 : %s\n\r", skill_names[aff->type], bar);
    }
    S2C();
    send_to_char("\n\r",ch);
  }

  // show list of eq affs...
  for (i = 0; i < MAX_WEAR; i++)
    if ((o = EQ(ch, i)))
    {
      bitv1 |= o->eqaffbit;
      bitv2 |= o->eqaff2bit;
    }

  if (bitv1)
  {
    sprintbit(bitv1, affected_bits, tmp1);
    sprintf(buf, "%%B%%6EQ Affects1%%0: %s\n\r", tmp1);
    S2C();
  }

  if (bitv2)
  {
    sprintbit(bitv2, affected2_bits, tmp2);
    sprintf(buf, "%%B%%6EQ Affects2%%0: %s\n\r", tmp2);
    S2C();
  }
  
  if (IS_PC(ch) && SINGING(ch))
  {
     sprintf(buf, "You are singing %%B%%6%s%%0.\n\r", song_names_cap[SINGING(ch)]);
     S2C();
   }

   if (IS_PC(ch) && PLAYING(ch))
   {
     sprintf(buf, "You are playing %%B%%6%s%%0.\n\r", song_names_cap[PLAYING(ch)]);
     S2C();
   }
}

ACMD(do_score)
{
   struct time_info_data playing_time;
   struct time_info_data real_time_passed(time_t t2, time_t t1);
   chdata *vict;
   char align[20];
   int i;

   playing_time = real_time_passed((time(0) - ch->player.time.logon) + 
       ch->player.time.played, 0);

   sprintf(buf, "%%5Name%%0: %-11s %%5Age%%0:  %d years %11s%%5GameTime%%0: %d days, %d hours\n\r",
	GET_NAME(ch), GET_AGE(ch), "", playing_time.day,playing_time.hours);
   S2C();

   str_cpy(buf2, currency_name_plural, MAX_STRING_LENGTH, "do_score");
   CAP(buf2);
   sprintf(buf, "%%5Str%%0: %s%2d%s/%s%3d%s %-6s%%5Hit%%0:  %4d(%4d) %-9s%%5%s%%0: %d\n\r",
	(GET_STR(ch) == ch->real_abils.str)?"":((GET_STR(ch) < ch->real_abils.str)?"%1":"%6"),GET_STR(ch),"%0",
	(GET_ADD(ch) == ch->real_abils.str_add)?"":((GET_ADD(ch) < ch->real_abils.str_add)?"%1":"%6"),GET_ADD(ch),"%0",
	"",GET_HIT(ch), GET_MAX_HIT(ch),"", buf2, GET_GOLD(ch));
   S2C();

   sprintf(buf, "%%5Int%%0: %s%2d%s %-10s%%5Mana%%0: %4d(%4d) %-9s%%5Total Exp%%0: %d\n\r",
	(GET_INT(ch) == ch->real_abils.intel)?"":((GET_INT(ch) < ch->real_abils.intel)?"%1":"%6"),GET_INT(ch),"%0",
	"", GET_MANA(ch), GET_MAX_MANA(ch), "", GET_EXP(ch));
   S2C();

   sprintf(buf, "%%5Wis%%0: %s%2d%s %-10s%%5Move%%0: %4d(%4d) %-9s",
	(GET_WIS(ch) == ch->real_abils.wis)?"":((GET_WIS(ch) < ch->real_abils.wis)?"%1":"%6"),GET_WIS(ch),"%0",
       	"", GET_MOVE(ch), GET_MAX_MOVE(ch), "");

   if (!IS_IMMORTAL(ch)) 
      sprintf(buf, "%s%%5Exp To Go%%0: %d\n\r", buf,
          (exp_table[GET_CLASS(ch)-1][GET_LEVEL(ch)+1]) - GET_EXP(ch));
   else
     str_cat(buf, "\n\r", MAX_STRING_LENGTH, "do_score");
   S2C();

   sprintf(buf, "%%5Dex%%0: %s%2d%s %-10s%%5AC%%0: %4d %-17s%%5Pracs%%0: %d\n\r",
	(GET_DEX(ch) == ch->real_abils.dex)?"":((GET_DEX(ch) < ch->real_abils.dex)?"%1":"%6"),GET_DEX(ch),"%0",
	"", GET_AC(ch), "",IS_PC(ch)?SPELLS_TO_LEARN(ch):0);
   S2C();

   if (GET_ALIGNMENT(ch) >= 900)
     strcpy(align, "%BHoly%0");
   else
   if (GET_ALIGNMENT(ch) > 400)
     strcpy(align, "%6Good%0");
   else
   if (GET_ALIGNMENT(ch) > -400)
     strcpy(align, "Neutral");
   else
   if (GET_ALIGNMENT(ch) > -900)
     strcpy(align, "%1Evil%0");
   else
   if (GET_ALIGNMENT(ch) <= -900)
     strcpy(align, "%1Demonic%0");

   sprintf(buf, "%%5Con%%0: %s%2d%s %-10s%%BArena Wins%%0: %3d %9s %%5Align%%0: %d (%s)\n\r",
	(GET_CON(ch) == ch->real_abils.con)?"":((GET_CON(ch) < ch->real_abils.con)?"%1":"%6"),GET_CON(ch),"%0",
	"", ((IS_PC(ch)) ? ch->pc_specials->saved.arena_wins : 0), 
	"", GET_ALIGNMENT(ch), align);
   S2C();

   sprintf(buf, "%%5Level %%6%d%%B%%7 %s ",GET_LEVEL(ch), genders[(int)GET_SEX(ch)]);
   if (IS_PC(ch))
   {
     strcat(buf, rcarray[(int)GET_RACE(ch)].racial_string);

     sprintf(buf+strlen(buf)," %s %%0%%5from %%B%%7%s%%0",clarray[(int)GET_CLASS(ch)].class_name, htowns[GET_HTOWN(ch)].name);
   }

   sprintf(buf, "%s, %%5speaking%%0 %%B%s%%0.\n\r",buf, gskill_names[SPEAKING(ch)]);
   S2C();

  if (IS_PC(ch))
  {
   if (ch->pc_specials->saved.clanleader && ch->pc_specials->saved.clan)
   {
     sprintf(buf, "%%5Leader of the clan%%0: %s.\n\r",ch->pc_specials->saved.clan);
     S2C();
   }
   else
   if (ch->pc_specials->saved.in_clan && ch->pc_specials->saved.clan)
   {
     sprintf(buf, "%%5Member of the clan%%0: %s.\n\r",ch->pc_specials->saved.clan);
     S2C();
   }
  }

  if ((age(ch).month == 0) && (age(ch).day == 0))
     send_to_char("It's your birthday today.\n\r",ch);

  if (IS_SHAMAN(ch))
  {
    if (RITES(ch) >= 0)
      sprintf(buf, "%%6Rituals left today%%0: %d\n\r", RITES(ch)); 
    else
      sprintf(buf, "%%6Ritual deficit%%0: %d\n\r", RITES(ch)); 
    S2C();
  }

  if (IS_WARLOCK(ch))
  {
    sprintf(buf, "%%6Warlock Ability Level%%0: %d\n\r", GET_WLEVEL(ch));
    S2C();
  }

  if (QUEST_PTS(ch) > 0)
  {
    sprintf(buf, "%%6Quest points%%0: %d\n\r",(int)QUEST_PTS(ch));
    S2C();
  }

  strcpy(buf, "%B%5Specials%0:");
  if (PRF_FLAGGED(ch, PRF_REQASS))
      str_cat(buf, " %1*Req Assassin*%0", MAX_STRING_LENGTH, "do_score");
  if (PRF_FLAGGED(ch, PRF_ASSASSIN))
      str_cat(buf, " %1*Assassin*%0", MAX_STRING_LENGTH, "do_score");
  if (IN_ARENA(ch))
      str_cat(buf, " (%B%6ARENA%0)", MAX_STRING_LENGTH, "do_score");
  if (PRF_FLAGGED(ch, PRF_ALOOT))
     str_cat(buf, " %6Aloot%0", MAX_STRING_LENGTH, "do_score");
  if (PRF_FLAGGED(ch, PRF_AGOLD))
     str_cat(buf, " %6Agold%0", MAX_STRING_LENGTH, "do_score");
  if (PRF_FLAGGED(ch, PRF_ASPLIT))
     str_cat(buf, " %6Asplit%0", MAX_STRING_LENGTH, "do_score");
  str_cat(buf, "\n\r", MAX_STRING_LENGTH, "do_score");
  S2C();

  // updated for new PLR2 flag order  1/18/98 -jtrhone
  if (num_remorts(ch))
  {
    strcpy(buf, "%B%5Dual Classes%0:");
    for (i=0; i < NUM_CLASSES; i++)
      if (PLR2_FLAGGED(ch, (1 << i)))
	sprintf(buf+strlen(buf), " %%6%s%%0", clarray[i+1].class_name);
    str_cat(buf, "\n\r", MAX_STRING_LENGTH, "do_score");
    S2C();
  }

  *buf = '\0';
  switch (GET_POS(ch)) {
   case POS_DEAD :
      str_cat(buf, "You are DEAD!\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_MORTALLYW :
      str_cat(buf, "You are mortally wounded!  You should seek help!\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_INCAP :
      str_cat(buf, "You are incapacitated, slowly fading away...\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_STUNNED :
      str_cat(buf, "You are stunned!  You can't move!\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_SLEEPING :
      str_cat(buf, "You are sleeping.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_RESTING  :
      str_cat(buf, "You are resting.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_SITTING  :
      str_cat(buf, "You are sitting.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_FIGHTING :
      if (FIGHTING(ch))
	 sprintf(buf, "%sYou are fighting %s.\n\r", buf, PERS(FIGHTING(ch), ch));
      else
	 str_cat(buf, "You are fighting thin air.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_STANDING :
      str_cat(buf, "You are standing.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_FLOATING:
      str_cat(buf, "You are floating.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   case POS_MOUNTED:
     if ((vict = get_mount_in_room(ch)))
     {
      str_cat(buf, "You are mounted on ", MAX_STRING_LENGTH, "do_score");
      str_cat(buf, GET_NAME(vict), MAX_STRING_LENGTH, "do_score");
      str_cat(buf, ".\n\r", MAX_STRING_LENGTH, "do_score");
     }
     else
       str_cat(buf, "You are mounted on a thin cushion of air!\n\r", MAX_STRING_LENGTH, "do_score");
     break;
   default :
      str_cat(buf, "You are just happily mellow.\n\r", MAX_STRING_LENGTH, "do_score");
      break;
   }
  if (*buf)
   S2C();

  *buf = '\0';
  if (IS_PC(ch))
  {
   if (GET_COND(ch, DRUNK) > 10)
      str_cat(buf, "%BYou are intoxicated%0.\n\r", MAX_STRING_LENGTH, "do_score");

   if (GET_COND(ch, FULL) == 0)
      str_cat(buf, "%BYou are hungry%0.\n\r", MAX_STRING_LENGTH, "do_score");

   if (GET_COND(ch, THIRST) == 0)
      str_cat(buf, "%BYou are thirsty%0.\n\r", MAX_STRING_LENGTH, "do_score");
  }
  if (*buf)
    S2C();
}

ACMD(do_time)
{
   char	*suf;
   int	weekday, day;
   extern const char	*longdays[];
   extern const char	*shortdays[];
   extern const char	*month_names[16];

   if (IS_NPC(ch)) return;

   sprintf(buf, "It is %d o'clock %s, on ",
       ((time_info.hours % 12 == 0) ? 12 : ((time_info.hours) % 12)),
       ((time_info.hours >= 12) ? "pm" : "am") );

   /* 35 days in a month */
   weekday = ((35 * time_info.month) + time_info.day + 1) % 7;

   sprintf(buf+strlen(buf),"%s, %%B%%5%s%%0.\n\r",shortdays[weekday],
	   longdays[weekday]);
   S2C();

   day = time_info.day + 1;   /* day in [1..35] */

   if (day == 1)
      suf = "st";
   else if (day == 2)
      suf = "nd";
   else if (day == 3)
      suf = "rd";
   else if (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, "The %%6%d%s%%0 Day of the %%5%s%%0, Year %%B%d%%0.\n\r",
       day, suf, month_names[(int)time_info.month], time_info.year);
   S2C();
}

// just put the mud date/time in a buffer/s  3/19/98 -jtrhone
void fill_time_buf(char *txt1, char* txt2)
{
   char	*suf;
   int	weekday, day;
   extern const char	*longdays[];
   extern const char	*shortdays[];
   extern const char	*month_names[16];

   sprintf(txt1, "It is %d o'clock %s, on ",
       ((time_info.hours % 12 == 0) ? 12 : ((time_info.hours) % 12)),
       ((time_info.hours >= 12) ? "pm" : "am") );

   /* 35 days in a month */
   weekday = ((35 * time_info.month) + time_info.day + 1) % 7;

   sprintf(txt1+strlen(txt1),"%s, %%B%%5%s%%0.\n\r",shortdays[weekday], longdays[weekday]);

   // now line 2
   day = time_info.day + 1;   /* day in [1..35] */

   if (day == 1)
      suf = "st";
   else if (day == 2)
      suf = "nd";
   else if (day == 3)
      suf = "rd";
   else if (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(txt2, "The %%6%d%s%%0 Day of the %%5%s%%0, Year %%B%d%%0.\n\r",
       day, suf, month_names[(int)time_info.month], time_info.year);
}

ACMD(do_weather)
{
  int zone;
  zndata *zn;
  extern char *accum_names[];
  extern char *precip_names[];
  extern char *gen_time_names[];
  extern char *season_names[];

  if (IN_NOWHERE(ch)) return;
  zone = world[ch->in_room].zone;

  zn = &zone_table[zone];  /* point zn to it, easier to work with */

  /* first lets get the zone weather data they are inside of */
  if (OUTSIDE(ch))
  {
    send_to_char("%B%5Current  Weather  Conditions%0\n\r",ch);
    send_to_char("%B%6-=-=-=-=-=-=-=-=-=-=-=-=-=-=%0\n\r",ch);
    sprintf(buf, "In this %s season, it is currently %s.\n\r",
		season_names[global_weather.season],
		gen_time_names[global_weather.sunlight]);
    sprintf(buf+strlen(buf), 
		 "%%6Approximate Temperature%%0: %2d.\n\r",zn->current_gtemp);
    sprintf(buf+strlen(buf),
		 "%%6Precip Type%%0: %s.\n\r",precip_names[zn->current_status]);

    if (zn->accum > 0)
      sprintf(buf+strlen(buf),
		 "%%6Accumulation amount%%0: %d inches of %s.\n\r",
		  zn->accum,accum_names[zn->accum_type]);
    page_string(ch->desc, buf, 1);
  }
  else
    send_to_char("That's difficult to tell when you are inside.\n\r", ch);
}

#define WHO_FORMAT \
"format: who [-f][-l minlev[-maxlev]][-n name][-s][-r][-z]\n\r"

// for lord/lady/ambass/impl/aimp/etc
// Added different colors for number of remorts. 08/05/98 -callahan
void get_level_title(chdata *tch, char *buf2)
{
  char titlebuf[20];

  if (!IS_IMMORTAL(tch) && PLR_FLAGGED(tch, PLR_LEGEND))
  {
    if (num_remorts(tch)) {
      switch(num_remorts(tch)) {
      case 1:
        strcpy(buf2, "%B%5[%0Legend%B%5]%0");	// Bold magenta
        break;
      case 2:
        strcpy(buf2, "%6[%0Legend%6]%0");	// Cyan
        break;
      case 3:
        strcpy(buf2, "%2[%0Legend%2]%0");	// Green
        break;
      case 4:
        strcpy(buf2, "%3[%0Legend%3]%0");	// Yellow
        break;
      case 5:
        strcpy(buf2, "%B%4[%0Legend%B%4]%0");	// Bold Blue
        break;
      case 6:
        strcpy(buf2, "%5[%0Legend%5]%0");	// Magenta
        break;
      case 7:
        strcpy(buf2, "%1[%0Legend%1]%0");	// Red
        break;
      case 8:
        strcpy(buf2, "%B%6[%0Legend%B%6]%0");	// Bold Cyan
        break;
      case 9:
        strcpy(buf2, "%B%3[%0Legend%B%3]%0");	// Bold Yellow
        break;
      case 10:
        strcpy(buf2, "%B%1[%0Legend%B%1]%0");	// Bold Red
        break;
      default:
        strcpy(buf2, "%B%2[%0Legend%B%2]%0");	// Bold Green
        break;
      }
    } else
      strcpy(buf2, "[Legend]");
    return;
  }

  switch (GET_LEVEL(tch)) {
  case LEV_IMPL:
    sprintf(buf2, "%%B%%6[%s]%%0", impname);
    break;
  case LEV_CIMP:
    sprintf(buf2, "%%B[%s]%%0", cimpname);
    break;
  case LEV_AIMP:
    sprintf(buf2, "%%B[%s]%%0", aimpname);
    break;
  case LEV_GOD:
    sprintf(buf2, "%%B[%s]%%0", godname);
    break;
  case LEV_IMM:
    if (PLR_FLAGGED(tch, PLR_AMBASS))
    sprintf(buf2,   "[%s]", ambassname);
    else
    if (PLR_FLAGGED(tch, PLR_TRUSTED))
    sprintf(buf2, "%%B[%s]%%0", trustedname);
    else
    sprintf(buf2,   "[%s]", avtrname);
    break;

  case LEV_LORD:
    switch ((int)GET_SEX(tch)) {
      case SEX_FEMALE:
        if (num_remorts(tch))
          sprintf(titlebuf, "%-6.6s",
                  clarray[(int)GET_CLASS(tch)].female_legend);
        else
          sprintf(buf2, "[%-6.6s]", clarray[(int)GET_CLASS(tch)].female_legend);
	break;
      default:
        if (num_remorts(tch))
          sprintf(titlebuf, "%-6.6s",
                  clarray[(int)GET_CLASS(tch)].male_legend);
        else
          sprintf(buf2, "[%-6.6s]", clarray[(int)GET_CLASS(tch)].male_legend);
	break;
    }

    if (num_remorts(tch))
      switch(num_remorts(tch)) {
      case 1:
        // Bold magenta
        sprintf(buf2, "%%B%%5[%%0%s%%B%%5]%%0", titlebuf);
        break;
      case 2:
        // Cyan
        sprintf(buf2, "%%6[%%0%s%%6]%%0", titlebuf);
        break;
      case 3:
        // Green
        sprintf(buf2, "%%2[%%0%s%%2]%%0", titlebuf);
        break;
      case 4:
        // Yellow
        sprintf(buf2, "%%3[%%0%s%%3]%%0", titlebuf);
        break;
      case 5:
        // Bold Blue
        sprintf(buf2, "%%B%%4[%%0%s%%B%%4]%%0", titlebuf);
        break;
      case 6:
        // Magenta
        sprintf(buf2, "%%5[%%0%s%%5]%%0", titlebuf);
        break;
      case 7:
        // Red
        sprintf(buf2, "%%1[%%0%s%%1]%%0", titlebuf);
        break;
      case 8:
        // Bold Cyan
        sprintf(buf2, "%%B%%6[%%0%s%%B%%6]%%0", titlebuf);
        break;
      case 9:
        // Bold Yellow
        sprintf(buf2, "%%B%%3[%%0%s%%B%%3]%%0", titlebuf);
        break;
      case 10:
        // Bold Red
        sprintf(buf2, "%%B%%1[%%0%s%%B%%1]%%0", titlebuf);
        break;
      default:
        // Bold Green
        sprintf(buf2, "%%B%%2[%%0%s%%B%%2]%%0", titlebuf);
        break;
      }
    break;

  default: 
    strcpy(buf2, "[------]");
    break;
  }
}

void GetWhoInfo(CharData *ch, char *buf)
{
  char titlebuf[20];

  sprintf(titlebuf, "%2d %s", Level(ch), CLASS_ABBR(ch));
    
  if (num_remorts(ch)) {
    switch(num_remorts(ch)) {
    case 1:
      // Bold magenta
      sprintf(buf, "%%B%%5[%%0%s%%B%%5]%%0", titlebuf);
      break;
    case 2:
      // Cyan
      sprintf(buf, "%%6[%%0%s%%6]%%0", titlebuf);
      break;
    case 3:
      // Green
      sprintf(buf, "%%2[%%0%s%%2]%%0", titlebuf);
      break;
    case 4:
      // Yellow
      sprintf(buf, "%%3[%%0%s%%3]%%0", titlebuf);
      break;
    case 5:
      // Bold Blue
      sprintf(buf, "%%B%%4[%%0%s%%B%%4]%%0", titlebuf);
      break;
    case 6:
      // Magenta
      sprintf(buf, "%%5[%%0%s%%5]%%0", titlebuf);
      break;
    case 7:
      // Red
      sprintf(buf, "%%1[%%0%s%%1]%%0", titlebuf);
      break;
    case 8:
      // Bold Cyan
      sprintf(buf, "%%B%%6[%%0%s%%B%%6]%%0", titlebuf);
      break;
    case 9:
      // Bold Yellow
      sprintf(buf, "%%B%%3[%%0%s%%B%%3]%%0", titlebuf);
      break;
    case 10:
      // Bold Red
      sprintf(buf, "%%B%%1[%%0%s%%B%%1]%%0", titlebuf);
      break;
    default:
      // Bold Green
      sprintf(buf, "%%B%%2[%%0%s%%B%%2]%%0", titlebuf);
      break;
    }
    sprintf(buf, "%s %s %s%%0", buf, Name(ch), Title(ch));
  } else
    sprintf(buf, "[%s] %s %s%%0", titlebuf, Name(ch), Title(ch));
}

/* sort who returns to qsort IN REVERSE order... i.e. DESCENDING */
int sort_who(const void *first, const void *second)
{
  struct who_data *one, *two;

  one = (struct who_data *) first;
  two = (struct who_data *) second;

  if (one->level < two->level)
    return 1;
  else
  if (one->level > two->level)
    return -1;
  else 
    return 0;
}

ACMD(do_who)
{
   int sort_who(const void *first, const void *second);
   char *argu = argument, name_search[80], mode;
   dsdata *d;
   chdata *tch = NULL, *real_ch = NULL;
   int	low = 0, high = LEV_IMPL, i, num_can_see = 0, whonum = 0;
   BOOL localwho = 0, short_list = 0, who_room = 0, flags = 0;
   static char whoarg[MAX_INPUT_LENGTH];
   static char buf[20000];

   if (IN_NOWHERE(ch)) return;

   if (strlen(argument) > MAX_POOFIN_LENGTH -10)
   {
     send_to_char("Nice try... the gods have been alerted to your attempt.\n\r",ch);
     sprintf(buf, "WARNING: %s attempted crash with WHO",GET_NAME(ch));
     mudlog(buf, NRM, LEV_IMM, TRUE); 
     return;
   }

   clear_who_list();

   skip_spaces(&argu);
   str_cpy(whoarg, argu, MAX_INPUT_LENGTH, "do_who");

   *name_search = '\0';

   while (*whoarg) 
   {
      half_chop(whoarg, arg, buf1);
      if (isdigit(*arg))
      {
	 sscanf(arg, "%d-%d", &low, &high);
	 str_cpy(whoarg, buf1, MAX_INPUT_LENGTH, "do_who");
      }
      else 
      if (*arg == '-' && (*arg+1))
      {
	 mode = *(arg + 1); /* point mode to the flag */
	 switch (mode) {
	 case 'f':
	    flags = TRUE;
	    str_cpy(whoarg, buf1, MAX_INPUT_LENGTH, "do_who");
	    break;
	 case 'z':
	    localwho = TRUE;
	    str_cpy(whoarg, buf1, MAX_INPUT_LENGTH, "do_who");
	    break;
	 case 's':
	    short_list = TRUE;
	    str_cpy(whoarg, buf1, MAX_INPUT_LENGTH, "do_who");
	    break;
	 case 'l':
	    half_chop(buf1, arg, whoarg);
	    sscanf(arg, "%d-%d", &low, &high);
	    break;
	 case 'n':
	    half_chop(buf1, name_search, whoarg);
	    break;
	 case 'r':
	    who_room = TRUE;
	    str_cpy(whoarg, buf1, MAX_INPUT_LENGTH, "do_who");
	    break;
	 default:
	    send_to_char(WHO_FORMAT, ch);
	    return;
	    break;
	 } /* end of switch */
      }
      else 
      { /* endif */
	 send_to_char(WHO_FORMAT, ch);
	 return;
      }
   } /* end while (parser) */

   for (d = descriptor_list; d; d = d->next) 
   {
      if (d->connected) continue;
      if (!(tch = d->character)) continue;

      /* NPC check here just to make sure we dont ref any pc_specs on npc*/
      if (IS_NPC(tch) && !IS_SWITCHED(tch)) continue;

	// if switched into a mob, use the original character for CAN_SEE
      if (IS_NPC(ch) && ch->desc && ch->desc->original)
	real_ch = ch->desc->original;
      else
	real_ch = ch;

      /* incognito hides everything except name/title about player */
      if (!IS_NPC(tch) && INCOG(tch) && !IS_IMMORTAL(ch) && can_see(real_ch, tch)) 
      {
         if (short_list) 
	 {
	   sprintf(buf, "[      ] %-11.11s%s%%0", GET_NAME(tch),
	           ((++num_can_see % 4) ? "" : "\n\r"));
	   S2C();
	   continue;
         } 
         else 
	 {
           sprintf(buf, "[      ] %s %s%%0\n\r",GET_NAME(tch), IS_PC(tch)?GET_TITLE(tch):"<>");

	   strcpy(who_list[whonum].name, buf);
 	   who_list[whonum].level = GET_LEVEL(tch);
	   if (IS_PC(tch))
 	     who_list[whonum].incog = INCOG(tch);
	   else
 	     who_list[whonum].incog = TRUE;
           whonum++;  
           num_can_see++;   
           continue;  /* ppl incognito are not identified by a special who*/ /* JRhone 2/95 */
         }
      }

      if (IS_PC(tch))
      {
        if (*name_search && str_cmp(GET_NAME(tch), name_search) && !strstr(GET_TITLE(tch), name_search))
	 continue;

        if ((!IS_IMMORTAL(ch) && INCOG(tch)) || !can_see(real_ch, tch) || 
            GET_LEVEL(tch) < low || GET_LEVEL(tch) > high)
	 continue;
      }

      // sneaking fix for who -z (do not show chars who be sneaking  6/14/98 -jtrhone)
      if (localwho && (world[ch->in_room].zone != world[tch->in_room].zone || IS_AFFECTED(tch, AFF_SNEAK)))
        continue;

      if (who_room && (tch->in_room != ch->in_room))
	 continue;

      if (short_list) 
      {
	 if (IS_PC(tch))
	   sprintf(buf, "[%2d %s] %-11.11s%s%%0", GET_LEVEL(tch), CLASS_ABBR(tch), GET_NAME(tch),
	           ((++num_can_see % 4) ? "" : "\n\r"));
	 S2C();
      } 
      else 
      {
	 num_can_see++;

	 /* lets do npcs first */
	 if (IS_NPC(tch) && IS_SWITCHED(tch))
	 {
	  sprintf(buf2," (%%B%s%%0)", GET_NAME(tch->desc->original));
 	  sprintf(buf, "[NPC   ] %s%s%%0",GET_NAME(tch),
		 (GET_LEVEL(ch) >= GET_LEVEL(tch->desc->original)) ? buf2 : "");
	 }
         else if (Level(tch) < LEV_LORD)
           GetWhoInfo(tch, buf);
         else 
	 {
	   get_level_title(tch, buf2);
	   sprintf(buf, "%s %s%s%%0 %s", buf2, GET_PRENAME(tch), GET_NAME(tch), 
		   GET_TITLE(tch));
	 }

	if (IS_PC(tch))
	{
         /* clan who stuff James Rhone */
  	 if (tch->pc_specials->saved.in_clan)
	   sprintf(buf + strlen(buf), " (%s)%s", tch->pc_specials->saved.clan,
	  	   (tch->pc_specials->saved.clanleader)?"+":"");

         // AFK stuff modified for string-handling. 05/04/98 -callahan
	 // Added idle for idletime of more than 5 minutes. 06/26/98 -callahan
	 if (AFK(tch)) {
           if (AFKString(tch)) {
             if ((time(NULL) - tch->desc->last_time) >= 60)
               sprintf(buf, "%s (%%BAFK %s:%s%%0)", buf,
                       time_format_2(time(NULL) - tch->desc->last_time),
                       AFKString(tch));
             else
               sprintf(buf, "%s (%%BAFK:%s%%0)", buf, AFKString(tch));
           } else if ((time(NULL) - tch->desc->last_time) >= 60)
             sprintf(buf, "%s (%%BAFK %s%%0)", buf,
                     time_format_2(time(NULL) - tch->desc->last_time));
         } else if ((time(NULL) - tch->desc->last_time) >= 300)
           sprintf(buf, "%s (%%BIdle %s%%0)", buf,
                   time_format_2(time(NULL) - tch->desc->last_time));

	 if (PLR_FLAGGED(tch, PLR_BUILDING))
	    strcat(buf, " (%BOLC%0)");
	 if (PLR2_FLAGGED(tch, PLR2_MENTOR))
	    strcat(buf, " (%BMENTOR%0)");

	if (flags)
	{ 
         if (IN_ARENA(tch))
             strcat(buf, "(%B%6ARENA%0)");
         if (PLR_FLAGGED(tch, PLR_RITUAL))
             strcat(buf, "(ritual)");
         if (PRF_FLAGGED(tch, PRF_REQASS))
             strcat(buf, "(%1Req Assassin%0)");
	 else
         if (PRF_FLAGGED(tch, PRF_ASSASSIN))
             strcat(buf, "(%1Assassin%0)");
       	 if (GET_INVIS_LEV(tch))
	    sprintf(buf, "%s (i%d)", buf, GET_INVIS_LEV(tch));
	 else 
	 if (IS_AFFECTED(tch, AFF_INVISIBLE))
	    strcat(buf, "(invis)");
	 if (PLR_FLAGGED(tch, PLR_MAILING))
	    strcat(buf, "(mailing)");
	 if (PLR_FLAGGED(tch, PLR_WRITING))
	    strcat(buf, "(posting)");
	 if (PRF_FLAGGED(tch, PRF_DEAF))
	    strcat(buf, "(deaf)");
	 if (PRF_FLAGGED(tch, PRF_NOTELL))
	    strcat(buf, "(notell)");
	 if (PRF_FLAGGED(tch, PRF_QUEST))
	    strcat(buf, "(quest)");
	} /* end if flags */
	} /* end if pc */

	 if (IS_NPC(tch) || IS_IMMORTAL(tch))
	    strcat(buf, "%0");  /* color normal */
	 strcat(buf, "\n\r");
	 strcpy(who_list[whonum].name, buf);

 	 who_list[whonum].level = GET_LEVEL(tch);

	 if (IS_PC(tch))
           who_list[whonum].incog = INCOG(tch);
	 else
           who_list[whonum].incog = TRUE;
         whonum++;
      } /* endif shortlist */
   } /* end of for */

   if (short_list && !(num_can_see % 4))
     send_to_char("\n\r", ch);
   buf[0] = '\0';

  /* ROA NEW WHO... jtrhone */
  if (!short_list)  
  {
   qsort((void *) who_list, MAX_PLAYERS, sizeof(struct who_data), sort_who);
   i = 0;
   if (who_list[i].level >= LEV_IMM)
     sprintf(buf+strlen(buf),"%%5%%B-=-=-=-%s Immortal Staff-=-=-=-%%0\n\r",shortmudname);
   while (who_list[i].level >= LEV_IMM)
   {
     strcat(buf, who_list[i].name);
     i++;
   }
   if (who_list[i].level > 0)
     strcat(buf, "%7%B-=-=-=-=-=-=-Mortals-=-=-=-=-=-=%0\n\r");
   while (who_list[i].level > 0)
   {
     if (!who_list[i].incog)
       strcat(buf, who_list[i].name);
     i++;
   }
   i = 0;
   while (i < MAX_PLAYERS && who_list[i].level > 0)
   {
     if (who_list[i].level < LEV_IMM && who_list[i].incog)
      strcat(buf, who_list[i].name);
     i++;
   }   
  }
  sprintf(buf1, "\n\r%d visible character%s.\n\r", num_can_see, (num_can_see != 1)?"s":"");
  strcat(buf, buf1);
  page_string(ch->desc, buf, 1);
}

void who_to_buf(char *whobuf)
{
   int sort_who(const void *first, const void *second);
   dsdata *d;
   chdata *tch = NULL;
   int i, num_can_see = 0;
   int whonum = 0;
   static char buf[20000];

   clear_who_list();

   for (d = descriptor_list; d; d = d->next) 
   {
      if (d->connected) continue;
      if (!(tch = d->character)) continue;
      if (GET_INVIS_LEV(tch) > 0) continue;

      /* incognito hides everything except name/title about player */
      if (!IS_NPC(tch) && INCOG(tch))
      {
           sprintf(buf, "[      ] %s %s%%0\n\r",GET_NAME(tch), 
		IS_PC(tch)?GET_TITLE(tch):"<>");
	   strcpy(who_list[whonum].name, buf);
 	   who_list[whonum].level = GET_LEVEL(tch);
	   if (IS_PC(tch))
 	     who_list[whonum].incog = INCOG(tch);
	   else
 	     who_list[whonum].incog = TRUE;
           whonum++;  
           num_can_see++;   
           continue;  /* ppl incognito are not identified by a special who*/
                      /* JRhone 2/95 */
      }

      num_can_see++;

      if (Level(tch) < LEV_LORD)
        GetWhoInfo(tch, buf);
      else 
      {
	   get_level_title(tch,buf2);
	   sprintf(buf, "%s %s%s%%0 %s", buf2, GET_PRENAME(tch), GET_NAME(tch), GET_TITLE(tch));
      }

	 strcat(buf, "\n\r");
	 strcpy(who_list[whonum].name, buf);

 	 who_list[whonum].level = GET_LEVEL(tch);

	 if (IS_PC(tch))
           who_list[whonum].incog = INCOG(tch);
	 else
           who_list[whonum].incog = TRUE;
         whonum++;
   } /* end of for */

   i = 0;
   strcpy(whobuf, "\n\r");
   qsort((void *) who_list, MAX_PLAYERS, sizeof(struct who_data), sort_who);
   if (who_list[i].level >= LEV_IMM)
     sprintf(whobuf+strlen(whobuf),"%%5%%B-=-=-=-%s Immortal Staff-=-=-=-%%0\n\r",shortmudname);
   while (who_list[i].level >= LEV_IMM)
   {
     strcat(whobuf, who_list[i].name);
     i++;
   }
   if (who_list[i].level > 0)
     strcat(whobuf, "%7%B-=-=-=-=-=-=-Mortals-=-=-=-=-=-=%0\n\r");
   while (who_list[i].level > 0)
   {
     if (!who_list[i].incog)
       strcat(whobuf, who_list[i].name);
     i++;
   }
   i = 0;
   while (i < MAX_PLAYERS && who_list[i].level > 0)
   {
     if (who_list[i].level < LEV_IMM && who_list[i].incog)
      strcat(whobuf, who_list[i].name);
     i++;
   }   

  sprintf(buf1, "\n\r%d visible character%s.\n\r", num_can_see,
	  (num_can_see != 1)?"s":"");
  strcat(whobuf, buf1);
}

#define USERS_FORMAT \
"format: users [-l minlevel[-maxlevel]] [-n name] [-h host] [-d] [-p]\n\r"

ACMD(do_users)
{
  chdata *tch;
  dsdata *d;
  char line[200], line2[220], idletime[10], classname[10], state[30],
       name_search[100], host_search[100], mode, *format;
  int low = 0, high = LEV_IMPL, num_can_see = 0, playing = 0, deadweight = 0,
      client = 0;
  static char buf2[20000];
  extern void fill_descriptor_state(dsdata *d, char *buf);

  if (strlen(argument) > MAX_POOFIN_LENGTH -1) {
    send_to_char("Nice try... the gods have been alerted to your attempt\n\r",ch);
    sprintf(buf, "WARNING: %s attempted crash with USERS",GET_NAME(ch));
    mudlog(buf, NRM, LEV_IMM, TRUE); 
    return;
  }

  host_search[0] = name_search[0] = '\0';
  *buf2 = '\0';

  str_cpy(buf, argument, MAX_STRING_LENGTH, "do_users");

  while (*buf) {
    half_chop(buf, arg, buf1);
    if (*arg == '-') {
      mode = *(arg + 1); /* just in case; we destroy arg in the switch */

      switch (mode) {
      case 'p':
        playing = TRUE;
        str_cpy(buf, buf1, MAX_STRING_LENGTH, "do_users");
        break;
      case 'd':
        deadweight = TRUE;
        str_cpy(buf, buf1, MAX_STRING_LENGTH, "do_users");
        break;
      case 'l':
        playing = TRUE;
        half_chop(buf1, arg, buf);
        sscanf(arg, "%d-%d", &low, &high);
        break;
      case 'n':
        playing = TRUE;
        half_chop(buf1, name_search, buf);
        break;
      case 'h':
        playing = TRUE;
        half_chop(buf1, host_search, buf);
        break;
      case 'c':
        client = TRUE;
        playing = TRUE;
        half_chop(buf1, host_search, buf);
        break;
      default:
        send_to_char(USERS_FORMAT, ch);
        return;
        break;
      } 
    } else { 
      send_to_char(USERS_FORMAT, ch);
      return;
    }
  } 

  strcpy(line, "%6Num Class    Name         State             On for Idle Site\r\n");
  strcat(line, "%5=-= =-=-=-=- =-=-=-=-=-=- =-=-=-=-=-=-=- =-=-=-=-= =-=- =-=-=-=-=-=-=-=-=-=-=-%0\r\n");

  send_to_char(line, ch);

  one_argument(argument, arg);

  Descriptors(d) {
    if (d->connected && playing)
      continue;

    if (!d->connected && deadweight)
      continue;

    if (!HAS_CLIENT(d) && client)
      continue;

    if (!d->connected) {
      if (d->original)
        tch = d->original;
      else if (!(tch = d->character))
        continue;

      if (*host_search && !strstr(d->host, host_search))
        continue;

      if (*name_search && str_cmp(Name(tch), name_search) && 
          !strstr(Title(tch), name_search))
        continue;

      if (!can_see(ch, tch) || Level(tch) < low || Level(tch) > high)
        continue;

      if (GET_INVIS_LEV(tch) > Level(ch))
        continue;

      if (d->original)
        sprintf(classname, "[%2d %s]", Level(d->original), CLASS_ABBR(d->original));
      else
        sprintf(classname, "[%2d %s]", Level(d->character), CLASS_ABBR(d->character));
    } else
      strcpy(classname, "  ---   ");

    if (!d->connected && d->original)
      str_cpy(state, "Switched", 30, "do_users");
    else
      fill_descriptor_state(d, state);

    sprintf(idletime, "%4s", time_format_2(time(NULL) - d->last_time));

    format = "%3d %-7s %-12s %-14s %9s %-4s ";

    if (d->character && d->character->player.name) {
      if (d->original)
        sprintf(line, format, d->desc_num, classname,
                d->original->player.name, state,
                time_format_1(time(NULL) - d->login_time), idletime);
      else
        sprintf(line, format, d->desc_num, classname,
                d->character->player.name, state,
                time_format_1(time(NULL) - d->login_time), idletime);
    } else
      sprintf(line, format, d->desc_num, "  ---   ", "UNDEFINED", state,
              time_format_1(time(NULL) - d->login_time), idletime);

    if (d->host && *d->host)
      sprintf(line + strlen(line), "%s\n\r", d->host);
    else
      strcat(line, "Hostname unknown\n\r");

    if (d->connected) {
      sprintf(line2, "%%3%s%%0", line);
      strcpy(line, line2);
    }

    if (d->connected || (D_CHECK(d) && can_see(ch, d->character))) {
      strcat(buf2, line);
      num_can_see++;
    }
  }

  sprintf(buf2+strlen(buf2), "\n\r%d visible sockets connected.\n\r", num_can_see);

  // 04/06/98 -callahan
  uptime_to_buf(buf);
  str_cat(buf2, buf, 20000, "do_users");

  // 05/01/98 -callahan
  date_to_buf(buf);
  sprintf(buf2, "%sCurrent: %s\r\n", buf2, buf);

  page_string(ch->desc, buf2, 1);
}

ACMD(do_inventory)
{
   send_to_char("You are carrying:\n\r", ch);
   list_obj_to_char(ch->carrying, ch, O_INV_MODE, TRUE);
   do_icount(ch, "", 0, 0);
}

ACMD(do_equipment)
{
  int	j;
  BOOL found;
  char cstr[MAX_INPUT_LENGTH];

  send_to_char("You are using:\n\r", ch);
  for (found = j = 0; j < MAX_WEAR; j++) 
  {
     if (EQ(ch, j)) 
     {
       if (WV_FLAGS(EQ(ch, j)))
         sprintbit(WV_FLAGS(EQ(ch,j)), wv_bits, buf2);
       else
         strcpy(buf2, "");

       sprintf(cstr, "%s %s%s%s", wv_bits[j], *buf2 ? "(" : "" , buf2, *buf2 ? ")" : "" );
       if (CAN_SEE_OBJ(ch, EQ(ch, j))) 
         sprintf(buf, "%%B%-35s%%0: %s\n\r", cstr,  EQ(ch, j)->shdesc);
       else 
         sprintf(buf, "%%B%-35s%%0: %%4Something...%%0\n\r", cstr);
       S2C();            
       found = TRUE;
     }
  }
  if (!found) 
    send_to_char(" Nothing.\n\r", ch);
}

ACMD(do_armor)
{
  int	j, tot = 0;
  BOOL found;
  obdata *o;

  send_to_char("Armor affects by position:\n\r", ch);
  for (found = j = 0; j < MAX_WEAR; j++) 
  {
    if ((o = EQ(ch, j)))
    {
	 if (CAN_SEE_OBJ(ch, o)) 
	 {
	    send_to_char(armor_where[j], ch);
            if (ITEM_TYPE(o) == ITEM_ARMOR)
	    { 
	      tot -= o->value[0];
              sprintf(buf, " %d (%10s)\n\r", -(o->value[0]),o->shdesc);
     	    }
            else
              sprintf(buf, " N/A\n\r");
            S2C();
	    found = TRUE;
	 } 
	 else 
	 {
	    send_to_char(armor_where[j], ch);
	    send_to_char(" Affect Unknown.\n\r", ch);
	    found = TRUE;
	 }
    }
  }
  if (!found) 
    send_to_char(" No affects.\n\r", ch);
  else
  {
    sprintf(buf, "Total worn armor affection: %d\n\r",tot);
    S2C();
  }
}

ACMD(do_gen_ps)
{
   switch (subcmd) {
   case SCMD_CREDITS : page_string(ch->desc, credits, 0); break;
   case SCMD_NEWS    : page_string(ch->desc, news, 0); break;
   case SCMD_MOTD    : page_string(ch->desc, motd, 0); break;
   case SCMD_IMOTD   : page_string(ch->desc, imotd, 0); break;
   case SCMD_RACES   : page_string(ch->desc, races, 0); break;
   case SCMD_INFO    : page_string(ch->desc, info, 0); break;
   case SCMD_WIZLIST : page_string(ch->desc, wizlist, 0); break;
   case SCMD_IMMLIST : page_string(ch->desc, immlist, 0); break;
   case SCMD_HANDBOOK: page_string(ch->desc, handbook, 0); break;
   case SCMD_POLICIES: page_string(ch->desc, policies, 0); break;
   case SCMD_CLEAR   : clrscr(ch); break;
   case SCMD_VERSION : send_to_char(RoA_version, ch); send_to_char("\n\r",ch); break;
   case SCMD_WHOAMI  : send_to_char(strcat(strcpy(buf, GET_NAME(ch)), "\n\r"), ch); break;
   default: return; break;
   }
}

void perform_mortal_where(chdata *ch, char *arg)
{
  chdata *i;
  dsdata *d;

  if (IN_NOWHERE(ch)) return;

  if (!*arg) 
  {
    send_to_char("%BVisible Players in your Zone%0\n\r", ch);
    send_to_char("%B-=-=-=-=-=-=-=-=-=-=-=-=-=-=%0\n\r", ch);
    for (d = descriptor_list; d; d = d->next)
      if (!d->connected) 
      {
	i = (d->original ? d->original : d->character);
        if (i && can_see(ch, i) && (i->in_room != NOWHERE) &&
	   (world[ch->in_room].zone == world[i->in_room].zone) &&
	   (!IS_AFFECTED(i, AFF_HIDE) || affected_by_spell(ch, SPELL_VIEW_HIDDEN) ||
            affected_by_spell(ch, SPELL_FOREST_SIGHT)) &&
	    !IS_AFFECTED(i, AFF_SNEAK) ) 
	{
	  sprintf(buf, "%-20s - %s\n\r", GET_NAME(i), world[i->in_room].name);
	  S2C();
	}
      }
  } 
  else 
  { 
    for (i = character_list; i; i = i->next)
      if (world[i->in_room].zone == world[ch->in_room].zone && can_see(ch, i) &&
	     (i->in_room != NOWHERE) && isname(arg, i->player.name) &&
           (!IS_AFFECTED(i, AFF_HIDE) || affected_by_spell(ch, SPELL_VIEW_HIDDEN) ||
            affected_by_spell(ch, SPELL_FOREST_SIGHT)) && !IS_AFFECTED(i, AFF_SNEAK)) 
      {
	sprintf(buf, "%-25s - %s\n\r", GET_NAME(i), world[i->in_room].name);
	S2C();
	return;
      }
      send_to_char("No-one around by that name.\n\r", ch);
   }
}

void perform_immort_where(chdata *ch, char *arg)
{
  chdata *i;
  obdata *k;
  dsdata *d;
  int num = 0, found = 0;
  int rm;
  char buf[20000];

  if (!*arg) 
  {
    send_to_char("%BPlayers%0\n\r", ch);
    send_to_char("%B-=-=-=-%0\n\r", ch);
    for (d = descriptor_list, *buf = '\0'; d; d = d->next)
	 if (!d->connected) 
	 {
	    i = (d->original ? d->original : d->character);
            if (i && ((can_see(ch, i)) && !IN_NOWHERE(i))) 
	    {
	       if (d->original)
		  sprintf(buf+strlen(buf), "%-20s - [%5d] %s (in %s)\n\r",
		     GET_NAME(i), world[d->character->in_room].number,
		     world[d->character->in_room].name, GET_NAME(d->character));
	       else
		  sprintf(buf+strlen(buf), "%-20s - [%5d] %s\n\r",GET_NAME(i),
		     world[i->in_room].number, world[i->in_room].name);
	    }
	 }
      if (*buf)
	page_string(ch->desc, buf, 1);
   } 
   else 
   if (is_abbrev(arg, "transport"))
   {
     strcpy(buf, "%B%6Transport Locations%0:\n\r"
		 "%B%6--------------------%0\n\r");
     for (num = 0; num < top_of_world; num++)
       if (world[num].trans_present > 0 &&
           (rm = real_room(world[num].trans_present)) >= 0)
       {
         if (TRANS_SHDESC(&world[rm]))
           sprintf(buf+strlen(buf), "[%5d] - %s (%d)\n\r", world[num].number,
		   TRANS_SHDESC(&world[rm]), world[rm].number);
         else
           sprintf(buf+strlen(buf), "[%5d] - %s (%d)\n\r", world[num].number,
		   world[rm].name, world[rm].number);
       }
     page_string(ch->desc, buf, 1);
     return;
   }
   else
   {
      int cnt;

      for (i = character_list, *buf = '\0', cnt = 0; i; i = i->next)
         if ((can_see(ch, i)) && !IN_NOWHERE(i) && isname(arg,i->player.name)) 
	 {
	    found = TRUE;
	    sprintf(buf+strlen(buf), "%3d. %-25s - [%5d] %s\n\r", ++num,GET_NAME(i),
	       world[i->in_room].number, world[i->in_room].name);
           
            // guess what... limit this to 100 mobs to prevent buf overflows
            // 3/2/98 -jtrhone
            if (++cnt > 100)
            {
              strcat(buf, "WARNING: List limited by buffer space.. halted.\n\r");
              break;
            }
	 }

      for (num = 0, k = object_list; k; k = k->next)
	 if (CAN_SEE_OBJ(ch, k) && (!IN_NOWHERE(k)) && isname(arg, k->name)) 
	 {
	    found = TRUE; 
	    sprintf(buf+strlen(buf), "%3d. %-25s - [%5d] %s\n\r",++num, k->shdesc,
		    world[k->in_room].number, world[k->in_room].name);

            if (++cnt > 100)
            {
              strcat(buf, "WARNING: List limited by buffer space.. halted.\n\r");
              break;
            }
	 }

      if (*buf && found)
	page_string(ch->desc, buf, 1);

      if (!found)
         send_to_char("Unable to locate anything with that name.\n\r",ch);
   }
}

ACMD(do_where)
{
   one_argument(argument, arg);

   if (IS_IMMORTAL(ch))
      perform_immort_where(ch, arg);
   else
      perform_mortal_where(ch, arg);
}

ACMD(do_levels)
{
  int	i;
  char buf[20000];

  if (IS_NPC(ch)) {
    send_to_char("You ain't nothin' but a hound-dog.\n\r", ch);
    return;
  }

  for (*buf = '\0', i = 1; i < LEV_IMM; i++)
      sprintf(buf+strlen(buf), "%%6Level%%0: %2d     %-10d %%5-%%0 %-10d\n\r", i, 
        exp_table[GET_CLASS(ch) - 1][i], exp_table[GET_CLASS(ch) - 1][i + 1]);
  page_string(ch->desc, buf, 1);
}

ACMD(do_consider)
{
  chdata *victim;
  int	diff;
  extern int get_mob_chart_level(chdata *mob);

  one_argument(argument, buf);

  if (!(victim = get_char_room_vis(ch, buf))) 
  {
    send_to_char("Consider killing whom?\n\r", ch);
    return;
  }

  if (victim == ch) 
  {
    send_to_char("Easy!  Very easy indeed!\n\r", ch);
    return;
  }

  if (IS_PC(victim)) 
  {
    send_to_char("Other players cannot be considered.\n\r", ch);
    return;
  }

  diff = (get_mob_chart_level(victim) - GET_LEVEL(ch));

  if (diff <= -10)
    send_to_char("You would most likely win blindfolded.\n\r", ch);
  else if (diff <= -5)
    send_to_char("You don't even consider that a fight.\n\r", ch);
  else if (diff <= -2)
    send_to_char("Easy.\n\r", ch);
  else if (diff <= -1)
    send_to_char("Fairly easy.\n\r", ch);
  else if (diff == 0)
    send_to_char("The perfect match!\n\r", ch);
  else if (diff <= 1)
    send_to_char("You would need some luck!\n\r", ch);
  else if (diff <= 2)
    send_to_char("You would need a lot of luck!\n\r", ch);
  else if (diff <= 3)
    send_to_char("You would need a lot of luck and great equipment!\n\r", ch);
  else if (diff <= 5)
    send_to_char("You gotta ask yourself a question...Do I feel lucky?\n\r", ch);
  else if (diff <= 10)
    send_to_char("Are you mad!?\n\r", ch);
  else if (diff <= 20)
    send_to_char("You ARE mad!\n\r", ch);
  else
    send_to_char("You %BMIGHT%0 last a round!  Then again...\n\r", ch);
}

ACMD(do_toggle)
{
  if (IS_NPC(ch))
    return;

  send_to_char("%6%BChannel Status%0:\n\r",ch);
  sprintf(buf, 
	"%%6Naturals%%0 : %%B%-3s%%0    " "%%6Tell%%0     : %%B%-3s%%0    " 
	"%%6Auction%%0  : %%B%-3s%%0\n\r" "%%6ArenaMes%%0 : %%B%-3s%%0    " 
        "%%6Mortlog%%0  : %%B%-3s%%0    " "%%6Info%%0     : %%B%-3s%%0\n\r" 
        "%%6Clan%%0     : %%B%-3s%%0    " "%%6Assassin%%0 : %%B%-3s%%0\n\r",
       ONOFF(!PRF_FLAGGED(ch, PRF_DEAF)), ONOFF(!PRF_FLAGGED(ch, PRF_NOTELL)), 
       ONOFF(!PRF_FLAGGED(ch, PRF_NOAUCT)), ONOFF(!PRF2_FLAGGED(ch, PRF2_NOARENA)),
       ONOFF(PRF_FLAGGED(ch, PRF_MORTLOG)), ONOFF(PLR_FLAGGED(ch, PLR_INFOCH)), 
       ONOFF(PRF_FLAGGED(ch, PRF_CLAN_CH)), ONOFF(PRF_FLAGGED(ch, PRF_ASSA_CH)));
  S2C();

  if (!WIMP_LEVEL(ch))
    strcpy(buf2, "OFF");
  else
    sprintf(buf2, "%-3d", WIMP_LEVEL(ch));

  send_to_char("\n\r%6%BPlayer Preferences%0:\n\r",ch);
  sprintf(buf,
        "%%6Brief%%0      : %%B%-3s%%0    " "%%6Compact%%0    : %%B%-3s%%0    " 
	"%%6Repeat%%0     : %%B%-3s%%0\n\r" "%%6AutoX%%0      : %%B%-3s%%0    " 
	"%%6ShortX%%0     : %%B%-3s%%0    " "%%6Line%%0       : %%B%-3s%%0\n\r"
        "%%6Legend%%0     : %%B%-3s%%0    " "%%6Summonable%%0 : %%B%-3s%%0    " 
	"%%6Color%%0      : %%B%-3s%%0\n\r" "%%6Incognito%%0  : %%B%-3s%%0    " 
	"%%6Nogive%%0     : %%B%-3s%%0    " "%%6AutoGold%%0   : %%B%-3s%%0\n\r"
        "%%6AutoLoot%%0   : %%B%-3s%%0    " "%%6AutoSplit%%0  : %%B%-3s%%0    "
	"%%6WimpLevel%%0  : %%B%-3s%%0\n\r",
       YESNO(PRF_FLAGGED(ch, PRF_BRIEF)), YESNO(PRF_FLAGGED(ch, PRF_COMPACT)),
       YESNO(!PRF_FLAGGED(ch, PRF_NOREPEAT)), YESNO(PRF_FLAGGED(ch, PRF_AUTOX)),
       YESNO(PRF_FLAGGED(ch, PRF_SHORTX)), YESNO(PLR_FLAGGED(ch, PLR_LINE)),
       YESNO(PLR_FLAGGED(ch, PLR_LEGEND)), YESNO(PRF_FLAGGED(ch, PRF_SUMMONABLE)),
       YESNO(PRF_FLAGGED(ch, PRF_COLOR)), YESNO(PRF_FLAGGED(ch, PRF_INCOGNITO)),
       YESNO(PRF2_FLAGGED(ch, PRF2_NOGIVE)), YESNO(PRF_FLAGGED(ch, PRF_AGOLD)),
       YESNO(PRF_FLAGGED(ch, PRF_ALOOT)), YESNO(PRF_FLAGGED(ch, PRF_ASPLIT)),
       buf2);
  S2C();

  strcpy(buf, "\n\r%6%BPlayer Specials%0:  ");
  if (PLR_FLAGGED(ch, PLR_INTAG))
    strcat(buf, "%B%6Tag%0 ");
  if (PLR_FLAGGED(ch, PLR_TAGGED))
    strcat(buf, "%B%6You're IT!%0 ");
  if (PLR_FLAGGED(ch, PLR_ARENA))
    strcat(buf, "%B%6Arena%0 ");
  if (PRF_FLAGGED(ch, PRF_REQASS))
    strcat(buf, "%B%1Request Assassin%0 ");
  else
  if (PRF_FLAGGED(ch, PRF_ASSASSIN))
    strcat(buf, "%B%1Assassin%0 ");
  strcat(buf, "\n\r");
  S2C();
}

// unflag every channel on a character
ACMD(do_nochannel)
{
  if (IS_NPC(ch))
    return;

  SET_BIT(PRF_FLAGS(ch), PRF_DEAF);
  SET_BIT(PRF_FLAGS(ch), PRF_NOTELL);
  SET_BIT(PRF_FLAGS(ch), PRF_NOQA);
  SET_BIT(PRF_FLAGS(ch), PRF_NOAUCT);
  SET_BIT(PRF_FLAGS(ch), PRF_NOOOC);
  SET_BIT(PRF_FLAGS(ch), PRF_NOGRATZ);
  SET_BIT(PRF_FLAGS(ch), PRF_NOMUSIC);
  SET_BIT(PRF2_FLAGS(ch), PRF2_NOARENA);

  REMOVE_BIT(PRF_FLAGS(ch), PRF_MORTLOG);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_CLAN_CH);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_ASSA_CH);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_QUEST);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_AREN_CH);
  REMOVE_BIT(PLR_FLAGS(ch), PLR_INFOCH);

  send_to_char("%4Silent mode%0.\n\r",ch);
}

// turn on every channel for a character
ACMD(do_allchannel)
{
  if (IS_NPC(ch))
    return;

  REMOVE_BIT(PRF_FLAGS(ch), PRF_DEAF);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTELL);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_NOQA);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_NOAUCT);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_NOOOC);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_NOGRATZ);
  REMOVE_BIT(PRF_FLAGS(ch), PRF_NOMUSIC);
  REMOVE_BIT(PRF2_FLAGS(ch), PRF2_NOARENA);

  SET_BIT(PRF_FLAGS(ch), PRF_MORTLOG);
  SET_BIT(PRF_FLAGS(ch), PRF_CLAN_CH);
  SET_BIT(PRF_FLAGS(ch), PRF_ASSA_CH);
  SET_BIT(PRF_FLAGS(ch), PRF_QUEST);
  SET_BIT(PRF_FLAGS(ch), PRF_AREN_CH);
  SET_BIT(PLR_FLAGS(ch), PLR_INFOCH);

  send_to_char("%B%6Loud mode%0.\n\r",ch);
}

void	sort_commands(void)
{
  int	a, b, tmp;

  num_of_cmds = 1;
  while (num_of_cmds < top_of_cmds && cmd_info[num_of_cmds].cmd_ptr)
  {
    cmd_info[num_of_cmds].sort_pos = num_of_cmds - 1;
    num_of_cmds++;
  }
  num_of_cmds--;

  for (a = 1; a <= num_of_cmds - 1; a++)
    for (b = a + 1; b <= num_of_cmds; b++)
      if (str_cmp(cmd_info[cmd_info[a].sort_pos].comm, cmd_info[cmd_info[b].sort_pos].comm) > 0) 
      {
        tmp = cmd_info[a].sort_pos;
        cmd_info[a].sort_pos = cmd_info[b].sort_pos;
        cmd_info[b].sort_pos = tmp;
      }
}

ACMD(do_commands)
{
  int	no, i, cmd_num;
  int	wizcomm = 0;
  chdata *vict;
  char buf[20000];

  one_argument(argument, buf);

  if (*buf) 
  {
    if (!(vict = get_char_vis(ch, buf)) || IS_NPC(vict)) 
    {
      send_to_char("Who is that?\n\r", ch);
      return;
    }
    if (GET_LEVEL(ch) < GET_LEVEL(vict)) 
    {
      send_to_char("Can't determine commands of people above your level.\n\r", ch);
      return;
    }
  } 
  else
    vict = ch;

  if (subcmd == SCMD_SOCIALS)
  {
    sprintf(buf,"\n\r%%6%s %%BSocials%%0:\n\r", longmudname);
    for (i=0, no=1; *roa_socials[i].social && (i < MAX_SOCIALS); i++)
    {
	sprintf(buf2, "%-11.11s", roa_socials[i].social);
	strcat(buf, buf2);
	if (!(no % 7))
	  strcat(buf, "\n\r");
	no++;
    }

    // Show how many are listed. 03/29/98 -callahan
    sprintf(buf + strlen(buf), "\r\n\r\nTotal listed: %d", no - 1);
    strcat(buf, "\n\r");
    page_string(ch->desc, buf, 1);
    return;
  }
  else
  if (subcmd == SCMD_WIZCOMM)
    wizcomm = 1;

  sprintf(buf, "The following %scommands are available to %s:\n\r",
	  wizcomm ? "privileged " : "", vict == ch ? "you" : GET_NAME(vict));

  for (no = 1, cmd_num = 1; cmd_num <= num_of_cmds; cmd_num++) 
  {
    i = cmd_info[cmd_num].sort_pos;
    if (cmd_info[i+1].minimum_level >= 0 && 
       (cmd_info[i+1].minimum_level >= LEV_IMM) == wizcomm && 
        GET_LEVEL(vict) >= cmd_info[i+1].minimum_level) 
    {
	 sprintf(buf + strlen(buf), "%-11.11s", cmd_info[i].comm);
	 if (!(no % 7))
	    strcat(buf, "\n\r");
	 no++;
    }
  }

  // Show how many are listed. 03/29/98 -callahan
  sprintf(buf + strlen(buf), "\r\n\r\nTotal listed: %d", no - 1);
  strcat(buf, "\n\r");
  page_string(ch->desc, buf, 1);
}

ACMD(do_diagnose)
{
  chdata *vict;

  one_argument(argument, buf);

  if (*buf) 
  {
    if (!(vict = get_char_room_vis(ch, buf))) 
    {
	 send_to_char("No-one by that name here.\n\r", ch);
	 return;
    } 
    else
      diag_char_to_char(vict, ch);
  } 
  else 
  {
    if (FIGHTING(ch))
	diag_char_to_char(FIGHTING(ch), ch);
    else
	send_to_char("Diagnose who?\n\r", ch);
   }
}