legend/
legend/area/
legend/player/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/
/***************************************************************************
 *  God Wars Mud copyright (C) 1994, 1995, 1996 by Richard Woolcock        *
 *  									   *
 *  Legend of Chrystancia copyright (C) 1999, 2000, 2001 by Matthew Little *
 *  This mud is NOT to be copied in whole or in part, or to be run without *
 *  the permission of Matthew Little. Nobody else has permission to        *
 *  authorise the use of this code.                                        *
 ***************************************************************************/

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

#define ALLOW_N00BS_TO_GROUP	WizConfig->n00bgroup
#define N00B_NO_GROUP_HOURS	WizConfig->n00bhours

NCLANS_DATA *nclans_table;

/*
 * Local functions.
 */
void talk_channel args ((CHAR_DATA * ch, char *argument, int channel, const char *verb));
bool is_in args ((char *, char *));
bool all_in args ((char *, char *));
char *oldelang args ((CHAR_DATA * ch, char *argument));
char *badlang args ((CHAR_DATA * ch, char *argument));
char *darktongue args ((CHAR_DATA * ch, char *argument));
char *drunktalk args ((CHAR_DATA * ch, char *argument));
char *beasttalk args ((CHAR_DATA * ch, char *argument));
char *beastchat args ((CHAR_DATA * ch, char *argument));

char *socialc args ((CHAR_DATA * ch, char *argument, char *you, char *them));
char *socialv args ((CHAR_DATA * ch, char *argument, char *you, char *them));
char *socialn args ((CHAR_DATA * ch, char *argument, char *you, char *them));

bool is_contained( const char *astr, const char *bstr )
{
  int i, alen, blen, count;

  alen = strlen(astr);
  blen = strlen(bstr);
  if (alen > blen) return FALSE;
  for (i = 0; i <= (blen - alen); i++)
  {
    count = 0;
    while (count < alen && UPPER(astr[count]) == UPPER(bstr[i+count])) count++;
    if (count == alen) return TRUE;
  }
  return FALSE;
}
 bool is_advertisement( char *check )
  {
   bool pfound = FALSE;
   int pcount = 0;
   int x = 0;

  
     if (is_contained("my mud",check) || is_contained("on port",check) || is_contained("same port",check)) return TRUE;

//commented out untill i can find a way for it to check for ips
//       if (is_contained(".", check)) return TRUE;
if (
    !str_infix(".net", check) ||
    !str_infix(".org", check) ||
    !str_infix(".cx", check) ||
    !str_infix(".gov", check) ||
    !str_infix(".edu", check) ||
    !str_infix(".us", check) ||
    !str_infix(".cc", check) ||
    !str_infix(".co", check) ||
    !str_infix(".uk", check) ||
    !str_infix(".sk", check) ||
    !str_infix(".au", check) ||
    !str_infix(".tj", check) ||
    !str_infix(".nz", check) ||
    !str_infix(".da", check) ||
    !str_infix(".tv", check) ||
    !str_infix(".biz", check) ||
    !str_infix(".tk", check) ||
    !str_infix(".nu", check)) return TRUE;

     // Look for 4 digit numbers
     for ( x = 0; x < strlen(check); x++ )
     {
      if (pcount == 4 && (!isdigit(check[x]) || check[x] == '\0')) { pfound = TRUE; x = strlen(check); }
      else {
       if (pcount > 0 && !isdigit(check[x])) pcount = 0;
       if (isdigit(check[x])) pcount += 1; }
     }

   if (pfound) return TRUE;
   return FALSE;
  }

 void adv_alert( CHAR_DATA *ch, char *chan, char *ad )
  {
   CHAR_DATA *imm;
   char buf[MSL];
   bool alerted = FALSE;
  
   if (ch->level > 8) return;
   sprintf(buf,"%s(%s) said: %s, using %s.", ch->name,ch->desc->host,ad, chan);
   log_string(buf, ch);
   wiznet(ch, WIZ_ADVER,7, buf);
   for (imm = char_list; imm != NULL; imm = imm->next)
   {
    if (IS_NPC(imm)) continue;
    if (!IS_IMMORTAL(imm)) continue;
  
    //stc(buf,imm);
    if (!IS_SET(imm->flag2,EXTRA_AFK)) 
     alerted = TRUE;
   }
  
   if (alerted == FALSE)
    make_note ("Personal", "Ad Admin", "imm immortal", "UNSEEN ADVERTISEMENT", 15, buf);
  
   return;
  }
/*
 * Generic channel function.
 */
void talk_channel (CHAR_DATA * ch, char *argument, int channel,
		   const char *verb)
{
   char buf[MAX_STRING_LENGTH];
   char buf2[MAX_STRING_LENGTH];
   char buf3[MAX_STRING_LENGTH];
   char ibuf[MSL];
   char iname[MSL];
   CHAR_DATA *vch;
   DESCRIPTOR_DATA *d;
   int position;
   int pos;
   bool ignored;

   if (IS_NPC (ch) && channel != CHANNEL_QUESTION && channel != CHANNEL_SHOUT)
      return;

   if (IS_IMMORTAL (ch) && IS_SET (ch->flag2, NOCHAN)
       && channel != CHANNEL_IMMTALK && channel != CHANNEL_FTALK)
   {
      stcprintf (ch, "You need to turn NOCHAN off before you can use %s.\n\r",
		 verb);
      return;
   }
   /* Added CANCHAN so we can give non newbies (people who already have a char) access to all channels */

   if (!IS_SET (ch->more, CANCHAN) && !IS_IMMORTAL (ch) && !IS_NPC (ch)
       && (get_hours (ch) < 3) && channel != CHANNEL_NEWBIE
       && channel != CHANNEL_FTALK)
/*
   {
      sprintf (buf, "You cannot %s until you are 3 hrs old.\n\r", verb);
      send_to_char (buf, ch);
      stc ("Use newbie <message>, instead.\n\r", ch);
      return;
   }
*/
   channel = CHANNEL_NEWBIE;

   if (!IS_IMMORTAL (ch) && (get_hours (ch) > 10)
       && !IS_SET (ch->extra2, NHELPER) && channel == CHANNEL_NEWBIE)
   {
      stc ("You are not a newbie use another channel!\n\r", ch);
      return;
   }
   if (!IS_SET (ch->more, CANCHAN) && (ch->chat_timer > 0)
       && !IS_IMMORTAL (ch) && channel == CHANNEL_NEWBIE)
   {
      sprintf (buf, "You cannot newbie for another %d ticks.\n\r",
	       ch->chat_timer);
      stc (buf, ch);
      return;
   }
   if (IS_SET (ch->in_room->added_flags, ROOM2_SILENCE) && !IS_IMMORTAL(ch))
   {
      send_to_char ("Something prevents you from speaking in this room.\n\r",
		    ch);
      return;
   }

   if (argument[0] == '\0')
   {
      sprintf (buf, "%s what?\n\r", verb);
      buf[0] = UPPER (buf[0]);
      stc (buf, ch);
      return;
   }
   if (IS_HEAD (ch, LOST_TONGUE))
   {
      sprintf (buf, "You can't %s without a tongue!\n\r", verb);
      send_to_char (buf, ch);
      return;
   }

   if (IS_EXTRA (ch, GAGGED))
   {
      sprintf (buf, "You can't %s with a gag on!\n\r", verb);
      send_to_char (buf, ch);
      return;
   }

   if (!IS_NPC (ch) && IS_SET (ch->act, PLR_SILENCE))
   {
      sprintf (buf, "You can't %s because you are silenced.\n\r", verb);
      send_to_char (buf, ch);
      return;
   }
/*
   if (!IS_IMMORTAL(ch))
      mal_smashaddy (argument);
*/
   if IS_SET
      (ch->deaf, CHANNEL_ALL) REMOVE_BIT (ch->deaf, CHANNEL_ALL);

   if (!IS_NPC (ch) && ch->lastchat != NULL)
   {

      if (!str_cmp (argument, ch->lastchat) && !IS_IMMORTAL (ch))
      {
	 stc ("You are unable to say the same thing twice in a row!. Find a different way to say it.\n\r", ch);
	 return;
      }
   }
   if (is_contained("Rowena", argument)
      || is_contained ("Legend of Rowena", argument)
      || is_contained ("Acidburn", argument)
      || is_contained ("Selff", argument)
      || is_contained ("jennyro.no-ip.info", argument)
      || is_contained ("pyropkfun.no-ip.info", argument))
   {
	send_to_char("Mentioning that MUD, or That Person here is against the RULES!!!\n\r", ch);
        send_to_char("Code Stealing MOTHER FUCKER!!\n\r", ch);
        return;
   }
   if (is_contained("rapidshare", argument)) return;


   free_string (ch->lastchat);
   ch->lastchat = str_dup (argument);
   REMOVE_BIT (ch->deaf, channel);
   switch (channel)
   {
   default:
      sprintf (buf, "#w[%s#w] You: #e$T#n", verb);
      if (!IS_NPC (ch) && ch->pcdata->condition[COND_DRUNK] > 10)
         act (buf, ch, NULL, drunktalk (ch, ((IS_IMMORTAL(ch) && !IS_SET (ch->more, MORE_CCHANNELS)) ? argument : bash_color (argument))), TO_CHAR);
      else if (!IS_NPC (ch) && ch->pcdata->stats[UNI_RAGE] > 0
	       && IS_CLASS (ch, CLASS_VAMPIRE)
               && !IS_IMMORTAL(ch))
         act (buf, ch, NULL, beastchat (ch, ((IS_IMMORTAL(ch) && !IS_SET (ch->more, MORE_CCHANNELS)) ? argument : bash_color (argument))), TO_CHAR);
      else
         act (buf, ch, NULL, ((IS_IMMORTAL(ch) && !IS_SET (ch->more, MORE_CCHANNELS)) ? argument : bash_color (argument)), TO_CHAR);
         sprintf (iname, "#w(%s)#n ", ch->name);

      sprintf (buf, "#w[%s#w] $n: #e$t#n", verb);
      if (IS_NPC (ch))
	 sprintf (buf2, "#w[%s#w]#w %s: #e$t#n", verb, ch->short_descr);
      else
	 sprintf (buf2, "#w[%s#w] $n: #e$t#n", verb);

      break;
/*
   case CHANNEL_CHAT:


      if (IS_SET (ch->extra2, WHINER))
      {
	 char orig_arg[MSL];
	 char dark_arg[MSL];

	 strcpy (orig_arg, argument);
	 strcpy (dark_arg, darktongue (ch, argument));

	 sprintf (buf, "#wYou whine '#y%s#w'#n\n\r", dark_arg);
	 send_to_char (buf, ch);
	 for (vch = char_list; vch != NULL; vch = vch->next)
	 {
	    if (ch == vch)
	       continue;
	    if (IS_IMMORTAL (vch))
	       sprintf (buf, "#w%s #wwhines '#y%s#w'#n\n\r", ch->name,
			orig_arg);
	    else
	       sprintf (buf, "#w%s #wwhines '#y%s#w'#n\n\r", ch->name,
			dark_arg);
	    send_to_char (buf, vch);
	 }
	 return;
      }
      else
      {
	 sprintf (buf, "#wYou %s '#y$T#w'#n", verb);
	 if (!IS_NPC (ch) && ch->pcdata->condition[COND_DRUNK] > 10)
	    act (buf, ch, NULL, drunktalk (ch, argument), TO_CHAR);
	 else if (!IS_NPC (ch) && ch->pcdata->stats[UNI_RAGE] > 0
		  && IS_CLASS (ch, CLASS_VAMPIRE)
                  && !IS_IMMORTAL(ch))
	    act (buf, ch, NULL, beastchat (ch, argument), TO_CHAR);

	 else
	    act (buf, ch, NULL, argument, TO_CHAR);

	 sprintf (iname, "#w(%s)#n ", ch->name);

	 sprintf (buf, "#w$n #ww%ss '#y$t#w'#n", verb);
	 sprintf (buf2, "#w$n #w%ss '#y$t#w'#n", verb);
      }
      break;
*/
   case CHANNEL_FLAME:
      sprintf (buf, "#y[#wFLAME#y] #r$n:#y $t#n");
      sprintf (buf2, "#y[#wFLAME#y] #r$n:#y $t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_NEWBIE:
      if (!IS_SET (ch->extra2, NHELPER))
      {
	 sprintf (buf, "#w[#cNEWBIE#w] $n:#c $t#n");
	 sprintf (buf2, "#w[#cNEWBIE#w] $n:#c $t#n");
      }
      else
      {
	 sprintf (buf, "#w[#cNEWBIE HELP#w] $n:#c $t#n");
	 sprintf (buf2, "#w[#cNEWBIE HELP#w] $n:#c $t#n");
      }
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_FTALK:
      sprintf (buf, "#w-[#yFTALK#w: %s]- #y$t#n", ch->name);
      sprintf (buf2, "#w-[#yFTALK#w: %s]- #y$t#n", ch->name);
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_BTALK:
      sprintf (buf, "#e>[#.%s#e]< #w'#c$t#w'#n", ch->name);
      sprintf (buf2, "#e>[#.%s#e]< #w'#c$t#w'#n", ch->name);
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      sprintf (buf3, "%s : %s", ch->name, argument);
      ltf (buf3, "bitchsession", FALSE);
      ch->position = position;
      break;

   case CHANNEL_SPOUSETALK:
      sprintf (buf, "#r-=[#w%s#r]=- #r$t#n", capitalize (ch->name));
      sprintf (buf2, "#r-=[#w%s#r]=- #r$t#n", capitalize (ch->name));
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_IMMTALK:
      sprintf (buf, "#w%s [#r%d#w]: #r$t#n", capitalize (ch->name),
	       ch->pcdata->wizinvis);
      sprintf (buf2, "#w%s [#r%d#w]: #r$t#n", capitalize (ch->name),
	       ch->pcdata->wizinvis);
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_FOUNDERTALK:
      sprintf (buf, "#w[#gFOUNDERTALK#w] $n: #g$t#n");
      sprintf (buf2, "#w[#gFOUNDERTALK#w] $n: #g$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_PRAY:
      sprintf (buf, "#y[[#yPRAY#y]]#w $n: #y$t#n");
      sprintf (buf2, "#y[[#yPRAY#y]]#w $n: #y$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_WRAITH:
      sprintf (buf, "#e+-#wWAIL#e-+#w $n: #e$t#n");
      sprintf (buf2, "#e+-#wWAIL#e-+#w $n: #e$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_BUILD:
      sprintf (buf, "#w$n= #c$t#n");
      sprintf (buf2, "#w$n= #c$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_MAGETALK:
      sprintf (buf, "#b{{#bMAGETALK#b}}#w $n: #b$t#n");
      sprintf (buf2, "#b{{#bMAGETALK#b}}#w $n: #b$t#n");

      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_CLANTALK:
      sprintf (ibuf, "#w(#nClan Channel %s#w)#n ", ch->clan);
      sprintf (buf, "#w$n clantalks '#o$t#w'#n");
      sprintf (buf2, "#w$n clantalks '#o$t#w'#n");
      position = ch->position;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_HOWL:
      sprintf (buf, "#o((#oHOWL#o))#w You: #o$t#n");
      sprintf (buf2, "#o((#oHOWL#o))#w $n: #o$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_KTALK:
      sprintf (ibuf, "#w(#nKingdom #r%d#w)#n ", ch->pcdata->kingdom);
      sprintf (buf, "#y.x[#g%s#y]x. #w'#y$t#w'#n", ch->name);
      sprintf (buf2, "#y.x[#g%s#y]x. #w'#y$t#w'#n", ch->name);
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_PTALK:
      sprintf (buf, "#y.#r^^^^#w$n#r^^^^#y.#w cries #W$t#n");
      sprintf (buf2, "#y.#r^^^^#w$n#r^^^^#y.#w cries #W$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_MIKTALK:
      sprintf (buf, "#p**#pMIKTALK#p**#w $n: #p$t#n");
      sprintf (buf2, "#p**#pMIKTALK#p**#w $n: #p$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_HIGHTALK:
      sprintf (buf, "#C-=#cHIGH#cTALK#C=-#w $n: #c$t#n");
      sprintf (buf2, "#C-=#cHIGH#cTALK#C=-#w $n: #c$t#n");
      position = ch->position;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_MONK:
      sprintf (buf, "#w<:#gHUM#w:> $n: #g$t#n");
      sprintf (buf2, "#w<:#gHUM#w:> $n: #g$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_SIGN:
      sprintf (buf, "#c.oO#cSIGN#cOo.#w $n: #c$t#n");
      sprintf (buf2, "#c.oO#cSIGN#cOo.#w $n: #c$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   case CHANNEL_VAMPTALK:
      sprintf (buf, "#R<<#rVAMPTALK#R>>#w $n: #r$t#n");
      sprintf (buf2, "#R<<#rVAMPTALK#R>>#w $n: #r$t#n");
      position = ch->position;
      ch->position = POS_STANDING;
      act4 (buf, ch, argument, NULL, TO_CHAR);
      ch->position = position;
      break;

   }

   for (d = first_descriptor; d != NULL; d = d->next)
   {
      CHAR_DATA *och;

      och = d->original ? d->original : d->character;
      vch = d->character;

      ignored = FALSE;

      if (d->connected == CON_PLAYING && vch != ch
	  && !IS_SET (och->deaf, channel) && !IS_SET (och->deaf, CHANNEL_ALL))

      {

	 for (pos = 0; pos < MAX_FORGET; pos++)
	 {
	    if (och->pcdata->forget[pos] == NULL)
	       break;
	    if (!str_cmp (ch->name, och->pcdata->forget[pos]))
	       ignored = TRUE;
	 }
	 if (ignored)
	    continue;
	 if (channel == CHANNEL_HOWL)
	    send_howl (och);
	 if ((channel == CHANNEL_CLANTALK || channel == CHANNEL_KTALK)
	     && (get_trust (och) >= LEVEL_IMPLEMENTOR))
	    send_to_char (ibuf, vch);
	 if (channel == CHANNEL_FTALK
	     && (!IS_NPC (och) && !IS_SET (och->more, MORE_FTALK2)
		 && !IS_CREATOR (och)))
	    continue;

	 if (channel == CHANNEL_BUILD && !IS_IMMORTAL (och))
	    continue;
	 if (channel == CHANNEL_BTALK
	     && (!IS_NPC (och) && !BITCH && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_FOUNDERTALK
	     && (!IS_NPC(och) && !is_clanleader(och)
		 && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_IMMTALK && !IS_IMMORTAL (och))
	    continue;
	 if (channel == CHANNEL_MIKTALK
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_NINJA)
		 && !IS_IMMORTAL(och)))
	    continue;
         if (channel == CHANNEL_PTALK
             && (!IS_NPC (och) && !IS_CLASS (och, CLASS_PHOENIX)   
                 && !IS_IMMORTAL(och)))
            continue;
	 if (channel == CHANNEL_WRAITH
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_WRAITH)
		 && !IS_IMMORTAL(och)))
	    continue;
	 if (channel == CHANNEL_HIGHTALK
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_HIGHLANDER)
		 && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_KTALK
	     && (!IS_NPC (och) && !IS_CREATOR (och)
		 && ch->pcdata->kingdom != och->pcdata->kingdom))
	    continue;
	 if (channel == CHANNEL_MONK
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_MONK)
		 && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_SIGN
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_DROW)
		 && !IS_IMMORTAL(och)))
	    continue;
	 if (channel == CHANNEL_CLANTALK
	     && (!IS_NPC (och) && !IS_IMMORTAL (och)
		 && str_cmp (ch->clan, och->clan)))
	    continue;
	 if (channel == CHANNEL_SPOUSETALK
	     && (!IS_NPC (och) && str_cmp (och->pcdata->marriage, ch->name)))
	    continue;
	 if (channel == CHANNEL_VAMPTALK
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_VAMPIRE)
		 && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_MAGETALK
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_MAGE)
		 && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_PRAY
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_DEMON)
		 && !IS_IMMORTAL (och)))
	    continue;
	 if (channel == CHANNEL_HOWL
	     && (!IS_NPC (och) && !IS_CLASS (och, CLASS_WEREWOLF)
		 && !IS_POLYAFF (och, POLY_WOLF) && !IS_IMMORTAL (och)))
	 {
	    if ((och->in_room) && (ch->in_room))
	    {
	       if ((och->in_room == ch->in_room))
	       {
		  act ("$n throws back $s head and howls loudly.", ch,
		       argument, och, TO_VICT);
		  continue;
	       }
	       else if ((och->in_room->area == ch->in_room->area))
	       {
		  act ("You hear a loud howl nearby.", ch, NULL, och,
		       TO_VICT);
		  continue;
	       }

	       else
	       {
		  act ("You hear a loud howl in the distance.", ch, NULL, och,
		       TO_VICT);
		  continue;
	       }

	    }
	 }

	 if (channel == CHANNEL_YELL
	     && vch->in_room->area != ch->in_room->area)
	    continue;

	 position = vch->position;
	 if (channel != CHANNEL_SHOUT && channel != CHANNEL_YELL)
	    vch->position = POS_STANDING;
	 {
	    if (channel != CHANNEL_FOUNDERTALK && channel != CHANNEL_CLANTALK
		&& channel != CHANNEL_FLAME && channel != CHANNEL_NEWBIE)
	    {
               act4 (buf2, ch, ((IS_IMMORTAL(ch) && !IS_SET (vch->more, MORE_CCHANNELS)) ? argument : bash_color (argument)), vch, TO_VICT);
	       vch->position = position;
	    }
	    else
	    {
               act4 (buf2, ch, ((IS_IMMORTAL(ch) && !IS_SET (vch->more, MORE_CCHANNELS)) ? argument : bash_color (argument)), vch, TO_VICT);
	       vch->position = position;
	    }
	    continue;
	 }
         act4 (buf, ch, ((IS_IMMORTAL(ch) && !IS_SET (vch->more, MORE_CCHANNELS)) ? argument : bash_color (argument)), vch, TO_VICT);
	 vch->position = position;
      }
   }

   if (channel == CHANNEL_QUESTION)
   {
      for ( vch = char_list; vch != NULL; vch = vch->next )
      {
         if (IS_NPC(vch) && vch->pIndexData->vnum == 25) break;
      }
      
      if (!vch) return;

      if (!str_infix("what",argument) || !str_infix("where", argument))
      {
         if (!str_infix("what",argument) && !str_infix(vch->short_descr,argument))
         {
            OBJ_DATA *obj;
            sprintf(buf, "%s So, you want to know what I have, eh %s?", ch->name, ch->name);
            do_tell(vch, buf);
            if (vch->carrying == NULL)
            {
               sprintf(buf, "%s Unfortunately, I don't appear to have a single item.", ch->name);
               do_tell(vch, buf);
               WAIT_STATE (ch, 12);
               return;
            }
            sprintf(buf, "%s I currently hold the following:", ch->name);
            do_tell(vch, buf);
            for (obj = vch->carrying; obj != NULL; obj = obj->next_content)
            {
               sprintf(buf, "%s %s", ch->name, obj->short_descr);
               do_tell(vch, buf);
            }
         }
         else if (!str_infix("where",argument) && !str_infix(vch->short_descr,argument))
         {
            sprintf(buf, "%s So %s, you want to know where I'm resting?", ch->name, ch->name);
            do_tell(vch, buf);
            if (!vch->in_room || !vch->in_room->area)
            {
               sprintf(buf, "%s Unfortunately, I have NO clue where I'm at.", ch->name);
               do_tell(vch, buf);
               return;
            }
            sprintf(buf, "%s It appears I've wandered into %s.", ch->name, vch->in_room->area->name);
            do_tell(vch, buf);
            sprintf(buf, "%s Roughly in the region of %s.", ch->name, vch->in_room->name);
            do_tell(vch, buf);
         }
      }
   }

   return;
}

