area_current/castle/
area_current/gahld/
clans/
player/
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.                              *
 *                                                                         *
 *  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.                                               *
 *                                                                         *
 *  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.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <math.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

/*
 * Global functions.
 */
sh_int martial_arts_attack;    /* The attack number for the global MA */

bool    remove_obj      args( ( CHAR_DATA *ch, int iWear, bool fReplace, bool fDisplay ) );

/*
 * Local functions.
 */
bool check_add_attack( CHAR_DATA *, CHAR_DATA * );
bool check_race_war( CHAR_DATA *, CHAR_DATA *);
void add_to_victory_list( CHAR_DATA *, CHAR_DATA *);
bool    check_dodge     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    check_killer    args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool    check_parry     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    dam_message     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,
int dt ) );
void    death_cry       args( ( CHAR_DATA *ch ) );
void    group_gain      args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int     xp_compute      args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
bool    is_safe         args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    make_corpse     args( ( CHAR_DATA *ch ) );
void    one_hit         args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) );
void    raw_kill        args( ( CHAR_DATA *victim ) );
void    disarm          args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    trip            args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    backstab        args( ( CHAR_DATA *ch, CHAR_DATA *victim) );
void    centaur_hoof    args( ( CHAR_DATA *ch, CHAR_DATA *victim) );
void    orc_brawl       args( ( CHAR_DATA *ch, CHAR_DATA *victim) );
bool    has_mirror      args( (CHAR_DATA *ch, CHAR_DATA *victim) );

bool OGRE_INTIMIDATE;

void    show_party_line      ( CHAR_DATA * );

void check_asn_obj(CHAR_DATA *victim)
  {
  if(!IS_NPC(victim) &&
     victim->fighting!=NULL &&
     victim->fighting->who->asn_obj!=NULL)
    {
    OBJ_DATA *obj;

    obj=victim->fighting->who->asn_obj;
    victim->fighting->who->asn_obj=NULL;
    if(obj->carried_by == victim)
      {
      obj_from_char( obj );
      obj_to_char(obj,victim->fighting->who);
      act("You quickly snatch the $p from $N's failing grasp!",
          victim->fighting->who, obj, victim, TO_CHAR );
      }
    }
  }

/*
 * Control the fights going on.
 * Called periodically by update_handler.
 */


void violence_update( void )
{
  CHAR_DATA *ch;
  CHAR_DATA *victim;
  CHAR_DATA *rch;
  PLAYER_GAME *gpl,*gpl_next;
  char ch_col[81];

  victim=NULL;

  /* Object Program Tick */
  for( gpl = first_player; gpl != NULL; gpl=gpl_next )
    {
    OBJ_DATA *obj;
    OBJ_PROG *prg;
    OBJ_WITH_PROG *with, *with_next;
  
    gpl_next=gpl->next;
    ch = gpl->ch;
    
    if( ch->desc != NULL && ch->obj_with_prog != NULL )
    for(with=ch->obj_with_prog;with!=NULL;with=with_next)
      {
      with_next = with->next;
      if( (obj = with->obj ) == NULL 
	   || obj->pIndexData == NULL )
        continue;
      if( ch->obj_prog_ip==0 && obj->pIndexData->obj_prog!=NULL)
        for( prg = obj->pIndexData->obj_prog; prg!=NULL ; prg=prg->next)
          if( prg->cmd == -3 )
           /* Let's reduce the rate of calls by 1/2 with 200% range */
      if( number_range(0,200) < prg->percentage )
        {
        open_timer( TIMER_OBJ_PROG );
        start_object_program( ch, obj, prg, "");
        close_timer( TIMER_OBJ_PROG );
        tail_chain();
        }
      }
    }

  for( ch = first_char; ch != NULL; ch = violence_ch_next)
    {
    violence_ch_next = ch->next;

    if( last_dead == ch || ch->name==NULL)
     continue;

    ch->attack=0;

      /* Cludge if they are not in the same room    -  Chaos 4/3/99 */
    if( ch->fighting != NULL && ch->fighting->who != NULL &&
        ch->in_room != ch->fighting->who->in_room )
       {
       stop_fighting( ch, FALSE );
       continue;
       }

      /* Cludge if they are not really fighting  -  Chaos 4/2/99  */
    if( ch->position == POS_FIGHTING && ch->fighting == NULL )
       {
       stop_fighting( ch, FALSE );
       continue;
       }

    if (ch == first_char  && ch->prev)
    {
           bug( "ERROR: first_char->prev != NULL, fixing..." );
           ch->prev = NULL;
    }
        /*
         * Experience gained during battle decreases as battle drags on
        if ( ch->fighting )
          if ( (++ch->fighting->duration % 24) == 0 )
            ch->fighting->xp = ((ch->fighting->xp * 9) / 10); */


 
         /* Fix the mobiles that show up for combat, but live */
    if( IS_NPC( ch )  &&  ch->fighting == NULL && ch->position==POS_STANDING )
      {
      if( IS_SET( ch->pIndexData->affected_by ,  AFF_INVISIBLE ) &&
         !IS_SET( ch->affected_by, AFF_INVISIBLE ) )
        {
        SET_BIT(ch->affected_by, AFF_INVISIBLE );
        }
      if( IS_SET( ch->pIndexData->affected_by ,  AFF_HIDE ) &&
         !IS_SET( ch->affected_by, AFF_HIDE ) )
        {
        SET_BIT(ch->affected_by, AFF_HIDE );
        }
      if( IS_SET( ch->pIndexData->affected_by ,  AFF_STEALTH ) &&
         !IS_SET( ch->affected_by, AFF_STEALTH ) )
        {
        SET_BIT(ch->affected_by, AFF_STEALTH );
        }
      }
    if (is_affected(ch, gsn_nightmare))
    {
     OBJ_DATA * obj;

      if (number_percent() < 5 && (obj = get_eq_char(ch, WEAR_LIGHT)) !=NULL)  
      {
       act( "$n screams and flings $s $p away!", ch, obj, NULL, TO_ROOM);
       switch (number_range(1,3))
       {
       case 1:act( "A large demon leers at you from within the glaring light of your $p!", ch, obj, NULL, TO_CHAR);
              break;
       case 2:act( "A soul rending shriek tears through your rational mind! Your $p vibrates in harmony with it!", ch, obj, NULL, TO_CHAR);
              break;
       case 3:act( "A mental picture of your imminent death emanates from your $p!", ch, obj, NULL, TO_CHAR);
              break;
       }
       act( "You fling your $p away!", ch, obj, NULL, TO_CHAR);
       obj_from_char( obj );
       obj_to_char( obj, ch );
      }
      else if ( number_percent() < 5 && (obj = get_eq_char(ch, WEAR_HOLD ))  !=NULL)
      {
       act( "$n screams and flings $s $p away!", ch, obj, NULL, TO_ROOM);
       switch (number_range(1,3))
       {
        case 1:act( "Your $p starts to slowly drain away your dwindling vitality!", ch, obj, NULL, TO_CHAR);
               break;
        case 2:act( "Your $p moans loudly and starts to switch! It's coming alive!", ch, obj, NULL, TO_CHAR);
               break;
        case 3:act( "A stabbing pain lances through you from your $p!", ch, obj, NULL, TO_CHAR);
               break;
       }
       act( "You fling your $p away!", ch, obj, NULL, TO_CHAR);
       obj_from_char( obj );
       obj_to_char( obj, ch );
      }
      else if ( number_percent() < 5 && (obj = get_eq_char(ch, WEAR_DUAL_WIELD ))  !=NULL)
      {
       act( "$n screams and flings $s $p away!", ch, obj, NULL, TO_ROOM);
       switch (number_range(1,3))
       {
        case 1:act( "Your $p starts to slowly drain away your dwindling vitality!", ch, obj, NULL, TO_CHAR);
               break;
        case 2:act( "Your $p moans loudly and starts to switch! It's coming alive!", ch, obj, NULL, TO_CHAR);
               break;
        case 3:act( "A stabbing pain lances through you from Your $p!", ch, obj, NULL, TO_CHAR);
               break;
       }
       act( "You fling your $p away!", ch, obj, NULL, TO_CHAR);
       obj_from_char( obj );
       obj_to_char( obj, ch );
      }
    }

    if (IS_AFFECTED(ch,AFF2_BLEEDING) )
    {
      AFFECT_DATA *paf;
      int dam = 0;
      ch_col[0]  = '\0';

      if(ch->ansi==1)
        {
        /* determine color of messages */
        if(ch->pcdata->color[4]!=0)
	  sprintf( ch_col, "\033[1;%d;%dm", ch->pcdata->color[0][4],
	           ch->pcdata->color[1][4]);
        }
      act("$tYour life is bleeding out of a nasty wound!",
          ch,ch_col,NULL,TO_CHAR);
      act("$n's life is bleeding out of a nasty wound!",ch,NULL,NULL,TO_ROOM);

        for ( paf = ch->first_affect; paf != NULL; paf = paf->next)
          if(paf->bitvector==AFF2_BLEEDING)
            dam+=paf->modifier;
        if( dam < 1 )
          dam = 1;
        if( ch->critical_hit_by != 0 )
          victim = get_pvnum_index( ch->critical_hit_by );
        else
          victim = NULL;
        if( victim == NULL )
          victim = ch;
	damage(victim,ch,dam,TYPE_NOFIGHT);
     
        if( last_dead == ch )
          continue;
    }

    /* Add poison continuous damage here */
    if( ( IS_NPC( ch ) && ch->npcdata->poison != NULL ) ||
        ( !IS_NPC( ch ) && ch->pcdata->poison != NULL ) )
      {
      POISON_DATA *pd, *npd, *ppd;
      CHAR_DATA *attacker, *fch;
      char buf[MAX_INPUT_LENGTH];
      int dmg;
     
      if( IS_NPC( ch ) )
        pd = ch->npcdata->poison;
      else
        pd = ch->pcdata->poison;
      ppd = NULL;


      if( pd!=NULL )
        {
        npd = pd->next;

        attacker = NULL;
        if( pd->poisoner >= 0 )
          attacker = get_pvnum_index( pd->poisoner );
        if( attacker==NULL )
          attacker = ch;

        if( pd->instant_damage_high > 0 )
          {
	  dmg = number_range( pd->instant_damage_low,pd->instant_damage_high);
          if( ( pd->for_npc && !IS_NPC( ch ) ) ||
              ( !pd->for_npc && IS_NPC( ch ) ) )
            dmg /= 3;

          for( fch=ch->in_room->first_person; fch!=NULL; fch=fch->next_in_room)
            if( fch == ch )
              send_to_char( "You are shocked by poison.\n\r", ch );
            else
            if( fch == attacker )
              {
              sprintf( buf, "%s is shocked by poison for %d hp.\n\r", 
                 IS_NPC(ch)?capitalize(ch->short_descr):capitalize(ch->name),
                 dmg );
              send_to_combat_char( buf, fch );
              }
            else
              {
              sprintf( buf, "%s is shocked by poison.\n\r", 
                 IS_NPC(ch)?capitalize(ch->short_descr):capitalize(ch->name));
              send_to_combat_char( buf, fch );
              }
   

          pd->instant_damage_low = 0;
          pd->instant_damage_high = 0;
 	
          damage(attacker, ch, dmg, TYPE_NOFIGHT);
          }
        else
          {
	  dmg=number_range( pd->constant_damage_low, pd->constant_damage_high);
          if( ( pd->for_npc && !IS_NPC( ch ) ) ||
              ( !pd->for_npc && IS_NPC( ch ) ) )
            dmg /= 3;
          for( fch=ch->in_room->first_person; fch!=NULL; fch=fch->next_in_room)
            if( fch == ch )
              send_to_char( "You shake from poison.\n\r", ch );
            else
            if( fch == attacker )
              {
              sprintf( buf, "%s is poisoned for %d hp.\n\r", 
                 IS_NPC(ch)?capitalize(ch->short_descr):capitalize(ch->name),
                 dmg );
              send_to_combat_char( buf, fch );
              }
            else
              {
              sprintf( buf, "%s shivers from poison.\n\r", 
                 IS_NPC(ch)?capitalize(ch->short_descr):capitalize(ch->name));
              send_to_combat_char( buf, fch );
              }
   
          damage(attacker, ch, dmg, TYPE_NOFIGHT);
          }


        if( pd->constant_duration <= 0 )
          {
          if( ppd == NULL )
            {
            if( IS_NPC( ch ) )
              ch->npcdata->poison = npd;
            else
              ch->pcdata->poison = npd;
            }
          else
            ppd->next = npd;
          DISPOSE( pd );
          pd = NULL;
          }
        else
          {
          pd->constant_duration --;
          ppd = pd;
          }

      pd = npd;
      }
    }

    if( last_dead == ch || ch->name==NULL)
      continue;
    if ( (  victim = who_fighting (ch)  ) == NULL || ch->in_room == NULL)
      continue;

    if( !is_in_room( victim, ch->in_room ) || ch == victim )
      {
      stop_fighting( ch, FALSE );
      continue;
      }

    if ( IS_AWAKE(ch) && ch->in_room == victim->in_room )
      {
      if( IS_NPC(ch) || ch->pcdata->auto_flags!=AUTO_QUICK )
        multi_hit( ch, victim, TYPE_UNDEFINED );
        if( last_dead == ch || ch->name==NULL)
          continue;
      set_fighting( ch, victim ); /*This is redundant Martin 19/3/99*/
      }
    else
      stop_fighting( ch, FALSE );

    /*
     * Fun for the whole family!
     */
        if( last_dead == ch || ch->name==NULL)
          continue;
      mprog_hitprcnt_trigger(ch,victim);
        if( last_dead == ch || ch->name==NULL)
          continue;
      mprog_fight_trigger(ch,victim);
        if( last_dead == ch || ch->name==NULL)
          continue;

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

      if ( IS_AWAKE(rch) && rch->fighting == NULL )
        {
        /*  rch assist ch against victim
         * PC's auto-assist others in their group unless PK.
         * Pets always assist their masters, even PK.
	 * Added a line so that if the mobile is grouped with the character
	 * They will assist the character rather than attacking a random 
	 * Opponent. - Martin
         */
        if( !IS_NPC( ch ) )
          if( ( !IS_NPC( rch ) && is_same_group(ch, rch) && IS_NPC(victim)) ||
                ( IS_NPC(rch) && IS_AFFECTED(rch, AFF_CHARM) &&
                         rch->master == ch ) ||
		(IS_NPC(rch) && is_same_group(ch,rch)) )

              if( !IS_AFFECTED(victim, AFF_CHARM))
                 {
                 multi_hit( rch, victim, TYPE_UNDEFINED );
                 continue;
                 }

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

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

            if ( target != NULL )
              multi_hit( rch, target, TYPE_UNDEFINED );
        
            }
          }
        }
      }
    }


  /*   Add Spam's party stat line here    */
  for( gpl = first_player; gpl != NULL; gpl=gpl_next )
    {
    gpl_next = gpl->next;
    if( IS_NPC( gpl->ch ) )
      sub_player( gpl->ch );
    else
      if( gpl->ch->fighting!= NULL && IS_SET(gpl->ch->pcdata->spam, 1024))
          show_party_line( gpl->ch );

     if(  gpl->ch->fighting!= NULL && gpl->ch->position == POS_FIGHTING 
	    &&   gpl->ch->hit > 0
	    &&   gpl->ch->hit <= gpl->ch->wimpy
	    &&   gpl->ch->wait == 0 
            &&   gpl->ch->desc==NULL)
      {
      do_flee( gpl->ch, "" );
      tail_chain();
      }
    }
  return;
}



/*  The SPAM stat line  */
void show_party_line( CHAR_DATA *ch )
  {
  CHAR_DATA *fch;
  char buf[MAX_STRING_LENGTH], buf2[200], buf3[200];

  buf[0]='\0';

  for( fch = ch->in_room->first_person; fch != NULL; fch = fch->next_in_room )
    if( fch != ch && is_same_group( ch, fch ) )
      {
      strcpy( buf3, !IS_NPC(fch)?capitalize(fch->name):
            capitalize(fch->short_descr));
      buf3[6]='\0';
      sprintf( buf2, "%s:%d/%d  ", buf3, fch->hit, fch->max_hit );
      strcat( buf, buf2 );
      }
  if( buf[0] != '\0' )
    send_to_combat_char( justify( buf ), ch );
  return;
  }
      



/*
 * Do one group of attacks.
 */
void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
	int     chance;
	int     level;
        int     cnt;
        int     dual_bonus;

   OGRE_INTIMIDATE=FALSE;
   /* Disallow fighting in different rooms and shops */
    if(victim->in_room!=ch->in_room )
      {
      stop_fighting( ch, FALSE);
      return;
      }

    if(find_keeper( ch ) !=NULL)
    {
     ch_printf(ch, "%s tells you 'No fighting in here! You thug!'\n\r", capitalize(find_keeper(ch)->short_descr));
     ch->reply=find_keeper( ch );
     return;
    }

 if( IS_NPC(victim))
  if( IS_SET( victim->act, ACT_PET) && 
      ((victim->fighting && victim->fighting->who==victim->master) ||
       victim->master==ch))
    {
    raw_kill( victim);
    return;
    }

   if( IS_AFFECTED( victim, AFF_CHARM) && 
     ((victim->fighting && victim->fighting->who==victim->master) ||
       victim->master==ch))
    {
    stop_follower( victim);
    affect_strip( victim, gsn_charm_person );
    }


	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
                stop_fighting( ch, TRUE);
		return;
	}

     if( !is_affected(ch, gsn_truesight) && has_mirror( ch, victim ) )
       return;

  if( ch->in_room != victim->in_room )
    return;
 
    /*Added Ogre Intimidate here  - Chaos 8/20/98 */
      if( !IS_NPC(ch) && ch->race==RACE_OGRE )
        if( number_range( 1,6 )==1 )
          {
          OGRE_INTIMIDATE=TRUE;
          send_to_combat_char( "You intimidate your opponent.\n\r", ch);
          send_to_combat_char( "You are intimidated by your opponent.\n\r",
               victim);
          }

	one_hit( ch, victim, dt );
	if ( !ch->fighting || ch->fighting->who != victim || 
	     dt == gsn_backstab || last_dead == victim)
		return;

      /* Added Orcish brawling  - Chaos 8/20/98  */
  if( !IS_NPC(ch) && ch->race == RACE_ORC )
    if ( number_percent( ) < 10 )
      {
      orc_brawl( ch, victim );
      if ( !ch->fighting || ch->fighting->who != victim || last_dead == victim )
        return;
      }

      /* Added Centaur Hoof Attack - Presto 4/17/99  */
  if( !IS_NPC(ch) && ch->race == RACE_CENTAUR )
    if ( number_percent( ) < (30 + ch->level/3) )
      {
      centaur_hoof( ch, victim );
      if ( !ch->fighting || ch->fighting->who != victim || last_dead == victim )
        return;
      }

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

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

  cnt = multi(ch, gsn_second_attack);
  if( cnt==-1 && !IS_NPC(ch))
    return;
  level = ch->mclass[multi(ch, gsn_second_attack)];

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

  chance=IS_NPC(ch)?ch->level*2:(ch->pcdata->learned[gsn_second_attack]+dual_bonus)*level/50;
  if ( number_percent( ) < chance )
    {
    one_hit( ch, victim, dt );
    if ( ch->fighting == NULL || ch->fighting->who != victim || last_dead == victim )
      return;
    }

  cnt = multi(ch, gsn_third_attack);
  if( cnt==-1 && !IS_NPC(ch))
    return;
  level = ch->mclass[multi(ch, gsn_third_attack)];

  chance=IS_NPC(ch) ? ch->level*2/3 :
           (ch->pcdata->learned[gsn_third_attack]+dual_bonus)*level/120;

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

  if ( number_percent( ) < chance )
    {
    one_hit( ch, victim, dt );
    if ( ch->fighting == NULL || ch->fighting->who != victim || last_dead == victim )
      return;
    }

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

  cnt = multi(ch, gsn_fourth_attack);
  if( cnt==-1 && !IS_NPC(ch))
    return;
  level = ch->mclass[multi(ch, gsn_fourth_attack)];

chance=IS_NPC(ch)?ch->level/3:(ch->pcdata->learned[gsn_fourth_attack]+dual_bonus)*level/320;
  if ( number_percent( ) < chance )
    one_hit( ch, victim, dt );

  return;
}


