/
rogue24b3/
rogue24b3/data/
/***************************************************************************\
[*]    ___    ____   ____   __   __  ____ [*]   ROGUE: ROM With Attitude  [*]
[*]   /#/ )  /#/  ) /#/  ) /#/  /#/ /#/   [*]    All rights reserved      [*]
[*]  /#/ <  /#/  / /#/ _  /#/  /#/ /#/--  [*]   Copyright(C) 2000-2001    [*]
[*] /#/   \(#(__/ (#(__/ (#(__/#/ (#(___  [*] Kenneth Conley (Mendanbar)  [*]
[*]  Expression of Digital Creativity..   [*]  scmud@mad.scientist.com    [*]
[-]---------------------------------------+-+-----------------------------[-]
[*] File: act_comm.c							  [*]
[*] Usage: main comunication source.					  [*]
\***************************************************************************/

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

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

#include <stdarg.h>
#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "tables.h"
#include "olc.h"
#include "pueblo.h"

void info( CHAR_DATA *ch, int level, char *message, ...)
{
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA * d;
    va_list args;


    va_start(args,message);
    vsnprintf(buf, MAX_STRING_LENGTH, message, args);
    va_end(args);


    for ( d = descriptor_list; d; d = d->next )
    {
        if ( d->connected == CON_PLAYING && 
             d->character != ch &&
	     !IS_SET(d->character->comm, COMM_NOINFO) &&
             get_trust(d->character) >= level )
           send_to_char(buf, d->character);
    }
}

ACMD(do_gen_menu) {
    extern char *MENU;

    if (IS_NPC(ch))
	return;

    switch (ch->position) {
	case POS_DEAD:
	case POS_INCAP:
	case POS_MORTAL:
	case POS_STUNNED:
	case POS_FIGHTING:
	    ch->Send("You are not in the correct position for that.\n\r");
	    return;
	default:
		break;
    }

    ch->desc->snoop_by = NULL;
    act("$n enters privacy mode.", ch, 0, 0, TO_ROOM);
    STATE(ch->desc) = CON_MENU;
    ch->Send(MENU);
    return;
}

/* RT code to display channel status */
ACMD(do_channels) {
    char buf[MAX_STRING_LENGTH];

    /* lists all channels and their status */
    ch->Send(
	"Channel        Status\n\r"
	"`m---------------------`n\n\r"
	"chat           %-3s\r\n"
	"info           %-3s\r\n"
	"music          %-3s\r\n"
	"grats          %-3s\r\n"
	"shouts         %-3s\r\n"
	"tells          %-3s\r\n",
	ONOFF(!COMM_FLAGGED(ch, COMM_NOGOSSIP)),
	ONOFF(!COMM_FLAGGED(ch, COMM_NOINFO)),
	ONOFF(!COMM_FLAGGED(ch, COMM_NOMUSIC)),
	ONOFF(!COMM_FLAGGED(ch, COMM_NOGRATS)),
	ONOFF(!COMM_FLAGGED(ch, COMM_NOSHOUT)),
	ONOFF(!COMM_FLAGGED(ch, COMM_NOTELL)));

    if (IS_IMMORTAL(ch)) {
	ch->Send(
		"god channel    %-3s\r\n",
		ONOFF(!COMM_FLAGGED(ch, COMM_NOWIZ)));
    }
    ch->Send(
	"quiet mode     %-3s\r\n",
	ONOFF(COMM_FLAGGED(ch, COMM_QUIET)));

    if (IS_SET(ch->comm,COMM_AFK))
	send_to_char("You are AFK.\n\r",ch);

    if (IS_SET(ch->comm,COMM_SNOOP_PROOF))
	send_to_char("You are immune to snooping.\n\r",ch);
   
    if (ch->lines != PAGELEN)
    {
	if (ch->lines)
	{
	    sprintf(buf,"You display %d lines of scroll.\n\r",ch->lines+2);
	    send_to_char(buf,ch);
 	}
	else
	    send_to_char("Scroll buffering is off.\n\r",ch);
    }

    if (IS_SET(ch->comm,COMM_MUTED))
     send_to_char("You cannot use channels.\n\r",ch);

}

/* afk command */
ACMD(do_afk) {
	smash_tilde(argument);
    if (IS_SET(ch->comm,COMM_AFK))
    {
      send_to_char("AFK mode removed. Type 'replay' to see tells.\n\r",ch);
      free_string(GET_AFK(ch));
      GET_AFK(ch) = str_dup("");
      act("$n is back from AFK!", ch, NULL, NULL, TO_ROOM);
      REMOVE_BIT(ch->comm,COMM_AFK);
    }
   else
   {
     send_to_char("You are now in AFK mode.\n\r",ch);
     free_string(GET_AFK(ch));
     GET_AFK(ch) = str_dup((*argument ? argument : "I am AFK!"));
     act("$n has just gone AFK: $T", ch, NULL, GET_AFK(ch), TO_ROOM);
     SET_BIT(ch->comm,COMM_AFK);
   }
}

ACMD(do_replay) {
    if (IS_NPC(ch))
    {
	send_to_char("You can't replay.\n\r",ch);
	return;
    }

    if (buf_string(ch->pcdata->buffer)[0] == '\0')
    {
	send_to_char("You have no tells to replay.\n\r",ch);
	return;
    }

    page_to_char(buf_string(ch->pcdata->buffer),ch);
    clear_buf(ch->pcdata->buffer);
}