void do_chathist (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *tok;
   char buffer[MAX_STRING_LENGTH];
   char let;

   int size, save, ct = 0;


   if (!(fp = fopen (CHAT_LOG_FILE, "a+")))
   {
      bug ("Cannot open CHAT_LOG_FILE!", 0);
      send_to_char ("BUG: Inform an Immortal\r\n", ch);
      return;
   }

   save = ftell (fp);
   fseek (fp, 0L, SEEK_END);
   size = ftell (fp);
   fseek (fp, size, SEEK_SET);

   while (size--)
   {
      fseek (fp, size, SEEK_SET);
      let = fgetc (fp);
      if (let == '>')
	 ct++;
      if (ct == 20)
	 break;
   }

   send_to_char ("#wChat History:#n\r\n", ch);

   while (fgets (buffer, (sizeof (buffer) - 2), fp) > 0)
   {
       tok =  strtok (buffer, ">");
      send_to_char (tok, ch);
   }
   fclose (fp);
   return;
}
void do_infohist (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *tok;
   char buffer[MAX_STRING_LENGTH];
   char let;
   int size, save, ct = 0;


   if (!(fp = fopen (INFO_FILE, "a+")))
   {
      bug ("Cannot open INFO_FILE!", 0);
      send_to_char ("BUG: Inform an Immortal\r\n", ch);
      return;
   }

   save = ftell (fp);
   fseek (fp, 0L, SEEK_END);
   size = ftell (fp);
   fseek (fp, size, SEEK_SET);

   while (size--)
   {
      fseek (fp, size, SEEK_SET);
      let = fgetc (fp);
      if (let == '>')
	 ct++;
      if (ct == 20)
	 break;
   }

   send_to_char ("#wInfo History:#n\r\n", ch);

   while (fgets (buffer, (sizeof (buffer) - 2), fp) > 0)
   {
       tok =  strtok (buffer, ">");
      send_to_char (tok, ch);
   }
   fclose (fp);
   return;
}
void do_fatalhist (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *tok;
   char buffer[MAX_STRING_LENGTH];
   char let;
   int size, save, ct = 0;


   if (!(fp = fopen (FATAL_FILE, "a+")))
   {
      bug ("Cannot open FATAL_FILE!", 0);
      send_to_char ("BUG: Inform an immortal\r\n", ch);
      return;
   }

   save = ftell (fp);
   fseek (fp, 0L, SEEK_END);
   size = ftell (fp);
   fseek (fp, size, SEEK_SET);

   while (size--)
   {
      fseek (fp, size, SEEK_SET);
      let = fgetc (fp);
      if (let == '>')
	 ct++;
      if (ct == 20)
	 break;
   }

   send_to_char ("#wFatality History:#n\r\n", ch);

   while (fgets (buffer, (sizeof (buffer) - 2), fp) > 0)
   {
      tok = strtok (buffer, ">");
      send_to_char (tok, ch);
   }
   fclose (fp);
   return;
}

void do_btalkhist (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *tok;
   char buffer[MAX_STRING_LENGTH];
   char let;
   int size, save, ct = 0;


   if (!(fp = fopen (BTALK_LOG_FILE, "a+")))
   {
      bug ("Cannot open BTALK_LOG_FILE!", 0);
      send_to_char ("BUG: Inform an immortal\r\n", ch);
      return;
   }

   save = ftell (fp);
   fseek (fp, 0L, SEEK_END);
   size = ftell (fp);
   fseek (fp, size, SEEK_SET);

   while (size--)
   {
      fseek (fp, size, SEEK_SET);
      let = fgetc (fp);
      if (let == '>')
	 ct++;
      if (ct == 20)
	 break;
   }

   send_to_char ("#wBitching History:#n\r\n", ch);

   while (fgets (buffer, (sizeof (buffer) - 2), fp) > 0)
   {
       tok =  strtok (buffer, ">");
      send_to_char (tok, ch);
   }
   fclose (fp);
   return;
}


void do_ktalkhist (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *tok;
   char buffer[MAX_STRING_LENGTH];
   char let;
   int size, save, ct = 0;

   if (!(fp = fopen (KTALK_LOG_FILE, "a+")))
   {
      bug ("Cannot open KTALK_LOG_FILE!", 0);
      send_to_char ("BUG: Inform an immortal\r\n", ch);
      return;
   }

   save = ftell (fp);
   fseek (fp, 0L, SEEK_END);
   size = ftell (fp);
   fseek (fp, size, SEEK_SET);

   while (size--)
   {
      fseek (fp, size, SEEK_SET);
      let = fgetc (fp);
      if (let == '>')
	 ct++;
      if (ct == 20)
	 break;
   }

   send_to_char ("#wKtalk History:#n\r\n", ch);

   while (fgets (buffer, (sizeof (buffer) - 2), fp) > 0)
   {
       tok =  strtok (buffer, ">");
      send_to_char (tok, ch);
   }
   fclose (fp);
   return;
}

/* Remove/Replace something in a string                   */
/* Replaces all instances of 'd' in 'str' with 'c'        */
char *switch_char (const char *str, const char d, const char c)
{
   static char strbuf[MAX_STRING_LENGTH];
   int i;

   /* Safe.. input length checked elsewhere for 'str'     */
   strcpy (strbuf, str);

   for (i = 0; str[i] != '\0'; i++)
   {
      if (strbuf[i] == d)
      {
	 strbuf[i] = c;
      }
   }
   strbuf[i] = '\0';
   return strbuf;

}



void do_newbie (CHAR_DATA * ch, char *argument)
{
   if (is_advertisement(argument))
adv_alert(ch, "newbie", argument);
   talk_channel (ch, argument, CHANNEL_NEWBIE, "newbie");
   //if (ch->chat_timer == 0 && strlen (argument) > 0
   //    && !IS_SET (ch->extra2, NHELPER))
   //   ch->chat_timer = 25;
   return;
}
void do_qtalk (CHAR_DATA * ch, char *argument)
{
      if (is_advertisement(argument))
adv_alert(ch, "Quest", argument);

   talk_channel (ch, argument, CHANNEL_QUESTION, "#cQUEST#n");
   if ((!str_cmp (argument, "what mob?"))
       || (!str_cmp (argument, "who was the thief?"))
       || (!str_cmp (argument, "who is the thief?"))
       || (!str_cmp (argument, "what item?"))
       || (!str_cmp (argument, "where are you?"))
       || (!str_cmp (argument, "who stole the item?"))
       || (!str_cmp (argument, "where is the thief?")))
      ask_quest_question (ch, argument);
   return;
}
void do_flame (CHAR_DATA * ch, char *argument)
{
   if (is_advertisement(argument))
adv_alert(ch, "flame", argument);
   talk_channel (ch, argument, CHANNEL_FLAME, "flame");
   return;
}

void do_chat (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *nstr;
   char buf[MSL];
//   char tmpbuf[MSL];
   time_t nowtime;
   char *strtime;
   struct tm *t;
   /* 
    * We use this char in 'chatlog.dat' to represent start of line
    * Thus we cannot use it in chat... so strip it out... 
    */
   nstr = switch_char (argument, '>', ' ');
   argument = nstr;

   nowtime = time(&current_time);
   t = localtime (&nowtime);

   
    strtime = asctime(gmtime(&current_time));
    strtime[strlen(strtime)-1] = '\0';
   buf[0] = '\0';
   strcat(buf, datestring(strtime));
 
   if (strlen (argument) < 1)
   {
      stc ("Chat what?\n\r", ch);
      return;
   }
/*
   if (!IS_SET (ch->more, CANCHAN) && !IS_IMMORTAL (ch)
       && (get_hours (ch) < 6))
   {
      sprintf (buf, "You cannot chat until you are 6 hrs old.\n\r");
      send_to_char (buf, ch);
      stc ("Use newbie <message>, instead.\n\r", ch);
      return;
   }
*/
 if (is_contained("rapidshare", argument)) return;
 if (is_badword("fuck", argument) ||
     is_badword("pussy", argument) ||
     is_badword("cock", argument) ||
     is_badword("shit", argument) ||
     is_badword("fuk", argument) ||
     is_badword("fucc", argument) ||
     is_badword("wank", argument) ||
     is_badword("cunt", argument) ||
     is_badword("nicca", argument) ||
     is_badword("niggah", argument) ||
     is_badword("dick", argument) ||
     is_badword("cum", argument) ||
     is_badword("cok", argument) ||
     is_badword("clit", argument) ||
     is_badword("penis", argument) ||
     is_badword("blowjob", argument) ||
     is_badword("kunt", argument) ||
     is_badword("anal", argument) ||
     is_badword("nigger", argument) ||
	 is_badword("fag", argument) ||
	 is_badword("prick", argument) )
 {
  talk_channel(ch, argument, CHANNEL_FLAME, "FLAME");
  
  return;
 }
 else
 {
   if (!(fp = fopen (CHAT_LOG_FILE, "a+")))
   {
      bug ("Cannot open CHAT_LOG_FILE!", 0);
      talk_channel (ch, argument, CHANNEL_CHAT, "#yCHAT#n");
      return;
   }

   if (IS_IMMORTAL (ch)
       && (IS_SET (ch->act, PLR_WIZINVIS) || IS_SET (ch->act, PLR_INCOG)))
      fprintf (fp, ">#w[#r%s#w] %15s: #y%s#n\r\n", buf, "a divine being",
	       argument);
   else
      fprintf (fp, ">#w[#r%s#w] %15s: #y%s#n\r\n", buf, ch->name,
               ((IS_IMMORTAL(ch) && !IS_SET (ch->more, MORE_CCHANNELS)) ? argument : bash_color (argument)));
   fclose (fp);
   if (is_advertisement(argument))
   adv_alert(ch, "chat", argument);
   talk_channel (ch, argument, CHANNEL_CHAT, "#yCHAT");
   return;
 }
}

/*
 * Alander's new channels.
 */
void do_music (CHAR_DATA * ch, char *argument)
{
   if (is_advertisement(argument))

adv_alert(ch, "music", argument);
   talk_channel (ch, argument, CHANNEL_MUSIC, "#bMUSIC#n");
   return;
}


void do_question (CHAR_DATA * ch, char *argument)
{
   if (is_advertisement(argument))

   adv_alert(ch, "question", argument);
   talk_channel (ch, argument, CHANNEL_QUESTION, "#gQUESTION#n");
   return;
}

/*
void do_answer (CHAR_DATA * ch, char *argument)
{
   talk_channel (ch, argument, CHANNEL_QUESTION, "#gANSWER#n");
   return;
}
*/

void do_shout (CHAR_DATA * ch, char *argument)
{
   if (is_advertisement(argument))

   adv_alert(ch, "shout", argument);

   talk_channel (ch, argument, CHANNEL_SHOUT, "#CSHOUT#n");
   WAIT_STATE (ch, 12);
   return;
}

void do_yell (CHAR_DATA * ch, char *argument)
{
   if (is_advertisement(argument))

   adv_alert(ch, "yell", argument);

   talk_channel (ch, argument, CHANNEL_YELL, "#CYELL#n");
   return;
}

void do_buildtalk (CHAR_DATA * ch, char *argument)
{
   talk_channel (ch, argument, CHANNEL_BUILD, "buildtalk");
   return;
}

void do_immthist (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *tok;
   char buffer[MAX_STRING_LENGTH];
   char let;
   int size, save, ct = 0;


   if (!(fp = fopen (IMMT_LOG_FILE, "a+")))
   {
      bug ("Cannot open IMMT_LOG_FILE!", 0);
      send_to_char ("BUG: Inform an Immortal\r\n", ch);
      return;
   }

   save = ftell (fp);
   fseek (fp, 0L, SEEK_END);
   size = ftell (fp);
   fseek (fp, size, SEEK_SET);

   while (size--)
   {
      fseek (fp, size, SEEK_SET);
      let = fgetc (fp);
      if (let == '>')
	 ct++;
      /* Set to number of lines we want in chathist  */
      if (ct == 20)
	 break;
   }

   send_to_char ("#wImmtalk History:#n\r\n", ch);

   while (fgets (buffer, (sizeof (buffer) - 2), fp) > 0)
   {
       tok =  strtok (buffer, ">");
      send_to_char (tok, ch);
   }
   fclose (fp);
   return;
}
void do_immtalk (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *nstr;
   char buf[MSL];
   time_t nowtime;
   struct tm *t;
   char *strtime;
   /*
    * We use this char in 'chatlog.dat' to represent start of line
    * Thus we cannot use it in chat... so strip it out...  
    */
   nstr = switch_char (argument, '>', ' ');
   argument = nstr;

   nowtime = time(&current_time);
   t = localtime (&nowtime);
   strtime = asctime(gmtime(&current_time));
   buf[0] = '\0';
   strtime[strlen(strtime)-1] = '\0';
   strcat(buf, datestring(strtime)); 
   if (strlen (argument) < 1)
   {
      stc ("Immtalk what?\n\r", ch);
      return;
   }
   if (!(fp = fopen (IMMT_LOG_FILE, "a+")))
   {
      bug ("Cannot open IMMT_LOG_FILE!", 0);
      talk_channel (ch, argument, CHANNEL_IMMTALK, "immtalk");
      return;
   }

   fprintf (fp, ">#w[#r%s#w] %13s: #r%s#n\r\n", buf, ch->name, argument);
   fclose (fp);

   talk_channel (ch, argument, CHANNEL_IMMTALK, "immtalk");
   return;
}

void do_founder (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch) || (!is_clanleader(ch)  && !IS_IMMORTAL (ch)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))

   adv_alert(ch, "foundertalk", argument);

   talk_channel (ch, argument, CHANNEL_FOUNDERTALK, "foundertalk");
   return;
}
void do_monktalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_MONK)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "hum", argument);

   talk_channel (ch, argument, CHANNEL_MONK, "monk");
   return;
}

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

   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_NINJA)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "miktalk", argument);
   talk_channel (ch, argument, CHANNEL_MIKTALK, "miktalk");
   return;
}
void do_phoenixcry (CHAR_DATA * ch, char *argument)
{
 
   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_PHOENIX)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "ptalk", argument);

   talk_channel (ch, argument, CHANNEL_PTALK, "ptalk");
   return;
}
void do_wraithtalk (CHAR_DATA * ch, char *argument)
{

   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_WRAITH)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "wail", argument);

   talk_channel (ch, argument, CHANNEL_WRAITH, "wail");
   return;
}

void do_ftalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch) || (!IS_SET (ch->more, MORE_FTALK2) && !IS_CREATOR (ch)))
   {
      do_rand_typo (ch);
      return;
   }
   talk_channel (ch, argument, CHANNEL_FTALK, "ftalk");
   return;
}

// new btalk per marianne's request
void do_btalk (CHAR_DATA * ch, char *argument)
{
   FILE *fp;
   char *nstr;
   char buf[MSL];
   time_t nowtime;
   struct tm *t;
   char *strtime;
   if (IS_NPC (ch) || (!BITCH && !IS_IMMORTAL (ch)))
   {
      stc ("There currently is no bitch session in progress\n\r", ch);
      return;
   }

   /* 
    * We use this char in 'chatlog.dat' to represent start of line
    * Thus we cannot use it in chat... so strip it out... 
    */
   nstr = switch_char (argument, '>', ' ');
   argument = nstr;

   nowtime = time (&current_time);
   t = localtime (&nowtime);
    buf[0] = '\0';
   
    strtime = asctime(gmtime(&current_time));
    strtime[strlen(strtime)-1] = '\0';
    strcat(buf, datestring(strtime)); 
    
   if (strlen (argument) < 1)
   {
      stc ("Bitch what?\n\r", ch);
      return;
   }

   if (!(fp = fopen (BTALK_LOG_FILE, "a+")))
   {
      bug ("Cannot open BTALK_LOG_FILE!", 0);
      talk_channel (ch, argument, CHANNEL_BTALK, "btalk");
      return;
   }

   fprintf (fp, ">#w[#r%s#w] %15s: #y%s#n\r\n", buf, ch->name,
            ((IS_IMMORTAL(ch) && !IS_SET (ch->more, MORE_CCHANNELS)) ? argument : bash_color (argument)));
   fclose (fp);

   talk_channel (ch, argument, CHANNEL_BTALK, "btalk");
   return;
}

