EotS/
EotS/area/
EotS/player/
EotS/src/
/**************************************************************************
 *  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.                              *
 *                                                                         *
 *  Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David   *
 *  Love, Guilherme 'Willie' Arnold, and Mitchell Tse.                     *
 *                                                                         *
 *  In order to use any part of this Envy Diku Mud, you must comply with   *
 *  the original Diku license in 'license.doc', the Merc license in        *
 *  'license.txt', as well as the Envy license in 'license.nvy'.           *
 *  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.                                                  *
 ***************************************************************************/

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



/*
 * Local functions.
 */
bool	check_dodge	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool    check_sidestep       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	death_xp_loss	     args( ( CHAR_DATA *victim ) );
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 ) );
bool	is_bare_hand	     args( ( CHAR_DATA *ch ) );
bool    is_wielding_poisoned args( ( CHAR_DATA *ch ) );
bool    is_wielding_flaming  args( ( CHAR_DATA *ch ) );
bool    is_wielding_chaos    args( ( CHAR_DATA *ch ) );
bool    is_wielding_icy      args( ( CHAR_DATA *ch ) );

void	make_corpse	     args( ( CHAR_DATA *ch ) );
void	one_hit		     args( ( CHAR_DATA *ch, CHAR_DATA *victim,
				    int dt ) );
void	one_dual	     args( ( CHAR_DATA *ch, CHAR_DATA *victim,
				    int dt ) );
void	one_triple	     args( ( CHAR_DATA *ch, CHAR_DATA *victim,
				    int dt ) );

void	raw_kill	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void	war_kill	     args( ( CHAR_DATA *ch ) );
void	set_fighting	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void	disarm		     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void	trip		     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    item_damage             args( ( CHAR_DATA *ch, int dam ) );
void    do_image		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void	do_flip			args( ( CHAR_DATA *ch, char *argument ) );
OBJ_DATA  *random_object args(( int level ));


/*
 * Control the fights going on.
 * Called periodically by update_handler.
 * Slightly less efficient than Merc 2.2.  Takes 10% of 
 *  total CPU time.
 */
void violence_update( void )
{
    CHAR_DATA *ch;
    CHAR_DATA *victim;
    CHAR_DATA *rch;
    bool       mobfighting;
    int stun;

    for ( ch = char_list; ch; ch = ch->next )
    {
	if ( !ch->in_room || ch->deleted )
	    continue;

	for (stun = 0; stun < STUN_MAX; stun++)
	{
	  if ( IS_STUNNED( ch, stun ) )
	    ch->stunned[stun]--;
	}

	if ( ( victim = ch->fighting ) )
	{
	    if ( IS_AWAKE( ch ) && ch->in_room == victim->in_room )
	        multi_hit( ch, victim, TYPE_UNDEFINED );
	    else
	        stop_fighting( ch, FALSE );
	    continue;
	}


	if ( IS_AFFECTED( ch, AFF_BLIND )
	    || ( IS_NPC( ch ) && ch->pIndexData->pShop ) )
	    continue;

	/* Ok. So ch is not fighting anyone.
	 * Is there a fight going on?
	 */

	mobfighting = FALSE;

	for ( rch = ch->in_room->people; rch; rch = rch->next_in_room )
	{
	    if ( rch->deleted
		|| !IS_AWAKE( rch )
		|| !( victim = rch->fighting ) )
	        continue;

	    if ( !IS_NPC( ch )
		&& ( !IS_NPC( rch ) || IS_AFFECTED( rch, AFF_CHARM ) )
		&& is_same_group( ch, rch )
		&& IS_NPC( victim ) )
		break;

	    if ( IS_NPC( ch )
		&& IS_NPC( rch )
		&& !IS_NPC( victim ) )
	    {
		mobfighting = TRUE;
		break;
	    }
	}

	if ( !victim || !rch )
	    continue;

	/*
	 * Now that someone is fighting, consider fighting another pc
	 * or not at all.
	 */
	if ( mobfighting )
	{
	    CHAR_DATA *vch;
	    int        number;

	    number = 0;
	    for ( vch = ch->in_room->people; vch; vch = vch->next_in_room )
	    {
		if ( can_see( ch, vch )
		    && ( vch->level > 5 )
		    && is_same_group( vch, victim )
		    && number_range( 0, number ) == 0 )
		{
		    victim = vch;
		    number++;
		}
	    }

	    if ( ( rch->pIndexData != ch->pIndexData && number_bits( 3 ) != 0 )
		|| ( IS_GOOD( ch ) && IS_GOOD( victim ) )
		|| abs( victim->level - ch->level ) > 3 )
	        continue;
	}
        mprog_hitprcnt_trigger( ch, victim );
        mprog_fight_trigger( ch, victim );
	multi_hit( ch, victim, TYPE_UNDEFINED );

    }

    return;
}

/*
 * Do one group of attacks.
 */
void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    int chance;
    int chance2;
    
    if ( IS_NPC( ch ) )
    {
      mprog_hitprcnt_trigger( ch, victim );
      mprog_fight_trigger( ch, victim );
    }
    
    if ( ( IS_AFFECTED2( ch, AFF_CONFUSED ) )
       && number_percent ( ) < 10 )
    {
      act(AT_YELLOW, "$n looks around confused at what's going on.", ch, NULL, NULL, TO_ROOM );
      send_to_char( AT_YELLOW, "You stand confused.\n\r", ch );
      return;
    }
    
    one_hit( ch, victim, dt );
    if(IS_AFFECTED(ch, AFF_HASTE))
      one_hit( ch, victim, dt );
    if (IS_AFFECTED2( ch, AFF_RUSH ) )
      one_hit( ch, victim, dt );
    if ( ch->fighting != victim || dt == gsn_backstab )
	return;

    if ( !IS_NPC( ch )
    && ( ( is_class( ch, CLASS_MONK ) && ch->pcdata->learned[gsn_blackbelt] > 0 )
    || ( is_class( ch, CLASS_WEREWOLF ) && ch->pcdata->learned[gsn_dualclaw] > 0 )
    || ch->pcdata->learned[gsn_dual] > 0 ) )
       {
        one_dual( ch, victim, dt );
		one_triple( ch, victim, dt );
	if(IS_AFFECTED(ch, AFF_HASTE))
	  one_dual( ch, victim, dt );
	one_triple( ch, victim, dt );
	if ( IS_AFFECTED2( ch, AFF_RUSH ) )
	  one_dual( ch, victim, dt );
	one_triple( ch, victim, dt );
        if ( ch->fighting != victim )
           return;
       }
    if ( ( IS_NPC( ch ) ) && ( ch->level > 15 ) )
       {
        one_dual( ch, victim, dt );
		one_triple( ch, victim, dt );
        if ( ch->fighting != victim )
           return;
       }
    chance = IS_NPC( ch ) ? ch->level - 5
                          : ch->pcdata->learned[gsn_second_attack]/2;
    if ( is_class( ch, CLASS_WEREWOLF ) )
    chance2 = IS_NPC( ch ) ? ch->level / 2 - 5
			   : ch->pcdata->learned[gsn_dualclaw] / 2;
    else if ( is_class( ch, CLASS_MONK ) && !get_eq_char( ch, WEAR_WIELD_2 ) )
    chance2 = IS_NPC( ch ) ? ch->level / 2 - 5
			   : ch->pcdata->learned[gsn_blackbelt] / 2;
    else
    chance2 = IS_NPC( ch ) ? ch->level/2 - 5
                          : ch->pcdata->learned[gsn_dual]/2;
    if ( number_percent( ) < chance )
    {
	one_hit( ch, victim, dt );
	update_skpell( ch, gsn_second_attack );
	if ( ch->fighting != victim )
	    return;
        if ( number_percent( ) < chance2 )
        {
         one_dual( ch, victim, dt );
		 one_triple( ch, victim, dt );
         if ( ch->fighting != victim )
           return;
        }
    }

    chance = IS_NPC( ch ) ? ch->level
                          : ch->pcdata->learned[gsn_third_attack]/4;
    if ( is_class( ch, CLASS_WEREWOLF ) )
    chance2 = IS_NPC( ch ) ? ch->level / 2
			   : ch->pcdata->learned[gsn_dualclaw] / 4;
    else if ( is_class( ch, CLASS_MONK ) && !get_eq_char( ch, WEAR_WIELD_2 ) )
    chance2 = IS_NPC( ch ) ? ch->level / 2 
			   : ch->pcdata->learned[gsn_blackbelt] / 4;
    else
    chance2 = IS_NPC( ch ) ? ch->level/2
                           :ch->pcdata->learned[gsn_dual]/4;
    if ( number_percent( ) < chance )
    {
	one_hit( ch, victim, dt );
	update_skpell( ch, gsn_third_attack );
	if ( ch->fighting != victim )
	    return;
        if ( number_percent( ) < chance2 )
        {
         one_dual( ch, victim, dt );
		 one_triple( ch, victim, dt );
         if ( ch->fighting != victim )
           return;
        }
    }

    chance = IS_NPC( ch ) ? ch->level/2
                          : ch->pcdata->learned[gsn_fourth_attack]/4;
    if ( number_percent( ) < chance && ch->wait == 0 )
    {
	one_hit( ch, victim, dt );
	update_skpell( ch, gsn_fourth_attack );
	if ( ch->fighting != victim )
	    return;
    }

    chance = IS_NPC( ch ) ? ch->level/2
                          : ch->pcdata->learned[gsn_fifth_attack]/8;
    if ( is_class( ch, CLASS_WEREWOLF ) )
    chance2 = IS_NPC( ch ) ? ch->level / 6
			   : ch->pcdata->learned[gsn_dualclaw] / 8;
    else if ( is_class( ch, CLASS_MONK ) && !get_eq_char( ch, WEAR_WIELD_2 ) )
    chance2 = IS_NPC( ch ) ? ch->level / 6
			   : ch->pcdata->learned[gsn_blackbelt] / 8;
    else
    chance2 = IS_NPC( ch ) ? ch->level/6
                          : ch->pcdata->learned[gsn_dual]/8;
    if ( number_percent( ) < chance && ch->wait == 0 )
    {
	one_hit( ch, victim, dt );
	update_skpell( ch, gsn_fifth_attack );
	if ( ch->fighting != victim )
	    return;
        if ( number_percent( ) < chance2 )
        {
         one_dual( ch, victim, dt );
		 one_triple( ch, victim, dt );
         if ( ch->fighting != victim )
           return;
        }
    }

    chance = IS_NPC( ch ) ? ch->level/4
                          : ch->pcdata->learned[gsn_sixth_attack]/16;
    if ( number_percent( ) < chance && ch->wait == 0 )
    {
	one_hit( ch, victim, dt );
	update_skpell( ch, gsn_sixth_attack );
	if ( ch->fighting != victim )
	    return;
    }

    chance = IS_NPC( ch ) ? ch->level/4
                          : ch->pcdata->learned[gsn_seventh_attack]/32;
    if ( is_class( ch, CLASS_WEREWOLF ) )
    chance2 = IS_NPC( ch ) ? ch->level / 4
			   : ch->pcdata->learned[gsn_dualclaw] / 32;
    else if ( is_class( ch, CLASS_MONK ) && !get_eq_char( ch, WEAR_WIELD_2 ) )
    chance2 = IS_NPC( ch ) ? ch->level / 4
			   : ch->pcdata->learned[gsn_blackbelt] / 22;
    else
    chance2 = IS_NPC( ch ) ? ch->level/4
                          : ch->pcdata->learned[gsn_dual]/32;
    if ( number_percent( ) < chance && ch->wait == 0 )
    {
	one_hit( ch, victim, dt );
	update_skpell( ch, gsn_seventh_attack );
	if ( ch->fighting != victim )
	    return;
        if ( number_percent( ) < chance2 )
        {
         one_dual( ch, victim, dt );
		 one_triple( ch, victim, dt );
         if ( ch->fighting != victim )
           return;
        }
    }

    if ( IS_AFFECTED2(ch, AFF_BERSERK) )
    {
      one_hit( ch, victim, dt );
      if (ch->fighting != victim )
	return;
      one_dual( ch, victim, dt );
      if (ch->fighting != victim )
	return;
	  one_triple( ch, victim, dt );
      if (ch->fighting != victim )
	return;

    }

    chance = IS_NPC( ch ) ? ch->level / 4
                          : 0;
    chance2 = IS_NPC( ch ) ? ch->level / 8
                          : 0;
    if ( number_percent( ) < chance )
	one_hit( ch, victim, dt );
    if ( number_percent( ) < chance2 )
         one_dual( ch, victim, dt );
	if ( number_percent( ) < chance2 )
		one_triple( ch, victim, dt );
    
    return;
}



/*
 * Hit one guy once.
 */
void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    char      buf [ MAX_STRING_LENGTH ];
    int       victim_ac;
    int       thac0;
    int       thac0_00;
    int       thac0_97;
    int       dam;
    int       diceroll;

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

    if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
	 IS_STUNNED( ch, STUN_TOTAL ) )
      return;

    /*
     * Figure out the type of damage message.
     */
    wield = get_eq_char( ch, WEAR_WIELD );
    if ( dt == TYPE_UNDEFINED )
    {
	dt = TYPE_HIT;
	if ( wield && wield->item_type == ITEM_WEAPON )
	    dt += wield->value[3];
	else if ( is_class( ch, CLASS_WEREWOLF ) && !wield )
	    dt += 5;
	else if ( is_class( ch, CLASS_MONK ) && !wield )
	    dt += 14;
    }

    /*
     * Calculate to-hit-armor-class-0 versus armor.
     */
    if ( IS_NPC( ch ) )
    {
	thac0_00 =  18;
	thac0_97 = -24;
    }
    else
    {
	thac0_00 = class_table[prime_class(ch)].thac0_00;
	thac0_97 = class_table[prime_class(ch)].thac0_97;
    }
    
    if (!IS_NPC(ch))
        thac0     = interpolate( ch->level, thac0_00, thac0_97 )
                  - GET_HITROLL( ch );
    else
        thac0     = interpolate(ch->level, thac0_00, thac0_97 )
                  - (ch->level + ch->level/2);
    
    if ( ( !IS_NPC( ch ) ) && ( ch->pcdata->learned[gsn_enhanced_hit] > 0 ) ) 
    {
       thac0 -= ch->pcdata->learned[gsn_enhanced_hit] / 5;
       update_skpell( ch, gsn_enhanced_hit );
    }

    victim_ac = UMAX( -15, GET_AC( victim ) / 10 );
/*
    if ( victim->level < L_APP && victim->class == CLASS_VAMPIRE )
     if ( !IS_SET( victim->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 6 && time_info.hour < 18 )
      {
	victim_ac += victim->level * 2;
      }
    }
*/    
    if ( !can_see( ch, victim ) )
	victim_ac -= 4;
    
    /*
     * The moment of excitement!
     */
    while ( ( diceroll = number_bits( 5 ) ) >= 20 )
	;

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

    /*
     * Hit.
     * Calc damage.
     */
         if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
           {
             if ( number_percent( ) < 50 )
	     {
	       if ( !IS_NPC(victim) )
		 spell_fireball ( skill_lookup("fireball"), 15, victim, ch );
	       else
		 spell_fireball ( skill_lookup("fireball"), 25, victim, ch );
	     }
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_ICESHIELD ) )
           {
             if ( ( number_percent( ) < 50 )
	       || ( number_percent( ) < 17 ) )
	     {
	       if ( !IS_NPC(victim) )
		 spell_icestorm ( skill_lookup("icestorm"), 20, victim, ch );
	       else
		 spell_fireball ( skill_lookup("icestorm"), 40, victim, ch );
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
           {
             if ( ( number_percent( ) < 50 )
	       || ( number_percent( ) < 17 ) )
	     {
	       if ( !IS_NPC(victim) )
		 spell_lightning_bolt ( skill_lookup("lightning bolt"), 15, victim, ch );
	       else
		 spell_lightning_bolt ( skill_lookup("lightning bolt"), 35, victim, ch );
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_CHAOS ) )  
           {
             if ( number_percent( ) < 50 )
	     {
	       if ( !IS_NPC(victim) )
		 spell_energy_drain ( skill_lookup("energy drain"), 30, victim, ch );
	       else
		 spell_energy_drain ( skill_lookup("energy drain"), 40, victim, ch );
	     }
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_VIBRATING ) )
           {
             if ( ( number_percent( ) < 50 )
	       || ( number_percent( ) < 17 ) )
	       spell_psionic_blast ( skill_lookup("psionic blast"), 25, victim, ch );
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED2( victim, AFF_BLADE ) )
           {
             if ( number_percent( ) < 40 )
                spell_holy_fires( skill_lookup("holy fires"), 45, victim, ch );
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED2( victim, AFF_FIELD ) )
	   {
	     if ( number_percent( ) < 10 )
		spell_death_field( skill_lookup("death field"),
		victim->level, victim, ch );        
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
    if ( IS_NPC( ch ) )
    {
	dam = number_range( ch->level / 3, ch->level * 3 / 2 );
	if ( wield )
	    dam += dam / 3;
    }
    else
    {
	if ( wield )
	    dam = number_range( wield->value[1], wield->value[2] );
	else if ( (is_class( ch, CLASS_WEREWOLF )
	     || is_class( ch, CLASS_MONK ))
	     && !wield )
	    dam = UMAX( number_fuzzy( ch->level / 2 + ch->level / 15 ),
			number_fuzzy( 5 ) );
	else
	    dam = number_range( 1, 4 );
	if ( wield && dam > 1000 && !IS_IMMORTAL(ch) )
	{
	    sprintf( buf, "One_hit dam range > 1000 from %d to %d",
		    wield->value[1], wield->value[2] );
	    bug( buf, 0 );
	    if ( wield->name )
	      bug( wield->name, 0 );
	}
    }

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL( ch );
    if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
        dam += dam / 8;
    if ( 
	(wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
    ||	(!wield && is_affected( ch, gsn_flamehand ) )
       )
        dam += dam / 8;
     if ( 
	(wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
     ||	(!wield && is_affected( ch, gsn_chaoshand ) )
        )
        dam += dam / 4;
    if ( 
	(wield && IS_SET( wield->extra_flags, ITEM_ICY   ) )
    ||	(!wield && is_affected( ch, gsn_frosthand ) )
       )
        dam += dam / 8;
    if ( is_class( ch, CLASS_WEREWOLF ) && !wield )
	dam += dam / 8;
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += dam * ch->pcdata->learned[gsn_enhanced_damage] / 150;
	update_skpell( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_claw] > 0 
    && !wield )
    {
	dam += dam / 4 * ch->pcdata->learned[gsn_enhanced_claw] / 150;
	update_skpell( ch, gsn_enhanced_claw );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_two] > 0 )
    {
        dam += dam / 4 * ch->pcdata->learned[gsn_enhanced_two] / 150;
	update_skpell( ch, gsn_enhanced_two );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_three] > 0 )
    {
        dam += dam / 4 * ch->pcdata->learned[gsn_enhanced_three] / 150;
	update_skpell( ch, gsn_enhanced_three );
    }
    if ( !IS_AWAKE( victim ) )
	dam *= 2;
    if ( dt == gsn_backstab )
       {
        if (ch->clan == 4)
           dam *= number_range ( 3, 8 );
	else
	   dam *= 2 + UMIN( ( ch->level / 8) , 4 );
       }
    if ( dam <= 0 )
	dam = 1;
    damage( ch, victim, dam, dt );
    tail_chain( );
    return;
}

