wolfpaw4.0-release/area/
wolfpaw4.0-release/backup/
wolfpaw4.0-release/bin/
wolfpaw4.0-release/boards/
wolfpaw4.0-release/clans/
wolfpaw4.0-release/councils/
wolfpaw4.0-release/deity/
wolfpaw4.0-release/finger/
wolfpaw4.0-release/gods/
wolfpaw4.0-release/guilds/
wolfpaw4.0-release/lockers/
wolfpaw4.0-release/log/
wolfpaw4.0-release/log/Clean/
wolfpaw4.0-release/maps/
wolfpaw4.0-release/offline_data/
wolfpaw4.0-release/player-obj/
wolfpaw4.0-release/player-obj/a/
wolfpaw4.0-release/player/
wolfpaw4.0-release/player/a/
wolfpaw4.0-release/plog/
wolfpaw4.0-release/save-rooms/
wolfpaw4.0-release/secure/
wolfpaw4.0-release/source/
wolfpaw4.0-release/source/betasrc/system/
wolfpaw4.0-release/source/betasrc/util/
wolfpaw4.0-release/system/clean-source/
wolfpaw4.0-release/system/clean-source/grux/
/*--------------------------------------------------------------------------*
 *                         ** WolfPaw 3.0 ** 				    *
 *--------------------------------------------------------------------------*
 *               WolfPaw 3.0 (c) 1997 - 1999 by Dale Corse		    *
 *--------------------------------------------------------------------------*
 *            The WolfPaw Coding Team is headed by: Greywolf                *
 *  With the Assitance from: Callinon, Dhamon, Sentra, Wyverns, Altrag      *
 *                           Scryn, Thoric, Justice, Tricops and Brogar.    *
 *--------------------------------------------------------------------------*
 *  Based on SMAUG 1.2a. Copyright 1994 - 1996 by Derek Snider		    *
 *  SMAUG Coding Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, *
 *		       Swordbearer, Gorog, Grishnakh and Tricops.           *
 *--------------------------------------------------------------------------*
 *  Merc 2.1 Diku MUD Improvments (C) 1992 - 1993 by Michael Chastain,      *
 *  Michael Quan, and Michael Tse. 					    *
 *  Original Diku MUD (C) 1990 - 1991 by Sebastian Hammer, Michael Seifert, *
 *  Hans Hendrik Strfeldt, Tom Madsen, and Katja Nyboe. 		    *
 *--------------------------------------------------------------------------*
 *			    Battle & death module			    *
 ****************************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"

extern char		lastplayercmd[MAX_INPUT_LENGTH];
extern CHAR_DATA *	gch_prev;

bool death_handler	      args( ( CHAR_DATA *ch, CHAR_DATA *victim, bool npcvict ) );
void maim_update( CHAR_DATA *ch, CHAR_DATA *victim );

/*
 * Local functions.
 */
void	dam_message	args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,
			    int dt ) );
void	death_cry	args( ( CHAR_DATA *ch ) );
void	group_gain	args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int	xp_compute	args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
int	align_compute	args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
ch_ret	one_hit		args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) );
int	obj_hitroll	args( ( OBJ_DATA *obj ) );
bool    remove_obj      args( ( CHAR_DATA *ch, int iWear, bool fReplace ));
int	number_kombat   args( ( void ) );
bool	dual_flip = FALSE;
bool    fight_in_progress; /* for pk arena scheduling */
void    quest_death_check args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); 
void    ego_update args( ( CHAR_DATA *ch, CHAR_DATA *victim, bool gain ) );
bool    can_flee_dir( CHAR_DATA *ch, int door );

/*
 * Check to see if weapon is poisoned.
 */
bool is_wielding_poisoned( CHAR_DATA *ch )
{
         OBJ_DATA *obj;

         if ( ( obj = get_eq_char( ch, WEAR_WIELD ) 	)
         &&   (IS_SET( obj->extra_flags, ITEM_POISONED) )	)
                  return TRUE;

         return FALSE;

}

/*
 * hunting, hating and fearing code				-Thoric
 */
bool is_hunting( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( !ch->hunting || ch->hunting->who != victim )
      return FALSE;
    
    return TRUE;    
}

bool is_hating( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( !ch->hating || ch->hating->who != victim )
      return FALSE;
    
    return TRUE;    
}

bool is_fearing( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( !ch->fearing || ch->fearing->who != victim )
      return FALSE;
    
    return TRUE;    
}

void stop_hunting( CHAR_DATA *ch )
{
    if ( ch->hunting )
    {
	STRFREE( ch->hunting->name );
	DISPOSE( ch->hunting );
	ch->hunting = NULL;
    }
    return;
}

void stop_hating( CHAR_DATA *ch )
{
    if ( ch->hating )
    {
	STRFREE( ch->hating->name );
	DISPOSE( ch->hating );
	ch->hating = NULL;
    }
    return;
}

void stop_fearing( CHAR_DATA *ch )
{
    if ( ch->fearing )
    {
	STRFREE( ch->fearing->name );
	DISPOSE( ch->fearing );
	ch->fearing = NULL;
    }
    return;
}

void start_hunting( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( ch->hunting )
      stop_hunting( ch );

    CREATE( ch->hunting, HHF_DATA, 1 );
    ch->hunting->name = QUICKLINK( victim->name );
    ch->hunting->who  = victim;
    return;
}

void start_hating( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( ch->hating )
      stop_hating( ch );

    CREATE( ch->hating, HHF_DATA, 1 );
    ch->hating->name = QUICKLINK( victim->name );
    ch->hating->who  = victim;
    return;
}

void start_fearing( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( ch->fearing )
      stop_fearing( ch );

    CREATE( ch->fearing, HHF_DATA, 1 );
    ch->fearing->name = QUICKLINK( victim->name );
    ch->fearing->who  = victim;
    return;
}

/*
 * Get the current armor class for a vampire based on time of day
 */
sh_int VAMP_AC( CHAR_DATA * ch )
{
  if ( IS_VAMPIRE( ch ) || IS_OUTSIDE( ch ) )
  {
    switch(weather_info.sunlight)
    {
    case SUN_DARK:
      return -8;
    case SUN_RISE:
      return 5;
    case SUN_LIGHT:
      return 10;
    case SUN_SET:
      return 2;
    default:
      return 0;
    }
  }
  else
    return 0;
}

int max_fight( CHAR_DATA *ch )
{
    return 8;
}

/*
 * Control the fights going on.
 * Called periodically by update_handler.
 * Many hours spent fixing bugs in here by Thoric, as noted by residual
 * debugging checks.  If you never get any of these error messages again
 * in your logs... then you can comment out some of the checks without
 * worry.
 */
