shadow/
shadow/data/command/
shadow/data/help/
shadow/data/religion/
shadow/data/skill/
/****************************************************************************
 * Automated Warfare Code                                                   *
 * Markanth : dlmud@dlmud.com                                               *
 * Devil's Lament : dlmud.com port 3778                                     *
 * Web Page : http://www.dlmud.com                                          *
 *                                                                          *
 * Provides 4 types of automated wars.                                      *
 *                                                                          *
 * All I ask in return is that you give me credit on your mud somewhere     *
 * or email me if you use it.                                               *
 ****************************************************************************/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"
#include "interp.h"
#include "tables.h"
#include "const.h"
/* local variables*/

CHAR_DATA * find_warmaster ( CHAR_DATA *ch )
{
    CHAR_DATA * warmaster;

    for ( warmaster = ch->in_room->people; warmaster != NULL; warmaster = warmaster->next_in_room )
    {
        if (!IS_NPC(warmaster))
            continue;

        if (warmaster->spec_fun == spec_lookup( "spec_warmaster" ) )
            return warmaster;
    }  

    if  ( warmaster == NULL || warmaster->spec_fun != spec_lookup( "warmaster" ))
    {
        send_to_char("What? You can't do that here.\n\r", ch);
        return NULL;
    }

    if ( warmaster->fighting != NULL )
    {
        send_to_char("Wait until the fighting stops.\n\r",ch );
        return NULL;
    }

    return NULL;
}                        

char *wartype_name(int type)
{
    switch (type)
    {
    case 1:
	return "Race";
    case 2:
	return "Class";
    case 3:
	return "Genocide";
    case 4:
	return "Clan";
    default:
	return "Unknown";
    }
}