//old do_btalk
/*void do_btalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch) || (!BITCH && !IS_IMMORTAL (ch)))
   {
      stc ("There currently is no bitch session in progress\n\r", ch);

      return;
   }
   talk_channel (ch, argument, CHANNEL_BTALK, "btalk");
   return;
}
*/
void do_hightalk (CHAR_DATA * ch, char *argument)
{

   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_HIGHLANDER)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "htalk", argument);

   talk_channel (ch, argument, CHANNEL_HIGHTALK, "hightalk");
   return;
}

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

   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_DROW)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "sign", argument);

   talk_channel (ch, argument, CHANNEL_SIGN, "sign");
   return;
}

void do_immclantalk (CHAR_DATA * ch, char *argument)
{
   char old_clan[MIL];
   char arg[MIL];

   argument = one_argument (argument, arg);
   if IS_NPC
      (ch) return;

   if (!IS_IMMORTAL (ch))
   {
      do_rand_typo (ch);
      return;
   }
   sprintf (old_clan, "%s", ch->clan);
   free_string (ch->clan);
   ch->clan = str_dup (arg);
   talk_channel (ch, argument, CHANNEL_CLANTALK, "clantalk");
   free_string (ch->clan);
   ch->clan = str_dup (old_clan);
}

void do_clantalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch))
      return;
   if (strlen (ch->clan) < 3)
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "calntalk", argument);

   talk_channel (ch, argument, CHANNEL_CLANTALK, "clantalk");
}
void do_wedtalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch))
      return;
   if (strlen (ch->pcdata->marriage) < 3)
   {
      do_rand_typo (ch);
      return;
   }

   talk_channel (ch, argument, CHANNEL_SPOUSETALK, "spousetalk");
}

void do_vamptalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_VAMPIRE)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "vtalk", argument);

   talk_channel (ch, argument, CHANNEL_VAMPTALK, "vamptalk");
   return;
}

void do_magetalk (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch) || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_MAGE)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "magetalk", argument);

   talk_channel (ch, argument, CHANNEL_MAGETALK, "magetalk");
   return;
}

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

   act ("You mutter a few prayers.", ch, NULL, NULL, TO_CHAR);
   act ("$n mutters a quick prayer.", ch, NULL, NULL, TO_ROOM);

   if (ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_ALTAR
       && ch->class == CLASS_NONE && ch->position != POS_FIGHTING)
   {
      send_to_char ("You glow bright blue as you are restored.\n\r", ch);
      ch->hit = ch->max_hit;
      ch->mana = ch->max_mana;
      ch->move = ch->max_move;
      ch->loc_hp[0] = 0;
      ch->loc_hp[1] = 0;
      ch->loc_hp[2] = 0;
      ch->loc_hp[3] = 0;
      ch->loc_hp[4] = 0;
      ch->loc_hp[5] = 0;
      ch->loc_hp[6] = 0;
      update_pos (ch);
   }
   if (IS_NPC (ch) || (!IS_CLASS (ch, CLASS_DEMON) && !IS_IMMORTAL (ch)))
      return;

   if (argument[0] == '\0' && IS_SET (ch->special, SPC_DEMON_LORD))
   {
      send_to_char ("What do you wish to pray?\n\r", ch);
      return;
   }
   else if (argument[0] == '\0')
   {
      if (strlen (ch->lord) < 3)
      {
	 stc ("Nothing Happens.\n\r", ch);
	 return;
      }

      if (ch->pcdata->stats[DEMON_CURRENT] < 1)
      {
	 send_to_char ("Nothing happens.\n\r", ch);
	 return;
      }
      if ((victim = get_char_world (ch, ch->lord)) == NULL)
      {
	 send_to_char ("Nothing happens.\n\r", ch);
	 return;
      }
      act ("You hear $n's prayers in your mind.", ch, NULL, victim, TO_VICT);
      send_to_char ("You feel energy pour into your body.\n\r", victim);
      if (ch->pcdata->stats[DEMON_CURRENT] == 1)
	 sprintf (buf, "You receive a single point of energy.\n\r");
      else
	 sprintf (buf, "You receive %d points of energy.\n\r",
		  ch->pcdata->stats[DEMON_CURRENT]);
      send_to_char (buf, victim);
      act ("$n is briefly surrounded by a halo of energy.", victim, NULL,
	   NULL, TO_ROOM);
      victim->pcdata->stats[DEMON_CURRENT] +=
	 ch->pcdata->stats[DEMON_CURRENT];
      victim->pcdata->stats[DEMON_TOTAL] += ch->pcdata->stats[DEMON_CURRENT];
      ch->pcdata->stats[DEMON_CURRENT] = 0;
      return;
   }
   if (IS_SET (ch->deaf, CHANNEL_PRAY))
   {
      send_to_char ("But you're not even on the channel!\n\r", ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "pray", argument);

   talk_channel (ch, argument, CHANNEL_PRAY, "pray");
   return;
}

void do_howl (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch)
       || (!IS_IMMORTAL (ch) && !IS_CLASS (ch, CLASS_WEREWOLF)
	   && !IS_POLYAFF (ch, POLY_WOLF)))
   {
      do_rand_typo (ch);
      return;
   }
   if (is_advertisement(argument))
adv_alert(ch, "howl", argument);

   talk_channel (ch, argument, CHANNEL_HOWL, "howl");
   send_howl (ch);

   return;
}

void do_say (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char name[80];
   char poly[MAX_STRING_LENGTH];
   char speak[15];
   char speaks[15];
   char endbit[5];
   char secbit[5];
   CHAR_DATA *to;

   bool is_ok;

   if (IS_HEAD (ch, LOST_TONGUE))
   {
      send_to_char ("You can't speak without a tongue!\n\r", ch);
      return;
   }
   if (IS_EXTRA (ch, GAGGED))
   {
      send_to_char ("You can't speak with a gag on!\n\r", ch);
      return;
   }

   if (ch->in_room != NULL
       && IS_SET (ch->in_room->added_flags, ROOM2_SILENCE))
   {
      send_to_char ("Your words make no sound!\n\r", ch);
      return;
   }

   if (strlen (argument) > MAX_INPUT_LENGTH)
   {
      send_to_char ("Line too long.\n\r", ch);
      return;
   }

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

   /* Allow the manipulation of a const argument */
   strcpy (buf, argument);
   argument = &buf[0];

   endbit[0] = argument[strlen (argument) - 1];
   endbit[1] = '\0';

   if (strlen (argument) > 1)
      secbit[0] = argument[strlen (argument) - 2];
   else
      secbit[0] = '\0';
   secbit[1] = '\0';

   if (IS_BODY (ch, CUT_THROAT))
   {
      sprintf (speak, "rasp");
      sprintf (speaks, "rasps");
   }
   else if (!IS_NPC (ch)
	    && (IS_SET (ch->special, SPC_WOLFMAN)
		|| IS_POLYAFF (ch, POLY_WOLF) || (IS_CLASS (ch, CLASS_VAMPIRE)
						  && ch->pcdata->
						  stats[UNI_RAGE] > 0)))
   {
      if (number_percent () > 50)
      {
	 sprintf (speak, "growl");
	 sprintf (speaks, "growls");
      }
      else
      {
	 sprintf (speak, "snarl");
	 sprintf (speaks, "snarls");
      }
   }
   else if (!IS_NPC (ch) && IS_POLYAFF (ch, POLY_BAT))
   {
      sprintf (speak, "squeak");
      sprintf (speaks, "squeaks");
   }
   else if (!IS_NPC (ch) && IS_POLYAFF (ch, POLY_SERPENT))
   {
      sprintf (speak, "hiss");
      sprintf (speaks, "hisses");
   }
   else if (!IS_NPC (ch) && IS_POLYAFF (ch, POLY_FROG))
   {
      sprintf (speak, "croak");
      sprintf (speaks, "croaks");
   }
   else if (!IS_NPC (ch) && IS_POLYAFF (ch, POLY_RAVEN))
   {
      sprintf (speak, "squark");
      sprintf (speaks, "squarks");
   }
   else if (!str_cmp (endbit, "!"))
   {
      sprintf (speak, "exclaim");
      sprintf (speaks, "exclaims");
   }
   else if (!str_cmp (endbit, "?"))
   {
      sprintf (speak, "ask");
      sprintf (speaks, "asks");
   }
   else if (secbit[0] != '\0' && str_cmp (secbit, ".")
	    && !str_cmp (endbit, "."))
   {
      sprintf (speak, "state");
      sprintf (speaks, "states");
   }
   else if (secbit[0] != '\0' && !str_cmp (secbit, ".")
	    && !str_cmp (endbit, "."))
   {
      sprintf (speak, "mutter");
      sprintf (speaks, "mutters");
   }
   else if (secbit[0] != '\0'
	    && (!str_cmp (secbit, ":") || !str_cmp (secbit, "=")
		|| !str_cmp (secbit, ";")) && !str_cmp (endbit, ")"))
   {
      sprintf (speak, "grin");
      sprintf (speaks, "grins");
   }
   else if (secbit[0] != '\0'
	    && (!str_cmp (secbit, ":") || !str_cmp (secbit, "=")
		|| !str_cmp (secbit, ";")) && (!str_cmp (endbit, "P")
					       || !str_cmp (endbit, "p")))
   {
      sprintf (speak, "joke");
      sprintf (speaks, "jokes");
   }
   else if (secbit[0] != '\0' && !str_cmp (secbit, ":")
	    && !str_cmp (endbit, "("))
   {
      sprintf (speak, "frown");
      sprintf (speaks, "frowns");
   }
   else
   {
      sprintf (speak, "say");
      sprintf (speaks, "says");
   }
   sprintf (poly, "#wYou %s '#g$T#w'#n", speak);
   if (!IS_NPC (ch))
   {
      if (ch->pcdata->condition[COND_DRUNK] > 10)
	 act (poly, ch, NULL, drunktalk (ch, argument), TO_CHAR);
      else if (ch->pcdata->stats[UNI_RAGE] > 0
               && IS_CLASS (ch, CLASS_VAMPIRE)
               && !IS_IMMORTAL(ch))
	 act (poly, ch, NULL, beasttalk (ch, argument), TO_CHAR);

      else if (IS_SPEAKING (ch, DIA_OLDE))
	 act (poly, ch, NULL, oldelang (ch, argument), TO_CHAR);
      else if (IS_SPEAKING (ch, DIA_BAD))
	 act (poly, ch, NULL, badlang (ch, argument), TO_CHAR);
      else
	 act (poly, ch, NULL, argument, TO_CHAR);
   }
   else
      act (poly, ch, NULL, argument, TO_CHAR);
   if (is_advertisement(argument))
adv_alert(ch, "say", argument);

   sprintf (poly, "#w$n #w%s '#g$T#w'#n", speaks);

   if (ch->in_room->vnum != ROOM_VNUM_IN_OBJECT)
   {
      act (poly, ch, NULL, argument, TO_ROOM);

      room_text (ch, strlower (argument));
      return;
   }

   to = ch->in_room->people;
   for (; to != NULL; to = to->next_in_room)
   {
      is_ok = FALSE;

      if (to->desc == NULL || !IS_AWAKE (to))
	 continue;

      if (ch == to)
	 continue;

      if (!IS_NPC (ch) && ch->pcdata->chobj != NULL
	  && ch->pcdata->chobj->in_room != NULL && !IS_NPC (to)
	  && to->pcdata->chobj != NULL && to->pcdata->chobj->in_room != NULL
	  && ch->in_room == to->in_room)
	 is_ok = TRUE;
      else
	 is_ok = FALSE;

      if (!IS_NPC (ch) && ch->pcdata->chobj != NULL &&
	  ch->pcdata->chobj->in_obj != NULL && !IS_NPC (to)
	  && to->pcdata->chobj != NULL && to->pcdata->chobj->in_obj != NULL
	  && ch->pcdata->chobj->in_obj == to->pcdata->chobj->in_obj)
	 is_ok = TRUE;
      else
	 is_ok = FALSE;

      if (!is_ok)
	 continue;

      if (IS_NPC (ch))
	 sprintf (name, ch->short_descr);
      else if (!IS_NPC (ch) && IS_AFFECTED (ch, AFF_POLYMORPH))
	 sprintf (name, ch->morph);
      else
	 sprintf (name, ch->name);
      name[0] = UPPER (name[0]);
      sprintf (poly, "%s %s '%s'.\n\r", name, speaks, argument);
      send_to_char (poly, to);
   }

   room_text (ch, strlower (argument));
   return;
}
void room_text (CHAR_DATA * ch, char *argument)
{
   CHAR_DATA *vch;
   CHAR_DATA *vch_next;
   CHAR_DATA *mob;
   OBJ_DATA *obj;
   ROOMTEXT_DATA *rt;
   bool mobfound;
   bool hop;

   char arg[MAX_INPUT_LENGTH];
   char arg1[MAX_INPUT_LENGTH];
   char arg2[MAX_INPUT_LENGTH];

   for (rt = ch->in_room->roomtext; rt != NULL; rt = rt->next)
   {
      if (!strcmp (argument, rt->input) || is_in (argument, rt->input)
	  || all_in (argument, rt->input))
      {
	 if (rt->name != NULL && rt->name != '\0' && str_cmp (rt->name, "all")
	     && str_cmp (rt->name, "|all*"))
	    if (!is_in (ch->name, rt->name))
	       continue;
	 mobfound = TRUE;
	 if (rt->mob != 0)
	 {
	    mobfound = FALSE;
	    for (vch = char_list; vch != NULL; vch = vch_next)
	    {
	       vch_next = vch->next;
	       if (vch->in_room == NULL)
		  continue;
	       if (!IS_NPC (vch))
		  continue;
	       if (vch->in_room == ch->in_room
		   && vch->pIndexData->vnum == rt->mob)
	       {
		  mobfound = TRUE;
		  break;
	       }
	    }
	 }
	 if (!mobfound)
	    continue;
	 hop = FALSE;
	 switch (rt->type % RT_RETURN)
	 {
	 case RT_SAY:
	    break;
	 case RT_LIGHTS:
	    do_changelight (ch, "");
	    break;
	 case RT_LIGHT:
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_DARK);
	    break;
	 case RT_DARK:
	    SET_BIT (ch->in_room->room_flags, ROOM_DARK);
	    break;
	 case RT_OBJECT:
	    if (get_obj_index (rt->power) == NULL)
	       return;
	    obj = create_object (get_obj_index (rt->power), ch->level);
	    if (IS_SET (rt->type, RT_TIMER))
	       obj->timer = 1;
	    if (CAN_WEAR (obj, ITEM_TAKE))
	       obj_to_char (obj, ch);
	    else
	       obj_to_room (obj, ch->in_room);
	    if (!str_cmp (rt->choutput, "copy"))
	       act (rt->output, ch, obj, NULL, TO_CHAR);
	    else
	       act (rt->choutput, ch, obj, NULL, TO_CHAR);
	    if (!IS_SET (rt->type, RT_PERSONAL))
	       act (rt->output, ch, obj, NULL, TO_ROOM);
	    hop = TRUE;
	    break;
	 case RT_MOBILE:
	    if (get_mob_index (rt->power) == NULL)
	       return;
	    mob = create_mobile (get_mob_index (rt->power));
	    char_to_room (mob, ch->in_room);
	    if (!str_cmp (rt->choutput, "copy"))
	       act (rt->output, ch, NULL, mob, TO_CHAR);
	    else
	       act (rt->choutput, ch, NULL, mob, TO_CHAR);
	    if (!IS_SET (rt->type, RT_PERSONAL))
	       act (rt->output, ch, NULL, mob, TO_ROOM);
	    hop = TRUE;
	    break;
	 case RT_SPELL:

	    (*skill_table[rt->power].spell_fun) (rt->power,
						 number_range (20, 30), ch,
						 ch);
	    break;
	 case RT_PORTAL:
	    if (get_obj_index (OBJ_VNUM_PORTAL) == NULL)
	       return;
	    obj = create_object (get_obj_index (OBJ_VNUM_PORTAL), 0);
	    obj->timer = 1;
	    obj->value[0] = rt->power;
	    obj->value[1] = 1;
	    obj_to_room (obj, ch->in_room);
	    break;
	 case RT_TELEPORT:
            if (ch->position == POS_FIGHTING)
            {
		stc("Not while fighting\n\r", ch);
                return;
            }
            if (ch->fight_timer > 0)
            {
		stc("Not while you have a fight timer\n\r", ch);
                return;
            }
	    if (get_room_index (rt->power) == NULL)
	       return;
	    if (!str_cmp (rt->choutput, "copy"))
	       act (rt->output, ch, NULL, NULL, TO_CHAR);
	    else
	       act (rt->choutput, ch, NULL, NULL, TO_CHAR);
	    if (!IS_SET (rt->type, RT_PERSONAL))
	       act (rt->output, ch, NULL, NULL, TO_ROOM);
	    char_from_room (ch);
	    char_to_room (ch, get_room_index (rt->power));
	    act ("$n appears in the room.", ch, NULL, NULL, TO_ROOM);
	    do_look (ch, "auto");
	    hop = TRUE;
	    break;
	 case RT_ACTION:
	    sprintf (arg, argument);
	    argument = one_argument (arg, arg1);
	    argument = one_argument (arg, arg2);
	    if ((mob = get_char_room (ch, arg2)) == NULL)
	       continue;
	    interpret (mob, rt->output);
	    break;
	 case RT_OPEN_LIFT:
	    open_lift (ch);
	    break;
	 case RT_CLOSE_LIFT:
	    close_lift (ch);
	    break;
	 case RT_MOVE_LIFT:
	    move_lift (ch, rt->power);
	    break;
	 default:
	    break;
	 }
	 if (hop && IS_SET (rt->type, RT_RETURN))
	    return;
	 else if (hop)
	    continue;
	 if (!str_cmp (rt->choutput, "copy") && !IS_SET (rt->type, RT_ACTION))
	    act (rt->output, ch, NULL, NULL, TO_CHAR);
	 else if (!IS_SET (rt->type, RT_ACTION))
	    act (rt->choutput, ch, NULL, NULL, TO_CHAR);
	 if (!IS_SET (rt->type, RT_PERSONAL) && !IS_SET (rt->type, RT_ACTION))
	    act (rt->output, ch, NULL, NULL, TO_ROOM);
	 if (IS_SET (rt->type, RT_RETURN))
	    return;
      }
   }
   return;
}

char *strlower (char *ip)
{
   static char buffer[MAX_INPUT_LENGTH];
   int pos;

   for (pos = 0; pos < (MAX_INPUT_LENGTH - 1) && ip[pos] != '\0'; pos++)
   {
      buffer[pos] = tolower (ip[pos]);
   }
   buffer[pos] = '\0';
   return buffer;
}

bool is_in (char *arg, char *ip)
{
   char *lo_arg;
   char cmp[MAX_INPUT_LENGTH];
   int fitted;

   if (ip[0] != '|')
      return FALSE;
   cmp[0] = '\0';
   lo_arg = strlower (arg);
   do
   {
      ip += strlen (cmp) + 1;
      fitted = sscanf (ip, "%[^*]", cmp);
      if (strstr (lo_arg, cmp) != NULL)
      {
	 return TRUE;
      }
   }
   while (fitted > 0);
   return FALSE;
}

