ackfuss-4.3.9/area/
ackfuss-4.3.9/board/
ackfuss-4.3.9/help/e/
ackfuss-4.3.9/help/f/
ackfuss-4.3.9/help/h/
ackfuss-4.3.9/help/l/
ackfuss-4.3.9/help/n/
ackfuss-4.3.9/help/q/
ackfuss-4.3.9/help/s/
ackfuss-4.3.9/help/u/
ackfuss-4.3.9/help/v/
ackfuss-4.3.9/help/y/
ackfuss-4.3.9/help/z/
ackfuss-4.3.9/npc/a/
ackfuss-4.3.9/npc/b/
ackfuss-4.3.9/npc/c/
ackfuss-4.3.9/npc/d/
ackfuss-4.3.9/npc/e/
ackfuss-4.3.9/npc/f/
ackfuss-4.3.9/npc/h/
ackfuss-4.3.9/npc/i/
ackfuss-4.3.9/npc/k/
ackfuss-4.3.9/npc/l/
ackfuss-4.3.9/npc/n/
ackfuss-4.3.9/npc/o/
ackfuss-4.3.9/npc/p/
ackfuss-4.3.9/npc/r/
ackfuss-4.3.9/npc/s/
ackfuss-4.3.9/npc/w/
ackfuss-4.3.9/player/c/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *       _/          _/_/_/     _/    _/     _/    ACK! MUD is modified    *
 *      _/_/        _/          _/  _/       _/    Merc2.0/2.1/2.2 code    *
 *     _/  _/      _/           _/_/         _/    (c)Stephen Zepp 1998    *
 *    _/_/_/_/      _/          _/  _/             Version #: 4.3          *
 *   _/      _/      _/_/_/     _/    _/     _/                            *
 *                                                                         *
 *                        http://ackmud.nuc.net/                           *
 *                        zenithar@ackmud.nuc.net                          *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/
/***************************************************************************
 * _/_/_/_/  _/    _/  _/_/_/_/ _/_/_/_/ AckFUSS is modified ACK!MUD 4.3.1 *
 * _/        _/    _/  _/       _/       copyright Matt Goff (Kline) 2008  *
 * _/_/      _/    _/  _/_/_/_/ _/_/_/_/                                   *
 * _/        _/    _/        _/       _/ Support for this code is provided *
 * _/        _/_/_/_/  _/_/_/_/ _/_/_/_/ at www.ackmud.net -- check it out!*
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>  /* For div_t, div() */
#include <string.h>
#include <time.h>
#include "globals.h"
#include <math.h>

#ifndef DEC_ACT_COMM_H
#include "h/act_comm.h"
#endif

#ifndef DEC_ACT_INFO_H
#include "h/act_info.h"
#endif

#ifndef DEC_ACT_MOB_H
#include "h/act_mob.h"
#endif

#ifndef DEC_ACT_MOVE_H
#include "h/act_move.h"
#endif

#ifndef DEC_ACT_OBJ_H
#include "h/act_obj.h"
#endif

#ifndef DEC_ACT_WIZ_H
#include "h/act_wiz.h"
#endif

#ifndef DEC_BUILDTAB_H
#include "h/buildtab.h"
#endif

#ifndef DEC_COMM_H
#include "h/comm.h"
#endif

#ifndef DEC_MONEY_H
#include "money.h"
#endif

bool deathmatch;

extern POL_DATA politics_data;
extern CHAR_DATA *quest_target;
extern CHAR_DATA *quest_mob;
extern OBJ_DATA *quest_object;
extern int quest_timer;

const float hr_damTable[121] = {
   0.311,
   0.325,
   0.341,
   0.358,
   0.378,
   0.399,
   0.423,
   0.449,
   0.478,
   0.509,
   0.543,
   0.579,
   0.618,
   0.659,
   0.703,
   0.749,
   0.797,
   0.846,
   0.897,
   0.948,
   1.000,
   1.012,
   1.024,
   1.036,
   1.048,
   1.060,
   1.071,
   1.083,
   1.094,
   1.105,
   1.117,
   1.127,
   1.138,
   1.149,
   1.159,
   1.169,
   1.178,
   1.188,
   1.197,
   1.206,
   1.215,
   1.223,
   1.231,
   1.239,
   1.247,
   1.254,
   1.261,
   1.268,
   1.274,
   1.281,
   1.287,
   1.292,
   1.298,
   1.303,
   1.308,
   1.313,
   1.317,
   1.322,
   1.326,
   1.330,
   1.333,
   1.337,
   1.340,
   1.344,
   1.347,
   1.350,
   1.352,
   1.355,
   1.357,
   1.360,
   1.362,
   1.364,
   1.366,
   1.368,
   1.370,
   1.372,
   1.373,
   1.375,
   1.376,
   1.377,
   1.379,
   1.380,
   1.381,
   1.382,
   1.383,
   1.384,
   1.385,
   1.386,
   1.387,
   1.387,
   1.388,
   1.389,
   1.389,
   1.390,
   1.391,
   1.391,
   1.392,
   1.392,
   1.393,
   1.393,
   1.393,
   1.394,
   1.394,
   1.395,
   1.395,
   1.395,
   1.395,
   1.396,
   1.396,
   1.396,
   1.396,
   1.397,
   1.397,
   1.397,
   1.397,
   1.397,
   1.397,
   1.398,
   1.398,
   1.398,
   1.398
};

/*
 * Local functions.
 */
bool  check_dodge      args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
bool  check_parry      args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
bool  check_skills     args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
void  dam_message      args( ( CHAR_DATA * ch, CHAR_DATA * victim, float dam, int dt ) );
void  death_message    args( ( CHAR_DATA * ch, CHAR_DATA * victim, int dt, int max_dt ) );
void  group_gain       args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
bool  is_safe          args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
void  make_corpse      args( ( CHAR_DATA * ch, char *argument ) );
void  set_fighting     args( ( CHAR_DATA * ch, CHAR_DATA * victim, bool check ) );
void  disarm           args( ( CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * obj ) );
void  trip             args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
void  check_adrenaline args( ( CHAR_DATA * ch, float damage ) );
void  obj_damage       args( ( OBJ_DATA * obj, CHAR_DATA * victim, float dam ) );
float combat_damcap    args( ( CHAR_DATA *ch, CHAR_DATA *victim, float dam, int dt ) );
void  check_brawl      args( ( CHAR_DATA *ch ) );
void  damage_gear      args( ( CHAR_DATA *ch ) );

/*
 * Control the fights going on.
 * Called periodically by update_handler.
 */
void violence_update( void )
{
   CHAR_DATA *ch;
   CHAR_DATA *ch_next;
   CHAR_DATA *victim;
   CHAR_DATA *rch;
   CHAR_DATA *rch_next;
   /*
    * CHAR_DATA *check_char;   
    */
/*  CHAR_DATA	*marker;  */
   bool has_cast = FALSE;



   CREF( ch_next, CHAR_NEXT );
   for( ch = first_char; ch; ch = ch_next )
   {

      ch_next = ch->next;


      /*
       * For stunning during combat
       * -Damane-    4/26/96 
       */

      if( ch->position == POS_STUNNED )
      {
         if( ch->wait > 0 )
         {
            ch->wait -= 1;
            continue;
         }
         else
         {
            ch->position = POS_STANDING;
            send_to_char( "You are no longer stunned.\n\r", ch );
            continue;
         }
      }
      has_cast = FALSE;

/* Healing rapidly for raged wolves  */

      if( !IS_NPC(ch) && (IS_WOLF( ch ) && IS_RAGED( ch )) )
      {
         if( !is_affected( ch, skill_lookup( "Enraged" ) ) )
            ch->act.reset(ACT_RAGED);
         ch->hit = ( UMIN( ch->max_hit, ( ch->hit + ch->max_hit / 150 ) ) );

      }

/* slight damage for players in a speeded stance, simulates fatigue */

      if( !IS_NPC( ch ) && ( stance_app[ch->stance].speed_mod > 0 ) )
      {
         ch->hit =
            UMAX( 10, ch->hit - number_range( get_psuedo_level( ch ) * 5 / 1000, get_psuedo_level( ch ) * 10 / 1000 ) );
      }

/*
 *  for when wolves can't cast normal spells, 
 *  increase regen rate mucho to compensate.  
 *  let's make it a skill instead..hehehe
 *
   if ( ch->fighting != NULL )
     ch->hit = ( UMIN( ch->max_hit, ( ch->hit + ( number_range( (20 * ch->max_hit /100) , 

 */

/* Heated armor damage :) ZEN  */

      if( ch->hit > 0
          && ch->in_room != NULL && get_room_index( ch->in_room->vnum ) != NULL && item_has_apply( ch, ITEM_APPLY_HEATED ) )
      {
         OBJ_DATA *heated_item;
         int heat_damage = 0;

         for( heated_item = ch->first_carry; heated_item != NULL; heated_item = heated_item->next_in_carry_list )
         {
            if( IS_SET( heated_item->item_apply, ITEM_APPLY_HEATED ) && heated_item->wear_loc != WEAR_NONE )
            {
               heat_damage = heated_item->level;
               if( IS_OBJ_STAT(heated_item,ITEM_EXTRA_REMORT) )
                  heat_damage *= 2;
               obj_damage( heated_item, ch, heat_damage );
               act( "@@W   $p@@N you are wearing are @@eBURNING@@N you!!!", ch, heated_item, NULL, TO_CHAR );
               act( "@@W   $p worn by $n is @@eBURNING@@N!!!", ch, heated_item, NULL, TO_ROOM );
               if( IS_NPC( ch ) )
                  do_remove( ch, heated_item->name );
            }
         }
      }

      if( ch->stunTimer > 0 )
      {
         ch->stunTimer--;
         continue;
      }
      /*
       * heal check for  solos ( mob )..   Zen  
       */


      if( ( ch->is_free == FALSE ) && ( IS_NPC( ch ) ) && ch->act.test(ACT_SOLO) && ch->hit > 0 )
      {
         if( ( ch->hit < ch->max_hit * 3 / 4 ) && ( ch->mana > mana_cost( ch, skill_lookup( "heal" ) ) ) )
         {
            do_cast( ch, "heal self" );
            has_cast = TRUE;
         }
      }
      else if( IS_NPC( ch ) && ch->hit < 0 )
      {
         ch->position = POS_DEAD;
         if( ch->fighting == NULL )
            if( ch->in_room != NULL )
               act( "Suddenly, $n is enveloped in a @@mBeam of light@@N, and is gone!", ch, NULL, NULL, TO_ROOM );
         stop_fighting( ch, TRUE );
         extract_char( ch, TRUE );
         continue;
      }

      area_resetting_global = TRUE;
      if( ( ch->is_free == FALSE ) && ( IS_NPC( ch ) ) && ( !IS_SET( ch->def, DEF_NONE ) ) && ch->hit > 0 )
      {
         if( ch->hit < ch->max_hit * 2 / 3 )
         {
            if( IS_SET( ch->def, DEF_CURE_LIGHT ) )
            {
               if( ch->mana > mana_cost( ch, skill_lookup( "cure light" ) ) )
               {
                  do_cast( ch, "\'cure light\' self" );
                  has_cast = TRUE;
               }
            }
            else if( IS_SET( ch->def, DEF_CURE_SERIOUS ) )
            {
               if( ch->mana > mana_cost( ch, skill_lookup( "cure serious" ) ) )
               {
                  do_cast( ch, "\'cure serious\' self" );
                  has_cast = TRUE;
               }
            }
            else if( IS_SET( ch->def, DEF_CURE_CRITIC ) )
            {
               if( ch->mana > mana_cost( ch, skill_lookup( "cure critical" ) ) )
               {
                  do_cast( ch, "\'cure critical\' self" );
                  has_cast = TRUE;
               }
            }
            else if( IS_SET( ch->def, DEF_CURE_HEAL ) )
            {
               if( ch->mana > mana_cost( ch, skill_lookup( "heal" ) ) )
               {
                  do_cast( ch, "heal self" );
                  has_cast = TRUE;
               }
            }
         }
      }
      else if( IS_NPC( ch ) && ch->hit < 0 )
      {
         ch->position = POS_DEAD;
         if( ch->fighting == NULL )
            if( ch->in_room != NULL )
               act( "Suddenly, $n is enveloped in a @@mBeam of light@@N, and is gone!", ch, NULL, NULL, TO_ROOM );
         extract_char( ch, TRUE );
         continue;
      }

      if( ( ch->is_free == FALSE )
          && ( IS_NPC( ch ) )
          && ( !IS_SET( ch->def, DEF_NONE ) )
          && ( ch->hit > 0 ) && ( ch->first_shield == NULL ) && ( !has_cast ) && ( ch->fighting == NULL ) )
      {
         if( ( IS_SET( ch->def, DEF_SHIELD_FIRE ) )
             && ( !is_affected( ch, skill_lookup( "fireshield" ) ) )
             && ( ch->mana > mana_cost( ch, skill_lookup( "fireshield" ) ) ) )
         {
            do_cast( ch, "fireshield" );
            has_cast = TRUE;
         }
         else
            if( ( IS_SET( ch->def, DEF_SHIELD_ICE ) )
                && ( !is_affected( ch, skill_lookup( "iceshield" ) ) )
                && ( ch->mana > mana_cost( ch, skill_lookup( "iceshield" ) ) ) )
         {
            do_cast( ch, "iceshield" );
            has_cast = TRUE;
         }
         else
            if( ( IS_SET( ch->def, DEF_SHIELD_SHOCK ) )
                && ( !is_affected( ch, skill_lookup( "shockshield" ) ) )
                && ( ch->mana > mana_cost( ch, skill_lookup( "shockshield" ) ) ) )
         {
            do_cast( ch, "shockshield" );
            has_cast = TRUE;
         }
      }
      area_resetting_global = FALSE;
/* Offensive spell handler, only use when actually fighting.. */

      if( ( IS_NPC( ch ) )
          && ( ch->is_free == FALSE )
          && ( ch->cast > 1 )
          && ( !has_cast )
          && ( ch->position > POS_RESTING )
          && ( ch->fighting != NULL )
          && ( ch->fighting->is_free != TRUE )
          && ( ch->in_room != NULL ) && ( ch->hit > 1 ) && ( ch->position == POS_FIGHTING ) )

      {
         short cast_frequency;
         short index;

         cast_frequency = get_psuedo_level( ch ) / 2; /* maybe set in olc later? */
         if( ( number_range( 0, 99 ) < cast_frequency ) && ( ch->mana >= ( 40 * ch->max_mana / 100 ) ) )
         {
            for( index = 1; index < 32; index++ )
            {
               if( ( IS_SET( ch->cast, ( 1 << index ) ) )
                   && ( number_range( 0, 99 ) < ( index * 3 + number_range( 0, 25 ) ) )
                   && ( ch->mana > mana_cost( ch, skill_lookup( rev_table_lookup( tab_cast_name, ( 1 << index ) ) ) ) ) )
               {
                  char cast_name[MSL];
                  snprintf( cast_name, MSL, "%s %s", rev_table_lookup( tab_cast_name, ( 1 << index ) ), ch->fighting->name );
                  do_cast( ch, cast_name );
                  has_cast = TRUE;
                  break;
               }
            }
         }

      }
      /*
       * Hunting mobs.
       * -S- Mod: use flags to work out what to do.... 
       */
      if( IS_NPC( ch ) && ch->fighting == NULL && IS_AWAKE( ch ) )
      {
         mob_hunt( ch );
         continue;
      }
      if( ( victim = ch->fighting ) == NULL || ch->in_room == NULL )
      {
         continue;
      }


      if( ( IS_AWAKE( ch ) )
          && ( ch->is_free == FALSE )
          && ( victim->is_free == FALSE )
          && ( ch->in_room != NULL ) && ( victim->in_room != NULL ) && ( ch->in_room == victim->in_room ) )
      {
         check_brawl(ch);
         one_hit( ch, victim, TYPE_UNDEFINED );
      }
      else
         stop_fighting( ch, FALSE );

      if( ( victim = ch->fighting ) == NULL )
         continue;

      mprog_hitprcnt_trigger( ch, victim );
      mprog_fight_trigger( ch, victim );

      /*
       * Fun for the whole family!   RCH is a non-fighting mob
       */
      if( IS_NPC( victim ) && ( get_psuedo_level( victim ) > 15 ) )
      {
         CREF( rch_next, CHAR_NEXTROOM );
         for( rch = ch->in_room->first_person; rch != NULL; rch = rch_next )
         {
            rch_next = rch->next_in_room;
            if( !IS_NPC( rch ) )
               continue;

            if( IS_AWAKE( rch ) && rch->fighting == NULL )
            {
               /*
                * NPC's assist NPC's of same type or 45% chance regardless.
                */
               if( !IS_AFFECTED( rch, AFF_CHARM ) )
               {
                  if( ( rch->pIndexData == victim->pIndexData )   /* is it the same as a target here?  */
                      || ( ( number_percent(  ) < 20 )
                           && ( abs( get_psuedo_level( rch ) - get_psuedo_level( victim ) ) < 35 ) ) )
                  {
                     CHAR_DATA *vch;
                     CHAR_DATA *target;
                     int number;

                     target = NULL;
                     number = 0;

                     /*
                      * vch is the target of the lazy mob...a player 
                      */
                     for( vch = ch->in_room->first_person; vch; vch = vch->next )
                     {
                        if( ( can_see( rch, vch ) ) && ( !IS_NPC( vch ) ) )
                        {
                           target = vch;
                           number++;
                        }
                     }

                     if( target != NULL )
                     {
                        if( abs( target->level - rch->level ) < 40 && rch != quest_mob ) /* Don't want the quest mob involved in the brawl. --Kline */
                           one_hit( rch, target, TYPE_UNDEFINED );
                     }
                  }
               }
            }
         }
         CUREF( rch_next );
      }
   }
   CUREF( ch_next );
   return;
}

#define ZERO_RATIO 20
#define ONE_STEPS 100l
#define MAX_IX 120
#define MAX_DAM_MOD 1.4



/*
 * Hit one guy once.
 */