ACMD(do_gocial) {
    int cmd;
    CHAR_DATA *victim = NULL;
    char arg[MAX_INPUT_LENGTH],
	 buf1[MAX_STRING_LENGTH],
	 buf2[MAX_STRING_LENGTH],
	 buf3[MAX_STRING_LENGTH],
	 command[MAX_INPUT_LENGTH];

    buf1[0] = '\0';
    buf2[0] = '\0';
    buf3[0] = '\0';
    argument = one_argument(argument, command);

    if (command[0] == '\0') {
	send_to_char("What do you wish to gocial?\n\r", ch);
	return;
    }
    if ((cmd = social_lookup(command)) == -1) {
	send_to_char("What kind of social is that?!?!\n\r",ch);
	return;
    }
    if (COMM_FLAGGED(ch, COMM_QUIET)) {
	send_to_char("You must turn off quiet mode first.\n\r",ch);
	return;
    }
    if (COMM_FLAGGED(ch, COMM_NOGOSSIP)) {
	send_to_char("But you have the chat channel turned off!\n\r",ch);
	return;
    }
    if (COMM_FLAGGED(ch, COMM_MUTED)) {
	send_to_char("The gods have revoked your channel priviliges.\n\r",ch);
	return;
    }

    if (ch->position < social_table[cmd].min_pos) {
	switch (ch->position) {
	case POS_DEAD:
		send_to_char("Lie still; you are DEAD!\n\r",ch);
		return;
	case POS_INCAP:
	case POS_MORTAL:
		send_to_char("You are hurt far too bad for that.\n\r",ch);
		return;
	case POS_STUNNED:
		send_to_char("You are too stunned for that.\n\r",ch);
		return;
	case POS_SLEEPING:
		send_to_char("In your dreams, or what?\n\r", ch);
		return;
	case POS_RESTING:
		send_to_char("Nah... You feel too relaxed to do that.\n\r", ch);
		return;
	case POS_SITTING:
		send_to_char("Maybe you should get on your feet first?\n\r", ch);
		return;
	case POS_FIGHTING:
		send_to_char("No way! You're fighting for your life!\n\r", ch);
		return;
	default:
		send_to_char("Your not sure how but your bugged.\n\r", ch);
		return;
	}
    }

    one_argument(argument, arg);
    if (arg[0] == '\0') {
	if (*social_table[cmd].char_no_arg)
	    sprintf(buf1, "`y[`bCHAT`y] %s`n", social_table[cmd].char_no_arg);
	if (*social_table[cmd].others_no_arg)
	    sprintf(buf2, "`y[`bCHAT`y] %s`n", social_table[cmd].others_no_arg);
    } else if ((victim = get_pc_world(ch, arg)) == NULL) {
	send_to_char("That person is not here.\n\r", ch);
	return;
    } else if (victim == ch) {
	if (*social_table[cmd].char_auto)
	    sprintf(buf1, "`y[`bCHAT`y] %s`n", social_table[cmd].char_auto);
	if (*social_table[cmd].others_auto)
	    sprintf(buf2, "`y[`bCHAT`y] %s`n", social_table[cmd].others_auto);
    } else {
	if (*social_table[cmd].char_found)
	    sprintf(buf1, "`y[`bCHAT`y] %s`n", social_table[cmd].char_found);
	if (*social_table[cmd].others_found)
	    sprintf(buf2, "`y[`bCHAT`y] %s`n", social_table[cmd].others_found);
	if (*social_table[cmd].vict_found)
	    sprintf(buf3, "`y[`bCHAT`y] %s`n", social_table[cmd].vict_found);
    }
    if (*buf1)
	act_social(buf1, ch, 0, victim, TO_CHAR, POS_DEAD);
    if (*buf2)
	act_social(buf2, ch, 0, victim, TO_ALLNOTVICT, POS_DEAD);
    if (*buf3 && victim != NULL)
	act_social(buf3, ch, 0, victim, TO_VICT, POS_DEAD);
    return;
}

