eldhamud_2.2.5/clans/
eldhamud_2.2.5/classes/
eldhamud_2.2.5/councils/
eldhamud_2.2.5/deity/
eldhamud_2.2.5/doc/
eldhamud_2.2.5/doc/DIKU/
eldhamud_2.2.5/doc/DIKU/.svn/
eldhamud_2.2.5/doc/DIKU/.svn/prop-base/
eldhamud_2.2.5/doc/DIKU/.svn/text-base/
eldhamud_2.2.5/doc/MERC/
eldhamud_2.2.5/doc/MERC/.svn/
eldhamud_2.2.5/doc/SMAUG/.svn/
eldhamud_2.2.5/doc/SMAUG/mudprogs/
eldhamud_2.2.5/doc/SMAUG/mudprogs/.svn/
eldhamud_2.2.5/gods/
eldhamud_2.2.5/houses/
eldhamud_2.2.5/player/
eldhamud_2.2.5/player/a/
eldhamud_2.2.5/races/
eldhamud_2.2.5/src/Headers/.svn/
eldhamud_2.2.5/src/ObjectFiles/.svn/
/****************************************************************************
 *			Eldhamud Codebase V2.2				    *
 * ------------------------------------------------------------------------ *
 *          EldhaMUD code (C) 2003-2008 by Robert Powell (Tommi)            *
 * ------------------------------------------------------------------------ *
 * Original SMAUG 1.4a written by Thoric (Derek Snider) with Altrag,        *
 * Blodkai, Haus, Narn, Scryn, Swordbearer, Tricops, Gorog, Rennard,        *
 * Grishnakh, Fireblade, and Nivek.                                         *
 *                                                                          *
 * Original MERC 2.1 code by Hatchet, Furey, and Kahn.                      *
 *                                                                          *
 * Original DikuMUD code by: Hans Staerfeldt, Katja Nyboe, Tom Madsen,      *
 * Michael Seifert, and Sebastian Hammer.                                   *
 * ------------------------------------------------------------------------ *
 *			    Battle & death module			    *
 ****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "./Headers/mud.h"
extern char lastplayercmd[MAX_INPUT_LENGTH];
extern CHAR_DATA *gch_prev;
OBJ_DATA *used_weapon;  /* Used to figure out which weapon later */
/*
 * Local functions.
 */
void new_dam_message args( ( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt, OBJ_DATA * obj ) );
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 ) );
void show_condition args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
/*
 * Check to see if player's attacks are (still?) suppressed
 * #ifdef TRI
 */
bool is_attack_supressed( CHAR_DATA * ch )
{
   TIMER *timer;
   if( IS_NPC( ch ) )
      return FALSE;
   timer = get_timerptr( ch, TIMER_ASUPRESSED );
   if( !timer )
      return FALSE;
   /*
    * perma-supression -- bard? (can be reset at end of fight, or spell, etc)
    */
   if( timer->value == -1 )
      return TRUE;
   /*
    * this is for timed supressions
    */
   if( timer->count >= 1 )
      return TRUE;
   return FALSE;
}

/*
 * Check to see if weapon is poisoned.
 */
