distorted/
distorted/area/
distorted/data/CLN/
#include <sys/types.h>
#include <sys/time.h> 
#include <malloc.h>
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <ctype.h> 
#include <time.h> 
#include "merc.h" 
 
DECLARE_DO_FUN(do_look     ); 
 
#define LESSER(x,y)             (((x) < (y)) ? (x) : (y)) 
#define GREATER(x,y)    (((x) > (y)) ? (x) : (y)) 
 
#define TEAM_MAX                6 



typedef struct _challenge_t 
{ 
        struct _challenge_t     *next; 
        int                     id; 
        int                     green; 
        int                     flags;    /* CC_???, defined below */ 
        char            *team1[TEAM_MAX]; 
        char            *team2[TEAM_MAX]; 
        int                     status1[TEAM_MAX]; 
        int                     status2[TEAM_MAX]; 
 
} challenge_t; 
 
/* condition flags */ 
#define CC_NOPOTIONS            0x001 
#define CC_NOSCROLLS            0x002 
#define CC_NOWIMPY              0x004 
 
/* status flags */ 
#define CS_ACCEPT               0x001 
#define CS_NORECALL             0x002 
#define CS_AFK                  0x004 
#define CS_CURSE                0x008 
 
// initialize status to CS_INIT 
// challenge can proceed only when everyone's status is CS_GO 
#define CS_INIT                 0 
#define CS_GO                   CS_ACCEPT 
 
challenge_t *chal_head = (challenge_t *)NULL; 
challenge_t  *cur_chal = (challenge_t *)NULL; 
int          challenge_count = 0; 
 
int in_current_challenge( char *pname ); 
static int named_in_challenge( char *pname, challenge_t *pchal ); 
static challenge_t *find_challenge( int cnum ); 
static void cleanup_challenge( challenge_t *pchal ); 
static void arena_message( char *message ); 
static void challenge_message( char *message, challenge_t *pchal ); 
static char *challenge_string( challenge_t *pchal, char *msg, int reverse ); 
static char *challenge_flags( challenge_t *pchal ); 
static int player_challenges( char *pname ); 
static int challenge_update( challenge_t *pchal ); 
static void start_duel( challenge_t *pchal ); 
static void challenge_status( int cnum, CHAR_DATA *ch ); 
static int challenge_finished( challenge_t *pchal ); 
static void noncom_check( void ); 
void arena_update args( ( void ) ); 
 
struct _cond 
{ 
        char    *keyword; 
        int             bit; 
        char    *name; 
        char    *flag; 
}; 
 
struct _cond cond_table[] = { 
        {"np",  CC_NOPOTIONS, "no_potions",   "{^P{x"}, 
        {"ns",  CC_NOSCROLLS, "no_scrolls",   "{!S{x"}, 
        {"nw",  CC_NOWIMPY,   "no_wimpy",     "{$W{x"}, 
        {NULL,  0,            NULL,              '\0'}, 
}; 
 
/*=======================================================================* 
 * function: arena_update 
 * purpose: called every tick from update.c.  check on stuff 
 *=======================================================================*/ 
