alanthia/area/
alanthia/gods/
alanthia/player/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
*	ROM 2.4 is copyright 1993-1996 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@efn.org)				   *
*	    Gabrielle Taylor						   *
*	    Brian Moore (zump@rom.org)					   *
*	By using this code, you have agreed to follow the terms of the	   *
*	ROM license, in the file Rom24/doc/rom.license			   *
***************************************************************************/

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

int hitchance;
int diceroll;

/*
 *  Tables for wrath
 */
char *const pos_table[] = {
    "dead", "mortal", "incap", "stun", "sleep", "rest", "sit", "fight",
    "stand",
    NULL
};

char *const eq_table[] = {
    "light", "finger_l", "finger_r", "neck_1", "neck_2", "torso", "head",
    "legs",
    "feet", "hands", "arms", "shield", "body", "waist", "wrist_l",
    "wrist_r",
    "wield", "hold", "float", NULL
};

/* command procedures needed */
DECLARE_DO_FUN(do_backstab);
DECLARE_DO_FUN(do_assassinate);
DECLARE_DO_FUN(do_emote);
DECLARE_DO_FUN(do_bash);
DECLARE_DO_FUN(do_berserk);
DECLARE_DO_FUN(do_trip);
DECLARE_DO_FUN(do_dirt);
DECLARE_DO_FUN(do_flee);
DECLARE_DO_FUN(do_kick);
DECLARE_DO_FUN(do_disarm);
DECLARE_DO_FUN(do_get);
DECLARE_DO_FUN(do_recall);
DECLARE_DO_FUN(do_yell);
DECLARE_DO_FUN(do_sacrifice);
DECLARE_DO_FUN(do_kill);
DECLARE_DO_FUN(do_circle);
DECLARE_DO_FUN(do_whirl);
DECLARE_DO_FUN(do_arial);
DECLARE_DO_FUN(do_stand);
DECLARE_DO_FUN(do_feed);
DECLARE_DO_FUN(do_flee);
DECLARE_DO_FUN(do_land);
DECLARE_ATTACK_FUN(attack_hit);


/*
 * Local functions.
 */
void check_assist args((CHAR_DATA * ch, CHAR_DATA * victim));
bool check_dodge args((CHAR_DATA * ch, CHAR_DATA * victim));
bool check_duck
args((CHAR_DATA * ch, CHAR_DATA * victim, char *attack_type));
void check_killer args((CHAR_DATA * ch, CHAR_DATA * victim));
bool check_parry args((CHAR_DATA * ch, CHAR_DATA * victim));
bool check_shield_block args((CHAR_DATA * ch, CHAR_DATA * victim));
void dam_message args((CHAR_DATA * ch, CHAR_DATA * victim, int dam,
		       int dt, bool immune));
void death_cry args((CHAR_DATA * ch, CHAR_DATA * victim));

void group_gain args((CHAR_DATA * ch, CHAR_DATA * victim));
int xp_compute
args((CHAR_DATA * gch, CHAR_DATA * victim, int total_levels));
bool is_safe args((CHAR_DATA * ch, CHAR_DATA * victim));
void make_corpse args((CHAR_DATA * ch, bool can_loot));
void death_penalty args((CHAR_DATA * ch));
void raw_kill args((CHAR_DATA * ch, CHAR_DATA * victim));
void one_hit args((CHAR_DATA * ch, CHAR_DATA * victim, int dt));
void mob_hit args((CHAR_DATA * ch, CHAR_DATA * victim, int dt));
void set_fighting args((CHAR_DATA * ch, CHAR_DATA * victim));
void disarm args((CHAR_DATA * ch, CHAR_DATA * victim));
bool has_number args((char *string));


/*
 * Control the fights going on.
 * Called periodically by update_handler.
 */
void violence_update(void)
{
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    CHAR_DATA *victim;

    for (ch = char_list; ch != NULL; ch = ch->next) {
	ch_next = ch->next;

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

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

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

	if (IS_NPC(ch)) {
	    if (HAS_TRIGGER(ch, TRIG_FIGHT))
		mp_percent_trigger(ch, victim, NULL, NULL, TRIG_FIGHT);
	    if (HAS_TRIGGER(ch, TRIG_HPCNT))
		mp_hprct_trigger(ch, victim);
	}
	/*
	 * Fun for the whole family!
	 */
	check_assist(ch, victim);
    }

    return;
}

/* for auto assisting */
void check_assist(CHAR_DATA * ch, CHAR_DATA * victim)
{
    CHAR_DATA *rch, *rch_next;

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

	if (IS_AWAKE(rch) && rch->fighting == NULL) {

	    /* quick check for ASSIST_PLAYER */
	    if (!IS_NPC(ch) && IS_NPC(rch)
		&& IS_SET(rch->off_flags, ASSIST_PLAYERS)
		&& rch->level + 6 > victim->level) {
		do_emote(rch, "screams and attacks!");
		multi_hit(rch, victim, TYPE_UNDEFINED);
		continue;
	    }
	    /* PCs next */
	    if (!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM)) {
		if (((!IS_NPC(rch) && IS_SET(rch->act, PLR_AUTOASSIST))
		     || IS_AFFECTED(rch, AFF_CHARM))
		    && is_same_group(ch, rch) && !is_safe(rch, victim))
		    multi_hit(rch, victim, TYPE_UNDEFINED);

		continue;
	    }

	    /* now check the NPC cases */
	    if (IS_NPC(ch) && !IS_AFFECTED(ch, AFF_CHARM)) {
		if ((IS_NPC(rch) && IS_SET(rch->off_flags, ASSIST_ALL))
		    || (IS_NPC(rch) && rch->group
			&& rch->group == ch->group) || (IS_NPC(rch)
							&& rch->race ==
							ch->race
							&& IS_SET(rch->
								  off_flags,
								  ASSIST_RACE))
		    || (IS_NPC(rch) && IS_SET(rch->off_flags, ASSIST_ALIGN)
			&& ((IS_GOOD(rch) && IS_GOOD(ch))
			    || (IS_EVIL(rch) && IS_EVIL(ch))
			    || (IS_NEUTRAL(rch) && IS_NEUTRAL(ch))))
		    || (rch->pIndexData == ch->pIndexData
			&& IS_SET(rch->off_flags, ASSIST_VNUM))) {
		    CHAR_DATA *vch;
		    CHAR_DATA *target;
		    int number;

		    if (number_bits(1) == 0)
			continue;

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

		    if (target != NULL) {
			do_emote(rch, "screams and attacks!");
			multi_hit(rch, target, TYPE_UNDEFINED);
		    }
		}
	    }
	}
    }
}


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

    /* decrement the wait */
    if (ch->desc == NULL)
	ch->wait = UMAX(0, ch->wait - PULSE_VIOLENCE);

    if (ch->desc == NULL)
	ch->daze = UMAX(0, ch->daze - PULSE_VIOLENCE);

    /* no attacks for stunnies -- just a check */
    if (ch->position < POS_RESTING)
	return;

    if (dt == gsn_assassinate) {
	one_hit(victim, ch, dt);
	return;
    }

    if (IS_NPC(ch)) {
	mob_hit(ch, victim, dt);
	return;
    }

    one_hit(ch, victim, dt);

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

    if (IS_AFFECTED(ch, AFF_HASTE))
	one_hit(ch, victim, dt);

    if (ch->fighting != victim || dt == gsn_backstab)
	return;

    chance = get_skill(ch, gsn_second_attack) / 2;

    if (number_percent() < chance) {
	one_hit(ch, victim, dt);
	check_improve(ch, gsn_second_attack, TRUE, 5);
	if (ch->fighting != victim)
	    return;
    }

    chance = get_skill(ch, gsn_third_attack) / 4;

    if (number_percent() < chance) {
	one_hit(ch, victim, dt);
	check_improve(ch, gsn_third_attack, TRUE, 6);
	if (ch->fighting != victim)
	    return;
    }

    chance = get_skill(ch, gsn_fourth_attack) / 4;

    if (number_percent() < chance) {
	one_hit(ch, victim, dt);
	check_improve(ch, gsn_fourth_attack, TRUE, 6);
	if (ch->fighting != victim)
	    return;
    }
    chance = get_skill(ch, gsn_fifth_attack) / 4;

    if (number_percent() < chance) {
	one_hit(ch, victim, dt);
	check_improve(ch, gsn_fifth_attack, TRUE, 6);
	if (ch->fighting != victim)
	    return;
    }
    chance = get_skill(ch, gsn_sixth_attack) / 4;

    if (number_percent() < chance) {
	one_hit(ch, victim, dt);
	check_improve(ch, gsn_sixth_attack, TRUE, 6);
	if (ch->fighting != victim)
	    return;
    }
    return;
}

/* procedure for all mobile attacks */
/* Grb: deprecated. mobs attack just like players. left this here for historical reasons */
void mob_hit(CHAR_DATA * ch, CHAR_DATA * victim, int dt)
{
    one_hit(ch, victim, dt);
    return;
}

/*
 * dt is the pointer to the element id in the attack_table
 */
int correct_dt(int dt, CHAR_DATA * ch, OBJ_DATA * wield)
{

    if (dt == TYPE_UNDEFINED) {
	dt = TYPE_HIT;

	if (wield != NULL && wield->item_type == ITEM_WEAPON)
	    dt = wield->value[3];
	else
	    dt = ch->dam_type;
    }

    return dt;
}

/* 
 * dam_type is the DAM_TYPE for the elemener in the attack_table
 */
int calc_dam_type(CHAR_DATA * ch, OBJ_DATA * wield, int dt)
{
    int dam_type;

    if (dt < TYPE_HIT)
	if (wield != NULL)
	    dam_type = attack_table[wield->value[3]].damage;
	else
	    dam_type = attack_table[ch->dam_type].damage;
    else
	dam_type = attack_table[dt - TYPE_HIT].damage;

    if (dam_type < 0)
	dam_type = DAM_BASH;

    return dam_type;
}

/*
 * Calc damage from a hit.
 * Returns total damage, including from, etc special weapon flags
 */
int calc_damage(CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * wield,
		int sn, int skill, int dt)
{

    int dam;

    if (IS_NPC(ch) && wield == NULL)
	dam = dice(ch->damage[DICE_NUMBER], ch->damage[DICE_TYPE]);
    else {
	if (sn != -1)
	    check_improve(ch, sn, TRUE, 5);
	if (wield != NULL) {
	    if (wield->pIndexData->new_format)
		dam = dice(wield->value[1], wield->value[2]) * skill / 100;
	    else
		dam = number_range(wield->value[1] * skill / 100,
				   wield->value[2] * skill / 100);

	    if (get_eq_char(ch, WEAR_SHIELD) == NULL)	/* no shield = more */
		dam = dam * 11 / 10;

	    /* sharpness! */
	    if (IS_WEAPON_STAT(wield, WEAPON_SHARP)
		&& (wield->condition <= (wield->level * 2))) {
		int percent;

		if ((percent = number_percent()) <= (skill / 8))
		    dam = 2 * dam + (dam * 2 * percent / 100);

		/* Condition Flagging! Wdl */

		wield->condition++;

		if (wield->condition == (wield->level * 2)) {
		    REMOVE_BIT(wield->value[4], WEAPON_SHARP);
		    send_to_char
			("{gYour weapon seems to dull slightly...{x\r\n",
			 ch);
		}
	    }
	} else
	    dam = number_range(1 + 4 * skill / 100, 2 * ch->level / 3
			       * skill / 100);
    }

/*    
 * Bonuses.
 */
    if (get_skill(ch, gsn_enhanced_damage) > 0) {
	diceroll = number_percent();
	if (diceroll <= get_skill(ch, gsn_enhanced_damage)) {
	    check_improve(ch, gsn_enhanced_damage, TRUE, 6);
	    dam += (3 * (ch->level)) / 20;
	}
    }
    if (get_skill(ch, gsn_ultra_damage) > 0) {
	diceroll = number_percent();
	if (diceroll <= get_skill(ch, gsn_ultra_damage)) {
	    check_improve(ch, gsn_ultra_damage, TRUE, 6);
	    dam += (2 * (ch->level)) / 9;
	}
    }
    if (!IS_AWAKE(victim))
	dam *= 2;
    else if (victim->position < POS_FIGHTING)
	dam = dam * 3 / 2;

    /* Backstab Damage */
    if (dt == gsn_backstab && wield != NULL) {
	dam *= 1 + (ch->level / 16);
    }

    dam += GET_DAMROLL(ch) * UMIN(100, skill) / 100;

    if (wield != NULL && ch->fighting == victim) {

	if (IS_WEAPON_STAT(wield, WEAPON_POISON)) {
	    int level;
	    AFFECT_DATA *poison, af;

	    if ((poison =
		 affect_find(wield->affected, gsn_poison)) == NULL)
		level = wield->level;
	    else
		level = poison->level;

	    if (!saves_spell(level / 2, victim, DAM_POISON)) {
		send_to_char
		    ("You feel poison coursing through your veins.\n\r",
		     victim);
		act("$n is poisoned by the venom on $p.", victim, wield,
		    NULL, TO_ROOM);

		af.where = TO_AFFECTS;
		af.type = gsn_poison;
		af.level = level * 3 / 4;
		af.duration = level / 2;
		af.location = APPLY_STR;
		af.modifier = -1;
		af.bitvector = AFF_POISON;
		affect_join(victim, &af);
	    }
	    /* weaken the poison if it's temporary */
	    if (poison != NULL) {
		poison->level = UMAX(0, poison->level - 2);
		poison->duration = UMAX(0, poison->duration - 1);

		if (poison->level == 0 || poison->duration == 0)
		    act("The poison on $p has worn off.", ch, wield, NULL,
			TO_CHAR);
	    }

	    return dam;

	}


	if (IS_WEAPON_STAT(wield, WEAPON_VAMPIRIC)) {
	    dam += number_range(1, wield->level / 2 + 1);
	    act("$p draws life from $n.", victim, wield, NULL, TO_ROOM);
	    act("You feel $p drawing your life away.",
		victim, wield, NULL, TO_CHAR);
	    damage(ch, victim, dam, 0, DAM_NEGATIVE, FALSE);
	    ch->alignment = UMAX(-1000, ch->alignment - 1);
	    ch->hit += dam / 2;
	    return dam;
	}

	if (IS_WEAPON_STAT(wield, WEAPON_HOLY)) {
	    dam += number_range(1, wield->level / 5 + 1);
	    act("$p absorbs life force from $n.", victim, wield, NULL,
		TO_ROOM);
	    act("You feel $p taking life force away from you.", victim,
		wield, NULL, TO_CHAR);
	    ch->alignment = UMAX(-1000, ch->alignment + 1);

	    if (ch->alignment > 1000) {
		ch->alignment = 1000;
	    }

	    return dam;
	}

	if (IS_WEAPON_STAT(wield, WEAPON_VORPAL)) {
	    dam += number_range(1, wield->level / 5 + 1);
	    act("$p makes $n weak and tired!", victim, wield, NULL,
		TO_ROOM);
	    act("You feel $p draining your strength!", victim, wield, NULL,
		TO_CHAR);
	    victim->move -= dam / 2;

	    if (victim->move < 1) {
		do_land(victim, "");
		victim->move = 0;
	    }

	    return dam;
	}

	if (IS_WEAPON_STAT(wield, WEAPON_FLAMING)) {
	    dam += number_range(1, wield->level / 4 + 1);
	    act("$n is burned by $p.", victim, wield, NULL, TO_ROOM);
	    act("$p sears your flesh.", victim, wield, NULL, TO_CHAR);
	    fire_effect((void *) victim, wield->level / 2, dam,
			TARGET_CHAR);
	    return dam;
	}

	if (IS_WEAPON_STAT(wield, WEAPON_FROST)) {
	    dam += number_range(1, wield->level / 6 + 2);
	    act("$p freezes $n.", victim, wield, NULL, TO_ROOM);
	    act("The cold touch of $p surrounds you with ice.",
		victim, wield, NULL, TO_CHAR);
	    cold_effect(victim, wield->level / 2, dam, TARGET_CHAR);
	    return dam;
	}

	if (IS_WEAPON_STAT(wield, WEAPON_SHOCKING)) {
	    dam += number_range(1, wield->level / 5 + 2);
	    act("$n is struck by lightning from $p.", victim, wield, NULL,
		TO_ROOM);
	    act("You are shocked by $p.", victim, wield, NULL, TO_CHAR);
	    shock_effect(victim, wield->level / 2, dam, TARGET_CHAR);
	    return dam;
	}

	if (IS_WEAPON_STAT(wield, WEAPON_QUICKPOISON)) {
	    dam += ((wield->level * 18) / 10);
	    act("$n is infected by $p.", victim, wield, NULL, TO_ROOM);
	    act("poison is flooding into your body", victim, wield, NULL,
		TO_CHAR);
	    return dam;
	}
    }

    return dam;


}