ACMD(do_gen_comm) {
	DESCRIPTOR_DATA *d;
	char buf[MAX_STRING_LENGTH];

	static UInt32 channels[] = {
		COMM_NOGOSSIP,
		COMM_NOMUSIC,
		COMM_NOGRATS,
		COMM_NOSHOUT,
		COMM_NOQUEST,
		COMM_NOCLAN,
		0, // BROADCAST
		0
	};

	static char *com_msgs[][5] = {
		{	"You cannot chat!!\n\r",
			"chat",
			"You aren't even on the channel!\n\r",
			"`y[`bCHAT`y] $n`y: %s`n",
			"`y[`bCHAT`y] -> %s`n"
		},
		{	"You cannot sing!!\n\r",
			"sing",
			"You aren't even on the channel!\n\r",
			"`y[`mMUSIC by $n`y] `m%s`n",
			"`y[`mMUSIC`y] -> `w%s`n"
		},
		{	"You cannot congratulate!!\n\r",
			"congrat",
			"You aren't even on the channel!\n\r",
			"`y[`bCONGRATS`y] $n`g: %s`n",
			"`y[`bCONGRATS`y] -> `g%s`n"
		},
		{	"You cannot shout!!\n\r",
			"shout",
			"Turn off your noshout flag first!\n\r",
			"$n `yshouts '%s`y'`n",
			"`yYou shout '%s`y'`n"
		},
		{	"You cannot quest talk!!\n\r",
			"quest talk",
			"You aren't even on the channel!\n\r",
			"`y[`bQUEST`y] $n`r: %s`n",
			"`y[`bQUEST`y] -> `r%s`n"
		},
		{	"You cannot converse with your clan!\n\r",
			"clan chat",
			"You aren't even on the channel!\n\r",
			"`y[`bCLAN`y] $n`c: %s`n",
			"`y[`bCLAN`y] -> `c%s`n"
		},
		{	"You cannot broadcast info!\n\r",
			"broadcast",
			"",
			"`y[`bINFO`y] $n`w: %s`n",
			"`y[`bINFO`y] -> `w%s`n"
		}
	};

	if (COMM_FLAGGED(ch, COMM_MUTED)) {
		send_to_char(com_msgs[subcmd][0], ch);
		return;
	}
	if (COMM_FLAGGED(ch, channels[subcmd])) {
		send_to_char(com_msgs[subcmd][2], ch);
		return;
	}
	if ((subcmd == SCMD_CLAN) && !is_clan(ch)) {
		send_to_char("You aren't even a clan member!\n\r", ch);
		return;
	}
	if ((subcmd != SCMD_BROADCAST) && (GET_COND(ch, COND_DRUNK) > 10))
		argument = makedrunk(argument, ch);
	if (!*argument) {
		ch->Send("Yes, %s, fine, %s we must, but WHAT???\n\r",
		com_msgs[subcmd][1], com_msgs[subcmd][1]);
		return;
	}
	check_color_string(argument);
	sprintf(buf, com_msgs[subcmd][4], argument);
	act2(buf, ch, NULL, NULL, TO_CHAR, POS_DEAD);
	sprintf(buf, com_msgs[subcmd][3], argument);

	for (d = descriptor_list; d != NULL; d = d->next) {
	    CHAR_DATA *vch = Original(d);

	    if ((STATE(d) == CON_PLAYING) && (vch != ch) &&
		!COMM_FLAGGED(vch, channels[subcmd]) &&
		!COMM_FLAGGED(vch, COMM_QUIET))
	    {
		if ((subcmd == SCMD_SHOUT) &&
		    ((IN_ROOM(vch)->area != IN_ROOM(ch)->area) ||
		    vch->position < POS_RESTING))
			continue;
		if ((subcmd == SCMD_CLAN) && !is_same_clan(ch, vch))
			continue;

		act2(buf, ch, NULL, vch, TO_VICT, POS_DEAD);
	    }
	}
}


ACMD(do_immtalk) {
    DESCRIPTOR_DATA *d;
    char buf1[MAX_INPUT_LENGTH];
    int level = LEVEL_IMMORTAL;
    buf1[0] = '\0';

    if (IS_NULLSTR(argument)) {
	send_to_char(	"Usage: immtalk <text> | #<level> <text> |\r\n"
			"       immtalk @on | @off\r\n", ch);
	return;
    }

    switch(*argument) {
	case '#':
		one_argument(argument+1, buf1);
		if (is_number(buf1)) {
			argument = one_argument(argument+1, buf1);
			level = URANGE(LEVEL_IMMORTAL, atoi(buf1), MAX_LEVEL);
			if (level > ch->level) {
				send_to_char("You can't immtalk above your own level.\r\n", ch);
				return;
			}
		}
		break;
	case '@':
		one_argument(argument+1, buf1);
		if (!str_cmp(buf1, "on")) {
			send_to_char("You can now hear immtalk.\r\n",ch);
			REMOVE_BIT(CHN_FLAGS(ch), COMM_NOWIZ);
			return;
		} else if (!str_cmp(buf1, "off")) {
			send_to_char("You are now deaf to immtalk.\r\n",ch);
			SET_BIT(CHN_FLAGS(ch), COMM_NOWIZ);
			return;
		}
		break;
	default:
		break;		
    }
    if (COMM_FLAGGED(ch, COMM_NOWIZ)) {
	send_to_char("You are not even on the channel. Twit.\r\n",ch);
	return;
    }
    if (IS_NULLSTR(argument)) {
	send_to_char("Don't bother the gods like that.\r\n", ch);
	return;
    }

    check_color_string(argument);
    for (d = descriptor_list; d != NULL; d = d->next) {
	CHAR_DATA *wch;
	wch = Original(d);

	if (d->connected == CON_PLAYING && (wch->level >= level)
	&& IS_IMMORTAL(wch) && !COMM_FLAGGED(wch, COMM_NOWIZ)) {
	    if (level > LEVEL_IMMORTAL)
		wch->Send("`c%s`c: <%d> %s`n\r\n",
		PERS2(ch, wch), level, argument);
	    else
		wch->Send("`c%s`c: %s`n\r\n",
		PERS2(ch, wch), argument);
	}
    }
}

ACMD(do_say) {
    char *verb, *s;
    char arg[MAX_STRING_LENGTH];

    check_color_string(argument);
    if (GET_COND(ch, COND_DRUNK) > 10)
	argument = makedrunk(argument, ch);

    if (!*argument) {
	send_to_char("Say what?\n\r", ch);
	return;
    }
    if (COMM_FLAGGED(ch, COMM_MUTED)) {
	send_to_char("You cannot speak!\n\r", ch);
	return;
    }
    strcpy(arg, argument);
    s = arg + strlen(arg);
    while (isspace(*(--s)));
	*(s + 1) = '\0';
    switch(*s) {
	case '?':	verb = "ask";		break;
	case '!':	verb = "exclaim";	break;
	default:	verb = "say";		break;
    }
    act("You $t, '$T`n'", ch, verb, arg, TO_CHAR);
    act("$n $ts, '$T`n'", ch, verb, arg, TO_ROOM);

    if (!IS_NPC(ch))
    {
	CHAR_DATA *mob, *mob_next;
	for (mob = ch->in_room->people; mob != NULL; mob = mob_next)
	{
	    mob_next = mob->next_in_room;
	    if (IS_NPC(mob) && HAS_TRIGGER(mob, TRIG_SPEECH)
	    &&  mob->position == mob->pIndexData->default_pos)
		mp_act_trigger(arg, mob, ch, NULL, NULL, TRIG_SPEECH);
	}
    }
    return;
}