bool is_wielding_poisoned( CHAR_DATA * ch )
{
   OBJ_DATA *obj;
   if( !used_weapon )
      return FALSE;
   if( ( obj = get_eq_char( ch, WEAR_WIELD ) ) != NULL && used_weapon == obj && IS_OBJ_STAT( obj, ITEM_POISONED ) )
      return TRUE;
   if( ( obj = get_eq_char( ch, WEAR_DUAL_WIELD ) ) != NULL && used_weapon == obj && IS_OBJ_STAT( obj, 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;
}

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.
 *
 * Note:  This function also handles some non-violence updates.
 */
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;
   SKILLTYPE *skill;
   static int pulse = 0;
   lst_ch = NULL;
   pulse = ( pulse + 1 ) % 100;
   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;
         do_shout( ch, "Thoric says, 'Prepare for the worst!'" );
      }
      /*
       * 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;
      }
      /*
       * Experience gained during battle deceases as battle drags on
       */
      if( ch->fighting )
         if( ( ++ch->fighting->duration % 24 ) == 0 )
            ch->fighting->xp = ( ( ch->fighting->xp * 9 ) / 10 );
      for( timer = ch->first_timer; timer; timer = timer_next )
      {
         timer_next = timer->next;
         if( --timer->count <= 0 )
         {
            if( timer->type == TIMER_ASUPRESSED )
            {
               if( timer->value == -1 )
               {
                  timer->count = 1000;
                  continue;
               }
            }
            if( timer->type == TIMER_NUISANCE )
            {
               DISPOSE( ch->pcdata->nuisance );
            }
            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 );
               }
            }
            affect_remove( ch, paf );
         }
      }
      if( char_died( ch ) )
         continue;
      /*
       * check for exits moving players around
       */
      if( ( retcode = pullcheck( ch, pulse ) ) == rCHAR_DIED || char_died( ch ) )
         continue;
      /*
       * Let the battle begin!
       */
      if( ( victim = who_fighting( ch ) ) == NULL || IS_AFFECTED( ch, AFF_PARALYSIS ) )
         continue;
      retcode = rNONE;
      if( xIS_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
       *  -- Added some victim death checks, because it IS possible.. -- Alty
       */
      rprog_rfight_trigger( ch );
      if( char_died( ch ) || char_died( victim ) )
         continue;
      mprog_hitprcnt_trigger( ch, victim );
      if( char_died( ch ) || char_died( victim ) )
         continue;
      mprog_fight_trigger( ch, victim );
      if( char_died( ch ) || char_died( victim ) )
         continue;
      /*
       * Fun for the whole family!
       */
      for( rch = ch->in_room->first_person; rch; rch = rch_next )
      {
         rch_next = rch->next_in_room;
         /*
          *   Group Fighting Styles Support:
          *   If ch is tanking
          *   If rch is using a more aggressive style than ch
          *   Then rch is the new tank   -h
          */
         /*
          * &&( is_same_group(ch, rch)      )
          */
         if( ( !IS_NPC( ch ) && !IS_NPC( rch ) )
             && ( rch != ch )
             && ( rch->fighting ) && ( who_fighting( rch->fighting->who ) == ch ) && ( !xIS_SET( rch->fighting->who->act, ACT_AUTONOMOUS ) ) && ( rch->style < ch->style ) )
         {
            rch->fighting->who->fighting->who = rch;
         }
         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 ) && rch->desc ) || IS_AFFECTED( rch, AFF_CHARM ) ) && is_same_group( ch, rch ) && !is_safe( rch, victim, TRUE ) )
                  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 ) && !xIS_SET( rch->act, ACT_NOASSIST ) && !xIS_SET( rch->act, ACT_PET ) )
            {
               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_in_room )
                  {
                     if( can_see( rch, vch, FALSE ) && is_same_group( vch, victim ) && number_range( 0, number ) == 0 )
                     {
                        if( vch->mount && vch->mount == rch )
                           target = NULL;
                        else
                        {
                           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 )
{
   ch_ret retcode;
   /*
    * add timer to pkillers
    */
   if( !IS_NPC( ch ) && !IS_NPC( victim ) )
   {
      if( xIS_SET( ch->act, PLR_NICE ) )
         return rNONE;
      add_timer( ch, TIMER_RECENTFIGHT, 11, NULL, 0 );
      add_timer( victim, TIMER_RECENTFIGHT, 11, NULL, 0 );
   }
   if( is_attack_supressed( ch ) )
      return rNONE;
   if( IS_NPC( ch ) && xIS_SET( ch->act, ACT_NOATTACK ) )
      return rNONE;
   if( ( retcode = one_hit( ch, victim, dt ) ) != rNONE )
      return retcode;
   if( who_fighting( ch ) != victim || dt == gsn_backstab || dt == gsn_circle )
      return rNONE;
   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 = gsn_pugilism;   /* Change back to -1 if this fails horribly */
   if( !IS_NPC( ch ) && wield )
   {
      switch ( wield->value[4] )
      {
            /*
             * Restructured weapon system - Samson 11-20-99
             */
         default:
            *gsn_ptr = -1;
            break;
         case WEP_BAREHAND:
            *gsn_ptr = gsn_pugilism;
            break;
         case WEP_SWORD:
            *gsn_ptr = gsn_swords;
            break;
         case WEP_DAGGER:
            *gsn_ptr = gsn_daggers;
            break;
         case WEP_WHIP:
            *gsn_ptr = gsn_whips;
            break;
         case WEP_TALON:
            *gsn_ptr = gsn_talonous_arms;
            break;
         case WEP_HAMMER:
            *gsn_ptr = gsn_maces_hammers;
            break;
         case WEP_ARCHERY:
            *gsn_ptr = gsn_archery;
            break;
         case WEP_BLOWGUN:
            *gsn_ptr = gsn_blowguns;
            break;
         case WEP_SLING:
            *gsn_ptr = gsn_slings;
            break;
         case WEP_AXE:
            *gsn_ptr = gsn_axes;
            break;
         case WEP_SPEAR:
            *gsn_ptr = gsn_spears;
            break;
         case WEP_STAFF:
            *gsn_ptr = gsn_staves;
            break;
         case WEP_POLEARM:
            *gsn_ptr = gsn_polearm;
            break;
      }
      if( *gsn_ptr != -1 )
         bonus = ( int )( ( LEARNED( ch, *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 -= ch->pcdata->favor / -400;
   }
   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
 */
short off_shld_lvl( CHAR_DATA * ch, CHAR_DATA * victim )
{
   short lvl;
   if( !IS_NPC( ch ) )  /* players get much less effect */
   {
      lvl = UMAX( 1, ( ch->level - 10 ) / 2 );
      if( number_percent(  ) + ( victim->level - lvl ) < 40 )
      {
         if( CAN_PKILL( ch ) && CAN_PKILL( victim ) )
            return ch->level;
         else
            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;
   int dam;
   int diceroll;
   int prof_bonus;
   int prof_gsn = -1;
   ch_ret retcode = rNONE;
   static bool dual_flip = FALSE;
   short random_number;
   /*
    * 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;
   used_weapon = NULL;
   /*
    * Figure out the weapon doing the damage        -Thoric
    * Dual wield support -- switch weapons each attack
    */
   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 );
   used_weapon = wield;
   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_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 );
   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, FALSE ) )
      victim_ac -= 4;
   /*
    * "learning" between combatants.  Takes the intelligence difference,
    * and multiplies by the times killed to make up a learning bonus
    * given to whoever is more intelligent    -Thoric
    * (basically the more intelligent one "learns" the other's fighting style)
    */
   if( ch->fighting && ch->fighting->who == victim )
   {
      short times = ch->fighting->timeskilled;
      if( times )
      {
         short 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 )
   {
      /*
       * Miss.
       */
      if( prof_gsn != -1 )
         learn_from_failure( ch, prof_gsn );
      damage( ch, victim, 0, dt );
      tail_chain(  );
      return rNONE;
   }
   /*
    * Hit.
    * Calc damage.
    */
   if( !wield )   /* bare hand dice formula fixed by Thoric */
      /*
       * Fixed again by korbillian@mud.tka.com 4000 (Cold Fusion Mud)
       */
      dam = number_range( ch->barenumdie, ch->baresizedie * ch->barenumdie ) + ch->damplus;
   else
      dam = number_range( wield->value[1], wield->value[2] );
   /*
    * Critical Hit -- Add onto by randomizing the critical hit and damage...
    *  By: Josh Jenks [Haelyn]...snippet for SMAUG 1.4a
    *  Added in and changed by Odis
    */
   if( diceroll >= 19 )
   {
      int place;
      place = number_range( 1, 4 );
      if( place == 1 )
      {
         act( AT_FIRE, "You hit $N's hand!", ch, NULL, victim, TO_CHAR );
         act( AT_FIRE, "$n hits your hand!", ch, NULL, victim, TO_VICT );
         act( AT_FIRE, "$n hits $N's!", ch, NULL, victim, TO_NOTVICT );
         dam *= 1.5;
      }
      else if( place == 2 )
      {
         act( AT_FIRE, "You critically hit $N in the chest!", ch, NULL, victim, TO_CHAR );
         act( AT_FIRE, "$n critically hits you in the chest!", ch, NULL, victim, TO_VICT );
         act( AT_FIRE, "$n critically hits $N in the chest!", ch, NULL, victim, TO_NOTVICT );
         dam *= 2;
      }
      else if( place == 3 )
      {
         act( AT_FIRE, "You bash $N's head!", ch, NULL, victim, TO_CHAR );
         act( AT_FIRE, "$n bashes your head!", ch, NULL, victim, TO_VICT );
         act( AT_FIRE, "$n bashes $N's head!", ch, NULL, victim, TO_NOTVICT );
         dam *= 3;
      }
      else if( place == 4 )
      {
         act( AT_FIRE, "You mutilate $N's groin!", ch, NULL, victim, TO_CHAR );
         act( AT_FIRE, "$n mutilates you in the groin!", ch, NULL, victim, TO_VICT );
         act( AT_FIRE, "$n mutilates $N's groin!", ch, NULL, victim, TO_NOTVICT );
         dam *= 2;
      }
   }
   /*
    * 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;
   /*
    * Auto increase styles and modify damage based on character's fighting style
    * code cut from smaugfuss boards, by Remcon
    */
   switch ( ch->style )
   {
      default:
      case STYLE_FIGHTING:
         if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_style_standard] > -1 )
            learn_from_success( ch, gsn_style_standard );
         break;
      case STYLE_DEFENSIVE:
         if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_style_defensive] > -1 )
            learn_from_success( ch, gsn_style_defensive );
         dam = ( int )( .85 * dam );
         break;
      case STYLE_EVASIVE:
         if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_style_evasive] > -1 )
            learn_from_success( ch, gsn_style_evasive );
         dam = ( int )( .8 * dam );
         break;
      case STYLE_AGGRESSIVE:
         if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_style_aggressive] > -1 )
            learn_from_success( ch, gsn_style_aggressive );
         dam = ( int )( 1.1 * dam );
         break;
      case STYLE_BERSERK:
         if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_style_berserk] > -1 )
            learn_from_success( ch, gsn_style_berserk );
         dam = ( int )( 1.2 * dam );
         break;
   }
   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( dt == gsn_backstab )
   {
      if( !IS_NPC( victim ) )
      {
         dam *= ( 2 + URANGE( 2, ch->level - ( victim->level / 8 ), 30 ) / 16 );
      }
      else
      {
         dam *= ( 2 + URANGE( 2, ch->level - ( victim->level / 4 ), 30 ) / 8 );
      }
   }
   if( dt == gsn_circle )
   {
      if( !IS_NPC( victim ) )
      {
         dam *= ( 2 + URANGE( 2, ch->level - ( victim->level / 8 ), 30 ) / 20 );
      }
      else
         dam *= ( 2 + URANGE( 2, ch->level - ( victim->level / 4 ), 30 ) / 16 );
   }
   if( dam <= 0 )
      dam = 1;
   plusris = 0;
   if( wield )
   {
      if( IS_OBJ_STAT( wield, 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( 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] != STRING_NULL )
         {
            act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
            found = TRUE;
         }
         if( skill->imm_vict && skill->imm_vict[0] != STRING_NULL )
         {
            act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
            found = TRUE;
         }
         if( skill->imm_room && skill->imm_room[0] != STRING_NULL )
         {
            act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
            found = TRUE;
         }
         if( found )
            return rNONE;
      }
      dam = 0;
   }
   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 spell support  -Thoric
    Modified by Tommi, to hit only 1 in 6 Sept 2005
    */
   random_number = number_range( 0, 5 );
   if( random_number == 1 )
   {
      if( wield && !IS_SET( victim->immune, RIS_MAGIC ) && !xIS_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 ) / 2, 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 ) && skill_table[aff->modifier]->spell_fun )
               retcode = ( *skill_table[aff->modifier]->spell_fun ) ( aff->modifier, ( wield->level + 3 ) / 2, ch, victim );
         if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
            return retcode;
      }
   }
   /*
    * magic shields that retaliate -Thoric
    * Modified by tommi, to not use spells, and to roll for success Aug 2005
    */
   random_number = number_range( 0, 12 );
   if( random_number == 5 )
   {
      if( IS_AFFECTED( victim, AFF_FIRESHIELD ) && !IS_AFFECTED( ch, AFF_FIRESHIELD ) )
      {
         act( AT_MAGIC, "Flames leap off of $N shield of flames and hit you.", ch, NULL, victim, TO_CHAR );
         act( AT_MAGIC, "Flames leap off of $n's fireshield hitting $N.", ch, NULL, victim, TO_NOTVICT );
      }
      else if( IS_AFFECTED( victim, AFF_ICESHIELD ) && !IS_AFFECTED( ch, AFF_ICESHIELD ) )
      {
         act( AT_MAGIC, "Shards of ice leap off of $N iceshield and hit you.", ch, NULL, victim, TO_CHAR );
         act( AT_MAGIC, "Ice shards leap off of $n's iceshield hitting $N.", ch, NULL, victim, TO_NOTVICT );
      }
      else if( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) && !IS_AFFECTED( ch, AFF_SHOCKSHIELD ) )
      {
         act( AT_MAGIC, "Shockwaves leap off of $N shockshield and hit you.", ch, NULL, victim, TO_CHAR );
         act( AT_MAGIC, "Shockwaves leap off of $n's fireshield hitting $N.", ch, NULL, victim, TO_NOTVICT );
      }
      else if( IS_AFFECTED( victim, AFF_ACIDMIST ) && !IS_AFFECTED( ch, AFF_ACIDMIST ) )
      {
         act( AT_MAGIC, "Drops of acid leap off of $N shield of acid and hit you.", ch, NULL, victim, TO_CHAR );
         act( AT_MAGIC, "Drops of acid leap  off of $n's fireshield hitting $N.", ch, NULL, victim, TO_NOTVICT );
      }
      else if( IS_AFFECTED( victim, AFF_VENOMSHIELD ) && !IS_AFFECTED( ch, AFF_VENOMSHIELD ) )
      {
         act( AT_MAGIC, "Flames leap off of $N shield of flames and hit you.", ch, NULL, victim, TO_CHAR );
         act( AT_MAGIC, "Flames off of $n's fireshield hitting $N.", ch, NULL, victim, TO_NOTVICT );
      }
      dam = dice( 4, ( ch->level / 3 ) );
      retcode = damage( ch, victim, dam, DAM_MAGIC );
      if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
         return retcode;
   }
   tail_chain(  );
   return retcode;
}