/* 
 * chance-to-hit calculations
 */
int calc_hit_chance(int hitchance, CHAR_DATA * ch, CHAR_DATA * victim,
		    int skill, int dt, int dam_type)
{

    int victim_ac;
#ifdef DEBUG
    char buf[MAX_STRING_LENGTH];
#endif


    hitchance = 50;
    hitchance += ((ch->level - victim->level) / 5);

#ifdef DEBUG
    sprintf(buf, "{YBased on level, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // size - smaller opponents are harder to hit
    hitchance -= ((ch->size - victim->size) * 3);

#ifdef DEBUG
    sprintf(buf, "{YBased on size, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // fatigue - we fight better when fresh
    // should reduce hit chance by 1 for every % below 50 char's mv is
    // should increase hit chance by 1 for every % above 90 char's mv is
    //FIXME:
    hitchance += (20 - ((ch->max_move - ch->move) / 25));

#ifdef DEBUG
    sprintf(buf, "{YBased on fatigue, chance to hit is %d{x\r\n",
	    hitchance);
    send_to_char(buf, ch);
#endif

    // strength - plus to hit if stronger than opponent
    hitchance += (get_curr_stat(ch, STAT_STR)
		  - get_curr_stat(victim, STAT_STR));

#ifdef DEBUG
    sprintf(buf, "{YBased on str, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // dexterity
    hitchance += (get_curr_stat(ch, STAT_DEX)
		  - get_curr_stat(victim, STAT_DEX));

#ifdef DEBUG
    sprintf(buf, "{YBased on dex, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // int
    hitchance += (get_curr_stat(ch, STAT_INT)
		  - get_curr_stat(victim, STAT_INT));

#ifdef DEBUG
    sprintf(buf, "{YBased on int, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // wisdom
    hitchance += (get_curr_stat(ch, STAT_WIS)
		  - get_curr_stat(victim, STAT_WIS));

#ifdef DEBUG
    sprintf(buf, "{YBased on wis, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // burden
    hitchance += (100 - (get_carry_weight(ch) / can_carry_w(ch) * 100));

#ifdef DEBUG
    sprintf(buf, "{YBased on burden, chance to hit is %d{x\r\n",
	    hitchance);
    send_to_char(buf, ch);
#endif

    // skill bonus
    hitchance += (skill / 10);

#ifdef DEBUG
    sprintf(buf, "{YBased on skill, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    // hitroll
    hitchance += ch->hitroll;

#ifdef DEBUG
    sprintf(buf, "{YAfter HR check, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    if (IS_AFFECTED(ch, AFF_BLIND))
	hitchance -= 125;

    if (IS_AFFECTED(victim, AFF_BLIND))
	hitchance += 60;

    if (dt == gsn_backstab) {
	hitchance -= 6 * (100 - get_skill(ch, gsn_backstab));
    }

    switch (dam_type) {
    case (DAM_PIERCE):
	victim_ac = GET_AC(victim, AC_PIERCE) / 25;
	break;
    case (DAM_BASH):
	victim_ac = GET_AC(victim, AC_BASH) / 25;
	break;
    case (DAM_SLASH):
	victim_ac = GET_AC(victim, AC_SLASH) / 25;
	break;
    default:
	victim_ac = GET_AC(victim, AC_EXOTIC) / 25;
	break;
    };

    if (victim->position < POS_FIGHTING)
	victim_ac += 12;

    if (victim->position < POS_RESTING)
	victim_ac += 20;

    hitchance += victim_ac / 100;

#ifdef DEBUG
    sprintf(buf, "{YOpponent's AC is %d{x\r\n", victim_ac);
    send_to_char(buf, ch);
    sprintf(buf, "{YAfter AC check, chance to hit is %d{x\r\n", hitchance);
    send_to_char(buf, ch);
#endif

    if (IS_DWARF(ch) && ch->pcdata->condition[COND_DRUNK] > 10)
	hitchance += ch->pcdata->condition[COND_DRUNK] / 3;
    else if (!IS_DWARF(ch) && !IS_NPC(ch)
	     && ch->pcdata->condition[COND_DRUNK] > 10)
	hitchance -= ch->pcdata->condition[COND_DRUNK] / 3;

#ifdef DEBUG
    sprintf(buf, "{YAfter drunk check, chance to hit is %d{x\r\n",
	    hitchance);
    send_to_char(buf, ch);
#endif

    /* turf bonus */
    if (ch->clan) {
	if (ch->in_room->turf_clan && (ch->in_room->turf_clan == ch->clan)) {
	    hitchance += UMIN(20, (ch->in_room->turf_level / 10));
	} else
	    if (ch->in_room->turf_clan
		&& (ch->in_room->turf_clan != ch->clan)) {
	    hitchance -= UMIN(20, (ch->in_room->turf_level / 10));
	}
    }

    if (hitchance < 0)
	hitchance = 0;

#ifdef DEBUFG
    sprintf(buf, "{YAfter turf check, chance to hit is %d{x\r\n",
	    hitchance);
    send_to_char(buf, ch);
#endif

    return hitchance;
}


int execute_attack(CHAR_DATA * ch, int attack, CHAR_DATA * victim,
		   OBJ_DATA * wield, int sn, int skill, int dam_type,
		   int dt)
{
    ATTACK_FUN *attack_fun;
    int damroll, dam;

    attack_fun = attack_table[attack].function;

    ch->cwait += attack_table[attack].cwait;

    damroll *= attack_table[attack].dr_mod;
    dam += (ch->damroll / 5);

    //FIXME: modify attacker's AC

    attack_fun(ch, victim, dt);

    dam = calc_damage(ch, victim, wield, sn, skill, dt);

    damage(ch, victim, dam, dt, dam_type, TRUE);

    return dam;
}


/*
* One attack stack
* The meat of the attacks has been moved to attacks.c
*/
void one_hit(CHAR_DATA * ch, CHAR_DATA * victim, int dt)
{
    OBJ_DATA *wield;
    int sn, skill;
    int dam_type;
    int current_attack;
    char buf[MAX_STRING_LENGTH];
    sn = -1;

    //just in case
    if (victim == ch || ch == NULL || victim == NULL
	|| victim->position == POS_DEAD || ch->in_room != victim->in_room)
	return;

    // execute an attack stack, one at a time, until out of attacks or time.
    while ((ch->cwait + attack_table[ch->current_attack + 1].cwait)
	   < COMBAT_WAIT_LENGTH) {

	//FIXME: Make sure to check for zero-time attacks so this can't hang

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

	// if ch has no attack stack set, use default attack.. ("hit") 
	if (!ch->current_attack
	    && ch->attack_stack[ch->current_attack] == -1)
	    current_attack = 0;

	if (ch->attack_stack[ch->current_attack] == -1)
	    ch->current_attack = 0;

	current_attack = ch->attack_stack[ch->current_attack];

	hitchance = 0;

#ifdef DEBUG
	sprintf(buf, "{Ycwait is %d{x\r\n", ch->cwait);
	send_to_char(buf, ch);
#endif

	// decide if we're attacking with a weapon or hand to hand
	wield = get_eq_char(ch, WEAR_WIELD);
	dt = correct_dt(dt, ch, wield);
	dam_type = calc_dam_type(ch, wield, dt);

	// and set up the skill
	skill = get_weapon_skill(ch, get_weapon_sn(ch));

	// decide % chance to hit
	hitchance =
	    calc_hit_chance(hitchance, ch, victim, skill, dt, dam_type);

	diceroll = number_range(0, 99);

#ifdef DEBUG
	sprintf(buf, "{YDiceroll was %d{x\r\n", diceroll);
	send_to_char(buf, ch);
#endif

	if (diceroll == 0 || (diceroll != 100 && diceroll > hitchance)) {
	    // whiffed
	    tail_chain();
	    return;
	}
#ifdef DEBUG
	sprintf(buf, "{YExecuting attack %d\r\n", current_attack);
	send_to_char(buf, ch);
#endif

	// kick some ass 
	execute_attack(ch, current_attack, victim, wield, sn, skill,
		       dam_type, dt);

	if (ch->attack_stack[ch->current_attack] == -1
	    || ch->attack_stack[ch->current_attack++] == -1)
	    ch->current_attack = 0;

    }				//  while (GET_CWAIT (ch) +

#ifdef DEBUG
    sprintf(buf, "{YResetting CWAIT..\r\n");
    send_to_char(buf, ch);
#endif
    ch->cwait = 0;

    tail_chain();
    return;
}


/*
 * Inflict damage from a hit.
 */
bool damage(CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt,
	    int dam_type, bool show)
{

    //char buf[MAX_STRING_LENGTH]; 
    char buf4[MAX_STRING_LENGTH];

    OBJ_DATA *corpse;
    bool immune;
    bool displaced = FALSE;	//displace spell

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

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

	check_killer(ch, victim);

	if (victim->position > POS_STUNNED) {
	    if (!is_same_group(ch, victim)) {
		if (victim->fighting == NULL) {
		    if (ch->master) {
			int percent = number_range(1, 12);

			if (percent < 6) {
			    set_fighting(victim, ch->master);
			} else {
			    set_fighting(victim, ch);
			}
		    } else {
			set_fighting(victim, ch);
		    }
		    if (victim->timer <= 4)
			victim->position = POS_FIGHTING;
		}
	    }
	}
	if (victim->position > POS_STUNNED) {
	    if (!is_same_group(ch, victim)) {
		if (ch->fighting == NULL)
		    set_fighting(ch, victim);
	    }
	}

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

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

    /*
     * Damage modifiers.
     */
    if IS_DWARF
	(victim) {
	if (dam > 1 && victim->pcdata->condition[COND_DRUNK] > 10)
	    dam -= dam / 5;
	if (dam < 0)
	    dam = 0;
	}

    if (dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY))
	dam = (3 * dam) / 4;

    if (dam > 1 && IS_AFFECTED(victim, AFF_HEAVENLY_SANCTUARY))
	dam = (23 * dam) / 25;

    if (dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch))
		    || (IS_AFFECTED(victim, AFF_PROTECT_GOOD)
			&& IS_GOOD(ch))))
	dam = (22 * dam) / 25;

    if (ch->clan) {
	if (ch->in_room->turf_clan && (ch->in_room->turf_clan == ch->clan)) {
	    dam += URANGE(0, (ch->in_room->turf_level / 10), 20);
	} else if (ch->in_room->turf_clan
		   && (ch->in_room->turf_clan != ch->clan)) {
	    dam -= URANGE(0, (ch->in_room->turf_level / 10), 20);
	}
    }

    if (dam < 0)
	dam = 0;

    immune = FALSE;

    /*
     * Check for parry, dodge, shield block, and displaced
     */
    if (dt >= TYPE_HIT && ch != victim && dt != gsn_whirl
	&& dt != gsn_circle) {

	if (check_parry(ch, victim))
	    return FALSE;
	if (check_dodge(ch, victim))
	    return FALSE;
	if (check_shield_block(ch, victim))
	    return FALSE;

	//Check if displaced
	if (is_affected(victim, skill_lookup("displace"))) {

	    if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

		//You're hitting the displaced version
		displaced = TRUE;
		if (IS_NPC(victim)
		    || !IS_SET(victim->act, PLR_AUTODEFENSE))
		    act("{y$n hits your displaced version.{x", ch, NULL,
			victim, TO_VICT);
		if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE))
		    act("{yYour hit goes right through $N.{x", ch, NULL,
			victim, TO_CHAR);
		return FALSE;
	    }
	}
    }

    switch (check_immune(victim, dam_type)) {
    case (IS_IMMUNE):
	immune = TRUE;
	dam = 0;
	break;
    case (IS_RESISTANT):
	dam = (21 * dam) / 25;
	break;
    case (IS_VULNERABLE):
	dam = (113 * dam) / 100;
	break;
    }

    if (show)
	dam_message(ch, victim, dam, dt, immune);

    if (dam <= 0)
	return FALSE;


    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */
    victim->hit -= dam;
    if (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL
	&& victim->hit < 1)
	victim->hit = 1;

    if (IS_VAMPIRE(victim) && victim->hit < 1 && victim->blood > 5) {
	send_to_char("Your partial immortality has saved you!\n\r",
		     victim);
	act("$n's partial immortality has saved $m!", victim, NULL, NULL,
	    TO_ROOM);

	if ((victim->blood > 4) && (!DAYTIME)) {
	    victim->hit = victim->blood * 3;
	    victim->blood = 3;
	} else {
	    if ((victim->blood > 4) && (DAYTIME)) {
		victim->hit = victim->blood * 2;
		victim->blood = 3;
	    }
	}


    }

    update_pos(victim);

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

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

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

    case POS_DEAD:
	act("{R$n is DEAD!!{x", victim, 0, 0, TO_ROOM);
	break;

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

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

    /*
     * Payoff for killing things.
     */

    // may kill imms in arena.
    if (victim->position == POS_DEAD
	|| (IS_IMMORTAL(victim) && (victim->hit < 2) && (victim->arena))) {

	// fake death in the arena, no corpse, no pain
	if (victim->arena == global_last_arena_id && ch->arena) {
	    stop_fighting(ch, FALSE);
	    stop_fighting(victim, FALSE);
	    sprintf(buf4,
		    "\r\n{c[{RARENA OF DEATH{c] %s just killed %s in the arena!{x",
		    ch->name, victim->name);
	    announce(buf4, ch);
	    arena_death(victim);

	    return FALSE;
	}

	group_gain(ch, victim);

	if (!IS_NPC(victim)) {
	    sprintf(log_buf, "%s killed by %s at %ld",
		    victim->name,
		    (IS_NPC(ch) ? ch->short_descr : ch->name),
		    ch->in_room->vnum);
	    log_string(log_buf);

	    /* For PKill, dying penalty is done in group_gain */
	    if (IS_NPC(ch)) {
		/*
		 * Dying penalty:
		 * 2/3 way back to previous level.
		 */
		gain_exp(victim, -250);
	    }
	    sprintf(log_buf, "%s has been killed by %s at %s [room %ld]",
		    (IS_NPC(victim) ? victim->short_descr : victim->name),
		    (IS_NPC(ch) ? ch->short_descr : ch->name),
		    ch->in_room->name, ch->in_room->vnum);
	}
	if (IS_NPC(victim))
	    wiznet(log_buf, NULL, NULL, WIZ_MOBDEATHS, 0, 0);
	else
	    wiznet(log_buf, NULL, NULL, WIZ_DEATHS, 0, 0);

	/*
	 * Death trigger
	 */

	/* RT new auto commands */

	if (!IS_NPC(ch)
	    && (corpse =
		get_obj_list(ch, "corpse", ch->in_room->contents)) != NULL
	    && corpse->item_type == ITEM_CORPSE_NPC
	    && can_see_obj(ch, corpse)) {
	    OBJ_DATA *coins;

	    corpse = get_obj_list(ch, "corpse", ch->in_room->contents);

	    if (IS_SET(ch->act, PLR_AUTOLOOT) && corpse && corpse->contains)	/* exists and not empty */
		do_get(ch, "all corpse");

	    if (IS_SET(ch->act, PLR_AUTOGOLD) && corpse && corpse->contains &&	/* exists and not empty */
		!IS_SET(ch->act, PLR_AUTOLOOT))
		if ((coins = get_obj_list(ch, "gcash", corpse->contains))
		    != NULL)
		    do_get(ch, "all.gcash corpse");

	    if (IS_SET(ch->act, PLR_AUTOSAC)) {
		if (IS_SET(ch->act, PLR_AUTOLOOT) && corpse
		    && corpse->contains)
		    return TRUE;	/* leave if corpse has treasure */
		else if (IS_VAMPIRE(ch)) {
		    do_feed(ch, "corpse");
		} else {
		    do_sacrifice(ch, "corpse");
		}
	    }
	}
	return TRUE;
    }
    if (victim == ch)
	return TRUE;

    /*
     * Take care of link dead people.
     */
    if (!IS_NPC(victim) && victim->desc == NULL) {
	if (number_range(0, victim->wait) == 0) {
	    do_recall(victim, "");
	    return TRUE;
	}
    }
    /*
     * Wimp out?
     */
    if (IS_NPC(victim) && dam > 0 && victim->wait < PULSE_VIOLENCE / 2) {
	if ((IS_SET(victim->act, ACT_WIMPY) && number_bits(2) == 0
	     && victim->hit < victim->max_hit / 5)
	    || (IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL
		&& victim->master->in_room != victim->in_room))
	    do_flee(victim, "");
    }
    if (!IS_NPC(victim)
	&& victim->hit > 0
	&& victim->hit <= victim->wimpy
	&& victim->wait < PULSE_VIOLENCE / 2)
	do_flee(victim, "");

    tail_chain();
    return TRUE;
}


bool is_safe(CHAR_DATA * ch, CHAR_DATA * victim)
{
    if (victim->in_room == NULL || ch->in_room == NULL)
	return TRUE;

    if (victim->fighting == ch || victim == ch)
	return FALSE;

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

    /* killing mobiles */
    if (IS_NPC(victim)) {

	/* safe room? */
	if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) {
	    send_to_char("Not in this room.\n\r", ch);
	    return TRUE;
	}

	if (victim->pIndexData->pShop != NULL) {
	    send_to_char("No killing shopkeepers.\n\r", ch);
	    return TRUE;
	}
	/* no killing healers, trainers, etc */
	if (IS_SET(victim->act, ACT_TRAIN)
	    || IS_SET(victim->act, ACT_PRACTICE)
	    || IS_SET(victim->act, ACT_REPAIR)
	    || IS_SET(victim->act, ACT_NO_ATTACK)
	    || IS_SET(victim->act, ACT_IS_HEALER)
	    || IS_SET(victim->act, ACT_BANKER)) {
	    send_to_char("No killing healers, trainers, etc.\n\r", ch);
	    return TRUE;
	}

	if (!IS_NPC(ch)) {
	    /* no pets */
	    if (IS_SET(victim->act, ACT_PET)) {
		act("But $N looks so cute and cuddly...",
		    ch, NULL, victim, TO_CHAR);
		return TRUE;
	    }

	    /* no charmed creatures unless owner */
	    if (IS_AFFECTED(victim, AFF_CHARM) && (ch != victim->master)) {
		send_to_char("You don't own that monster.\n\r", ch);
		return TRUE;
	    }
	    if (IS_AFFECTED(ch, AFF_CHARM)
		&& IS_AFFECTED(victim, AFF_CHARM)) {
		return TRUE;
	    }
	}
    }
    /* killing players */
    else {
	/* NPC doing the killing */
	if (IS_NPC(ch)) {
	    /* safe room check */
	    if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) {
		send_to_char("Not in this room.\n\r", ch);
		return TRUE;
	    }
	    /* charmed mobs and pets cannot attack players while owned */
	    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL
		&& ch->master->fighting != victim) {
		send_to_char("Players are your friends!\n\r", ch);
		return TRUE;
	    }
	}
	/* player doing the killing */
	else {
	    /* Have to be a PKILL to kill */

	    if (!IS_SET(ch->act, PLR_PKILL) && (!ch->tmp_pkill)) {
		send_to_char
		    ("You must type {YPKILL{x twice before you can kill or steal from anyone.\n\r",
		     ch);
		return TRUE;
	    }
	    /* Not allowed killing NON-Pkillers */

	    if (!IS_SET(victim->act, PLR_PKILL) && (!victim->tmp_pkill)) {
		send_to_char("No killing non-pkillers.\n\r", ch);
		return TRUE;
	    }
	    if (IS_SET(victim->in_room->room_flags, ROOM_SAFE)) {
		send_to_char("You're in a safe room.\n\r", ch);
		return TRUE;
	    }

	    if (!ch->tmp_pkill && !victim->tmp_pkill) {
		if (ch->level > victim->level + 25) {
		    send_to_char("Pick on someone your own size!\n\r", ch);
		    return TRUE;
		} else if (ch->level < victim->level - 25) {
		    send_to_char("Pick on someone your own size!\n\r", ch);
		    return TRUE;
		}
	    }
	}
    }
    return FALSE;
}

