/*
 * itcombat.c       Routines to handle inter-terminal combat
 */
#include "include.h"
/***************************************************************************
/ FUNCTION NAME: Do_opponent_struct(struct client_t *c, struct opponent_t *theOpponent)
/
/ FUNCTION: Check to see if a player entered an occupied square
/
/ AUTHOR:  Brian Kelly, 8/16/99
/
/ ARGUMENTS: 
/	struct server_t s - the server strcture
/	struct game_t this_game - pointer to the player we're checking
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/
void Do_opponent_struct(struct client_t *c, struct opponent_t *theOpponent)
{
    char string_buffer[SZ_LINE];
    c->battle.ring_in_use = FALSE;
    c->battle.melee_damage = 0.0;
    c->battle.skirmish_damage = 0.0;
    c->battle.tried_luckout = FALSE;
    strcpy(theOpponent->name, c->modifiedName);
    theOpponent->processID = c->game->clientPid;
      /* passable experience = all player exp now that nicking is capped */
      /* Kings and higher are immune to nicking */
    if  (c->player.special_type >= SC_KING) {
	theOpponent->experience = 0.0;
    }
    else {
        theOpponent->experience = floor(c->player.experience /
                (30 * c->player.level + 1));
    }
    theOpponent->strength = c->player.strength + c->player.sword;
    theOpponent->max_strength = theOpponent->strength;
    theOpponent->energy = c->player.energy;
    theOpponent->max_energy = c->player.max_energy + c->player.shield;
    theOpponent->speed = c->player.quickness + 1;
    theOpponent->max_speed = theOpponent->speed;
    theOpponent->brains = c->player.brains;
    theOpponent->size = c->player.level;
    /* the bigger they are, the harder they fall to all or nothing */
    theOpponent->sin = c->player.sin + floor(c->player.level / 100);
    sprintf(string_buffer, 
            "%s, %s, Level %.0lf, Sin %.0f has effective Sin of %.0lf\n",
            c->player.lcname, 
            c->realm->charstats[c->player.type].class_name, 
            c->player.level,
            c->player.sin,
            theOpponent->sin);
    Do_log(COMBAT_LOG, string_buffer);
    theOpponent->shield = 0;
    theOpponent->special_type = SM_IT_COMBAT;
    theOpponent->treasure_type = 0;
    theOpponent->flock_percent = 0;
        /* throw up spells for combat */
    Do_starting_spells(c);
}
/***************************************************************************
/ FUNCTION NAME: Do_setup_it_combat(struct client_t *c, struct game_t *theGame)
/
/ FUNCTION: Check to see if a player entered an occupied square
/
/ AUTHOR:  Brian Kelly, 8/16/99
/
/ ARGUMENTS: 
/	struct server_t s - the server strcture
/	struct game_t this_game - pointer to the player we're checking
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/
Do_setup_it_combat(struct client_t *c, struct game_t *theGame)
{
float ftemp;
/* WARNING: c->realm->realm_lock is passed LOCKED! */
/*
    Do_lock_mutex(&c->realm->realm_lock);
*/
    struct it_combat_t *theCombat;
    struct event_t *event_ptr;
    struct it_combat_t *it_combat_ptr;
    char string_buffer[SZ_LINE];
    theCombat = (struct it_combat_t *) Do_malloc(SZ_IT_COMBAT);
    theCombat->opponentFlag[0] = FALSE;
    theCombat->opponentFlag[1] = FALSE;
    theCombat->next_opponent = NULL;
    theCombat->player_ptr = NULL;
    Do_init_mutex(&theCombat->theLock);
    c->game->it_combat = theCombat;
    if (theGame->it_combat == NULL) {
	theGame->it_combat = theCombat;
        Do_unlock_mutex(&c->realm->realm_lock);
	event_ptr = (struct event_t *) Do_create_event();
	event_ptr->type = IT_COMBAT_EVENT;
	event_ptr->arg4 = theCombat;
	event_ptr->to = theGame;
	event_ptr->from = c->game;
	Do_send_event(event_ptr);
        Do_send_clear(c);
        if (c->player.blind)
            sprintf(string_buffer,
		    "You hear another player nearby!\n");
	else
            sprintf(string_buffer,
		    "You see another player in the distance!\n");
    }
    else {
	
	it_combat_ptr = theGame->it_combat;
	while (it_combat_ptr->next_opponent != NULL)
	    it_combat_ptr = it_combat_ptr->next_opponent;
	it_combat_ptr->next_opponent = theCombat;
        Do_unlock_mutex(&c->realm->realm_lock);
        Do_send_clear(c);
        if (c->player.blind)
            sprintf(string_buffer,
		    "You sense that several players are nearby!\n");
	else
            sprintf(string_buffer,
		    "You see several players in the distance!\n");
    }
    Do_send_line(c, string_buffer);
    Do_lock_mutex(&theCombat->theLock);
    Do_opponent_struct(c, &theCombat->opponent[0]);
    c->battle.opponent = &theCombat->opponent[1];
    Do_unlock_mutex(&theCombat->theLock);
	/* for attacking another player, pick up sin */
    Do_sin(c, .5);
    sprintf(string_buffer, "%s ATTACKED another player.\n", c->player.lcname);
    Do_log(BATTLE_LOG, string_buffer);
    Do_send_line(c, "Waiting for the other player(s)...\n");
    Do_it_combat_turns(c, theCombat, &theCombat->opponent[0],
	    &theCombat->opponentFlag[0], &theCombat->opponentFlag[1]);
    return;
}
/***************************************************************************
/ FUNCTION NAME: Do_it_combat(struct client_t *c, struct event_t *theEvent)
/
/ FUNCTION: Check to see if a player entered an occupied square
/
/ AUTHOR:  Brian Kelly, 8/16/99
/
/ ARGUMENTS: 
/	struct server_t s - the server strcture
/	struct game_t this_game - pointer to the player we're checking
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/
Do_it_combat(struct client_t *c, struct event_t *theEvent, int available)
{
    struct it_combat_t *theCombat;
    char string_buffer[SZ_LINE];
    Do_send_clear(c);
    theCombat = (struct it_combat_t *) theEvent->arg4;
    Do_lock_mutex(&theCombat->theLock);
	/* if our flag is set, there is a problem */
    if (!theCombat->opponentFlag[1]) {
        theCombat->opponentFlag[0] = TRUE;
        theCombat->opponentFlag[1] = FALSE;
        Do_opponent_struct(c, &theCombat->opponent[1]);
        if (c->player.energy <= 0) {
	    theCombat->message = IT_JUST_DIED;
            Do_unlock_mutex(&theCombat->theLock);
            kill(theCombat->opponent[0].processID ,SIGIO);
            Do_lock_mutex(&c->realm->realm_lock);
            c->game->it_combat = NULL;
            Do_unlock_mutex(&c->realm->realm_lock);
	    return;
        }
        else if (!available) {
	    theCombat->message = IT_JUST_LEFT;
            Do_unlock_mutex(&theCombat->theLock);
            kill(theCombat->opponent[0].processID ,SIGIO);
            Do_lock_mutex(&c->realm->realm_lock);
            c->game->it_combat = NULL;
            Do_unlock_mutex(&c->realm->realm_lock);
	    return;
        }
        else {
            theCombat->message = IT_REPORT;
	}
    }
    c->battle.opponent = &theCombat->opponent[0];
    if (c->player.blind) {
	if (c->stuck) {
	    c->stuck = FALSE;
            sprintf(string_buffer,
	       "Before you can move, you hear another player in the area!\n");
	}
	else {
            sprintf(string_buffer,
		    "You hear another player approach!\n");
	}
    }
    else {
	if (c->stuck) {
	    c->stuck = FALSE;
	    sprintf(string_buffer,
		    "Before you can move, %s enters the area!\n",
		    theCombat->opponent[0].name);
	}
	else {
	    sprintf(string_buffer,
		    "You see %s approaching from the distance!\n",
		    theCombat->opponent[0].name);
	}
    }
    Do_unlock_mutex(&theCombat->theLock);
    kill(theCombat->opponent[0].processID ,SIGIO);
    Do_send_line(c, string_buffer);
    Do_send_buffer(c);
    sleep(2);
    Do_it_combat_turns(c, theCombat, &theCombat->opponent[1],
	    &theCombat->opponentFlag[1], &theCombat->opponentFlag[0]);
    return;
}
/***************************************************************************
/ FUNCTION NAME: void Do_it_combat_turn(struct client_t *c, struct it_combat_t *theCombat, struct opponent_t *myStats, bool *my Flag, bool *hisFlag)
/
/ FUNCTION: Check to see if a player entered an occupied square
/
/ AUTHOR:  Brian Kelly, 8/16/99
/
/ ARGUMENTS: 
/	struct server_t s - the server strcture
/	struct game_t this_game - pointer to the player we're checking
/
/ RETURN VALUE: none
/
/ MODULES CALLED: monstlist(), checkenemy(), activelist(),
/       throneroom(), checkbattle(), readmessage(), changestats(), writerecord()
,
/       tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampe
red(),
/       fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(),
/       signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(),
/       strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain()
,
/       playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initials
tate(),
/       scorelist(), titlelist()
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/
Do_it_combat_turns(struct client_t *c, struct it_combat_t *theCombat,
	struct opponent_t *myStats, bool *myFlag, bool *hisFlag)
{
    short theMessage;
    double theArg;
    short newMessage;
    double newArg;
    char string_buffer[SZ_LINE];
    char error_msg[SZ_ERROR_MESSAGE];
    struct event_t *event_ptr;
    struct realm_object_t *object_ptr;
    float ftemp;
    for (;;) {
	c->timeoutFlag = 0;
	Do_wait_flag(c, myFlag, &theCombat->theLock); 
            /* handle our flag  */
	Do_lock_mutex(&theCombat->theLock);
	    /* see if the player timed out */
	if (c->timeoutFlag && theCombat->message != IT_BORED) {
	    theMessage = IT_ABANDON;
	}
	else {
	    theMessage = theCombat->message;
	    theArg = theCombat->arg1;
	    *myFlag = FALSE;
	}
            /* unlock the flags so the other thread can check it  */
	Do_unlock_mutex(&theCombat->theLock);
	    /* if the other thread received an event, we're server */
	if (theMessage == IT_REPORT) {
	    if (c->player.blind)
	        sprintf(string_buffer,
			"You have encountered another player.\n");
	    else {
		sprintf(string_buffer, "You have encountered %s.\n",
			c->battle.opponent->name);
	        Do_send_line(c, string_buffer);
	    }
		/* defender always attacks first */
	    theMessage = IT_DEFEND;
	}
	    /* battle continues, decide who goes next */
	if (theMessage == IT_CONTINUE) {
	    if (RND() * c->battle.opponent->speed > RND() *
		    myStats->speed) {
		theMessage = IT_DEFEND;
	    }
	    else
		theMessage = IT_ECHO;
	}
	    /* if the opponent just left the game */
	if (theMessage == IT_JUST_LEFT) {
	    sprintf(string_buffer,
		    "You arrive just to see %s vanish from the realm.\n",
		    c->battle.opponent->name);
	    Do_send_line(c, string_buffer);
	    c->battle.opponent->experience = 0.0;
	    theMessage = IT_DEFEAT;
	}
	    /* if the opponent passes on combat */
	if (theMessage == IT_JUST_DIED) {
	    sprintf(string_buffer, "%s falls dead at your feet.\n",
		    c->battle.opponent->name);
	    Do_send_line(c, string_buffer);
	    c->battle.opponent->experience = 0.0;
	    theMessage = IT_DEFEAT;
	}
	    /* if the opponent passes on combat */
	if (theMessage == IT_BORED) {
	    sprintf(string_buffer,
		    "%s became bored and left the battlefield.\n",
		    c->battle.opponent->name);
	    Do_send_line(c, string_buffer);
	    c->battle.opponent->experience = 0.0;
	    theMessage = IT_DEFEAT;
	}
	    /* if the opponent is having network trouble */
	if (theMessage == IT_CONCEDE) {
	    sprintf(string_buffer, "%s concedes the battle.\n",
		    c->battle.opponent->name);
	    Do_send_line(c, string_buffer);
	    theMessage = IT_DEFEAT;
	}
	newMessage = IT_CONTINUE;
	string_buffer[0] = '\0';
	switch (theMessage) {
	    /* we've encountered a problem - every thread for himself */
	case IT_ABANDON:
            sprintf(error_msg,
		    "[%s] now abandoning it_combat in Do_it_combat_turns.\n",
                    c->connection_id);
            Do_log_error(error_msg);
		/* leave a message for our opponent */
	    theCombat->message = IT_BORED;
	    Do_lock_mutex(&theCombat->theLock);
	    *hisFlag = TRUE;
	    Do_unlock_mutex(&theCombat->theLock);
	    kill(c->battle.opponent->processID, SIGIO);
                /* clear any spells */
            Do_energy(c, c->player.energy, c->player.max_energy,
                    c->player.shield, 0.0, FALSE);
            Do_strength(c, c->player.max_strength, c->player.sword, 0, FALSE);
            Do_speed(c, c->player.max_quickness, c->player.quicksilver, 0,
                    FALSE);
                /* pull ourselves out of combat */
            Do_lock_mutex(&c->realm->realm_lock);
            c->game->it_combat = NULL;
	    c->game->virtual = TRUE;
            Do_unlock_mutex(&c->realm->realm_lock);
		/* get away from this square and this battle */
            event_ptr = (struct event_t *) Do_create_event();
            event_ptr->to = c->game;
            event_ptr->from = c->game;
            event_ptr->type = MOVE_EVENT;
	    event_ptr->arg3 = A_NEAR;
            Do_file_event(c, event_ptr);
            return;
	    /* we decided to attack, so have the opponent echo an attack */
	case IT_ECHO:
	    newMessage = IT_DEFEND;
	    break;
	    /* we are to attack */
	case IT_ATTACK:
	        /* give the character fatigue */
	    ++c->battle.rounds;
	    Do_speed(c, c->player.max_quickness, c->player.quicksilver,
	            c->battle.speedSpell, FALSE);
	    myStats->speed = c->player.quickness;
                /* if the player has a ring in use */
            if (c->battle.ring_in_use) {
                    /* age ring */
                if (c->player.ring_type != R_DLREG) {
                    --c->player.ring_duration;
                }
                    /* regardless of ring type, heal the character */
                Do_energy(c, c->player.max_energy + c->player.shield,
                        c->player.max_energy, c->player.shield,
                        c->battle.force_field, FALSE);
            }
	    Do_send_line(c,
		    "You attack this round.  Please choose your attack:\n");
	    Do_playerhits(c, &newMessage, &newArg);
		/* if the player put up a shield, copy the info over */
	    if (newMessage == IT_SHIELD) {
		myStats->shield = c->battle.force_field;
	    }
	    break;
	    /* we are to defend */
	case IT_DEFEND:
	    sprintf(string_buffer,
		   "%s attacks for this round.  Please wait for a decision.\n",
		   c->battle.opponent->name);
	    newMessage = IT_ATTACK;
	    break;
	    /* the other thread is declaring victory */
	case IT_VICTORY:
	    newMessage = IT_DEFEAT;
		/* clear any spells */
	    Do_energy(c, c->player.energy, c->player.max_energy,
		    c->player.shield, 0.0, FALSE);
	    Do_strength(c, c->player.max_strength, c->player.sword, 0, FALSE);
	    Do_speed(c, c->player.max_quickness, c->player.quicksilver, 0,
		    FALSE);
	    c->battle.force_field = 0;
	    c->battle.strengthSpell = 0;
	    c->battle.speedSpell = 0;
	    break;
	    /* the other thread stands defeated - we clean up */
	case IT_DEFEAT:
		/* award experience if there is any to be had */
	    if (c->battle.opponent->experience) {
		Do_experience(c, c->battle.opponent->experience, FALSE);
		    /* for killing another player, pick up sin */
		Do_sin(c, sqrt(c->battle.opponent->size) / 3.1);
sprintf(error_msg, "%s KILLED %s in IT combat.\n", c->player.lcname,
c->battle.opponent->name);
Do_log(BATTLE_LOG, error_msg);
	    }
		/* clear any spells */
	    Do_energy(c, c->player.energy, c->player.max_energy,
		    c->player.shield, 0.0, FALSE);
	    Do_strength(c, c->player.max_strength, c->player.sword, 0, FALSE);
	    Do_speed(c, c->player.max_quickness, c->player.quicksilver, 0,
		    FALSE);
	    c->battle.force_field = 0;
	    c->battle.strengthSpell = 0;
	    c->battle.speedSpell = 0;
		/* if we're in the throne room and are not king */
		/* become king NOW (another battle may be pending) */
	    if (c->player.location == PL_THRONE && c->player.special_type !=
		    SC_KING && c->player.special_type != SC_STEWARD) {
		    /* become steward */
        	if (c->player.level >= 10 && c->player.level < 200) {
		    Do_steward(c);
		}
        	else if (c->player.level >= 1000 && c->player.level < 2000) {
		    Do_king(c);
		}
	    }
	    Do_lock_mutex(&c->realm->realm_lock);
		/* if there are no more battles to fight */
	    if (theCombat->next_opponent == NULL) {
		    /* pull ourselves out of combat */
	        c->game->it_combat = NULL;
	        Do_unlock_mutex(&c->realm->realm_lock);
		    /* create a body event for ourselves */
		    /* opponent put player struct here if he will die */
	        if (theCombat->player_ptr != NULL) {
		    event_ptr = (struct event_t *) Do_create_event();
		    event_ptr->to = c->game;
		    event_ptr->from = c->game;
		    event_ptr->type = CORPSE_EVENT;
		        /* the body can be cursed */
		    event_ptr->arg1 = TRUE;
		    event_ptr->arg4 = theCombat->player_ptr;
		    Do_file_event(c, event_ptr);
	        }
	    }
		/* if there are more opponents to fight */
	    else {
	        event_ptr = (struct event_t *) Do_create_event();
                event_ptr->to = c->game;
                event_ptr->from = c->game;
	       	event_ptr->type = IT_COMBAT_EVENT;
	        event_ptr->arg4 = (void *)theCombat->next_opponent;
	        Do_file_event(c, event_ptr);
		    /* put ourselves back in combat */
		c->game->it_combat = theCombat->next_opponent;
		    /* create a realm object for this kill, if necessary */
		if (theCombat->player_ptr != NULL) {
		    object_ptr = (struct realm_object_t *)
			    Do_malloc(SZ_REALM_OBJECT);
		    object_ptr->x = c->player.x;
		    object_ptr->y = c->player.y;
		    object_ptr->type = CORPSE;
		    object_ptr->arg1 = theCombat->player_ptr;
		    object_ptr->next_object = c->realm->objects;
		    c->realm->objects = object_ptr;
		}
	        Do_unlock_mutex(&c->realm->realm_lock);
	    }
	    Do_unlock_mutex(&theCombat->theLock);
	    Do_destroy_mutex(&theCombat->theLock);
	    free((void *)theCombat);
	    Do_send_line(c, "You are victorious!\n");
	    Do_more(c);
	    Do_send_clear(c);
	    return;
	case IT_MELEE:
	    sprintf(string_buffer,
		    "%s melees with you hitting %.0f times!\n",
		    c->battle.opponent->name, theArg);
	    Do_energy(c, myStats->energy, c->player.max_energy,
		    c->player.shield, myStats->shield, FALSE);
	    break;
	case IT_SKIRMISH:
	    sprintf(string_buffer,
		    "%s skirmishes with you hitting %.0f times!\n",
		    c->battle.opponent->name, theArg);
	    Do_energy(c, myStats->energy, c->player.max_energy,
		    c->player.shield, myStats->shield, FALSE);
	    break;
	case IT_NICKED:
	    c->battle.opponent->experience += theArg;
	    theArg *= 30.0 * c->player.level + 1.0;
	    sprintf(string_buffer,
		    "%s nicks you taking %.0f experience!\n",
		    c->battle.opponent->name, theArg);
	    Do_energy(c, myStats->energy, c->player.max_energy,
		    c->player.shield, myStats->shield, FALSE);
	    Do_speed(c, c->player.max_quickness, c->player.quicksilver,
		    c->battle.speedSpell + 2, FALSE);
		/* only subtract positive values, characters managed to
			get negative experience */
	    if (theArg > 0) {
	        c->player.experience -= theArg;
	    }
	    break;
        case IT_EVADED:
	    sprintf(string_buffer, "%s flees the battle!\n",
		    c->battle.opponent->name);
	    c->battle.opponent->experience = 0;
	    newMessage = IT_VICTORY;
	    break;
        case IT_WIZEVADE:
	    sprintf(string_buffer, "%s laughs at your pitiful attack and teleports away!\n",
		    c->battle.opponent->name);
	    c->battle.opponent->experience = 0;
	    newMessage = IT_VICTORY;
	    break;
        case IT_NO_EVADE:
	    sprintf(string_buffer,
		    "%s tried to flee, but couldn't shake you!\n",
		    c->battle.opponent->name);
	    break;
        case IT_LUCKOUT:
	    sprintf(string_buffer, "%s successfully lucks out in the battle!\n",
		    c->battle.opponent->name);
	    Do_energy(c, myStats->energy, c->player.max_energy,
		    c->player.shield, myStats->shield, FALSE);
	    break;
        case IT_NO_LUCKOUT:
	    sprintf(string_buffer,
		    "%s failed to luckout in the battle!\n",
		    c->battle.opponent->name);
	    break;
        case IT_RING:
		sprintf(string_buffer, "%s puts on a ring!\n",
			c->battle.opponent->name);
		break;
        case IT_NO_RING:
	    sprintf(string_buffer, "%s searches in vain for a ring!\n",
		    c->battle.opponent->name);
	    break;
        case IT_ALL_OR_NOT:
	    sprintf(string_buffer,
		    "%s casts All or Nothing, blasting you for %.0f damage!\n",
		    c->battle.opponent->name, theArg);
	    Do_energy(c, myStats->energy, c->player.max_energy,
		    c->player.shield, myStats->shield, FALSE);
	    break;
        case IT_NO_ALL_OR_NOT:
	    sprintf(string_buffer,
		    "%s flubs an attempt to cast All or Nothing!\n",
		    c->battle.opponent->name);
	    break;
        case IT_BOLT:
	    sprintf(string_buffer,
		    "%s hit you with a %.0f damage Mana Bolt!\n",
		    c->battle.opponent->name, theArg);
	    Do_energy(c, myStats->energy, c->player.max_energy,
		    c->player.shield, myStats->shield, FALSE);
	    break;
        case IT_NO_BOLT:
	    sprintf(string_buffer,
		    "%s casts a Mana Bolt that peters out!\n",
		    c->battle.opponent->name);
	    break;
        case IT_SHIELD:
	    sprintf(string_buffer, "%s throws up a Force Shield!\n",
		    c->battle.opponent->name);
	    break;
        case IT_NO_SHIELD:
	    sprintf(string_buffer, "%s messes up a Force Shield spell!\n",
		    c->battle.opponent->name);
	    break;
        case IT_TRANSFORM:
	    Do_lock_mutex(&c->realm->monster_lock);
	    sprintf(string_buffer,
		    "%s casts Transform, turning you into %s!\n",
		    c->battle.opponent->name,
		    c->realm->monster[(int)theArg].name);
	    event_ptr = (struct event_t *) Do_create_event();
	    event_ptr->type = DEATH_EVENT;
	    event_ptr->arg1 = theArg;
	    event_ptr->arg3 = K_TRANSFORMED;
	    Do_unlock_mutex(&c->realm->monster_lock);
	    Do_handle_event(c, event_ptr);
	    newMessage = IT_DEFEAT;
	    break;
        case IT_NO_TRANSFORM:
	    sprintf(string_buffer, "%s fails to cast a Transform spell!\n",
		    c->battle.opponent->name);
	    break;
        case IT_TRANSFORM_BACK:
	    sprintf(string_buffer,
		    "%s's Transform spell backfires!  %s turns into %s!\n",
		    c->battle.opponent->name, c->battle.opponent->name,
		    c->realm->monster[(int)theArg].name);
	    Do_cancel_monster(c->battle.opponent);
	    newMessage = IT_VICTORY;
	    break;
        case IT_MIGHT:
	    sprintf(string_buffer,
		    "%s buffs up with an Increase Might spell!\n",
		    c->battle.opponent->name);
	    c->battle.opponent->strength += c->player.max_strength;
	    break;
        case IT_NO_MIGHT:
	    sprintf(string_buffer,
		    "%s flounders with an Increase Might spell!\n",
		    c->battle.opponent->name);
	    break;
        case IT_HASTE:
	    sprintf(string_buffer,
		    "%s casts a Haste spell and speeds up!\n",
		    c->battle.opponent->name);
	    c->battle.opponent->strength += c->player.max_quickness;
	    break;
        case IT_NO_HASTE:
	    sprintf(string_buffer,
		    "%s casts an ineffective Haste spell!\n",
		    c->battle.opponent->name);
	    break;
        case IT_TRANSPORT:
	    sprintf(string_buffer,
		    "%s sends you away with a Transport spell!\n",
		    c->battle.opponent->name);
	    event_ptr = (struct event_t *) Do_create_event();
	    event_ptr->type = MOVE_EVENT;
	    event_ptr->arg3 = A_FAR;
	    Do_file_event(c, event_ptr);
	    newMessage = IT_DEFEAT;
	    break;
        case IT_NO_TRANSPORT:
	    sprintf(string_buffer,
		    "%s misfires a Transport spell!\n",
		    c->battle.opponent->name);
	    break;
        case IT_TRANSPORT_BACK:
	    sprintf(string_buffer,
		    "%s is transported away from a bounced Transport spell!\n",
		    c->battle.opponent->name);
	    Do_cancel_monster(c->battle.opponent);
	    newMessage = IT_VICTORY;
	    break;
        case IT_PARALYZE:
	    sprintf(string_buffer,
		    "%s casts a Paralyze spell holding you in place!\n",
		    c->battle.opponent->name);
	    break;
        case IT_NO_PARALYZE:
	    sprintf(string_buffer, "%s casts a dud Paralyze spell!\n",
		    c->battle.opponent->name);
	    break;
        case IT_PASS:
	    sprintf(string_buffer, "%s whistles a happy tune.\n",
		    c->battle.opponent->name);
	    break;
	default:
	    sprintf(error_msg,
		    "[%s] Unknown combat message %d in Do_it_combat_turn.\n",
		    c->connection_id, theMessage);
	    Do_log_error(error_msg);		
            theCombat->message = IT_ABANDON;
            Do_lock_mutex(&theCombat->theLock);
            *hisFlag = TRUE;
            Do_unlock_mutex(&theCombat->theLock);
	    kill(c->battle.opponent->processID, SIGIO);
            Do_lock_mutex(&c->realm->realm_lock);
            c->game->it_combat = NULL;
	    c->game->virtual = TRUE;
            Do_unlock_mutex(&c->realm->realm_lock);
	    c->run_level = EXIT_THREAD;
	    return;
	}
	if (strlen(string_buffer))
	    Do_send_line(c, string_buffer);
	    /* if the character has died */
        if (c->player.energy <= 0.0) {
	    newMessage = IT_DEFEAT;
	    event_ptr = (struct event_t *) Do_create_event();
	    event_ptr->type = DEATH_EVENT;
	    event_ptr->arg3 = K_IT_COMBAT;
	    event_ptr->arg4 = (void *)
		    Do_malloc(strlen(c->battle.opponent->name) + 1);
	    strcpy(event_ptr->arg4, c->battle.opponent->name);
		/* if we leave a corpse */
	    if (c->player.level < 3000 && c->player.special_type != SC_KING &&
		    (!c->battle.ring_in_use || !(c->player.ring_type ==
		    R_DLREG || c->player.ring_type == R_NAZREG))) {
		    /* create a copy of ourselves for the corpse */
	        theCombat->player_ptr = (struct player_t *)
			Do_copy_record(&c->player, FALSE);
	    }
	    Do_handle_event(c, event_ptr);
	}
	    /* if we lost, remove us from battle completely */
	    /* otherwise the winner could encounter us again before we move */
	if (newMessage == IT_DEFEAT || newMessage == IT_EVADED) {
	    Do_lock_mutex(&c->realm->realm_lock);
	    c->game->it_combat = NULL;
	    c->game->virtual = TRUE;
	    Do_unlock_mutex(&c->realm->realm_lock);
	}
	    /* send off the new message */
	theCombat->message = newMessage;
	theCombat->arg1 = newArg;
	Do_lock_mutex(&theCombat->theLock);
	*hisFlag = TRUE;
	Do_unlock_mutex(&theCombat->theLock);
	kill(c->battle.opponent->processID, SIGIO);
	if (c->player.poison > 0.0) 
	    myStats->energy = c->player.energy;
	if (newMessage == IT_DEFEAT) {
	    Do_orphan_events(c);
	    Do_more(c);
	    Do_send_clear(c);
	    return;
	}
    }
}