bool check_hit( CHAR_DATA *ch, CHAR_DATA *victim, int hit_roll, int dam_type )
{
	int thac0;
	int diceroll;
        int level;
        int scale;
        int cnt;

  /*   Chaos 10/5/93
   * Calculate to-hit-armor-class-0 versus armor.
   */

      if (dam_type ==  gsn_throw )
          {
	  cnt = multi(ch,gsn_throw);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 13;
          }
      else if (dam_type ==  gsn_kick )
          {
	  cnt = multi(ch,gsn_kick);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 17;
          }
      else if (dam_type ==  gsn_knife )
          {
	  cnt = multi(ch,gsn_knife);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else if (dam_type ==  gsn_shoot )
          {
	  cnt = multi(ch,gsn_shoot);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else if (dam_type ==  gsn_backstab )
          {
	  cnt = multi(ch,gsn_backstab);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else if (dam_type ==  gsn_circle )
          {
	  cnt = multi(ch,gsn_circle);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else if (dam_type ==  gsn_gouge )
          {
	  cnt = multi(ch,gsn_gouge);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else if (dam_type ==  gsn_trip )
          {
	  cnt = multi(ch,gsn_trip);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else if (dam_type ==  gsn_bash )
          {
	  cnt = multi(ch,gsn_bash);
          if( cnt == -1 )
            return( FALSE );
          level = ch->mclass[ cnt ] + ( ch->level - ch->mclass[cnt] ) / 3;
          scale = 15;
          }
      else   
         {   /* Normal attack here */
          level = ch->level;
          scale = 10;   /* later to be divided by 10 */
	 }
      if ( IS_NPC( victim ) )
        thac0 = mob_armor(victim)- victim->npcdata->armor/3 +
                victim->level * 4 + 2;
      else
	thac0 = 0 - (GET_AC(victim) -100 );

      /* Nice AC bonus for improved invis 8/8/98 Martin */
      if(is_affected(victim, gsn_improved_invis) 
        && !(IS_AFFECTED(ch, AFF_DETECT_INVIS) 
        || is_affected(ch, gsn_truesight)))
         thac0 -= 40;

      if ( IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch) )
  	  thac0 -= 20;

      if ( IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) )
  	  thac0 -= 20;

          /* Let's make knife based on dex  -  Chaos  4/23/99  */
      if ( dam_type==gsn_knife )
  	  thac0 += (get_curr_dex(ch)*2 - 35);

      if( OGRE_INTIMIDATE )
          thac0 += (ch->level/10);

      if( victim->position == POS_SLEEPING )
        hit_roll += level/10+5;
      if( victim->position == POS_RESTING )
        hit_roll += level/20+3;

      if( !IS_NPC( ch ) && ch->in_room->sector_type == SECT_ETHEREAL )
        thac0 += 200 - (get_curr_wis( ch ) + get_curr_int( ch )) * 2;
      if( !IS_NPC( ch ) && ch->in_room->sector_type == SECT_ASTRAL )
        thac0 += 100 - get_curr_int( ch ) * 2;

      if( ch->distracted > 0 )
        {
        hit_roll -= level/10+5;
        ch->distracted --;  /* Hey, let's get a bit of our bearings */
        }
      if( victim->distracted > 0 )
        {
        hit_roll += level/7+4;
        victim->distracted --;
        }

      if ( IS_NPC( ch ) )
        diceroll=number_range(0,34+scale*level+hit_roll+GET_HITROLL(ch))+
                       level*2;
      else
        diceroll=number_range(0,39+(scale*level*12)/10
                       +hit_roll+GET_HITROLL(ch))+level*2;

      if ( ch->move<=0 )
	diceroll -= 10;

      if ( !can_see( ch, victim ) )
	diceroll -= 40;

      return( diceroll >= thac0 );
}




/*
 * Hit one guy once.
 */
void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
	OBJ_DATA *wield;
	int dam;

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}
	/*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
	if ( victim->position == POS_DEAD  || ch->in_room != victim->in_room )
		return;
    /*
     * Figure out the weapon doing the damage                   
     * Dual wield support -- switch weapons each attack
     */
    if ( (wield = get_eq_char( ch, WEAR_DUAL_WIELD )) != NULL )
    {
        if ( dual_flip == FALSE )
        {
            dual_flip = TRUE;
            wield = get_eq_char( ch, WEAR_WIELD );
        }
        else
            dual_flip = FALSE;
    }
    else
        wield = get_eq_char( ch, WEAR_WIELD );


    /* Start the cheating check */
      if( IS_NPC( victim ) )
        {
        CHAR_DATA *ch_ld;
        ch_ld = ch;
        if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) && ch->master != NULL )
          ch_ld = ch->master;
        if( ch_ld != NULL && !IS_NPC( ch_ld ) )
          victim->npcdata->pvnum_last_hit = ch_ld->pcdata->pvnum;
        if( ch_ld != NULL )
          {
          if( ch_ld->leader != NULL && !IS_NPC(ch_ld->leader))
            victim->npcdata->pvnum_last_hit_leader = 
                   ch_ld->leader->pcdata->pvnum;
          else
          if( !IS_NPC(ch_ld))
            victim->npcdata->pvnum_last_hit_leader = 
                   ch_ld->pcdata->pvnum;
          }
        }


    /*  Make them a bit tired   */
      if( !IS_NPC( ch ) && ch->move > 0 )
        ch->move--;

	/*
     * Figure out the type of damage message.
     */
	if ( dt == TYPE_UNDEFINED )
	{
		dt = TYPE_HIT;
		if ( wield != NULL && wield->item_type == ITEM_WEAPON )
			dt += wield->value[3];
	}

   /* Use check_hit with no hit_roll modifiers here     - Chaos 17/12/95  */
	if( !check_hit( ch, victim, 0, dt) )
	{
		/* Miss. */

          /* Remove poison from the weapon    -   Chaos 4/20/99  */
        if( wield != NULL && wield->poison != NULL )
          {
          POISON_DATA *npd, *pd;

          for( pd=wield->poison; pd!=NULL; pd=npd )
            {
            npd=pd->next;
            DISPOSE( pd );
            }
          wield->poison = NULL;
          }

	 damage( ch, victim, 0, dt );
	 tail_chain( );
	 return;
	}


         /* Add poison off of item */
    if( wield != NULL && wield->poison != NULL )
     {
     POISON_DATA *npd, *pd;

     if( IS_NPC(ch) || ch->pcdata->pvnum != wield->poison->owner )
       {
       for( pd=wield->poison; pd!=NULL; pd=npd )
         {
         npd=pd->next;
         DISPOSE( pd );
         }
       wield->poison = NULL;
       }
     else
        {
  /*
        npd = wield->poison;
        for( pd=wield->poison; pd != NULL; pd=pd->next )
          {
          if( pd->next != NULL )
            npd = pd->next;
          if( IS_NPC( ch ) )
            pd->poisoner=0;
          else
            pd->poisoner=ch->pcdata->pvnum;
          }
  
        if( IS_NPC( victim) )
          {
          npd->next = victim->npcdata->poison;
          victim->npcdata->poison = wield->poison;
          }
        else
          {
          npd->next = victim->pcdata->poison;
          victim->pcdata->poison = wield->poison;
          }
        wield->poison = NULL;  */

        if( IS_NPC( ch ) )
          wield->poison->poisoner=0;
        else
          wield->poison->poisoner=ch->pcdata->pvnum;

        if( IS_NPC( victim) )
          {
          wield->poison->next = victim->npcdata->poison;
          victim->npcdata->poison = wield->poison;
          }
        else
          {
          wield->poison->next = victim->pcdata->poison;
          victim->pcdata->poison = wield->poison;
          }

        wield->poison = NULL;  

       }
     }
        
   if( !is_affected(ch, gsn_truesight) && has_mirror( ch, victim ) )
    {
    WAIT_STATE( ch, PULSE_VIOLENCE*2 );
    return;
    } 

	/*
     * Hit.
     * Calc damage.
     */
  dam=0;
	if ( IS_NPC(ch) )
    {
		if((wield != NULL)&&(wield->item_type==ITEM_WEAPON))
			dam = dice( wield->value[1], wield->value[2] ) /2 +
			    dice( ch->npcdata->damnodice, ch->npcdata->damsizedice) +
			    ch->npcdata->damplus;
		else
			dam = dice( ch->npcdata->damnodice, ch->npcdata->damsizedice) + 
			    ch->npcdata->damplus;
    }
  else
	  if((wield != NULL)&&(wield->item_type==ITEM_WEAPON))
		  dam = dice( wield->value[1], wield->value[2] );
	  else
		  dam=number_range(1,4+ch->level/6)+ch->mclass[CLASS_MONK]*2/3;

    /*
     * Bonuses.
     */
dam += GET_DAMROLL(ch);
    if ( !IS_NPC(ch) && multi(ch,gsn_enhanced_damage)!=-1 &&
      ch->pcdata->learned[gsn_enhanced_damage] > 0 )
	dam += dam * ch->pcdata->learned[gsn_enhanced_damage] / 250;
/* was *2    now is *1.33   Chaos 10/10/93  */
if ( !IS_AWAKE(victim) )
	dam = 4*dam/3;

if( !IS_NPC( ch ) && ch->in_room->sector_type == SECT_ETHEREAL )
  dam = 2 * dam / 3;
else
if( !IS_NPC( ch ) && ch->in_room->sector_type == SECT_ASTRAL )
  dam = 2 * dam / 3;

if ( dt == gsn_backstab && (multi(ch, gsn_backstab)!=-1 || IS_NPC(ch)))
  {
  if(!IS_NPC(ch))
    dam = dam*(12 + ch->mclass[multi(ch,gsn_backstab)])/10;/* Chaos 11/3/93 */
  else
    dam = dam*(15 + ch->level/4)/10;
  }
if ( dt == gsn_circle && (multi(ch, gsn_circle)!=-1 || IS_NPC(ch)))
  {
    dam = (dam*(12 + ch->mclass[multi(ch,gsn_circle)])/10)/4;
  }
if ( dt == gsn_knife && (multi(ch, gsn_knife)!=-1 || IS_NPC(ch)))
  {
  if(!IS_NPC(ch))
    {
    dam = dam*(30 + ch->mclass[multi(ch,gsn_knife)])/30;/* Order 11/16/93 */
    /* now check to see if it's a critical knife */
    if (!IS_AFFECTED(victim,AFF2_BLEEDING) )
    if(number_percent() < 25 && multi(ch,gsn_critical_hit) != -1 &&
       number_percent() < ch->pcdata->learned[gsn_critical_hit])
      {
      AFFECT_DATA af;
      char ch_col[81];

      af.type      = gsn_critical_hit;
      af.duration  = 0;
      af.modifier  = number_range(5,ch->mclass[multi(ch,gsn_critical_hit)]/1.5);
      af.location  = APPLY_NONE;
      af.bitvector = AFF2_BLEEDING;
      if( !IS_NPC( ch ) )
        victim->critical_hit_by = ch->pcdata->pvnum;
      else
        victim->critical_hit_by = 0;

      affect_join( victim, &af );
      ch_col[0]='\0';
      if(ch->vt100==1 && (ch->ansi==1))
        {
        /* determine color of messages */
        if(ch->pcdata->color[5]!=0)
	  sprintf( ch_col, "\033[1;%d;%dm", ch->pcdata->color[0][5],
	           ch->pcdata->color[1][5]);
        }
      SET_BIT(victim->affected2_by, 0-AFF2_BLEEDING);
      act("$tYou feel particularly satisfied as...",ch,ch_col,NULL,TO_CHAR);
      }
    }
  else
    dam = dam*(30 + ch->level/4)/30;/* Order 11/16/93 */
  }

if ( dam <= 0 )
  dam = 1;
damage( ch, victim, dam, dt );
tail_chain( );
return;
}



void damage_hurt( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
  {
  bool auto_sac, auto_loot;
  bool confused;
  char buf[MAX_INPUT_LENGTH];
  BOUNTY_DATA *bptr;

  /*
   * Hurt the victim.
   * Inform the victim of his new state.
   */
	victim->hit -= dam;
    /*
     * Get experience based on % of damage done                 -Martin
    if ( dam && ch != victim
    &&  !IS_NPC(ch) && ch->fighting && ch->fighting->xp )
    {
	int xp_gain;
        if ( ch->fighting->who == victim )
            xp_gain = (int) (ch->fighting->xp * dam) / victim->max_hit;
        else
            xp_gain = (int) (xp_compute( ch, victim ) * 0.85 * dam) / victim->max_hit;
        gain_exp( ch, xp_gain );
    }  */

	if ( !IS_NPC(victim)
	    &&   victim->level >= LEVEL_IMMORTAL
	    &&   victim->hit < 1 )
		victim->hit = 1;
	if ( !IS_NPC(victim)
	    &&   victim->which_god == GOD_POLICE
	    &&   victim->hit < 1 )
		victim->hit = 1;

         /* Dave is seriously cheating here for Angi
                       - Chaos  4/14/96 
            I guess we forgive you, Martin 18/8/98*/
        if( (IS_AFFECTED( ch, AFF_CHARM) || !IS_NPC( ch )) &&
            !IS_NPC( victim ) &&
            victim->hit < 1 &&
            victim->pcdata->pvnum == 56092 && 
            !strcasecmp(victim->name,"lovely") )
          victim->hit = 1;

      if( ch!=victim )
	update_pos( victim );

	if( victim->position != POS_DEAD && dam>0)
		show_char_to_char_1( victim, NULL);

	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_combat_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_combat_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_combat_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_combat_char( "You have been KILLED!!\n\r\n\r", victim );
		break;

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

 /*
  * Sleep spells and extremely wounded folks.
  */
  if ( !IS_AWAKE(victim) || ch==victim ) 
  if( dt!=TYPE_NOFIGHT )
  {
    if (victim->fighting != NULL
    && victim->fighting->who->hunting != NULL
    && victim->fighting->who->hunting->who == victim)
	stop_hunting(victim->fighting->who);

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

    stop_fighting( victim, FALSE );
  }

  /* Intercept object programs for damaging others */
  if( !IS_NPC( ch ) && dam > 0 && victim->position != POS_DEAD )
  if( dt!=TYPE_NOFIGHT )
    {
    OBJ_DATA *obj;
    OBJ_PROG *prg;
    OBJ_WITH_PROG *with;

    if( ch->desc != NULL )
    for(with=ch->obj_with_prog;with!=NULL;with=with->next)
      {
      if( (obj = with->obj ) == NULL || obj->pIndexData == NULL )
        continue;
      if( ch->obj_prog_ip==0 && obj->pIndexData->obj_prog!=NULL)
	for( prg = obj->pIndexData->obj_prog; prg!=NULL ; prg=prg->next)
	  if( prg->cmd == -6 && number_percent() < prg->percentage )
	    {
            open_timer( TIMER_OBJ_PROG );
	    start_object_program( ch, obj, prg, "");
            close_timer( TIMER_OBJ_PROG );
	    tail_chain();
	    }
      }
    }

/* Intercept object programs for getting damaged */
  if( !IS_NPC( victim ) && dam > 0 && victim->position != POS_DEAD )
    {
    OBJ_DATA *obj;
    OBJ_PROG *prg;
    OBJ_WITH_PROG *with;

    if( victim->desc != NULL )
     for(with=victim->obj_with_prog;with!=NULL;with=with->next)
      {
      if( (obj = with->obj ) == NULL || obj->pIndexData == NULL )
        continue;
      if( victim->obj_prog_ip==0 && obj->pIndexData->obj_prog!=NULL)
	for( prg = obj->pIndexData->obj_prog; prg!=NULL ; prg=prg->next)
	  if( prg->cmd == -5 && number_percent() < prg->percentage )
	    {
            open_timer( TIMER_OBJ_PROG );
	    start_object_program( victim, obj, prg, "");
            close_timer( TIMER_OBJ_PROG );
	    tail_chain();
	    }
      }
    }

    /*
     * Payoff for killing things.
     */
	if ( victim->position == POS_DEAD )
	{
         last_dead = victim;
      if( victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA &&
         !IS_NPC( victim))
      {
      int i;
      if( !IS_NPC( ch))
	{
        if (ch!=victim)
          add_to_victory_list( ch, victim );
        if(( which_god(ch) == GOD_CHAOS || which_god(ch) == GOD_ORDER ||
            which_god(ch) == GOD_DEMISE || which_god(ch) == GOD_POLICE ) &&
          ( which_god(victim) == GOD_CHAOS || which_god(victim) == GOD_ORDER ||
            which_god(victim) == GOD_POLICE ) &&
	  ( which_god( ch)!=0 && which_god(victim)!=0 ) )
	    {
            char buf2 [MAX_INPUT_LENGTH];
            sprintf(buf2, "%s", get_name(ch));

	    victim->pcdata->history[HISTORY_KILL_BY_EN]++;
	    ch->pcdata->history[HISTORY_KILL_EN]++;

            bptr = get_bounty(victim->name);
            if( bptr != NULL)
            {
              gold_transaction( ch, bptr->amount );
              remove_bounty( bptr );
              save_bounties();
              sprintf(buf, "You collect the bounty on %s of %d gold coins.\n\r",
                      capitalize(victim->name), bptr->amount);
              send_to_char(buf, ch);
            }

   	    if (ch->pcdata->clan != NULL && victim->pcdata->clan != NULL )
	    {
  	     ch->pcdata->clan->pkills[which_god(ch)]++;
  	     victim->pcdata->clan->pdeaths[which_god(victim)]++;
	     save_clan( ch->pcdata->clan );
	     save_clan( victim->pcdata->clan );
	    }
   	    ch->hit = ch->max_hit;
            ch->mana = ch->max_mana;
            ch->move = ch->max_move;
/* Stupid highlander reference here.  Removed by Chaos  4/22/99
            act( "Bolts of blue energy rise from the corpse, seeping into $n.", ch, victim->name, NULL, TO_ROOM );
            act( "Bolts of blue energy rise from the corpse, seeping into you.", ch, victim->name, NULL, TO_CHAR ); */
 
            sprintf(buf, "%s has slain %s!", buf2, get_name(victim));
            do_battle(buf);
	    save_char_obj(ch, NORMAL_SAVE);  /*save killer, and killed is saved in raw_kill*/
	    }
        else
        if( check_race_war( ch, victim ) )
          {
	  victim->pcdata->history[HISTORY_LOSE_ARMY]++;
	  ch->pcdata->history[HISTORY_KILL_ARMY]++;

            bptr = get_bounty(victim->name);
            if( bptr != NULL)
            {
              gold_transaction( ch, bptr->amount );
              remove_bounty( bptr );
              save_bounties();
              sprintf(buf, "You collect the bounty on %s of %d gold coins.\n\r",
                      capitalize(victim->name), bptr->amount);
              send_to_char(buf, ch);
            }

   	    if (ch->pcdata->clan != NULL && victim->pcdata->clan != NULL )
 	    {
  	     ch->pcdata->clan->pkills[CLAN_RACE_KILL]++;
	     save_clan( ch->pcdata->clan );
  	     victim->pcdata->clan->pdeaths[CLAN_RACE_DEATH]++;
	     save_clan( victim->pcdata->clan );
	    }
	  save_char_obj(ch, NORMAL_SAVE);  /*save killer, and killed is saved in raw_kill*/
          }
        else if( victim != ch )
	    {
	    victim->pcdata->history[HISTORY_KILL_BY_PC]++;
	    ch->pcdata->history[HISTORY_KILL_PC]++;

            bptr = get_bounty(victim->name);
            if( bptr != NULL)
            {
              gold_transaction( ch, bptr->amount );
              remove_bounty( bptr );
              save_bounties();
              sprintf(buf, "You collect the bounty on %s of %d gold coins.\n\r",
                      capitalize(victim->name), bptr->amount);
              send_to_char(buf, ch);
            }

   	    if (ch->pcdata->clan != NULL && victim->pcdata->clan != NULL )
   	    {
  	     ch->pcdata->clan->pkills[CLAN_ASSASSINATE_KILL]++;
	     save_clan( ch->pcdata->clan );
  	     victim->pcdata->clan->pdeaths[CLAN_ASSASSINATE_DEATH]++;
	     save_clan( victim->pcdata->clan );
	    }
   	     save_char_obj(ch, NORMAL_SAVE);  /*save killer, and killed is saved in raw_kill*/
	    }
       
         if (victim != ch) 
         {
           i=ch->pcdata->killnum-1;
           if (i<0) i=MAX_KILL_TRACK-1;
           STRFREE (ch->pcdata->killname[i] );
           sprintf(buf, "Z%12s (%dx Level %2d) on %s", victim->name, victim->pcdata->reincarnation, victim->level, (char *) ctime( &current_time)); 
           buf[strlen(buf)-1]='\0';
           ch->pcdata->killname[i] = STRALLOC(buf);
           ch->pcdata->killnum=i;
         }
	}
     else
      {
       victim->pcdata->history[HISTORY_KILL_BY_NPC]++;
       if (victim->pcdata->clan != NULL) 
        {
  	 victim->pcdata->clan->mdeaths++;
	 save_clan( victim->pcdata->clan );
    	}
      }
     }
  
     if(IS_NPC(victim) && !IS_NPC(ch) && ch->pcdata->clan != NULL) 
      {
        ch->pcdata->clan->mkills++;
      }
     if ( !IS_NPC(victim)  )
      {
       sprintf( log_buf, "%s killed by %s at %u",
	                  victim->name, get_name( ch ), 
		          victim->in_room->vnum );
       log_string( log_buf );

       if (victim->level < 2)
	gain_exp( victim, 0-(victim->exp/2));
       else
       if(victim->exp>exp_level(victim->class,(victim->level)-1 )+1)
        gain_exp( victim, exp_level(victim->class, (victim->level)-1 )+1 -
		   victim->exp);

        if( victim->level == 91   && victim->pcdata->death_timer == 0 &&
          victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA)
             /* Knights Death     - Chaos 9/14/95 */
          {
          victim->max_hit -= 20 * (victim->pcdata->reincarnation + 3 ) / 3;
          victim->actual_max_hit -= 20 * (victim->pcdata->reincarnation + 3 ) / 3;
          victim->pcdata->death_timer = 2;
           save_char_obj(ch, NORMAL_SAVE);
          }
        if( victim->level > 91 && victim->level < 96  &&
            victim->pcdata->death_timer == 0 &&
             victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA)
          {
          int add_hp, add_mana, add_move;
          victim->level --;
          victim->mclass[ victim->class ]  --;
          add_hp = 130;
          add_mana = 100;
          add_move = 85;
          add_hp      *= (victim->pcdata->reincarnation + 2 ) / 2;
          add_mana    *= (victim->pcdata->reincarnation + 3 ) / 3;
          add_move    *= (victim->pcdata->reincarnation + 3 ) / 3;

          victim->max_hit -= add_hp;
          victim->max_move -= add_mana;
          victim->max_mana -= add_move;
          victim->actual_max_hit -= add_hp;
          victim->actual_max_move -= add_mana;
          victim->actual_max_mana -= add_move;

          knight_adjust_hpmnmv( victim );

		  if(victim->exp>exp_level(victim->class,(victim->level)-1 )+1)
	  gain_exp( victim, exp_level(victim->class, (victim->level)-1 )+1 -
		   victim->exp);

          REMOVE_BIT( ch->act, PLR_THIEF);
          sub_player( ch);
          add_player( ch);
          victim->pcdata->death_timer = 2;
          save_char_obj(ch, NORMAL_SAVE);
          save_char_obj(ch, BACKUP_SAVE);
          }


       if( victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA)
        if(IS_SET(victim->act, PLR_KILLER) || IS_SET(victim->act, PLR_THIEF))
         {
          if(victim->level>1)
	    if(victim->exp>exp_level(victim->class, (victim->level)-2 )+1)
	      gain_exp( victim, exp_level(victim->class, (victim->level)-2 )+1-
		   victim->exp);
          if(victim->level<2)
	      gain_exp( victim, -victim->exp);
          if(IS_SET(victim->act, PLR_KILLER))
            victim->act-=PLR_KILLER;
          if(IS_SET(victim->act, PLR_THIEF))
            victim->act-=PLR_THIEF;
          }
        }
   else
	  group_gain( ch, victim );

	  if (IS_NPC(victim)&&(victim == ch))
             {
             if( victim->position == POS_DEAD )
               raw_kill( victim ) ;
	     return;
             }

    if( !confused )
      set_fighting(victim, ch);
    /*victim->fighting->who=ch;  -Presto 3/28/99*/


        auto_loot = FALSE;
        auto_sac = FALSE;
	if ( !IS_NPC(ch) && IS_NPC(victim) )
            {
            if ( IS_SET(ch->act, PLR_AUTOSAC) )
              auto_sac = TRUE;
            if ( IS_SET(ch->act, PLR_AUTOLOOT)|| IS_SET( ch->act,
			    PLR_AUTO_SPLIT) )
              auto_loot = TRUE;
            }

      if( !IS_NPC( ch ) && !IS_NPC( victim ) && 
          ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA )
        {
        PLAYER_GAME *gpl;
        sprintf( buf, "%s has killed %s.\n\r", ch->name, victim->name );
      for( gpl = first_player ; gpl != NULL; gpl = gpl->next )
         if( gpl->ch != ch && gpl->ch != victim && 
             gpl->ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA )
           send_to_combat_char( buf, ch );
         }
          
         /* keep track of mob vnum killed */
        /* 
        if ( !IS_NPC(ch) )       
            add_kill( ch, victim );
           */

#ifdef AREA_KILL
  if( IS_NPC( victim) && !IS_NPC(ch ) )
    {
    int anum;
    anum = victim->pIndexData->area->low_r_vnum/100;
    ch->pcdata->area_kills[ anum ]++;
    }
#endif

         raw_kill( victim );

        if ( auto_loot )
        {
          FIGHT_DATA *fptr;

          fptr=ch->fighting;
          ch->fighting=NULL;
	  do_get( ch, NULL );
          ch->fighting=fptr;
        }

        if( auto_sac )
	  do_sacrifice( ch, "corpse" );

        if( !IS_NPC( ch ) )
         if(ch->vt100==1 && IS_SET( ch->act, PLR_PROMPT))
          vt100prompt( ch );

		return;
	}


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

	if ( !IS_NPC(victim)
	    &&   victim->hit > 0
	    &&   victim->hit <= victim->wimpy
	    &&   victim->wait == 0 )
             {
		 if( victim->desc!=NULL)
                   {
                   if( victim->desc->back_buf != NULL )
                     {
                     int leny;
                     leny=str_cpy_max( buf, victim->desc->back_buf, 
                            MAX_STRING_LENGTH );
                     leny=str_apd_max( buf, "\rflee\r", leny,
                            MAX_STRING_LENGTH );
                     STRFREE(victim->desc->back_buf );
                     victim->desc->back_buf = str_dup( buf );
                     }
                   else
		    victim->desc->intop = str_apd_max( victim->desc->inbuf,
                         "\rflee\r", victim->desc->intop, MAX_INPUT_LENGTH);
                   }
		 /* This particular set of code will stop fights
                 else
		   do_flee( victim, "" );*/
            }

        if( !IS_NPC( ch ) )
         if(ch->vt100==1 && IS_SET( ch->act, PLR_PROMPT))
          vt100prompt( ch );

        if( !IS_NPC( victim ) )
         if(victim->vt100==1 && IS_SET( victim->act, PLR_PROMPT))
          vt100prompt( victim );

	tail_chain( );
	return;
}

void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
  /* char buf[MAX_INPUT_LENGTH]; */
  bool confused;

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

  if( ch==NULL )
    ch=victim;

  confused = FALSE;

  if( dt!=TYPE_NOFIGHT )
    switch(ch->position)
      {
      case POS_SLEEPING:
      case POS_RESTING:
        do_stand(ch,"");
        return;
        break;
      case POS_STANDING:
        ch->position=POS_FIGHTING;
        break;
      }

  /* Disallow fighting in shops */
  if(find_keeper(ch)!=NULL && dt!=TYPE_NOFIGHT)
  {
    stop_fighting(ch, TRUE);
    return;
  }

  if( ch->fighting==NULL && ch!=victim  && dt!=TYPE_NOFIGHT)
    set_fighting(ch,victim);
  if( victim->fighting==NULL && ch!=victim  && dt!=TYPE_NOFIGHT)
    set_fighting(victim,ch);


      /* Confusion spell   - Chaos  7/26/96 */
  if( IS_AFFECTED( ch, AFF2_CONFUSION ) && number_range(0,2)==0  
      && dt!=TYPE_NOFIGHT)
    {
    CHAR_DATA *fch;
    int tch, pch;

    for( tch=0, fch=ch->in_room->first_person; fch != NULL; fch=fch->next_in_room )
      {
          if (IS_AFFECTED( fch, AFF_ETHEREAL ))
            continue; /* Stop confused ppl being so confused they start 
			 attacking ethereals - Martin */
          if(IS_AFFECTED( fch,AFF2_MIRROR_IMAGE))
            continue; /* Stop very strange behaviour when confused person
			 strikes mirrored person... - Martin */
          if(!is_same_group(ch, fch))
            continue;
      if( fch != ch )
        tch++;
      }

    if( tch > 1 )
      {
      pch = number_range( 1, tch );
      for( tch=0, fch=ch->in_room->first_person; fch != NULL; fch=fch->next_in_room )
        if( fch != ch )
          {
          if (IS_AFFECTED( fch, AFF_ETHEREAL ))
            continue; /* Stop confused ppl being so confused they start 
			 attacking ethereals - Martin */
          if(IS_AFFECTED( fch,AFF2_MIRROR_IMAGE))
            continue; /* Stop very strange behaviour when confused person
			 strikes mirrored person... - Martin */
          if(!is_same_group(ch, fch))
            continue;
          tch++;
          if( tch == pch )
            {
            victim = fch;
            confused = TRUE;
            break;
            }
          }
      }
    }

    /* Start the cheating check */
      if( IS_NPC( victim ) && victim!=ch && !confused && dam>0 &&
          dt!=TYPE_NOFIGHT)
        {
        CHAR_DATA *ch_ld;
        ch_ld = ch;
        if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) && ch->master != NULL )
          ch_ld = ch->master;
        if( ch_ld != NULL && !IS_NPC( ch_ld ) )
          victim->npcdata->pvnum_last_hit = ch_ld->pcdata->pvnum;
        if( ch_ld != NULL )
          {
          if( ch_ld->leader != NULL && !IS_NPC(ch_ld->leader))
            victim->npcdata->pvnum_last_hit_leader = 
                   ch_ld->leader->pcdata->pvnum;
          else
          if( !IS_NPC(ch_ld))
            victim->npcdata->pvnum_last_hit_leader = 
                   ch_ld->pcdata->pvnum;
          }
        }

  if( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) )
    if( ch->in_room->sector_type == SECT_ETHEREAL || 
        ch->in_room->sector_type == SECT_ASTRAL )
      if( dt != TYPE_HIT && dt != TYPE_UNDEFINED)
        {
        dam = 4 * dam / 7;
        }

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

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

  /*
   * Stop up any residual loopholes.
   *  Modified moving dam cap  -  Chaos  4/27/99
   */
    {
    int dam_cap;

    if ( dt == gsn_backstab &&  dam > 1600 &&
         number_percent()<ch->pcdata->learned[gsn_greater_backstab] ) 
        dam_cap = 800+ch->level*10;
    else
        dam_cap = 800+ch->level*6;

	if ( dam > dam_cap)
          dam = dam_cap;
    }


	if ( victim != ch )
	{

        /*
	 * Certain attacks are forbidden.
	 * Most other attacks are returned.
	 */
                if ( is_safe( ch, victim ) && dt!=TYPE_NOFIGHT)
	          return;

		if ( ( dt < 0 || dt > MAX_SKILL || !is_spell(dt) ) && 
                   dt!=TYPE_NOFIGHT &&
              ( !is_affected(ch, gsn_truesight) && has_mirror( ch, victim ) ) )
                  return;


		if ( victim->position > POS_STUNNED && ch!=victim &&
                     dt!=TYPE_NOFIGHT )
		{
			if ( victim->fighting == NULL && !confused )
				set_fighting( victim, ch );
		}

		if ( ch->position > POS_STUNNED && ch!=victim &&
                     dt!=TYPE_NOFIGHT )
		{
			if ( ch->fighting == NULL && !confused )
				set_fighting( 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 
                            &&   dt!=TYPE_NOFIGHT )
			{
				stop_fighting( ch, TRUE );
				multi_hit( ch, victim->master, TYPE_UNDEFINED
				    );
				return;
			}
		}


        /*
	 * Inviso attacks ... not.
	 */
	/* Stuff like starvation and poison shouldn't take them out of
	   stealth or invis ... Martin 9/2/99 */
	if (dt != TYPE_NOMESSAGE && dt!=TYPE_NOFIGHT)
	{
		if ( IS_AFFECTED(ch, AFF_HIDE) )
		  {
		  affect_strip( ch, gsn_hide );
		  REMOVE_BIT( ch->affected_by, AFF_HIDE );
		  act( "$n steps out from $s hiding spot.", ch, NULL, NULL,
			      TO_ROOM );
		  act( "You step out from your hiding spot.", ch, NULL, NULL,
			      TO_CHAR );
		  }

		if ( IS_AFFECTED(ch, AFF_STEALTH) )
		{
			affect_strip( ch, gsn_stealth );
			affect_strip( ch, gsn_greater_stealth );
			REMOVE_BIT( ch->affected_by, AFF_STEALTH );
			act( "$n steps out into the room.", ch, NULL, NULL,
			    TO_ROOM );
			act( "You step out into the room .", ch, NULL, NULL,
			    TO_CHAR );
		}

		if ( IS_AFFECTED(ch, AFF_INVISIBLE) )
		{
			affect_strip( ch, gsn_invis );
			affect_strip( ch, gsn_mass_invis );
                        if (!is_affected(ch, gsn_improved_invis) )
 			{
			 REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
			 act( "$n fades into existence.", ch, NULL, NULL,
			    TO_ROOM );
 			}
		}
 	}
	/*
	 * Damage modifiers.
	 */
		if ( IS_AFFECTED(victim, AFF_SANCTUARY) )
			dam = dam * 2/3;

    /* Gith Damage +25% astral, +10% ethereal, -10% material plane */
    if(ch->race == RACE_GITH && ch->in_room != NULL)
    {
      if(ch->in_room->sector_type == SECT_ASTRAL)
        dam = dam * 5/4;
      else if(ch->in_room->sector_type == SECT_ETHEREAL)
        dam = dam * 11/10;
      else
        dam = dam * 9/10;
    }

/*
  		Changing effect of protection...adding protection from good
		- Martin 10/8/98
		if ( IS_AFFECTED(victim, AFF_PROTECT) && IS_EVIL(ch) )
			dam -= dam * 1/3;
*/
		if ( dam < 0 )
			dam = 0;

	/*
	 * Check for disarm, trip, parry, and dodge.
	 */
	      if ( dt >= TYPE_HIT) 
		{
			if ( IS_NPC(ch) && number_percent( ) < (ch->level / 20 + 1) )
					trip( ch, victim );
			if ( check_parry( ch, victim ) )
				return;
			if ( check_dodge( ch, victim ) )
				return;
			if ( IS_NPC(ch) && number_percent( ) < (ch->level / 30 + 1) )
					disarm( ch, victim );
	                if (IS_AFFECTED(victim, AFF2_FIRESHIELD))
                        {
       			    
        		 damage(victim, ch, UMAX(1, number_fuzzy(dam/4)), gsn_fire_shield);
  			 if (ch==last_dead) return;
                        }
		}
                 
               if (dt != gsn_anatomy) 
		dam_message( ch, victim, dam, dt );
           }
          else if (dt != gsn_anatomy) 
	    dam_message( ch, victim, dam, dt );

        if (dt == gsn_anatomy)
           dam=victim->hit;

    /*  Adjust damage based on monster kills  - Chaos  5/17/99  */