bool is_safe_spell(CHAR_DATA * ch, CHAR_DATA * victim, bool area)
{
    if (victim->in_room == NULL || ch->in_room == NULL)
	return TRUE;

    if (victim == ch && area)
	return TRUE;

    if (victim->fighting == ch || victim == ch)
	return FALSE;

    if (IS_IMMORTAL(ch) && ch->level > LEVEL_IMMORTAL && !area)
	return FALSE;

    /* killing mobiles */
    if (IS_NPC(victim)) {
	/* safe room? */
	if (IS_SET(victim->in_room->room_flags, ROOM_SAFE))
	    return TRUE;

	if (victim->pIndexData->pShop != NULL)
	    return TRUE;

	/* no killing healers, trainers, etc */
	if (IS_SET(victim->act, ACT_TRAIN)
	    || IS_SET(victim->act, ACT_PRACTICE)
	    || IS_SET(victim->act, ACT_IS_HEALER)
	    || IS_SET(victim->act, ACT_BANKER))
	    return TRUE;

	if (!IS_NPC(ch)) {
	    /* no pets */
	    if (IS_SET(victim->act, ACT_PET))
		return TRUE;

	    /* no charmed creatures unless owner */
	    if (IS_AFFECTED(victim, AFF_CHARM)
		&& (area || ch != victim->master))
		return TRUE;

	    /* legal kill? -- cannot hit mob fighting non-group member */
	    if (victim->fighting != NULL
		&& !is_same_group(ch, victim->fighting))
		return TRUE;
	} else {
	    /* area effect spells do not hit other mobs */
	    if (area && !is_same_group(victim, ch->fighting))
		return TRUE;
	}
    }
    /* killing players */
    else {
	if (area && IS_IMMORTAL(victim) && victim->level > LEVEL_IMMORTAL)
	    return TRUE;

	/* NPC doing the killing */
	if (IS_NPC(ch)) {
	    /* charmed mobs and pets cannot attack players while owned */
	    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL
		&& ch->master->fighting != victim)
		return TRUE;

	    /* safe room? */
	    if (IS_SET(victim->in_room->room_flags, ROOM_SAFE))
		return TRUE;

	    /* legal kill? -- mobs only hit players grouped with opponent */
	    if (ch->fighting != NULL
		&& !is_same_group(ch->fighting, victim))
		return TRUE;
	}
	/* player doing the killing */
	else {
	    if (!IS_SET(ch->act, PLR_PKILL))
		return TRUE;

	    if (!IS_SET(victim->act, PLR_PKILL))
		return TRUE;

	    // PK range check
	    if ((IS_SET(ch->act, PLR_PKILL)
		 && (IS_SET(victim->act, PLR_PKILL))
		 && (victim->level < (ch->level - 25))))
		return TRUE;

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

    }
    return FALSE;
}

/*
 * See if an attack justifies a KILLER flag.
 */

void check_killer(CHAR_DATA * ch, CHAR_DATA * victim)
{
    /* This function is currenly unused. Taken out by Bloodbath. */
    return;
}



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

    if (!IS_AWAKE(victim))
	return FALSE;

    if (get_skill(victim, gsn_parry) == 0)
	return FALSE;

    /*Mobs don't need weapons to parry anymore.  Only
       players do.  Severhand */
    if (victim->pIndexData == NULL)
	if (get_eq_char(victim, WEAR_WIELD) == NULL) {
	    return FALSE;
	}

    chance = get_skill(victim, gsn_parry);
    if ((!can_see(ch, victim)) && (!IS_NPC(ch)))
	chance *= 2;

    if (!can_see(ch, victim))
	chance = (chance * 3) / (chance * 2);
    if (!can_see(victim, ch))
	chance /= 2;
    if (number_percent() >= ((chance - 60) / 2))
	return FALSE;

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

    if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE))
	act("{yYou parry $n's attack.{x", ch, NULL, victim, TO_VICT);

    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE))
	act("{y$N parries your attack.{x", ch, NULL, victim, TO_CHAR);

    check_improve(victim, gsn_parry, TRUE, 6);
    return TRUE;
}

/*
 * Check for shield block.
 */
bool check_shield_block(CHAR_DATA * ch, CHAR_DATA * victim)
{
    int chance;

    if (!IS_AWAKE(victim))
	return FALSE;

    if (get_skill(victim, gsn_shield_block) == 0)
	return FALSE;

    chance = get_skill(victim, gsn_shield_block);
    if ((!can_see(ch, victim)) && (!IS_NPC(ch)))
	chance *= 2;

    if (!can_see(ch, victim))
	chance *= 1, 5;

    if (!can_see(victim, ch))
	chance /= 2;

    chance += get_curr_stat(victim, STAT_STR);
    chance -= get_curr_stat(ch, STAT_STR);


    if (get_eq_char(victim, WEAR_SHIELD) == NULL)
	return FALSE;

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

    if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE))
	act("{yYou block $n's attack with your shield.{x", ch, NULL,
	    victim, TO_VICT);

    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE))
	act("{y$N blocks your attack with a shield.{x", ch, NULL, victim,
	    TO_CHAR);

    check_improve(victim, gsn_shield_block, TRUE, 6);
    return TRUE;
}


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

    if (!IS_AWAKE(victim))
	return FALSE;

    if (get_skill(victim, gsn_dodge) == 0)
	return FALSE;

    chance = get_skill(victim, gsn_dodge);

    if ((!can_see(ch, victim)) && (!IS_NPC(ch)))
	chance *= 2;

    if (!can_see(ch, victim))
	chance *= 1, 5;

    if (!can_see(victim, ch))
	chance /= 2;

    chance -= get_curr_stat(ch, STAT_DEX);
    chance += get_curr_stat(victim, STAT_DEX);

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

    if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE))
	act("{yYou dodge $n's attack.{x", ch, NULL, victim, TO_VICT);

    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE))
	act("{y$N dodges your attack.{x", ch, NULL, victim, TO_CHAR);

    check_improve(victim, gsn_dodge, TRUE, 6);
    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 ((victim->desc != NULL) && (victim->position == POS_MORPHED)) {
	victim->position = POS_STANDING;
	return;
    }
    if (IS_NPC(victim) && victim->hit < 1) {
	victim->position = POS_DEAD;
	return;
    }
    if (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)
{
    if (ch->fighting != NULL) {
	bug("Set_fighting: already fighting", 0);
	return;
    }
    if (IS_AFFECTED(ch, AFF_SLEEP))
	affect_strip(ch, gsn_sleep);

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

    return;
}



void stop_fighting(CHAR_DATA * ch, bool fBoth)
{
    CHAR_DATA *fch;

    for (fch = char_list; fch != NULL; fch = fch->next) {
	if (fch == ch || (fBoth && fch->fighting == ch)) {
	    fch->fighting = NULL;
	    fch->position = IS_NPC(fch) ? fch->default_pos : POS_STANDING;
	    update_pos(fch);
	}
    }

    return;
}



/*
 * Take 1 point from the highest modified stat on death.
 * Reset char's affs and whatnot. 
 * Called by raw_kill and kill_self.
 */
void death_penalty(CHAR_DATA * ch)
{
    int h, i, j = 0, highstat = 0;
    if (IS_NPC(ch)) {
	ch->pIndexData->killed++;
	kill_table[URANGE(0, ch->level, MAX_LEVEL - 1)].killed++;
	extract_char(ch, TRUE);
	return;
    }
    ch->pcdata->deaths++;	/* Increase deaths by 1 */

    if (ch->pcdata->deaths % 10 == 0) {
	for (h = 0; h <= (ch->level / 50); h++) {
	    for (i = 0; i < MAX_STATS; i++) {
		if (ch->perm_stat[i] > highstat) {
		    highstat = ch->perm_stat[i];
		    j = i;
		}
	    }
	}
	ch->perm_stat[j] -= 1;	/*Decrease Stat by 1 */
    }

    extract_char(ch, FALSE);

    while (ch->affected)
	affect_remove(ch, ch->affected);

    ch->affected_by = ch->race->aff;

    for (i = 0; i < 4; i++)
	ch->armor[i] = 100;

    ch->position = POS_RESTING;
    ch->hit = 1;
    ch->mana = 1;
    ch->move = 1;

    if (IS_VAMPIRE(ch))
	ch->blood = UMAX(10, ch->blood);

    if (ch->max_mana > 10)
	ch->max_mana -= 3;
    if (ch->max_move > 10)
	ch->max_move -= 3;
    if (ch->max_hit > 10)
	ch->max_hit -= 3;

    if (!IS_WRAITH(ch) && !IS_VAMPIRE(ch)) {
	ch->pcdata->condition[COND_HUNGER] = 12;
	ch->pcdata->condition[COND_THIRST] = 12;
    }
    ch->pcdata->condition[COND_DRUNK] = 0;
    ch->move = ch->max_move / 75;
    ch->mana = ch->max_mana / 75;
    if ((ch->clan == 2) || (ch->clan == 9) || (ch->clan == 10)
	|| (ch->clan == 7) || (ch->clan == 4) || (ch->clan == 3)) {
	SET_BIT(ch->comm, PLR_PKILL);
    }
    return;
}

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

    if (IS_NPC(ch)) {
	name = ch->short_descr;
	corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0);
	corpse->timer = number_range(3, 6);
	if (ch->gold > 0) {
	    obj_to_obj(create_money(ch->gold), corpse);
	    ch->gold = 0;
	}
	corpse->cost = 0;
    } else {
	name = ch->name;
	corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
	corpse->timer = number_range(25, 40);
	if (!can_loot)
	    REMOVE_BIT(ch->act, PLR_CANLOOT);
	if (!IS_SET(ch->act, PLR_PKILL)) {
	    corpse->owner = str_dup(ch->name);
	    corpse->oname = str_dup(ch->name);
	} else {
	    corpse->owner = NULL;
	    corpse->oname = str_dup(ch->name);
	    if (ch->gold > 1) {
		obj_to_obj(create_money(ch->gold / 2), corpse);
		ch->gold -= ch->gold / 2;
	    }
	}

	corpse->cost = 0;
    }

    corpse->level = ch->level;

    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 != NULL; obj = obj_next) {
	bool floating = FALSE;

	obj_next = obj->next_content;

	if (obj->wear_loc == WEAR_FLOAT)
	    floating = TRUE;

	obj_from_char(obj);

	if (obj->item_type == ITEM_POTION)
	    obj->timer = number_range(500, 1000);

	if (obj->item_type == ITEM_SCROLL)
	    obj->timer = number_range(1000, 2500);

	if (IS_SET(obj->extra_flags, ITEM_ROT_DEATH) && !floating) {
	    obj->timer = number_range(5, 10);
	    REMOVE_BIT(obj->extra_flags, ITEM_ROT_DEATH);
	}

	REMOVE_BIT(obj->extra_flags, ITEM_VIS_DEATH);

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

	else if (floating) {
	    if (IS_OBJ_STAT(obj, ITEM_ROT_DEATH)) {	/* get rid of it! */
		if (obj->contains != NULL) {
		    OBJ_DATA *in, *in_next;
		    act("$p evaporates,scattering its contents.",
			ch, obj, NULL, TO_ROOM);
		    for (in = obj->contains; in != NULL; in = in_next) {
			in_next = in->next_content;
			obj_from_obj(in);
			obj_to_room(in, ch->in_room);
		    }
		} else
		    // floating, rot death, not a container
		    act("$p evaporates.", ch, obj, NULL, TO_ROOM);
		extract_obj(obj);
	    } else {
		// floating, not rot death
		act("$p falls to the floor.", ch, obj, NULL, TO_ROOM);
		obj_to_room(obj, ch->in_room);
	    }
	    // not floating, not rot death
	} else {
	    obj_to_obj(obj, corpse);
/*
        if (obj->bound) {
          obj_to_char(obj, ch);
        } else
*/
	}

    }				// end for loop

    obj_to_room(corpse, ch->in_room);
    return;
}