ACMD(do_spec_comm) {
    CHAR_DATA *vict;
    char buf[MAX_STRING_LENGTH];
    char *action_sing, *action_plur, *action_others;

    if (COMM_FLAGGED(ch, COMM_MUTED)) {
	send_to_char("MMmmFff! You cannot speak!\n\r", ch);
	return;
    }
    if (subcmd == SCMD_WHISPER) {
	action_sing = "whisper to";
	action_plur = "whispers to";
	action_others = "$n whispers something to $N.";
    } else {
	action_sing = "ask";
	action_plur = "asks";
	action_others = "$n asks $N a question.";
    }
    argument = one_argument(argument, buf);

    if (!*buf || !*argument)
	ch->Send("Whom do you want to %s.. and what??\n\r", action_sing);
    else if (!(vict = get_char_room(ch, buf)))
	send_to_char("That person is not here.\n\r", ch);
    else if (vict == ch)
	send_to_char("You try to reach your mouth around to your ear but it doesn't work.\n\r", ch);
    else {
	sprintf(buf, "$n %s you, '%s'", action_plur, argument);
	act(buf, ch, 0, vict, TO_VICT);
	sprintf(buf, "You %s $N, '%s'", action_sing, argument);
	act(buf, ch, 0, vict, TO_CHAR);
	act(action_others, ch, 0, vict, TO_NOTVICT);
    }
    return;
}

ACMD(do_tell) {
    char arg[MAX_INPUT_LENGTH],buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    if ( IS_SET(ch->comm, COMM_NOTELL) || IS_SET(ch->comm,COMM_NOTELL))
    {
	send_to_char( "Your message didn't get through.\n\r", ch );
	return;
    }

    if ( IS_SET(ch->comm, COMM_QUIET) )
    {
	send_to_char( "You must turn off quiet mode first.\n\r", ch);
	return;
    }

    if (IS_SET(ch->comm,COMM_NOTELL))
    {
	send_to_char("You must turn off deaf mode first.\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 ) )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->desc == NULL && !IS_NPC(victim))
    {
	act2("$N seems to have misplaced $S link...try again later.",
	    ch,NULL,victim,TO_CHAR, POS_DEAD);
	sprintf(buf,"%s `rtells you '%s`r'`n\n\r",PERS2(ch,victim),argument);
        buf[0] = UPPER(buf[0]);
        add_buf(victim->pcdata->buffer,buf);
	return;
    }

    if ( !IS_STAFF(ch) && !IS_AWAKE(victim) )
    {
	act( "$E can't hear you.", ch, 0, victim, TO_CHAR);
	return;
    }
  
    if ((IS_SET(victim->comm,COMM_QUIET) || IS_SET(victim->comm,COMM_NOTELL))
    && !IS_IMMORTAL(ch))
    {
	act( "$E is not receiving tells.", ch, 0, victim, TO_CHAR);
  	return;
    }

    if (IS_SET(victim->comm,COMM_AFK))
    {
	if (IS_NPC(victim))
	{
	    act("$E is AFK, and not receiving tells.",ch,NULL,victim,TO_CHAR);
	    return;
	}

	act2("$N is AFK and may not hear your tell.\r\n"
		"MESSAGE: $t\r\n", ch,GET_AFK(victim),victim,TO_CHAR,POS_DEAD);
	sprintf(buf,"%s `rtells you, '%s`r'`n\n\r",PERS2(ch,victim),argument);
	buf[0] = UPPER(buf[0]);
	add_buf(victim->pcdata->buffer,buf);
    }

    act2( "`rYou tell $N`r, '$t`r'`n", ch, argument, victim, TO_CHAR,POS_DEAD );
    act2("$n `rtells you, '$t`r'`n",ch,argument,victim,TO_VICT,POS_DEAD);
    victim->reply	= ch;

    if ( !IS_NPC(ch) && IS_NPC(victim) && HAS_TRIGGER(victim,TRIG_SPEECH) )
	mp_act_trigger( argument, victim, ch, NULL, NULL, TRIG_SPEECH );
    return;
}



ACMD(do_reply) {
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];

    if ( IS_SET(ch->comm, COMM_NOTELL) )
    {
	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 ( victim->desc == NULL && !IS_NPC(victim))
    {
        act2("$N seems to have misplaced $S link...try again later.",
            ch,NULL,victim,TO_CHAR, POS_DEAD);
        sprintf(buf,"%s `rtells you '%s`r'`n\n\r",PERS2(ch,victim),argument);
        buf[0] = UPPER(buf[0]);
        add_buf(victim->pcdata->buffer,buf);
        return;
    }

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

    if ((IS_SET(victim->comm,COMM_QUIET) || IS_SET(victim->comm,COMM_NOTELL))
    &&  !IS_IMMORTAL(ch) && !IS_IMMORTAL(victim))
    {
        act_new( "$E is not receiving tells.", ch, 0, victim, TO_CHAR,POS_DEAD, TRUE, FALSE);
        return;
    }

    if (IS_SET(victim->comm,COMM_AFK))
    {
        if (IS_NPC(victim))
        {
            act_new("$E is AFK, and not receiving tells.",
		ch,NULL,victim,TO_CHAR,POS_DEAD, TRUE, FALSE);
            return;
        }
 
        sprintf(buf,"%s `rtells you, '%s`r'`n\n\r",PERS2(ch,victim),argument);
	buf[0] = UPPER(buf[0]);
        add_buf(victim->pcdata->buffer,buf);
    }

    act2("`rYou tell $N`r, '$t`r'`n",ch,argument,victim,TO_CHAR,POS_DEAD);
    act2("$n `rtells you, '$t`r'`n",ch,argument,victim,TO_VICT,POS_DEAD);
    victim->reply	= ch;
    return;
}



ACMD(do_shout) {
    DESCRIPTOR_DATA *d;

    if (COMM_FLAGGED(ch, COMM_NOSHOUT))
    {
	send_to_char("You aren't even on the channel!\r\n",ch);
	return;
    }
    if (COMM_FLAGGED(ch, COMM_MUTED))
    {
        send_to_char( "You can't shout.\n\r", ch );
        return;
    }
 
    if ( argument[0] == '\0' )
    {
	send_to_char( "Shout what?\n\r", ch );
	return;
    }


    act("You shout '$t'",ch,argument,NULL,TO_CHAR);
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected == CON_PLAYING
	&&   d->character != ch
	&&   d->character->in_room != NULL
	&&   d->character->in_room->area == ch->in_room->area 
        &&   !IS_SET(d->character->comm,COMM_QUIET) )
	{
	    act("$n shouts '$t'",ch,argument,d->character,TO_VICT);
	}
    }

    return;
}