bool start_war(CHAR_DATA * ch, char *argument)
{
    char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *wch, *warmaster;
    int blevel, elevel, type;

    warmaster = find_warmaster( ch );
  
    if (!warmaster)
        return FALSE;

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

    if (arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0')
    {
	send_to_char("Syntax: war start <min_level> <max_level> <type>\n\r"
	       "where <type> is either:\n\r"
	       "1 - race war,\n\r2 - klass war,\n\r3 - genocide war,\n\r4 - clan war\n\r",
	       ch);
	return FALSE;
    }

    blevel = atoi(arg1);
    elevel = atoi(arg2);
    type = atoi(arg3);

    if (blevel <= 0 || blevel > MAX_LEVEL)
    {
	sprintf(buf, "Level must be between 1 and %d.\n\r", MAX_LEVEL);
	send_to_char(buf, ch);
	return FALSE;
    }

    if (blevel <= 0 || elevel > MAX_LEVEL)
    {
	sprintf(buf, "Level must be between 1 and %d.\n\r", MAX_LEVEL);
	send_to_char(buf, ch);
	return FALSE;
    }

    if (elevel < blevel)
    {
	send_to_char("Max level must be greater than the min level.\n\r", ch);
	return FALSE;
    }

    if (elevel - blevel < 5)
    {
	send_to_char("Levels must have a difference of at least 5.\n\r", ch);
	return FALSE;
    }

    if (type < 1 || type > 4)
    {
	send_to_char
	  ("The type either has to be 1 (race), 2 (class), 3 (genocide) or 4 (clan).\n\r",
	   ch);
	return FALSE;
    }

    if (war_info.iswar != WAR_OFF)
    {
	send_to_char("There is already a war going!\n\r", ch);
	return FALSE;
    }

    if (!IS_IMMORTAL(ch))
    {
	int cost = 500;

	if (ch->gold < cost)
	{
	    sprintf(buf,
		     "$N tells you 'It costs %d gold to start a %s war.'", cost,
		     wartype_name(type));
	    act(buf, ch, NULL, warmaster, TO_CHAR);
	    return FALSE;
	}
	else
	{
	    sprintf(buf,
		     "$N tells you 'Thank you $n, %s war started, you are %d gold lighter.'",
		     wartype_name(type), cost);
		act(buf, ch, NULL, warmaster, TO_CHAR);
	    ch->gold -= cost;
	}
    }

    war_info.iswar = WAR_WAITING;
    free_string(war_info.who);
    war_info.who = str_dup(ch->name);
    war_info.min_level = blevel;
    war_info.max_level = elevel;
    war_info.wartype = type;
    sprintf(buf, "$n announces a %s war for levels %d to %d.  Type 'WAR' to kill or be killed.",
	     wartype_name(war_info.wartype), war_info.min_level,
	     war_info.max_level);
    war_channel(ch, buf);
    sprintf(buf, "You announce a %s war for levels %d to %d.\n\r",
	     wartype_name(war_info.wartype), war_info.min_level,
	     war_info.max_level);
    send_to_char(buf, ch);
    war_info.timer = 3;
    war_info.next = 0;
    for (wch = char_list; wch != NULL; wch = wch->next)
    {
	if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
	    REMOVE_BIT(wch->act, PLR_WAR);
    }
    return TRUE;
}

void auto_war(void)
{
    CHAR_DATA *wch, *wch_last, *warmaster;
    int maxlvl = 0, minlvl = MAX_LEVEL, middle = LEVEL_HERO / 2;
    int clan = 0, count = 0, lbonus = 0, half = 0;
    char buf[MAX_INPUT_LENGTH];

    if (war_info.iswar != WAR_OFF)
	return;

    for (wch = char_list; wch != NULL; wch = wch->next)
    {
	if (!IS_NPC(wch) && !IS_IMMORTAL(wch))
	{
	    count++;
	    maxlvl = UMAX(maxlvl, wch->level);
	    minlvl = UMIN(minlvl, wch->level);
	    if (is_clan(wch))
	    {
		for (wch_last = char_list; wch_last != NULL;
		     wch_last = wch_last->next)
		{
		    if (!IS_NPC(wch_last) && !IS_IMMORTAL(wch_last) && is_clan(wch_last) &&
			!is_same_clan(wch, wch_last))
			clan++;
		}
	    }
	}
    }

    if (count < 2)
    {
	end_war();
	return;
    }

    lbonus = number_range(5, 10);
    minlvl = UMAX(1, minlvl - lbonus);
    maxlvl = UMIN(LEVEL_HERO, maxlvl + lbonus);
    half = ((maxlvl - minlvl) / 2);
    middle = URANGE(minlvl, maxlvl - half, maxlvl);
    minlvl = number_range(minlvl, middle - lbonus);
    maxlvl = number_range(middle + lbonus, maxlvl);

    for(warmaster = char_list; warmaster != NULL; warmaster = warmaster->next)
    {
        if(!IS_NPC(warmaster))
            continue;
        if(warmaster->pIndexData->vnum == MOB_VNUM_WARMASTER)
            break;
    }

    war_info.iswar = WAR_WAITING;
    free_string(war_info.who);
    war_info.who =
      !warmaster ? str_dup("AutoWar (tm)") : str_dup(warmaster->short_descr);
    war_info.min_level = minlvl;
    war_info.max_level = maxlvl;

    if (clan >= 2)
	war_info.wartype = number_range(1, 4);
    else
	war_info.wartype = number_range(1, 3);

    sprintf(buf, "{G%s {B%s{x war for levels {G%d to {B%d%s{x.  Type 'WAR' to kill or be killed.",
	     !warmaster ? "A" : "$n announces a",
	     wartype_name(war_info.wartype), war_info.min_level,
	     war_info.max_level, !warmaster ? " has started" : "");
    war_channel(warmaster, buf);
    war_info.timer = 3;
    war_info.next = 0;
    for (wch = char_list; wch != NULL; wch = wch->next)
    {
	if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
	    REMOVE_BIT(wch->act, PLR_WAR);
    }
}

void end_war(void)
{
    CHAR_DATA *wch;

    free_string(war_info.who);
    war_info.who = str_dup("");
    war_info.wartype = 0;
    war_info.min_level = 0;
    war_info.max_level = 0;
    war_info.iswar = WAR_OFF;
    war_info.inwar = 0;
    war_info.timer = 0;
    war_info.next = number_range(30, 60);
    for (wch = char_list; wch != NULL; wch = wch->next)
    {
	if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
	{
	    stop_fighting(wch, TRUE);
	    REMOVE_BIT(wch->act, PLR_WAR);
	    if (IS_SET(wch->in_room->room_flags, ROOM_ARENA) ||
		wch->in_room->vnum == ROOM_VNUM_WAITROOM)
	    {
		char_from_room(wch);
		char_to_room(wch, get_room_index(ROOM_VNUM_TEMPLE));
	    }
	    wch->hit = wch->max_hit;
	    wch->mana = wch->max_mana;
	    wch->move = wch->max_move;
	    update_pos(wch);
            do_function( wch, &do_look, "auto" );
	}
    }
}

void do_war(CHAR_DATA *ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;
    int i = 0;

    if (IS_NPC(ch))
    {
	send_to_char("Mobiles not supported yet.\n\r", ch);
	return;
    }

    argument = one_argument(argument, arg);

    if (arg[0] == '\0')
    {
	send_to_char("Syntax:  {Rwar {Bstart <minlev> <maxlev> <#type>{x\n\r", ch);
	send_to_char("         {Rwar {Btalk <message>{x\n\r", ch);
	send_to_char("         {Rwar {Bstatus{x\n\r", ch);
	send_to_char("         {Rwar {Binfo{x\n\r", ch);
	send_to_char("         {Rwar {Bjoin{x\n\r", ch);
	if (IS_IMMORTAL(ch))
    {
	    send_to_char("         war end\n\r"
	                 "         war next\n\r", ch);
    }
	return;
    }

    else if (!str_cmp(arg, "start"))
    {
	start_war(ch, argument);
    return;
    }

    else if (!str_cmp(arg, "talk"))
    {
	war_talk(ch, argument);
	return;
    }

    else if (!str_cmp(arg, "next") && IS_IMMORTAL(ch))
    {
	if (war_info.iswar == TRUE)
	{
	    send_to_char("Not while a war is running.\n\r", ch);
	    return;
	}

	i = is_number(argument) ? atoi(argument) : number_range(30, 100);
	war_info.next = i;
	sprintf(buf, "The next war will start in %d minutes.\n\r",
	war_info.next);
        send_to_char(buf, ch);
	return;
    }

    if (war_info.iswar != TRUE)
    {
	sprintf(buf,
		 "Their is no war going! The next war will start in %d minutes.\n\r",
		 war_info.next);
        send_to_char(buf, ch);
	return;
    }

    if (!str_cmp(arg, "end") && IS_IMMORTAL(ch))
    {
	end_war();
	sprintf(buf, "You end the war. Next war in %d minutes.\n\r",
		 war_info.next);
    send_to_char(buf, ch);
	sprintf(buf, "$n has ended the war. The next autowar will start in %d minutes.",
		 war_info.next);
    war_channel(ch, buf);
	sprintf(buf, "You have ended the war. The next autowar will start in %d minutes.\n\r",
		 war_info.next);
    send_to_char(buf, ch);
	return;
    }
    else if (!str_cmp(arg, "info"))
    {
	sprintf(buf, "Started by  : %s\n\r",
		 war_info.who[0] == '\0' ? "Unknown" : war_info.who);
    send_to_char(buf, ch);
	sprintf(buf, "Fighting    : %d player%s.\n\r", war_info.inwar,
		 war_info.inwar == 1 ? "" : "s");
    send_to_char(buf, ch);
	sprintf(buf, "Levels      : %d - %d\n\r", war_info.min_level,
		 war_info.max_level);
    send_to_char(buf, ch);
	sprintf(buf, "Status      : %s for %d minutes.\n\r",
		 war_info.iswar == WAR_WAITING ? "Waiting" : "Running",
		 war_info.timer);
    send_to_char(buf, ch);
	sprintf(buf, "Type        : %s war.\n\r",
		 wartype_name(war_info.wartype));
    send_to_char(buf, ch);
	return;
    }
    else if (!str_cmp(arg, "check"))
    {
	CHAR_DATA *wch;
	bool found = FALSE;

	for (wch = char_list; wch != NULL; wch = wch->next)
	{
	    if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
	    {
		sprintf(buf,
			 "%-12s : [%ld%% hit] [%ld%% mana] [Pos: %s]\n\r",
			 wch == ch ? "You" : wch->name,
			 wch->hit * 100 / wch->max_hit,
			 wch->mana * 100 / wch->max_mana,
			 position_table[wch->position].short_name);
	    send_to_char(buf, ch);	 
		found = TRUE;
	    }
	}
	if (!found)
	    send_to_char("No one in the war yet.\n\r", ch);
	return;
    }
    else if (!str_cmp(arg, "join"))
    {
	if (war_info.iswar == WAR_RUNNING)
	{
	    send_to_char("The war has allready started, your too late.\n\r", ch);
	    return;
	}

	if (ch->level < war_info.min_level || ch->level > war_info.max_level)
	{
	    send_to_char("Sorry, you can't join this war.\n\r", ch);
	    return;
	}

	if (IS_SET(ch->act, PLR_WAR))
	{
	    send_to_char("You are already in the war.\n\r", ch);
	    return;
	}

        if (war_info.wartype == 4 && !is_clan(ch) )
	{
	    send_to_char("You aren't in a clan, you can't jon this war.\n\r", ch);
	    return;
	}

	if ((location = get_room_index(ROOM_VNUM_WAITROOM)) == NULL)
	{
	    send_to_char("The arena isn't completed yet, sorry.\n\r", ch);
	    return;
	}
	else
	{
	    act("$n has gone to join the war!", ch, NULL, NULL,
		TO_ROOM);
	    char_from_room(ch);
	    char_to_room(ch, location);
	    SET_BIT(ch->act, PLR_WAR);
	    sprintf(buf, "%s (Level %d) joins the war!", ch->name, ch->level);
            war_channel(NULL, buf);
	    act("$n has arrived to join the war!", ch, NULL, NULL, TO_ROOM);
	    war_info.inwar++;
            do_function( ch, &do_look, "auto" );
	}
	return;
    }

    auto_war( );    
    return;
}

bool abort_race_war(void)
{
    CHAR_DATA *ch;
    CHAR_DATA *vict;

    for (ch = char_list; ch != NULL; ch = ch->next)
    {
	if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WAR))
	{
	    for (vict = char_list; vict != NULL; vict = vict->next)
	    {
		if (!IS_NPC(vict) && IS_SET(vict->act, PLR_WAR))
		{
		    if (ch->race == vict->race)
			continue;
		    else
			return FALSE;
		}
	    }
	}
    }
    return TRUE;
}