void death_cry(CHAR_DATA * ch, CHAR_DATA * victim)
{

    ROOM_INDEX_DATA *was_in_room;
    char buf[MAX_STRING_LENGTH];
    char *msg;
    char *msg2;
    char *msg3;
    int door, i;
    long vnum[4];
    int number;

    if (ch == victim)
	return;

    buf[0] = '\0';

/*
 *   msg  goes only to the killer
 *   msg2 goes only to the victim
 *   msg3 goes to everyone else

 act ($p =  weapon
 act $n = victim
 msg $N = victim
 msg $n = agressor
 */

    vnum[0] = 0;
    vnum[1] = 0;
    vnum[2] = 0;
    vnum[3] = 0;
    msg = "You grab $N's neck and twist it sharply. *SNAP*";
    msg2 = "$n grabs your neck and gives it a sharp twist! *SNAP*";
    msg3 = "$n grabs $N's neck and gives it a sharp twist. *SNAP*";


    number = number_range(0, 8);

    // vorpal weapons always yield heads. ;)
    if (get_eq_char(ch, WEAR_WIELD)
	&& IS_WEAPON_STAT(get_eq_char(ch, WEAR_WIELD), WEAPON_VORPAL))
	number = 3;

    switch (number) {

    case 0:
	msg =
	    "Gurgling blood, $N falls to the ground and spasms violently.";
	msg2 =
	    "Gurgling blood, you fall to the ground and spasm violently!";
	msg3 =
	    "Gurgling blood, $N falls to the ground and spasms violently.";

	break;

    case 1:
	if (IS_SET(victim->parts, PART_GUTS)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"Slicing $N's stomach open, you watch as $E trips over $S own guts.";
	    msg2 =
		"$n slices your stomach open, and you trip over your own intestines!";
	    msg3 =
		"$n slices $N's stomach open, causing $M to trip over $S own intestines.";
	    vnum[0] = OBJ_VNUM_GUTS;
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg =
		"Thrusting your dagger through $N's stomach, you unmercifully tear $S guts from $S body.";
	    msg2 =
		"$n thrusts $s dagger into your stomach, wrapping your slimy guts around $s blade.";
	    msg3 =
		"Intestines spill on the ground as $n's dagger pierces $N one final time.";
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg = "Hacking open $N's stomach, you chop at $S guts.";
	    msg2 = "$n savagely rips your stomach open with $s axe!";
	    msg3 =
		"$n hacks into $N's midsection, and cracked ribs pop out amid bloody ribbons of tissue.";
	    vnum[0] = OBJ_VNUM_GUTS;
	    vnum[1] = OBJ_VNUM_TORN_HEART;
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg =
		"Your whip easily slices into $N's stomach, and $S guts slide from $S body.";
	    msg2 =
		"The head of $n's whip carves an arc deep into your stomach, blood oozing in its wake!";
	    msg3 =
		"$n carves out $N's guts with a graceful flick of $s whip.";
	    vnum[0] = OBJ_VNUM_GUTS;
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg =
		"Your polearm thrusts into $N's stomach, exposing $S insides to the open air.";
	    msg2 =
		"$n brings $s polearm down into your stomach, flinging your guts into the air as it exits.";
	    msg3 =
		"$n brings $s polearm down into $N's stomach, and guts explode from $N's body.";
	    vnum[1] = OBJ_VNUM_TORN_HEART;
	    vnum[0] = OBJ_VNUM_GUTS;
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg =
		"Thrusting your sharp spear into $N's stomach, you force $S entrails from $S body.";
	    msg2 =
		"A single thrust of $n's spear guts you, and your entrails spill out of the ragged wound.";
	    msg3 =
		"A single thrust of $n's spear carves a hole in $N's stomach, spilling $S guts down $S legs.";
	    vnum[0] = OBJ_VNUM_GUTS;
	} else {
	    msg =
		"Ripping $N's stomach open, you watch as $E trips over $S own guts.";
	    msg2 =
		"$n rips your stomach open, and you trip over your own guts!";
	    msg3 =
		"$n rips $N stomach open, causing $N to trip over $S own guts.";
	    vnum[0] = OBJ_VNUM_GUTS;
	}
	break;

    case 2:
	if (IS_SET(victim->parts, PART_GUTS)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"With one mighty swipe of your sword, you sever $N's spine and $S guts spill from both halves.";
	    msg2 =
		"$n's cold blade slices you in half, and your warm, frothy guts pour down over your body!";
	    msg3 =
		"$n slices $N in half, causing $N to trip over $S own guts.";
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg = "Piercing $N's stomach, $S entrails are visable.";
	    msg2 =
		"$n pierces your stomach, you die staring in awe of them!";
	    msg3 =
		"$n pierces $N stomach, $N dies while they are exposed from $S body.";
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg = "Hacking $N's stomach, $S entrails are exposed.";
	    msg2 = "$n opens your stomach!";
	    msg3 =
		"$n pierces $N stomach, $N dies watching $S innards leave $S body.";
	    vnum[0] = OBJ_VNUM_GUTS;
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg = "Whipping $N's stomach, $S entrails are exposed.";
	    msg2 = "$n opens your stomach!";
	    msg3 = "$n's whip opens $N's torso!";
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg =
		"$n opens $N's stomach with a long stroke from $S polearm forcing $S guts from $S body.";
	    msg2 = "$n opens your stomach!";
	    msg3 = "$n opens $N's stomach with his polearm.";
	    vnum[0] = OBJ_VNUM_GUTS;
	} else if (IS_SET(victim->parts, PART_GUTS)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg = "Thrusting at $N's stomach you expose $N's entrails.";
	    msg2 =
		"$n thrusts $S spear into your stomach, exposing your entrails.";
	    msg3 = "$n thrusts $S spear deep into $N's stomach.";
	} else {
	    msg = "As you pound $N, $S entrails become visable.";
	    msg2 = "$n's pounding rips you open!";
	    msg3 = "$n rips $N open and exposes $S entrails.";
	}
	break;

    case 3:
	if (IS_SET(victim->parts, PART_HEAD)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"$n connects $s sword just under $N's head, instantly decapitating $M.";
	    msg2 =
		"$n's sword connects with your neck, instantly decapitating you!";
	    msg3 = "$n's sword decapitates $N, sending blood everywhere!";
	    vnum[0] = OBJ_VNUM_SEVERED_HEAD;
	} else if (IS_SET(victim->parts, PART_HEAD)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg = "You dig deep into $N's head and dislodge an eye!";
	    msg2 = "$n's plundges $S dagger deep into your eye!";
	    msg3 =
		"$n's dagger plunges deep into $N's head, poping out $S eye.";
	    vnum[0] = OBJ_VNUM_EYE;
	    vnum[1] = OBJ_VNUM_SEVERED_HEAD;
	} else if (IS_SET(victim->parts, PART_HEAD)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg =
		"Your hack off $N's ear, then swing around, instantly decapitating $M.";
	    msg2 =
		"$n's axe hacks off your ear, swings around, and decapitates you!";
	    msg3 =
		"$n's axe connects with $N's head with explosive force! Body parts fly everywhere!";
	    vnum[0] = OBJ_VNUM_EAR;
	    vnum[1] = OBJ_VNUM_EYE;
	    vnum[2] = OBJ_VNUM_SEVERED_HEAD;
	} else if (IS_SET(victim->parts, PART_HEAD)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg =
		"Your whip wraps tightly around $N's neck, gruesomely pulling it from $S body.";
	    msg2 =
		"$n's whip wraps around your neck and rips your head off!";
	    msg3 =
		"$n's whip wraps $N's neck, $n yanks, and messily decapitates $M.";
	    vnum[0] = OBJ_VNUM_SEVERED_HEAD;
	} else if (IS_SET(victim->parts, PART_HEAD)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg =
		"Your polearm connects with $N's neck, instantly decapitating $M.";
	    msg2 =
		"$n's polearm connects with your neck, instantly decapitating you!";
	    msg3 =
		"$n's polearm connects with $N's neck, instantly decapitating $M.";
	    vnum[0] = OBJ_VNUM_SEVERED_HEAD;
	    vnum[1] = OBJ_VNUM_EAR;
	} else if (IS_SET(victim->parts, PART_HEAD)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg = "Your thrust separates $N's neck from his head.";
	    msg2 = "$n's thrust separates $S neck from $S head!";
	    msg3 = "$n's thrust takes $N's head, from $M neck.";
	    vnum[0] = OBJ_VNUM_SEVERED_HEAD;
	} else {
	    msg =
		"You knock $N's head off! $S head plops onto the ground.";
	    msg2 =
		"$n knocks your head off! Your head plops onto the ground.";
	    msg3 =
		"$n knocks $N's head off! $S head plops onto the ground.";
	    vnum[0] = OBJ_VNUM_SEVERED_HEAD;
	    vnum[1] = OBJ_VNUM_EYE;
	}

	break;

    case 4:
	if (IS_SET(victim->parts, PART_HEART)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"Your intricate swordwork cuts $N's heart from $S chest.";
	    msg2 = "$n sword cuts your heart from your chest!";
	    msg3 = "$n cuts $N's heart from $S chest.";
	    vnum[0] = OBJ_VNUM_TORN_HEART;
	} else if (IS_SET(victim->parts, PART_HEART)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg =
		"You plunge your dagger deep into $N's heart, extinguishing $S life.";
	    msg2 =
		"$n pokes $s dagger into your chest, penetrating your heart!";
	    msg3 = "$n stabs $s dagger deep into $N's chest!";
	} else if (IS_SET(victim->parts, PART_HEART)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg = "Your axe tears $N's heart and entrails from $S torso.";
	    msg2 = "$n tears your guts from your torso!";
	    msg3 = "$n tears $N's heart and entrails from $S torso.";
	    vnum[0] = OBJ_VNUM_TORN_HEART;
	    vnum[1] = OBJ_VNUM_GUTS;
	} else if (IS_SET(victim->parts, PART_HEART)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg =
		"You send your whip into $N's chest and tear out $S heart.";
	    msg2 = "$n tears your heart from your chest!";
	    msg3 = "$n's tears into $N's chest, tearing out $S heart.";
	    vnum[0] = OBJ_VNUM_TORN_HEART;
	} else if (IS_SET(victim->parts, PART_HEART)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg = "You hack $N's insides from $S torso.";
	    msg2 = "$n hacks your heart and entrails from your torso!";
	    msg3 =
		"$n's polearm hacks $N's heart and entrails from $S torso.";
	    vnum[0] = OBJ_VNUM_GUTS;
	    vnum[1] = OBJ_VNUM_TORN_HEART;
	} else if (IS_SET(victim->parts, PART_HEART)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg =
		"Using labyrinthine thrusts, you remove $N's heart from $S torso.";
	    msg2 =
		"$n removes your heart from your chest with a series of complex thrusts!";
	    msg3 =
		"$n removes $N's heart from $S chest after a series of complex thrusts.";
	    vnum[0] = OBJ_VNUM_TORN_HEART;
	} else {
	    msg =
		"You tear $N's heart from $S chest and crush it in your hand.";
	    msg2 =
		"$n tears your heart from your chest and crushes it in $s hand!";
	    msg3 =
		"$n tears $N's heart from $S chest and crushes it in $s hand.";
	    vnum[0] = OBJ_VNUM_TORN_HEART;
	}
	break;

    case 5:
	if (IS_SET(victim->parts, PART_ARMS)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"Savagely, you slice $N's arm and watch it fall from $S corpse.";
	    msg2 = "Savagely, $n slices your arm off!";
	    msg3 = "Savagely, $n cuts $N's arm off.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	} else if (IS_SET(victim->parts, PART_ARMS)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg =
		"Savagely, you cut into some of $N's fingers as $S raises his arm in defense.";
	    msg2 =
		"Raising your hand in defense $n cuts into some of your fingers!";
	    msg3 =
		"$N raises $S arm in defense, $n cuts into some of $S fingers.";
	} else if (IS_SET(victim->parts, PART_ARMS)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg = "Savagely, you hack $N's arm off!";
	    msg2 = "Savagely, $n hacks your arm off!";
	    msg3 = "Savagely, $n hacks $N's arm off.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	} else if (IS_SET(victim->parts, PART_ARMS)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg =
		"Savagely, you rip $N's arm from $S torso off with your whip.";
	    msg2 = "Savagely, $n rips your arm off with $s whip!";
	    msg3 = "Savagely, $n rips $N's arm off with $s whip.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	} else if (IS_SET(victim->parts, PART_ARMS)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg = "Savagely, you separate $N's arm from $S torso.";
	    msg2 = "Savagely, $n separates your arm from your torso!";
	    msg3 = "Savagely, $n separates $N's arm from his torso.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	} else if (IS_SET(victim->parts, PART_ARMS)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg =
		"Savagely, you thrust your spear between $N's arm and $S torso.";
	    msg2 =
		"Savagely, $n thrusts {s spear between your arm and torso!";
	    msg3 =
		"Savagely, $n thrusts {s spear between $N's arm and $S torso.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	} else {
	    msg = "Savagely, you rip $N's arm from $S corpse.";
	    msg2 = "Savagely, $n rips your arm off!";
	    msg3 = "Savagely, $n rips $N's arm off.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	}
	break;

    case 6:
	if (IS_SET(victim->parts, PART_LEGS)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg = "You slice $N's leg off with your sword.";
	    msg2 = "$n slices your leg off with $s sword!";
	    msg3 = "$n slices $N's leg with $s sword.";
	    vnum[0] = OBJ_VNUM_SLICED_LEG;
	} else if (IS_SET(victim->parts, PART_LEGS)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg = "You stab at $N's legs as $E dies.";
	    msg2 = "$n stabs into your legs with $s dagger!";
	    msg3 = "$n stabs into $N's legs with $s dagger as $N dies.";
	} else if (IS_SET(victim->parts, PART_LEGS)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg = "You hack both of $N's legs off with your axe!";
	    msg2 = "$n hacks your legs off with $s axe!";
	    msg3 = "$n hacks $N's legs off with $s axe.";
	    vnum[0] = OBJ_VNUM_SLICED_LEG;
	    vnum[1] = OBJ_VNUM_SLICED_LEG;
	} else if (IS_SET(victim->parts, PART_LEGS)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg = "You wrap your whip around $N's leg, and rip it off!";
	    msg2 = "$n wraps his whip around your leg and rips it off!";
	    msg3 = "$n wraps $s whip around $N's leg, ripping it off.";
	    vnum[0] = OBJ_VNUM_SLICED_LEG;
	} else if (IS_SET(victim->parts, PART_LEGS)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg =
		"Your sweeping polearm takes $N's legs from $S fresh corpse.";
	    msg2 = "$n hacks your legs from your body!";
	    msg3 = "$n's polearm hacks $N's leg from $S body.";
	    vnum[0] = OBJ_VNUM_SLICED_LEG;
	    vnum[1] = OBJ_VNUM_SLICED_LEG;
	} else if (IS_SET(victim->parts, PART_LEGS)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg = "Your thrust snaps $N's leg off.";
	    msg2 = "$n snaps your leg off with $s spear!";
	    msg3 = "$n spear separates $N's leg from $S body.";
	    vnum[0] = OBJ_VNUM_SLICED_LEG;
	} else {
	    msg = "You knock $N's leg off and stuff it down $S throat.";
	    msg2 =
		"$n knocks your leg off and stuffs it down your throat!";
	    msg3 = "$n knocks $N's leg off and stuffs it down $S throat.";
	    vnum[0] = OBJ_VNUM_SLICED_LEG;
	}
	break;

    case 7:
	if (IS_SET(victim->parts, PART_BRAINS)
	    && get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"Your slice cuts $N's head wide open, and $S brains spill out.";
	    msg2 =
		"$n's slice splits your head wide open, and your brains spill out!";
	    msg3 =
		"$n's slice splits $N's head wide open, and $S brains spill out.";
	    vnum[0] = OBJ_VNUM_BRAINS;
	} else if (IS_SET(victim->parts, PART_BRAINS)
		   && get_weapon_sn(ch) == gsn_dagger) {
	    msg =
		"Your stab cracks $N's head wide open, and $S brains spill out.";
	    msg2 =
		"$n's stab cracks your head wide open, and your brains spill out!";
	    msg3 =
		"$n's stab cracks $N's head wide open, and $S brains spill out.";
	    vnum[0] = OBJ_VNUM_BRAINS;
	} else if (IS_SET(victim->parts, PART_BRAINS)
		   && get_weapon_sn(ch) == gsn_axe) {
	    msg = "Your hack splits $N's head wide open.";
	    msg2 = "$n's hack splits your head wide open!";
	    msg3 = "$n's hack splits $N's head wide open.";
	    vnum[0] = OBJ_VNUM_EYE;
	    vnum[1] = OBJ_VNUM_EAR;
	    vnum[2] = OBJ_VNUM_BRAINS;
	} else if (IS_SET(victim->parts, PART_BRAINS)
		   && get_weapon_sn(ch) == gsn_whip) {
	    msg =
		"Your whip splits $N's head wide open, and $S brains spill out.";
	    msg2 =
		"$n's whip splits your head wide open, and your brains spill out!";
	    msg3 =
		"$n's whip splits $N's head wide open, and $S brains spill out.";
	    vnum[0] = OBJ_VNUM_BRAINS;
	} else if (IS_SET(victim->parts, PART_BRAINS)
		   && get_weapon_sn(ch) == gsn_polearm) {
	    msg = "Your slice splits $N's head wide open.";
	    msg2 = "$n's blow splits your head wide open!";
	    msg3 = "$n's polearm splits $N's head wide open.";
	    vnum[0] = OBJ_VNUM_EYE;
	    vnum[1] = OBJ_VNUM_BRAINS;
	} else if (IS_SET(victim->parts, PART_BRAINS)
		   && get_weapon_sn(ch) == gsn_spear) {
	    msg = "Your thrust takes off the top of $N's head.";
	    msg2 = "$n's thrust take off the top of your head!";
	    msg3 = "$n's thrust takes off the top of $N's head.";
	    vnum[0] = OBJ_VNUM_BRAINS;
	} else {
	    msg =
		"Your blow splits $N's head wide open, and $S brains spill out.";
	    msg2 =
		"$n's blow splits your head wide open, and your brains spill out!";
	    msg3 =
		"$n's blow splits $N's head wide open, and $S brains spill out.";
	    vnum[0] = OBJ_VNUM_BRAINS;
	}
	break;

    case 8:
	if (get_weapon_sn(ch) == gsn_sword) {
	    msg =
		"Dropping to a crouch, you drive your blade upward, impaling $N.";
	    msg2 =
		"Dropping to a crouch, $n drives $s blade upward, impaling you!";
	    msg3 =
		"Dropping to a crouch, $n drives $s blade upward, impaling $N.";
	} else if (get_weapon_sn(ch) == gsn_dagger) {
	    msg =
		"Dropping to a crouch, you drive your dagger up into $N.";
	    msg2 =
		"Dropping to a crouch, $n drives $s dagger deep into you!";
	    msg3 = "Dropping to a crouch, $n drives $s dagger into $N.";
	} else if (get_weapon_sn(ch) == gsn_axe) {
	    msg =
		"Dropping to a crouch, your axe sends parts of $N everywhere.";
	    msg2 =
		"Dropping to a crouch, $n sends parts of you everywhere!";
	    msg3 =
		"Dropping to a crouch, $n sends parts of $N everywhere.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	    vnum[1] = OBJ_VNUM_EAR;
	    vnum[2] = OBJ_VNUM_BRAINS;
	    vnum[3] = OBJ_VNUM_SLICED_LEG;
	} else if (get_weapon_sn(ch) == gsn_whip) {
	    msg = "Backing up, you strink deep into $N.";
	    msg2 = "Backing up, $n strikes $s whip deep into you!";
	    msg3 = "Backing up, $n strikes his whip deep into $N.";
	} else if (get_weapon_sn(ch) == gsn_polearm) {
	    msg =
		"Dropping to a crouch, your polearm send parts of $N everywhere.";
	    msg2 =
		"Dropping to a crouch, $n sends parts of you everywhere!";
	    msg3 =
		"Dropping to a crouch, $n sends parts of $N everywhere.";
	    vnum[0] = OBJ_VNUM_SLICED_ARM;
	    vnum[1] = OBJ_VNUM_EYE;
	    vnum[2] = OBJ_VNUM_SEVERED_HEAD;
	    vnum[3] = OBJ_VNUM_SLICED_LEG;
	} else if (get_weapon_sn(ch) == gsn_spear) {
	    msg =
		"Dropping to a crouch, you drive your spear upward, impaling $N.";
	    msg2 =
		"Dropping to a crouch, $n drives $s spear upward, impaling you!";
	    msg3 =
		"Dropping to a crouch, $n drives $s spear upward, impaling $N.";
	} else {
	    msg = "Dropping to a crouch, you swing upward, destroying $N.";
	    msg2 =
		"Dropping to a crouch, $n swings upward, destroying you!";
	    msg3 =
		"Dropping to a crouch, $n swings upward, destroying $N.";
	    vnum[0] = OBJ_VNUM_EAR;
	    vnum[1] = OBJ_VNUM_EYE;
	    vnum[2] = OBJ_VNUM_SEVERED_HEAD;
	    vnum[3] = OBJ_VNUM_SLICED_LEG;
	}

	break;
    }

    if (!IS_NPC(victim) && victim->pcdata->bounty > 0) {
	msg =
	    "You smash $N's head off! $S head plops onto the ground...perhaps there's a reward.";
	msg2 =
	    "$n smashes your head off! Your head plops onto the ground.";
	msg3 = "$n smashes $N's head off! $S head plops onto the ground.";
	vnum[0] = OBJ_VNUM_SEVERED_HEAD;
    }
    act_new(msg, ch, NULL, victim, TO_CHAR, POS_RESTING);	/* Only to Killer */
    act_new(msg2, ch, NULL, victim, TO_VICT, POS_DEAD);	/* Only to victim */
    act_new(msg3, ch, NULL, victim, TO_NOTVICT, POS_RESTING);	/* Everyone else  */


    for (i = 0; i < 4; i++) {
	if (vnum[i] != 0) {
	    EXTRA_DESCR_DATA *ed;
	    OBJ_DATA *obj;
	    char *name;

	    name = IS_NPC(victim) ? victim->short_descr : victim->name;
	    obj = create_object(get_obj_index(vnum[i]), 0);

	    if (!IS_NPC(victim) && victim->pcdata->bounty > 0)
		obj->timer = 0;
	    else
		obj->timer = number_range(10, 20);

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

	    if (!IS_NPC(victim) && victim->pcdata->bounty > 0) {
		sprintf(buf,
			"{MTake this to %s and get a bounty of %d gold!{x\n\r",
			victim->pcdata->bountier, victim->pcdata->bounty);

		ed = new_extra_descr();

		ed->keyword = str_dup("head");
		ed->description = str_dup(buf);
		ed->next = obj->extra_descr;
		obj->extra_descr = ed;

		victim->pcdata->bounty = 0;
		free_string(victim->pcdata->bountier);
		victim->pcdata->bountier = str_dup("");
	    }

	    if (obj->item_type == ITEM_FOOD) {
		if (IS_SET(victim->form, FORM_POISON))
		    obj->value[3] = 1;
		else if (!IS_SET(ch->form, FORM_EDIBLE))
		    obj->item_type = ITEM_TRASH;
	    }

	    if (obj->item_type == ITEM_PILL)
		obj->value[0] = (obj->level / 2) + 1;

	    obj_to_room(obj, victim->in_room);
	}
    }

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

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

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

    ch->in_room = was_in_room;

    buf[0] = '\0';
    return;
}

void raw_kill(CHAR_DATA * ch, CHAR_DATA * victim)
{
    char buf4[MSL];

    stop_fighting(victim, TRUE);

    if (IS_NPC(victim) && HAS_TRIGGER(victim, TRIG_DEATH)) {
	victim->position = POS_STANDING;
	mp_percent_trigger(victim, ch, NULL, NULL, TRIG_DEATH);
    }
    death_cry(ch, victim);

    // fake death in the arena, no corpse, no pain
    if (victim->arena == global_last_arena_id && ch->arena) {
	stop_fighting(ch, FALSE);
	stop_fighting(victim, FALSE);
	sprintf(buf4,
		"{c[{RARENA OF DEATH{c] %s just killed %s in the arena!{x",
		ch->name, victim->name);
	announce(buf4, ch);
	arena_death(victim);

	return;
    }


    /* For the Announce Channel */

    if (!IS_NPC(victim)) {
	DESCRIPTOR_DATA *d;

	for (d = descriptor_list; d != NULL; d = d->next) {
	    CHAR_DATA *wch;

	    wch = d->original ? d->original : d->character;

	    if (d->connected == CON_PLAYING
		&& d->character != ch
		&& d->character != victim
		&& IS_SET(wch->comm, COMM_ANNOUNCE)
		&& !IS_SET(wch->comm, COMM_QUIET)) {
		sprintf(log_buf,
			"{c[{RK{rI{RL{rL{RE{rD{c] %s forces $n into Death's willing embrace!{x",
			capitalize(PERS(ch, d->character)));

		act_new(log_buf, victim, NULL, d->character, TO_VICT,
			POS_DEAD);
	    }
	}
    }

    make_corpse(victim, IS_NPC(ch) ? FALSE : TRUE);
    death_penalty(victim);

    return;
}


void kill_self(CHAR_DATA * ch)
{
    ROOM_INDEX_DATA *was_in_room;
    char *msg;
    int door;

    stop_fighting(ch, TRUE);

    send_to_char("{RYou have DIED!!{x\n\r\n\r", ch);

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

    was_in_room = ch->in_room;

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

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

    ch->in_room = was_in_room;

    /* For the Announce Channel */

    if (!IS_NPC(ch)) {
	DESCRIPTOR_DATA *d;

	for (d = descriptor_list; d != NULL; d = d->next) {
	    CHAR_DATA *wch;

	    wch = d->original ? d->original : d->character;

	    if (d->connected == CON_PLAYING
		&& d->character != ch && IS_SET(wch->comm, COMM_ANNOUNCE)
		&& !IS_SET(wch->comm, COMM_QUIET)) {
		act_new("{c[{RANNOUNCE{c] $n has killed $mself!{x", ch,
			NULL, d->character, TO_VICT, POS_DEAD);
	    }
	}
    }

    make_corpse(ch, FALSE);
    death_penalty(ch);

    return;
}


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


    if (ch == victim)
	kill_self(victim);
    else {
	create_blood_pool(victim);
	raw_kill(ch, victim);
	send_to_char
	    ("\n{R{*Ow! Ow! Ow! Ow! Ow! That SUCKED! You're dead. :({x\n\r\n\r",
	     victim);
    }

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

    if (!victim->no_exp)
	turf_mod(ch, victim);

    members = 0;
    group_levels = 0;
    high_level = 0;
    for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) {
	if (is_same_group(gch, ch)) {
	    members++;
	    group_levels += gch->level;

	    if (gch->level > high_level)
		high_level = gch->level;
	}
    }

    if (members == 0) {
	bug("Group_gain: members.", members);
	members = 1;
	group_levels = ch->level;
    }

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

    for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) {
	if (!is_same_group(gch, ch) || IS_NPC(gch))
	    continue;

	xp = (xp_compute(gch, victim, high_level));

	xp = xp / members;

	if ((ch->desc && victim->desc)
	    && (!str_cmp(victim->desc->host, ch->desc->host))) {
	    send_to_char
		("Cheat attempt logged, no experience for you!\r\n", ch);
	    return;
	}
	// to stop guardian/summon farming.
	if (victim->no_exp)
	    xp = 0;

	sprintf(buf, "{RYou receive %d experience points.{x\n\r", xp);
	send_to_char(buf, gch);
	gain_exp(gch, xp);

	if (!IS_NPC(gch) && !IS_NPC(victim))
	    ++gch->pcdata->kills;

	/* Now for the poor PKillers who lost */
	if (!IS_NPC(gch) && !IS_NPC(victim)) {
	    gain_exp(victim, xp * -1);

	    if (IS_SET(victim->act, PLR_PKILL))	/* No longer a PKILLER */
		REMOVE_BIT(victim->act, PLR_PKILL);

	    sprintf(buf, "{RYou lose %d experience points.{x\n\r", xp);
	    send_to_char(buf, victim);
	}
    }

    return;
}



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

    level_range = victim->level - total_levels;

    //    exp = 0;
    /* compute the base exp */
    switch (level_range) {
    default:
	base_exp = 0;
	break;
    case -9:
	base_exp = 5;
	break;
    case -8:
	base_exp = 7;
	break;
    case -7:
	base_exp = 9;
	break;
    case -6:
	base_exp = 11;
	break;
    case -5:
	base_exp = 13;
	break;
    case -4:
	base_exp = 17;
	break;
    case -3:
	base_exp = 35;
	break;
    case -2:
	base_exp = 45;
	break;
    case -1:
	base_exp = 55;
	break;
    case 0:
	base_exp = 100;
	break;
    case 1:
	base_exp = 115;
	break;
    case 2:
	base_exp = 120;
	break;
    case 3:
	base_exp = 125;
	break;
    case 4:
	base_exp = 130;
	break;
    case 5:
	base_exp = 135;
	break;
    case 6:
	base_exp = 140;
	break;
    case 7:
	base_exp = 145;
	break;
    case 8:
	base_exp = 150;
	break;
    case 9:
	base_exp = 155;
	break;
    case 10:
	base_exp = 160;
	break;
    case 11:
	base_exp = 165;
	break;
    case 12:
	base_exp = 170;
	break;
    case 13:
	base_exp = 175;
	break;
    case 14:
	base_exp = 180;
	break;
    case 15:
	base_exp = 185;
	break;
    case 16:
	base_exp = 190;
	break;

    case 17:
	base_exp = 195;
	break;

    case 18:
	base_exp = 200;
	break;
    case 19:
	base_exp = 205;
	break;
    case 20:
	base_exp = 215;
	break;
    case 21:
	base_exp = 225;
	break;
    case 22:
	base_exp = 235;
	break;
    case 23:
	base_exp = 245;
	break;
    case 24:
	base_exp = 255;
	break;
    case 25:
	base_exp = 265;
	break;
    case 26:
	base_exp = 275;
	break;
    case 27:
	base_exp = 285;
	break;
    case 28:
	base_exp = 295;
	break;
    case 29:
	base_exp = 305;
	break;
    case 30:
	base_exp = 315;
	break;
    case 31:
	base_exp = 325;
	break;
    case 32:
	base_exp = 335;
	break;
    case 33:
	base_exp = 345;
	break;
    case 34:
	base_exp = 355;
	break;
    case 35:
	base_exp = 365;
	break;
    case 36:
	base_exp = 375;
	break;
    case 37:
	base_exp = 385;
	break;
    case 38:
	base_exp = 395;
	break;
    case 39:
	base_exp = 405;
	break;
    case 40:
	base_exp = 415;
	break;
    }

    if (level_range > 40) {
	base_exp = 450;
    }


    xp = base_exp;


	/***********************************************************
	*  checks for remort					   *
	***********************************************************/
    xp = (xp / (gch->remorts + 1));



    if (xp < 0) {
	xp = 0;
    }

    /* randomize the rewards */
    xp = number_range(xp * 4 / 5, xp * 5 / 4);

    if (gch->level < 10)
	xp = xp * 4;
    if (gch->level < 20 && gch->level >= 10)
	xp = xp * 3;
    if (gch->level < 30 && gch->level >= 20)
	xp = xp * 2;