ACMD(do_emote) {
    if (!IS_NPC(ch) && IS_SET(ch->comm, COMM_MUTED))
    {
        send_to_char( "You can't show your emotions.\n\r", ch );
        return;
    }
 
    if ( argument[0] == '\0' )
    {
        send_to_char( "Emote what?\n\r", ch );
        return;
    }
 
    MOBtrigger = FALSE;
    act( "$n $T", ch, NULL, argument, TO_ROOM );
    act( "$n $T", ch, NULL, argument, TO_CHAR );
    MOBtrigger = TRUE;
    return;
}

ACMD(do_pmote) {
    CHAR_DATA *vch;
    char *letter,*name;
    char last[MAX_INPUT_LENGTH], temp[MAX_STRING_LENGTH];
    int matches = 0;

    if ( !IS_NPC(ch) && IS_SET(ch->comm, COMM_MUTED))
    {
        send_to_char( "You can't show your emotions.\n\r", ch );
        return;
    }
 
    if ( argument[0] == '\0' )
    {
        send_to_char( "Emote what?\n\r", ch );
        return;
    }
 
    act( "$n $t", ch, argument, NULL, TO_CHAR );

    for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
    {
	if (vch->desc == NULL || vch == ch)
	    continue;

	if ((letter = strstr(argument,vch->name)) == NULL)
	{
	    MOBtrigger = FALSE;
	    act("$N $t",vch,argument,ch,TO_CHAR);
	    MOBtrigger = TRUE;
	    continue;
	}

	strcpy(temp,argument);
	temp[strlen(argument) - strlen(letter)] = '\0';
   	last[0] = '\0';
 	name = vch->name;
	
	for (; *letter != '\0'; letter++)
	{ 
	    if (*letter == '\'' && matches == strlen(vch->name))
	    {
		strcat(temp,"r");
		continue;
	    }

	    if (*letter == 's' && matches == strlen(vch->name))
	    {
		matches = 0;
		continue;
	    }
	    
 	    if (matches == strlen(vch->name))
	    {
		matches = 0;
	    }

	    if (*letter == *name)
	    {
		matches++;
		name++;
		if (matches == strlen(vch->name))
		{
		    strcat(temp,"you");
		    last[0] = '\0';
		    name = vch->name;
		    continue;
		}
		strncat(last,letter,1);
		continue;
	    }

	    matches = 0;
	    strcat(temp,last);
	    strncat(temp,letter,1);
	    last[0] = '\0';
	    name = vch->name;
	}

	MOBtrigger = FALSE;
	act("$N $t",vch,temp,ch,TO_CHAR);
	MOBtrigger = TRUE;
    }
	
    return;
}


/*
 * All the posing stuff.
 */
struct	pose_table_type
{
    char *	message[2*MAX_CLASS];
};