#ifdef AREA_KILL
  if( IS_NPC( victim) && !IS_NPC(ch ) )
    {
    int anum;
    anum = victim->pIndexData->area->low_r_vnum/100;
    if( ch->pcdata->area_kills[ anum ]>250 )
      dam = dam * 500 / ( 250 + ch->pcdata->area_kills[ anum ] );
    }
#endif

    damage_hurt( ch, victim, dam, dt );

#ifdef EQUIPMENT_DAMAGE

      /* Armor damage  - Chaos  4/17/99  */
    if( dam>0 && dt == TYPE_HIT )
      if( number_range( 0, 2000 ) < (170-ch->level)/5 )
        damage_equipment( victim , FALSE );

      /* Weapon damage */
    if( dam>0 && dt == TYPE_HIT )
      if( number_range( 0, 20000 ) < (170-ch->level)/5 )
        damage_equipment( ch , TRUE );
#endif

    return;
}


bool has_mirror(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(IS_AFFECTED(victim,AFF2_MIRROR_IMAGE))
    {
    AFFECT_DATA *paf;
    bool all;

       /* Let's make intelligence define who sees images */
    if( number_range( 10, 60) < get_curr_int( ch ) )
      all = TRUE;
    else
      all = FALSE;

    for ( paf = victim->first_affect; paf != NULL; paf = paf->next)
      {
      if(paf->bitvector==AFF2_MIRROR_IMAGE)
        {
        if(all)
          {
          affect_strip(victim,paf->type);
          }
        else
        if(number_range(0,paf->modifier)!=0)
          {
          act("You destroy $N in one blow!  Huh?",ch,NULL,victim,TO_CHAR);
          act("$n destroys $N in one blow!",ch,NULL,victim,TO_ROOM);

          paf->modifier-=1;
          if(paf->modifier==0)
            affect_strip(victim,paf->type);
          if( ch!=victim )
            set_fighting( ch, victim );
          if( ch!=victim )
            set_fighting( victim, ch );
          return TRUE;
          }
        break;
        }
      }
    if(all)
      {
      act("You discover the real $N.",ch,NULL,victim,TO_CHAR);
      act("$N's images disappear.",ch,NULL,victim,TO_ROOM);
      set_fighting( ch, victim );
      set_fighting( victim, ch );
      }
    }
  return FALSE;
}

bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{
	if ( IS_NPC(ch) || IS_NPC(victim) )
		return FALSE;

	/* Thx Josh! */
	if ( victim->fighting && who_fighting( victim ) == ch )
		return FALSE;

        if(victim->mclass[CLASS_ASSASSIN] == victim->level &&
           victim->level!=95 && IS_SET(victim->act, PLR_KILLER) &&
           ch->level <= victim->level+10)
          return FALSE;

	if ( ch->level/2 > victim->level )
	{
		send_to_combat_char( "You may not attack that low of a level player.\n\r",
		    ch );
		return TRUE;
	}

	return FALSE;
}


/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
    /*
     * NPC's are fair game.
     */
	if ( (IS_NPC(victim) && !IS_AFFECTED(victim, AFF_CHARM))
     || ch->in_room->area->low_r_vnum==ROOM_VNUM_ARENA)
		return;

     if ( which_god(victim) == GOD_DEMISE ) 
         return;

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

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

		send_to_combat_char( "*** You are now a KILLER!! ***\n\r", ch->master
		    );
		SET_BIT(ch->master->act, PLR_KILLER);
                ch->master->killer_played=ch->master->played;
		/*      stop_follower( ch );  */
		return;
	}

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

	send_to_combat_char( "*** You are now a KILLER!! ***\n\r", ch );
	if(ch->desc->original!=NULL)
	{
		SET_BIT(ch->desc->original->act, PLR_KILLER);
                ch->desc->original->killer_played=ch->desc->original->played;
		save_char_obj(ch->desc->original, NORMAL_SAVE);
	}
	else
	{
		SET_BIT(ch->act, PLR_KILLER);
                ch->killer_played=ch->played;
		save_char_obj(ch, NORMAL_SAVE);
	}
	return;
}



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

	if ( !IS_AWAKE(victim) )
		return FALSE;

	if ( IS_NPC(victim) )
	{
		/* Tuan was here.  :) */
		chance  = UMIN( 30, victim->level/2+5 );
	}
	else
	{
          if( multi(victim, gsn_parry) == -1 )
            return( FALSE );

		if ( get_eq_char( victim, WEAR_WIELD ) == NULL )
			return FALSE;
		chance  = victim->pcdata->learned[gsn_parry]/2;
	}

      if( OGRE_INTIMIDATE )
        chance -= 13;

	if ( number_percent( ) >= chance + (victim->level - ch->level)/4 )
		return FALSE;

	if( IS_SET( victim->attack, 2))
		return FALSE;
	else
		victim->attack+=2;

     if( IS_NPC( victim ) || !IS_SET( victim->pcdata->spam, 8))
	act( "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
     if( IS_NPC( ch ) || !IS_SET( ch->pcdata->spam, 2))
	act( "$N parries your attack.", ch, NULL, victim, TO_CHAR    );
	return TRUE;
}



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

	if ( !IS_AWAKE(victim) )
		return FALSE;

	if ( IS_NPC(victim) )
		/* Tuan was here.  :) */
		chance  = UMIN( 25, victim->level/3+5 );
	else
          {
          if( multi(victim, gsn_dodge) == -1 )
            return( FALSE );
		chance  = victim->pcdata->learned[gsn_dodge] / 3;
	  }

      if( OGRE_INTIMIDATE )
        chance -= 10;

	if ( number_percent( ) >= chance + (victim->level - ch->level)/4 )
		return FALSE;

	if ( IS_SET( victim->attack, 4))
		return FALSE;
	else
		victim->attack+=4;

     if( IS_NPC( victim ) || !IS_SET( victim->pcdata->spam, 8))
	act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT    );
     if( IS_NPC( ch ) || !IS_SET( ch->pcdata->spam, 2))
	act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR    );
	return TRUE;
}



/*
 * Set position of a victim.
 */
void update_pos( CHAR_DATA *victim )
{
  if ( victim->hit > 0 )
  {
    if ( victim->position <= POS_STUNNED )
      victim->position = POS_STANDING;
	return;
  }

	if ( IS_NPC(victim) || victim->hit <= -11 )
	{
		victim->position = POS_DEAD;
		return;
	}

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

  if(( victim->position < POS_RESTING || victim->position == POS_FIGHTING ) &&
         in_camp(victim))
    {
    CHAR_DATA *gch;
    for(gch=victim->in_room->first_person;gch!=NULL;gch=gch->next_in_room)
      if(is_same_group(victim,gch) && IS_AFFECTED(gch,AFF2_CAMPING))
        {
        send_to_combat_char( "Your camp is destroyed!\n\r", victim );
        REMOVE_BIT(gch->affected2_by, 0-AFF2_CAMPING);
        break;
        }
    }
  return;
}

void add_kill( CHAR_DATA *ch, CHAR_DATA *mob )
{
    int x;
    sh_int vnum;

    return;

    if ( IS_NPC(ch) )
    {
        bug( "add_kill: trying to add kill to npc", 0 );
        return;
    }
    if ( !IS_NPC(mob) )
    {
        bug( "add_kill: trying to add kill non-npc", 0 );
        return;
    }
    vnum = mob->pIndexData->vnum;
    for ( x = 0; x < MAX_MOB_KILL_TRACK; x++ )
        if ( ch->pcdata->killed[x].vnum == vnum )
        {
            if ( ch->pcdata->killed[x].count < 50 )
                ++ch->pcdata->killed[x].count;
            return;
        }
        else
        if ( ch->pcdata->killed[x].vnum == 0 )
            break;
    memmove( (char *) ch->pcdata->killed+sizeof(KILLED_DATA),
                ch->pcdata->killed, (MAX_MOB_KILL_TRACK-1) * sizeof(KILLED_DATA) );
    ch->pcdata->killed[0].vnum  = vnum;
    ch->pcdata->killed[0].count = 1;
}

int times_killed( CHAR_DATA *ch, CHAR_DATA *mob )
{
    int x;
    sh_int vnum;

    return(0);

    if ( IS_NPC(ch) )
    {
        bug( "times_killed: ch is not a player", 0 );
        return 0;
    }
    if ( !IS_NPC(mob) )
    {
        bug( "times_killed: mob is not a mobile", 0 );
        return 0;
    }

    vnum = mob->pIndexData->vnum;
    for ( x = 0; x < MAX_MOB_KILL_TRACK; x++ )
        if ( ch->pcdata->killed[x].vnum == vnum )
            return ch->pcdata->killed[x].count;
        else
        if ( ch->pcdata->killed[x].vnum == 0 )
            break;

    return 0;
}

void free_fight( CHAR_DATA *ch )
{
   if ( ch==NULL )
   {
        bug( "Free_fight: null ch!", 0 );
        return;
   }
   if ( ch->fighting!=NULL )
   {
     if ( !ch->fighting->who && ch->fighting->who != last_dead )
       --ch->fighting->who->num_fighting;
     DISPOSE( ch->fighting );
   }
   ch->fighting = NULL;
   ch->position = POS_STANDING;
   ch->asn_obj  = NULL;
   return;
}

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

  if( ch==victim )
    return;

  if ( ch->fighting != NULL )
    {
/*
    log_printf("Set_fighting: %s -> %s (already fighting %s)",
	ch->name, victim->name, ch->fighting->who->name ); */
    return;
    }

  if ( IS_AFFECTED(ch, AFF_SLEEP) )
    affect_strip( ch, gsn_sleep );
   CREATE( fight, FIGHT_DATA, 1 );
   fight->who   = victim;
   fight->xp    =  0;
   /* fight->xp    = (int) xp_compute( ch, victim ) * 0.85; */
   if ( !IS_NPC(ch) && IS_NPC(victim) )
     fight->timeskilled = times_killed(ch, victim);
   ch->num_fighting = 1;
   ch->fighting = fight;
   victim->num_fighting++;

  ch->position = POS_FIGHTING;
  update_pos( ch );

  return;
}


/*
 * Make a corpse out of a character.
 */
void make_corpse( CHAR_DATA *ch )
{
  char buf[MAX_INPUT_LENGTH];
  OBJ_DATA *corpse;
  OBJ_DATA *obj;
  OBJ_DATA *obj_next;
  CHAR_DATA *fch;
  char *name;

  if( IS_NPC( ch ) && IS_SET( ch->act, ACT_UNDEAD ) )
    {
    for ( obj = ch->first_carrying; obj != NULL; obj = obj_next )
      {
      obj_next = obj->next_content;
      obj_from_char( obj );
      if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
        extract_obj( obj );
      else
        obj_to_room( obj, ch->in_room );
      }
    return;
    }

  if ( IS_NPC(ch) )
    {
    name            = ch->short_descr;
    corpse          = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0);
    corpse->timer   = number_range( 2, 4 );
    corpse->level   = ch->level;
    if( ch->fighting != NULL)
      {
      if( IS_NPC(ch->fighting->who) && IS_AFFECTED( ch->fighting->who, AFF_CHARM))
        if( !IS_NPC( ch->fighting->who->master))
          corpse->owned_by = ch->fighting->who->master->pcdata->pvnum;
      if( !IS_NPC( ch->fighting->who))
        corpse->owned_by = ch->fighting->who->pcdata->pvnum;
      if( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM) && ch->master!=NULL &&
          ch->master->pcdata!=NULL )
        corpse->owned_by = ch->master->pcdata->pvnum;
      }
    else
      corpse->owned_by=-1;
    if ( ch->gold > 0 )
      {
      obj_to_obj( create_money( ch->gold ), corpse );
      ch->gold = 0;
      }
    }
  else
    {
    name            = ch->name;
    corpse          = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
    corpse->timer   = number_range( 50, 80 );
    if( ch->pcdata->corpse==NULL)
      {
      ch->pcdata->corpse=corpse;
      ch->pcdata->corpse_room=ch->in_room->vnum;
      }
    corpse->owned_by= ch->pcdata->pvnum;

    for( fch=first_char; fch!=NULL; fch=fch->next)
      if( IS_NPC(fch) && fch->master==ch && IS_SET( fch->act, ACT_PET ) )
        SET_BIT( fch->act, ACT_WILL_DIE);
    }

  sprintf( buf, corpse->short_descr, name );
  STRFREE (corpse->short_descr );
  corpse->short_descr = STRALLOC( buf );

  sprintf( buf, "corpse %s", ch->name );
  STRFREE (corpse->name );
  corpse->name = STRALLOC( buf );

  sprintf( buf, corpse->description, name );
  STRFREE (corpse->description );
  corpse->description = STRALLOC( buf  );
  
  for ( obj = ch->first_carrying; obj != NULL; obj = obj_next )
    {
    obj_next = obj->next_content;
    /* modification to keep object with character -Dug 12/4/93 */
    if(!IS_SET(obj->extra_flags, ITEM_INVENTORY) && can_drop_obj(ch, obj))
      {
      obj_from_char( obj );
      if( IS_NPC( ch ))
        if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
          extract_obj( obj );
      obj_to_obj( obj, corpse );
      }
    }

  obj_to_room( corpse, ch->in_room );
  if( !IS_NPC( ch ) )
  {
    ch->pcdata->time_of_death = current_time;
    ch->pcdata->just_died_ctr = 300; /* 5 minutes */
    ch->pcdata->condition[COND_FULL] = 20;
    ch->pcdata->condition[COND_THIRST] = 20;
    send_to_combat_char( "Your perils have ended in defeat.\n\r", ch);
  }

  return;
}



/*
 * Improved Death_cry contributed by Diavolo.
 */
void death_cry( CHAR_DATA *ch )
{
	ROOM_INDEX_DATA *was_in_room;
	char *msg;
	int door;
	int vnum;
	int ran;
	bool IS_BODY;

  /* check for null ch  -Presto 3/28/99 */
  if (ch == NULL)
  {
    bug("null ch in death_cry.",0);
    return;
  }

	ran = number_bits( 4 );
	vnum = 0;
      IS_BODY = ( IS_NPC( ch ) && IS_SET( ch->pIndexData->act, ACT_BODY )  &&
	    ch->pIndexData->body_parts!=0);

      if( IS_BODY  && number_bits(2)==0  && !IS_SET( ch->act, ACT_UNDEAD))
	  {
	  int dir, cnt;

          
	  ran=number_range( 0, MAX_BODY -1);
	  dir=(number_range(0,1)*2)-1;
          cnt=0;
	  while( !IS_SET( ch->pIndexData->attack_parts, 1<<ran) &&
                 cnt<MAX_BODY  )
	    {
            cnt++;
	    ran+=dir;
	    if(ran<0)
	      ran=MAX_BODY-1;
	    if(ran>=MAX_BODY)
	      ran=0;
	    }
          if( cnt==MAX_BODY )
	     msg  = "$n splatters blood on your armor.";             
          else
             {
	     vnum = OBJ_VNUM_SLICED_LEG;                           
	     msg = body_table[ran].sliced;
             }
	  }
     else
       msg  = "You hear $n's death cry.";                               


   if( IS_SET( ch->act, ACT_UNDEAD ) )
     {
     vnum = 0;
     ran = 7;
     }

     if( vnum==0 )
      switch ( ran )
	{
	default: 
		break;
	case  0: 
		msg  = "$n hits the ground ... DEAD.";                  
		break;
	case  1: 
		msg  = "$n splatters blood on your armor.";             
		break;
	case  2: 
	       if(IS_BODY)
		 break;
		msg  = "You smell $n's sphincter releasing in death.";
		vnum = OBJ_VNUM_FINAL_TURD;                             
		break;
	case  3: 
	       if(IS_BODY)
		 break;
		msg  = "$n's severed head plops on the ground.";
		vnum = OBJ_VNUM_SEVERED_HEAD;                           
		break;
	case  4: 
	       if(IS_BODY)
		 break;
		msg  = "$n's heart is torn from $s chest.";
		vnum = OBJ_VNUM_TORN_HEART;                             
		break;
	case  5: 
	       if(IS_BODY)
		 break;
		msg  = "$n's arm is sliced from $s dead body.";
		vnum = OBJ_VNUM_SLICED_ARM;                             
		break;
	case  6: 
	       if(IS_BODY)
		 break;
		msg  = "$n's leg is sliced from $s dead body.";
		vnum = OBJ_VNUM_SLICED_LEG;                             
		break;
         case 7:
             msg = "$n turns to dust.";
             break;
	}
       if (!IS_SET(ch->act, ACT_ELEMENTAL))
	act( msg, ch, NULL, NULL, TO_ROOM );

	if ( vnum != 0 )
	{
		char buf[MAX_INPUT_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 );

	     if( IS_BODY )
		sprintf( buf, body_table[ran].short_descr, name );
	     else
		sprintf( buf, obj->short_descr, name );
	     STRFREE (obj->short_descr );
	     obj->short_descr = STRALLOC( buf );

	     if( IS_BODY )
		sprintf( buf, body_table[ran].description, name );
	     else
		sprintf( buf, obj->description, name );
		STRFREE (obj->description );
		obj->description = STRALLOC(  buf );

	     if( IS_BODY )
		{
		sprintf( buf, body_table[ran].name, name );
		STRFREE (obj->name );
		obj->name = STRALLOC( buf );
		sprintf( buf, body_table[ran].long_descr, name );
		STRFREE (obj->long_descr );
		obj->long_descr = STRALLOC( buf );
		}

		obj_to_room( obj, ch->in_room );
	}

	if ( IS_NPC(ch) )
		msg = "You hear something's death cry.";
	else
		msg = "You hear someone's death cry.";

	was_in_room = ch->in_room;
	for ( door = 0; door <= 5; door++ )
	{
		EXIT_DATA *pexit;

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

	return;
}



void raw_kill( CHAR_DATA *victim )
{
  ROOM_INDEX_DATA *old_room;
  CHAR_DATA *fch;

  for( fch=first_char; fch != NULL; fch=fch->next )
    {
    if( who_fighting(fch) == victim && 
	IS_AFFECTED( fch, AFF_CHARM) &&
        IS_NPC( fch) && 
	IS_SET( fch->act, ACT_ONE_FIGHT) )
      SET_BIT( fch->act, ACT_WILL_DIE);
     
    if( IS_NPC( fch) && IS_AFFECTED( fch, AFF_CHARM ) &&
         fch->master == victim && victim != fch )
      {
      /*fch->fighting->who=fch->master;*/
      raw_kill( fch );
      }
    }


  if(IS_NPC(victim))
     mprog_death_trigger(victim);/* This must be before make_corpse */
  else     /* check for assassin stuff */
     {
      check_asn_obj(victim);/* This must be before make_corpse */
      if( victim->fighting!=NULL)
        mprog_kill_trigger(victim->fighting->who);
     } 

  if( ( victim->pcdata != NULL && victim->pcdata->poison != NULL ) ||
      ( victim->npcdata != NULL && victim->npcdata->poison != NULL ) )
            {
            POISON_DATA *pd, *ppd;
            if( IS_NPC( victim ) )
              pd = victim->npcdata->poison;
            else
              pd = victim->pcdata->poison;
            for( ; pd!=NULL; pd=ppd )
              {
              ppd = pd->next;
              DISPOSE( pd );
              }
            if( IS_NPC( victim ) )
              victim->npcdata->poison=NULL;
            else
              victim->pcdata->poison=NULL;
            }

  make_corpse( victim );
  old_room=victim->in_room;

  if ( IS_NPC(victim) )
    {
    if( IS_SET( victim->act, ACT_PET) && victim->master!=NULL
        && !IS_SET( victim->act, ACT_ELEMENTAL) )
      send_to_combat_char("Your pet dies a horrible death.\n\r", victim->master);
    victim->pIndexData->killed++;
    kill_table[URANGE(0, victim->level, MAX_LEVEL-1)].killed++;
    leave_fighting( victim, old_room);
    extract_char( victim, TRUE );
    return;
    }
  leave_fighting( victim, old_room);
  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, NORMAL_SAVE);

  return;
}