void one_dual( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    char      buf [ MAX_STRING_LENGTH ];
    int       victim_ac;
    int       thac0;
    int       thac0_00;
    int       thac0_97;
    int       dam;
    int       diceroll;

    /*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
    if ( !(get_eq_char( ch, WEAR_WIELD_2 ))
    && !is_class( ch, CLASS_WEREWOLF )
    && !is_class( ch, CLASS_MONK ) )
 	return;
    if ( is_class( ch, CLASS_WEREWOLF )
    && ( get_eq_char( ch, WEAR_SHIELD )
    || get_eq_char( ch, WEAR_HOLD ) ) )
	return;
    if ( is_class( ch, CLASS_MONK )
    && ( get_eq_char( ch, WEAR_SHIELD )
    || get_eq_char( ch, WEAR_HOLD ) ) )
	return;
    if ( ( is_class( ch, CLASS_MONK ) && ch->pcdata->learned[gsn_blackbelt] == 0 )
    && ( is_class( ch, CLASS_WEREWOLF ) && ch->pcdata->learned[gsn_dualclaw] == 0 )
    && !get_eq_char( ch, WEAR_WIELD_2 ) )
	return;
    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
	 IS_STUNNED( ch, STUN_TOTAL ) )
      return;

    /*
     * Figure out the type of damage message.
     */
    wield = get_eq_char( ch, WEAR_WIELD_2 );
    if ( dt == TYPE_UNDEFINED )
    {
	dt = TYPE_HIT;
	if ( wield && wield->item_type == ITEM_WEAPON )
	    dt += wield->value[3];
	else if ( is_class( ch, CLASS_WEREWOLF ) && !wield )
	    dt += 5;
	else if ( is_class( ch, CLASS_MONK ) && !wield )
	    dt += 15;
    }

    /*
     * Calculate to-hit-armor-class-0 versus armor.
     */
    if ( IS_NPC( ch ) )
    {
	thac0_00 =  20;
	thac0_97 = -20;
    }
    else
    {
	thac0_00 = class_table[prime_class(ch)].thac0_00;
	thac0_97 = class_table[prime_class(ch)].thac0_97;
    }
    thac0     = interpolate( ch->level, thac0_00, thac0_97 )
              - GET_HITROLL( ch );
    victim_ac = UMAX( -15, GET_AC( victim ) / 10 );
/*
    if ( victim->level < L_APP && victim->class == CLASS_VAMPIRE )
     if ( !IS_SET( victim->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 6 && time_info.hour < 18 )
      {
	victim_ac += victim->level * 2;
      }
    }
*/
    if ( !can_see( ch, victim ) )
	victim_ac -= 4;

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

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

    update_skpell( ch, gsn_dual );

    /*
     * Hit.
     * Calc damage.
     */
/*	if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
           {
             if ( number_percent( ) < 50 )
                spell_fireball ( skill_lookup("fireball"), 5, victim, ch );
           }
	if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
           {
             if ( number_percent( ) < 50 )
                spell_lightning_bolt ( skill_lookup("lightning bolt"), 15, victim, ch );
           }
	if ( IS_AFFECTED( victim, AFF_CHAOS ) )
           {
	     if ( number_percent( ) < 50 )
                spell_energy_drain ( skill_lookup("energy drain"), 25, victim, ch );
           }
	if ( IS_AFFECTED( victim, AFF_VIBRATING ) )
           {
             if ( number_percent( ) < 50 )
                spell_psionic_blast ( skill_lookup("psionic blast"), 25, victim, ch );
           }*/
    
    if ( IS_NPC( ch ) )
    {
	dam = number_range( ch->level / 3, ch->level );
	if ( wield )
	    dam += dam / 4;
    }
    else
    {
	if ( wield )
	    dam = number_range( wield->value[1], wield->value[2] );
	else if ( (is_class( ch, CLASS_WEREWOLF ) 
	     || is_class( ch, CLASS_MONK ))
	     && !wield )
	    dam = UMAX( number_fuzzy( ch->level / 2 + ch->level / 15 ),
			number_fuzzy( 5 ) );
	else
	    dam = number_range( 1, 4 );
	if ( wield && dam > 1000 )
	{
	    sprintf( buf, "One_hit dam range > 1000 from %d to %d",
		    wield->value[1], wield->value[2] );
	    bug( buf, 0 );
	}
    }

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL( ch );
    if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
        dam += dam / 4;
    if (
	(wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
    ||	(!wield && is_affected( ch, gsn_flamehand ) )
       )
        dam += dam / 8;
    if ( 
	(wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
    ||	(!wield && is_affected( ch, gsn_chaoshand ) )
       )
        dam += dam / 8;
    if ( 
	(wield && IS_SET( wield->extra_flags, ITEM_ICY   ) )
    ||	(!wield && is_affected( ch, gsn_frosthand ) )
       )
        dam += dam / 4;
    if ( is_class( ch, CLASS_WEREWOLF ) && !wield )
	{
	dam += dam / 4;
	update_skpell( ch, gsn_dualclaw );
	}
    if ( is_class( ch, CLASS_MONK ) && !wield )
	update_skpell( ch, gsn_blackbelt );
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += dam * ch->pcdata->learned[gsn_enhanced_damage] / 150;
	update_skpell( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_claw] > 0
    && !wield )
    {
	dam += dam * ch->pcdata->learned[gsn_enhanced_claw] / 150;
	update_skpell( ch, gsn_enhanced_claw );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_two] > 0 )
    {
        dam += dam * ch->pcdata->learned[gsn_enhanced_two] / 150;
	update_skpell( ch, gsn_enhanced_two );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_three] > 0 )
    {
        dam += dam * ch->pcdata->learned[gsn_enhanced_three] / 150;
	update_skpell( ch, gsn_enhanced_three );
    }
    if ( !IS_AWAKE( victim ) )
	dam *= 2;
    if ( dt == gsn_backstab )
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );

    if ( dam <= 0 )
	dam = 1;

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

void one_triple( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    char      buf [ MAX_STRING_LENGTH ];
    int       victim_ac;
    int       thac0;
    int       thac0_00;
    int       thac0_97;
    int       dam;
    int       diceroll;

    /*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
    if ( !(get_eq_char( ch, WEAR_WIELD_3 )))
 	return;
    if (( get_eq_char( ch, WEAR_SHIELD )
    || get_eq_char( ch, WEAR_HOLD ) ) )
	return;
    if ( ( get_eq_char( ch, WEAR_SHIELD )
    || get_eq_char( ch, WEAR_HOLD ) ) )
	return;

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

    if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
	 IS_STUNNED( ch, STUN_TOTAL ) )
      return;

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

    /*
     * Calculate to-hit-armor-class-0 versus armor.
     */
    if ( IS_NPC( ch ) )
    {
	thac0_00 =  20;
	thac0_97 = -20;
    }
    else
    {
	thac0_00 = class_table[prime_class(ch)].thac0_00;
	thac0_97 = class_table[prime_class(ch)].thac0_97;
    }
    thac0     = interpolate( ch->level, thac0_00, thac0_97 )
              - GET_HITROLL( ch );
    victim_ac = UMAX( -15, GET_AC( victim ) / 10 );

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

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

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

    /*
     * Hit.
     * Calc damage.
     */
/*	if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
           {
             if ( number_percent( ) < 50 )
                spell_fireball ( skill_lookup("fireball"), 5, victim, ch );
           }
	if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
           {
             if ( number_percent( ) < 50 )
                spell_lightning_bolt ( skill_lookup("lightning bolt"), 15, victim, ch );
           }
	if ( IS_AFFECTED( victim, AFF_CHAOS ) )
           {
	     if ( number_percent( ) < 50 )
                spell_energy_drain ( skill_lookup("energy drain"), 25, victim, ch );
           }
	if ( IS_AFFECTED( victim, AFF_VIBRATING ) )
           {
             if ( number_percent( ) < 50 )
                spell_psionic_blast ( skill_lookup("psionic blast"), 25, victim, ch );
           }*/
    
    if ( IS_NPC( ch ) )
    {
	dam = number_range( ch->level / 3, ch->level );
	if ( wield )
	    dam += dam / 4;
    }
    else
    {
	if ( wield )
	    dam = number_range( wield->value[1], wield->value[2] );
	else
	    dam = number_range( 1, 4 );
	if ( wield && dam > 5000 )
	{
	    sprintf( buf, "One_hit dam range > 1000 from %d to %d",
		    wield->value[1], wield->value[2] );
	    bug( buf, 0 );
	}
    }

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL( ch );
    if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
        dam += dam / 4;
    if (
	(wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
    ||	(!wield && is_affected( ch, gsn_flamehand ) )
       )
        dam += dam / 8;
    if ( 
	(wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
    ||	(!wield && is_affected( ch, gsn_chaoshand ) )
       )
        dam += dam / 8;
    if ( wield && IS_SET( wield->extra_flags, ITEM_ICY   ) )
        dam += dam / 4;
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += dam * ch->pcdata->learned[gsn_enhanced_damage] / 150;
	update_skpell( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_two] > 0 )
    {
        dam += dam * ch->pcdata->learned[gsn_enhanced_two] / 150;
	update_skpell( ch, gsn_enhanced_two );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_three] > 0 )
    {
        dam += dam * ch->pcdata->learned[gsn_enhanced_three] / 150;
	update_skpell( ch, gsn_enhanced_three );
    }
    if ( !IS_AWAKE( victim ) )
	dam *= 2;
    if ( dt == gsn_backstab )
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );

    if ( dam <= 0 )
	dam = 1;

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

/*
 * Inflict damage from a hit.
 */