/*
 * Calculate damage based on resistances, immunities and suceptibilities
 *					-Thoric
 */
short ris_damage( CHAR_DATA * ch, short dam, int ris )
{
   short modifier;
   modifier = 10;
   if( IS_SET( ch->immune, ris ) && !IS_SET( ch->no_immune, ris ) )
      modifier -= 10;
   if( IS_SET( ch->resistant, ris ) && !IS_SET( ch->no_resistant, ris ) )
      modifier -= 2;
   if( IS_SET( ch->susceptible, ris ) && !IS_SET( ch->no_susceptible, ris ) )
   {
      if( IS_NPC( ch ) && IS_SET( ch->immune, ris ) )
         modifier += 0;
      else
         modifier += 2;
   }
   if( modifier <= 0 )
      return -1;
   if( modifier == 10 )
      return dam;
   return ( dam * modifier ) / 10;
}

/*
 * Inflict damage from a hit.   This is one damn big function.
 */
ch_ret damage( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt )
{
   char buf[MAX_STRING_LENGTH];
   char buf1[MAX_STRING_LENGTH];
   char filename[256];
   short dameq;
   short maxdam;
   bool npcvict;
   bool loot;
   OBJ_DATA *damobj;
   ch_ret retcode;
   short dampmod;
   CHAR_DATA *gch /*, *lch */ ;
   int init_gold, new_gold, gold_diff;
   short anopc = 0;  /* # of (non-pkill) pc in a (ch) */
   short bnopc = 0;  /* # of (non-pkill) pc in b (victim) */
   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 );
   /*
    * 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
         /*
          * Added checks for the 3 new dam types, and removed DAM_PEA - Grimm
          * Removed excess duplication, added hack and lash RIS types - Samson 1-9-00
          */
      if( dt == ( TYPE_HIT + DAM_CRUSH ) )
         dam = ris_damage( victim, dam, RIS_BLUNT );
      else if( dt == ( TYPE_HIT + DAM_STAB ) || dt == ( TYPE_HIT + DAM_PIERCE ) || dt == ( TYPE_HIT + DAM_THRUST ) )
         dam = ris_damage( victim, dam, RIS_PIERCE );
      else if( dt == ( TYPE_HIT + DAM_SLASH ) )
         dam = ris_damage( victim, dam, RIS_SLASH );
      else if( dt == ( TYPE_HIT + DAM_HACK ) )
         dam = ris_damage( victim, dam, RIS_HACK );
      else if( dt == ( TYPE_HIT + DAM_LASH ) )
         dam = ris_damage( victim, dam, RIS_LASH );
      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] != STRING_NULL )
            {
               act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
               found = TRUE;
            }
            if( skill->imm_vict && skill->imm_vict[0] != STRING_NULL )
            {
               act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
               found = TRUE;
            }
            if( skill->imm_room && skill->imm_room[0] != STRING_NULL )
            {
               act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
               found = TRUE;
            }
            if( found )
               return rNONE;
         }
         dam = 0;
      }
   }
   /*
    * Precautionary step mainly to prevent people in Hell from finding
    * a way out. --Shaddai
    */
   if( xIS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
      dam = 0;
   if( dam && npcvict && ch != victim )
   {
      if( !xIS_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 if( !xIS_SET( victim->act, ACT_PACIFIST ) )   /* Gorog */
            start_hunting( victim, ch );
      }
      if( victim->hating )
      {
         if( victim->hating->who != ch )
         {
            STRFREE( victim->hating->name );
            victim->hating->name = QUICKLINK( ch->name );
            victim->hating->who = ch;
         }
      }
      else if( !xIS_SET( victim->act, ACT_PACIFIST ) )   /* Gorog */
         start_hating( victim, ch );
   }
   /*
    * Stop up any residual loopholes.
    */
   if( dt == gsn_backstab )
      maxdam = ch->level * 80;
   else
      maxdam = ch->level * 40;
   if( dam > maxdam )
   {
      sprintf( buf, "Damage: %d more than %d points!", dam, maxdam );
      bug( buf, dam );
      sprintf( buf, "** %s (lvl %d) -> %s **", ch->name, ch->level, victim->name );
      bug( buf, 0 );
      dam = maxdam;
   }
   if( victim != ch )
   {
      /*
       * Certain attacks are forbidden.
       * Most other attacks are returned.
       */
      if( is_safe( ch, victim, TRUE ) )
         return rNONE;
      check_attacker( ch, victim );
      if( victim->position > POS_STUNNED )
      {
         if( !victim->fighting && victim->in_room == ch->in_room )
            set_fighting( victim, ch );
         /*
          * vwas: victim->position = POS_FIGHTING;
          */
         if( IS_NPC( victim ) && victim->fighting )
            victim->position = POS_FIGHTING;
         else if( victim->fighting )
         {
            switch ( victim->style )
            {
               case ( STYLE_EVASIVE ):
                  victim->position = POS_EVASIVE;
                  break;
               case ( STYLE_DEFENSIVE ):
                  victim->position = POS_DEFENSIVE;
                  break;
               case ( STYLE_AGGRESSIVE ):
                  victim->position = POS_AGGRESSIVE;
                  break;
               case ( STYLE_BERSERK ):
                  victim->position = POS_BERSERK;
                  break;
               default:
                  victim->position = POS_FIGHTING;
            }
         }
      }
      if( victim->position > POS_STUNNED )
      {
         if( !ch->fighting && victim->in_room == ch->in_room )
            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 == 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.
       */
      /*
       * 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 );
               }
         }
      }

      /*
       * 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 );
      if( dam < 0 )
         dam = 0;
      if( quad_damage == TRUE && !IS_NPC( ch ) )
      {
         dam = dam * 4;
      }
      /*
       * Check for disarm, trip, parry, dodge and tumble.
       */
      if( dt >= TYPE_HIT && ch->in_room == victim->in_room )
      {
         if( check_parry( ch, victim ) )
            return rNONE;
         if( check_dodge( ch, victim ) )
            return rNONE;
         if( check_tumble( 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;
      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 > 50 && dt != TYPE_UNDEFINED )
   {
      /*
       * get a random body eq part
       */
      dameq = number_range( WEAR_LIGHT, WEAR_FEET );
      damobj = get_eq_char( victim, dameq );
      if( damobj )
      {
         if( dam > get_obj_resistance( damobj ) && number_bits( 1 ) == 0 )
         {
            set_cur_obj( damobj );
            damage_obj( damobj );
         }
         dam -= 10;  /* add a bonus for having something to block the blow */
      }
      else
         dam += 10;  /* add penalty for bare skin! */
   }
   /*
    * Hurt the victim.
    * Inform the victim of his new state.
    */
   victim->hit -= dam;
   /*
    * 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 );
   }
   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] != STRING_NULL )
               act( AT_DEAD, skill->die_char, ch, NULL, victim, TO_CHAR );
            if( skill->die_vict && skill->die_vict[0] != STRING_NULL )
               act( AT_DEAD, skill->die_vict, ch, NULL, victim, TO_VICT );
            if( skill->die_room && skill->die_room[0] != STRING_NULL )
               act( AT_DEAD, skill->die_room, ch, NULL, victim, TO_NOTVICT );
         }
         act( AT_DEAD, "$n is DEAD!!", victim, 0, 0, TO_ROOM );
         act( AT_DEAD, "You have been KILLED!!\n\r", victim, 0, 0, TO_CHAR );
         break;
      default:
         /*
          * Victim mentalstate affected, not attacker -- oops ;)
          * Thanks to gfinello@mail.karmanet.it for finding this bug
          */
         if( dam > victim->max_hit / 4 )
         {
            act( AT_HURT, "That really did HURT!", victim, 0, 0, TO_CHAR );
         }
         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 );
         }
         break;
   }
   /*
    * Sleep spells and extremely wounded folks.
    */
   if( !IS_AWAKE( victim ) /* lets make 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 );
   }
   /*
    * Payoff for killing things.
    */
   if( victim->position == POS_DEAD )
   {
      group_gain( ch, victim );
      if( !npcvict )
      {
         sprintf( log_buf, "%s (%d) killed by %s at %d", victim->name, victim->level, ( IS_NPC( ch ) ? ch->short_descr : ch->name ), victim->in_room->vnum );
         log_string( log_buf );
         to_channel( log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL );
         if( !IS_NPC( ch ) && !IS_IMMORTAL( ch ) && ch->pcdata->clan
             && ch->pcdata->clan->clan_type != CLAN_ORDER && ch->pcdata->clan->clan_type != CLAN_GUILD && victim != ch )
         {
            sprintf( filename, "%s%s.record", CLAN_DIR, ch->pcdata->clan->name );
            sprintf( log_buf, "&P(%2d) %-12s &wvs &P(%2d) %s &P%s ... &w%s",
                     ch->level,
                     ch->name,
                     victim->level,
                     !CAN_PKILL( victim ) ? "&W<Peaceful>" : victim->pcdata->clan ? victim->pcdata->clan->badge : "&P(&WUnclanned&P)", victim->name, ch->in_room->area->name );
            if( victim->pcdata->clan && victim->pcdata->clan->name == ch->pcdata->clan->name )
               ;
            else
               append_to_file( filename, log_buf );
         }
         /*
          * Dying penalty:
          * Loss of quater your exp! :)
          */
         if( victim->exp > 0 )
            gain_exp( victim, 0 - ( victim->exp / 4 ) );
         /*
          * New penalty... go back to the beginning of current level.
          victim->exp = 0;
          */
      }
      else if( !IS_NPC( ch ) )   /* keep track of mob vnum killed */
         add_kill( ch, victim );
      check_killer( ch, victim );
      if( ch->in_room == victim->in_room )
         loot = legal_loot( ch, victim );
      else
         loot = FALSE;
      set_cur_char( victim );
      raw_kill( ch, victim );
      victim = NULL;
      if( !IS_NPC( ch ) && loot )
      {
         /*
          * Autogold by Scryn 8/12
          */
         if( xIS_SET( ch->act, PLR_AUTOGOLD ) )
         {
            init_gold = ch->gold;
            do_get( ch, "coins 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( xIS_SET( ch->act, PLR_AUTOLOOT ) && victim != ch )   /* prevent nasty obj problems -- Blodkai */
            do_get( ch, "all corpse" );
         else
            do_look( ch, "in corpse" );
         if( xIS_SET( ch->act, PLR_AUTOSAC ) )
            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( ( xIS_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 && xIS_SET( victim->act, PLR_FLEE ) )
      do_flee( victim, "" );
   tail_chain(  );
   return rNONE;
}

/*
 * Changed is_safe to have the show_messg boolian.  This is so if you don't
 * want to show why you can't kill someone you can't turn it off.  This is
 * useful for things like area attacks.  --Shaddai
 */
bool is_safe( CHAR_DATA * ch, CHAR_DATA * victim, bool show_messg )
{
   if( char_died( victim ) || char_died( ch ) )
      return TRUE;
   /*
    * Thx Josh!
    */
   if( who_fighting( ch ) == ch )
      return FALSE;
   if( !victim )  /*Gonna find this is_safe crash bug -Blod */
   {
      bug( "Is_safe: %s opponent does not exist!", ch->name );
      return TRUE;
   }
   if( !victim->in_room )
   {
      bug( "Is_safe: %s has no physical location!", victim->name );
      return TRUE;
   }
   if( xIS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
   {
      if( show_messg )
      {
         set_char_color( AT_MAGIC, ch );
         send_to_char( "A magical force prevents you from attacking.\n\r", ch );
      }
      return TRUE;
   }
   if( ( IS_PACIFIST( ch ) ) && !IN_ARENA( ch ) )  /* Fireblade */
   {
      if( show_messg )
      {
         set_char_color( AT_MAGIC, ch );
         ch_printf( ch, "You are a pacifist and will not fight.\n\r" );
      }
      return TRUE;
   }
   if( ( IS_PACIFIST( ch ) ) && !IN_ARENA( ch ) )  /* Gorog */
   {
      char buf[MAX_STRING_LENGTH];
      if( show_messg )
      {
         sprintf( buf, "%s is a pacifist and will not fight.\n\r", capitalize( victim->short_descr ) );
         set_char_color( AT_MAGIC, ch );
         send_to_char( buf, ch );
      }
      return TRUE;
   }
   if( !IS_NPC( ch ) && ch->level >= LEVEL_IMMORTAL )
      return FALSE;
   if( !IS_NPC( ch ) && !IS_NPC( victim ) && ch != victim && IS_SET( victim->in_room->area->flags, AFLAG_NOPKILL ) )
   {
      if( show_messg )
      {
         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( ( get_age( ch ) < 17 || ch->level < 5 ) && !IN_ARENA( ch ) )
   {
      if( show_messg )
      {
         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( ( get_age( victim ) < 17 || victim->level < 5 ) && !IN_ARENA( victim ) )
   {
      if( show_messg )
      {
         set_char_color( AT_WHITE, ch );
         send_to_char( "They are yet too young to die.\n\r", ch );
      }
      return TRUE;
   }
   if( ( ch->level - victim->level > 15 || victim->level - ch->level > 15 ) && !IN_ARENA( ch ) )
   {
      if( show_messg )
      {
         set_char_color( AT_IMMORT, ch );
         send_to_char( "The gods do not allow murder when there is such a difference in level.\n\r", ch );
      }
      return TRUE;
   }
   if( ( get_timer( victim, TIMER_PKILLED ) > 0 ) && !IN_ARENA( ch ) )
   {
      if( show_messg )
      {
         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 ) && !IN_ARENA( ch ) )
   {
      if( show_messg )
      {
         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;
         /*
          * Fix for crashes when killing mobs of level 0
          * * by Joe Fabiano -rinthos@yahoo.com
          * * on 03-16-03.
          */
         if( victim->level < 1 )
            level_ratio = URANGE( 1, ch->level, MAX_LEVEL );
         else
            level_ratio = URANGE( 1, ch->level / victim->level, MAX_LEVEL );
         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;
   }
   /*
    * If you kill yourself nothing happens.
    */
   if( ch == victim || ch->level >= LEVEL_IMMORTAL )
      return;
   /*
    * Any character in the arena is ok to kill.
    * Added pdeath and pkills here
    */
   if( in_arena( ch ) )
   {
      if( !IS_NPC( ch ) && !IS_NPC( victim ) )
      {
         ch->pcdata->pkills++;
         victim->pcdata->pdeaths++;
      }
      return;
   }
   /*
    * So are killers and thieves.
    */
   if( xIS_SET( victim->act, PLR_KILLER ) || xIS_SET( victim->act, PLR_THIEF ) )
   {
      if( !IS_NPC( ch ) )
      {
         if( ch->pcdata->clan )
         {
            if( victim->level < 10 )
               ch->pcdata->clan->pkills[0]++;
            else if( victim->level < 15 )
               ch->pcdata->clan->pkills[1]++;
            else if( victim->level < 20 )
               ch->pcdata->clan->pkills[2]++;
            else if( victim->level < 30 )
               ch->pcdata->clan->pkills[3]++;
            else if( victim->level < 40 )
               ch->pcdata->clan->pkills[4]++;
            else if( victim->level < 50 )
               ch->pcdata->clan->pkills[5]++;
            else
               ch->pcdata->clan->pkills[6]++;
         }
         ch->pcdata->pkills++;
         ch->in_room->area->pkills++;
      }
      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 ) )
   {
      /*
       * not of same clan? Go ahead and kill!!!
       */
      if( !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 )
         {
            if( victim->level < 10 )
               ch->pcdata->clan->pkills[0]++;
            else if( victim->level < 15 )
               ch->pcdata->clan->pkills[1]++;
            else if( victim->level < 20 )
               ch->pcdata->clan->pkills[2]++;
            else if( victim->level < 30 )
               ch->pcdata->clan->pkills[3]++;
            else if( victim->level < 40 )
               ch->pcdata->clan->pkills[4]++;
            else if( victim->level < 50 )
               ch->pcdata->clan->pkills[5]++;
            else
               ch->pcdata->clan->pkills[6]++;
         }
         ch->pcdata->pkills++;
         ch->hit = ch->max_hit;
         ch->mana = ch->max_mana;
         ch->move = ch->max_move;
         if( ch->pcdata )
            ch->pcdata->condition[COND_BLOODTHIRST] = ( 10 + ch->level );
         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 )
         {
            if( ch->level < 10 )
               victim->pcdata->clan->pdeaths[0]++;
            else if( ch->level < 15 )
               victim->pcdata->clan->pdeaths[1]++;
            else if( ch->level < 20 )
               victim->pcdata->clan->pdeaths[2]++;
            else if( ch->level < 30 )
               victim->pcdata->clan->pdeaths[3]++;
            else if( ch->level < 40 )
               victim->pcdata->clan->pdeaths[4]++;
            else if( ch->level < 50 )
               victim->pcdata->clan->pdeaths[5]++;
            else
               victim->pcdata->clan->pdeaths[6]++;
         }
         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 );
         /*
          * xSET_BIT(victim->act, PLR_PK);
          */
         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, LEVEL_AVATAR );
         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( !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 )
      {
         if( ch->level < 10 )
            victim->pcdata->clan->pdeaths[0]++;
         else if( ch->level < 15 )
            victim->pcdata->clan->pdeaths[1]++;
         else if( ch->level < 20 )
            victim->pcdata->clan->pdeaths[2]++;
         else if( ch->level < 30 )
            victim->pcdata->clan->pdeaths[3]++;
         else if( ch->level < 40 )
            victim->pcdata->clan->pdeaths[4]++;
         else if( ch->level < 50 )
            victim->pcdata->clan->pdeaths[5]++;
         else
            victim->pcdata->clan->pdeaths[6]++;
      }
      victim->pcdata->pdeaths++;
      victim->in_room->area->pdeaths++;
   }
   if( xIS_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 );
   xSET_BIT( ch->act, PLR_KILLER );
   if( xIS_SET( ch->act, PLR_ATTACKER ) )
      xREMOVE_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 ) || xIS_SET( victim->act, PLR_KILLER ) || xIS_SET( victim->act, PLR_THIEF ) )
      return;
   /*
    * deadly char check
    */
   if( !IS_NPC( ch ) && !IS_NPC( victim ) && CAN_PKILL( ch ) && CAN_PKILL( 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 ) || ch == victim || ch->level >= LEVEL_IMMORTAL || xIS_SET( ch->act, PLR_ATTACKER ) || xIS_SET( ch->act, PLR_KILLER ) || IN_ARENA( ch ) )
      return;
   xSET_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 );
         xREMOVE_BIT( victim->mount->act, ACT_MOUNTED );
         victim->mount = NULL;
      }
      victim->position = POS_DEAD;
      return;
   }
   if( victim->hit <= 0 )
      victim->position = POS_DEAD;
   if( victim->mount )
   {
      act( AT_ACTION, "$n falls unconscious from $N.", victim, NULL, victim->mount, TO_ROOM );
      xREMOVE_BIT( victim->mount->act, ACT_MOUNTED );
      victim->mount = NULL;
   }
   return;
}

/*
 * Start fights.
 */
void set_fighting( CHAR_DATA * ch, CHAR_DATA * victim )
{
   FIGHT_DATA *fight;
   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;
   }
   /*
    * 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;
    */
   if( IS_NPC( ch ) )
      ch->position = POS_FIGHTING;
   else
      switch ( ch->style )
      {
         case ( STYLE_EVASIVE ):
            ch->position = POS_EVASIVE;
            break;
         case ( STYLE_DEFENSIVE ):
            ch->position = POS_DEFENSIVE;
            break;
         case ( STYLE_AGGRESSIVE ):
            ch->position = POS_AGGRESSIVE;
            break;
         case ( STYLE_BERSERK ):
            ch->position = POS_BERSERK;
            break;
         default:
            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 )
{
   if( !ch )
   {
      bug( "who_fighting: null ch", 0 );
      return NULL;
   }
   if( !ch->fighting )
      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;
   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 );
      }
   }
   return;
}

/* Vnums for the various bodyparts */
int part_vnums[] = { 12,   /* Head */
   14,   /* arms */
   15,   /* legs */
   13,   /* heart */
   44,   /* brains */
   16,   /* guts */
   45,   /* hands */
   46,   /* feet */
   47,   /* fingers */
   48,   /* ear */
   49,   /* eye */
   50,   /* long_tongue */
   51,   /* eyestalks */
   52,   /* tentacles */
   53,   /* fins */
   54,   /* wings */
   55,   /* tail */
   56,   /* scales */
   59,   /* claws */
   87,   /* fangs */
   58,   /* horns */
   57,   /* tusks */
   55,   /* tailattack */
   85,   /* sharpscales */
   84,   /* beak */
   86,   /* haunches */
   83,   /* hooves */
   82,   /* paws */
   81,   /* forelegs */
   80,   /* feathers */
   0, /* r1 */
   0  /* r2 */
};

/* Messages for flinging off the various bodyparts */
char *part_messages[] = {
   "$n's severed head plops from its neck.",
   "$n's arm is sliced from $s dead body.",
   "$n's leg is sliced from $s dead body.",
   "$n's heart is torn from $s chest.",
   "$n's brains spill grotesquely from $s head.",
   "$n's guts spill grotesquely from $s torso.",
   "$n's hand is sliced from $s dead body.",
   "$n's foot is sliced from $s dead body.",
   "A finger is sliced from $n's dead body.",
   "$n's ear is sliced from $s dead body.",
   "$n's eye is gouged from its socket.",
   "$n's tongue is torn from $s mouth.",
   "An eyestalk is sliced from $n's dead body.",
   "A tentacle is severed from $n's dead body.",
   "A fin is sliced from $n's dead body.",
   "A wing is severed from $n's dead body.",
   "$n's tail is sliced from $s dead body.",
   "A scale falls from the body of $n.",
   "A claw is torn from $n's dead body.",
   "$n's fangs are torn from $s mouth.",
   "A horn is wrenched from the body of $n.",
   "$n's tusk is torn from $s dead body.",
   "$n's tail is sliced from $s dead body.",
   "A ridged scale falls from the body of $n.",
   "$n's beak is sliced from $s dead body.",
   "$n's haunches are sliced from $s dead body.",
   "A hoof is sliced from $n's dead body.",
   "A paw is sliced from $n's dead body.",
   "$n's foreleg is sliced from $s dead body.",
   "Some feathers fall from $n's dead body.",
   "r1 message.",
   "r2 message."
};

/*
 * Improved Death_cry contributed by Diavolo.
 * Additional improvement by Thoric (and removal of turds... sheesh!)
 * Support for additional bodyparts by Fireblade
 */
void death_cry( CHAR_DATA * ch )
{
   ROOM_INDEX_DATA *was_in_room;
   char *msg;
   EXIT_DATA *pexit;
   int vnum, shift, cindex, i;
   if( !ch )
   {
      bug( "DEATH_CRY: null ch!", 0 );
      return;
   }
   vnum = 0;
   msg = NULL;
   switch ( number_range( 0, 5 ) )
   {
      default:
         msg = "You hear $n's death cry.";
         break;
      case 0:
         msg = "$n screams furiously as $e falls to the ground in a heap!";
         break;
      case 1:
         msg = "$n hits the ground ... DEAD.";
         break;
      case 2:
         msg = "$n catches $s guts in $s hands as they pour through $s fatal" " wound!";
         break;
      case 3:
         msg = "$n splatters blood on your armor.";
         break;
      case 4:
         msg = "$n gasps $s last breath and blood spurts out of $s " "mouth and ears.";
         break;
      case 5:
         shift = number_range( 0, 31 );
         cindex = 1 << shift;
         for( i = 0; i < 32 && ch->xflags; i++ )
         {
            if( HAS_BODYPART( ch, cindex ) )
            {
               msg = part_messages[shift];
               vnum = part_vnums[shift];
               break;
            }
            else
            {
               shift = number_range( 0, 31 );
               cindex = 1 << shift;
            }
         }
         if( !msg )
            msg = "You hear $n's death cry.";
         break;
   }
   act( AT_CARNAGE, msg, ch, NULL, NULL, TO_ROOM );
   if( vnum )
   {
      char buf[MAX_STRING_LENGTH];
      OBJ_DATA *obj;
      char *name;
      if( !get_obj_index( vnum ) )
      {
         bug( "death_cry: invalid vnum", 0 );
         return;
      }
      name = IS_NPC( ch ) ? ch->short_descr : ch->name;
      obj = create_object( get_obj_index( vnum ), 0 );
      obj->timer = number_range( 4, 7 );
      if( IS_AFFECTED( ch, AFF_POISON ) )
         obj->value[3] = 10;
      sprintf( buf, obj->short_descr, name );
      STRFREE( obj->short_descr );
      obj->short_descr = STRALLOC( buf );
      sprintf( buf, obj->description, name );
      STRFREE( obj->description );
      obj->description = STRALLOC( buf );
      obj = obj_to_room( obj, ch->in_room, ch );
   }
   if( IS_NPC( ch ) )
      msg = "You hear something's death cry.";
   else
      msg = "You hear someone's death cry.";
   was_in_room = ch->in_room;
   for( pexit = was_in_room->first_exit; pexit; pexit = pexit->next )
   {
      if( pexit->to_room && pexit->to_room != was_in_room )
      {
         ch->in_room = pexit->to_room;
         act( AT_CARNAGE, msg, ch, NULL, NULL, TO_ROOM );
      }
   }
   ch->in_room = was_in_room;
   return;
}

void raw_kill( CHAR_DATA * ch, CHAR_DATA * victim )
{
   int wear_loc;
   OBJ_DATA *obj;
   if( !victim )
   {
      bug( "raw_kill: null victim!", 0 );
      return;
   }
   /*
    * backup in case hp goes below 1
    */
   if( NOT_AUTHED( victim ) )
   {
      bug( "raw_kill: killing unauthed", 0 );
      return;
   }
   stop_fighting( victim, TRUE );

   mprog_death_trigger( ch, victim );
   if( char_died( victim ) )
      return;
   /*
    * death_cry( victim );
    */
   rprog_death_trigger( ch, victim );
   if( char_died( victim ) )
      return;
   make_corpse( victim, ch );
   if( victim->in_room->sector_type == SECT_OCEANFLOOR
       || victim->in_room->sector_type == SECT_UNDERWATER || victim->in_room->sector_type == SECT_WATER_SWIM || victim->in_room->sector_type == SECT_WATER_NOSWIM )
      act( AT_BLOOD, "$n's blood slowly clouds the surrounding water.", victim, NULL, NULL, TO_ROOM );
   else if( victim->in_room->sector_type == SECT_AIR )
      act( AT_BLOOD, "$n's blood sprays wildly through the air.", victim, NULL, NULL, TO_ROOM );
   else
      make_blood( victim );
   if( IS_NPC( victim ) )
   {
      victim->pIndexData->killed++;
      extract_char( victim, TRUE );
      victim = NULL;
      return;
   }
   set_char_color( AT_DIEMSG, victim );
   if( victim->pcdata->mdeaths + victim->pcdata->pdeaths < 3 )
      do_help( victim, "new_death" );
   else
      do_help( victim, "_DIEMSG_" );
   extract_char( victim, FALSE );
   if( !victim )
   {
      bug( "oops! raw_kill: extract_char destroyed pc char", 0 );
      return;
   }
   for( wear_loc = WEAR_LIGHT; wear_loc <= MAX_WEAR; wear_loc++ )
   {
      if( ( obj = get_eq_char( victim, wear_loc ) ) == NULL )
         continue;
      unequip_char( victim, obj );
   }
   while( victim->first_affect )
      affect_remove( victim, victim->first_affect );
   victim->affected_by = race_table[victim->race]->affected;
   victim->resistant = 0;
   victim->susceptible = 0;
   victim->immune = 0;
   victim->carry_weight = 0;
   victim->armor = 100;
   victim->armor += race_table[victim->race]->ac_plus;
   victim->attacks = race_table[victim->race]->attacks;
   victim->defenses = race_table[victim->race]->defenses;
   victim->mod_str = 0;
   victim->mod_dex = 0;
   victim->mod_wis = 0;
   victim->mod_int = 0;
   victim->mod_con = 0;
   victim->mod_cha = 0;
   victim->mod_lck = 0;
   victim->damroll = 0;
   victim->hitroll = 0;
   victim->alignment = URANGE( -1000, victim->alignment, 1000 );
   victim->saving_poison_death = race_table[victim->race]->saving_poison_death;
   victim->saving_wand = race_table[victim->race]->saving_wand;
   victim->saving_para_petri = race_table[victim->race]->saving_para_petri;
   victim->saving_breath = race_table[victim->race]->saving_breath;
   victim->saving_spell_staff = race_table[victim->race]->saving_spell_staff;
   victim->position = POS_RESTING;
   victim->hit = UMAX( 1, victim->hit );
   /*
    * Shut down some of those naked spammer killers - Blodkai
    */
   if( victim->level < LEVEL_AVATAR )
      victim->mana = UMAX( 1, victim->mana );
   else
      victim->mana = 1;
   victim->move = UMAX( 1, victim->move );
   /*
    * time to add back tattos information
    */
   if( IS_SET( victim->tattoo, TATTOO_WOLF ) )
   {
      xSET_BIT( victim->affected_by, AFF_SNEAK );
      victim->armor -= 10;
   }
   if( IS_SET( victim->tattoo, TATTOO_BULL ) )
   {
   }
   if( IS_SET( victim->tattoo, TATTOO_PANTHER ) )
   {
      xSET_BIT( victim->affected_by, AFF_HIDE );
   }
   if( IS_SET( victim->tattoo, TATTOO_BEAR ) )
   {
      SET_BIT( victim->immune, RIS_SLEEP );
      SET_BIT( victim->resistant, RIS_NONMAGIC );
      victim->damroll += 20;
   }
   if( IS_SET( victim->tattoo, TATTOO_RABBIT ) )
   {
      victim->armor -= 10;
   }
   if( IS_SET( victim->tattoo, TATTOO_DRAGON ) )
   {
      victim->hitroll += 25;
      victim->damroll += 25;
      victim->armor -= 50;
      xSET_BIT( victim->affected_by, AFF_FLYING );
      SET_BIT( victim->resistant, RIS_MAGIC );
   }
   if( IS_SET( victim->tattoo, TATTOO_MOON ) )
   {
      xSET_BIT( victim->affected_by, AFF_TRUESIGHT );
      SET_BIT( victim->resistant, RIS_DRAIN );
      victim->perm_int += 2;
   }
   /*
    * Pardon crimes...                  -Thoric
    */
   if( xIS_SET( victim->act, PLR_KILLER ) )
   {
      xREMOVE_BIT( victim->act, PLR_KILLER );
      send_to_char( "The gods have pardoned you for your murderous acts.\n\r", victim );
   }
   if( xIS_SET( victim->act, PLR_THIEF ) )
   {
      xREMOVE_BIT( victim->act, PLR_THIEF );
      send_to_char( "The gods have pardoned you for your thievery.\n\r", victim );
   }
   victim->pcdata->condition[COND_FULL] = 12;
   victim->pcdata->condition[COND_THIRST] = 12;
   if( IS_SET( sysdata.save_flags, SV_DEATH ) )
      save_char_obj( victim );
   return;
}

void group_gain( CHAR_DATA * ch, CHAR_DATA * victim )
{
   char buf[MAX_STRING_LENGTH];
   CHAR_DATA *gch, *gch_next;
   CHAR_DATA *lch;
   int 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( IS_NPC( ch ) || victim == ch )
      return;
   if( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_QUESTOR ) && IS_NPC( victim ) )
   {
      if( ch->pcdata->questmob == victim->pIndexData->vnum )
      {
         send_to_char( "You have completed your quest!\n\r", ch );
         send_to_char( "Return to the questmaster to recieve your reward before your time runs out!\n\r", ch );
         ch->pcdata->questmob = -1;
      }
   }
   members = 0;
   for( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
   {
      if( is_same_group( gch, ch ) )
         members++;
   }
   if( members == 0 )
   {
      bug( "%s: members %d", __FUNCTION__, members );
      members = 1;
   }
   lch = ch->leader ? ch->leader : ch;
   for( gch = ch->in_room->first_person; gch; gch = gch_next )
   {
      OBJ_DATA *obj;
      OBJ_DATA *obj_next;
      gch_next = gch->next_in_room;
      if( !is_same_group( gch, ch ) )
         continue;
      if( gch->level - lch->level > 15 )
      {
         send_to_char( "You are too high for this group.\n\r", gch );
         continue;
      }
      if( gch->level - lch->level < -15 )
      {
         send_to_char( "You are too low for this group.\n\r", gch );
         continue;
      }
      xp = ( int )( xp_compute( gch, victim ) * 0.1765 ) / members;
      if( !gch->fighting )
         xp /= 2;
      if( double_exp == TRUE )
      {
         xp = xp * 2;
      }
      if( ch->level < 30 && xp < 100 )
         xp = 100;
      gch->alignment = align_compute( gch, victim );
      sprintf( buf, "You receive %d experience points.\n\r", xp );
      send_to_char( buf, gch );
      gain_exp( gch, xp );
      for( obj = gch->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( gch ) ) ||
             ( IS_OBJ_STAT( obj, ITEM_ANTI_GOOD ) && IS_GOOD( gch ) ) || ( IS_OBJ_STAT( obj, ITEM_ANTI_NEUTRAL ) && IS_NEUTRAL( gch ) ) )
         {
            act( AT_MAGIC, "You are zapped by $p.", gch, obj, NULL, TO_CHAR );
            act( AT_MAGIC, "$n is zapped by $p.", gch, obj, NULL, TO_ROOM );
            obj_from_char( obj );
            obj = obj_to_room( obj, gch->in_room, ch );
            oprog_zap_trigger( gch, obj );   /* mudprogs */
            if( char_died( gch ) )
               break;
         }
      }
   }
   return;
}