void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
  char buf[MAX_INPUT_LENGTH];
  CHAR_DATA *gch;
  CHAR_DATA *lch;
  int xp;
  int levelst;
  OBJ_DATA *obj, *tmpobj;
  OBJ_DATA *obj_next;


  /*
   * 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!
   */
  if ( victim == ch )
    return;

  if( IS_AFFECTED( victim, AFF_CHARM))   /* No exp for pets */
    return;

  if( IS_NPC( victim) && victim->pIndexData->vnum==9901 ) /* No Demons */
    return;

  levelst = 0;

  /* for ( gch = ch->in_room->first_person; gch != NULL; gch = gch->next_in_room ) */

  for ( gch = first_char; gch != NULL; gch = gch->next ) 
    {
    if ( is_same_group( gch, ch ) || (IS_NPC(gch) && gch->master == ch ) ||
        ( IS_NPC(ch) && ch->master!=NULL && is_same_group( gch, ch->master ) ) )
      {
      levelst+=gch->level;
      if( ch->in_room == gch->in_room )
        {
        gch->alignment-=victim->alignment/50;
        if(gch->alignment<-1000)
          gch->alignment=-1000;
        if(gch->alignment>1000)
          gch->alignment=1000;
        }
      }
    }


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

  
  if( ch->master != NULL && IS_NPC( ch ) )
    lch = (ch->master->leader != NULL) ? ch->master->leader : ch->master;
  else
    lch = (ch->leader != NULL) ? ch->leader : ch;

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

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

    if(!IS_NPC( gch ) && !IS_AFFECTED( gch, AFF_CHARM ) )
      {
      int cnt;
      xp = xp_compute( gch, victim )* gch->level / levelst;
      if( gch->pcdata->reincarnation > 0 )
       {
       for( cnt=0; cnt<gch->pcdata->reincarnation; cnt++)
         xp /= 2;
       gch->pcdata->allow_reincarnate = 0;
       }

      if( gch->level == 90 )  
        xp /= 2;
      if( gch->level > 90 && gch->level <= 95 )
        xp = 3 * xp / 4;

        /* God initiates  -  Chaos  4/18/99  */
      if( which_god(gch)==GOD_INIT_ORDER || which_god(gch)==GOD_INIT_CHAOS )
        {
        int found_follower;
        CHAR_DATA *tgch;

        found_follower = GOD_NEUTRAL;
        for ( tgch=gch->in_room->first_person; tgch!=NULL; 
              tgch=tgch->next_in_room )
        if ( is_same_group( gch, tgch ) && gch!=tgch && !IS_NPC(tgch) )
          if( which_god(tgch)==GOD_CHAOS || which_god(tgch)==GOD_ORDER )
            {
            found_follower =  which_god(tgch );
            break;
            }
        if( found_follower == GOD_NEUTRAL )
          {
          xp = (75-(ch->pcdata->reincarnation*10)) * xp / 100;
          sprintf( buf, "You receive %d experience points.\n\r", xp );
          }
        else
          if( which_god( gch ) == GOD_INIT_CHAOS && found_follower==GOD_CHAOS )
            {
            xp = (95-(ch->pcdata->reincarnation*8)) * xp / 100;
            sprintf( buf, "With assistance from Chaos, you receive %d experience points.\n\r", xp );
            }
        else
          if( which_god( gch ) == GOD_INIT_ORDER && found_follower==GOD_ORDER )
            {
            xp = (95-(ch->pcdata->reincarnation*8)) * xp / 100;
            sprintf( buf, "With Order's assistance, you receive %d experience points.\n\r", xp );
            }
        else
            {
            xp = (70-(ch->pcdata->reincarnation*13)) * xp / 100;
            sprintf( buf, "Your god only allows you %d experience points.\n\r", xp );
            }
        }
     else
      sprintf( buf, "You receive %d experience points.\n\r", xp );

      send_to_combat_char( buf, gch );
      gain_exp( gch, xp );
      }

   if( !IS_NPC( gch ) )
    for ( obj = gch->first_carrying; obj != NULL; obj = obj_next )
      {
      obj_next = obj->next_content;
      if ( obj->wear_loc == WEAR_NONE )
        continue;

      if ( ( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)    && IS_EVIL(gch)    )
      ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)    && IS_GOOD(gch)    )
      ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(gch) ) )
        {
        act( "You can no longer wear $p until your alignment is fixed.", gch, obj, NULL, TO_CHAR );
        act( "$n is zapped by $p.",   gch, obj, NULL, TO_ROOM );
        if ( obj == get_eq_char( victim, WEAR_WIELD )
         &&  (tmpobj = get_eq_char( victim, WEAR_DUAL_WIELD)) != NULL )
         tmpobj->wear_loc = WEAR_WIELD;
        unequip_char(gch, obj);
        }
      }
    }

  return;
}


/*
 * Calculate roughly how much experience a character is worth
 */
int get_exp_worth( CHAR_DATA *ch )
{
    int exp;

    exp = ch->level * ch->level * ch->level * 5;
    exp += ch->max_hit;
    exp -= (ch->armor-50) * 2;
    if (IS_NPC ( ch ) )
      exp += ( ch->npcdata->damnodice * ch->npcdata->damsizedice + 
	         GET_DAMROLL(ch) ) * 50;
    exp += GET_HITROLL(ch) * ch->level * 10;
    if ( IS_AFFECTED(ch, AFF_SANCTUARY) )
      exp += exp * 1.5;
    exp = URANGE( MIN_EXP_WORTH, exp, MAX_EXP_WORTH );

    return exp;
}


/*
 * Compute xp for a kill.
 * Also adjust alignment of killer.
 * Edit this function to change xp computations.
 */
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
  int xp;
  int spread;

  if( gch->in_room == NULL )
    return( 0 );
  if( IS_SET( gch->in_room->room_flags, ROOM_RIP ) )
    return( 0 );
  if( IS_SET( gch->in_room->room_flags, ROOM_IS_CASTLE ) )
    return( 0 );
  if (IS_NPC(victim) && (victim->pIndexData->vnum==9900 ))
    return( 0 );

  xp=(int)((float)exp_level(CLASS_MONSTER,victim->level)*
           ((float)(number_range(0,40)-20)/100.0+1.0));
  if(!IS_NPC(victim))
    xp=0;
  if(xp<75)
    xp=75;
  spread=10+gch->level/8;
  if(gch->level>victim->level)
    xp=xp * spread / ( gch->level - victim->level + spread );

/*
    xp    = (get_exp_worth( victim )
          *  URANGE( 0, (victim->level - gch->level) + 10, 13 )) / 10; */

  if( gch->in_room != NULL && gch->in_room->sector_type == SECT_ASTRAL )
    xp = xp + (xp * 35 / 100);
  if( gch->in_room != NULL && gch->in_room->sector_type == SECT_ETHEREAL )
    xp = xp + (xp * 30 / 100);

    xp = number_range( (xp*3) >> 2, (xp*5) >> 2 );
    /* reduce exp for killing the same mob repeatedly           -Martin 
    if ( !IS_NPC( gch ) )
    {
        int times = times_killed( gch, victim );

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

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



char * const attack_table[] =
	{
		"hit",
		"slice",  "stab",  "slash", "whip", "claw",
		"blast",  "pound", "crush", "grep", "bite",
		"pierce", "hit",
            "combination punch",  "palm punch",  "thrust kick",
            "spinning back-hand",  "jump kick",  "round house",
            "knee",       "claw",     "bite",
            "head butt",  "elbow slam", "uppercut",
            "hooves" 
	};

void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
  CHAR_DATA *fch;
  char buf1[256], buf2[256], buf3[256], bufc[256];
  char youHit[41],hitYou[41];
  const char *vs;
  const char *vp;
  const char *attack;
  char punct;
  int percent;
  int blen;

  percent = 100 * dam / victim->max_hit;

  attack = NULL;
  if ( dam ==   0 ) { 
	vs = "miss";    
	vp = "misses";          
	}
  else if ( percent <=   2 ) { 
	vs = "scratch"; 
	vp = "scratches";       
	}
  else if ( percent <=   4 ) { 
	vs = "graze";   
	vp = "grazes";          
	}
  else if ( percent <=   6 ) { 
	vs = "hit";     
	vp = "hits";            
	}
  else if ( percent <=   9 ) { 
	vs = "injure";  
	vp = "injures";         
	}
  else if ( percent <=  12 ) { 
	vs = "wound";   
	vp = "wounds";          
	}
  else if ( percent <=  15 ) { 
	vs = "maul";       
	vp = "mauls";           
	}
  else if ( percent <=  18 ) { 
	vs = "decimate";        
	vp = "decimates";       
	}
  else if ( percent <=  21 ) { 
	vs = "devastate";       
	vp = "devastates";      
	}
  else if ( percent <=  25 ) { 
	vs = "maim";    
	vp = "maims";           
	}
  else if ( percent <=  29 ) { 
	vs = "MUTILATE";        
	vp = "MUTILATES";       
	}
  else if ( percent <=  33 ) { 
	vs = "DISEMBOWEL";      
	vp = "DISEMBOWELS";     
	}
  else if ( percent <=  37 ) { 
	vs = "* EVISCERATE *";      
	vp = "* EVISCERATES *";     
	}
  else if ( percent <=  41 ) { 
	vs = "** MASSACRE **";        
	vp = "** MASSACRES **";       
	}
  else if ( percent <= 50 ) { 
	vs = "*** DEMOLISH ***";
	vp = "*** DEMOLISHES ***";                      
	}
  else if ( percent <= 70 ) { 
	vs = "**** ANNIHILATE ****";
	vp = "**** ANNIHILATES ****";             
	}
  else { 
	vs = "**** *OBLITERATE* ****";
	vp = "**** *OBLITERATES* ****";             
	}

  punct   = (percent <= 18) ? '.' : '!';

  youHit[0]='\0';
  hitYou[0]='\0';
  if(victim->vt100==1)
    if((dam>0) && (victim->ansi==1))
    {
      /* determine color of messages */
      if(victim->pcdata->color[4]!=0)
	sprintf( hitYou, "\033[1;%d;%dm", victim->pcdata->color[0][4],
	     victim->pcdata->color[1][4]);
    }
  if(ch->vt100==1)
    if((dam>0) && (ch->ansi==1))
    {
      /* determine color of messages */
      if(ch->pcdata->color[5]!=0)
	sprintf( youHit, "\033[1;%d;%dm", ch->pcdata->color[0][5],
	    ch->pcdata->color[1][5]);
    }

  if ( dt == TYPE_HIT )
  {
    if( ch->level>50 && dam>0)
      sprintf( buf2, "%sYou %s $N for %dhp%c", youHit,   vs, dam, punct );
    else
      sprintf( buf2, "%sYou %s $N%c", youHit,   vs, punct );

    if( IS_NPC( ch ) && IS_SET(ch->pIndexData->act, ACT_BODY) &&
      ch->pIndexData->attack_parts!=0)
    {
      int part, dir;
      char buf4[200];

      part=number_range( 0, MAX_BODY -1);
      dir=(number_range(0,1)*2)-1;
      while( !IS_SET( ch->pIndexData->attack_parts, 1<<part))
      {
        part+=dir;
        if(part<0)
          part=MAX_BODY-1;
        if(part>=MAX_BODY)
          part=0;
      }

      sprintf( buf4, body_table[part].attack, capitalize(get_name(ch)));
      sprintf( buf1, "%s %s %s%c", capitalize(buf4), vp,
        get_name( victim ), punct );

      sprintf( buf4, body_table[part].attack, capitalize(get_name(ch)));
      if(victim->level>50 && dam>0)
        sprintf( buf3, "%s%s %s you for %dhp%c", hitYou, buf4, vp, dam, punct);
      else
        sprintf( buf3, "%s%s %s you%c", hitYou, buf4, vp, punct );
    }
    else
    {
      strcpy( bufc, get_name( ch ) );
      sprintf( buf1, "%s %s %s%c",   bufc, vp, get_name( victim ), punct );
      if(victim->level>50 && dam>0)
        sprintf( buf3, "%s%s %s you for %dhp%c", hitYou,  
          IS_NPC( ch ) ? capitalize( ch->short_descr ) : 
          get_name( ch ), vp, dam, punct );
      else
        sprintf( buf3, "%s%s %s you%c", hitYou,  
          IS_NPC( ch ) ? capitalize( ch->short_descr ) : 
          get_name( ch ), vp, punct );
    }
  }
  else if (dt == TYPE_NOMESSAGE || dt==TYPE_NOFIGHT )
    return;
  else
  {
    if( dt == gsn_martial_arts )
    {
      if( martial_arts_attack > 0 )
        attack  = attack_table[12+martial_arts_attack];
      else
        attack  = attack_table[18-martial_arts_attack];
    }
    else
      if( dt == TYPE_HOOVES )
        attack = attack_table[25];
      else if ( dt >= 0 && dt < MAX_SKILL )
        attack  = skill_table[dt].noun_damage;
      else if ( dt >= TYPE_HIT )
      {
        OBJ_DATA *obj;
        if (dual_flip == FALSE && get_eq_char(ch, WEAR_DUAL_WIELD) != NULL)
          obj = get_eq_char( ch, WEAR_DUAL_WIELD );
        else
          obj = get_eq_char( ch, WEAR_WIELD );

        if(  obj->pIndexData->attack_string!=NULL)
          attack = obj->pIndexData->attack_string;
        else
          if(dt<TYPE_HIT+sizeof(attack_table)/sizeof(attack_table[0]) )
            attack  = attack_table[dt - TYPE_HIT];
      }
      else
      {
        if( dt!=TYPE_UNDEFINED)
	  bug( "Dam_message: bad dt %d.", dt );
        dt  = TYPE_HIT;
	attack  = attack_table[0];
      }

    strcpy(bufc, capitalize(get_name( ch )) );
    sprintf(buf1, "%s's %s %s %s%c", bufc, attack, vp, get_name(victim), punct);

    if( ch->level>50 && dam>0)
      sprintf( buf2, "%sYour %s %s $N for %dhp%c", youHit,attack,vp,dam,punct );
    else
		  sprintf( buf2, "%sYour %s %s $N%c",  youHit,   attack, vp, punct );
    if( victim->level > 50 && dam>0)
      {
      sprintf(buf3,"%s%s's %s %s you for %dhp%c",hitYou,
                IS_NPC( ch ) ? capitalize( ch->short_descr ) : 
                get_name( ch ), attack, vp, dam, punct );
      }
    else
      {
      sprintf(buf3,"%s%s's %s %s you%c",hitYou,
                IS_NPC( ch ) ? capitalize( ch->short_descr ) : 
                get_name( ch ), attack, vp, punct );
      }
	  }

    /*  Spam code for combat      -  Chaos 12/20/94    */
    blen = strlen( buf1 );
    for( fch=ch->in_room->first_person ; fch != NULL ; fch=fch->next_in_room )
      if( !IS_NPC( fch ) && fch != ch && fch != victim )
       if( fch->position > POS_SLEEPING )
        {
        bool  gch, gvic;
        gch = is_same_group( ch, fch );
        gvic = is_same_group( victim, fch );
        if( gch && !gvic )
          {
          if( dam <= 0 && !IS_SET( fch->pcdata->spam, 32))
            send_to_char( buf1, fch );
          if( dam > 0 && !IS_SET( fch->pcdata->spam, 16))
            send_to_char( buf1, fch );
          } 
        else
          if( !gch && gvic )
            {
            if( dam <= 0 && !IS_SET( fch->pcdata->spam, 128))
              send_to_char( buf1, fch );
            if( dam > 0 && !IS_SET( fch->pcdata->spam, 64))
              send_to_char( buf1, fch );
            } 
        else
          if( !gch && !gvic )
            {
            if( dam <= 0 && !IS_SET( fch->pcdata->spam, 512))
              send_to_char( buf1, fch );
            if( dam > 0 && !IS_SET( fch->pcdata->spam, 256))
              send_to_char( buf1, fch );
            } 
       else
         send_to_combat_char( buf1, fch );
       }

    if( dam == 0 )
      {
      if( IS_NPC( ch ) || !IS_SET( ch->pcdata->spam, 2 ))
       if( ch->position > POS_SLEEPING )
	      act( buf2, ch, "", victim, TO_CHAR );
      if( IS_NPC( victim ) || !IS_SET( victim->pcdata->spam, 8 ))
       if( victim->position > POS_SLEEPING )
	      act( buf3, ch, "", victim, TO_VICT );
      }
    else
      {
      if( IS_NPC( ch ) || !IS_SET( ch->pcdata->spam, 1 ))
       if( ch->position > POS_SLEEPING )
	      act( buf2, ch, "", victim, TO_CHAR );
      if( IS_NPC( victim ) || !IS_SET( victim->pcdata->spam, 4 ))
       if( victim->position > POS_SLEEPING )
	      act( buf3, ch, "", victim, TO_VICT );
      }
	return;
}



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

	if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
		return;
        if ( ( tmpobj = get_eq_char( victim, WEAR_DUAL_WIELD ) ) != NULL
           &&     number_bits( 1 ) == 0 )
          obj = tmpobj;

	if (IS_SET(obj->extra_flags,ITEM_INVENTORY))
		return;

	if ( get_eq_char( ch, WEAR_WIELD ) == NULL && number_bits( 1 ) ==
	    0 )
		return;

	/*   if( IS_SET(ch->attack, 1))      Temp fix by Chaos 12/17/93
      return;
    else
      ch->attack+=1;   */

	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 );

	if( !IS_NPC(victim) && victim->pcdata->learned[gsn_rearm] > number_percent())
	{
		act( "You rearm yourself!!!", ch, NULL, victim, TO_VICT);
		act( "$N rearms $Mself!!!", ch, NULL, victim, TO_CHAR );
		act( "$N rearms $Mself!!!", ch, NULL, victim, TO_NOTVICT
		    );
		return;
	}
    if ( obj == get_eq_char( victim, WEAR_WIELD )
    &&  (tmpobj = get_eq_char( victim, WEAR_DUAL_WIELD)) != NULL )
       tmpobj->wear_loc = WEAR_WIELD;

  unequip_char( victim, obj);
	return;
}



/*
 * Trip a creature.
 * Caller must check for successful attack.
 */
void do_trip( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
        int cnt;

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}

	cnt = multi( ch, gsn_trip);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char( "Huh?!\n\r", ch);
		return;
	}

	if ( ( victim = who_fighting(ch) ) == NULL )
	{
		send_to_combat_char( "You aren't fighting anyone.\n\r", ch );
		return;
	}

        if ( IS_NPC(ch) 
          || (number_percent()< (ch->pcdata->learned[gsn_trip])
          && check_hit( ch, victim, 0-GET_HITROLL(ch), gsn_trip ) ) )
	WAIT_STATE( ch, skill_table[gsn_trip].beats*200/(200+ch->mclass[cnt]));
    
	{
		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( victim, PULSE_VIOLENCE/2 );
		victim->position = POS_RESTING;
	}
		WAIT_STATE( ch,     PULSE_VIOLENCE/2 );

	return;
}
void trip( CHAR_DATA *ch, CHAR_DATA *victim )
{
	if ( IS_SET(ch->attack, 8))
		return;
	else
		ch->attack+=8;

	if ( victim->wait == 0 )
	{
		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,     PULSE_VIOLENCE/2 );
		WAIT_STATE( victim, PULSE_VIOLENCE/6 );
		victim->position = POS_RESTING;
	}

	return;
}



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

	if( IS_SET( ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}
    if(find_keeper( ch ) !=NULL)
    {
     ch_printf(ch, "%s tells you 'No fighting in here! You thug!'\n\r", capitalize(find_keeper(ch)->short_descr));
     ch->reply=find_keeper( ch );
     return;
    }

	if(! IS_NPC(ch))
	  ch->pcdata->just_died_ctr=0;


      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
      /* if wounded below 50% - Presto 06/22/98 */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < (ch->max_hit/2) )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

  one_argument( argument, arg );
  found=FALSE;
  victim = NULL;
  if ( argument[0] == '\0' )
  {
    for(victim=ch->in_room->first_person;victim!=NULL;victim=victim->next_in_room)
      if(IS_NPC( victim) && ch!=victim &&
         ch->level<=victim->level-(ch->level*2+10))
      {
        sprintf(buf, "%s doesn't think you should fight in here.\n\r",
	              capitalize(victim->short_descr));
        send_to_combat_char( buf, ch);
        return;
      }
	
    for(victim=ch->in_room->first_person;found==FALSE && victim!=NULL;
        victim=victim->next_in_room)
      if(can_see(ch, victim) && !IS_AFFECTED( victim, AFF_CHARM) &&
         IS_NPC( victim) && ch!=victim && !is_same_group(ch,victim))
      {
        found=TRUE;
        break;
      }

    if(!found)
    {
      send_to_combat_char( "You cannot see anyone you can attack.\n\r", ch);
      return;
  }
	  }

	if(!found)
		if ( ( victim = get_char_room_even_hidden( ch, arg ) ) == NULL )
		  {
			send_to_combat_char( "They aren't here.\n\r", ch );
			return;
		  }

	if ( !IS_NPC(victim) && ch->in_room->area->low_r_vnum!=ROOM_VNUM_ARENA)
	  {
    send_to_combat_char( "You must MURDER a player.\n\r", ch);
    return;
	  }
	else
	  {
		if ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
		  {
			if( victim->master == ch && IS_SET( victim->act, ACT_PET))
	      {
	      raw_kill( victim );
	      return;
	      }
		  send_to_combat_char( "You cannot kill a slave.\n\r", ch );
		  return;
		  }
    }

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

	if ( is_safe( ch, victim ) )
    {
          act("You shouldn't try that here.",ch,NULL,NULL,TO_CHAR);
	  return;
    }

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

  if( (!IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) ) &&
    ( IS_NPC( victim) && victim->fighting==NULL && 
      victim->npcdata->pvnum_last_hit_leader > 0 ) ) 
    {
    CHAR_DATA *ch_ld;
    int pvnum_ld;

    ch_ld = ch;
    if( IS_NPC( ch ) )
      ch_ld = ch_ld->master;
    if( ch_ld->leader != NULL )
      ch_ld = ch_ld->leader;
    if( !IS_NPC( ch_ld ) )
      pvnum_ld=ch_ld->pcdata->pvnum;
    else
      pvnum_ld=0;
    if( pvnum_ld != victim->npcdata->pvnum_last_hit_leader )
      {
      sprintf( buf ,"%s was recently fought.  Try later.\n\r", 
          capitalize(victim->short_descr));
      send_to_combat_char( buf, ch);
      return;
      }
    }


  if( IS_NPC( victim) && victim->fighting!=NULL && 
             (!IS_NPC( ch ) || IS_AFFECTED(ch,AFF_CHARM)) &&
             !is_same_group( ch, victim->fighting->who ))
  {
    sprintf( buf ,"%s seems to be in combat already!\n\r", capitalize(victim->short_descr));
    send_to_combat_char( buf, ch);
    return;
  }

  if ( ch->position == POS_FIGHTING )
  {
    if((who_fighting(ch)==victim) ||
       IS_NPC(ch) ||
       (number_percent() > ch->pcdata->learned[gsn_attack] ))
    {
      send_to_combat_char( "You do the best you can!\n\r", ch);
      return;
    }
/*    Stop a fight if you try to kill during a fight???  Chaos - 4/4/99
    else
      stop_fighting(ch,FALSE); */
  }

     if( !is_affected(ch, gsn_truesight) && has_mirror( ch, victim ) )
          {
	  WAIT_STATE( ch, PULSE_VIOLENCE*2 );
          return;
          } 

	WAIT_STATE( ch, PULSE_VIOLENCE/2 );
  if(!IS_NPC(ch) &&
     ch->mclass[CLASS_ASSASSIN]==ch->level &&
     number_percent () < (float)ch->pcdata->learned[gsn_quick_draw]*.95)
    {
      OBJ_DATA * obj;
	if((obj=get_eq_char(ch,WEAR_WIELD))!=NULL
	    &&(obj->value[3]==11||obj->value[3]==2))
	{
	 if( number_percent( ) < ch->pcdata->learned[gsn_knife] )
	  one_hit( ch, victim, gsn_knife );
	 else
	  damage( ch, victim, 0, gsn_knife );
	}
    }
	multi_hit( ch, victim, TYPE_UNDEFINED );
	return;
}



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