void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
	    DESCRIPTOR_DATA *d;
		bool warkilled = FALSE;

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

    if(!IS_NPC(ch) && !IS_NPC(victim))
    {
      if (!(ch == victim) )
      {
       ch->combat_timer = 90;
       victim->combat_timer = 90;
      }
    }

    /*
     * Stop up any residual loopholes.
     */
    if ( dam > 3500 )
    {
        char buf [ MAX_STRING_LENGTH ];

      if ( dt != 91 && ch->level <= LEVEL_HERO
      && dt != 40 )
      {
	if ( IS_NPC( ch ) && ch->desc && ch->desc->original )
	    sprintf( buf,
		    "Damage: %d from %s by %s: > 3500 points with %d dt!",
		    dam, ch->name, ch->desc->original->name, dt );
	else
	    sprintf( buf,
		    "Damage: %d from %s: > 3500 points with %d dt!",
		    dam, ch->name, dt );

	bug( buf, 0 );
      }
    }

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

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

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

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

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

	/*
	 * Inviso attacks ... not.
	 */
	if ( IS_AFFECTED( ch, AFF_INVISIBLE ) )
	{
	    affect_strip( ch, gsn_invis      );
	    affect_strip( ch, gsn_mass_invis );
	    REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
	    act(AT_GREY, "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
	}
	if (IS_AFFECTED2( ch, AFF_PHASED ) )
	{
            affect_strip ( ch, skill_lookup("phase shift") );
	    affect_strip ( ch, skill_lookup("mist form") );
	    REMOVE_BIT( ch->affected_by2, AFF_PHASED );
	    act(AT_GREY, "$n returns from an alternate plane.", ch, NULL, NULL, TO_ROOM );
	}
	/*
	 * Damage modifiers.
	 */
	if ( ch->race == RACE_OGRE )
            dam -= dam / 20;
/*
    if ( ch->level < L_APP && ch->class == CLASS_VAMPIRE )
     if ( !IS_SET( ch->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 6 && time_info.hour < 18 )
      {
       send_to_char( AT_RED, 
       "The sunlight has weakened your attack.\n\r", ch );
       dam -= dam / 2;
      }
    }

    if ( victim->level < L_APP && victim->class == CLASS_VAMPIRE )
     if ( !IS_SET( victim->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 6 && time_info.hour < 18 )
      {
       send_to_char( AT_RED, 
       "The sunlight has weakened your defence.\n\r", victim );
       dam += dam / 2;
      }
    }

    if ( ch->class == CLASS_VAMPIRE )
     if ( !IS_SET( ch->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 23 || time_info.hour < 1 )
      {
	dam *= 2;
      }
    }

    if ( victim->class == CLASS_VAMPIRE )
     if ( !IS_SET( victim->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 23 || time_info.hour < 1 )
      {
	dam /= 2;
      }
    }
*/
	/*
	 * Check for disarm, trip, parry, and dodge.
	 */
	if (    dt >= TYPE_HIT           || dt == gsn_feed
	     || dt == gsn_jab_punch      || dt == gsn_kidney_punch
	     || dt == gsn_cross_punch    || dt == gsn_roundhouse_punch
	     || dt == gsn_uppercut_punch || dt == gsn_punch
	     || dt == gsn_flykick        || dt == gsn_high_kick
	     || dt == gsn_jump_kick      || dt == gsn_spin_kick 
	     || dt == gsn_kick
  	   )
	{
	    int leveldiff = ch->level - victim->level;

	    if ( IS_NPC( ch ) && number_percent( )
		< ( leveldiff < -5 ? ch->level / 2 : UMAX( 10, leveldiff ) )
		&& dam == 0 && number_bits(4) == 0)
		disarm( ch, victim );
	    if ( IS_NPC( ch ) && number_percent( )
		< ( leveldiff < -5 ? ch->level / 2 : UMAX( 20, leveldiff ) )
		&& dam == 0 && number_bits(4) == 0)
		trip( ch, victim );
	    if ( check_parry( ch, victim ) && dam > 0 )
		return;
	    if ( check_dodge( ch, victim ) && dam > 0 )
		return;
	    if ( check_sidestep( ch, victim ) && dam > 0 )
		return;
       }
    if ( !IS_NPC( ch )
    && ( dt == 1014 || dt == 1015                   /* FIST & CLAW   */
		    || ( dt == 1005                 /* DAMAGE - Hann */
			 && is_class( ch, CLASS_WEREWOLF )
			 && is_class( ch, CLASS_MONK )
			 && is_bare_hand( ch ) ) )
    && ch->pcdata->learned[gsn_anatomyknow] > 0
    && number_percent( ) <= ch->pcdata->learned[gsn_anatomyknow] / 9 )
	{
	update_skpell( ch, gsn_anatomyknow );
	send_to_char( AT_RED, "You hit a pressure point!\n\r", ch );
	act( AT_RED, "$n hit one of $N's pressure points!",
		     ch, NULL, victim, TO_NOTVICT );
	act( AT_RED, "$n hit you with a precise shot.", 
		     ch, NULL, victim, TO_VICT );
	if ( number_percent( ) < 2 )
		{
		victim->hit = 1;
		}
	else if ( number_percent( ) < 10 )
		{
		STUN_CHAR( victim, 2, STUN_TOTAL );
		victim->position = POS_STUNNED;
		dam *= 4;
		}
	else
		dam += 500;
	}

	
	if ( IS_AFFECTED( victim, AFF_SANCTUARY ) )
	    dam /= 2;
        if ( IS_AFFECTED2( victim, AFF_GOLDEN ) )
	    dam /= 4;
	if ( IS_AFFECTED2( victim, AFF_DANCING ) )
	    dam += dam/2;
	if ( IS_AFFECTED( victim, AFF_FIRESHIELD )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 8;
	if ( IS_AFFECTED( victim, AFF_ICESHIELD )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 8;
	if ( IS_AFFECTED( victim, AFF_CHAOS )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 4;
	if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 4;
	if ( IS_AFFECTED( victim, AFF_VIBRATING )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 4;
	if ( IS_AFFECTED2( victim, AFF_INERTIAL ) )
	    dam -= dam / 8;
        if ( IS_SET( victim->act, UNDEAD_TYPE( victim ) ) )
            dam -= dam / 8;      
	if ( IS_AFFECTED2( victim, AFF_BLADE )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 4;
	if ( IS_AFFECTED2( victim, AFF_FIELD )
        && !( dt == gsn_backstab && chance( number_range( 5, 10 ) ) ) )
	    dam -= dam / 4;
	if ( IS_AFFECTED( victim, AFF_PROTECT   )
	    && IS_EVIL( ch ) )
	    dam -= dam / 4;
	if ( IS_AFFECTED2( victim, AFF_PROTECTION_GOOD )
	    && IS_EVIL( ch ) )
	    dam -= dam / 4;
	if ( dam < 0 )
	    dam = 0;

    }

    /* We moved dam_message out of the victim != ch if above
     * so self damage would show.  Other valid type_undefined
     * damage is ok to avoid like mortally wounded damage - Kahn
     */
    if ( ( !IS_NPC(ch) ) && ( !IS_NPC(victim) ) )
       dam -= dam/4;
    if ( dt != TYPE_UNDEFINED )
        dam_message( ch, victim, dam, dt );

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */
    if ( !IS_NPC(ch) && prime_class( ch ) == CLASS_WARRIOR )
       dam += dam/2;
    if ( ( !IS_NPC(ch) ) && (ch->race == RACE_OGRE ) )
       dam += dam/10;
    if (!IS_NPC(ch) && !IS_NPC(victim))
      dam /= number_range(2, 4);
    if ( dam > 25 && number_range( 0, 100 ) <= 15 )
      item_damage(victim, dam);

    victim->hit -= dam;
    if ( ( ( !IS_NPC( victim )                  /* so imms only die by */
	   && IS_NPC( ch )                      /* the hands of a PC   */
	   && victim->level >= LEVEL_IMMORTAL )
	 ||
	   ( !IS_NPC( victim )                   /* so imms don,t die  */
	   && victim->level >= LEVEL_IMMORTAL    /* by poison type dmg */
	   && ch == victim ) )                   /* since an imm == pc */
	 && victim->hit < 1 )
	    victim->hit = 1;

    if ( dam > 0 && dt > TYPE_HIT
	&& ( ( is_wielding_poisoned( ch )
	&& !saves_spell( ch->level, victim ) )
	|| ( is_class( ch, CLASS_WEREWOLF ) && is_bare_hand( ch ) ) )
        && victim->race != RACE_GHOUL )
    {
	AFFECT_DATA af;

	af.type      = gsn_poison;
	af.duration  = 1;
	af.location  = APPLY_STR;
	af.modifier  = -2;
	af.bitvector = AFF_POISON;
	affect_join( victim, &af );
    }
    if ( dam > 0 && dt > TYPE_HIT
       && is_wielding_flaming( ch )
       && number_percent( ) < 10 )
          spell_fireball ( skill_lookup("fireball"), 20, ch, victim );
  if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if ( dam > 0 && ( dt == 1014 
		 || dt == 1015 
		 || ( dt == 1005 
		      && is_class( ch, CLASS_WEREWOLF )
		      && is_class( ch, CLASS_MONK )
		      && is_bare_hand( ch ) ) )
    && is_affected( ch, gsn_flamehand )
    && number_percent( ) < 33 )
	  spell_burning_hands( skill_lookup("burning hands"),
	  ch->level, ch, victim );
  if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if ( dam > 0 && dt > TYPE_HIT
       && is_wielding_icy( ch )
       && number_percent( ) < 20 )
          spell_icestorm ( skill_lookup("icestorm"), 30, ch, victim );  
  if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
    if ( dam > 0 && ( dt == 1014 
		 || dt == 1015 
		 || ( dt == 1005 
		      && is_class( ch, CLASS_WEREWOLF )
		      && is_class( ch, CLASS_MONK ) 
		      && is_bare_hand( ch ) ) )
    && is_affected( ch, gsn_frosthand )
    && number_percent( ) < 20 )
	spell_chill_touch( skill_lookup("chill touch"), ch->level * 3,
	ch, victim );
  if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if ( dam > 0 && dt > TYPE_HIT
       && is_wielding_chaos( ch )
       && number_percent( ) < 20 )
          spell_energy_drain ( skill_lookup("energy drain"), 45, ch, victim );
   if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
   if ( dam > 0 && ( dt == 1014 
		 || dt == 1015 
		 || ( dt == 1005 
		      && is_class( ch, CLASS_WEREWOLF )
		      && is_class( ch, CLASS_MONK ) 
		      && is_bare_hand( ch ) ) )
  && is_affected( ch, gsn_chaoshand )
  && number_percent( ) < 10 )
	spell_energy_drain( skill_lookup("energy drain"), 
	ch->level * 1.5, ch, victim );
  if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
       
    if (  IS_SET( ch->act, UNDEAD_TYPE( ch ) )
       && !saves_spell(ch->level, victim )
       && !is_class( victim, CLASS_NECROMANCER )
       && victim->race != RACE_GHOUL )
    {
	AFFECT_DATA af;

	af.type      = gsn_poison;
	af.duration  = 2;
	af.location  = APPLY_CON;
	af.modifier  = -1;
	af.bitvector = AFF_POISON;
	affect_join( victim, &af );
    }
       
    update_pos( victim );	

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

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

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

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

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

    /*
     * Sleep spells and extremely wounded folks.
     */
    if ( !IS_AWAKE( victim ) )
	stop_fighting( victim, FALSE );

    /*
     * Payoff for killing things.
     */
    if ( victim->position == POS_DEAD )
    {
        if ( !IS_ARENA(ch) && !IS_SET( victim->act2, PLR_WAR ))
        {
	  group_gain( ch, victim );

          if(((ch->guild != NULL) ? ch->guild->type & GUILD_CHAOS : 0)
           && ch->guild == victim->guild
           && victim->guild_rank > ch->guild_rank)
          {
            int temp;
            temp = ch->guild_rank;
            ch->guild_rank = victim->guild_rank;
            victim->guild_rank = temp;
          }
          if ( ( !IS_NPC(ch) ) && ( !IS_NPC(victim) ) )
          {
            CLAN_DATA  *pClan;
            CLAN_DATA  *Cland;
            if ( ch->clan != victim->clan )
            {
              if ( (pClan = get_clan_index(ch->clan)) != NULL )
                pClan->pkills++;
              if ( (Cland = get_clan_index(victim->clan)) != NULL )
                Cland->pdeaths++;
            }
/*            REMOVE_BIT(victim->act, PLR_THIEF);*/
          }
          if ( ( !IS_NPC(ch) ) && ( IS_NPC(victim) ) )
          {
           CLAN_DATA    *pClan;
           if ( (pClan=get_clan_index(ch->clan)) != NULL )
             pClan->mkills++;
          }
          if ( ( IS_NPC(ch) ) && (!IS_NPC(victim)) )
          {
           CLAN_DATA   *pClan;
           if ( (pClan=get_clan_index(victim->clan)) != NULL )
             pClan->mdeaths++;
          }
        
	  if ( !IS_NPC( victim ) )
	  {
		  if (!IS_NPC(ch) && ch != victim)
		  {
	             ch->pkills++;
		         victim->pkilled++;
		  }
	    /*
	     * Dying penalty:
	     * 1/2 way back to previous level.
	     */
	    if ( victim->level < LEVEL_HERO 
	    || ( victim->level >= LEVEL_HERO && IS_NPC( ch ) ) )
/*		death_xp_loss( victim ); */
	    sprintf( log_buf, "%s killed by %s at %d.", victim->name,
	        ch->name, victim->in_room->vnum );
	    log_string( log_buf, CHANNEL_LOG, -1 );
            wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0);
	    if ( !IS_NPC( ch )
	    && IS_SET( victim->act, PLR_THIEF )
	    && ch->guild
	    && !strcmp( ch->guild->name, "MERCENARY" ) )
		{
		REMOVE_BIT( victim->act, PLR_THIEF );
		info( "%s the puny thief gets destroyed by the &rMERCENARY&C %s!",
		      (int)victim->name, (int)ch->name );
		}
	    else if ( !IS_NPC( ch )
	    && IS_SET( ch->act, PLR_THIEF )
	    && victim->guild
	    && !strcmp( victim->guild->name, "MERCENARY" ) )
		{
		info( "%s, the sly thief, has killed the &rMERCENARY&C %s.",
		      (int)ch->name, (int)victim->name );
				if ( ch != victim )
				{
	             ch->pkills++;
		         victim->pkilled++;
				}
		}
	    else
		{
	        info( "%s gets slaughtered by %s!", (int)victim->name,
                  (int)(IS_NPC(ch) ? ch->short_descr : ch->name) );
		}
	    save_clans();
	  }
	}
	else if(war.iswar == TRUE && IS_SET(victim->act2, PLR_WAR))
	{
	   char  buf[MAX_STRING_LENGTH];
	   warkilled = TRUE;
	   sprintf(buf, "&C%s &chas become a casualty of war.", victim->name );
	   info(buf, 0, 0 );
	   ch->warpts = ch->warpts + 1;
	   send_to_char(C_DEFAULT, "You have been awarded 1 war point for your kill.\n\r", ch);
	   ch->warkills = ch->warkills + 1;
	   victim->wardeaths = victim->wardeaths + 1;
       if(IS_SET(victim->act2, TEAM_RED))
		   war.team_red--;
       if(IS_SET(victim->act2, TEAM_BLUE))
		   war.team_blue--;
	   war.inwar--;
	   if (!IS_NPC( victim ))
	   war_kill( victim );
	    if (war.wartype == 1 && war.inwar == 1)
		{
	       sprintf( buf, "&C%s &Rhas survived iron man war!", ch->name );
	       info( buf, 0, 0 );
		   ch->warpts = ch->warpts + 100;
		   send_to_char(C_DEFAULT, "You have been awarded 100 war points for your victory.\n\r", ch);
	       war.wartype = 0;
	       war.max_level = 0;
	       war.max_level = 0;
	       war.inwar = 0;
	       war.count = 0;
	       war.timeleft = 0;
           war.iswar = FALSE;
	       REMOVE_BIT(ch->act2, PLR_WAR);
	       char_from_room(ch);
	       char_to_room(ch, get_room_index(ROOM_VNUM_TEMPLE));
		}
		else if(war.team_red == 0 && war.wartype != 1)
		{
	       sprintf( buf, "&CThe &BBLUE TEAM &chas won the war!" );
	       info( buf, 0, 0 );
		   ch->warpts = ch->warpts + 20;
		   send_to_char(C_DEFAULT, "You have been awarded 20 war points for the winning kill.\n\r", ch);
	       war.wartype = 0;
	       war.max_level = 0;
	       war.max_level = 0;
	       war.inwar = 0;
	       war.count = 0;
	       war.timeleft = 0;
           war.iswar = FALSE;
	       REMOVE_BIT(ch->act2, PLR_WAR);
           REMOVE_BIT(ch->act2, TEAM_BLUE);
	       char_from_room(ch);
	       char_to_room(ch, get_room_index(ROOM_VNUM_TEMPLE));

  for (d = descriptor_list; d != NULL; d = d->next)
  {
	if (!IS_NPC(d->character))
    {
      if (IS_SET(d->character->act2, PLR_WAR))
        REMOVE_BIT(d->character->act2, PLR_WAR);
          if(IS_SET(d->character->act2, TEAM_RED))
           REMOVE_BIT(d->character->act2, TEAM_RED);
           if(IS_SET(d->character->act2, TEAM_BLUE))
		   {
			ch->warpts = ch->warpts + 10;
			send_to_char(C_DEFAULT, "You have been awarded 10 war points for your victory.\n\r", ch);
           REMOVE_BIT(d->character->act2, TEAM_BLUE);
		   }
    }
		}
		}
				else if(war.team_blue == 0 && war.wartype != 1 )
		{
	       sprintf( buf, "&CThe &RRED TEAM &chas won the war!" );
	       info( buf, 0, 0 );
		   ch->warpts = ch->warpts + 20;
		   send_to_char(C_DEFAULT, "You have been awarded 20 war points for the winning kill.\n\r", ch);
	       war.wartype = 0;
	       war.max_level = 0;
	       war.max_level = 0;
	       war.inwar = 0;
	       war.count = 0;
	       war.timeleft = 0;
           war.iswar = FALSE;
	       REMOVE_BIT(ch->act2, PLR_WAR);
           if(IS_SET(ch->act2, TEAM_RED))
           REMOVE_BIT(ch->act2, TEAM_RED);
	       char_from_room(ch);
	       char_to_room(ch, get_room_index(ROOM_VNUM_TEMPLE));
  for (d = descriptor_list; d != NULL; d = d->next)
  {
    if (!IS_NPC(d->character))
    {
      if (IS_SET(d->character->act2, PLR_WAR))
        REMOVE_BIT(d->character->act2, PLR_WAR);
          if(IS_SET(d->character->act2, TEAM_RED))
		   {
			ch->warpts = ch->warpts + 10;
			send_to_char(C_DEFAULT, "You have been awarded 10 war points for your victory.\n\r", ch);
           REMOVE_BIT(d->character->act2, TEAM_RED);
		  }
           if(IS_SET(d->character->act2, TEAM_BLUE))
           REMOVE_BIT(d->character->act2, TEAM_BLUE);
    }
  }
		}
		}
	    else if(!IS_SET(victim->act2, PLR_WAR))
		{
	    sprintf(log_buf, "&C%s &chas defeated &C%s &cin the arena!",
	          ch->name, victim->name);
	    wiznet(log_buf, NULL, NULL, WIZ_DEATHS, 0, 0);
	    log_string(log_buf, CHANNEL_LOG, -1);
	    challenge(log_buf, 0, 0);
	    ch->arenawon++;
	    victim->arenalost++;
		}
	if (warkilled == FALSE)
	raw_kill( ch, victim );

	/* Ok, now we want to remove the deleted flag from the
	 * PC victim.
	 */
	if ( !IS_NPC( victim ) )
	    victim->deleted = FALSE;

	if ( !IS_NPC( ch ) && IS_NPC( victim ) )
	{
	    if ( IS_SET( ch->act, PLR_AUTOLOOT ) )
		do_get( ch, "all corpse" );
	    else
		do_look( ch, "in corpse" );

	    if ( IS_SET( ch->act, PLR_AUTOCOINS ) )
	        do_get( ch, "all.coin corpse" );
	    if ( IS_SET( ch->act, PLR_AUTOSAC  ) )
		do_sacrifice( ch, "corpse" );
	}

	return;
    }

    if ( victim == ch )
	return;

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

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

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

    tail_chain( );
    return;
}

void item_damage( CHAR_DATA *ch, int dam )
{
        OBJ_DATA  *obj_lose;
        OBJ_DATA  *obj_next;
        
	for ( obj_lose = ch->carrying; obj_lose; obj_lose = obj_next )
	{
            char *msg;

	    obj_next = obj_lose->next_content;
	    if ( obj_lose->deleted )
	        continue;
	    if ( number_bits( 2 ) != 0 )
   		continue;
#ifdef NEW_MONEY
/* Check if total cost in copper is less than 500,000 */

	    if ( ( (obj_lose->pIndexData->cost.gold*C_PER_G) +
		    (obj_lose->pIndexData->cost.silver*S_PER_G) +
		    (obj_lose->pIndexData->cost.copper) ) < 5000*100 )
		continue;
#else
            if ( obj_lose->pIndexData->cost < 5000 )
                continue; 
#endif
	    if ( obj_lose->wear_loc == WEAR_NONE )
	        continue;
	    if ( IS_SET( obj_lose->extra_flags, ITEM_NO_DAMAGE ) )
	        continue;
       	    switch ( obj_lose->item_type )
	    {
	    default:
	      msg = "Your $p gets ruined!";
	      extract_obj( obj_lose );
	      break;
	    case ITEM_DRINK_CON:
	    case ITEM_POTION:
	    case ITEM_CONTAINER:
	    case ITEM_LIGHT:
	      msg = "Your $p shatters!";
	      extract_obj( obj_lose );
	      break;
            case ITEM_WEAPON:
	    case ITEM_ARMOR:
#ifdef NEW_MONEY
/*		 if ( ( obj_lose->cost.gold +
		      (obj_lose->cost.silver/SILVER_PER_GOLD) +
		      (obj_lose->cost.copper/COPPER_PER_GOLD) ) != 0 )
*/
		 if ( ( (obj_lose->cost.gold*100) +
			(obj_lose->cost.silver*10) +
			(obj_lose->cost.copper) ) != 0 )
		 {
		    obj_lose->cost.gold   = ( obj_lose->cost.gold > 0 ) ? 
					    (obj_lose->cost.gold - dam/6) : 0;
		    obj_lose->cost.silver = ( obj_lose->cost.silver > 0 ) ?
					    (obj_lose->cost.silver - dam/6) : 0;
		    obj_lose->cost.copper = ( obj_lose->cost.copper > 0 ) ?
					    (obj_lose->cost.copper - dam/6) : 0;
		 }
/*		 if ( (obj_lose->cost.gold +
 		      (obj_lose->cost.silver/SILVER_PER_GOLD) +
		      (obj_lose->cost.copper/COPPER_PER_GOLD) ) < 0 )
*/
		 if ( ( (obj_lose->cost.gold*100) +
			(obj_lose->cost.silver*10) +
			(obj_lose->cost.copper) ) < 0 )
#else
              	 if ( obj_lose->cost != 0 )
              	    obj_lose->cost -= dam/6;
              	 if (obj_lose->cost < 0)
#endif
              	   {
              	    OBJ_DATA       *pObj;
              	    OBJ_INDEX_DATA *pObjIndex;
              	    char           *name;
              	    char           buf[MAX_STRING_LENGTH];
              	    
              	    pObjIndex = get_obj_index(4);
              	    pObj = create_object(pObjIndex, obj_lose->level);
              	    name = obj_lose->short_descr;
              	    sprintf(buf, pObj->description, name);
              	    free_string(pObj->description);
              	    pObj->description = str_dup(buf);
              	    pObj->weight = obj_lose->weight;
              	    pObj->timer = obj_lose->level;
              	    msg = "$p has been destroyed!";
              	    extract_obj( obj_lose );
              	    obj_to_room ( pObj, ch->in_room );
              	   }
              	  else
              	   {
              	    msg = "$p has been damaged!";
              	   }
              	  break;
              	    
	    }

	    act(AT_YELLOW, msg, ch, obj_lose, NULL, TO_CHAR );
            return;	
  	}
    return;
}

bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{
  CLAN_DATA *pClan;

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

  if ( !IS_NPC(ch) && !IS_NPC(victim) &&
       (IS_SET(ch->in_room->room_flags, ROOM_NO_PKILL) ||
	IS_SET(victim->in_room->room_flags, ROOM_NO_PKILL)) )
    return TRUE;

  if ( IS_AFFECTED( ch, AFF_PEACE ) )
      return TRUE;

  if ( IS_SET( ch->in_room->room_flags, ROOM_PKILL ) &&
       IS_SET( victim->in_room->room_flags, ROOM_PKILL ) )
    return FALSE;

  if ( IS_NPC( victim ) )
    return FALSE;

  if ( IS_SET( victim->act, PLR_THIEF )
  && ( ch->guild && !strcmp( ch->guild->name, "MERCENARY" ) ) )
	return FALSE;
  if ( IS_SET( ch->act, PLR_THIEF )
  && ( victim->guild && !strcmp( victim->guild->name, "MERCENARY" ) ) )
/*	return FALSE; */
        return TRUE;

/* SIGH
  if ( !(IS_SET(ch->act, PLR_PKILLER)) || ( (IS_SET(ch->act, PLR_PKILLER)) &&
       !(IS_SET(victim->act, PLR_PKILLER)) ) )
  {
    send_to_char(AT_WHITE, "You cannot pkill unless you are BOTH pkillers!\n\r", ch );
    return TRUE;
  }
*/

  if ( abs(ch->level - victim->level) > 5 && ( !IS_NPC(ch) )
	  && (!IS_SET(victim->act2, PLR_WAR)))
  {
    send_to_char(AT_WHITE, "That is not in the pkill range... valid range is +/- 5 levels.\n\r", ch );
    return TRUE;
  }

  if ( IS_NPC( ch ) )
  {
    if ( IS_SET(ch->affected_by, AFF_CHARM) && ch->master )
    {
      CHAR_DATA *nch;

      for ( nch = ch->in_room->people; nch; nch = nch->next )
	if ( nch == ch->master )
	  break;

      if ( nch == NULL )
	return FALSE;
      else
	ch = nch; /* Check person who ordered mob for clan stuff.. */
    }
    else
      return FALSE;
  }

/* give pkill guilds ability to pkill */
/* Err.. we might not want pkill guilds attacking unguilded.. */
  if ( (ch->guild && (ch->guild->type & GUILD_PKILL)) &&
       (victim->guild && (victim->guild->type & GUILD_PKILL)) )
  {
    return FALSE;
  }

  pClan = get_clan_index( ch->clan );

  if ( ( ch->clan == 0 ) && ( !IS_SET(pClan->settings, CLAN_PKILL) )
	  && (!IS_SET(victim->act2, PLR_WAR)))
  {
    send_to_char(AT_WHITE, "You must be clanned to murder.\n\r", ch );
    return TRUE;
  }

  pClan = get_clan_index( victim->clan);

  if ( ( victim->clan == 0 ) && ( !IS_SET(pClan->settings, CLAN_PKILL) )
	  && (!IS_SET(victim->act2, PLR_WAR)))
  {
    send_to_char(AT_WHITE, "You can only murder clanned players.\n\r",ch);
    return TRUE;
  }

  pClan = get_clan_index( ch->clan );

  if ( ch->clan == victim->clan &&
       IS_SET( pClan->settings, CLAN_CIVIL_PKILL) )
  {
   return FALSE;
  }

/* can murder self for testing =) */
  if ( ch->clan == victim->clan && ch != victim && ch->clan != 0 
	  && (!IS_SET(victim->act2, PLR_WAR)))
  {
    send_to_char(AT_WHITE, "You cannot murder your own clan member.\n\r",ch);
    return TRUE;
  }

  if ( !IS_SET(pClan->settings, CLAN_PKILL) 
	  && (!IS_SET(victim->act2, PLR_WAR)))
  {
    send_to_char(AT_WHITE, "Peaceful clan members cannot murder.\n\r",ch);
    return TRUE;
  }

  pClan = get_clan_index( victim->clan );
  if ( !IS_SET(pClan->settings, CLAN_PKILL )
	  && (!IS_SET(victim->act2, PLR_WAR)))
  {
    send_to_char(AT_WHITE, "You may not murder peaceful clan members.\n\r",ch);
    return TRUE;
  }

  if ( IS_SET( victim->act, PLR_KILLER ) )
    return FALSE;


  return FALSE;
}



/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
    CLAN_DATA *pClan;
    char 	buf [ MAX_STRING_LENGTH ];
    
    if ( IS_ARENA(victim) )
      return;
    /*
     * NPC's are fair game.
     * So are killers and thieves.
     */
    if (   IS_NPC( victim )
	|| IS_SET( victim->act, PLR_KILLER )
	|| IS_SET( victim->act, PLR_THIEF  ) )
	return;
     
    /*
     * NPC's are cool of course
     * Hitting yourself is cool too (bleeding).
     * And current killers stay as they are.
     */
    if ( IS_NPC( ch )
	|| ch == victim
	|| IS_SET( ch->act, PLR_KILLER ) 
	|| IS_SET( ch->act, PLR_THIEF ) )
	return;
    pClan = get_clan_index( ch->clan );
    if ( /*ch->clan != 0 ||*/ ( IS_SET(pClan->settings, CLAN_PKILL) ) ||
( ch->clan == victim->clan && IS_SET(pClan->settings, CLAN_CIVIL_PKILL)) )
       return;
    send_to_char(AT_RED, "*** You are now a KILLER!! ***\n\r", ch );
    sprintf(buf,"$N is attempting to murder %s",victim->name);
    wiznet(buf,ch,NULL,WIZ_FLAGS,0,0);
    SET_BIT(ch->act, PLR_KILLER);
    save_char_obj( ch, FALSE );
    return;
}

bool is_bare_hand( CHAR_DATA *ch )
{
    if ( !get_eq_char( ch, WEAR_WIELD ) 
    && !get_eq_char( ch, WEAR_WIELD_2 ) )
	return TRUE;
    return FALSE;
}

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

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

    return FALSE;

}
bool is_wielding_flaming( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

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

    return FALSE;

}

bool is_wielding_icy( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

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

    return FALSE;

}
bool is_wielding_chaos( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

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

    return FALSE;

}


/*
 * 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( 60, 2 * victim->level );
	if ( !get_eq_char( victim, WEAR_WIELD ) )
	    chance = chance / 2;
    }
    else
    {
	if ( !get_eq_char( victim, WEAR_WIELD ) )
	    return FALSE;
	chance	= victim->pcdata->learned[gsn_parry] / 2;
    }

    if ( ch->wait != 0 )
      chance /= 4;

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

    update_skpell( ch, gsn_parry );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N parries your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
    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( 60, 2 * victim->level );
    else
        chance  = victim->pcdata->learned[gsn_dodge] / 2
		+ victim->pcdata->learned[gsn_dodge_two] / 2;

    if ( ch->wait != 0 )
      chance /= 4;

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

    update_skpell( ch, gsn_dodge );
    update_skpell( ch, gsn_dodge_two );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N dodges your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You dodge $n's attack.", ch, NULL, victim, TO_VICT    );
    return TRUE;
}

bool check_sidestep( CHAR_DATA *ch, CHAR_DATA *victim )
{
    int chance;

    if ( !IS_AWAKE( victim ) )
        return FALSE;
    
    if ( IS_NPC( victim ) )
        /* Tuan was here.  :) */
        return FALSE;
    
    if ( victim->race != RACE_SHADOW )
        return FALSE;
    
    chance = 50;
    
    if ( number_percent( ) >= chance + victim->level - ch->level )
        return FALSE;         
            
    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N sidesteps your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You sidestep $n's attack.", ch, NULL, victim, TO_VICT    );
    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;

    return;
}



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

    char buf [ MAX_STRING_LENGTH ];

    if ( ch->fighting )
    {
	bug( "Set_fighting: already fighting", 0 );
	sprintf( buf, "...%s attacking %s at %d", 
		( IS_NPC( ch )     ? ch->short_descr     : ch->name     ),
		( IS_NPC( victim ) ? victim->short_descr : victim->name ),
		victim->in_room->vnum );
	bug( buf , 0 );
	return;
    }

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

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

    return;
}



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

    for ( fch = char_list; fch; fch = fch->next )
    {
	if ( fch == ch || ( fBoth && fch->fighting == ch ) )
	{
	    fch->fighting	= NULL;
	    fch->hunting        = NULL;
	    fch->position	= POS_STANDING;
	    if ( is_affected( fch, gsn_berserk ) )
	    {
	      affect_strip( fch, gsn_berserk );
	      send_to_char(C_DEFAULT, skill_table[gsn_berserk].msg_off,fch);
	      send_to_char(C_DEFAULT, "\n\r",fch);
	      
	      act(C_DEFAULT, skill_table[gsn_berserk].room_msg_off,fch,
		  NULL, NULL, TO_ROOM);
	    }
	    else if ( is_affected( fch, gsn_frenzy ) )
	    {
	      affect_strip( fch, gsn_frenzy );
	      send_to_char(C_DEFAULT, skill_table[gsn_frenzy].msg_off,fch);
	      send_to_char(C_DEFAULT, "\n\r",fch);
	      act(C_DEFAULT,skill_table[gsn_frenzy].room_msg_off,fch,
		  NULL, NULL, TO_ROOM);
	    }
	    if ( IS_AFFECTED2(fch, AFF_BERSERK) )
              REMOVE_BIT(fch->affected_by2, AFF_BERSERK);
	    update_pos( fch );
	}
    }

    return;
}