void one_hit( CHAR_DATA * ch, CHAR_DATA * victim, int dt )
{
   OBJ_DATA *wield;
   OBJ_DATA *shield;
   int victim_ac;
   int remort_bonus;
   float dam;
   int diceroll;
   int ix;
   float dam_mod;
   /*
    * Can't beat a dead char!
    * Guard against weird room-leavings.
    */
   if( ( ch->stance == STANCE_CASTER ) || ( ch->stance == STANCE_WIZARD ) )
      return;

   if( ch->position == POS_RIDING )
   {
      if( ch->riding && ( ch->riding->in_room == ch->in_room ) )
      {
         do_dismount( ch, "" );
      }
      else
      {
         ch->position = POS_FIGHTING;
      }
   }

   if( victim->position == POS_DEAD || ch->in_room != victim->in_room )
      return;

   if( !IS_NPC( ch ) && ( ( ch->stance == STANCE_AMBUSH ) || ( ch->stance == STANCE_AC_BEST ) ) )
   {
      send_to_char( "You step out of the shadows.\n\r", ch );
      ch->stance = STANCE_WARRIOR;
      ch->stance_ac_mod = 0;
      ch->stance_dr_mod = 0;
      ch->stance_hr_mod = 0;
      act( "$n steps out of the Shadows!", ch, NULL, NULL, TO_ROOM );
   }

   /*
    * Figure out the type of damage message.
    */
   wield = get_eq_char( ch, WEAR_HOLD_HAND_L );
   if( !IS_WEAPON( wield ) )
      wield = get_eq_char( ch, WEAR_HOLD_HAND_R );
   if( !IS_WEAPON( wield ) )
      wield = NULL;
   if( dt == TYPE_UNDEFINED )
   {
      dt = TYPE_HIT;
      if( wield != NULL && wield->item_type == ITEM_WEAPON )
         dt += wield->value[3];
   }
   /*
    * check for martial arts  Taken out for wierd act crash bug with type_martial ZEN
    * if ( dt == TYPE_HIT && wield == NULL )
    * if ( number_percent() < ( IS_NPC(ch) ? 
    * ( IS_SET(ch->skills, MOB_MARTIAL ) ? 75 : 0 ) : ( ch->pcdata->learned[gsn_martial_arts]/4) ) )
    * dt = TYPE_MARTIAL;
    * 
    */
   /*
    * Calculate to-hit-armor-class-0 versus armor.
    */


   victim_ac = GET_AC( victim );
   if( !can_see( ch, victim ) )
      victim_ac -= 200;

   if( dt == gsn_backstab || dt == gsn_circle )
      victim_ac += 300;

   /*
    * The moment of excitement!
    */
   diceroll = number_range( ( get_psuedo_level( ch ) * 5 ), ( get_psuedo_level( ch ) * 21 ) ) + GET_HITROLL( ch );

/* players get a tohit bonus for now  */

   if( !IS_NPC( ch ) )
      diceroll += number_range( get_psuedo_level( ch ), ( get_psuedo_level( ch ) * 1 ) );
   if( ( remort_bonus = get_psuedo_level( ch ) > 100 ) )
      diceroll += remort_bonus * 1;

   if( IS_NPC( ch ) )
   {
      diceroll += ( get_psuedo_level( ch ) * 5 );
      if( ch->act.test(ACT_SOLO) )
         diceroll += ( get_psuedo_level( ch ) * 5 );
   }
   if( IS_AFFECTED( ch, AFF_CLOAK_ADEPT ) )
      diceroll += get_psuedo_level( ch ) * 2;

/* Player vs player bonus, to handle unbalanced hitroll vs ac */
   if( !IS_NPC( ch ) && !IS_NPC( victim ) && get_psuedo_level( ch ) > 80 && get_psuedo_level( victim ) > 80 )
      diceroll += number_range( 1000, 2000 );
   if( IS_NPC( ch ) && victim_ac < -3000 && get_psuedo_level( ch ) > 110 && ( number_range( 0, 100 ) < 10 ) )
      diceroll += 3000;

   if( victim_ac > -100 )
   {
      if( diceroll + victim_ac < 0 )
         ix = -1;
      else
         ix = ZERO_RATIO;
   }
   else
   {
      /*
       * This finds the ratio of excess hit roll to AC, and
       * breaks it into steps as defined by constants above,
       * for use in damage modifier lookup table.
       * Long int calculation avoids overflow problems. 
       */
      ix = -( ONE_STEPS * ( long int )( diceroll + victim_ac ) ) / ( long int )victim_ac;
      ix += ZERO_RATIO;
   }



   if( ix < 0 )
   {
      dam_mod = 0.0;

      damage( ch, victim, 0, dt );
      tail_chain(  );
      return;
   }
   else if( ix <= MAX_IX )
      dam_mod = hr_damTable[ix];
   else
      dam_mod = MAX_DAM_MOD;
   /*
    * Hit.
    * Calc damage.
    * Tried to make it easy for players to hit mobs... --Stephen
    */
   if( IS_NPC( ch ) )
   {
      if( wield )
         dam = number_range( wield->value[1], wield->value[2] );
      else
         dam = number_range( ch->level / 3, ch->level / 2 );
      if( ch->act.test(ACT_SOLO ) )
         dam *= 1.5;

   }
   else
   {
      if( wield != NULL )
         dam = number_range( wield->value[1], wield->value[2] );
      else
         dam = UMAX( number_range( 2, 4 ), ch->level / 4 );
   }

   /*
    * Bonuses.
    */
   dam += number_range( GET_DAMROLL( ch ) * 13 / 20, GET_DAMROLL( ch ) * 15 / 20 );
   if( ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
       || item_has_apply( ch, ITEM_APPLY_ENHANCED ) || ( IS_NPC( ch ) && IS_SET( ch->skills, MOB_ENHANCED ) ) )
   {
      if( IS_NPC( ch ) )
         dam += dam * 1 / 20;
      else
         dam += ( ch->pcdata->learned[gsn_enhanced_damage] > 0 ) ?
            dam * ch->pcdata->learned[gsn_enhanced_damage] / 150 : dam * .4;
   }
   if( IS_NPC(ch) && IS_SET(ch->skills,MOB_PROWESS) )
      dam += number_range((int)(ch->level * 1.5),(int)(ch->level * 3));
   if( !IS_NPC(ch) && ch->pcdata->learned[gsn_combat_prowess] > 0 )
      dam += number_range((int)(ch->pcdata->learned[gsn_combat_prowess] * 1.5),(int)(ch->pcdata->learned[gsn_combat_prowess] * 3));
   if( !IS_AWAKE( victim ) )
      dam *= 1.5;
   /*
    * extra damage from martial arts 
    */
   if( dt == TYPE_MARTIAL )
      dam = ( dam * 4 ) / 3;

   if( dt == gsn_backstab )
      dam *= 1.4;
   if( dt == gsn_circle )
      dam *= 1.1;
   if( IS_AFFECTED( ch, AFF_CLOAK_ADEPT ) )
      dam *= 1.2;
   if( dam <= 0 )
      dam = 1;
   shield = NULL;
   if( IS_SHIELD( shield = get_eq_char( victim, WEAR_HOLD_HAND_R ) ) )
   {
   }
   else if( IS_SHIELD( shield = get_eq_char( victim, WEAR_HOLD_HAND_L ) ) )
   {
   }
   else
      shield = NULL;
   {
      int skin_mods;
      if( !IS_NPC( victim ) )
      {
         skin_mods = race_table[victim->race].race_flags;
      }
      else
      {
         skin_mods = ( victim->race == 0 ? victim->pIndexData->race_mods : race_table[victim->race].race_flags );
      }
      if( IS_SET( skin_mods, RACE_MOD_TOUGH_SKIN ) )
         dam_mod -= .1;
      else if( IS_SET( skin_mods, RACE_MOD_STONE_SKIN ) )
         dam_mod -= .2;
      else if( IS_SET( skin_mods, RACE_MOD_IRON_SKIN ) )
         dam_mod -= .3;
   }
   if( ( ( IS_NPC( victim ) )
         || ( victim->pcdata->learned[gsn_shield_block] > 0 ) )
       && ( shield )
       && ( number_range( 1, 4 ) != 3 )
       && ( number_percent(  ) <
            ( IS_NPC( victim ) ?
              get_psuedo_level( victim ) / 7 :
              victim->pcdata->learned[gsn_shield_block] / 5 )
            + ( IS_NPC( victim ) ? 10 : ( 1 * ( victim->lvl[3] - ch->level ) + victim->lvl2[2] / 8 ) ) ) )
      /*
       * Shield Block! 
       */
   {
      act( "$n blocks $N's attack with $p", victim, shield, ch, TO_NOTVICT );
      act( "$N blocks your attack with $p", ch, shield, victim, TO_CHAR );
      act( "You block $N's attack with $p", victim, shield, ch, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   else
   {
      dam *= dam_mod;
      if( ( wield )
          && ( dam > 0 ) && ( IS_OBJ_STAT(wield,ITEM_EXTRA_LIFESTEALER) ) && ( number_range( 0, 99 ) < ( wield->level / 4 ) ) )
      {
         act( "@@W$n screams in @@Ragony@@W as an evil @@da@@eur@@da@@W flows from $p!@@N", victim, wield, ch, TO_NOTVICT );
         act( "@@WYou feel a surge of health as $p sucks the life of $N@@N!!", ch, wield, victim, TO_CHAR );
         act( "@@WYou scream in @@Ragony@@W as $p shrieks, and shrouds you in an evil @@da@@eur@@da@@N!!", victim, wield, ch,
              TO_CHAR );
         if( ( ch->lvl2[0] > 0 ) || ( ch->lvl2[3] > 0 ) )
         {
            ch->hit = UMIN( ch->max_hit, ch->hit + number_range( (int)(dam * .075), (int)(dam * 1.72) ) );
         }
         else
         {
            ch->hit = UMIN( ch->max_hit, ch->hit + number_range( (int)(dam * .03), (int)(dam * .13) ) );
         }

         ch->alignment = UMAX( -1000, ch->alignment - 50 );
      }
   }
   damage_gear(victim);
   damage( ch, victim, (int)dam, dt );


   tail_chain(  );
   return;
}



/*
 * Inflict damage from a hit.
 */
void damage( CHAR_DATA * ch, CHAR_DATA * victim, float dam, int dt )
{
   OBJ_DATA *sil_weapon;
   int sn;
   int tmp_dt;

   tmp_dt = dt;

   if( dt == gsn_circle || dt == gsn_backstab || dt == gsn_charge ) /* Ugly workarounds for records and dam management --Kline */
    dt = -1;

   if( victim->is_free == TRUE )
   {
      bug( "Freed victim in one_hit", 0 );
      return;
   }

   if( victim != ch )
   {
      /*
       * Certain attacks are forbidden.
       * Most other attacks are returned.
       */
      if( is_safe( ch, victim ) )
         return;
      if( victim != ch->fighting )
         check_killer( ch, victim );

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

      if( victim->position > POS_STUNNED )
      {
         if( ch->fighting == NULL )
         {
            set_fighting( ch, victim, TRUE );
            /*
             * check_killer( ch, victim );
             */
         }

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

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

      /*
       * Inviso attacks ... not.
       */
      if( IS_AFFECTED( ch, AFF_INVISIBLE ) )
      {
         affect_strip( ch, gsn_invis );
         affect_strip( ch, gsn_mass_invis );
         REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
         act( "$n shimmers into existence.", ch, NULL, NULL, TO_ROOM );
      }

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

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

      if( dam < 0 )
         dam = 0;

      /*
       * Check for disarm, trip, parry, and dodge.
       */
      if( dt >= TYPE_HIT )
      {
         if( IS_NPC( ch ) && ( number_percent(  ) < ch->level / 6 ) && IS_SET( ch->skills, MOB_DISARM ) )
            disarm( ch, victim, NULL );

         if( IS_NPC( ch ) && ( number_percent(  ) < ch->level / 6 ) && IS_SET( ch->skills, MOB_TRIP ) )
            trip( ch, victim );

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

   if( ((IS_NPC(ch) && IS_SET(ch->skills,MOB_CRUSHING) && number_percent() < 80) || (!IS_NPC(ch) && number_percent() < ch->pcdata->learned[gsn_crushing_blow])) && dt != -1 )
   {
    if( (IS_NPC(ch) && number_percent() < 9) || (!IS_NPC(ch) && (number_range(85,300) - ch->pcdata->learned[gsn_crushing_blow]) < 10) )
    {
     act("@@WYou @@e*@@RCRUSH@@e* @@W$N's body with the force of your blow!@@N",ch,NULL,victim,TO_CHAR);
     act("@@W$n @@e*@@RCRUSHES@@e* @@Wyour body with the force of $s blow!@@N",ch,NULL,victim,TO_VICT);
     act("@@W$n @@e*@@RCRUSHES@@e* @@W$N's body with the force of $s blow!@@N",ch,NULL,victim,TO_NOTVICT);
     dam *= 2.5;
    }
   }

   dam = combat_damcap(ch,victim,dam,dt);

      if( dt != -1 )
         dam_message( ch, victim, dam, dt );
   }

/* for now, can only have one shield up, or alternatively, only the first
   shield does anything		 */

   if( ( victim->first_shield != NULL ) && ( ch != victim ) && ( dam > 0 ) )
   {
      char buf1[MSL];
      char buf2[MSL];
      char buf3[MSL];
      snprintf( buf1, MSL, "%s", victim->first_shield->absorb_message_room );
      if( ch->act.test(ACT_BLIND_PLAYER ) )
         snprintf( buf2, MSL, "%s", "$K shield ouch" );
      else
         snprintf( buf2, MSL, "%s", victim->first_shield->absorb_message_victim );
      if( victim->act.test(ACT_BLIND_PLAYER ) )
         snprintf( buf3, MSL, "%s", "Your shield cool" );
      else
         snprintf( buf3, MSL, "%s", victim->first_shield->absorb_message_self );
      victim->first_shield->hits -= (short)dam;
      dam = dam - dam * ( victim->first_shield->percent / 100 );
      if( victim->first_shield->harmfull == TRUE )
      {

         ch->hit = UMAX( 10, ( ch->hit - victim->first_shield->attack_dam ) );
      }
      act( buf1, victim, NULL, ch, TO_NOTVICT );
      act( buf2, ch, NULL, victim, TO_CHAR );
      act( buf3, victim, NULL, ch, TO_CHAR );

      if( victim->first_shield->hits <= 0 )
      {
         AFFECT_DATA *shield_aff;

         for( shield_aff = victim->first_affect; shield_aff != NULL; shield_aff = shield_aff->next )
            if( shield_aff->type == victim->first_shield->sn )
               break;
         if( shield_aff != NULL )
            affect_remove( victim, shield_aff );
      }
   }
   /*
    * Hurt the victim.
    * Inform the victim of his new state.
    */
   victim->hit -= (int)dam;

   if( !IS_NPC(ch) )
   {
    if( dam > ch->pcdata->records->pdam_amt )
    {
     send_to_char("@@yYou've broken your physical damage record!@@N\n\r",ch);
     ch->pcdata->records->pdam_amt = (int)dam;
     ch->pcdata->records->pdam_gsn = tmp_dt;
    }
   }

   if( !IS_NPC( victim ) )
      check_adrenaline( victim, dam );

   if( !IS_NPC( victim ) && IS_WOLF( victim ) && ( dam > 350 ) )
      do_rage( victim, "FORCE" );


   if( ( IS_AFFECTED( victim, AFF_CLOAK_FLAMING ) ) && ( ch != victim )
       /*
        * && ( dt == TYPE_HIT ) 
        */  )
   {


      act( "@@N$n's @@ecloak@@N flares and envelops $N in @@eflames@@N!!", victim, NULL, ch, TO_NOTVICT );
      if( ch->act.test(ACT_BLIND_PLAYER ) )
         act( "Flame cloak on $K ouch", ch, NULL, victim, TO_CHAR );
      else
         act( "@@N$N's @@ecloak@@N flares, and envelops you with @@eflame@@N!!", ch, NULL, victim, TO_CHAR );
      if( victim->act.test(ACT_BLIND_PLAYER ) )
         act( "Your Flame cloak flares", victim, NULL, ch, TO_CHAR );
      else
         act( "@@NYour @@ecloak@@N flares, and envelops $N with @@eflame@@N!!!", victim, NULL, ch, TO_CHAR );

      if( ( is_shielded( ch, ICE_SHIELD ) ) && ( number_range( 1, 100 ) < 30 ) && ( ch != victim ) )
      {
         CHAR_DATA *rch;
         CHAR_DATA *rch_next;
         OBJ_DATA *explosion;
         CHAR_DATA *elemental;

         act( "@@e------------------------@@N", ch, NULL, NULL, TO_CHAR );
         act( "@@l************************@@N", ch, NULL, NULL, TO_CHAR );
         act( "@@W!!!!!!!!!!!!!!!!!!!!!!!!@@N", ch, NULL, NULL, TO_CHAR );
         act( "@@NThe elemental forces of @@eFire@@N and @@aIce@@N destroy each other!!!", ch, NULL, NULL, TO_CHAR );
         act( "@@W!!!!!!!!!!!!!!!!!!!!!!!!@@N", ch, NULL, NULL, TO_CHAR );
         act( "@@l************************@@N", ch, NULL, NULL, TO_CHAR );
         act( "@@e------------------------@@N", ch, NULL, NULL, TO_CHAR );
         act( "@@e------------------------@@N", ch, NULL, NULL, TO_ROOM );
         act( "@@l************************@@N", ch, NULL, NULL, TO_ROOM );
         act( "@@W!!!!!!!!!!!!!!!!!!!!!!!!@@N", ch, NULL, NULL, TO_ROOM );
         act( "@@NThe elemental forces of @@eFire@@N and @@aIce@@N destroy each other!!!", ch, NULL, NULL, TO_ROOM );
         act( "@@W!!!!!!!!!!!!!!!!!!!!!!!!@@N", ch, NULL, NULL, TO_ROOM );
         act( "@@l************************@@N", ch, NULL, NULL, TO_ROOM );
         act( "@@e------------------------@@N", ch, NULL, NULL, TO_ROOM );
         act( "@@N$N's @@ecloak@@N is ripped to shreds!!!@@N", ch, NULL, victim, TO_ROOM );
         act( "@@NYour @@ecloak@@N is ripped to shreds!!!@@N", ch, NULL, victim, TO_VICT );


         affect_strip( ch, skill_lookup( "iceshield" ) );
         affect_strip( victim, skill_lookup( "iceshield" ) );
         affect_strip( ch, skill_lookup( "fireshield" ) );
         affect_strip( victim, skill_lookup( "fireshield" ) );
         affect_strip( ch, skill_lookup( "cloak:flaming" ) );
         affect_strip( victim, skill_lookup( "cloak:flaming" ) );
         if( IS_SET( ch->affected_by, AFF_CLOAK_FLAMING ) )
            REMOVE_BIT( ch->affected_by, AFF_CLOAK_FLAMING );
         if( IS_SET( victim->affected_by, AFF_CLOAK_FLAMING ) )
            REMOVE_BIT( victim->affected_by, AFF_CLOAK_FLAMING );


         if( ( explosion = create_object( get_obj_index( OBJ_VNUM_CONFLAGRATION ), 120 ) ) != NULL )
            if( ( elemental = create_mobile( get_mob_index( MOB_VNUM_COMBAT_ELEMENTAL ) ) ) != NULL )
            {
               char bufz[MSL];

               explosion->level = 120;
               free_string( explosion->short_descr );
               explosion->short_descr = str_dup( "@@mConflagration@@N" );
               free_string( explosion->long_descr );
               explosion->long_descr = str_dup( "@@N A @@eFlaming @@NStaff of @@aIce@@N is supsended in mid air!" );

               elemental->level = 140;
               free_string( elemental->name );
               elemental->name = str_dup( ".hidden" );
               free_string( elemental->short_descr );
               elemental->short_descr = str_dup( "@@NThe @@rConflict@@N of @@eFire @@Nand @@aIce@@N" );
               free_string( elemental->long_descr );
               elemental->long_descr = str_dup( "@@NA @@rPillar@@N of @@eFire @@Nand @@aIce@@N immolates itself!" );

               char_to_room( elemental, ch->in_room );
               obj_to_char( explosion, elemental );
               snprintf( bufz, MSL, "%s", explosion->name );
               do_wear( elemental, bufz );

               if( number_range( 0, 99 ) < 40 )
                  obj_cast_spell( skill_lookup( "Retributive strike" ), 100, elemental, NULL, explosion );
               else
               {
                  CREF( rch_next, CHAR_NEXTROOM );
                  for( rch = ch->in_room->first_person; rch != NULL; rch = rch_next )
                  {
                     rch_next = rch->next_in_room;
                     if( get_psuedo_level( rch ) < 70 )
                        continue;
                     send_to_char( "\n\r@@NYou are @@ablasted@@N by the @@econflagration@@N!\n\r", rch );
                     if( number_range( 0, 99 ) < 50 )
                        obj_cast_spell( skill_lookup( "frost breath" ), 120, elemental, rch, explosion );
                     else
                        obj_cast_spell( skill_lookup( "lava burst" ), 120, elemental, rch, explosion );
                  }
                  if( ( elemental->fighting != NULL ) && ( IS_NPC( elemental->fighting ) ) )
                  {
                     stop_fighting( elemental, TRUE );
                     if( ( number_range( 0, 99 ) < 50 ) && ( !IS_NPC( ch ) ) )
                     {
                        one_hit( elemental, ch, TYPE_UNDEFINED );
                     }
                     else if( !IS_NPC( victim ) )
                     {
                        one_hit( elemental, victim, TYPE_UNDEFINED );
                     }
                  }
                  CUREF( rch_next );
               }
            }
      }
      else
      {
         float flame_damage;
         flame_damage = dam * get_psuedo_level( victim ) / 300;
         if( IS_NPC( ch ) )
         {
            if( ch->act.test(ACT_SOLO ) )
               flame_damage = flame_damage / 5;
            else
               flame_damage = flame_damage / 3;
         }
         if( ( IS_NPC( victim ) ) && ( victim->act.test(ACT_SOLO ) ) )
            flame_damage = flame_damage * 1.5;

         ch->hit = UMAX( -5, ch->hit - (int)flame_damage );
      }

   }
   if( ( is_affected( victim, skill_lookup( "cloak:misery" ) ) ) && ( ch != victim ) && ( number_range( 0, 99 ) < 35 )
       /*
        * && ( dt == TYPE_HIT ) 
        */  )
   {
      AFFECT_DATA af;
      act( "@@N$n's @@dcloak@@N flares and shrouds $N in @@dmisery@@N!!", victim, NULL, ch, TO_NOTVICT );
      if( ch->act.test(ACT_BLIND_PLAYER ) )
         act( "Flame cloak on $K ouch", ch, NULL, victim, TO_CHAR );
      else
         act( "@@N$N's @@dcloak@@N flares, and shrouds you with @@dmisery@@N!!", ch, NULL, victim, TO_CHAR );
      if( victim->act.test(ACT_BLIND_PLAYER ) )
         act( "Your Death cloak flares", victim, NULL, ch, TO_CHAR );
      else
         act( "@@NYour @@dcloak@@N flares, and shrouds $N with @@dmisery@@N!!!", victim, NULL, ch, TO_CHAR );
      if( TRUE )
      {
         af.type = skill_lookup( "curse" );
         af.duration = 1;
         af.location = APPLY_HITROLL;
         af.modifier = -1;
         af.bitvector = AFF_CURSE;
         affect_join( ch, &af );

         af.location = APPLY_DAMROLL;
         af.modifier = -1;
         affect_join( ch, &af );

         af.location = APPLY_AC;
         af.modifier = -5;
         affect_join( ch, &af );
      }
   }
   update_pos( victim );

   if( ( IS_NPC( victim ) || !IS_VAMP( victim ) ) && !( deathmatch ) )
   {
      switch ( victim->position )
      {
         case POS_MORTAL:
            act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM );
            send_to_char( "You are mortally wounded, and will die soon, if not aided.\n\r", victim );
            break;

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

         case POS_STUNNED:
            act( "$n is too stunned to do anything!", victim, NULL, NULL, TO_ROOM );
            send_to_char( "You are too stunned to do anything!\n\r", victim );
            break;

         case POS_DEAD:
            if( ( sil_weapon = get_eq_char( ch, WEAR_HOLD_HAND_L ) ) == NULL )
               sil_weapon = get_eq_char( ch, WEAR_HOLD_HAND_R );
            if( IS_WOLF( victim ) && ( !IS_NPC( ch ) ) && ( ch->pcdata->learned[gsn_decapitate] != 0 )
                && ( sil_weapon != NULL ) && ( IS_OBJ_STAT(sil_weapon,ITEM_EXTRA_SILVER) ) )
            {
               int chance;

               chance = IS_NPC( ch ) ? ch->level * 2 : ch->pcdata->learned[gsn_decapitate];
               chance += 25;

               if( ( victim->pcdata->super->level * 5 ) > ch->level )
                  chance -= ( victim->pcdata->super->level * 5 ) - ch->level;

               if( number_percent(  ) < chance )
               {
                  act( "You DECAPITATE $N's head off with one skillful stroke!", ch, NULL, victim, TO_CHAR );
                  act( "$n DECAPITATES $N's head off with one skillful stroke!", ch, NULL, victim, TO_NOTVICT );
                  send_to_char( "You suddenly feel the world is spinning away from you!", victim );
                  send_to_char( "You have been DECAPITATED!!", victim );
                  send_to_char( "You feel the rage of the wolf flow from your body.....\n\r", victim );
                  send_to_char( "You THINK you are dead!  Ooops....\n\r", victim );
               }

               victim->act.reset(ACT_WEREWOLF);
               victim->pcdata->super->level = 0;
               victim->pcdata->super->exp = 0;
               victim->pcdata->super->energy = 0;
               victim->pcdata->super->energy_max = 0;
               victim->pcdata->super->generation = -1;
               victim->pcdata->super->bloodline = 0;
               victim->pcdata->recall_vnum = 3001;

               for( sn = 0; sn <= MAX_SKILL; sn++ )
                  if( ( skill_table[sn].flag2 == WOLF ) && ( victim->pcdata->learned[sn] > 0 ) )
                     victim->pcdata->learned[sn] = 0;
            }

            act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
            send_to_char( "You have been KILLED!!\n\r\n\r", victim );
            break;

         default:
            if( dam > victim->max_hit / 4 )
               send_to_char( "That really did HURT!\n\r", victim );
            if( victim->hit < victim->max_hit / 4 )
               send_to_char( "You sure are BLEEDING!\n\r", victim );
            break;
      }
   }  /* end of if statement */
   /*
    * Sleep spells and extremely wounded folks.
    */
   if( !IS_AWAKE( victim ) )
      stop_fighting( victim, FALSE );

   /*
    * Payoff for killing things.
    */



   if( victim->position == POS_DEAD && ( IS_NPC( victim ) || !IS_VAMP( victim ) || ( deathmatch ) ) )
   {
      group_gain( ch, victim );

      /* Update mquest */
      update_mquest_kill(ch,victim);

      /*
       * Sort out kill counts..... 
       */
      if( !IS_NPC( ch ) )
      {
         if( !IS_NPC( victim ) )
            ch->pcdata->records->pk++;
         else
            ch->pcdata->records->mk++;
      }
      if( !IS_NPC( victim ) )
      {
         if( !IS_NPC( ch ) )
            victim->pcdata->records->pd++;
         else
            victim->pcdata->records->md++;
      }

      if( !IS_NPC( victim ) || victim->act.test(ACT_INTELLIGENT ) )
      {
/*	    if ( !IS_NPC(ch) && !IS_NPC(victim)
	         && is_set(ch->act,ACT_PKOK)
	         && is_set(victim->act,ACT_PKOK) )
	    {

	     snprintf(buf, "%s kills %s in mortal combat.", ch->name, victim->name);
	     info(buf, 1);
	    }
	    else
	    {
             snprintf( buf, MSL, "%s turns %s into a corpse.  Whooops.",
               ( IS_NPC(ch) ? ch->short_descr : ch->name ),
               ( IS_NPC(victim) ? victim->short_descr : victim->name) );
             info( buf, 1 );	   
            }
*/

         snprintf( log_buf, (2 * MIL), "%s killed by %s at %d",
                  ( IS_NPC( victim ) ? victim->short_descr : victim->name ),
                  ( IS_NPC( ch ) ? ch->short_descr : ch->name ), victim->in_room->vnum );
         log_string( log_buf );

         notify( log_buf, 82 );

         /*
          * As level gain is no longer automatic, a dead char loses
          * * 1/2 their gained exp.  -S- 
          * * Fixed my bug here too, hehe!
          */

         if( victim->exp > 0 )
         {
            gain_exp( victim, ( 0 - ( victim->exp / 2 ) ) );
            victim->exp = UMAX( victim->exp, 0 );
         }

      }

      if( IS_NPC( ch ) )
         raw_kill( victim, "" );
      else
      {
         char name_buf[MAX_STRING_LENGTH];
         snprintf( name_buf, MSL, "%s", ch->name );
         raw_kill( victim, name_buf );
      }

      if( deathmatch && !IS_NPC( victim ) )
         do_quit( victim, "" );

      if( IS_NPC( ch ) && IS_NPC( victim ) && ch->act.test(ACT_INTELLIGENT ) )
      {
         do_get( ch, "all from corpse" );
         do_sacrifice( ch, "corpse" );
         check_re_equip( ch );
         check_rewield( ch );
      }

      if( !IS_NPC( ch ) && IS_NPC( victim ) )
      {
         if( ch->act.test(ACT_AUTOLOOT ) )
            do_get( ch, "all from corpse" );
         else
            do_look( ch, "in corpse" );

         if( ch->act.test(ACT_AUTOSAC ) )
            do_sacrifice( ch, "corpse" );
      }

      return;
   }

   if( victim == ch )
      return;

   /*
    * Take care of link dead people.
    */
   if( !IS_NPC( victim ) && victim->desc == NULL )
   {
      if( number_range( 0, victim->wait ) == 0 )
      {
         do_recall( victim, "" );
         return;
      }
   }

   /*
    * Wimp out?
    */
   if( IS_NPC( victim ) && dam > 0 )
   {
      if( ( victim->act.test(ACT_WIMPY ) && number_bits( 1 ) == 0
            && victim->hit < victim->max_hit / 2 )
          || ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master != NULL && victim->master->in_room != victim->in_room ) )
         do_flee( victim, "" );
   }

   if( !IS_NPC( victim ) && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait == 0 )
      do_flee( victim, "" );

   tail_chain(  );
   return;

}



bool is_safe( CHAR_DATA * ch, CHAR_DATA * victim )
{
   if( deathmatch )
      return FALSE;  /* Deathmatch? Anything goes!! */


/*we are going to have safe rooms no attacks at all  SRZ 2 Jul 96
    if ( IS_NPC(ch) || IS_NPC(victim) )
	return FALSE;
*/


   /*
    * No PC vs. PS attacks in safe rooms 
    */
   if( ( victim->in_room != NULL ) && victim->in_room->room_flags.test(RFLAG_SAFE) )
   {
      send_to_char( "Not a chance!  This is a safe room.\n\r", ch );
      return TRUE;
   }

   if( victim->act.test(ACT_KILLER ) )
      return FALSE;
   if( victim->act.test(ACT_THIEF ) )
      return FALSE;
   /*
    * Vampires are considered PKOK 
    */

   if( !IS_NPC( ch ) && !IS_NPC( victim )
       && ( victim->act.test(ACT_PKOK )
            || victim->act.test(ACT_VAMPIRE ) )
       && ( ch->act.test(ACT_PKOK ) || ch->act.test(ACT_VAMPIRE ) ) )
      return FALSE;

   if( ( ( victim->level < 10 ) || ( victim->level + 20 < ch->level ) ) && ( !IS_NPC( victim ) ) && ( !IS_NPC( ch ) ) )
   {
      send_to_char( "The Gods prevent your foul deed.\n\r", ch );
      return TRUE;
   }

   return FALSE;
}



struct hunt_mobs_tp
{
   int mob_vnum;
   int room_vnum;
   int min_level;
   char *name;
}
hunt_mobs[] =
{
   {
   3062, 3001, 0, "Bug"},
   {
   3561, 3001, 40, "Shadow Dragon"},
   {
   18302, 3001, 80, "Bounty Hunter"},
   {
   18301, 3001, 100, "The Avenger"},
   {
   18306, 3001, 240, "Blayze"},
   {
   -1, -1, -1, " "}
};

/* SRZ huntlist!  */
/* Scrapped MAX_HUNTERS - can now change table without 
 * full recompile.  Was unused in checking loop. -S-
 **** LEAVE THE LAST ELEMENT of the table in place! ****/


/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer( CHAR_DATA * ch, CHAR_DATA * victim )
{
   /*
    * Follow charm thread to responsible character.
    * Attacking someone's charmed char is hostile!
    * -S- Mod:  Set sentence according to difference in levels -
    * this is no. times the player must die before the killer flag
    * will be removed.
    */

   int diff;
   int a;
   MOB_INDEX_DATA *pMobIndex;
   ROOM_INDEX_DATA *pRoomIndex;
   CHAR_DATA *hunter;

   if( ( ch->fighting == victim ) )
      return;
/*
   if ( ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL ) 
      && ( ch->fighting != victim )  )
	victim = victim->master;   */

   /*
    * NPC's are fair game.
    * So are killers and thieves.
    */
   if( IS_NPC( victim ) || victim->act.test(ACT_KILLER ) || victim->in_room->room_flags.test(RFLAG_PK) /* -S- Mod */
       || victim->act.test(ACT_THIEF ) || IS_VAMP( victim ) || IS_WOLF( victim )   /*
                                                                                        * || ( ch->fighting == victim )  */
       || ( ch == victim ) )
      return;

   /*
    * if in deathmatch, anything goes 
    */
   if( deathmatch )
      return;
   if( ch->sentence > 5000 )
      return;

   /*
    * Check to see if ch & victim are in clans, and enemies 
    */

   if( !IS_NPC( ch ) && !IS_NPC( victim ) )
   {

      if( ( ch->pcdata->clan != 0 ) && ( victim->pcdata->clan != 0 )
          && ( politics_data.diplomacy[ch->pcdata->clan][victim->pcdata->clan] < -450 ) )
         return;

      if( ch->act.test(ACT_PKOK ) && victim->act.test(ACT_PKOK ) )
         return;
   }



   /*
    * Charm-o-rama.
    */
/*    if ( IS_SET(ch->affected_by, AFF_CHARM) && ( ch->fighting != victim ) )
    {
	if ( ch->master == NULL )
	{
	    char buf[MAX_STRING_LENGTH];

	    snprintf( buf, MSL, "Check_killer: %s bad AFF_CHARM",
		IS_NPC(ch) ? ch->short_descr : ch->name );
	    bug( buf, 0 );
	    affect_strip( ch, gsn_charm_person );
	    REMOVE_BIT( ch->affected_by, AFF_CHARM );
	    return;
	}
	
	ch=ch->master;  */

   /*
    * stop_follower( ch ); Don't think we need to do this 
    */

   /*
    * }    
    */

   /*
    * if ( IS_SET(victim->affected_by, AFF_CHARM) )
    * {
    * if ( victim->master == NULL)
    * {
    * char buf[MAX_STRING_LENGTH];
    * 
    * snprintf( buf, MSL, "Check_killer: %s bad AFF_CHARM",
    * IS_NPC(ch) ? victim->short_descr : victim->name );
    * bug( buf, 0 );
    * affect_strip( ch, gsn_charm_person );
    * REMOVE_BIT( victim->affected_by, AFF_CHARM );
    * return;
    * }
    * victim=victim->master;
    * }
    * 
    */

   /*
    * NPC's are cool of course (as long as not charmed).
    * Hitting yourself is cool too (bleeding).
    * So is being immortal (Alander's idea).
    * BAH.  Imms get flagged too now, unless pkok.
    * And current killers stay as they are.
    */
   if( IS_NPC( ch ) || ch == victim )
      return;

   send_to_char( "*** You are a PLAYER KILLER!! ***\n\r", ch );

   {
      char buf[MAX_STRING_LENGTH];

      snprintf( buf, MSL, "%s flagged as a KILLER for attack on %s.", ch->name, victim->name );
      monitor_chan( buf, MONITOR_COMBAT );
   }
   diff = 3;
   if( get_psuedo_level( ch ) > get_psuedo_level( victim ) )
   {
      diff += ( get_psuedo_level( ch ) - get_psuedo_level( victim ) ) / 7;
      if( diff > 5 )
         diff = 5;
   }
   ch->sentence += diff * get_psuedo_level( ch ) * 3; /* Magic # - Ramias */
   if( ch->adept_level > 0 )
      ch->sentence += diff * get_psuedo_level( ch ) * 2;

   ch->act.set(ACT_KILLER);
   save_char_obj( ch );


   /*
    * MAG Create a hunter for the person 
    */
   diff = get_psuedo_level( ch );

   /*
    * Added if check back... meant to penalize for attacking lower
    * * level players -S-
    */

   if( get_psuedo_level( ch ) > get_psuedo_level( victim ) )
      diff += get_psuedo_level( ch ) - get_psuedo_level( victim );
/*     
    if (diff > MAX_LEVEL)
     diff=MAX_LEVEL;
                       SRZ just set the level of the hunter to the level of the player :) */

   /*
    * Fixed for loop so it can't become infinite -S- 
    */
   for( a = 0; hunt_mobs[a].min_level != -1; a++ )
   {
      if( diff <= hunt_mobs[a].min_level )
         break;
   }

   if( hunt_mobs[a].mob_vnum == -1 )
   {
      notify( "No killer hunter found in check_killer!", 83 );
      return;
   }

   if( ( pMobIndex = get_mob_index( hunt_mobs[a].mob_vnum ) ) == NULL )
   {
      bug( "check_killer: No such mob %i.", hunt_mobs[a].mob_vnum );
      return;
   }

   if( ( pRoomIndex = get_room_index( hunt_mobs[a].room_vnum ) ) == NULL )
   {
      bug( "check_killer: No such room %i.", hunt_mobs[a].room_vnum );
      return;
   }

   hunter = create_mobile( pMobIndex );
   char_to_room( hunter, pRoomIndex );
   /*
    * do_gossip( hunter, "Well, someone's gonna get it!" ); 
    */
   set_hunt( hunter, NULL, ch, NULL, HUNT_WORLD | HUNT_OPENDOOR | HUNT_PICKDOOR | HUNT_UNLOCKDOOR | HUNT_INFORM,
             HUNT_CR | HUNT_MERC );

   return;
}



/*
 * Check for parry.
 */
bool check_parry( CHAR_DATA * ch, CHAR_DATA * victim )
{
   float chance = 0;

   if( !IS_AWAKE( victim ) )
      return FALSE;

   if( IS_NPC( victim ) && !IS_SET( victim->skills, MOB_PARRY ) )
      return FALSE;

   if( IS_NPC( victim ) )
   {
      /*
       * Tuan was here.  :) 
       */
      chance = get_psuedo_level( victim ) / 3.2 + get_curr_str( victim ) * 2 / 5;
      if( victim->act.test(ACT_SOLO ) )
         chance += 15;
   }
   else
   {
      OBJ_DATA *weapon;
      if( ( weapon = get_eq_char( victim, WEAR_HOLD_HAND_L ) ) == NULL )
         weapon = get_eq_char( victim, WEAR_HOLD_HAND_R );
      if( ( weapon == NULL ) || ( !IS_WEAPON( weapon ) ) )
      {
         return FALSE;
      }
      if( !IS_NPC( victim ) && IS_WOLF( victim ) && ( IS_SHIFTED( victim ) || IS_RAGED( victim ) ) )
         return FALSE;

      chance = ( victim->pcdata->learned[gsn_parry] / 3.5 ) + get_curr_str( victim ) * 3 / 5;
   }
   if( IS_AFFECTED( victim, AFF_CLOAK_ADEPT ) )
      chance += 5;

   if( number_percent(  ) < ( chance + ( get_psuedo_level( victim ) - get_psuedo_level( ch ) ) / 2 ) )
   {

      /*
       * act( "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
       * act( "$N parries your attack.", ch, NULL, victim, TO_CHAR    );  
       */
      return TRUE;
   }
   return FALSE;
}



/*
 * Check for dodge.
 */
bool check_dodge( CHAR_DATA * ch, CHAR_DATA * victim )
{
   float chance = 0;

   if( !IS_AWAKE( victim ) )
      return FALSE;

   if( IS_NPC( victim ) && !IS_SET( victim->skills, MOB_DODGE ) )
      return FALSE;

   if( IS_NPC( victim ) )
   {
      /*
       * Tuan was here.  :) 
       */
      chance = get_psuedo_level( victim ) / 3.1 + get_curr_dex( victim ) * 2 / 5;
      if( victim->act.test(ACT_SOLO ) )
         chance += 15;
   }
   else
   {
      chance = ( victim->pcdata->learned[gsn_dodge] / 3.5 ) + get_curr_dex( victim ) * 3 / 5;
      if( ch->lvl2[4] > 0 )   /* Monk  */
         chance += ch->lvl2[4] / 8;
   }
   if( IS_AFFECTED( victim, AFF_CLOAK_ADEPT ) )
      chance += 5;

   if( !IS_NPC( victim ) && IS_WOLF( victim ) && ( IS_SHIFTED( victim ) || IS_RAGED( victim ) ) )
      chance += 20;


   if( number_percent(  ) < ( chance + ( get_psuedo_level( victim ) - get_psuedo_level( ch ) ) / 2 ) )
   {

      /*
       * act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT    );
       * act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR    );  
       */
      return TRUE;
   }
   return FALSE;
}


/*
 * Check_skills : if IS_NPC(ch) then check ch->skills to see if there are
 * any extra attack skills available for use --Stephen
 */

bool check_skills( CHAR_DATA * ch, CHAR_DATA * victim )
{
   int cnt, check;

   if( !IS_NPC( ch ) )
      return FALSE;

   if( number_percent(  ) < 30 + ( ch->level - victim->level ) )
      return FALSE;

   /*
    * Count how many of the attack skills are available 
    */

   cnt = 0;
   if( IS_SET( ch->skills, MOB_PUNCH ) )
      cnt++;
   if( IS_SET( ch->skills, MOB_HEADBUTT ) )
      cnt++;
   if( IS_SET( ch->skills, MOB_KNEE ) )
      cnt++;
   if( IS_SET( ch->skills, MOB_DIRT ) )
      cnt++;
   if( IS_SET( ch->skills, MOB_CHARGE ) )
      cnt++;

   if( cnt == 0 )
      return FALSE;  /* There were no attack skills set */

   check = number_range( 1, cnt );

   cnt = 0;
   if( IS_SET( ch->skills, MOB_PUNCH ) && ( ++cnt == check ) )
   {
      do_punch( ch, "" );
      return TRUE;
   }
   if( IS_SET( ch->skills, MOB_HEADBUTT ) && ( ++cnt == check ) )
   {
      do_headbutt( ch, "" );
      return TRUE;
   }
   if( IS_SET( ch->skills, MOB_KNEE ) && ( ++cnt == check ) )
   {
      do_knee( ch, "" );
      return TRUE;
   }
   if( IS_SET( ch->skills, MOB_DIRT ) && ( ++cnt == check ) )
   {
      do_dirt( ch, "" );
      return TRUE;
   }
   if( IS_SET( ch->skills, MOB_CHARGE ) && ( ++cnt == check ) )
   {
      do_charge( ch, "" );
      return TRUE;
   }

   return FALSE;
}



/*
 * Set position of a victim.
 */
void update_pos( CHAR_DATA * victim )
{
   char buf[MAX_STRING_LENGTH];
   OBJ_DATA *obj;
   int num, counter;

   if( victim->hit > 0 )
   {
      if( IS_SET( victim->affected_by, AFF_VAMP_HEALING ) )
         REMOVE_BIT( victim->affected_by, AFF_VAMP_HEALING );

      if( victim->position <= POS_STUNNED && victim->stunTimer == 0 )
      {
         act( "$n stands, and gets to $s feet.", victim, NULL, NULL, TO_ROOM );
         victim->position = POS_STANDING;
      }
      return;
   }
   if( IS_VAMP( victim )
       && ( victim->hit < 1 ) && !IS_SET( victim->affected_by, AFF_VAMP_HEALING ) && !IS_NPC( victim ) && !( deathmatch ) )
   {
      CHAR_DATA *check;

      if( !IS_NPC( victim ) )
         gain_exp( victim, 0 - ( victim->exp / 4 ) );

      snprintf( buf, MSL, "%s (vampire) has been misted!", victim->name );
      monitor_chan( buf, MONITOR_COMBAT );

      act( "$n turns to mist and floats away....", victim, NULL, NULL, TO_ROOM );
      act( "You turn to mist and float back to the morgue...", victim, NULL, NULL, TO_CHAR );

/* Universe -  need to add junk here */
      if( IS_VAMP( victim ) && ( ( victim->fighting != NULL ) && !IS_NPC( victim->fighting ) ) )
      {
         counter = number_range( 2, 4 );

         while( counter > 0 )
         {
            num = number_range( 1, UMIN( 1, victim->carry_number ) );
            obj = victim->first_carry;
            if( obj == NULL )
               break;

            for( obj = victim->first_carry; obj != NULL; obj = obj->next_in_carry_list )
            {
               num = num - 1;
               if( num == 0 )
                  break;
            }

            if( obj == NULL )
               continue;

            if( obj != NULL && !IS_OBJ_STAT(obj,ITEM_EXTRA_NO_LOOT) )
            {
               obj_from_char( obj );
               obj_to_room( obj, victim->in_room );
            }
            counter = counter - 1;
         }
      }
      /*
       * drop stuff if is (WANTED) 
       */
      if( ( victim->act.test(ACT_KILLER ) || victim->act.test(ACT_THIEF ) )
          && ( ( victim->fighting != NULL )
               && ( ( !IS_NPC( victim->fighting ) )
                    || ( !str_cmp( rev_spec_lookup( victim->fighting->spec_fun ), "spec_executioner" ) ) ) ) )
      {
         counter = number_range( 2, 3 );

         while( counter > 0 )
         {
            num = number_range( 1, UMIN( 1, victim->carry_number ) );
            obj = victim->first_carry;
            if( obj == NULL )
               break;

            for( obj = victim->first_carry; obj != NULL; obj = obj->next_in_carry_list )
            {
               num = num - 1;
               if( num == 0 )
                  break;
            }

            if( obj == NULL )
               continue;

            if( obj != NULL && !IS_OBJ_STAT(obj,ITEM_EXTRA_NO_LOOT) )
            {
               obj_from_char( obj );
               obj_to_room( obj, victim->in_room );
            }
            counter = counter - 1;
         }
      }

      /*
       * drop stuff if is (WANTED) 
       */
      if( ( victim->fighting != NULL ) && ( !IS_NPC( victim->fighting ) ) && ( IS_WOLF( victim->fighting ) ) )
      {
         counter = number_range( 4, 8 );

         while( counter > 0 )
         {
            num = number_range( 1, UMIN( 1, victim->carry_number ) );
            obj = victim->first_carry;
            if( obj == NULL )
               break;

            for( obj = victim->first_carry; obj != NULL; obj = obj->next_in_carry_list )
            {
               num = num - 1;
               if( num == 0 )
                  break;
            }

            if( obj == NULL )
               continue;

            if( obj != NULL && !IS_OBJ_STAT(obj,ITEM_EXTRA_NO_LOOT) )
            {
               obj_from_char( obj );
               obj_to_room( obj, victim->in_room );
            }
            counter = counter - 1;
         }
      }
      char_from_room( victim );
      char_to_room( victim, get_room_index( victim->pcdata->recall_vnum ) );
      act( "A mist floats in, and forms into $n's corpse!", victim, NULL, NULL, TO_ROOM );

      SET_BIT( victim->affected_by, AFF_VAMP_HEALING );

      stop_fighting( victim, TRUE );
      victim->hit = -20;
      for( check = first_char; check != NULL; check = check->next )
      {
         if( check->hunting == victim )
            end_hunt( check );
      }
      return;
   }

   if( IS_VAMP( victim ) && IS_SET( victim->affected_by, AFF_VAMP_HEALING ) && !( deathmatch ) && !IS_NPC( victim ) )
   {

      /*
       * Then they don't really die... just regen slowly...! 
       */
      if( victim->hit < -20 )
         victim->hit = -20;

      if( victim->hit == -20 )
      {
         act( "$n's body slowly regains it's shape!", victim, NULL, NULL, TO_ROOM );
         send_to_char( "Your body slowly regains it's shape!\n\r", victim );
         victim->hit++;
         victim->position = POS_MORTAL;
      }
      else if( victim->hit > -20 && victim->hit < -15 )
         victim->hit++;
      else if( victim->hit == -15 )
      {
         act( "$n's skin grows back into place!", victim, NULL, NULL, TO_ROOM );
         send_to_char( "Your skin grows back into place!\n\r", victim );
         victim->hit++;
      }
      else if( victim->hit > -15 && victim->hit < -10 )
         victim->hit++;
      else if( victim->hit == -10 )
      {
         act( "$n's wounds form scar tissue and vanish!", victim, NULL, NULL, TO_ROOM );
         send_to_char( "Your wounds form scar tissue and vanish!\n\r", victim );
         victim->hit++;
      }
      else if( victim->hit > -10 && victim->hit < -5 )
         victim->hit++;
      else if( victim->hit == -5 )
      {
         act( "$n's looks like $s old self again.", victim, NULL, NULL, TO_ROOM );
         send_to_char( "Your look like your old self again.\n\r", victim );
         victim->hit++;
      }
      else if( victim->hit > -5 && victim->hit < -1 )
         victim->hit++;
      else
      {
         REMOVE_BIT( victim->affected_by, AFF_VAMP_HEALING );
         victim->position = POS_STUNNED;
         victim->hit = 5;
      }
      return;
   }

   if( ( !IS_NPC( victim ) ) && ( IS_VAMP( victim ) ) && !( deathmatch ) )
      return;

   if( IS_NPC( victim ) && victim->hit <= 0 )
   {
      victim->position = POS_DEAD;
      return;
   }
   if( victim->hit <= -10 )
      victim->position = POS_DEAD;
   else if( victim->hit <= -6 )
      victim->position = POS_MORTAL;
   else if( victim->hit <= -3 )
      victim->position = POS_INCAP;
   else
      victim->position = POS_STUNNED;

   return;
}



/*
 * Start fights.
 */
void set_fighting( CHAR_DATA * ch, CHAR_DATA * victim, bool check )
{
   static FIGHT_DATA *fight;
   FIGHT_DATA *vfight;

   if( ch->fighting != NULL )
   {
      /*
       * bug( "Set_fighting: already fighting", 0 );  
       */
      return;
   }

   /*
    * Check here for killer flag 
    */
   if( check )
      check_killer( ch, victim );


/*    if ( IS_NPC(victim) && is_set(victim->act, ACT_HUNTER ) )
                make_hunt( victim, ch );*//*
    * fun fun FUN! 
    */


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

   ch->fighting = victim;
   ch->position = POS_FIGHTING;

   /*
    * Check if mob has ACT_REMEMBER (ch to attack) SET 
    */

   if( IS_NPC( victim ) && !IS_NPC( ch ) && victim->act.test(ACT_REMEMBER ) )
   {
      /*
       * Then set victim->target to player's name... 
       */
      if( victim->target != NULL )
         free_string( victim->target );
      if( ch != NULL && ch->is_free == FALSE )
         victim->target = str_dup( ch->name );
   }

   /* Keep out duplicates */
   for( vfight = first_fight; vfight != NULL; vfight = vfight->next )
    if( vfight->ch == ch )
     return;
   /*
   snprintf_2(log_buf,"Adding %s vs %s to the fight queue.",ch->name,victim->name);
   monitor_chan(log_buf,MONITOR_DEBUG);
   */
   GET_FREE(fight,fight_free);
   fight->ch = ch;
   LINK(fight,first_fight,last_fight,next,prev);

   return;
}



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

   ch->fighting = NULL;
   ch->position = POS_STANDING;
   update_pos( ch );

   if( !fBoth )
      return;

   CREF( fch_next, CHAR_NEXT );
   for( fch = first_char; fch != NULL; fch = fch_next )
   {
      fch_next = fch->next;
      if( fch->fighting == ch )
      {
         fch->fighting = NULL;
         fch->position = POS_STANDING;
         update_pos( fch );
      }
   }
   CUREF( fch_next );
   return;
}



/*
 * Make a corpse out of a character.
 */
void make_corpse( CHAR_DATA * ch, char *argument )
{
   char buf[MAX_STRING_LENGTH];
   char arg[MAX_INPUT_LENGTH];
   OBJ_DATA *corpse;
   OBJ_DATA *obj;
   OBJ_DATA *obj_next;
   CHAR_DATA *target = NULL;
   CHAR_DATA *wch;
   char *name;
   bool leave_corpse = FALSE;
   /*
    * int counter, num;   
    */

   one_argument( argument, arg );

   if( deathmatch )
      return;

   /*
    * Vampire bodies crumble to dust when really killed 
    */
   if( IS_VAMP( ch ) && !IS_NPC( ch ) )
      return;

   if( IS_NPC( ch ) )
   {
      if( ( ch->in_room != NULL ) && IS_SET( ch->in_room->affected_by, ROOM_BV_SOUL_NET ) )
      {
         ROOM_INDEX_DATA *room;
         ROOM_AFFECT_DATA *raf;
         ROOM_AFFECT_DATA *raf_next;
         corpse = create_object( get_obj_index( OBJ_VNUM_CAPTURED_SOUL ), ch->level );
         corpse->level = ch->level;
         obj_to_room( corpse, ch->in_room );
         OREF( obj_next, OBJ_NEXTCONTENT );
         for( obj = ch->first_carry; obj != NULL; obj = obj_next )
         {
            obj_next = obj->next_in_carry_list;
            obj_from_char( obj );
            extract_obj( obj );
         }
         OUREF( obj_next );
         act( "@@eAs $n's soul attempts to fade from the room, the @@dSoul Net@@e quickly collapses, entombing the soul into a small figurine!!", ch, NULL, NULL, TO_ROOM );
         room = ch->in_room;
         for( raf = room->first_room_affect; raf != NULL; raf = raf_next )
         {
            raf_next = raf->next;
            if( raf->bitvector == ROOM_BV_SOUL_NET )
            {
               r_affect_remove( room, raf );
            }
         }
         return;
      }
      else  /* still NPC, no soul net */
      {
         int gold;
         time_t lifetime;

         name = ch->short_descr;
         corpse = create_object( get_obj_index( OBJ_VNUM_CORPSE_NPC ), 0 );
         corpse->timer = number_range( 3, 6 );
         corpse->level = ch->level; /* for animate spell */
         /*
          * Takes a mob 8 rl hours to gain full gold. 
          */
         lifetime = current_time - ( ch->logon );
         gold = 5 * ( ch->level ) * ( UMIN( 100, lifetime * 100 / ( 8 * 3600 ) ) ) / 100;
         /*
          * Then take from 1/5 of maximum (i.e. level) to maximum gold. 
          */
         gold = number_range( gold / 5, gold );
         /*
          * Add special gold. 
          */
         gold += ch->gold;

         /*
          * Not everybody is rich. --Kline
          */
         if( !race_table[ch->race].has_money )
          gold = 0;

         if( gold > 0 )
         {
            join_money( round_money( gold, TRUE ), corpse->money );
         }
         ch->gold = 0;
      }
   }
   else  /* player */
   {
      name = ch->name;
      corpse = create_object( get_obj_index( OBJ_VNUM_CORPSE_PC ), 0 );
      corpse->timer = number_range( 20, 30 );

      snprintf( buf, MSL, "%s", ch->name );
      free_string( corpse->owner );
      corpse->owner = str_dup( buf );

      if( ( arg[0] != '\0' ) && ( !IS_NPC( ch ) ) )
      {
         target = NULL;
         for( wch = first_char; wch != NULL; wch = wch->next )
         {
            if( !IS_NPC( wch ) && is_name( arg, wch->name ) )
            {
               target = wch;
               break;
            }
         }
         if( ( target != NULL ) && !IS_NPC( target ) )
         {
            if( ( IS_WOLF( ch ) ) && ( IS_VAMP( target ) || IS_WOLF( target ) ) )
            {
               leave_corpse = TRUE;
               corpse->value[0] = 1;
            }
            if( ch->act.test(ACT_PKOK ) )
               corpse->value[0] = 1;
            if( ch->pcdata->clan > 0 )
            {
               if( target->pcdata->clan != ch->pcdata->clan &&
                   ( politics_data.diplomacy[ch->pcdata->clan][target->pcdata->clan] < -450 ) )
               {
                  corpse->value[2] = target->pcdata->clan;
               }
            }
            else
               corpse->value[2] = -1;
            corpse->value[3] = number_range( 2, 5 );
         }
      }
   }  /* end of player only */


   if( ( ch->act.test(ACT_KILLER ) || ch->act.test(ACT_THIEF ) )
       && ( ( target != NULL )
            && ( ( !IS_NPC( target ) ) || ( !str_cmp( rev_spec_lookup( target->spec_fun ), "spec_executioner" ) ) ) ) )

   {
      corpse->value[0] = 1;
      corpse->value[3] = number_range( 3, 6 );
   }
   snprintf( buf, MSL, corpse->short_descr, name );
   free_string( corpse->short_descr );
   corpse->short_descr = str_dup( buf );

   snprintf( buf, MSL, corpse->long_descr, name );
   free_string( corpse->long_descr );
   corpse->long_descr = str_dup( buf );
   OREF( obj_next, OBJ_NEXTCONTENT );
   for( obj = ch->first_carry; obj != NULL; obj = obj_next )
   {
      obj_next = obj->next_in_carry_list;
      obj_from_char( obj );
      if( ( obj == quest_object ) && ( ch == quest_target ) )
      {
         obj->value[0] = UMAX( 1, obj->value[0] * quest_timer / 10 );
         obj->value[1] = UMAX( 1, obj->value[1] * quest_timer / 10 );
         obj->value[2] = UMAX( 1, obj->value[2] * quest_timer / 10 );
      }
      if( IS_OBJ_STAT(obj,ITEM_EXTRA_INVENTORY) )
         extract_obj( obj );
      else
         obj_to_obj( obj, corpse );
   }
   OUREF( obj_next );

   if( !IS_NPC( ch ) )
   {
      if( ( ch->act.test(ACT_PKOK ) )
          || ( target != NULL && ( target->pcdata->clan != ch->pcdata->clan )
               && ( politics_data.diplomacy[ch->pcdata->clan][target->pcdata->clan] < -450 ) )
          || ( ( ch->level > 30 )
               && ( ch->act.test(ACT_KILLER ) || ch->act.test(ACT_THIEF ) ) ) || ( leave_corpse ) )
         obj_to_room( corpse, ch->in_room );
      else
         obj_to_room( corpse, get_room_index( ROOM_VNUM_MORGUE ) );
      {
         CORPSE_DATA *this_corpse;
         GET_FREE( this_corpse, corpse_free );
         this_corpse->next = NULL;
         this_corpse->prev = NULL;
         this_corpse->this_corpse = corpse;
         LINK( this_corpse, first_corpse, last_corpse, next, prev );
      }
      save_corpses(  );
      return;
   }
   else
   {
      if( ch->act.test(ACT_INTELLIGENT ) )
      {
         obj_to_room( corpse, get_room_index( ROOM_VNUM_INT_HEAL ) );
      }
      else
      {
         obj_to_room( corpse, ch->in_room );
      }
      return;
   }

}



/*
 * Improved Death_cry contributed by Diavolo.
 */
void death_cry( CHAR_DATA * ch )
{
   /*
    * FIXME:  *ONLY* PKOK victims get a head loaded. 
    */
   /*
    * Make this give 'cry' message, don't load anything 
    */
   ROOM_INDEX_DATA *was_in_room;
   char *msg;
   int door;



   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;
   if( ( was_in_room == NULL ) || ( was_in_room->vnum == 0 ) )
      return;

   for( door = 0; door < MAX_DIR; door++ )
   {
      EXIT_DATA *pexit;

      if( ( pexit = was_in_room->exit[door] ) != NULL && pexit->to_room != NULL && pexit->to_room != was_in_room )
      {
         ch->in_room = pexit->to_room;
         act( msg, ch, NULL, NULL, TO_ROOM );
      }
   }
   ch->in_room = was_in_room;

   return;
}



void raw_kill( CHAR_DATA * victim, char *argument )
{
   CHAR_DATA *check;
   char arg[MAX_STRING_LENGTH];
   char buf[MAX_STRING_LENGTH];

   one_argument( argument, arg );

   stop_fighting( victim, TRUE );
   mprog_death_trigger( victim );
   if( victim == quest_target )
      quest_target = NULL;
   if( victim == quest_mob )
   {
      snprintf( buf, MSL, "Oh well, I guess the quest is over, since I am about to @@eDIE!!!!!@@N" );
      do_crusade( victim, buf );

      quest_mob = NULL;
   }



   if( ( IS_NPC( victim ) || !IS_VAMP( victim ) ) && ( victim->is_free == FALSE ) && ( victim->in_room != NULL ) )
      make_corpse( victim, arg );

   for( check = first_char; check != NULL; check = check->next )
   {
      if( check->hunting == victim )
         end_hunt( check );
/*        unhunt(check);*/
   }


   if( IS_NPC( victim ) && !victim->act.test(ACT_INTELLIGENT ) )
   {
      victim->pIndexData->killed++;
      kill_table[URANGE( 0, victim->level, MAX_LEVEL - 1 )].killed++;
      extract_char( victim, TRUE );
      return;

   }

   extract_char( victim, FALSE );
   while( victim->first_affect )
      affect_remove( victim, victim->first_affect );
   victim->affected_by = 0;
   victim->armor = 100;
   victim->position = POS_RESTING;
   victim->hit = UMAX( 1, victim->hit );
   victim->mana = UMAX( 1, victim->mana );
   victim->move = UMAX( 1, victim->move );
   save_char_obj( victim );
   if( IS_NPC( victim ) && victim->act.test(ACT_INTELLIGENT ) )
   {

      OBJ_DATA *my_corpse = NULL;

      for( my_corpse = victim->in_room->first_content; my_corpse; my_corpse = my_corpse->next_in_room )
      {
         if( ( my_corpse->item_type == ITEM_CORPSE_NPC )
             /*
              * && ( strstr( victim->short_descr, my_corpse->description ) != NULL ) 
              */  )
         {
            break;
         }
      }
      if( my_corpse == NULL )
      {
         char monbuf[MSL];
         snprintf( monbuf, MSL, "%s is looking for their corpse in room %d, but it's not there",
                  victim->name, victim->in_room->vnum );
         monitor_chan( monbuf, MONITOR_MOB );
      }
      else
      {
         OBJ_DATA *obj;
         victim->is_quitting = FALSE;
         do_stand( victim, "" );
         for( obj = my_corpse->first_content; obj; obj = obj->next_content )
         {
            obj_from_obj( obj );
            obj_to_char( obj, victim );
         }
         do_get( victim, "all from corpse" );
         do_sacrifice( victim, "corpse" );
         do_wear( victim, "all" );
      }
   }
   return;
}



void group_gain( CHAR_DATA * ch, CHAR_DATA * victim )
{
   char buf[MAX_STRING_LENGTH];
   CHAR_DATA *gch;
   CHAR_DATA *lch;
   int members;
   int huggy;  /* To work out exp gained */
   float funky;  /* Hope you LOVE these var names, Mag */
   int base;
   int vamp_exp;


   /*
    * Monsters don't get kill xp's or alignment changes.
    * P-killing doesn't help either.
    * Dying of mortal wounds or poison doesn't give xp to anyone!
    * -S- Mod: INTELLIGENT mobs *can* gain exp.  So there!
    */

   if( ( ( IS_NPC( ch ) )
         && ( ( !ch->act.test(ACT_INTELLIGENT ) )
              && ( ch->rider == NULL ) ) ) || ( !IS_NPC( victim ) ) || ( victim == ch ) )
      return;

   members = 0;
   huggy = 0;

   base = victim->exp;  /* Now share this out... */
   if( victim->act.test(ACT_INTELLIGENT ) )
      base = exp_for_mobile( victim->level, victim );

   for( gch = ch->in_room->first_person; gch != NULL; gch = gch->next_in_room )
   {
      if( is_same_group( gch, ch ) )
      {
         members++;
         huggy += UMAX( get_psuedo_level( gch ), ( get_psuedo_level( ch ) - 25 ) );
      }
   }

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


   /*
    * Bonus for grouping 
    */

   if( members < 2 );   /* Changed from funky */
   else if( members < 3 )
      base *= ( 5 / 2 );   /* funky wasn't initialised */
   else if( members < 4 )
      base *= 3;  /* anyways.. hmm MAG */
   else if( members < 5 )
      base *= ( 7 / 2 );
   else if( members < 6 )
      base *= 4;
   else
      base *= ( 9 / 2 );


   /*
    * Question is, if someone's exp is capped, do you dole out the rest
    * to the other people? or just reduce the total amount given to the
    * group (by not doling it out).
    * As it is, the total exp is reduced. I'll leave it that way.
    * 
    */

   lch = ( ch->leader != NULL ) ? ch->leader : ch;

   for( gch = ch->in_room->first_person; gch != NULL; gch = gch->next_in_room )
   {
      OBJ_DATA *obj;
      OBJ_DATA *obj_next;
      int align;

      if( !is_same_group( gch, ch ) )
         continue;

      /*
       * Calc each char's xp seperately, but mult by ch->lev/tot_group_lev. 
       */

      funky = ( base * get_psuedo_level( gch ) ) / huggy;   /* gch's % of exp gained */

      /*
       * Now the max is just 250K 
       */
      if( funky < 0 )
         funky = 823421;
      funky = UMIN( funky, 1500000 );
      if( ( abs( ( get_psuedo_level( gch ) - get_psuedo_level( victim ) ) ) > 23 )
          || ( get_psuedo_level( gch ) > ( get_psuedo_level( victim ) + 17 ) ) )
      {
         funky = ( funky / 5000 );
         vamp_exp = 0;
      }
      else
         vamp_exp = 1;

      if( gch->adept_level > 0 )
         funky /= 1000;

      /* Support changing exp on the fly. --Kline */
      funky *= sysdata.expmult;

      snprintf( buf, MSL, "You Receive %.0f Experience Points.\n\r", funky );
      send_to_char( buf, gch );
      if( AI_MOB(gch) )
         gch->intell_exp += (int)funky;
      gain_exp( gch, (int)funky );

      if( IS_VAMP( gch ) && !IS_NPC( gch ) )

         gch->pcdata->super->exp += vamp_exp;

      if( !IS_NPC( gch ) && IS_WOLF( gch ) )

         gch->pcdata->super->exp += vamp_exp;

      if( !IS_NPC( gch ) && ( gch->pcdata->learned[gsn_emotion_control] < 73 ) )
      {
         align = gch->alignment - ( victim->alignment * ( 80 - gch->pcdata->learned[gsn_emotion_control] ) / 100 );

         if( align > 500 )
            gch->alignment = UMIN( gch->alignment + ( align - 500 ) / 4, 1000 );
         else if( align < -500 )
            gch->alignment = UMAX( gch->alignment + ( align + 500 ) / 4, -1000 );
         else
            gch->alignment -= gch->alignment / 4;
      }
      for( obj = ch->first_carry; obj != NULL; obj = obj_next )
      {
         obj_next = obj->next_in_carry_list;
         if( obj->wear_loc == WEAR_NONE )
            continue;

         if( ( IS_OBJ_STAT( obj, ITEM_EXTRA_ANTI_EVIL ) && IS_EVIL( ch ) )
             || ( IS_OBJ_STAT( obj, ITEM_EXTRA_ANTI_GOOD ) && IS_GOOD( ch ) )
             || ( IS_OBJ_STAT( obj, ITEM_EXTRA_ANTI_NEUTRAL ) && IS_NEUTRAL( ch ) ) )
         {
            if( !IS_OBJ_STAT( obj, ITEM_EXTRA_NO_DROP ) )
            {
               act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
               act( "$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM );
               obj_from_char( obj );
               obj_to_room( obj, ch->in_room );
            }
            else
            {
               act( "You feel $p slither out of your grasp, and back into your inventory!", ch, obj, NULL, TO_CHAR );
               act( "$p slithers out of $n's hands and back into $s inventory!", ch, obj, NULL, TO_ROOM );
               unequip_char( ch, obj );
            }
            return;
         }
      }
   }


   return;
}

struct dam_table_str
{
   int min_dam;
   const char *col;
   const char *vs;
   const char *vp;
   const char *str;
};
struct dam_table_str dam_table[] = {
   {2900, "@@l", "!!!!VIVESECT!!!!", "!!!!VIVESECTS!!!!", " into a living corpse with"},
   {2400, "@@m", "!!!!OBLITERATE!!!!", "!!!!OBLITERATES!!!!", " into disappearing particles with"},
   {2100, "@@m", "!!!!DEVASTATE!!!!", "!!!!DEVASTATES!!!!", "'s very existence with"},
   {1700, "@@m", "!!!!MUTILATE!!!!", "!!!!MUTILATES!!!!", " with"},
   {1450, "@@e", "****ANNIHILATE****", "****ANNIHILATES****", " into the bloody ground with"},
   {1375, "@@e", "***EVISCERATE***", "***EVISCERATES***", " into lots of small pieces with"},
   {1300, "@@e", "**DEMOLISH**", "**DEMOLISHES**", ", spraying $S guts all over the ground with"},
   {1200, "@@R", "*PULVERISE*", "*PULVERISES*", ", spreading blood and gore over the floor with"},
   {1150, "@@R", "THWACK", "THWACKS", ", leaving $M dazed and reeling with"},
   {1100, "@@R", "annihilate", "annihilates", " with"},
   {900, "@@p", "eviscerate", "eviscerates", " with"},
   {850, "@@p", "demolish", "demolishes", " with"},
   {800, "@@p", "pulverise", "pulverises", " with"},
   {700, "@@y", "thwack", "thwacks", " with"},
   {650, "@@y", "flay", "flays", "'s body mercillesly with"},
   {600, "@@y", "lacerate", "lacerates", " into a map of the mud with"},
   {500, "@@G", "maul", "mauls", " with great vengeance and FURIOUS anger from"},
   {450, "@@G", "tear", "tears", "'s skin into shreds with"},
   {400, "@@r", "rip apart", "rips apart", "'s skull with"},
   {350, "@@r", "remove", "removes", "'s ability to have children from"},
   {300, "@@c", "smash", "smashes", " forcefully with"},
   {250, "@@c", "cause", "causes", " to scream in agony from"},
   {200, "@@c", "laugh at", "laughs at", ", drawing trails of blood with"},
   {100, "@@a", "make", "makes", " wince in pain from"},
   {50, "@@a", "mark", "marks", " with an X from"},
   {28, "@@a", "wound", "wounds", " painfully with"},
   {20, "@@b", "graze", "grazes", " with"},
   {10, "@@b", "bonk", "bonks", " on the head with"},
   {7, "@@b", "scratch", "scratches", " roughly with"},
   {5, "@@b", "nick", "nicks", " gently with"},
   {2, "@@b", " tickle", "tickles", " softly with"},
   {0, "@@g", " fail to hit", "fails to hit", " with"}
};

void dam_message( CHAR_DATA * ch, CHAR_DATA * victim, float dam, int dt )
{
   static char *const attack_table[] = {
      "hit",
      "slice", "stab", "slash", "whip", "claw",
      "blast", "pound", "crush", "grip", "bite",
      "pierce", "suction", "tail whip"
   };

   char buf1[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH], buf3[MAX_STRING_LENGTH];
   const char *vs;   /* Singular */
   const char *vp;   /* Plural   */
   const char *str;  /* Strength */
   const char *attack;
   const char *col;
   char punct;
   int dam_table_num, check_dt;
   bool dead = FALSE;

   if( dam >= victim->hit )
      dead = TRUE;

   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
   {
      dt = TYPE_HIT + 5;   /* claw attack */
   }

   for( dam_table_num = 0; dam_table[dam_table_num].min_dam > dam; dam_table_num++ )
      ;

   col = dam_table[dam_table_num].col;
   vs = dam_table[dam_table_num].vs;
   vp = dam_table[dam_table_num].vp;
   str = dam_table[dam_table_num].str;




   punct = ( dam <= 64 ) ? '.' : '!';

   /*
    * Use combat skills, etc to make unarmed combat more fun :) 
    */

   if( dt == TYPE_MARTIAL )
   {


      col = "@@m";

      switch ( number_range( 0, 13 ) )
      {
         case 0:
            vs = "head punch";
            vp = "head punches";
            break;
         case 1:
            vs = "high kick";
            vp = "high kicks";
            break;
         case 2:
            vs = "vital kick";
            vp = "vital kick";
            break;
         case 3:
            vs = "head bash";
            vp = "head bashes";
            break;
         case 4:
            vs = "side kick";
            vp = "side kicks";
            break;
         case 5:
            vs = "elbow";
            vp = "elbows";
            break;
         case 6:
            vs = "body punch";
            vp = "body punches";
            break;
         case 7:
            vs = "low kick";
            vp = "low kicks";
            break;
         case 8:
            vs = "graze";
            vp = "grazes";
            break;
         case 9:
            vs = "knee smash";
            vp = "knee smashes";
            break;
         case 10:
            vs = "kidney punch";
            vp = "kidney punches";
            break;
         case 11:
            vs = "arm twist";
            vp = "arm twists";
            break;
         case 12:
            vs = "uppercut";
            vp = "uppercuts";
            break;
         case 13:
            vs = "rabbit punch";
            vp = "rabbit punches";
            break;
         default:
            vs = "foot sweep";
            vp = "foot sweeps";
            break;

      }
   }
   else if( dt == TYPE_HIT )
   {
      col = "@@m";
      if( dam == 0 )
      {
         vs = "miss";
         vp = "misses";
      }
      else if( dam <= 50 )
      {
         col = "@@c";
         vs = "tickle";
         vp = "tickles";
      }
      else if( dam <= 125 )
      {
         col = "@@a";
         vs = "glance";
         vp = "glances";
      }
      else if( dam <= 275 )
      {
         col = "@@G";
         vs = "slice";
         vp = "slices";
      }
      else if( dam <= 400 )
      {
         col = "@@r";
         vs = "strike";
         vp = "strikes";
      }
      else if( dam <= 550 )
      {
         col = "@@R";
         vs = "whallop";
         vp = "whallops";
      }
      else if( dam <= 800 )
      {
         col = "@@e";
         vs = "maul";
         vp = "mauls";
      }
      else
      {
         col = "@@2@@W";
         vs = "thwack";
         vp = "thwacks";
      }
      if( sysdata.shownumbers == TRUE )
      {
         snprintf( buf1, MSL, "%s$n %s%s $N%c@@g @@l(@@d%.0f@@l)@@N", col, col, vp, punct, dam );
         snprintf( buf2, MSL, "%sYou %s%s $N%c@@g @@l(@@d%.0f@@l)@@N", col, col, vs, punct, dam );
         snprintf( buf3, MSL, "%s$n %s%s you%c@@g @@l(@@d%.0f@@l)@@N", col, col, vp, punct, dam );
      }
      else
      {
         snprintf( buf1, MSL, "%s$n %s%s $N%c@@g", col, col, vp, punct );
         snprintf( buf2, MSL, "%sYou %s%s $N%c@@g", col, col, vs, punct );
         snprintf( buf3, MSL, "%s$n %s%s you%c@@g", col, col, vp, punct );
      }

   }
   else
   {
      if( dt >= 0 && dt < MAX_SKILL )
         attack = skill_table[dt].noun_damage;
      else if( dt >= TYPE_HIT && dt < TYPE_HIT + (int)sizeof( attack_table ) / (int)sizeof( attack_table[0] ) )
      {
         check_dt = UMAX( 0, ( dt - TYPE_HIT ) );
         check_dt = UMIN( check_dt, 13 );
         attack = attack_table[check_dt];
      }
      else
      {
         bug( "Dam_message: bad dt %d.", dt );
         dt = TYPE_HIT;
         attack = attack_table[0];
      }

      if( sysdata.shownumbers == TRUE )
      {
         if( dt != TYPE_MARTIAL )
         {
            snprintf( buf1, MSL, "%s$n %s%s $N%s%s $s %s%c@@g @@l(@@d%.0f@@l)@@N", col, col, vp, col, str, attack, punct, dam );
            snprintf( buf2, MSL, "%sYou %s%s $N%s%s your %s%c@@g @@l(@@d%.0f@@l)@@N", col, col, vs, col, str, attack, punct, dam );
            if( *str == '\'' )
               snprintf( buf3, MSL, "%s$n %s%s your%s%s $s %s%c@@g @@l(@@d%.0f@@l)@@N", col, col, vp, col, str + 2, attack, punct,
                        dam );
            else
               snprintf( buf3, MSL, "%s$n %s%s you%s%s $s %s%c@@g @@l(@@d%.0f@@l)@@N", col, col, vp, col, str, attack, punct, dam );
         }
         else
         {
            snprintf( buf1, MSL, "$n pulls a karate move on $N!" );
            snprintf( buf2, MSL, "You pull a karate move on $N!" );
            snprintf( buf3, MSL, "$n pulls a karate move on you!" );
         }
      }
      else
      {

         if( dt != TYPE_MARTIAL )
         {
            snprintf( buf1, MSL, "%s$n %s%s $N%s%s $s %s%c@@g", col, col, vp, col, str, attack, punct );
            snprintf( buf2, MSL, "%sYou %s%s $N%s%s your %s%c@@g", col, col, vs, col, str, attack, punct );
            if( *str == '\'' )
               snprintf( buf3, MSL, "%s$n %s%s your%s%s $s %s%c@@g", col, col, vp, col, str + 2, attack, punct );
            else
               snprintf( buf3, MSL, "%s$n %s%s you%s%s $s %s%c@@g", col, col, vp, col, str, attack, punct );
         }
         else
         {
            snprintf( buf1, MSL, "$n pulls a karate move on $N!" );
            snprintf( buf2, MSL, "You pull a karate move on $N!" );
            snprintf( buf3, MSL, "$n pulls a karate move on you!" );
         }

      }
   }
   act( buf1, ch, NULL, victim, TO_NOTVICT );
   if( ch->act.test(ACT_BLIND_PLAYER ) )
   {
      if( dam < victim->max_hit / 30 )
         act( "You glance $K", ch, NULL, victim, TO_CHAR );
      else if( dam < victim->max_hit / 20 )
         act( "You hit $K", ch, NULL, victim, TO_CHAR );
      else if( dam < victim->max_hit / 10 )
         act( "You nail $K", ch, NULL, victim, TO_CHAR );
      else
         act( "You thwack $K", ch, NULL, victim, TO_CHAR );
   }
   else
      act( buf2, ch, NULL, victim, TO_CHAR );
   if( victim->act.test(ACT_BLIND_PLAYER ) )
   {
      if( dam < victim->max_hit / 30 )
         act( "$k glances you", ch, NULL, victim, TO_VICT );
      else if( dam < victim->max_hit / 20 )
         act( "$k hits you", ch, NULL, victim, TO_VICT );
      else if( dam < victim->max_hit / 10 )
         act( "$k nails you", ch, NULL, victim, TO_VICT );
      else
         act( "$k thwacks you", ch, NULL, victim, TO_VICT );
   }
   else
      act( buf3, ch, NULL, victim, TO_VICT );

   if( dead )
   {
      int foo;

      foo = sizeof( attack_table ) / sizeof( attack_table[0] );
      death_message( ch, victim, ( dt - TYPE_HIT ), foo );
   }
   return;
}



/*
 * Disarm a creature.
 * Caller must check for successful attack.
 */
void disarm( CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * obj )
{
   int chance;

   set_fighting( ch, victim, TRUE );
   if( obj == NULL )
   {
      if( ( ( obj = get_eq_char( victim, WEAR_HOLD_HAND_L ) ) == NULL ) || ( obj->item_type != ITEM_WEAPON ) )
         if( ( ( obj = get_eq_char( victim, WEAR_HOLD_HAND_R ) ) == NULL ) || ( obj->item_type != ITEM_WEAPON ) )
         {
            send_to_char( "Your opponent is not wielding a weapon.\n\r", ch );
            return;
         }
   }
   if( IS_OBJ_STAT(obj,ITEM_EXTRA_NO_DISARM) )
      return;

   if( !IS_NPC( victim ) && IS_WOLF( victim ) && ( IS_SHIFTED( victim ) || IS_RAGED( victim ) ) )
      return;


   /*
    * Check to see if victim is warrior, and if they deflect the disarm
    * In part, this idea comes from HiddenWorlds,
    * but it's also pretty common sense really ;)
    * Stephen
    */

   chance = IS_NPC( victim ) ? IS_SET( victim->skills, MOB_NODISARM ) ? 90 : 0 : victim->pcdata->learned[gsn_nodisarm];

   if( number_percent(  ) < chance )
   {
      act( "You dodge $n's disarm attempt!", ch, NULL, victim, TO_VICT );
      act( "You fail to disarm $N!", ch, NULL, victim, TO_CHAR );
      act( "$N dodges $n's disarm attempt!", ch, NULL, victim, TO_NOTVICT );
      return;
   }

   act( "$n DISARMS you!", ch, NULL, victim, TO_VICT );
   act( "You disarm $N!", ch, NULL, victim, TO_CHAR );
   act( "$n DISARMS $N!", ch, NULL, victim, TO_NOTVICT );

   obj_from_char( obj );
   /*
    * if ( IS_NPC(victim) )
    * obj_to_char( obj, victim );
    * else 
    */

   obj_to_room( obj, victim->in_room );

   return;
}



/*
 * Trip a creature.
 * Caller must check for successful attack.
 */
void trip( CHAR_DATA * ch, CHAR_DATA * victim )
{
   if( victim->wait == 0 )
   {
      int chance;

      chance = IS_NPC( victim ) ? IS_SET( victim->skills, MOB_NOTRIP ) ? 75 : 0 : victim->pcdata->learned[gsn_notrip];

      /*
       * Check for no-trip 
       */
      if( number_percent(  ) < chance )
      {
         act( "You sidestep $n's attempt to trip you!", ch, NULL, victim, TO_VICT );
         act( "$N sidesteps your attempt to trip $M!", ch, NULL, victim, TO_CHAR );
         act( "$N sidesteps $n's attempt to trip $m!", ch, NULL, victim, TO_NOTVICT );
         return;
      }

      act( "$n trips you and you go down!", ch, NULL, victim, TO_VICT );
      act( "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR );
      act( "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT );

      WAIT_STATE( ch, 100 );
      WAIT_STATE( victim, 300 );
      victim->position = POS_RESTING;
   }

   return;
}



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

   one_argument( argument, arg );

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

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

   if( !IS_NPC( victim ) && !( deathmatch ) )
   {
      if( !victim->act.test(ACT_KILLER ) && !victim->act.test(ACT_THIEF ) )
      {
         send_to_char( "You must MURDER a player.\n\r", ch );
         return;
      }
   }
   else
   {
      if( IS_AFFECTED( victim, AFF_CHARM ) && victim->master != NULL )
      {
         send_to_char( "You must MURDER a charmed creature.\n\r", ch );
         return;
      }
   }

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

   if( is_safe( ch, victim ) )
      return;

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

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

   WAIT_STATE( ch, 150 );
   check_killer( ch, victim );
   one_hit( ch, victim, TYPE_UNDEFINED );
   return;
}

void do_target( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   if( ( !IS_NPC( ch ) ) && ( ch->pcdata->learned[gsn_target] < 65 ) )
   {
      send_to_char( "You are not trained enough in this skill!!\n\r", ch );
      return;
   }
   one_argument( argument, arg );

   if( arg[0] == '\0' )
   {
      send_to_char( "Target 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 ) && !( deathmatch ) )
   {
      if( !victim->act.test(ACT_KILLER ) && !victim->act.test(ACT_THIEF ) )
      {
         send_to_char( "You must MURDER a player.\n\r", ch );
         return;
      }
   }
   else
   {
      if( IS_AFFECTED( victim, AFF_CHARM ) && victim->master != NULL )
      {
         send_to_char( "You must MURDER a charmed creature.\n\r", ch );
         return;
      }
   }

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

   if( is_safe( ch, victim ) )
      return;

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

   if( ch->position == POS_FIGHTING )
   {
      send_to_char( "@@rTracking, tracking, tracking...@@eGOT HIM!!!@@N\n\r", ch );
      stop_fighting( ch, FALSE );
   }

   WAIT_STATE( ch, 150 );
   check_killer( ch, victim );
   one_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 arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;

   one_argument( argument, arg );

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

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

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

   if( is_safe( ch, victim ) )
   {
      send_to_char( "Not here.\n\r", ch );
      return;
   }

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

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

   WAIT_STATE( ch, 150 );
   snprintf( log_buf, (2 * MIL), "%s attacked by %s.\n\r", victim->name, ch->name );
   notify( log_buf, MAX_LEVEL - 2 );

   if( IS_NPC( ch ) || IS_NPC( victim )
       || !ch->act.test(ACT_PKOK ) || !victim->act.test(ACT_PKOK ) )
   {
      /*
       * If not pkok people, do yell. 
       */
      do_yell( victim, "Help! I'M BEING ATTACKED!!! ARRRGGGHHHHHH!" );
   }
   check_killer( ch, victim );
   one_hit( ch, victim, TYPE_UNDEFINED );
   return;
}



void do_backstab( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   OBJ_DATA *obj;
   int cnt;
   int best;
   int level;
   int mult;
   int chance;
   float dam;
   bool crack = FALSE;


    /******************************************************************
     * Modified:  'damage' may now be called with sn = -1, in order to *
     * stop damage message being displayed.  Handle ALL the related    *
     * calculations here, including how many hits.  Check for critical *
     * hits too, as well as things like invis and sneak.               * 
      ******************************************************************/

   best = -1;
   level = 0;

   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
   {
      send_to_char( "You cannot do that while in this form.\n\r", ch );
      return;
   }

   if( !IS_NPC( ch ) )
   {
      for( cnt = 0; cnt < MAX_CLASS; cnt++ )
         if( ch->lvl[cnt] >= skill_table[gsn_backstab].skill_level[cnt] && ch->lvl[cnt] > level )
         {
            best = cnt;
            level = ch->lvl[cnt];
         }
      if( ch->lvl2[1] > 0 )
         level = level + ch->lvl2[1] / 2;
   }
   else
   {
      best = ch->p_class;
      level = ch->level;
   }

   if( best == -1 )
   {
      send_to_char( "You better leave the assassin trade to thieves.\n\r", ch );
      return;
   }

   one_argument( argument, arg );

   if( arg[0] == '\0' )
   {
      send_to_char( "Backstab 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 == NULL ) || ( victim->is_free != FALSE ) )
      return;
   if( IS_NPC( victim ) && victim->act.test(ACT_NO_BODY ) )
   {
      act( "$N has no body to backstab!", ch, NULL, victim, TO_CHAR );
      return;
   }

   if( victim == ch )
   {
      send_to_char( "How can you sneak up on yourself?\n\r", ch );
      return;
   }

   if( is_safe( ch, victim ) )
      return;

   if( ( obj = get_eq_char( ch, WEAR_HOLD_HAND_L ) ) == NULL || obj->value[3] != 11 )
      if( ( obj = get_eq_char( ch, WEAR_HOLD_HAND_R ) ) == NULL || obj->value[3] != 11 )
      {
         send_to_char( "You need to wield a piercing weapon.\n\r", ch );
         return;
      }

   if( victim->fighting != NULL )
   {
      send_to_char( "You can't backstab a fighting person.\n\r", ch );
      return;
   }

   chance = ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_backstab] / 2 );

   /*
    * Handle Modifiers -- chance will affect thac, etc
    */

   if( !IS_AWAKE( victim ) )
      chance += 75;

   if( IS_AFFECTED( victim, AFF_SNEAK ) || item_has_apply( victim, ITEM_APPLY_SNEAK ) )
      chance -= 10;

   if( IS_AFFECTED( ch, AFF_SNEAK ) || item_has_apply( ch, ITEM_APPLY_SNEAK ) )
      chance += 20;

   if( IS_AFFECTED( ch, AFF_INVISIBLE ) || item_has_apply( ch, ITEM_APPLY_INV ) )
      chance += ( IS_AFFECTED( victim, AFF_DETECT_INVIS ) ? -20 : 20 );

   if( IS_AFFECTED( victim, AFF_INVISIBLE ) || item_has_apply( victim, ITEM_APPLY_INV ) )
      chance -= 10;

   if( get_psuedo_level( ch ) >= get_psuedo_level( victim ) )
      chance += 10;
   else
      chance -= 10;

   /*
    * Work out multiplier 
    */
   mult = 1 + ( level >= 20 ) + ( level >= 50 ) + ( level >= 90 ) + ( level >= 120 );

   /*
    * Work out damage 
    */
   dam = number_range( obj->value[1], obj->value[2] );
   dam += number_range( level / 2, level * 2 ) + GET_DAMROLL( ch ) / 2;
   dam *= mult;
   check_killer( ch, victim );
   if( chance < number_percent(  ) )
   {
      /*
       * Miss 
       */
      act( "$n tries to backstab $N, but misses!", ch, NULL, victim, TO_NOTVICT );
      act( "You try to backstab $N, but miss!", ch, NULL, victim, TO_CHAR );
      act( "$N tries to backstab you, but misses!", victim, NULL, ch, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   else
   {
     /*
      * HIT!
      */

      if( !IS_NPC( ch ) && ch->pcdata->order[0] == 2 && number_percent( ) == chance )
      {
       crack = TRUE;
       dam *= 2;
      }

      dam = combat_damcap(ch,victim,dam,gsn_backstab);

      if( sysdata.shownumbers == TRUE )
      {
         char actbuf[MSL];
         snprintf( actbuf, MSL, "$n places $p into the back of $N!! @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, ch, obj, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "You place $p into the back of $N!! @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, ch, obj, victim, TO_CHAR );
         snprintf( actbuf, MSL, "$N places $p into your back!! @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, victim, obj, ch, TO_CHAR );
      }
      else
      {
         act( "$n places $p into the back of $N!!", ch, obj, victim, TO_NOTVICT );
         act( "You place $p into the back of $N!!", ch, obj, victim, TO_CHAR );
         act( "$N places $p into your back.  OUCH!", victim, obj, ch, TO_CHAR );
      }
      if( crack )
         send_to_room( "You hear a large CRACK!\n\r", ch->in_room );

      damage( ch, victim, dam, gsn_backstab );
   }

   WAIT_STATE( ch, skill_table[gsn_backstab].beats );
   return;
}



void do_flee( CHAR_DATA * ch, char *argument )
{
   ROOM_INDEX_DATA *was_in;
   ROOM_INDEX_DATA *now_in;
   CHAR_DATA *victim;
   char buf[MAX_STRING_LENGTH];
   int attempt;
   int cost;   /* xp cost for a flee */

   if( ( victim = ch->fighting ) == NULL )
   {
      if( ch->position == POS_FIGHTING )
         ch->position = POS_STANDING;
      send_to_char( "You aren't fighting anyone.\n\r", ch );
      return;
   }

   /*
    * Check if mob will "allow" ch to flee... 
    */

   if( victim->act.test(ACT_NO_FLEE ) && !IS_NPC( ch ) && IS_NPC( victim ) )
   {
      send_to_char( "You attempt to flee from battle, but fail!\n\r", ch );
      snprintf( buf, MSL, "%s tells you 'No way will you escape ME!!'\n\r", victim->short_descr );
      send_to_char( buf, ch );
      return;
   }
   if( deathmatch )
   {
      if( ch->hit < 200 )
      {
         send_to_char( "@@eYou are in too much pain!!@@N\n\r", ch );
         return;
      }
      else
      {
         send_to_char( "@@eYour enemy nails you one more time!@@N\n\r", ch );
         ch->hit -= 150;
      }
   }

   was_in = ch->in_room;
   for( attempt = 0; attempt < 6; attempt++ )
   {
      EXIT_DATA *pexit;
      int door;

      door = number_door(  );
      if( ( pexit = was_in->exit[door] ) == 0
          || pexit->to_room == NULL
          || pexit->exit_info.test(EX_CLOSED)
          || ( IS_NPC( ch )
               && ( pexit->to_room->room_flags.test(RFLAG_NO_MOB)
                    || ( ch->act.test(ACT_STAY_AREA ) && pexit->to_room->area != ch->in_room->area ) ) ) )
         continue;

      move_char( ch, door, TRUE );
      if( ( now_in = ch->in_room ) == was_in )
         continue;

      ch->in_room = was_in;
      act( "$n has fled!", ch, NULL, NULL, TO_ROOM );
      ch->in_room = now_in;

      if( !IS_NPC( ch ) )
      {
         cost = number_range( ch->exp / 15, ch->exp / 10 );
         if( ch->adept_level > 0 )
            cost /= 1000;
         cost = UMIN( cost, ch->exp );
         snprintf( buf, MSL, "You flee from combat!  You lose %d exps.\n\r", cost );
         send_to_char( buf, ch );
         gain_exp( ch, ( 0 - cost ) );
      }
      if( ( ch->fighting != NULL ) && ( AI_MOB( ch->fighting ) ) )
      {
         ch->fighting->ngroup->state = GRP_STATE_HUNTING;
         ch->fighting->ngroup->leader->hunting = ch;
      }
      stop_fighting( ch, TRUE );
      /*
       * 75% chance that mobs will hunt fleeing people. -- Alty 
       */
      if( IS_NPC( victim ) && !victim->act.test(ACT_SENTINEL ) && number_bits( 2 ) > 0 )
         set_hunt( victim, NULL, ch, NULL, HUNT_WORLD | HUNT_INFORM | HUNT_OPENDOOR, HUNT_MERC | HUNT_CR );
      return;
   }

   cost = get_psuedo_level( ch ) * 3;
   if( ch->adept_level > 0 )
      cost = 0;
   cost = UMIN( cost, ch->exp );
   snprintf( buf, MSL, "You failed!  You lose %d exps.\n\r", cost );
   send_to_char( buf, ch );
   gain_exp( ch, ( 0 - cost ) );
   return;
}


void do_rescue( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   CHAR_DATA *fch;
   int best;
   int cnt;

   best = -1;

   if( !IS_NPC( ch ) )
   {
      for( cnt = 0; cnt < MAX_CLASS; cnt++ )
         if( ch->lvl[cnt] >= skill_table[gsn_rescue].skill_level[cnt] && ch->lvl[cnt] >= best )
            best = cnt;
   }
   else
      best = ch->level;

   if( best == -1 )
   {
      send_to_char( "You don't know how to rescue!!\n\r", ch );
      return;
   }

   one_argument( argument, arg );

   if( arg[0] == '\0' )
   {
      send_to_char( "Rescue 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( "What about fleeing instead?\n\r", ch );
      return;
   }

   if( !IS_NPC( ch ) && IS_NPC( victim ) )
   {
      send_to_char( "Doesn't need your help!\n\r", ch );
      return;
   }

   if( ch->fighting == victim )
   {
      send_to_char( "Too late.\n\r", ch );
      return;
   }

   if( ( fch = victim->fighting ) == NULL )
   {
      send_to_char( "That person is not fighting right now.\n\r", ch );
      return;
   }

   WAIT_STATE( ch, skill_table[gsn_rescue].beats );
   if( !IS_NPC( ch ) && number_percent(  ) > ch->pcdata->learned[gsn_rescue] )
   {
      send_to_char( "You fail the rescue.\n\r", ch );
      return;
   }

   act( "You rescue $N!", ch, NULL, victim, TO_CHAR );
   act( "$n rescues you!", ch, NULL, victim, TO_VICT );
   act( "$n rescues $N!", ch, NULL, victim, TO_NOTVICT );

   stop_fighting( fch, FALSE );
   stop_fighting( victim, FALSE );

   set_fighting( ch, fch, TRUE );
   set_fighting( fch, ch, FALSE );
   return;
}


void do_disarm( CHAR_DATA * ch, char *argument )
{
   CHAR_DATA *victim;
   OBJ_DATA *obj;
   int percent;
   int best;
   int cnt;

   best = -1;

   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
   {
      send_to_char( "You cannot do that while in this form.\n\r", ch );
      return;
   }


   if( !IS_NPC( ch ) )
   {
      for( cnt = 0; cnt < MAX_CLASS; cnt++ )
         if( ch->lvl[cnt] >= skill_table[gsn_disarm].skill_level[cnt] && ch->lvl[cnt] >= best )
            best = cnt;
   }
   else
      best = ch->level;

   if( best == -1 )
   {
      send_to_char( "You don't know how to disarm!\n\r", ch );
      return;
   }

   if( ( !IS_WEAPON( get_eq_char( ch, WEAR_HOLD_HAND_L ) ) ) && ( !IS_WEAPON( get_eq_char( ch, WEAR_HOLD_HAND_R ) ) ) )
   {
      send_to_char( "You must wield a weapon to disarm.\n\r", ch );
      return;
   }

   if( ( victim = ch->fighting ) == NULL )
   {
      send_to_char( "You aren't fighting anyone.\n\r", ch );
      return;
   }
   if( !IS_NPC( victim ) && IS_WOLF( victim ) && ( IS_SHIFTED( victim ) || IS_RAGED( victim ) ) )
   {
      send_to_char( "Try slicing off their claws instead!\n\r", ch );
      return;
   }

   if( ( ( obj = get_eq_char( victim, WEAR_HOLD_HAND_L ) ) == NULL ) || ( obj->item_type != ITEM_WEAPON ) )
      if( ( ( obj = get_eq_char( victim, WEAR_HOLD_HAND_R ) ) == NULL ) || ( obj->item_type != ITEM_WEAPON ) )
      {
         send_to_char( "Your opponent is not wielding a weapon.\n\r", ch );
         return;
      }
   if( IS_OBJ_STAT(obj,ITEM_EXTRA_NO_DISARM) )
      return;


   WAIT_STATE( ch, skill_table[gsn_disarm].beats );
   percent = number_percent(  ) + victim->level - ch->level;
   if( IS_NPC( ch ) || percent < ch->pcdata->learned[gsn_disarm] * 2 / 3 )
      disarm( ch, victim, obj );
   else
      send_to_char( "You failed.\n\r", ch );
   return;
}

void do_circle( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   OBJ_DATA *obj;
   int cnt;
   int best;
   int level;
   int mult;
   float chance;
   float dam;
   bool crack = FALSE;


   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
   {
      send_to_char( "You cannot do that while in this form.\n\r", ch );
      return;
   }


    /******************************************************************
     * Modified:  'damage' may now be called with sn = -1, in order to *
     * stop damage message being displayed.  Handle ALL the related    *
     * calculations here, including how many hits.  Check for critical *
     * hits too, as well as things like invis and sneak.               * 
      ******************************************************************/

   best = -1;
   level = 0;


   if( !IS_NPC( ch ) )
   {
      for( cnt = 0; cnt < MAX_CLASS; cnt++ )
         if( ch->lvl[cnt] >= skill_table[gsn_circle].skill_level[cnt] && ch->lvl[cnt] > level )
         {
            best = cnt;
            level = ch->lvl[cnt];
         }
      if( ch->lvl2[1] > 0 )
         level += ch->lvl2[1] / 2;
   }
   else
   {
      best = ch->p_class;
      level = ch->level;
   }

   if( best == -1 )
   {
      send_to_char( "You better leave the assassin trade to thieves.\n\r", ch );
      return;
   }

   one_argument( argument, arg );

   if( arg[0] == '\0' )
   {
      send_to_char( "Backstab 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 == NULL ) || ( victim->is_free != FALSE ) )
      return;

   if( IS_NPC( victim ) && victim->act.test(ACT_NO_BODY ) )
   {
      act( "$N has no body to backstab!", ch, NULL, victim, TO_CHAR );
      return;
   }

   if( victim == ch )
   {
      send_to_char( "How can you sneak up on yourself?\n\r", ch );
      return;
   }

   if( is_safe( ch, victim ) )
      return;

   if( ( obj = get_eq_char( ch, WEAR_HOLD_HAND_L ) ) == NULL || obj->value[3] != 11 )
      if( ( obj = get_eq_char( ch, WEAR_HOLD_HAND_R ) ) == NULL || obj->value[3] != 11 )
      {
         send_to_char( "You need to wield a piercing weapon.\n\r", ch );
         return;
      }

   if( victim->fighting == NULL )
   {
      send_to_char( "You're victim must be fighting!\n\r", ch );
      return;
   }

   chance = ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_circle] / 4.5 );

   /*
    * Handle Modifiers -- chance will affect thac, etc
    */

   if( !IS_AWAKE( victim ) )
      chance += 75;

   if( IS_AFFECTED( victim, AFF_SNEAK ) || item_has_apply( victim, ITEM_APPLY_SNEAK ) )
      chance -= 10;

   if( IS_AFFECTED( ch, AFF_SNEAK ) || item_has_apply( ch, ITEM_APPLY_SNEAK ) )
      chance += 10;

   if( IS_AFFECTED( ch, AFF_INVISIBLE ) || item_has_apply( ch, ITEM_APPLY_INV ) )
      chance += ( IS_AFFECTED( victim, AFF_DETECT_INVIS ) ? -20 : 20 );

   if( IS_AFFECTED( victim, AFF_INVISIBLE ) || item_has_apply( victim, ITEM_APPLY_INV ) )
      chance -= 10;

   if( get_psuedo_level( ch ) >= get_psuedo_level( victim ) )
      chance += 10;
   else
      chance -= 10;

   /*
    * Work out multiplier 
    */
   mult = 1 + ( level >= 20 ) + ( level >= 50 ) + ( level >= 90 ) + ( level >= 120 );

   /*
    * Work out damage 
    */
   dam = number_range( obj->value[1], obj->value[2] );
   dam += number_range( level / 2, level * 2 ) + GET_DAMROLL( ch ) / 2;
   dam *= mult;
   if( victim != ch->fighting )
      check_killer( ch, victim );
   if( chance < number_percent(  ) )
   {
      /*
       * Miss 
       */
      act( "$n tries to backstab $N, but misses!", ch, NULL, victim, TO_NOTVICT );
      act( "You try to backstab $N, but miss!", ch, NULL, victim, TO_CHAR );
      act( "$N tries to backstab you, but misses!", victim, NULL, ch, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   else
   {
      /*
       * HIT! 
       */

      if( !IS_NPC( ch ) && ch->pcdata->order[0] == 2 && number_percent(  ) == chance )
      {
       crack = TRUE;
       dam *= 2;
      }

      dam = combat_damcap(ch,victim,dam,gsn_circle);

      if( sysdata.shownumbers == TRUE )
      {
         char actbuf[MSL];
         snprintf( actbuf, MSL, "$n places $p into the back of $N!! @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, ch, obj, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "You place $p into the back of $N!! @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, ch, obj, victim, TO_CHAR );
         snprintf( actbuf, MSL, "$N places $p into your back!! @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, victim, obj, ch, TO_CHAR );
      }
      else
      {
         act( "$n places $p into the back of $N!!", ch, obj, victim, TO_NOTVICT );
         act( "You place $p into the back of $N!!", ch, obj, victim, TO_CHAR );
         act( "$N places $p into your back.  OUCH!", victim, obj, ch, TO_CHAR );
      }

      if( crack )
         send_to_room( "You hear a large CRACK!\n\r", ch->in_room );

      damage( ch, victim, dam, gsn_circle );
   }

   WAIT_STATE( ch, skill_table[gsn_circle].beats );
   return;
}



void do_trip( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   int best;
/*    int cnt;  */

   best = -1;

   if( !IS_NPC( ch ) )
   {
      /*
       * for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
       * if ( ch->lvl[cnt] >= skill_table[gsn_trip].skill_level[cnt] 
       * && ch->lvl[cnt] >= best )
       * best = cnt;  
       */
      if( ch->pcdata->learned[gsn_trip] > 75 )
         best = UMAX( 79, get_psuedo_level( ch ) );
   }
   else
      best = ch->level;

   if( best == -1 )
   {
      send_to_char( "You don't know of such a skill.\n\r", ch );
      return;
   }

   one_argument( argument, arg );

   if( arg[0] == '\0' )
   {
      send_to_char( "Trip 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( "That wouldn't even be funny.\n\r", ch );
      return;
   }

   if( is_safe( ch, victim ) )
      return;

   if( victim->fighting == NULL )
   {
      send_to_char( "You can't trip someone who isn't fighting.\n\r", ch );
      return;
   }

   check_killer( ch, victim );

   if( number_percent(  ) < ( IS_NPC( ch ) ? 50 : 2 * ch->pcdata->learned[gsn_trip] ) )
   {
      check_killer( ch, victim );
      trip( ch, victim );
      WAIT_STATE( ch, skill_table[gsn_trip].beats );

   }

   return;
}

void do_dirt( CHAR_DATA * ch, char *argument )
{

   AFFECT_DATA af;
   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   int best;
   /*
    * int cnt;   
    */

   best = -1;

   if( !IS_NPC( ch ) )
   {
      /*
       * for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
       * if ( ch->lvl[cnt] >= skill_table[gsn_dirt].skill_level[cnt] 
       * && ch->lvl[cnt] >= best )
       * best = cnt;  
       */
      if( ch->pcdata->learned[gsn_dirt] > 75 )
         best = UMAX( 79, get_psuedo_level( ch ) );
   }
   else
      best = ch->level;

   if( best == -1 )
   {
      send_to_char( "You don't know of such a skill.\n\r", ch );
      return;
   }

   one_argument( argument, arg );

   if( arg[0] == '\0' && ch->fighting == NULL )
   {
      send_to_char( "Kick dirt at whom?\n\r", ch );
      return;
   }

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

   if( victim == NULL )
      victim = ch->fighting;

   if( victim == ch )
   {
      send_to_char( "That wouldn't be too smart, would it??.\n\r", ch );
      return;
   }

   if( is_safe( ch, victim ) )
      return;

   if( victim->fighting == NULL )
   {
      send_to_char( "Try doing this to them, when fighting...\n\r", ch );
      return;
   }

   if( IS_AFFECTED( victim, AFF_BLIND ) )
      return;

   WAIT_STATE( ch, skill_table[gsn_dirt].beats );

   if( number_percent(  ) > ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_dirt] ) )
   {
      act( "You kick dirt at $M but miss!", ch, NULL, victim, TO_CHAR );
      act( "$n kicks dirt at you but misses!", ch, NULL, victim, TO_VICT );
      act( "$n kicks dirt at $N but misses!", ch, NULL, victim, TO_NOTVICT );
      return;
   }
   else
   {
      act( "You kick dirt at $S eyes!", ch, NULL, victim, TO_CHAR );
      act( "$n kicks dirt in your eyes!", ch, NULL, victim, TO_VICT );
      act( "$n kicks dirt at $N's eyes!", ch, NULL, victim, TO_NOTVICT );

      af.type = skill_lookup( "blindness" );
      af.location = APPLY_HITROLL;
      af.modifier = -2;
      af.duration = 1;
      af.bitvector = AFF_BLIND;
      affect_to_char( victim, &af );
   }
   return;
}

void do_bash( CHAR_DATA * ch, char *argument )
{

   char arg[MAX_INPUT_LENGTH];
   CHAR_DATA *victim;
   int best;
/*    int cnt;  */

   best = -1;

   if( !IS_NPC( ch ) )
   {
      /*
       * for ( cnt = 0; cnt < MAX_CLASS; cnt++ )
       * if ( ch->lvl[cnt] >= skill_table[gsn_dirt].skill_level[cnt] 
       * && ch->lvl[cnt] >= best )
       * best = cnt;  
       */
      if( ch->pcdata->learned[gsn_bash] > 75 )
         best = UMAX( 79, get_psuedo_level( ch ) );
   }
   else
      best = ch->level;

   if( best == -1 )
   {
      send_to_char( "You don't know of such a skill.\n\r", ch );
      return;
   }

   one_argument( argument, arg );

   if( arg[0] == '\0' )
   {
      send_to_char( "Bash 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( "Forget it!\n\r", ch );
      return;
   }

   if( is_safe( ch, victim ) )
      return;

   if( victim->fighting == NULL )
   {
      send_to_char( "It might help if you were fighting.....\n\r", ch );
      return;
   }

   WAIT_STATE( ch, skill_table[gsn_bash].beats );

   if( ( IS_NPC( ch ) && ( number_percent(  ) > 75 + ( ch->level ) / 2 ) )
       || ( !IS_NPC( ch ) && ( 2 * number_percent(  ) > ch->pcdata->learned[gsn_bash] ) ) )
   {
      act( "Your bash misses $M, and you fall!", ch, NULL, victim, TO_CHAR );
      act( "$n trys to bash you, misses, and falls!", ch, NULL, victim, TO_VICT );
      act( "$n trys to bash $N but misses, and falls!", ch, NULL, victim, TO_NOTVICT );
      return;
   }
   else
   {
      act( "Your bash sends $M flying!", ch, NULL, victim, TO_CHAR );
      act( "$n bashes you, sending you flying!", ch, NULL, victim, TO_VICT );
      act( "$n's bash sends $N's flying!", ch, NULL, victim, TO_NOTVICT );

      /*
       * If victim very weak, set pos to stunned, stop fighting 
       */
      if( victim->hit < ( victim->max_hit / 50 ) + 1 )
      {
         act( "$N stays on the floor.", ch, NULL, victim, TO_CHAR );
         act( "You are unable to get up.", ch, NULL, victim, TO_VICT );
         act( "$N stays on the floor.", ch, NULL, victim, TO_NOTVICT );
         stop_fighting( victim, TRUE );   /* MAG: might del this? -S- */
         victim->position = POS_RESTING;
         update_pos( victim );
      }
      else
      {
         /*
          * Do some damage instead... 
          */
         damage( ch, victim, ( best + 12 ) * 2, -1 );
      }

   }

   return;

}


void do_berserk( CHAR_DATA * ch, char *argument )
{
   AFFECT_DATA af;
   int best;
   int level;

   bool prime;

   prime = FALSE;
   best = -1;


   if( IS_NPC( ch ) )
      return;

   if( ch->pcdata->order[0] == 2 )
      prime = TRUE;

   level = ch->lvl[2];


   if( ch->fighting == NULL )
   {
      send_to_char( "You can only go berserk when fighting!\n\r", ch );
      return;
   }

   if( is_affected( ch, gsn_berserk ) )
   {
      send_to_char( "You are already berserk!!\n\r", ch );
      return;
   }

   if( ch->pcdata->learned[gsn_berserk] == 0 )
   {
      send_to_char( "You don't know how to use this skill!\n\r", ch );
      return;
   }



   WAIT_STATE( ch, skill_table[gsn_berserk].beats );


   if( number_percent(  ) < ( ch->pcdata->learned[gsn_berserk] / 2 ) )
   {
      /*
       * Failure 
       */
      act( "$n calls on the Dark Powers, but they don't answer!", ch, NULL, NULL, TO_ROOM );
      send_to_char( "You call on the Dark Powers.  They don't answer!", ch );
      return;
   }



   af.type = gsn_berserk;
   af.duration = ( best == 2 ) ? 4 : 2;
   af.location = APPLY_AC;
   af.modifier = ( best == 2 ) ? level : ( level * 2 );
   af.bitvector = 0;
   affect_to_char( ch, &af );

   af.location = APPLY_HITROLL;
   af.modifier = ( prime )
      ? ( 10 + ( level >= 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 80 ) )
      : ( 5 + ( level >= 25 ) + ( level >= 50 ) );
   affect_to_char( ch, &af );

   af.location = APPLY_DAMROLL;
   af.modifier = ( prime )
      ? ( 12 + ( level >= 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 80 ) )
      : ( 2 + ( level >= 25 ) + ( level >= 50 ) );
   affect_to_char( ch, &af );


   af.location = APPLY_SAVING_SPELL;
   af.modifier = ( prime )
      ? ( 10 - ( level >= 20 ) - ( level >= 40 ) - ( level >= 60 ) - ( level >= 80 ) )
      : ( 20 - ( level >= 25 ) - ( level >= 50 ) );
   affect_to_char( ch, &af );

   act( "$n calls on the Dark Powers, who answer!!!", ch, NULL, NULL, TO_ROOM );
   send_to_char( "You call on the Dark Powers.  They answer!!!\n\r", ch );
   return;
}

void do_punch( CHAR_DATA * ch, char *argument )
{

   CHAR_DATA *victim;
   int dam;
   bool prime;
   int chance;

   prime = FALSE;


   if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_punch] == 0 )
   {
      send_to_char( "You are not trained in this skill!\n\r", ch );
      return;
   }



   if( ( ( victim = get_char_room( ch, argument ) ) == NULL ) && ch->fighting == NULL )
   {
      send_to_char( "No such victim!\n\r", ch );
      return;
   }


   if( victim == NULL )
      victim = ch->fighting;

   if( !IS_NPC( ch ) && ch->pcdata->order[0] == 3 )
      prime = TRUE;

   if( IS_NPC( ch ) )
      dam = number_range( ch->level / 3, ch->level / 2 );
   else
      dam = number_range( ch->lvl[3] / 2, ch->lvl[3] * ( prime ? 2 : 1 ) );

   chance = ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_punch] / 2 );

   chance += ( ch->lvl[3] - victim->level );


   WAIT_STATE( ch, skill_table[gsn_punch].beats );

   check_killer( ch, victim );
   if( number_percent(  ) < chance )
   {

      if( sysdata.shownumbers == TRUE )
      {
         /*
          * HIT! 
          */
         char actbuf[MSL];
         snprintf( actbuf, MSL, "$n punches $N!! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "$N punches you really hard!! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, victim, NULL, ch, TO_CHAR );
         snprintf( actbuf, MSL, "You punch $N!! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_CHAR );
      }
      else
      {
         act( "$n punches $N really hard!", ch, NULL, victim, TO_NOTVICT );
         act( "$N punches you really hard!", victim, NULL, ch, TO_CHAR );
         act( "You punch $N really hard!", ch, NULL, victim, TO_CHAR );
      }
      damage( ch, victim, dam, -1 );
   }
   else
   {
      /*
       * MISS 
       */
      act( "$n tries to punch $N, but misses!", ch, NULL, victim, TO_NOTVICT );
      act( "$N tries to punch you, but misses!", victim, NULL, ch, TO_CHAR );
      act( "You try to punch $N, but miss!", ch, NULL, victim, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   return;
}


void do_headbutt( CHAR_DATA * ch, char *argument )
{

   CHAR_DATA *victim;
   int dam;
   bool prime;
   int chance;

   prime = FALSE;


   if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_headbutt] == 0 )
   {
      send_to_char( "You are not trained in this skill!\n\r", ch );
      return;
   }



   if( ( ( victim = get_char_room( ch, argument ) ) == NULL ) && ch->fighting == NULL )
   {
      send_to_char( "No such victim!\n\r", ch );
      return;
   }


   if( victim == NULL )
      victim = ch->fighting;

   if( victim == ch )
   {
      send_to_char( "You can't reach!\n\r", ch );
      return;
   }

   if( !IS_NPC( ch ) && ch->pcdata->order[0] == 3 )
      prime = TRUE;

   if( IS_NPC( ch ) )
      dam = number_range( ch->level / 3, ch->level / 2 );
   else
      dam = number_range( ch->lvl[3] / 2, ch->lvl[3] * ( prime ? 2 : 1 ) );

   chance = ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_headbutt] / 2 );

   chance += ( ch->lvl[3] - victim->level );


   WAIT_STATE( ch, skill_table[gsn_headbutt].beats );


   if( number_percent(  ) < chance )
   {
      /*
       * HIT 
       */
      check_killer( ch, victim );
      if( sysdata.shownumbers == TRUE )
      {
         /*
          * HIT! 
          */
         char actbuf[MSL];
         snprintf( actbuf, MSL, "$n headbutts $N in the face! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "$N headbutts you in the face! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, victim, NULL, ch, TO_CHAR );
         snprintf( actbuf, MSL, "You headbutt $N in the face! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_CHAR );
      }
      else
      {
         act( "$n headbutts $N in the face!", ch, NULL, victim, TO_NOTVICT );
         act( "$N headbutts you in the face!", victim, NULL, ch, TO_CHAR );
         act( "You headbutt $N in the face!", ch, NULL, victim, TO_CHAR );
      }

      damage( ch, victim, ( dam * 4 ) / 5, -1 );
   }
   else
   {
      /*
       * MISS 
       */
      check_killer( ch, victim );
      act( "$n tries to headbutt $N, but misses!", ch, NULL, victim, TO_NOTVICT );
      act( "$N tries to headbutt you, but misses!", victim, NULL, ch, TO_CHAR );
      act( "You try to headbutt $N, but miss!", ch, NULL, victim, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   return;
}


void do_charge( CHAR_DATA * ch, char *argument )
{

   CHAR_DATA *victim;
   float dam;
   bool prime;
   int chance;

   prime = FALSE;


   if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_charge] == 0 )
   {
      send_to_char( "You are not trained in this skill!\n\r", ch );
      return;
   }

   if( ( IS_NPC( ch ) ) && ( get_psuedo_level( ch ) < 80 ) )
      return;

   if( ( ( victim = get_char_room( ch, argument ) ) == NULL ) && ch->fighting == NULL )
   {
      send_to_char( "No such victim!\n\r", ch );
      return;
   }


   if( victim == NULL )
      victim = ch->fighting;

   if( victim == ch )
   {
      send_to_char( "You can't reach!\n\r", ch );
      return;
   }

   if( !IS_NPC( ch ) && ch->pcdata->order[0] == 3 )
      prime = TRUE;


   dam = number_range( get_psuedo_level( ch ), get_psuedo_level( ch ) * 3 );

   if( !IS_NPC( ch ) )
      chance = ch->pcdata->learned[gsn_charge] / 2;
   else
      chance = 50;

   chance += ( ( get_psuedo_level( ch ) - ( get_psuedo_level( victim ) - 30 ) ) / 2 );


   WAIT_STATE( ch, skill_table[gsn_charge].beats );

   check_killer( ch, victim );

   if( number_percent(  ) < chance )
   {
      /*
       * HIT 
       */

      dam = combat_damcap(ch,victim,dam,gsn_charge);

      if( sysdata.shownumbers == TRUE )
      {
         /*
          * HIT! 
          */
         char actbuf[MSL];
         snprintf( actbuf, MSL, "@@a$n @@acharges $N@@a, and knocks them over!@@N @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "@@a$N @@acharges right into you!@@N @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, victim, NULL, ch, TO_CHAR );
         snprintf( actbuf, MSL, "@@aYou charge right into $N@@a, and knock him over!@@N @@l(@@W%.0f@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_CHAR );
      }
      else
      {
         act( "@@a$n @@acharges $N@@a, and knocks them over!@@N", ch, NULL, victim, TO_NOTVICT );
         act( "@@a$N @@acharges right into you!@@N", victim, NULL, ch, TO_CHAR );
         act( "@@aYou charge right into $N@@a, and knock him over!@@N", ch, NULL, victim, TO_CHAR );
      }

      damage( ch, victim, dam, gsn_charge );
   }
   else
   {
      /*
       * MISS 
       */
      act( "$n@@b charges $N@@b, but runs right past!@@b", ch, NULL, victim, TO_NOTVICT );
      act( "$N @@bcharges you, but runs right past!@@N", victim, NULL, ch, TO_CHAR );
      act( "@@bYou try to charge $N@@b, but run past him. DOH!!@@N", ch, NULL, victim, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   return;
}



void do_knee( CHAR_DATA * ch, char *argument )
{

   CHAR_DATA *victim;
   int dam;
   bool prime;
   int chance;

   prime = FALSE;


   if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_knee] == 0 )
   {
      send_to_char( "You are not trained in this skill!\n\r", ch );
      return;
   }



   if( ( ( victim = get_char_room( ch, argument ) ) == NULL ) && ch->fighting == NULL )
   {
      send_to_char( "No such victim!\n\r", ch );
      return;
   }


   if( victim == NULL )
      victim = ch->fighting;

   if( IS_NPC( victim ) && victim->act.test(ACT_NO_BODY ) )
   {
      act( "$N doesn't have a definable body to knee!", ch, NULL, victim, TO_CHAR );
      return;
   }



   if( !IS_NPC( ch ) && ch->pcdata->order[0] == 3 )
      prime = TRUE;

   if( IS_NPC( ch ) )
      dam = number_range( ch->level / 3, ch->level / 2 );
   else
      dam = number_range( ch->lvl[3] / 2, ch->lvl[3] * ( prime ? 2 : 1 ) );

   chance = ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_knee] / 2 );

   chance += ( ch->lvl[3] - victim->level );


   WAIT_STATE( ch, skill_table[gsn_knee].beats );

   check_killer( ch, victim );

   if( number_percent(  ) < chance )
   {
      /*
       * HIT 
       */
      if( sysdata.shownumbers == TRUE )
      {
         /*
          * HIT! 
          */
         char actbuf[MSL];
         snprintf( actbuf, MSL, "$n grabs $N and knees $M in the groin! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "$N grabs you, and knees you in the groin! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, victim, NULL, ch, TO_CHAR );
         snprintf( actbuf, MSL, "You grab $M and knee $M in the groin! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_CHAR );
      }
      else
      {
         act( "$n grabs $N and knees $M in the groin!", ch, NULL, victim, TO_NOTVICT );
         act( "$N grabs you, and knees you in the groin!", victim, NULL, ch, TO_CHAR );
         act( "You grab $M and knee $M in the groin!", ch, NULL, victim, TO_CHAR );
      }

      damage( ch, victim, ( dam * 3 ) / 5, -1 );
   }
   else
   {
      /*
       * MISS 
       */
      act( "$n tries to grab $N, but $E twists free!", ch, NULL, victim, TO_NOTVICT );
      act( "$N tries to grab you, but you twist free!", victim, NULL, ch, TO_CHAR );
      act( "You try to grab $N, but $E twists free!", ch, NULL, victim, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   return;
}


void do_kick( CHAR_DATA * ch, char *argument )
{

   CHAR_DATA *victim;
   int dam;
   bool prime;
   int chance;

   prime = FALSE;


   if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_kick] == 0 )
   {
      send_to_char( "You are not trained in this skill!\n\r", ch );
      return;
   }

   if( ch->in_room->vnum == ROOM_VNUM_JAIL )
   {
      send_to_char( "Isn't jail punishment enough for you?", ch );
      return;
   }

   if( ( ( victim = get_char_room( ch, argument ) ) == NULL ) && ch->fighting == NULL )
   {
      send_to_char( "No such victim!\n\r", ch );
      return;
   }


   if( victim == NULL )
      victim = ch->fighting;

   if( !IS_NPC( ch ) && ch->pcdata->order[0] == 3 )
      prime = TRUE;

   if( IS_NPC( ch ) )
      dam = number_range( ch->level / 3, ch->level / 2 );
   else
      dam = number_range( ch->lvl[3] / 2, ch->lvl[3] * ( prime ? 2 : 1 ) );

   chance = ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[gsn_kick] / 2 );

   chance += ( ch->lvl[3] - ( victim->level + 5 ) );


   WAIT_STATE( ch, skill_table[gsn_kick].beats );

   check_killer( ch, victim );
   if( number_percent(  ) < chance )
   {
      /*
       * HIT 
       */

      if( sysdata.shownumbers == TRUE )
      {
         /*
          * HIT! 
          */
         char actbuf[MSL];
         snprintf( actbuf, MSL, "$n kicks $N really hard! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_NOTVICT );
         snprintf( actbuf, MSL, "$N kicks you really hard! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, victim, NULL, ch, TO_CHAR );
         snprintf( actbuf, MSL, "You kick $N really hard! @@l(@@W%d@@l)@@N", dam );
         act( actbuf, ch, NULL, victim, TO_CHAR );
      }
      else
      {
         act( "$n kicks $N really hard!", ch, NULL, victim, TO_NOTVICT );
         act( "$N kicks you really hard!", victim, NULL, ch, TO_CHAR );
         act( "You kick $N really hard!", ch, NULL, victim, TO_CHAR );
      }

      damage( ch, victim, dam, -1 );
   }
   else
   {
      /*
       * MISS 
       */
      act( "$n tries to kick $N, but misses!", ch, NULL, victim, TO_NOTVICT );
      act( "$N tries to kick you, but misses!", victim, NULL, ch, TO_CHAR );
      act( "You try to kick $N, but miss!", ch, NULL, victim, TO_CHAR );
      damage( ch, victim, 0, -1 );
   }
   return;
}

/* -S- Addition: Like damage() but called by objects, no message */
/* WARNING: No killer checks made, etc.  Only use if no keeper for obj */

void obj_damage( OBJ_DATA * obj, CHAR_DATA * victim, float dam )
{
   if( ( victim->position == POS_DEAD ) || ( victim->is_free == TRUE ) )
      return;

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

   if( ( IS_AFFECTED( victim, AFF_PROTECT ) || item_has_apply( victim, ITEM_APPLY_PROT ) )
       && IS_OBJ_STAT(obj,ITEM_EXTRA_EVIL) )
      dam -= dam / 4;

   if( dam < 0 )
      dam = 0;

   /*
    * Hurt the victim.
    * Inform the victim of his new state.
    */
   victim->hit -= (int)dam;


   update_pos( victim );

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

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

      case POS_STUNNED:
         act( "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM );
         send_to_char( "You are stunned, but will probably recover.\n\r", victim );
         break;

      case POS_DEAD:
         act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
         send_to_char( "You have been KILLED!!\n\r\n\r", victim );
         break;

      default:
         if( dam > victim->max_hit / 4 )
            send_to_char( "That really did HURT!\n\r", victim );
         if( victim->hit < victim->max_hit / 4 )
            send_to_char( "You sure are BLEEDING!\n\r", victim );
         break;
   }

   /*
    * Payoff for killing things.
    */
   if( victim->position == POS_DEAD )
   {

      if( !IS_NPC( victim ) )
      {

         snprintf( log_buf, (2 * MIL), "%s killed by %s at %d", victim->name, obj->short_descr, victim->in_room->vnum );
         log_string( log_buf );

         notify( log_buf, 82 );

         /*
          * As level gain is no longer automatic, a dead char loses
          * * 1/2 their gained exp.  -S- 
          * * Fixed my bug here too, hehe!
          */

         if( victim->exp > 0 )
         {
            gain_exp( victim, ( 0 - ( victim->exp / 2 ) ) );
            victim->exp = UMAX( victim->exp, 0 );
         }

      }

      raw_kill( victim, "" );

      if( deathmatch && !IS_NPC( victim ) )
         do_quit( victim, "" );


      return;
   }


   tail_chain(  );
   return;
}


void death_message( CHAR_DATA * ch, CHAR_DATA * victim, int dt, int max_dt )
{
   /*
    * Used to display assorted death messages, based on dt 
    * * max_dt == number of entries in attack table in dam_message,
    * * so we know if kill was unarmed, armed, or through spells or skills.
    * * Stephen
    */

   char buf1[MAX_STRING_LENGTH];
   char buf2[MAX_STRING_LENGTH];
   char buf3[MAX_STRING_LENGTH];
   int vnum;

   /*
    * For debugging purposes  
    * snprintf( buf, MSL, "dt: %d max_dt: %d\n\r", dt, max_dt );
    * notify( buf, 1 );  
    */

   vnum = 0;   /* Used to load up body parts.... eewwwwww! */

   if( dt == 0 )
   {
      if( !( IS_NPC( victim ) && victim->act.test(ACT_NO_BODY ) ) )
         switch ( number_range( 0, 9 ) )
         {
            case 0:
               snprintf( buf1, MSL, "$n grabs $N's neck, and twists until there is a loud SNAP!" );
               snprintf( buf2, MSL, "You grab $N's neck, and twist until there is a loud SNAP!" );
               snprintf( buf3, MSL, "$n grabs your neck, and twists until there is a loud SNAP!" );
               break;
            case 1:
               snprintf( buf1, MSL, "$n slams $s fist into $N and crushes $S heart!" );
               snprintf( buf2, MSL, "You slam your fist into $N and crush $S heart!" );
               snprintf( buf3, MSL, "$n slams $s fist into you, and crushes your heart!" );
               break;
            case 2:
               snprintf( buf1, MSL, "$n rams $s hand into $N's ribcage, and rips out $S guts!" );
               snprintf( buf2, MSL, "You ram your hand into $N's ribcage, and rip out $S guts!" );
               snprintf( buf3, MSL, "$n rams $s hand into your ribcage, and rips out your guts!" );
               break;
            case 3:
               snprintf( buf1, MSL, "$n grabs $N, and rips $S head clean off!" );
               snprintf( buf2, MSL, "You grab $N, and rip his head clean off!" );
               snprintf( buf3, MSL, "$n grabs you, and rips your head clean off!" );
               break;
            case 4:
               snprintf( buf1, MSL, "$n reaches behind $N, and rips $S spine out of $S back!" );
               snprintf( buf2, MSL, "You reach behind $N, and rip $S spine out of $S back!" );
               snprintf( buf3, MSL, "$n reaches behind you, and rips your spine out of your back!" );
               break;
            case 5:
               snprintf( buf1, MSL, "$n rips $N's face open via $S eye sockets!" );
               snprintf( buf2, MSL, "You rip $N's face open via $S eye sockets!" );
               snprintf( buf3, MSL, "$n rips your face open via your eye sockets!" );
               break;
            case 6:
               snprintf( buf1, MSL, "$n rips off $N's head and vomits down $S throat!" );
               snprintf( buf2, MSL, "You rip off $N's head and vomit down $S throat!" );
               snprintf( buf3, MSL, "$n rips off your head and vomits down your throat!" );
               break;
            case 7:
               snprintf( buf1, MSL, "$N splurts blood as $n rips open $S chest with $s teeth!" );
               snprintf( buf2, MSL, "$N splurts blood as you rip open $S chest with your teeth!" );
               snprintf( buf3, MSL, "You splurt blood as $n rips open your chest with $s teeth!" );
               break;
            case 8:
               snprintf( buf1, MSL, "$n wrenches $N's arms out from their sockets!" );
               snprintf( buf2, MSL, "You wrench $N's arms out from their sockets!" );
               snprintf( buf3, MSL, "$n wrenches your arms out of thier sockets!" );
               break;
            case 9:
               snprintf( buf1, MSL, "$n shatters $N's skull with a punch.  Brains leak out." );
               snprintf( buf2, MSL, "You shatter $N's skull with a punch.  Brains leak out." );
               snprintf( buf3, MSL, "$n shatters your skull with a punch.  Brains leak out." );
               break;
         }
      else  /* Unarmed, mob has no_body */
      {
         snprintf( buf1, MSL, "$n shatters $N's skull with a punch.  Brains leak out." );
         snprintf( buf2, MSL, "You shatter $N's skull with a punch.  Brains leak out." );
         snprintf( buf3, MSL, "$n shatters your skull with a punch.  Brains leak out." );
      }
   }


   if( dt <= max_dt && dt > 0 )
      switch ( dt )
      {
         case 1: /* slice */
         case 3: /* slash */
            switch ( number_range( 0, 4 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n slices $N's head clean from $S neck" );
                  snprintf( buf2, MSL, "You slice $N's head clean from $S neck" );
                  snprintf( buf3, MSL, "$n slices your head clean from your neck" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n slashes open $N's chest; $S entrails pour out!" );
                  snprintf( buf2, MSL, "You slash open $N's chest; $S entrails pour out!" );
                  snprintf( buf3, MSL, "$n slashes open your chest; your entrails pour out!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$n slices $N's throat open.  Blood sprays out wildly!" );
                  snprintf( buf2, MSL, "You slice $N's throat open.  Blood sprays out wildly!" );
                  snprintf( buf3, MSL, "$n slices your throat open.  Blood sprays out wildly!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n slices $N's legs off, leaving two bloody stumps!" );
                  snprintf( buf2, MSL, "You slice $N's legs off, leaving two bloody stumps!" );
                  snprintf( buf3, MSL, "$n slices your legs off, leaving two bloody stumps!" );
                  break;
               case 4:
                  snprintf( buf1, MSL, "$n slashes $N's eyeballs out!" );
                  snprintf( buf2, MSL, "You slash $N's eyeballs out!" );
                  snprintf( buf3, MSL, "$n slashes your eyeballs out!" );
                  break;
            }
            break;
         case 2: /* Stab */
         case 11:   /* Pierce */
            switch ( number_range( 0, 4 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n rips a gaping hole down $N's back!" );
                  snprintf( buf2, MSL, "You rip a gaping hole down $N's back!" );
                  snprintf( buf3, MSL, "$n rips a gaping hole down your back!" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n stabs into $N, and cuts $S heart out!" );
                  snprintf( buf2, MSL, "You stab into $N, and cut $S heart out!" );
                  snprintf( buf3, MSL, "$n stabs into you, and cuts your heart out!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$n stabs into $N's back, and wrenches out $S spine!" );
                  snprintf( buf2, MSL, "You stab into $N's back, and wrench out $S spine!" );
                  snprintf( buf3, MSL, "$n stabs into your back, and wrenches out your spine!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n plunges $s weapon into $N's head!" );
                  snprintf( buf2, MSL, "You plunge your weapon into $N's head!" );
                  snprintf( buf3, MSL, "$n plunges $s weapon into your head!" );
                  break;
               case 4:
                  snprintf( buf1, MSL, "$n stabs into $N's chest, skewering $S heart!" );
                  snprintf( buf1, MSL, "$n stabs into $N's chest, skewering $S heart!" );
                  snprintf( buf2, MSL, "You stab into $N's chest, skewering $S heart!" );
                  snprintf( buf2, MSL, "You stab into $N's chest, skewering $S heart!" );
                  snprintf( buf3, MSL, "$n stabs into your chest, skewering your heart!" );
                  break;
            }
            break;
         case 4: /* Whip */
            switch ( number_range( 0, 3 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n whips out $N's eyes, spraying blood everywhere!" );
                  snprintf( buf2, MSL, "You whip out $N's eyes, spraying blood everywhere!" );
                  snprintf( buf3, MSL, "$n whips out your eyes, spraying blood everywhere!" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n's whip catches $N's head, and rips it off!" );
                  snprintf( buf2, MSL, "Your whip catches $N's head, and rips it off!" );
                  snprintf( buf3, MSL, "$n's whip catches your head, and rips it off!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$n's whip wraps around $N's arms, yanking them off!" );
                  snprintf( buf2, MSL, "Your whip wraps around $N's arms, yanking them off!" );
                  snprintf( buf3, MSL, "$n's whip wraps around your arms, yanking them off!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n's whip cuts open $N's main artery, spraying blood!" );
                  snprintf( buf2, MSL, "Your whip cuts open $N's main artery, spraying blood!" );
                  snprintf( buf3, MSL, "$n's whip cuts open your main artery, spraying blood!" );
                  break;
            }
            break;
         case 5: /* Claw */
            switch ( number_range( 0, 4 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n claws out $N's heart!" );
                  snprintf( buf2, MSL, "You claw out $N's heart!" );
                  snprintf( buf3, MSL, "$n claws out your heart!" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n's claw catches $N's back, slicing it open!" );
                  snprintf( buf2, MSL, "Your claw catches $N's back, slicing it open!" );
                  snprintf( buf3, MSL, "$n's claw catches your back, slicing it open!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$N screams in agony, as $n's claw removes $S eyes!" );
                  snprintf( buf1, MSL, "$N screams in agony, as $n's claw removes $S eyes!" );
                  snprintf( buf2, MSL, "$N screams in agony, as your claw removes $S eyes!" );
                  snprintf( buf2, MSL, "$N screams in agony, as your claw removes $S eyes!" );
                  snprintf( buf3, MSL, "You scream in agony, as $n's claw removes your eyes!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n's claw ruptures $N's ribcage, shredding $S heart!" );
                  snprintf( buf2, MSL, "Your claw ruptures $N's ribcage, shredding $S heart!" );
                  snprintf( buf3, MSL, "$n's claw ruptures your ribcage, shredding your heart!" );
                  break;
               case 4:
                  snprintf( buf1, MSL, "$n's claw slashes $N's neck, decapitating $M!" );
                  snprintf( buf2, MSL, "Your claw slashes $N's neck, decapitating $M!" );
                  snprintf( buf3, MSL, "$n's claw slashes your neck, decapitating you!" );
                  break;
            }
            break;
         case 7: /* Pound */
         case 8: /* Crush */
            switch ( number_range( 0, 4 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n pounds $N's head; $S brains leak from $S ears!" );
                  snprintf( buf2, MSL, "You pound $N's head; $S brains leak from $S ears!" );
                  snprintf( buf3, MSL, "$n pounds your head; your brains leak from your ears!" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n crushes $N's ribcage, and $S entrails slop out!" );
                  snprintf( buf2, MSL, "You crush $N's ribcage, and $S entrails slop out!" );
                  snprintf( buf3, MSL, "$n crushes your ribcage, and your entrails slop out!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$n pounds $N's spine until you hear it CRACK!" );
                  snprintf( buf2, MSL, "You pound $N's spine until you hear it CRACK!" );
                  snprintf( buf3, MSL, "$n pounds your spine until you hear it CRACK!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n pounds $N's face, forcing $S nose into $S brain!" );
                  snprintf( buf2, MSL, "You pound $N's face, forcing $S nose into $S brain!" );
                  snprintf( buf3, MSL, "$n pounds your face, forcing your nose into your brain!" );
                  break;
               case 4:
                  snprintf( buf1, MSL, "$n crushes $N's head down into $S neck!" );
                  snprintf( buf2, MSL, "You crush $N's head down into $S neck!" );
                  snprintf( buf3, MSL, "$n crushes your head down into your neck!" );
                  break;
            }
            break;
         case 6: /* Blast */
            switch ( number_range( 0, 4 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n's blast totally obliterates $N's head!" );
                  snprintf( buf2, MSL, "Your blast totally obliterates $N's head!" );
                  snprintf( buf3, MSL, "$n's blast totally obliterates your head!" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n's blast makes $N's head fly into the air!" );
                  snprintf( buf2, MSL, "Your blast makes $N's head fly into the air!" );
                  snprintf( buf3, MSL, "$n's blast makes your head fly into the air!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$n blasts $N's stomach open - entrails plop out!" );
                  snprintf( buf2, MSL, "You blast $N's stomach open - entrails plop out!" );
                  snprintf( buf3, MSL, "$n blasts your stomach open - entrails plop out!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n's blast removes $N's legs from $S body!" );
                  snprintf( buf2, MSL, "Your blast removes $N's legs from $S body!" );
                  snprintf( buf3, MSL, "$n's blast removes your legs from your body!" );
                  break;
               case 4:
                  snprintf( buf1, MSL, "$n's blast splits $N's back, and $S spine falls out!" );
                  snprintf( buf2, MSL, "Your blast splits $N's back, and $S spine falls out!" );
                  snprintf( buf3, MSL, "$n's blast splits your back, and your spine falls out!" );
                  break;
            }
            break;
         default:   /* grep, bite, suction */
            switch ( number_range( 0, 3 ) )
            {
               case 0:
                  snprintf( buf1, MSL, "$n pulls $N's heart clean from $S ribcage!" );
                  snprintf( buf2, MSL, "You pull $N's heart clean from $S ribcage!" );
                  snprintf( buf3, MSL, "$n pulls your heart clean from your ribcage!" );
                  break;
               case 1:
                  snprintf( buf1, MSL, "$n snags $N's spine, and rips it out!" );
                  snprintf( buf2, MSL, "You snag $N's spine, and rip it out!" );
                  snprintf( buf3, MSL, "$n snags your spine, and rips it out!" );
                  break;
               case 2:
                  snprintf( buf1, MSL, "$N's stomach splits open, and $S entrails slip out!" );
                  snprintf( buf2, MSL, "$N's stomach splits open, and $S entrails slip out!" );
                  snprintf( buf3, MSL, "Your stomach splits open, and your entrails slip out!" );
                  break;
               case 3:
                  snprintf( buf1, MSL, "$n pulls $N's heart from $S chest!" );
                  snprintf( buf2, MSL, "You pull $N's heart from $S chest!" );
                  snprintf( buf3, MSL, "$n pulls your heart from your chest!" );
                  break;
            }
            break;
      }
   act( buf1, ch, NULL, victim, TO_NOTVICT );
   act( buf2, ch, NULL, victim, TO_CHAR );
   act( buf3, ch, NULL, victim, TO_VICT );

   /*
    * Load up object, if needed. 
    */
   if( vnum != 0 )
   {
      char buf[MAX_STRING_LENGTH];
      OBJ_DATA *obj;
      char *name;

      name = IS_NPC( ch ) ? ch->short_descr : ch->name;
      obj = create_object( get_obj_index( vnum ), 0 );
      obj->timer = number_range( 4, 7 );

      snprintf( buf, MSL, obj->short_descr, name );
      free_string( obj->short_descr );
      obj->short_descr = str_dup( buf );

      snprintf( buf, MSL, obj->long_descr, name );
      free_string( obj->long_descr );
      obj->long_descr = str_dup( buf );

      obj_to_room( obj, ch->in_room );
   }



   return;
}

void do_assist( CHAR_DATA * ch, char *argument )
{
   /*
    * Allow players to join in fight, by typing assist, 
    * * or assist <name>.  Will only ever allow players to
    * * assist a group member  -- Stephen
    */

   CHAR_DATA *assist = NULL;
   CHAR_DATA *ppl;
   char actbuf[MSL];

   if( argument[0] != '\0' )  /* then check for assist <name> */
   {
      if( ( assist = get_char_room( ch, argument ) ) == NULL )
      {
         send_to_char( "They don't seem to be here right now...\n\r", ch );
         return;
      }
      if( assist == ch )
      {
         send_to_char( "You sure need help!\n\r", ch );
         return;
      }
      if( !is_same_group( ch, assist ) )
      {
         act( "Sorry, $N isn't in your group...", ch, NULL, assist, TO_CHAR );
         return;
      }
      if( ( assist->fighting != NULL ) && ( ch->fighting == NULL ) )
      {
         snprintf( actbuf, MSL, "$n screams, '%s'", IS_NPC( ch ) ? "BANZAI!! $N must be assisted!!" : ch->pcdata->assist_msg );
         act( actbuf, ch, NULL, assist, TO_ROOM );
         snprintf( actbuf, MSL, "You scream, '%s'", IS_NPC( ch ) ? "BANZAI!! $N must be assisted!!" : ch->pcdata->assist_msg );
         act( actbuf, ch, NULL, assist, TO_CHAR );
         set_fighting( ch, assist->fighting, TRUE );
         return;
      }
      send_to_char( "Doesn't look like anyone needs your help right now...\n\r", ch );
      return;
   }

   /*
    * Check if any group members in room AND fighting 
    */

   for( ppl = ch->in_room->first_person; ppl != NULL; ppl = ppl->next_in_room )
      if( ( ppl != ch ) && ( is_same_group( ch, ppl ) ) )
         break;

   if( ppl == NULL )
   {
      send_to_char( "Doesn't look like anyone needs your help right now...\n\r", ch );
      return;
   }

   /*
    * Assisting leader is main priority 
    */
   if( ( ch->leader != NULL )
       && ( ch->leader->in_room == ch->in_room )
       && ( ch->leader->fighting != NULL ) && ( ch->fighting == NULL ) && ( ch->leader != ch ) )
   {
      snprintf( actbuf, MSL, "$n screams, '%s'", IS_NPC( ch ) ? "BANZAI!! $N must be assisted!!" : ch->pcdata->assist_msg );
      act( actbuf, ch, NULL, ch->leader, TO_ROOM );
      snprintf( actbuf, MSL, "You scream, '%s'", IS_NPC( ch ) ? "BANZAI!! $N must be assisted!!" : ch->pcdata->assist_msg );
      act( actbuf, ch, NULL, ch->leader, TO_CHAR );
      set_fighting( ch, ch->leader->fighting, TRUE );
      return;
   }

   /*
    * Ok, so no leader to help... lets look for other group members 
    */
   for( ppl = ch->in_room->first_person; ppl != NULL; ppl = ppl->next_in_room )
      if( ( is_same_group( ch, ppl ) ) && ( ppl != ch ) && ( ppl->fighting != NULL ) && ( ch->fighting == NULL ) )
      {
         snprintf( actbuf, MSL, "$n screams, '%s'", IS_NPC( ch ) ? "BANZAI!! $N must be assisted!!" : ch->pcdata->assist_msg );
         act( actbuf, ch, NULL, ppl, TO_ROOM );
         snprintf( actbuf, MSL, "You scream, '%s'", IS_NPC( ch ) ? "BANZAI!! $N must be assisted!!" : ch->pcdata->assist_msg );
         act( actbuf, ch, NULL, ppl, TO_CHAR );
         set_fighting( ch, ppl->fighting, TRUE );
         return;
      }


   send_to_char( "Doesn't look like anyone needs your help right now...\n\r", ch );
   return;
}

void do_stake( CHAR_DATA * ch, char *argument )
{
   /*
    * If player has an object of TYPE_STAKE (s)he can try and stake
    * * a fallen ( hit<0 ) vampire.  Note that there is still a check
    * * for pkilling here... PKOK players can be vamp hunters with
    * * no worries! (:  Player must also have learnt the stake skill.
    * * A sleeping vamp is also considered vulnerable.
    */

   CHAR_DATA *victim;
   OBJ_DATA *stake;
   int chance;
   char arg[MAX_INPUT_LENGTH];
   int sn;

   one_argument( argument, arg );

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

   victim = get_char_room( ch, arg );

   if( victim == NULL )
   {
      send_to_char( "Couldn't find the target.\n\r", ch );
      return;
   }
   if( victim == ch )
   {
      send_to_char( "Oh yeah, that would be a really good idea!\n\r", ch );
      return;
   }

   if( ( stake = get_eq_char( ch, WEAR_HOLD_HAND_L ) ) == NULL )
      stake = get_eq_char( ch, WEAR_HOLD_HAND_R );
   if( stake == NULL || stake->item_type != ITEM_STAKE )
   {
      send_to_char( "You have to be holding some sort of stake to do that\n\r", ch );
      return;
   }
   if( IS_NPC( victim ) )
   {
      send_to_char( "This is only used against PLAYER @@dVampyres@@N!!\n\r", ch );
      return;
   }

   chance = IS_NPC( ch ) ? ch->level * 2 : ch->pcdata->learned[gsn_stake];
   if( !IS_AWAKE( victim ) )
      chance += 25;

   /*
    * Make it harder to stake higher level targets 
    */
   if( ( victim->pcdata->super->level * 5 ) > ch->level )
      chance -= ( victim->pcdata->super->level * 5 ) - ch->level;

   if( victim->hit > 0 && IS_AWAKE( victim ) )  /* i.e. not vulnerable! */
      chance = 0;

   if( !IS_VAMP( victim ) )
      chance = 0;

   WAIT_STATE( ch, skill_table[gsn_stake].beats );
   check_killer( ch, victim );

   if( number_percent(  ) < chance )
   {
      /*
       * Success 
       */
      act( "$n raises $p above $s head and plunges it into $N's heart!", ch, stake, victim, TO_NOTVICT );
      act( "You raise $p above your head and plunge it into $N's heart!", ch, stake, victim, TO_CHAR );
      act( "$n raises $p above his head and plunges it into your heart!", ch, stake, victim, TO_VICT );
      act( "$n screams in agony and withers to black dust!", victim, NULL, NULL, TO_ROOM );
      send_to_char( "You scream in agony and withers to black dust!\n\r", victim );
      send_to_char( "@@NYou find yourself back in Moribund....\n\r", victim );
      send_to_char( "@@NSuddenly, you realize that your @@eKindred@@Nknowledge\n\r", victim );
      send_to_char( "@@Nis gone! So, THAT's what the sun looks like to mortals!\n\r", victim );
      send_to_char( "@@NYou had almost forgotten.....\n\r", victim );



      victim->act.reset(ACT_VAMPIRE);
      victim->pcdata->super->level = 0;
      victim->pcdata->super->exp = 0;
      victim->pcdata->super->energy = 0;
      victim->pcdata->super->energy_max = 0;
      victim->pcdata->super->generation = -1;
      victim->pcdata->super->bloodline = 0;
      victim->pcdata->recall_vnum = 3001;

/* remove vamp skills from dead vamp  */

      for( sn = 0; sn <= MAX_SKILL; sn++ )
         if( ( skill_table[sn].flag2 == VAMP ) && ( victim->pcdata->learned[sn] > 0 ) )
            victim->pcdata->learned[sn] = 0;

      if( !IS_NPC( victim ) )
         gain_exp( victim, 0 - ( 3 * victim->exp / 4 ) );

      raw_kill( victim, "" );
      return;
   }
   else
   {
      act( "$n tries to plunge $p into $N's chest, but misses!", ch, stake, victim, TO_NOTVICT );
      act( "You try to plunge $p into $N's chest, but miss!", ch, stake, victim, TO_CHAR );
      act( "$n tries to plunge $p into your chest, but misses!", ch, stake, victim, TO_VICT );
      set_fighting( ch, victim, TRUE );
   }
   return;
}

void do_stun( CHAR_DATA * ch, char *argument )
{
   CHAR_DATA *victim;
   int chance;
   int chance2;

   if( IS_NPC( ch ) )   /* for now */
      return;


   if( ( ( victim = ch->fighting ) == NULL ) || ( victim->in_room == NULL ) )
   {
      send_to_char( "You must be fighting someone first!\n\r", ch );
      return;
   }
   if( !IS_NPC( ch ) && ( ch->pcdata->learned[gsn_stun] == 0 ) )
   {
      send_to_char( "Huh?", ch );
      return;
   }

   chance = 45 - ( 100 * victim->hit / victim->max_hit );
   /*
    * The lower the victim's hp, the greater the chance 
    */

   chance2 = IS_NPC( ch ) ? ch->level * 2 : ch->pcdata->learned[gsn_stun];

   WAIT_STATE( ch, skill_table[gsn_stun].beats );

   if( ( number_percent(  ) + number_percent(  ) ) < ( chance + chance2 ) )
   {
      /*
       * Success 
       */
      act( "You slam into $N, leaving $M stunned.", ch, NULL, victim, TO_CHAR );
      act( "$n slams into you, leaving you stunned.", ch, NULL, victim, TO_VICT );
      act( "$n slams into $N, leaving $M stunned.", ch, NULL, victim, TO_NOTVICT );

      victim->stunTimer += number_range( 1, get_psuedo_level( ch ) / 30 );
      if( ch->lvl2[4] > 40 )
         victim->stunTimer += number_range( 1, 2 );

/*      if ( !IS_NPC( ch ) )
      {
        if( ch->lvl2[3] > ch->lvl2[5] )
        {
  	  victim->stunTimer += ch->lvl2[3] / 15;
	  return;
        }      
        else 
        {
          set_stun( victim, ch->lvl2[5] / 15 );
          return;
        }
      }   */
   }
   else
   {
      /*
       * Ooops! 
       */
      act( "You try to slam into $N, but miss and fall onto your face!", ch, NULL, victim, TO_CHAR );
      act( "$n tries to slam into you, but misses and falls onto $s face!", ch, NULL, victim, TO_VICT );
      act( "$n tries to slam into $N, but misses and falls onto $s face!", ch, NULL, victim, TO_NOTVICT );
      damage( ch, ch, number_range( 5, 20 ), TYPE_UNDEFINED );
      return;
   }
   return;
}

void do_feed( CHAR_DATA * ch, char *argument )
{
   CHAR_DATA *victim;
   char arg[MAX_INPUT_LENGTH];
   int chance;
   int bloodgain = 0;
   one_argument( argument, arg );

   if( !IS_VAMP( ch ) )
   {
      send_to_char( "Huh?\n\r", ch );
      return;
   }
   if( ( victim = ch->fighting ) == NULL )
   {
      send_to_char( "You must be fighting someone first!\n\r", ch );
      return;

   }

   if( victim == ch )
   {
      send_to_char( "What are you?  A blood donor?\n\r", ch );
      return;
   }

   if( victim->in_room->room_flags.test(RFLAG_SAFE) )
   {
      send_to_char( "The Gods prevent your foul deed.  This is a safe room!\n\r", ch );
      return;
   }

   if( victim->hit > 0 && victim->position > POS_FIGHTING )
   {
      /*
       * failure 
       */
      act( "$N is far too alert to let you do that!", ch, NULL, victim, TO_CHAR );
      return;
   }

   chance = IS_NPC( ch ) ? ch->level : ch->pcdata->learned[gsn_feed];
   WAIT_STATE( ch, skill_table[gsn_feed].beats );
   check_killer( ch, victim );
   if( number_percent(  ) < chance )
   {
      /*
       * Success! 
       */
      act( "You plunge your fangs into $N's neck, and taste sweet blood!", ch, NULL, victim, TO_CHAR );
      act( "$n plunges $s fangs into your neck, and sucks your blood!", ch, NULL, victim, TO_VICT );
      act( "$n plunges $s fangs into $N's neck and sucks $S blood!", ch, NULL, victim, TO_NOTVICT );
      if( ch->pcdata->super->energy <= -5 )
      {
         ch->pcdata->super->energy = ch->pcdata->super->energy_max;
         send_to_char( " You have now entered the ranks of the @@dKINDRED@@N!!!!\n\r", ch );
      }
      else
      {

         bloodgain = ( ( 20 - ch->pcdata->super->generation ) + ch->pcdata->super->level );
         if( bloodgain > victim->level )
            bloodgain = victim->level;
      }

      if( ( ch->pcdata->super->energy + bloodgain ) > ch->pcdata->super->energy_max )
         ch->pcdata->super->energy = ch->pcdata->super->energy_max;
      else
         ch->pcdata->super->energy += bloodgain;

      if( victim->hit > 0 )
      {
         act( "$N screams in horror at you at jumps to $s feet!", ch, NULL, victim, TO_CHAR );
         act( "You scream in horror at $n and jump to your feet!", ch, NULL, victim, TO_VICT );
         act( "$N screams in horror at $n and jumps to $S feet!", ch, NULL, victim, TO_NOTVICT );
         do_say( victim, "You'll pay for that!" );
         victim->position = POS_STANDING;
         one_hit( victim, ch, TYPE_UNDEFINED );
      }



      if( IS_VAMP( victim ) )
      {
         return;  /* for now :P SRZ 
                   * if ( !IS_NPC(ch) && !IS_NPC(victim) )
                   * {
                   * ch->pcdata->super->energy = victim->pcdata->super->energy;
                   * victim->pcdata->super->energy = 0;
                   * }
                   * if ( !IS_NPC(ch) && IS_NPC(victim) )
                   * gain_bloodlust( ch, victim->level*2 );
                   * if ( IS_NPC(ch) && !IS_NPC(victim) )
                   * victim->pcdata->super->energy = 0;     */
      }



      return;
   }
   else
   {
      /*
       * D'oh! 
       */
      act( "You try to find a spot on $N's neck to suck blood, but fail!", ch, NULL, victim, TO_CHAR );
      act( "$n tries to find a spot on your neck to suck blood, but fails!", ch, NULL, victim, TO_VICT );
      act( "$n tries to find a spot on $N's neck to suck blood, but fails!", ch, NULL, victim, TO_NOTVICT );
      /*
       * Any penalty? 
       */
      return;
   }
   return;
}


void check_adrenaline( CHAR_DATA * ch, float damage )
{

   AFFECT_DATA af;



   if( damage > 200 && ch->pcdata->learned[gsn_adrenaline] > 70 )
   {

      af.type = skill_lookup( "adrenaline bonus" );
      af.duration = 1;
      af.location = APPLY_DAMROLL;
      af.modifier = 1;
      af.bitvector = 0;
      affect_join( ch, &af );
      send_to_char( "You feel a surge of @@eadrenaline@@N!!!\n\r", ch );
   }
   return;

}

void do_frenzy( CHAR_DATA * ch, char *argument )
{
   CHAR_DATA *vch;
   CHAR_DATA *vch_next;
   int moves = 0;
   int damage = 0;

   if( IS_NPC( ch ) )
      return;

   if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_frenzy] == 0 )
   {
      send_to_char( "You are not trained in this skill!\n\r", ch );
      return;
   }


   if( !IS_NPC( ch ) && ch->move < 100 && ch->position == POS_FIGHTING )
   {
      send_to_char( "You're too tired to go into a frenzy!\n\r", ch );
      return;
   }

   if( !IS_NPC( ch ) && number_percent(  ) > ch->pcdata->learned[gsn_frenzy] )
   {
      send_to_char( "You try to go into a frenzy, but nearly cut your leg off!\n\r", ch );
      return;
   }

   if( ( ( ch->move / 10 ) < 75 ) && ch->move >= 75 )
      moves = 75;
   else
      moves = ch->move / 10;

   if( ch->hit > 200 )
      damage = 20;

   WAIT_STATE( ch, skill_table[gsn_frenzy].beats );

   if( !IS_NPC( ch ) && ch->position == POS_FIGHTING )
      ch->move -= moves;
   ch->hit -= damage;
   CREF( vch_next, CHAR_NEXTROOM );
   for( vch = ch->in_room->first_person; vch != NULL; vch = vch_next )
   {
      vch_next = vch->next_in_room;
      if( vch->in_room == NULL )
         continue;

      if( vch->in_room == ch->in_room )
      {
         if( vch != ch && ( vch->in_room == ch->in_room )
             && ( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) && ( vch->master != ch ) && ( !is_same_group( ch, vch ) ) )
         {
            act( "$N is @@Wgored@@N by your FRENZY!!!\n\r", ch, NULL, vch, TO_CHAR );
            act( "$n goes into a FRENZY, @@Wgoring@@N $N!!!", ch, NULL, vch, TO_ROOM );
            check_killer( ch, vch );
            one_hit( ch, vch, -1 );
            continue;
         }
      }
   }
   CUREF( vch_next );

   return;
}




void do_rage( CHAR_DATA * ch, char *argument )
{
   char arg[MAX_INPUT_LENGTH];
   int chance = 0;


   one_argument( argument, arg );



   if( IS_NPC( ch ) || !IS_WOLF( ch ) )
   {
      send_to_char( "Huh?\n\r", ch );
      return;
   }
   if( IS_RAGED( ch ) )
   {
      send_to_char( "You are already @@rRAGING@@N!!!\n\r", ch );
      return;
   }

   chance = 60 - ( ch->hit / ch->max_hit * 100 );
   if( weather_info.moon_loc == MOON_PEAK )
      chance += 15;
   if( IS_SHIFTED( ch ) )
      chance += 20;
   if( weather_info.moon_phase == MOON_FULL )
      chance += 30;
   if( weather_info.moon_phase == MOON_NEW )
      chance -= 30;
   if( weather_info.moon_loc == MOON_DOWN )
      chance -= 20;
   if( weather_info.moon_loc == MOON_PEAK )
      chance += 20;

   if( str_cmp( arg, "FORCE" ) )
   {
      chance += ( ( 5 - ch->pcdata->super->generation ) * 10 );
      chance += ch->pcdata->super->level;
      if( ( ch->pcdata->super->generation < 4 ) || ( ch->pcdata->super->level > 14 ) )
         chance += 50;
   }
   else
   {
      chance -= ( ( 5 - ch->pcdata->super->generation ) * 10 );
      chance -= ch->pcdata->super->level;
      if( ( ch->pcdata->super->generation < 4 ) || ( ch->pcdata->super->level > 14 ) )
         chance -= 50;
   }


   if( number_range( 0, 100 ) < chance )
   {
      AFFECT_DATA af1;
      AFFECT_DATA af2;
      AFFECT_DATA af3;
      AFFECT_DATA af4;

      int duration;

      af1.type = skill_lookup( "Rage:sharpened claws" );
      af2.type = skill_lookup( "Rage:wolven strength" );
      af3.type = skill_lookup( "Rage:disregard for pain" );
      af4.type = skill_lookup( "Enraged" );

      if( !str_cmp( arg, "FORCE" ) )
      {
         duration = number_range( ch->pcdata->super->generation / 4, 4 );

         af4.duration = duration;
         af4.location = APPLY_NONE;
         af4.modifier = 0;
         af4.bitvector = 0;
         affect_join( ch, &af4 );


         af1.duration = duration;
         af1.location = APPLY_DAMROLL;
         af1.modifier = ( 10 - ch->pcdata->super->generation ) * 4;
         af1.bitvector = 0;
         affect_join( ch, &af1 );

         af2.duration = duration;
         af2.location = APPLY_HITROLL;
         af2.modifier = ( 10 - ch->pcdata->super->generation ) * 4;
         af2.bitvector = 0;
         affect_join( ch, &af2 );

         af3.duration = duration;
         af3.location = APPLY_AC;
         af3.modifier = ( 5 + ch->pcdata->super->generation ) * 10;
         af3.bitvector = 0;
         affect_join( ch, &af3 );



      }
      else
      {
         duration = number_range( ch->pcdata->super->generation / 3, 5 );
         af4.duration = duration;
         af4.location = 0;
         af4.modifier = 0;
         af4.bitvector = 0;
         affect_join( ch, &af4 );


         af1.duration = duration;
         af1.location = APPLY_DAMROLL;
         af1.modifier = ( 10 - ch->pcdata->super->generation ) * 4;
         af1.bitvector = 0;
         affect_join( ch, &af1 );

         af2.duration = duration;
         af2.location = APPLY_HITROLL;
         af2.modifier = ( 10 - ch->pcdata->super->generation ) * 4;
         af2.bitvector = 0;
         affect_join( ch, &af2 );

         af3.duration = duration;
         af3.location = APPLY_AC;
         af3.modifier = ( 5 + ch->pcdata->super->generation ) * 15;
         af3.bitvector = 0;
         affect_join( ch, &af3 );


      }
      send_to_char( "You are @@eENRAGED!!!!!!\n\r", ch );
      ch->act.set(ACT_RAGED);
      ch->pcdata->super->energy = ( ch->pcdata->super->energy_max - number_range( 0, ch->pcdata->super->generation * 3 ) );
      ch->stance = STANCE_WARRIOR;
      ch->stance_ac_mod = 0;
      ch->stance_dr_mod = 0;
      ch->stance_hr_mod = 0;
   }
   else
      send_to_char( "You fail to become @@eENRAGED@@N.\n\r", ch );
   return;


};

float get_speed( CHAR_DATA *ch, int slot )
{
 float value = 4.00;
 int i;
 OBJ_DATA *wield;

 if( !IS_NPC(ch) )
 {
  switch(slot) {
   case SPEED_LH:   wield = get_eq_char(ch,WEAR_HOLD_HAND_L);  break;
   case SPEED_RH:   wield = get_eq_char(ch,WEAR_HOLD_HAND_R);  break;
   case SPEED_TAIL: wield = NULL;                              break;
   default: wield = NULL; break;
  }
  if( wield != NULL && wield->item_type == ITEM_WEAPON )
   value = wield->speed;
  else
  {
   if( slot == SPEED_TAIL )
    value = number_range(30,60);
   for( i = ch->level; i > 0; i-- )
    value -= 0.01;
  }
 }
 else
 {
  for( i = ch->level; i > 0 && value > 0.99; i -= 13 )
   value -= 0.14;
 }
 value += stance_app[ch->stance].speed_mod;
 if( (IS_NPC(ch) && IS_SET(ch->skills,MOB_REFLEXES) && number_percent() < 80) || (!IS_NPC(ch) && number_percent() < ch->pcdata->learned[gsn_enhanced_reflexes]) )
  value -= 0.02;
 if( (IS_NPC(ch) && IS_SET(ch->skills,MOB_SLEIGHT) && number_percent() < 80) || (!IS_NPC(ch) && number_percent() < ch->pcdata->learned[gsn_sleight_of_hand]) )
  value -= 0.04;
 if( (IS_NPC(ch) && IS_SET(ch->skills,MOB_QUICKSTRIKE) && number_percent() < 80) || (!IS_NPC(ch) && number_percent() < ch->pcdata->learned[gsn_quickstrike]) )
  value -= 0.06;

 if( value < 1 )
  value = 1;

 return value;
}

void combat_update( void )
{
 FIGHT_DATA *fight;
 CHAR_DATA *ch;
 CHAR_DATA *victim;

 for( fight = first_fight; fight != NULL; fight = fight->next )
 {
  if( fight->ch == NULL )
  {
   //monitor_chan("Removing a null fight->ch from queue.",MONITOR_DEBUG);
   UNLINK(fight,first_fight,last_fight,next,prev);
   PUT_FREE(fight,fight_free);
   return;
  }
  if( fight->ch->fighting == NULL )
  {
   //monitor_chan("Removing a null fight->ch->fighting from queue.",MONITOR_DEBUG);
   UNLINK(fight,first_fight,last_fight,next,prev);
   PUT_FREE(fight,fight_free);
   return;
  }
  ch = fight->ch;
  victim = ch->fighting;

  /*
   * Speed based combat. Arms attack independantly of each other,
   * as do special racials such as fangs or tails. --Kline
   */
  if( ch->position == POS_FIGHTING && victim != NULL )
  {
   /* Left hand attack (primary) */
   ch->speed[SPEED_LH] -= 0.01;

   if( ch->speed[SPEED_LH] <= 0 )
   {
    one_hit(ch, victim, TYPE_UNDEFINED);
    ch->speed[SPEED_LH] = get_speed(ch,SPEED_LH);
   }

   /* Right hand attack (if we dualwield) */
   if( (IS_NPC(ch) && IS_SET(ch->skills,MOB_DUALWIELD)) || (!IS_NPC(ch) && ch->pcdata->learned[gsn_dualwield] > 10) )
   {
    ch->speed[SPEED_RH] -= 0.01;

    if( ch->speed[SPEED_RH] <= 0 )
    {
     one_hit(ch, victim, TYPE_UNDEFINED);
     ch->speed[SPEED_RH] = get_speed(ch,SPEED_RH);
    }
   }

   /* Tail attack (if we have one) */
   if( IS_SET(race_table[ch->race].race_flags,RACE_MOD_TAIL) )
   {
    ch->speed[SPEED_TAIL] -= 0.01;

    if( ch->speed[SPEED_TAIL] <= 0 )
    {
     one_hit(ch,victim,(TYPE_HIT + 13));
     ch->speed[SPEED_TAIL] = get_speed(ch,SPEED_TAIL);
    }
   }
  }
 }
}

float combat_damcap( CHAR_DATA *ch, CHAR_DATA *victim, float dam, int dt )
{
 char buf[MSL];

 if( dam > sysdata.damcap )
 {
  snprintf( buf, MSL, "Combat: %1.0f damage by %s, attacking %s, dt %d", dam, IS_NPC( ch ) ? ch->short_descr : ch->name, IS_NPC( victim ) ? victim->short_descr : victim->name, dt );
  if( ch->level < 82 )
  {
   monitor_chan( buf, MONITOR_COMBAT );
   log_f( "%s", buf );
  }
  dam = sysdata.damcap;
 }

 return dam;
}

void check_brawl( CHAR_DATA *ch )
{
 #define MAX_BRAWLS 10
 CHAR_DATA *fight[MAX_BRAWLS], *rch, *rch_next, *vch, *vch_next;
 short i = 0, x = 0;

 for( i = 0; i < MAX_BRAWLS; i++ )
  fight[i] = NULL;

 for( rch = ch->in_room->first_person; rch != NULL; rch = rch_next )
 {
  rch_next = rch->next_in_room;

  if( rch->fighting == NULL && IS_AWAKE(rch) && rch->master != ch && !IS_IMMORTAL(rch) && number_percent() <= 2 )
  {
   if( IS_NPC(rch) && (rch->act.test(ACT_TRAIN) || rch->act.test(ACT_PRACTICE) || rch->pIndexData->pShop != NULL) )
    continue;

   for( vch = ch->in_room->first_person; vch != NULL; vch = vch_next )
   {
    vch_next = vch->next_in_room;

    if( vch->fighting == NULL && rch->master != ch && !IS_IMMORTAL(vch) && i < MAX_BRAWLS )
    {
     fight[i] = vch;
     i++;
    }
   }
   x = number_range(0,i); /* Only search as many as we found */
   if( fight[x] != NULL )
   {
    if( !IS_NPC(rch) && !IS_NPC(fight[x]) ) /* Don't force PVP */
     continue;
    if( !can_see(rch,fight[x]) )
    continue;
    rch->fighting = fight[x];
    rch->position = POS_FIGHTING;
    act("@@eYou find yourself caught up in the brawl!@@N",rch,NULL,NULL,TO_CHAR);
    act("@@e$n finds $mself caught up in the brawl!@@N",rch,NULL,NULL,TO_ROOM);
   }
  }
 }
}

void damage_gear( CHAR_DATA *ch )
{
 OBJ_DATA *obj;

 for( obj = ch->first_carry; obj != NULL; obj = obj->next_in_carry_list )
 {
  if( obj->wear_loc == WEAR_NONE )
   continue;
  if( number_percent() < 50 )
   obj->durability--;
  if( obj->durability == 1 )
  {
   act("@@y$p breaks and falls off.@@N",ch,obj,NULL,TO_CHAR);
   act("@@y$n's $p breaks and falls off.@@N",ch,obj,NULL,TO_ROOM);
   remove_obj(ch,obj->wear_loc,TRUE);
  }
 }
}