void add_to_victory_list( CHAR_DATA *ch, CHAR_DATA *victim)
{
  int i;
  char buf[MAX_STRING_LENGTH];
  i=victory_list_current-1;
  if (i<0) i=VICTORY_LIST_SIZE-1;
  STRFREE (victory_list[i] );
  sprintf(buf, "Z%12s (%dx Level %2d) %12s (%dx Level %2d) %s", ch->name, ch->pcdata->reincarnation, ch->level, victim->name, victim->pcdata->reincarnation, victim->level, (char *) ctime( &current_time)); 
  buf[strlen(buf)-1]='\0';
  victory_list[i] = STRALLOC(buf);
  victory_list_current=i;
  save_victors();
  return;
}


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

  if( IS_NPC( ch ) || IS_NPC( victim ) )
    return( FALSE );

  if( ch->pcdata->army_status != 1 || victim->pcdata->army_status != 1 )
    return( FALSE );

  if( victim->race == Race_Battle_List[ ch->race ] )
    return( TRUE );

  /*  Changing to random based wars  -  Chaos 6/22/97  
  switch( ch->race )
    {
    case RACE_HUMAN:
      if( victim->race == RACE_HALFLING )
        return( TRUE );
      else
        return( FALSE );
    case RACE_HALFLING:
      if( victim->race == RACE_HUMAN )
        return( TRUE );
      else
        return( FALSE );
    case RACE_ELF:
      if( victim->race == RACE_OGRE )
        return( TRUE );
      else
        return( FALSE );
    case RACE_DROW:
      if( victim->race == RACE_GNOME )
        return( TRUE );
      else
        return( FALSE );
    case RACE_DWARF:
      if( victim->race == RACE_ORC )
        return( TRUE );
      else
        return( FALSE );
    case RACE_GNOME:
      if( victim->race == RACE_DROW )
        return( TRUE );
      else
        return( FALSE );
    case RACE_ORC:
      if( victim->race == RACE_DWARF )
        return( TRUE );
      else
        return( FALSE );
    case RACE_OGRE:
      if( victim->race == RACE_ELF )
        return( TRUE );
      else
        return( FALSE );
    default:
      return( FALSE );
    }      */

  return( FALSE );
}



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

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}

      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < (ch->max_hit/2) )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;


	one_argument( argument, arg );

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

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

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

        if(find_keeper( ch)!=NULL)
      	{
		ch_printf(ch, "%s tells you 'No fighting in here! You thug!'\n\r", capitalize(find_keeper(ch)->short_descr));
                ch->reply=find_keeper( ch );
		return;
	}
	if ( is_safe( ch, victim ) )
		return;

	if( IS_AFFECTED( victim, AFF_CHARM) && victim->master == ch)
	  {
           if(IS_SET(victim->act,ACT_PET))
	    {
              raw_kill( victim);
   	      return;
	    }
           else
            {
             send_to_combat_char( "You cannot murder your slave.\n\r", ch);
             return;
            }
	  }
        else if( IS_AFFECTED( victim, AFF_CHARM) )
         {
          send_to_combat_char( "You cannot murder someone's pet.\n\r", ch);
          return;
         }

	if( IS_AFFECTED( ch, AFF_CHARM) )
	{
	  send_to_combat_char( "You're too charmed to murder right now.\n\r",
	    ch);
	  return;
	}

	if ( ch->position == POS_FIGHTING )
	{
		send_to_combat_char( "You do the best you can!\n\r", ch );
		return;
	}
    if( !IS_NPC(victim))
       if(victim->pcdata->just_died_ctr > 0)
      {
        send_to_char("That person is currently protected by the gods.\n\r", ch);
        return;
      }

  if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) && ( !IS_NPC( ch ) ||
        IS_AFFECTED( victim, AFF_CHARM ) ) )
     return;

 if (!IS_NPC(ch) && !IS_NPC(victim) && victim->fighting != NULL )
  {
   send_to_combat_char( "You may not murder that person, at the moment.\n\r", ch);
   return;
  }

	/* Lagging players for murdering gives Rangers an immense advantage
	   over all other classes. If a spell caster or knifer does the murder
	   he/she must wait two rounds before being able to actually attack,
	   whereas rangers start hammering away right away.
	   - Martin 7/8/98  */
        
           WAIT_STATE( ch, PULSE_VIOLENCE*2 );

  if (!IS_NPC(ch)) 
   ch->pcdata->just_died_ctr = 0;
  /* if they are an assassin with K flag, ignore the following checks */

 if (!can_attack (ch, victim) )
  {
   send_to_combat_char( "You may not murder that person, at the moment.\n\r", ch);
   return;
  }
  
  if ((victim->mclass[CLASS_ASSASSIN] == victim->level &&
     victim->level != 95 && IS_SET(victim->act, PLR_KILLER) &&
     ch->level <= victim->level+10))

    /* Took out gang-banging against Asns  -  Chaos  4/17/99  */
  if( victim->fighting!=NULL  || victim->hit<victim->max_hit/4 )
   {
    send_to_combat_char( "You may not murder that person, at the moment.\n\r", ch);
    return;
   }

  if ( !IS_NPC(victim ) && victim->pcdata->corpse != NULL)
   {
    char buf12[180];
    sprintf( buf12, "%s has been killed quite recently.\n\r", 
             get_name( victim ) );
    send_to_combat_char( buf12, ch );
    return;
   }

  /* Code for total and max pvnum attacks  -  Chaos 5/6/99  */
  if( !IS_NPC(ch) && !IS_NPC(victim) )
    if( !check_add_attack( ch, victim ) )
      {
       char buf12[180];
       sprintf( buf12, "%s has been attacked too many times today.  You should leave them alone.\n\r", 
                get_name( victim ) );
       send_to_combat_char( buf12, ch );
       return;
      }


    if( !IS_NPC(victim))
    {
        if( which_god(ch) == GOD_CHAOS || which_god(ch) == GOD_ORDER ||
            which_god(ch) == GOD_DEMISE || which_god(ch) == GOD_POLICE )
        if( which_god(victim) == GOD_CHAOS || which_god(victim) == GOD_ORDER ||
            which_god(victim) == GOD_DEMISE || which_god(victim) == GOD_POLICE )
          if( which_god(victim) != which_god(ch) )
          {
            char buf2 [MAX_INPUT_LENGTH];
            sprintf(buf2, "%s", get_name(ch));

	    sprintf( buf, "%s battles 'Help!  I am being attacked by %s!'", 
              get_name(victim), buf2);
	    do_battle( buf );
          }
          else
          {
	    sprintf( buf, "Help!  I am being attacked by %s!", get_name( ch ) );
	    do_shout( victim, buf );
	    do_chat( victim, buf );

            victim->wait = 0;  /* remove time penalty of shout */
          }
	  check_killer( ch, victim );
    }
   
  if ( IS_AFFECTED(victim, AFF2_HAS_FLASH) && !IS_NPC(ch) && !IS_NPC(victim))
  {
    if (number_percent() < victim->pcdata->learned[gsn_flash_powder]/2)
    {
     AFFECT_DATA af;
     int attempt;
     ROOM_INDEX_DATA *was_in;
     ROOM_INDEX_DATA *now_in;

     REMOVE_BIT(victim->affected2_by, 0-AFF2_HAS_FLASH); 
    act( "$n throws some powder onto the ground and there is a bright flash!", victim, NULL, NULL, TO_ROOM );
    act( "You throw some powder onto the ground and there is a bright flash!", victim, NULL, ch, TO_CHAR );

     if (!is_affected(ch, gsn_truesight))
     {
      af.type=gsn_flash_powder;
      af.bitvector = AFF_BLIND;
      af.duration=0;
      af.modifier=0;
      affect_to_char(ch, &af);
     }
     else
      {
      act( "$N is unaffected by the bright flash!", ch, NULL, victim, TO_VICT );
      act( "You ignore the effects of the flash.", ch, NULL, victim, TO_CHAR );
      }
 

  was_in = victim->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
        ||   IS_SET(pexit->exit_info, EX_CLOSED)
        || ( IS_NPC(victim)
        &&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
      continue;

    if( IS_NPC(victim) && pexit->to_room->area != victim->in_room->area )
      continue;

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

    char_from_room( victim );
    char_to_room( victim, was_in );
    char_from_room( victim );
    char_to_room( victim, now_in );
    }
    if (victim->in_room != was_in)
      return;
   }
   else
   {
     send_to_char( "You fumble the flash powder and it spills everywhere!\n\r", victim);
     REMOVE_BIT(victim->affected2_by, 0-AFF2_HAS_FLASH); 
   }
  }


     if( !is_affected(ch, gsn_truesight) && has_mirror( ch, victim ) )
          {
	  WAIT_STATE( ch, PULSE_VIOLENCE*2 );
          return;
          } 

  if(!IS_NPC(ch) &&
     number_percent () < (float)ch->pcdata->learned[gsn_quick_draw]*.75)
    {
      OBJ_DATA * obj;
	if((obj=get_eq_char(ch,WEAR_WIELD))!=NULL
	    &&(obj->value[3]==11||obj->value[3]==2))
	{
	 if( number_percent( ) < ch->pcdata->learned[gsn_knife] )
	  one_hit( ch, victim, gsn_knife );
	 else
	  damage( ch, victim, 0, gsn_knife );
	}
    }
  /* if they are set to auto backstab then do it for murder */
  if(!IS_NPC(ch) && ch->pcdata->auto_flags!=AUTO_OFF &&
     skill_lookup(ch->pcdata->auto_command)==gsn_backstab &&
     victim->hit == victim->max_hit &&
     ch->mclass[CLASS_ROGUE]==ch->level)
    backstab(ch,victim);
  else
    multi_hit( ch, victim, TYPE_UNDEFINED );
  return;
}

void backstab(CHAR_DATA *ch, CHAR_DATA *victim)
{
  int cnt;
	cnt = multi( ch, gsn_backstab);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char(
		    "You are not that practiced a cut-throat.\n\r", ch
		    );
		return;
	}
  WAIT_STATE( ch, skill_table[gsn_backstab].beats*200/(200+ch->mclass[cnt]));

/* Anatomy skill - Martin 4/8/98 */
  if (IS_NPC(victim) && !IS_NPC(ch) 
      && (victim->level<(ch->mclass[CLASS_ROGUE]-10)) 
      && number_percent()<ch->pcdata->learned[gsn_anatomy]/12)
    {
      act( "$n thrusts $s $p into $N, killing $M instantly!", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_ROOM);
      act( "You thrust your $p into $N, killing $M instantly!", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_CHAR);
      one_hit( ch, victim, gsn_anatomy );
      return;
    }
  one_hit( ch, victim, gsn_backstab );
  return;
}

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

  if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
    {
    send_to_combat_char( "You cannot do that here.\n\r", ch);
    return;
    }
  one_argument( argument, arg );


      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;


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

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

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

  if ( is_safe( ch, victim ) )
    return;

  if( !IS_NPC(victim) && ( (IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM)) ||
      !IS_NPC(ch)))
    if ( ch->in_room->area->low_r_vnum!=ROOM_VNUM_ARENA )
      {
      send_to_combat_char( "You may not backstab another player.\n\r", ch);
      return;
      }
  if( (IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM)) || !IS_NPC(ch))
    if( IS_NPC( victim) && IS_AFFECTED( victim, AFF_CHARM))
      {
      send_to_combat_char( "You can't do that to a pet.\n\r", ch);
      return;
      }

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

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

  if (( victim->hit < victim->max_hit )/*&&(victim->distracted<5)*/)
    {
    act( "$N is hurt and suspicious ... you can't sneak up.",
        ch, NULL, victim, TO_CHAR );
    return;
    }
  if(!IS_NPC(ch))
    if( 1 > ch->pcdata->learned[gsn_backstab] )
      {
      act( "You cannot backstab anything.",
          ch, NULL, victim, TO_CHAR );
      return;
      }

  if( !IS_NPC(ch) && !IS_NPC(victim) )
	if ( !can_reincarnate_attack( ch, victim) )
	{
	send_to_combat_char( "They have not reached your spiritual ability yet.\n\r", ch );
		return;
	}

  if( (!IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) ) &&
    ( IS_NPC( victim) && victim->fighting==NULL && 
      victim->npcdata->pvnum_last_hit_leader > 0 ) ) 
    {
    CHAR_DATA *ch_ld;
    int pvnum_ld;
    char buf[MAX_INPUT_LENGTH];

    ch_ld = ch;
    if( IS_NPC( ch ) )
      ch_ld = ch_ld->master;
    if( ch_ld->leader != NULL )
      ch_ld = ch_ld->leader;
    if( !IS_NPC( ch_ld ) )
      pvnum_ld=ch_ld->pcdata->pvnum;
    else
      pvnum_ld=0;
    if( pvnum_ld != victim->npcdata->pvnum_last_hit_leader )
      {
      sprintf( buf ,"%s was recently fought.  Try later.\n\r", 
           capitalize( victim->short_descr));
      send_to_combat_char( buf, ch);
      return;
      }
    }
     if( !is_affected(ch, gsn_truesight) && has_mirror( ch, victim ) )
    {
    WAIT_STATE( ch, PULSE_VIOLENCE*2 );
    return;
    } 

  backstab(ch,victim);
  return;
}



void do_flee( CHAR_DATA *ch, char *argument )
{
  ROOM_INDEX_DATA *was_in;
  ROOM_INDEX_DATA *now_in;
  CHAR_DATA *victim, *fch;
  int attempt, exp;
  char buf[MAX_INPUT_LENGTH];

  if( ch->wait > 0 )
    return;

  if ( ( victim = who_fighting(ch) ) == NULL )
    if(!IS_NPC(ch) || IS_AFFECTED( ch, AFF_CHARM))
      {
      send_to_combat_char( "You aren't fighting anyone.\n\r", ch );
      return;
      }

  was_in = ch->in_room;

  /* Slight lag for fleers */
  WAIT_STATE( ch, PULSE_VIOLENCE/3 );

  if( IS_NPC( ch ) || (ch->class != CLASS_MONK &&
      !(ch->race == RACE_AVIARAN && IS_OUTSIDE(ch))))
  {
  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
        ||   IS_SET(pexit->exit_info, EX_CLOSED)
        || ( IS_NPC(ch)
        &&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
      continue;

    if( IS_NPC(ch) && pexit->to_room->area != ch->in_room->area )
      continue;

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

    if (IS_SET(ch->in_room->room_flags, ROOM_SMOKE)
            && number_percent()<(40-get_curr_int(ch)))

      {
       send_to_char( "You blunder around and get lost in the smoke!\n\r", ch);
       continue;
      }

    char_from_room( ch );
    char_to_room( ch, was_in );
    act( "$n flees head over heels!", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, now_in );
    act( "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM);

    if ( !IS_NPC(ch) )
      {
      exp = ch->level*ch->level*2+ch->level*10+50;
      sprintf( buf, "You flee from combat!  You lose %d exp.\n\r",
          exp);
      send_to_combat_char( buf, ch);
      gain_exp( ch, 0-exp);
      }

    /* Chaos 11/19/93 */
    if(was_in != now_in)
      for(fch = was_in->first_person; fch != NULL; fch = fch->next_in_room)
        if(fch->fighting && 
	   who_fighting (fch) == ch &&
	   IS_AFFECTED (fch, AFF_HUNT) &&
	   !IS_AFFECTED (fch, AFF_CHARM) )

          if((IS_NPC(fch) && number_percent()<50) ||
             (!IS_NPC(fch) && number_percent()<
              (fch->pcdata->learned[gsn_hunt] *
	       (45+fch->mclass[multi(fch,gsn_hunt)]/2)/100)))
            {
            send_to_combat_char("You hunt them down.\n\r", fch);
            char_from_room( fch );
            char_to_room( fch, ch->in_room );
            send_to_combat_char("You have been hunted down.\n\r", ch);

  	    stop_fighting( ch, TRUE);
            stop_fighting( fch, TRUE);

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

    if( was_in == now_in)
      {
      if( !IS_NPC( ch))
        {
        exp = ch->level*ch->level*1+20;
        sprintf( buf, "You failed!  You lose %d exp.\n\r", exp);
        send_to_combat_char( buf, ch);
        gain_exp( ch, -exp);
        }
      return;
      }
   if (victim!=NULL)
        if( which_god(ch) == GOD_CHAOS || which_god(ch) == GOD_ORDER ||
            which_god(ch) == GOD_DEMISE || which_god(ch) == GOD_POLICE )
        if( which_god(victim) == GOD_CHAOS || which_god(victim) == GOD_ORDER ||
            which_god(victim) == GOD_DEMISE || which_god(victim) == GOD_POLICE )
          if( which_god(victim) != which_god(ch) )
    {
     char buf2 [MAX_INPUT_LENGTH];
     sprintf(buf2, "%s", get_name(ch));
     if (ch->desc == NULL)
       sprintf(buf, "%s's arcane connection to the realm has been severed like a coward while in battle with %s!", buf2, get_name(victim));
     else
       sprintf(buf, "%s has fled like a coward from the wrath of %s!", buf2, get_name(victim));

     do_battle( buf );
    }
    leave_fighting( ch, was_in);
    return;
    }
  send_to_combat_char("Ah!!!  You can't find an exit!\n\r",ch);
  return;
  }
else
  {
  int door_count, door_cnt;
  /* ROOM_INDEX_DATA *location; */
  EXIT_DATA *pexit;
  int door;

      door_count = 0;
      now_in = NULL;

         /* Hey, we're testing directions and it's noisy */
      ALLOW_OUTPUT = FALSE;

      for( door = 0;   door < 6; door++ )
        if ( ( pexit = was_in->exit[door] ) == 0
            ||   pexit->to_room == NULL
            ||   pexit->to_room == was_in
            ||   IS_SET(pexit->exit_info, EX_CLOSED)
            || ( IS_NPC(ch)
            &&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
          continue;
        else
          {
          move_char( ch, door );
          if ( ( now_in = ch->in_room ) == was_in )
            continue;

          char_from_room( ch );
          char_to_room( ch, was_in );
          door_count++;
          }

      ALLOW_OUTPUT = TRUE;

      if( door_count == 0 )
        {
        send_to_combat_char( "You cannot flee from here.\n\r", ch );
        return;
        }

      door_cnt = number_range( 0, door_count - 1 );
      door_count = 0;
      for( door = 0;   door < 6; door++ )
        if ( ( pexit = was_in->exit[door] ) == 0
            ||   pexit->to_room == NULL
            ||   pexit->to_room == was_in
            ||   IS_SET(pexit->exit_info, EX_CLOSED)
            || ( IS_NPC(ch)
            &&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
          continue;
        else
          {
          move_char( ch, door );
          if ( ( now_in = ch->in_room ) == was_in )
            continue;

          char_from_room( ch );
          char_to_room( ch, was_in );
          if( door_count == door_cnt )
            {
            break;
            }
          door_count++;
          }
       }


    act( "$n flees head over heels!", ch, NULL, NULL, TO_ROOM );

    char_from_room( ch );
    char_to_room( ch, now_in );
    act( "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM );


    if ( !IS_NPC(ch) )
     {
     exp = ch->level*ch->level+ch->level*50+25;
     /* exp = ( exp_level( ch->class, ch->level+1 ) - exp_level( ch->class, ch->level ) ) * 0.03; */
      if (ch->level < 95) 
       {
        sprintf( buf, "You flee head over heels from combat, losing %d experience.\n\r", exp);
        send_to_combat_char( buf, ch);
        gain_exp( ch, 0-exp);
       }
      else
        send_to_combat_char( "You flee head over heels from combat.\n\r", ch);
      }

    /* Chaos 11/19/93 */
    if(was_in != now_in)
      for(fch = was_in->first_person; fch != NULL; fch = fch->next_in_room)
        if(fch->fighting && 
	   who_fighting (fch) == ch &&
	   IS_AFFECTED (fch, AFF_HUNT) &&
	   !IS_AFFECTED (fch, AFF_CHARM) )

          if((IS_NPC(fch) && number_percent()<50) ||
             (!IS_NPC(fch) && number_percent()<
              (fch->pcdata->learned[gsn_hunt] *
	       (45+fch->mclass[multi(fch,gsn_hunt)]/2)/100)))
            {
            send_to_combat_char("You hunt them down.\n\r", fch);
            char_from_room( fch );
            char_to_room( fch, ch->in_room );
            send_to_combat_char("You have been hunted down.\n\r", ch);

            stop_fighting( ch, TRUE);
            stop_fighting( fch, TRUE);

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

   if( was_in == now_in)
   {
      if( !IS_NPC( ch))
        {
        exp = ch->level*ch->level*1+20;
	/*exp = ( exp_level( ch->class, ch->level+1 ) - exp_level( ch->class, ch->level ) ) * 0.01;*/
	if (ch->level<95)
          sprintf( buf, "You attempt fo flee from combat, losing %d exp.\n\r", exp);
	else
          sprintf( buf, "You attempt fo flee from combat, but can't escape .\n\r" );
        send_to_combat_char( buf, ch);
        gain_exp( ch, -exp);
        }
      return;
   }

        if( which_god(ch) == GOD_CHAOS || which_god(ch) == GOD_ORDER ||
            which_god(ch) == GOD_DEMISE || which_god(ch) == GOD_POLICE )
        if( which_god(victim) == GOD_CHAOS || which_god(victim) == GOD_ORDER ||
            which_god(victim) == GOD_DEMISE || which_god(victim) == GOD_POLICE )
          if( which_god(victim) != which_god(ch) )
    {
     char buf2 [MAX_INPUT_LENGTH];
     sprintf(buf2, "%s", get_name(ch));

     if (ch->desc == NULL)
       sprintf(buf, "%s's arcane connection to the realm has been severed like a coward while in battle with %s!", buf2, get_name(victim));
     else
       sprintf(buf, "%s has fled like a coward from the wrath of %s!", buf2, get_name(victim));
     do_battle( buf );
    }
    stop_fighting( ch, TRUE);
    return;
}


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

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

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

	if ( victim == ch )
	{
		send_to_combat_char( "What about fleeing instead?\n\r", ch );
		return;
	}

	if ( !IS_NPC(ch) && IS_NPC(victim) && victim->master!=ch)
	{
		send_to_combat_char( "Doesn't need your help!\n\r", ch );
		return;
	}

	if ( !ch->fighting )
	{
		send_to_combat_char( "Too late.\n\r", ch );
		return;
	}

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

        if( !IS_NPC( victim ) && !IS_NPC( fch ) )
	{
		send_to_combat_char( "That person cannot be rescued.\n\r", ch );
		return;
	}

        if( multi( ch, gsn_rescue)==-1 && !IS_NPC(ch))
	{
		send_to_combat_char( "You cannot rescue.\n\r", ch );
		return;
	}


	WAIT_STATE( ch, skill_table[gsn_rescue].beats );
	if ((!IS_NPC(ch) && number_range(0,150) >
	    ch->pcdata->learned[gsn_rescue]) || !is_same_group( ch, victim))
	{
		send_to_combat_char( "You fail the rescue.\n\r", ch );
                ch_printf(victim, "%s tried to rescue you, but failed!\n\r", get_name(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 );

	/* Chaos fixed on  4/22/99  */
    stop_fighting( victim, FALSE );
    for(fch=ch->in_room->first_person; fch!=NULL; fch=fch->next_in_room)
      if( who_fighting( fch ) == victim)
        {
        stop_fighting( fch, FALSE );
        if ( who_fighting(ch)!=NULL )
          stop_fighting( ch, FALSE );
        set_fighting( fch, ch );
        set_fighting( ch, fch );
        set_fighting( victim, fch );
        }

    return;
}



void do_kick( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	int cnt;

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}
      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;


	cnt = multi( ch, gsn_kick);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char( "You better leave the martial arts to fighters.\n\r", ch
		    );
		return;
	}

	if ( ( victim = who_fighting ( ch ) ) == NULL )
	{
		send_to_combat_char( "You aren't fighting anyone.\n\r", ch );
		return;
	}

	WAIT_STATE( ch, skill_table[gsn_kick].beats*200/(200+ch->mclass[cnt]));
    

	if ( IS_NPC(ch))
		damage( ch, victim, number_range( 1, ch->level ), gsn_kick);
	/* else if( number_percent( ) < ch->pcdata->learned[gsn_kick] ) */
	else if( number_percent( ) < ch->pcdata->learned[gsn_kick] &&
                 check_hit( ch, victim, 0-GET_HITROLL(ch), gsn_kick ) )
		damage( ch, victim, GET_DAMROLL(ch)+5+
		    number_range(ch->mclass[cnt],4*ch->mclass[cnt])/3, gsn_kick);
	else
		damage( ch, victim, 0, gsn_kick );

	return;
}

void do_bash( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    int chance,cnt;

    if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) )
    {
        send_to_char( "You can't concentrate enough for that.\n\r", ch );
        return;
    }

    if (get_eq_char(ch, WEAR_SHIELD) == NULL)
    {
        send_to_char("You cannot bash without a shield!\n\r", ch );
        return;
    }

    cnt = multi( ch, gsn_kick);
    if(cnt==-1 && !IS_NPC(ch))
    {
     send_to_combat_char( "You better leave the martial arts to fighters.\n\r", ch);
     return;
    }

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

   chance = ((get_curr_dex(ch) + get_curr_str(ch))
           -  (get_curr_dex(victim)     + get_curr_str(victim)))  + 10;

    WAIT_STATE( ch, skill_table[gsn_bash].beats*200/(200+ch->mclass[cnt]));

  if ( (number_percent () < ch->pcdata->learned[gsn_bash]/2 )
       && check_hit(ch, victim, chance, gsn_bash) )
    {
        damage( ch, victim, number_range( ch->level, ch->level*2 ), gsn_bash );
        if (number_percent()<chance)
        {
          WAIT_STATE( victim, PULSE_VIOLENCE );
          victim->position = POS_RESTING;
        }
    }
    else
    {
        damage( ch, victim, 0, gsn_bash );
    }
    return;
}


void do_martial_arts( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	int cnt, level;
        int dmgL, dmgH;
        int tshares, pshare;

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}

      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

	cnt = multi( ch, gsn_kick);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char(
		    "You better leave the martial arts to fighters.\n\r", ch
		    );
		return;
	}
      if( IS_NPC( ch ) )
        level = ch->level;
      else
        level = ch->mclass[ cnt ];

	if(!IS_NPC(ch) && level < 40 )
	{
		send_to_combat_char(
		    "You better leave the martial arts to fighters.\n\r", ch
		    );
		return;
	}

	if ( ( victim = who_fighting(ch) ) == NULL )
	{
		send_to_combat_char( "You aren't fighting anyone.\n\r", ch );
		return;
	}

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

            /* Find total shares */
    if( level < 50 )
      tshares = 8;
    else if( level < 60 )
      tshares = 15;
    else if( level < 70 )
      tshares = 21;
    else if( level < 80 )
      tshares = 26;
    else if( level < 90 )
      tshares = 30;
    else
      tshares = 33;

    pshare = number_range( 1, tshares );

    if( pshare <= 8 )
      martial_arts_attack = 1;
    else if( pshare <= 15 )
      martial_arts_attack = 2;
    else if( pshare <= 21 )
      martial_arts_attack = 3;
    else if( pshare <= 26 )
      martial_arts_attack = 4;
    else if( pshare <= 30 )
      martial_arts_attack = 5;
    else
      martial_arts_attack = 6;

    switch( martial_arts_attack )
      {
      case 2:
        dmgL = 5* level / 8;
        dmgH = 7 * level / 4;
        break;
      case 3:
        dmgL = 6 * level / 8;
        dmgH = 2 * level;
        break;
      case 4:
        dmgL = 7 * level / 8;
        dmgH = 9 * level / 4;
        break;
      case 5:
        dmgL = level;
        dmgH = 10 * level / 4;
        break;
      case 6:
        dmgL = 9 * level / 8;
        dmgH = 11 * level / 4;
        break;
      case 1:
      default:
        dmgL = level / 2;
        dmgH = 3 * level / 2;
        break;
      }

	if ( IS_NPC(ch))
	  damage( ch, victim, number_range( dmgL, dmgH), gsn_martial_arts);
	else
          if( number_percent( ) < ch->pcdata->learned[gsn_martial_arts] &&
              check_hit( ch, victim, 0-GET_HITROLL(ch), gsn_kick ) )
	    damage( ch, victim, GET_DAMROLL(ch)+5+
		    number_range(dmgL, dmgH), gsn_martial_arts);
	else
		damage( ch, victim, 0, gsn_martial_arts );

	return;
}




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

	cnt = multi( ch, gsn_disarm);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char( "You don't know how to disarm opponents.\n\r",
		    ch );
		return;
	}

	if ( ( victim = who_fighting(ch) ) == NULL )
	{
		send_to_combat_char( "You aren't fighting anyone.\n\r", ch );
		return;
	}

	if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
	{
		send_to_combat_char( "Your opponent is not wielding a weapon.\n\r",
		    ch );
		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 );
	else
		send_to_combat_char( "You failed.\n\r", ch );
	return;
}



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



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

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

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

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

	/*
        if ( IS_NPC(victim) && ch->level<99 && !IS_NPC(ch) )
	{
		send_to_combat_char( "You failed.\n\r", ch );
		return;
	}
       */
	if ( !IS_NPC(victim) && victim->level >= ch->level )
	{
		send_to_combat_char( "You failed.\n\r", ch );
		return;
	}

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

/*        victim->fighting->who=ch;*/
	raw_kill( victim );
        stop_hating( ch );
        stop_fearing( ch );
        stop_hunting( ch );
	return;
}

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

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

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

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

	if ( IS_NPC(victim) && ch->level<99 && !IS_NPC(ch) )
	{
		send_to_combat_char( "You failed.\n\r", ch );
		return;
	}

	if ( !IS_NPC(victim) && victim->level > ch->level )
	{
		send_to_combat_char( "You failed.\n\r", ch );
		return;
	}

	act( "You slaughter $M in cold blood!",  ch, NULL, victim, TO_CHAR   );
	act( "$n slaughters you in cold blood!", ch, NULL, victim, TO_VICT   );
	act( "$n slaughters $N in cold blood!",  ch, NULL, victim, TO_NOTVICT);
  /*victim->fighting->who=ch;*/
	if ( !IS_NPC(victim)  )
	{
	 log_printf( "%s slaughtered by %s at %u",
			    victim->name, get_name( ch ) ,
			    victim->in_room->vnum );

	 if (victim->level < 2)
  	  gain_exp( victim, 0-(victim->exp/2));
	 else
 	  if(victim->exp>exp_level(victim->class,(victim->level)-1)+1)
	   gain_exp( victim, exp_level(victim->class, (victim->level)-1)+1-
		   victim->exp);
	  if(IS_SET(victim->act, PLR_KILLER) || IS_SET(victim->act, PLR_THIEF))
	  {
  	   if(victim->level>1)
             if(victim->exp>exp_level(victim->class, (victim->level)-2)+1)
	       gain_exp( victim, exp_level(victim->class, (victim->level)-2)+1-
		   victim->exp);
	   if(victim->level<2)
	     gain_exp( victim, -victim->exp);
           if(IS_SET(victim->act, PLR_KILLER))
	     victim->act-=PLR_KILLER;
	   if(IS_SET(victim->act, PLR_THIEF))
	     victim->act-=PLR_THIEF;
	  }
	 }
	raw_kill( victim );
	return;
}