/*	if (victim->alignment > 0)
		gch->alignment -= base_align;
	if (gch->alignment < -1000)
		gch->alignment = -1000;
					
	else
		gch->alignment += base_align;
		if (gch->alignment > 1000)
			gch->alignment = 1000;*/

    if (xp > 450)
	xp = 450;

    return xp;
}


void
dam_message(CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt,
	    bool immune)
{
    char buf1[256], buf2[256], buf3[256], buf4[256];
    char cdam[256], vdam[256], selfdam[256];

    const char *vs;
    const char *vp;
    const char *attack;
    char punct;

    if (ch == NULL || victim == NULL)
	return;

    if (dam == 0) {
	vs = "{Wmiss{x";
	vp = "{Wmisses{x";
    } else if (dam <= 4) {
	vs = "{Cscratch{x";
	vp = "{Cscratches{x";
    } else if (dam <= 8) {
	vs = "{Cgraze{x";
	vp = "{Cgrazes{x";
    } else if (dam <= 12) {
	vs = "{Chit{x";
	vp = "{Chits{x";
    } else if (dam <= 16) {
	vs = "{Rinjure{x";
	vp = "{Rinjures{x";
    } else if (dam <= 22) {
	vs = "{Rwound{x";
	vp = "{Rwounds{x";
    } else if (dam <= 29) {
	vs = "{Rmaul{x";
	vp = "{Rmauls{x";
    } else if (dam <= 36) {
	vs = "{Ydecimate{x";
	vp = "{Ydecimates{x";
    } else if (dam <= 43) {
	vs = "{Ydevastate{x";
	vp = "{Ydevastates{x";
    } else if (dam <= 50) {
	vs = "{Ymaim{x";
	vp = "{Ymaims{x";
    } else if (dam <= 59) {
	vs = "{GMUTILATE{x";
	vp = "{GMUTILATES{x";
    } else if (dam <= 72) {
	vs = "{GDISEMBOWEL{x";
	vp = "{GDISEMBOWELS{x";
    } else if (dam <= 88) {
	vs = "{GDISMEMBER{x";
	vp = "{GDISMEMBERS{x";
    } else if (dam <= 105) {
	vs = "{MMASSACRE{x";
	vp = "{MMASSACRES{x";
    } else if (dam <= 125) {
	vs = "{MMANGLE{x";
	vp = "{MMANGLES{x";
    } else if (dam <= 150) {
	vs = "{M*** DEMOLISH ***{x";
	vp = "{M*** DEMOLISHES ***{x";
    } else if (dam <= 175) {
	vs = "{m*** DEVASTATE ***{x";
	vp = "{M*** DEVASTATES ***{x";
    } else if (dam <= 245) {
	vs = "{M=== OBLITERATE ==={x";
	vp = "{M=== OBLITERATES ==={x";
    } else if (dam <= 350) {
	vs = "{M>>> ANNIHILATE <<<{x";
	vp = "{M>>> ANNIHILATES <<<{x";
    } else if (dam <= 550) {
	vs = "{M<<< ERADICATE >>>{x";
	vp = "{M<<< ERADICATES >>>{x";
    } else if (dam <= 850) {
	vs = "{M<<< LIQUIDATE >>>{x";
	vp = "{M<<< LIQUIDATES >>>{x";
    } else {
	vs = "{Ydo {RUNSPEAKABLE {Ythings to{x";
	vp = "{Ydoes {RUNSPEAKABLE {Ythings to{x";
    }

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

    if (IS_SET(ch->act, PLR_AUTODAMAGE)) {
	sprintf(cdam, " {W[{C%d{W]", dam);
	sprintf(selfdam, " {W[{R%d{W]", dam);
    } else {
	cdam[0] = '\0';
	selfdam[0] = '\0';
    }

    if (IS_SET(victim->act, PLR_AUTODAMAGE))
	sprintf(vdam, " {W[{R%d{W]", dam);
    else
	vdam[0] = '\0';

    if (dt == TYPE_HIT) {
	if (ch == victim) {
	    sprintf(buf1, "$n %s $melf%c", vp, punct);
	    sprintf(buf2, "You %s yourself%c%s{x", vs, punct, selfdam);
	} else {
	    sprintf(buf1, "$n %s $N%c", vp, punct);
	    sprintf(buf2, "{gYou %s{g $N%c%s{x", vs, punct, cdam);
	    sprintf(buf3, "{g$n %s{g you%c%s{x", vp, punct, vdam);
	}
    } else {
	if (dt >= 0 && dt < MAX_SKILL)
	    attack = skill_table[dt].noun_damage;
	else if (dt >= TYPE_HIT && dt < TYPE_HIT + MAX_DAMAGE_MESSAGE)
	    attack = attack_table[dt - TYPE_HIT].noun;
	else {
	    bug("Dam_message: bad dt %d.", dt);
	    sprintf(buf4, "char: did it! %s target was %s", ch->name,
		    victim->name);
	    bug(buf4, 0);
	    dt = TYPE_HIT;
	    attack = attack_table[0].name;
	}

	if (immune) {
	    if (ch == victim) {
		sprintf(buf1, "$n is unaffected by $s own %s.", attack);
		sprintf(buf2, "Luckily, you are immune to that.");
	    } else {
		sprintf(buf1, "$N is unaffected by $n's %s!", attack);
		sprintf(buf2, "{G$N is unaffected by your %s!{x", attack);
		sprintf(buf3, "{G$n's %s is powerless against you.{x",
			attack);
	    }
	} else {
	    if (ch == victim) {
		sprintf(buf1, "$n's %s %s $m%c", attack, vp, punct);
		sprintf(buf2, "Your %s %s you%c%s{x", attack, vp, punct,
			selfdam);
	    } else {
		sprintf(buf1, "$n's %s %s $N%c", attack, vp, punct);
		sprintf(buf2, "{gYour %s %s{g $N%c%s{x", attack, vp, punct,
			cdam);
		sprintf(buf3, "{g$n's %s %s{g you%c%s{x", attack, vp,
			punct, vdam);
	    }
	}
    }

    if (ch == victim) {
	act(buf1, ch, NULL, NULL, TO_ROOM);
	act(buf2, ch, NULL, NULL, TO_CHAR);
    } else {
	act(buf1, ch, NULL, victim, TO_NOTVICT);
	act(buf2, ch, NULL, victim, TO_CHAR);
	act(buf3, ch, NULL, victim, TO_VICT);
    }

    return;
}



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

    if ((obj = get_eq_char(victim, WEAR_WIELD)) == NULL)
	return;

    if (IS_OBJ_STAT(obj, ITEM_NOREMOVE)) {
	act("$S weapon won't budge!", ch, NULL, victim, TO_CHAR);
	act("$n tries to disarm you, but your weapon won't budge!",
	    ch, NULL, victim, TO_VICT);
	act("$n tries to disarm $N, but fails.", ch, NULL, victim,
	    TO_NOTVICT);
	return;
    }
    if (IS_AFFECTED(victim, AFF_TALON)) {
	act("$S weapon sticks to $M like glue!", ch, NULL, victim,
	    TO_CHAR);
	act("$n tries to disarm you, but your weapon sticks like glue!",
	    ch, NULL, victim, TO_VICT);
	act("$n tries to disarm $N, but $N's weapon sticks to $M like glue.", ch, NULL, victim, TO_NOTVICT);
	return;
    }
    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're disarming the displaced version
	    send_to_char("Your aim goes right through the weapon...\n\r",
			 ch);
	    displaced = TRUE;
	    return;
	}
    act("{M$n {YDISARMS {Myou and sends your weapon flying!{x",
	ch, NULL, victim, TO_VICT);
    act("You disarm $N!", ch, NULL, victim, TO_CHAR);
    act("$n disarms $N!", ch, NULL, victim, TO_NOTVICT);

    obj_from_char(obj);
    if (IS_OBJ_STAT(obj, ITEM_NODROP) || IS_OBJ_STAT(obj, ITEM_INVENTORY))
	obj_to_char(obj, victim);
    else {
	obj_to_room(obj, victim->in_room);
	if (IS_NPC(victim) && victim->wait == 0
	    && can_see_obj(victim, obj))
	    get_obj(victim, obj, NULL);
    }
    return;
}

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

    if ((chance = get_skill(ch, gsn_berserk)) == 0
	|| (IS_NPC(ch) && !IS_SET(ch->off_flags, OFF_BERSERK))
	|| (!IS_NPC(ch)
	    && ch->level <
	    skill_table[gsn_berserk].skill_level[ch->class])) {
	send_to_char("You turn red in the face, but nothing happens.\n\r",
		     ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_BERSERK) || is_affected(ch, gsn_berserk)
	|| is_affected(ch, skill_lookup("frenzy"))) {
	send_to_char("You get a little madder.\n\r", ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_CALM)) {
	send_to_char("You're feeling to mellow to berserk.\n\r", ch);
	return;
    }
    if (ch->mana < 50) {
	send_to_char("You can't get up enough energy.\n\r", ch);
	return;
    }
    /* modifiers */

    /* fighting */
    if (ch->position == POS_FIGHTING)
	chance += 10;

    /* damage -- below 50% of hp helps, above hurts */
    hp_percent = 100 * ch->hit / ch->max_hit;
    chance += 25 - hp_percent / 2;

    if (number_percent() < chance) {
	AFFECT_DATA af;

	if (ch->level < 300)
	    WAIT_STATE(ch, 12);
	ch->mana -= 50;
	ch->move /= 2;

	/* heal a little damage */
	ch->hit += ch->level * 2;
	ch->hit = UMIN(ch->hit, ch->max_hit);

	send_to_char("Your pulse races as you are consumed by rage!\n\r",
		     ch);
	act("$n gets a wild look in $s eyes.", ch, NULL, NULL, TO_ROOM);
	check_improve(ch, gsn_berserk, TRUE, 2);

	af.where = TO_AFFECTS;
	af.type = gsn_berserk;
	af.level = ch->level;
	af.duration = number_fuzzy(ch->level / 8);
	af.modifier = UMAX(1, ch->level / 5);
	af.bitvector = AFF_BERSERK;

	af.location = APPLY_HITROLL;
	affect_to_char(ch, &af);

	af.location = APPLY_DAMROLL;
	affect_to_char(ch, &af);

	af.modifier = UMAX(10, 10 * (ch->level / 5));
	af.location = APPLY_AC;
	affect_to_char(ch, &af);
    } else {
	if (ch->level < 300)
	    WAIT_STATE(ch, 36);
	ch->mana -= 25;
	ch->move /= 2;

	send_to_char("Your pulse speeds up, but nothing happens.\n\r", ch);
	check_improve(ch, gsn_berserk, FALSE, 2);
    }
}