bool all_in (char *arg, char *ip)
{
   char *lo_arg;
   char cmp[MAX_INPUT_LENGTH];
   int fitted;

   if (ip[0] != '&')
      return FALSE;
   cmp[0] = '\0';
   lo_arg = strlower (arg);
   do
   {
      ip += strlen (cmp) + 1;
      fitted = sscanf (ip, "%[^*]", cmp);
      if (strstr (lo_arg, cmp) == NULL)
      {
	 return FALSE;
      }
   }
   while (fitted > 0);
   return TRUE;
}

/* No Reply to stop people sending you replies */
void do_noreply (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch))
      return;

   if (IS_SET (ch->newbits, NEW_NOREPLY))
   {
      REMOVE_BIT (ch->newbits, NEW_NOREPLY);
      send_to_char ("You accept replies.\n\r", ch);
   }
   else
   {
      SET_BIT (ch->newbits, NEW_NOREPLY);
      send_to_char ("You stop accepting replies.\n\r", ch);
   }
   return;
}
void do_nochan (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch))
      return;

   if (IS_SET (ch->flag2, NOCHAN))
   {
      REMOVE_BIT (ch->flag2, NOCHAN);
      send_to_char ("You can use all channels again.\n\r", ch);
   }
   else
   {
      SET_BIT (ch->flag2, NOCHAN);
      send_to_char ("You can now only use immtalk/ftalk.\n\r", ch);
   }
   return;
}

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

   if (IS_SET (ch->flag2, NOBEEP))
   {
      REMOVE_BIT (ch->flag2, NOBEEP);
      stc ("You can be beeped again!\n\r", ch);
   }
   else
   {
      SET_BIT (ch->flag2, NOBEEP);
      stc ("You can nolonger be beeeped!\n\r", ch);
   }
   return;
}
void do_review (CHAR_DATA * ch, char *argument)
{
   int i;

   if (IS_NPC (ch) || (ch->pcdata == NULL))
   {
      send_to_char ("Not for NPCs.\n\r", ch);
      return;
   }
   stc ("#wTell History:#n\n\r", ch);

   i = ch->pcdata->tell_history_pos;
   do
   {
      send_to_char (ch->pcdata->tell_history[i], ch);
      i = (i + 1) % TELL_HISTORY_SIZE;
   }
   while (i != ch->pcdata->tell_history_pos);

   return;
}

void do_tell (CHAR_DATA * ch, char *argument)
{
   char arg[MAX_INPUT_LENGTH];
   char poly[MAX_STRING_LENGTH];
   CHAR_DATA *victim;
   int position;
   char buf[MSL];
   time_t nowtime;
   struct tm *t;
    char *strtime;
   
   nowtime = time (&current_time);
   t = localtime (&nowtime);
   //strftime (buf, 100, "%H:%M:%S", t);
    buf[0] = '\0';
   
    strtime = asctime(gmtime(&current_time));
    strtime[strlen(strtime)-1] = '\0';
    strcat(buf, timestring(strtime)); 
    

   if (!IS_IMMORTAL (ch) && (ch->mkill < 20) && !IS_NPC (ch))
   {
      stc ("Until you have killed 20 mobs, you are unable to send tells.\n\r",
	   ch);
      return;

   }
   if ((IS_NPC (ch) && ch->pIndexData->vnum != 25) || IS_SET (ch->act, PLR_SILENCE))
   {
      send_to_char ("Your message didn't get through.\n\r", ch);
      return;
   }

   if (IS_EXTRA (ch, GAGGED))
   {
      send_to_char ("Your message didn't get through.\n\r", ch);
      return;
   }
   argument = one_argument (argument, arg);

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

   /*
    * Can tell to PC's anywhere, but NPC's only in same room.
    * -- Furey
    */

   if ((victim = get_char_world (ch, arg)) == NULL
       || ((IS_NPC (victim) && victim->in_room != ch->in_room) && !IS_NPC(ch)))
   {
      send_to_char ("They aren't here.\n\r", ch);
      return;
   }

   if (!IS_NPC (victim) && IS_SET (victim->act, PLR_SILENCE))
   {
      stc ("They are currently silenced, so will be unable to reply.\n\r",
	   ch);
   }

   if (!IS_IMMORTAL (ch) && !IS_AWAKE (victim))
   {
      act ("$E can't hear you.", ch, 0, victim, TO_CHAR);
      return;
   }

   if (!IS_NPC (victim) && victim->desc == NULL)
   {
      act ("$E is currently link dead.", ch, 0, victim, TO_CHAR);
      return;
   }

   if (IS_SET (victim->deaf, CHANNEL_TELL))
   {
      if ((IS_NPC (victim) || IS_NPC (ch)
	   || strlen (victim->pcdata->marriage) < 2
	   || str_cmp (ch->name, victim->pcdata->marriage))
	  && ((ch->trust < (MAX_LEVEL - 3)) && (ch->level < (MAX_LEVEL - 3))))
      {
	 act ("$E can't hear you.", ch, 0, victim, TO_CHAR);
	 return;
      }
   }
   sprintf (poly, "#wYou tell %s '#c$t#w'#n",
	    IS_NPC (victim) ? victim->short_descr : victim->name);
   act (poly, ch, argument, victim, TO_CHAR);
   position = victim->position;
   victim->position = POS_STANDING;

   if (IS_IMMORTAL(ch) )
   {

   sprintf (poly, "#w%s tells you '^1#c$t#n#w'#n",
            IS_NPC (ch) ? ch->short_descr : ch->name);
   sprintf (log_buf, "Log %s: %s tells you %s", victim->name,   
            IS_NPC (ch) ? ch->short_descr : ch->name, argument);
   }
   else
   {
   sprintf (poly, "#w%s tells you '#c$t#w'#n",
	    IS_NPC (ch) ? ch->short_descr : ch->name);
   sprintf (log_buf, "Log %s: %s tells you %s", victim->name,
  	    IS_NPC (ch) ? ch->short_descr : ch->name, argument);
   }
   act (poly, ch, argument, victim, TO_VICT);
   if (is_advertisement(argument))
adv_alert(ch, "tell", argument);

   if (IS_SET (victim->act, PLR_LOG))
      log_player (log_buf, victim, TRUE);
   if (victim->pcdata)
   {
      int pos = (victim->pcdata->tell_history_pos);
      victim->pcdata->tell_history_pos =
	 (victim->pcdata->tell_history_pos + 1) % TELL_HISTORY_SIZE;

      sprintf (poly, "#w[#r%s#w] #c(From) #w%15s: #c%s#n\r\n", buf, ch->name,
	       argument);
      free_string (victim->pcdata->tell_history[pos]);
      victim->pcdata->tell_history[pos] = str_dup (poly);
   }

   if (ch->pcdata)
   {
      int pos = (ch->pcdata->tell_history_pos);
      ch->pcdata->tell_history_pos =
	 (ch->pcdata->tell_history_pos + 1) % TELL_HISTORY_SIZE;
      sprintf (poly, "#w[#r%s#w] #c  (To) #w%15s: #c%s#n\r\n", buf,
	       victim->name, argument);
      free_string (ch->pcdata->tell_history[pos]);
      ch->pcdata->tell_history[pos] = str_dup (poly);
   }

   victim->position = position;
   victim->reply = ch;
   return;
}

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

   if (IS_EXTRA (ch, GAGGED))
   {
      send_to_char ("Not with a gag on!\n\r", ch);
      return;
   }

   argument = one_argument (argument, arg);

   if (arg[0] == '\0' || argument[0] == '\0')
   {
      send_to_char ("Syntax: whisper <person> <message>\n\r", ch);
      return;
   }

   if ((victim = get_char_world (ch, arg)) == NULL
       || (victim->in_room != ch->in_room))
   {
      send_to_char ("They aren't here.\n\r", ch);
      return;
   }

   if (!IS_AWAKE (victim))
   {
      act ("$E cannot hear you.", ch, 0, victim, TO_CHAR);
      return;
   }

   if (!IS_NPC (victim) && victim->desc == NULL)
   {
      act ("$E is currently link dead.", ch, 0, victim, TO_CHAR);
      return;
   }

   act ("#wYou whisper to $N '#C$t#w'#n", ch, argument, victim, TO_CHAR);
   act ("#w$n whispers to you '#C$t#w'", ch, argument, victim, TO_VICT);
   if (is_advertisement(argument))
adv_alert(ch, "whisper", argument);

   return;
}

void do_reply (CHAR_DATA * ch, char *argument)
{
   char poly[MAX_STRING_LENGTH];
   CHAR_DATA *victim;
   int position;
   char buf[MSL];
   time_t nowtime;
   struct tm *t;
   char *strtime;

   if (argument[0] == '\0')
   {
      send_to_char ("What do you wish to reply?\n\r", ch);
      return;
   }
   nowtime = time (&current_time);
   t = localtime (&nowtime);
 buf[0] = '\0';
   
    strtime = asctime(gmtime(&current_time));
    strtime[strlen(strtime)-1] = '\0';
    strcat(buf, timestring(strtime)); 
    

   if (!IS_NPC (ch) && IS_SET (ch->act, PLR_SILENCE))
   {
      send_to_char ("Your message didn't get through.\n\r", ch);
      return;
   }
   if (IS_EXTRA (ch, GAGGED))
   {
      send_to_char ("Your message didn't get through.\n\r", ch);
      return;
   }
   if ((victim = ch->reply) == NULL)
   {
      send_to_char ("They aren't here.\n\r", ch);
      return;
   }

   if (IS_SET (victim->newbits, NEW_NOREPLY) && !IS_IMMORTAL (ch))
   {
      act ("$E can't hear you.", ch, 0, victim, TO_CHAR);
      return;
   }
   if (!IS_IMMORTAL (ch) && !IS_AWAKE (victim))
   {
      act ("$E can't hear you.", ch, 0, victim, TO_CHAR);
      return;
   }
   if (!IS_NPC (victim) && victim->desc == NULL)
   {
      act ("$E is currently link dead.", ch, 0, victim, TO_CHAR);
      return;
   }

   sprintf (poly, "#wYou reply to %s '#c$t#w'#n",
	    IS_NPC (victim) ? victim->short_descr : victim->name);
   act (poly, ch, argument, victim, TO_CHAR);
   position = victim->position;
   victim->position = POS_STANDING;

   if (IS_IMMORTAL(ch) )
   {
   sprintf (poly, "#w%s replies '^1#c$t#n#w'#n",
	    IS_NPC (ch) ? ch->short_descr : ch->name);
   sprintf (log_buf, "Log %s: %s replies %s", victim->name,
	    IS_NPC (ch) ? ch->short_descr : ch->name, argument);
   }
   else
   {
   sprintf (poly, "#w%s replies '#c$t#w'#n",
	    IS_NPC (ch) ? ch->short_descr : ch->name);
   sprintf (log_buf, "Log %s: %s replies %s", victim->name,
	    IS_NPC (ch) ? ch->short_descr : ch->name, argument);
   }
   if (is_advertisement(argument))
adv_alert(ch, "reply", argument);

   act (poly, ch, argument, victim, TO_VICT);
   if (IS_SET (victim->act, PLR_LOG))
      log_player (log_buf, victim, TRUE);

   if (victim->pcdata)
   {
      int pos = (victim->pcdata->tell_history_pos);
      victim->pcdata->tell_history_pos =
	 (victim->pcdata->tell_history_pos + 1) % TELL_HISTORY_SIZE;

      sprintf (poly, "#w[#r%s#w] #c(From) #w%15s: #c%s#n\r\n", buf, ch->name,
	       argument);
      free_string (victim->pcdata->tell_history[pos]);
      victim->pcdata->tell_history[pos] = str_dup (poly);
   }

   if (ch->pcdata)
   {
      int pos = (ch->pcdata->tell_history_pos);
      ch->pcdata->tell_history_pos =
	 (ch->pcdata->tell_history_pos + 1) % TELL_HISTORY_SIZE;
      sprintf (poly, "#w[#r%s#w] #c  (To) #w%15s: #c%s#n\r\n", buf,
	       victim->name, argument);
      free_string (ch->pcdata->tell_history[pos]);
      ch->pcdata->tell_history[pos] = str_dup (poly);
   }

   victim->position = position;
   victim->reply = ch;
   return;
}


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

   char name[80];
   char poly[MAX_INPUT_LENGTH];
   CHAR_DATA *to;
   bool is_ok;

   if (!IS_NPC (ch) && IS_SET (ch->act, PLR_NO_EMOTE))
   {
      send_to_char ("You can't show your emotions.\n\r", ch);
      return;
   }

   if (IS_HEAD (ch, LOST_TONGUE) || IS_HEAD (ch, LOST_HEAD)
       || IS_EXTRA (ch, GAGGED))
   {
      send_to_char ("You can't show your emotions.\n\r", ch);
      return;
   }

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

   for (plast = argument; *plast != '\0'; plast++)
      ;

   strcpy (buf, argument);
   if (isalpha (plast[-1]))
      strcat (buf, ".");

   act ("$n $T", ch, NULL, buf, TO_CHAR);

   if (ch->in_room->vnum != ROOM_VNUM_IN_OBJECT)
   {
      act ("$n $T", ch, NULL, buf, TO_ROOM);
      return;
   }

   to = ch->in_room->people;
   for (; to != NULL; to = to->next_in_room)
   {
      is_ok = FALSE;

      if (to->desc == NULL || !IS_AWAKE (to))
	 continue;

      if (ch == to)
	 continue;

      if (!IS_NPC (ch) && ch->pcdata->chobj != NULL
	  && ch->pcdata->chobj->in_room != NULL && !IS_NPC (to)
	  && to->pcdata->chobj != NULL && to->pcdata->chobj->in_room != NULL
	  && ch->in_room == to->in_room)
	 is_ok = TRUE;
      else
	 is_ok = FALSE;

      if (!IS_NPC (ch) && ch->pcdata->chobj != NULL &&
	  ch->pcdata->chobj->in_obj != NULL && !IS_NPC (to)
	  && to->pcdata->chobj != NULL && to->pcdata->chobj->in_obj != NULL
	  && ch->pcdata->chobj->in_obj == to->pcdata->chobj->in_obj)
	 is_ok = TRUE;
      else
	 is_ok = FALSE;

      if (!is_ok)
	 continue;

      if (IS_NPC (ch))
	 sprintf (name, ch->short_descr);
      else if (!IS_NPC (ch) && IS_AFFECTED (ch, AFF_POLYMORPH))
	 sprintf (name, ch->morph);
      else
	 sprintf (name, ch->name);
      name[0] = UPPER (name[0]);
      sprintf (poly, "%s %s\n\r", name, buf);
      send_to_char (poly, to);
   }
   return;
}

void do_xemote (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char buf2[MAX_STRING_LENGTH];
   char oldarg[MAX_STRING_LENGTH];
   char *plast;

   char name[80];
   char you[80];
   char them[80];
   char poly[MAX_INPUT_LENGTH];
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *to;
   CHAR_DATA *victim;
   bool is_ok;

   argument = one_argument (argument, arg);

   if (!IS_NPC (ch) && IS_SET (ch->act, PLR_NO_EMOTE))
   {
      send_to_char ("You can't show your emotions.\n\r", ch);
      return;
   }

   if (IS_HEAD (ch, LOST_TONGUE) || IS_HEAD (ch, LOST_HEAD)
       || IS_EXTRA (ch, GAGGED))
   {
      send_to_char ("You can't show your emotions.\n\r", ch);
      return;
   }

   if (strlen (argument) > MAX_INPUT_LENGTH)
   {
      send_to_char ("Line too long.\n\r", ch);
      return;
   }

   if (argument[0] == '\0' || arg[0] == '\0')
   {
      send_to_char ("Syntax: emote <person> <sentence>\n\r", ch);
      return;
   }

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

   if (IS_NPC (ch))
      strcpy (you, ch->short_descr);
   else
      strcpy (you, ch->name);
   if (IS_NPC (victim))
      strcpy (you, victim->short_descr);
   else
      strcpy (you, victim->name);
/*
oldarg = argument;
*/
   strcpy (oldarg, argument);
   strcpy (buf, argument);
   for (plast = argument; *plast != '\0'; plast++)
      ;

   if (isalpha (plast[-1]))
      strcat (buf, ".");
   argument = socialc (ch, buf, you, them);

   strcpy (buf, argument);
   strcpy (buf2, "You ");
   buf[0] = LOWER (buf[0]);
   strcat (buf2, buf);
   capitalize (buf2);
   act (buf2, ch, NULL, victim, TO_CHAR);

   if (ch->in_room->vnum != ROOM_VNUM_IN_OBJECT)
   {
      strcpy (buf, oldarg);
      for (plast = argument; *plast != '\0'; plast++)
	 ;
      if (isalpha (plast[-1]))
	 strcat (buf, ".");

      argument = socialn (ch, buf, you, them);

      strcpy (buf, argument);
      strcpy (buf2, "$n ");
      buf[0] = LOWER (buf[0]);
      strcat (buf2, buf);
      capitalize (buf2);
      act (buf2, ch, NULL, victim, TO_NOTVICT);

      strcpy (buf, oldarg);
      for (plast = argument; *plast != '\0'; plast++)
	 ;
      if (isalpha (plast[-1]))
	 strcat (buf, ".");

      argument = socialv (ch, buf, you, them);

      strcpy (buf, argument);
      strcpy (buf2, "$n ");
      buf[0] = LOWER (buf[0]);
      strcat (buf2, buf);
      capitalize (buf2);
      act (buf2, ch, NULL, victim, TO_VICT);
      return;
   }

   to = ch->in_room->people;
   for (; to != NULL; to = to->next_in_room)
   {
      is_ok = FALSE;

      if (to->desc == NULL || !IS_AWAKE (to))
	 continue;

      if (ch == to)
	 continue;

      if (!IS_NPC (ch) && ch->pcdata->chobj != NULL
	  && ch->pcdata->chobj->in_room != NULL && !IS_NPC (to)
	  && to->pcdata->chobj != NULL && to->pcdata->chobj->in_room != NULL
	  && ch->in_room == to->in_room)
	 is_ok = TRUE;
      else
	 is_ok = FALSE;

      if (!IS_NPC (ch) && ch->pcdata->chobj != NULL &&
	  ch->pcdata->chobj->in_obj != NULL && !IS_NPC (to)
	  && to->pcdata->chobj != NULL && to->pcdata->chobj->in_obj != NULL
	  && ch->pcdata->chobj->in_obj == to->pcdata->chobj->in_obj)
	 is_ok = TRUE;
      else
	 is_ok = FALSE;

      if (!is_ok)
	 continue;

      if (IS_NPC (ch))
	 sprintf (name, ch->short_descr);
      else if (!IS_NPC (ch) && IS_AFFECTED (ch, AFF_POLYMORPH))
	 sprintf (name, ch->morph);
      else
	 sprintf (name, ch->name);
      name[0] = UPPER (name[0]);
      sprintf (poly, "%s %s\n\r", name, buf);
      send_to_char (poly, to);
   }
   return;
}

void do_bug (CHAR_DATA * ch, char *argument)
{
   append_file (ch, BUG_FILE, argument);
   send_to_char ("Ok.  Thanks.\n\r", ch);
   return;
}

void do_idea (CHAR_DATA * ch, char *argument)
{
   append_file (ch, IDEA_FILE, argument);
   send_to_char ("Ok.  Thanks.\n\r", ch);
   return;
}

void do_typo (CHAR_DATA * ch, char *argument)
{
   append_file (ch, TYPO_FILE, argument);
   send_to_char ("Ok.  Thanks.\n\r", ch);
   return;
}

void do_rent (CHAR_DATA * ch, char *argument)
{
   send_to_char ("There is no rent here.  Just save and quit.\n\r", ch);
   return;
}

void do_qui (CHAR_DATA * ch, char *argument)
{
   send_to_char ("If you want to QUIT, you have to spell it out.\n\r", ch);
   return;
}