bool abort_class_war(void)
{
    CHAR_DATA *ch;
    CHAR_DATA *vict;

    for (ch = char_list; ch != NULL; ch = ch->next)
    {
	if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WAR))
	{
	    for (vict = char_list; vict != NULL; vict = vict->next)
	    {
		if (!IS_NPC(vict) && IS_SET(vict->act, PLR_WAR))
		{
		    if (ch->klass == vict->klass)
			continue;
		    else
			return FALSE;
		}
	    }
	}
    }
    return TRUE;
}

bool abort_clan_war(void)
{
    CHAR_DATA *ch;
    CHAR_DATA *vict;

    for (ch = char_list; ch != NULL; ch = ch->next)
    {
	if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WAR) && is_clan(ch))
	{
	    for (vict = char_list; vict != NULL; vict = vict->next)
	    {
		if (!IS_NPC(vict) && IS_SET(vict->act, PLR_WAR) && is_clan(vict))
		{
		    if (is_same_clan(ch, vict))
			continue;
		    else
			return FALSE;
		}
	    }
	}
    }
    return TRUE;
}

void war_update ( void )
{
    char buf[MAX_STRING_LENGTH];

    if ( war_info.iswar == WAR_OFF && war_info.next > 0 )
    {
        if ( --war_info.next <= 0 )
            auto_war (  );
    }

    else if ( war_info.iswar == WAR_WAITING )
    {
        int randm = 0;

        war_info.timer--;

        if ( war_info.timer > 0 )
        {
            sprintf ( buf, "%d minute%s left to join the war. (Levels %d - %d, %s War)",
                       war_info.timer, war_info.timer == 1 ? "" : "s",
                       war_info.min_level, war_info.max_level,
                       wartype_name ( war_info.wartype ) );
            war_channel(NULL, buf);
        }
        else
        {
            if ( war_info.inwar < 2 )
            {
                end_war (  );
                sprintf ( buf, "Not enough people for a war.  Next autowar in %d minutes.",
                           war_info.next );
                war_channel(NULL, buf);
            }
            else if ( war_info.wartype == 1 && abort_race_war (  ) )
            {
                end_war (  );
                sprintf ( buf, "Not enough races for a war.  Next autowar in %d minutes.",
                           war_info.next );
                war_channel(NULL, buf);
            }
            else if ( war_info.wartype == 2 && abort_class_war (  ) )
            {
                end_war (  );
                sprintf ( buf, "Not enough classes for a war.  Next autowar in %d minutes.",
                           war_info.next );
                war_channel(NULL, buf);
            }
            else if ( war_info.wartype == 4 && abort_clan_war (  ) )
            {
                end_war (  );
                sprintf ( buf, "Not enough clans for a war.  Next autowar in %d minutes.",
                           war_info.next );
                war_channel(NULL, buf);
            }
            else
            {
                CHAR_DATA *wch;

                sprintf(buf,  "The battle begins! %d players are fighting!",
                           war_info.inwar );
                war_channel ( NULL, buf);
                          
                war_info.timer =
                    number_range ( 3 * war_info.inwar, 5 * war_info.inwar );
                war_info.iswar = WAR_RUNNING;
                for ( wch = char_list; wch != NULL; wch = wch->next )
                {
                    if ( !IS_NPC(wch) && IS_SET ( wch->act, PLR_WAR ) )
                    {
                        randm = number_range ( 12004, 12080  );
                        char_from_room ( wch );
                        char_to_room ( wch, get_room_index ( randm ) );
                        do_function ( wch, &do_look, "auto" );
                    }
                }
            }
        }
    }

    else if ( war_info.iswar == WAR_RUNNING )
    {
        if ( war_info.inwar == 0 )
        {
            end_war (  );
            sprintf ( buf, "No one left in the War, next war will start in %d minutes.",
                       war_info.next );
                war_channel(NULL, buf);
            return;
        }

        switch ( war_info.timer )
        {
            case 0:
                end_war (  );
                sprintf ( buf, "Time has run out on the War, next war will start in %d minutes.",
                           war_info.next );
                war_channel(NULL, buf);
                return;
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 10:
            case 15:
                sprintf ( buf, "%d minute%s remaining in the war.",
                           war_info.timer, war_info.timer > 1 ? "s" : "" );
                war_channel(NULL, buf);
            default:
                war_info.timer--;
                break;
        }
        return;
    }
}