void do_bash(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell

    one_argument(argument, arg);

    if ((chance = get_skill(ch, gsn_bash)) == 0
	|| (IS_NPC(ch) && !IS_SET(ch->off_flags, OFF_BASH))
	|| (!IS_NPC(ch)
	    && ch->level < skill_table[gsn_bash].skill_level[ch->class])) {
	send_to_char("Bashing? What's that?\n\r", ch);
	return;
    }
    if (arg[0] == '\0') {
	victim = ch->fighting;
	if (victim == NULL) {
	    send_to_char("But you aren't fighting anyone!\n\r", ch);
	    return;
	}
    } else if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }
    if (victim->position < POS_FIGHTING) {
	act("You'll have to let $M get back up first.", ch, NULL, victim,
	    TO_CHAR);
	return;
    }
    if (victim == ch) {
	send_to_char("You try to bash your brains out, but fail.\n\r", ch);
	return;
    }
    if (is_safe(ch, victim))
	return;
    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_NPC(victim) &&
	victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) {
	act("But $N is your friend!", ch, NULL, victim, TO_CHAR);
	return;
    }
    /* modifiers */

    /* size  and weight */
    chance += ch->carry_weight / 250;
    chance -= victim->carry_weight / 200;

    if (ch->size < victim->size)
	chance += (ch->size - victim->size) * 15;
    else
	chance += (ch->size - victim->size) * 10;


    /* stats */
    chance += get_curr_stat(ch, STAT_STR);
    chance -= (get_curr_stat(victim, STAT_DEX) * 4) / 3;
    chance -= GET_AC(victim, AC_BASH) / 25;
    /* speed */
    if (IS_SET(ch->off_flags, OFF_FAST) || IS_AFFECTED(ch, AFF_HASTE))
	chance += 10;
    if (IS_SET(victim->off_flags, OFF_FAST)
	|| IS_AFFECTED(victim, AFF_HASTE))
	chance -= 30;

    /* level */
    /*chance += (ch->level - victim->level); */

    if (!IS_NPC(victim) && chance < get_skill(victim, gsn_dodge)) {	/*
									   act("$n tries to bash you, but you dodge it.",ch,NULL,victim,TO_VICT);
									   act("$N dodges your bash, you fall flat on your face.",ch,NULL,victim,TO_CHAR);
									   WAIT_STATE(ch,skill_table[gsn_bash].beats);
									   return; */
	chance -= 3 * (get_skill(victim, gsn_dodge) - chance);
    }
    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're bashing the displaced version
	    send_to_char("You charge and... fly through him...\n\r", ch);
	    chance = 0;
	    displaced = TRUE;
	}

    /* now the attack */
    if (number_percent() < chance) {

	act("$n sends you sprawling with a powerful bash!",
	    ch, NULL, victim, TO_VICT);
	act("You slam into $N, and send $M flying!", ch, NULL, victim,
	    TO_CHAR);
	act("$n sends $N sprawling with a powerful bash.", ch, NULL,
	    victim, TO_NOTVICT);
	check_improve(ch, gsn_bash, TRUE, 1);

	DAZE_STATE(victim, PULSE_VIOLENCE);
	WAIT_STATE(ch, skill_table[gsn_bash].beats);
	damage(ch, victim, number_range(2, 2 + 2 * ch->size + chance / 20),
	       gsn_bash, DAM_BASH, TRUE);

    } else {
	damage(ch, victim, 0, gsn_bash, DAM_BASH, FALSE);
	act("You fall flat on your face!", ch, NULL, victim, TO_CHAR);
	act("$n falls flat on $s face.", ch, NULL, victim, TO_NOTVICT);
	act("You evade $n's bash, causing $m to fall flat on $s face.",
	    ch, NULL, victim, TO_VICT);
	check_improve(ch, gsn_bash, FALSE, 1);
	WAIT_STATE(ch, skill_table[gsn_bash].beats * 3 / 2);
    }
    check_killer(ch, victim);
}

void do_dirt(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell

    one_argument(argument, arg);

    if ((chance = get_skill(ch, gsn_dirt)) == 0 || (!IS_NPC(ch)
						    && ch->level <
						    skill_table[gsn_dirt].
						    skill_level[ch->
								class])) {
	send_to_char("You get your feet dirty.\n\r", ch);
	return;
    }

    if (arg[0] == '\0') {
	victim = ch->fighting;
	if (victim == NULL) {
	    send_to_char("But you aren't in combat!\n\r", ch);
	    return;
	}
    } else if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }

    if (IS_AFFECTED(victim, AFF_BLIND)) {
	act("$E's already been blinded.", ch, NULL, victim, TO_CHAR);
	return;
    }

    if (victim == ch) {
	send_to_char("Very funny.\n\r", ch);
	return;
    }
    if (is_safe(ch, victim))
	return;
    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_NPC(victim) &&
	victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }

    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) {
	act("But $N is such a good friend!", ch, NULL, victim, TO_CHAR);
	return;
    }
    /* modifiers */

    /* dexterity */
    chance += get_curr_stat(ch, STAT_DEX);
    chance -= 2 * get_curr_stat(victim, STAT_DEX);

    /* speed  */
    if (IS_SET(ch->off_flags, OFF_FAST) || IS_AFFECTED(ch, AFF_HASTE))
	chance += 10;
    if (IS_SET(victim->off_flags, OFF_FAST)
	|| IS_AFFECTED(victim, AFF_HASTE))
	chance -= 25;

    /* sloppy hack to prevent false zeroes */
    if (chance % 5 == 0)
	chance += 1;

    /* terrain */

    switch (ch->in_room->sector_type) {
    case (SECT_INSIDE):
	chance -= 20;
	break;
    case (SECT_CITY):
	chance -= 10;
	break;
    case (SECT_FIELD):
	chance += 5;
	break;
    case (SECT_FOREST):
	break;
    case (SECT_HILLS):
	break;
    case (SECT_MOUNTAIN):
	chance -= 10;
	break;
    case (SECT_WATER_SWIM):
	chance = 0;
	break;
    case (SECT_WATER_NOSWIM):
	chance = 0;
	break;
    case (SECT_AIR):
	chance = 0;
	break;
    case (SECT_DESERT):
	chance += 10;
	break;
    }

    if (chance == 0) {
	send_to_char("There isn't any dirt to kick.\n\r", ch);
	return;
    }
    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're throwing dirt at the displaced version
	    send_to_char("The dirt... flies through him...\n\r", ch);
	    chance = 0;
	    displaced = TRUE;
	}

    /* now the attack */
    if (number_percent() < chance) {
	AFFECT_DATA af;
	act("$n is blinded by the dirt in $s eyes!", victim, NULL, NULL,
	    TO_ROOM);
	act("$n kicks dirt in your eyes!", ch, NULL, victim, TO_VICT);
	damage(ch, victim, number_range(2, 5), gsn_dirt, DAM_NONE, FALSE);
	send_to_char("You can't see a thing!\n\r", victim);
	check_improve(ch, gsn_dirt, TRUE, 2);
	WAIT_STATE(ch, skill_table[gsn_dirt].beats);

	af.where = TO_AFFECTS;
	af.type = gsn_dirt;
	af.level = ch->level;
	af.duration = 2;
	af.location = APPLY_HITROLL;
	af.modifier = -4;
	af.bitvector = AFF_BLIND;

	affect_to_char(victim, &af);
    } else {
	damage(ch, victim, 0, gsn_dirt, DAM_NONE, TRUE);
	check_improve(ch, gsn_dirt, FALSE, 2);
	WAIT_STATE(ch, skill_table[gsn_dirt].beats);
    }
    check_killer(ch, victim);
}

void do_trip(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell

    one_argument(argument, arg);

    if ((chance = get_skill(ch, gsn_trip)) == 0
	|| (IS_NPC(ch) && (IS_AFFECTED(ch, AFF_BLIND)))
	|| (!IS_NPC(ch)
	    && ch->level < skill_table[gsn_trip].skill_level[ch->class])) {
	send_to_char("Tripping?  What's that?\n\r", ch);
	return;
    }
    if (arg[0] == '\0') {
	victim = ch->fighting;
	if (victim == NULL) {
	    send_to_char("But you aren't fighting anyone!\n\r", ch);
	    return;
	}
    } else if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }
    if (is_safe(ch, victim))
	return;
    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_NPC(victim) &&
	victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_AFFECTED(victim, AFF_FLYING)) {
	act("$S feet aren't on the ground.", ch, NULL, victim, TO_CHAR);
	return;
    }
    if (victim->position < POS_FIGHTING) {
	act("$N is already down.", ch, NULL, victim, TO_CHAR);
	return;
    }
    if (victim == ch) {
	send_to_char("You fall flat on your face!\n\r", ch);
	WAIT_STATE(ch, 2 * skill_table[gsn_trip].beats);
	act("$n trips over $s own feet!", ch, NULL, NULL, TO_ROOM);
	return;
    }
    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) {
	act("$N is your beloved master.", ch, NULL, victim, TO_CHAR);
	return;
    }
    /* modifiers */

    /* size */
    if (ch->size < victim->size)
	chance += (ch->size - victim->size) * 10;	/* bigger = harder to trip */

    /* dex */
    chance += get_curr_stat(ch, STAT_DEX);
    chance -= get_curr_stat(victim, STAT_DEX) * 3 / 2;

    /* speed */
    if (IS_SET(ch->off_flags, OFF_FAST) || IS_AFFECTED(ch, AFF_HASTE))
	chance += 10;
    if (IS_SET(victim->off_flags, OFF_FAST)
	|| IS_AFFECTED(victim, AFF_HASTE))
	chance -= 20;

    /* level */
    /*chance += (ch->level - victim->level) * 2; */

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're trying to trip the displaced version
	    send_to_char("The attempt passes through the legs...\n\r", ch);
	    chance = 0;
	    displaced = TRUE;
	}

    /* now the attack */
    if (number_percent() < chance) {
	act("$n trips you and you go down!", ch, NULL, victim, TO_VICT);
	act("You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR);
	act("$n trips $N, sending $M to the ground.", ch, NULL, victim,
	    TO_NOTVICT);
	check_improve(ch, gsn_trip, TRUE, 1);

	DAZE_STATE(victim, PULSE_VIOLENCE);
	WAIT_STATE(ch, skill_table[gsn_trip].beats);
	victim->position = POS_RESTING;
	damage(ch, victim, number_range(2, 2 + 2 * victim->size), gsn_trip,
	       DAM_BASH, TRUE);
    } else {
	damage(ch, victim, 0, gsn_trip, DAM_BASH, TRUE);
	WAIT_STATE(ch, skill_table[gsn_trip].beats * 2 / 3);
	check_improve(ch, gsn_trip, FALSE, 1);
    }
    check_killer(ch, victim);
}



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

    if (arg[0] == '\0') {
	send_to_char("Kill whom?\n\r", ch);
	return;
    }
    if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }
    if (victim == ch) {
	send_to_char("You hit yourself.  Ouch!\n\r", ch);
	multi_hit(ch, ch, TYPE_UNDEFINED);
	return;
    }
    if (is_safe(ch, victim))
	return;

    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) {
	act("$N is your beloved master.", ch, NULL, victim, TO_CHAR);
	return;
    }
    if (ch->position == POS_FIGHTING) {
	send_to_char("You do the best you can!\n\r", ch);
	return;
    }
    if (ch->level < 201)
	WAIT_STATE(ch, 12);

    if (IS_NPC(ch)) {
	mob_remember(victim, ch, MEM_HOSTILE);
    }

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



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