void do_suicide( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
  bool killer, thief;
  killer=FALSE;
  thief=FALSE;
  if(!IS_NPC(ch))
    {
    if( IS_SET( ch->act, PLR_KILLER) )
      killer = TRUE;
    if( IS_SET( ch->act, PLR_THIEF) )
      thief = TRUE;
    }
  if(IS_AFFECTED(ch,AFF_CHARM)&&!IS_SET(ch->act,ACT_PET))
    {
    wipe_string( argument );
    return;
    }
  if(ch->fighting != NULL)
    {
    sprintf( arg, "%s is trying to kill you, and suicide is not an option.\n\r",
      ch->fighting->who->name );
    send_to_combat_char( arg, ch);
    wipe_string( argument );
    return;
    }
  if( IS_NPC( ch))
    {
    /*if( IS_AFFECTED( ch, AFF_CHARM))
      ch->fighting->who=ch->master;*/
    raw_kill( ch );
    wipe_string( argument );
    return;
    }
	one_argument_nolower( argument, arg );
	if ( arg[0] == '\0' )
	{
		send_to_combat_char( "!!!  WARNING  !!!   This command is used to kill yourself.\n\rTo use you must enter in your password after the command.\n\r", ch );
    wipe_string( argument );
		return;
	}
  if(!strcasecmp(crypt(arg,ch->pcdata->pwd),ch->pcdata->pwd))
    {
    send_to_combat_char( "You commited suicide!\n\r", ch);
    /*ch->fighting->who=ch;*/
    raw_kill(ch);
    if( killer)
      SET_BIT( ch->act, PLR_KILLER);
    if( thief)
      SET_BIT( ch->act, PLR_THIEF);
    wipe_string( argument );
    return;
    }
  else
    {
    send_to_combat_char( "That was not your password.  Are you sure you want to commit suicide?\n\r", ch);
    wipe_string( argument );
    return;
    }
  wipe_string( argument );
  return;
}


/* klugee globals...-dug */
int fCRrNum,fCRvNum,fCRvCnt;

/*
 * Find a char in the room.
 */
CHAR_DATA *fCR_get_char_room(CHAR_DATA *ch,ROOM_INDEX_DATA *rm, char *argument
)
{
	CHAR_DATA *rch;

	if(IS_SET(rm->room_flags,ROOM_PRIVATE|ROOM_SAFE|ROOM_SOLITARY)||
	    (!IS_NPC(ch) && !IS_SET(ch->act, PLR_HOLYLIGHT) && room_is_dark(rm)))
		return NULL;
	for(rch = rm->first_person; rch != NULL; rch = rch->next_in_room )
	{
		if(!can_see(ch,rch)||!is_name(argument,rch->name))
			continue;
		if(++fCRvCnt==fCRvNum)
			return rch;
	}
	for(rch = rm->first_person; rch != NULL; rch = rch->next_in_room )
	{
		if(!can_see(ch,rch)||!is_name_short(argument,rch->name))
			continue;
		if(++fCRvCnt==fCRvNum)
			return rch;
	}
	return NULL;
}

void findCharRoom(CHAR_DATA *ch,ROOM_INDEX_DATA *rm,CHAR_DATA **victim,int
dirNum,int shoot_range,char *chName)
{
	if(++fCRrNum>shoot_range)
		return;
	if((*victim=fCR_get_char_room(ch,rm,chName))==NULL)
	{
		if(rm->exit[dirNum]==NULL)
			return;
		if(IS_SET(rm->exit[dirNum]->exit_info, EX_CLOSED))
			return;
		if(rm->exit[dirNum]->to_room==NULL)
			return;
		findCharRoom(ch,rm->exit[dirNum]->to_room,victim,dirNum,shoot_range,
		    chName);
	}
	return;
}

int findCharDir(CHAR_DATA *ch,CHAR_DATA **victim, int dirNum, char *chName)
{
	char arg[MAX_INPUT_LENGTH];
	int shoot_range;

	fCRrNum=0;
	fCRvCnt=0;
	fCRvNum=number_argument(chName,arg);
	if(IS_NPC(ch))
		shoot_range=MED_RANGE;
	else
		shoot_range=ch->pcdata->learned[gsn_long_range]>0?LONG_RANGE:
		    ch->pcdata->learned[gsn_med_range]>0?MED_RANGE:SHORT_RANGE;
	if(ch->in_room->exit[dirNum]==NULL)
		return 0;
	if(IS_SET(ch->in_room->exit[dirNum]->exit_info, EX_CLOSED))
		return 0;
	if(ch->in_room->exit[dirNum]->to_room==NULL)
		return 0;
	findCharRoom(ch,ch->in_room->exit[dirNum]->to_room,victim,dirNum,
	    shoot_range,arg);
	return fCRrNum;
}

int getDirNumber(char *dirName)
{
	int dirLen;

	dirLen=strlen(dirName);
	if(dirLen==0)
		return -1;
	if(strncmp(dirName,"north",dirLen)==0)
		return DIR_NORTH;
	if(strncmp(dirName,"east",dirLen)==0)
		return DIR_EAST;
	if(strncmp(dirName,"south",dirLen)==0)
		return DIR_SOUTH;
	if(strncmp(dirName,"west",dirLen)==0)
		return DIR_WEST;
	if(strncmp(dirName,"up",dirLen)==0)
		return DIR_UP;
	if(strncmp(dirName,"down",dirLen)==0)
		return DIR_DOWN;
	return -1;
}

void do_shoot( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	OBJ_DATA  *ammo,*ammo2,*weapon;
	int cnt,ammoNum,dirNum,distance,dam;
	char *dirName,*chName,*arg,buf1[MAX_INPUT_LENGTH],buf2[MAX_INPUT_LENGTH];
  char buf[MAX_INPUT_LENGTH];


      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

	cnt = multi(ch,gsn_shoot);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char("You'd better leave the shooting to the assassins.\n\r",
		    ch );
		return;
	}
	if(ch->wait!=0)
	{
		send_to_combat_char("You fumble around and don't get any shots off!\n\r",
		    ch);
		return;
	}
	if(IS_SET(ch->in_room->room_flags,ROOM_SAFE))
	{
		send_to_combat_char("You can't shoot from this location!\n\r",ch);
		return;
	}
	if(ch->fighting!=NULL)
	/*	if(ch->in_room==(ch->fighting->who)->in_room)*/
		{
			send_to_combat_char( "You are too distracted to shoot!\n\r", ch );
			return;
		}
	weapon=get_eq_char(ch,WEAR_WIELD);
	if( weapon==NULL)
	{
		send_to_combat_char( "You must wield a weapon to shoot!\n\r", ch);
		return;
	}
	if(weapon->item_type!=ITEM_WEAPON)
	{
		send_to_combat_char( "You must wield a weapon to shoot!\n\r", ch);
		return;
	}
	if(weapon->value[0]==0)
	{
		send_to_combat_char("You are not wielding a weapon that can shoot!\n\r", ch);
		return;
	}
	ammoNum=weapon->value[0];

	for(ammo=ch->first_carrying,ammo2=NULL;ammo!=NULL;ammo=ammo->next_content)
	{
		if(ammo->item_type==ITEM_AMMO)
			if(ammo->value[0]==ammoNum)
				break;
		if(ammo->item_type==ITEM_CONTAINER)
			if((ammo->first_content!=NULL)&&!IS_SET(ammo->value[1], CONT_CLOSED))
			{
				for(ammo2=ammo->first_content;ammo2!=NULL;ammo2= ammo2->next_content)
				{
					if(ammo2->item_type==ITEM_AMMO)
						if(ammo2->value[0]==ammoNum)
						{
							OBJ_DATA *ammoTmp;
							ammoTmp=ammo;
							ammo=ammo2;
							ammo2=ammoTmp;
							break;
						}
				}
				if(ammo2!=NULL)
					break;
			}
	}
	if(ammo==NULL)
	{
		send_to_combat_char("Ooops...forgot to stock up on ammunition, eh?\n\r", ch);
		return;
	}
	arg=one_argument(argument,buf1);
	one_argument(arg,buf2);
	if((dirNum=getDirNumber(buf1))==-1)
	{
		if((dirNum=getDirNumber(buf2))==-1)
		{
			send_to_combat_char( "Shoot which direction?\n\r", ch );
			return;
		}
		dirName=buf2;
		chName=buf1;
	}
	else
	{
		dirName=buf1;
		chName=buf2;
	}
	if (chName[0]=='\0')
	{
		send_to_combat_char( "Shoot at whom?\n\r", ch );
		return;
	}
	victim=NULL; /* to get rid of warnings */
	distance=findCharDir(ch,&victim,dirNum,chName);
	if(victim==NULL)
	{
		send_to_combat_char("Your victim must have slipped out of sight!\n\r", ch);
		return;
	}
	if(ch==victim)
	{
		send_to_combat_char("Shooting yourself could prove painful.\n\r", ch );
		return;
	}
      if( ch->in_room->area != victim->in_room->area )
	{
		send_to_combat_char("They are too far to shoot at.\n\r", ch );
		return;
	}
	if(distance==0)
	{
		send_to_combat_char("They are too close to shoot at!\n\r", ch );
		return;
	}
	if(IS_NPC(victim)&&victim->shot_aware)
	{
		send_to_combat_char("Your target is too wary to be shot at!\n\r", ch);
		return;
	}
  if( !IS_NPC(victim) && !IS_NPC(ch) && 
       ch->in_room->area->low_r_vnum!=ROOM_VNUM_ARENA)
    {
    send_to_combat_char( "You may not shoot another player.\n\r", ch);
    return;
    }
  if( IS_NPC( victim) && victim->fighting!=NULL && !IS_NPC( ch ) &&
	!is_same_group( ch, victim->fighting->who ))
    {
    sprintf( buf ,"%s seems to be busy!\n\r", capitalize(victim->short_descr));
    send_to_combat_char( buf, ch);
    return;
    }

  if( (!IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) ) &&
    ( IS_NPC( victim) && victim->fighting==NULL && 
      victim->npcdata->pvnum_last_hit_leader > 0 ) ) 
    {
    CHAR_DATA *ch_ld;
    int pvnum_ld;

    ch_ld = ch;
    if( IS_NPC( ch ) )
      ch_ld = ch_ld->master;
    if( ch_ld->leader != NULL )
      ch_ld = ch_ld->leader;
    if( !IS_NPC( ch_ld ) )
      pvnum_ld=ch_ld->pcdata->pvnum;
    else
      pvnum_ld=0;
    if( pvnum_ld != victim->npcdata->pvnum_last_hit_leader )
      {
      sprintf( buf ,"%s was recently fought.  Try later.\n\r", 
           capitalize(victim->short_descr));
      send_to_combat_char( buf, ch);
      return;
      }
    }

	/* set wait time for speed of archer...*/
	if(ch->mclass[cnt]==-1 && !IS_NPC(ch) )
    {
    send_to_combat_char( "You can't do that!\n\r", ch);
    return;
    }
	if(!IS_NPC(ch))
		WAIT_STATE( ch, ammo->value[2]/(1+(ch->mclass[cnt]/10)));
	else
		WAIT_STATE( ch, ammo->value[2]);
	if(ammo2==NULL)
		obj_from_char(ammo);
	else
	{
		act( "$n pulls $p from $P.", ch, ammo, ammo2, TO_ROOM );
		act( "You pull $p from $P.", ch, ammo, ammo2, TO_CHAR );
		obj_from_obj(ammo);
	}
	if(IS_NPC(victim))
	{
		victim->shot_timer=2;
		victim->shot_from=rev_dir[dirNum];
	}
	if(IS_NPC(ch))
	{
		if(number_percent()<30)
			extract_obj( ammo );
		else
			obj_to_char( ammo, victim);
		dam=number_range( 1, ammo->value[1]*ammo->value[3]/distance);
	}
	else if(number_percent( ) < ch->pcdata->learned[gsn_shoot] &&
               check_hit( ch, victim, 0, gsn_shoot) )
	{
		if(number_percent()<25)
			extract_obj( ammo );
		else
			obj_to_char( ammo, victim);
		dam=number_range( 1, ammo->value[1]*ammo->value[3]/distance);
	}
	else
	{
		if ( IS_SET( ammo->extra_flags, ITEM_INVENTORY ) &&(number_percent()<
		    25))
			extract_obj( ammo );
		else
      {
      ammo->sac_timer=OBJ_SAC_TIME;
			obj_to_room(ammo,victim->in_room);
      }
		dam=0;
	}
	  mprog_range_trigger(victim,ch);
	damage(ch,victim,dam,gsn_shoot);
  stop_fighting( ch, TRUE);
	return;
}

void do_throw( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	OBJ_DATA  *weapon;
	int cnt,dirNum,distance,dam;
	char buf1[MAX_INPUT_LENGTH],buf2[MAX_INPUT_LENGTH],buf3[MAX_INPUT_LENGTH],
	    *arg,*dirName,*chName,*objName,buf[MAX_INPUT_LENGTH];
	bool wielded;


      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

	cnt = multi(ch,gsn_throw);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char("You decide not to throw...might hurt your back.\n\r",
		    ch );
		return;
	}
	if(ch->wait!=0)
	{
		send_to_combat_char("You fumble around and don't throw a thing!\n\r",
		    ch);
		return;
	}
	if(IS_SET(ch->in_room->room_flags,ROOM_SAFE))
	{
		send_to_combat_char("You can't throw from this location!\n\r",ch);
		return;
	}
	if(ch->fighting!=NULL)
	/*	if(ch->in_room==(ch->fighting->who)->in_room)*/
		{
			send_to_combat_char( "You are too distracted to throw!\n\r",
			    ch );
			return;
		}
	buf1[0]='\0';
	buf2[0]='\0';
	buf3[0]='\0';
	arg=one_argument(argument,buf1);
	arg=one_argument(arg,buf2);
	arg=one_argument(arg,buf3);
	if((dirNum=getDirNumber(buf1))==-1)
	{
		if((dirNum=getDirNumber(buf2))==-1)
		{
			if((dirNum=getDirNumber(buf3))==-1)
			{
				send_to_combat_char( "Throw which direction?\n\r",
				    ch );
				return;
			}
			else
			{
				dirName=buf3;
				chName=buf2;
				objName=buf1;
			}
		}
		else
		{
			chName=buf3;
			dirName=buf2;
			objName=buf1;
		}
	}
	else
	{
		chName=buf3;
		objName=buf2;
		dirName=buf1;
	}
	if (chName[0]=='\0')
	{
		send_to_combat_char( "Throw what at whom?\n\r", ch );
		return;
	}
	victim=NULL; /* to get rid of warnings */
	distance=findCharDir(ch,&victim,dirNum,chName);
	if(victim==NULL)
	{
		send_to_combat_char("Your victim must have slipped out of sight!\n\r",
		    ch);
		return;
	}
	if(ch==victim)
	{
		send_to_combat_char("You can't throw that at yourself!\n\r", ch
		    );
		return;
	}
      if( ch->in_room->area != victim->in_room->area )
	{
		send_to_combat_char("They are too far to throw things at.\n\r", ch );
		return;
	}
	if(distance==0)
	{
		send_to_combat_char("They are too close to throw at!\n\r", ch );
		return;
	}
	if(IS_NPC(victim)&&victim->shot_aware)
	{
		send_to_combat_char("You can't seem to get a good sight of your target!\n\r",
		    ch);
		return;
	}
  if( !IS_NPC(victim) && !IS_NPC(ch) &&
       ch->in_room->area->low_r_vnum!=ROOM_VNUM_ARENA)
    {
    send_to_combat_char( "You may not throw at another player.\n\r", ch);
    return;
    }
  if( IS_NPC( victim) && victim->fighting!=NULL && !IS_NPC( ch ) &&
	!is_same_group( ch, victim->fighting->who ))
    {
    sprintf( buf ,"%s seems to be busy!\n\r", capitalize(victim->short_descr));
    send_to_combat_char( buf, ch);
    return;
    }
  if( (!IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) ) &&
    ( IS_NPC( victim) && victim->fighting==NULL && 
      victim->npcdata->pvnum_last_hit_leader > 0 ) ) 
    {
    CHAR_DATA *ch_ld;
    int pvnum_ld;

    ch_ld = ch;
    if( IS_NPC( ch ) )
      ch_ld = ch_ld->master;
    if( ch_ld->leader != NULL )
      ch_ld = ch_ld->leader;
    if( !IS_NPC( ch_ld ) )
      pvnum_ld=ch_ld->pcdata->pvnum;
    else
      pvnum_ld=0;
    if( pvnum_ld != victim->npcdata->pvnum_last_hit_leader )
      {
      sprintf( buf ,"%s was recently fought.  Try later.\n\r", 
          capitalize(victim->short_descr));
      send_to_combat_char( buf, ch);
      return;
      }
    }
	wielded=FALSE;
	weapon=get_eq_char(ch,WEAR_WIELD);
	if(weapon!=NULL)
		if(is_name(objName,weapon->name))
			wielded=TRUE;
	if(weapon!=NULL && !wielded)
		if(is_name_short(objName,weapon->name))
			wielded=TRUE;
	if(!wielded)
	{
		if(!remove_obj(ch,WEAR_WIELD,TRUE, FALSE))
		{
			send_to_combat_char("You can't throw with another weapon wielded!\n\r",
			    ch);
			return;
		}
		for(weapon=ch->first_carrying; weapon!=NULL; weapon=weapon->next_content)
		{
			if(weapon->item_type==ITEM_WEAPON)
				if(is_name(objName,weapon->name))
					break;
		}
		for(weapon=ch->first_carrying; weapon!=NULL; weapon=weapon->next_content)
		{
			if(weapon->item_type==ITEM_WEAPON)
				if(is_name_short(objName,weapon->name))
					break;
		}
	}
	if(weapon==NULL)
	{
		send_to_combat_char("Hmmm...you don't seem to have that weapon.\n\r",
		    ch);
		return;
	}
	if(weapon->value[3]!=2&&weapon->value[3]!=6&&weapon->value[3]!=7 &&
     weapon->value[3]!=8&&weapon->value[3]!=11)
	{
		send_to_combat_char("You can't throw that type of weapon!",ch);
		return;
	}

	if(!wielded)
		WAIT_STATE( ch, skill_table[gsn_throw].beats );
	else
		WAIT_STATE( ch, skill_table[gsn_throw].beats/2 );
	if(IS_NPC(victim))
		victim->shot_timer=2;
	dam=1;
	if(IS_NPC(ch))
	{
		obj_from_char(weapon);
		if(number_percent()<20)
			extract_obj( weapon );
		else
			obj_to_char( weapon, victim);
	}
	else if(number_percent( ) < ch->pcdata->learned[gsn_throw] &&
               !check_hit( ch, victim, 0, gsn_throw )  )
	{
		obj_from_char(weapon);
		if(number_percent()<5)
			extract_obj( weapon );
		else
			obj_to_char( weapon, victim);
	}
	else
	{
		obj_from_char(weapon);
		if ( IS_SET( weapon->extra_flags, ITEM_INVENTORY ) &&(number_percent()<
		    5))
			extract_obj( weapon );
		else
      {
      weapon->sac_timer=OBJ_SAC_TIME;
			obj_to_room( weapon, victim->in_room);
      }
		dam=0;
	}
	if(dam==1)
		one_hit(ch,victim,gsn_throw);
	else
		damage(ch,victim,0,gsn_throw);
	if(victim->position!=POS_DEAD)
		mprog_range_trigger(victim,ch);
  stop_fighting( ch, TRUE);
	return;
}

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


      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

	if ( !IS_NPC(ch) && multi(ch,gsn_divert)==-1)
	{
		send_to_combat_char( "You can't do that!\n\r", ch );
		return;
	}

	if(ch->fighting==NULL)
	{
		send_to_combat_char( "You aren't fighting!\n\r", ch );
		return;
	}
	one_argument( argument, arg );
	if ( arg[0] == '\0' )
	{
		send_to_combat_char( "Divert to whom?\n\r", ch );
		return;
	}

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

	if ( victim == ch )
	{
		send_to_combat_char( "That's stupid.\n\r", ch );
		return;
	}

	if(( victim->level < ch->level )&&(!is_same_group(ch,victim)))
	{
		send_to_combat_char( "You can't divert to a lower level character!\n\r",
		    ch );
		return;
	}

	if ( ch->fighting->who == victim )
	{
		act( "Trying to make $m fight $mself?",  ch, NULL, victim,
		    TO_CHAR    );
		return;
	}

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

	WAIT_STATE( ch, skill_table[gsn_divert].beats );
	if ((!IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_divert])
	     || !IS_NPC(fch))
	{
		send_to_combat_char( "You fail the divert.\n\r", ch );
		return;
	}

	act( "You divert the attack to $N!",  ch, NULL, victim, TO_CHAR 
	    );
	act( "$n diverts the attack to you!", ch, NULL, victim, TO_VICT 
	    );
	act( "$n diverts the attack to $N!",  ch, NULL, victim, TO_NOTVICT
	    );

	/* Chaos 12/27/93  
	for( fch=first_char; fch!=NULL; fch=fch->next)
		if( fch->fighting->who == ch)
			fch->fighting->who = victim;*/

    	/* Re-done by Martin 9/19/99 */
	stop_fighting(victim, FALSE);
	if (ch->fighting)
	  stop_fighting(ch, FALSE);
	for( fch=ch->in_room->first_person; fch!=NULL; fch=fch->next_in_room)
	{
		if( fch->fighting && fch->fighting->who == ch)
		{
			stop_fighting(fch, FALSE);
			set_fighting(fch, victim);
		}
	}

	return;
}