/*
 * New alignment shift computation ported from Sillymud code.
 * Samson 3-13-98
 */
int align_compute( CHAR_DATA * gch, CHAR_DATA * victim )
{
   int change, align;
   if( IS_NPC( gch ) )
      return gch->alignment;
   align = gch->alignment;
   if( IS_GOOD( gch ) && IS_GOOD( victim ) )
      change = ( victim->alignment / 100 ) * ( UMAX( 1, ( victim->level - gch->level ) ) );
   else if( IS_EVIL( gch ) && IS_GOOD( victim ) )
      change = ( victim->alignment / 60 ) * ( UMAX( 1, ( victim->level - gch->level ) ) );
   else if( IS_EVIL( victim ) && IS_GOOD( gch ) )
      change = ( victim->alignment / 60 ) * ( UMAX( 1, ( victim->level - gch->level ) ) );
   else if( IS_EVIL( gch ) && IS_EVIL( victim ) )
      change = ( ( victim->alignment / 100 ) + 1 ) * ( UMAX( 1, ( victim->level - gch->level ) ) );
   else
      change = ( victim->alignment / 80 ) * ( UMAX( 1, ( victim->level - gch->level ) ) );
   if( change == 0 )
   {
      if( victim->alignment > 0 )
         change = 1;
      else if( victim->alignment < 0 )
         change = -1;
   }
   align -= change;
   align = UMAX( align, -1000 );
   align = UMIN( align, 1000 );
   return align;
}