void check_war(CHAR_DATA * ch, CHAR_DATA * victim)
{
    CHAR_DATA *wch;
    char buf[MAX_STRING_LENGTH];
    int reward = number_range(500, 1500);
    int qreward = number_range( 50, 150 );

    if (IS_NPC(ch) || IS_NPC(victim))
	return;

    REMOVE_BIT(victim->act, PLR_WAR);
    war_info.inwar--;
    stop_fighting(victim, TRUE);
    char_from_room(victim);
    char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
	victim->hit = UMAX(1, victim->hit);
	victim->mana = UMAX(1, victim->hit);
	victim->move = UMAX(1, victim->hit);
    update_pos(victim);
    do_look(victim, "auto");
    send_to_char("\n\r", ch);
    send_to_char("\n\r", victim);
    sprintf(buf, "%s was killed in combat by %s!",
	     victim->name, ch->name);
    war_channel(NULL, buf);
    switch (war_info.wartype)
    {
    case 1:
	if (abort_race_war())
	{
	    sprintf(buf, "The %s's have won the War!",
		     pc_race_table[ch->race].name);
            war_channel(NULL, buf);

	    for (wch = char_list; wch != NULL; wch = wch->next)
	    {
		if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
		    continue;

		if (wch->race == ch->race)
		{
		    wch->gold += reward;
                    wch->pcdata->questpoints += qreward;
		    sprintf(buf,
			     "You recieve %d gold and %d questpoints for winning the war!\n\r", reward, qreward );
		    send_to_char(buf, wch);
		}

	    }
	    end_war();
	    return;
	}			// end abort
	break;
    case 2:
	if (abort_class_war())
	{
	    sprintf(buf, "The %s's have won the War!", class_long( ch ) );
            war_channel(NULL, buf);

	    for (wch = char_list; wch != NULL; wch = wch->next)
	    {
		if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
		    continue;
		if (wch->klass == ch->klass)
		{
		    wch->gold += reward;
                    wch->pcdata->questpoints += reward;
		    sprintf(buf,
			     "You recieve %d gold and %d questpoints for winning the war!\n\r", reward, qreward );
			send_to_char(buf, wch);
		}
	    }
	    end_war();
	    return;
	}
	break;
    case 4:
	if (abort_clan_war())
	{
	    sprintf(buf, "%s has won the War!",
		     clan_table[ch->clan].who_name);
        war_channel(NULL, buf);
	    for (wch = char_list; wch != NULL; wch = wch->next)
	    {
		if (!IS_NPC(wch) && IS_SET(wch->act, PLR_WAR))
		    continue;
		if (is_same_clan(ch, wch))
		{
		    wch->gold += reward;
                    wch->pcdata->questpoints += qreward;
		    sprintf(buf,
			     "You recieve %d gold and %d questpoints for winning the war!\n\r", reward, qreward );
			send_to_char(buf, wch);
		}
	    }
	    end_war();
	    return;
	}
	break;
    case 3:
	if (war_info.inwar == 1)
	{
	    sprintf(buf, "%s has won the War!", ch->name); 
            war_channel(NULL, buf);
	    ch->gold += reward;
            ch->pcdata->questpoints += reward;
            sprintf(buf,
	             "You recieve %d gold and %d questpoints for winning the war!\n\r", reward, qreward );
			send_to_char(buf, ch);
	    end_war();
	    return;
	}
	break;
    }
    return;
}