void do_knife( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA *obj;
	int cnt;

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}

      /* Stop fights of aggressives if currently hurt - Chaos 11/10/97  */
    if( IS_NPC(ch) && ch->fighting==NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

	cnt = multi( ch, gsn_knife);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char( "You'd better leave the nasty stuff to assassins.\n\r",
		    ch );
		return;
	}

	if((obj=get_eq_char(ch,WEAR_WIELD))==NULL
	    ||(obj->value[3]!=11&&obj->value[3]!=2))
	{
		send_to_combat_char( "You need to wield a piercing weapon.\n\r",
		    ch );
		return;
	}
	one_argument( argument, arg );
	if ( arg[0] == '\0' )
	  {
	       if ( ( victim = who_fighting(ch) ) == NULL )
		{
			send_to_combat_char("You are not fighting anyone.\n\r",ch);
			return;
		}
          }
	else
	{
		victim=get_char_room_even_hidden(ch,arg);
		if(victim==NULL)
		{
			send_to_combat_char("Knife who?\n\r",ch);
			return;
		}
	}

    if( !IS_NPC(ch) && ( !IS_NPC(victim) || IS_AFFECTED( victim, AFF_CHARM)) )
     {
      if(ch->fighting==NULL || ( ch->fighting->who != victim ) )
	{
	send_to_combat_char( "You may not do that.\n\r", ch);
	return;
	}
     }

 if( IS_NPC( victim ))
 if ( victim->fighting && victim->fighting->who!=ch 
    && IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
  {
  if( victim->master == ch && IS_SET( victim->act, ACT_PET))
    {
    raw_kill( victim );
    return;
    }
  send_to_combat_char( "You cannot kill a slave.\n\r", ch );
  return;
  }

  if( victim->fighting != NULL && !is_same_group( victim->fighting->who, ch ))
    {
    send_to_combat_char( "They are currently busy.\n\r", ch );
    return;
    }
   
  if( ( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) ) &&
    ( IS_NPC( victim) && victim->fighting==NULL && 
      victim->npcdata->pvnum_last_hit_leader > 0 ) ) 
    {
    CHAR_DATA *ch_ld;
    int pvnum_ld;

    ch_ld = ch;
    if( IS_NPC( ch ) )
      ch_ld = ch_ld->master;
    if( ch_ld->leader != NULL )
      ch_ld = ch_ld->leader;
    if( !IS_NPC( ch_ld ) )
      pvnum_ld=ch_ld->pcdata->pvnum;
    else
      pvnum_ld=0;
    if( pvnum_ld != victim->npcdata->pvnum_last_hit_leader )
      {
      char buf[MAX_INPUT_LENGTH];
      sprintf( buf ,"%s was recently fought.  Try later.\n\r", 
          capitalize(victim->short_descr));
      send_to_combat_char( buf, ch);
      return;
      }
    }

     WAIT_STATE( ch, skill_table[gsn_knife].beats*100/(100+ch->mclass[cnt]));
	if ( IS_NPC(ch))
	  one_hit( ch, victim, gsn_knife );
	else if( number_percent( ) < ch->pcdata->learned[gsn_knife] )
	  one_hit( ch, victim, gsn_knife );
	else
	  damage( ch, victim, 0, gsn_knife );

	return;
}

void do_distract( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int cnt;
        char buf[MAX_INPUT_LENGTH];

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
	{
		send_to_combat_char( "You cannot do that here.\n\r", ch);
		return;
	}
	cnt = multi( ch, gsn_distract);
	if(cnt==-1 && !IS_NPC(ch))
	{
		send_to_combat_char( "They'd just get mad at you if you tried.\n\r",
		    ch );
		return;
	}
	one_argument(argument,arg);
	if((victim=get_char_room(ch,arg))==NULL)
	{
		send_to_combat_char("Distract who?\n\r",ch);
		return;
	}

  if( (!IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) ) &&
    ( IS_NPC( victim) && victim->fighting==NULL && 
      victim->npcdata->pvnum_last_hit_leader > 0 ) ) 
    {
    CHAR_DATA *ch_ld;
    int pvnum_ld;

    ch_ld = ch;
    if( IS_NPC( ch ) )
      ch_ld = ch_ld->master;
    if( ch_ld->leader != NULL )
      ch_ld = ch_ld->leader;
    if( !IS_NPC( ch_ld ) )
      pvnum_ld=ch_ld->pcdata->pvnum;
    else
      pvnum_ld=0;
    if( pvnum_ld != victim->npcdata->pvnum_last_hit_leader )
      {
      sprintf( buf ,"%s was recently fought.  Try later.\n\r", 
          capitalize(victim->short_descr));
      send_to_combat_char( buf, ch);
      return;
      }
    }

	WAIT_STATE( ch, skill_table[gsn_distract].beats );
	if ( IS_NPC(ch)||
	    ( number_percent( ) < ch->pcdata->learned[gsn_distract]+
	    (ch->level-victim->level)*10 ))
	{
		send_to_combat_char("You convince them that their shoes are untied!\n\r",
		    ch);
		victim->distracted+=10;/* number of waits they will be distracted for */
		return;
	}
	else
	{
		send_to_combat_char( "They suddenly look very suspicious.\n\r", ch );
		act( "$n tries to distract you!", ch, NULL, victim, TO_VICT);
		victim->distracted=0;
		if(IS_NPC(victim)&&(victim->level>ch->level)&&(number_percent()>40))
		{
			act( "$n suddenly looks VERY angry!",victim,NULL,
			    NULL,TO_ROOM);
			if(victim->fighting!=NULL)
				stop_fighting(victim,FALSE);
			one_hit(victim,ch,TYPE_UNDEFINED);
			if((ch->position!=POS_DEAD)&&(number_percent()<60))
			{
				stop_fighting(victim,FALSE);
				one_hit(victim,ch,TYPE_UNDEFINED);
			}
		}
		return;
	}

	return;
}

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

    if ( !ch->fighting )
      return NULL;

    return ch->fighting->who;
}

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

  free_fight( ch );
  update_pos( ch );

  if (!fBoth)
   return; 

  for ( fch = first_char ; fch != NULL; fch = fch->next )
    if ( who_fighting( fch ) == ch ) 
      {
      free_fight( fch );
      update_pos( fch );
      }
  return;
}

void leave_fighting( CHAR_DATA *ch, ROOM_INDEX_DATA *was_in)
{
  CHAR_DATA *fch, *gch;
  bool done;

  stop_fighting( ch, TRUE );
  return;
  for(fch = was_in->first_person; fch != NULL; fch = fch->next_in_room)
    if(fch->fighting->who==ch && fch!= ch->master &&
       !is_same_group( ch, fch) && !( IS_NPC( ch) && IS_NPC( fch) &&
       !IS_AFFECTED( ch, AFF_CHARM) && !IS_AFFECTED( fch, AFF_CHARM )))
      {/* Found someone in the attacking party */
      done=FALSE;
      for(gch = was_in->first_person; !done && gch != NULL; gch = gch->next_in_room)
        if( gch!=ch && gch!=fch)
          if( is_same_group( ch, gch) || 
              ( IS_NPC( gch) && !IS_AFFECTED( gch, AFF_CHARM ) &&
                IS_NPC( ch) && !IS_AFFECTED( ch, AFF_CHARM) &&
                ch->fighting->who != NULL && is_same_group(ch->fighting->who,fch)))
            if( ( IS_NPC( gch) && !IS_AFFECTED( gch, AFF_CHARM )) ||
                (IS_NPC( fch) && !IS_AFFECTED( fch, AFF_CHARM)) )
              if( should_fight( fch, gch ))
                {/* Set attacking player to fight next opponent */
                fch->fighting->who=gch;
                done=TRUE;
                }
      if(!done)
        stop_fighting( fch, FALSE);
      }


  return;
}

bool should_fight( CHAR_DATA *ch, CHAR_DATA *victim)
  {
  if( IS_NPC( ch) && !IS_AFFECTED( ch, AFF_CHARM) && 
      (ch->pIndexData->vnum!=9900 || IS_AFFECTED(ch, AFF2_POSSESS))
      && (!IS_NPC( victim) || IS_AFFECTED( victim, AFF_CHARM)))
    if( ch->level +60 < victim->level)
      return( FALSE );
  return(TRUE);
  }

void do_auto( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_INPUT_LENGTH];
  int sn, cnt;

  if( IS_NPC( ch) || IS_AFFECTED( ch, AFF_CHARM))
    return;

  if( argument[0]=='\0')
    {
    send_to_combat_char( "Syntax:  AUTO [AUTO] [QUICK] [<skill/spell>]\n\r", ch);
    if( ch->pcdata->auto_command !=NULL || ch->pcdata->auto_command[0]=='\0')
      sprintf( buf, "Current command:  %s\n\r", ch->pcdata->auto_command);
    else
      sprintf( buf, "Current command:  Not defined\n\r" );
    send_to_combat_char( buf, ch);
    if( ch->pcdata->auto_flags == AUTO_OFF)
      send_to_combat_char( "Current mode:  Off\n\r", ch);
    if( ch->pcdata->auto_flags == AUTO_AUTO)
      send_to_combat_char( "Current mode:  Auto\n\r", ch);
    if( ch->pcdata->auto_flags == AUTO_QUICK)
      send_to_combat_char( "Current mode:  Quick\n\r", ch);
    return;
    }

  if( !strcasecmp( argument, "auto") )
    {
    send_to_combat_char( "Turning AUTO mode on.\n\r", ch);
    ch->pcdata->auto_flags=AUTO_AUTO;
    return;
    }
  
  if( !strcasecmp( argument, "quick") )
    {
    send_to_combat_char( "Turning QUICK mode on.\n\r", ch);
    ch->pcdata->auto_flags=AUTO_QUICK;
    return;
    }

  if( !strcasecmp( argument, "off") )
    {
    send_to_combat_char( "Turning auto modes off.\n\r", ch);
    ch->pcdata->auto_flags=AUTO_OFF;
    return;
    }

  /* scan for valid skill/spell */

    sn = skill_lookup( argument );
    if( sn < 0)
       {
       send_to_combat_char( "That is not a skill/spell.\n\r", ch );
       return;
       }
  /* Disallow ppl to do silly things like auto parry or auto short range
     Martin 7/8/98 */
    if ( skill_table[sn].minimum_position != POS_FIGHTING 
         && sn != gsn_backstab )
       {
       send_to_combat_char( "You cannot put that skill/spell on auto.\n\r", ch );
       return;
       }
      
    cnt = multi( ch, sn);

    if(cnt==-1 && !IS_NPC(ch))
       {
	send_to_combat_char( "You can't do that.\n\r", ch );
	return;
       }

  strcpy( argument, skill_table[sn].name);

  STRFREE (ch->pcdata->auto_command);
  ch->pcdata->auto_command = STRALLOC( argument );
  sprintf( buf, "Auto command set to: %s\n\r", argument );
  send_to_combat_char( buf, ch);
  return;
  }