void do_murder(CHAR_DATA * ch, char *argument)
{
    do_kill(ch, argument);
    return;
}



void do_backstab(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
//    OBJ_DATA *obj;
    OBJ_DATA *wield;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell

    one_argument(argument, arg);

    if (!IS_NPC(ch))
	chance = (get_skill(ch, gsn_backstab));
    else
	chance = UMIN(ch->level, 100);

    if (chance <= 1) {
	send_to_char("You don't know how to backstab, silly.\r\n", ch);
	return;
    }

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

    if (ch->fighting != NULL) {
	send_to_char("You can't backstab someone you're fighting!\n\r",
		     ch);
	return;
    } else if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }

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

    if (is_safe(ch, victim))
	return;
    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_NPC(victim)
	&& victim->fighting != NULL
	&& !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }

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

    if (!IS_NPC(ch)) {
	/*Only certain weapons can be used */
	wield = get_eq_char(ch, WEAR_WIELD);
	if (wield == NULL || wield->item_type != ITEM_WEAPON) {
	    send_to_char
		("You do need to use some sort of a weapon to backstab.\n\r",
		 ch);
	    return;
	} else {
	    switch (wield->value[0]) {
	    case (WEAPON_SWORD):
		chance -= 10;
		break;
	    case (WEAPON_DAGGER):
		chance = chance;
		break;
	    case (WEAPON_SPEAR):
		send_to_char
		    ("You realy should try a different weapon next time\n\r",
		     ch);
		return;
		break;
	    case (WEAPON_MACE):
		send_to_char
		    ("How do you expect to stab someone with a mace?\n\r",
		     ch);
		return;
		break;
	    case (WEAPON_AXE):
		send_to_char("A axe blow is to slow for a backstab\n\r",
			     ch);
		return;
		break;
	    case (WEAPON_FLAIL):
		send_to_char("Flails can't be used to backstab\n\r", ch);
		return;
		break;
	    case (WEAPON_EXOTIC):
		send_to_char
		    ("Your knowledge of this weapon isn't great enough\n\r",
		     ch);
		return;
		break;
	    case (WEAPON_WHIP):
		send_to_char("It's impossible to backstab with a whip\n\r",
			     ch);
		return;
		break;
	    case (WEAPON_POLEARM):
		send_to_char("You realy should use a other weapon\n\r",
			     ch);
		return;
		break;
	    default:
		send_to_char("You realy should use a weapon with a blade",
			     ch);
		return;
		break;
	    }
	}
	check_killer(ch, victim);
    }
    WAIT_STATE(ch, skill_table[gsn_backstab].beats);

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're backstabbing the displaced version
	    send_to_char
		("The stab mysteriously goes right through the back...\n\r",
		 ch);
	    chance = 0;
	    displaced = TRUE;
	}
    if ((number_percent() <= chance) || (chance >= 2 && !IS_AWAKE(victim))) {
	check_improve(ch, gsn_backstab, TRUE, 1);
	one_hit(ch, victim, gsn_backstab);
    }

    else {
	check_improve(ch, gsn_backstab, FALSE, 1);
	damage(ch, victim, 0, gsn_backstab, DAM_NONE, TRUE);
    }

    return;
}

void do_assassinate(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell

    one_argument(argument, arg);

    if (arg[0] == '\0') {
	send_to_char("Assassinate whom?\n\r", ch);
	return;
    }
    if (ch->fighting != NULL) {
	send_to_char("It's a little too late for that now.\n\r", ch);
	return;
    }
    if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }
    if (victim == ch) {
	send_to_char("Perhaps you should try delete.\n\r", ch);
	return;
    }
    if (IS_IMMORTAL(victim) && victim->arena == FALSE) {
	send_to_char("Assassinate an immortal? Are you crazy!?\n\r", ch);
	return;
    }

    if (is_safe(ch, victim))
	return;
    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_NPC(victim) && victim->fighting != NULL) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (get_eq_char(ch, WEAR_WIELD) == NULL) {
	send_to_char("You need to wield a weapon to assassinate.\n\r", ch);
	return;
    }

    /*Assassination chance */
    chance = ((get_skill(ch, gsn_assassinate) / 3));

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

    if (IS_AFFECTED(ch, AFF_SNEAK))
	chance += 15;
    else if (get_trust(victim) < ch->invis_level
	     || IS_AFFECTED(victim, AFF_BLIND)
	     || (IS_AFFECTED(ch, AFF_INVISIBLE)
		 && !IS_AFFECTED(victim, AFF_DETECT_INVIS))
	     || (room_is_dark(victim->in_room)
		 && !IS_AFFECTED(victim, AFF_INFRARED)))
	chance += 10;

    chance = URANGE(1, chance, 1100);

    if (can_see(victim, ch))
	chance -= 50;

    if (get_skill(ch, gsn_assassinate) <= 1) {
	send_to_char("You don't know how to assassinate, silly.\r\n", ch);
	return;
    }

    check_killer(ch, victim);

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're trying to kill the displaced version
	    send_to_char("Your attempt goes right through...\n\r", ch);
	    chance = 0;
	    displaced = TRUE;
	}
    if (number_percent() <= chance) {
	act("You assassinate $N in cold blood!", ch, NULL, victim,
	    TO_CHAR);
	act("$n assassinates you in cold blood!", ch, NULL, victim,
	    TO_VICT);
	act("$n assassinates $N in cold blood!", ch, NULL, victim,
	    TO_NOTVICT);
	check_improve(ch, gsn_assassinate, TRUE, 1);
	if (victim->arena == FALSE)
	    if (IS_SET(victim->act, PLR_PKILL))	/* No longer a PKILLER */
		REMOVE_BIT(victim->act, PLR_PKILL);

	victim->hit = 1;

	raw_kill(ch, victim);
    } else {
	WAIT_STATE(ch, skill_table[gsn_assassinate].beats);
	act("Your assassination attempt on $N failed!", ch, NULL, victim,
	    TO_CHAR);
	act("$n's assassination attempt on you failed!", ch, NULL, victim,
	    TO_VICT);
	act("$n's assassination attempt on $N failed!", ch, NULL, victim,
	    TO_NOTVICT);
	check_improve(ch, gsn_assassinate, FALSE, 1);
	multi_hit(ch, victim, TYPE_UNDEFINED);
    }

    return;
}


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

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

    if (ch->position < POS_FIGHTING) {
	do_stand(ch, "");
    }

    if (IS_AFFECTED(ch, AFF_LETHARGY)) {
	send_to_char("You are too lethargic to flee.\n\r", ch);
	return;
    }

    if (ch->daze) {
	send_to_char("You are too dazed to flee!\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->u1.to_room == NULL
	    || IS_SET(pexit->exit_info, EX_CLOSED)
	    || number_range(0, ch->daze) != 0 || (IS_NPC(ch)
						  && IS_SET(pexit->u1.
							    to_room->
							    room_flags,
							    ROOM_NO_MOB)))
	    continue;

	move_char(ch, door, FALSE, FALSE);

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

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

	if (!IS_NPC(ch)) {
	    send_to_char("You flee from combat!\n\r", ch);
	    if (IS_AFFECTED(ch, AFF_SNEAK)) {
		if ((ch->class == 2) && (number_percent() > 10)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
		if ((ch->class == 4) && (number_percent() > 10)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
		if ((ch->class == 0) && (number_percent() > 30)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
		if ((ch->class == 1) && (number_percent() > 30)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
		if ((ch->class == 3) && (number_percent() > 40)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
		if ((ch->class == 5) && (number_percent() > 60)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
		if ((ch->class == 6) && (number_percent() > 30)) {
		    send_to_char("You snuck away safely.\n\r", ch);
		}
	    }

	    else {
		if (ch->arena == FALSE) {
		    send_to_char("You lost 10 exp.\n\r", ch);
		    ch->exp -= 10;
		}
	    }
	}

	stop_fighting(ch, TRUE);
	return;
    }

    send_to_char("PANIC! You couldn't escape!\n\r", ch);
    return;
}



void do_rescue(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *fch;
    bool displaced;
    displaced = FALSE;		//displace spell

    one_argument(argument, arg);
    if (arg[0] == '\0') {
	send_to_char("Rescue whom?\n\r", ch);
	return;
    }
    if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }
    if (victim == ch) {
	send_to_char("What about fleeing instead?\n\r", ch);
	return;
    }
    if (!IS_NPC(ch) && IS_NPC(victim)) {
	send_to_char("Doesn't need your help!\n\r", ch);
	return;
    }
    if (ch->fighting == victim) {
	send_to_char("Too late.\n\r", ch);
	return;
    }
    if ((fch = victim->fighting) == NULL) {
	send_to_char("That person is not fighting right now.\n\r", ch);
	return;
    }
    if (victim->fighting != NULL && !is_same_group(ch, victim->fighting)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    if (IS_NPC(fch) && !is_same_group(ch, victim)) {
	send_to_char("Kill stealing is not permitted.\n\r", ch);
	return;
    }
    WAIT_STATE(ch, skill_table[gsn_rescue].beats);

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, -50, 0, 0)) {

	    //You're rescuing the displaced version
	    send_to_char
		("You, amazingly, accidently step through the person while trying to rescue...\n\r",
		 ch);
	    displaced = TRUE;
	    send_to_char("You fail the rescue.\n\r", ch);
	    check_improve(ch, gsn_rescue, FALSE, 1);
	    return;
	}
    if (number_percent() > get_skill(ch, gsn_rescue)) {
	send_to_char("You fail the rescue.\n\r", ch);
	check_improve(ch, gsn_rescue, FALSE, 1);
	return;
    }
    act("You rescue $N!", ch, NULL, victim, TO_CHAR);
    act("$n rescues you!", ch, NULL, victim, TO_VICT);
    act("$n rescues $N!", ch, NULL, victim, TO_NOTVICT);
    check_improve(ch, gsn_rescue, TRUE, 1);

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

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



void do_kick(CHAR_DATA * ch, char *argument)
{
    CHAR_DATA *victim;
    bool displaced;
    displaced = FALSE;		//displace spell

    if (!IS_NPC(ch)
	&& ch->level < skill_table[gsn_kick].skill_level[ch->class]) {
	send_to_char("You better leave the martial arts to fighters.\n\r",
		     ch);
	return;
    }
    if (IS_NPC(ch) && !IS_SET(ch->off_flags, OFF_KICK))
	return;

    if (IS_NPC(ch) && (IS_AFFECTED(ch, AFF_BLIND))) {
	return;
    }
    if ((victim = ch->fighting) == NULL) {
	send_to_char("You aren't fighting anyone.\n\r", ch);
	return;
    }
    WAIT_STATE(ch, skill_table[gsn_kick].beats);

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're kicking the displaced version
	    send_to_char("Your boot goes right through...\n\r", ch);
	    displaced = TRUE;
	    damage(ch, victim, 0, gsn_kick, DAM_BASH, TRUE);
	    check_improve(ch, gsn_kick, FALSE, 1);
	    return;
	}
    if (get_skill(ch, gsn_kick) > number_percent()) {
	damage(ch, victim, number_range(1, ch->level), gsn_kick, DAM_BASH,
	       TRUE);
	check_improve(ch, gsn_kick, TRUE, 1);
    } else {
	damage(ch, victim, 0, gsn_kick, DAM_BASH, TRUE);
	check_improve(ch, gsn_kick, FALSE, 1);
    }
    check_killer(ch, victim);
    return;
}

void do_arial(CHAR_DATA * ch, char *argument)
{
    CHAR_DATA *victim;
    bool displaced;
    displaced = FALSE;		//displace spell

    if (!IS_NPC(ch)
	&& ch->level < skill_table[gsn_arial].skill_level[ch->class]) {
	send_to_char("You better leave the flying to the birds.\n\r", ch);
	return;
    }
    if (IS_NPC(ch) && !IS_SET(ch->off_flags, OFF_ARIAL))
	return;

    if ((victim = ch->fighting) == NULL) {
	send_to_char("You aren't fighting anyone.\n\r", ch);
	return;
    }
    WAIT_STATE(ch, skill_table[gsn_arial].beats);

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're trying to land on the displaced version
	    send_to_char("You land right on top... and through...\n\r",
			 ch);
	    displaced = TRUE;
	    damage(ch, victim, 0, gsn_arial, DAM_BASH, TRUE);
	    check_improve(ch, gsn_arial, FALSE, 1);
	    return;
	}
    if (get_skill(ch, gsn_arial) > number_percent()) {
	damage(ch, victim, number_range(15, ch->level), gsn_arial,
	       DAM_BASH, TRUE);
	check_improve(ch, gsn_arial, TRUE, 1);
    } else {
	damage(ch, victim, 0, gsn_arial, DAM_BASH, TRUE);
	check_improve(ch, gsn_arial, FALSE, 1);
    }
    check_killer(ch, victim);
    return;
}

void do_whirl(CHAR_DATA * ch, char *argument)
{
    CHAR_DATA *victim;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell

    if (ch->position < POS_FIGHTING) {
	return;
    }

    if ((chance = get_skill(ch, gsn_whirl)) == 0) {
	send_to_char("You don't know how to whirl around opponents.\n\r",
		     ch);
	return;
    }
    if (IS_NPC(ch) && (IS_AFFECTED(ch, AFF_BLIND))) {
	return;
    }
    if ((victim = ch->fighting) == NULL) {
	send_to_char("You aren't fighting anyone.\n\r", ch);
	return;
    }
    if (!can_see(ch, victim)) {
	send_to_char("You can't see your opponent well enough to aim.\n\r",
		     ch);
	return;
    }
    /* check duck */
    if (check_duck(ch, victim, "whirl")) {
	WAIT_STATE(ch, skill_table[gsn_whirl].beats);
	return;
    }
    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're whirling the displaced version
	    send_to_char("You whirl and swing... right through...\n\r",
			 ch);
	    chance = 0;
	    displaced = TRUE;
	}

    /* and now the attack */
    if (number_percent() < chance) {
	WAIT_STATE(ch, skill_table[gsn_whirl].beats);
	act("You whirl your body around $N and flank $M!", ch, NULL,
	    victim, TO_CHAR);
	act("$n whirls $s body around you and flanks you!", ch, NULL,
	    victim, TO_VICT);
	act("$n whirls $s body around $N and flanks $M!", ch, NULL, victim,
	    TO_NOTVICT);

	check_improve(ch, gsn_whirl, TRUE, 1);

	one_hit(ch, victim, gsn_whirl);

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

	if (IS_AFFECTED(ch, AFF_HASTE))
	    one_hit(ch, victim, gsn_whirl);

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

	chance = get_skill(ch, gsn_second_attack) / 4;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_whirl);
	    check_improve(ch, gsn_second_attack, TRUE, 5);
	    if (ch->fighting != victim)
		return;
	}

	chance = get_skill(ch, gsn_third_attack) / 6;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_whirl);
	    check_improve(ch, gsn_third_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}

	chance = get_skill(ch, gsn_fourth_attack) / 8;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_whirl);
	    check_improve(ch, gsn_fourth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}

	chance = get_skill(ch, gsn_fifth_attack) / 10;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_whirl);
	    check_improve(ch, gsn_fifth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}

	chance = get_skill(ch, gsn_sixth_attack) / 16;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_whirl);
	    check_improve(ch, gsn_sixth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}
	chance = get_skill(ch, gsn_fifth_attack) / 10;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_whirl);
	    check_improve(ch, gsn_fifth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}



    } else {
	WAIT_STATE(ch, skill_table[gsn_whirl].beats);
	act("You fail to whirl your body around $N.", ch, NULL, victim,
	    TO_CHAR);
	act("$n tries to whirl $s body around you, but fails.", ch, NULL,
	    victim, TO_VICT);
	act("$n tries to whirl $s body around $N, but fails.", ch, NULL,
	    victim, TO_NOTVICT);
	check_improve(ch, gsn_whirl, FALSE, 1);
    }
    check_killer(ch, victim);
    return;
}