const	struct	pose_table_type	pose_table	[]	=
{
    {
	{
	    "You sizzle with energy.",
	    "$n sizzles with energy.",
	    "You feel very holy.",
	    "$n looks very holy.",
	    "You perform a small card trick.",
	    "$n performs a small card trick.",
	    "You show your bulging muscles.",
	    "$n shows $s bulging muscles."
	}
    },

    {
	{
	    "You turn into a butterfly, then return to your normal shape.",
	    "$n turns into a butterfly, then returns to $s normal shape.",
	    "You nonchalantly turn wine into water.",
	    "$n nonchalantly turns wine into water.",
	    "You wiggle your ears alternately.",
	    "$n wiggles $s ears alternately.",
	    "You crack nuts between your fingers.",
	    "$n cracks nuts between $s fingers."
	}
    },

    {
	{
	    "Blue sparks fly from your fingers.",
	    "Blue sparks fly from $n's fingers.",
	    "A halo appears over your head.",
	    "A halo appears over $n's head.",
	    "You nimbly tie yourself into a knot.",
	    "$n nimbly ties $mself into a knot.",
	    "You grizzle your teeth and look mean.",
	    "$n grizzles $s teeth and looks mean."
	}
    },

    {
	{
	    "Little red lights dance in your eyes.",
	    "Little red lights dance in $n's eyes.",
	    "You recite words of wisdom.",
	    "$n recites words of wisdom.",
	    "You juggle with daggers, apples, and eyeballs.",
	    "$n juggles with daggers, apples, and eyeballs.",
	    "You hit your head, and your eyes roll.",
	    "$n hits $s head, and $s eyes roll."
	}
    },

    {
	{
	    "A slimy green monster appears before you and bows.",
	    "A slimy green monster appears before $n and bows.",
	    "Deep in prayer, you levitate.",
	    "Deep in prayer, $n levitates.",
	    "You steal the underwear off every person in the room.",
	    "Your underwear is gone!  $n stole it!",
	    "Crunch, crunch -- you munch a bottle.",
	    "Crunch, crunch -- $n munches a bottle."
	}
    },

    {
	{
	    "You turn everybody into a little pink elephant.",
	    "You are turned into a little pink elephant by $n.",
	    "An angel consults you.",
	    "An angel consults $n.",
	    "The dice roll ... and you win again.",
	    "The dice roll ... and $n wins again.",
	    "... 98, 99, 100 ... you do pushups.",
	    "... 98, 99, 100 ... $n does pushups."
	}
    },

    {
	{
	    "A small ball of light dances on your fingertips.",
	    "A small ball of light dances on $n's fingertips.",
	    "Your body glows with an unearthly light.",
	    "$n's body glows with an unearthly light.",
	    "You count the money in everyone's pockets.",
	    "Check your money, $n is counting it.",
	    "Arnold Schwarzenegger admires your physique.",
	    "Arnold Schwarzenegger admires $n's physique."
	}
    },

    {
	{
	    "Smoke and fumes leak from your nostrils.",
	    "Smoke and fumes leak from $n's nostrils.",
	    "A spot light hits you.",
	    "A spot light hits $n.",
	    "You balance a pocket knife on your tongue.",
	    "$n balances a pocket knife on your tongue.",
	    "Watch your feet, you are juggling granite boulders.",
	    "Watch your feet, $n is juggling granite boulders."
	}
    },

    {
	{
	    "The light flickers as you rap in magical languages.",
	    "The light flickers as $n raps in magical languages.",
	    "Everyone levitates as you pray.",
	    "You levitate as $n prays.",
	    "You produce a coin from everyone's ear.",
	    "$n produces a coin from your ear.",
	    "Oomph!  You squeeze water out of a granite boulder.",
	    "Oomph!  $n squeezes water out of a granite boulder."
	}
    },

    {
	{
	    "Your head disappears.",
	    "$n's head disappears.",
	    "A cool breeze refreshes you.",
	    "A cool breeze refreshes $n.",
	    "You step behind your shadow.",
	    "$n steps behind $s shadow.",
	    "You pick your teeth with a spear.",
	    "$n picks $s teeth with a spear."
	}
    },

    {
	{
	    "A fire elemental singes your hair.",
	    "A fire elemental singes $n's hair.",
	    "The sun pierces through the clouds to illuminate you.",
	    "The sun pierces through the clouds to illuminate $n.",
	    "Your eyes dance with greed.",
	    "$n's eyes dance with greed.",
	    "Everyone is swept off their foot by your hug.",
	    "You are swept off your feet by $n's hug."
	}
    },

    {
	{
	    "The sky changes color to match your eyes.",
	    "The sky changes color to match $n's eyes.",
	    "The ocean parts before you.",
	    "The ocean parts before $n.",
	    "You deftly steal everyone's weapon.",
	    "$n deftly steals your weapon.",
	    "Your karate chop splits a tree.",
	    "$n's karate chop splits a tree."
	}
    },

    {
	{
	    "The stones dance to your command.",
	    "The stones dance to $n's command.",
	    "A thunder cloud kneels to you.",
	    "A thunder cloud kneels to $n.",
	    "The Grey Mouser buys you a beer.",
	    "The Grey Mouser buys $n a beer.",
	    "A strap of your armor breaks over your mighty thews.",
	    "A strap of $n's armor breaks over $s mighty thews."
	}
    },

    {
	{
	    "The heavens and grass change colour as you smile.",
	    "The heavens and grass change colour as $n smiles.",
	    "The Burning Man speaks to you.",
	    "The Burning Man speaks to $n.",
	    "Everyone's pocket explodes with your fireworks.",
	    "Your pocket explodes with $n's fireworks.",
	    "A boulder cracks at your frown.",
	    "A boulder cracks at $n's frown."
	}
    },

    {
	{
	    "Everyone's clothes are transparent, and you are laughing.",
	    "Your clothes are transparent, and $n is laughing.",
	    "An eye in a pyramid winks at you.",
	    "An eye in a pyramid winks at $n.",
	    "Everyone discovers your dagger a centimeter from their eye.",
	    "You discover $n's dagger a centimeter from your eye.",
	    "Mercenaries arrive to do your bidding.",
	    "Mercenaries arrive to do $n's bidding."
	}
    },

    {
	{
	    "A black hole swallows you.",
	    "A black hole swallows $n.",
	    "Valentine Michael Smith offers you a glass of water.",
	    "Valentine Michael Smith offers $n a glass of water.",
	    "Where did you go?",
	    "Where did $n go?",
	    "Four matched Percherons bring in your chariot.",
	    "Four matched Percherons bring in $n's chariot."
	}
    },

    {
	{
	    "The world shimmers in time with your whistling.",
	    "The world shimmers in time with $n's whistling.",
	    "The great gods give you a staff.",
	    "The great gods give $n a staff.",
	    "Click.",
	    "Click.",
	    "Atlas asks you to relieve him.",
	    "Atlas asks $n to relieve him."
	}
    }
};



ACMD(do_pose) {
    int level;
    int pose;

    if ( IS_NPC(ch) )
	return;

    level = UMIN( ch->level, sizeof(pose_table) / sizeof(pose_table[0]) - 1 );
    pose  = number_range(0, level);

    act(pose_table[pose].message[2*ch->Class+0], ch, NULL, NULL, TO_CHAR);
    act(pose_table[pose].message[2*ch->Class+1], ch, NULL, NULL, TO_ROOM);

    return;
}

