phantasia4/
phantasia4/conf/
phantasia4/phantasia/bin/
phantasia4/phantasia/src/utilities/
phantasia4/public_html/cgi-bin/
/*
 * 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;
	}
    }
}