void arena_update( void ) 
{ 
        challenge_t             *pchal,*pnext; 
        char                    buf[MAX_STRING_LENGTH]; 
        int                             winner,i; // whichteam; 
        CHAR_DATA               *pplayer;
//		CHAR_DATA				*pplayercheck; 
        CHAR_DATA               *rch;  
 
        // update all the individual challenges 
        for (pchal = chal_head; pchal; pchal = pnext ) 
        { 
                pnext = pchal->next; 
                challenge_update( pchal ); 
        } 
 
        // scan the arena and boot mortal non-combatants therefrom 
        noncom_check(); 
 
        // if any challenge is running, see if it's done.  You can tell because 
        // one team will be entirely absent from rooms ARENA_LO to ARENA_HI. 
        if ((cur_chal) && ((winner = challenge_finished(cur_chal)))) 
        { 
                // tell everyone about it 
                sprintf( buf, "[{$ARENA{x] Challenge [%d]:  ", cur_chal->id ); 
                strcat( buf, challenge_string(cur_chal,"DEFEATED ", ((winner == 2)) )); 
                strcat( buf, "{x\n\r" ); 
                arena_message( buf ); 
 
                // send everyone to lounge 
                for( i = 0; i < (2*TEAM_MAX); i++ ) 
                { 
                        if (cur_chal->team1[i] == NULL) 
                                continue; 
 
                        pplayer = get_char_anyone( NULL,cur_chal->team1[i] ); 

 
                        if (pplayer == NULL) 
                                continue; 
         
                for ( rch = pplayer->in_room->people; rch != NULL; rch = rch->next_in_room )  
                {                                                                
                        if ( rch->fighting != NULL )  
                                {                                           
                                stop_fighting( rch, TRUE );                                  
                        }                                                                        
                }
//Dusk
                        affect_strip(pplayer,skill_lookup("cripple"));
                        affect_strip(pplayer,skill_lookup("siphon energy"));
                        affect_strip(pplayer,skill_lookup("siphon life")); 
//JLR
                        affect_strip(pplayer,skill_lookup("poison"));
                        affect_strip(pplayer,skill_lookup("chill touch"));
                        affect_strip(pplayer,skill_lookup("fire breath"));
                        affect_strip(pplayer,skill_lookup("slow"));
                        affect_strip(pplayer,skill_lookup("weaken"));
                        affect_strip(pplayer,skill_lookup("curse"));
                        affect_strip(pplayer,skill_lookup("wither"));
                        affect_strip(pplayer,skill_lookup("blindness"));
                        affect_strip(pplayer,skill_lookup("blindness dust"));
                        affect_strip(pplayer,skill_lookup("plague"));
						affect_strip(pplayer,skill_lookup("shriek"));
                        affect_strip(pplayer,skill_lookup("sleep"));
//Tien
                        affect_strip(pplayer,skill_lookup("feeble mind"));
                        affect_strip(pplayer,skill_lookup("dirt kick"));
                        affect_strip(pplayer,skill_lookup("faerie fire"));
                        affect_strip(pplayer,skill_lookup("headache"));
                        affect_strip(pplayer,skill_lookup("adamantium palm"));
                        affect_strip(pplayer,skill_lookup("call lightning"));
                        affect_strip(pplayer,skill_lookup("prismatic spray"));
                        affect_strip(pplayer,skill_lookup("gouge"));
						affect_strip(pplayer,skill_lookup("charm person"));
/* Stheno/Revye */
						affect_strip(pplayer,skill_lookup("nerve"));				
						affect_strip(pplayer,skill_lookup("garrote"));				
						affect_strip(pplayer,skill_lookup("fear aura"));				
						affect_strip(pplayer,skill_lookup("burning skin"));				
						affect_strip(pplayer,skill_lookup("smokebomb"));				
						affect_strip(pplayer,skill_lookup("dirt kicking"));				
						affect_strip(pplayer,skill_lookup("voodan curse"));
						affect_strip(pplayer,skill_lookup("sense vitality"));
						/* affect_strip(pplayer,skill_lookup(""));				
						*/
						
			
			pplayer->hit = pplayer->max_hit;
                        pplayer->mana = pplayer->max_mana;
                        pplayer->move = pplayer->max_move;

//Jair
					/* This is a hack job to get arena wins and losses working */
 /*					whichteam=0;
					

					for( i = 0; (pchal->team1[i]) && (i<TEAM_MAX); i++ ) 
        			{ 
                		pplayercheck = get_char_anyone( NULL,pchal->team1[i] );
						if (pplayercheck == pplayer)
							whichteam=1;
			        } 

					for( i = 0; (pchal->team1[i]) && (i<TEAM_MAX); i++ ) 
        			{ 
                		pplayercheck = get_char_anyone( NULL,pchal->team1[i] );
						if (pplayercheck == pplayer)
							whichteam=2;
			        } 

						if (whichteam == winner)
							pplayer->pcdata->awins += 1;
						else
							pplayer->pcdata->alosses += 1;

*/

                        char_from_room(pplayer); 
                        char_to_room(pplayer, get_room_index(ROOM_ARENA_LOUNGE)); 
                        act ("$n appears in the room.", pplayer, NULL, NULL, TO_ROOM); 
                        do_look(pplayer, "auto" );
                } 
 
                cleanup_challenge( cur_chal ); 
                cur_chal = (challenge_t *)NULL; 
        } 
 
        // if no challenge is going, look for a green one 
        if (!cur_chal) 
        { 
                for (pchal=chal_head;(pchal) && (!pchal->green);pchal = pchal->next); 
 
                if (pchal) 
                { 
                        // we have a green challenge.  do it 
                        start_duel( pchal ); 
                } 
        } 
} 
 
/*=======================================================================* 
 * function: start_duel 
 * purpose: begin a duel.  transport everyone to the arena, do everything. 
 *=======================================================================*/ 