void do_circle(CHAR_DATA * ch, char *argument)
{
    CHAR_DATA *victim;
    int chance;
    bool displaced;
    displaced = FALSE;		//displace spell
    if (ch->position < POS_FIGHTING) {
	return;
    }

    if ((chance = get_skill(ch, gsn_circle)) == 0) {
	send_to_char("You don't know how to circle opponents.\n\r", ch);
	return;
    }

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

    if (!can_see(ch, victim)) {
	send_to_char("You can't see your opponent well enough to aim.\n\r",
		     ch);
	return;
    }
    /* check duck */
    if (check_duck(ch, victim, "circle")) {
	WAIT_STATE(ch, skill_table[gsn_circle].beats);
	return;
    }
    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're circling the displaced version
	    send_to_char("You circle and swing... right through...\n\r",
			 ch);
	    chance = 0;
	    displaced = TRUE;
	}

    /* and now the attack */
    if (number_percent() < chance) {
	WAIT_STATE(ch, (skill_table[gsn_circle].beats * 2) / 3);
	act("You circle around $N and attack!", ch, NULL, victim, TO_CHAR);
	act("$n circles around you and attacks!", ch, NULL, victim,
	    TO_VICT);
	act("$n circles around $N and attacks!", ch, NULL, victim,
	    TO_NOTVICT);

	check_improve(ch, gsn_circle, TRUE, 1);

	one_hit(ch, victim, gsn_circle);

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

	if (IS_AFFECTED(ch, AFF_HASTE))
	    one_hit(ch, victim, gsn_circle);

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

	chance = get_skill(ch, gsn_second_attack) / 4;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_circle);
	    check_improve(ch, gsn_second_attack, TRUE, 5);
	    if (ch->fighting != victim)
		return;
	}

	chance = get_skill(ch, gsn_third_attack) / 6;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_circle);
	    check_improve(ch, gsn_third_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}
	chance = get_skill(ch, gsn_fourth_attack) / 8;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_circle);
	    check_improve(ch, gsn_fourth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}

	chance = get_skill(ch, gsn_fifth_attack) / 12;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_circle);
	    check_improve(ch, gsn_fifth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}
	chance = get_skill(ch, gsn_sixth_attack) / 16;

	if (number_percent() < chance) {
	    one_hit(ch, victim, gsn_circle);
	    check_improve(ch, gsn_sixth_attack, TRUE, 6);
	    if (ch->fighting != victim)
		return;
	}
    } else {
	WAIT_STATE(ch, (skill_table[gsn_circle].beats * 2) / 3);
	act("You fail to circle around $N.", ch, NULL, victim, TO_CHAR);
	act("$n tries to circle around you, but fails.", ch, NULL, victim,
	    TO_VICT);
	act("$n tries to circle around $N, but fails.", ch, NULL, victim,
	    TO_NOTVICT);
	check_improve(ch, gsn_circle, FALSE, 1);
    }
    check_killer(ch, victim);
    return;
}

bool check_duck(CHAR_DATA * ch, CHAR_DATA * victim, char *attack_type)
{
    int chance;

    if (!IS_AWAKE(victim))
	return FALSE;

    chance = get_skill(victim, gsn_duck) * 3 / 4;

    if (!can_see(victim, ch))
	chance /= 2;

    if (number_percent() >= chance)
	return FALSE;

    if (IS_NPC(victim) || !IS_SET(victim->act, PLR_AUTODEFENSE))
	act("{yYou duck $n's $t.{x", ch, attack_type, victim, TO_VICT);

    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_AUTODEFENSE))
	act("{y$N ducks your $t.{x", ch, attack_type, victim, TO_CHAR);

    check_improve(victim, gsn_duck, TRUE, 6);
    return TRUE;
}

void do_disarm(CHAR_DATA * ch, char *argument)
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    int chance, hth, ch_weapon, vict_weapon, ch_vict_weapon;
    bool displaced;
    displaced = FALSE;		//displace spell

    hth = 0;

    if ((chance = get_skill(ch, gsn_disarm)) == 0) {
	send_to_char("You don't know how to disarm opponents.\n\r", ch);
	return;
    }

    if (get_eq_char(ch, WEAR_WIELD) == NULL
	&& ((hth = get_skill(ch, gsn_hand_to_hand)) == 0
	    || (IS_NPC(ch) && !IS_SET(ch->off_flags, OFF_DISARM)))) {
	send_to_char("You must wield a weapon to disarm.\n\r", ch);
	return;
    }

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

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

    /* find weapon skills */
    ch_weapon = get_weapon_skill(ch, get_weapon_sn(ch));
    vict_weapon = get_weapon_skill(victim, get_weapon_sn(victim));
    ch_vict_weapon = get_weapon_skill(ch, get_weapon_sn(victim));

    /* modifiers */

    /* skill */
    if (get_eq_char(ch, WEAR_WIELD) == NULL)
	chance = chance * hth / 150;
    else
	chance = chance * ch_weapon / 100;

    chance += (ch_vict_weapon / 2 - vict_weapon) / 2;

    /* dex vs. strength */
    chance += get_curr_stat(ch, STAT_DEX);
    chance -= 2 * get_curr_stat(victim, STAT_STR);

    //Check if displaced
    if (is_affected(victim, skill_lookup("displace")))
	if (displace_new_effect(ch, (void *) victim, 0, 0, 0)) {

	    //You're disarming the displaced version
	    send_to_char("You attempt to disarm goes right through...\n\r",
			 ch);
	    chance = 0;
	    displaced = TRUE;
	}

    /* and now the attack */
    if (number_percent() < chance) {
	WAIT_STATE(ch, skill_table[gsn_disarm].beats);
	disarm(ch, victim);
	check_improve(ch, gsn_disarm, TRUE, 1);
    } else {
	WAIT_STATE(ch, skill_table[gsn_disarm].beats);
	act("You fail to disarm $N.", ch, NULL, victim, TO_CHAR);
	act("$n tries to disarm you, but fails.", ch, NULL, victim,
	    TO_VICT);
	act("$n tries to disarm $N, but fails.", ch, NULL, victim,
	    TO_NOTVICT);
	check_improve(ch, gsn_disarm, FALSE, 1);
    }
    check_killer(ch, victim);
    return;
}


void do_surrender(CHAR_DATA * ch, char *argument)
{
    CHAR_DATA *mob;
    if ((mob = ch->fighting) == NULL) {
	send_to_char("But you're not fighting!\n\r", ch);
	return;
    }
    act("You surrender to $N!", ch, NULL, mob, TO_CHAR);
    act("$n surrenders to you!", ch, NULL, mob, TO_VICT);
    act("$n tries to surrender to $N!", ch, NULL, mob, TO_NOTVICT);
    stop_fighting(ch, TRUE);

    if (!IS_NPC(ch) && IS_NPC(mob)
	&& (!HAS_TRIGGER(mob, TRIG_SURR)
	    || !mp_percent_trigger(mob, ch, NULL, NULL, TRIG_SURR))) {
	act("$N seems to ignore your cowardly act!", ch, NULL, mob,
	    TO_CHAR);
	multi_hit(mob, ch, TYPE_UNDEFINED);
	return;
    }
    if (!IS_NPC(mob)) {
	act("$N seems to ignore your cowardly act!", ch, NULL, mob,
	    TO_CHAR);
	multi_hit(mob, ch, TYPE_UNDEFINED);
	return;
    }
    send_to_char("You lost 10 exp.\n\r", ch);
    gain_exp(ch, -10);
}


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


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

    one_argument(argument, arg);

    if ((arg[0] == '\0') && ch->position != POS_FIGHTING) {
	send_to_char("Slay whom?\n\r", ch);
	return;
    }
    if (((victim = get_char_room(ch, arg)) == NULL) &&
	ch->position != POS_FIGHTING) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }
    if (ch->position == POS_FIGHTING)
	victim = ch->fighting;

    if (victim == NULL) {
	send_to_char("Victim == NULL, blue sucks.\n\r", ch);
	return;
    }
    if (ch == victim) {
	send_to_char("Suicide is a mortal sin.\n\r", ch);
	return;
    }
    if (IS_IMMORTAL(victim)) {
	if (!IS_NPC(ch)) {
	    send_to_char("You failed.\n\r", ch);
	    return;
	}
    }
    if (IS_IMMORTAL(victim) && ch->level <= victim->level) {
	send_to_char("You failed.\n\r", ch);
	return;
    }

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

    raw_kill(ch, victim);
    return;
}

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

    if (IS_NPC(ch))
	return;

    if (argument[0] != '\0') {
	buf[0] = '\0';
	smash_tilde(argument);

	if (argument[0] == '-') {
	    int len;
	    bool found = FALSE;

	    if (ch->pcdata->wrath == NULL || ch->pcdata->wrath[0] == '\0') {
		send_to_char("No lines left to remove.\n\r", ch);
		return;
	    }
	    strcpy(buf, ch->pcdata->wrath);

	    for (len = strlen(buf); len > 0; len--) {
		if (buf[len] == '\r') {
		    if (!found) {	/* back it up */
			if (len > 0)
			    len--;
			found = TRUE;
		    } else
			/* found the second one */
		    {
			buf[len + 1] = '\0';
			free_string(ch->pcdata->wrath);
			ch->pcdata->wrath = str_dup(buf);
			send_to_char
			    ("Your divine fury takes the form of:\n\r",
			     ch);
			send_to_char(ch->pcdata->wrath ? ch->pcdata->
				     wrath : "(None).\n\r", ch);
			return;
		    }
		}
	    }
	    buf[0] = '\0';
	    free_string(ch->pcdata->wrath);
	    ch->pcdata->wrath = str_dup(buf);
	    send_to_char
		("Mortals no longer need fear your mark upon them.\n\r",
		 ch);
	    return;
	}
	if (argument[0] == '+') {
	    if (ch->pcdata->wrath != NULL)
		strcat(buf, ch->pcdata->wrath);
	    argument++;
	    while (isspace(*argument))
		argument++;
	}
	if (strlen(buf) >= 1024) {
	    send_to_char
		("Your fury is great indeed, too great.  Use less lines.\n\r",
		 ch);
	    return;
	}
	strcat(buf, argument);
	strcat(buf, "\n\r");
	free_string(ch->pcdata->wrath);
	ch->pcdata->wrath = str_dup(buf);
    }
    send_to_char("Your divine fury takes the form of:\n\r", ch);
    send_to_char(ch->pcdata->wrath ? ch->pcdata->wrath : "(None).\n\r",
		 ch);
    return;
}


void do_wrath(CHAR_DATA * ch, char *argument)
{
    char arg1[MAX_INPUT_LENGTH];	/* Lot of arguments */
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char arg4[MAX_INPUT_LENGTH];
    char arg5[MAX_INPUT_LENGTH];
    char arg6[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *SmittenEQ;
    const int MAX_WRATH_FRACTION = 95;
    int hp_percent = 0;
    int mana_percent = 0;
    int move_percent = 0;
    int pos = 0;
    int eq = 0;

    argument = one_argument(argument, arg1);	/* Combine the arguments */
    argument = one_argument(argument, arg2);
    argument = one_argument(argument, arg3);
    argument = one_argument(argument, arg4);
    argument = one_argument(argument, arg5);
    argument = one_argument(argument, arg6);

    if (IS_NPC(ch))
	return;

    if (arg1[0] == '\0') {
	send_to_char("Syntax:\n\r", ch);
	send_to_char
	    ("Wrath <victim> <hp> <mana> <move> <position> <equipment>\n\r",
	     ch);
	return;
    }
    if ((victim = get_char_world(ch, arg1)) == NULL) {
	send_to_char("They are saved only through their absence.\n\r", ch);
	return;
    }
    if (!IS_NPC(victim) && get_trust(victim) >= get_trust(ch)) {
	send_to_char("Your reach exceeds your grasp.\n\r", ch);
	return;
    }
    if (arg2[0] != '\0')
	hp_percent = atoi(arg2);
    else
	hp_percent = 50;

    if (hp_percent > MAX_WRATH_FRACTION || hp_percent < 0) {
	send_to_char("Hp percent must be between 0 and 95.\n\r", ch);
	return;
    }
    if (arg3[0] != '\0')
	mana_percent = atoi(arg3);
    else
	mana_percent = 0;

    if (mana_percent > MAX_WRATH_FRACTION || mana_percent < 0) {
	send_to_char("Mana percent must be between 0 and 95.\n\r", ch);
	return;
    }
    if (arg4[0] != '\0')
	move_percent = atoi(arg4);
    else
	move_percent = 0;

    if (move_percent > MAX_WRATH_FRACTION || move_percent < 0) {
	send_to_char("Move percent must be between 0 and 95.\n\r", ch);
	return;
    }
    if (ch->alignment > 300) {
	act_new("Your actions have brought the holy power of $n upon you!",
		ch, NULL, victim, TO_VICT, POS_DEAD);
	act_new("$N has brought the holy power of $n upon themselves!", ch,
		NULL, victim, TO_NOTVICT, POS_DEAD);
    }
    if (ch->alignment > -301 && ch->alignment < 301) {
	act_new("Your actions have called the divine fury of $n upon you!",
		ch, NULL, victim, TO_VICT, POS_DEAD);
	act_new("$N has called the divine fury of $n upon themselves!", ch,
		NULL, victim, TO_NOTVICT, POS_DEAD);
    }
    if (ch->alignment < -300) {
	act_new("You are struck down by the infernal power of $n!!", ch,
		NULL, victim, TO_VICT, POS_DEAD);
	act_new
	    ("The hellspawned, infernal power of $n has struck down $N!!",
	     ch, NULL, victim, TO_NOTVICT, POS_DEAD);
    }
    if (ch->pcdata->wrath[0] != '\0') {
	send_to_char(ch->pcdata->wrath, victim);
    }
    if (hp_percent > 75 && victim->hit > victim->max_hit / 4)
	send_to_char("{RThat really did HURT!{x\n\r", victim);

    for (eq = 0; eq_table[eq] != NULL; eq++) {
	if (!str_prefix(eq_table[eq], arg6)) {
	    if ((SmittenEQ = get_eq_char(victim, eq)) != NULL) {
		sprintf(buf, "$n's %s is blown away!",
			SmittenEQ->short_descr);
		act(buf, victim, NULL, NULL, TO_ROOM);
		sprintf(buf, "Your %s is blown away!\n\r",
			SmittenEQ->short_descr);
		send_to_char(buf, victim);

		unequip_char(victim, SmittenEQ);
		obj_from_char(SmittenEQ);
		obj_to_room(SmittenEQ, victim->in_room);
	    }
	    break;
	}
    }

    for (pos = 0; pos_table[pos] != NULL; pos++) {
	if (!str_prefix(pos_table[pos], arg5)) {
	    victim->position = pos;	/* This only works because of the way the pos_table is arranged. */
	    if (victim->position == POS_FIGHTING)
		victim->position = POS_STANDING;	/* POS_FIGHTING is bad */

	    if (victim->position < POS_STUNNED)
		victim->position = POS_STUNNED;

	    if (victim->position == POS_STUNNED) {
		act("$n is stunned, but will probably recover.", victim,
		    NULL, NULL, TO_ROOM);
		send_to_char
		    ("You are stunned, but will probably recover.\n\r",
		     victim);
	    }
	    if (victim->position == POS_RESTING
		|| victim->position == POS_SITTING) {
		act("$n is knocked onto $s butt!", victim, NULL, NULL,
		    TO_ROOM);
		send_to_char("You are knocked onto your butt!\n\r",
			     victim);
	    }
	    break;
	}
    }

    /* Calculate total hp loss */
    victim->hit -= ((victim->hit * hp_percent) / 100);
    if (victim->hit < 1)
	victim->hit = 1;

    /* Calculate total mana loss */
    victim->mana -= ((victim->mana * mana_percent) / 100);
    if (victim->mana < 1)
	victim->mana = 1;

    /* Calculate total move loss */
    victim->move -= ((victim->move * move_percent) / 100);
    if (victim->move < 1)
	victim->move = 1;

    send_to_char("Your will is done, your power felt.\n\r", ch);
    return;
}


bool has_number(char *string)
{
    if (string[0] == '\0')
	return FALSE;

    for (; *string != '\0'; string++) {
	if (isdigit(*string))
	    return TRUE;
    }
    return FALSE;
}