/*
 * 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 ) + 17, 13 ) ) / 10;
   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;
   /*
    * 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->played / gchlev;
      if( xp_ratio > 20000 )  /* 5/4 */
         xp = ( xp * 5 ) >> 2;
      else if( xp_ratio > 16000 )   /* 3/4 */
         xp = ( xp * 3 ) >> 2;
      else if( xp_ratio > 10000 )   /* 1/2 */
         xp >>= 1;
      else if( xp_ratio > 5000 ) /* 1/4 */
         xp >>= 2;
      else if( xp_ratio > 3500 ) /* 1/8 */
         xp >>= 3;
      else if( xp_ratio > 2000 ) /* 1/16 */
         xp >>= 4;
   }
   /*
    * Level based experience gain cap.  Cannot get more experience for
    * a kill than the amount for your current experience level   -Thoric
    */
   return URANGE( 0, xp, exp_level( gch, gchlev + 1 ) );
}

/*
 * Revamped by Thoric to be more realistic
 * Added code to produce different messages based on weapon type - FB
 * Added better bug message so you can track down the bad dt's -Shaddai
 */
void new_dam_message( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt, OBJ_DATA * obj )
{
   char buf1[256], buf2[256], buf3[256];
   char bugbuf[MAX_STRING_LENGTH];
   const char *vs;
   const char *vp;
   const char *attack;
   char punct;
   short dampc;
   struct skill_type *skill = NULL;
   bool gcflag = FALSE;
   bool gvflag = FALSE;
   int d_index, w_index;
   ROOM_INDEX_DATA *was_in_room;
   if( !dam )
      dampc = 0;
   else
      dampc = ( ( dam * 1000 ) / victim->max_hit ) + ( 50 - ( ( victim->hit * 50 ) / victim->max_hit ) );
   if( ch->in_room != victim->in_room )
   {
      was_in_room = ch->in_room;
      char_from_room( ch );
      char_to_room( ch, victim->in_room );
   }
   else
      was_in_room = NULL;
   /*
    * Get the weapon index
    */
   if( dt > 0 && dt < top_sn )
   {
      w_index = 0;
   }
   else if( dt >= TYPE_HIT && dt < TYPE_HIT + sizeof( attack_table ) / sizeof( attack_table[0] ) )
   {
      w_index = dt - TYPE_HIT;
   }
   else
   {
      sprintf( bugbuf, "Dam_message: bad dt %d from %s in %d.", dt, ch->name, ch->in_room->vnum );
      bug( bugbuf, 0 );
      dt = TYPE_HIT;
      w_index = 0;
   }
   /*
    * get the damage index
    */
   if( dam == 0 )
      d_index = 0;
   else if( dampc < 0 )
      d_index = 1;
   else if( dampc <= 100 )
      d_index = 1 + dampc / 10;
   else if( dampc <= 200 )
      d_index = 11 + ( dampc - 100 ) / 20;
   else if( dampc <= 900 )
      d_index = 16 + ( dampc - 200 ) / 100;
   else
      d_index = 23;
   /*
    * Lookup the damage message
    */
   vs = s_message_table[w_index][d_index];
   vp = p_message_table[w_index][d_index];
   punct = ( dampc <= 30 ) ? '.' : '!';
   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 )
   {
      sprintf( buf1, "$n %s $N%c [%i]", vp, punct, dam );
      sprintf( buf2, "You %s $N%c [%i]", vs, punct, dam );
      sprintf( buf3, "$n %s you%c [%i]", vp, punct, dam );
   }
   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
      {
         sprintf( bugbuf, "Dam_message: bad dt %d from %s in %d.", dt, ch->name, ch->in_room->vnum );
         bug( bugbuf, 0 );
         dt = TYPE_HIT;
         attack = attack_table[0];
      }
      sprintf( buf1, "$n's poisoned %s %s $N%c [%i]", attack, vp, punct, dam );
      sprintf( buf2, "Your poisoned %s %s $N%c [%i]", attack, vp, punct, dam );
      sprintf( buf3, "$n's poisoned %s %s you%c [%i]", attack, vp, punct, dam );
   }
   else
   {
      if( skill )
      {
         attack = skill->noun_damage;
         if( dam == 0 )
         {
            bool found = FALSE;
            if( skill->miss_char && skill->miss_char[0] != STRING_NULL )
            {
               act( AT_HIT, skill->miss_char, ch, NULL, victim, TO_CHAR );
               found = TRUE;
            }
            if( skill->miss_vict && skill->miss_vict[0] != STRING_NULL )
            {
               act( AT_HITME, skill->miss_vict, ch, NULL, victim, TO_VICT );
               found = TRUE;
            }
            if( skill->miss_room && skill->miss_room[0] != STRING_NULL )
            {
               if( strcmp( skill->miss_room, "supress" ) )
                  act( AT_ACTION, skill->miss_room, ch, NULL, victim, TO_NOTVICT );
               found = TRUE;
            }
            if( found ) /* miss message already sent */
            {
               if( was_in_room )
               {
                  char_from_room( ch );
                  char_to_room( ch, was_in_room );
               }
               return;
            }
         }
         else
         {
            if( skill->hit_char && skill->hit_char[0] != STRING_NULL )
               act( AT_HIT, skill->hit_char, ch, NULL, victim, TO_CHAR );
            if( skill->hit_vict && skill->hit_vict[0] != STRING_NULL )
               act( AT_HITME, skill->hit_vict, ch, NULL, victim, TO_VICT );
            if( skill->hit_room && skill->hit_room[0] != STRING_NULL )
               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] ) )
      {
         if( obj )
            attack = obj->short_descr;
         else
            attack = attack_table[dt - TYPE_HIT];
      }
      else
      {
         sprintf( bugbuf, "Dam_message: bad dt %d from %s in %d.", dt, ch->name, ch->in_room->vnum );
         bug( bugbuf, 0 );
         dt = TYPE_HIT;
         attack = attack_table[0];
      }
      sprintf( buf1, "$n %s $N%c [%i]", vp, punct, dam );
      sprintf( buf2, "You %s $N%c [%i]", vs, punct, dam );
      sprintf( buf3, "$n %s you%c [%i]", vp, punct, dam );
   }
   act( AT_ACTION, buf1, ch, NULL, victim, TO_NOTVICT );
   if( !gcflag )
      act( AT_HIT, buf2, ch, NULL, victim, TO_CHAR );
   if( !gvflag )
      act( AT_HITME, buf3, ch, NULL, victim, TO_VICT );
   if( was_in_room )
   {
      char_from_room( ch );
      char_to_room( ch, was_in_room );
   }
   return;
}