static void start_duel( challenge_t *pchal ) 
{ 
        challenge_t             *pc; 
        CHAR_DATA               *pplayer; 
        char                    buf[MAX_STRING_LENGTH]; 
        int                             i,start_pos; 
        ROOM_INDEX_DATA *start1,*start2; 
 
        assert(pchal); 
 
        // take pchal off the challenge list 
        if (chal_head == pchal) 
        {       // first entry on list 
                chal_head = pchal->next; 
        } 
        else 
        { 
                for (pc = chal_head; (pc->next) && (pc->next != pchal); pc = pc->next); 
 
                if (pc->next == pchal) 
                { 
                        pc->next = pchal->next; 
                } 
                else 
                {       // not on the list.  Bogus.  Just return. 
                        return; 
                } 
        } 
 
        // write it to cur_chal 
        cur_chal = pchal; 
 
        // tell everyone about it 
        sprintf( buf, "[{$ARENA{x] Challenge [%d]%s:  ", pchal->id, 
                challenge_flags( pchal )); 
        strcat( buf, challenge_string(pchal,"VERSUS ",FALSE )); 
        strcat( buf, "{Rhas begun!{x\n\r\n\r" ); 
        arena_message( buf ); 
 
        start_pos = ROOM_ARENA_LO + 1 + (rand() % (ROOM_ARENA_HI-ROOM_ARENA_LO)); 
        start1 = get_room_index(start_pos); 
        start_pos = ROOM_ARENA_LO + 1 + (rand() % (ROOM_ARENA_HI-ROOM_ARENA_LO)); 
        start2 = get_room_index(start_pos); 
 
        if ((start1 == NULL) || (start2 == NULL)) 
        { 
                bug ("Arena doesn't exist.",0); 
                cleanup_challenge(pchal); 
                cur_chal = NULL; 
                return; 
        } 
 
        // here's where we'd send all the people to the arena and stuff 
        for( i = 0; (pchal->team1[i]) && (i<TEAM_MAX); i++ ) 
        { 
                pplayer = get_char_anyone( NULL,pchal->team1[i] ); 
//		pplayer_orig = pplayer;
                char_from_room(pplayer); 
                char_to_room(pplayer, start1); 
        affect_strip(pplayer,gsn_plague);
        affect_strip(pplayer,gsn_poison);
        affect_strip(pplayer,gsn_blindness);
        affect_strip(pplayer,gsn_sleep);
        affect_strip(pplayer,gsn_curse);
        pplayer->hit    = pplayer->max_hit;
        pplayer->mana   = pplayer->max_mana;
        pplayer->move   = pplayer->max_move;
        update_pos(pplayer);
        send_to_char("You have been Pre-Arena Restored.\n",pplayer);
                act ("$n appears in the room.", pplayer, NULL, NULL, TO_ROOM); 
                do_look(pplayer, "auto" ); 
//              send_to_char( "If the arena were working, you'd be sent to the arena " 
//                      "now.\n\r", pplayer ); 
        } 
 
        for( i = 0; (pchal->team2[i]) && (i<TEAM_MAX); i++ ) 
        { 
                pplayer = get_char_anyone( NULL,pchal->team2[i] ); 
//                pplayer_orig = pplayer;
                char_from_room(pplayer); 
                char_to_room(pplayer, start2); 
         affect_strip(pplayer,gsn_plague);
        affect_strip(pplayer,gsn_poison);
        affect_strip(pplayer,gsn_blindness);
        affect_strip(pplayer,gsn_sleep);
        affect_strip(pplayer,gsn_curse);
        pplayer->hit    = pplayer->max_hit;
        pplayer->mana   = pplayer->max_mana;
        pplayer->move   = pplayer->max_move;
        update_pos(pplayer);
        send_to_char("You have been Pre-Arena Restored.",pplayer);
                act ("$n appears in the room.", pplayer, NULL, NULL, TO_ROOM); 
                do_look(pplayer, "auto" ); 
 
//              send_to_char( "If the arena were working, you'd be sent to the arena " 
//                      "now.\n\r", pplayer ); 
        } 
} 
 
/*=======================================================================* 
 * function: do_challenge 
 * purpose: sends initial arena match query 
 *=======================================================================*/ 