/*
 * Make a corpse out of a character.
 */
void make_corpse( CHAR_DATA *ch )
{
    OBJ_DATA        *corpse;
    OBJ_DATA        *obj;
    OBJ_DATA        *obj_next;
/*    ROOM_INDEX_DATA *location;*/
    char            *name;
    char             buf [ MAX_STRING_LENGTH ];
	OBJ_DATA		*random;
	int			level = ch->level;

    /* No corpses in the arena. -- Altrag */
    if ( IS_ARENA(ch) )
    {
      CHAR_DATA *gch = (ch == arena.fch ? arena.sch : arena.fch);
      int award;
      
      /* Arena master takes 1/5.. *wink* */
      award = (arena.award * 4) / 5;
      sprintf(log_buf, "&C%s &chas been awarded &W%d &ccoins for %s victory.",
              gch->name, award, (gch->sex == SEX_NEUTRAL ? "its" :
              (gch->sex == SEX_MALE ? "his" : "her")));
      /* wiznet(log_buf, NULL, NULL, WIZ_DEATHS, 0, 0); */
      log_string(log_buf, CHANNEL_LOG, -1);
      challenge(log_buf, 0, 0);
#ifdef NEW_MONEY
      gch->money.gold += award;
#else
      gch->gold += award;
#endif
      sprintf(log_buf, "You have been awarded %d gold coins for your victory."
              "\n\r", award);
      send_to_char(AT_YELLOW, log_buf, gch);
      char_from_room(gch);
      char_to_room(gch, get_room_index(ROOM_VNUM_ALTAR));
      return;
    }
      if ( !IS_NPC( ch ) && ch->level <= 20 )
    {
	char_from_room( ch );
	char_to_room( ch, get_room_index(ROOM_VNUM_MORGUE) );
    } 
    if ( IS_NPC( ch ) )
    {
        /*
	 * This longwinded corpse creation routine comes about because
	 * we dont want anything created AFTER a corpse to be placed  
	 * INSIDE a corpse.  This had caused crashes from obj_update()
	 * in extract_obj() when the updating list got shifted from
	 * object_list to obj_free.          --- Thelonius (Monk)
	 */
#ifdef NEW_MONEY
	if ( (ch->money.gold > 0) || (ch->money.silver > 0) ||
	     (ch->money.copper > 0) )
#else
	if ( ch->gold > 0 )
#endif
	{
	    OBJ_DATA * coins;
#ifdef NEW_MONEY
	    coins	  = create_money( &ch->money );
#else
	    coins         = create_money( ch->gold );
#endif
	    name	  = ch->short_descr;
	    corpse	  = create_object(
					  get_obj_index( OBJ_VNUM_CORPSE_NPC ),
					  0 );
	    corpse->timer = number_range( 2, 4 );
	    obj_to_obj( coins, corpse );
#ifdef NEW_MONEY
	    ch->money.gold = ch->money.silver = ch->money.copper = 0;
#else
	    ch->gold = 0;
#endif
	}
	else
	{
	    name	  = ch->short_descr;
	    corpse	  = create_object(
					  get_obj_index( OBJ_VNUM_CORPSE_NPC ),
					  0 );
	    corpse->timer = number_range( 2, 4 );
	}
    }
    else
    {
	name		= ch->name;
	corpse		= create_object(
					get_obj_index( OBJ_VNUM_CORPSE_PC ),
					0 );
	corpse->timer	= number_range( 25, 40 );
#ifdef NEW_MONEY
/* Check if ch has any money, doesn't matter about converting */

	if ( ( ( ch->money.gold + ch->money.silver + 
		 ch->money.copper ) > 0 ) &&
	        ( ch->level > 5 ) )
	{
	  OBJ_DATA * coins;
	  coins = create_money( &ch->money );
	  obj_to_obj( coins, corpse );
	  ch->money.gold = ch->money.silver = ch->money.copper = 0;
	}
#else
	if ( ( ch->gold > 0 ) && ( ch->level > 5 ) )
	{
	  OBJ_DATA * coins;
	  coins = create_money( ch->gold );
	  obj_to_obj( coins, corpse );
	  ch->gold = 0;
	}
#endif
    }

    sprintf( buf, corpse->short_descr, name );
    free_string( corpse->short_descr );
    corpse->short_descr = str_dup( buf );

    sprintf( buf, corpse->description, name );
    free_string( corpse->description );
    corpse->description = str_dup( buf );

    for ( obj = ch->carrying; obj; obj = obj_next )
    {
	obj_next = obj->next_content;

        if ( obj->deleted )
	    continue;
	obj_from_char( obj );
	if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
	    extract_obj( obj );
	else
	    obj_to_obj( obj, corpse );
    }
	if ( (number_percent() > 50) && IS_NPC(ch) )
	{
		random = random_object( level );
		obj_to_obj( random, corpse );
	}

/*    sprintf( buf, "NPC killed: %s -> %d", ch->name, ch->in_room->vnum );
    log_string( buf, CHANNEL_NONE, -1 );
    wiznet(buf,NULL,NULL,WIZ_MOBDEATHS,0,0);*/
    if ( ( IS_NPC( ch ) ) && ( !IS_SET( ch->act, UNDEAD_TYPE( ch ) ) ) )
       corpse->ac_vnum=ch->pIndexData->vnum;
    obj_to_room( corpse, ch->in_room );
    if ( !IS_NPC( ch ) )
    corpse_back( ch, corpse );
    
    return;
}


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

    if ( IS_ARENA(ch) )
      return;

    vnum = 0;
    switch ( number_bits( 4 ) )
    {
    default: msg  = "You hear $n's death cry.";				break;
    case  0: msg  = "$n hits the ground ... DEAD.";			break;
    case  1: msg  = "$n splatters blood on your armor.";		break;
    case  2: msg  = "$n's innards fall to the ground with a wet splat.";     break;
    case  3: msg  = "$n's severed head plops on the ground.";
	     vnum = OBJ_VNUM_SEVERED_HEAD;				break;
    case  4: msg  = "$n's heart is torn from $s chest.";
	     vnum = OBJ_VNUM_TORN_HEART;				break;
    case  5: msg  = "$n's arm is sliced from $s dead body.";
	     vnum = OBJ_VNUM_SLICED_ARM;				break;
    case  6: msg  = "$n's leg is sliced from $s dead body.";
	     vnum = OBJ_VNUM_SLICED_LEG;				break;
    }

    act(AT_BLOOD, msg, ch, NULL, NULL, TO_ROOM );

    if ( vnum != 0 )
    {
	char     *name;
	char      buf [ MAX_STRING_LENGTH ];

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

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

	sprintf( buf, obj->description, name );
	free_string( obj->description );
	obj->description = str_dup( buf );

	obj_to_room( obj, ch->in_room );
    }

    obj		= create_object( get_obj_index(OBJ_VNUM_FINAL_TURD), 0 );
    obj->timer	= number_range( 3, 5 );
    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] )
	    && pexit->to_room
	    && pexit->to_room != was_in_room )
	{
	    ch->in_room = pexit->to_room;
	    act(AT_BLOOD, msg, ch, NULL, NULL, TO_ROOM );
	}
    }
    ch->in_room = was_in_room;

    return;
}



void raw_kill( CHAR_DATA *ch, CHAR_DATA *victim )
{
    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;
    bool is_arena = IS_ARENA(ch);
    
    stop_fighting( victim, TRUE );
    if ( ch != victim )
        mprog_death_trigger( victim, ch );
    rprog_death_trigger( victim->in_room, victim );
    make_corpse( victim );

    for ( paf = victim->affected; paf; paf = paf_next )
        {
     	 paf_next = paf->next;
         affect_remove( victim, paf );
        }
    for ( paf = victim->affected2; paf; paf = paf_next )
      {
       paf_next = paf->next;
       affect_remove2( victim, paf );
      }
    victim->affected_by	= 0;
    victim->affected_by2 = 0;
    if ( IS_NPC( victim ) )
    {
	victim->pIndexData->killed++;
	kill_table[URANGE( 0, victim->level, MAX_LEVEL-1 )].killed++;
	extract_char( victim, TRUE );
	return;
    }

    extract_char( victim, FALSE );
    if ( !is_arena )
    {
      victim->armor        = 100;
      victim->hitroll      = 0;
      victim->damroll      = 0;
      victim->saving_throw = 0;
      victim->carry_weight = 0;
      victim->carry_number = 0;
    }
    victim->position     = POS_RESTING;
    victim->hit	         = UMAX( 1, victim->hit  );
    victim->mana         = UMAX( 1, victim->mana );
    victim->bp           = UMAX( 1, victim->bp   );
    victim->move         = UMAX( 1, victim->move );
    save_char_obj( victim, FALSE );
    return;
}

void war_kill( CHAR_DATA *victim )
{
    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;
    
    stop_fighting( victim, TRUE );
    rprog_death_trigger( victim->in_room, victim );
      char_from_room(victim);
      char_to_room(victim, get_room_index(ROOM_VNUM_MORGUE));

    for ( paf = victim->affected; paf; paf = paf_next )
        {
     	 paf_next = paf->next;
         affect_remove( victim, paf );
        }
    for ( paf = victim->affected2; paf; paf = paf_next )
      {
       paf_next = paf->next;
       affect_remove2( victim, paf );
      }
	REMOVE_BIT( victim->act2, PLR_WAR );
	if (IS_SET( victim->act2, TEAM_RED ))
		REMOVE_BIT( victim->act2, TEAM_RED );
	if (IS_SET( victim->act2, TEAM_BLUE ))
		REMOVE_BIT( victim->act2, TEAM_BLUE );
    victim->affected_by	= 0;
    victim->affected_by2 = 0;
    victim->position     = POS_RESTING;
    victim->hit	         = UMAX( 1, victim->hit  );
    victim->mana         = UMAX( 1, victim->mana );
    victim->bp           = UMAX( 1, victim->bp   );
    victim->move         = UMAX( 1, victim->move );
    save_char_obj( victim, FALSE );
    return;
}


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

    /*
     * 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 ( IS_NPC( ch ) || victim == ch )
	return;
    
    members = 0;
    for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
    {
	if ( is_same_group( gch, ch ) )
	    members++;
    }

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

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

    for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
    {
	OBJ_DATA *obj;
	OBJ_DATA *obj_next;

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

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

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

	xp = xp_compute( gch, victim ) / members;
/*    sprintf( buf, "%s -> gains %dxp", gch->name, xp);
    log_string( buf, CHANNEL_NONE, -1 );*/
	sprintf( buf, "You receive %d experience points.\n\r", xp );
	send_to_char(AT_WHITE, buf, gch );
	gain_exp( gch, xp );

	for ( obj = ch->carrying; obj; obj = obj_next )
	{
	    obj_next = obj->next_content;
	    if ( obj->deleted )
	        continue;
	    if ( obj->wear_loc == WEAR_NONE )
		continue;

            if ( !IS_NPC( ch ) )
	    if (   ( IS_OBJ_STAT( obj, ITEM_ANTI_EVIL    )
		    && IS_EVIL   ( ch ) )
		|| ( IS_OBJ_STAT( obj, ITEM_ANTI_GOOD    )
		    && IS_GOOD   ( ch ) )
		|| ( IS_OBJ_STAT( obj, ITEM_ANTI_NEUTRAL )
		    && IS_NEUTRAL( ch ) ) )
	    {
		act(AT_BLUE, "You are zapped by $p.", ch, obj, NULL, TO_CHAR );
		act(AT_BLUE, "$n is zapped by $p.",   ch, obj, NULL, TO_ROOM );
		obj_from_char( obj );
		obj_to_room( obj, ch->in_room );
	    }
	}
    }

    if ( IS_SET(ch->act, PLR_QUESTOR ) && IS_NPC( victim ))
    {
        if ( ch->questmob && victim == ch->questmob )
        {
           send_to_char(AT_WHITE, "You have almost completed your QUEST!\n\r", ch);
           send_to_char(AT_WHITE, "Return to the QuestMaster before your time runs out!\n\r", ch );
           ch->questmob = NULL;
        }
    }

    return;
}



/*
 * Compute xp for a kill.
 * Also adjust alignment of killer.
 * Edit this function to change xp computations.
 * NOTE: New xp system by Hannibal
 */
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
    int xp;
    int xp_cap = 750;
    int align;

    align = gch->alignment - victim->alignment;
    if ( align > 500 )
    gch->alignment = UMIN( gch->alignment + ( align - 500 ) / 4, 1000 );
    else if ( align < -500 )
    gch->alignment = UMAX( gch->alignment + ( align + 500 ) / 4, -1000 );
    else
    gch->alignment -= victim->alignment / 3;
    
    /* mob lvl is 5 lvls lower than pc or more */
    if ( victim->level + 5 <= gch->level )
	return 0;
    /* 3-4 levels lower */
    if ( victim->level + 3 == gch->level 
    || victim->level + 4 == gch->level )
	{
	xp = ( gch->level < 10 ) ? number_range( 50, 100 ) + 10 : 0;
	return xp;
	}
    /* if same lvl or up to 2 lvls lower */
    if ( victim->level > gch->level - 3 
    && victim->level <= gch->level )
	{
	xp = number_range( 0, 10 ) + number_range( 10, 15 );
	xp = ( gch->level < 10 ) ? xp + number_range( 50, 100 ) : xp;
	return xp;
	}
    /* if higher lvl then... */
    xp = ( victim->level - gch->level ) * number_range( 25, 40 );
    xp = ( gch->level < 10 ) ? xp + number_range( 35, 50 ) : xp;

    /* if they kill 5 lvls bigger then them or more add 0-50xp */
    xp = ( victim->level >= gch->level + 5 ) ? xp + number_range( 0, 50 )
					     : xp;
    /* Enforce xp cap */
    xp = UMIN( xp_cap, xp );
    xp = UMAX( 0, xp );

	/* Xp Boost */
	if ( doubleexp() == TRUE && gch->level <= 15)
		xp = xp * 4;
	else if ( doubleexp() == TRUE && gch->level <= 30 && gch->level > 15)
		xp = xp * 3;
	else if ( doubleexp() == TRUE && gch->level <= 50 && gch->level > 30)
		xp = xp * 2;

	return xp;
    
/* OLD xp system
    int xp;
    int align;
    int extra;
    int level;
    int number;

    xp    = 150 - URANGE( -10, gch->level - victim->level, 10 ) * 30;
    align = gch->alignment - victim->alignment;

    if ( align >  500 )
    {
	gch->alignment  = UMIN( gch->alignment + ( align - 500 ) / 4,  1000 );
	xp = 5 * xp / 4;
    }
    else if ( align < -500 )
    {
	gch->alignment  = UMAX( gch->alignment + ( align + 500 ) / 4, -1000 );
	xp = 5 * xp / 4;
    }
    else
    {
	gch->alignment -= victim->alignment / 3;
	xp = 3 * xp / 4;
    }
*/
    /*
     * Adjust for popularity of target:
     *   -1/8 for each target over  'par' (down to - 50%)
     *   +1/8 for each target under 'par' (  up to + 25%)
     */
/*    level  = URANGE( 0, victim->level, 99 );
    number = UMAX( 1, kill_table[level].number );
    if(IS_NPC(victim))
      extra  = victim->pIndexData->killed - kill_table[level].killed / number;
    else
      extra = 0;
    xp    -= xp * URANGE( -2, extra, 4 ) / 8;

    xp     = number_range( xp * 3 / 4, xp * 5 / 4 );
    xp     = UMAX( 0, xp );
    return xp;
*/
}