ACMD(do_idea) {
	append_file(ch, IDEA_FILE, argument);
	send_to_char("Idea logged.\r\n",ch);
	return;
}

ACMD(do_bug) {
    append_file( ch, BUG_FILE, argument );
    send_to_char( "Bug logged.\n\r", ch );
    return;
}

ACMD(do_typo) {
    append_file( ch, TYPO_FILE, argument );
    send_to_char( "Typo logged.\n\r", ch );
    return;
}

void do_start(CHAR_DATA *ch) {
    char buf[MAX_STRING_LENGTH];
    void build_player_index();
    extern int get_player_database();

    SET_BIT(PLR_FLAGS(ch), PLR_AUTOEXIT);

    ch->level		= 1;
    ch->exp		= exp_per_level(ch, ch->pcdata->points);
    ch->hit		= ch->max_hit;
    ch->mana		= ch->max_mana;
    ch->move		= ch->max_move;
    ch->train		= 3;
    ch->practice	= 5;
    ch->perm_stat[class_table[ch->Class].attr_prime] += 3;

    if (get_player_database() == 0) {
	ch->level	= MAX_LEVEL;
	ch->max_hit	= ch->hit	= 5000;
	ch->max_mana	= ch->mana	= 5000;
	ch->max_move	= ch->move	= 82;
	ch->pcdata->security	= 9;
	ch->staff_level		= CAT_CODER;
	update_wizlist(ch, ch->level);
	SET_BIT(STF_FLAGS(ch), 0xFFFFFFFF);
	SET_BIT(PLR_FLAGS(ch), PLR_LOADROOM);
	GET_LOADROOM(ch) = 1210;
	save_char_obj(ch);
	build_player_index();
    }

    sprintf(buf, "the %s",
	title_table[ch->Class][ch->level][ch->sex == SEX_FEMALE ? 1 : 0]);
    set_title(ch, buf);

    if (PLR_FLAGGED(ch, PLR_PUEBLO))
	send_to_char("<xch_mudtext>`n",ch);

    do_function(ch, &do_outfit, "", 0);
    obj_to_char(create_object(get_obj_index(OBJ_VNUM_MAP), 0), ch);
    send_to_char("\n\r", ch);
}

ACMD(do_quit) {
    DESCRIPTOR_DATA *d, *d_next;

    if (IS_NPC(ch))
	return;

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

    if (ch->position  < POS_STUNNED) {
	send_to_char("You're not DEAD yet.\n\r", ch);
	return;
    }

    info(ch, 0, "`y[`bINFO`y] %s has left the game!`n\r\n", RealName(ch));
    STATE(ch->desc) = CON_CLOSE;
    mudlogf(NRM, UMAX(LVL_CODER, ch->invis_level), TRUE, "%s has quit the game.", RealName(ch));
    send_to_char("Alas, all good things must come to an end.\n\r", ch);
    act("$n has left the game.", ch, NULL, NULL, TO_ROOM);

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

    /* toast evil cheating bastards */
    for (d = descriptor_list; d != NULL; d = d_next)
    {
	CHAR_DATA *tch;

	d_next = d->next;

	if (d == ch->desc)
		continue;

	tch = Original(d);
	if (tch && tch->id == ch->id)
	{
	    extract_char(tch);
	    close_socket(d);
	} 
    }
    STATE(ch->desc) = CON_DISCONNECT;
    return;
}



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

    save_crash(ch);
    save_char_obj(ch);
    ch->Send("Saving %s.\r\n", ch->name);
    return;
}



ACMD(do_follow) {
/* RT changed to allow unlimited following and follow the NOFOLLOW rules */
    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_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 (!IS_NPC(victim) && IS_SET(victim->act,PLR_NOFOLLOW) && !IS_IMMORTAL(ch))
    {
	act("$N doesn't seem to want any followers.\n\r",
             ch,NULL,victim, TO_CHAR);
        return;
    }

    REMOVE_BIT(ch->act,PLR_NOFOLLOW);
    
    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 )
    {
	mudlogf(BRF, LVL_CODER, TRUE, "SYSERR: add_follower: non-null master.");
	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 )
    {
	mudlogf(BRF, LVL_CODER, TRUE, "SYSERR: stop_follower: null master.");
	return;
    }

    if ( IS_AFFECTED(ch, AFF_CHARM) )
    {
	REMOVE_BIT( ch->affected_by, AFF_CHARM );
	affect_strip( ch, gsn_charm_person );
    }

    if ( can_see( ch->master, ch ) && ch->in_room != NULL)
    {
	act( "$n stops following you.",     ch, NULL, ch->master, TO_VICT    );
    	act( "You stop following $N.",      ch, NULL, ch->master, TO_CHAR    );
    }
    if (ch->master->pet == ch)
	ch->master->pet = NULL;

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

/* nukes charmed monsters and pets */
void nuke_pets( CHAR_DATA *ch )
{    
    CHAR_DATA *pet;

    if ((pet = ch->pet) != NULL)
    {
    	stop_follower(pet);
    	if (pet->in_room != NULL)
    	    act("$N slowly fades away.",ch,NULL,pet,TO_NOTVICT);
    	extract_char(pet);
    }
    ch->pet = NULL;

    return;
}



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

    if ( ch->master != NULL )
    {
    	if (ch->master->pet == ch)
    	    ch->master->pet = 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;
}