void do_challenge(CHAR_DATA *ch, char *argument) 
{ 
        CHAR_DATA               *victim;  
        char                    buf[MAX_STRING_LENGTH], arg[MAX_INPUT_LENGTH]; 
        int                             done = FALSE, i; 
        int                             team = 0; 
        int                             count = 0; 
        int                             reuse = FALSE; 
        int                             hilevel = 0, lowlevel = 0; 
        challenge_t             *pchal, *pc; 
 
        if(IS_NPC(ch)) 
                return;  
 
        if( arena == FIGHT_LOCK ) 
        { 
                send_to_char("Sorry, the arena is currently locked from use.\n\r",ch); 
                return; 
        }
        
        if(ch->hit < ch->max_hit*3/4)
        {
         send_to_char("You are not healthy enough to fight in the arena.\n\r",ch);
         return;
        }

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

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

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

        // challenge block? 
        if (!strcasecmp(argument, "block")) 
        { 
                if (IS_SET(ch->comm,COMM_NOARENA)) 
                { 
                        REMOVE_BIT(ch->comm,COMM_NOARENA); 
                        send_to_char("You will now receive arena updates and challenges.\n\r",ch); 
                } 
                else 
                { 
                        SET_BIT(ch->comm,COMM_NOARENA); 
                        send_to_char("You will no longer receive arena updates and challenges.\n\r",ch); 
                } 
 
                return; 
        } 
 
        // challenge list? 
        if (!strcasecmp(argument, "list")) 
        { 
                if (cur_chal) 
                { 
                        sprintf( buf, "Current challenge [%d]%s:  ", cur_chal->id, 
                                challenge_flags( cur_chal )); 
                        strcat(buf,challenge_string(cur_chal,"VERSUS ",FALSE)); 
                        strcat(buf,"\n\r"); 
                        send_to_char(buf,ch); 
                } 

                if (chal_head) 
                { 
                        for(pc=chal_head;pc;pc=pc->next) 
                        { 
                                sprintf( buf, "{%cChallenge [%d]%s:{x  ", 
                                        pc->green ? 'G' : 'R', pc->id, challenge_flags( pc )); 
                                strcat(buf,challenge_string(pc,"VERSUS ",FALSE)); 
                                strcat(buf,"\n\r"); 
                                send_to_char(buf,ch); 
                        } 
                } 
                else 
                        send_to_char("No pending challenges.\n\r",ch); 
                return; 
        } 
        // challenge status 
        if (!strncasecmp(argument, "status", 6 )) 
        { 
                argument = one_argument(argument,arg); 
                argument = one_argument(argument,arg); 
 
                if (arg[0] == 0) 
                { 
                        send_to_char("Give a challenge number.\n\r",ch); 
                        return; 
                } 
 
                challenge_status( atoi(arg), ch ); 
                return; 
 
        } 
 
 
        if ( IS_SET(ch->comm,COMM_NOARENA) ) 
        { 
                send_to_char("You're configured to ignore the arena.\n\r", ch ); 
                return; 
        } 

        if (ch->in_room->vnum == ROOM_VNUM_CORNER) 
                return; 

        if(argument[0] == '\0') 
        { 
                send_to_char("Usage: challenge [-conditions] <opponent1> [opponent2] ... [with] [teammate1] [teammate2] ....\n\r",ch); 
                return; 
        } 
 
        // so far so good.  allocate. 
        pchal = (challenge_t *)calloc(1L,sizeof(challenge_t));

        if (pchal == NULL) 
                return; 
 
        // write our name to the head of team1 
        pchal->team1[0] = strdup( ch->name ); 
        count = 0; 
 
        // set challeger accepted 
        pchal->status1[0] |= CS_ACCEPT; 
 
        // initialize hilevel and lowlevel 
        hilevel = ch->level; 
        lowlevel = ch->level; 
 
        // now peel off the names, one at a time 
        do 
        { 
                argument = one_argument(argument,arg); 
 
                // end of args? 
                if (arg[0] == 0) 
                { 
                        done = TRUE; 
                        continue; 
                } 
 
                // look for the team separator 
                if ((!strcmp(arg,"with")) && (team == 0)) 
                { 
                        if (count == 0) 
                        { 
                                send_to_char( "You need at least one player on the other t" 
                                        "eam.\n\r", ch ); 
                                cleanup_challenge( pchal ); 
                                return; 
                        } 
 
                        team++; 
                        count = 1; 
                        continue; 
                } 
 
                // condition flag? 
                if (arg[0] == '-') 
                { 
                        for (i=0; cond_table[i].keyword; i++) 
                        { 
                                if (!strcasecmp(&arg[1], cond_table[i].keyword)) 
                                        pchal->flags |= cond_table[i].bit; 
                        } 
 
                        continue; 
                } 
 
                // match name 
                victim = get_char_world(ch,arg); 
 
                // not found? 
                if (victim == NULL) 
                { 
                        sprintf( buf, "Bad target: %s\n\r", arg ); 
                        send_to_char( buf, ch ); 
                        cleanup_challenge(pchal); 
                        return; 
                } 
 
                // npc, immortal, or self?
                if(IS_NPC(victim) || victim == ch || victim == NULL) 
                { 
                        send_to_char("You cannot challenge NPC's, or yourself.\n\r",ch); 
                        cleanup_challenge(pchal); 
                        return; 
                }

                if(victim->hit < victim->max_hit*2/3)
                {
                 send_to_char("They are not healthy enough to fight in the arena.\n\r",ch);
                 return;
                }
                
                if( victim->fight_timer > 0 )
        	{
         		send_to_char("They cannot fight in the arena right now.\n\r",ch);
         		return;
        	}
 
                for (i=0; (pchal->team1[i]) && (i<TEAM_MAX); i++) 
                        if (!strcmp(victim->name,pchal->team1[i])) 
                                reuse = TRUE; 
 
                for (i=0; (pchal->team2[i]) && (i<TEAM_MAX); i++) 
                        if (!strcmp(victim->name,pchal->team2[i])) 
                                reuse = TRUE; 
 
                // already named? 
                if (reuse) 
                { 
                        send_to_char("Each player can be named only once in a given challenge.\n\r",ch); 
                        cleanup_challenge(pchal); 
                        return; 
                } 
 
                // noarena? 
                if ( IS_SET(victim->comm,COMM_NOARENA) ) 
                { 
                        sprintf( buf, "%s is blocking all challenges.\n\r", victim->name ); 
                        send_to_char( buf, ch ); 
                        cleanup_challenge( pchal ); 
                        return; 
                } 
 
                // named in too many? 
                if (player_challenges(victim->name) >= 4) 
                { 
                        sprintf( buf, "%s is already named in four challenges.  That's" 
                                        " the limit.\n\r", victim->name ); 
                        send_to_char(buf,ch); 
                        return; 
                } 
 
                // team full? 
                if (count >= TEAM_MAX) 
                { 
                        send_to_char("Team size limit exceeded.\n\r",ch); 
                        cleanup_challenge(pchal); 
                        return; 
                } 
 
                hilevel = GREATER(hilevel,victim->level); 
                lowlevel = LESSER(hilevel,victim->level); 
 
                // level range 
                if ((hilevel - lowlevel > 20) && (!IS_IMMORTAL(ch)))
                { 
                        send_to_char("All players in a challenge must be within 20 levels of one another.\n\r",ch); 
                        cleanup_challenge(pchal); 
                        return; 
                } 
 
                if (team) 
                { 
                        pchal->status1[count] = CS_INIT; 
                        pchal->team1[count++] = strdup( victim->name ); 
                } 
                else 
                { 
                        pchal->status2[count] = CS_INIT; 
                        pchal->team2[count++] = strdup( victim->name ); 
                } 
 
        } while ( !done ); 
 
        // valid challenge.  Move on. 
 
        // get an available challenge number 
        pchal->id = ++challenge_count; 
 
        // add challenge to the queue 
        if (chal_head) 
        { 
                // walk list, append to end 
                for (pc = chal_head; pc->next; pc = pc->next); 
                pc->next = pchal; 
        } 
        else 
        { 
                // no entries on list 
                chal_head = pchal; 
        } 
 
        // announce it 
        sprintf( buf, "[{$ARENA{x] Challenge [%d] issued!  ", pchal->id ); 
        strcat( buf, challenge_string(pchal,"VERSUS ",FALSE)); 
        strcat( buf, "\n\r" ); 
        strcat( buf, "Special Conditions:" ); 
        if (pchal->flags) 
        { 
                for( i = 0; cond_table[i].keyword; i++ ) 
                { 
                        if (pchal->flags & cond_table[i].bit) 
                        { 
                                strcat( buf, " " ); 
                                strcat( buf, cond_table[i].name ); 
                        } 
                } 
        } 
        else 
        { 
                strcat( buf, " None" ); 
        } 
        strcat( buf, "\n\r" ); 
        arena_message(buf); 
 
} 
 