#ifndef dam_message
void dam_message( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt )
{
   new_dam_message( ch, victim, dam, dt );
}
#endif
void do_kill( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   one_argument( argument, arg );
   if( arg[0] == STRING_NULL )
   {
      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( !IS_NPC( victim ) )
   {
      if( !xIS_SET( victim->act, PLR_KILLER ) || !xIS_SET( victim->act, PLR_THIEF ) )
      {
         send_to_char( "You must MURDER a player.\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, TRUE ) )
      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 || ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK )
   {
      send_to_char( "You do the best you can!\n\r", ch );
      return;
   }
   WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
   check_attacker( ch, victim );
   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] == STRING_NULL )
   {
      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, TRUE ) )
      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 )
            xSET_BIT( ch->master->act, PLR_ATTACKER );
      }
   }
   if( ch->position == POS_FIGHTING || ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK )
   {
      send_to_char( "You do the best you can!\n\r", ch );
      return;
   }
   if( !IS_NPC( victim ) && xIS_SET( ch->act, PLR_NICE ) )
   {
      send_to_char( "You feel too nice to do that!\n\r", ch );
      return;
   }
   /*
    * if ( !IS_NPC( victim ) && xIS_SET(victim->act, PLR_PK ) )
    */
   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 );
   check_illegal_pk( ch, victim );
   check_attacker( ch, victim );
   multi_hit( ch, victim, TYPE_UNDEFINED );
   return;
}