void violence_update( void )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *ch;
    CHAR_DATA *lst_ch;
    CHAR_DATA *victim;
    CHAR_DATA *rch, *rch_next;
    AFFECT_DATA *paf, *paf_next;
    TIMER	*timer, *timer_next;
    ch_ret     retcode;
    int	       x, attacktype=0, cnt;
    SKILLTYPE	*skill;
    ZONE_DATA *in_zone;

    lst_ch = NULL;
    for ( ch = last_char; ch; lst_ch = ch, ch = gch_prev )
    {
	set_cur_char( ch );

	if ( ch == first_char && ch->prev )
	{
	   bug( "ERROR: first_char->prev != NULL, fixing...", 0 );
	   ch->prev = NULL;
	}

	gch_prev	= ch->prev;

	if ( gch_prev && gch_prev->next != ch )
	{
	    sprintf( buf, "FATAL: violence_update: %s->prev->next doesn't point to ch.",
		ch->name );
	    bug( buf, 0 );	    
	    bug( "Short-cutting here", 0 );
	    ch->prev = NULL;
	    gch_prev = NULL;
	}

	/*
	 * See if we got a pointer to someone who recently died...
	 * if so, either the pointer is bad... or it's a player who
	 * "died", and is back at the healer...
	 * Since he/she's in the char_list, it's likely to be the later...
	 * and should not already be in another fight already
	 */
	if ( char_died(ch) )
	    continue;

	/*
	 * See if we got a pointer to some bad looking data...
	 */
	if ( !ch->in_room || !ch->name )
	{
	    log_string( "violence_update: bad ch record!  (Shortcutting.)" );
	    sprintf( buf, "ch: %d  ch->in_room: %d  ch->prev: %d  ch->next: %d",
	    	(int) ch, (int) ch->in_room, (int) ch->prev, (int) ch->next );
	    log_string( buf );
	    log_string( lastplayercmd );
	    if ( lst_ch )
	      sprintf( buf, "lst_ch: %d  lst_ch->prev: %d  lst_ch->next: %d",
	      		(int) lst_ch, (int) lst_ch->prev, (int) lst_ch->next );
	    else
	      strcpy( buf, "lst_ch: NULL" );
	    log_string( buf );
	    gch_prev = NULL;
	    continue;
	}


	for ( timer = ch->first_timer; timer; timer = timer_next )
	{
	    timer_next = timer->next;
	    if ( --timer->count <= 0 )
	    {
		if ( timer->type == TIMER_DO_FUN )
		{
		    int tempsub;

		    tempsub = ch->substate;
		    ch->substate = timer->value;
		    (timer->do_fun)( ch, "" );
		    if ( char_died(ch) )
		      break;
		    ch->substate = tempsub;
		}
		extract_timer( ch, timer );
	    }
	}

	if ( char_died(ch) )
	  continue;

	/*
	 * We need spells that have shorter durations than an hour.
	 * So a melee round sounds good to me... -Thoric
	 */
	for ( paf = ch->first_affect; paf; paf = paf_next )
	{
	      paf_next	= paf->next;
	      if ( paf->duration > 0 )
		paf->duration--;
	      else
	      if ( paf->duration < 0 )
		;
	      else
	      {
		  if ( !paf_next
		  ||    paf_next->type != paf->type
		  ||    paf_next->duration > 0 )
		  {
		      skill = get_skilltype(paf->type);
		      if ( paf->type > 0 && skill && skill->msg_off )
		      {
                          set_char_color( AT_WEAROFF, ch );
			  send_to_char( skill->msg_off, ch );
			  send_to_char( "\n\r", ch );
		      }
		  }
		  if (paf->type == gsn_possess)
	          {
	            ch->desc->character       = ch->desc->original;
    	            ch->desc->original        = NULL;
    		    ch->desc->character->desc = ch->desc;
   	            ch->desc->character->switched = NULL;
    		    ch->desc                  = NULL;
		  }
		  affect_remove( ch, paf );
	      }
	}
	
	if (( victim = who_fighting( ch ) ) == NULL
	||   IS_AFFECTED( ch, AFF_PARALYSIS ) )
	    continue;

        retcode = rNONE;

	if ( IS_SET(ch->in_room->room_flags, ROOM_SAFE ) )
	{
	   sprintf( buf, "violence_update: %s fighting %s in a SAFE room.",
	   	ch->name, victim->name );
	   log_string( buf );
	   stop_fighting( ch, TRUE );
	}
	else
	if ( IS_AWAKE(ch) && ch->in_room == victim->in_room )
	    retcode = multi_hit( ch, victim, TYPE_UNDEFINED );
	else
	    stop_fighting( ch, FALSE );

	if ( char_died(ch) )
	    continue;

	if ( retcode == rCHAR_DIED
	|| ( victim = who_fighting( ch ) ) == NULL )
	    continue;

	/*
	 *  Mob triggers
	 */
	rprog_rfight_trigger( ch );
	if ( char_died(ch) )
	    continue;
	mprog_hitprcnt_trigger( ch, victim );
	if ( char_died(ch) )
	    continue;
	mprog_fight_trigger( ch, victim );
	if ( char_died(ch) )
	    continue;

	/*
	 * Maimers --GW
	 */
	 maim_update( ch, victim );
         if ( char_died(ch) )
	     continue;

	/*
	 * NPC special attack flags				-Thoric
	 */
	if ( IS_NPC(ch) )
	{
	  cnt = 0;
	  if ( ch->attacks )
	    for ( ;; )
	    {
	      if ( cnt++ > 10 )
	      {
		attacktype = 0;
		break;
	      }
	      x = number_range( 7, 31 );
	      attacktype = 1 << x;
	      if ( IS_SET( ch->attacks, attacktype ) )
	        break;
	    }

	  if ( 30 + (ch->level/4) < number_percent( ) )
	    attacktype = 0;
	  switch( attacktype )
	  {
	  case ATCK_BASH:
	    do_bash( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_STUN:
	    do_stun( ch, "" ); 
	    retcode = global_retcode;
	    break;
	  case ATCK_GOUGE:
	    do_gouge( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_FEED:
	    do_feed( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_DRAIN:
	    retcode = spell_energy_drain( skill_lookup( "energy drain" ), ch->level, ch, victim );
	    break;
	  case ATCK_FIREBREATH:
	    retcode = spell_fire_breath( skill_lookup( "fire breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_FROSTBREATH:
	    retcode = spell_frost_breath( skill_lookup( "frost breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_ACIDBREATH:
	    retcode = spell_acid_breath( skill_lookup( "acid breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_LIGHTNBREATH:
	    retcode = spell_lightning_breath( skill_lookup( "lightning breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_GASBREATH:
	    retcode = spell_gas_breath( skill_lookup( "gas breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_SPIRALBLAST:         
            retcode = spell_spiral_blast( skill_lookup( "spiral blast" ),
                        ch->level, ch, victim );
	    break;
	   case ATCK_POISON:
	    retcode = spell_poison( gsn_poison, ch->level, ch, victim );
	    break;
	  case ATCK_NASTYPOISON:
	    /*
	    retcode = spell_nasty_poison( skill_lookup( "nasty poison" ), ch->level, ch, victim );
	     */
	    break;
	  case ATCK_GAZE:
	    /*
	    retcode = spell_gaze( skill_lookup( "gaze" ), ch->level, ch, victim );
	     */
	    break;
	  case ATCK_BLINDNESS:
	    retcode = spell_blindness( gsn_blindness, ch->level, ch, victim );
	    break;
	  case ATCK_CAUSESERIOUS:
	    retcode = spell_cause_serious( skill_lookup( "cause serious" ), ch->level, ch, victim );
	    break;
	  case ATCK_EARTHQUAKE:
	    retcode = spell_earthquake( skill_lookup( "earthquake" ), ch->level, ch, victim );
	    break;
	  case ATCK_CAUSECRITICAL:
	    retcode = spell_cause_critical( skill_lookup( "cause critical" ), ch->level, ch, victim );
	    break;
	  case ATCK_CURSE:
	    retcode = spell_curse( skill_lookup( "curse" ), ch->level, ch, victim );
	    break;
	  case ATCK_FLAMESTRIKE:
	    retcode = spell_flamestrike( skill_lookup( "flamestrike" ), ch->level, ch, victim );
	    break;
	  case ATCK_HARM:
	    retcode = spell_harm( skill_lookup( "harm" ), ch->level, ch, victim );
	    break;
	  case ATCK_FIREBALL:
	    retcode = spell_fireball( skill_lookup( "fireball" ), ch->level, ch, victim );
	    break;
	  case ATCK_COLORSPRAY:
	    retcode = spell_colour_spray( skill_lookup( "colour spray" ), ch->level, ch, victim );
	    break;
	  case ATCK_WEAKEN:
	    retcode = spell_weaken( skill_lookup( "weaken" ), ch->level, ch, victim );
	    break;
	  }
	  if ( retcode == rCHAR_DIED || (char_died(ch)) )
	    continue;

	  /*
	   * NPC special defense flags				-Thoric
	   */
	  cnt = 0;
	  if ( ch->defenses )
	    for ( ;; )
	    {
	      if ( cnt++ > 10 )
	      {
		attacktype = 0;
		break;
	      }
	      x = number_range( 2, 18 );
	      attacktype = 1 << x;
	      if ( IS_SET( ch->defenses, attacktype ) )
	        break;
	    }
	  if ( 50 + (ch->level/4) < number_percent( ) )
	    attacktype = 0;
	  switch( attacktype )
	  {
	    case DFND_CURELIGHT:
	      act( AT_MAGIC, "$n mutters a few incantations...and looks a little better.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_smaug( skill_lookup( "cure light" ), ch->level, ch, ch );
	      break;
	    case DFND_CURESERIOUS:
	      act( AT_MAGIC, "$n mutters a few incantations...and looks a bit better.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_smaug( skill_lookup( "cure serious" ), ch->level, ch, ch );
	      break;
	    case DFND_CURECRITICAL:
	      act( AT_MAGIC, "$n mutters a few incantations...and looks a bit healthier.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_smaug( skill_lookup( "cure critical" ), ch->level, ch, ch );
	      break;
	    case DFND_DISPELMAGIC:
	      act( AT_MAGIC, "$n mutters a few incantations...and waves $s arms about.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_dispel_magic( skill_lookup( "dispel magic" ), ch->level, ch, victim );
	      break;
	    case DFND_DISPELEVIL:
	      act( AT_MAGIC, "$n mutters a few incantations...and waves $s arms about.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_dispel_evil( skill_lookup( "dispel evil" ), ch->level, ch, victim );
	      break;
	    case DFND_SANCTUARY:
	      if ( !IS_AFFECTED(victim, AFF_SANCTUARY) )
	      {
		act( AT_MAGIC, "$n mutters a few incantations...", ch, NULL, NULL, TO_ROOM );
		retcode = spell_smaug( skill_lookup( "sanctuary" ), ch->level, ch, ch );
	      }
	      else
	        retcode = rNONE;
	      break;
	  }
	  if ( retcode == rCHAR_DIED || (char_died(ch)) )
	    continue;
	}

	/*
	 * Fun for the whole family!
	 */
	for ( rch = ch->in_room->first_person; rch; rch = rch_next )
	{
	    rch_next = rch->next_in_room;

	    if ( IS_AWAKE(rch) && !rch->fighting )
	    {
		/*
		 * PC's auto-assist others in their group.
		 */
		if ( !IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) )
		{
		    if ( ( !IS_NPC(rch) || IS_AFFECTED(rch, AFF_CHARM) )
		    &&   is_same_group(ch, rch) )
			multi_hit( rch, victim, TYPE_UNDEFINED );
		    continue;
		}

		/*
		 * NPC's assist NPC's of same type or 12.5% chance regardless.
		 */
		if ( IS_NPC(rch) && !IS_AFFECTED(rch, AFF_CHARM)
		&&  !IS_SET(rch->act, ACT_NOASSIST) )
		{
		    if ( char_died(ch) )
			break;
		    if ( rch->pIndexData == ch->pIndexData
		    ||   number_bits( 3 ) == 0 )
		    {
			CHAR_DATA *vch;
			CHAR_DATA *target;
			int number;

			target = NULL;
			number = 0;			for ( vch = ch->in_room->first_person; vch; vch = vch->next )
			{
			    if ( can_see( rch, vch )
			    &&   is_same_group( vch, victim )
			    &&   number_range( 0, number ) == 0 )
			    {
				target = vch;
				number++;
			    }
			}

			if ( target )
			    multi_hit( rch, target, TYPE_UNDEFINED );
		    }
		}
	    }
	}
    }

for( in_zone = first_zone; in_zone; in_zone = in_zone->next )
{
    for ( ch = in_zone->last_mob; ch; lst_ch = ch, ch = gch_prev )
    {
	set_cur_char( ch );

	if ( ch == in_zone->first_mob && ch->prev )
	{
	   bug( "ERROR: first_char->prev != NULL, fixing...", 0 );
	   ch->prev = NULL;
	}

	gch_prev	= ch->prev;

	if ( gch_prev && gch_prev->next != ch )
	{
	    sprintf( buf, "FATAL: violence_update: %s->prev->next doesn't point to ch.",
		ch->name );
	    bug( buf, 0 );	    
	    bug( "Short-cutting here", 0 );
	    ch->prev = NULL;
	    gch_prev = NULL;
	}

	/*
	 * See if we got a pointer to someone who recently died...
	 * if so, either the pointer is bad... or it's a player who
	 * "died", and is back at the healer...
	 * Since he/she's in the char_list, it's likely to be the later...
	 * and should not already be in another fight already
	 */
	if ( char_died(ch) )
	    continue;

	/*
	 * See if we got a pointer to some bad looking data...
	 */
	if ( !ch->in_room || !ch->name )
	{
	    log_string( "violence_update: bad ch record!  (Shortcutting.)" );
	    sprintf( buf, "ch: %d  ch->in_room: %d  ch->prev: %d  ch->next: %d",
	    	(int) ch, (int) ch->in_room, (int) ch->prev, (int) ch->next );
	    log_string( buf );
	    log_string( lastplayercmd );
	    if ( lst_ch )
	      sprintf( buf, "lst_ch: %d  lst_ch->prev: %d  lst_ch->next: %d",
	      		(int) lst_ch, (int) lst_ch->prev, (int) lst_ch->next );
	    else
	      strcpy( buf, "lst_ch: NULL" );
	    log_string( buf );
	    gch_prev = NULL;
	    continue;
	}


	for ( timer = ch->first_timer; timer; timer = timer_next )
	{
	    timer_next = timer->next;
	    if ( --timer->count <= 0 )
	    {
		if ( timer->type == TIMER_DO_FUN )
		{
		    int tempsub;

		    tempsub = ch->substate;
		    ch->substate = timer->value;
		    (timer->do_fun)( ch, "" );
		    if ( char_died(ch) )
		      break;
		    ch->substate = tempsub;
		}
		extract_timer( ch, timer );
	    }
	}

	if ( char_died(ch) )
	  continue;

	/*
	 * We need spells that have shorter durations than an hour.
	 * So a melee round sounds good to me... -Thoric
	 */
	for ( paf = ch->first_affect; paf; paf = paf_next )
	{
	      paf_next	= paf->next;
	      if ( paf->duration > 0 )
		paf->duration--;
	      else
	      if ( paf->duration < 0 )
		;
	      else
	      {
		  if ( !paf_next
		  ||    paf_next->type != paf->type
		  ||    paf_next->duration > 0 )
		  {
		      skill = get_skilltype(paf->type);
		      if ( paf->type > 0 && skill && skill->msg_off )
		      {
                          set_char_color( AT_WEAROFF, ch );
			  send_to_char( skill->msg_off, ch );
			  send_to_char( "\n\r", ch );
		      }
		  }
		  if (paf->type == gsn_possess)
	          {
	            ch->desc->character       = ch->desc->original;
    	            ch->desc->original        = NULL;
    		    ch->desc->character->desc = ch->desc;
   	            ch->desc->character->switched = NULL;
    		    ch->desc                  = NULL;
		  }
		  affect_remove( ch, paf );
	      }
	}
	
	if (( victim = who_fighting( ch ) ) == NULL
	||   IS_AFFECTED( ch, AFF_PARALYSIS ) )
	    continue;

        retcode = rNONE;

	if ( IS_SET(ch->in_room->room_flags, ROOM_SAFE ) )
	{
	   sprintf( buf, "violence_update: %s fighting %s in a SAFE room.",
	   	ch->name, victim->name );
	   log_string( buf );
	   stop_fighting( ch, TRUE );
	}
	else
	if ( IS_AWAKE(ch) && ch->in_room == victim->in_room )
	    retcode = multi_hit( ch, victim, TYPE_UNDEFINED );
	else
	    stop_fighting( ch, FALSE );

	if ( char_died(ch) )
	    continue;

	if ( retcode == rCHAR_DIED
	|| ( victim = who_fighting( ch ) ) == NULL )
	    continue;

    if ( ch->stun_rounds < 1 )
    {
	/*
	 *  Mob triggers
	 */
	rprog_rfight_trigger( ch );
	if ( char_died(ch) )
	    continue;
	mprog_hitprcnt_trigger( ch, victim );
	if ( char_died(ch) )
	    continue;
	mprog_fight_trigger( ch, victim );
	if ( char_died(ch) )
	    continue;

	/* Smart Mobbies -- YIKES! --GW */
	smart_update( ch, victim ); 

	/*
	 * Maimers --GW
	 */
	 maim_update( ch, victim );
         if ( char_died(ch) )
	     continue;

	/*
	 * NPC special attack flags				-Thoric
	 */
	if ( IS_NPC(ch) )
	{
	  cnt = 0;
	  if ( ch->attacks )
	    for ( ;; )
	    {
	      if ( cnt++ > 10 )
	      {
		attacktype = 0;
		break;
	      }
	      x = number_range( 7, 31 );
	      attacktype = 1 << x;
	      if ( IS_SET( ch->attacks, attacktype ) )
	        break;
	    }

	  if ( 30 + (ch->level/4) < number_percent( ) )
	    attacktype = 0;
	  switch( attacktype )
	  {
	  case ATCK_BASH:
	    do_bash( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_STUN:
	    do_stun( ch, "" ); 
	    retcode = global_retcode;
	    break;
	  case ATCK_GOUGE:
	    do_gouge( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_FEED:
	    do_feed( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_DRAIN:
	    retcode = spell_energy_drain( skill_lookup( "energy drain" ), ch->level, ch, victim );
	    break;
	  case ATCK_FIREBREATH:
	    retcode = spell_fire_breath( skill_lookup( "fire breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_FROSTBREATH:
	    retcode = spell_frost_breath( skill_lookup( "frost breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_ACIDBREATH:
	    retcode = spell_acid_breath( skill_lookup( "acid breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_LIGHTNBREATH:
	    retcode = spell_lightning_breath( skill_lookup( "lightning breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_GASBREATH:
	    retcode = spell_gas_breath( skill_lookup( "gas breath" ), ch->level, ch, victim );
	    break;
	  case ATCK_SPIRALBLAST:         
            retcode = spell_spiral_blast( skill_lookup( "spiral blast" ),
                        ch->level, ch, victim );
	    break;
	   case ATCK_POISON:
	    retcode = spell_poison( gsn_poison, ch->level, ch, victim );
	    break;
	  case ATCK_NASTYPOISON:
	    /*
	    retcode = spell_nasty_poison( skill_lookup( "nasty poison" ), ch->level, ch, victim );
	     */
	    break;
	  case ATCK_GAZE:
	    /*
	    retcode = spell_gaze( skill_lookup( "gaze" ), ch->level, ch, victim );
	     */
	    break;
	  case ATCK_BLINDNESS:
	    retcode = spell_blindness( gsn_blindness, ch->level, ch, victim );
	    break;
	  case ATCK_CAUSESERIOUS:
	    retcode = spell_cause_serious( skill_lookup( "cause serious" ), ch->level, ch, victim );
	    break;
	  case ATCK_EARTHQUAKE:
	    retcode = spell_earthquake( skill_lookup( "earthquake" ), ch->level, ch, victim );
	    break;
	  case ATCK_CAUSECRITICAL:
	    retcode = spell_cause_critical( skill_lookup( "cause critical" ), ch->level, ch, victim );
	    break;
	  case ATCK_CURSE:
	    retcode = spell_curse( skill_lookup( "curse" ), ch->level, ch, victim );
	    break;
	  case ATCK_FLAMESTRIKE:
	    retcode = spell_flamestrike( skill_lookup( "flamestrike" ), ch->level, ch, victim );
	    break;
	  case ATCK_HARM:
	    retcode = spell_harm( skill_lookup( "harm" ), ch->level, ch, victim );
	    break;
	  case ATCK_FIREBALL:
	    retcode = spell_fireball( skill_lookup( "fireball" ), ch->level, ch, victim );
	    break;
	  case ATCK_COLORSPRAY:
	    retcode = spell_colour_spray( skill_lookup( "colour spray" ), ch->level, ch, victim );
	    break;
	  case ATCK_WEAKEN:
	    retcode = spell_weaken( skill_lookup( "weaken" ), ch->level, ch, victim );
	    break;
	  }
	  if ( retcode == rCHAR_DIED || (char_died(ch)) )
	    continue;

	  /*
	   * NPC special defense flags				-Thoric
	   */
	  cnt = 0;
	  if ( ch->defenses )
	    for ( ;; )
	    {
	      if ( cnt++ > 10 )
	      {
		attacktype = 0;
		break;
	      }
	      x = number_range( 2, 18 );
	      attacktype = 1 << x;
	      if ( IS_SET( ch->defenses, attacktype ) )
	        break;
	    }
	  if ( 50 + (ch->level/4) < number_percent( ) )
	    attacktype = 0;
	  switch( attacktype )
	  {
	    case DFND_CURELIGHT:
	      act( AT_MAGIC, "$n mutters a few incantations...and looks a little better.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_smaug( skill_lookup( "cure light" ), ch->level, ch, ch );
	      break;
	    case DFND_CURESERIOUS:
	      act( AT_MAGIC, "$n mutters a few incantations...and looks a bit better.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_smaug( skill_lookup( "cure serious" ), ch->level, ch, ch );
	      break;
	    case DFND_CURECRITICAL:
	      act( AT_MAGIC, "$n mutters a few incantations...and looks a bit healthier.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_smaug( skill_lookup( "cure critical" ), ch->level, ch, ch );
	      break;
	    case DFND_DISPELMAGIC:
	      act( AT_MAGIC, "$n mutters a few incantations...and waves $s arms about.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_dispel_magic( skill_lookup( "dispel magic" ), ch->level, ch, victim );
	      break;
	    case DFND_DISPELEVIL:
	      act( AT_MAGIC, "$n mutters a few incantations...and waves $s arms about.", ch, NULL, NULL, TO_ROOM );
	      retcode = spell_dispel_evil( skill_lookup( "dispel evil" ), ch->level, ch, victim );
	      break;
	    case DFND_SANCTUARY:
	      if ( !IS_AFFECTED(victim, AFF_SANCTUARY) )
	      {
		act( AT_MAGIC, "$n mutters a few incantations...", ch, NULL, NULL, TO_ROOM );
		retcode = spell_smaug( skill_lookup( "sanctuary" ), ch->level, ch, ch );
	      }
	      else
	        retcode = rNONE;
	      break;
	  }
	  if ( retcode == rCHAR_DIED || (char_died(ch)) )
	    continue;
	}

      }

	/*
	 * Fun for the whole family!
	 */
	for ( rch = ch->in_room->first_person; rch; rch = rch_next )
	{
	    rch_next = rch->next_in_room;

	    if ( IS_AWAKE(rch) && !rch->fighting )
	    {
		/*
		 * PC's auto-assist others in their group.
		 */
		if ( !IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) )
		{
		    if ( ( !IS_NPC(rch) || IS_AFFECTED(rch, AFF_CHARM) )
		    &&   is_same_group(ch, rch) )
			multi_hit( rch, victim, TYPE_UNDEFINED );
		    continue;
		}

		/*
		 * NPC's assist NPC's of same type or 12.5% chance regardless.
		 */
		if ( IS_NPC(rch) && !IS_AFFECTED(rch, AFF_CHARM)
		&&  !IS_SET(rch->act, ACT_NOASSIST) )
		{
		    if ( char_died(ch) )
			break;
		    if ( rch->pIndexData == ch->pIndexData
		    ||   number_bits( 3 ) == 0 )
		    {
			CHAR_DATA *vch;
			CHAR_DATA *target;
			int number;

			target = NULL;
			number = 0;			for ( vch = ch->in_room->first_person; vch; vch = vch->next )
			{
			    if ( can_see( rch, vch )
			    &&   is_same_group( vch, victim )
			    &&   number_range( 0, number ) == 0 )
			    {
				target = vch;
				number++;
			    }
			}

			if ( target )
			    multi_hit( rch, target, TYPE_UNDEFINED );
		    }
		}
	    }
	}
    }
}
    return;
}



/*
 * Do one group of attacks.
 */
ch_ret multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    int     chance;
    int	    dual_bonus;
    ch_ret  retcode=rNONE;
   
    if ( !ch || !victim )
	return rNONE;

	arrest(ch);
	if ( check_warrents(ch)==TRUE)
	return rNONE;

    if ( IS_AFFECTED(victim,AFF_REFLECT_DAMAGE) )
      act(AT_RED,"$n's chest glows, as some damage reflects!",victim,NULL,NULL,TO_ROOM);


    /* add timer if player is attacking another player */
    if ( !IS_NPC(ch) && !IS_NPC(victim) )
      add_timer( ch, TIMER_RECENTFIGHT, 20, NULL, 0 );

    if ( !IS_NPC(ch) && IS_SET( ch->act, PLR_NICE ) && !IS_NPC( victim ) )
      return rNONE;

    if ( ch->stun_rounds > 0 )
    {
	ch->stun_rounds--;
	return rNONE;
    }

     if ( char_died(victim) )
	return rCHAR_DIED;

   if ( ch && victim && ch->in_room && victim->in_room && 
        ( ch->in_room == victim->in_room ) )
    {
    if ( (retcode = one_hit( ch, victim, dt )) != rNONE )
      return retcode;
    }

    if ( who_fighting( ch ) != victim || dt == gsn_backstab || 
         dt == gsn_circle || dt == gsn_assassinate )
	return rNONE;
	
    /* Very high chance of hitting compared to chance of going berserk */
    /* 40% or higher is always hit.. don't learn anything here though. */
    /* -- Altrag */
    chance = IS_NPC(ch) ? 100 : (ch->pcdata->learned[gsn_berserk]*5/2);

    if ( char_died(victim) )
	return rCHAR_DIED;

    if ( IS_AFFECTED(ch, AFF_BERSERK) && number_percent() < chance )
      if ( (retcode = one_hit( ch, victim, dt )) != rNONE ||
            who_fighting( ch ) != victim )
        return retcode;

    if ( char_died(victim) )
	return rCHAR_DIED;

    if ( get_eq_char( ch, WEAR_DUAL_WIELD ) )
    {
      dual_bonus = IS_NPC(ch) ? (ch->level / 10) : (ch->pcdata->learned[gsn_dual_wield] / 10);
      chance = IS_NPC(ch) ? ch->level : ch->pcdata->learned[gsn_dual_wield];
      if ( number_percent( ) < chance )
      {
	learn_from_success( ch, gsn_dual_wield );
	retcode = one_hit( ch, victim, dt );
	if ( retcode != rNONE || who_fighting( ch ) != victim )
	    return retcode;
      }
      else
	learn_from_failure( ch, gsn_dual_wield );
    }
    else
      dual_bonus = 0;

    if ( ch->move < 10 )
      dual_bonus = -20;

    /*
     * NPC predetermined number of attacks			-Thoric
     */
    if ( IS_NPC(ch) && ch->numattacks > 0 )
    {
	for ( chance = 0; chance <= ch->numattacks; chance++ )
	{
          if ( char_died(victim) )
    	    return rCHAR_DIED;

	   retcode = one_hit( ch, victim, dt );
	   if ( retcode != rNONE || who_fighting( ch ) != victim )
	     return retcode;
	}
	return retcode;
    }

    chance = IS_NPC(ch) ? ch->level
	   : (int) ((ch->pcdata->learned[gsn_second_attack]+dual_bonus)/1.5);
    if ( number_percent( ) < chance )
    {
       if ( char_died(victim) )
    	   return rCHAR_DIED;

	learn_from_success( ch, gsn_second_attack );
	retcode = one_hit( ch, victim, dt );
	if ( retcode != rNONE || who_fighting( ch ) != victim )
	    return retcode;
    }
    else
	learn_from_failure( ch, gsn_second_attack );

    chance = IS_NPC(ch) ? ch->level
	   : (int) ((ch->pcdata->learned[gsn_third_attack]+(dual_bonus*1.5))/2);
    if ( number_percent( ) < chance )
    {
        if ( char_died(victim) )
  	    return rCHAR_DIED;

	learn_from_success( ch, gsn_third_attack );
	retcode = one_hit( ch, victim, dt );
	if ( retcode != rNONE || who_fighting( ch ) != victim )
	    return retcode;
    }
    else
	learn_from_failure( ch, gsn_third_attack );

    chance = IS_NPC(ch) ? ch->level
	   : (int) ((ch->pcdata->learned[gsn_fourth_attack]+(dual_bonus*2))/3);
    if ( number_percent( ) < chance )
    {
          if ( char_died(victim) )
	       return rCHAR_DIED;

	learn_from_success( ch, gsn_fourth_attack );
	retcode = one_hit( ch, victim, dt );
	if ( retcode != rNONE || who_fighting( ch ) != victim )
	    return retcode;
    }
    else
	learn_from_failure( ch, gsn_fourth_attack );

    chance = IS_NPC(ch) ? ch->level
	   : (int) ((ch->pcdata->learned[gsn_fifth_attack]+(dual_bonus*3))/4);
    if ( number_percent( ) < chance )
    {
         if ( char_died(victim) )
  	    return rCHAR_DIED;

	learn_from_success( ch, gsn_fifth_attack );
	retcode = one_hit( ch, victim, dt );
	if ( retcode != rNONE || who_fighting( ch ) != victim )
	    return retcode;
    }
    else
	learn_from_failure( ch, gsn_fifth_attack );

   chance = IS_NPC(ch) ? ch->level
	  : (int) ((ch->pcdata->learned[gsn_sixth_attack]+(dual_bonus*4))/5);
   if ( number_percent( ) < chance )
   {
         if ( char_died(victim) )
	     return rCHAR_DIED;

	learn_from_success(ch, gsn_sixth_attack );
	retcode = one_hit(ch, victim, dt );
	if( retcode != rNONE || who_fighting( ch ) != victim )
	   return retcode;
   }
   else
	learn_from_failure(ch, gsn_sixth_attack );

   chance = IS_NPC(ch) ? ch->level
	  : (int) ((ch->pcdata->learned[gsn_seventh_attack]+(dual_bonus*5))/6);
   if ( number_percent( ) < chance )
   {
        if ( char_died(victim) )
	    return rCHAR_DIED;

	learn_from_success(ch, gsn_seventh_attack );
	retcode = one_hit(ch, victim, dt );
	if( retcode != rNONE || who_fighting( ch ) != victim )
	   return retcode;
   }
   else
	learn_from_failure(ch, gsn_seventh_attack );


    retcode = rNONE;

    if ( char_died(victim) )
	return rCHAR_DIED;

    chance = IS_NPC(ch) ? (int) (ch->level / 2) : 0;
    if ( number_percent( ) < chance )
	retcode = one_hit( ch, victim, dt );

    if ( retcode == rNONE )
    {
	int move;

	if ( !IS_AFFECTED(ch, AFF_FLYING)
	&&   !IS_AFFECTED(ch, AFF_FLOATING) )
	  move = encumbrance( ch, movement_loss[UMIN(SECT_MAX-1, ch->in_room->sector_type)] );
	else
	  move = encumbrance( ch, 1 );
	if ( ch->move )
	  ch->move = UMAX( 0, ch->move - move );
    }

    return retcode;
}


/*
 * Weapon types, haus
 */
int weapon_prof_bonus_check( CHAR_DATA *ch, OBJ_DATA *wield, int *gsn_ptr )
{
    int bonus;

    bonus = 0;	*gsn_ptr = -1;
    if ( !IS_NPC(ch) && ch->level > 5 && wield )   
    {
	switch(wield->value[3])
	{
	   default:	*gsn_ptr = -1;			break;
           case 0:      *gsn_ptr = gsn_pugilism;        break;
           case 1:	*gsn_ptr = gsn_long_blades;	break;
           case 2:	*gsn_ptr = gsn_short_blades;	break;
           case 3:      *gsn_ptr = gsn_short_blades;    break;
           case 4:	*gsn_ptr = gsn_flexible_arms;	break;
           case 5:	*gsn_ptr = gsn_talonous_arms;	break;
	   case 6:	*gsn_ptr = gsn_pugilism;	break;
           case 7:      *gsn_ptr = gsn_bludgeons;       break;
           case 8:	*gsn_ptr = gsn_bludgeons;	break;
	   case 10:     *gsn_ptr = gsn_short_blades;    break;
           case 11:     *gsn_ptr = gsn_short_blades;    break;
	   case 12:     *gsn_ptr = gsn_bludgeons;       break;
	   case 13:	
	   case 14:	
	   case 15:	
	   case 16:	
	   case 17:	*gsn_ptr = gsn_missile_weapons; break;
	}
	if ( *gsn_ptr != -1 )
	  bonus = (int) ((ch->pcdata->learned[*gsn_ptr] -50)/10);

       /* Reduce weapon bonuses for misaligned clannies.
       if ( IS_CLANNED(ch) )
       {
          bonus = bonus / 
          ( 1 + abs( ch->alignment - ch->pcdata->clan->alignment ) / 1000 );
       }*/

	if ( IS_DEVOTED( ch ) )
	{
	   bonus = bonus - abs( ch->pcdata->favor ) / -100 ;
	}

    }
    return bonus;
}

/*
 * Calculate the tohit bonus on the object and return RIS values.
 * -- Altrag
 */
int obj_hitroll( OBJ_DATA *obj )
{
	int tohit = 0;
	AFFECT_DATA *paf;
	
	for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
		if ( paf->location == APPLY_HITROLL )
			tohit += paf->modifier;
	for ( paf = obj->first_affect; paf; paf = paf->next )
		if ( paf->location == APPLY_HITROLL )
			tohit += paf->modifier;
	return tohit;
}

/*
 * Offensive shield level modifier
 */
sh_int off_shld_lvl( CHAR_DATA *ch, CHAR_DATA *victim )
{
    sh_int lvl;

    if ( !IS_NPC(ch) )		/* players get much less effect */
    {
	lvl = UMAX( 1, (ch->level - 10) / 2 );
	if ( number_percent() + (victim->level - lvl) < 35 )
	  return lvl;
	else
	  return 0;
    }
    else
    {
	lvl = ch->level / 2;
	if ( number_percent() + (victim->level - lvl) < 70 )
	  return lvl;
	else
	  return 0;
    }
}

/*
 * Hit one guy once.
 */
ch_ret one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    int victim_ac;
    int thac0;
    int thac0_00;
    int thac0_32;
    int plusris;
    long dam, x;
    int diceroll;
    int attacktype, cnt;
    int	prof_bonus;
    int	prof_gsn;
    ch_ret retcode=rNONE;

    if ( !ch || !victim )
	return rVICT_DIED;

    if ( char_died(victim) )
	return rCHAR_DIED;

    /*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return rVICT_DIED;

    /*
     * Rooms seem to get fucked in fights - fix it --GW
     */
    if ( ch->in_room )
      ch->was_in_room = ch->in_room;
    if ( victim->in_room )
      victim->was_in_room = victim->in_room;
    if ( !ch->in_room && ch->was_in_room )
      char_to_room(ch,ch->was_in_room);
    if ( !victim->in_room && victim->was_in_room )
      char_to_room(victim,victim->was_in_room);

    /*
     * New Stun Code --GW
     */
    if ( ch->stun_rounds > 0 )
	return rNONE;

    /*
     * Figure out the weapon doing the damage			-Thoric
     */
    if ( (wield = get_eq_char( ch, WEAR_DUAL_WIELD )) != NULL )
    {
       if ( dual_flip == FALSE )
       {
	 dual_flip = TRUE;
	 wield = get_eq_char( ch, WEAR_WIELD );
       }
       else
	 dual_flip = FALSE;
    }
    else
      wield = get_eq_char( ch, WEAR_WIELD );

    prof_bonus = weapon_prof_bonus_check( ch, wield, &prof_gsn );

    if ( ch->fighting		/* make sure fight is already started */
    &&   dt == TYPE_UNDEFINED
    &&   IS_NPC(ch)
    &&   ch->attacks != 0 )
    {
	cnt = 0;
	for ( ;; )
	{
	   x = number_range( 0, 6 );
	   attacktype = 1 << x;
	   if ( IS_SET( ch->attacks, attacktype ) )
	     break;
	   if ( cnt++ > 16 )
	   {
	     attacktype = 0;
	     break;
	   }
	}
	if ( attacktype == ATCK_BACKSTAB )
	  attacktype = 0;
	if ( wield && number_percent( ) > 25 )
	  attacktype = 0;
	switch ( attacktype )
	{
	  default:
	    break;
	  case ATCK_BITE:
	    do_bite( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_CLAWS:
	    do_claw( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_TAIL:
	    do_tail( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_STING:
	    do_sting( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_PUNCH:
	    do_punch( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_KICK:
	    do_kick( ch, "" );
	    retcode = global_retcode;
	    break;
	  case ATCK_TRIP:
	    attacktype = 0;
	    break;
	}
	if ( attacktype )
	  return retcode;
    }

    if ( dt == TYPE_UNDEFINED )
    {
	dt = TYPE_HIT;
	if ( wield && wield->item_type == ITEM_WEAPON )
	    dt += wield->value[3];
    }

    /*
     * Calculate to-hit-armor-class-0 versus armor.
     */
    if ( ch->class == -1 )
	return 0;

    if ( IS_NPC(ch) )
    {
	thac0_00 = ch->mobthac0;
	thac0_32 =  0;
    }
    else
    {
	thac0_00 = class_table[ch->class]->thac0_00;
	thac0_32 = class_table[ch->class]->thac0_32;
    }
    thac0     = interpolate( ch->level, thac0_00, thac0_32 ) - GET_HITROLL(ch);
    victim_ac = UMAX( -19, (int) (GET_AC(victim) / 10) );

    /* if you can't see what's coming... */
    if ( wield && !can_see_obj( victim, wield) )
	victim_ac += 1;
    if ( !can_see( ch, victim ) )
	victim_ac -= 4;

    /*
     * "learning" between combatients.  Takes the intelligence difference,
     * and multiplies by the times killed to make up a learning bonus
     * given to whoever is more intelligent		-Thoric
     */
    if ( ch->fighting && ch->fighting->who == victim )
    {
	sh_int times = ch->fighting->timeskilled;

	if ( times )
	{
	    sh_int intdiff = get_curr_int(ch) - get_curr_int(victim);

	    if ( intdiff != 0 )
		victim_ac += (intdiff*times)/10;
	}
    }

    /* Weapon proficiency bonus */
    victim_ac += prof_bonus;

    /*
     * The moment of excitement!
     */
    while ( ( diceroll = number_bits( 5 ) ) >= 20 )
	;

    if ( diceroll == 0
    || ( diceroll != 19 && diceroll < thac0 - victim_ac ) )
    {
	/* Miss. */
	if ( prof_gsn != -1 )
	  learn_from_failure( ch, prof_gsn );
	damage( ch, victim, 0, dt );
	tail_chain( );
	return rNONE;
    }

    /*
     * Hit.
     * Calc damage.
     */

    /* Thoric's Dice job re-fixed by Greywolf, thanks to G. Moody. --GW */

       dam = number_range( ch->barenumdie, ch->baresizedie * ch->barenumdie ) + ch->damplus;
       dam += number_range( ch->perm_str, ( ch->level * 2.4 ));

	if ( wield )
	dam += number_range(wield->value[1],wield->value[2]);

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL(ch);

    if ( prof_bonus )
      dam += prof_bonus / 4;

    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += (int) (dam * ch->pcdata->learned[gsn_enhanced_damage] / 120);
	learn_from_success( ch, gsn_enhanced_damage );
    }

    if ( !IS_AWAKE(victim) )
	dam *= 2;
    if ( dt == gsn_backstab )
	dam *= (2 + URANGE( 2, ch->level - (victim->level/4), 30 ) / 8);
    if ( dt == gsn_assassinate )
	dam *= (4 + URANGE( 2, ch->level - (victim->level/2), 30) / 4 );

/* This comment-keyword is here for easy jumping -- Cal  (CIRCLE) */
/* It's a little silly I know but hey it's original :P */
    if ( dt == gsn_circle )
 	dam *= (2 + URANGE( 2, ch->level - (victim->level/4), 30 ) / 16); 

    plusris = 0;

	 wield = get_eq_char( ch, WEAR_WIELD );

    if ( wield && !IS_SET(wield->magic_flags, ITEM_DISSOLVE_IMM) )
    {
       
      if ( IS_SET( wield->extra_flags, ITEM_MAGIC ) )
        dam = ris_damage( victim, dam, RIS_MAGIC );
      else
        dam = ris_damage( victim, dam, RIS_NONMAGIC );

      /*
       * Handle PLUS1 - PLUS6 ris bits vs. weapon hitroll	-Thoric
       */
      plusris = obj_hitroll( wield );
    }
    else
      dam = ris_damage( victim, dam, RIS_NONMAGIC );

    /* check for RIS_PLUSx 					-Thoric */
  if ( (wield && !IS_SET(wield->magic_flags, ITEM_DISSOLVE_IMM)) || !wield )
  {
    if ( dam )
    {
	int x, res, imm, sus, mod;

	if ( plusris )
	   plusris = RIS_PLUS1 << UMIN(plusris, 7);

	/* initialize values to handle a zero plusris */
	imm = res = -1;  sus = 1;

	/* find high ris */
	for ( x = RIS_PLUS1; x <= RIS_PLUS6; x <<= 1 )
	{
	   if ( IS_SET( victim->immune, x ) )
		imm = x;
	   if ( IS_SET( victim->resistant, x ) )
		res = x;
	   if ( IS_SET( victim->susceptible, x ) )
		sus = x;
	}
	mod = 10;
	if ( imm >= plusris )
	  mod -= 10;
	if ( res >= plusris )
	  mod -= 2;
	if ( sus <= plusris )
	  mod += 2;

	/* check if immune */
	/* Cackle.. opps.. I guess immune isnt 100% anymore eh... GW */
	if ( (x=number_range(1,100)) > 75 )
	{
  	  if ( mod <= 0 )
	    dam = -1;
	  if ( mod != 10 )
	    dam = (dam * mod) / 10;
	}
    }
}
    if ( prof_gsn != -1 )
    {
      if ( dam > 0 )
        learn_from_success( ch, prof_gsn );
      else
        learn_from_failure( ch, prof_gsn );
    }

if ( (wield && !IS_SET(wield->magic_flags, ITEM_DISSOLVE_IMM) ) || !wield )
{
    /* immune to damage */
    if ( dam == -1 )
    {
	if ( dt >= 0 && dt < top_sn )
	{
	    SKILLTYPE *skill = skill_table[dt];
	    bool found = FALSE;

	    if ( skill->imm_char && skill->imm_char[0] != '\0' )
	    {
		act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
		found = TRUE;
	    }
	    if ( skill->imm_vict && skill->imm_vict[0] != '\0' )
	    {
		act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
		found = TRUE;
	    }
	    if ( skill->imm_room && skill->imm_room[0] != '\0' )
	    {
		act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
		found = TRUE;
	    }
	    if ( found )
	      return rNONE;
	}
	dam = 0;
    }
}
    if ( !ch )
        return rNONE;
    if ( !victim )
        return rNONE;

/* Damage Cap --GW */
/* Player vs. Player Cap */
if ( !IS_NPC(ch) && !IS_NPC(victim) && dam > 1500 )
	dam = 1500;
/* Mob vs. Player */
if ( IS_NPC(ch) && !IS_NPC(victim) && dam > 4500 )
        dam = 4500;
/* Player vs. Mob */
if ( !IS_NPC(ch) && IS_NPC(victim) && dam > 2000 )
        dam = 2000;

    if ( (retcode = damage( ch, victim, dam, dt )) != rNONE )
      return retcode;
    if ( char_died(ch) )
      return rCHAR_DIED;
    if ( char_died(victim) )
      return rVICT_DIED;

    retcode = rNONE;
    if ( dam == 0 )
      return retcode;

/* weapon spells	-Thoric */
    if ( wield && ((x=number_range(1,100))>50) /* 50% fail chance..--GW */
    &&  (!IS_SET(wield->magic_flags, ITEM_DISSOLVE_IMM) && !IS_SET(victim->immune, RIS_MAGIC))
    &&  !IS_SET(victim->in_room->room_flags, ROOM_NO_MAGIC) )
    {
	AFFECT_DATA *aff;
	
	if ( retcode != rNONE || char_died(ch) || char_died(victim) )
		return rCHAR_DIED;
	for ( aff = wield->pIndexData->first_affect; aff; aff = aff->next )
	   if ( aff->location == APPLY_WEAPONSPELL
	   &&   IS_VALID_SN(aff->modifier)
	   &&   !char_died(ch)
	   &&   !char_died(victim)
	   &&   skill_table[aff->modifier]->spell_fun )
		retcode = (*skill_table[aff->modifier]->spell_fun) (aff->modifier, (ch->level+3)/3, ch, victim );
	if ( retcode != rNONE || char_died(ch) || char_died(victim) )
		return retcode;
	for ( aff = wield->first_affect; aff; aff = aff->next )
	   if ( aff->location == APPLY_WEAPONSPELL
	   &&   IS_VALID_SN(aff->modifier)
	   &&   !char_died(ch)
	   &&   !char_died(victim)
	   &&   skill_table[aff->modifier]->spell_fun )
		retcode = (*skill_table[aff->modifier]->spell_fun) (aff->modifier, (ch->level+3)/3, ch, victim );
	if ( retcode != rNONE || char_died(ch) || char_died(victim) )
		return retcode;
    }

    /*
     * magic shields that retaliate				-Thoric
     */
    if ( IS_AFFECTED( victim, AFF_FIRESHIELD )
    &&  !IS_AFFECTED( ch, AFF_FIRESHIELD ) )
	retcode = spell_fireball( gsn_fireball, off_shld_lvl(victim, ch), victim, ch );
    if ( retcode != rNONE || char_died(ch) || char_died(victim) )
      return retcode;

    if ( IS_AFFECTED( victim, AFF_ICESHIELD )
    &&  !IS_AFFECTED( ch, AFF_ICESHIELD ) )
         retcode = spell_chill_touch( gsn_chill_touch, off_shld_lvl(victim, ch), victim, ch );
    if ( retcode != rNONE || char_died(ch) || char_died(victim) )
      return retcode;

    if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD )
    &&  !IS_AFFECTED( ch, AFF_SHOCKSHIELD ) )
	retcode = spell_lightning_bolt( gsn_lightning_bolt, off_shld_lvl(victim, ch), victim, ch );
    if ( retcode != rNONE || char_died(ch) || char_died(victim) )
      return retcode;

    tail_chain( );
    return retcode;
}

/*
 * Calculate damage based on resistances, immunities and suceptibilities
 *					-Thoric
 */
sh_int ris_damage( CHAR_DATA *ch, long dam, int ris )
{
   sh_int modifier;
   int rand=0;

   modifier = 10;
   if ( IS_SET(ch->immune, ris ) )
     modifier -= 10;
   if ( IS_SET(ch->resistant, ris ) )
     modifier -= 2;
   if ( IS_SET(ch->susceptible, ris ) )
     modifier += 2;

/* Failure.. it is NOT an Immunity!--GW*/
if ( modifier < 0 && ch->fighting && (rand=number_range(1,100))<(ch->fighting->who->level/4))
  return dam;

   if ( modifier <= 0 )
     return -1;
   if ( modifier == 10 )
     return dam;
   return (dam * modifier) / 10;
}


/*
 * Inflict damage from a hit.
 */
ch_ret damage( CHAR_DATA *ch, CHAR_DATA *victim, long dam, int dt )
{
    char buf1[MAX_STRING_LENGTH];
    sh_int dameq;
    sh_int maxdam;
    bool npcvict;
    bool loot;
    long xp_gain;
    OBJ_DATA *damobj;
    OBJ_DATA *obj;
    ch_ret retcode;
    sh_int dampmod;
    CHAR_DATA *gch;
    bool death;
    bool selfdeath;
    int init_gold, new_gold, gold_diff;
    extern sh_int dam_no_msg;

    death = FALSE;
    selfdeath = FALSE;

    retcode = rNONE;

    if ( !ch )
    {
	bug( "Damage: null ch!", 0 );
	return rERROR;
    }
    if ( !victim )
    {
	bug( "Damage: null victim!", 0 );
	return rVICT_DIED;
    }

    if ( victim->position == POS_DEAD )
	return rVICT_DIED;

    npcvict = IS_NPC(victim);

    if ( ch->stun_rounds > 0 )
     return rNONE;

    /*
     * Check damage types for RIS				-Thoric
     */
    if ( dam && dt != TYPE_UNDEFINED )
    {
	if ( IS_FIRE(dt) )
	  dam = ris_damage(victim, dam, RIS_FIRE);
	else
	if ( IS_COLD(dt) )
	  dam = ris_damage(victim, dam, RIS_COLD);
	else
	if ( IS_ACID(dt) )
	  dam = ris_damage(victim, dam, RIS_ACID);
	else
	if ( IS_ELECTRICITY(dt) )
	  dam = ris_damage(victim, dam, RIS_ELECTRICITY);
	else
	if ( IS_ENERGY(dt) )
	  dam = ris_damage(victim, dam, RIS_ENERGY);
	else
	if ( IS_DRAIN(dt) )
	  dam = ris_damage(victim, dam, RIS_DRAIN);
	else
	if ( dt == gsn_poison || IS_POISON(dt) )
	  dam = ris_damage(victim, dam, RIS_POISON);
	else
	if ( dt == (TYPE_HIT + 7) || dt == (TYPE_HIT + 8) )
	  dam = ris_damage(victim, dam, RIS_BLUNT);
	else
	if ( dt == (TYPE_HIT + 2) || dt == (TYPE_HIT + 11)
	||   dt == (TYPE_HIT + 10) )
	  dam = ris_damage(victim, dam, RIS_PIERCE);
	else
	if ( dt == (TYPE_HIT + 1) || dt == (TYPE_HIT + 3)
	||   dt == (TYPE_HIT + 4) || dt == (TYPE_HIT + 5) )
	  dam = ris_damage(victim, dam, RIS_SLASH);

	if ( dam == -1 )
	{
	    if ( dt >= 0 && dt < top_sn )
	    {
		bool found = FALSE;
		SKILLTYPE *skill = skill_table[dt];


		if ( skill->imm_char && skill->imm_char[0] != '\0' )
		{
		   act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
		   found = TRUE;
		}
		if ( skill->imm_vict && skill->imm_vict[0] != '\0' )
		{
		   act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
		   found = TRUE;
		}
		if ( skill->imm_room && skill->imm_room[0] != '\0' )
		{
		   act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
		   found = TRUE;
		}
		if ( found )
		   return rNONE;
	    }
	    dam = 0;
	}
    }

    if ( dam && npcvict && ch != victim )
    {
	if ( !IS_SET( victim->act, ACT_SENTINEL ) )
 	{
	   if ( victim->hunting )
	   {
	     if ( victim->hunting->who != ch )
	     {
		STRFREE( victim->hunting->name );
		victim->hunting->name = QUICKLINK( ch->name );
		victim->hunting->who  = ch;
	     }
           }
	   else
	     start_hunting( victim, ch );
	}

      if ( victim->hating )
      {
	if ( victim->hating->who != ch )
	{
	   if (victim && victim->hating && victim->hating->name )
	   STRFREE( victim->hating->name );
	   victim->hating->name = QUICKLINK( ch->name );
	   victim->hating->who  = ch;
	}
      }
      else
	start_hating( victim, ch );
    }

    /*
     * Stop up any residual loopholes.
     */
    maxdam = ch->level * 30;
    if ( dt == gsn_backstab )
      maxdam = ch->level * 80;
    if ( dt == gsn_assassinate )
      maxdam = ch->level * 80;
    if ( ( dam > maxdam) &&(ch->level2 != 50 ))
	dam = maxdam;

    if ( victim != ch )
    {
	/*
	 * Certain attacks are forbidden.
	 * Most other attacks are returned.
	 */
         if ( !ch )
	    return rNONE;

	 if ( !victim )
	    return rNONE;

	if (ch && victim && is_safe( ch, victim ) )
	    return rNONE;


	if ( victim->position > POS_STUNNED )
	{
	    if ( !victim->fighting )
		set_fighting( victim, ch );
	    if ( victim->fighting )
		victim->position = POS_FIGHTING;
	}

	if ( victim->position > POS_STUNNED )
	{
	    if ( !ch->fighting )
		set_fighting( ch, victim );

	    /*
	     * If victim is charmed, ch might attack victim's master.
	     */
	    if ( IS_NPC(ch)
	    &&   npcvict
	    &&   IS_AFFECTED(victim, AFF_CHARM)
	    &&   victim->master
	    &&   victim->master->in_room == ch->in_room
	    &&   number_bits( 3 ) == 0 )
	    {
		stop_fighting( ch, FALSE );
		retcode = multi_hit( ch, victim->master, TYPE_UNDEFINED );
		return retcode;
	    }
	}


	/*
	 * More charm stuff.
	 */
	if ( victim->master && victim->master == ch )
	    stop_follower( victim );

        /* Pkill stuff.  If a deadly attacks another deadly or is attacked by one,
         * then ungroup any nondealies.  Disabled untill I can figure out the right
         * way to do it.
         */
         
/*	{
	  sh_int anopc = 0;  * # of (non-pkill) pc in a (ch) *
	  sh_int bnopc = 0;  * # of (non-pkill) pc in b (victim) *
	  CHAR_DATA *lch;   * leader ch *

	  * count the # of non-pkill pc in a ( not including == ch ) *
	  for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
	    if ( is_same_group( ch, gch ) && !IS_NPC( gch )
		&& !IS_PKILL( gch ) && ( ch != gch ) ) anopc++;

	  * count the # of non-pkill pc in b ( not including == victim ) *
	  for ( gch = victim->in_room->first_person; gch; gch = gch->next_in_room )
	    if ( is_same_group( victim, gch ) && !IS_NPC( gch )
		&& !IS_PKILL( gch ) && ( victim != gch ) ) bnopc++;


	  * only consider disbanding if both groups have 1(+) non-pk pc *
	  if ( ( bnopc > 0 ) && ( anopc > 0 ) )
	  {
	    * look at group a through ch's leader first *
	    lch = ch->leader ? ch->leader : ch;
	    if ( lch != ch )
	    {
	      * stop following leader if it isn't pk *
	      if ( !IS_NPC(lch) && !IS_PKILL( lch ) )
		stop_follower( ch );
	       else
		{
		  * disband non-pk members from lch's group if it is pk *
		  for ( gch = ch->in_room->first_person; gch; 
			gch = gch->next_in_room )
		  {
		    if ( is_same_group( lch, gch )
		      && ( lch != gch )
		      && !IS_NPC(gch) && !IS_PKILL( gch ) )
		      stop_follower( gch );
		  }
		}
	    } 
	   else
	    for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
	    {
	      * ch is leader - disband non-pks from group *
	      if ( is_same_group( ch, gch )
		&& ( ch != gch )
	        && ( !IS_PKILL( gch ) && !IS_NPC( gch ) ) )
	        stop_follower( gch );
	    }

	    * time to look at the victims group through its leader *
	    lch = victim->leader ? victim->leader : victim;

	    if ( lch != victim )
	    {
	      * if leader isn't deadly, stop following lch *
	      if ( !IS_PKILL( lch ) && !IS_NPC( lch ) )
	        stop_follower( victim );
	       else
		{
		  * lch is pk, disband non-pk's from group *
	          for ( gch = victim->in_room->first_person; gch; 
			gch = gch->next_in_room )
	    	  {
	     	    if ( is_same_group( lch, gch )
		      && ( lch != gch )
	              && ( !IS_PKILL( gch ) && !IS_NPC( gch ) ) )
	              stop_follower( gch );
	          }
		}
	    }
	   else
	    {
	      * victim is leader of group - disband non-pks *
	      for ( gch = victim->in_room->first_person; gch;
		 gch = gch->next_in_room )
	      {
		if ( is_same_group( victim, gch )
		  && ( victim != gch )
 		  && !IS_PKILL( gch ) && !IS_NPC( gch ) )
		  stop_follower( gch );
	      }
	    }
	  }
	}*/

	{
	  sh_int anopc = 0;  /* # of (non-pkill) pc in a (ch) */
	  sh_int bnopc = 0;  /* # of (non-pkill) pc in b (victim) */

	  /* count the # of non-pkill pc in a ( not including == ch ) */
	  for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
	    if ( is_same_group( ch, gch ) && !IS_NPC( gch )
		&& !IS_PKILL( gch ) && ( ch != gch ) ) anopc++;

	  /* count the # of non-pkill pc in b ( not including == victim)*/
	  for ( gch = victim->in_room->first_person; gch; gch = gch->next_in_room )
	    if ( is_same_group( victim, gch ) && !IS_NPC( gch )
		&& !IS_PKILL( gch ) && ( victim != gch ) ) bnopc++;


	  /* only consider disbanding if both groups have 1(+) non-pk pc,
	     or when one participant is pc, and the other group has 1(+)
	     pk pc's (in the case that participant is only pk pc in group)*/
	  if ( ( bnopc > 0 && anopc > 0 )
	    || ( bnopc > 0 && !IS_NPC(ch) )
	    || ( anopc > 0 && !IS_NPC(victim) ) )
	  {
	    /* Disband from same group first */
	    if ( is_same_group(ch, victim) )
	    {
	      /* Messages to char and master handled in stop_follower */
	      act( AT_ACTION, "$n disbands from $N's group.",
	           (ch->leader == victim) ? victim : ch, NULL,
	           (ch->leader == victim) ? victim->master : ch->master,
	           TO_NOTVICT );
	      if ( ch->leader == victim )
	        stop_follower(victim);
	      else
	        stop_follower(ch);
	    }
	    /* if leader isnt pkill, leave the group and disband ch */
	    if ( ch->leader != NULL && !IS_NPC(ch->leader) &&
	        !IS_PKILL(ch->leader) )
	    {
	      act( AT_ACTION, "$n disbands from $N's group.", ch, NULL,
	           ch->master, TO_NOTVICT );
	      stop_follower( ch );
	    }
	    else
	    {
	      for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
	        if ( is_same_group(gch, ch) && !IS_NPC( gch ) &&
	             !IS_PKILL( gch ) && gch != ch )
	        {
	          act( AT_ACTION, "$n disbands from $N's group.", ch, NULL,
	               gch->master, TO_NOTVICT );
	          stop_follower( gch );
	        }
	    }
	    /* if leader isnt pkill, leave the group and disband victim */
	    if ( victim->leader != NULL && !IS_NPC(victim->leader) &&
	        !IS_PKILL(victim->leader) )
	    {
	      act( AT_ACTION, "$n disbands from $N's group.", victim, NULL,
	           victim->master, TO_NOTVICT );
	      stop_follower( victim );
	    }
	    else
	    {
	      for ( gch = victim->in_room->first_person; gch; gch = gch->next_in_room )
	        if ( is_same_group(gch, victim) && !IS_NPC( gch ) &&
	             !IS_PKILL( gch ) && gch != victim )
	        {
	          act( AT_ACTION, "$n disbands from $N's group.", gch, NULL,
	               gch->master, TO_NOTVICT );
	          stop_follower( gch );
	        }
	    }
	  }
	}
	    
/*         for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
         {
           if ( is_same_group( ch, gch ) 
                && ( IS_PKILL( ch ) != IS_PKILL( gch ) ) )
           {
             stop_follower( ch );
             stop_follower( gch );
           }
         }
                
         for ( gch = victim->in_room->first_person; gch; gch = gch->next_in_room )
         {
           if ( is_same_group( victim, gch ) 
                && ( IS_PKILL( victim ) != IS_PKILL( gch ) ) )
           {
             stop_follower( victim ); 
             stop_follower( gch );
           }
         }
*/
	/*
	 * Inviso attacks ... not.
	 */
	if ( IS_AFFECTED(ch, AFF_INVISIBLE) || IS_SET(ch->act, ACT_MOBINVIS) )
	{
	    affect_strip( ch, gsn_invis );
	    affect_strip( ch, gsn_mass_invis );
	    xREMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
	    REMOVE_BIT( ch->act, ACT_MOBINVIS );	   
	act( AT_MAGIC, "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
	}

	/* Take away Hide */
	if ( IS_AFFECTED(ch, AFF_HIDE) )
	     xREMOVE_BIT(ch->affected_by, AFF_HIDE);     

	/*
	 * Damage modifiers.
	 */
	if ( IS_AFFECTED(victim, AFF_SANCTUARY) )
	    dam /= 2;

	if ( IS_AFFECTED(victim, AFF_PROTECT) && IS_EVIL(ch) )
	    dam -= (int) (dam / 4);

	/*
	 * Check for disarm, trip, parry, and dodge.
	 */
	if ( dt >= TYPE_HIT && victim->stun_rounds < 1 )
	{
	    if ( IS_NPC(ch)
	    &&   IS_SET( ch->attacks, DFND_DISARM )
	    &&   ch->level > 9
	    &&   number_percent( ) < ch->level / 2 )
		disarm( ch, victim );

	    if ( IS_NPC(ch)
	    &&   IS_SET( ch->attacks, ATCK_TRIP )
	    &&   ch->level > 5
	    &&   number_percent( ) < ch->level / 2 )
		trip( ch, victim );

	    if ( check_parry( ch, victim ) )
		return rNONE;
	    if ( check_dodge( ch, victim ) )
		return rNONE;
	}

    /*
     * Check control panel settings and modify damage
     */
    if ( IS_NPC(ch) )
    {
	if ( npcvict )
	  dampmod = sysdata.dam_mob_vs_mob;
	else
	  dampmod = sysdata.dam_mob_vs_plr;
    }
    else
    {
	if ( npcvict )
	  dampmod = sysdata.dam_plr_vs_mob;
	else
	  dampmod = sysdata.dam_plr_vs_plr;
    }
    if ( dampmod > 0 )
      dam = ( dam * dampmod ) / 100;

     /* Make stunned Mobiles/Characters take 1/4 the damage, being thay cannot
      * defend themselves, and are dying to fast --GW
      */
	if ( victim->stun_rounds > 0 )
	   dam = dam/4;

	dam_message( ch, victim, dam, dt );
    }


    /*
     * Code to handle equipment getting damaged, and also support  -Thoric
     * bonuses/penalties for having or not having equipment where hit
     */
    if (dam > 10 && dt != TYPE_UNDEFINED)
    {
	/* get a random body eq part */
	dameq  = number_range(WEAR_LIGHT, WEAR_EYES);
	damobj = get_eq_char(victim, dameq);
	if ( damobj )
	{
	  if ( dam > get_obj_resistance(damobj) )
	  {
	     set_cur_obj(damobj);
	     damage_obj(damobj);
	  }
	  dam -= 5;  /* add a bonus for having something to block the blow */
	}
	else
	  dam += 5;  /* add penalty for bare skin! */
    }


    /* Reflect Damage Stuff --GW */
  if ( IS_AFFECTED(victim, AFF_REFLECT_DAMAGE) )
  {
   CHAR_DATA *dam_char, *dam_next;

    for( dam_char = victim->in_room->first_person; dam_char; dam_char = dam_next )
    {
      dam_next = dam_char->next_in_room;

      /* Don't hit myself.. */
      if ( dam_char == victim || IS_NPC(ch) || dam==0 )
	continue;

      dam_no_msg = 1;
      /* Inflict 1/4th the damage done on each character (yes it hurts!) */
      damage(victim,ch,(dam/4),TYPE_UNDEFINED);
      dam_no_msg = 0;
    }
   dam = dam/4;
  }

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */

    if ( dam > 1500 || dam < 0 )
     dam = 1500;

    URANGE(0,victim->hit -= dam,victim->max_hit+5);


    /*
     * Get experience based on % of damage done			-Thoric
     */
    if ( dam && ch != victim
    &&  !IS_NPC(ch) && ch->fighting && ch->fighting->xp )
    {
	if ( ch->fighting->who == victim )
	  xp_gain = URANGE(0, (int) (ch->fighting->xp * dam) / victim->max_hit, 2100000000);
	else
	  xp_gain = URANGE(0, (int) (xp_compute( ch, victim ) * 1.90 * dam) / victim->max_hit, 2100000000);

	if ( IS_NPC(ch->fighting->who) && IS_SET(ch->fighting->who->act,ACT_CREATE_LIFE_MOB))
	xp_gain=0;

	if ( !IS_NPC(ch) )
	ch->pcdata->battle_xp += xp_gain;
	
	gain_exp( ch, xp_gain, TRUE );
    }

    if (!IS_NPC(victim)
    && ( !in_arena(victim) && chaos != 1 ) 
    && !IS_SET(victim->pcdata->flags, PCFLAG_KOMBAT )
    && victim->level >= LEVEL_IMMORTAL
    &&   victim->hit < 1 )
       victim->hit = 1;

    /* Make sure newbies dont die */

    if (!IS_NPC(victim) && NOT_AUTHED(victim) && victim->hit < 1)
	victim->hit = 1;

    if ( dam > 0 && dt > TYPE_HIT
    && !IS_AFFECTED( victim, AFF_POISON )
    &&  is_wielding_poisoned( ch )
    && !IS_SET( victim->immune, RIS_POISON )
    && !saves_poison_death( ch->level, victim ) )
    {
	AFFECT_DATA af;

	af.type      = gsn_poison;
	af.duration  = 20;
	af.location  = APPLY_STR;
	af.modifier  = -2;
	af.bitvector = meb(AFF_POISON);
	affect_join( victim, &af );
	ch->mental_state = URANGE( 20, ch->mental_state + 2, 100 );
    }

    /*
     * Vampire self preservation				-Thoric
     */
    if ( IS_VAMPIRE(victim) )
    {
      if ( dam >= (victim->max_hit / 10) )	/* get hit hard, lose blood */
	gain_condition(victim, COND_BLOODTHIRST, -1 - (victim->level / 20));
      if ( victim->hit <= (victim->max_hit / 8)
      && victim->pcdata->condition[COND_BLOODTHIRST]>5 )
      {
	gain_condition(victim, COND_BLOODTHIRST,
		-URANGE(3, victim->level / 10, 8) );
	victim->hit += URANGE( 4, (victim->max_hit / 30), 15);
	set_char_color(AT_BLOOD, victim);
	send_to_char("You howl with rage as the beast within stirs!\n\r", victim);
      }
    }

    if ( !npcvict
    &&   get_trust(victim) >= LEVEL_IMMORTAL
    &&	 get_trust(ch)	   >= LEVEL_IMMORTAL
    &&   victim->hit < 1 )
	victim->hit = 1;
    update_pos( victim );

    switch( victim->position )
    {
    case POS_MORTAL:
	act( AT_DYING, "$n is mortally wounded, and will die soon, if not aided.",
	    victim, NULL, NULL, TO_ROOM );
	act( AT_DANGER, "You are mortally wounded, and will die soon, if not aided.",
	victim, NULL, NULL, TO_CHAR );
	break;

    case POS_INCAP:
	act( AT_DYING, "$n is incapacitated and will slowly die, if not aided.",
	    victim, NULL, NULL, TO_ROOM );
	act( AT_DANGER, "You are incapacitated and will slowly die, if not aided.",
	victim, NULL, NULL, TO_CHAR );
	break;

    case POS_STUNNED:
        if ( !IS_AFFECTED( victim, AFF_PARALYSIS ) )
        {
	  act( AT_ACTION, "$n is stunned, but will probably recover.",
	    victim, NULL, NULL, TO_ROOM );
	  act( AT_HURT, "You are stunned, but will probably recover.",
	    victim, NULL, NULL, TO_CHAR );
	}
	break;

    case POS_DEAD:
	if ( dt >= 0 && dt < top_sn )
	{
	    SKILLTYPE *skill = skill_table[dt];

	    if ( skill->die_char && skill->die_char[0] != '\0' )
	      act( AT_DEAD, skill->die_char, ch, NULL, victim, TO_CHAR );
	    if ( skill->die_vict && skill->die_vict[0] != '\0' )
	      act( AT_DEAD, skill->die_vict, ch, NULL, victim, TO_VICT );
	    if ( skill->die_room && skill->die_room[0] != '\0' )
	      act( AT_DEAD, skill->die_room, ch, NULL, victim, TO_NOTVICT );
	}
        stop_fighting(victim,TRUE);
	   if ( !IS_NPC(ch) && IS_SET( ch->pcdata->flags, PCFLAG_OLD_DEATH ) )
    		grim_reaper(victim,TRUE);
   		else
    		grim_reaper(victim,FALSE);

/*        if ( !victim->in_room )
	{
	   if ( victim->in_room )
	     char_from_room(victim);

	   char_to_room(victim,victim->was_in_room);
	}

        if ( !ch->in_room )
	{
	   if ( ch->in_room )
	     char_from_room(ch);

	   char_to_room(ch,ch->was_in_room);
	}
*/
	break;

    default:
	if ( dam > victim->max_hit / 4 )
	{
	   act( AT_HURT, "That really did HURT!", victim, 0, 0, TO_CHAR );
	   if ( number_bits(3) == 0 )
		worsen_mental_state( ch, 1 );
	}
	if ( victim->hit < victim->max_hit / 4 )

	{
	   act( AT_DANGER, "You wish that your wounds would stop BLEEDING so much!",
		victim, 0, 0, TO_CHAR );
	   if ( number_bits(2) == 0 )
		worsen_mental_state( ch, 1 );
	}
	break;
    }

    /*
     * Sleep spells and extremely wounded folks.
     */
    /*if ( *//*!IS_AWAKE(victim) Nah let them die! --GW */		/*letsmake NPC's not slaughter PC's */
    /*&&   !IS_AFFECTED( victim, AFF_PARALYSIS ) )
    {*/
/*	if ( victim->fighting
	&&   victim->fighting->who->hunting
	&&   victim->fighting->who->hunting->who == victim )
	   stop_hunting( victim->fighting->who );

	if ( victim->fighting
	&&   victim->fighting->who->hating
	&&   victim->fighting->who->hating->who == victim )
	   stop_hating( victim->fighting->who );

	if (!npcvict && IS_NPC(ch))
	  stop_fighting( victim, TRUE );
	else
	  stop_fighting( victim, FALSE );*/
/*    }*/

    /* Added this cause the mobile seems to still be fightin the char and vice
       versa after the attack is done, for ranged attacks  --GW */
    if ( ch->in_room != victim->in_room )
    stop_fighting(ch,TRUE);
 
    /*
     * Payoff for killing things.
     * Was to much crap here, in death.c now --GW
     */
     if ( victim->position == POS_DEAD )
     {
	group_gain( ch, victim );

	/*
	 * Check to see if thats there Quest Mob! --GW
         */
	quest_death_check(ch,victim);

	/* 
         * Fix up the killers ego --GW
         */
	ego_update(ch,victim, TRUE);


 
        if ( !npcvict )
        {

        if ( ( death_handler( ch, victim, npcvict ))==TRUE )
	{
        return TRUE;
	}
     
   	    /*
	     * Dying penalty:
	     * 1/2 way back to previous level.
	     */
	    if ( victim->exp > exp_level(victim, victim->level) )
	     victim->exp -= (victim->exp/2);
            do_help(victim,"_DIEMSG_");

	    /*
	     * New penalty... go back to the beginning of current level.
	     victim->exp = exp_level( victim, victim->level );
	     */
      }
	else
	if ( !IS_NPC(ch) )		/* keep track of mob vnum killed */
	    add_kill( ch, victim );

	loot = legal_loot( ch, victim );

	set_cur_char(victim);
	raw_kill( ch, victim );
	victim = NULL;

	if ( !IS_NPC(ch) && loot )
	{
	   /* Autogold by Scryn 8/12 */
	    if ( IS_SET(ch->act, PLR_AUTOGOLD) && npcvict )
	    {
		init_gold = ch->gold;
		do_get( ch, "coins corpse" );
		do_get( ch, "pieces corpse" );
		new_gold = ch->gold;
		gold_diff = (new_gold - init_gold);
		if (gold_diff > 0)
                {
                  sprintf(buf1,"%d",gold_diff);
		  do_split( ch, buf1 );
		} 
	    }
	    if ( IS_SET(ch->act, PLR_AUTOLOOT) && npcvict )
		do_get( ch, "all corpse" );
	    else
		do_look( ch, "in corpse" );


	    if ( IS_SET(ch->act, PLR_AUTOSAC) && npcvict )
	    {
		      if ( ms_find_obj(ch) )
        		return rVICT_DIED;
	   if ( ch->in_room )
	   {
	    obj = get_obj_list_rev( ch, "corpse", ch->in_room->last_content );
	    
    	       if ( !obj )
               {
                  return rVICT_DIED;
               }
		if ( obj->item_type == ITEM_CORPSE_NPC ) 
		do_sacrifice( ch, "corpse" );
	    }
	    }
	   }	

    	if ( IS_SET( sysdata.save_flags, SV_KILL ) )
	   save_char_obj( ch );
		return rVICT_DIED;
    }

    if ( victim == ch )
	return rNONE;

    /*
     * Take care of link dead people.
     */
    if ( !npcvict && !victim->desc  
    && !IS_SET( victim->pcdata->flags, PCFLAG_NORECALL ) )
    {
	if ( number_range( 0, victim->wait ) == 0)
	{
	    do_recall( victim, "" );
	    return rNONE;
	}
    }

    /*
     * Wimp out?
     */
    if ( npcvict && dam > 0 )
    {
	if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 1 ) == 0
	&&   victim->hit < victim->max_hit / 2 )
	||   ( IS_AFFECTED(victim, AFF_CHARM) && victim->master
	&&     victim->master->in_room != victim->in_room ) )
	{
	    start_fearing( victim, ch );
	    stop_hunting( victim );
	    do_flee( victim, "" );
	}
    }

    if ( !npcvict
    &&   victim->hit > 0
    &&   victim->hit <= victim->wimpy
    &&   victim->wait == 0 )
	do_flee( victim, "" );
    else
    if ( !npcvict && IS_SET( victim->act, PLR_FLEE ) )
	do_flee( victim, "" );

    tail_chain( );
    return rNONE;
}



bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{
//    int victclan;
//    int chclan;

    /* safety checks -- GW */
    if ( ch == NULL )
	return FALSE;

    if ( victim == NULL )
	return FALSE;	

    /* Thx Josh! */
    if ( who_fighting( ch ) == ch )
	return FALSE;

/* ARENA room checking */
        if( in_arena( ch )
        && in_arena(victim) )
        return FALSE;

/*CHAOS On? */	
	if( chaos == 1)
	return FALSE;

/* In a Club Maze? */
	if ( ch->in_room && ch->in_room->area &&
		IS_SET( ch->in_room->area->flags, AFLAG_CLUB_HALL ) )
	return FALSE;

/* in Kombat? */
	if( !IS_NPC(ch) && IS_SET(ch->pcdata->flags,PCFLAG_KOMBAT) &&
	  ( ch->in_room->vnum != 21440 ))
	return FALSE;

/* in CTF? */
	if( !IS_NPC(ch) && IS_SET(ch->pcdata->flagstwo,MOREPC_CTF) &&
	  ( ch->in_room->vnum != 21440 ))
	return FALSE;

/* Dragon? */
	if( !IS_NPC(ch) && !IS_NPC(victim) && victim->advclass == 14 )
	return FALSE;

//    victclan = victim->pcdata->clan;
//    chclan = ch->pcdata->clan;

//	not no .. but FUCK NO! leave it alone. --GW
//    if ( victim->pcdata->clan != ch->pcdata->clan )
//      return FALSE;


    if ( !victim->in_room )
     char_to_room(victim, ch->in_room);

    if ( victim && victim->in_room )
    {
    if ( IS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
    {
	set_char_color( AT_MAGIC, ch );
	send_to_char( "A magical force prevents you from attacking.\n\r", ch );
	return TRUE;
    }
    }

    if ( ch->level > LEVEL_IMMORTAL )
        return FALSE;

    

    if( !IS_NPC( ch ) && !IS_NPC( victim )
       && ch != victim 
       && IS_SET( victim->in_room->area->flags, AFLAG_NOPKILL ) ) 
    {
        set_char_color( AT_IMMORT, ch );
        send_to_char( "The gods have forbidden player killing in this area.\n\r", ch );
        return TRUE;
    }
 
    if ( IS_NPC(ch) || IS_NPC(victim) )
	return FALSE;

	if (!IS_NPC(ch)) 
    {
	if( !IS_NPC(ch) && IS_SET(ch->pcdata->flags, PCFLAG_ASSASSIN))
	return FALSE;

	if( !IS_NPC(ch) && IS_SET(victim->pcdata->flags, PCFLAG_ASSASSIN))
	return FALSE;
	}

    if ( ch->level < 5 )
    {
	set_char_color( AT_WHITE, ch );	
	send_to_char( "You are not yet ready, needing age or experience, if not both. \n\r", ch );
	return TRUE;
    }

    if ( victim->level < 5 )
    {
	set_char_color( AT_WHITE, ch );
	send_to_char( "They are yet too young to die.\n\r", ch );
	return TRUE;
    }

    if ( get_timer(victim, TIMER_PKILLED) > 0 )
    {
	set_char_color( AT_GREEN, ch );
        send_to_char( "That character has died within the last 5 minutes.\n\r", ch);
        return TRUE;
    }
  
    if ( get_timer(ch, TIMER_PKILLED) > 0 )
    {
	set_char_color( AT_GREEN, ch );
        send_to_char( "You have been killed within the last 5 minutes.\n\r", ch );
        return TRUE;
    }

    return FALSE;
}

/*
 * just verify that a corpse looting is legal
 */
bool legal_loot( CHAR_DATA *ch, CHAR_DATA *victim )
{
    /* anyone can loot mobs */
    if ( IS_NPC(victim) )
      return TRUE;
    /* non-charmed mobs can loot anything */
    if ( IS_NPC(ch) && !ch->master )
      return TRUE;
    /* members of different clans can loot too! -Thoric */
    if ( !IS_NPC(ch) && !IS_NPC(victim)
    &&    IS_SET( ch->pcdata->flags, PCFLAG_DEADLY ) 
    &&    IS_SET( victim->pcdata->flags, PCFLAG_DEADLY ) ) 
	return TRUE;
    return FALSE;
}

/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
    /*
     * NPC's are fair game.
     */
    if ( IS_NPC(victim) )
    {
	if ( !IS_NPC( ch ) )
	{
	  int level_ratio;
	  level_ratio = URANGE( 1, ch->level / victim->level, 50);
	  if ( ch->pcdata->clan )
	    ch->pcdata->clan->mkills++;
	  ch->pcdata->mkills++;
	  ch->in_room->area->mkills++;
	  if ( ch->pcdata->deity ) 
	  {
	    if ( victim->race == ch->pcdata->deity->npcrace )
	      adjust_favor( ch, 3, level_ratio );
	    else
	      if ( victim->race == ch->pcdata->deity->npcfoe )
		adjust_favor( ch, 17, level_ratio );
	      else
                adjust_favor( ch, 2, level_ratio );
	  }
	}
	return;
    }


    /*
     * Any character in the arena is ok to kill.
     */

    if ( in_arena( ch ) )
      return;

     /*
      * Chaos is on, kill away:)
      */

     if ( chaos == 1 )
      return;

     /*
      * In a club HALL or MAZE?
      */
     if ( ch->in_room && ch->in_room->area &&
		IS_SET( ch->in_room->area->flags, AFLAG_CLUB_HALL ) )
     return;


     /*
      * Mortal Kombat
      */
     if ( ( !IS_NPC(ch) && !IS_NPC(victim) ) &&
	    IS_SET( ch->pcdata->flags, PCFLAG_KOMBAT ) )
       return;

     /* CTF */
     if ( ( !IS_NPC(ch) && !IS_NPC(victim) ) &&
	    IS_SET( ch->pcdata->flagstwo, MOREPC_CTF ) )
       return;


     /*
      * Dragons
      */
     if ( !IS_NPC(ch) && !IS_NPC(victim) )
     {
      if ( IS_ADVANCED(ch) && IS_ADVANCED(victim) )
      {
	if ( ch->advclass == 14 && victim->advclass == 14 )
	{
	   if( ch->advlevel <= (victim->advlevel+10) )
   	     return;
	}
      }
     }
    /*
     * So are killers and thieves.
     */
    if ( IS_SET(victim->act, PLR_KILLER)
    || IS_SET(victim->pcdata->flags, PCFLAG_ASSASSIN)
    || IS_SET(victim->act, PLR_THIEF) )
    {
	if ( !IS_NPC( ch ) )
	{
	  if ( ch->pcdata->clan )
	    ch->pcdata->clan->pkills++;
	  ch->in_room->area->pkills++;
	}
	return;
    }

    if ( ( ch->level > (victim->level+10) ) || 
	   !IS_SET( victim->pcdata->flags, PCFLAG_DEADLY)
	|| (IS_ADVANCED(ch) && !IS_ADVANCED(victim)) )
    {
    set_char_color( AT_WHITE, ch );
    send_to_char( "A strange feeling grows deep inside you, and a tingle goes up your spine...\n\r", ch );
    set_char_color( AT_IMMORT, ch );
    send_to_char( "A deep voice booms inside your head, 'Thou shall now be known as a deadly murderer!!!'\n\r", ch );
    set_char_color( AT_WHITE, ch );
    send_to_char( "You feel as if your soul has been revealed for all to see.\n\r", ch );
    SET_BIT(ch->act, PLR_KILLER);
    if ( IS_SET( ch->act, PLR_ATTACKER) )
      REMOVE_BIT(ch->act, PLR_ATTACKER);
    save_char_obj( ch );
    return;
    }

    /* clan checks					-Thoric */
    if ( ( !IS_NPC(ch) && !IS_NPC(victim) )
    &&    (IS_SET( ch->pcdata->flags, PCFLAG_DEADLY )
    &&    IS_SET( victim->pcdata->flags, PCFLAG_DEADLY ))
    &&    ( ( ( IS_ADVANCED(ch) && IS_ADVANCED(victim))
    &&	  ( ch->advlevel <= (victim->advlevel+10) ) )
    ||    ( ( !IS_ADVANCED(ch) && !IS_ADVANCED(victim) )
    &&	  ( ch->level <= (victim->advlevel+10) ) ) ) )
    {
      
      /* not of same clan? Go ahead and kill!!! */
      if   (!IS_NPC(ch) && ( ch->pcdata->clan && victim->pcdata->clan)
      &&   (ch->pcdata->clan->clan_type != CLAN_NOKILL
      &&   victim->pcdata->clan->clan_type != CLAN_NOKILL)
      &&   (ch->pcdata->clan != victim->pcdata->clan ) ) 

      {
	if ( ch->pcdata->clan ) ch->pcdata->clan->pkills++;
	  ch->hit = ch->max_hit;
	  ch->mana = ch->max_mana;
	  ch->move = ch->max_move;
	if ( ch->pcdata )
	  ch->pcdata->condition[COND_BLOODTHIRST] = get_bloodthirst(ch);
	update_pos(victim);
	if ( victim != ch )
	{
	  act( AT_MAGIC, "Bolts of blue energy rise from the corpse, seeping into $n.", ch, victim->name, NULL, TO_ROOM );
	  act( AT_MAGIC, "Bolts of blue energy rise from the corpse, seeping into you.", ch, victim->name, NULL, TO_CHAR ); 
	}
	if ( victim->pcdata->clan )
	  victim->pcdata->clan->pdeaths++;
	victim->pcdata->pdeaths++;   
	adjust_favor( victim, 11, 1 );
	adjust_favor( ch, 2, 1 );
	add_timer( victim, TIMER_PKILLED, 115, NULL, 0 );
	WAIT_STATE( victim, 3 * PULSE_VIOLENCE );
	/* SET_BIT(victim->act, PLR_PK); */
	return; 
      }
	return;
    }


    /*
     * Charm-o-rama.
     */
    if ( IS_AFFECTED(ch, AFF_CHARM) )
    {
	if ( !ch->master )
	{
	    char buf[MAX_STRING_LENGTH];

	    sprintf( buf, "Check_killer: %s bad AFF_CHARM",
		IS_NPC(ch) ? ch->short_descr : ch->name );
	    bug( buf, 0 );
	    affect_strip( ch, gsn_charm_person );
	    xREMOVE_BIT( ch->affected_by, AFF_CHARM );
	    return;
	}

	/* stop_follower( ch ); */
//	if ( ch->master )
//	  check_killer( ch->master, victim );
	return;
    }

    /*
     * NPC's are cool of course (as long as not charmed).
     * Hitting yourself is cool too (bleeding).
     * So is being immortal (Alander's idea).
     * And current killers stay as they are.
     */
    if ( IS_NPC(ch) )
    {
      if ( !IS_NPC(victim) )
      {
	int level_ratio;
        if ( victim->pcdata->clan )
          victim->pcdata->clan->mdeaths++;
        victim->pcdata->mdeaths++;
	victim->in_room->area->mdeaths++;
	level_ratio = URANGE( 1, ch->level / victim->level, 50 );
	if ( victim->pcdata->deity )
	{
	  if ( ch->race == victim->pcdata->deity->npcrace )
	    adjust_favor( victim, 12, level_ratio );
	  else
	    if ( ch->race == victim->pcdata->deity->npcfoe )
		adjust_favor( victim, 15, level_ratio );
	    else
	        adjust_favor( victim, 11, level_ratio );
	}
      }
      return;
    }

    if ( ch == victim || ch->level >= LEVEL_IMMORTAL )
      return;
      
    if ( !IS_NPC(ch) )
    {
      if ( ch->pcdata->clan )
        ch->pcdata->clan->illegal_pk++;
      ch->pcdata->illegal_pk++;
      ch->in_room->area->illegal_pk++;
    }
    if ( !IS_NPC(victim) )
    {
      if ( victim->pcdata->clan )
        victim->pcdata->clan->pdeaths++;
      victim->pcdata->pdeaths++;
      victim->in_room->area->pdeaths++;
    }

    if ( IS_SET(ch->act, PLR_KILLER) )
      return;

    set_char_color( AT_WHITE, ch );
    send_to_char( "A strange feeling grows deep inside you, and a tingle goes up your spine...\n\r", ch );
    set_char_color( AT_IMMORT, ch );
    send_to_char( "A deep voice booms inside your head, 'Thou shall now be known as a deadly murderer!!!'\n\r", ch );
    set_char_color( AT_WHITE, ch );
    send_to_char( "You feel as if your soul has been revealed for all to see.\n\r", ch );
    SET_BIT(ch->act, PLR_KILLER);
    if ( IS_SET( ch->act, PLR_ATTACKER) )
      REMOVE_BIT(ch->act, PLR_ATTACKER);
    save_char_obj( ch );
    return;
}

/*
 * See if an attack justifies a ATTACKER flag.
 */
void check_attacker( CHAR_DATA *ch, CHAR_DATA *victim )
{

/* 
 * Made some changes to this function Apr 6/96 to reduce the prolifiration
 * of attacker flags in the realms. -Narn
 */
    /*
     * NPC's are fair game.
     * So are killers and thieves.
     */
    if ( IS_NPC(victim)
    ||   IS_SET(victim->act, PLR_KILLER)
    ||   IS_SET(victim->act, PLR_THIEF) )
	return;

    /* deadly char check */
    if ( !IS_NPC(ch) && !IS_NPC(victim)
         && CAN_PKILL( ch ) && CAN_PKILL( victim ) ) 
    {
      if ( !(ch->pcdata->clan && victim->pcdata->clan 
           && ch->pcdata->clan == victim->pcdata->clan ) )
        return;
    }

    /*
     * Charm-o-rama.
     */
    if ( IS_AFFECTED(ch, AFF_CHARM) )
    {
	if ( !ch->master )
	{
	    char buf[MAX_STRING_LENGTH];

	    sprintf( buf, "Check_attacker: %s bad AFF_CHARM",
		IS_NPC(ch) ? ch->short_descr : ch->name );
	    bug( buf, 0 );
	    affect_strip( ch, gsn_charm_person );
	    xREMOVE_BIT( ch->affected_by, AFF_CHARM );
	    return;
	}

        /* Won't have charmed mobs fighting give the master an attacker 
           flag.  The killer flag stays in, and I'll put something in 
           do_murder. -Narn */
	/*SET_BIT(ch->master->act, PLR_ATTACKER);*/
	/* stop_follower( ch ); */
	return;
    }

    /*
     * NPC's are cool of course (as long as not charmed).
     * Hitting yourself is cool too (bleeding).
     * So is being immortal (Alander's idea).
     * And current killers stay as they are.
     */
    if ( IS_NPC(ch)
    ||   ch == victim
    ||   ch->level >= LEVEL_IMMORTAL
    ||   IS_SET(ch->act, PLR_ATTACKER)
    ||   IS_SET(ch->act, PLR_KILLER) )
	return;

    SET_BIT(ch->act, PLR_ATTACKER);
    save_char_obj( ch );
    return;
}


/*
 * Set position of a victim.
 */
void update_pos( CHAR_DATA *victim )
{
    if ( !victim )
    {
      bug( "update_pos: null victim", 0 );
      return;
    }

    if ( victim->hit > 0 )
    {
	if ( victim->position <= POS_STUNNED )
	  victim->position = POS_STANDING;
	if ( (IS_AFFECTED( victim, AFF_PARALYSIS )))
	  victim->position = POS_STUNNED;
	return;
    }

    if ( IS_NPC(victim) || victim->hit <= -11 )
    {
	if ( victim->mount )
	{
	  act( AT_ACTION, "$n falls from $N.",
		victim, NULL, victim->mount, TO_ROOM );
	  REMOVE_BIT( victim->mount->act, ACT_MOUNTED );
	  victim->mount = NULL;
	}
	victim->position = POS_DEAD;
	return;
    }

	 if ( victim->hit <= -6 ) victim->position = POS_MORTAL;
    else if ( victim->hit <= -3 ) victim->position = POS_INCAP;
    else                          victim->position = POS_STUNNED;

    if (( victim->position > POS_STUNNED
    && (  IS_AFFECTED( victim, AFF_PARALYSIS) ) ) )
      victim->position = POS_STUNNED;

    if ( victim->mount )
    {
	act( AT_ACTION, "$n falls unconscious from $N.",
		victim, NULL, victim->mount, TO_ROOM );
	REMOVE_BIT( victim->mount->act, ACT_MOUNTED );
	victim->mount = NULL;
    }
    return;
}


/*
 * Start fights.
 */
void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
{
    FIGHT_DATA *fight=NULL;

    if ( ch->fighting )
    {
	char buf[MAX_STRING_LENGTH];

	sprintf( buf, "Set_fighting: %s -> %s (already fighting %s)",
		ch->name, victim->name, ch->fighting->who->name );
	bug( buf, 0 );
	return;
    }

    if ( IS_AFFECTED(ch, AFF_SLEEP) )
      affect_strip( ch, gsn_sleep );

    /* Limit attackers -Thoric */
    if ( victim->num_fighting > max_fight(victim) )
    {
	send_to_char( "There are too many people fighting for you to join in.\n\r", ch );
	return;
    }

    CREATE( fight, FIGHT_DATA, 1 );
    fight->who	 = victim;
    fight->xp	 = (int) xp_compute( ch, victim ) * 0.85;
    fight->align = align_compute( ch, victim );
    if ( !IS_NPC(ch) && IS_NPC(victim) )
      fight->timeskilled = times_killed(ch, victim);
    ch->num_fighting = 1;
    ch->fighting = fight;
    ch->position = POS_FIGHTING;
    victim->num_fighting++;
/*    if ( victim->switched && IS_AFFECTED(victim->switched, AFF_POSSESS))
    {
	send_to_char( "You are disturbed!\n\r", victim->switched );
	do_return( victim->switched, "" );
    }*/
    return;
}


CHAR_DATA *who_fighting( CHAR_DATA *ch )
{
char bug_buf[MAX_STRING_LENGTH];

    if ( !ch )
    {
	bug( "who_fighting: null ch", 0 );
	return NULL;
    }

    if ( !ch->fighting )
      return NULL;

    if ( !ch->fighting->who )
	{
	sprintf(bug_buf,"who_fighting: NULL ch->fighting->who (%s)",
		ch->name );
	return NULL;
	}

    return ch->fighting->who;
}

void free_fight( CHAR_DATA *ch )
{
   if ( !ch )
   {
	bug( "Free_fight: null ch!", 0 );
	return;
   }
   if ( ch->fighting )
   {
     if ( !char_died(ch->fighting->who) )
       --ch->fighting->who->num_fighting;
     DISPOSE( ch->fighting );
   }
   ch->fighting = NULL;
   if ( ch->mount )
     ch->position = POS_MOUNTED;
   else
     ch->position = POS_STANDING;
   /* Berserk wears off after combat. -- Altrag */
   if ( IS_AFFECTED(ch, AFF_BERSERK) )
   {
     affect_strip(ch, gsn_berserk);
     set_char_color(AT_WEAROFF, ch);
     send_to_char(skill_table[gsn_berserk]->msg_off, ch);
     send_to_char("\n\r", ch);
   }
   return;
}


/*
 * Stop fights.
 */
void stop_fighting( CHAR_DATA *ch, bool fBoth )
{
    CHAR_DATA *fch;
    ZONE_DATA *in_zone;

    if( !ch )
	return;

    free_fight( ch );
    update_pos( ch );

    if ( !fBoth )   /* major short cut here by Thoric */
      return;

    for ( fch = first_char; fch; fch = fch->next )
    {
	if ( who_fighting( fch ) == ch )
	{
	    free_fight( fch );
	    update_pos( fch );
	}
    }
if ( ch->in_room && ch->in_room->area && ch->in_room->area->zone )
in_zone=find_zone(ch->in_room->area->zone->number);
else
in_zone = find_zone(1);

    for ( fch = in_zone->first_mob; fch; fch = fch->next )
    {
	if ( who_fighting( fch ) == ch )
	{
	    free_fight( fch );
	    update_pos( fch );
	}
    }

    return;
}

void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *gch;
    CHAR_DATA *lch;
    long xp;
    int members;

    /*
     * Monsters don't get kill xp's or alignment changes.
     * Dying of mortal wounds or poison doesn't give xp to anyone!
     */
    if ( !ch )
     return;

    if ( !victim) 
     return;

    if ( IS_NPC(ch) || victim == ch || war == 1 || (IS_NPC(ch) && IS_SET(ch->pcdata->flags, PCFLAG_KOMBAT) ) )
	return;

    members = 0;
    for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
    {
	if ( gch && ch && is_same_group( gch, ch ) )
	    members++;
    }

    if ( members == 0 )
    {
	bug( "Group_gain: members.", members );
	members = 1;
    }

    lch = ch->leader ? ch->leader : ch;

    for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
    {
/*	OBJ_DATA *obj;
	OBJ_DATA *obj_next;
-- used for zap .. no longer used --GW
*/
	if ( !is_same_group( gch, ch ) )
	    continue;

	if ( gch->level - lch->level >  10 )
	{
	    send_to_char( "You are too high for this group.\n\r", gch );
	    continue;
	}

	if ( gch->level - lch->level < -10 )
	{
	    send_to_char( "You are too low for this group.\n\r", gch );
	    continue;
	}

	xp = (int) (xp_compute( gch, victim ) * 0.3 ) / members;
	if ( !gch->fighting )
	  xp /= 2;

	if ( IS_NPC(victim) && IS_SET(victim->acttwo, ACT_CREATE_LIFE_MOB))
	xp = 0;

	gch->alignment = align_compute( gch, victim );
	buf[0] = '\0';
	sprintf( buf, "You receive %s experience points for the Kill.\n\r", num_comma(xp) );
	send_to_char( buf, gch );

      /* New 'statistical' display of EXP Gain per kill --GW */
      if ( !IS_NPC(ch) )
      {
        sprintf( buf, "You received a total of %s experiance points for Damage Inflicted.\n\r",num_comma(ch->pcdata->battle_xp));
	send_to_char( buf, gch );
	sprintf( buf, "Total Experiance Gained: %s\n\r",num_comma(ch->pcdata->battle_xp + xp));
        send_to_char( buf, gch );
	ch->pcdata->battle_xp = 0;
       }
	buf[0] = '\0';
	gain_exp( gch, xp, TRUE );

/* this sucks .. remove --GW */
/*	for ( obj = ch->first_carrying; obj; obj = obj_next )
	{
	    obj_next = obj->next_content;
	    if ( obj->wear_loc == WEAR_NONE )
		continue;

	    if ( ( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)    && IS_EVIL(ch)    )
	    ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)    && IS_GOOD(ch)    )
	    ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch) ) )
	    {
		act( AT_MAGIC, "You are zapped by $p.", ch, obj, NULL, TO_CHAR );
		act( AT_MAGIC, "$n is zapped by $p.",   ch, obj, NULL, TO_ROOM );
	        
                remove_obj ( ch, obj->wear_loc, TRUE );
		oprog_zap_trigger(ch, obj);  
		if ( char_died(ch) )
		  return;
	    }
	}
*/
   if (!IS_NPC(gch) && IS_SET(gch->pcdata->flags,PCFLAG_QUESTING )
        && IS_NPC(victim))
        {
            if (gch->pcdata->questmob == victim->pIndexData->vnum)
            {
               send_to_char("You have almost completed your quest!\n\r",gch);
        send_to_char(
        "Return to the questmaster before your time runs of time.\n\r",gch);
                ch->pcdata->questmob = -1;
            }
        }


    }

    return;
}


int align_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
    int align, newalign;

    align = gch->alignment - victim->alignment;

    if ( align >  500 )
	newalign  = UMIN( gch->alignment + (align-500)/4,  1000 );
    else
    if ( align < -500 )
	newalign  = UMAX( gch->alignment + (align+500)/4, -1000 );
    else
	newalign  = gch->alignment - (int) (gch->alignment / 4);

    return newalign;
}


/*
 * Calculate how much XP gch should gain for killing victim
 * Lots of redesigning for new exp system by Thoric
 */
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
    int align;
    int xp;
    int xp_ratio;
    int gchlev = gch->level;

    xp	  = (get_exp_worth( victim )
    	  *  URANGE( 0, (victim->level - gchlev) + 25, 13 )) / 5.9;

	if ( doubleexp == 1)
	xp = xp*2;

    align = gch->alignment - victim->alignment;

    /* bonus for attacking opposite alignment */
    if ( align >  990 || align < -990 )
	xp = (xp*5) >> 2;
    else
    /* penalty for good attacking same alignment */
    if ( gch->alignment > 300 && align < 250 )
	xp = (xp*3) >> 2;

    xp = number_range( (xp*3) >> 2, (xp*5) >> 2 );

    /* get 1/4 exp for players					-Thoric */
    if ( !IS_NPC( victim ) )
      xp /= 4;
    else
    /* reduce exp for killing the same mob repeatedly		-Thoric */
    if ( !IS_NPC( gch ) )
    {
	int times = times_killed( gch, victim );

	if ( times >= 20 )
	   xp = 0;
	else
	if ( times )
	{
	   xp = (xp * (20-times)) / 20;
	   if ( times > 15 )
	     xp /= 3;
	   else
	   if ( times > 10 )
	     xp >>= 1;
	}

    }

    /*
     * semi-intelligent experienced player vs. novice player xp gain
     * "bell curve"ish xp mod by Thoric
     * based on time played vs. level
     */
    if ( !IS_NPC( gch ) && gchlev > 5 )
    {
       xp_ratio = (int) gch->pcdata->played / gchlev;
       if ( xp_ratio > 20000 )
         xp = (xp*5) >> 2;
       else
       if ( xp_ratio < 16000 )
         xp = (xp*3) >> 2;
       else
       if ( xp_ratio < 10000 )
         xp >>= 1;
       else
       if ( xp_ratio < 5000 )
         xp >>= 2;
       else
       if ( xp_ratio < 3500 )
         xp >>= 3;
       else
       if ( xp_ratio < 2000 )
         xp >>= 4;
    }

    /*
     * Level based experience gain cap.  Cannot get more experience for
     * a kill than the amount for your current experience level   -Thoric
     */

    /* NO Exp for Ghosts!!!!!! --GW */
    if ( IS_AFFECTED( victim, AFF_GHOST ) )
    xp = 0;

    return URANGE(0, xp, exp_level( gch, gchlev ));
}


/*
 * Revamped by Thoric to be more realistic
 */
void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
    char buf1[256], buf2[256], buf3[256];
    char *vs;
    char *vp;
    char *attack;
    char punct;
    sh_int dampc;
    struct skill_type *skill = NULL;
    bool gcflag = FALSE;
    bool gvflag = FALSE; 
    extern sh_int dam_no_msg;

    if ( !ch || !victim )
	return;

    vs = NULL;
    vp = NULL;
    attack = NULL;

    if ( dam_no_msg == 1 )
      return;    

    if ( ! dam )
      dampc = 0;
    else
      dampc = URANGE( 0,( (dam * 1000) / victim->max_hit) +
              ( 50 - ((victim->hit * 50) / victim->max_hit) ),32000);

	 if ( dampc  <	  0 ) { vs = "HELP"; vp = "HELPS"; }
    else if ( dam   ==    0 ) { vs = "miss";	vp = "misses";}
    else if ( dampc <=    5 ) { vs = "barely hit";vp = "barely hits";}
    else if ( dampc <=   10 ) { vs = "scratch";	vp = "scratches";	}
    else if ( dampc <=   20 ) { vs = "scrape";	vp = "scrapes";		}
    else if ( dampc <=   30 ) { vs = "graze";	vp = "grazes";		}
    else if ( dampc <=   40 ) { vs = "bruise";	vp = "bruises";		}
    else if ( dampc <=   50 ) { vs = "hit";	vp = "hits";		}
    else if ( dampc <=   60 ) { vs = "hurt";	vp = "hurts";		}
    else if ( dampc <=   75 ) { vs = "wound";	vp = "wounds";	}
    else if ( dampc <=   80 ) { vs = "lacerate";	vp = "lacerates";		}
    else if ( dampc <=   90 ) { vs = "harm";    vp = "harms";		}
    else if ( dampc <=  125 ) { vs = "ravage";	vp = "ravages";	}
    else if ( dampc <=  150 ) { vs = "demolish"; vp = "demolishes";	}
    else if ( dampc <=  200 ) { vs = "cripple";	vp = "cripples";		}
    else if ( dampc <=  300 ) { vs = "MANGLE";vp = "MANGLES";	}
    else if ( dampc <=  400 ) { vs = "DISMEMBER";vp = "DISMEMBERS";	}
    else if ( dampc <=  500 ) { vs = "== SLAUGHTER ==";  vp = "== SLAUGHTERS ==";	}
    else if ( dampc <=  600 ) { vs = "**  LIQUEFY **"; vp = "** LIQUEFIES **";	}
    else if ( dampc <=  750 ) { vs = "|| DISINTEGRATE ||";vp = "|| DISINTEGRATES ||";	}
    else if ( dampc <=  990 ) { vs = "<== TERMINATE ==>";
			        vp = "<== TERMINATES ==>";			}
    else                      { vs = "do *** TERRIBLE THINGS *** to";
			        vp = "does *** TERRIBLE THINGS *** to";		}

    punct   = '\0';

    punct   = (dampc <= 30) ? '.' : '!';

    if ( dam < 0 )
	dam = 0;

    if ( dam == 0 && (!IS_NPC(ch) && 
       (IS_SET(ch->pcdata->flags, PCFLAG_GAG)))) gcflag = TRUE;

    if ( dam == 0 && (!IS_NPC(victim) &&
       (IS_SET(victim->pcdata->flags, PCFLAG_GAG)))) gvflag = TRUE;

    if ( dt >=0 && dt < top_sn )
	skill = skill_table[dt];
    if ( dt == TYPE_HIT )
    {
        buf1[0] = '\0';
        buf2[0] = '\0';
        buf3[0] = '\0';

	sprintf( buf1, "&G$n &R%s&G $N%c&W",  vp, punct );
	sprintf( buf2, "&GYou &R%s&G $N%c&W", vs, punct );
	sprintf( buf3, "&G$n &R%s&G you%c&W", vp, punct );
    }
    else
    if ( dt > TYPE_HIT && is_wielding_poisoned( ch ) )
    {
	if ( dt < TYPE_HIT + sizeof(attack_table)/sizeof(attack_table[0]) )
	    attack	= attack_table[dt - TYPE_HIT];
	else
	{
	    dt  = TYPE_HIT;
	    attack  = attack_table[0];
        }

        buf1[0] = '\0';
        buf3[0] = '\0';
        buf2[0] = '\0';
	sprintf( buf1, "&G$n's &Rpoisoned %s&G %s $N%c&W", attack, vp,punct);
	sprintf( buf2, "&GYour &Rpoisoned %s&G %s $N%c&W", attack, vp,punct);
	sprintf( buf3, "&G$n's &Rpoisoned %s&G %s you%c&W", attack, vp,punct); 
    }
    else
    {
	if ( skill )
	{
	    attack	= skill->noun_damage;
	    if ( dam == 0 )
	    {
		bool found = FALSE;

		if ( skill->miss_char && skill->miss_char[0] != '\0' )
		{
		   act( AT_HIT, skill->miss_char, ch, NULL, victim,TO_CHAR);
		   found = TRUE;
		}
		if ( skill->miss_vict && skill->miss_vict[0] != '\0' )
		{
		   act( AT_HITME, skill->miss_vict, ch, NULL, victim,TO_VICT );
		   found = TRUE;
		}
		if ( skill->miss_room && skill->miss_room[0] != '\0' )
		{
		   act( AT_ACTION, skill->miss_room, ch, NULL, victim, TO_NOTVICT );
		   found = TRUE;
		}
		if ( found )	/* miss message already sent */
		  return;
	    }
	    else
	    {
		if ( skill->hit_char && skill->hit_char[0] != '\0' )
		  act( AT_HIT, skill->hit_char, ch, NULL, victim, TO_CHAR );
		if ( skill->hit_vict && skill->hit_vict[0] != '\0' )
		  act( AT_HITME, skill->hit_vict, ch, NULL, victim, TO_VICT );
		if ( skill->hit_room && skill->hit_room[0] != '\0' )
		  act( AT_ACTION, skill->hit_room, ch, NULL, victim, TO_NOTVICT );
	    }
	}
	else if ( dt >= TYPE_HIT
	&& dt < TYPE_HIT + sizeof(attack_table)/sizeof(attack_table[0]) )
	    attack	= attack_table[dt - TYPE_HIT];
	else
	{
	    dt  = TYPE_HIT;
	    attack  = attack_table[0];
	}

	buf1[0] = '\0';
	buf2[0] = '\0';
	buf3[0] = '\0';


	sprintf( buf1, "&G$n's %s &R%s&G $N%c&W",  attack, vp, punct );
	sprintf( buf2, "&GYour %s &R%s&G $N%c&W",  attack, vp, punct );
	sprintf( buf3, "&G$n's %s &R%s&G you%c&W", attack, vp, punct );
    }

    act( AT_PLAIN, buf1, ch, NULL, victim, TO_NOTVICT );
    if (!gcflag)  act( AT_PLAIN, buf2, ch, NULL, victim, TO_CHAR );
    if (!gvflag) act( AT_PLAIN, buf3, ch, NULL, victim, TO_VICT );

    return;
}


void do_kill( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Kill whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == NULL )
    return;

    if ( victim == NULL )
    return;

    if ( !IS_NPC(victim) )
    {
	if ( !IS_SET(victim->act, PLR_KILLER)
	&&   !IS_SET(victim->act, PLR_THIEF) )
	{
	    send_to_char( "You must MURDER a player.\n\r", ch );
	    return;
	}

    }

   /*
    *
    else
    {
	if ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
	{
	    send_to_char( "You must MURDER a charmed creature.\n\r", ch );
	    return;
	}
    }
    *
    */

    if ( victim == ch )
    {
	send_to_char( "You hit yourself.  Ouch!\n\r", ch );
	multi_hit( ch, ch, TYPE_UNDEFINED );
	return;
    }

    if ( is_safe( ch, victim ) )
	return;

    if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
    {
    act( AT_PLAIN, "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( ch->position == POS_FIGHTING )
    {
	send_to_char( "You do the best you can!\n\r", ch );
	return;
    }

    WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
//    check_killer( ch, victim );
//    check_attacker( ch, victim );
   if ( IS_IMMORTAL(ch) && IS_NPC(victim) && (get_trust(ch) < 56 ) )
   {
     send_to_char("You should not be killing mobiles!\n\r",ch);
     return;
   }

    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}



void do_murde( CHAR_DATA *ch, char *argument )
{
    send_to_char( "If you want to MURDER, spell it out.\n\r", ch );
    return;
}



void do_murder( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Murder whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char( "Suicide is a mortal sin.\n\r", ch );
	return;
    }

    if ( is_safe( ch, victim ) )
	return;

    if ( IS_AFFECTED(ch, AFF_CHARM) ) 
    {
      if ( ch->master == victim )
      {
        act( AT_PLAIN, "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
	return;
      }
      else
      {
        if ( ch->master )
          SET_BIT(ch->master->act, PLR_ATTACKER);
      }
    }

    if ( ch->position == POS_FIGHTING )
    {
	send_to_char( "You do the best you can!\n\r", ch );
	return;
    }

    if ( !IS_NPC( victim ) && IS_SET( ch->act, PLR_NICE ) )
    {
      send_to_char( "You feel too nice to do that!\n\r", ch );
      return;
    }
/*
    if ( !IS_NPC( victim ) && IS_SET( victim->act, PLR_PK ) )
*/

if ( !check_pk_ok(victim,ch)) 
  return;


    if (!IS_NPC (victim))
       {
       sprintf( log_buf, "%s: murder %s.", ch->name, victim->name );
       log_string_plus( log_buf, LOG_NORMAL, ch->level );
       }

    WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
    sprintf( buf, "Help!  I am being attacked by %s!", 
                   IS_NPC( ch ) ? ch->short_descr : ch->name );
    if ( IS_PKILL(victim) )
	do_wartalk( victim, buf );
    else
	do_yell( victim, buf );

/* Replaced these with New check --GW */
//    check_killer( ch, victim );
//    check_illegal_pk( ch, victim );
//    check_attacker( ch, victim );
    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}

bool in_arena( CHAR_DATA *ch )
{

if ( !ch || !ch->in_room )
return FALSE;

if ( ch->in_room && ( ch->in_room->vnum < 30 || ch->in_room->vnum > 44 ) )
  return FALSE;

return TRUE;
}

bool check_illegal_pk( CHAR_DATA *ch, CHAR_DATA *victim )
{


  if (!IS_NPC (victim) && !IS_NPC(ch))
  {
	if (ch == victim)
	return FALSE;

     if ( !IS_NPC(ch) && IS_ADVANCED(ch) && ch->advclass == 14 
     && !IS_NPC(victim) && IS_ADVANCED(victim) && victim->advclass == 14
     && ch->advlevel <= (victim->advlevel+10) )
	return FALSE;

    if ( IS_SET( victim->pcdata->flags, PCFLAG_DEADLY ) 
    && IS_SET( ch->pcdata->flags, PCFLAG_DEADLY ) 
    && (ch->level > (victim->level+10) ) )
      return FALSE;

    if ( IS_SET( victim->pcdata->flags, PCFLAG_ASSASSIN ) ||
	 IS_SET( ch->pcdata->flags, PCFLAG_ASSASSIN) )
	return FALSE;

     if ( in_arena( ch ) && in_arena(victim) )
	return FALSE;

    if (chaos == 1)
	return FALSE;

/* In a Club Maze? */
	if ( ch->in_room && ch->in_room->area &&
		IS_SET( ch->in_room->area->flags, AFLAG_CLUB_HALL ) )
	return FALSE;


    if ( IS_SET(ch->pcdata->flags, PCFLAG_KOMBAT ) ) 
	return FALSE;

    if ( IS_SET(ch->pcdata->flagstwo, MOREPC_CTF ) ) 
	return FALSE;

      sprintf( log_buf, "%s performing illegal pkill on %s at %d",
      (IS_NPC(ch) ? ch->short_descr : ch->name),
      victim->name,
      ch->in_room->vnum );
      log_string( log_buf );
      to_channel( log_buf, CHANNEL_MONITOR, "[ ** ", LEVEL_IMMORTAL );
      return TRUE;
  }
  return FALSE;
}


void do_flee( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *was_in;
    ROOM_INDEX_DATA *now_in=NULL;
    char buf[MAX_STRING_LENGTH];
    sh_int door;
    EXIT_DATA *pexit;
    bool succeded;
    sh_int attempt;

    if ( !who_fighting( ch ) )
    {
	if ( ch->position == POS_FIGHTING )
	{
	  if ( ch->mount )
	    ch->position = POS_MOUNTED;
	  else
	    ch->position = POS_STANDING;
	}
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( ch->move <= 0 )
    {
	send_to_char( "You're too exhausted to flee from combat!\n\r", ch );
	return;
    }

    /* No fleeing while stunned. - Narn */
    /* Ya .. --GW */
    if ( ch->position < POS_FIGHTING || ch->stun_rounds > 0 )
    {
       send_to_char("your to stunned to do that!",ch);
	return; 
    }
    succeded = FALSE;
    was_in = ch->in_room;
    for ( attempt = 0; attempt < 6; attempt++ )
    {

	door = number_door( );
	if ( ( pexit = get_exit(was_in, door) ) == NULL 
	|| ( IS_SET(pexit->exit_info, EX_CLOSED)
	&&   !IS_AFFECTED( ch, AFF_PASS_DOOR ) )
	|| ( !IS_NPC(ch) && IS_SET( ch->pcdata->flagstwo, MOREPC_ALIENS ) &&
	      IS_SET( pexit->to_room->room_flags, ROOM_DEATH ) )
	|| ( IS_NPC(ch)
	&&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
	    continue;

	if ( !can_flee_dir(ch, door) )
	  continue;

	succeded = TRUE; 
        affect_strip ( ch, gsn_sneak );
        xREMOVE_BIT( ch->affected_by, AFF_SNEAK );
	if ( ch->mount && ch->mount->fighting )
	    stop_fighting( ch->mount, TRUE );
	stop_fighting( ch, TRUE );
	move_char( ch, get_exit( ch->in_room, door ), 0, FALSE );
	now_in = ch->in_room;
	break;
        }

        if ( succeded == TRUE )
	{ 
	char_from_room(ch);
        char_to_room(ch, was_in );
//	ch->in_room = was_in;
	act( AT_FLEE, "$n flees head over heels!", ch, NULL, NULL, TO_ROOM );
        char_from_room(ch);
        char_to_room(ch, now_in);
//	ch->in_room = now_in;
	act( AT_FLEE, "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM );

	if ( !IS_NPC(ch) && !in_arena(ch) && (war == 0))
	{
	    CHAR_DATA *wf = who_fighting(ch);
	    int level_ratio=0;	    
	    sprintf(buf, "You flee from combat!");
	    act( AT_FLEE, buf, ch, NULL, NULL, TO_CHAR );
	    if ( wf ) level_ratio = URANGE( 1, wf->level / ch->level, 50 );
	    if ( ch->pcdata->deity )
	    {
	      if ( wf && wf->race == ch->pcdata->deity->npcrace )
		adjust_favor( ch, 1, level_ratio );
   	      else
		if ( wf && wf->race == ch->pcdata->deity->npcfoe )
		  adjust_favor( ch, 16, level_ratio );
		else
		  adjust_favor( ch, 0, level_ratio );
	    }
	}
    
	stop_fighting( ch, TRUE );
	return;
   }    
    if ( !IS_NPC(ch) && !in_arena(ch) && (war == 0 ) )
    {
    sprintf(buf, "You attempt to flee from combat! And &RFAIL!&w\n\r");
    send_to_char( buf, ch );
    }
    else
    {
    send_to_char("You Failed to Flee!!\n\r",ch);
    }

    return;
}



void do_sla( CHAR_DATA *ch, char *argument )
{
    send_to_char( "If you want to SLAY, spell it out.\n\r", ch );
    return;
}



void do_slay( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg );
    one_argument( argument, arg2 );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Slay whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "Suicide is a mortal sin.\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) && get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "immolate" ) )
    {
      act( AT_FIRE, "Your fireball turns $N into a blazing inferno.",  ch, NULL, victim, TO_CHAR    );
      act( AT_FIRE, "$n releases a searing fireball in your direction.", ch, NULL, victim, TO_VICT    );
      act( AT_FIRE, "$n points at $N, who bursts into a flaming inferno.",  ch, NULL, victim, TO_NOTVICT );
    }

    else if ( !str_cmp( arg2, "shatter" ) )
    {
      act( AT_LBLUE, "You freeze $N with a glance and shatter the frozen corpse into tiny shards.",  ch, NULL, victim, TO_CHAR    );
      act( AT_LBLUE, "$n freezes you with a glance and shatters your frozen body into tiny shards.", ch, NULL, victim, TO_VICT    );
      act( AT_LBLUE, "$n freezes $N with a glance and shatters the frozen body into tiny shards.",  ch, NULL, victim, TO_NOTVICT );
    }

    else if ( !str_cmp( arg2, "demon" ) )
    {
      act( AT_IMMORT, "You gesture, and a slavering demon appears.  With a horrible grin, the",  ch, NULL, victim, TO_CHAR );
      act( AT_IMMORT, "foul creature turns on $N, who screams in panic before being eaten alive.",  ch, NULL, victim, TO_CHAR );
      act( AT_IMMORT, "$n gestures, and a slavering demon appears.  The foul creature turns on",  ch, NULL, victim, TO_VICT );
      act( AT_IMMORT, "you with a horrible grin.   You scream in panic before being eaten alive.",  ch, NULL, victim, TO_VICT );
      act( AT_IMMORT, "$n gestures, and a slavering demon appears.  With a horrible grin, the",  ch, NULL, victim, TO_NOTVICT );
      act( AT_IMMORT, "foul creature turns on $N, who screams in panic before being eaten alive.",  ch, NULL, victim, TO_NOTVICT );
    }

    else if ( !str_cmp( arg2, "kombat" ) )
    {
    sprintf(buf,"THE SKIES TURN RED AS %s SCREAMS -- MORTAL KOMBAT!!!!!
In the distance you hear %s scream in pain, while being burned alive!\n\r",
		capitalize(ch->name),QUICKLINK(victim->name));
    echo_to_all(AT_CARNAGE,buf,ECHOTAR_ALL);
     }

    else if ( !str_cmp( arg2, "pinball") && get_trust(ch) >= 58)
    {
    sprintf(buf, "
\a\aThe sound of pinball machines fills the Realms! %s slowly
appears in the center of the Sky, directly above %s, holding a giant Pinball
Machine! Suddenly, %s drops the Pinball Machine, you hear a SPLAT as it
hits %s at Terminal Volocity!\n\r\n\r
You hear the sound of a Free Game in the Distance!\n\r",
QUICKLINK(ch->name),
QUICKLINK(victim->name),
QUICKLINK(ch->name),
QUICKLINK(victim->name));
echo_to_all(AT_CARNAGE,buf,ECHOTAR_ALL);
}
    
    else if ( !str_cmp( arg2, "flush") && get_trust(ch) >= LEVEL_GOD)
    {
       sprintf(buf, "
\a\aYou hear the slow sound of rushing water, and suddenly see a bolt
of entense energy slam into %s, paralyzing them.  Then
%s creates a giant toilet and drowns %s! You hear %s's
helpless gurgles for help.\n\r
You hear the faint sound of flushing in the distance...\n\r",
QUICKLINK(victim->name),
QUICKLINK(ch->name),
QUICKLINK(victim->name),
QUICKLINK(victim->name));
echo_to_all(AT_CARNAGE,buf,ECHOTAR_ALL);
}

    else if ( !str_cmp( arg2, "squish") && get_trust(ch) >= LEVEL_GOD )
    {
       sprintf(buf, "
\a\aSuddenly there is a dull rumble throughout the land. A bright beam of
intense light sent by %s encases %s. A giant hand then
appears and plummets  down to earth squashing %s with a
thunderous boom which is hear all over the land . The hills echo with 
%s's screams of pain.\n\r
The hand moves away revealing a smear of blood and flesh.\n\r",
QUICKLINK(ch->name),
QUICKLINK(victim->name),
QUICKLINK(victim->name),
QUICKLINK(victim->name));
echo_to_all(AT_CARNAGE,buf,ECHOTAR_ALL);
}
    else if ( !str_cmp( arg2, "soul" ) && get_trust(ch) >= LEVEL_GOD )
    {
       sprintf(buf,"
\a\aThe earth shakes violently! Suddenly %s raises from the ground up
to the center of the sky! In a large ball of flame demons seem to shoot
from all directions as %s points at %s and screams -- BANISH!!
%s is ripped limb from limb! then suddenly goes limp as the head
demon punches its claw through thier chest and rips out thier very SOUL!\n\r
%s's lifeless body hits the ground with a bone shattering thud....\n\r",
QUICKLINK(victim->name),
QUICKLINK(ch->name),
QUICKLINK(victim->name),
QUICKLINK(victim->name),
QUICKLINK(victim->name));

echo_to_all(AT_BLOOD,buf,ECHOTAR_ALL);
}

    else if ( !str_cmp( arg2, "pounce" ) && get_trust(ch) >= LEVEL_FATE )
    {
      act( AT_BLOOD, "Leaping upon $N with bared fangs, you tear open $S throat and toss the corpse to the ground...",  ch, NULL, victim, TO_CHAR );
      act( AT_BLOOD, "In a heartbeat, $n rips $s fangs through your throat!  Your blood sprays and pours to the ground as your life ends...", ch, NULL, victim, TO_VICT );
      act( AT_BLOOD, "Leaping suddenly, $n sinks $s fangs into $N's throat.  As blood sprays and gushes to the ground, $n tosses $N's dying body away.",  ch, NULL, victim, TO_NOTVICT );
    }
 
    else if ( !str_cmp( arg2, "slit" ) && get_trust(ch) >= LEVEL_FATE )
    {
      act( AT_BLOOD, "You calmly slit $N's throat.", ch, NULL, victim, TO_CHAR );
      act( AT_BLOOD, "$n reaches out with a clawed finger and calmly slits your throat.", ch, NULL, victim, TO_VICT );
      act( AT_BLOOD, "$n calmly slits $N's throat.", ch, NULL, victim, TO_NOTVICT );
    }

    else
    {
      act( AT_IMMORT, "You slay $N in cold blood!",  ch, NULL, victim, TO_CHAR    );
      act( AT_IMMORT, "$n slays you in cold blood!", ch, NULL, victim, TO_VICT    );
      act( AT_IMMORT, "$n slays $N in cold blood!",  ch, NULL, victim, TO_NOTVICT );
    }

    victim->died_in_room = NULL;
    victim->died_in_room = victim->in_room;
    set_cur_char(victim);
    raw_kill( ch, victim );
    return;
}

/*
 * Hit one guy with a projectile.
 * Handles use of missile weapons (wield = missile weapon)
 * or thrown items/weapons
 */
ch_ret projectile_hit( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *wield,
                       OBJ_DATA *projectile, sh_int dist )
{
    int victim_ac;
    int thac0;
    int thac0_00;
    int thac0_32;
    int plusris;
    int dam;
    int diceroll;
    int prof_bonus;
    int prof_gsn = -1;
    int proj_bonus;
    int dt;
    ch_ret retcode;

    if ( !projectile )
        return rNONE;

    if ( projectile->item_type == ITEM_PROJECTILE
    ||   projectile->item_type == ITEM_WEAPON )
    {
        dt = TYPE_HIT + projectile->value[3];
        proj_bonus = number_range(projectile->value[1], projectile->value[2]);
    }
    else
    {
        dt = TYPE_UNDEFINED;
        proj_bonus = number_range(1, URANGE(2, get_obj_weight(projectile), 100) );
    }

    /*
     * Can't beat a dead char!
     */
    if ( victim->position == POS_DEAD || char_died(victim) )
    {
        extract_obj(projectile);
        return rVICT_DIED;
    }

    if ( wield )
        prof_bonus = weapon_prof_bonus_check( ch, wield, &prof_gsn );
    else
        prof_bonus = 0;

    if ( dt == TYPE_UNDEFINED )
    {
        dt = TYPE_HIT;
        if ( wield && wield->item_type == ITEM_MISSILE_WEAPON )
            dt += wield->value[3];
    }

    /*
     * Calculate to-hit-armor-class-0 versus armor.
     */
    if ( IS_NPC(ch) )
    {
        thac0_00 = ch->mobthac0;
        thac0_32 =  0;
    }
    else
    {
        thac0_00 = class_table[ch->class]->thac0_00;
        thac0_32 = class_table[ch->class]->thac0_32;
    }
    thac0     = interpolate( ch->level, thac0_00, thac0_32 ) - GET_HITROLL(ch) + (dist*2);
    victim_ac = UMAX( -30, (int) (GET_AC(victim) / 20) );

    /* if you can't see what's coming... */
    if ( !can_see_obj( victim, projectile) )
        victim_ac += 1;
    if ( !can_see( ch, victim ) )
        victim_ac -= 4;

    /* Weapon proficiency bonus */
    victim_ac += prof_bonus;

    /*
     * The moment of excitement!
     */
    while ( ( diceroll = number_bits( 5 ) ) >= 20 )
        ;

    if ( diceroll == 0
    || ( diceroll != 19 && diceroll < thac0 - victim_ac ) )
    {
        /* Miss. */
        if ( prof_gsn != -1 )
            learn_from_failure( ch, prof_gsn );

        /* Do something with the projectile */
        if ( number_percent() < 50 )
            extract_obj(projectile);
        else
        {
            if ( projectile->in_obj )
                obj_from_obj(projectile);
            if ( projectile->carried_by )
                obj_from_char(projectile);
            obj_to_room(projectile, victim->in_room);
        }
        damage( ch, victim, 0, dt );
        tail_chain( );
        return rNONE;
    }

    /*
     * Hit.
     * Calc damage.
     */
    if ( !wield )       /* dice formula fixed by Thoric */
        dam = proj_bonus;
    else
        dam = number_range(wield->value[1], wield->value[2]) + (proj_bonus / 10);

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL(ch);

    if ( prof_bonus )
        dam += prof_bonus / 4;

    /*
     * Calculate Damage Modifiers from Victim's Fighting Style
     */
/*    if ( victim->position == POS_BERSERK )
       dam = 1.2 * dam;
    else if ( victim->position == POS_AGGRESSIVE )
       dam = 1.1 * dam;
    else if ( victim->position == POS_DEFENSIVE )
       dam = .85 * dam;
    else if ( victim->position == POS_EVASIVE )
       dam = .8 * dam;*/

    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
        dam += (int) (dam * LEARNED(ch, gsn_enhanced_damage) / 120);
        learn_from_success( ch, gsn_enhanced_damage );
    }

    if ( !IS_AWAKE(victim) )
        dam *= 2;

    if ( dam <= 0 )
        dam = 1;

    plusris = 0;

    if ( IS_OBJ_STAT(projectile, ITEM_MAGIC) )
        dam = ris_damage( victim, dam, RIS_MAGIC );
    else
        dam = ris_damage( victim, dam, RIS_NONMAGIC );

    /*
     * Handle PLUS1 - PLUS6 ris bits vs. weapon hitroll -Thoric
     */
    if ( wield )
        plusris = obj_hitroll( wield );

    /* check for RIS_PLUSx                                      -Thoric */
    if ( dam )
    {
        int x, res, imm, sus, mod;

        if ( plusris )
           plusris = RIS_PLUS1 << UMIN(plusris, 7);

        /* initialize values to handle a zero plusris */
        imm = res = -1;  sus = 1;

        /* find high ris */
        for ( x = RIS_PLUS1; x <= RIS_PLUS6; x <<= 1 )
        {
           if ( IS_SET( victim->immune, x ) )
                imm = x;
           if ( IS_SET( victim->resistant, x ) )
                res = x;
           if ( IS_SET( victim->susceptible, x ) )
                sus = x;
        }
        mod = 10;
        if ( imm >= plusris )
          mod -= 10;
        if ( res >= plusris )
          mod -= 2;
        if ( sus <= plusris )
          mod += 2;

        /* check if immune */
        if ( mod <= 0 )
          dam = -1;
        if ( mod != 10 )
          dam = (dam * mod) / 10;
    }

    if ( prof_gsn != -1 )
    {
      if ( dam > 0 )
        learn_from_success( ch, prof_gsn );
      else
        learn_from_failure( ch, prof_gsn );
    }

    /* immune to damage */
    if ( dam == -1 )
    {
        if ( dt >= 0 && dt < top_sn )
        {
            SKILLTYPE *skill = skill_table[dt];
            bool found = FALSE;

            if ( skill->imm_char && skill->imm_char[0] != '\0' )
            {
                act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
                found = TRUE;
            }
            if ( skill->imm_vict && skill->imm_vict[0] != '\0' )
            {
                act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
                found = TRUE;
            }
            if ( skill->imm_room && skill->imm_room[0] != '\0' )
            {
                act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
                found = TRUE;
            }
            if ( found )
            {
                if ( number_percent() < 50 )
                    extract_obj(projectile);
                else
                {
                    if ( projectile->in_obj )
                        obj_from_obj(projectile);
                    if ( projectile->carried_by )
                        obj_from_char(projectile);
                    obj_to_room(projectile, victim->in_room);
                }
                return rNONE;
            }
        }
        dam = 0;
    }
    if ( (retcode = damage( ch, victim, dam, dt )) != rNONE )
    {
        extract_obj(projectile);
        return retcode;
    }
    if ( char_died(ch) )
    {
        extract_obj(projectile);
        return rCHAR_DIED;
    }
    if ( char_died(victim) )
    {
        extract_obj(projectile);
        return rVICT_DIED;
    }

    retcode = rNONE;
    if ( dam == 0 )
    {
        if ( number_percent() < 50 )
            extract_obj(projectile);
        else
        {
            if ( projectile->in_obj )
                obj_from_obj(projectile);
            if ( projectile->carried_by )
                obj_from_char(projectile);
            obj_to_room(projectile, victim->in_room);
        }
        return retcode;
    }

/* weapon spells        -Thoric */
    if ( wield
    &&  !IS_SET(victim->immune, RIS_MAGIC)
    &&  !IS_SET(victim->in_room->room_flags, ROOM_NO_MAGIC) )
    {
        AFFECT_DATA *aff;

        for ( aff = wield->pIndexData->first_affect; aff; aff = aff->next )
           if ( aff->location == APPLY_WEAPONSPELL
           &&   IS_VALID_SN(aff->modifier)
           &&   skill_table[aff->modifier]->spell_fun )
                retcode = (*skill_table[aff->modifier]->spell_fun) ( aff->modifier, (wield->level+3)/3, ch, victim );
        if ( retcode != rNONE || char_died(ch) || char_died(victim) )
        {
            extract_obj(projectile);
            return retcode;
        }
        for ( aff = wield->first_affect; aff; aff = aff->next )
           if ( aff->location == APPLY_WEAPONSPELL
           &&   IS_VALID_SN(aff->modifier)
           &&   skill_table[aff->modifier]->spell_fun )
                retcode = (*skill_table[aff->modifier]->spell_fun) ( aff->modifier, (wield->level+3)/3, ch, victim );
        if ( retcode != rNONE || char_died(ch) || char_died(victim) )
        {
            extract_obj(projectile);
            return retcode;
        }
    }
    extract_obj(projectile);

    tail_chain( );
    return retcode;
}


/* Can we flee that way? --GW */
bool can_flee_dir( CHAR_DATA *ch, int door )
{
CHAR_DATA *mob, *next_mob=NULL;
bool blocked, mob_found;

blocked=FALSE;
mob_found=FALSE;

/* Find a Mob with a block flag */
for( mob = ch->in_room->first_person; mob; mob=next_mob)
{
  next_mob=mob->next_in_room;

  if ( IS_NPC(mob) &&
       (IS_SET(mob->acttwo, ACT2_BNORTH) ||
        IS_SET(mob->acttwo, ACT2_BSOUTH) ||
        IS_SET(mob->acttwo, ACT2_BEAST) ||
        IS_SET(mob->acttwo, ACT2_BWEST) ||
        IS_SET(mob->acttwo, ACT2_BUP) ||
        IS_SET(mob->acttwo, ACT2_BDOWN)))
  {
    mob_found=TRUE;
    break;
  }
}

/* No mob? Kick us.. */
if ( !mob_found )
return TRUE;

/* Does it block the Dir im trying to flee!!?! */
switch(door)
{
  case DIR_NORTH:
     if ( IS_SET(mob->acttwo, ACT2_BNORTH ) )
     {
	blocked=TRUE;
	break;
     }
     else
	break;
  case DIR_SOUTH:
     if ( IS_SET(mob->acttwo, ACT2_BSOUTH ) )
     {
	blocked=TRUE;
	break;
     }
     else
	break;
  case DIR_EAST:
     if ( IS_SET(mob->acttwo, ACT2_BEAST ) )
     {
	blocked=TRUE;
	break;
     }
     else
	break;
  case DIR_WEST:
     if ( IS_SET(mob->acttwo, ACT2_BWEST ) )
     {
	blocked=TRUE;
	break;
     }
     else
	break;
  case DIR_UP:
     if ( IS_SET(mob->acttwo, ACT2_BUP ) )
     {
	blocked=TRUE;
	break;
     }
     else
	break;
  case DIR_DOWN:
     if ( IS_SET(mob->acttwo, ACT2_BDOWN ) )
     {
	blocked=TRUE;
	break;
     }
     else
	break;
}

/* Yep - tell them to fuck off.. */
if (blocked)
{
char buf[MSL];

buf[0]='\0';

  sprintf(buf,"HAHA! You can't flee from me, %s!",capitalize(ch->name));
  do_say(mob,buf);
  return FALSE;
}

/* Guess not.. run like a child! hehe */
return TRUE;
}