void do_quit (CHAR_DATA * ch, char *argument)
{
   DESCRIPTOR_DATA *d;
  ROOM_INDEX_DATA* was_in = NULL;

   char buf[MAX_STRING_LENGTH];
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;
   CHAR_DATA *mount;
   int temp_num;
   int targetroom;

   if (IS_NPC (ch))
      return;

   if (ch->position == POS_FIGHTING)
   {
      send_to_char ("No way! You are fighting.\n\r", ch);
      return;
   }

   if (IS_SET (ch->flag2, AFF2_CHALLENGED))
   {
      stc ("You cannot quit. You will have to decline first.\n\r", ch);
      return;
   }
   if (IS_SET (ch->flag2, AFF2_CHALLENGER))
   {
      stc ("You cannot quit, You have a challenge in progress.\n\r", ch);
      return;
   }
   if (IS_SET (ch->flag2, AFF2_INARENA))
   {
      CHAR_DATA *player;
      for (player = char_list; player != NULL; player = player->next)
         if (!IS_NPC(player) && player != ch && player->in_room != NULL && is_inarena(player))
         {
            stc ("You cannot quit while you're in the arena.\n\r", ch);
            return;
         }
   }

   if (IS_SET (ch->war, JOINING))
   {
      stc ("You can't quit your joining a war!\n\r", ch);
      return;
   }
   if (IS_SET (ch->war, WARRING))
   {
      stc ("You can't quit while in a WAR!\n\r", ch);
      return;
   }
   if (ch->position < POS_SLEEPING)
   {
      send_to_char ("You're not DEAD yet.\n\r", ch);
      return;
   }
    was_in = ch->was_in_room ? ch->was_in_room : ch->in_room;

   if (auction_info.high_bidder == ch || auction_info.owner == ch)
   {
      send_to_char ("You still have a stake in the auction!\n\r", ch);
      return;
   }
   if (!IS_NPC (ch) && IS_EXTRA2 (ch, EXTRA2_NEUTRAL))
   {
      if (ch->in_room != NULL)
      {
	 REMOVE_BIT (ch->extra2, EXTRA2_NEUTRAL);
	 act ("$n stops making the time-out sign.", ch, NULL, NULL, TO_ROOM);
	 send_to_char
	    ("The peaceful harmony in the air gradually fades away to nothing.\n\r",
	     ch);
	 act ("The peaceful harmony in the air gradually fades away to nothing.", ch, NULL, NULL, TO_ROOM);
      }
   }
   if (!IS_NPC (ch) && IS_SET (ch->newbits, NEW_DARKNESS))
   {
      if (ch->in_room != NULL)
      {
         if (IS_CLASS (ch, CLASS_DROW) || WORN_ARTIFACT (ch, ARTI_HEART_OF_DARKNESS))
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
         if (IS_CLASS(ch, CLASS_FAE) && IS_KITH (ch, KITH_SLUAGH))
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
	 if (IS_CLASS (ch, CLASS_WEREWOLF))
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_DARK);
	 REMOVE_BIT (ch->newbits, NEW_DARKNESS);
	 send_to_char
	    ("The darkness in the room gradually fades away to nothing.\n\r",
	     ch);
	 act ("The darkness in the room gradually fades away to nothing.", ch,
	      NULL, NULL, TO_ROOM);
      }
   }
/*
   if (!IS_IMMORTAL (ch) && ch->level > 1 && ch->pcdata->login_timer > 0
       && ch->desc != NULL)
   {
      sprintf (buf,
	       "You still have '#r%d#n' ticks left on your login timer before you can quit!\n\r",
	       ch->pcdata->login_timer);
      stc (buf, ch);
      return;
   }
*/
   if (!IS_IMMORTAL (ch) && (ch->fight_timer > 0) && ch->desc != NULL)
   {
      stcprintf (ch,
		 "You still have '#r%d#n' ticks left on your fight timer before you can quit.\n\r",
		 ch->fight_timer);
      return;
   }


   temp_num = get_totalscore (ch);
   if ((mount = ch->mount) != NULL)
      do_dismount (ch, "");

   if (IS_SET (ch->pcdata->tempflag, TEMP_VT100))
   {
      do_vt100 (ch, "");
   }
   do_rand_quote (ch);
   if (ch->pcdata->obj_vnum == 0)
   {
      char *temp = 0;

      do_qinfo (ch, exitmsg (temp, ch));
   }

   if (IS_SET(ch->flag2, AFF2_INARENA)) REMOVE_BIT(ch->flag2, AFF2_INARENA);

   if (ch->pcdata->in_progress)
      free_note (ch->pcdata->in_progress);

   /*
    * After extract_char the ch is no longer valid!
    */
   d = ch->desc;

   for (obj = object_list; obj != NULL; obj = obj->next)
   {
      if ((IS_SET (obj->quest2, QUEST2_OWNERSHIP) && !str_cmp(obj->questowner, ch->name)) && obj->carried_by != NULL && obj->carried_by != ch)
      {
         act ("$p jumps out of $n's hands.", obj->carried_by, obj, NULL, TO_ROOM);
	 obj_from_char (obj);
         obj_to_char (obj, ch);
	 continue;
      }
   }

   if (WizConfig->artifacts == ARTIFACTS_DONATION || WizConfig->artifacts == ARTIFACTS_RANDOM || WizConfig->artifacts == ARTIFACTS_HUNT)
   {
   CHAR_DATA *vch = NULL;
   if (WizConfig->artifacts == ARTIFACTS_HUNT)
   {
      for ( vch = char_list; vch != NULL; vch = vch->next )
      {
         if (IS_NPC(vch) && vch->pIndexData->vnum == 25) break;
      }
   }
   for (obj = ch->carrying; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;

      if (IS_SET (obj->quest, QUEST_ARTIFACT))
      {
         act ("$p jumps out of $n's hands.", obj->carried_by, obj, NULL, TO_ROOM);
	 obj_from_char (obj);
         if (WizConfig->artifacts == ARTIFACTS_DONATION)
           obj_to_room (obj, get_room_index(3010));
         else if (WizConfig->artifacts == ARTIFACTS_HUNT)
           obj_to_char (obj, vch);
         else
           obj_to_room (obj, get_empty_room());
         update_artitable (ch);
	 continue;
      }
   }
   }

   for (obj = ch->carrying; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;

      if (obj->item_type == ITEM_PIECE  || obj->item_type == ITEM_AQUEST || ((IS_SET (obj->quest2, QUEST2_OWNERSHIP) && str_cmp(obj->questowner, ch->name))))

/*|| obj->item_type == ITEM_STOKEN */

      {
	 act ("$p jumps out of $n's hands.", ch, obj, NULL, TO_ROOM);
	 obj_from_char (obj);
	 targetroom = number_range (1, 15000);
	 while (get_room_index (targetroom) == NULL)
	 {
	    targetroom = number_range (1, 15000);
	 }
	 obj_to_room (obj, get_room_index (targetroom));
	 continue;
      }
      if (obj->wear_loc == WEAR_NONE)
	 continue;
      if (!IS_NPC (ch)
	  &&
	  ((obj->
	    chobj != NULL && !IS_NPC (obj->chobj)
	    && obj->chobj->pcdata->obj_vnum != 0)
	   || obj->item_type == ITEM_KEY))
	 unequip_char (ch, obj);
   }
   save_char_obj (ch);
   update_artitable (ch);
   check_leaderboard (ch);
   adjust_hiscore ("pkill", ch, ch->pkill);
   adjust_hiscore ("pdeath", ch, ch->pdeath);
   adjust_hiscore ("mkill", ch, ch->mkill);
   adjust_hiscore ("mdeath", ch, ch->mdeath);
   adjust_hiscore ("awins", ch, ch->awins);
   adjust_hiscore ("alosses", ch, ch->alosses);
   adjust_hiscore ("exp", ch, ch->pcdata->score[SCORE_TOTAL_XP]);
   adjust_hiscore ("quest", ch, ch->pcdata->score[SCORE_QUEST]);
   adjust_hiscore ("tier", ch, ch->tier);
   adjust_hiscore ("hours", ch, get_hours (ch));

   if (IS_SET (ch->extra2, EXTRA2_INFECTED))
   {
      REMOVE_BIT (ch->extra2, EXTRA2_INFECTED);
      SET_BIT (ch->extra2, EXTRA2_VACCINATED);
      mal_info.parasite_timer = 1;
      act ("The Parasite has fled $n's body.", ch, NULL, NULL, TO_ROOM);
      stc ("The Parasite has fled your body.", ch);
      update_parasite ();
   }

     if (!IS_IMMORTAL (ch))
   {
   if (ch->pcdata->obj_vnum != 0)
      act ("$n slowly fades out of existance.", ch, NULL, NULL, TO_ROOM);
   else
      act ("$n has left the game.", ch, NULL, NULL, TO_ROOM);
   }
   if (d != NULL)
      close_socket2 (d, FALSE);

   if (ch->in_room != NULL)
      char_from_room (ch);
   char_to_room (ch, get_room_index (30002));

   sprintf (log_buf, "%s has quit.", ch->name);
   log_string (log_buf, ch);
 if (was_in != NULL)
    {
        if ( ch->desc != NULL && ch->desc->host != NULL && strlen( ch->desc->host ) > 1 )
            sprintf( log_buf, "%s@%s has left (%d)", ch->name, ch->desc->host, was_in->vnum );
        else
            sprintf( log_buf, "%s@%s has left (%d)", ch->name, ch->lasthost, was_in->vnum );
        wiznet (ch, WIZ_LOGINS, 11, log_buf);
    }

   if ((obj = ch->pcdata->chobj) != NULL)
   {
      obj->chobj = NULL;
      ch->pcdata->chobj = NULL;
      extract_obj (obj);
   }

   if (IS_SET (ch->more, MORE_TAG))
   {
      REMOVE_BIT (ch->more, MORE_TAG);
      sprintf (buf, "%s has quit the TAG Game, Tag Over", ch->name);
      do_taginfo (ch, buf);
   }
/*
   if (IS_SET (ch->act, PLR_AUTOBACKUP))
   {
      do_silentbackup (ch, "");
   }
*/

   if (ch->pcdata->chobj != NULL)
      extract_obj (ch->pcdata->chobj);
   extract_char (ch, TRUE, FALSE);
   return;
}
void do_quit2 (CHAR_DATA * ch, char *argument)
{
   DESCRIPTOR_DATA *d;

   char buf[MAX_STRING_LENGTH];
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;
   CHAR_DATA *mount;
   int temp_num;
   int targetroom;

   if (IS_NPC (ch))
      return;

   if (ch->position == POS_FIGHTING)
   {
      send_to_char ("No way! You are fighting.\n\r", ch);
      return;
   }

   if (IS_SET (ch->flag2, AFF2_CHALLENGED))
   {
      stc ("You cannot quit. You will have to decline first.\n\r", ch);
      return;
   }
   if (IS_SET (ch->flag2, AFF2_CHALLENGER))
   {
      stc ("You cannot quit, You have a challenge in progress.\n\r", ch);
      return;
   }
   if (IS_SET (ch->flag2, AFF2_INARENA))
   {
      stc ("You cannot quit while you're in the arena.\n\r", ch);
      return;
   }

   if (IS_SET (ch->war, JOINING))
   {
      stc ("You can't quit your joining a war!\n\r", ch);
      return;
   }
   if (IS_SET (ch->war, WARRING))
   {
      stc ("You can't quit while in a WAR!\n\r", ch);
      return;
   }
   if (ch->position < POS_SLEEPING)
   {
      send_to_char ("You're not DEAD yet.\n\r", ch);
      return;
   }
   if (auction_info.high_bidder == ch || auction_info.owner == ch)
   {
      send_to_char ("You still have a stake in the auction!\n\r", ch);
      return;
   }
   if (!IS_NPC (ch) && IS_EXTRA2 (ch, EXTRA2_NEUTRAL))
   {
      if (ch->in_room != NULL)
      {
	 REMOVE_BIT (ch->extra2, EXTRA2_NEUTRAL);
	 act ("$n stops making the time-out sign.", ch, NULL, NULL, TO_ROOM);
	 send_to_char
	    ("The peaceful harmony in the air gradually fades away to nothing.\n\r",
	     ch);
	 act ("The peaceful harmony in the air gradually fades away to nothing.", ch, NULL, NULL, TO_ROOM);
      }
   }
   if (!IS_NPC (ch) && IS_SET (ch->newbits, NEW_DARKNESS))
   {
      if (ch->in_room != NULL)
      {
         if (IS_CLASS (ch, CLASS_DROW) || WORN_ARTIFACT (ch, ARTI_HEART_OF_DARKNESS))
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
         if (IS_CLASS(ch, CLASS_FAE) && IS_KITH (ch, KITH_SLUAGH))
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
	 if (IS_CLASS (ch, CLASS_WEREWOLF))
	    REMOVE_BIT (ch->in_room->room_flags, ROOM_DARK);
	 REMOVE_BIT (ch->newbits, NEW_DARKNESS);
	 send_to_char
	    ("The darkness in the room gradually fades away to nothing.\n\r",
	     ch);
	 act ("The darkness in the room gradually fades away to nothing.", ch,
	      NULL, NULL, TO_ROOM);
      }
   }
/*
   if (!IS_IMMORTAL (ch) && ch->level > 1 && ch->pcdata->login_timer > 0
       && ch->desc != NULL)
   {
      sprintf (buf,
	       "You still have '#r%d#n' ticks left on your login timer before you can quit!\n\r",
	       ch->pcdata->login_timer);
      stc (buf, ch);
      return;
   }
*/
   if (!IS_IMMORTAL (ch) && (ch->fight_timer > 0) && ch->desc != NULL)
   {
      stcprintf (ch,
		 "You still have '#r%d#n' ticks left on your fight timer before you can quit.\n\r",
		 ch->fight_timer);
      return;
   }

/*   if  ( ( IS_SET( ch->extra, EXTRA_OSWITCH ) )  || ( ch->pcdata->obj_vnum > 0 ) )
   {
	stc( "You need to be in non-object form to log out.\n\r", ch );
	return;
   }
*/
   temp_num = get_totalscore (ch);
   if ((mount = ch->mount) != NULL)
      do_dismount (ch, "");
   if (ch->desc && ch->desc->out_compress)
   {
      compressEnd (ch->desc, TELOPT_COMPRESS2, TRUE);
      compressEnd (ch->desc, TELOPT_COMPRESS, TRUE);
   }
   if (IS_SET (ch->pcdata->tempflag, TEMP_VT100))
   {
      do_vt100 (ch, "");
   }

   do_rand_quote (ch);
   if (ch->pcdata->obj_vnum == 0)
   {
      char *temp = 0;

      do_qinfo (ch, exitmsg (temp, ch));
   }

   /*
    * After extract_char the ch is no longer valid!
    */
   d = ch->desc;

   for (obj = ch->carrying; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;

      if (obj->item_type == ITEM_PIECE /*|| obj->item_type == ITEM_STOKEN */ )
      {
	 act ("$p jumps out of $n's hands.", ch, obj, NULL, TO_ROOM);
	 obj_from_char (obj);
	 targetroom = number_range (1, 15000);
	 while (get_room_index (targetroom) == NULL)
	 {
	    targetroom = number_range (1, 15000);
	 }
	 obj_to_room (obj, get_room_index (targetroom));
	 continue;
      }
      if (obj->wear_loc == WEAR_NONE)
	 continue;
      if (!IS_NPC (ch)
	  &&
	  ((obj->
	    chobj != NULL && !IS_NPC (obj->chobj)
	    && obj->chobj->pcdata->obj_vnum != 0)
	   || obj->item_type == ITEM_KEY))
	 unequip_char (ch, obj);
   }
   save_char_obj (ch);
   update_artitable (ch);
   check_leaderboard (ch);

   if (IS_SET (ch->extra2, EXTRA2_INFECTED))
   {
      REMOVE_BIT (ch->extra2, EXTRA2_INFECTED);
      SET_BIT (ch->extra2, EXTRA2_VACCINATED);
      mal_info.parasite_timer = 1;
      act ("The Parasite has fled $n's body.", ch, NULL, NULL, TO_ROOM);
      stc ("The Parasite has fled your body.", ch);
      update_parasite ();
   }

   if (ch->pcdata->obj_vnum != 0)
      act ("$n slowly fades out of existance.", ch, NULL, NULL, TO_ROOM);
   else
      act ("$n has left the game.", ch, NULL, NULL, TO_ROOM);

   if (d != NULL)
      close_socket2 (d, FALSE);

   if (ch->in_room != NULL)
      char_from_room (ch);
   char_to_room (ch, get_room_index (30002));

   sprintf (log_buf, "%s has quit.", ch->name);
   log_string (log_buf, ch);
   wiznet (ch, WIZ_LOGINS, 11, log_buf);
   if ((obj = ch->pcdata->chobj) != NULL)
   {
      obj->chobj = NULL;
      ch->pcdata->chobj = NULL;
      extract_obj (obj);
   }

   if (IS_SET (ch->more, MORE_TAG))
   {
      REMOVE_BIT (ch->more, MORE_TAG);
      sprintf (buf, "%s has quit the TAG Game, Tag Over", ch->name);
      do_taginfo (ch, buf);
   }
   if (IS_SET (ch->act, PLR_AUTOBACKUP))
   {
      do_silentbackup (ch, "");
   }

   if (ch->pcdata->chobj != NULL)
      extract_obj (ch->pcdata->chobj);
   extract_char (ch, TRUE, FALSE);
   return;
}

void do_save (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch))
      return;
/*
    if (ch->registerred == 0)
    {
        stc("You #7MUST#n register before you can save.\n\r",ch);
        do_help(ch, "registration");
        return;
    }
*/

   if (!IS_IMMORTAL (ch) && ch->mkill < 5)
   {
      send_to_char ("You must kill at least 5 mobs before you can save.\n\r",
		    ch);
      return;
   }
   update_artitable (ch);
   check_leaderboard (ch);
   get_totalscore (ch);
   adjust_hiscore ("status", ch, ch->race);
   adjust_hiscore ("pkill", ch, ch->pkill);
   adjust_hiscore ("pdeath", ch, ch->pdeath);
   adjust_hiscore ("mkill", ch, ch->mkill);
   adjust_hiscore ("mdeath", ch, ch->mdeath);
   adjust_hiscore ("awins", ch, ch->awins);
   adjust_hiscore ("alosses", ch, ch->alosses);
   adjust_hiscore ("exp", ch, ch->pcdata->score[SCORE_TOTAL_XP]);
   adjust_hiscore ("quest", ch, ch->pcdata->score[SCORE_QUEST]);
   adjust_hiscore ("tier", ch, ch->tier);
   adjust_hiscore ("hours", ch, get_hours (ch));
   save_char_obj (ch);
   check_leaderboard (ch);
   check_ill_items (ch);
   //rem_ninja_mask (ch);
   send_to_char ("Saved.\n\r", ch);
   return;
}

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

   if (ch->mkill < 5 && !IS_IMMORTAL (ch))
      return;
   save_char_obj (ch);
   return;
}

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

   one_argument (argument, arg);

   if (arg[0] == '\0')
   {
      send_to_char ("Follow whom?\n\r", ch);
      return;
   }
   if ((victim = get_char_room (ch, arg)) == NULL)
   {
      send_to_char ("They aren't here.\n\r", ch);
      return;
   }
if (IS_SET (victim->extra2, NHELPER))
{
	stc("You are unable to follow Newbie Helpers!\n\r", ch);
        return;
}
   if (IS_AFFECTED (ch, AFF_CHARM) && ch->master != NULL)
   {
      act ("But you'd rather follow $N!", ch, NULL, ch->master, TO_CHAR);
      return;
   }

   if (victim == ch)
   {
      if (ch->master == NULL)
      {
	 send_to_char ("You already follow yourself.\n\r", ch);
	 return;
      }
      stop_follower (ch);
      return;
   }

   if (ch->master != NULL)
      stop_follower (ch);

   add_follower (ch, victim);
   return;
}