void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
    static char * const  attack_table [ ] =
    {
	"hit",
	"slice",  "stab",    "slash", "whip", "claw",
	"blast",  "pound",   "crush", "grep", "bite",
	"pierce", "suction", "chop", "left fist", "right fist"
    };
    const  char         *vs;
    const  char         *vp;
    const  char         *attack;
           char          buf          [ MAX_STRING_LENGTH ];
           char          buf1         [ 256 ];
           char          buf2         [ 256 ];
           char          buf3         [ 256 ];
           char          buf4         [ 256 ];
           char          buf5         [ 256 ];
           char          punct;

	 if ( dam ==   0 ) { vs = "miss";	vp = "misses";		}
    else if ( dam <=   4 ) { vs = "scratch";	vp = "scratches";	}
    else if ( dam <=   8 ) { vs = "graze";	vp = "grazes";		}
    else if ( dam <=  12 ) { vs = "hit";	vp = "hits";		}
    else if ( dam <=  16 ) { vs = "injure";	vp = "injures";		}
    else if ( dam <=  20 ) { vs = "wound";	vp = "wounds";		}
    else if ( dam <=  24 ) { vs = "maul";       vp = "mauls";		}
    else if ( dam <=  28 ) { vs = "decimate";	vp = "decimates";	}
    else if ( dam <=  32 ) { vs = "devastate";	vp = "devastates";	}
    else if ( dam <=  36 ) { vs = "maim";	vp = "maims";		}
    else if ( dam <=  40 ) { vs = "MUTILATE";	vp = "MUTILATES";	}
    else if ( dam <=  44 ) { vs = "DISEMBOWEL";	vp = "DISEMBOWELS";	}
    else if ( dam <=  48 ) { vs = "EVISCERATE";	vp = "EVISCERATES";	}
    else if ( dam <=  52 ) { vs = "MASSACRE";	vp = "MASSACRES";	}
    else if ( dam <= 100 ) { vs = "*** DEMOLISH ***";
			     vp = "*** DEMOLISHES ***";			}
    else if ( dam <= 150 ) { vs = "*** DEVASTATE ***";
			     vp = "*** DEVASTATES ***";			}
    else if ( dam <= 250 ) { vs = "*** OBLITERATE ***";
			     vp = "*** OBLITERATES ***";		}
    else if ( dam <= 300 ) { vs = "=== OBLITERATE ===";
			     vp = "=== OBLITERATES ===";		}
    else if ( dam <= 500 ) { vs = "*** ANNIHILATE ***";
			     vp = "*** ANNIHILATES ***";		}
    else if ( dam <= 750 ) { vs = ">>> ANNIHILATE <<<";
			     vp = ">>> ANNIHILATES <<<";		}
    else if ( dam <= 1000) { vs = "<<< ERADICATE >>>";
			     vp = "<<< ERADICATES >>>";			}
    else                   { vs = "&Xdo &rUNSPEAKABLE&X things to";
			     vp = "&Xdoes &rUNSPEAKABLE&X things to";
}

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

    if ( dt == TYPE_HIT )
    {
	sprintf( buf1, "You &r%s&X $N%c (%d)",       vs, punct, dam );
	sprintf( buf2, "$n &G%s&X you%c (%d)",       vp, punct, dam );
	sprintf( buf3, "$n &z%s&X $N%c (%d)",        vp, punct, dam );
	sprintf( buf4, "You &G%s&X yourself%c (%d)", vs, punct, dam );
	sprintf( buf5, "$n &z%s&X $mself%c (%d)",    vp, punct, dam );
    }
    else
    {
	if ( is_sn(dt) )
	    attack	= skill_table[dt].noun_damage;
	else if (   dt >= TYPE_HIT
		 && dt  < TYPE_HIT
		        + sizeof( attack_table )/sizeof( attack_table[0] ) )
	    attack	= attack_table[dt - TYPE_HIT];
	else
	{
	    sprintf( buf, "Dam_message: bad dt %d caused by %s.", dt,
		    ch->name );
	    bug( buf, 0 );
	    dt      = TYPE_HIT;
	    attack  = attack_table[0];
	}

	if ( dt > TYPE_HIT && is_wielding_poisoned( ch ) )
	{
    sprintf( buf1, "Your &gpoisoned&X %s &r%s&X $N%c (%d)",  attack, vp,punct, dam );
    sprintf( buf2, "$n's &gpoisoned&X %s &G%s&X you%c (%d)", attack, vp,punct, dam );
    sprintf( buf3, "$n's &gpoisoned&X %s &z%s&X $N%c (%d)",  attack, vp,punct, dam );
    sprintf( buf4, "Your &gpoisoned&X %s &G%s&X you%c (%d)", attack, vp,punct, dam );
    sprintf( buf5, "$n's &gpoisoned&X %s &z%s&X $n%c (%d)",  attack, vp,punct, dam );
	}
	else
	{
	    sprintf( buf1, "Your %s &r%s&X $N%c (%d)",  attack, vp, punct,dam );
	    sprintf( buf2, "$n's %s &G%s&X you%c (%d)", attack, vp, punct,dam );
	    sprintf( buf3, "$n's %s &z%s&X $N%c (%d)",  attack, vp, punct,dam );
	    sprintf( buf4, "Your %s &G%s&X you%c (%d)", attack, vp, punct,dam );
	    sprintf( buf5, "$n's %s &z%s&X $n%c (%d)",  attack, vp, punct,dam );
	}
    }

    if ( victim != ch )
    {
        if ( dam != 0 || IS_SET( ch->act, PLR_COMBAT ) )
	  act(AT_WHITE, buf1, ch, NULL, victim, TO_CHAR    );
	if ( dam != 0 || IS_SET( victim->act, PLR_COMBAT ) )
	  act(AT_WHITE, buf2, ch, NULL, victim, TO_VICT    );
	act(AT_GREY, buf3, ch, NULL, victim, 
	    dam == 0 ? TO_COMBAT : TO_NOTVICT );
    }
    else
    {
        if ( dam != 0 || IS_SET( ch->act, PLR_COMBAT ) )
	  act(AT_WHITE, buf4, ch, NULL, victim, TO_CHAR    );
  	act(AT_GREY, buf5, ch, NULL, victim,
	    dam == 0 ? TO_COMBAT : TO_NOTVICT );
     }
      
    return;
}



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

    if ( !( obj = get_eq_char( victim, WEAR_WIELD ) ) )
	if ( !( obj = get_eq_char( victim, WEAR_WIELD_2 ) ) )
	if ( !( obj = get_eq_char( victim, WEAR_WIELD_3 ) ) )
	   return;

    if ( !get_eq_char( ch, WEAR_WIELD ) && number_bits( 1 ) == 0 )
	if ( !get_eq_char( ch, WEAR_WIELD_2 ) && number_bits( 1 ) == 0 )
	if ( !get_eq_char( ch, WEAR_WIELD_3 ) && number_bits( 1 ) == 0 )
	   return;

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

    obj_from_char( obj );
    if ( IS_NPC( victim ) )
	obj_to_char( obj, victim );
    else
	obj_to_room( obj, victim->in_room );

    return;
}



/*
 * Trip a creature.
 * Caller must check for successful attack.
 */
void trip( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( ( IS_AFFECTED( victim, AFF_FLYING ) )
       || (victim->race == RACE_PIXIE )
       || (victim->race == RACE_ELDER ) )
       return;
       
    if ( !IS_STUNNED( victim, STUN_COMMAND ) && !IS_STUNNED(ch, STUN_TO_STUN) )
    {
	act(AT_CYAN, "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR    );
	act(AT_CYAN, "$n trips you and you go down!", ch, NULL, victim, TO_VICT    );
	act(AT_GREY, "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT );

	WAIT_STATE( ch, PULSE_VIOLENCE );
	STUN_CHAR(victim, 2, STUN_COMMAND);
	STUN_CHAR(ch, 3, STUN_TO_STUN);
	victim->position = POS_RESTING;
    }

    return;
}



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

    one_argument( argument, arg );
 
    if ( !( victim = get_char_room( ch, arg ) ) )
    {
      send_to_char( AT_WHITE, "That person is not here.\n\r", ch );
      return;
    }

    if ( is_safe( ch, victim ) )
      {
       send_to_char( AT_WHITE, "You cannot.\n\r", ch );
       return;
      }	   
    
    if ( arg[0] == '\0' )
    {
	send_to_char(AT_WHITE, "Kill whom?\n\r", ch );
	return;
    }

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

    if ( is_affected( victim, gsn_image ))
    {
        do_image( victim, ch );
        affect_strip( victim, skill_lookup("image"));
        REMOVE_BIT( victim->affected_by, gsn_image );
        return;
    }         


    if ( IS_AFFECTED(victim, AFF_PEACE ))
    {
      send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED( ch, AFF_PEACE ) )
    {
	    affect_strip( ch, skill_lookup("aura of peace" ));
	    REMOVE_BIT( ch->affected_by, AFF_PEACE );
    }
    if ( !IS_NPC( victim ) && !IS_ARENA(victim) )
    {
	if (   !IS_SET( victim->act, PLR_KILLER )
	    && !IS_SET( victim->act, PLR_THIEF  )
		&& !IS_SET( victim->act2, PLR_WAR   ))
	{
	    send_to_char(AT_WHITE, "You must MURDER a player.\n\r", ch );
	    return;
	}
    }
    else
    {
	if ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master )
	{
	    send_to_char(AT_WHITE, "You must MURDER a charmed creature.\n\r", ch );
	    return;
	}
    }

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

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

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

    WAIT_STATE( ch, PULSE_VIOLENCE );
	if ( (!IS_SET( victim->act2, PLR_WAR ) ) )
    check_killer( ch, victim );
    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}



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



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

    one_argument( argument, arg );

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

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

    if ( IS_AFFECTED(victim, AFF_PEACE ))
    {
      send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED( ch, AFF_PEACE ))
    {
	    affect_strip( ch, skill_lookup("aura of peace") );
	    REMOVE_BIT( ch->affected_by, AFF_PEACE );
    }

    if ( is_affected( victim, gsn_image ))
    {
	do_image( victim, ch );
	affect_strip( victim, skill_lookup("image"));
	REMOVE_BIT( victim->affected_by, gsn_image );
	return;
    }


    if ( victim == ch )
    {
	send_to_char(C_DEFAULT, "Suicide is a mortal sin.\n\r", ch );
	return;
    }
    if ( is_safe( ch, victim ) )
	return;
    if ( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
    {
	act(C_DEFAULT, "$N is your beloved master!", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( !IS_SET( ch->act, PLR_PKILLER ) && !IS_ARENA( ch ) &&
	 !IS_NPC( victim ) )  /* chars can murder mobs */
    {
	send_to_char(C_DEFAULT, 
 		"You must be a Pkiller to kill another mortal!\n\r", ch );
	return;
    }

    if ( !IS_SET( victim->act, PLR_PKILLER ) && !IS_ARENA( victim ) 
	 && !IS_NPC( victim ) ) /* chars can murder mobs */
    {
	send_to_char(C_DEFAULT, "You can only pkill other Pkillers.\n\r", ch );
	return;
    }

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

    WAIT_STATE( ch, PULSE_VIOLENCE );
    if ( !IS_NPC( victim ) )
    {
        sprintf( buf, "Help!  I am being attacked by %s!", ch->name );
        do_shout( victim, buf );
    }
    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}


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

      if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_backstab ) )
      {
	send_to_char(C_DEFAULT,
		   "You better leave the assassin trade to thieves.\n\r", ch );
	return;
      }

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

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

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

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

    if ( is_affected( victim, gsn_image ))
    {
	do_image( victim, ch );
	affect_strip( victim, skill_lookup("image"));
	REMOVE_BIT( victim->affected_by, gsn_image );
	return;
    }


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

    if ( victim->hit < MAX_HIT(victim) * 0.4 )
    {
	act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
	    ch, NULL, victim, TO_CHAR );
	return;
    }

    check_killer( ch, victim );
    WAIT_STATE( ch, skill_table[gsn_backstab].beats );
    if ( !IS_AWAKE( victim )
	|| IS_NPC( ch )
	|| number_percent( ) < ch->pcdata->learned[gsn_backstab] )
    {
	multi_hit( ch, victim, gsn_backstab );
	update_skpell( ch, gsn_backstab );
	if ( ( obj = get_eq_char( ch, WEAR_WIELD_2 ) )
	&& ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_backstab_2] > 0 )
	&& ( obj->value[3] == 11 || obj->value[3] == 2 ) )
	    {
	    multi_hit( ch, victim, gsn_backstab );
	    update_skpell( ch, gsn_backstab_2 );
		if ( get_eq_char( ch, WEAR_WIELD_3 ))
			multi_hit( ch, victim, gsn_backstab );
	    }
    }
    else
	damage( ch, victim, 0, gsn_backstab );

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

    if (ch->clan != 4)
      {
	send_to_char( C_DEFAULT, "Huh?\n\r", ch );
	return;
      }

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

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

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

    if ( is_safe( ch, victim ) )
      return;

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

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

    if ( victim->hit < (MAX_HIT(victim)-50) )
    {
	act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
	    ch, NULL, victim, TO_CHAR );
	return;
    }

    WAIT_STATE( ch, skill_table[gsn_backstab].beats );
    multi_hit( ch, victim, gsn_backstab );

    return;
}



void do_flee( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA       *victim;
    ROOM_INDEX_DATA *was_in;
    ROOM_INDEX_DATA *now_in;
    int              attempt;

    if ( IS_AFFECTED( ch, AFF_ANTI_FLEE ) )
    {
      send_to_char( AT_RED, "You cannot!\n\r", ch );
      return;
    }
    
    if ( !( victim = ch->fighting ) )
    {
	if ( ch->position == POS_FIGHTING )
	    ch->position = POS_STANDING;
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( IS_SET( ch->in_room->room_flags, ROOM_NO_FLEE ) )
    {
      if ( !IS_ARENA(ch) )
      {
        send_to_char(C_DEFAULT, "You failed!  You lose 10 exps.\n\r", ch );
        gain_exp( ch, -10 );
      }
      else
        send_to_char(C_DEFAULT, "You failed!\n\r", ch);
      return;
    }	   

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

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

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

	ch->in_room = was_in;
	act(C_DEFAULT, "$n has fled!", ch, NULL, NULL, TO_ROOM );
	if ( IS_ARENA(ch) )
	  act(AT_RED, "$n has escaped!  After $m!", ch, NULL, victim,
	      TO_VICT);
	ch->in_room = now_in;

	if ( !IS_NPC( ch ) )
	{
	  if ( !IS_ARENA(ch) )
	  {
	    send_to_char(C_DEFAULT, "You flee from combat!  You lose 25 exps.\n\r", ch );
	    gain_exp( ch, -25 );
	  }
	  else
	    send_to_char(C_DEFAULT, "You flee from combat!\n\r", ch);
	}

        if ( ch->fighting && IS_NPC( ch->fighting ) )
          if ( IS_SET( ch->fighting->act, ACT_TRACK ) )
            ch->fighting->hunting = ch;

	stop_fighting( ch, TRUE );
	return;
    }

    if ( !IS_ARENA(ch) )
    {
      send_to_char(C_DEFAULT, "You failed!  You lose 10 exps.\n\r", ch );
      gain_exp( ch, -10 );
    }
    else
      send_to_char(C_DEFAULT, "You failed!\n\r", ch );
    return;
}



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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_rescue ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the heroic acts to warriors.\n\r", ch );
	return;
    }

    one_argument( argument, arg );

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

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

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

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

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

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

    if ( !is_same_group( ch, victim ) )
    {
	send_to_char(C_DEFAULT, "Why would you want to?\n\r", ch );
	return;
    }

    if ( !check_blind ( ch ) )
        return;

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

    update_skpell( ch, gsn_rescue );

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

    stop_fighting( fch, FALSE );

    set_fighting( fch, ch );

    return;
}



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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_gouge ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to thieves.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
        return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_gouge].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_gouge] )
    {
	update_skpell( ch, gsn_gouge );
	damage( ch, victim, number_range( 100, ch->level*5 ), gsn_gouge );
        if ( number_percent( ) < 10 )
        {
	AFFECT_DATA af;

	af.type      = gsn_blindness;
	af.duration  = 5;
	af.location  = APPLY_HITROLL;
	af.modifier  = -10;
	af.bitvector = AFF_BLIND;
	affect_join( victim, &af );
	act( AT_GREY, "$N is blinded!", ch, NULL, victim, TO_CHAR );
    }
       
    update_pos( victim );	
    }
    else
	damage( ch, victim, 0, gsn_gouge );

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_circle ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to thieves.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

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

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
        return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_circle].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_circle] )
    {
	update_skpell( ch, gsn_circle );
	damage( ch, victim, number_range( 400, ch->level*9 ), gsn_circle );
        update_pos( victim );	
    }
    else
	damage( ch, victim, 0, gsn_circle );

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_kick ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to warriors.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
        return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_kick].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_kick] )
    {
	damage( ch, victim, number_range( 100, ch->level*3 ), gsn_kick );
	update_skpell( ch, gsn_kick );
    }
    else
	damage( ch, victim, 0, gsn_kick );

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_high_kick ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to warriors.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_high_kick].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_high_kick] )
    {
	damage( ch, victim, number_range( 150, ch->level*4 ), gsn_high_kick );
	update_skpell( ch, gsn_high_kick );
    }
    else
	damage( ch, victim, 0, gsn_high_kick );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's high kick connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's high kick hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 20, ch->level ), gsn_high_kick );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_jump_kick ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to warriors.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_jump_kick].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_jump_kick] )
    {
	damage( ch, victim, number_range( 200, ch->level*4 ), gsn_jump_kick );
	update_skpell( ch, gsn_jump_kick );
    }
    else
	damage( ch, victim, 0, gsn_jump_kick );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's jump kick connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's jump kick hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 30, ch->level ), gsn_jump_kick );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_spin_kick ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to warriors.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_spin_kick].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_spin_kick] )
    {
	damage( ch, victim, number_range( 250, ch->level*5 ), gsn_spin_kick );
	update_skpell( ch, gsn_spin_kick );
    }
    else
	damage( ch, victim, 0, gsn_spin_kick );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's spin kick connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's spin kick hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 40, ch->level ), gsn_spin_kick  );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_punch].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_punch] )
    {
	damage( ch, victim, number_range( 100, ch->level*3 ), gsn_punch );
	update_skpell( ch, gsn_punch );
    }
    else
	damage( ch, victim, 0, gsn_punch );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's punch connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's punch hit's home!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 1, ch->level ), gsn_punch );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_jab_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_jab_punch].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_jab_punch] )
    {
	damage( ch, victim, number_range( 125, ch->level*3 ), gsn_jab_punch );
	update_skpell( ch, gsn_jab_punch );
    }
    else
	damage( ch, victim, 0, gsn_jab_punch );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's jab connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's jab hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 1, ch->level ), gsn_jab_punch );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_kidney_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_kidney_punch].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_kidney_punch] )
    {
	damage( ch, victim, number_range( 150, ch->level*3 ), gsn_kidney_punch );
	update_skpell( ch, gsn_kidney_punch );
    }
    else
	damage( ch, victim, 0, gsn_kidney_punch );

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_cross_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_cross_punch].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_cross_punch] )
    {
	damage( ch, victim, number_range( 175, ch->level*3 ), gsn_cross_punch );
	update_skpell( ch, gsn_cross_punch );
    }
    else
	damage( ch, victim, 0, gsn_cross_punch );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's cross connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's cross hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 1, ch->level ), gsn_cross_punch );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_roundhouse_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_roundhouse_punch].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_roundhouse_punch] )
    {
	damage( ch, victim, number_range( 200, ch->level*3 ), gsn_roundhouse_punch );
	update_skpell( ch, gsn_roundhouse_punch );
    }
    else
	damage( ch, victim, 0, gsn_roundhouse_punch );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's roundhouse connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's roundhouse hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 1, ch->level ), gsn_roundhouse_punch );
	}

    return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_uppercut_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_uppercut_punch].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_uppercut_punch] )
    {
	damage( ch, victim, number_range( 225, ch->level*3 ), gsn_uppercut_punch );
	update_skpell( ch, gsn_uppercut_punch );
    }
    else
	damage( ch, victim, 0, gsn_uppercut_punch );

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

    if ( !IS_NPC( ch ) )
	chance = ch->pcdata->mod_str + ( ch->level - victim->level ) + ch->pcdata->perm_str;

    if ( ( number_percent( ) < chance ) || IS_NPC( ch ) )
       {
	 act( AT_RED, "You hear a crunch as you connect with $N's head.", ch, NULL, victim, TO_CHAR );
	 act( AT_RED, "$n's uppercut connects firmly with your head!", ch, NULL, victim, TO_VICT );
	 act( C_DEFAULT, "$n's uppercut hit $N's head!", ch, NULL, victim, TO_ROOM );
	 damage( ch, victim, number_range( 1, ch->level ), gsn_uppercut_punch );
	}

    return;
}

void do_flury( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
    int        count = 0;

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_punch ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave the martial arts to fighters.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
	return;
    }
    one_argument( argument, arg );

    if ( ( get_eq_char( ch, WEAR_WIELD ) ) || ( get_eq_char( ch, WEAR_WIELD_2 ) ) ||
	 ( get_eq_char( ch, WEAR_HOLD ) ) )
    {
	send_to_char(C_DEFAULT, "You cannot begin such a flury while your hands are full!\n\r",  ch);
	return;
    }

    victim = ch->fighting;

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

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

    act( AT_RED, "You throw a flury of punches and kicks at $N!", ch, NULL, victim, TO_CHAR );
    act( AT_RED, "$n throws a flury of punches and kicks at you!", ch, NULL, victim, TO_VICT );
    act( C_DEFAULT, "$n throws a flury of punches and kicks at $N!", ch, NULL, victim, TO_ROOM );

    if ( can_use_skpell( ch, gsn_punch ) && number_percent( ) < 10 )
    {
      do_punch( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_kick ) && number_percent( ) < 10 )
    {
      do_kick( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_jab_punch ) && number_percent( ) < 10 )
    {
      do_jab_punch( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_kidney_punch ) && number_percent( ) < 10 )
    {
      do_kidney_punch( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_cross_punch ) && number_percent( ) < 10 )
    {
      do_cross_punch( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_high_kick ) && number_percent( ) < 10 )
    {
      do_high_kick( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_roundhouse_punch ) && number_percent( ) < 10 )
    {
      do_roundhouse_punch( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_jump_kick ) && number_percent( ) < 10 )
    {
      do_jump_kick( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_uppercut_punch ) && number_percent( ) < 10 )
    {
      do_uppercut_punch( ch, arg );
      count++;
    }

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

    if ( can_use_skpell( ch, gsn_spin_kick ) && number_percent( ) < 10 )
    {
      do_spin_kick( ch, arg );
      count++;
    }

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

    /* nothing hit */
    if ( count == 0 )
    {
    act( AT_RED, "But none of your attacks hit $N!", ch, NULL, victim, TO_CHAR );
    act( AT_RED, "But none of $n attacks hit you!", ch, NULL, victim, TO_VICT );
    act( C_DEFAULT, "But none of $n attacks hit $N!", ch, NULL, victim, TO_ROOM );
    }
    return;
}


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

    if ( !is_class( ch, CLASS_VAMPIRE ) )
       {
	 send_to_char( AT_WHITE, "You may not feed on the living.\n\r", ch );
	 return;
       }

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_feed ) )
    {
	send_to_char(AT_RED,
	    "You are yet to young to feast on the blood of the living.\n\r", ch );
	return;
    }
    if ( !ch->fighting )
    {
	send_to_char(AT_WHITE, "You aren't fighting anyone.\n\r", ch );
	return;
    }