ACMD(do_order) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH],arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *och;
    CHAR_DATA *och_next;
    bool found;
    bool fAll;

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

    if (!str_cmp(arg2,"delete") || !str_cmp(arg2,"mob"))
    {
        send_to_char("That will NOT be done.\n\r",ch);
        return;
    }

    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" ) )
    {
	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_AFFECTED(victim, AFF_CHARM) || victim->master != ch 
	||  (IS_IMMORTAL(victim) && victim->trust >= ch->trust))
	{
	    send_to_char( "Do it yourself!\n\r", ch );
	    return;
	}
    }

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

	if ( IS_AFFECTED(och, AFF_CHARM)
	&&   och->master == ch
	&& ( fAll || och == victim ) )
	{
	    found = TRUE;
	    sprintf( buf, "$n orders you to '%s'.", argument );
	    act( buf, ch, NULL, och, TO_VICT );
	    interpret( och, argument );
	}
    }

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



ACMD(do_group) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );

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

	leader = (ch->leader != NULL) ? ch->leader : ch;
	sprintf( buf, "%s's group:\n\r", PERS(leader, ch) );
	send_to_char( buf, ch );

	for ( gch = char_list; gch != NULL; gch = gch->next )
	{
	    if ( is_same_group( gch, ch ) )
	    {
		sprintf( buf,
		"[%3d %s] %-16s %4d/%4d hp %4d/%4d mana %4d/%4d mv %5d xp\n\r",
		    gch->level,
		    IS_NPC(gch) ? "Mob" : class_table[gch->Class].who_name,
		    capitalize( PERS(gch, ch) ),
		    gch->hit,   gch->max_hit,
		    gch->mana,  gch->max_mana,
		    gch->move,  gch->max_move,
		    gch->exp    );
		send_to_char( buf, ch );
	    }
	}
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", 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 ( victim->master != ch && ch != victim )
    {
	act_new("$N isn't following you.",ch,NULL,victim,TO_CHAR,POS_SLEEPING,
	TRUE, FALSE);
	return;
    }
    
    if (IS_AFFECTED(victim,AFF_CHARM))
    {
        send_to_char("You can't remove charmed mobs from your group.\n\r",ch);
        return;
    }
    
    if (IS_AFFECTED(ch,AFF_CHARM))
    {
    	act_new("You like your master too much to leave $m!",
	    ch,NULL,victim,TO_VICT,POS_SLEEPING, TRUE, FALSE);
    	return;
    }

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

    victim->leader = ch;
    act_new("$N joins $n's group.",ch,NULL,victim,TO_NOTVICT,POS_RESTING, TRUE, FALSE);
    act_new("You join $n's group.",ch,NULL,victim,TO_VICT,POS_SLEEPING, TRUE, FALSE);
    act_new("$N joins your group.",ch,NULL,victim,TO_CHAR,POS_SLEEPING, TRUE, FALSE);
    return;
}


/*
 * 'Split' originally by Gnort, God of Chaos.
 */
ACMD(do_split) {
    char buf[MAX_STRING_LENGTH];
    char arg1[MAX_INPUT_LENGTH],arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *gch;
    int members;
    int amount_gold = 0, amount_silver = 0;
    int share_gold, share_silver;
    int extra_gold, extra_silver;

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

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

    if (arg2[0] != '\0')
	amount_gold = atoi(arg2);

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

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

    if ( ch->gold <  amount_gold || ch->silver < amount_silver)
    {
	send_to_char( "You don't have that much to split.\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 ) && !IS_AFFECTED(gch,AFF_CHARM))
	    members++;
    }

    if ( members < 2 )
    {
	send_to_char( "Just keep it all.\n\r", ch );
	return;
    }
	    
    share_silver = amount_silver / members;
    extra_silver = amount_silver % members;

    share_gold   = amount_gold / members;
    extra_gold   = amount_gold % members;

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

    ch->silver	-= amount_silver;
    ch->silver	+= share_silver + extra_silver;
    ch->gold 	-= amount_gold;
    ch->gold 	+= share_gold + extra_gold;

    if (share_silver > 0)
    {
	sprintf(buf,
	    "You split %d silver coins. Your share is %d silver.\n\r",
 	    amount_silver,share_silver + extra_silver);
	send_to_char(buf,ch);
    }

    if (share_gold > 0)
    {
	sprintf(buf,
	    "You split %d gold coins. Your share is %d gold.\n\r",
	     amount_gold,share_gold + extra_gold);
	send_to_char(buf,ch);
    }

    if (share_gold == 0)
    {
	sprintf(buf,"$n splits %d silver coins. Your share is %d silver.",
		amount_silver,share_silver);
    }
    else if (share_silver == 0)
    {
	sprintf(buf,"$n splits %d gold coins. Your share is %d gold.",
		amount_gold,share_gold);
    }
    else
    {
	sprintf(buf,
	"$n splits %d silver and %d gold coins, giving you %d silver and %d gold.\n\r",
	 amount_silver,amount_gold,share_silver,share_gold);
    }

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

    return;
}



ACMD(do_gtell) {
    CHAR_DATA *gch;

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

    if ( IS_SET( ch->comm, COMM_NOTELL ) )
    {
	send_to_char( "Your message didn't get through!\n\r", ch );
	return;
    }

    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
	if ( is_same_group( gch, ch ) )
	    act_new("$n tells the group '`w$t`n'",
		ch,argument,gch,TO_VICT,POS_SLEEPING, TRUE, FALSE);
    }
    act("You tell the group '`w$t`n'", ch, argument, 0, TO_CHAR);
    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 == NULL || bch == NULL)
	return FALSE;

    if ( ach->leader != NULL ) ach = ach->leader;
    if ( bch->leader != NULL ) bch = bch->leader;
    return ach == bch;
}