void add_follower (CHAR_DATA * ch, CHAR_DATA * master)
{
   if (ch->master != NULL)
   {
      bug ("Add_follower: non-null master.", 0);
      return;
   }

   ch->master = master;
   ch->leader = NULL;

   if (can_see (master, ch))
      act ("$n now follows you.", ch, NULL, master, TO_VICT);

   act ("You now follow $N.", ch, NULL, master, TO_CHAR);

   return;
}

void stop_follower (CHAR_DATA * ch)
{
   if (ch->master == NULL)
   {
      bug ("Stop_follower: null master.", 0);
      return;
   }

   if (IS_AFFECTED (ch, AFF_CHARM))
   {
      REMOVE_BIT (ch->affected_by, AFF_CHARM);
      affect_strip (ch, gsn_charm_person);
   }
   if (!IS_NPC (ch->master) && ch->master->pcdata->followers > 0
       && IS_NPC (ch))
      ch->master->pcdata->followers--;

   if (can_see (ch->master, ch))
      act ("$n stops following you.", ch, NULL, ch->master, TO_VICT);
   act ("You stop following $N.", ch, NULL, ch->master, TO_CHAR);

   ch->master = NULL;
   ch->leader = NULL;
   return;
}

void die_follower (CHAR_DATA * ch)
{
   CHAR_DATA *fch;

   if (ch->master != NULL)
      stop_follower (ch);

   ch->leader = NULL;

   for (fch = char_list; fch != NULL; fch = fch->next)
   {
      if (fch->master == ch)
	 stop_follower (fch);
      if (fch->leader == ch)
	 fch->leader = fch;

   }

   return;
}

void do_order (CHAR_DATA * ch, char *argument)
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   CHAR_DATA *och;
   CHAR_DATA *och_next;
   bool found;
   bool fAll;

   argument = one_argument (argument, arg);

   if (arg[0] == '\0' || argument[0] == '\0')
   {
      send_to_char ("Order whom to do what?\n\r", ch);
      return;
   }

   if (IS_AFFECTED (ch, AFF_CHARM))
   {
      send_to_char ("You feel like taking, not giving, orders.\n\r", ch);
      return;
   }

   if (!str_cmp (arg, "all"))
   {
      if (is_in
	  (argument,
	   "|quit*rem*drop*gift*claim*consent*propose*accept*vampi*ma *maj*reca*/*ha *hav*train*token*arenaagree*arena*challege*decline*k*kill*trai *auction*auc *"))
      {
	 send_to_char ("You cannot make that sort of order.\n\r", ch);
	 return;
      }
      fAll = TRUE;
      victim = NULL;
   }
   else
   {
      fAll = FALSE;
      if ((victim = get_char_room (ch, arg)) == NULL)
      {
	 send_to_char ("They aren't here.\n\r", ch);
	 return;
      }

      if (victim == ch)
      {
	 send_to_char ("Aye aye, right away!\n\r", ch);
	 return;
      }
      if (is_in
	  (argument,
	   "|quit*rem*drop*gift*claim*consent*propose*accept*vampi*ma *maj*reca*/*ha *hav*train*token*challenge*decline*arenaagree*kill*k*trai *auction*auc *delete*"))
      {
	 send_to_char ("You cannot make that sort of order.\n\r", ch);
	 return;
      }
      if (!IS_NPC (victim) && get_hours (victim) < 10)
      {
	 stc ("Not on a newbie!\n\r", ch);
	 return;
      }
      if ((!IS_AFFECTED (victim, AFF_CHARM) || victim->master != ch)
	  && !(IS_CLASS (ch, CLASS_VAMPIRE)
	       && IS_CLASS (victim, CLASS_VAMPIRE)))
      {
	 send_to_char ("Do it yourself!\n\r", ch);
	 return;
      }

      if (IS_CLASS (ch, CLASS_VAMPIRE) && IS_CLASS (victim, CLASS_VAMPIRE)
	  && ((ch->pcdata->stats[UNI_GEN] != 2)
	      || str_cmp (ch->clan, victim->clan)))
      {
	 act ("$N ignores your order.", ch, NULL, victim, TO_CHAR);
	 act ("You ignore $n's order.", ch, NULL, victim, TO_VICT);
	 return;
      }

   }

   found = FALSE;
   for (och = ch->in_room->people; och != NULL; och = och_next)
   {
      och_next = och->next_in_room;
      if (och == ch)
	 continue;

      if ((IS_AFFECTED (och, AFF_CHARM) && och->master == ch
	   && (fAll || och == victim)))
      {
	 found = TRUE;
	 act ("$n orders you to '$t'.", ch, argument, och, TO_VICT);
         if (!IS_NPC(och)) och->pcdata->evilchat = ch;
	 interpret (och, argument);
      }
      else if (!IS_NPC (ch) && !IS_NPC (och) && (fAll || och == victim)
	       && IS_CLASS (ch, CLASS_VAMPIRE)
	       && IS_CLASS (och, CLASS_VAMPIRE)
	       && ch->pcdata->stats[UNI_GEN] < och->pcdata->stats[UNI_GEN]
	       && !str_cmp (ch->clan, och->clan))
      {
	 found = TRUE;
	 act ("$n orders you to '$t'.", ch, argument, och, TO_VICT);
         if (!IS_NPC(och)) och->pcdata->evilchat = ch;
	 interpret (och, argument);
      }
   }

   if (found)
   {
      send_to_char ("Ok.\n\r", ch);
      WAIT_STATE (ch, 12);
   }
   else
      send_to_char ("You have no followers here.\n\r", ch);
   return;
}

void do_group (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   char hit_str[MAX_INPUT_LENGTH];
   char mana_str[MAX_INPUT_LENGTH];
   char move_str[MAX_INPUT_LENGTH];
   char mhit_str[MAX_INPUT_LENGTH];
   char mmana_str[MAX_INPUT_LENGTH];
   char mmove_str[MAX_INPUT_LENGTH];
   char exp_str[MAX_INPUT_LENGTH];

   one_argument (argument, arg);

   if (IS_NPC(ch)) return;

   if (!IS_NPC (ch) && get_trust (ch) == LEVEL_BUILDER)
   {
      send_to_char ("Perhaps you should just stick to building?\n\r", ch);
      return;
   }

   if (arg[0] == '\0')
   {
      CHAR_DATA *gch;
      CHAR_DATA *leader;

      leader = (ch->leader != NULL) ? ch->leader : ch;
      sprintf (buf, "#C-=[#w%s's Group#C]=-#n", PERS2 (leader, ch));
      cent_to_char (buf, ch);

      for (gch = char_list; gch != NULL; gch = gch->next)
      {
	 sprintf (hit_str, "%d", gch->hit);
	 COL_SCALE (hit_str, ch, gch->hit, gch->max_hit);
	 sprintf (mana_str, "%1d", gch->mana);
	 COL_SCALE (mana_str, ch, gch->mana, gch->max_mana);
	 sprintf (move_str, "%d", gch->move);
	 COL_SCALE (move_str, ch, gch->move, gch->max_move);
         sprintf (exp_str, "%lli", gch->exp);
	 COL_SCALE (exp_str, gch, gch->exp, 1000000);
	 sprintf (mhit_str, "%d", gch->max_hit);
	 ADD_COLOUR (ch, mhit_str, L_CYAN);
	 sprintf (mmana_str, "%d", gch->max_mana);
	 ADD_COLOUR (ch, mmana_str, L_CYAN);
	 sprintf (mmove_str, "%d", gch->max_move);
	 ADD_COLOUR (ch, mmove_str, L_CYAN);
	 if (is_same_group (gch, ch))
	 {
	    sprintf (buf, "#C[#w%s#C]", capitalize (PERS2 (gch, ch)));
	    cent_to_char (buf, ch);
	    sprintf (buf,
		     "#C[#w%s/%s #whp#C] [#w%s/%s #wmana#C] [#w%s/%s #wmove#C] [#w%s #wExp#C]",
		     hit_str, mhit_str, mana_str, mmana_str, move_str,
		     mmove_str, exp_str);
	    cent_to_char (buf, ch);
	 }
      }
      return;
   }

   if (ch->master != NULL || (ch->leader != NULL && ch->leader != ch))
   {
      send_to_char ("But you are following someone else!\n\r", ch);
      return;
   }
   if( !str_cmp( argument, "disband" ) )
    {
        CHAR_DATA *gch;
        int count = 0;
            
      if( ch->leader || ch->master )
        {
            send_to_char( "You cannot disband a group if you're following someone.\n\r", ch );
            return;
        }   
        
      for( gch = char_list; gch != NULL; gch = gch->next )  
        {
         if( ( gch->master == ch || is_same_group( ch, gch ) ) && ( ch != gch ) )
            {
                gch->leader = NULL;
                gch->master = NULL;
                count++;
                send_to_char( "Your group is disbanded.\n\r", gch );
            }
        }
      if( count == 0 )
            send_to_char( "You have no group members to disband.\n\r", ch );
        else
            send_to_char( "You disband your group.\n\r", ch );
        return;
    }
         
   if( !str_cmp( argument, "all" ) )
    {
        CHAR_DATA *rch;
        int count = 0;
   
      for( rch = ch->in_room->people; rch; rch = rch->next_in_room )
        {
         if( ch != rch && !IS_NPC( rch ) && can_see( ch, rch ) && rch->master == ch
               && !ch->master && !ch->leader && !is_same_group( rch, ch ) )
            {
		if ( ALLOW_N00BS_TO_GROUP == FALSE )
		{
 			if ( (get_hours (rch) < N00B_NO_GROUP_HOURS ) && (get_hours (ch) >= N00B_NO_GROUP_HOURS ) )
			    continue;
 			if ( (get_hours (ch) < N00B_NO_GROUP_HOURS ) && (get_hours (rch) >= N00B_NO_GROUP_HOURS) )
			    continue;
		}
                rch->leader = ch;
                count++;
            }
        }
      if( count == 0 )
            send_to_char( "You have no eligible group members.\n\r", ch );
        else
        {
            act( "$n groups $s followers.", ch, NULL, NULL, TO_ROOM );
            send_to_char( "You group your followers.\n\r", ch );
        }
        return;
    }

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

   if (IS_NPC (victim))
   {
      send_to_char ("Nope\n\r", ch);
      return;
   }

   if (!IS_NPC (ch) && get_trust (ch) == LEVEL_BUILDER)
   {
      send_to_char ("Perhaps you should just let them build?\n\r", ch);
      return;
   }

   if (victim->master != ch && ch != victim)
   {
      act ("$N isn't following you.", ch, NULL, victim, TO_CHAR);
      return;
   }

   if (is_same_group (victim, ch) && ch != victim)
   {
      victim->leader = NULL;
      act ("$n removes $N from $s group.", ch, NULL, victim, TO_NOTVICT);
      act ("$n removes you from $s group.", ch, NULL, victim, TO_VICT);
      act ("You remove $N from your group.", ch, NULL, victim, TO_CHAR);
      return;
   }

   if ( ALLOW_N00BS_TO_GROUP == FALSE )
   {
	   if ( ( get_hours (victim) < N00B_NO_GROUP_HOURS ) &&  (get_hours (ch) >= N00B_NO_GROUP_HOURS ) )
	   {
		send_to_char( "They are a newbie.  You are not.  Go kill something instead.\n\r", ch );
		send_to_char( "You are a newbie, they are not.  They have better things to do.\n\r", victim );
		return;
   	}

   	if ( ( get_hours (victim) >= N00B_NO_GROUP_HOURS ) &&  (get_hours (ch) < N00B_NO_GROUP_HOURS ) )
   	{
		send_to_char( "They are a newbie.  You are not.  Go kill something instead.\n\r", victim );
		send_to_char( "You are a newbie, they are not.  They have better things to do.\n\r", ch );
		return;
   	}
   }
   victim->leader = ch;
   act ("$N joins $n's group.", ch, NULL, victim, TO_NOTVICT);
   act ("You join $n's group.", ch, NULL, victim, TO_VICT);
   act ("$N joins your group.", ch, NULL, victim, TO_CHAR);
   return;
}

/*
 * 'Split' originally by Gnort, God of Chaos.
 */
void do_split (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *gch;
   int members;
   int amount;
   int share;
   int extra;

   one_argument (argument, arg);

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

   amount = atoi (arg);

   if (amount < 0)
   {
      send_to_char ("Your group wouldn't like that.\n\r", ch);
      return;
   }

   if (amount == 0)
   {
      send_to_char ("You hand out zero coins, but no one notices.\n\r", ch);
      return;
   }

   if (ch->gold < amount)
   {
      send_to_char ("You don't have that much gold.\n\r", ch);
      return;
   }

   members = 0;
   for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room)
   {
      if (is_same_group (gch, ch))
	 members++;
   }

   if (members < 2)
   {
      send_to_char ("Just keep it all.\n\r", ch);
      return;
   }

   share = amount / members;
   extra = amount % members;

   if (share == 0)
   {
      send_to_char ("Don't even bother, cheapskate.\n\r", ch);
      return;
   }

   ch->gold -= amount;
   ch->gold += share + extra;

   sprintf (buf, "You split %d gold coins.  Your share is %d gold coins.\n\r",
	    amount, share + extra);
   send_to_char (buf, ch);

   sprintf (buf, "$n splits %d gold coins.  Your share is %d gold coins.",
	    amount, share);

   for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room)
   {
      if (gch != ch && is_same_group (gch, ch))
      {
	 act (buf, ch, NULL, gch, TO_VICT);
	 gch->gold += share;
      }
   }

   return;
}

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

   if (argument[0] == '\0')
   {
      send_to_char ("Tell your group what?\n\r", ch);
      return;
   }
  if (IS_SET (ch->act, PLR_SILENCE))
   {
      sprintf (buf, "You can't gtell because you are silenced.\n\r");
      send_to_char (buf, ch);
      return;
   }
   if (IS_SET (ch->act, PLR_NO_TELL))
   {
      send_to_char ("Your message didn't get through!\n\r", ch);
      return;
   }

   /*
    * Note use of send_to_char, so gtell works on sleepers.
    */
   sprintf (buf, "#r%s #wtells the group '#y%s#w'.#n\n\r", ch->name,
	    argument);
   for (gch = char_list; gch != NULL; gch = gch->next)
   {
      if (is_same_group (gch, ch))
	 send_to_char (buf, gch);
   }

   return;
}

/*
 * It is very important that this be an equivalence relation:
 * (1) A ~ A
 * (2) if A ~ B then B ~ A
 * (3) if A ~ B  and B ~ C, then A ~ C
 */
bool is_same_group (CHAR_DATA * ach, CHAR_DATA * bch)
{
   if (ach->leader != NULL)
      ach = ach->leader;
   if (bch->leader != NULL)
      bch = bch->leader;
   return ach == bch;
}

void do_changelight (CHAR_DATA * ch, char *argument)
{
   if (IS_SET (ch->in_room->room_flags, ROOM_DARK))
   {
      REMOVE_BIT (ch->in_room->room_flags, ROOM_DARK);
      act ("The room is suddenly filled with light!", ch, NULL, NULL,
	   TO_CHAR);
      act ("The room is suddenly filled with light!", ch, NULL, NULL,
	   TO_ROOM);
      return;
   }
   SET_BIT (ch->in_room->room_flags, ROOM_DARK);
   act ("The lights in the room suddenly go out!", ch, NULL, NULL, TO_CHAR);
   act ("The lights in the room suddenly go out!", ch, NULL, NULL, TO_ROOM);
   return;
}

void open_lift (CHAR_DATA * ch)
{
   ROOM_INDEX_DATA *location;
   int in_room;

   in_room = ch->in_room->vnum;
   location = get_room_index (in_room);

   if (is_open (ch))
      return;

   act ("The doors open.", ch, NULL, NULL, TO_CHAR);
   act ("The doors open.", ch, NULL, NULL, TO_ROOM);
   move_door (ch);
   if (is_open (ch))
      act ("The doors close.", ch, NULL, NULL, TO_ROOM);
   if (!same_floor (ch, in_room))
      act ("The lift judders suddenly.", ch, NULL, NULL, TO_ROOM);
   if (is_open (ch))
      act ("The doors open.", ch, NULL, NULL, TO_ROOM);
   move_door (ch);
   open_door (ch, FALSE);
   char_from_room (ch);
   char_to_room (ch, location);
   open_door (ch, TRUE);
   move_door (ch);
   open_door (ch, TRUE);
   thru_door (ch, in_room);
   char_from_room (ch);
   char_to_room (ch, location);
   return;
}

void close_lift (CHAR_DATA * ch)
{
   ROOM_INDEX_DATA *location;
   int in_room;

   in_room = ch->in_room->vnum;
   location = get_room_index (in_room);

   if (!is_open (ch))
      return;
   act ("The doors close.", ch, NULL, NULL, TO_CHAR);
   act ("The doors close.", ch, NULL, NULL, TO_ROOM);
   open_door (ch, FALSE);
   move_door (ch);
   open_door (ch, FALSE);
   char_from_room (ch);
   char_to_room (ch, location);
   return;
}

void move_lift (CHAR_DATA * ch, int to_room)
{
   ROOM_INDEX_DATA *location;
   int in_room;

   in_room = ch->in_room->vnum;
   location = get_room_index (in_room);

   if (is_open (ch))
      act ("The doors close.", ch, NULL, NULL, TO_CHAR);
   if (is_open (ch))
      act ("The doors close.", ch, NULL, NULL, TO_ROOM);
   if (!same_floor (ch, to_room))
      act ("The lift judders suddenly.", ch, NULL, NULL, TO_CHAR);
   if (!same_floor (ch, to_room))
      act ("The lift judders suddenly.", ch, NULL, NULL, TO_ROOM);
   move_door (ch);
   open_door (ch, FALSE);
   char_from_room (ch);
   char_to_room (ch, location);
   open_door (ch, FALSE);
   thru_door (ch, to_room);
   return;
}

bool same_floor (CHAR_DATA * ch, int cmp_room)
{
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;

   for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;
      if (obj->item_type != ITEM_PORTAL)
	 continue;
      if (obj->pIndexData->vnum == 30001)
	 continue;
      if (obj->value[0] == cmp_room)
	 return TRUE;
      else
	 return FALSE;
   }
   return FALSE;
}

bool is_open (CHAR_DATA * ch)
{
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;

   for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;
      if (obj->item_type != ITEM_PORTAL)
	 continue;
      if (obj->pIndexData->vnum == 30001)
	 continue;
      if (obj->value[2] == 0)
	 return TRUE;
      else
	 return FALSE;
   }
   return FALSE;
}

void move_door (CHAR_DATA * ch)
{
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;
   ROOM_INDEX_DATA *pRoomIndex;

   for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;
      if (obj->item_type != ITEM_PORTAL)
	 continue;
      if (obj->pIndexData->vnum == 30001)
	 continue;
      pRoomIndex = get_room_index (obj->value[0]);
      char_from_room (ch);
      char_to_room (ch, pRoomIndex);
      return;
   }
   return;
}

void thru_door (CHAR_DATA * ch, int doorexit)
{
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;

   for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;
      if (obj->item_type != ITEM_PORTAL)
	 continue;
      if (obj->pIndexData->vnum == 30001)
	 continue;
      obj->value[0] = doorexit;
      return;
   }
   return;
}

void open_door (CHAR_DATA * ch, bool be_open)
{
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;

   for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
   {
      obj_next = obj->next_content;
      if (obj->item_type != ITEM_PORTAL)
	 continue;
      if (obj->pIndexData->vnum == 30001)
	 continue;
      if (obj->value[2] == 0 && !be_open)
	 obj->value[2] = 3;
      else if (obj->value[2] == 3 && be_open)
	 obj->value[2] = 0;
      return;
   }
   return;
}