/*
    if ( ch->level < L_APP && ch->class == CLASS_VAMPIRE )
     if ( !IS_SET( ch->in_room->room_flags, ROOM_INDOORS ) )
     {
      if ( time_info.hour > 6 && time_info.hour < 18 )
      {
	send_to_char(AT_RED, "You may not feed during the cursed day.\n\r", ch );
	return;
      }
    }
*/
    if ( !check_blind( ch ) )
        return;

    one_argument( argument, arg );

    victim = ch->fighting;

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

    WAIT_STATE( ch, skill_table[gsn_feed].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_feed] )
       {
	  int        amnt;
	  
  	  update_skpell( ch, gsn_feed );
	  amnt = number_range( 5, 20 );

	  if ( ( ch->bp + amnt ) > MAX_BP(ch))
	    ch->bp = MAX_BP(ch);
	  else
	    ch->bp += amnt;

	  damage( ch, victim, number_range( 1, ch->level ), gsn_feed );
       }
    else
	damage( ch, victim, 0, gsn_feed );

    return;
}



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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_disarm ) )
    {
	send_to_char(C_DEFAULT, "You don't know how to disarm opponents.\n\r", ch );
	return;
    }

    if ( ( !get_eq_char( ch, WEAR_WIELD ) ) 
    && ( !get_eq_char( ch, WEAR_WIELD_2 ) ) 
    && !is_class( ch, CLASS_WEREWOLF ) )
    {
	send_to_char(C_DEFAULT, "You must wield a weapon to disarm.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( !check_blind( ch ) )
        return;

    one_argument( argument, arg );

    victim = ch->fighting;

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

    if ( victim->fighting != ch && ch->fighting != victim )
    {
	act(C_DEFAULT, "$E is not fighting you!", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( !( obj = get_eq_char( victim, WEAR_WIELD ) ) )
    {
	if ( !( obj = get_eq_char( victim, WEAR_WIELD_2 ) ) )
	{
	  send_to_char(C_DEFAULT, "Your opponent is not wielding a weapon.\n\r", ch );
	  return;
        }
    }

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



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



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

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

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

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

    if ( ( !IS_NPC( victim ) && victim->level >= ch->level && victim != ch ) ||
	    (IS_NPC( ch ) && !IS_NPC( victim )) )
    {
	send_to_char(C_DEFAULT, "You failed.\n\r", ch );
	return;
    }
/*
    act(C_DEFAULT, "You slay $M in cold blood!",  ch, NULL, victim, TO_CHAR    );
    act(C_DEFAULT, "$n slays you in cold blood!", ch, NULL, victim, TO_VICT    );
    act(C_DEFAULT, "$n slays $N in cold blood!",  ch, NULL, victim, TO_NOTVICT );
*/


    sprintf( buf, "You %s.",
        ( ch->pcdata && ch->pcdata->slayusee[0] != '\0' )
        ? ch->pcdata->slayusee : "slay $N in cold blood." );
    act( AT_RED, buf, ch, NULL, victim, TO_CHAR );

    sprintf( buf, "%s %s.", ch->name,
            ( ch->pcdata && ch->pcdata->slayvict[0] != '\0' )
            ? ch->pcdata->slayvict : "slays you in cold blood!" );
    act(AT_RED, buf, ch, NULL, victim, TO_VICT );

    sprintf( buf, "%s %s.", ch->name,
            ( ch->pcdata && ch->pcdata->slayroom[0] != '\0' )
            ? ch->pcdata->slayroom : "slays $N in cold blood!");
    act(AT_RED, buf, ch, NULL, victim, TO_NOTVICT );

    sprintf( log_buf, "%s slays %s at %d.\n\r", ch->name, victim->name,
             victim->in_room->vnum );
    log_string( log_buf, CHANNEL_LOG, ch->level - 1 );
    if ( !IS_NPC( victim ) )
      wiznet( log_buf,ch, NULL, WIZ_DEATHS, 0, 0 );
    raw_kill( ch, victim );
    return;
}

int per_type( CHAR_DATA *ch, OBJ_DATA *Obj )
{
  switch ( Obj->item_type )
  {
    case ITEM_WEAPON:
      return number_range( 5, ch->level + 5 );
    case ITEM_STAFF:
      return number_range( 3, ch->level + 3 );
    case ITEM_WAND:
      return number_range( 2, ch->level + 2 );
    default:
      return number_range( 1, ch->level );
  }
  return number_range( 1, ch->level );
}

void do_throw( CHAR_DATA *ch, char *argument )
{
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  char arg3[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *victim;
  ROOM_INDEX_DATA *to_room;
  ROOM_INDEX_DATA *in_room;
  OBJ_DATA *Obj;
  EXIT_DATA *pexit;
  int dir = 0;
  int dist = 0;
  int MAX_DIST = 2;
  extern char *dir_noun [];

  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );
  argument = one_argument( argument, arg3 );

  if ( arg1[0] == '\0' )
  {
    send_to_char( C_DEFAULT, "Throw what item?\n\r", ch );
    return;
  }

  if ( ( Obj = get_obj_wear( ch, arg1 ) ) == NULL )
  {
    send_to_char( C_DEFAULT,
		 "You are not wearing, wielding, or holding that item.\n\r",
		 ch );
    return;
  }

  if ( Obj->wear_loc != WEAR_WIELD && Obj->wear_loc != WEAR_WIELD_2 &&
       Obj->wear_loc != WEAR_HOLD )
  {
    send_to_char( C_DEFAULT,
		 "You are not wielding or holding that item.\n\r", ch );
    return;
  }

  if ( IS_SET( Obj->extra_flags, ITEM_NOREMOVE ) || IS_SET( Obj->extra_flags,
							    ITEM_NODROP ) )
  {
    send_to_char( C_DEFAULT, "You can't let go of it!\n\r", ch );
    return;
  }

  in_room = ch->in_room;
  to_room = ch->in_room;

  if ( ( victim = ch->fighting ) == NULL )
  {
    if ( arg2[0] == '\0' )
    {
      send_to_char( C_DEFAULT, "Throw it at who?\n\r", ch );
      return;
    }

    if ( arg3[0] == '\0' )
    {
      if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
      {
	send_to_char( C_DEFAULT, "They aren't here.\n\r", ch );
	return;
      }
    }
    else
    {
      if ( get_curr_str( ch ) >= 20 )
      {
        MAX_DIST = 3;
        if ( get_curr_str( ch ) == 25 )
          MAX_DIST = 4;
      }
      
      for ( dir = 0; dir < 6; dir++ )
	if ( arg2[0] == dir_name[dir][0] && !str_prefix( arg2,
							 dir_name[dir] ) )
	  break;

      if ( dir == 6 )
      {
	send_to_char( C_DEFAULT, "Throw in which direction?\n\r", ch );
	return;
      }

      if ( ( pexit = to_room->exit[dir] ) == NULL ||
	   ( to_room = pexit->to_room ) == NULL )
      {
	send_to_char( C_DEFAULT, "You cannot throw in that direction.\n\r",
		     ch );
	return;
      }

      if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
      {
	send_to_char( C_DEFAULT, "You cannot throw through a door.\n\r", ch );
	return;
      }

      for ( dist = 1; dist <= MAX_DIST; dist++ )
      {
	char_from_room( ch );
	char_to_room( ch, to_room );
	if ( ( victim = get_char_room( ch, arg3 ) ) != NULL )
	  break;

	if ( ( pexit = to_room->exit[dir] ) == NULL ||
	     ( to_room = pexit->to_room ) == NULL ||
	       IS_SET( pexit->exit_info, EX_CLOSED ) )
	{
	  sprintf( buf, "A $p flys in from $T and hits the %s wall.", 
		   dir_name[dir] );
	  act( AT_WHITE, buf, ch, Obj, dir_noun[rev_dir[dir]], TO_ROOM );
	  sprintf( buf, "You throw your $p %d room%s $T, where it hits a wall.",
		   dist, dist > 1 ? "s" : "" );
	  act( AT_WHITE, buf, ch, Obj, dir_name[dir], TO_CHAR );
	  char_from_room( ch );
	  char_to_room( ch, in_room );
	  oprog_throw_trigger( Obj, ch );
	  unequip_char( ch, Obj );
	  obj_from_char( Obj );
	  obj_to_room( Obj, to_room );
	  return;
	}
      }

      if ( victim == NULL )
      {
	act( AT_WHITE, 
	    "A $p flies in from $T and falls harmlessly to the ground.",
	    ch, Obj, dir_noun[rev_dir[dir]], TO_ROOM );
	sprintf( buf,
		"Your $p falls harmlessly to the ground %d room%s $T of here.",
		dist, dist > 1 ? "s" : "" );
	act( AT_WHITE, buf, ch, Obj, dir_name[dir], TO_CHAR );
	char_from_room( ch );
	char_to_room( ch, in_room );
	oprog_throw_trigger( Obj, ch );
	unequip_char( ch, Obj );
	obj_from_char( Obj );
	obj_to_room( Obj, to_room );
	return;
      }
    }
    if ( dist > 0 )
    {
      char_from_room( ch );
      char_to_room( ch, in_room );
      act( AT_WHITE, "A $p flys in from $T and hits $n!", victim, Obj,
	  dir_noun[rev_dir[dir]], TO_NOTVICT );
      act( AT_WHITE, "A $p flys in from $T and hits you!", victim, Obj,
	  dir_noun[rev_dir[dir]], TO_CHAR );
      sprintf( buf, "Your $p flew %d rooms %s and hit $N!", dist,
	      dir_name[dir] );
      act( AT_WHITE, buf, ch, Obj, victim, TO_CHAR );
      oprog_throw_trigger( Obj, ch );
      unequip_char( ch, Obj );
      obj_from_char( Obj );
      obj_to_room( Obj, to_room );
      damage( ch, victim, per_type( ch, Obj ), gsn_throw );
 
      update_skpell( ch, gsn_throw ); /* Throw not given to any class though */

      if ( IS_NPC( victim ) )
      {
         if ( victim->level > 3 )
             victim->hunting = ch;
      }  
      return;
    }
  }
  unequip_char( ch, Obj );
  obj_from_char( Obj );
  obj_to_room( Obj, to_room );
  act( AT_WHITE, "$n threw a $p at $N!", ch, Obj, victim, TO_ROOM );
  act( AT_WHITE, "You throw your $p at $N.", ch, Obj, victim, TO_CHAR );
  oprog_throw_trigger( Obj, ch );
  damage( ch, victim, per_type( ch, Obj ), gsn_throw );
  multi_hit( victim, ch, TYPE_UNDEFINED );
  return;
}


/*
void do_track( CHAR_DATA *ch, char *argument )
{
   ROOM_INDEX_DATA *room[30];
   ROOM_INDEX_DATA *to_room;
   ROOM_INDEX_DATA *in_room;
   EXIT_DATA *pexit[30];
   char arg[MAX_STRING_LENGTH];
   int vnums[30];
   int dist[30];
   int sdir[30];
   int dir[6];
   int nsdir;
  
   nsdir = 1;
   
   argument = one_argument( argument, arg );
   
   if ( is_number( arg ) || arg[0] == \0' )
   {
      send_to_char( AT_WHITE, "Track what?\n\r", ch );
      return;
   }
   
   in_room = ch->in_room;
   to_room = ch->in_room;
   
   for ( dir = 0; dir != -1; dir++ )
   {
      if ( !( pexit[nsdir] = ch->in_room->exit[dir] ) 
        || ( !( to_room = pexit[nsdir]->to_room ) ) )
      {
        if ( dir == 6 )
          dir = -1;
        continue;
        
        char_from_room( ch );
        char_to_room( ch, to_room );
        
        if ( get_char_room( ch, arg ) )
           break;
        
        
      }
  
   }
   
   if ( dir != -1 )
   {
     sprintf( log_buf, "You sense the trail of %s to the %s.\n\r",
          arg, dir_name[dir] );
     send_to_char( AT_WHITE, log_buf, ch );
     char_from_room( ch );
     char_to_room( ch, in_room );
   }
   
   if ( dir == -1 )
   {
     sprintf( log_buf, "You can't sense any %s from here.\n\r", arg );
     send_to_char( AT_WHITE, log_buf, ch );
     return;
   }
   
   return;
}
*/
  
void do_drain_life(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *victim;
  int	     dam;

  if(!IS_NPC(ch)
   && !can_use_skpell( ch, gsn_drain_life ) )
  {
    send_to_char(C_DEFAULT, "You failed.\n\r", ch);
    return;
  }

  if(argument[0] != '\0')
  {
    if(!(victim = get_char_room(ch, argument)))
    {
      send_to_char(C_DEFAULT, "They aren't here.\n\r", ch);
      return;
    }
  }
  else
  {
    if(!(victim = ch->fighting))
    {
      send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch);
      return;
    }
  }

  if(is_safe(ch, victim))
    return;

  WAIT_STATE(ch, skill_table[gsn_drain_life].beats);
  /* 3xlevel + 1dlevel*/
  if(IS_NPC(ch) || number_percent() < ch->pcdata->learned[gsn_drain_life])
  {
    dam = ch->level + number_range(ch->level / 2, ch->level);
    damage(ch, victim, dam, gsn_drain_life);
    update_skpell(ch, gsn_drain_life);
    ch->hit = UMIN(ch->hit + dam/2, MAX_HIT(ch));
  }
  else
  {
    send_to_char(C_DEFAULT, "You failed.", ch);
    damage(ch, victim, 0, gsn_drain_life);
  }

  return;
}

void do_mental_drain(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *victim;
  int	     dam;
  int	     drain;
  int        dmana;

  if(!IS_NPC(ch)
   && !can_use_skpell( ch, gsn_mental_drain ) )
  {
    send_to_char(C_DEFAULT, "You failed.\n\r", ch);
    return;
  }

  if(argument[0] != '\0')
  {
    if(!(victim = get_char_room(ch, argument)))
    {
      send_to_char(C_DEFAULT, "They aren't here.\n\r", ch);
      return;
    }
  }
  else
  {
    if(!(victim = ch->fighting))
    {
      send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch);
      return;
    }
  }

  if(is_safe(ch, victim))
    return;
  if ( ch->race == RACE_ILLITHID )
     WAIT_STATE(ch, skill_table[gsn_mental_drain].beats/3);
  else
      WAIT_STATE(ch, skill_table[gsn_mental_drain].beats);
  /* 3xlevel + 1d100*/
  if(IS_NPC(ch) || number_percent() < ch->pcdata->learned[gsn_mental_drain])
  {
    dam = number_range(ch->level / 5, ch->level);
/*    drain = 2 * ch->level + number_range(ch->level / 4, ch->level * 2);*/
    dmana = drain = ch->level + number_range(ch->level / 4, ch->level);
     if ( ch->race == RACE_ILLITHID )
	{
	dam *= 1.5;
	dmana = drain *= 2.5;
	}
    damage(ch, victim, dam, gsn_mental_drain);
    update_skpell(ch, gsn_mental_drain);
/*    ch->hit = UMIN(ch->hit + dam/4, MAX_HIT(ch));*/
    if ( !IS_NPC(victim) )
    {
      dmana = UMAX(victim->mana - dmana, 0 );
      drain = UMAX(victim->move - drain, 0 );
      victim->mana -= dmana;
      victim->move -= drain;
    }
    ch->mana = UMIN(ch->mana + dmana / 2, MAX_MANA(ch));
    ch->move = UMIN(ch->move + drain / 2, MAX_MOVE(ch));
  }
  else
  {
    send_to_char(C_DEFAULT, "You failed.", ch);
    damage(ch, victim, 0, gsn_mental_drain);
  }

  return;
}

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

  if (!IS_NPC(ch) && !can_use_skpell( ch, gsn_stun ) )
  {
    send_to_char(C_DEFAULT, "You failed.\n\r", ch );
    return;
  }

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

  if ( victim->position == POS_STUNNED || IS_STUNNED( ch, STUN_TO_STUN ) )
    return;

  if ( ( IS_NPC(ch) || number_percent() < ch->pcdata->learned[gsn_stun] ) &&
      number_percent() < (ch->level * 75) / victim->level )
  {
    STUN_CHAR( ch, 10, STUN_TO_STUN );
    STUN_CHAR( victim, 3, STUN_TOTAL );
    victim->position = POS_STUNNED;
    act( AT_WHITE, "You stun $N!", ch, NULL, victim, TO_CHAR );
    act( AT_WHITE, "$n stuns $N!", ch, NULL, victim, TO_NOTVICT );
    act( AT_WHITE, "$n stuns you!", ch, NULL, victim, TO_VICT );
    update_skpell(ch, gsn_stun);
    return;
  }

  send_to_char(C_DEFAULT, "You failed.\n\r", ch );
  return;
}

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

  if ( !ch->fighting )
    return;

  if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_berserk] < number_percent() )
  {
    send_to_char(C_DEFAULT, "You failed.\n\r",ch);
    return;
  }

  af.type = gsn_berserk;
  af.level = ch->level;
  af.duration = ch->level / 10;
  af.bitvector = AFF_BERSERK;

  af.location = APPLY_DAMROLL;
  af.modifier = IS_NPC(ch) ? ch->level / 2 : ch->damroll * 2 / 3;
  affect_to_char2(ch, &af);

  af.location = APPLY_HITROLL;
  af.modifier = IS_NPC(ch) ? ch->level / 2 : ch->hitroll * 2 / 3;
  affect_to_char2(ch, &af);

  af.location = APPLY_AC;
  af.modifier = ch->level * -2;
  affect_to_char2(ch, &af);

  send_to_char(AT_WHITE, "You suddenly go berserk.\n\r",ch);
  act(AT_WHITE, "$n suddenly goes berserk!", ch, NULL, NULL, TO_ROOM );
  update_skpell( ch, gsn_berserk );
  return;
}