/*=======================================================================* 
 * function: do_accept                                                   * 
 * purpose: to accept the arena match, and move the players to the arena * 
 *=======================================================================*/ 
void do_accept(CHAR_DATA *ch, char *argument) 
{ 
        int                     cnum, index; 
        char            buf[MAX_STRING_LENGTH]; 
        challenge_t     *pc; 
 
        if (argument[0] == '\0') 
        { 
                send_to_char("Accept challenges by number.\n\r",ch); 
                return; 
        } 
        
        if( ch->fight_timer > 0 )
        {
         	send_to_char("You cannot fight in the arena until your fight timer expires.\n\r",ch);
         	return;
        }
 
        cnum = atoi( argument ); 
 
        pc = find_challenge( cnum ); 
 
        if (!pc) 
        { 
                send_to_char("No such challenge.\n\r",ch); 
                return; 
        } 
 
        if (!(index = named_in_challenge( ch->name, pc ))) 
        { 
                send_to_char("You're not named in that challenge.\n\r",ch); 
                return; 
        } 
 
        // already accepted? 
        if (pc->status1[index-1] & CS_ACCEPT) 
        { 
                send_to_char("You've already accepted that challenge.\n\r", ch ); 
                return; 
        } 
 
        sprintf(buf,"[{$ARENA{x] Challenge %d accepted by %s.\n\r",cnum,ch->name); 
        arena_message(buf); 
        pc->status1[index-1] |= CS_ACCEPT; 
 
        // if this results in the challenge going green, do an update, so that 
        // the challenge may launch immediately. 
        if (challenge_update( pc )) 
        { 
                arena_update(); 
        } 
 
        return; 
} 
 
/*=======================================================================* 
 * function: do_decline                                                  * 
 * purpose: to chicken out from a sent arena challenge                   * 
 *=======================================================================*/ 
void do_decline(CHAR_DATA *ch, char *argument ) 
{ 
        int                     cnum; 
        char            buf[MAX_STRING_LENGTH]; 
        challenge_t     *pc; 
 
        if (argument[0] == '\0') 
        { 
                send_to_char("Decline challenges by number.\n\r",ch); 
                return; 
        } 
 
        cnum = atoi( argument ); 
 
        pc = find_challenge( cnum ); 
 
        if (!pc) 
        { 
                send_to_char("No such challenge.\n\r",ch); 
                return; 
        } 
 
        if ((!named_in_challenge( ch->name, pc )) && 
                (!IS_IMMORTAL(ch))) 
        { 
                send_to_char("You're not named in that challenge.\n\r",ch); 
                return; 
        } 
 
        sprintf(buf,"[{$ARENA{x] Challenge %d declined by %s.\n\r",cnum,ch->name); 
        arena_message(buf); 
        cleanup_challenge(pc); 
 
        return; 
} 
 
/*======================================================================* 
 * function: do_bet                                                     * 
 * purpose: to allow players to wager on the outcome of arena battles   * 
 *======================================================================*/ 
void do_bet(CHAR_DATA *ch, char *argument) 
{ 
        return;  
} 
 
/*=======================================================================* 
 * function: in_current_challenge 
 * purpose: returns 0 if player isn't in current challenge (or if there 
 * isn't one.)  Returns 1 if he's on team 1, 2 if he's on team 2 
 *=======================================================================*/ 
int in_current_challenge( char *pname ) 
{ 
        int                     index; 
 
        index = named_in_challenge( pname, cur_chal ); 
 
        if (index > TEAM_MAX) 
                return 2; 
 
        if (index) 
                return 1; 
 
        return 0; 
} 
 
/*=======================================================================* 
 * function: named_in_challenge                                          * 
 * purpose: returns TRUE if pname is named in challenge pchal            * 
 *=======================================================================*/ 
static int named_in_challenge( char *pname, challenge_t *pchal ) 
{ 
        int                     i; 
 
        if (pchal == (challenge_t *)NULL) 
                return 0; 
 
        for (i=0;(pchal->team1[i]) && (i<TEAM_MAX);i++) 
                if (!strcasecmp(pname,pchal->team1[i])) 
                        return i+1; 
 
        for (i=0;(pchal->team2[i]) && (i<TEAM_MAX);i++) 
                if (!strcasecmp(pname,pchal->team2[i])) 
                        return i+1+TEAM_MAX; 
 
        return FALSE; 
} 
 