void do_speak (CHAR_DATA * ch, char *argument)
{
   char arg[MAX_INPUT_LENGTH];
   char buf[MAX_INPUT_LENGTH];

   argument = one_argument (argument, arg);

   if (IS_NPC (ch))
      return;

   if (arg[0] == '\0')
   {
      if (IS_SPEAKING (ch, LANG_DARK))
	 send_to_char ("You are speaking the Dark tongue.\n\r", ch);
      else if (IS_SPEAKING (ch, DIA_OLDE))
	 send_to_char ("You are speaking Olde Worlde.\n\r", ch);
      else if (IS_SPEAKING (ch, DIA_BAD))
	 send_to_char ("You are speaking very badly.\n\r", ch);
      else
	 send_to_char ("You are speaking the common language.\n\r", ch);
      strcpy (buf, "You can speak the following languages:");
      strcat (buf, " Common Olde Bad");
      if (CAN_SPEAK (ch, LANG_DARK))
	 strcat (buf, " Dark");
      strcat (buf, ".\n\r");
      send_to_char (buf, ch);
      return;
   }

   if (!str_cmp (arg, "dark"))
   {
      if (!CAN_SPEAK (ch, LANG_DARK))
      {
	 send_to_char ("You cannot speak the Dark tongue.\n\r", ch);
	 return;
      }
      if (IS_SPEAKING (ch, LANG_DARK))
      {
	 send_to_char ("But you are already speaking the Dark tongue!\n\r",
		       ch);
	 return;
      }
      ch->pcdata->language[0] = LANG_DARK;
      send_to_char ("Ok.\n\r", ch);
      return;
   }
   else if (!str_cmp (arg, "common"))
   {
      if (ch->pcdata->language[0] == LANG_COMMON)
      {
	 send_to_char ("But you are already speaking the common tongue!\n\r",
		       ch);
	 return;
      }
      ch->pcdata->language[0] = LANG_COMMON;
      send_to_char ("Ok.\n\r", ch);
      return;
   }
   else if (!str_cmp (arg, "olde"))
   {
      if (ch->pcdata->language[0] == DIA_OLDE)
      {
	 send_to_char ("But you are already speaking Olde Worlde!\n\r", ch);
	 return;
      }
      ch->pcdata->language[0] = DIA_OLDE;
      send_to_char ("Ok.\n\r", ch);
      return;
   }
   else if (!str_cmp (arg, "bad"))
   {
      if (ch->pcdata->language[0] == DIA_BAD)
      {
	 send_to_char ("But you are already speaking badly!\n\r", ch);
	 return;
      }
      ch->pcdata->language[0] = DIA_BAD;
      send_to_char ("Ok.\n\r", ch);
      return;
   }
   else
   {
      strcpy (buf, "You can speak the following languages:");
      strcat (buf, " Common Olde Bad");
      if (CAN_SPEAK (ch, LANG_DARK))
	 strcat (buf, " Dark");
      strcat (buf, ".\n\r");
      send_to_char (buf, ch);
      return;
   }

   return;
}
char *badlang( CHAR_DATA *ch, char *argument )
{
    char buf  [MAX_STRING_LENGTH];
    char *pName;
    int iSyl;
    int length;
        
    struct spk_type
    {
        char *  old;
        char *  new;
    };
        
    static const struct spk_type spk_table[] =
    {
        { " ",          " "             },
        { "my name is", "i calls meself"},
        { "are not",    "aint"          },
        { "have",       "'av"           },
        { "my",         "me"            },
        { "hello",      "oy"            },
        { "hi ",        "oy "           },
        { "i am",       "im"            },
        { "it is",      "tis"           },
        { "the ",       "@"             },
        { " the",       " da"           },
        { "thank",      "fank"          },
        { "that",       "dat"           },
        { "with",       "wiv"           },
        { "they",       "day"           },
        { "this",       "dis"           },
        { "then",       "den"           },
        { "there",      "ver"           },
        { "their",      "ver"           },
        { "thing",      "fing"          },
        { "think",      "fink"          },
        { "was",        "woz"           },
        { "would",      "wud"           },
        { "what ",      "^"             },
        { "what",       "wot"           },
        { "where",      "weer"          },
        { "when",       "wen"           },
        { "are",        "is"            },
        { "you",        "ya"            },
        { "your ",      "&"             },
        { "your",       "yer"           },
        { "dead",       "ded"           },
        { "kill",       "stomp"         },
        { "food",       "nosh"          },
        { "blood",      "blud"          },
        { "vampire",    "sucker"        },
        { "kindred",    "suckers"       },
       { "fire",       "hot"           },
        { "dwarf",      "stunty"        },
        { "dwarves",    "stunties"      },
        { "goblin",     "gobbo"         },
        { "death",      "def"           },
        { "immune",     "mune"          },
        { "immunit",    "munit"         },
        { "childer",    "nippers"       },
        { "childe",     "nipper"        },
        { "child",      "nipper"        },
        { "tradition",  "wassname"      },
        { "generation", "batch"         },
        { "founded",    "made"          },
        { "sired",      "nipped"        },
        { "sire",       "dad"           },
        { "lineage",    "istory"        },
        { "road",       "path"          },
        { "recognize",  "dats"          },
        { "recognize",  "dats"          },
        { "decapitate", "headchop"      },
        { "decap",      "chop"          },
        { "recites",    "sez"           },
        { "recite",     "sez"           },
        { "a", "a" }, { "b", "b" }, { "c", "c" }, { "d", "d" },
        { "e", "e" }, { "f", "f" }, { "g", "g" }, { "h", "h" },
        { "i", "i" }, { "j", "j" }, { "k", "k" }, { "l", "l" },
        { "m", "m" }, { "n", "n" }, { "o", "o" }, { "p", "p" },
        { "q", "q" }, { "r", "r" }, { "s", "s" }, { "t", "t" },
        { "u", "u" }, { "v", "v" }, { "w", "w" }, { "x", "x" },
        { "y", "y" }, { "z", "z" }, { ",", "," }, { ".", "." },
        { ";", ";" }, { ":", ":" }, { "(", "(" }, { ")", ")" },
        { ")", ")" }, { "-", "-" }, { "!", "!" }, { "?", "?" },
        { "1", "1" }, { "2", "2" }, { "3", "3" }, { "4", "4" },
        { "5", "5" }, { "6", "6" }, { "7", "7" }, { "8", "8" },
        { "9", "9" }, { "0", "0" }, { "%", "%" }, { "'", "'" },
        { "#", "#" }, {  "",  "" }
    };
    buf[0]      = '\0';
        
    if ( argument[0] == '\0' ) return argument;
        
    for ( pName = argument; *pName != '\0'; pName += length )
    {
        for ( iSyl = 0; (length = strlen(spk_table[iSyl].old)) != 0; iSyl++ )
        { 
            if ( !str_prefix( spk_table[iSyl].old, pName ) )   
            {
                if (!str_cmp(spk_table[iSyl].new,",") ||
                    !str_cmp(spk_table[iSyl].new,"!") ||
                    !str_cmp(spk_table[iSyl].new,"?"))
                {
                    if (strlen(buf) < MAX_INPUT_LENGTH)
                    switch (number_range(1,20))
                    {
                        default: break;
                        case 1: strcat( buf, ", ya stupid fucker" ); break;
                        case 2: strcat( buf, ", ya idiot" ); break;
                        case 3: strcat( buf, ", ya damn fool" ); break;
                        case 4: strcat( buf, ", ya fick mug" ); break;
                        case 5: strcat( buf, ", ya fuckin' jerk" ); break;
                        case 6: strcat( buf, ", asshole" ); break;
                        case 7: strcat( buf, ", dickwipe" ); break;
                    }
                }
                else if (!str_cmp(spk_table[iSyl].new,"@"))
                {
                   if (strlen(buf) >= MAX_INPUT_LENGTH)
                        strcat( buf, "da " );
                    else switch (number_range(1,10))
                    {
                        default: strcat( buf, "da " ); break;
                        case 1: strcat( buf, "da bloody " ); break;
                        case 2: strcat( buf, "da fuckin' " ); break;
                        case 3: strcat( buf, "da goddamn " ); break;
                        case 4: strcat( buf, "da flippin' " ); break;
                        case 5: strcat( buf, "da stupid " ); break;
                        case 6: strcat( buf, "da stinkin' " ); break;
                    }
                    break;
                }
                else if (!str_cmp(spk_table[iSyl].new,"^"))
                {
                    if (strlen(buf) >= MAX_INPUT_LENGTH)
                        strcat( buf, "wot " );
                    else switch (number_range(1,10))
                    {
                        default: strcat( buf, "wot " ); break;
                        case 1: strcat( buf, "wot da fuck " ); break;
                       case 2: strcat( buf, "wot, i sez, " ); break;
                        case 3: strcat( buf, "wot da hell " ); break;
                        case 4: strcat( buf, "wot da flip " ); break;
                    }
                    break;
                }
                else if (!str_cmp(spk_table[iSyl].new,"&"))
                {
                    if (strlen(buf) >= MAX_INPUT_LENGTH)
                        strcat( buf, "yer " );
                    else switch (number_range(1,10))
                    {
                        default: strcat( buf, "yer " ); break;
                        case 1: strcat( buf, "yer bloody " ); break;
                        case 2: strcat( buf, "yer fuckin' " ); break;
                        case 3: strcat( buf, "yer damn " ); break;
                        case 4: strcat( buf, "yer flippin' " ); break;
                        case 5: strcat( buf, "yer stupid " ); break;
                        case 6: strcat( buf, "yer stinkin' " ); break;
                    }
                    break;
                }
                if (pName[0] == UPPER(pName[0]))
                {
                    char uTable[MSL];
                    uTable[0] = '\0';
                    strcat(uTable, spk_table[iSyl].new);
                    uTable[0] = UPPER(uTable[0]);
                    strcat(buf, uTable);
                }
                else strcat( buf, spk_table[iSyl].new );
                break;
            }
        }
                        
        if ( length == 0 )
            length = 1;
    }
                        
    argument[0] = '\0';
    strcpy(argument,buf);
    return argument; 
}
char *oldelang( CHAR_DATA *ch, char *argument )
{
    char buf  [MAX_STRING_LENGTH];
    char *pName;
    int iSyl;
    int length;
        
    struct spk_type
    {
        char *  old;
        char *  new;
    };
        
    static const struct spk_type spk_table[] =
    {
        { " ",          " "             },
        { "have",       "hath"          },
        { "hello",      "hail"          },
        { "hi ",        "hail "         },
        { " hi",        " hail"         },
        { "are",        "art"           },
        { "your",       "thy"           },
        { "you",        "thou"          },
        { "i think",    "methinks"      },
        { "do ",        "doth "         },
        { " do",        " doth"         },
        { "it was",     "twas"          },
        { "before",     "ere"           },
        { "a", "a" }, { "b", "b" }, { "c", "c" }, { "d", "d" },
        { "e", "e" }, { "f", "f" }, { "g", "g" }, { "h", "h" },
        { "i", "i" }, { "j", "j" }, { "k", "k" }, { "l", "l" },
        { "m", "m" }, { "n", "n" }, { "o", "o" }, { "p", "p" },
        { "q", "q" }, { "r", "r" }, { "s", "s" }, { "t", "t" },
        { "u", "u" }, { "v", "v" }, { "w", "w" }, { "x", "x" },
        { "y", "y" }, { "z", "z" }, { ",", "," }, { ".", "." },
        { ";", ";" }, { ":", ":" }, { "(", "(" }, { ")", ")" },
        { ")", ")" }, { "-", "-" }, { "!", "!" }, { "?", "?" },
        { "1", "1" }, { "2", "2" }, { "3", "3" }, { "4", "4" },
        { "5", "5" }, { "6", "6" }, { "7", "7" }, { "8", "8" },
        { "9", "9" }, { "0", "0" }, { "%", "%" }, { "'", "'" },
        { "#", "#" }, {  "",  "" }
    };
    buf[0]      = '\0';
    if ( argument[0] == '\0' ) return argument;
        
    for ( pName = str_dup(argument); *pName != '\0'; pName += length )
    {
        for ( iSyl = 0; (length = strlen(spk_table[iSyl].old)) != 0; iSyl++ )
        { 
            if ( !str_prefix( spk_table[iSyl].old, pName ) )   
            {
                if (pName[0] == UPPER(pName[0]))
                {
                    char uTable[MSL];
                    uTable[0] = '\0';
                    strcat(uTable, spk_table[iSyl].new);
                    uTable[0] = UPPER(uTable[0]);
                    strcat(buf, uTable);
                }
                else strcat( buf, spk_table[iSyl].new );
                break;
            }
        }
    
        if ( length == 0 )
            length = 1;
    }   
    
    argument[0] = '\0';
    strcpy(argument,buf);
          
    return argument;
}

char *random_letter ()
{
   char *letter;
   int num;

   num = number_range (1, 26);

   switch (num)
   {
   case 1:
      letter = "a";
      break;
   case 2:
      letter = "b";
      break;
   case 3:
      letter = "c";
      break;
   case 4:
      letter = "d";
      break;
   case 5:
      letter = "e";
      break;
   case 6:
      letter = "f";
      break;
   case 7:
      letter = "g";
      break;
   case 8:
      letter = "h";
      break;
   case 9:
      letter = "i";
      break;
   case 10:
      letter = "j";
      break;
   case 11:
      letter = "k";
      break;
   case 12:
      letter = "l";
      break;
   case 13:
      letter = "m";
      break;
   case 14:
      letter = "n";
      break;
   case 15:
      letter = "o";
      break;
   case 16:
      letter = "p";
      break;
   case 17:
      letter = "q";
      break;
   case 18:
      letter = "r";
      break;
   case 19:
      letter = "s";
      break;
   case 20:
      letter = "t";
      break;
   case 21:
      letter = "u";
      break;
   case 22:
      letter = "v";
      break;
   case 23:
      letter = "w";
      break;
   case 24:
      letter = "x";
      break;
   case 25:
      letter = "y";
      break;
   case 26:
      letter = "z";
      break;
   default:
      letter = "?";
      break;
   }

   return letter;
}

char *darktongue (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char arg[MAX_STRING_LENGTH];
   int length;

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;

   for (argument = one_argument (argument, arg);;)
   {
      for (length = strlen (arg); length != 0; length--)
	 strcat (buf, random_letter ());
      argument = one_argument (argument, arg);
      if (arg[0] == '\0')
	 break;
      strcat (buf, " ");
   }

   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);

   return argument;
}

char *drunktalk (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char *pName;
   int iSyl;
   int length;
   int loop;

   struct spk_type
   {
      char *old;
      char *new;
   };

   static const struct spk_type spk_table[] = {
       { " ",          " "             },
        { "is",         "ish"           },
        { "a", "a" }, { "b", "b" }, { "c", "c" }, { "d", "d" },
        { "e", "e" }, { "f", "f" }, { "g", "g" }, { "h", "h" },
        { "i", "i" }, { "j", "j" }, { "k", "k" }, { "l", "l" },
        { "m", "m" }, { "n", "n" }, { "o", "o" }, { "p", "p" },
        { "q", "q" }, { "r", "r" }, { "s", "s" }, { "t", "t" },
        { "u", "u" }, { "v", "v" }, { "w", "w" }, { "x", "x" },
        { "y", "y" }, { "z", "z" }, { ",", "," }, { ".", "." },
        { ";", ";" }, { ":", ":" }, { "(", "(" }, { ")", ")" },
        { ")", ")" }, { "-", "-" }, { "!", "!" }, { "?", "?" },
        { "1", "1" }, { "2", "2" }, { "3", "3" }, { "4", "4" },
        { "5", "5" }, { "6", "6" }, { "7", "7" }, { "8", "8" },
        { "9", "9" }, { "0", "0" }, { "%", "%" }, { "'", "'" },
        { "#", "#" }, {  "",  "" }
   };

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;

 for ( pName = str_dup(argument); *pName != '\0'; pName += length )
    {
        for ( iSyl = 0; (length = strlen(spk_table[iSyl].old)) != 0; iSyl++ )
        {
            if ( !str_prefix( spk_table[iSyl].old, pName ) )
            {
                if (pName[0] == UPPER(pName[0]))
                {
                    char uTable[MSL];
                    uTable[0] = '\0';
                    strcat(uTable, spk_table[iSyl].new);
                    uTable[0] = UPPER(uTable[0]);   
                    strcat(buf, uTable);
                }
                else strcat( buf, spk_table[iSyl].new );
                if (number_range(1,5) == 1 && str_cmp(spk_table[iSyl].new," "))
                    strcat( buf, spk_table[iSyl].new );
                else if (!str_cmp(spk_table[iSyl].new," "))
                {
                    if (number_range(1,5) == 1 && strlen(buf) < MAX_INPUT_LENGTH)
                        strcat( buf, "*hic* " );
                }
                break;
            }   
        }
    
        if ( length == 0 )
            length = 1;
    }
   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);
   for (loop = 1; loop < strlen (argument); loop++)
   {
      if (number_range (1, 2) == 1)
	 argument[loop] = UPPER (argument[loop]);
   }

   return argument;
}