bool is_safe_war(CHAR_DATA * ch, CHAR_DATA * wch)
{
    if (war_info.iswar == WAR_OFF)
	return FALSE;

    if (!IS_IN_WAR(ch) || !IS_IN_WAR(wch))
	return FALSE;

    if (war_info.wartype == 3)
	return FALSE;

    if (war_info.wartype == 1 && ch->race == wch->race)
	return TRUE;

    if (war_info.wartype == 2 && ch->klass == wch->klass)
	return TRUE;

    if (war_info.wartype == 4 && is_same_clan(ch, wch))
	return TRUE;

    return FALSE;
}

void war_talk(CHAR_DATA *ch, char *argument)
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];
    
    if (argument[0] == '\0')
    {
	send_to_char
	  ("Wartalk what?\n\r",
	   ch);
	return;
    }
    sprintf(buf, "(WarTalk) You drum: %s\n\r", argument);
	send_to_char(buf, ch);

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

	if (d->connected == CON_PLAYING && (victim = d->character) != ch &&
	    !IS_SET(victim->comm, COMM_QUIET) && IS_IN_WAR(victim))
	{
	    sprintf(buf, "(WarTalk) %s drums: %s\n\r",
		     PERS(ch, victim), argument);
		send_to_char(buf, victim);
    }
    }
    return;
}