/*=======================================================================* 
 * function: player_challenges 
 * purpose: counts the number of challenges in which a player is named 
 *=======================================================================*/ 
static int player_challenges( char *pname ) 
{ 
        challenge_t             *pc; 
        int                             count = 0; 
 
        for (pc=chal_head;pc;pc = pc->next) 
        { 
                if (named_in_challenge(pname, pc)) 
                        count++; 
        } 
 
        return count; 
} 
 
/*=======================================================================* 
 * function: find_challenge 
 * purpose: returns a pointer to the challenge with id cnum, NULL if none 
 *=======================================================================*/ 
static challenge_t *find_challenge( int cnum ) 
{ 
        challenge_t             *pc; 
 
        for (pc=chal_head;pc;pc = pc->next) 
                if (pc->id == cnum) 
                        return pc; 
 
        return (challenge_t *)NULL; 
} 
 
/*=======================================================================* 
 * function: arena_message 
 * purpose: send message to everyone who isn't NO_ARENA 
 *=======================================================================*/ 
 static void arena_message( char *message ) 
 { 
        DESCRIPTOR_DATA *d; 
 
        for (d=descriptor_list; d; d=d->next) 
        { 
                if ((d->connected == CON_PLAYING) && 
                        (!IS_SET(d->character->comm,COMM_NOARENA))) 
                        send_to_char(message,d->character); 
        } 
 } 
 
/*=======================================================================* 
 * function: challenge_message 
 * purpose: send message to everyone named in a given challenge 
 *=======================================================================*/ 
 static void challenge_message( char *message, challenge_t *pchal ) 
 { 
        int                     team,count; 
        CHAR_DATA       *pplayer; 
        char            **names; 
        int                     *status; 
 
        // loop through the players 
        for ( team = 0; team < 2; team++ ) 
        { 
                names = (team) ? pchal->team2 : pchal->team1; 
                status = (team) ? pchal->status2 : pchal->status1; 
 
                for (count = 0; (count < TEAM_MAX) && (names[count]); count++ ) 
                { 
                        // match name 
                        pplayer = get_char_anyone( NULL,names[count] ); 
 
                        // connected? 
                        if (pplayer != NULL) 
                                send_to_char( message, pplayer ); 
                } 
        } 
 } 
 
/*=======================================================================* 
 * function: challenge_status 
 * purpose: send status of challenge number cnum to player ch 
 *=======================================================================*/ 
static void challenge_status( int cnum, CHAR_DATA *ch ) 
{ 
        challenge_t     *pc; 
        char            buf[MAX_STRING_LENGTH]; 
        CHAR_DATA       *pplayer; 
        int                     i; 
 
        pc = find_challenge( cnum ); 
 
        if (pc == NULL) 
        { 
                send_to_char("No such challenge.\n\r", ch ); 
                return; 
        } 
 
        // print the title line 
        sprintf( buf, "{%cChallenge [%d]:{x  ", 
                pc->green ? 'G' : 'R', pc->id ); 
        strcat(buf,challenge_string(pc, "VERSUS ", FALSE)); 
        strcat(buf,"\n\r"); 
        strcat( buf, "Special Conditions:" ); 
        if (pc->flags) 
        { 
                for( i = 0; cond_table[i].keyword; i++ ) 
                { 
                        if (pc->flags & cond_table[i].bit) 
                        { 
                                strcat( buf, " " ); 
                                strcat( buf, cond_table[i].name ); 
                        } 
                } 
        } 
        else 
        { 
                strcat( buf, " None" ); 
        } 
        strcat( buf, "\n\r" ); 
        send_to_char(buf,ch); 
 
        if (pc->green) 
        { 
                send_to_char("Challenge is {GREADY{x.\n\r", ch ); 
                return; 
        } 
 
        send_to_char("Challenge is {RBLOCKED{x because:\n\r", ch ); 
 
        // now list each problem 
        for (i = 0; i < 2*TEAM_MAX; i++ ) 
        { 
                if (!(pc->team1[i])) 
                        continue; 
 
                // match the player 
                pplayer = get_char_anyone( NULL,pc->team1[i] ); 
 
                // player found? (should never happen) 
                if (pplayer == NULL) 
                { 
                        sprintf( buf, "> %s isn't connected.\n\r", pplayer->name ); 
                        send_to_char( buf, ch ); 
                } 
 
                // hasn't accepted? 
                if (!(pc->status1[i] & CS_ACCEPT)) 
                { 
                        sprintf( buf, "> %s hasn't accepted yet.\n\r", pplayer->name ); 
                        send_to_char( buf, ch ); 
                } 
 
                // cursed? 
                if (pc->status1[i] & CS_CURSE) 
                { 
                        sprintf( buf, "> %s hasn't accepted yet.\n\r", pplayer->name ); 
                        send_to_char( buf, ch ); 
                } 
 
                // afk? 
                if (pc->status1[i] & CS_AFK) 
                { 
                        sprintf( buf, "> %s is AFK.\n\r", pplayer->name ); 
                        send_to_char( buf, ch ); 
                } 
 
                // no-recall? 
                if (pc->status1[i] & CS_NORECALL) 
                { 
                        sprintf( buf, "> %s is in a no-recall area.\n\r", pplayer->name ); 
                        send_to_char( buf, ch ); 
                } 
        } 
} 
 