char *beasttalk (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char *pName;
   int iSyl;
   int length;

   struct spk_type
   {
      char *old;
      char *new;
   };

   static const struct spk_type spk_table[] = {
      { " ",          " "             },
        { "what ",      "^"             },
        { "your ",      "&"             },
        { "the ",       "@"             },
        { "my ",        "$"             },
        { "'", "'" },
        { "a", "a" }, { "b", "b" }, { "c", "c" }, { "d", "d" },
        { "e", "e" }, { "f", "f" }, { "g", "g" }, { "h", "h" },
        { "i", "i" }, { "j", "j" }, { "k", "k" }, { "l", "l" },
        { "m", "m" }, { "n", "n" }, { "o", "o" }, { "p", "p" },
        { "q", "q" }, { "r", "r" }, { "s", "s" }, { "t", "t" },
        { "u", "u" }, { "v", "v" }, { "w", "w" }, { "x", "x" },
        { "y", "y" }, { "z", "z" }, { ",", "," }, { ".", "." },
        { ";", ";" }, { ":", ":" }, { "(", "(" }, { ")", ")" },
        { ")", ")" }, { "-", "-" }, { "!", "!" }, { "?", "?" },
        { "1", "1" }, { "2", "2" }, { "3", "3" }, { "4", "4" },
        { "5", "5" }, { "6", "6" }, { "7", "7" }, { "8", "8" },
        { "9", "9" }, { "0", "0" }, { "%", "%" }, { "'", "'" },
        { "#", "#" }, {  "",  "" }
   };

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;

   for (pName = argument; *pName != '\0'; pName += length)
   {
      for (iSyl = 0; (length = strlen (spk_table[iSyl].old)) != 0; iSyl++)
      {
	 if (!str_prefix (spk_table[iSyl].old, pName))
	 {
	    if (!str_cmp (spk_table[iSyl].new, ",")
		|| !str_cmp (spk_table[iSyl].new, "!")
		|| !str_cmp (spk_table[iSyl].new, "?"))
	    {
	       if (strlen (buf) < MAX_INPUT_LENGTH)
		  switch (number_range (1, 20))
		  {
		  default:
		     break;
		  case 1:
		     strcat (buf, ", you stupid fucker");
		     break;
		  case 2:
		     strcat (buf, ", you idiot");
		     break;
		  case 3:
		     strcat (buf, ", you damn fool");
		     break;
		  case 4:
		     strcat (buf, ", you little shit");
		     break;
		  case 5:
		     strcat (buf, ", you fucking jerk");
		     break;
		  case 6:
		     strcat (buf, ", asshole");
		     break;
		  case 7:
		     strcat (buf, ", cock sucker");
		     break;
		  case 8:
		     strcat (buf, ", fuckwit");
		     break;
		  }
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "@"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "the ");
	       else
		  switch (number_range (1, 10))
		  {
		  default:
		     strcat (buf, "the ");
		     break;
		  case 1:
		     strcat (buf, "the bloody ");
		     break;
		  case 2:
		     strcat (buf, "the fucking ");
		     break;
		  case 3:
		     strcat (buf, "the goddamn ");
		     break;
		  case 4:
		     strcat (buf, "the stupid ");
		     break;
		  case 5:
		     strcat (buf, "the stinking ");
		     break;
		  }
	       break;
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "^"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "what ");
	       else
		  switch (number_range (1, 5))
		  {
		  default:
		     strcat (buf, "what ");
		     break;
		  case 1:
		     strcat (buf, "what the fuck ");
		     break;
		  case 2:
		     strcat (buf, "what the hell ");
		     break;
		  }
	       break;
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "&"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "your ");
	       else
		  switch (number_range (1, 10))
		  {
		  default:
		     strcat (buf, "your ");
		     break;
		  case 1:
		     strcat (buf, "your bloody ");
		     break;
		  case 2:
		     strcat (buf, "your fucking ");
		     break;
		  case 3:
		     strcat (buf, "your damn ");
		     break;
		  case 4:
		     strcat (buf, "your goddamn ");
		     break;
		  case 5:
		     strcat (buf, "your stupid ");
		     break;
		  case 6:
		     strcat (buf, "your stinking ");
		     break;
		  }
	       break;
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "$"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "my ");
	       else
		  switch (number_range (1, 10))
		  {
		  default:
		     strcat (buf, "my ");
		     break;
		  case 1:
		     strcat (buf, "my bloody ");
		     break;
		  case 2:
		     strcat (buf, "my fucking ");
		     break;
		  case 3:
		     strcat (buf, "my damn ");
		     break;
		  case 4:
		     strcat (buf, "my goddamn ");
		     break;
		  case 5:
		     strcat (buf, "my stupid ");
		     break;
		  case 6:
		     strcat (buf, "my stinking ");
		     break;
		  }
	       break;
	    }
            if (pName[0] == UPPER(pName[0]))
                {
                    char uTable[MSL];
                    uTable[0] = '\0';
                    strcat(uTable, spk_table[iSyl].new);
                    uTable[0] = UPPER(uTable[0]);
                    strcat(buf, uTable);
                }
                else strcat( buf, spk_table[iSyl].new );
	    if (!str_cmp (spk_table[iSyl].new, " ")
		&& strlen (buf) < MAX_INPUT_LENGTH)
	    {
	       switch (number_range (1, 20))
	       {
	       default:
		  break;
	       case 1:
		  strcat (buf, "*snarl* ");
		  break;
	       case 2:
		  strcat (buf, "*growl* ");
		  break;
	       }
	    }
	    break;
	 }
      }

      if (length == 0)
	 length = 1;
   }

   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);

   return argument;
}

char *beastchat (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   char *pName;
   int iSyl;
   int length;

   struct spk_type
   {
      char *old;
      char *new;
   };

   static const struct spk_type spk_table[] = {
       { " ",          " "             },
        { "what ",      "^"             },
        { "your ",      "&"             },
        { "the ",       "@"             },
        { "my ",        "$"             },
        { "'", "'" },
        { "a", "a" }, { "b", "b" }, { "c", "c" }, { "d", "d" },
        { "e", "e" }, { "f", "f" }, { "g", "g" }, { "h", "h" },
        { "i", "i" }, { "j", "j" }, { "k", "k" }, { "l", "l" },
        { "m", "m" }, { "n", "n" }, { "o", "o" }, { "p", "p" },
        { "q", "q" }, { "r", "r" }, { "s", "s" }, { "t", "t" },
        { "u", "u" }, { "v", "v" }, { "w", "w" }, { "x", "x" },
        { "y", "y" }, { "z", "z" }, { ",", "," }, { ".", "." },
        { ";", ";" }, { ":", ":" }, { "(", "(" }, { ")", ")" },
        { ")", ")" }, { "-", "-" }, { "!", "!" }, { "?", "?" },
        { "1", "1" }, { "2", "2" }, { "3", "3" }, { "4", "4" },
        { "5", "5" }, { "6", "6" }, { "7", "7" }, { "8", "8" },
        { "9", "9" }, { "0", "0" }, { "%", "%" }, { "'", "'" },
        { "#", "#" }, {  "",  "" }
   };

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;
   for (pName = argument; *pName != '\0'; pName += length)
   {
      for (iSyl = 0; (length = strlen (spk_table[iSyl].old)) != 0; iSyl++)
      {
	 if (!str_prefix (spk_table[iSyl].old, pName))
	 {
	    if (!str_cmp (spk_table[iSyl].new, ",")
		|| !str_cmp (spk_table[iSyl].new, "!")
		|| !str_cmp (spk_table[iSyl].new, "?"))
	    {
	       if (strlen (buf) < MAX_INPUT_LENGTH)
		  switch (number_range (1, 20))
		  {
		  default:
		     break;
		  case 1:
		     strcat (buf, ", you stupid fuckers");
		     break;
		  case 2:
		     strcat (buf, ", you idiots");
		     break;
		  case 3:
		     strcat (buf, ", you sad spods");
		     break;
		  case 4:
		     strcat (buf, ", you bunch of shits");
		     break;
		  case 5:
		     strcat (buf, ", you fucking jerks");
		     break;
		  case 6:
		     strcat (buf, ", assholes");
		     break;
		  case 7:
		     strcat (buf, ", cock suckers");
		     break;
		  case 8:
		     strcat (buf, ", fuckwits");
		     break;
		  }
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "@"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "the ");
	       else
		  switch (number_range (1, 10))
		  {
		  default:
		     strcat (buf, "the ");
		     break;
		  case 1:
		     strcat (buf, "the bloody ");
		     break;
		  case 2:
		     strcat (buf, "the fucking ");
		     break;
		  case 3:
		     strcat (buf, "the goddamn ");
		     break;
		  case 4:
		     strcat (buf, "the stupid ");
		     break;
		  case 5:
		     strcat (buf, "the stinking ");
		     break;
		  }
	       break;
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "^"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "what ");
	       else
		  switch (number_range (1, 5))
		  {
		  default:
		     strcat (buf, "what ");
		     break;
		  case 1:
		     strcat (buf, "what the fuck ");
		     break;
		  case 2:
		     strcat (buf, "what the hell ");
		     break;
		  }
	       break;
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "&"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "your ");
	       else
		  switch (number_range (1, 10))
		  {
		  default:
		     strcat (buf, "your ");
		     break;
		  case 1:
		     strcat (buf, "your bloody ");
		     break;
		  case 2:
		     strcat (buf, "your fucking ");
		     break;
		  case 3:
		     strcat (buf, "your damn ");
		     break;
		  case 4:
		     strcat (buf, "your goddamn ");
		     break;
		  case 5:
		     strcat (buf, "your stupid ");
		     break;
		  case 6:
		     strcat (buf, "your stinking ");
		     break;
		  }
	       break;
	    }
	    else if (!str_cmp (spk_table[iSyl].new, "$"))
	    {
	       if (strlen (buf) >= MAX_INPUT_LENGTH)
		  strcat (buf, "my ");
	       else
		  switch (number_range (1, 10))
		  {
		  default:
		     strcat (buf, "my ");
		     break;
		  case 1:
		     strcat (buf, "my bloody ");
		     break;
		  case 2:
		     strcat (buf, "my fucking ");
		     break;
		  case 3:
		     strcat (buf, "my damn ");
		     break;
		  case 4:
		     strcat (buf, "my goddamn ");
		     break;
		  case 5:
		     strcat (buf, "my stupid ");
		     break;
		  case 6:
		     strcat (buf, "my stinking ");
		     break;
		  }
	       break;
	    }
if (pName[0] == UPPER(pName[0]))
                {
                    char uTable[MSL];
                    uTable[0] = '\0';
                    strcat(uTable, spk_table[iSyl].new);
                    uTable[0] = UPPER(uTable[0]);
                    strcat(buf, uTable);
                }
                else 
	    strcat (buf, spk_table[iSyl].new);
	 }
      }

      if (length == 0)
	 length = 1;
   }

   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);

   return argument;
}

char *socialc (CHAR_DATA * ch, char *argument, char *you, char *them)
{
   char buf[MAX_STRING_LENGTH];
   char *pName;
   int iSyl;
   int length;

   struct spk_type
   {
      char *old;
      char *new;
   };

   static const struct spk_type spk_table[] = {
      {" ", " "},
      {"you are", "$E is"},
      {"you.", "$M."},
      {"you,", "$M,"},
      {"you ", "$M "},
      {" you", " $M"},
      {"your ", "$S "},
      {" your", " $S"},
      {"yours.", "theirs."},
      {"yours,", "theirs,"},
      {"yours ", "theirs "},
      {" yours", " theirs"},
      {"begins", "begin"},
      {"caresses", "caress"},
      {"gives", "give"},
      {"glares", "glare"},
      {"grins", "grin"},
      {"licks", "lick"},
      {"looks", "look"},
      {"loves", "love"},
      {"plunges", "plunge"},
      {"presses", "press"},
      {"pulls", "pull"},
      {"runs", "run"},
      {"slaps", "slap"},
      {"slides", "slide"},
      {"smashes", "smash"},
      {"squeezes", "squeeze"},
      {"stares", "stare"},
      {"sticks", "stick"},
      {"strokes", "stroke"},
      {"tugs", "tug"},
      {"thinks", "think"},
      {"thrusts", "thrust"},
      {"whistles", "whistle"},
      {"wraps", "wrap"},
      {"winks", "wink"},
      {"wishes", "wish"},
      {" winks", " wink"},
      {" his", " your"},
      {"his ", "your "},
      {" her", " your"},
      {"her ", "your "},
      {" him", " your"},
      {"him ", "your "},
      {"the", "the"},
      {" he", " you"},
      {"he ", "you "},
      {" she", " you"},
      {"she ", "you "},
      {"a", "a"}, {"b", "b"}, {"c", "c"}, {"d", "d"},
      {"e", "e"}, {"f", "f"}, {"g", "g"}, {"h", "h"},
      {"i", "i"}, {"j", "j"}, {"k", "k"}, {"l", "l"},
      {"m", "m"}, {"n", "n"}, {"o", "o"}, {"p", "p"},
      {"q", "q"}, {"r", "r"}, {"s", "s"}, {"t", "t"},
      {"u", "u"}, {"v", "v"}, {"w", "w"}, {"x", "x"},
      {"y", "y"}, {"z", "z"}, {",", ","}, {".", "."},
      {";", ";"}, {":", ":"}, {"(", "("}, {")", ")"},
      {")", ")"}, {"-", "-"}, {"!", "!"}, {"?", "?"},
      {"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"},
      {"5", "5"}, {"6", "6"}, {"7", "7"}, {"8", "8"},
      {"9", "9"}, {"0", "0"}, {"%", "%"}, {"", ""}
   };

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;

   for (pName = argument; *pName != '\0'; pName += length)
   {
      for (iSyl = 0; (length = strlen (spk_table[iSyl].old)) != 0; iSyl++)
      {
	 if (!str_prefix (spk_table[iSyl].old, pName))
	 {
	    strcat (buf, spk_table[iSyl].new);
	    break;
	 }
      }

      if (length == 0)
	 length = 1;
   }

   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);

   return argument;
}

char *socialv (CHAR_DATA * ch, char *argument, char *you, char *them)
{
   char buf[MAX_STRING_LENGTH];
   char *pName;
   int iSyl;
   int length;

   struct spk_type
   {
      char *old;
      char *new;
   };

   static const struct spk_type spk_table[] = {
      {" ", " "},
      {" his", " $s"},
      {"his ", "$s "},
      {" her", " $s"},
      {"her ", "$s "},
      {" him", " $m"},
      {"him ", "$m "},
      {" he", " $e"},
      {"he ", "$e "},
      {" she", " $e"},
      {"she ", "$e "},
      {"a", "a"}, {"b", "b"}, {"c", "c"}, {"d", "d"},
      {"e", "e"}, {"f", "f"}, {"g", "g"}, {"h", "h"},
      {"i", "i"}, {"j", "j"}, {"k", "k"}, {"l", "l"},
      {"m", "m"}, {"n", "n"}, {"o", "o"}, {"p", "p"},
      {"q", "q"}, {"r", "r"}, {"s", "s"}, {"t", "t"},
      {"u", "u"}, {"v", "v"}, {"w", "w"}, {"x", "x"},
      {"y", "y"}, {"z", "z"}, {",", ","}, {".", "."},
      {";", ";"}, {":", ":"}, {"(", "("}, {")", ")"},
      {")", ")"}, {"-", "-"}, {"!", "!"}, {"?", "?"},
      {"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"},
      {"5", "5"}, {"6", "6"}, {"7", "7"}, {"8", "8"},
      {"9", "9"}, {"0", "0"}, {"%", "%"}, {"", ""}
   };

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;

   for (pName = argument; *pName != '\0'; pName += length)
   {
      for (iSyl = 0; (length = strlen (spk_table[iSyl].old)) != 0; iSyl++)
      {
	 if (!str_prefix (spk_table[iSyl].old, pName))
	 {
	    strcat (buf, spk_table[iSyl].new);
	    break;
	 }
      }

      if (length == 0)
	 length = 1;
   }

   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);

   return argument;
}

char *socialn (CHAR_DATA * ch, char *argument, char *you, char *them)
{
   char buf[MAX_STRING_LENGTH];
   char *pName;
   int iSyl;
   int length;

   struct spk_type
   {
      char *old;
      char *new;
   };

   static const struct spk_type spk_table[] = {
      {" ", " "},
      {"you are", "$N is"},
      {"you.", "$N."},
      {"you,", "$N,"},
      {"you ", "$N "},
      {" you", " $N"},
      {"your.", "$N's."},
      {"your,", "$N's,"},
      {"your ", "$N's "},
      {" your", " $N's"},
      {"yourself", "$Mself"},
      {" his", " $s"},
      {"his ", "$s "},
      {" her", " $s"},
      {"her ", "$s "},
      {" him", " $m"},
      {"him ", "$m "},
      {" he", " $e"},
      {"he ", "$e "},
      {" she", " $e"},
      {"she ", "$e "},
      {"a", "a"}, {"b", "b"}, {"c", "c"}, {"d", "d"},
      {"e", "e"}, {"f", "f"}, {"g", "g"}, {"h", "h"},
      {"i", "i"}, {"j", "j"}, {"k", "k"}, {"l", "l"},
      {"m", "m"}, {"n", "n"}, {"o", "o"}, {"p", "p"},
      {"q", "q"}, {"r", "r"}, {"s", "s"}, {"t", "t"},
      {"u", "u"}, {"v", "v"}, {"w", "w"}, {"x", "x"},
      {"y", "y"}, {"z", "z"}, {",", ","}, {".", "."},
      {";", ";"}, {":", ":"}, {"(", "("}, {")", ")"},
      {")", ")"}, {"-", "-"}, {"!", "!"}, {"?", "?"},
      {"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"},
      {"5", "5"}, {"6", "6"}, {"7", "7"}, {"8", "8"},
      {"9", "9"}, {"0", "0"}, {"%", "%"}, {"", ""}
   };

   buf[0] = '\0';

   if (argument[0] == '\0')
      return argument;

   for (pName = argument; *pName != '\0'; pName += length)
   {
      for (iSyl = 0; (length = strlen (spk_table[iSyl].old)) != 0; iSyl++)
      {
	 if (!str_prefix (spk_table[iSyl].old, pName))
	 {
	    strcat (buf, spk_table[iSyl].new);
	    break;
	 }
      }

      if (length == 0)
	 length = 1;
   }

   argument[0] = '\0';
   strcpy (argument, buf);
   argument[0] = UPPER (argument[0]);

   return argument;
}

//Ignore and Unignore stuff

void do_ignore (CHAR_DATA * ch, char *argument)
{
   CHAR_DATA *rch;
   char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
   DESCRIPTOR_DATA *d;
   int pos;
   bool found = FALSE;

   if (ch->desc == NULL)
      rch = ch;
   else
      rch = ch->desc->original ? ch->desc->original : ch;

   if (IS_NPC (rch))
      return;

   smash_tilde (argument);

   argument = one_argument (argument, arg);

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

      if (rch->pcdata->forget[0] == NULL)
      {
	 send_to_char ("You are not ignoring anyone.\n\r", ch);
	 return;
      }
      send_to_char ("You are currently ignoring:\n\r", ch);

      for (pos = 0; pos < MAX_FORGET; pos++)
      {
	 if (rch->pcdata->forget[pos] == NULL)
	    break;

	 sprintf (buf, "    %s\n\r", rch->pcdata->forget[pos]);
	 send_to_char (buf, ch);
      }
      return;
   }

   for (pos = 0; pos < MAX_FORGET; pos++)
   {
      if (rch->pcdata->forget[pos] == NULL)
	 break;

      if (!str_cmp (arg, rch->pcdata->forget[pos]))
      {
	 send_to_char ("You have already ignored that person.\n\r", ch);
	 return;
      }
   }

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

      if (d->connected != CON_PLAYING || !can_see (ch, d->character))
	 continue;

      wch = (d->original != NULL) ? d->original : d->character;

      if (!can_see (ch, wch))
	 continue;

      if (!str_cmp (arg, wch->name))
      {
	 found = TRUE;
	 if (wch == ch)
	 {
	    send_to_char ("You can't ignore yourself!\n\r", ch);
	    return;
	 }
	 if (wch->level >= LEVEL_IMMORTAL && !IS_CREATOR (ch))
	 {
	    send_to_char ("That person is very hard to ignore.\n\r", ch);
	    return;
	 }
      }
   }

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

   for (pos = 0; pos < MAX_FORGET; pos++)
   {
      if (rch->pcdata->forget[pos] == NULL)
	 break;
   }

   if (pos >= MAX_FORGET)
   {
      send_to_char ("Sorry, you have reached the ignore limit.\n\r", ch);
      return;
   }
   free_string (rch->pcdata->forget[pos]);
   rch->pcdata->forget[pos] = str_dup (arg);
   sprintf (buf, "You are now ignoring %s.\n\r", arg);
   send_to_char (buf, ch);
}

void do_unignore (CHAR_DATA * ch, char *argument)
{
   CHAR_DATA *rch;
   char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
   int pos;
   bool found = FALSE;

   if (ch->desc == NULL)
      rch = ch;
   else
      rch = ch->desc->original ? ch->desc->original : ch;

   if (IS_NPC (rch))
      return;

   argument = one_argument (argument, arg);

   if (arg[0] == '\0')
   {
      if (rch->pcdata->forget[0] == NULL)
      {
	 send_to_char ("You are not ignoring anyone.\n\r", ch);
	 return;
      }
      send_to_char ("You are currently ignoring:\n\r", ch);

      for (pos = 0; pos < MAX_FORGET; pos++)
      {
	 if (rch->pcdata->forget[pos] == NULL)
	    break;

	 sprintf (buf, "    %s\n\r", rch->pcdata->forget[pos]);
	 send_to_char (buf, ch);
      }
      return;
   }

   for (pos = 0; pos < MAX_FORGET; pos++)
   {
      if (rch->pcdata->forget[pos] == NULL)
	 break;

      if (found)
      {
	 rch->pcdata->forget[pos - 1] = rch->pcdata->forget[pos];
	 rch->pcdata->forget[pos] = NULL;
	 continue;
      }

      if (!strcmp (arg, rch->pcdata->forget[pos]))
      {
	 send_to_char ("Ignore removed.\n\r", ch);
	 free_string (rch->pcdata->forget[pos]);
	 rch->pcdata->forget[pos] = NULL;
	 found = TRUE;
      }
   }

   if (!found)
      send_to_char ("No one by that name is ignored.\n\r", ch);
}