/*
 * Check to see if the player is in an "Arena".
 */
bool in_arena( CHAR_DATA * ch )
{
   if( xIS_SET( ch->in_room->room_flags, ROOM_ARENA ) )
      return TRUE;
   if( IS_SET( ch->in_room->area->flags, AFLAG_FREEKILL ) )
      return TRUE;
   if( ch->in_room->vnum >= 29 && ch->in_room->vnum <= 43 )
      return TRUE;
   if( !str_cmp( ch->in_room->area->filename, "arena.are" ) )
      return TRUE;
   return FALSE;
}

bool check_illegal_pk( CHAR_DATA * ch, CHAR_DATA * victim )
{
   char buf[MAX_STRING_LENGTH];
   char buf2[MAX_STRING_LENGTH];
   if( !IS_NPC( victim ) && !IS_NPC( ch ) )
   {
      if( ( !IS_SET( victim->pcdata->flags, PCFLAG_DEADLY )
            || ch->level - victim->level > 10
            || !IS_SET( ch->pcdata->flags, PCFLAG_DEADLY ) ) && !in_arena( ch ) && ch != victim && !( IS_IMMORTAL( ch ) && IS_IMMORTAL( victim ) ) )
      {
         if( IS_NPC( ch ) )
            sprintf( buf, " (%s)", ch->name );
         if( IS_NPC( victim ) )
            sprintf( buf2, " (%s)", victim->name );
         sprintf( log_buf, "&p%s on %s%s in &W***&rILLEGAL PKILL&W*** &pattempt at %d",
                  ( lastplayercmd ), ( IS_NPC( victim ) ? victim->short_descr : victim->name ), ( IS_NPC( victim ) ? buf2 : "" ), victim->in_room->vnum );
         last_pkroom = victim->in_room->vnum;
         log_string( log_buf );
         to_channel( log_buf, CHANNEL_MONITOR, "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;
   int attempt;
   short door;
   EXIT_DATA *pexit;
   int oldmap = ch->map;
   int oldx = ch->x;
   int oldy = ch->y;
   if( !who_fighting( ch ) )
   {
      if( ch->position == POS_FIGHTING || ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK )
      {
         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( IS_AFFECTED( ch, AFF_BERSERK ) )
   {
      send_to_char( "Flee while berserking?  You aren't thinking very clearly...\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 more aggressive than standard or hurt. - Haus
    */
   if( !IS_NPC( ch ) && ch->position < POS_FIGHTING )
   {
      send_to_char( "You can't flee in an aggressive stance...\n\r", ch );
      return;
   }
   if( IS_NPC( ch ) && ch->position <= POS_SLEEPING )
      return;
   was_in = ch->in_room;
   for( attempt = 0; attempt < 8; attempt++ )
   {
      door = number_door(  );
      if( ( pexit = get_exit( was_in, door ) ) == NULL
          || !pexit->to_room
          || IS_SET( pexit->exit_info, EX_NOFLEE )
          || ( IS_SET( pexit->exit_info, EX_CLOSED ) && !IS_AFFECTED( ch, AFF_PASS_DOOR ) ) || ( IS_NPC( ch ) && xIS_SET( pexit->to_room->room_flags, ROOM_NO_MOB ) ) )
         continue;
      affect_strip( ch, gsn_sneak );
      xREMOVE_BIT( ch->affected_by, AFF_SNEAK );
      if( ch->mount && ch->mount->fighting )
         stop_fighting( ch->mount, TRUE );
      move_char( ch, pexit, 0, door );
      if( IS_PLR_FLAG( ch, PLR_ONMAP ) || IS_ACT_FLAG( ch, ACT_ONMAP ) )
      {
         now_in = ch->in_room;
         if( ch->map == oldmap && ch->x == oldx && ch->y == oldy )
            continue;
      }
      else
      {
         if( ( now_in = ch->in_room ) == was_in )
            continue;
      }
      ch->in_room = was_in;
      act( AT_FLEE, "$n flees head over heels!", ch, NULL, NULL, TO_ROOM );
      ch->in_room = now_in;
      act( AT_FLEE, "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM );
      if( !IS_NPC( ch ) )
      {
         CHAR_DATA *wf = who_fighting( ch );
         act( AT_FLEE, "You flee head over heels from combat!", ch, NULL, NULL, TO_CHAR );
         /*
          * I dont like to loose just cause i bit off more than i can chew
          * los = exp_level( ch, ch->level+1 ) * 0.02;
          * if ( ch->level < 50 )
          * {
          * sprintf( buf, "Curse the gods, you've lost %d experience!", los );
          * act( AT_FLEE, buf, ch, NULL, NULL, TO_CHAR );
          * gain_exp( ch, 0 - los );
          * }
          */
         if( wf && ch->pcdata->deity )
         {
            int level_ratio = URANGE( 1, wf->level / ch->level, 50 );
            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;
   }
   /*
    * los = exp_level( ch, ch->level+1 ) * 0.01;
    * act( AT_FLEE, "You attempt to flee from combat but can't escape!", ch, NULL, NULL, TO_CHAR );
    * if ( ch->level < 50 && number_bits( 3 ) == 1 )
    * {
    * sprintf( buf, "Curse the gods, you've lost %d experience!\n\r", los );
    * act( AT_FLEE, buf, ch, NULL, NULL, TO_CHAR );
    * gain_exp( ch, 0 - los );
    * }
    */
   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];
   argument = one_argument( argument, arg );
   one_argument( argument, arg2 );
   if( arg[0] == STRING_NULL )
   {
      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, "pounce" ) )
   {
      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" ) )
   {
      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 if( !str_cmp( arg2, "dog" ) )
   {
      act( AT_BLOOD, "You order your dogs to rip $N to shreds.", ch, NULL, victim, TO_CHAR );
      act( AT_BLOOD, "$n orders $s dogs to rip you apart.", ch, NULL, victim, TO_VICT );
      act( AT_BLOOD, "$n orders $s dogs to rip $N to shreds.", 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 );
   }
   set_cur_char( victim );
   raw_kill( ch, victim );
   return;
}