void do_spam( CHAR_DATA *ch, char *arg)
  {
  int val;

  if( arg == NULL || arg[0]=='\0' )
    {
    send_to_combat_char( "SPAM control settings:\n\r", ch);
      send_to_combat_char( "Toggle  Status  Description\n\r", ch);

    if( !IS_SET( ch->pcdata->spam, 1))
      send_to_combat_char( "  A       On    You hit\n\r" , ch);
    else
      send_to_combat_char( "  A       Off   You hit\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 2))
      send_to_combat_char( "  B       On    You miss\n\r" , ch);
    else
      send_to_combat_char( "  B       Off   You miss\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 4))
      send_to_combat_char( "  C       On    They hit you\n\r" , ch);
    else
      send_to_combat_char( "  C       Off   They hit you\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 8))
      send_to_combat_char( "  D       On    They miss you\n\r" , ch);
    else
      send_to_combat_char( "  D       Off   They miss you\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 16))
      send_to_combat_char( "  E       On    Party hits\n\r" , ch);
    else
      send_to_combat_char( "  E       Off   Party hits\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 32))
      send_to_combat_char( "  F       On    Party misses\n\r" , ch);
    else
      send_to_combat_char( "  F       Off   Party misses\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 64))
      send_to_combat_char( "  G       On    They hit party\n\r" , ch);
    else
      send_to_combat_char( "  G       Off   They hit party\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 128))
      send_to_combat_char( "  H       On    They miss party\n\r" , ch);
    else
      send_to_combat_char( "  H       Off   They miss party\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 256))
      send_to_combat_char( "  I       On    Other hit\n\r" , ch);
    else
      send_to_combat_char( "  I       Off   Other hit\n\r" , ch);
    
    if( !IS_SET( ch->pcdata->spam, 512))
      send_to_combat_char( "  J       On    Other miss\n\r" , ch);
    else
      send_to_combat_char( "  J       Off   Other miss\n\r" , ch);
    
    if( IS_SET( ch->pcdata->spam, 1024))
      send_to_combat_char( "  K       On    Show party status line\n\r" , ch);
    else
      send_to_combat_char( "  K       Off   Show party status line\n\r" , ch);

    return;
    }

  val = -1;

  if( arg[0]=='a' || arg[0]=='A')
    val = 1;
  if( arg[0]=='b' || arg[0]=='B')
    val = 2;
  if( arg[0]=='c' || arg[0]=='C')
    val = 4;
  if( arg[0]=='d' || arg[0]=='D')
    val = 8;
  if( arg[0]=='e' || arg[0]=='E')
    val = 16;
  if( arg[0]=='f' || arg[0]=='F')
    val = 32;
  if( arg[0]=='g' || arg[0]=='G')
    val = 64;
  if( arg[0]=='h' || arg[0]=='H')
    val = 128;
  if( arg[0]=='i' || arg[0]=='I')
    val = 256;
  if( arg[0]=='j' || arg[0]=='J')
    val = 512;
  if( arg[0]=='k' || arg[0]=='K')
    val = 1024;
    
  if( val == -1 )
    {
    send_to_combat_char( "That is not an option.\n\r", ch );
    return;
    }
  if( IS_SET( ch->pcdata->spam, val ))
    ch->pcdata->spam -= val;
  else
    ch->pcdata->spam += val;

  do_spam( ch, "" );   /* show stat change */
   
  return;
  }

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

void do_assassinate( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_INPUT_LENGTH];
  char arg[MAX_INPUT_LENGTH],arg2[MAX_INPUT_LENGTH];
  CHAR_DATA *victim;
  int exp_cost,level;

  if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
    {
    send_to_combat_char( "You cannot do that here.\n\r", ch);
    return;
    }

  if( multi( ch, gsn_assassinate)==-1 || IS_NPC(ch) || 
      ch->class!=CLASS_ASSASSIN)
    {
    send_to_combat_char( "Only assassins can assassinate.\n\r", ch );
    return;
    }
  level=IS_NPC(ch) ? ch->level : ch->mclass[multi(ch,gsn_assassinate)];
  if(level!=ch->level)
    {
    send_to_combat_char( "Only pure assassins can assassinate.\n\r", ch );
    return;
    }


  argument=one_argument( argument, arg );

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

  if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
    send_to_combat_char( "They aren't here.\n\r", ch );
    return;
    }
    
  if ( victim == ch )
    {
    send_to_combat_char( "Suicide is a mortal sin.\n\r", ch );
    return;
    }

  if(find_keeper( ch)!=NULL)
      	{
		ch_printf(ch, "%s tells you 'No fighting in here! You thug!'\n\r", capitalize(find_keeper(ch)->short_descr));
                ch->reply=find_keeper( ch );
		return;
	}
  if ( is_safe( ch, victim ) || ch->level > victim->level+10 )
    {
    send_to_combat_char( "You may not assassinate them.\n\r", ch );
    return;
    }

  if( IS_AFFECTED( victim, AFF_CHARM) && victim->master == ch)
    {
    send_to_combat_char( "Um....ur...you do realize that you could just 'kill' it?\n\r", ch );
    return;
    }
  
  /* Increase cost to assassinate Peaceful first_person - Martin 25/12/98

  if (!IS_NPC(victim) && victim->pcdata->clan !=NULL &&
	victim->pcdata->clan->type == CLAN_PEACEFUL )
    exp_cost=(exp_level(ch->class,level)-exp_level(ch->class,level-1))/8;
  else */

    exp_cost=(exp_level(ch->class,level)-exp_level(ch->class,level-1))/10;

  if(ch->exp < exp_level(ch->class,level-1)+exp_cost )
    {
    ch_printf(ch,"You need a minimum of %d experience to assassinate %s!\n\r",
            exp_level(ch->class,level-1)+exp_cost, get_name(victim));
    return;
    }
  if( IS_AFFECTED( ch, AFF_CHARM) )
    {
    send_to_combat_char( "You're too charmed to assassinate right now.\n\r", ch);
    return;
    }

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

  if(victim->fighting!=NULL)
    {
    send_to_combat_char("You may not assassinate that person, at the moment.\n\r",ch);
    return;
    }

/*   Removed by Chaos   - 12/19/98 
  if( !IS_NPC(ch) && !IS_NPC(victim) )
	if ( !can_reincarnate_attack( ch, victim) )
	{
	send_to_combat_char( "They have not reached your spiritual ability yet.\n\r", ch );
		return;
	}
*/

  if( !IS_NPC(victim))
     if(victim->pcdata->just_died_ctr > 0)
    {
      send_to_char("That person is currently protected by the gods.\n\r", ch);
      return;
    }

  if ( !IS_NPC(victim ))
    if( victim->pcdata->corpse != NULL)
    {
    char buf12[180];
    sprintf( buf12, "%s has been killed quite recently.\n\r",
             get_name( victim ) );
    send_to_combat_char( buf12, ch );
    return;
    }

  /* Code for total and max pvnum attacks  -  Chaos 4/20/99  */
  if( !IS_NPC(ch) && !IS_NPC(victim) )
    {
    int oldest_attack, total_pvnum_attacks, attacks_today, cnt;

    attacks_today = 0;
    oldest_attack = 0;
    total_pvnum_attacks=0;
    for( cnt=0; cnt<MAX_PK_ATTACKS; cnt++)
      {
      if( victim->pcdata->last_pk_attack_time[cnt] == 0 )
          oldest_attack = cnt;
      else
        if( victim->pcdata->last_pk_attack_time[oldest_attack] > 
            victim->pcdata->last_pk_attack_time[cnt] )
          oldest_attack = cnt;
      if( victim->pcdata->last_pk_attack_time[cnt]+24*60*60 > current_time )
        attacks_today++;
      if( ch->pcdata->pvnum == victim->pcdata->last_pk_attack_pvnum[cnt] && 
          victim->pcdata->last_pk_attack_time[cnt]+24*60*60 > current_time )
        total_pvnum_attacks++;
      }

    if( attacks_today == MAX_PK_ATTACKS )
      {
       char buf12[180];
       sprintf( buf12, "%s has been attacked too many times today.  You should leave them alone.\n\r", 
                get_name( victim ) );
       send_to_combat_char( buf12, ch );
       return;
      }

    if( total_pvnum_attacks >= 6 )
      {
       char buf12[180];
       sprintf( buf12, "You have attacked %s too many times today.\n\r", 
                get_name( victim ) );
       send_to_combat_char( buf12, ch );
       return;
      }

    victim->pcdata->last_pk_attack_time[oldest_attack]=current_time;
    victim->pcdata->last_pk_attack_pvnum[oldest_attack]=ch->pcdata->pvnum;
    victim->pcdata->last_pk_attack_name[oldest_attack]=
          str_dup(capitalize(ch->name));
        
    }


  /* Let's protect the little first_person  - Chaos 12/19/98  */
  if( !IS_NPC(victim) && ( which_god(victim)==GOD_INIT_ORDER ||
      which_god(victim)==GOD_INIT_CHAOS) )
    {
    send_to_combat_char("You may not assassinate a neutral citizen of the Realm.\n\r",ch);
    return;
    }

  if(!IS_NPC(victim) && which_god( victim ) == GOD_POLICE )
    {
    send_to_combat_char("You may not assassinate that person.\n\r",ch);
    return;
    }

  /* ok...check and see if the victim has the specified item */
  argument=one_argument( argument, arg2 );
  if ( arg2[0] != '\0' )
    {
    OBJ_DATA *obj;

    if ( ( obj = get_obj_list( victim, arg2, victim->first_carrying ) ) == NULL )
      {
      send_to_combat_char( "They don't seem to have it!\n\r", ch );
      return;
      }

    if(!can_drop_obj( ch, obj) ||
       IS_SET(obj->extra_flags,ITEM_INVENTORY) ||
       obj->level>ch->level)
      {
      send_to_combat_char( "You wouldn't be able to pry it away.\n\r", ch );
      return;
      }

    if ( ch->carry_number + get_obj_number( obj ) > can_carry_n( ch ) )
      {
      send_to_combat_char( "You have your hands full.\n\r", ch );
      return;
      }

    if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
      {
      send_to_combat_char( "You can't carry that much weight.\n\r", ch );
      return;
      }

    ch->asn_obj=obj;
    }
  else
    ch->asn_obj=NULL;

  /* We don't mind a lag on assassinate, it's an anti-social skill :)
     Martin 7/8/98 */  
  WAIT_STATE( ch, PULSE_VIOLENCE*1 );
  if( !IS_NPC(victim))
    {
    if (!IS_NPC(ch) && !(number_percent() < ch->pcdata->learned[gsn_muffle]/2))
     {
      sprintf( buf, "Help!  %s is trying to assassinate me!", get_name( ch ) );
      do_shout( victim, buf );
           do_chat( victim, buf );
      victim->wait = 4;  /* remove time penalty of shout */
     }
    else
     {
      act( "You quickly silence $N before they can call for help!", ch, NULL, victim, TO_CHAR);
      act( "You are silenced by $n before you can call for help!", ch, NULL, victim, TO_VICT);
     }
    check_killer( ch, victim );
    }
  if(IS_NPC(ch) || (number_percent( ) < ch->pcdata->learned[gsn_assassinate]))
   {

/* Quick Draw support....we grab what we need from do_knife. No extra lag
   here as the assassin will be lagged from assassinate anyway.
   Martin 7/8/98 */

  if(!IS_NPC(ch) && victim->hit == victim->max_hit &&
     ch->mclass[CLASS_ASSASSIN]==ch->level &&
     number_percent () < (float)ch->pcdata->learned[gsn_quick_draw]*.95)
    {
      OBJ_DATA * obj;
	if((obj=get_eq_char(ch,WEAR_WIELD))!=NULL
	    &&(obj->value[3]==11||obj->value[3]==2))
	{
	 if( number_percent( ) < ch->pcdata->learned[gsn_knife] )
	  one_hit( ch, victim, gsn_knife );
	 else
	  damage( ch, victim, 0, gsn_knife );
	}
    }
    multi_hit( ch, victim, TYPE_UNDEFINED );
   }
  else
    ch->asn_obj=NULL;
  gain_exp(ch,0-exp_cost);
  return;
  }

void do_gouge( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    AFFECT_DATA af;
    sh_int dam=0;
    int chance;
    int cnt;

    if ( IS_NPC(ch) && IS_AFFECTED( ch, AFF_CHARM ) )
    {
        send_to_char( "You can't concentrate enough for that.\n\r", ch );
        return;
    }
    cnt = multi(ch, gsn_gouge);
    if ( cnt == -1 && !IS_NPC(ch)) 
     {
 	ch_printf(ch, "You haven't been taught this dirty trick!\n\r");
        return;
     }

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

    chance = (( get_curr_dex(victim) - get_curr_dex(ch)) * 10) + 10;
    if ( IS_NPC(ch) 
        || (number_percent()< (ch->pcdata->learned[gsn_gouge]+ chance )
        && check_hit( ch, victim, 0-GET_HITROLL(ch), gsn_gouge ) ) )
    {
        dam = number_range( 5, ch->level );
        damage( ch, victim, dam, gsn_gouge );
        if ( ch->fighting && ch->fighting->who == victim && last_dead != victim)
        {
             if ( !IS_AFFECTED( victim, AFF_BLIND ) )
              {
                if (!is_affected(ch, gsn_truesight))
                {
                  af.type      = gsn_blindness;
                  af.location  = APPLY_HITROLL;
                  af.modifier  = -6;
                  af.duration = ( ch->mclass[multi(ch,gsn_gouge)]/2 ) / get_curr_con( victim );
                  af.bitvector = AFF_BLIND;
                  affect_to_char( victim, &af );
                  act( "You can't see a thing!", victim, NULL, NULL, TO_CHAR );
                }
     else
      {
      act( "$N seems to be able to see despite your attack!", ch, NULL, victim, TO_CHAR );
      act( "You are unaffected by $n's attack.", ch, NULL, victim, TO_VICT );
      }
              }
                WAIT_STATE( ch,     PULSE_VIOLENCE );
/*
                if ( !IS_NPC( ch ) && !IS_NPC( victim ) )
                {
                  if ( number_bits( 1 ) == 0 )
                  {
                    ch_printf( ch, "%s looks momentarily dazed.\n\r",
                        victim->name );
                    send_to_char( "You are momentarily dazed ...\n\r",
                        victim );
                    WAIT_STATE( victim, PULSE_VIOLENCE );
                  }
                }
                else
                  WAIT_STATE( victim, PULSE_VIOLENCE );
*/
        }
        else
        if ( last_dead == victim)
        {
            act( "Your fingers plunge into your victim's brain, causing immediate death!",
                ch, NULL, NULL, TO_CHAR );
        }
    }
    else
    {
        WAIT_STATE( ch, skill_table[gsn_gouge].beats );
        damage( ch, victim, 0, gsn_gouge );
    }

    return;
}

void do_circle( CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;


    if ( ( victim = who_fighting(ch) ) == NULL )
    {
        send_to_char( "You can't circle when you aren't fighting.\n\r", ch);
        return;
    }

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


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

    if ( !ch->fighting )
    {
        send_to_char( "You can't circle when you aren't fighting.\n\r", ch);
        return;
    }

    if ( !victim->fighting )
    {
        send_to_char( "You can't circle around a person who is not fighting.\n\r", ch );
        return;
    }

    if ( victim->num_fighting < 2 )
    {
    act( "You can't circle around them without a distraction.",
            ch, NULL, victim, TO_CHAR );
        return;
    }


    WAIT_STATE( ch, skill_table[gsn_circle].beats );
    if ( IS_NPC(ch) || (number_percent()< ch->pcdata->learned[gsn_circle] 
        && check_hit( ch, victim, 0-GET_HITROLL(ch), gsn_circle ) ) )
    {
        WAIT_STATE( ch,     2 * PULSE_VIOLENCE );
        one_hit( ch, victim, gsn_circle );
    }
    else
    {
        WAIT_STATE( ch,     2 * PULSE_VIOLENCE );
        damage( ch, victim, 0, gsn_circle );
    }
    return;
}

void do_berserk( CHAR_DATA *ch, char *argument )
  {
  int cnt;

  if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
    {
    send_to_combat_char( "You cannot do that here.\n\r", ch);
    return;
    }
  cnt = multi( ch, gsn_berserk);
  if(!IS_NPC(ch) && ch->mclass[cnt]!=ch->level)
    {
    send_to_combat_char("You spit foam and roar but nobody seems to notice.\n\r", ch);
    return;
    }

  WAIT_STATE( ch, skill_table[gsn_berserk].beats );
    
  if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_berserk] )
    {
    AFFECT_DATA af;

    if ( IS_AFFECTED(ch,AFF2_BERSERK) )
      {
      send_to_combat_char( "You are berserk!  Kill!  Kill!  Kill!\n\r", ch );
      return;
      }

    af.type      = gsn_berserk;
    af.duration  = 5;
    af.modifier  = 0 - (IS_NPC(ch)?ch->level:ch->mclass[cnt]) / 2 ;
    /* af.modifier  = (ch->armor>0)?ch->armor/4:-ch->armor/4; */
    af.location  = APPLY_AC;
    af.bitvector = AFF2_BERSERK;
    affect_to_char( ch, &af );
    af.type      = gsn_berserk;
    af.duration  = 5;
    af.modifier  = (IS_NPC(ch)?ch->level:ch->mclass[cnt]) / 2 ;
    /* af.modifier  = (ch->hitroll>0)?ch->hitroll/5:-ch->hitroll/5; */
    af.location  = APPLY_HITROLL;
    af.bitvector = AFF2_BERSERK;
    affect_to_char( ch, &af );
    af.type      = gsn_berserk;
    af.duration  = 5;
    af.modifier  = (IS_NPC(ch)?ch->level:ch->mclass[cnt]) / 3 ;
    /* af.modifier  = (ch->damroll>0)?ch->damroll/5:-ch->damroll/5; */
    af.location  = APPLY_DAMROLL;
    af.bitvector = AFF2_BERSERK;
    affect_to_char( ch, &af );
    send_to_combat_char( "Now you REALLY wanna KILL!\n\r",ch);
    SET_BIT(ch->affected2_by, 0-AFF2_BERSERK);
    }
  else
    send_to_combat_char("You failed to go berserk!\n\r",ch);

  return;
  }

void do_rank( CHAR_DATA *ch, char *arg )
  {
  char buf[200];
  int rnk;

  if( *arg == '\0' && !IS_NPC( ch ) )
    {
    sprintf( buf, "Rank: %d\n\r", ch->rank );
    send_to_combat_char( buf, ch );
    return;
    }

  rnk = atol( arg );
  if( rnk > 10 )
    rnk = 10;
  if( rnk < 0 )
    rnk = 0;
  ch->rank = (unsigned char)rnk;

  if( !IS_NPC( ch ) )
    {
    sprintf( buf, "Rank: %d\n\r", ch->rank );
    send_to_combat_char( buf, ch );
    }

  return;

  }


void knight_adjust_hpmnmv( CHAR_DATA *ch )
  {
  int val_hp, val_mana, val_move;
  int tmp;

  val_hp = ch->actual_max_hit;
  val_mana = ch->actual_max_mana;
  val_move = ch->actual_max_move;

  if( val_mana < 100 && val_move < 100 )
    {
    tmp = 200 - val_move - val_mana;
    val_hp -= tmp;
    val_mana = 100;
    val_move = 100;
    }
  else
  if( val_mana < 100 )
    {
    tmp = 100 - val_mana;
    if( val_move - tmp/2 < 100 )
      {
      tmp -= ( val_move - 100 );
      val_move = 100;
      val_mana = 100;
      val_hp -= tmp;
      }
    else
      {
      val_mana = 100;
      val_move -= (tmp/2);
      val_hp -= (tmp/2);
      }
    }
  else
  if( val_move < 100 )
    {
    tmp = 100 - val_move;
    if( val_mana - tmp/2 < 100 )
      {
      tmp -= ( val_mana - 100 );
      val_move = 100;
      val_mana = 100;
      val_hp -= tmp;
      }
    else
      {
      val_move = 100;
      val_mana -= (tmp/2);
      val_hp -= (tmp/2);
      }
    }


  tmp = ch->actual_max_hit - ch->max_hit;
  ch->actual_max_hit = val_hp;
  ch->max_hit = val_hp - tmp;

  tmp = ch->actual_max_mana - ch->max_mana;
  ch->actual_max_mana = val_mana;
  ch->max_mana = val_mana - tmp;

  tmp = ch->actual_max_move - ch->max_move;
  ch->actual_max_move = val_move;
  ch->max_move = val_move - tmp;

  if( ch->hit > ch->max_hit )
    ch->hit = ch->max_hit;

  if( ch->mana > ch->max_mana )
    ch->mana = ch->max_mana;

  if( ch->move > ch->max_move )
    ch->move = ch->max_move;

  return;
  }

      /* Mixed race wars, this lists who fights who  --  Chaos  6/22/97 */
void do_war( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_INPUT_LENGTH];
  char fbuf[MAX_STRING_LENGTH];
  int tn;

  sprintf( fbuf, "                -------- Race War List --------\n\r" );
  for( tn=0; tn<MAX_RACE; tn++)
    if( Race_Battle_List[tn]>tn)
      {
      sprintf( buf, "      %20s  battles  %s\n\r",
        race_table[tn].race_name, race_table[Race_Battle_List[tn]].race_name);
       strcat( fbuf, buf );
      }
  send_to_char( fbuf, ch );
  return;
  }

void mix_race_war( void )
  {
  int rmonth, tn, pick;
  bool found;
  /* int cnt, ccnt, scnt; */
  CHAR_DATA *fch;

  rmonth = time_info.year*17 + time_info.month;
  srand( rmonth );

  for( tn=0; tn<MAX_RACE ; tn++)
   Race_Battle_List[tn]=-1;

  for( found=FALSE, tn=0; tn<MAX_RACE; tn++, found=FALSE)
    while( !found )
      {
      if( Race_Battle_List[tn]!=-1 )
        found = TRUE;
      else
        {
        pick = rand() % MAX_RACE;
        if( pick!=tn && Race_Battle_List[ pick ] == -1 )
          {
          found = TRUE;
          Race_Battle_List[ tn ] = pick;
          Race_Battle_List[ pick ] = tn;
          }
        }
      }

        /* We need to erase existing mixes 
      (Why remove old attacks?  Doesn't matter really.  - Chaos 6/30/97 )
    for( ccnt=0; ccnt<MAX_RACE; ccnt++)
     for( cnt=0; cnt<ARMY_LIST_SIZE; cnt++)
      {
      for( scnt=0; scnt<2; scnt++)
        {
        if( army_loses_name[scnt][ccnt][cnt]!=NULL )
          STRFREE (army_loses_name[scnt][ccnt][cnt] );
        army_loses_name[scnt][ccnt][cnt]=NULL;
        if( army_kills_name[scnt][ccnt][cnt]!=NULL )
          STRFREE (army_kills_name[scnt][ccnt][cnt] );
        army_kills_name[scnt][ccnt][cnt]=NULL ;
        }
      army_kills_amt[ccnt][cnt]=0;
      army_loses_amt[ccnt][cnt]=0;
      }  */

  for( fch=first_char; fch!=NULL; fch=fch->next )
    if( !IS_NPC( fch ) && fch->pcdata->army_status==1 )
      {
      send_to_char( "A new war begins!\n\r\n\r", fch );
      do_war( fch, "" );
      }

  return;
  }
      
bool can_reincarnate_attack( CHAR_DATA *ch, CHAR_DATA *victim )
  {

  if( IS_NPC(ch) || IS_NPC(victim) )
    return( TRUE );
   
  if ( ch->pcdata->reincarnation==0 && victim->pcdata->reincarnation==0 )
    return TRUE;
  else
  if ( ch->pcdata->reincarnation != 0 && victim->pcdata->reincarnation != 0)
    return TRUE;

  return( FALSE );
  }

/* Put all the attack permission stuff into one nice neat function
 Martin 2/11/98  actually, I dunno about the whole neat thing 8/11/98 Martin*/
 
bool can_attack( CHAR_DATA *ch, CHAR_DATA *victim)
{
  bool reincok=FALSE;

  if (IS_NPC(ch) || IS_NPC(victim))
    return TRUE;

  if (which_god(ch) == GOD_INIT_ORDER || which_god(ch) == GOD_INIT_CHAOS )
    return FALSE;
  if (which_god(victim)==GOD_INIT_ORDER || which_god(victim)==GOD_INIT_CHAOS )
    return FALSE;

  if ((which_god(victim) == GOD_DEMISE || which_god(ch) == GOD_POLICE)
      && victim->level>=ch->level*3/4  )
    return TRUE;

  if (which_god(ch) == GOD_DEMISE || which_god(victim) == GOD_POLICE)
    return FALSE;

  if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)  
    return TRUE;

  if ((victim->mclass[CLASS_ASSASSIN] == victim->level &&
     victim->level != 95 && IS_SET(victim->act, PLR_KILLER) &&
     ch->level <= victim->level+10))
    return TRUE;

  if ( ch->pcdata->reincarnation==0 && victim->pcdata->reincarnation==0 )
    reincok=TRUE;
  else
  if ( ch->pcdata->reincarnation != 0 && victim->pcdata->reincarnation != 0)
    reincok=TRUE;

        if( which_god(ch) == GOD_CHAOS || which_god(ch) == GOD_ORDER ||
            which_god(ch) == GOD_DEMISE || which_god(ch) == GOD_POLICE )
        if( which_god(victim) == GOD_CHAOS || which_god(victim) == GOD_ORDER ||
            which_god(victim) == GOD_DEMISE || which_god(victim) == GOD_POLICE )
          if( which_god(victim) != which_god(ch) )
      if( reincok && victim->level>=ch->level*3/4 )
    return TRUE;


  if (( ch->pcdata->army_status == 1 && victim->pcdata->army_status == 1 
       && victim->race == Race_Battle_List[ch->race] ) && reincok
      && victim->level>=ch->level*3/4  )
    return TRUE;
  return FALSE;
}

  /* Centaur Hooves  - Presto 4/17/99  */
void centaur_hoof( CHAR_DATA *ch, CHAR_DATA *victim)
{
  int dam;

  if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
    return;

  if( IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit )
    if( !IS_AFFECTED( ch, AFF_CHARM ) )
      return;

  if(IS_NPC(ch) || ch->race!=RACE_CENTAUR || victim==NULL)
    return;

  dam=number_range(1, 6 + ch->level / 5 ) + ch->level * 3 / 4;

  if( check_hit( ch, victim, 0-GET_HITROLL(ch), 0 ) )
    damage( ch, victim, GET_DAMROLL(ch)+dam, TYPE_HOOVES);
  else
    damage( ch, victim, 0, TYPE_HOOVES );

  return;
}

  /* Orish Brawling  - Chaos 8/20/98  */
void orc_brawl( CHAR_DATA *ch, CHAR_DATA *victim)
{
	int level;
        int dmgL, dmgH;
        int tshares, pshare;

	if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
		return;

    if( IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit )
      if( !IS_AFFECTED( ch, AFF_CHARM ) )
        return;

	if(IS_NPC(ch) || ch->race!=RACE_ORC || victim==NULL)
		return;

    level=ch->level;
    
            /* Find total shares */
    if( level < 30 )
      tshares = 8;
    else if( level < 50 )
      tshares = 15;
    else if( level < 65 )
      tshares = 21;
    else if( level < 80 )
      tshares = 26;
    else if( level < 90 )
      tshares = 30;
    else
      tshares = 33;

    pshare = number_range( 1, tshares );

    if( pshare <= 8 )
      martial_arts_attack = -1;
    else if( pshare <= 15 )
      martial_arts_attack = -2;
    else if( pshare <= 21 )
      martial_arts_attack = -3;
    else if( pshare <= 26 )
      martial_arts_attack = -4;
    else if( pshare <= 30 )
      martial_arts_attack = -5;
    else
      martial_arts_attack = -6;

    switch( martial_arts_attack )
      {
      case -2:
        dmgL = 3* level / 8;
        dmgH = 3 * level / 4;
        break;
      case -3:
        dmgL = 4 * level / 8;
        dmgH = level;
        break;
      case -4:
        dmgL = 5 * level / 8;
        dmgH = 5 * level / 4;
        break;
      case -5:
        dmgL = 2*level/3;
        dmgH = 7 * level / 4;
        break;
      case -6:
        dmgL = 7 * level / 8;
        dmgH = 9 * level / 4;
        break;
      case -1:
      default:
        dmgL = level / 3;
        dmgH = 2 * level / 3;
        break;
      }

     if( check_hit( ch, victim, 0-GET_HITROLL(ch), 0 ) )
	    damage( ch, victim, GET_DAMROLL(ch)+5+
		    number_range(dmgL, dmgH), gsn_martial_arts);
	else
		damage( ch, victim, 0, gsn_martial_arts );

	return;
}

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

    return TRUE;
}

bool is_hating( CHAR_DATA *ch, CHAR_DATA *victim )

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

    if ( !ch->hating || ch->hating->who != victim )
      return FALSE;

    return TRUE;
}

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

    return TRUE;
}

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

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

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

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

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

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

  if( IS_NPC( victim ) )
    return;

  if( victim->level < 25 )
    return;

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

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

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

void found_prey( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char victname[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];

    if (victim == NULL)
    {
        bug("Found_prey: null victim", 0);
        return;
    }

    if ( victim->in_room == NULL )
    {
        bug( "Found_prey: null victim->in_room", 0 );
        return;
    }

    sprintf( victname, IS_NPC( victim ) ? victim->short_descr : victim->name );

/*  This is stupid    -  Chaos 4/18/99 */
    if ( !can_see(ch, victim) )
    {
        if ( number_percent( ) < 90 )
            return;
        switch( number_bits( 2 ) )
        {
        case 0: sprintf( buf, "Don't make me find you, %s!", victname );
                do_say( ch, buf );
                break;
        case 1: act( "$n sniffs around the room for $N.", ch, NULL, victim, TO_NOTVICT );
                act( "You sniff around the room for $N.", ch, NULL, victim, TO_CHAR );
                act( "$n sniffs around the room for you.", ch, NULL, victim, TO_VICT );
                sprintf( buf, "I can smell your blood!" );
                do_say( ch, buf );
                break;
        case 2: sprintf( buf, "I'm going to tear %s apart!", victname );
                do_shout( ch, buf );
                break;
        case 3: do_say( ch, "Just wait until I find you...");
                break;
        }
        return;
    }

    if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
    {
        if ( number_percent( ) < 90 )
            return;
        switch( number_bits( 2 ) )
        {
        case 0: do_say( ch, "C'mon out, you coward!" );
                sprintf( buf, "%s is a bloody coward!", victname );
                do_shout( ch, buf );
                break;
        case 1: sprintf( buf, "Let's take this outside, %s", victname );
                do_say( ch, buf );
                break;
        case 2: sprintf( buf, "%s is a yellow-bellied wimp!", victname );
                do_shout( ch, buf );
                break;
        case 3: act( "$n takes a few swipes at $N.", ch, NULL, victim, TO_NOTVICT );
                act( "You try to take a few swipes $N.", ch, NULL, victim, TO_CHAR );
                act( "$n takes a few swipes at you.", ch, NULL, victim, TO_VICT );
                break;
        }
        return;
    }

    switch( number_bits( 2 ) )
    {
     case 0: sprintf( buf, "Your blood is mine, %s!", victname );
             do_shout( ch, buf);
             break;
     case 1: sprintf( buf, "Alas, we meet again, %s!", victname );
             do_say( ch, buf );
             break;
     case 2: sprintf( buf, "What do you want on your tombstone, %s?", victname );
             do_say( ch, buf );
             break;
     case 3: act( "$n lunges at $N from out of nowhere!", ch, NULL, victim, TO_NOTVICT );
             act( "You lunge at $N catching $M off guard!", ch, NULL, victim, TO_CHAR );
             act( "$n lunges at you from out of nowhere!", ch, NULL, victim, TO_VICT );
    }  

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

void do_attack( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_STRING_LENGTH];

  get_attack_string( ch, ch, buf );
  send_to_char( ansi_translate_text( ch, buf), ch );

  return;
  }
  
void get_attack_string( CHAR_DATA *ch, CHAR_DATA *viewer, char *buf )
  {
  int cnt, leng;
  int attacks;
  char buf2[MAX_INPUT_LENGTH];

  if( ch==NULL || IS_NPC(ch) )
    {
    strcpy( buf, "You cannot list attackers.\n\r" );
    return;
    }

  leng = str_cpy_max( buf, "{130}  Total Player Killer Attacks:\n\r" ,
                MAX_STRING_LENGTH);

  attacks=0;
  for( cnt=0; cnt<MAX_PK_ATTACKS; cnt++)
    if( ch->pcdata->last_pk_attack_time[cnt]>0)
      {
      attacks++;
      if( ch->pcdata->last_pk_attack_time[cnt]+24*60*60 > current_time )
        sprintf( buf2, "{170}%s {120}attacked you today on %s\r",
            ch->pcdata->last_pk_attack_name[cnt],
	    ctime((const time_t *)&ch->pcdata->last_pk_attack_time[cnt]));
      else
        sprintf( buf2, "{070}%s {020}attacked you before today on %s\r",
            ch->pcdata->last_pk_attack_name[cnt],
	    ctime((const time_t *)&ch->pcdata->last_pk_attack_time[cnt]));
      leng = str_apd_max( buf, buf2, leng, MAX_STRING_LENGTH );
      }

  if(attacks == 0 )
    {
    if( viewer == ch )
      sprintf( buf, "{130}  You have never been attacked.\n\r" );
    else
      sprintf( buf, "{130}  %s has never been attacked.\n\r", ch->name );
    }

  return;
  }

  /* Code for total and max pvnum attacks  -  Chaos 4/20/99  */
bool check_add_attack( CHAR_DATA *ch, CHAR_DATA *victim )
  {
  bool god_war;
  if( !IS_NPC(ch) && !IS_NPC(victim) )
    {
    int oldest_attack, total_pvnum_attacks, attacks_today, cnt;

    attacks_today = 0;
    oldest_attack = 0;
    total_pvnum_attacks=0;
    for( cnt=0; cnt<MAX_PK_ATTACKS; cnt++)
      {
      if( victim->pcdata->last_pk_attack_time[cnt] == 0 )
          oldest_attack = cnt;
      else
        if( victim->pcdata->last_pk_attack_time[oldest_attack] > 
            victim->pcdata->last_pk_attack_time[cnt] )
          oldest_attack = cnt;
      if( victim->pcdata->last_pk_attack_time[cnt]+24*60*60 > current_time )
        attacks_today++;
      if( ch->pcdata->pvnum == victim->pcdata->last_pk_attack_pvnum[cnt] && 
          victim->pcdata->last_pk_attack_time[cnt]+24*60*60 > current_time )
        total_pvnum_attacks++;
      }

    if( attacks_today == MAX_PK_ATTACKS )
      return( FALSE );

    god_war = FALSE;
        if( which_god(ch) == GOD_CHAOS || which_god(ch) == GOD_ORDER ||
            which_god(ch) == GOD_DEMISE || which_god(ch) == GOD_POLICE )
        if( which_god(victim) == GOD_CHAOS || which_god(victim) == GOD_ORDER ||
            which_god(victim) == GOD_DEMISE || which_god(victim) == GOD_POLICE )
          if( which_god(victim) != which_god(ch) )
        god_war = TRUE;

    if( god_war && total_pvnum_attacks >= 10 )
      return( FALSE );
    if( !god_war && total_pvnum_attacks >= 8 )
      return( FALSE );

    victim->pcdata->last_pk_attack_time[oldest_attack]=current_time;
    victim->pcdata->last_pk_attack_pvnum[oldest_attack]=ch->pcdata->pvnum;
    victim->pcdata->last_pk_attack_name[oldest_attack]=
          str_dup(capitalize(ch->name));
        
    }

  return( TRUE );
  }