void do_soulstrike( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim = ch->fighting;
  int dam;

  if ( !victim )
  {
    send_to_char( AT_WHITE, "You aren't fighting anyone!\n\r", ch );
    return;
  }

  if (!IS_NPC(ch) && ch->pcdata->learned[gsn_soulstrike] < number_percent( ))
  {
    send_to_char(AT_BLUE, "You failed.\n\r", ch );
    return;
  }

  if ( IS_NEUTRAL(ch) )
  {
    send_to_char(AT_RED, "Nothing happened.\n\r", ch );
    return;
  }

  dam = number_range( ch->level / 3, (ch->level * 2) / 3 );
  if ( ch->hit < dam * 2 )
  {
    send_to_char(AT_WHITE, "You do not have the strength.\n\r", ch );
    return;
  }

/* Don't need a check for update_pos, because of the previous check. */
  ch->hit -= dam;

  dam = number_range( dam * 3, dam * 5 );
  WAIT_STATE(ch, 2*PULSE_VIOLENCE);

  if ( IS_EVIL(ch) )
  {
    send_to_char(AT_RED, "Your soul recoils!\n\r", ch);
    damage(ch, ch, dam, gsn_soulstrike);
    return;
  }

  act( AT_BLUE, "Your soul strikes deep into $N.", ch, NULL, victim, TO_CHAR );
  act( AT_BLUE, "$n's soul strikes deep into you.", ch, NULL, victim, TO_VICT );
  act( AT_BLUE, "$n's soul strikes deep into $N.", ch, NULL, victim, TO_NOTVICT );
  damage(ch, victim, dam, gsn_soulstrike);

  update_skpell( ch, gsn_soulstrike );

  return;
}
void do_multiburst( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim = ch->fighting;
  char	arg1 [ MAX_INPUT_LENGTH ];
  char	arg2 [ MAX_INPUT_LENGTH ];
  int	sn1;
  int	sn2;
  bool	legal1 = FALSE;
  bool	legal2 = FALSE;
  int	mana = 0;

  if ( IS_NPC( ch ) )
	return;
  if ( !can_use_skpell( ch, gsn_multiburst ) )
	{
	send_to_char( C_DEFAULT, "You're not enough of a mage to do multibursts.\n\r" , ch );
	return;
	}
  if ( IS_STUNNED( ch, STUN_MAGIC ) )
	{
	send_to_char( AT_LBLUE, "You are too stunned to multiburst.\n\r", ch );
	return;
	}

  if ( ch->pcdata->learned[gsn_multiburst] < number_percent( ) )
	{
	send_to_char( C_DEFAULT, "You fail your multiburst.\n\r", ch );
	return;
	}
  if ( !ch->fighting )
	{
	send_to_char( C_DEFAULT, "You aren't fighting.\n\r", ch );
	return;
	}
    if ( IS_AFFECTED( ch, AFF_MUTE ))
	{
	send_to_char(AT_WHITE, "You have been silenced.\n\r", ch);
	return;
	}

  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );
  sn1 = skill_lookup( arg1 );
  sn2 = skill_lookup( arg2 );

  if ( sn1 != -1
  && can_use_skpell( ch, sn1 )
  && skill_table[sn1].target != TAR_CHAR_SELF
  && (*skill_table[sn1].spell_fun) != (*spell_null) )
	legal1 = TRUE;
  if ( sn2 != -1
  && can_use_skpell( ch, sn2 )
  && skill_table[sn2].target != TAR_CHAR_SELF
  && (*skill_table[sn2].spell_fun) != (*spell_null) )
	legal2 = TRUE;

  if ( !legal1 && !legal2 )
	{
	WAIT_STATE( ch, skill_table[gsn_multiburst].beats );
	send_to_char( C_DEFAULT, "Your multiburst fails.\n\r", ch );
	return;
	}
  if ( legal1 )
	{
	mana += SPELL_COST( ch, sn1 );
	mana += SPELL_COST( ch, sn1 ) * 0.2;
	}
  if ( legal2 )
	{
	mana += SPELL_COST( ch, sn2 );
	mana += SPELL_COST( ch, sn2 ) * 0.2;
	}
  mana += mana * 0.1;
  if ( ch->mana < mana && ch->level < LEVEL_IMMORTAL )
	{
	WAIT_STATE( ch, skill_table[gsn_multiburst].beats );
	send_to_char( C_DEFAULT, "You don't have enough mana to multiburst these spells.\n\r", ch );
	return;
	}
  WAIT_STATE( ch, skill_table[gsn_multiburst].beats );
  send_to_char( AT_RED, "You release a burst of energy!\n\r", ch );
  act( AT_RED, "$n releases a burst of energy.", ch, NULL, NULL, TO_ROOM );

  update_skpell( ch, gsn_multiburst );

  if ( legal1 )
	(*skill_table[sn1].spell_fun) ( sn1, 
					URANGE( 1, ch->level, LEVEL_HERO ),
					ch, victim );
  if ( victim->position != POS_DEAD && ch->in_room == victim->in_room )
  {
  if ( legal2 )
	(*skill_table[sn2].spell_fun) ( sn2,
					URANGE( 1, ch->level, LEVEL_HERO ),
					ch, victim );
  }
  if ( ch->level < LEVEL_IMMORTAL )
	MT( ch ) -= mana;
  return;
}

void do_rage( CHAR_DATA *ch, char *argument )
{
  OBJ_DATA *wield;
  OBJ_DATA *wield2;
  char	    buf [ MAX_INPUT_LENGTH ];
  AFFECT_DATA af;

  if ( IS_AFFECTED2( ch, AFF_RAGE ) )
	return;
  if ( !can_use_skpell( ch, gsn_rage ) )
	{
	send_to_char( C_DEFAULT, "You are not enough of a beast.\n\r", ch );
	return;
	}
  if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_rage] < number_percent( ) )
	{
	send_to_char( C_DEFAULT, "You cannot summon enough anger.\n\r", ch );
	return;
	}

  wield = get_eq_char( ch, WEAR_WIELD );
  wield2 = get_eq_char( ch , WEAR_WIELD_2 );

  if ( wield || wield2 )
	{
	sprintf( buf, 
        "You become enraged and toss your weapon%s to the ground.\n\r",
	( wield && wield2 ) ? "s" : "" );
	send_to_char( AT_RED, buf, ch );
	sprintf( buf,
	"$n tosses his weapon%s to the ground in a fit of rage.",
	( wield && wield2 ) ? "s" : "" );
	act( C_DEFAULT, buf, ch, NULL, NULL, TO_ROOM );
	if ( wield )
		{
		obj_from_char( wield );
		obj_to_room( wield, ch->in_room );
		}
	if ( wield2 )
		{
		obj_from_char( wield2 );
		obj_to_room( wield2, ch->in_room );
		}
	}
  else
	{
	send_to_char( AT_RED,
	"You become enraged and surge with power.\n\r", ch );
	}

  update_skpell( ch, gsn_rage );
 
  af.type	 = gsn_rage;
  af.level	 = ch->level;
  af.duration	 = ch->level * 0.4;
  af.location	 = APPLY_STR;
  af.modifier	 = 5;
  af.bitvector	 = AFF_RAGE;
  affect_to_char2( ch, &af );

  af.location	 = APPLY_HITROLL;
  af.modifier	 = ch->level;
  affect_to_char2( ch, &af );

  af.location	 = APPLY_DAMROLL;
  af.modifier	 = ch->level;
  affect_to_char2( ch, &af );

  return;
}
	
void do_challenge(CHAR_DATA *ch, char *argument)
{
  int award;
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  int rvnum = ch->in_room->vnum;
#ifdef NEW_MONEY
  MONEY_DATA amount;    
#endif

  if ( IS_NPC(ch) )
  {
    send_to_char( C_DEFAULT, "NPC's can't fight in the arena.\n\r", ch );
    return;
  }
  if ( rvnum == ROOM_VNUM_HELL
  || rvnum == ROOM_VNUM_RJAIL )
  {
    send_to_char( C_DEFAULT, "Nice try, but get out the real way.\n\r", ch );
    return;
  }
  if ( arena.fch && arena.sch )
  {
    send_to_char( C_DEFAULT, "There are already two people fighting in the"
                  " arena.\n\r", ch );
    return;
  }
  if ( arena.cch )
  {
    sprintf(arg1, "%s is offering a challenge.  Type accept to accept it.\n\r",
            arena.cch->name);
    send_to_char( C_DEFAULT, arg1, ch );
    return;
  }
  argument = one_argument(argument, arg1);
  argument = one_argument(argument, arg2);
  
  if ( (is_number(arg1) && (award = atoi(arg1)) < 1 )
  || ( !is_number(arg1) && !is_number(arg2) )
  || ( is_number(arg2) && (award = atoi(arg2)) < 1 ) )
  {
    send_to_char( C_DEFAULT, "Syntax: challenge [player] <award>\n\r", ch );
    send_to_char( C_DEFAULT, " Player is the optional name of a specific person to challenge.\n\r", ch);
    send_to_char( C_DEFAULT, " Award is at least 1 gold coins.\n\r", ch );
    return;
  }
  else if ( (award = atoi(arg2)) )
  {
    DESCRIPTOR_DATA *d;
    bool found = FALSE;
    for ( d = descriptor_list; d; d = d->next )
	{
	if ( d->connected == CON_PLAYING
	&& is_name( NULL, arg1, d->character->name )
	&& d->character && ch ) 
		{
		found = TRUE;
		arena.och = d->character;
		break;
		}
	}
  if ( !found )
    {
    send_to_char( C_DEFAULT, "They aren't here.\n\r", ch );
    return;
    }
  }
  else
    award = atoi(arg1);
#ifdef NEW_MONEY
/* Convert and compare copper values: */
  if ( award*100 > ( ch->money.gold*C_PER_G + ch->money.silver*S_PER_G +
                     ch->money.copper ) )
/*  if ( award > ( ch->money.gold + (ch->money.silver/SILVER_PER_GOLD) +
               (ch->money.copper/COPPER_PER_GOLD) ) )  */
  {
#else
  if ( award > ch->gold )
  {
#endif
    send_to_char( C_DEFAULT, "You can't afford that.\n\r", ch );
    arena.och = NULL;
    return;
  }
  if ( !get_room_index(ROOM_ARENA_ENTER_F) ||
       !get_room_index(ROOM_ARENA_ENTER_S) )
  {
    send_to_char( C_DEFAULT, "An error has occured.  Please inform an Immortal.\n\r", ch );
    return;
  }
  arena.cch = ch;
  arena.count = 0;
  arena.award = award;
#ifdef NEW_MONEY
  amount.silver = amount.copper = 0;
  amount.gold = award;
  spend_money( &ch->money, &amount );
#else
  ch->gold -= award;
#endif
  if ( arena.och )
  sprintf(log_buf, "&C%s &cchallenges &C%s &cto a fight in the arena for &W%d &cgold coins.", 
	  ch->name, arena.och->name, award );
  else
  sprintf(log_buf, "&C%s &coffers a challenge in the arena for &W%d &cgold coins.",
          ch->name, award);
/*  wiznet(log_buf, NULL, NULL, WIZ_DEATHS, 0, 0); */
  log_string(log_buf, CHANNEL_LOG, -1);
  challenge(log_buf, 0, 0);
  send_to_char( C_DEFAULT, "Your challenge has been offered.\n\r", ch );
  return;
}

void do_accept(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *cch, *och;
  int rvnum = ch->in_room->vnum;
#ifdef NEW_MONEY
  MONEY_DATA amount;
#endif
  
  if ( IS_NPC(ch) )
  {
    send_to_char( C_DEFAULT, "NPC's may not fight in the arena.\n\r", ch );
    return;
  }
  if ( !(cch = arena.cch) )
  {
    send_to_char( C_DEFAULT, "There is no challenge being offered.\n\r", ch );
    return;
  }
  if ( rvnum == ROOM_VNUM_HELL
  || rvnum == ROOM_VNUM_RJAIL )
  { 
    send_to_char( C_DEFAULT, "Nice try, but get out the real way.\n\r", ch );
    return;
  }
  if ( ch->fighting )
  {
    send_to_char( C_DEFAULT, "You are already fighting.\n\r", ch );
    return;
  }
  if ( ch == cch )
  {
    send_to_char( C_DEFAULT, "You can't accept your own challenge!\n\r", ch );
    return;
  }
  if ( ( och = arena.och ) && och != ch )
  {
    send_to_char( C_DEFAULT, "You are not the one being challenged.\n\r", ch );
    return;
  }
#ifdef NEW_MONEY
  if ( ( ch->money.gold*C_PER_G + ch->money.silver*S_PER_G +
         ch->money.copper ) < arena.award*100 )
/*  if ( (ch->money.gold + (ch->money.silver/SILVER_PER_GOLD) +
       (ch->money.copper/COPPER_PER_GOLD) ) < arena.award )  */
  {
    send_to_char( C_DEFAULT, "You cannot afford that.\n\r", ch );
    return;
  }
 
  amount.silver = amount.copper = 0;
  amount.gold = arena.award;
  spend_money( &ch->money, &amount );
#else
  if ( ch->gold < arena.award )
  {
    send_to_char( C_DEFAULT, "You cannot afford that.\n\r", ch );
    return;
  }
  ch->gold -= arena.award;
#endif
  arena.award *= 2;
  arena.fch = cch;
  arena.sch = ch;
  arena.cch = NULL;
  arena.och = NULL;
  send_to_char( C_DEFAULT, "Your challenge has been accepted.\n\r", cch );
  stop_fighting(cch, FALSE);
  act( AT_LBLUE, "A pentagram forms around $n and he slowly dissipates.",
       cch, NULL, NULL, TO_ROOM );
  char_from_room(cch);
  char_to_room(cch, get_room_index(ROOM_ARENA_ENTER_F));
  do_look(cch, "auto");
  act( AT_LBLUE, "A pentagram forms around $n and he slowly dissipates.",
       ch, NULL, NULL, TO_ROOM );
  char_from_room(ch);
  char_to_room(ch, get_room_index(ROOM_ARENA_ENTER_S));
  do_look(ch, "auto");
  sprintf(log_buf, "&C%s &chas accepted &C%s&c's challenge.",
          ch->name, cch->name);
/*  wiznet(log_buf, NULL, NULL, WIZ_DEATHS, 0, 0); */
  log_string(log_buf, CHANNEL_LOG, -1);
  challenge(log_buf, 0, 0);
  send_to_char(AT_RED, "Be prepared.\n\r", ch);
  send_to_char(AT_RED, "Be prepared.\n\r", cch);
  return;
}
void do_bite(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *victim;
  int	     dam;
  float	     wait_mod;

  if(!IS_NPC(ch)
   && !can_use_skpell( ch, gsn_bite ) )
  {
    send_to_char(C_DEFAULT, "You gnash your teeth wildly.\n\r", ch);
    return;
  }

  if(argument[0] != '\0')
  {
    if(!(victim = get_char_room(ch, argument)))
    {
      send_to_char(C_DEFAULT, "They aren't here.\n\r", ch);
      return;
    }
  }
  else
  {
    if(!(victim = ch->fighting))
    {
      send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch);
      return;
    }
  }

  if(is_safe(ch, victim))
    return;
  if ( ch->level < 25 )
	wait_mod = 0.5;
  else if ( ch->level < 40 )
	wait_mod = 1;
  else if ( ch->level < 60 )
	wait_mod = 1.5;
  else if ( ch->level < 80 )
	wait_mod = 2;
  else
	wait_mod = 3;
  WAIT_STATE(ch, skill_table[gsn_bite].beats / wait_mod);
  if(IS_NPC(ch) || number_percent() < ch->pcdata->learned[gsn_bite])
  {
    dam = ch->level + number_range(ch->level, ch->level * 5);
    damage(ch, victim, dam, gsn_bite);
    update_skpell(ch, gsn_bite);
  }
  else
  {
    send_to_char(C_DEFAULT, "You failed.", ch);
    damage(ch, victim, 0, gsn_bite);
  }

  return;
}

void do_rush( CHAR_DATA *ch, char *argument )
{
  AFFECT_DATA af;

  if ( IS_NPC( ch ) )
	return;
  if ( IS_AFFECTED2( ch, AFF_RUSH ) )
	return;
  if ( !can_use_skpell( ch, gsn_rush ) )
	{
	send_to_char( C_DEFAULT, "You can't pump yourself up enough.\n\r", ch );
	return;
	}
  WAIT_STATE( ch, skill_table[gsn_rush].beats );
  if ( ch->pcdata->learned[gsn_rush] < number_percent( ) )
	{
	send_to_char( C_DEFAULT, "You failed.\n\r", ch );
	return;
	}
  send_to_char( AT_RED, "You pump yourself up and make the adrenaline flow.\n\r", ch );
  act( AT_WHITE, "$n seems to be pumped up.", ch, NULL, NULL, TO_ROOM );
  af.type	 = gsn_rush;
  af.level	 = ch->level;
  af.duration	 = ch->level / 4;
  af.location	 = APPLY_DEX;
  af.modifier	 = -2;
  af.bitvector	 = AFF_RUSH;
  affect_to_char2( ch, &af );

  update_skpell( ch, gsn_rush );

  return;
}
void do_howl_of_fear(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *victim;
  
  if(!IS_NPC(ch)
   && is_class( ch, gsn_howlfear ) )
  {
    send_to_char(C_DEFAULT, "You failed.\n\r", ch);
    return;
  }
  if ( IS_NPC( ch ) )
	return;
  if(argument[0] != '\0')
  {
    if(!(victim = get_char_room(ch, argument)))
    {
      send_to_char(C_DEFAULT, "They aren't here.\n\r", ch);
      return;
    }
  }
  else
  {
    if(!(victim = ch->fighting))
    {
      send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch);
      return;
    }
  }

  if(is_safe(ch, victim))
    return;
  if (is_affected(victim, gsn_howlfear) )
    {
    act( AT_RED, "$N is already scared witless.", ch, NULL, victim, TO_CHAR );
    return;
    }
  WAIT_STATE(ch, skill_table[gsn_howlfear].beats);
  if(number_percent() < ch->pcdata->learned[gsn_howlfear])
  {
    AFFECT_DATA af;
    af.type	 = gsn_howlfear;
    af.level	 = ch->level;
    af.duration	 = 10;
    af.location	 = APPLY_DAMROLL;
    af.modifier	 = 0 - ch->level / 2;
    af.bitvector = 0;
    affect_to_char( victim, &af );
   
    af.location	 = APPLY_HITROLL;
    af.modifier	 = 0 - ch->level / 2;
    affect_to_char( victim, &af );
  
    af.level	 = ch->level;
    af.duration	 = 10;
    af.location	 = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_ANTI_FLEE;
    affect_to_char( victim, &af );

    act( AT_RED, "Your chilling howl instills fear in $N.", 
         ch, NULL, victim, TO_CHAR );
    act( AT_RED, "You cringe in terror at the sound of $n's howl.",
	 ch, NULL, victim, TO_VICT );
    act( AT_RED, "$n howls and $N cringes back in terror.",
	 ch, NULL, victim, TO_NOTVICT );
    if ( !victim->fighting )
	set_fighting( victim, ch );
  }

  update_skpell( ch, gsn_howlfear );

  return;
}

void do_frenzy( CHAR_DATA *ch, char *argument )
{
  AFFECT_DATA af;
  if ( IS_AFFECTED2( ch, AFF_BERSERK ) )
    return;
  if ( !ch->fighting )
    return;

  if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_frenzy] < number_percent() )
  {
    send_to_char(C_DEFAULT, "You failed.\n\r",ch);
    return;
  }

  af.type = gsn_frenzy;
  af.level = ch->level;
  af.duration = ch->level / 10;
  af.bitvector = AFF_BERSERK;

  af.location = APPLY_DAMROLL;
  af.modifier = IS_NPC(ch) ? ch->level / 2 : ch->damroll * 2 / 3;
  affect_to_char2(ch, &af);

  af.location = APPLY_HITROLL;
  af.modifier = IS_NPC(ch) ? ch->level / 2 : ch->hitroll * 2 / 3;
  affect_to_char2(ch, &af);

  af.location = APPLY_AC;
  af.modifier = ch->level * -2;
  affect_to_char2(ch, &af);

  send_to_char(AT_WHITE, "You go into a frenzy.\n\r",ch);
  act(AT_WHITE, "$n suddenly goes into a frenzy", ch, NULL, NULL, TO_ROOM );
  update_skpell( ch, gsn_frenzy );
  return;
}