void extract_war ( CHAR_DATA * ch )
{
    char buf[MAX_STRING_LENGTH];

    if ( war_info.iswar != WAR_OFF && IS_SET ( ch->act, PLR_WAR ) )
    {
        REMOVE_BIT ( ch->act, PLR_WAR );
        war_info.inwar--;
        if ( war_info.iswar == WAR_RUNNING )
        {
            if ( war_info.inwar == 0 || war_info.inwar == 1 )
            {
                war_channel ( ch, "$n has left. War over." );
                end_war (  );
            }
            if ( abort_race_war (  ) )
            {
                war_channel ( ch, "$n has left. War over." );
                end_war (  );
            }
            else if ( abort_class_war (  ) )
            {
                war_channel ( ch, "$n has left. War over." );
                end_war (  );
            }
            else if ( abort_clan_war (  ) )
            {
                war_channel ( ch, "$n has left. War over." );
                end_war (  );
            }
            else
            {
                sprintf ( buf, "$n has left. %d players in the war.",
                           war_info.inwar );
                war_channel(ch, buf);
            }
        }
       
        do_function( ch, &do_recall, "" );
    }
}

void war_channel(CHAR_DATA *ch, char *message)
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA *dch;
    char buf[MAX_INPUT_LENGTH];

    for(d = descriptor_list; d != NULL; d = d->next)
    {
        if(d->connected != CON_PLAYING)
            continue;

        if((dch = d->character) == NULL)
            continue;

        sprintf(buf, "WAR: %s", message);

        if(ch) /* don't use $N only $n in message */
            act(buf, ch, NULL, dch, TO_VICT);
        else
        {
            strcat(buf, "\n\r");
            send_to_char(buf, dch);
        }
    }
}