/*=======================================================================* 
 * function: cleanup_challenge 
 * purpose: frees all memory associated with a given challenge and 
 * removes it from the queue 
 *=======================================================================*/ 
static void cleanup_challenge( challenge_t *pchal ) 
{ 
	char			errmsg[MAX_STRING_LENGTH];
        int                             i; 
        challenge_t             *pc; 
        sprintf(errmsg,"Arena Check 3");
        log_string( errmsg );  
        // free up names 
        for (i=0;(pchal->team1[i]) && (i<TEAM_MAX);i++) 
        { 
                free( pchal->team1[i] ); 
                pchal->team1[i] = NULL; 
        } 
 
        for (i=0;(pchal->team2[i]) && (i<TEAM_MAX);i++) 
        { 
                free( pchal->team2[i] ); 
                pchal->team2[i] = NULL; 
        } 
 
        // take it off the list (if it's on) 
        if (chal_head == pchal) 
        {       // first entry on list 
                chal_head = pchal->next; 
        } 
        else if (chal_head) 
        { 
                for (pc = chal_head; (pc->next) && (pc->next != pchal); pc = pc->next); 
 
                if (pc->next == pchal) 
                        pc->next = pchal->next; 
        } 
 
        // now free the challenge itself 
        free(pchal); 
        return; 
} 
 
 
/*=======================================================================* 
 * function: challenge_string 
 * purpose: write a brief description of a challenge to a static buffer 
 * and return a pointer thereto. 
 *=======================================================================*/ 
static char *challenge_string( challenge_t *pchal, char *msg, int reverse ) 
{ 
        static char buf[MAX_STRING_LENGTH]; 
        int                     i; 
        char            **first, **second; 
 
        if (reverse) 
        { 
                first = pchal->team2; 
                second = pchal->team1; 
        } 
        else 
        { 
                first = pchal->team1; 
                second = pchal->team2; 
        } 
 
        buf[0] = '\0'; 
 
        // announce it 
        for( i = 0; (first[i]) && (i<TEAM_MAX); i++ ) 
        { 
                strcat(buf,first[i]); 
                strcat(buf," "); 
        } 
 
        strcat( buf, msg ); 
 
        for( i = 0; (second[i]) && (i<TEAM_MAX); i++ ) 
        { 
                strcat(buf,second[i]); 
                strcat(buf," "); 
        } 
 
        return buf; 
} 
 
/*=======================================================================* 
 * function: challenge_flags 
 * purpose: write a short string containing challenge flags 
 *=======================================================================*/ 
static char *challenge_flags( challenge_t *pchal ) 
{ 
        static char     buf[MAX_STRING_LENGTH]; 
        int                     i = 0,j; 
 
        sprintf( buf, "{x(" ); 
        for( j=0; cond_table[j].keyword; j++ ) 
        { 
                if (pchal->flags & cond_table[j].bit) 
                { 
                        strcat( buf, cond_table[j].flag ); 
                        i++; 
                } 
        } 
        strcat( buf, ")" ); 
 
        if (i == 0) 
                buf[0] = '\0'; 
 
        return buf; 
} 
 
/*=======================================================================* 
 * function: challenge_update 
 * purpose: updates the status bits of a given challenge 
 * returns TRUE if the challenge goes green as of this update 
 *=======================================================================*/ 
static int challenge_update( challenge_t *pchal ) 
{ 
        static char buf[MAX_STRING_LENGTH]; 
        int                     team,count; 
        CHAR_DATA       *pplayer; 
        char            **names; 
        int                     *status; 
        int                     green, retval = FALSE; 
 
        green = TRUE; 
 
        // loop through the players 
        for ( team = 0; team < 2; team++ ) 
        { 
                names = (team) ? pchal->team2 : pchal->team1; 
                status = (team) ? pchal->status2 : pchal->status1; 
 
                for (count = 0; (count < TEAM_MAX) && (names[count]); count++ ) 
                { 
                        // match name 
                        pplayer = get_char_anyone( NULL,names[count] ); 
 
                        // connected? 
                        if (pplayer == NULL) 
                        { 
                                sprintf( buf, "Challenge [%d] expires - %s has quit.\n", 
                                        pchal->id, names[count] ); 
                                challenge_message( buf, pchal ); 
                                cleanup_challenge(pchal); 
                                return FALSE; 
                        } 
 
                        // no recall? 
                        if (IS_SET(pplayer->in_room->room_flags,ROOM_NO_RECALL)) 
                                status[count] |= CS_NORECALL; 
                        else 
                                status[count] &= ~CS_NORECALL; 
 
                        // afk? 
                        if (IS_SET(pplayer->comm,COMM_AFK)) 
                                status[count] |= CS_AFK; 
                        else 
                                status[count] &= ~CS_AFK; 
 
                        // curse? 
                        if (IS_AFFECTED(pplayer,AFF_CURSE)) 
                                status[count] |= CS_CURSE; 
                        else 
                                status[count] &= ~CS_CURSE; 
 
                        // still green? 
                        if (status[count] != CS_GO) 
                                green = FALSE; 
                } 
        } 
 
        if (green != pchal->green) 
        { 
                sprintf( buf, "Challenge [%d] is now %s.\n", pchal->id, 
                        green ? "{GREADY{x" : "{RBLOCKED{x" ); 
                challenge_message( buf, pchal ); 
                if (green) 
                        retval = TRUE; 
        } 
 
        pchal->green = green; 
 
        return retval; 
} 
 