void do_reflex( CHAR_DATA *ch, char *argument )
{
  AFFECT_DATA af;

  if ( IS_NPC( ch ) )
	return;
  if ( IS_AFFECTED( ch, AFF_HASTE ) )
	return;
  if ( !can_use_skpell( ch, gsn_reflex ) )
	return;
  WAIT_STATE( ch, skill_table[gsn_reflex].beats );
  if ( ch->pcdata->learned[gsn_reflex] < number_percent( ) )
	{
	send_to_char( C_DEFAULT, "You failed.\n\r", ch );
	return;
	}
  send_to_char( AT_RED, "You feel yourself more agile.\n\r", ch );
  act( AT_WHITE, "$n is moving more fluidly.", ch, NULL, NULL, TO_ROOM );
  af.type	 = gsn_reflex;
  af.level	 = ch->level;
  af.duration	 = ch->level / 4;
  af.location	 = APPLY_DEX;
  af.modifier	 = 4;
  af.bitvector	 = AFF_HASTE;
  affect_to_char( ch, &af );

  update_skpell( ch, gsn_reflex );

  return;
}

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

    if ( !IS_NPC( ch )
	&& !can_use_skpell( ch, gsn_rake ) )
    {
	send_to_char(C_DEFAULT,
	    "You'd better leave animalistic actions to werewolves.\n\r", ch );
	return;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }

    one_argument( argument, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return;
	}
    if ( IS_AFFECTED( victim, AFF_BLIND ) )
	return;

    WAIT_STATE( ch, skill_table[gsn_rake].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_rake] )
    {
	damage( ch, victim, number_range( 100, ch->level*5 ), gsn_rake );
  	update_skpell( ch, gsn_rake );
        if ( number_percent( ) < 75 )
        {
	AFFECT_DATA af;

	af.type      = gsn_blindness;
	af.duration  = 5;
	af.location  = APPLY_HITROLL;
	af.modifier  = -10;
	af.bitvector = AFF_BLIND;
	affect_join( victim, &af );
    }
       
    update_pos( victim );	
    }
    else
	damage( ch, victim, 0, gsn_rake );

    return;
}
void do_bladepalm( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  int dam = 0;
  if ( IS_NPC( ch ) )
	return;
  if ( !can_use_skpell( ch, gsn_bladepalm ) )
	{
	send_to_char( AT_GREY, "You know nothing of martial arts.\n\r", ch );
	return;
	}
  if ( get_eq_char( ch, WEAR_WIELD ) && get_eq_char( ch, WEAR_WIELD_2 ) )
	{
	send_to_char( AT_GREY, "You need at least one free hand to perform a blade palm.\n\r", ch );
	return;
	}
  if ( argument[0] != '\0' )
	{
	if ( !(victim=get_char_room(ch, argument)) )
	   {
	   send_to_char(C_DEFAULT, "They aren't there.\n\r", ch );
	   return;
	   }
	}
  else
	{
	if ( !(victim = ch->fighting) )
	   {
 	   send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	   return;
	   }
	}
  
  if ( is_safe(ch, victim) )
	return;
  WAIT_STATE(ch, skill_table[gsn_bladepalm].beats);
  if ( ch->pcdata->learned[gsn_bladepalm] > number_percent( ) )
	{
	int anatomy = ch->pcdata->learned[gsn_anatomyknow];
	if ( anatomy > 0
	&& number_percent( ) < number_range( anatomy / 9, anatomy / 4.5 ) )
		{
		update_skpell( ch, gsn_anatomyknow );
		send_to_char( AT_RED, "You hit a pressure point!\n\r", ch );
		act( AT_RED, "$n hit one of $N's pressure points!",
		     ch, NULL, victim, TO_NOTVICT );
		act( AT_RED, "$n hit you with a precise shot.", 
		     ch, NULL, victim, TO_VICT );
		if ( number_percent( ) < 5 )
			{
			victim->hit = 1;
			}
		else if ( number_percent( ) < 25 )
			{
			STUN_CHAR( victim, 3, STUN_TOTAL );
			victim->position = POS_STUNNED;
			dam += 500;
			}
		else
			dam += 300;
		}
	dam += number_fuzzy( ch->level / 2 + ch->level / 15 );
	dam += GET_DAMROLL( ch );
	if ( is_affected( ch, gsn_flamehand ) )
		dam += dam / 8;
	if ( is_affected( ch, gsn_frosthand ) )
		dam += dam / 4;
	if ( is_affected( ch, gsn_chaoshand ) )
		dam += dam / 4;
	if ( ch->pcdata->learned[gsn_enhanced_damage] > 0 )
		dam += dam / 4 * ch->pcdata->learned[gsn_enhanced_damage] / 150;
	damage( ch, victim, dam, gsn_bladepalm );

	update_skpell( ch, gsn_bladepalm );

	}
  else
	damage( ch, victim, 0, gsn_bladepalm );
  return;
}

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

  if ( !IS_NPC( ch )
  && !can_use_skpell( ch, gsn_flykick ) )
    {
    send_to_char( AT_GREY, "You do not hav knowledge of martial arts.\n\r", ch );
    return;
    }
 if ( !ch->fighting )
    {
    send_to_char( AT_GREY, "You aren't fighting anyone.\n\r", ch );
    return;
    }
 one_argument( argument, arg );
 victim = ch->fighting;
 if ( arg[0] != '\0' )
    if ( !(victim=get_char_room( ch, arg )) )
	{
	send_to_char( AT_GREY, "They aren't here.\n\r", ch );
	return;
	}
 WAIT_STATE( ch, skill_table[gsn_flykick].beats );
 if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_flykick] )
 {
	damage( ch, victim, number_range( 200, ch->level*6 ), gsn_flykick );
	update_skpell( ch, gsn_flykick );
 }
 else
	damage( ch, victim, 0, gsn_flykick );
 return;
}
void do_nerve( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  char buf[MAX_INPUT_LENGTH];
  OBJ_DATA *wield;
  OBJ_DATA *dual;
  OBJ_DATA *hold;
  OBJ_DATA *triple;
  if ( IS_NPC( ch ) )
	return;
  if ( !can_use_skpell( ch, gsn_nerve ) )
	{
	send_to_char( AT_GREY, "Huh?\n\r", ch );
	return;
	}
  if ( !(victim = ch->fighting) )
  {
    send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r",ch);
    return;
  }
  if ( number_percent() < ch->pcdata->learned[gsn_nerve] 
  && number_percent() < (ch->level * 75) / victim->level )
  {
	AFFECT_DATA af;
	act( AT_YELLOW, "You pinch $N's arm nerves!", ch, NULL, victim, TO_CHAR );
	act( AT_YELLOW, "$n pinched your arm nerves.", ch, NULL, victim, TO_VICT );
	act( AT_YELLOW, "$n pinched $N's arm nerves.", ch, NULL, victim, TO_NOTVICT );
	wield = get_eq_char( victim, WEAR_WIELD );
	dual = get_eq_char( victim, WEAR_WIELD_2 );
	triple = get_eq_char( victim, WEAR_WIELD_3 );
	if ( wield || dual || triple )
		{
                if ( IS_SIMM( victim, IMM_NERVE ) )
		  {
		  sprintf( buf, 
		  "$N shrugs off the blow and grips $S weapon%s tightly.",
		  ( wield && dual ) ? "s" : "" );
		  act( AT_GREY, buf, ch, NULL, victim, TO_NOTVICT );
		  }
		else
		  {
		  sprintf( buf, "$N drops $S weapon%s to the ground.",
		         ( wield && dual ) ? "s" : "" );
		  act( AT_GREY, buf, ch, NULL, victim, TO_CHAR );
		  act( AT_GREY, buf, ch, NULL, victim, TO_NOTVICT );
		  sprintf( buf, "You drop your weapon%s to the ground.\n\r",
			( wield && dual ) ? "s" : "" );
 		  send_to_char( AT_GREY, buf, victim );
		  if ( wield )
			{
			obj_from_char( wield );
			obj_to_room( wield, victim->in_room );
			}
		  if ( dual )
			{
			obj_from_char( dual );
			obj_to_room( dual, victim->in_room );
			}
		  if ( triple )
			{
			obj_from_char( triple );
			obj_to_room( triple, victim->in_room );
			}
		  }
		}
	if ( (hold = get_eq_char( victim, WEAR_HOLD )) )
		{
		if ( !IS_SIMM( victim, IMM_NERVE ) )
		  {
		  act( AT_GREY, "$N drops $S $p.", ch, hold, victim, TO_CHAR );
    		  act( AT_GREY, "$N drops $S $p.", ch, hold, victim, TO_NOTVICT );
		  act( AT_GREY, "You drop your $p.", ch, hold, victim, TO_VICT );
		  obj_from_char( hold );
		  obj_to_room( hold, victim->in_room );
		  }
		else
		  act( AT_GREY, "$N grips $S $p tightly.", ch, hold, victim, TO_NOTVICT );
		}
	if ( IS_SIMM( ch, IMM_NERVE ) )
	  return;
	af.type      = gsn_nerve;
	af.duration  = 1;
	af.location  = APPLY_NONE;
	af.modifier  = 0;
	af.bitvector = 0;
	affect_join( victim, &af );

	update_skpell( ch, gsn_nerve );
   }

   return;
}
void do_trip( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  if ( IS_NPC( ch ) )
	return;
  if ( !can_use_skpell( ch, gsn_trip ) )
    {
    send_to_char( AT_GREY, "Huh?\n\r", ch );
    return;
    }
  if ( !(victim=ch->fighting) )
    {
    send_to_char( AT_GREY, "You aren't fighting anyone.\n\r", ch );
    return;
    }

  if ( ch->pcdata->learned[gsn_trip] > number_percent( ) )
  {
	trip( ch, victim );
	update_skpell( ch, gsn_trip );
  }

  return;

}
void do_shriek( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  OBJ_DATA *obj, *obj_next;
  OBJ_DATA *potion, *potion_next;
  int dam;
  int blown = 0;
  int max_blown = 0;
  if ( !IS_NPC( ch )
  &&   !can_use_skpell( ch, gsn_shriek ) )
	{
	send_to_char( AT_GREY, "Huh?\n\r", ch );
	return;
	}
  if ( !(victim = ch->fighting) )
	{
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
	}
  max_blown = ( IS_NPC( ch ) ) ? 10 : 25;
  if ( ( obj = victim->carrying ) && !saves_spell( ch->level, victim ) )
    {
    for ( obj = victim->carrying; obj; obj = obj_next )
	{
	obj_next = obj->next_content;
	if ( blown >= max_blown )
	  break;
	if ( obj->deleted )
	  continue;
	switch ( obj->item_type )
	  {
	  default: continue;
	  case ITEM_POTION:
	  case ITEM_CONTAINER:
	  }
	if ( obj->item_type == ITEM_CONTAINER )
	  {
	  if ( !obj->contains )
	    continue;
	  for ( potion = obj->contains; potion; potion = potion_next )
	    {
	    potion_next = potion->next_content;
	    if ( blown >= max_blown )
	        break;
	    if ( potion->deleted )
		continue;
	    if ( potion->item_type != ITEM_POTION )
		continue;
	    if ( number_bits( 2 ) != 0 )
		{
		extract_obj( potion );
		act(AT_BLUE, "You feel something explode from within $p.",
		    victim, obj, NULL, TO_CHAR );
		blown++;
		}
	    }
	  continue;
	  }
	if ( number_bits( 2 ) != 0 )
	  {
	  act(AT_BLUE, "$p vibrates and explodes!", victim, obj, NULL, TO_CHAR );
	  extract_obj( obj );
	  blown++;
	  }
	}
    }
  dam = number_range( 100, ch->level * 3 );
  dam += blown * 10;
  damage( ch, victim, dam, gsn_shriek );
  update_skpell( ch, gsn_shriek );
  WAIT_STATE( ch, skill_table[gsn_shriek].beats );		
} 
void death_xp_loss( CHAR_DATA *victim )
{
  int base_xp, xp_lastlvl, xp_loss, classes, mod;
  classes = number_classes( victim );
  if ( victim->level < LEVEL_HERO )
    {
    xp_lastlvl = classes == 1 ? 1000 * victim->level
	       : classes * 2000 * victim->level; 
    xp_loss = ( xp_lastlvl - victim->exp ) / 2;
    if ( victim->exp > xp_lastlvl )
      gain_exp( victim, xp_loss );
    }
  else if ( victim->level < L_CHAMP3 )
    {
    mod = 1;
    base_xp = classes == 1 ? 100000 : 200000;
    xp_lastlvl = base_xp * classes;
    switch ( victim->level )
      {
      case LEVEL_HERO: mod = 1;
      case L_CHAMP1:   mod = 4;
      case L_CHAMP2:   mod = 10;
      }
    xp_lastlvl = xp_lastlvl * mod;
    if ( victim->exp > xp_lastlvl )
      {
      xp_loss = (xp_lastlvl - victim->exp ) / 2;
      xp_loss = UMAX( -10000 * classes, xp_loss );
      gain_exp( victim, xp_loss );
      }
    }
  return;
}

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

    if ( !IS_NPC( ch )
        && !can_use_skpell( ch, gsn_lure ) )
    {
        send_to_char(C_DEFAULT,
            "You cannot lure.\n\r", ch );
        return;
    }

    if ( !ch->fighting )
    {
        send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
        return;
    }

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

    if ( !IS_NPC( ch ) && ch->pcdata->learned[gsn_blindfight] > 0
    && ch->pcdata->learned[gsn_blindfight] < number_percent( ) )
    {
    if ( !check_blind( ch ) )
        return;
    }

    one_argument( argument, arg );
    victim = ch->fighting;

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

    dt = TYPE_UNDEFINED;

    WAIT_STATE( ch, skill_table[gsn_lure].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_lure] )
    {
        act(AT_WHITE, "$n lures $N into a vulnerable position.", ch, NULL, victim, TO_ROOM );
	send_to_char( AT_WHITE, "Your oppenet has lured you into a vulnerable position.\n\r", victim );
	send_to_char( AT_WHITE, "You lure your opponent into a vulnerable position.\n\r", ch);
      one_hit( ch, victim, dt );
    if(IS_AFFECTED(ch, AFF_HASTE))
      one_hit( ch, victim, dt );
    if (IS_AFFECTED2( ch, AFF_RUSH ) )
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_second_attack) )
      one_hit( ch, victim, dt ); 
    if(can_use_skpell( ch, gsn_third_attack) ) 
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_fourth_attack) )
      one_hit( ch, victim, dt );
     if(can_use_skpell( ch, gsn_fifth_attack) )
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_sixth_attack) )
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_seventh_attack) )
      one_hit( ch, victim, dt );
/*    if(can_use_skpell( ch, gsn_eigth_attack) )
      one_hit( ch, victim, dt ); */
    if ( IS_AFFECTED2(ch, AFF_BERSERK) )
       one_hit( ch, victim, dt );
/* put more reasons to attack here */

     one_dual( ch, victim, dt);
     one_triple( ch, victim, dt);

     }
	update_skpell( ch, gsn_lure );
    return;
}

void do_image( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char  dt; 
    char buf[MAX_STRING_LENGTH];


    dt = TYPE_UNDEFINED;
    
        act(AT_WHITE, "$n attacks $N!", ch, NULL, victim, TO_ROOM );
	act( AT_WHITE, "An image of $n shatters!", ch, NULL, NULL, TO_ROOM
);
	sprintf( buf, "An image of %s shatters!\n\r", ch->name );
	send_to_char( AT_WHITE, buf, victim );
	sprintf( buf, "%s attacks one of your images!", victim->name );
	send_to_char( AT_WHITE, buf, ch);
      one_hit( ch, victim, dt );
    if(IS_AFFECTED(ch, AFF_HASTE))
      one_hit( ch, victim, dt );
    if (IS_AFFECTED2( ch, AFF_RUSH ) )
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_second_attack) )
      one_hit( ch, victim, dt ); 
    if(can_use_skpell( ch, gsn_third_attack) ) 
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_fourth_attack) )
      one_hit( ch, victim, dt );
     if(can_use_skpell( ch, gsn_fifth_attack) )
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_sixth_attack) )
      one_hit( ch, victim, dt );
    if(can_use_skpell( ch, gsn_seventh_attack) )
      one_hit( ch, victim, dt );
/*    if(can_use_skpell( ch, gsn_eigth_attack) )
      one_hit( ch, victim, dt ); */
    if ( IS_AFFECTED2(ch, AFF_BERSERK) )
       one_hit( ch, victim, dt );
/* put more reasons to attack here */

     one_dual( ch, victim, dt);
	 one_triple( ch, victim, dt);
     multi_hit( ch, victim, dt );

    return;
}

void do_flip(CHAR_DATA *ch, char *argument)
{
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  EXIT_DATA *pexit;
  CHAR_DATA *victim;
  ROOM_INDEX_DATA *from_room;
  int door;
  char buf1[256], buf2[256], buf3[256];

  argument = one_argument(argument, arg1);
  one_argument(argument, arg2);

  if(arg1[0] == '\0')
  {
    send_to_char(AT_BLUE, "Flip who what where?", ch);
    return;
  }

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

  if(victim->position != POS_FIGHTING)
  {
    send_to_char(AT_BLUE, "You aren't fighting anybody.\n\r", ch);
    return;
  }
  WAIT_STATE( ch, skill_table[gsn_flip].beats );
  if ( IS_NPC( ch ) || number_percent( ) < ch->pcdata->learned[gsn_flip] )
   {
	damage( ch,  victim, number_range( 100, ch->level*6 ), gsn_flip );
   }
   else
	damage( ch, victim, 0, gsn_flip );
	

  if ( victim->position == POS_STUNNED || IS_STUNNED( ch, STUN_TO_STUN ) )
	return;
  if ( ( IS_NPC(ch) || number_percent() < ch->pcdata->learned[gsn_flip] ) &&
      number_percent() < (ch->level * 100) / victim->level )
  {
    STUN_CHAR( ch, 10, STUN_TO_STUN );
    STUN_CHAR( victim, 3, STUN_TOTAL );
    victim->position = POS_STUNNED;
    act( AT_WHITE, "You knock the wind out of $N!", ch, NULL, victim, TO_CHAR );
    act( AT_WHITE, "$n knocks the wind out of $N!", ch, NULL, victim, TO_NOTVICT );
    act( AT_WHITE, "$n knocks the wind out of you!", ch, NULL, victim, TO_VICT );
    update_skpell(ch, gsn_flip);
    
  }

  if ( !str_cmp( arg2, "n" ) || !str_cmp( arg2, "north" ) ) door = 0;
  else if ( !str_cmp( arg2, "e" ) || !str_cmp( arg2, "east"  ) ) door = 1;
  else if ( !str_cmp( arg2, "s" ) || !str_cmp( arg2, "south" ) ) door = 2;
  else if ( !str_cmp( arg2, "w" ) || !str_cmp( arg2, "west"  ) ) door = 3;
  else if ( !str_cmp( arg2, "u" ) || !str_cmp( arg2, "up"    ) ) door = 4;
  else if ( !str_cmp( arg2, "d" ) || !str_cmp( arg2, "down"  ) ) door = 5;
  else door = dice(1,6) - 1;

  if(ch == victim)
  {
    send_to_char(AT_BLUE, "You attempt to flip yourself, oook.\n\r", ch);
    return;
  }

  pexit = ch->in_room->exit[door];
  if(pexit == NULL || IS_SET(pexit->exit_info, EX_CLOSED))
  {
    act(AT_BLUE, "There is no exit, but you flip $M anyways.", ch, NULL,
victim, TO_CHAR);
    act(AT_BLUE, "$n flips $N.", ch, NULL, victim, TO_NOTVICT);
    act(AT_BLUE, "$n flips you, ouch.", ch, NULL, victim, TO_VICT);
    return;
  }
  if (!can_use_skpell( ch, gsn_flip ))
	{
	send_to_char(AT_WHITE, "HEEEYaaaaAA!", ch );
	return;
	}
  if ( pexit->to_room->vnum == ROOM_VNUM_SMITHY )
	{
	act(AT_BLUE, "You flip $N, but a force field prevents $S entry.",
ch, NULL, victim, TO_CHAR );
	act(AT_BLUE, "$n flips $N, but a force field makes $M bounce back.", ch, NULL, victim, TO_NOTVICT );
	act(AT_BLUE, "$n flips you, but you bounce off of a force field.",
ch, NULL, victim, TO_VICT );
	return;
	}
    if ( number_percent( ) < ch->pcdata->learned[gsn_flip] ){
  sprintf(buf1, "You flip $N, sending $M %s.", dir_name[door]);
  sprintf(buf2, "$n flips $N, sending $M %s.", dir_name[door]);
  sprintf(buf3, "$n flips you, sending you %s.", dir_name[door]);
  act(AT_BLUE, buf2, ch, NULL, victim, TO_NOTVICT );
  act(AT_BLUE, buf1, ch, NULL, victim, TO_CHAR );
  act(AT_BLUE, buf3, ch, NULL, victim, TO_VICT );
  from_room = victim->in_room;
  eprog_enter_trigger( pexit, victim->in_room, victim );
  char_from_room(victim);
  char_to_room(victim, pexit->to_room);

  act(AT_BLUE, "$n comes flying into the room.", victim, NULL, NULL,
TO_ROOM);
  if ( (pexit = pexit->to_room->exit[rev_dir[door]]) &&
       pexit->to_room == from_room )
    eprog_exit_trigger( pexit, victim->in_room, victim );
  else
    rprog_enter_trigger( victim->in_room, victim );
    }
  return;
}