/*=======================================================================* 
 * function: challenge_finished 
 * purpose: returns 0 if challenge isn't done yet, 1 if team 1 won, 2 if 
 * team 2 won. 
 *=======================================================================*/ 
static int challenge_finished( challenge_t *pchal ) 
{ 
        int                     i,found; 
        CHAR_DATA       *pc; 
 
        found = FALSE; 
 
        // is team 1 entirely absent from rooms ARENA_LO to ARENA_HI? 
        for (i = 0; (pchal->team1[i]) && (i<TEAM_MAX) && (!found); i++) 
        { 
                pc = get_char_anyone( NULL,pchal->team1[i] ); 
 
                if ((pc) && (pc->in_room->vnum >= ROOM_ARENA_LO) && 
                        (pc->in_room->vnum <= ROOM_ARENA_HI)) 
                        found = TRUE; 
        } 
 
        if (!found) 
                return 2; 
         
        found = FALSE; 
 
        // is team 2 entirely absent from rooms ARENA_LO to ARENA_HI? 
        for (i = 0; (pchal->team2[i]) && (i<TEAM_MAX) && (!found); i++) 
        { 
                pc = get_char_anyone( NULL,pchal->team2[i] ); 
 
                if ((pc) && (pc->in_room->vnum >= ROOM_ARENA_LO) && 
                        (pc->in_room->vnum <= ROOM_ARENA_HI)) 
                        found = TRUE; 
        } 
 
        if (!found) 
                return 1; 
 
        return 0; 
         
} 
 
/*=======================================================================* 
 * function: noncom_check 
 * purpose: scan arena for mortals who shouldn't be there & remove them. 
 *=======================================================================*/ 
static void noncom_check( void ) 
{ 
        DESCRIPTOR_DATA *d; 
 
        for (d=descriptor_list; d; d=d->next) 
        { 
                // ignore them if they're disconnected 
                if (d->connected != CON_PLAYING) 
                        continue; 
 
                // ignore them if they're not in the arena 
                if ((d->character->in_room->vnum < ROOM_ARENA_LO) || 
                        (d->character->in_room->vnum > ROOM_ARENA_MORGUE)) 
                        continue; 
 
                // ignore if they're in the arena lounge 
                if (d->character->in_room->vnum == ROOM_ARENA_LOUNGE) 
                        continue; 
 
                // ignore them if they're named in the current challenge 
                if ((cur_chal) && (named_in_challenge(d->character->name,cur_chal))) 
                        continue; 
 
                // let immortals hang around if they want 
                if (IS_IMMORTAL(d->character)) 
                        continue; 
 
                // boot 'em to lounge 
                send_to_char("You've been auto-removed from the arena.\n\r", 
                        d->character ); 
                char_from_room(d->character); 
                char_to_room(d->character, get_room_index(ROOM_ARENA_LOUNGE)); 
                act ("$n appears in the room.", d->character, NULL, NULL, TO_ROOM); 
                do_look(d->character, "auto" ); 
 
        } 
 } 
 
/*=======================================================================* 
 * function: arena_can_quaff 
 * purpose: returns FALSE if ch is in arena during a challenge that forbids 
 * use of potions, true otherwise 
 *=======================================================================*/ 
int arena_can_quaff( CHAR_DATA *ch ) 
{ 
        if (!cur_chal) 
                return TRUE; 
 
        if (!IN_ARENA(ch)) 
                return TRUE; 
 
        if (!(cur_chal->flags & CC_NOPOTIONS)) 
                return TRUE; 
 
        send_to_char( "No potions may be used during this duel.\n\r", ch ); 
 
        return FALSE; 
} 
 
/*=======================================================================* 
 * function: arena_can_recite 
 * purpose: returns FALSE if ch is in arena during a challenge that forbids 
 * use of scrolls, true otherwise 
 *=======================================================================*/ 
int arena_can_recite( CHAR_DATA *ch ) 
{ 
        if (!cur_chal) 
                return TRUE; 
 
        if (!IN_ARENA(ch)) 
                return TRUE; 
 
        if (!(cur_chal->flags & CC_NOSCROLLS)) 
                return TRUE; 
 
        send_to_char( "No scrolls may be used during this duel.\n\r", ch ); 
 
        return FALSE; 
} 
 
/*=======================================================================* 
 * function: arena_can_wimpy 
 * purpose: returns FALSE if ch is in arena during a challenge that forbids 
 * use of wimpy, true otherwise 
 *=======================================================================*/ 
int arena_can_wimpy( CHAR_DATA *ch ) 
{ 
        if (!cur_chal) 
                return TRUE; 
 
        if (!IN_ARENA(ch)) 
                return TRUE; 
 
        if (!(cur_chal->flags & CC_NOWIMPY)) 
                return TRUE; 
 
        return FALSE; 
} 
 
/*=======================================================================*/