emud/area_current/
emud/area_current/castle/
emud/area_current/newareas/
emud/area_current/nwcentral/
emud/area_current/scontinent/
emud/clans/
emud/player/
emud/player/d/e/bak/
emud/player/e/m/
emud/player/e/m/bak/
/***************************************************************************
 * Emud  2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem.   *
 *                                                                         *
 * MrMud 1.4 by David Bills and Dug Michael.                               *
 *                                                                         *
 * Merc  2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael      *
 * Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                         *
 * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe.     *
 ***************************************************************************/

#include "emud.h"

/*
	Global functions.
*/

sh_int	martial_arts_attack;
sh_int	fisticuffs_attack;
sh_int	brawling_attack;
sh_int	body_part_attack;

bool		OGRE_INTIMIDATE;

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

/*
	Local functions.
*/

bool		check_add_attack	( CHAR_DATA *, CHAR_DATA *);
void		clear_attack_list	( CHAR_DATA * );
void		spam_attack_list	( CHAR_DATA * );
void		add_to_victory_list	( CHAR_DATA *, CHAR_DATA *);
void		show_party_line	( CHAR_DATA * );
void		raw_kill			args( ( CHAR_DATA *victim ) );
void		arena_death		args( ( CHAR_DATA *victim ) );
void		player_death		args( ( CHAR_DATA *victim ) );
bool		check_dodge		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 ) );
bool		check_tumble		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		check_killer		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		dam_message		args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt));
char		*get_dam_nounce	args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt));
void		one_hit			args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt));
bool		has_mirror		args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt));
bool		has_icicle_armor	args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt));
bool		is_safe			args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int		xp_compute		args( ( CHAR_DATA *gch,CHAR_DATA *victim ) );
void		group_gain		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		disarm			args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		trip				args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		backstab			args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		orc_brawl			args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void		fisticuffs		args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) );
void		martial_arts		args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) );

struct attack_type
{
	char			*	message;
	int				dam_type;
};

const struct attack_type attack_table[] =
{
	{
		"hit",					DAM_THRUST
	},
	{
		"slice", 					DAM_SLICE
	},
	{
		"stab",					DAM_PIERCE
	},
	{
		"slash",					DAM_SLICE
	},
	{
		"whip",					DAM_REND
	},
	{
		"claw",					DAM_REND
	},
	{
		"blast",					DAM_THRUST
	},
	{
		"pound",					DAM_BASH
	},
	{
		"crush",					DAM_BASH
	},
	{
		"grep",					DAM_THRUST
	},
	{
		"bite",					DAM_PIERCE
	},
	{
		"pierce",					DAM_PIERCE
	},
	{
		"chop",					DAM_CHOP
	}
};


const struct attack_type martial_arts_table[] =
{
	{
		"combination punch",		DAM_THRUST
	},
	{
		"palm punch",				DAM_THRUST
	},
	{
		"thrust kick",				DAM_BASH
	},
	{
		"spinning back-hand",		DAM_THRUST
	},
	{
		"jump kick",				DAM_THRUST
	},
	{
		"round house",				DAM_BASH
	},
	{
		"flip kick",				DAM_THRUST
	},
	{
		"thrusting spear hand",		DAM_PIERCE
	},
	{
		"spinning reverse kick",		DAM_THRUST
	},
	{
		"spinning hook kick",		DAM_THRUST
	},
	{
		"flying scissors kick",		DAM_REND
	},
	{
		"triple round house kick",	DAM_BASH
	}
};


const struct attack_type fisticuffs_table[] =
{
	{
		"combination punch",		DAM_THRUST
	},
	{
		"uppercut",				DAM_THRUST
	},
	{
		"kidney punch",			DAM_THRUST
	},
	{
		"fist blow",				DAM_BASH
	},
	{
		"haymaker",				DAM_BASH
	},
	{
		"sucker punch",			DAM_BASH
	}
};


const struct attack_type brawling_table[] =
{
	{
		"knee",					DAM_THRUST
	},
	{
		"claw",					DAM_REND
	},
	{
		"bite",					DAM_PIERCE
	},
	{
		"head butt",				DAM_BASH
	},
	{
		"elbow slam",				DAM_THRUST
	},
	{
		"uppercut",				DAM_THRUST
	}
};


void check_asn_obj(CHAR_DATA *victim)
{
	push_call("check_asn_obj(%p)",victim);

	if (IS_NPC(victim) || victim->fighting == NULL || IS_NPC(victim->fighting->who))
	{
		pop_call();
		return;
	}

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

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

void violence_update( void )
{
	CHAR_DATA *ch;
	CHAR_DATA *victim;
	CHAR_DATA *rch;
	OBJ_DATA *obj;
	PLAYER_GAME *gpl;

	push_call("violence_update()");

	for (ch = mud->f_char ; ch ; ch = mud->update_wch)
	{
		mud->update_wch = ch->next;

		if (ch->distracted > 0)
		{
			ch->distracted--;

			if (ch->distracted == 0 && IS_NPC(ch) && ch->position < ch->pIndexData->position)
			{
				do_stand(ch, "");
			}
		}

		if (!IS_NPC(ch))
		{
			if ((obj = get_eq_char(ch, WEAR_WIELD)) != NULL && get_obj_weight(obj) > str_app[get_curr_str(ch)].wield)
			{
				act( "$p slips out of your weakened grasp.", ch, obj, NULL, TO_CHAR );
				act( "$p slips out of $n's weakened grasp.", ch, obj, NULL, TO_ROOM );
				unequip_char(ch, obj);
			}

			if (is_affected(ch, gsn_nightmare))
			{
				if (number_percent() < 5 && (obj = get_eq_char(ch, WEAR_LIGHT)) !=NULL)
				{
					act( "$n screams and flings $p away!", ch, obj, NULL, TO_ROOM);
					switch (number_range(1,3))
					{
						case 1:
							act( "The evil leer of a demon appears within the glaring light of $p!", ch, obj, NULL, TO_CHAR);
							break;
						case 2:
							act( "A soul rending shriek is torn from $p!", ch, obj, NULL, TO_CHAR);
							break;
						case 3:
							act( "Images of your painful demise emanate from $p!", ch, obj, NULL, TO_CHAR);
							break;
					}
					act( "You scream and fling $p away!", ch, obj, NULL, TO_CHAR);
					unequip_char(ch, obj);
				}
				else if (number_percent() < 5 && (obj = get_eq_char(ch, WEAR_HOLD))  !=NULL)
				{
					act( "$n screams and flings $p away!", ch, obj, NULL, TO_ROOM);
					switch (number_range(1,3))
					{
						case 1:
							act( "$p starts to slowly drain away your dwindling vitality!", ch, obj, NULL, TO_CHAR);
							break;
						case 2:
							act( "A whisper hisses from $p 'You shall do my bidding weakling!", ch, obj, NULL, TO_CHAR);
							break;
						case 3:
							act( "A stabbing pain lances through you from $p!", ch, obj, NULL, TO_CHAR);
							break;
					}
					act( "You scream and fling $p away!", ch, obj, NULL, TO_CHAR);
					unequip_char(ch, obj);
				}
				else if ( number_percent() < 5 && (obj = get_eq_char(ch, WEAR_WIELD ))  !=NULL)
				{
					act( "$n screams and flings $p away!", ch, obj, NULL, TO_ROOM);
					switch (number_range(1,3))
					{
						case 1:
							act( "The hilt of $p glows red starting to smolder with heat!", ch, obj, NULL, TO_CHAR);
							break;
						case 2:
							act( "Like a viper, $p turns on you and tries to strike!", ch, obj, NULL, TO_CHAR);
							break;
						case 3:
							act( "$p takes on a life of its own, struggling within your grasp!", ch, obj, NULL, TO_CHAR);
							break;
					}
					act( "You scream and fling $p away!", ch, obj, NULL, TO_CHAR);
					unequip_char(ch, obj);
				}
			}
		}

		if (IS_AFFECTED(ch, AFF2_BLEEDING))
		{
			AFFECT_DATA *paf;
			int dam = 0;

			ch_printf(ch, "%sYour life is bleeding out of many nasty wounds!\n\r", get_color_string(ch, COLOR_YOU_ARE_HIT, VT102_BOLD));
			act("$n's life is bleeding out of a many nasty wounds!", ch, NULL, NULL, TO_ROOM);

			for (paf = ch->first_affect ; paf ; paf = paf->next)
			{
				if (paf->bitvector == AFF2_BLEEDING)
				{
					dam += paf->modifier;
				}
			}
			if (dam < 1)
			{
				dam = 1;
			}
			if ((victim = get_char_pvnum(ch->critical_hit_by)) == NULL)
			{
				victim = ch;
			}
			damage(victim, ch, dam, TYPE_NOFIGHT);
		}

		if (IS_AFFECTED(ch, AFF2_TORRID_BALM) && number_bits(1))
		{
			AFFECT_DATA *paf;
			int dam = 0;

			switch(number_bits(2))
			{
				case 0:
					act("Your skin blisters from the torrid balm enveloping you.",	ch, NULL, NULL, TO_CHAR);
					act("$n's skin blisters from the torrid balm enveloping $m.",	ch, NULL, NULL, TO_ROOM);
					break;
				case 1:
					act("Torment lashes through you as the torrid balm brands your flesh.",	ch, NULL, NULL, TO_CHAR);
					act("Torment lashes through $n as torrid balm brands $s flesh.",			ch, NULL, NULL, TO_ROOM);
					break;
				case 2:
					act("You feel your flesh rendered by the torrid balm.",	ch, NULL, NULL, TO_CHAR);
					act("You watch $n's flesh rendered by torrid balm.",		ch, NULL, NULL, TO_ROOM);
					break;
				case 3:
					act("You scream out in agony as the torrid balm consumes you.",	ch, NULL, NULL, TO_CHAR);
					act("$n screams out in agony as torrid balm consumes $m.",		ch, NULL, NULL, TO_ROOM);
					break;
			}

			for (paf = ch->first_affect ; paf ; paf = paf->next)
			{
				if (paf->bitvector == AFF2_TORRID_BALM)
				{
					dam = number_range(1, 10 + paf->duration * 10) + paf->duration * paf->duration;
					if (number_bits(2) == 0)
					{
						paf->modifier += IS_NPC(ch) ? 5 : -1;
					}
				}
			}
			dam = URANGE(1, dam, UMAX(ch->hit, 1));
			damage(ch, ch, dam, TYPE_NOFIGHT);
		}

		/*
			Add poison continuous damage here
		*/

		if (ch->poison)
		{
			POISON_DATA *pd;
			CHAR_DATA *attacker, *fch;
			int dmg;

			pd = ch->poison;

			attacker = get_char_pvnum(pd->poisoner);

			if (attacker == NULL)
			{
				attacker = ch;
			}

			if (pd->instant_damage_high > 0)
			{
				dmg = number_range(pd->instant_damage_low, pd->instant_damage_high);

				pd->instant_damage_high = 0;
			}
			else
			{
				dmg = number_range(pd->constant_damage_low, pd->constant_damage_high);
			}

			if (pd->for_npc != IS_NPC(ch))
			{
				dmg /= 2;
			}

			for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room)
			{
				if (fch == ch && ch == attacker)
				{
					ch_printf(fch, "%sYou are shocked by poison for %dhp.\n\r", get_color_string(fch, COLOR_YOU_HIT, VT102_BOLD), dmg);
				}
				else if (fch == ch)
				{
					ch_printf(ch, "%sYou are shocked by poison.\n\r", get_color_string(ch, COLOR_YOU_ARE_HIT, VT102_BOLD));
				}
				else if (fch == attacker)
				{
					ch_printf(fch, "%s%s is shocked by poison for %dhp.\n\r", get_color_string(fch,COLOR_YOU_HIT,VT102_BOLD), capitalize(get_name(ch)), dmg);
				}
				else
				{
					ch_printf(fch, "%s is shocked by poison.\n\r", capitalize(get_name(ch)));
				}
			}

			damage(attacker, ch, dmg, TYPE_NOFIGHT);

			if (pd->constant_duration <= 0)
			{
				ch->poison = ch->poison->next;
				FREEMEM(pd);
			}
			else
			{
				pd->constant_duration--;
			}
		}

		if (ch->fighting == NULL)
		{
			if (ch->position == POS_FIGHTING)
			{
				stop_fighting(ch, FALSE);
			}
			continue;
		}

		if ((victim = who_fighting(ch)) == NULL)
		{
			stop_fighting(ch, FALSE);
			continue;
		}

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

		if (ch->position < POS_SLEEPING)
		{
			continue;
		}

		if (ch->attack != 0)
		{
			ch->attack = 0;
		}

		if (IS_NPC(ch))
		{
			if (!IS_SET(ch->act, ACT_NO_DAMAGE))
			{
				multi_hit( ch, victim, TYPE_UNDEFINED );
			}
			else if (!IS_SET(ch->pIndexData->progtypes, FIGHT_PROG))
			{
				log_build_printf(ch->pIndexData->vnum, "mob has ACT_NO_DAMAGE set but has no fight prog");
			}
		}
		else
		{
			ch->pcdata->last_combat = mud->current_time;

			if (ch->pcdata->auto_flags != AUTO_QUICK)
			{
				check_improve(ch, gsn_first_strike);

				multi_hit( ch, victim, TYPE_UNDEFINED );
			}
		}

		if (!valid_fight(ch, victim))
		{
			continue;
		}

		set_fighting(victim, ch);

		mprog_hitprcnt_trigger(ch, victim);

		if (!valid_fight(ch, victim))
		{
			continue;
		}

		mprog_fight_trigger(ch, victim);

		if (!valid_fight(ch, victim))
		{
			continue;
		}

		/*
			assist rules - Scandum 27-02-2002

			- charmed mobs are not assisted
			- players only assist when victim is a mob
			- grouped mobs assist, no questions asked
			- mobs do not attack their master
			- mobs do not attack their own kind (same vnum)
			- mobs do not attack someone more than 30 levels below
			- mobs of same vnum have 50.0% chance to assist
			- mobs of diff vnum have 12.5% chance to assist
			- mobs attack a random party member of the victim
		*/

		if (IS_AFFECTED(victim, AFF_CHARM) || IS_AFFECTED(ch, AFF_CHARM))
		{
			continue;
		}

		for (rch = ch->in_room->first_person ; rch ; rch = mud->update_rch)
		{
			mud->update_rch = rch->next_in_room;

			if (!IS_AWAKE(rch) || rch->fighting || IS_AFFECTED(rch, AFF_ETHEREAL))
			{
				continue;
			}

			if (!IS_NPC(rch) || rch->desc)
			{
				if (is_same_group(ch, rch) && IS_NPC(victim))
				{
					multi_hit(rch, victim, TYPE_UNDEFINED);
				}
				continue;
			}

			if (IS_AFFECTED(rch, AFF_CHARM))
			{
				if (rch->master == ch)
				{
					multi_hit(rch, victim, TYPE_UNDEFINED);
				}
				continue;
			}

			if (is_same_group(ch, rch))
			{
				multi_hit(rch, victim, TYPE_UNDEFINED);
				continue;
			}

			if (!IS_NPC(ch) || rch->master == who_fighting(ch))
			{
				continue;
			}

			if (rch->pIndexData == victim->pIndexData)
			{
				continue;
			}

			if (rch->pIndexData != ch->pIndexData && number_bits(2))
			{
				continue;
			}

			if (rch->level / 2 <= ch->level && rch->level * 2 >= ch->level && number_bits(1))
			{
				CHAR_DATA *vch;
				CHAR_DATA *target = NULL;
				int number;

				for (number = 0, vch = ch->in_room->first_person ; vch ; vch = vch->next_in_room, number++)
				{
					if (can_see(rch, vch) && is_same_group(vch, victim) && number_range(0, number) == 0)
					{
						target = vch;
					}
				}
				if (target != NULL)
				{
					multi_hit(rch, target, TYPE_UNDEFINED);
				}
 			}
		}
	}
	/*
		Add Spam's party stat line here
	*/
	for (gpl = mud->f_player ; gpl ; gpl = gpl->next)
	{
		if (gpl->ch->fighting != NULL && IS_SET(gpl->ch->pcdata->spam, 1024))
		{
			show_party_line( gpl->ch );
		}
		if (gpl->ch->desc == NULL && gpl->ch->fighting && gpl->ch->wait == 0)
		{
			do_flee(gpl->ch, "");
		}
	}

	pop_call();
	return;
}

/*
	The SPAM stat line
*/

void show_party_line( CHAR_DATA *ch )
{
	CHAR_DATA *fch;
	char buf[MAX_STRING_LENGTH], buf2[200], buf3[200];

	push_call("show_party_line(%p)",ch);
	buf[0]='\0';

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

/*
	Do one group of attacks.
*/

void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
	int chance, level, bonus;
	OBJ_DATA *wield;

	push_call("multi_hit(%p,%p,%p)",ch,victim,dt);

	OGRE_INTIMIDATE = FALSE;

	/*
		Disallow fighting in different rooms and shops
	*/

	if (victim->in_room != ch->in_room)
	{
		stop_fighting(ch, FALSE);
		pop_call();
		return;
	}

	if (is_safe(ch, NULL))
	{
		stop_fighting(ch, FALSE);
		pop_call();
		return;
	}

	if (victim->fighting == NULL)
	{
		if (!IS_NPC(victim) || (IS_SET(victim->act, ACT_CLASS) && victim->class == CLASS_GLADIATOR))
		{
			if (number_range(1, 200) < learned(victim, gsn_impale))
			{
				wield = get_eq_char(victim, WEAR_WIELD);

				if (wield && wield->item_type == ITEM_WEAPON && wield->value[0] == WEAPON_TYPE_SPEAR)
				{
					act("You thrust $p into the ground.", victim, wield, NULL, TO_CHAR);
					act("$n thrusts $p into the ground.", victim, wield, NULL, TO_ROOM);

					one_hit(victim, ch, gsn_impale);
				}
			}
		}
	}

	if (ch->in_room != victim->in_room)
	{
		stop_fighting(ch, FALSE);
		pop_call();
		return;
	}

	/*
		Added Ogre Intimidate here  - Chaos 8/20/98
	*/

	if (rspec_req(ch, RSPEC_INTIMIDATE) && !rspec_req(victim, RSPEC_INTIMIDATE))
	{
		if (!IS_UNDEAD(victim) && number_range(1,6) == 1)
		{
			OGRE_INTIMIDATE = TRUE;
			send_to_char( "You intimidate your opponent.\n\r", ch);
			send_to_char( "You are intimidated by your opponent.\n\r", victim);
		}
	}

	one_hit(ch, victim, dt);

	if (!valid_fight(ch, victim) || ch->fighting->who != victim)
	{
		pop_call();
		return;
	}

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

	/*
		Added Orcish brawling  - Chaos 8/20/98
	*/

	if (rspec_req(ch, RSPEC_BRAWLING) && number_bits(3) == 0)
	{
		orc_brawl(ch, victim);

		if (!valid_fight(ch, victim) || ch->fighting->who != victim)
		{
			pop_call();
			return;
		}
	}

	if (get_eq_char(ch, WEAR_DUAL_WIELD) || ch->race == RACE_KRAKEN || rspec_req(ch, RSPEC_MULTI_ARMS) || is_affected(ch,AFF2_STEELHAND))
	{
		if (rspec_req(ch, RSPEC_MULTI_ARMS))
		{
			chance = UMAX(50, learned(ch, gsn_dual_wield));
		}
		else
		{
			chance = learned(ch, gsn_dual_wield);
		}
		bonus  = chance / 10;

		if (number_percent() < chance)
		{
			one_hit(ch, victim, dt);
			check_improve(ch, gsn_dual_wield);
		}

		if (!valid_fight(ch, victim) || ch->fighting->who != victim)
		{
			pop_call();
			return;
		}
	}
	else
	{
		bonus = 0;
	}

	if (IS_AFFECTED(ch, AFF_HASTE))
	{
		bonus += 10;
	}

	if (!IS_NPC(ch) && multi(ch, gsn_second_attack) == -1)
	{
		pop_call();
		return;
	}

	level  = multi_skill_level(ch, gsn_second_attack);
	chance = (learned(ch, gsn_second_attack)+bonus)*level/50;

	if (number_percent() < chance)
	{
		one_hit(ch, victim, dt);

		if (!valid_fight(ch, victim) || ch->fighting->who != victim)
		{
			pop_call();
			return;
		}
		check_improve(ch, gsn_second_attack);
	}

	if (!IS_NPC(ch) && multi(ch, gsn_third_attack) == -1)
	{
		pop_call();
		return;
	}
	level  = multi_skill_level(ch, gsn_third_attack);
	chance = (learned(ch, gsn_third_attack)+bonus)*level/150;

	if (number_percent() < chance)
	{
		one_hit(ch, victim, dt);

		if (!valid_fight(ch, victim) || ch->fighting->who != victim)
		{
			pop_call();
			return;
		}
		check_improve(ch, gsn_third_attack);
	}

	if (!IS_NPC(ch) && multi(ch, gsn_fourth_attack) == -1)
	{
		pop_call();
		return;
	}

	level  = multi_skill_level(ch, gsn_fourth_attack);
	chance = (learned(ch, gsn_fourth_attack)+bonus)*level/300;

	if (number_percent() < chance)
	{
		one_hit(ch, victim, dt);

		if (!valid_fight(ch, victim) || ch->fighting->who != victim)
		{
			pop_call();
			return;
		}
		check_improve(ch, gsn_fourth_attack);
	}

	if (!IS_NPC(ch) && multi(ch, gsn_fifth_attack) == -1)
	{
		pop_call();
		return;
	}

	level  = multi_skill_level(ch, gsn_fifth_attack);
	chance = (learned(ch, gsn_fifth_attack)+bonus)*level/450;

	if (number_percent() < chance)
	{
		one_hit(ch,victim,dt);

		if (!valid_fight(ch, victim) || ch->fighting->who != victim)
		{
			pop_call();
			return;
		}
		check_improve(ch, gsn_fifth_attack);
	}
	pop_call();
	return;
}

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

	push_call("check_hit(%p,%p,%p,%p)",ch,victim,hit_roll,dam_type);

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

	level = multi_skill_level(ch, dam_type);

	if (dam_type == gsn_kick)				scale = 15;
	else if (dam_type == gsn_shoot)			scale = 14;
	else if (dam_type == gsn_backstab)			scale = 14;
	else if (dam_type == gsn_head_butt)		scale = 14;
	else if (dam_type == gsn_knife)			scale = 13;
	else if (dam_type == gsn_trip)			scale = 13;
	else if (dam_type == gsn_circle)			scale = 13;
	else if (dam_type == gsn_throw)			scale = 13;
	else if (dam_type == gsn_vampiric_touch)	scale = 13;
	else if (dam_type == gsn_whirl)			scale = 13;
	else if (dam_type == gsn_impale)			scale = 13;
	else if (dam_type == gsn_bash)			scale = 12;
	else if (dam_type == gsn_fisticuffs)		scale = 12;
	else if (dam_type == gsn_gouge)			scale = 12;
	else if (dam_type == gsn_martial_arts)		scale = 11;
	else if (dam_type == gsn_acupunch)			scale = 11;
	else if (dam_type == gsn_cripple)			scale = 11;
	else
	{
		scale = 10;
		level = ch->level;
	}

	if (scale != 10 && number_percent() > learned(ch, dam_type))
	{
		if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WIZTIME))
		{
			ch_printf_color(ch, "{078}(check_hit(false) scale: %d, level: %d, learned: %d)\n\r", scale, level, learned(ch, dam_type));
		}
		pop_call();
		return FALSE;
	}


	if (IS_NPC(victim))
	{
		thac0 = mob_armor(victim) + victim->level*4;
	}
	else
	{
		thac0 = 0 - (GET_AC(victim) - 100);
	}

	if (IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch))
	{
		thac0 += 20;
	}

	if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) )
	{
		thac0 += 20;
	}

	if (OGRE_INTIMIDATE)
	{
		thac0 -= ch->level*2;
	}

	if (victim->position == POS_SLEEPING)
	{
		thac0 = 0;
	}

	if (victim->position == POS_RESTING || victim->position == POS_SITTING)
	{
		thac0 -= ch->level;
	}

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

	if (ch->distracted > 0)
	{
		thac0 += ch->level/3;
		ch->distracted--;
	}
	if (victim->distracted > 0)
	{
		thac0 -= ch->level/3;
		victim->distracted--;
	}

	if (IS_NPC(ch))
	{
		diceroll = number_range(0, 34 + scale*level + hit_roll) + level*2;
	}
	else
	{
		if (learned(ch, gsn_precision))
		{
			hit_roll += hit_roll * URANGE(25, multi_skill_level(ch, gsn_precision)/2, 50) * learned(ch, gsn_precision) / 10000;
		}
		diceroll = number_range(0, 39 + scale*level*12/10) + (hit_roll > 0 ? number_range(1, hit_roll * 2) : hit_roll) + level*2;
	}

	if (dam_type >= TYPE_HIT)
	{
		if ((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL)
		{
			if (!IS_SET(mud->flags, MUD_DUALFLIP))
			{
				wield = get_eq_char( ch, WEAR_WIELD );
			}
		}
		else
		{
			wield = get_eq_char(ch, WEAR_WIELD);
		}

		if (wield != NULL && wield->item_type == ITEM_WEAPON)
		{
			diceroll = (100 + weapon_skill(ch, wield->value[0])) * diceroll / 200;
		}
	}

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

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

	if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WIZTIME))
	{
		ch_printf_color(ch, "{078}(check_hit() diceroll: %d, thac: %d)\n\r", diceroll, thac0);
	}

	pop_call();
	return(diceroll >= thac0);
}

/*
	Hit one guy once.
*/

void one_hit(CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
	OBJ_DATA *wield;
	AFFECT_DATA *paf;
	int dam;

	push_call("one_hit(%p,%p,%p)",ch,victim,dt);

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

	if ((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL)
	{
		TOGGLE_BIT(mud->flags, MUD_DUALFLIP);

		if (!IS_SET(mud->flags, MUD_DUALFLIP))
		{
			wield = get_eq_char(ch, WEAR_WIELD);
		}
	}
	else
	{
		wield = get_eq_char(ch, WEAR_WIELD);
	}

	/*
		Make them a bit tired
	*/

	if (!IS_NPC(ch) && ch->move > 0)
	{
		ch->move--;
	}

	/*
		Figure out the type of damage message.
	*/

	if (dt == TYPE_UNDEFINED)
	{
		if (IS_SET(ch->attack, ATTACK_MIRROR))
		{
			pop_call();
			return;
		}

		dt = TYPE_HIT;

		if (wield != NULL && wield->item_type == ITEM_WEAPON)
		{
			dt += wield->value[3];
		}
	}

	/*
		Calc damage and check for specials
	*/

	dam = 0;

	if (IS_NPC(ch))
	{
		dam = dice(get_damnodice(ch), get_damsizedice(ch)) + ch->npcdata->damplus;

		if (wield != NULL && wield->item_type == ITEM_WEAPON)
		{
			dam += weapon_skill(ch, wield->value[0]) * dice(wield->value[1], wield->value[2]) / 200;
		}
		else if (IS_SET(ch->act, ACT_CLASS))
		{
			switch (ch->class)
			{
				case CLASS_SHAMAN:
					dt = gsn_fisticuffs;
					break;
				case CLASS_NINJA:
					dt = gsn_martial_arts;
					break;
			}
		}
	}
	else
	{
		if (wield != NULL && wield->item_type == ITEM_WEAPON)
		{
			dam = (100 + weapon_skill(ch, wield->value[0])) * dice(wield->value[1], wield->value[2]) / 200;
		}
		else
		{
			dam = dice(get_damnodice(ch), get_damsizedice(ch));

			if(is_affected(ch,AFF2_STEELHAND)) /* only counts if no weapons are worn */
			{
				for(paf=ch->first_affect;paf != NULL || paf->bitvector==AFF2_STEELHAND; paf=paf->next)
				{
					/* temporary check */
					if(paf->bitvector != AFF2_STEELHAND)
					{
						log_printf("(%s [%d]): have to fix right affect grabbing.\n",__FILE__,__LINE__);
					}
					/* end of temp check */
				}
				dam = dice(ch->level,paf->modifier);
			}
			else if (learned(ch, gsn_fisticuffs) || learned(ch, gsn_martial_arts))
			{
				if (multi(ch, gsn_fisticuffs) != -1 && !wield && number_percent() < multi_skill_level(ch, gsn_fisticuffs))
				{
					dt = gsn_fisticuffs;
				}
				else if (multi(ch, gsn_martial_arts) != -1 && !wield && number_percent() < multi_skill_level(ch, gsn_martial_arts))
				{
					dt = gsn_martial_arts;
				}
			}
		}
	}

	/*
		Bonuses.
	*/

	dam += GET_DAMROLL(ch);

	if (victim->position == POS_SLEEPING)
	{
		dam = 4*dam/3;
	}

	if (victim->position == POS_RESTING)
	{
		dam = 6*dam/5;
	}

	if (victim->position == POS_SITTING)
	{
		dam = 7*dam/6;
	}

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

	if (dt == gsn_backstab)
	{
		if (!IS_NPC(ch))
		{
			if (number_percent() > learned(ch, gsn_greater_backstab))
			{
				dam = dam*(12 + multi_skill_level(ch, gsn_backstab))/10;
			}
			else
			{
				dam = dam*(12 + multi_skill_level(ch, gsn_backstab))/8;
			}
		}
		else
		{
			dam = dam*(12 + ch->level/2)/10;
		}
	}
	else if (dt == gsn_circle)
	{
		if (!IS_NPC(ch))
		{
			dam = dam*(12 + multi_skill_level(ch, gsn_circle))/20;
		}
		else
		{
			dam = dam*(12 + ch->level/2)/20;
		}
	}
	else if (dt == gsn_knife)
	{
		if (!IS_NPC(ch))
		{
			dam = dam * (12 + multi_skill_level(ch, gsn_knife))/24;
		}
		else
		{
			dam = dam * (12 + ch->level/2)/24;
		}
	}
	else if (dt == gsn_impale)
	{
		if (!IS_NPC(ch))
		{
			dam = dam * (10 + multi_skill_level(ch, gsn_impale))/25;
		}
		else
		{
			dam = dam * (10 + ch->level/2)/25;
		}
	}
	else if (dt == gsn_martial_arts)
	{
		martial_arts(ch, victim, dam);
		pop_call();
		return;
	}
	else if (dt == gsn_fisticuffs)
	{
		fisticuffs(ch, victim, dam);
		pop_call();
		return;
	}
	else	if (gsn_anatomy && !check_hit(ch, victim, GET_HITROLL(ch), dt))
	{
		damage(ch, victim, 0, dt);
		check_improve(victim, gsn_armor_usage);
		pop_call();
		return;
	}

	if (dam <= 0)
	{
		dam = 1;
	}

	damage(ch, victim, dam, dt);

	if (dt == gsn_backstab)
	{
		check_improve(ch, gsn_backstab);
		check_improve(ch, gsn_greater_backstab);
	}
	else if (dt == gsn_knife)
	{
		check_improve(ch, gsn_knife);
	}
	else if (dt == gsn_impale)
	{
		check_improve(ch, gsn_impale);
	}
	pop_call();
	return;
}

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

	/*
		Hurt the victim.
		Inform the victim of his new state.
	*/

	push_call("damage_hurt(%p,%p,%p,%p)",ch,victim,dam,dt);

	victim->hit -= dam;

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

	update_pos(victim);


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

	if (dam > 0 && dt != TYPE_NOFIGHT && !is_spell(dt))
	{
		if (IS_AFFECTED(victim, AFF2_FIRESHIELD) || victim->race == RACE_PHOENIX)
		{
			if (number_percent() <= 25)
			{
				damage(victim, ch, number_fuzzy(dam), gsn_fire_shield);
			}

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

		if (IS_AFFECTED(victim, AFF2_ICICLE_ARMOR))
		{
			if (number_percent() <= 10)
			{
				damage(victim, ch, number_fuzzy(ch->level), gsn_icicle_armor);
			}

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

	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:
			if (victim->fighting)
			{
				if (IS_NPC(ch) && ch->master)
				{
					victim->fighting->who = ch->master;
				}
				else
				{
					victim->fighting->who = ch;
				}
			}
			mprog_death_trigger(victim);
			mprog_kill_trigger(ch);
			act( "$n is DEAD!!", victim, NULL, NULL, TO_ROOM );
			send_to_char( "You have been KILLED!!\n\r\n\r", victim );
			break;
		default:
			if (dam > victim->max_hit / 4 && (IS_NPC(victim) || victim->level < LEVEL_IMMORTAL))
			{
				send_to_char( "*** That really did HURT!\n\r", victim);
			}
			if (victim->hit < victim->max_hit / 4 && (IS_NPC(victim) || victim->level < LEVEL_IMMORTAL))
			{
				send_to_char( "*** You sure are BLEEDING!\n\r", victim);
			}
			break;
	}

	/*
		Sleep spells and extremely wounded folks.
	*/
	if (!IS_AWAKE(victim) || ch == victim)
	{
		if (dt != TYPE_NOFIGHT)
		{
			if (victim->fighting)
			{
				stop_hate_fear(victim->fighting->who);
			}
		}
	}
	/*
		Intercept object programs for damaging others
	*/
	if (!IS_NPC(ch) && dam > 0 && victim->position != POS_DEAD)
	{
		if (dt != TYPE_NOFIGHT && ch->desc != NULL)
		{
			OBJ_DATA *obj, *obj_next;
			OBJ_PROG *prg;

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

				if (obj->carried_by && IS_SET(obj->pIndexData->progtypes, TRIG_DAMAGE))
				{
					for (prg = obj->pIndexData->first_prog ; prg ; prg = prg->next)
					{
						if (prg->trigger == TRIG_DAMAGE && number_percent() <= prg->percentage)
						{
							start_object_program(ch, obj, prg, "");
						}
					}
				}
			}
		}
	}

	/*
		Intercept object programs for getting damaged
	*/

	if (!IS_NPC(victim) && dam > 0 && victim->position != POS_DEAD)
	{
		OBJ_DATA *obj, *obj_next;
		OBJ_PROG *prg;

		if (dt != TYPE_NOFIGHT && victim->desc != NULL)
		{
			for (obj = victim->first_carrying ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (obj->carried_by && IS_SET(obj->pIndexData->progtypes, TRIG_HIT))
				{
					for (prg = obj->pIndexData->first_prog ; prg != NULL ; prg = prg->next)
					{
						if (prg->trigger == TRIG_HIT && number_percent() <= prg->percentage)
						{
							start_object_program( victim, obj, prg, "");
						}
					}
				}
			}
		}
	}

	/*
		Payoff for killing things.
	*/

	if (victim->position == POS_DEAD)
	{
		OBJ_DATA *obj;

		if (victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA && !IS_NPC(victim))
		{
			if (!IS_NPC(ch))
			{
				if (ch != victim)
				{
					add_to_victory_list( ch, victim );
					spam_attack_list(victim);
				}
				if ((which_god(ch) != GOD_NEUTRAL && which_god(victim) != GOD_NEUTRAL)
				&&  (which_god(ch) != which_god(victim)))
				{
					if (get_bounty(victim->name) != NULL)
					{
						collect_bounty(ch, victim);
					}

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

					if (ch->pcdata->clan != NULL && victim->pcdata->clan != NULL)
					{
						switch (which_god(ch))
						{
							case GOD_ULMO:
								ch->pcdata->clan->pkills[CLAN_ULMO_KILL]++;
								break;
							case GOD_DEMISE:
								ch->pcdata->clan->pkills[CLAN_DEMISE_KILL]++;
								break;
							case GOD_GAIA:
								ch->pcdata->clan->pkills[CLAN_GAIA_KILL]++;
								break;
							case GOD_HYPNOS:
								ch->pcdata->clan->pkills[CLAN_HYPNOS_KILL]++;
								break;
							case GOD_MANWE:
								ch->pcdata->clan->pkills[CLAN_MANWE_KILL]++;
								break;
						}
						switch (which_god(victim))
						{
							case GOD_ULMO:
								victim->pcdata->clan->pdeaths[CLAN_ULMO_DEATH]++;
								break;
							case GOD_DEMISE:
								victim->pcdata->clan->pdeaths[CLAN_DEMISE_DEATH]++;
								break;
							case GOD_GAIA:
								victim->pcdata->clan->pdeaths[CLAN_GAIA_DEATH]++;
								break;
							case GOD_HYPNOS:
								victim->pcdata->clan->pdeaths[CLAN_HYPNOS_DEATH]++;
								break;
							case GOD_MANWE:
								victim->pcdata->clan->pdeaths[CLAN_MANWE_DEATH]++;
								break;
						}
						save_clan(ch->pcdata->clan);
						save_clan(victim->pcdata->clan);
					}
					ch->hit  = ch->max_hit;
					ch->mana = ch->max_mana;
					ch->move = ch->max_move;

					act(god_table[ch->pcdata->god].pk_char_msg, ch, NULL, victim, TO_CHAR);
					act(god_table[ch->pcdata->god].pk_room_msg, ch, NULL, victim, TO_ROOM);

					sprintf(buf, "%s", get_name(ch));
					do_battle("%s has slain %s!", buf, get_name(victim));
				}
				else if (victim != ch)
				{
					log_printf("NEUTRAL PKILL");
					victim->pcdata->history[HISTORY_KILL_BY_PC]++;
					ch->pcdata->history[HISTORY_KILL_PC]++;
				}
			}
			else
			{
				victim->pcdata->history[HISTORY_KILL_BY_NPC]++;
				if (victim->pcdata->clan != NULL)
				{
					victim->pcdata->clan->mdeaths++;
					save_clan( victim->pcdata->clan );
				}
			}
		}

		if (IS_NPC(victim) && !IS_NPC(ch))
		{
			if (ch->pcdata->clan != NULL)
			{
				ch->pcdata->clan->mkills++;
			}
			ch->pcdata->history[HISTORY_KILL_NPC]++;
		}

		if (!IS_NPC(victim))
		{
			log_printf("%s killed by %s at %u", victim->name, get_name( ch ),  victim->in_room->vnum );

			save_char_obj(victim, BACKUP_SAVE);

			if (victim->race != RACE_PHOENIX && IS_NPC(ch))
			{
				int exp_loss = victim->pcdata->exp - exp_level(victim->class, victim->level - 1);

				if (exp_loss > 0)
				{
					gain_exp(victim, 0 - exp_loss / 2);
				}
			}

			/*
				Knights Death     - Chaos 9/14/95
			*/

			if (victim->level > 91 && victim->level < 96 && victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA && victim->race != RACE_PHOENIX)
			{
				int add_hp, add_mana, add_move;
				victim->level--;
				victim->pcdata->mclass[victim->class]--;
				add_hp = 130;
				add_mana = 100;
				add_move = 85;
				add_hp   *= (victim->pcdata->reincarnation + 2 ) / 2;
				add_mana *= (victim->pcdata->reincarnation + 3 ) / 3;
				add_move *= (victim->pcdata->reincarnation + 3 ) / 3;
				victim->max_hit -= add_hp;
				victim->max_move -= add_mana;
				victim->max_mana -= add_move;
				victim->pcdata->actual_max_hit -= add_hp;
				victim->pcdata->actual_max_move -= add_mana;
				victim->pcdata->actual_max_mana -= add_move;

				knight_adjust_hpmnmv( victim );

				if (victim->pcdata->exp > exp_level(victim->class,(victim->level)-1 )+1)
				{
					gain_exp(victim, exp_level(victim->class, (victim->level)-1 )+1 - victim->pcdata->exp);
				}
				sub_player(victim);
				add_player(victim);
			}

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

		if ((ch == victim))
		{
			if (ch->position == POS_DEAD)
			{
				if (IS_NPC(ch))
				{
					log_printf("[%u] %s just killed itself using damage type %d.", ch->pIndexData->vnum, ch->short_descr, dt);
				}
				else
				{
					log_printf("%s just killed itself using damage type %d.", get_name(ch), dt);
				}
				raw_kill(ch);
			}
			pop_call();
			return;
		}

		if (!confused)
		{
			set_fighting(victim, ch);
		}

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

		if (!IS_NPC(ch) && !IS_NPC(victim) && ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
		{
			PLAYER_GAME *gpl;
			sprintf( buf, "%s has killed %s!\n\r", ch->name, victim->name );
			for (gpl = mud->f_player ; gpl ; gpl = gpl->next )
			{
				if (gpl->ch != ch && gpl->ch != victim &&  gpl->ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA )
				{
					send_to_char( buf, gpl->ch );
				}
			}
		}

		raw_kill( victim );

		if ((obj = get_obj_list(ch, "npc_corpse", ch->in_room->first_content)) != NULL && can_see_obj(ch, obj))
		{
			if ( auto_loot )
			{
				FIGHT_DATA *fptr;

				fptr = ch->fighting;
				ch->fighting = NULL;
				do_get( ch, NULL );
				ch->fighting = fptr;
			}
			if (auto_sac && rspec_req(ch, RSPEC_VAMPIRIC) && ch->pcdata->condition[COND_THIRST] < 48)
			{
				do_drink (ch, "npc_corpse");
			}
			if ( auto_sac )
			{
				do_sacrifice (ch, "npc_corpse");
			}
		}

		if (ch->desc && CH(ch->desc)->pcdata->vt100 == 1)
		{
			vt100prompt( ch );
		}
		pop_call();
		return;
	}

	if (!IS_NPC(victim) && victim->hit > 0 && victim->hit <= victim->pcdata->wimpy && victim->wait == 0)
	{
		if (victim->desc != NULL && victim->desc->incomm[0] == '\0')
		{
			SET_BIT(victim->pcdata->interp, INTERP_AUTO);
			str_cpy_max(victim->desc->incomm, "flee", MAX_INPUT_LENGTH);
		}
	}

	if (ch->desc)
	{
		if (CH(ch->desc)->pcdata->vt100 == 1)
		{
			vt100prompt( ch );
		}
	}
	if (victim->desc)
	{
		if (CH(victim->desc)->pcdata->vt100 == 1)
		{
			vt100prompt( victim );
		}
	}
	pop_call();
	return;
}

void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
	OBJ_DATA *wield;
	bool confused;

	push_call("damage(%p,%p,%p,%p)",ch,victim,dam,dt);

	if (victim->position == POS_DEAD)
	{
		pop_call();
		return;
	}

	if (dt != TYPE_NOFIGHT)
	{
		if (is_safe(ch, NULL))
		{
			/*
				Disallow damage in shops and safe place.
			*/
			stop_fighting(ch, FALSE);
			pop_call();
			return;
		}

		ch->furniture = NULL;

		if (ch->fighting == NULL && ch != victim)
		{
			set_fighting(ch,victim);
		}

		if (victim->fighting == NULL && ch != victim)
		{
			set_fighting(victim,ch);
		}

		if (ch->position == POS_STANDING)
		{
			ch->position = POS_FIGHTING;
		}

		if (victim != ch)
		{
			if (IS_AFFECTED(ch, AFF_HIDE))
			{
				affect_strip(ch, gsn_hide);
				REMOVE_BIT(ch->affected_by, AFF_HIDE);
				act( "$n steps out from $s hiding spot.",   ch, NULL, NULL, TO_ROOM );
				act( "You step out from your hiding spot.", ch, NULL, NULL, TO_CHAR );
			}

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

			if (IS_AFFECTED(ch, AFF_INVISIBLE))
			{
				affect_strip(ch, gsn_invis);
				REMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
				if (!IS_AFFECTED(ch, AFF_IMP_INVISIBLE))
				{
					act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
				}
			}

			if (has_mirror(ch, victim, dt) || has_icicle_armor(ch, victim, dt))
			{
				if (ch->position < POS_FIGHTING)
				{
					ch->position++;
				}
				pop_call();
				return;
			}
		}
	}


	if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !CAN_FLY(ch) && which_god(ch) != GOD_ULMO)
	{
		if (number_percent() > 80 && number_percent() > get_curr_dex(ch))
		{
			switch (number_bits(1))
			{
				case 0:
					act("You slip on the ice, falling flat on your back.",		ch, NULL, NULL, TO_CHAR);
					act("$n slips on the ice, falling flat on $s back.",		ch, NULL, NULL, TO_ROOM);
					break;
				case 1:
					act("You lose your footing on the slippery ice and fall.",	ch, NULL, NULL, TO_CHAR);
					act("$n loses $s footing on the slippery ice and falls.",	ch, NULL, NULL, TO_ROOM);
					break;
			}
			wait_state(ch, PULSE_VIOLENCE / 4);

			ch->position = POS_SITTING;

			pop_call();
			return;
		}
	}

	if (dt != TYPE_NOFIGHT)
	{
		switch (ch->position)
		{
			case POS_SLEEPING:
				if (!IS_AFFECTED(ch, AFF_SLEEP))
				{
					ch->position = POS_RESTING;
				}
				pop_call();
				return;

			case POS_RESTING:
			case POS_SITTING:
				do_stand(ch,"");
				pop_call();
				return;
		}
	}


	/*
     	Confusion spell   - Chaos  7/26/96
	*/

	confused = FALSE;

	if (IS_AFFECTED(ch, AFF2_CONFUSION) && number_range(0,4) == 0 && dt != TYPE_NOFIGHT)
	{
		CHAR_DATA *fch;
		int tch, pch;

		for (tch = 0, fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room)
		{
			if (!can_see(ch, fch))
			{
				continue;
			}

			if (!can_attack(ch, fch) && ch != fch)
			{
				continue;
			}
			tch++;
		}
		if (tch > 1)
		{
			pch = number_range(1, tch);
			for (tch = 0, fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room )
			{
				if (!can_see(ch, fch))
				{
					continue;
				}

				if (!can_attack(ch, fch) && ch != fch)
				{
					continue;
				}
				tch++;
				if (tch == pch)
				{
					victim = fch;
					confused = TRUE;
					break;
				}
			}
		}
	}

	/*
		Set recently fought info.
	*/

	if (IS_NPC(victim) && !IS_NPC(ch) && !confused && dam > 0 && dt != TYPE_NOFIGHT)
	{
		if (ch->leader && !IS_NPC(ch->leader))
		{
			victim->npcdata->pvnum_last_hit = ch->leader->pcdata->pvnum;
		}
		else
		{
			victim->npcdata->pvnum_last_hit = ch->pcdata->pvnum;
		}
	}

	if (dam && IS_NPC(victim) && ch != victim && dt != TYPE_NOFIGHT)
	{
		if (ch->level > 25 && victim->npcdata->hate_fear != ch->name)
		{
			RESTRING(victim->npcdata->hate_fear, ch->name);
		}
	}

	/*
		Damage enhancers
	*/

	if (!IS_NPC(ch) && !is_spell(dt) && dt != TYPE_NOFIGHT)
	{
		if (get_curr_str(ch) > 29)
		{
			dam = dam * get_curr_str(ch) / 29;
		}
		if (multi(ch, gsn_enhanced_damage) != -1)
		{
			dam += dam * URANGE(15, multi_skill_level(ch, gsn_enhanced_damage)/2, 35) * learned(ch, gsn_enhanced_damage) / 10000;
			check_improve(ch, gsn_enhanced_damage);
		}
	}

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

	if (dt == gsn_backstab)
	{
		int dam_cap;
		int used_reincs;

		used_reincs = IS_NPC(ch) ? 0 : URANGE(0, ch->pcdata->reincarnation, 100);

		if (number_percent() < learned(ch, gsn_greater_backstab))
		{
			dam_cap = 800+ch->level*10 + (250*used_reincs);
		}
		else
		{
			dam_cap = 800+ch->level*6 + (250*used_reincs);
		}

		dam_cap = number_fuzzy(dam_cap);

		if (dam > dam_cap)
		{
			dam = dam_cap;
		}
	}

	if (victim != ch)
	{
		/*
			Certain attacks are forbidden.
			Most other attacks are Returned.
		*/

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

		if (ch->position > POS_STUNNED && ch != victim && dt != TYPE_NOFIGHT)
		{
			if (ch->fighting == NULL && !confused)
			{
				set_fighting( ch, victim );
			}
			/*
				If victim is charmed, ch might attack victim's master.
			*/
			if (IS_NPC(ch) && IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room == ch->in_room && number_bits(4) == 0 && dt != TYPE_NOFIGHT)
			{
				stop_fighting(ch, FALSE);
				multi_hit(ch, victim->master, TYPE_UNDEFINED);
				pop_call();
				return;
			}
		}


		/*
			Add poison off of item
		*/

		if ((wield = get_eq_char(ch, WEAR_WIELD)) != NULL && wield->poison != NULL && dam > 0)
		{
			POISON_DATA *pd;

			if (IS_NPC(ch) || ch->pcdata->pvnum != wield->poison->owner)
			{
				while ((pd = wield->poison) != NULL)
				{
					wield->poison = wield->poison->next;
					FREEMEM(pd);
				}
			}
			else
			{
				if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
				{
					wield->poison->poisoner = -1;
				}
				else
				{
					wield->poison->poisoner = ch->pcdata->pvnum;
				}

				wield->poison->next = victim->poison;
				victim->poison		= wield->poison;
			}
			wield->poison = NULL;
		}

		if (dt == gsn_knife && !IS_AFFECTED(victim, AFF2_BLEEDING) && dam > 0)
		{
			if (multi(ch, gsn_critical_hit) != -1 && number_percent() < learned(ch, gsn_critical_hit) / 4)
			{
				AFFECT_DATA af;

				af.type      = gsn_critical_hit;
				af.duration  = 0;
				af.modifier  = 20 + number_range(1, multi_skill_level(ch, gsn_critical_hit)/2);
				af.location  = APPLY_NONE;
				af.bittype   = AFFECT_TO_CHAR;
				af.bitvector = AFF2_BLEEDING;
				if (!IS_NPC(ch))
				{
					victim->critical_hit_by = ch->pcdata->pvnum;
				}
				else
				{
					victim->critical_hit_by = 0;
				}
				affect_join( victim, &af );

				SET_BIT(victim->affected2_by, 0-AFF2_BLEEDING);
				ch_printf(ch, "%sYou feel particularly satisfied as...\n\r", get_color_string(ch,COLOR_YOU_HIT,VT102_BOLD));
				check_improve(ch, gsn_critical_hit);
			}
		}

		/*
			Check for disarm, trip, parry, and dodge.
		*/

 		if (dt >= TYPE_HIT)
		{
			if (IS_NPC(ch) && ch->desc == NULL)
			{
				if (number_percent() < ch->level / 30 + 1)
				{
					trip(ch, victim);
				}
				if (number_percent() < ch->level / 30 + 1)
				{
					disarm(ch, victim);
				}
			}
			if (victim->position > POS_RESTING)
			{
				if (check_parry(ch, victim))
				{
					pop_call();
					return;
				}
				if (check_dodge(ch, victim))
				{
					pop_call();
					return;
				}
				if (check_shield_block(ch, victim))
				{
					pop_call();
					return;
				}
			}
		}
		else if (victim->position > POS_RESTING && !is_spell(dt))
		{
			if (check_tumble(ch, victim))
			{
				pop_call();
				return;
			}
		}
	}

	if (dt >= TYPE_HIT)
	{
		OBJ_DATA *obj;
		if (IS_SET(mud->flags, MUD_DUALFLIP) && get_eq_char(ch, WEAR_DUAL_WIELD) != NULL)
		{
			obj = get_eq_char(ch, WEAR_DUAL_WIELD);
		}
		else
		{
			obj = get_eq_char(ch, WEAR_WIELD);
		}
		if (obj && IS_SET(obj->extra_flags, ITEM_BURNING))
		{
			dt = gsn_flame_blade;

			if (dam > 0)
			{
				dam += dice(1, 1 + obj->level / 10);
			}
		}
	}

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

	if (dam > 0 && is_affected(victim, gsn_mana_shield))
	{
		int ms_red, ms_dam;

		ms_red = URANGE(25, 100 * victim->mana / UMAX(1, victim->max_mana), 75);
		ms_dam = UMIN(dam*ms_red/100, victim->mana);

		dam -= ms_dam;
		victim->mana -= ms_dam;
	}

	if (dt != gsn_anatomy)
	{
		dam_message(ch, victim, dam, dt);
	}
	else
	{
		dam = victim->hit;
	}

	if (dam > 0 && is_affected(victim, gsn_mana_shield))
	{
		if (100*victim->mana/victim->max_mana < 25)
		{
			act("$n flares brightly as $s mana shield shatters!", victim, NULL, NULL, TO_ROOM);
			send_to_char("You flare brightly as your mana shield shatters!\n\r", victim);
			affect_strip(victim, gsn_mana_shield);
		}
	}

	damage_hurt(ch, victim, dam, dt);

	pop_call();
	return;
}


bool has_mirror(CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
	AFFECT_DATA *paf;
	char message[MAX_INPUT_LENGTH];
	const char *attack;
	bool all;

	push_call("has_mirror(%p,%p)",ch,victim);

	attack = NULL;
	all    = FALSE;

	if (IS_AFFECTED(ch, AFF_TRUESIGHT))
	{
		pop_call();
		return FALSE;
	}

	if (!IS_AFFECTED(victim, AFF2_MIRROR_IMAGE))
	{
		pop_call();
		return FALSE;
	}

	if (dt == TYPE_NOFIGHT)
	{
		pop_call();
		return FALSE;
	}

	SET_BIT(ch->attack, ATTACK_MIRROR);

	for (paf = victim->first_affect ; paf ; paf = paf->next)
	{
		if (paf->bitvector == AFF2_MIRROR_IMAGE)
		{
			if (number_range(0, paf->modifier))
			{
				paf->modifier -= 1;

				if (paf->modifier <= 0)
				{
					all = TRUE;
					affect_strip(victim, paf->type);
				}
			}
			else
			{
				act( "You discover the real $T.", ch, NULL, short_to_name(get_name(victim), 1), TO_CHAR);
				act( "Your images disappear.",    ch, NULL, victim, TO_VICT    );
				act( "$N's images disappear.",    ch, NULL, victim, TO_NOTVICT );
				affect_strip(victim, paf->type);

				pop_call();
				return FALSE;
			}
			break;
		}
	}
	body_part_attack = get_body_part(ch, victim, dt, 0);
	attack = get_dam_nounce(ch, victim, dt);

	if (attack[0] != '\0')
	{
		sprintf(message, "Your %s destroys $N in one blow!", attack);
		act(message, ch, NULL, victim, TO_CHAR);
		sprintf(message, "$n's %s destroys $N in one blow!", attack);
		act(message, ch, NULL, victim, TO_ROOM);
	}
	else
	{
		act("You destroy $N in one blow!", ch, NULL, victim, TO_CHAR);
		act("$n destroys $N in one blow!", ch, NULL, victim, TO_ROOM);
	}

	if (all)
	{
		act( "You discover the real $T.", ch, NULL, short_to_name(get_name(victim), 1), TO_CHAR    );
		act( "Your images disappear.",    ch, NULL, victim, TO_VICT    );
		act( "$N's images disappear.",    ch, NULL, victim, TO_NOTVICT );
	}
	pop_call();
	return TRUE;
}


bool has_icicle_armor(CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
	AFFECT_DATA *paf;
	char message[MAX_INPUT_LENGTH];
	const char *attack = NULL;

	push_call("has_icicle_armor(%p,%p)",ch,victim);

	if (!IS_AFFECTED(victim, AFF2_ICICLE_ARMOR))
	{
		pop_call();
		return FALSE;
	}

	if (dt == TYPE_NOFIGHT || is_spell(dt))
	{
		pop_call();
		return FALSE;
	}

	for (paf = victim->first_affect ; paf ; paf = paf->next)
	{
		if (paf->bitvector == AFF2_ICICLE_ARMOR)
		{
			if (number_range(0, 200) < paf->modifier * -1)
			{
				body_part_attack = get_body_part(ch, victim, dt, 0);
				attack = get_dam_nounce(ch, victim, dt);

				if (attack[0] == '\0')
				{
					attack = "hit";
				}

				affect_modify(victim, paf, FALSE);

				paf->modifier += 5;

				affect_modify(victim, paf, TRUE);

				if (paf->modifier < 0)
				{
					sprintf(message, "Your %s shatters a spike of $N's icicle armor into a hundred pieces!", attack);
					act(message, ch, NULL, victim, TO_CHAR);
					sprintf(message, "$n's %s shatters a spike of your icicle armor into a hundred pieces!", attack);
					act(message, ch, NULL, victim, TO_VICT);
					sprintf(message, "$n's %s shatters a spike of $N's icicle armor into a hundred pieces!", attack);
					act(message, ch, NULL, victim, TO_NOTVICT);
				}
				else
				{
					sprintf(message, "Your %s splinters $N's icicle armor into a thousand pieces!", attack);
					act(message, ch, NULL, victim, TO_CHAR);
					sprintf(message, "$n's %s splinters your icicle armor into a thousand pieces!", attack);
					act(message, ch, NULL, victim, TO_VICT);
					sprintf(message, "$n's %s splinters $N's icicle armor into a thousand pieces!", attack);
					act(message, ch, NULL, victim, TO_NOTVICT);

					affect_strip(victim, paf->type);
				}
				pop_call();
				return TRUE;
			}
			break;
		}
	}
	pop_call();
	return FALSE;
}

/*
	true if victim is a legal target for a mass attack - Scandum 27/05/2002
*/

bool can_mass_attack( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("can_mass_attack(%p,%p)",ch,victim);

	if (victim == ch)
	{
		pop_call();
		return FALSE;
	}

	if (victim->fighting && victim->fighting->who == ch)
	{
		pop_call();
		return TRUE;
	}

	if (victim->fighting && !is_same_group(ch, victim->fighting->who))
	{
		pop_call();
		return FALSE;
	}

	if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL))
	{
		pop_call();
		return FALSE;
	}

	if (is_same_group(ch, victim))
	{
		pop_call();
		return FALSE;
	}

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

	if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM))
	{
		pop_call();
		return FALSE;
	}

	if (!IS_NPC(ch) && !IS_NPC(victim))
	{
		pop_call();
		return FALSE;
	}

	if (check_recently_fought(ch, victim))
	{
		pop_call();
		return FALSE;
	}
	pop_call();
	return TRUE;
}

/*
	Rewrote this function to put all the no fighting crap in one
	neat function, charmed and possessed mobs attack like players.

	Scandum 18/02/02
*/

bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim)
{
	push_call("is_safe(%p,%p)",ch,victim);

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

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

	if (victim == NULL)
	{
		pop_call();
		return FALSE;
	}

	if (who_fighting(ch) == victim)
	{
		pop_call();
		return FALSE;
	}

	if (who_fighting(victim) == ch)
	{
		pop_call();
		return FALSE;
	}

	if (ch == victim)
	{
		send_to_char( "You may not do that.\n\r", ch );
		pop_call();
		return TRUE;
	}

	if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master)
	{
		if (victim->master == ch)
		{
			raw_kill(victim);
			pop_call();
			return TRUE;
		}
		send_to_char( "You cannot kill a slave.\n\r", ch );
		pop_call();
		return TRUE;
	}

	if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
	{
		pop_call();
		return FALSE;
	}

	if (IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit / 2)
	{
		if (!IS_AFFECTED(ch, AFF_CHARM) && ch->desc == NULL)
		{
			pop_call();
			return TRUE;
		}
	}

	if (!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) || ch->desc != NULL)
	{
		if (!IS_NPC(victim))
		{
			send_to_char( "You must MURDER a player.\n\r", ch);
			pop_call();
			return TRUE;
		}
	}

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

	if (check_recently_fought(ch, victim))
	{
		ch_printf(ch, "%s was recently fought.  Try later.\n\r", capitalize(victim->short_descr));
		pop_call();
		return TRUE;
	}

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

	pop_call();
	return FALSE;
}

bool check_recently_fought( CHAR_DATA *ch, CHAR_DATA *victim )
{
	CHAR_DATA *ch_ld;
	int pvnum_ld;

	push_call("check_recently_fought(%p,%p)",ch,victim);

	if (!IS_NPC(victim))
	{
		pop_call();
		return FALSE;
	}

	if (victim->npcdata->pvnum_last_hit == 0)
	{
		pop_call();
		return FALSE;
	}

	if (MP_VALID_MOB(ch))
	{
		pop_call();
		return FALSE;
	}

	ch_ld = ch;

	if (IS_NPC(ch) && ch->master)
	{
		ch_ld = ch_ld->master;
	}

	if (ch_ld->leader != NULL)
	{
		ch_ld = ch_ld->leader;
	}

	if (!IS_NPC(ch_ld))
	{
		pvnum_ld = ch_ld->pcdata->pvnum;
	}
	else
	{
		pvnum_ld = 0;
	}

	if (ch_ld == NULL || IS_NPC(ch_ld))
	{
		pop_call();
		return TRUE;
	}

	if (pvnum_ld != victim->npcdata->pvnum_last_hit)
	{
		pop_call();
		return TRUE;
	}
	pop_call();
	return FALSE;
}

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

void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("check_killer(%p,%p)",ch,victim);

	if (IS_SET(victim->act, PLR_KILLER))
	{
		pop_call();
		return;
	}

	if (!IS_SET(ch->act, PLR_KILLER))
	{
		send_to_char("*** You are now a KILLER!! ***\n\r", ch);
	}
	SET_BIT(ch->act, PLR_KILLER);
	ch->pcdata->killer_played = ch->pcdata->played;

	pop_call();
	return;
}

bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim )
{
	int chance;
	bool cross_parry, reposte;

	push_call("check_parry(%p,%p)",ch,victim);

	if (IS_SET(victim->attack, ATTACK_PARRY))
	{
		pop_call();
		return FALSE;
	}

	if (get_eq_char(victim, WEAR_WIELD) == NULL)
	{
		pop_call();
		return FALSE;
	}

	if (!IS_NPC(victim) && multi(victim, gsn_parry) == -1)
	{
		pop_call();
		return( FALSE );
	}

	reposte     = (!IS_NPC(victim) && number_percent() < learned(victim, gsn_reposte));
	cross_parry = (get_eq_char(victim, WEAR_DUAL_WIELD) != NULL);

	chance = learned(victim, gsn_parry) / (5 - cross_parry - reposte);

	reposte     =     reposte ? number_bits(1) : FALSE;
	cross_parry = cross_parry ? number_bits(1) : FALSE;

	if (OGRE_INTIMIDATE)
	{
		chance     -= 15;
		reposte     = FALSE;
	}

	if (number_percent() > chance)
	{
		pop_call();
		return FALSE;
	}
	else
	{
		SET_BIT(victim->attack, ATTACK_PARRY);
	}

	if (!IS_NPC(ch) && number_percent() < learned(ch, gsn_precision)/3)
	{
		act( "You try to parry $n's attack, but $s aim is too precise.",		ch, NULL, victim, TO_VICT);
		act( "$N tries to parry your attack, but your aim is too precise.",	ch, NULL, victim, TO_CHAR);

		check_improve(ch, gsn_precision);

		pop_call();
		return FALSE;
	}

	if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8))
	{
		if (reposte)
		{
			act( "You parry and reposte $n's attack.", ch, NULL, victim, TO_VICT);
		}
		else if (cross_parry)
		{
			act( "You cross-parry $n's attack.", ch, NULL, victim, TO_VICT);
		}
		else
		{
			act( "You parry $n's attack.", ch, NULL, victim, TO_VICT);
		}
	}

	if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2))
	{
		if (reposte)
		{
			act( "$N parries and repostes your attack.", ch, NULL, victim, TO_CHAR);
		}
		else if (cross_parry)
		{
			act( "$N cross-parries your attack.", ch, NULL, victim, TO_CHAR);
		}
		else
		{
			act( "$N parries your attack.", ch, NULL, victim, TO_CHAR);
		}
	}

	if (reposte)
	{
		one_hit(victim, ch, TYPE_UNDEFINED);
		check_improve(victim, gsn_reposte);
	}
	else
	{
		check_improve(victim, gsn_parry);
	}
	pop_call();
	return TRUE;
}

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

	push_call("check_dodge(%p,%p)",ch,victim);

	if (IS_SET(victim->attack, ATTACK_DODGE))
	{
		pop_call();
		return FALSE;
	}

	if (!learned(victim, gsn_dodge))
	{
		pop_call();
		return( FALSE );
	}

	chance = UMIN(multi_skill_level(victim, gsn_dodge)/2+5, learned(victim, gsn_dodge) / 3);

	if (OGRE_INTIMIDATE)
	{
		chance -= 15;
	}

	if (number_percent() > chance)
	{
		pop_call();
		return FALSE;
	}
	else
	{
		SET_BIT(victim->attack, ATTACK_DODGE);
	}

	if (!IS_NPC(ch) && number_percent() < learned(ch, gsn_precision)/3)
	{
		act( "You try to dodge $n's attack, but $s aim is too precise.",		ch, NULL, victim, TO_VICT);
		act( "$N tries to dodge your attack, but your aim is too precise.",	ch, NULL, victim, TO_CHAR);

		check_improve(ch, gsn_precision);

		pop_call();
		return FALSE;
	}

	if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8))
	{
		act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT);
	}

	if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2))
	{
		act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR);
	}
	check_improve(victim, gsn_dodge);
	pop_call();
    	return TRUE;
}

bool check_shield_block( CHAR_DATA *ch, CHAR_DATA *victim )
{
	int chance = 0;

	push_call("check_shield_block(%p,%p)",ch,victim);

	if (IS_SET(victim->attack, ATTACK_BLOCK))
	{
		pop_call();
		return FALSE;
	}

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

	if (!learned(victim, gsn_shield_block))
	{
		pop_call();
		return( FALSE );
	}
	else
	{
		chance = UMIN(multi_skill_level(victim, gsn_shield_block)/2+5, learned(victim, gsn_shield_block) / 3);
	}

	if (OGRE_INTIMIDATE)
	{
		chance -= 15;
	}

	if (number_percent() > chance)
	{
		pop_call();
		return FALSE;
	}
	else
	{
		SET_BIT(victim->attack, ATTACK_BLOCK);
	}

	if (!IS_NPC(ch) && number_percent() < learned(ch, gsn_precision)/3)
	{
		act( "You try to dodge $n's attack, but $s aim is too precise.",		ch, NULL, victim, TO_VICT);
		act( "$N tries to dodge your attack, but your aim is too precise.",	ch, NULL, victim, TO_CHAR);

		check_improve(ch, gsn_precision);

		pop_call();
		return FALSE;
	}

	if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8))
	{
		act( "You block $n's attack.", ch, NULL, victim, TO_VICT);
	}

	if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2))
	{
		act( "$N blocks your attack.", ch, NULL, victim, TO_CHAR);
	}
	check_improve(victim, gsn_shield_block);
	pop_call();
	return TRUE;
}


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

	push_call("check_tumble(%p,%p)",ch,victim);

	if (IS_SET(victim->attack, ATTACK_TUMBLE))
	{
		pop_call();
		return FALSE;
	}

	if (IS_NPC(victim) && (!IS_SET(victim->act, ACT_CLASS) || victim->class != CLASS_NINJA))
	{
		pop_call();
		return FALSE;
	}

	if (!learned(victim, gsn_tumble))
	{
		pop_call();
		return( FALSE );
	}

	chance = UMIN(multi_skill_level(victim, gsn_tumble)/2+5, learned(victim, gsn_tumble) / 3);

	if (OGRE_INTIMIDATE)
	{
		chance -= 15;
	}

	if (number_percent() > chance)
	{
		pop_call();
		return FALSE;
	}
	else
	{
		SET_BIT(victim->attack, ATTACK_TUMBLE);
	}

	if (ch == NULL)
	{
		act( "You flip back on your feet.", victim, NULL, NULL, TO_CHAR);
		act( "$n flips back on his feet.",  victim, NULL, NULL, TO_ROOM);
	}
	else
	{
		if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8))
		{
			act( "You tumble away from $n's attack.", ch, NULL, victim, TO_VICT);
		}

		if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2))
		{
			act( "$N tumbles away from your attack.", ch, NULL, victim, TO_CHAR);
		}
	}
	check_improve(victim, gsn_tumble);
	pop_call();
    	return TRUE;
}

/*
	Set position of a victim.
*/

void update_pos( CHAR_DATA *victim )
{
	push_call("update_pos(%p)",victim);

	if (victim->fighting && in_camp(victim))
	{
		CHAR_DATA *gch;
		for (gch = victim->in_room->first_person ; gch ; gch = gch->next_in_room)
		{
			if (is_same_group(victim, gch) && IS_AFFECTED(gch, AFF2_CAMPING))
			{
				send_to_char( "Your camp is destroyed!\n\r", victim );
				REMOVE_BIT(gch->affected2_by, 0-AFF2_CAMPING);
				break;
			}
		}
	}

	if (victim->hit > 0)
	{
		if (victim->position <= POS_STUNNED)
		{
			victim->position = POS_STANDING;
		}
		pop_call();
		return;
	}

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

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

void free_fight( CHAR_DATA *ch )
{
	push_call("free_fight(%p)",ch);

	if (ch->fighting != NULL)
	{
		if ((ch->fighting->prev == NULL && ch->fighting != mud->f_fight)
		||  (ch->fighting->next == NULL && ch->fighting != mud->l_fight))
		{
			log_printf("UNLINK ERROR free_fight: fight data not found on %s", ch->name);
			dump_stack();
			pop_call();
			return;
		}

		UNLINK(ch->fighting, mud->f_fight, mud->l_fight, next, prev);
		FREEMEM(ch->fighting);
	}

	ch->position = POS_STANDING;

	if (!IS_NPC(ch))
	{
		ch->pcdata->asn_obj = NULL;
	}
	update_pos(ch);

	pop_call();
	return;
}

/*
	Start fights.
*/

void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
{
	FIGHT_DATA *fight;

	push_call("set_fighting(%p,%p)",ch,victim);

	if (ch == victim)
	{
		pop_call();
		return;
	}

	if (ch->fighting)
	{
		pop_call();
		return;
	}

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

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

	ALLOCMEM(fight, FIGHT_DATA, 1);

	fight->who	= victim;
	fight->ch		= ch;

	LINK(fight, mud->f_fight, mud->l_fight, next, prev);

	ch->fighting	= fight;

	if (ch->position == POS_STANDING)
	{
		ch->position = POS_FIGHTING;
	}

	if (!IS_NPC(ch))
	{
		ch->pcdata->last_combat = mud->current_time;
	}

	if (!IS_NPC(victim))
	{
		victim->pcdata->last_combat = mud->current_time;
	}

	update_pos(ch);

	pop_call();
	return;
}

/*
	Make a corpse out of a character.
*/

void make_corpse( CHAR_DATA *ch )
{
	char buf[MAX_INPUT_LENGTH];
	OBJ_DATA *corpse;
	OBJ_DATA *obj;
	OBJ_DATA *obj_next;

	push_call("make_corpse(%p)",ch);

	if (IS_NPC(ch) && IS_SET(ch->act, ACT_UNDEAD))
	{
		for (obj = ch->first_carrying ; obj ; obj = obj_next)
		{
			obj_next = obj->next_content;

			if (IS_SET(obj->extra_flags, ITEM_INVENTORY))
			{
				junk_obj( obj );
			}
			else
			{
				obj_to_room( obj, ch->in_room->vnum );
			}
		}
		pop_call();
		return;
	}

	if (IS_NPC(ch))
	{
		corpse             = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0);
		corpse->timer      = number_range( 2, 4 );
		corpse->level      = ch->level;
		corpse->owned_by   = 0;

		if (ch->fighting != NULL)
		{
			if (IS_NPC(ch->fighting->who) && IS_AFFECTED(ch->fighting->who, AFF_CHARM))
			{
				if (!IS_NPC(ch->fighting->who->master))
				{
					corpse->owned_by = ch->fighting->who->master->pcdata->pvnum;
				}
			}
			if (!IS_NPC(ch->fighting->who))
			{
				corpse->owned_by = ch->fighting->who->pcdata->pvnum;
			}
			if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL && ch->master->pcdata!=NULL )
			{
				corpse->owned_by = ch->master->pcdata->pvnum;
			}
		}
		if (ch->gold > 0)
		{
			obj_to_obj(create_money(ch->gold), corpse);
			ch->gold = 0;
		}
		if (IS_SET(ch->act, ACT_MOUNT))
		{
			SET_BIT(corpse->extra_flags, ITEM_MOUNT);
		}
	}
	else
	{
		corpse		= create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
		corpse->timer	= 60;

		SET_BIT(corpse->extra_flags, ITEM_MODIFIED);

		if (ch->pcdata->corpse == NULL)
		{
			ch->pcdata->corpse		= corpse;
			ch->pcdata->corpse_room	= ch->in_room->vnum;
		}
		corpse->owned_by = ch->pcdata->pvnum;
	}

	sprintf(buf, "corpse %s %s", IS_NPC(ch) ? "npc_corpse" : "pc_corpse", short_to_name(get_name(ch), 1));
	RESTRING(corpse->name, buf);

	sprintf(buf, "the corpse of %s", get_name(ch));
	RESTRING(corpse->short_descr, buf);

	sprintf(buf, "The corpse of %s is lying here.", get_name(ch));
	RESTRING(corpse->long_descr, buf);

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

		if (!IS_SET(obj->extra_flags, ITEM_INVENTORY) && !IS_SET(obj->extra_flags, ITEM_NODROP))
		{
			obj_to_obj( obj, corpse );
		}
	}

	obj_to_room(corpse, ch->in_room->vnum);

	if (!IS_NPC(ch))
	{
		ch->pcdata->time_of_death		= mud->current_time;
		ch->pcdata->just_died_ctr		= 10;
		ch->pcdata->condition[COND_FULL]	= 48;
		ch->pcdata->condition[COND_THIRST]	= 48;
		ch->pcdata->condition[COND_DRUNK]	=  0;

		if (ch->race != RACE_PHOENIX)
		{
			ch_printf(ch, "%s\n\r", god_table[ch->pcdata->god].death_msg);
		}
		else
		{
			send_to_char("You have arisen from your ashes.\n\r", ch);
		}
	}
	pop_call();
	return;
}

/*
	Improved Death_cry contributed by Diavolo.
*/

void death_cry( CHAR_DATA *ch )
{
	EXIT_DATA *pexit;
	char *msg;
	int door, vnum, ran, temp_vnum;
	bool IS_BODY;

	push_call("death_cry(%p)",ch);

	ran     = number_bits(4);
	vnum    = 0;
	IS_BODY = (IS_NPC(ch) && (IS_SET(ch->act, ACT_BODY) || IS_SET(ch->act, ACT_RACE)));

	if (IS_BODY && number_bits(2) == 0 && !IS_SET(ch->act, ACT_UNDEAD))
	{
		ran = get_body_part(ch, NULL, TYPE_HIT, 1);

		if (ran == -1)
		{
			msg = "$n splatters blood on your armor.";
		}
		else
		{
			vnum = OBJ_VNUM_SLICED_LEG;
			msg  = body_table[ran].sliced;
		}
	}
	else
	{
		msg  = "You hear $n's death cry.";
	}

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

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

	if (vnum != 0)
	{
		char buf[MAX_INPUT_LENGTH];
		OBJ_DATA *obj;
		char *name;

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

		SET_BIT(obj->extra_flags, ITEM_MODIFIED);

		if (IS_BODY)
		{
			sprintf(buf, body_table[ran].short_descr, name);
		}
		else
		{
			sprintf(buf, obj->short_descr, name);
		}
		RESTRING(obj->short_descr, buf);

		if (IS_BODY)
		{
			sprintf(buf, body_table[ran].long_descr, capitalize(name));
		}
		else
		{
			sprintf(buf, obj->long_descr, name);
		}
		RESTRING(obj->long_descr, buf);

		if (IS_BODY)
		{
			sprintf(buf, body_table[ran].name, name);
			RESTRING(obj->name, buf);

			sprintf(buf, body_table[ran].description, capitalize(name));
			RESTRING(obj->description, buf);
		}
		obj_to_room(obj, ch->in_room->vnum);
	}

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

	temp_vnum = ch->in_room->vnum;

	for (door = 0 ; door <= 5 ; door++)
	{
		if ((pexit = get_exit(temp_vnum, door)) != NULL)
		{
			ch->in_room = room_index[pexit->to_room];
			act( msg, ch, NULL, NULL, TO_ROOM );
		}
	}
	ch->in_room = room_index[temp_vnum];

	pop_call();
	return;
}

void raw_kill( CHAR_DATA *victim )
{
	FIGHT_DATA	*fight,	*fight_next;
	PET_DATA		*pet,	*pet_next;

	push_call("raw_kill(%p)",victim);

	if (IS_NPC(victim))
	{
		if (IS_SET(victim->act, ACT_WILL_DIE))
		{
			pop_call();
			return;
		}
		SET_BIT(victim->act, ACT_WILL_DIE);
	}

	for (fight = mud->f_fight ; fight ; fight = fight_next)
	{
		fight_next = fight->next;

		if (IS_NPC(fight->ch) && fight->ch != victim)
		{
			if (who_fighting(fight->ch) == victim && IS_SET(fight->ch->act, ACT_ONE_FIGHT) && !SET_BIT(victim->act, ACT_WILL_DIE))
			{
				raw_kill(fight->ch);
				fight_next = mud->f_fight;
			}
		}
	}

	for (pet = mud->f_pet ; pet ; pet = pet_next)
	{
		pet_next = pet->next;

		if (IS_NPC(pet->ch) && pet->ch != victim)
		{
			if (pet->ch->master == victim && IS_AFFECTED(pet->ch, AFF_CHARM) && !IS_SET(pet->ch->act, ACT_WILL_DIE))
			{
				raw_kill(pet->ch);
				pet_next = mud->f_pet;
			}
		}
	}

	if (victim->poison)
	{
		POISON_DATA *pd;

		while ((pd = victim->poison) != NULL)
		{
			victim->poison = victim->poison->next;
			FREEMEM( pd );
		}
	}

	while (victim->first_affect)
	{
		affect_from_char(victim, victim->first_affect);
	}
	victim->affected_by		= 0;
	victim->affected2_by	= 0;

	if (!IS_NPC(victim))
	{
		if (victim->pcdata->shadowing)
		{
			stop_shadow(victim);
		}

		if (victim->pcdata->shadowed_by)
		{
			stop_shadow(victim->pcdata->shadowed_by);
		}

		if (victim->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
		{
			arena_death(victim);
		}
		else
		{
			player_death(victim);
		}
		pop_call();
		return;
	}

	make_corpse( victim );

	stop_fighting(victim, TRUE);

	if (IS_AFFECTED(victim, AFF_CHARM) && victim->master && !IS_SET(victim->act, ACT_ELEMENTAL))
	{
		send_to_char("Your pet dies a horrible death.\n\r", victim->master);
	}

	junk_mob(victim);

	if (victim->desc && victim->desc->original)
	{
		victim->desc->original->hit -= 50;

		send_to_char("You suffer from the death of your imp!\n\r", victim);

		do_return(victim, NULL);
	}
	pop_call();
	return;
}


void arena_death( CHAR_DATA *victim )
{
	push_call("arena_death(%p)",victim);

	victim->position 		= POS_RESTING;
	victim->hit      		= UMAX( 1, victim->hit  );
	victim->mana     		= UMAX( 1, victim->mana );
	victim->move     		= UMAX( 1, victim->move );

	stop_fighting(victim, TRUE);

	char_from_room(victim);
	char_to_room(victim, ROOM_VNUM_TEMPLE);

	char_reset(victim);

	pop_call();
	return;
}

void player_death( CHAR_DATA *victim )
{
	OBJ_DATA *obj, *obj_next;

	push_call("player_death(%p)",victim);

	if (victim->pcdata->death_room == ROOM_VNUM_SCHOOL)
	{
		if (victim->in_room->area->low_r_vnum != ROOM_VNUM_SCHOOL)
		{
			victim->pcdata->death_room = ROOM_VNUM_TEMPLE;
		}
	}

	check_asn_obj(victim);

	stop_fighting(victim, TRUE);

	make_corpse(victim);

	for (obj = victim->first_carrying ; obj ; obj = obj_next)
	{
		obj_next = obj->next_content;
		if (!IS_SET(obj->extra_flags, ITEM_INVENTORY))
		{
			junk_obj( obj );
		}
	}

	char_from_room(victim);

	if (victim->level < 2)
	{
		char_to_room(victim, ROOM_VNUM_SCHOOL);
	}
	else
	{
		char_to_room(victim, victim->pcdata->death_room);
	}
	victim->pcdata->recall = victim->in_room->vnum;

	victim->position 		= POS_RESTING;
	victim->hit      		= UMAX( 1, victim->hit  );
	victim->mana     		= UMAX( 1, victim->mana );
	victim->move     		= UMAX( 1, victim->move );

	char_reset(victim);

	save_char_obj(victim, NORMAL_SAVE);

	pop_call();
	return;
}

void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
	CHAR_DATA *gch;
	int xp, cnt, group_level, group_count;

	push_call("group_gain(%p,%p)",ch,victim);

	if (IS_AFFECTED(victim, AFF_CHARM))
	{
		pop_call();
		return;
	}

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

	morph_update(ch, victim);

	group_level = group_count = 0;

	for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room)
	{
		if (is_same_group(gch, ch))
		{
			if (group_level < reinc_eq_level(gch))
			{
				group_level = reinc_eq_level(gch);
			}
			group_count += 1;

			gch->alignment -= victim->alignment / 50;

			if (gch->alignment < -1000)
			{
				gch->alignment = -1000;
			}
			if (gch->alignment > 1000)
			{
				gch->alignment = 1000;
			}
		}
	}

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

		xp = xp_compute(gch, victim) * reinc_eq_level(gch) / UMAX(1, group_level);
			
		xp = xp * 100 / (80 + group_count * 20);

		if (gch->pcdata->reincarnation > 0)
		{
			for (cnt = 0 ; cnt < gch->pcdata->reincarnation ; cnt++)
			{
				 xp = xp * 2 / 3;
			}
		}

		if (gch->level == 90)
		{
			xp /= 2;
		}

		if (gch->level > 90)
		{
			xp = xp * 2 / 3;
		}

		ch_printf(gch, god_table[which_god(gch)].exp_msg, xp);
		ch_printf(gch, "\n\r");

		gain_exp(gch, xp);

		check_zap(gch, TRUE);
	}
	pop_call();
	return;
}


/*
	Calculate roughly how much experience a character is worth
*/

int get_exp_worth( CHAR_DATA *ch )
{
	int exp = 0;

	push_call("get_exp_worth(%p)",ch);

	exp += ch->max_hit;

	exp += get_damnodice(ch) * get_damsizedice(ch) + GET_DAMROLL(ch);

	pop_call();
	return exp;
}


/*
	Compute xp for a kill.
	Edit this function to change xp computations.
*/

int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
	int xp;
	int spread;

	push_call("xp_compute(%p,%p)",gch,victim);

	if (gch->in_room == NULL)
	{
		pop_call();
		return(0);
	}

	if (IS_SET(gch->in_room->room_flags, ROOM_RIP))
	{
		pop_call();
		return(0);
	}

	if (IS_SET(gch->in_room->room_flags, ROOM_IS_CASTLE))
	{
		pop_call();
		return(0);
	}

	xp = exp_level(CLASS_MONSTER, victim->level) * (number_range(0, 50) / 100.0 + 0.75);

	if (!IS_NPC(victim))
	{
		xp = 0;
	}

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

	if (which_god(gch) != GOD_NEUTRAL)
	{
		xp = xp * (100 + gch->pcdata->reincarnation) / 100;
	}

	if (gch->desc && gch->desc->mccp)
	{
		xp = xp * 11 / 10;
	}

	spread = 10 + reinc_eq_level(gch) / 10;

	if (reinc_eq_level(gch) > victim->level)
	{
		xp = xp * spread / (reinc_eq_level(gch) - victim->level + spread);
	}

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

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

	xp = number_range(xp * 0.75, xp * 1.25);

	pop_call();
	return xp;
}


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

	push_call("dam_message(%p,%p,%d,%d)",ch,victim,dam,dt);

	if (dt == TYPE_NOFIGHT)
	{
		pop_call();
		return;
	}

	percent = 100 * dam / UMAX(1, victim->max_hit);

	attack = NULL;

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

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

	strcpy(hitYou, (dam <= 0) ? "" : get_color_code(victim, COLOR_YOU_ARE_HIT, VT102_BOLD));
	strcpy(youHit, (dam <= 0) ? "" : get_color_code(ch, COLOR_YOU_HIT, VT102_BOLD));

	str_cpy_max(ch_name, get_name(ch), 64);

	if (dt == TYPE_HIT)
	{
		attack = get_dam_nounce(ch, victim, dt);

		if (attack[0] != '\0')
		{
			sprintf(buf1, "%s's %s %s %s%c", capitalize(ch_name), attack, vp, get_name(victim), punct);

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

			if (ch->level > 50 && dam > 0)
			{
				sprintf(buf2, "%sYou %s $N for %dhp%c", youHit, vs, dam, punct );
			}
			else
			{
				sprintf(buf2, "%sYou %s $N%c", youHit, vs, punct);
			}
			if (victim->level > 50 && dam > 0)
			{
				sprintf(buf3, "%s%s %s you for %dhp%c", hitYou, capitalize(get_name(ch)), vp, dam, punct);
			}
			else
			{
				sprintf(buf3, "%s%s %s you%c", hitYou, capitalize(get_name(ch)), vp, punct);
			}
		}
	}
	else
	{
		attack = get_dam_nounce(ch, victim, dt);

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

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

	/*
		Spam code for combat			-	Chaos 12/20/94
	*/

	for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room)
	{
		if (fch->desc && fch != ch && fch != victim)
		{
			if (fch->position > POS_SLEEPING)
			{
				bool	gch, gvic;
				gch = is_same_group( ch, fch );
				gvic = is_same_group( victim, fch );
				if (gch && !gvic)
				{
					if (dam <= 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 32))
					{
						ch_printf(fch, "%s\n\r", buf1);
					}
					if (dam > 0  && !IS_SET(CH(fch->desc)->pcdata->spam, 16))
					{
						ch_printf(fch, "%s\n\r", buf1);
					}
				}
				else	if (!gch && gvic)
				{
					if (dam <= 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 128))
					{
						ch_printf(fch, "%s\n\r", buf1);
					}
					else if (dam > 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 64))
					{
						ch_printf(fch, "%s%s\n\r", get_color_string(fch,COLOR_PARTY_HIT,VT102_BOLD), buf1);
					}
				}
				else	if (!gch && !gvic)
				{
					if (dam <= 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 512))
					{
						ch_printf(fch, "%s\n\r", buf1);
					}
					if (dam > 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 256))
					{
						ch_printf(fch, "%s\n\r", buf1);
					}
				}
				else
				{
					ch_printf(fch, "%s\n\r", buf1);
				}
			}
		}
	}
	if (dam == 0)
	{
		if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2))
		{
			if (ch->position > POS_SLEEPING)
			{
				act(buf2, ch, NULL, victim, TO_CHAR);
			}
		}
		if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8))
		{
			if (victim->position > POS_SLEEPING)
			{
				act(buf3, ch, NULL, victim, TO_VICT);
			}
		}
	}
	else
	{
		if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 1))
		{
			if (ch->position > POS_SLEEPING)
			{
				act(buf2, ch, NULL, victim, TO_CHAR);
			}
		}
		if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 4))
		{
			if (victim->position > POS_SLEEPING)
			{
				act(buf3, ch, NULL, victim, TO_VICT);
			}
		}
	}

	if (!IS_NPC(ch) && dt > TYPE_HIT)
	{
		if ((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL)
		{
			if (!IS_SET(mud->flags, MUD_DUALFLIP))
			{
				wield = get_eq_char( ch, WEAR_WIELD );
			}
		}
		else
		{
			wield = get_eq_char(ch, WEAR_WIELD);
		}

		if (wield == NULL || wield->item_type != ITEM_WEAPON)
		{
			pop_call();
			return;
		}

		switch (wield->value[0])
		{
			case WEAPON_TYPE_SWORD:		check_improve(ch, gsn_weapon_sword);	break;
			case WEAPON_TYPE_DAGGER:		check_improve(ch, gsn_weapon_dagger);	break;
			case WEAPON_TYPE_AXE:		check_improve(ch, gsn_weapon_axe);		break;
			case WEAPON_TYPE_MACE:		check_improve(ch, gsn_weapon_mace);	break;
			case WEAPON_TYPE_STAFF:		check_improve(ch, gsn_weapon_staff);	break;
			case WEAPON_TYPE_WHIP:		check_improve(ch, gsn_weapon_whip);	break;
			case WEAPON_TYPE_FLAIL:		check_improve(ch, gsn_weapon_flail);	break;
			case WEAPON_TYPE_SPEAR:		check_improve(ch, gsn_weapon_spear);	break;
			case WEAPON_TYPE_CLAW:		check_improve(ch, gsn_weapon_claw);	break;
		}
	}
	pop_call();
	return;
}


int get_body_part( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int type )
{
	int part, pick, cnt, body;

	push_call("get_body_part(%p,%p,%p,%p)",ch,victim,dt,type);

	if (dt != TYPE_HIT)
	{
		pop_call();
		return -1;
	}

	if (IS_NPC(ch) && IS_SET(ch->act, ACT_BODY) && ch->pIndexData->attack_parts && type == 0)
	{
		body = ch->pIndexData->attack_parts;
	}
	else if (IS_NPC(ch) && IS_SET(ch->act, ACT_BODY) && ch->pIndexData->body_parts && type == 1)
	{
		body = ch->pIndexData->body_parts;
	}
	else if (!IS_NPC(ch) || IS_SET(ch->act, ACT_RACE))
	{
		body = race_table[ch->race].attack_parts;
	}
	else
	{
		pop_call();
		return -1;
	}

	for (cnt = part = 0 ; part < MAX_BODY ; part++)
	{
		if (IS_SET(body, 1 << part))
		{
			cnt++;
		}
	}
	pick = number_range(1, cnt);

	for (cnt = part = 0 ; part < MAX_BODY ; part++)
	{
		if (IS_SET(body, 1 << part) && ++cnt == pick)
		{
			pop_call();
			return part;
		}
	}
	pop_call();
	return -1;
}


/*
	Scandum 4-6-2003
*/

int damage_modify( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int dam )
{
	int dam_type = DAM_THRUST;

	push_call("damage_modify(%p,%p,%p,%p)",ch,victim,dt,dam);

	if (dt == TYPE_HIT)
	{
		body_part_attack = get_body_part(ch, victim, dt, 0);
	}

	if (dam <= 0)
	{
		pop_call();
		return 0;
	}

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

	if (!IS_NPC(victim) && dam > 1 && number_percent() < learned(victim, gsn_resilience))
	{
		dam = UMAX(1, UMAX(dam - victim->level / 9, dam / 2));
		if (number_bits(2) == 0)
		{
			check_improve(victim, gsn_resilience);
		}
	}

	if (IS_AFFECTED(victim, AFF_SANCTUARY))
	{
		if (dam > 1)
		{
			dam = dam * 2/3;
		}
	}

	if (is_affected(victim, gsn_black_aura))
	{
		dam = dam * 5/4;
	}

	/*
		Gith Damage +25% astral, +25% ethereall
	*/

	if (ch->in_room)
	{
		if (ch->in_room->sector_type == SECT_ASTRAL && rspec_req(ch, RSPEC_ASTRAL))
		{
			dam = dam * 5/4;
		}
		if (ch->in_room->sector_type == SECT_ETHEREAL && rspec_req(ch, RSPEC_ETHEREAL))
		{
			dam = dam * 5/4;
		}
	}

	if (IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch))
	{
		dam = dam * 10/11;
	}

	if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch))
	{
		dam = dam * 10/11;
	}

	if (dt == TYPE_NOFIGHT)
	{
		pop_call();
		return dam;
	}

	if (dt == TYPE_HIT)
	{
		if (body_part_attack != -1)
		{
			dam_type = body_table[body_part_attack].dam_type;
		}
	}
	else
	{
		if (dt == gsn_martial_arts)
		{
			dam_type = martial_arts_table[martial_arts_attack].dam_type;
		}
		else if (dt == gsn_fisticuffs)
		{
			dam_type = fisticuffs_table[fisticuffs_attack].dam_type;
		}
		else if (dt == gsn_brawling)
		{
			dam_type = brawling_table[brawling_attack].dam_type;
		}
		else if (dt >= 0 && dt < MAX_SKILL)
		{
			dam_type = skill_table[dt].dam_type;
		}
		else if (dt >= TYPE_HIT)
		{
			if (dt < TYPE_HIT+sizeof(attack_table)/sizeof(attack_table[0]))
			{
				dam_type = attack_table[dt - TYPE_HIT].dam_type;
			}
		}
		else
		{
			if (dt != TYPE_UNDEFINED)
			{
				bug("damage_modify: bad dt %d.", dt);
			}
		}
	}

	if (dam <= 0)
	{
		dam = 1;
	}

	if (dam_type == DAM_NONE)
	{
		pop_call();
		return dam;
	}

	if (dam_type == god_table[which_god(victim)].resistance)
	{
		dam = dam * 75 / 100;
	}

	if (IS_UNDEAD(victim))
	{
		if (IS_SET(DAM_LIFE|DAM_POISON|DAM_EVIL, dam_type))
		{
			dam = dam * 75 / 100;
		}
	}

	if (IS_SET(race_table[victim->race].res_low, dam_type))
	{
		dam = dam * 90 / 100;
	}

	if (IS_SET(race_table[victim->race].res_high, dam_type))
	{
		dam = dam * 80 / 100;
	}

	if (IS_SET(race_table[victim->race].vul_low, dam_type))
	{
		dam = dam * 110 / 100;
	}

	if (IS_SET(race_table[victim->race].vul_high, dam_type))
	{
		dam = dam * 120 / 100;
	}

	if (dam <= 0)
	{
		dam = 1;
	}

	pop_call();
	return dam;
}


char *get_dam_nounce( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
	static char *attack;

	push_call("get_dam_nounce(%p,%p,%p)",ch,victim,dt);

	attack = "";

	if (dt == TYPE_HIT)
	{
		if (body_part_attack != -1)
		{
			attack = body_table[body_part_attack].attack;
		}
	}
	else
	{
		if (dt == gsn_martial_arts)
		{
			attack = martial_arts_table[martial_arts_attack].message;
		}
		else if (dt == gsn_fisticuffs)
		{
			attack = fisticuffs_table[fisticuffs_attack].message;
		}
		else if (dt == gsn_brawling)
		{
			attack = brawling_table[brawling_attack].message;
		}
		else if (dt == gsn_object_rape)
		{
			attack = &mpdamstring[0];
		}
		else if (dt >= 0 && dt < MAX_SKILL)
		{
			attack = skill_table[dt].noun_damage;
		}
		else if (dt >= TYPE_HIT)
		{
			OBJ_DATA *obj;
			if (IS_SET(mud->flags, MUD_DUALFLIP) && get_eq_char(ch, WEAR_DUAL_WIELD) != NULL)
			{
				obj = get_eq_char(ch, WEAR_DUAL_WIELD);
			}
			else
			{
				obj = get_eq_char(ch, WEAR_WIELD);
			}
			if (obj->pIndexData->attack_string[0] != '\0')
			{
				attack = obj->pIndexData->attack_string;
			}
			else if (dt < TYPE_HIT+sizeof(attack_table)/sizeof(attack_table[0]))
			{
				attack = attack_table[dt - TYPE_HIT].message;
			}
		}
		else
		{
			if (dt != TYPE_UNDEFINED)
			{
				bug("get_dam_nounce: bad dt %d.", dt);
			}
			attack	= attack_table[0].message;
		}
	}
	pop_call();
	return attack;
}

int get_damnodice( CHAR_DATA *ch)
{
	int dam = 0;

	push_call("get_damnodice(%p)",ch);

	if (IS_NPC(ch))
	{
		dam = ch->npcdata->damnodice;
	}
	else
	{
		if (learned(ch, gsn_fisticuffs) || learned(ch, gsn_martial_arts))
		{
			if (multi_skill_level(ch, gsn_fisticuffs) >= multi_skill_level(ch, gsn_martial_arts))
			{
				dam = 3 + multi_skill_level(ch, gsn_fisticuffs) * learned(ch, gsn_fisticuffs) / 150;
			}
			else
			{
				dam = 3 + multi_skill_level(ch, gsn_martial_arts) * learned(ch, gsn_martial_arts) / 150;
			}
			if (is_affected(ch, gsn_stone_fist))
			{
				dam += 3 + multi_skill_level(ch, gsn_stone_fist) / 20;
			}
		}
		else
		{
			dam = 1;
		}

	}
	pop_call();
	return dam;
}

int get_damsizedice( CHAR_DATA *ch)
{
	int dam = 0;

	push_call("get_damsizedice(%p)",ch);

	if (IS_NPC(ch))
	{
		dam = ch->npcdata->damsizedice;
	}
	else
	{
		if (learned(ch, gsn_fisticuffs) || learned(ch, gsn_martial_arts))
		{
			dam = 2;
		}
		else
		{
			dam = 4 + ch->level * 2 / 3;

			if (is_affected(ch, gsn_stone_fist))
			{
				dam += 10 + multi_skill_level(ch, gsn_stone_fist) / 10;
			}
		}
	}
	pop_call();
	return dam;
}

/*
	Disarm a creature.
	Caller must check for successful attack.
*/

void disarm( CHAR_DATA *ch, CHAR_DATA *victim )
{
	OBJ_DATA *obj;

	push_call("disarm(%p,%p)",ch,victim);

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

	if (get_eq_char(victim, WEAR_DUAL_WIELD) != NULL && number_bits(1) == 0)
	{
		obj = get_eq_char(victim, WEAR_DUAL_WIELD);
	}

	if (IS_SET(obj->extra_flags,ITEM_INVENTORY))
	{
		send_to_char( "You failed.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_see_obj(ch, obj))
	{
		if (number_percent() > 33)
		{
			send_to_char( "You failed.\n\r", ch);
			pop_call();
			return;
		}
	}

	if (get_eq_char(ch, WEAR_WIELD) == NULL && number_bits(1) == 0)
	{
		send_to_char( "You failed.\n\r", ch);
		pop_call();
		return;
	}

	if (IS_SET(ch->attack, ATTACK_DISARM))
	{
		pop_call();
		return;
	}
	else
	{
		SET_BIT(ch->attack, ATTACK_DISARM);
	}

	if (number_bits(1) == 0 && is_affected(victim, gsn_stone_fist))
	{
		act( "$n tries to disarm you, but your stone fist's grasp is unbreakable.", ch, NULL, victim, TO_VICT);
		act( "You try to disarm $N, but $S stone fist's grasp is unbreakable.",     ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}

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

	if (!IS_NPC(victim) && learned(victim, gsn_rearm) > number_percent())
	{
		if (can_see_in_room(victim, victim->in_room) && !IS_AFFECTED(victim, AFF_BLIND))
		{
			act( "You rearm yourself!!!", ch, NULL, victim, TO_VICT    );
			act( "$N rearms $Mself!!!",   ch, NULL, victim, TO_CHAR    );
			act( "$N rearms $Mself!!!",   ch, NULL, victim, TO_NOTVICT );
			check_improve(victim, gsn_rearm);
			pop_call();
			return;
		}
	}

	unequip_char(victim, obj);

	pop_call();
	return;
}

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

	push_call("do_cripple(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch, gsn_cripple) == -1)
	{
		send_to_char( "You better leave the street fighting to the marauders.\n\r", ch);
		pop_call();
		return;
	}

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

	wait_state(ch, skill_table[gsn_trip].beats);

	if (!IS_AFFECTED(ch, AFF_TRUESIGHT) && IS_AFFECTED(victim, AFF2_MIRROR_IMAGE))
	{
		damage(ch, victim, 0, gsn_cripple);
	}

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_cripple))
	{
		ch_printf(ch, "%s evades your vicious kick.\n\r", capitalize(get_name(victim)));
		pop_call();
		return;
	}

	act( "$n cripples you with a well aimed kick!", ch, NULL, victim, TO_VICT    );
	act( "You cripple $N with a well aimed kick!", ch, NULL, victim, TO_CHAR    );
	act( "$n cripples $N with a well aimed kick!", ch, NULL, victim, TO_NOTVICT );

	check_improve(ch, gsn_cripple);

	af.type      = gsn_cripple;
	af.duration  = number_range(1,2);
	af.bitvector = 0;

	if (IS_NPC(victim))
	{
		af.modifier  = number_range(5, ch->level/5);
		af.location  = APPLY_AC;
	}
	else
	{
		af.modifier  = -1 * number_range(1, ch->level/20);
		af.location  = APPLY_DEX;
	}
	affect_join( victim, &af );

	victim->speed = UMIN(victim->speed, get_max_speed(victim));

	pop_call();
	return;
}

/*
	Trip, player version
*/

void do_trip( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	char text2[MAX_STRING_LENGTH];

	push_call("do_trip(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch, gsn_trip) == -1)
	{
		send_to_char( "You better leave the tripping to the street fighters.\n\r", ch);
		pop_call();
		return;
	}

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

	wait_state(ch, skill_table[gsn_trip].beats);

	if (!IS_AFFECTED(ch, AFF_TRUESIGHT) && IS_AFFECTED(victim, AFF2_MIRROR_IMAGE))
	{
		damage(ch, victim, 0, gsn_trip);
	}

	if (CAN_FLY(victim))
	{
		sprintf(text2,"%s flies over your outstretched leg.\n\r", capitalize(get_name(victim)));
		send_to_char(text2, ch);
		pop_call();
		return;
	}

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_trip))
	{
		sprintf(text2,"%s jumps over your outstretched leg.\n\r", capitalize(get_name(victim)));
		send_to_char(text2, ch);
		pop_call();
		return;
	}

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

	if (!check_tumble(NULL, victim))
	{
		victim->position = POS_RESTING;
		wait_state(victim, skill_table[gsn_trip].beats / 2);
	}
	pop_call();
	return;
}

/*
	Trip, mob version
*/

void trip( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("trip(%p,%p)",ch,victim);

	if (IS_SET(ch->attack, ATTACK_TRIP))
	{
		pop_call();
		return;
	}
	else
	{
		SET_BIT(ch->attack, ATTACK_TRIP);
	}

	if (victim->position <= POS_RESTING)
	{
		pop_call();
		return;
	}

	if (CAN_FLY(victim))
	{
		ch_printf(ch, "%s flies over your outstretched leg.\n\r", capitalize(get_name(victim)));
		pop_call();
		return;
	}

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

	if (!check_tumble(NULL, victim))
	{
		victim->position = POS_RESTING;
	}
	pop_call();
	return;
}

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

	push_call("do_kill(%p,%p)",ch,argument);

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

	found  = FALSE;
	victim = NULL;

	one_argument(argument, arg);

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

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

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

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	if ( ch->position == POS_FIGHTING )
	{
		if (who_fighting(ch) == victim
		||  IS_NPC(ch)
		||  number_percent() > learned(ch, gsn_attack))
		{
			send_to_char( "You do the best you can!\n\r", ch);
			pop_call();
			return;
		}
		else
		{
			stop_fighting(ch, FALSE);
			check_improve(ch, gsn_attack);
		}
	}

	if (!IS_NPC(ch) && ch->pcdata->auto_flags == AUTO_QUICK && ch->hit > ch->pcdata->wimpy && ch->wait == 0)
	{
		int sn;
		bool ms	= FALSE;

		if (!str_prefix("mass ", ch->pcdata->auto_command))
		{
			ms = TRUE;
			sn = skill_lookup(&ch->pcdata->auto_command[5]);
		}
		else
		{
			sn = skill_lookup(ch->pcdata->auto_command);
		}

		if (sn != -1 && is_spell(sn) && ch->mana >= 3 * get_mana(ch, sn))
		{
			sprintf(buf, "'%s'", skill_table[sn].name);

			set_fighting(ch,victim);
			set_fighting(victim,ch);

			if (ms)
			{
				do_mass(ch, buf);
			}
			else
			{
				do_cast(ch, buf);
			}
			pop_call();
			return;
		}
	}

	wait_state(ch, PULSE_VIOLENCE/2);
	multi_hit(ch, victim, TYPE_UNDEFINED);

	pop_call();
	return;
}

void do_murde( CHAR_DATA *ch, char *argument )
{
	push_call("do_murde(%p,%p)",ch,argument);

	send_to_char( "If you want to MURDER, spell it out.\n\r", ch );

	pop_call();
	return;
}

void add_to_victory_list( CHAR_DATA *ch, CHAR_DATA *victim)
{
	int i;
	char buf[MAX_STRING_LENGTH];

	push_call("add_to_victory_list(%p,%p)",ch,victim);

	for (i = 1 ; i < VICTORY_LIST_SIZE ; i++)
	{
		STRFREE(victory_list[i-1]);
		victory_list[i-1] = STRALLOC(victory_list[i]);
	}
	sprintf(buf, "Z%12s (%2dx Level %2d) %12s (%2dx Level %2d) %s", ch->name, ch->pcdata->reincarnation, ch->level, victim->name, victim->pcdata->reincarnation, victim->level, get_time_string(mud->current_time));

	RESTRING(victory_list[i-1], buf);

	save_victors();
	pop_call();
	return;
}

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

	push_call("do_murder(%p,%p)",ch,argument);

	one_argument( argument, arg );

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

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

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

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

	if (IS_NPC(ch) || IS_NPC(victim))
	{
		send_to_char( "You may not murder them.\n\r", ch );
		pop_call();
		return;
	}

	if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
	{
		send_to_char("Use kill instead.\n\r", ch);
		pop_call();
		return;
	}

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

	if (!can_attack (ch, victim) )
	{
		send_to_char( "You may not murder that person.\n\r", ch);
		pop_call();
		return;
	}

	if (victim->pcdata->just_died_ctr > 0)
	{
		send_to_char("That person is currently protected by their god.\n\r", ch);
		pop_call();
		return;
	}

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

	if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF))
	{
		if (victim->hit < victim->max_hit / 5)
		{
			send_to_char( "It would be dishonorable to murder someone so badly injured.\n\r", ch);
			pop_call();
			return;
		}

		if (ch->pcdata->last_connect + 120 > mud->current_time)
		{
			ch_printf(ch, "You must wait %d seconds before you can murder anyone.\n\r", ch->pcdata->last_connect + 120 - mud->current_time);
			pop_call();
			return;
		}
	}

	if (!IS_NPC(victim ) && victim->pcdata->corpse != NULL)
	{
		ch_printf(ch, "%s has been killed quite recently.\n\r", get_name(victim));
		pop_call();
		return;
	}

	/*
		Code for total and max pvnum attacks  -  Chaos 5/6/99
	*/

	if (!check_add_attack(ch, victim))
	{
		ch_printf(ch, "%s has been attacked too many times.\n\r", get_name(victim));
		pop_call();
		return;
	}

	sprintf(buf, "%s", get_name(ch));
	do_battle("%s battles 'Help!  I am being attacked by %s!'", get_name(victim), buf);

	check_killer( ch, victim );

	if (IS_AFFECTED(victim, AFF2_HAS_FLASH))
	{
		if (number_percent() < learned(victim, gsn_flash_powder)/3)
		{
			AFFECT_DATA af;
			int attempt;
			ROOM_INDEX_DATA *was_in;

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

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

			was_in = victim->in_room;

			for (attempt = 0 ; attempt < 6 ; attempt++)
			{
				int door;

				door = number_door();

				if (!is_valid_exit(victim, was_in, number_door()))
				{
					continue;
				}

				move_char(victim, door, TRUE);

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

	ch->pcdata->just_died_ctr = 0;

	clear_attack_list(ch);

	log_printf("ROOM [%u] MURDER %s attacking %s", ch->in_room->vnum, ch->name, victim->name);

	if (ch->pcdata->auto_flags == AUTO_QUICK && ch->hit > ch->pcdata->wimpy && ch->wait == 0)
	{
		int sn;
		bool ms	= FALSE;

		if (!str_prefix("mass ", ch->pcdata->auto_command))
		{
			ms = TRUE;
			sn = skill_lookup(&ch->pcdata->auto_command[5]);
		}
		else
		{
			sn = skill_lookup(ch->pcdata->auto_command);
		}

		if (sn != -1 && is_spell(sn) && ch->mana >= 3 * get_mana(ch, sn))
		{
			sprintf(buf, "'%s'", skill_table[sn].name);

			set_fighting(ch,victim);
			set_fighting(victim,ch);

			if (ms)
			{
				do_mass(ch, buf);
			}
			else
			{
				do_cast(ch, buf);
			}
			pop_call();
			return;
		}
	}

	/*
		bs chance based on multi_skill_level - Scandum 12/02/02
	*/

	if (number_range(50, 99) < 100 * victim->hit / UMAX(1, victim->max_hit)
	&& check_hit(ch, victim, GET_HITROLL(ch), gsn_backstab)
	&& number_percent() < 100*multi_skill_level(ch, gsn_backstab)/ch->level)
	{
		OBJ_DATA * obj;
		if ((obj = get_eq_char(ch,WEAR_WIELD)) != NULL && (obj->value[3]==11 || obj->value[3]==2))
		{
			one_hit(ch, victim, gsn_backstab);
			wait_state(ch, skill_table[gsn_backstab].beats);
		}
		pop_call();
		return;
	}
	wait_state(ch, PULSE_VIOLENCE/2);
	multi_hit( ch, victim, TYPE_UNDEFINED );

	pop_call();
	return;
}


void backstab( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("backstab(%p,%p)",ch,victim);

	/*
		Anatomy skill - Martin 4/8/98
	*/

	if (IS_NPC(victim) && !IS_NPC(ch) && victim->level < (ch->level-10)
	&& number_percent() < learned(ch, gsn_anatomy)/12)
	{
		if (number_bits(1) == 0)
		{
			act( "$n thrusts $p into $N's heart.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_ROOM);
			act( "You thrust $p into $N's heart.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_CHAR);
		}
		else
		{
			act( "$n slits $N's throat with $p.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_ROOM);
			act( "You slit $N's throat with $p.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_CHAR);
		}
		check_improve(ch, gsn_anatomy);
		one_hit( ch, victim, gsn_anatomy );
		pop_call();
		return;
	}
	one_hit( ch, victim, gsn_backstab );
	pop_call();
	return;
}

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

	push_call("do_backstab(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (!IS_NPC(ch) && multi(ch, gsn_backstab) == -1)
	{
		send_to_char("You are not that practiced a cut-throat.\n\r", ch );
		pop_call();
		return;
	}

	if (argument[0] == '\0')
	{
		for (victim = ch->in_room->first_person ; victim ; victim = victim->next_in_room)
		{
			if (IS_NPC(victim) && ch != victim && ch->level <= victim->level-(ch->level*2+10))
			{
				if (can_see(ch, victim))
				{
					ch_printf(ch, "%s doesn't think you should fight in here.\n\r", capitalize(victim->short_descr));
					pop_call();
					return;
				}
			}
		}

		for (victim = ch->in_room->first_person ; victim ; victim = victim->next_in_room)
		{
			if (can_see(ch, victim) && !IS_AFFECTED(victim, AFF_CHARM)
			&& IS_NPC(victim) && ch != victim && !is_same_group(ch,victim))
			{
				break;
			}
		}
		if (victim == NULL)
		{
			send_to_char( "You cannot see anyone you can backstab.\n\r", ch);
			pop_call();
			return;
		}
	}
	else
	{
		if ((victim = get_char_room(ch, arg)) == NULL)
		{
			send_to_char( "They aren't here.\n\r", ch );
			pop_call();
			return;
		}
	}

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

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	if (!IS_NPC(ch) && !IS_NPC(victim))
	{
		if (ch->in_room->area->low_r_vnum != ROOM_VNUM_ARENA)
		{
			send_to_char( "You may not backstab another player.\n\r", ch);
			pop_call();
			return;
		}
	}

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

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

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

	wait_state(ch, skill_table[gsn_backstab].beats);

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_backstab)
	||  number_range(50, 100) > 100 * victim->hit / UMAX(1, victim->max_hit))
	{
		damage( ch, victim, 0, gsn_backstab);
		pop_call();
		return;
	}
	backstab(ch,victim);
	pop_call();
	return;
}

void do_flee( CHAR_DATA *ch, char *argument )
{
	ROOM_INDEX_DATA *was_in = NULL;
	ROOM_INDEX_DATA *now_in = NULL;
	CHAR_DATA *victim       = NULL;
	CHAR_DATA *fch          = NULL;
	EXIT_DATA *pexit        = NULL;
	int dir, attempt, exp, hunt_door, hunt_chance;

	int door, door_count;
	bool valid_exits[6]={FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};
	char buf[MAX_INPUT_LENGTH];

	push_call("do_flee(%p,%p)",ch,argument);

	/*
		Check berserk and position for link lost players - Scandum 21-08-2002
	*/

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

	if (ch->position < POS_FIGHTING)
	{
		send_to_char("Get up first!.\n\r", ch);
		pop_call();
		return;
	}

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

	was_in = ch->in_room;
	now_in = ch->in_room;

	dir = -1;

	if (argument[0] && number_percent() < learned(ch, gsn_withdraw))
	{
		dir = direction_door(argument);
	}

	if (IS_SET(ch->in_room->room_flags, ROOM_SMOKE)
	&& number_bits(2)
	&& !IS_AFFECTED(ch, AFF_TRUESIGHT))
	{
		send_to_char( "You blunder around and get lost in the smoke!\n\r", ch);
		if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE))
		{
			wait_state(ch, PULSE_VIOLENCE / 4);
		}
		else
		{
			wait_state(ch, PULSE_VIOLENCE / 8);
		}
		pop_call();
		return;
	}

	if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !CAN_FLY(ch) && which_god(ch) != GOD_ULMO)
	{
		if (number_bits(2) == 0 && number_percent() > get_curr_dex(ch))
		{
			switch (number_bits(1))
			{
				case 0:
					act("You try to flee but your feet slip on the icy surface.",		ch, NULL, NULL, TO_CHAR);
					act("$n tries to flee but $s feet slip on the icy surface.",		ch, NULL, NULL, TO_ROOM);
					break;
				case 1:
					act("Your feet slip as you try to flee and you crash to the ice.",	ch, NULL, NULL, TO_CHAR);
					act("$n's feet slip as $e tries to flee and $e crashes to the ice.",	ch, NULL, NULL, TO_ROOM);
					break;
			}
			wait_state(ch, PULSE_VIOLENCE / 4);

			ch->position = POS_SITTING;

			pop_call();
			return;
		}
	}

	if (is_affected(ch, gsn_cripple) && number_bits(1) == 0)
	{
		act("You try to limp away from combat, but $N does not let you get very far.", ch, NULL, victim, TO_CHAR);
		act("$n tries to limp away from combat, but you do not let $m get very far.",  ch, NULL, victim, TO_VICT);
		act("$n tries to limp away from combat, but $N does not let $m get very far.", ch, NULL, victim, TO_NOTVICT);
		if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE))
		{
			wait_state( ch, PULSE_VIOLENCE/2 );
		}
		else
		{
			wait_state( ch, PULSE_VIOLENCE/4 );
		}
		pop_call();
		return;
	}

	for (door = 0, door_count = 0 ; door < 6 ; door++)
	{
		if (cspec_req(ch, CSPEC_QUICK_FLEE) || dir == door)
		{
			if (!can_move_char(ch, door))
			{
				continue;
			}
		}
		else
		{
			if ((pexit = get_exit(was_in->vnum, door)) == NULL)
			{
				continue;
			}
			if (!can_use_exit(ch, pexit))
			{
				continue;
			}
			if (IS_SET(pexit->exit_info, EX_CLOSED))
			{
				continue;
			}
			if (IS_NPC(ch))
			{
				if (IS_SET(room_index[pexit->to_room]->room_flags, ROOM_NO_MOB))
				{
					continue;
				}
				if (room_index[pexit->to_room]->area != ch->in_room->area)
				{
					continue;
				}
				if (IS_SET(ch->act, ACT_STAY_SECTOR) && ch->reset && room_index[pexit->to_room]->sector_type != room_index[ch->reset->arg3]->sector_type)
				{
					continue;
				}
			}
		}
		valid_exits[door] = TRUE;
		door_count++;
	}

	if (door_count == 0)
	{
		send_to_char("Ah!!!  You can't find an exit!\n\r",ch);
		if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE))
		{
			wait_state( ch, PULSE_VIOLENCE/4 );
		}
		else
		{
			wait_state( ch, PULSE_VIOLENCE/8 );
		}
		pop_call();
		return;
	}

	if (!can_see_in_room(ch, now_in) || IS_AFFECTED(ch, AFF_BLIND) || IS_NPC(ch)
	|| (dir == -1 && !cspec_req(ch, CSPEC_QUICK_FLEE) && !rspec_req(ch,RSPEC_EASY_FLEE) && !IS_OUTSIDE(ch)))
	{
		for (attempt = 0 ; attempt < 6; attempt++)
		{
			door = number_door();
			if (valid_exits[door] != TRUE)
			{
				continue;
			}
			move_char(ch, door, TRUE);
			now_in = ch->in_room;
			break;
		}
	}
	else if (was_in == now_in)
	{
		if (dir == -1)
		{
			door = number_door();
		}
		else
		{
			door = dir;
		}
		while(valid_exits[door] != TRUE)
		{
			door++;
			if (door > 5)
			{
				door = 0;
			}
		}
		move_char(ch, door, TRUE);
		now_in = ch->in_room;
	}

	if (was_in != now_in)
	{
		char_from_room( ch );
		char_to_room( ch, was_in->vnum );
		act( "$n flees head over heels!", ch, NULL, NULL, TO_ROOM );
		char_from_room( ch );
		char_to_room( ch, now_in->vnum );
		act( "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM);
	}
	if (was_in != now_in)
	{
		if (IS_NPC(ch) || ch->level >= 95)
		{
			send_to_char( "You flee head over heels from combat.\n\r", ch);
		}
		else
		{
			if (rspec_req(ch,CSPEC_QUICK_FLEE))
			{
				exp = 25+ch->level*ch->level*1.5;
			}
			else
			{
				exp = 50+ch->level*ch->level*2.5;
			}
			sprintf( buf, "You flee head over heels from combat, losing %d experience.\n\r", exp);
			send_to_char( buf, ch);
			gain_exp( ch, 0-exp);
		}
		check_improve(ch, gsn_withdraw);
	}
	/*
		Hunt skill - Chaos 11/19/93
	*/

	if (was_in != now_in)
	{
		for (fch = was_in->first_person ; fch ; fch = fch->next_in_room)
		{
			if (IS_NPC(fch))
			{
				if (was_in->area != now_in->area)
				{
					continue;
				}
				if (IS_SET(ch->act, ACT_STAY_SECTOR) && ch->reset && now_in->sector_type != room_index[ch->reset->arg3]->sector_type)
				{
					continue;
				}
			}

			if (fch->fighting
			&&  fch->fighting->who == ch
			&&  IS_AFFECTED(fch, AFF_HUNT)
			&& !IS_AFFECTED(fch, AFF_CHARM))
			{
				hunt_chance  = learned(fch, gsn_hunt)           / 4;
				hunt_chance += learned(fch, gsn_greater_hunt)   / 5;
				hunt_chance += 33 * multi_skill_level(fch, gsn_hunt) / fch->level;
				hunt_chance -= can_hear(fch, ch) ? 0 : 10;
				hunt_chance -= can_see(fch, ch)  ? 0 : 10;
				hunt_chance -= rspec_req(ch, RSPEC_EASY_FLEE) ? 10 : 0;
				hunt_chance += fch->speed * 10;
				hunt_chance -=  ch->speed * 10;
				hunt_chance -= learned(ch, gsn_withdraw) / 10;

				if (!IS_NPC(fch) && IS_SET(fch->act, PLR_WIZTIME))
				{
					ch_printf_color(fch, "{078}(do_flee() hunt_chance: %d)\n\r", hunt_chance);
				}
				if (number_percent() < hunt_chance)
				{
					if (IS_AFFECTED(fch, AFF_BLIND)) /* added a harder hunt for blinded hunters, Manwe */
					{
						hunt_door = number_door();

						if (fch->in_room->exit[hunt_door] != 0)
						{
							pexit = fch->in_room->exit[hunt_door];

							if (room_index[pexit->to_room] == NULL)
							{
								send_to_char("You try to hunt them down, but you blunder into a wall.\n\r",fch);
								act("$n starts hunting, but blunders into a wall!",fch, NULL, NULL, TO_ROOM);
							}
							else if (IS_SET(pexit->exit_info, EX_CLOSED) && !IS_AFFECTED(fch, AFF_PASS_DOOR) && !rspec_req(ch,RSPEC_PASS_DOOR))
							{
								send_to_char("You try to hunt them down, but you smash into a closed door.\n\r",fch);
								act("$n starts hunting, but smashes into a closed door!",fch, NULL, NULL, TO_ROOM);
							}
							else if (IS_SET(pexit->exit_info, EX_CLOSED) && IS_SET(pexit->exit_info, EX_PASSPROOF))
							{
								send_to_char("You try to hunt them down, but you smash into a closed door.\n\r",fch);
								act("$n starts hunting, but smashes into a closed door!",fch, NULL, NULL, TO_ROOM);
							}
							else
							{
								char_from_room(fch);
								char_to_room(fch, pexit->to_room);

								if (fch->in_room == ch->in_room)
								{
									send_to_char("You try to hunt them down, and now you SMELL them...\n\r",fch);
									send_to_char("You have been hunted down.\n\r",ch);
									stop_fighting(ch,TRUE);
									stop_fighting(fch,TRUE);
									set_fighting(ch,fch);
									set_fighting(fch,ch);
									pop_call();
									return;
								}
								else
								{
									send_to_char("You tried to hunt them down, but now you're lost.\n\r",fch);
									act("$n looks as if they're hunting, but looks somehow lost.",fch, NULL, NULL, TO_ROOM);
								}
							}
						}
						else
						{
							send_to_char("You try to hunt them down, but you blunder into a wall.\n\r",fch);
							act("$n starts hunting, but blunders into a wall!",fch, NULL, NULL, TO_ROOM);
						}
					}
					else
					{
						send_to_char("You hunt them down!\n\r", fch);
						check_improve(fch, gsn_hunt);
						check_improve(fch, gsn_greater_hunt);
						char_from_room( fch );
						char_to_room( fch, ch->in_room->vnum );
						send_to_char("You have been hunted down.\n\r", ch);

						stop_fighting( ch, TRUE);
						stop_fighting( fch, TRUE);
						set_fighting( ch, fch);
						set_fighting( fch, ch);
						pop_call();
						return;
					}
				}
			}
		}
	}

	if (was_in == now_in && !IS_SET(now_in->room_flags, ROOM_SAFE))
	{
		if (IS_NPC(ch) || ch->level >= 95)
		{
			send_to_char("You failed!\n\r", ch);
		}
		else
		{
			exp = 20+ch->level*ch->level*1;
			sprintf( buf, "You failed!  You lose %d exp.\n\r", exp);
			send_to_char( buf, ch);
			gain_exp( ch, -exp);
		}
		if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE))
		{
			wait_state( ch, PULSE_VIOLENCE/4 );
		}
		else
		{
			wait_state( ch, PULSE_VIOLENCE/8 );
		}
		pop_call();
		return;
	}

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


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

	push_call("do_rescue(%p,%p)",ch,argument);

	one_argument( argument, arg );

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

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

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

	if (!IS_NPC(ch) && IS_NPC(victim) && victim->master!=ch)
	{
		send_to_char( "They do not need your help.\n\r", ch );
		pop_call();
		return;
	}

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

	for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room)
	{
		if (fch->fighting && fch->fighting->who == victim)
		{
			break;
		}
	}

	if (fch == NULL)
	{
		send_to_char( "That person isn't under attack.\n\r", ch );
		pop_call();
		return;
	}

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

	wait_state( ch, skill_table[gsn_rescue].beats );

	if (number_percent() > learned(ch, gsn_rescue)
	|| !is_same_group(ch, victim) || !IS_NPC(fch))
	{
		send_to_char( "You failed to rescue.\n\r", ch );
		ch_printf(victim, "%s tried to rescue you, but failed!\n\r", get_name(ch));
		pop_call();
		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);

	for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room)
	{
		if (fch->fighting && fch->fighting->who == victim)
		{
			fch->fighting->who = ch;
			break;
		}
	}
	pop_call();
	return;
}


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

	push_call("do_headbutt(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch, gsn_head_butt) == -1)
	{
		send_to_char( "You better leave the fisticuffs to the shamans.\n\r", ch);
		pop_call();
		return;
	}

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

	wait_state( ch, skill_table[gsn_head_butt].beats );

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_head_butt))
	{
		damage( ch, victim, 0, gsn_head_butt );
		pop_call();
		return;
	}
	else
	{
		int dam = 5 + GET_DAMROLL(ch);

		if (IS_NPC(ch))
		{
			dam += number_range(1, ch->level*2);
		}
		else
		{
			dam += number_range(multi_skill_level(ch, gsn_head_butt)/2, multi_skill_level(ch, gsn_head_butt)*2);
		}
		damage(ch, victim, dam, gsn_head_butt);
		check_improve(ch, gsn_head_butt);
	}
	pop_call();
	return;
}

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

	push_call("do_kick(%p,%p)",ch,argument);

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

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

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

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_kick))
	{
		damage( ch, victim, 0, gsn_kick );
		pop_call();
		return;
	}
	else
	{
		int dam = 5 + GET_DAMROLL(ch);

		if (IS_NPC(ch))
		{
			dam += number_range(1, ch->level*2);
		}
		else
		{
			dam += number_range(multi_skill_level(ch, gsn_kick), multi_skill_level(ch, gsn_kick)*4/3);
		}
		damage(ch, victim, dam, gsn_kick);
		check_improve(ch, gsn_kick);
	}
	pop_call();
	return;
}

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

	push_call("do_bash(%p,%p)",ch,argument);

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

	if (learned(ch, gsn_bash) == 0)
	{
		send_to_char( "You better leave the martial arts to fighters.\n\r", ch);
		pop_call();
		return;
	}

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

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

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_bash))
	{
		damage( ch, victim, 0, gsn_bash );
		pop_call();
		return;
	}
	else
	{
		int dam = 10 + GET_DAMROLL(ch);

		if (IS_NPC(ch))
		{
			dam += number_range(1, ch->level*3);
		}
		else
		{
			dam += number_range(multi_skill_level(ch, gsn_bash), multi_skill_level(ch, gsn_bash)*2);
		}

		if (IS_AFFECTED(ch, AFF_TRUESIGHT) || !IS_AFFECTED(victim, AFF2_MIRROR_IMAGE))
		{
			if (number_bits(2) == 0)
			{
				act( "$n sends you sprawling with $s powerful bash!",  ch, NULL, victim, TO_VICT   );
				act( "You send $N sprawling with your powerful bash!", ch, NULL, victim, TO_CHAR   );
				act( "$n sends $N sprawling with $s powerful bash!",   ch, NULL, victim, TO_NOTVICT);

				wait_state(victim, skill_table[gsn_bash].beats/2);
				victim->position = POS_RESTING;
			}
		}
		damage(ch, victim, dam, gsn_bash);
		check_improve(ch, gsn_bash);
	}
	pop_call();
	return;
}

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

	push_call("do_whirl(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && which_god(ch) != GOD_MANWE)
	{
		send_to_char( "You better leave the airial fighting to the Manwe followers.\n\r", ch);
		pop_call();
		return;
	}

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

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

	wait_state(ch, skill_table[gsn_whirl].beats);

	act("You spin around your pole in a whirlwind of movement!", ch, NULL, NULL, TO_CHAR);
	act("$n spins around $s pole in a whirlwind of movement!",   ch, NULL, NULL, TO_ROOM);

	for (victim = ch->in_room->first_person ; victim ; victim = victim_next)
	{
		victim_next = victim->next_in_room;

		if (can_mass_attack(ch, victim))
		{
			if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_whirl))
			{
				damage( ch, victim, 0, gsn_whirl);
				pop_call();
				return;
			}
			else
			{
				int dam = GET_DAMROLL(ch);

				if (IS_NPC(ch))
				{
					dam += number_range(1, ch->level*2);
				}
				else
				{
					dam += number_range(1, multi_skill_level(ch, gsn_whirl)*7/3);
				}
				damage(ch, victim, dam, gsn_whirl);
				check_improve(ch, gsn_whirl);
			}
		}
	}
	pop_call();
	return;
}

void do_acupunch(CHAR_DATA *ch, char *argument)
{
	CHAR_DATA *victim;
	int level, stun, dmgL, dmgH;

	push_call("do_acupunch(%p,%p)",ch,argument);

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

	if (!IS_NPC(ch) && multi(ch,gsn_acupunch) == -1)
	{
		send_to_char("Don't try this at home!!!\n\r",ch);
		pop_call();
		return;
	}

	if (get_eq_char(ch, WEAR_WIELD) != NULL)
	{
		send_to_char("You cannot punch while wielding a weapon.\n\r", ch);
		pop_call();
		return;
	}

	if (IS_NPC(ch))
	{
		level = ch->level;
	}
	else
	{
		level = multi_skill_level(ch, gsn_acupunch);
	}

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

	wait_state(ch, skill_table[gsn_acupunch].beats);

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_acupunch))
	{
 		damage(ch,victim,0,gsn_acupunch);
 		pop_call();
 		return;
	}
	dmgL = level / 2;

	switch (number_range(1, 9))
	{
		default: dmgH = level * 2; stun = 0; break;
		case 1:  dmgH = level * 2; stun = 1; break;
		case 2:  dmgH = level * 3; stun = 2; break;
		case 3:  dmgH = level * 4; stun = 3; break;
	}

	damage(ch, victim, GET_DAMROLL(ch)+number_range(dmgL,dmgH), gsn_acupunch);

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

	if (stun)
	{
		act("$n stuns you and you go down!", ch, NULL, victim, TO_VICT);
		act("$n stuns $N and $E goes down!", ch, NULL, victim, TO_NOTVICT);
		act("You stun $N and $E goes down!", ch, NULL, victim, TO_CHAR);
	}

	switch (stun)
	{
		case 1:
			victim->position = POS_SITTING;
			break;
		case 2:
			victim->position = POS_RESTING;
			wait_state(victim, skill_table[gsn_acupunch].beats / 3);
			break;
		case 3:
			victim->position = POS_SLEEPING;
			wait_state(victim,(skill_table[gsn_acupunch].beats) / 2);
			break;
	}
	check_improve(ch, gsn_acupunch);
	pop_call();
	return;
}


void fisticuffs( CHAR_DATA *ch, CHAR_DATA *victim, int dam )
{
	int level;

	push_call("fisticuffs(%p,%p,%p)",ch,victim,dam);

	level = multi_skill_level(ch, gsn_fisticuffs);

	if (number_bits(1) == 0)
	{
		fisticuffs_attack = number_range(level/30, level/17);
	}
	else
	{
		fisticuffs_attack = number_range(0,5);
	}

	fisticuffs_attack = URANGE(0, fisticuffs_attack, 5);

	switch (fisticuffs_attack)
	{
		case 0: dam = (int) dam * 1.1; break;
		case 1: dam = (int) dam * 1.2; break;
		case 2: dam = (int) dam * 1.3; break;
		case 3: dam = (int) dam * 1.4; break;
		case 4: dam = (int) dam * 1.5; break;
		case 5: dam = (int) dam * 1.6; break;
	}

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_fisticuffs))
	{
		damage(ch, victim, 0, gsn_fisticuffs);
	}
	else
	{
		damage(ch, victim, dam, gsn_fisticuffs);
		check_improve(ch, gsn_fisticuffs);
	}
	pop_call();
	return;
}


void martial_arts( CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{
	int level;

	push_call("martial_arts_attack(%p,%p,%p)",ch,victim,dam);

	level = multi_skill_level(ch, gsn_martial_arts);

	if (number_bits(1) == 0)
	{
		martial_arts_attack = number_range(level/16, level/8);
	}
	else
	{
		martial_arts_attack = number_range(0,11);
	}

	martial_arts_attack = URANGE(0, martial_arts_attack, 11);

	switch (martial_arts_attack)
	{
		case  0: dam = (int) dam * 1.00; break;
		case  1: dam = (int) dam * 1.05; break;
		case  2: dam = (int) dam * 1.10; break;
		case  3: dam = (int) dam * 1.15; break;
		case  4: dam = (int) dam * 1.20; break;
		case  5: dam = (int) dam * 1.25; break;
		case  6: dam = (int) dam * 1.30; break;
		case  7: dam = (int) dam * 1.35; break;
		case  8: dam = (int) dam * 1.40; break;
		case  9: dam = (int) dam * 1.45; break;
		case 10: dam = (int) dam * 1.50; break;
		case 11: dam = (int) dam * 1.55; break;
	}

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_martial_arts))
	{
		damage(ch, victim, 0, gsn_martial_arts);
	}
	else
	{
		damage(ch, victim, dam, gsn_martial_arts);
		check_improve(ch, gsn_martial_arts);
	}
	pop_call();
	return;
}


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

	push_call("do_disarm(%p,%p)",ch,argument);

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

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

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

	wait_state( ch, skill_table[gsn_disarm].beats );

	if (IS_NPC(ch) || number_range(1, 100+get_curr_str(victim)) < learned(ch, gsn_disarm))
	{
		disarm( ch, victim );
		check_improve(ch, gsn_disarm);
	}
	else
	{
		send_to_char( "You failed.\n\r", ch );
	}
	pop_call();
	return;
}


void do_sla( CHAR_DATA *ch, char *argument )
{
	push_call("do_sla(%p,%p)",ch,argument);

	send_to_char( "If you want to SLAY, spell it out.\n\r", ch );

	pop_call();
	return;
}


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

	push_call("do_slay(%p,%p)",ch,argument);

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

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

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

	if (!IS_NPC(victim) && victim->level == MAX_LEVEL)
	{
		act( "$N laughs at your pathetic attempt to slay $M.",  ch, NULL, victim, TO_CHAR   );
		act( "You laugh at $n's pathetic attempt to slay you.", ch, NULL, victim, TO_VICT   );
		act( "$N laughs at $n's pathetic attempt to slay $M.",  ch, NULL, victim, TO_NOTVICT);
		pop_call();
		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);

	/*
		to make progs trigger :)
	*/

	set_fighting(victim, ch);
	mprog_death_trigger(victim);
	raw_kill(victim);

	stop_hate_fear(ch);

	pop_call();
	return;
}


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

	push_call("do_slaughter(%p,%p)",ch,argument);

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

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

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

	if (!IS_NPC(victim) && victim->level == MAX_LEVEL)
	{
		act( "$N laughs at your pathetic attempt to slaughter $M.",  ch, NULL, victim, TO_CHAR   );
		act( "You laugh at $n's pathetic attempt to slaughter you.", ch, NULL, victim, TO_VICT   );
		act( "$N laughs at $n's pathetic attempt to slaughter $M.",  ch, NULL, victim, TO_NOTVICT);
		pop_call();
		return;
	}

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

	if (!IS_NPC(victim))
	{
		log_printf("%s slaughtered by %s at %u", victim->name, get_name(ch), victim->in_room->vnum);

		if (victim->pcdata->exp > exp_level(victim->class, (victim->level)-1)+1)
		{
			gain_exp( victim, exp_level(victim->class, (victim->level)-1)+1 - victim->pcdata->exp);
		}
		if (IS_SET(victim->act, PLR_KILLER) || IS_SET(victim->act, PLR_THIEF))
		{
			if (victim->pcdata->exp > exp_level(victim->class, (victim->level)-2)+1)
			{
				gain_exp( victim, exp_level(victim->class, (victim->level)-2)+1 - victim->pcdata->exp);
			}
			if (IS_SET(victim->act, PLR_KILLER))
			{
				REMOVE_BIT(victim->act, PLR_KILLER);
			}
			if (IS_SET(victim->act, PLR_THIEF))
			{
				REMOVE_BIT(victim->act, PLR_THIEF);
			}
		}
	}
	set_fighting(victim,ch);	/* to make progs trigger :) */
	mprog_death_trigger(victim);
	raw_kill( victim );

	pop_call();
	return;
}


void do_suicide( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	bool killer, thief;
	killer=FALSE;
	thief=FALSE;

	push_call("do_suicide(%p,%p)",ch,argument);

	if (IS_NPC(ch))
	{
		raw_kill(ch);
		pop_call();
		return;
	}

	if (IS_SET(ch->act, PLR_KILLER))
	{
		killer = TRUE;
	}

	if (IS_SET(ch->act, PLR_THIEF))
	{
		thief = TRUE;
	}

	if (ch->fighting != NULL)
	{
		ch_printf(ch, "%s is trying to kill you, and suicide is not an option.\n\r", ch->fighting->who->name );
		pop_call();
		return;
	}

	one_argument_nolower( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char( "!!!  WARNING  !!!   This command is used to kill yourself.\n\rTo use you must enter in your password after the command.\n\r", ch );
		pop_call();
		return;
	}

	if (encrypt64(arg) == ch->pcdata->password)
	{
		send_to_char( "You commited suicide!\n\r", ch);
		raw_kill(ch);
		if (killer)
		{
			SET_BIT( ch->act, PLR_KILLER);
		}
		if (thief)
		{
			SET_BIT( ch->act, PLR_THIEF);
		}
	}
	else
	{
		send_to_char( "That was not your password.  Are you sure you want to commit suicide?\n\r", ch);
	}
	pop_call();
	return;
}


void do_shoot(CHAR_DATA *ch, char *argument)
{
	CHAR_DATA *victim;
	OBJ_DATA  *ammo, *cont, *weapon;
	int dir, dam;
	char *name;
	char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];

	push_call("do_shoot(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch, gsn_shoot) == -1)
	{
		send_to_char("You better leave the shooting to ninjas.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->fighting != NULL)
	{
		send_to_char( "You are too distracted to shoot!\n\r", ch );
		pop_call();
		return;
	}

	if ((weapon = get_eq_char(ch,WEAR_WIELD)) == NULL)
	{
		send_to_char("You must wield a weapon to shoot!\n\r", ch);
		pop_call();
		return;
	}

	if (weapon->item_type != ITEM_WEAPON)
	{
		send_to_char("You are not wielding a weapon.\n\r", ch);
		pop_call();
		return;
	}

	switch(weapon->value[0])
	{
		case WEAPON_TYPE_SHORTBOW:
		case WEAPON_TYPE_LONGBOW:
		case WEAPON_TYPE_CROSSBOW:
		case WEAPON_TYPE_BLOWPIPE:
			break;
		default:
			send_to_char("You are not wielding a weapon that can shoot.\n\r", ch);
			break;
	}

	for (ammo = ch->first_carrying ; ammo ; ammo = ammo->next_content)
	{
		if (ammo->item_type == ITEM_AMMO && ammo->value[0] == weapon->value[0] && ammo->level <= weapon->level)
		{
			break;
		}
		if (ammo->item_type == ITEM_CONTAINER && !IS_SET(ammo->value[1], CONT_CLOSED))
		{
			cont = ammo;

			for (ammo = ammo->first_content ; ammo ; ammo = ammo->next_content)
			{
				if (ammo->item_type == ITEM_AMMO && ammo->value[0] == weapon->value[0] && ammo->level <= weapon->level)
				{
					break;
				}
			}
			if (ammo)
			{
				break;
			}
			else
			{
				ammo = cont;
			}
		}
	}
	if (ammo == NULL)
	{
		send_to_char("Ooops...forgot to stock up on ammunition, eh?\n\r", ch);
		pop_call();
		return;
	}

	if (number_percent() > learned(ch, gsn_shoot))
	{
		send_to_char("You fumble around and don't get any shots off!\n\r", ch);
		pop_call();
		return;
	}

	argument = one_argument(argument, buf1);
	argument = one_argument(argument, buf2);

	if ((dir = direction_door(buf1)) == -1)
	{
		if ((dir = direction_door(buf2)) == -1)
		{
			send_to_char( "Shoot which direction?\n\r", ch );
			pop_call();
			return;
		}
		name = buf1;
	}
	else
	{
		name = buf2;
	}

	if (*name == '\0')
	{
		send_to_char( "Shoot at whom?\n\r", ch );
		pop_call();
		return;
	}

	if ((victim = find_char_dir(ch, dir, name)) == NULL)
	{
		send_to_char("Your victim must have slipped out of sight!\n\r", ch);
		pop_call();
		return;
	}

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	if (find_keeper(victim) != NULL || IS_SET(victim->in_room->room_flags, ROOM_SAFE))
	{
		send_to_char("You can't shoot into that room.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->in_room->area != victim->in_room->area)
	{
		send_to_char("They are too far to shoot at.\n\r", ch );
		pop_call();
		return;
	}

	if (IS_NPC(victim) && victim->hit < victim->max_hit / 2)
	{
		send_to_char("Your target is too wary to be shot at!\n\r", ch);
		pop_call();
		return;
	}

	/*
		set wait time partial based on ammo speed..
	*/

	wait_state(ch, skill_table[gsn_shoot].beats - ammo->value[2] * 2);

	if (ammo->in_obj)
	{
		act( "$n pulls $p from $P.", ch, ammo, ammo->in_obj, TO_ROOM );
		act( "You pull $p from $P.", ch, ammo, ammo->in_obj, TO_CHAR );
	}

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_shoot))
	{
		act( "$p whistles past your face.", ch, ammo, victim, TO_VICT );
		act( "$p whistles past $N's face.", ch, ammo, victim, TO_CHAR );

		if (number_percent() < 50)
		{
			junk_obj(ammo);
		}
		else
		{
			ammo->sac_timer = OBJ_SAC_TIME;
			obj_to_room(ammo, victim->in_room->vnum);
		}
	}
	else
	{
		dam = number_range(1, ammo->value[1] * ammo->value[3]);
		obj_to_char(ammo, victim);
		damage(ch, victim, dam, gsn_shoot);

		if (MP_VALID_MOB(victim) && dam > 0)
		{
			mprog_range_trigger(victim, ch, rev_dir[dir]);
		}
	}
	pop_call();
	return;
}

void do_throw( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	OBJ_DATA  *weapon;
	int dir, dam, wielded;
	char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH], buf3[MAX_INPUT_LENGTH];
	char *name, *item;

	push_call("do_throw(%p,%p)",ch,argument);

	if (IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit / 2)
	{
		pop_call();
		return;
	}

	if (!IS_NPC(ch) && multi(ch, gsn_throw) == -1)
	{
		send_to_char("You decide not to throw...might hurt your back.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->fighting != NULL)
	{
		send_to_char( "You are too distracted to throw!\n\r", ch );
		pop_call();
		return;
	}

	argument = one_argument(argument, buf1);
	argument = one_argument(argument, buf2);
	argument = one_argument(argument, buf3);

	if ((dir = direction_door(buf1)) == -1)
	{
		if ((dir = direction_door(buf2)) == -1)
		{
			if ((dir = direction_door(buf3)) == -1)
			{
				send_to_char( "Throw which direction?\n\r", ch );
				pop_call();
				return;
			}
			else
			{
				name = buf2;
				item = buf1;
			}
		}
		else
		{
			name = buf3;
			item = buf1;
		}
	}
	else
	{
		name = buf3;
		item = buf2;
	}

	if (name[0] == '\0' || item[0] == '\0')
	{
		send_to_char( "Throw what at whom?\n\r", ch );
		pop_call();
		return;
	}

	if ((victim = find_char_dir(ch, dir, name)) == NULL)
	{
		send_to_char("Your victim must have slipped out of sight.\n\r", ch);
		pop_call();
		return;
	}

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	if (find_keeper(victim) != NULL || IS_SET(victim->in_room->room_flags, ROOM_SAFE))
	{
		send_to_char("You can't throw into that room.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->in_room->area != victim->in_room->area)
	{
		send_to_char("They are too far to throw things at.\n\r", ch);
		pop_call();
		return;
	}

	if (IS_NPC(victim) && victim->hit < victim->max_hit/2)
	{
		send_to_char("You can't seem to get a good sight of your target.\n\r", ch);
		pop_call();
		return;
	}


	wielded = FALSE;

	if ((weapon = get_eq_char(ch, WEAR_WIELD)) != NULL)
	{
		if (is_name(item, weapon->name) || is_name_short(item, weapon->name))
		{
			wielded = TRUE;
		}
	}

	if (wielded == FALSE)
	{
		if (!remove_obj(ch, WEAR_WIELD, TRUE, FALSE))
		{
			send_to_char("You can't throw with another weapon wielded!\n\r", ch);
			pop_call();
			return;
		}
		weapon = get_obj_carry(ch, item);
	}

	if (weapon == NULL)
	{
		send_to_char("Hmmm...you don't seem to have that weapon.\n\r", ch);
		pop_call();
		return;
	}

	if (IS_SET(weapon->extra_flags, ITEM_NODROP))
	{
		send_to_char("You can't let go of it.\n\r", ch);
		pop_call();
		return;
	}

	switch (weapon->value[0])
	{
		case WEAPON_TYPE_DAGGER:
		case WEAPON_TYPE_AXE:
		case WEAPON_TYPE_SPEAR:
			break;
		default:
			send_to_char("You can't throw that type of weapon.\n\r", ch);
			pop_call();
			return;
	}

	if (!wielded)
	{
		wait_state( ch, skill_table[gsn_throw].beats );
	}
	else
	{
		wait_state( ch, skill_table[gsn_throw].beats / 2 );
	}

	if (number_percent() > learned(ch, gsn_throw))
	{
		send_to_char("You fumble around and don't throw a thing!\n\r", ch);
		pop_call();
		return;
	}

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_throw))
	{
		act("$p whistles past your face.", ch, weapon, victim, TO_VICT );
		act("$p whistles past $N's face.", ch, weapon, victim, TO_CHAR );

		if (number_percent() < 50)
		{
			junk_obj(weapon);
		}
		else
		{
			weapon->sac_timer = OBJ_SAC_TIME;
			obj_to_room(weapon, victim->in_room->vnum);
		}
	}
	else
	{
		dam = 3 * number_range(weapon->value[1], weapon->value[1]*weapon->value[2]);
		obj_to_char(weapon, victim);

		damage(ch, victim, dam, gsn_throw);

		if (MP_VALID_MOB(victim) && dam > 0)
		{
			mprog_range_trigger(victim, ch, rev_dir[dir]);
		}
		stop_fighting(ch, FALSE);

		pop_call();
		return;
	}
}

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

	push_call("do_divert(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch,gsn_divert) == -1)
	{
		send_to_char( "What about fleeing instead?\n\r", ch );
		pop_call();
		return;
	}

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

	for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room)
	{
		if (fch->fighting && fch->fighting->who == ch)
		{
			break;
		}
	}
	if (fch == NULL)
	{
		send_to_char( "You aren't under attack.\n\r", ch );
		pop_call();
		return;
	}

	one_argument( argument, arg );

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

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

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

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

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

	if (!is_same_group(ch,victim))
	{
		act( "$N isn't a member of your group.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}

	wait_state( ch, skill_table[gsn_divert].beats );

	if (!IS_NPC(ch->fighting->who))
	{
		send_to_char( "You fail the divert.\n\r", ch );
		pop_call();
		return;
	}

	if (number_percent() > learned(ch, gsn_divert) || !IS_NPC(fch))
	{
		send_to_char( "You fail the divert.\n\r", ch );
		pop_call();
		return;
	}

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

	check_improve(ch, gsn_divert);

	for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room)
	{
		if (fch->fighting && fch->fighting->who == ch)
		{
			fch->fighting->who = victim;
			break;
		}
	}
	pop_call();
	return;
}

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

	push_call("do_knife(%p,%p)",ch,argument);

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

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

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if ((victim = who_fighting(ch)) == NULL)
		{
			send_to_char("You are not fighting anyone.\n\r",ch);
			pop_call();
			return;
		}
	}
	else if ((victim = get_char_room(ch,arg)) == NULL)
	{
		send_to_char("Knife whom?\n\r",ch);
		pop_call();
		return;
	}

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	wait_state( ch, skill_table[gsn_knife].beats );

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_knife))
	{
		damage( ch, victim, 0, gsn_knife);
	}
	else
	{
		one_hit( ch, victim, gsn_knife );
	}

	pop_call();
	return;
}

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

	push_call("do_distract(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch, gsn_distract) == -1)
	{
		send_to_char( "They'd just get mad at you if you tried.\n\r", ch );
		pop_call();
		return;
	}

	one_argument(argument,arg);

	if ((victim = get_char_room(ch,arg)) == NULL)
	{
		send_to_char("Distract whom?\n\r",ch);
		pop_call();
		return;
	}

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	wait_state( ch, skill_table[gsn_distract].beats );

	if (IS_NPC(ch) || number_range(1, 150) < learned(ch, gsn_distract))
	{
		switch (number_bits(1))
		{
			case 0:
				act( "$n informs you that your shoes are untied.", ch, NULL, victim, TO_VICT    );
				act( "You inform $N that $S shoes are untied.",    ch, NULL, victim, TO_CHAR    );
				act( "$n inform $N that $S shoes are untied.",     ch, NULL, victim, TO_NOTVICT );
				break;
			case 1:
				act( "$n points at the sky above you and gasps. ", ch, NULL, victim, TO_VICT    );
				act( "You point at the sky above $M and gasp.",    ch, NULL, victim, TO_CHAR    );
				act( "$n points at the sky above $N and gasps.",   ch, NULL, victim, TO_NOTVICT );
				break;
		}
		check_improve(ch, gsn_distract);
		victim->distracted += 10;
		wait_state( victim, skill_table[gsn_distract].beats );
	}
	else
	{
		send_to_char( "They suddenly look very suspicious.\n\r", ch );
		act( "$n is trying to distract you!", ch, NULL, victim, TO_VICT);
		victim->distracted = 0;
		if (IS_NPC(victim) && (number_bits(1) == 0))
		{
			act( "$n suddenly looks VERY angry!",victim,NULL, NULL,TO_ROOM);
			multi_hit(victim,ch,TYPE_UNDEFINED);
		}
	}
	pop_call();
	return;
}

bool	valid_fight( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("valid_fight(%p,%p)",ch,victim);

	if (who_fighting(ch) == NULL)
	{
		pop_call();
		return FALSE;
	}

	if (ch->in_room != victim->in_room)
	{
		pop_call();
		return FALSE;
	}

	pop_call();
	return TRUE;
}


CHAR_DATA *who_fighting( CHAR_DATA *ch )
{
	push_call("who_fighting(%p)",ch);

	if (ch->fighting == NULL)
	{
		pop_call();
		return NULL;
	}

	if (ch->fighting->who == NULL)
	{
		pop_call();
		return NULL;
	}

	if (ch->fighting->who->name == NULL)
	{
		log_printf("who_fighting: who->name == NULL for %s", ch->name);
		dump_stack();
		pop_call();
		return NULL;
	}

	if (ch->fighting->who->in_room != ch->in_room)
	{
		pop_call();
		return NULL;
	}

	pop_call();
	return ch->fighting->who;
}


void stop_fighting( CHAR_DATA *ch, bool fBoth )
{
	FIGHT_DATA *fight, *fight_next;

	push_call("stop_fighting(%p,%p)",ch,fBoth);

	free_fight( ch );

	if (!fBoth)
	{
		pop_call();
		return;
	}

	for (fight = mud->f_fight ; fight ; fight = fight_next)
	{
		fight_next = fight->next;

		if (fight->who == ch)
		{
			free_fight(fight->ch);
		}
	}
	pop_call();
	return;
}

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

	push_call("do_auto(%p,%p)",ch,argument);

	if (IS_NPC(ch))
	{
		pop_call();
		return;
	}

	if (argument[0] == '\0')
	{
		send_to_char( "Syntax:  AUTO [AUTO|QUICK] [SKILL|SPELL]\n\r", ch);

		if (ch->pcdata->auto_command != NULL && ch->pcdata->auto_command[0] != '\0')
		{
			ch_printf( ch, "Current command: %s\n\r", ch->pcdata->auto_command);
		}
		else
		{
			ch_printf( ch, "Current command: Not defined\n\r" );
		}

		switch (ch->pcdata->auto_flags)
		{
			case AUTO_OFF:
				send_to_char( "Current mode:    Off\n\r", ch);
				break;
			case AUTO_AUTO:
				send_to_char( "Current mode:    Auto\n\r", ch);
				break;
			case AUTO_QUICK:
				send_to_char( "Current mode:    Quick\n\r", ch);
				break;
		}
		pop_call();
		return;
	}

	if (!strcasecmp( argument, "auto"))
	{
		if (ch->pcdata->auto_command[0] != '\0')
		{
			send_to_char( "Turning AUTO mode on.\n\r", ch);
			ch->pcdata->auto_flags = AUTO_AUTO;
			pop_call();
			return;
		}
		else
		{
			send_to_char( "You haven't defined a combat skill/spell.\n\r", ch);
			pop_call();
			return;
		}
	}

	if (!strcasecmp(argument, "quick"))
	{
		if (ch->pcdata->auto_command[0] != '\0')
		{
			send_to_char( "Turning QUICK mode on.\n\r", ch);
			ch->pcdata->auto_flags=AUTO_QUICK;
			pop_call();
			return;
		}
		else
		{
			send_to_char( "You haven't defined a combat skill/spell.\n\r", ch);
			pop_call();
			return;
		}
	}

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

	/*
		Adding mass to auto command - Scandum 18-04-2002
	*/

	if (!str_prefix("mass ", argument))
	{
		if (learned(ch, gsn_mass) <= 0)
		{
			send_to_char( "You can't do that.\n\r", ch );
			pop_call();
			return;
		}
		sn = skill_lookup( &argument[5] );
		ms = TRUE;

		if (!is_spell(sn))
		{
			send_to_char( "That is not a spell.\n\r", ch );
			pop_call();
			return;
		}
	}
	else
	{
		sn = skill_lookup( argument );
		ms = FALSE;
	}

	if (sn < 0 && ms == FALSE)
	{
		send_to_char( "That is not a skill or spell.\n\r", ch );
		pop_call();
		return;
	}

	/*
		Disallow ppl to do auto short range etc - Martin 7/8/98
	*/

	if (skill_table[sn].minimum_position != POS_FIGHTING)
	{
		send_to_char( "You can only put combat skills/spells on auto.\n\r", ch );
		pop_call();
		return;
	}

	if (!IS_SET(skill_table[sn].race, 1 << ch->race))
	{
		if (multi(ch, sn) == -1 || learned(ch, sn) <= 0)
		{
			send_to_char( "You can't do that.\n\r", ch );
			pop_call();
			return;
		}
	}

	if (ms == TRUE)
	{
		int sha_mlv = ch->pcdata->mclass[CLASS_SHAMAN];
		int sor_mlv = ch->pcdata->mclass[CLASS_SORCERER];

		if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE
		&& sor_mlv < skill_table[gsn_mass].skill_level[CLASS_SORCERER])
		|| (skill_table[sn].target == TAR_CHAR_DEFENSIVE
		&& sha_mlv < skill_table[gsn_mass].skill_level[CLASS_SHAMAN]))
		{
			send_to_char( "You don't have enough skill in the proper class.\n\r", ch );
			pop_call();
			return;
		}
		if (skill_table[sn].target != TAR_CHAR_OFFENSIVE
		&&  skill_table[sn].target != TAR_CHAR_DEFENSIVE)
		{
			send_to_char( "You cannot put mass spells on auto mass.\n\r", ch );
			pop_call();
			return;
		}
		sprintf(argument, "mass %s", skill_table[sn].name);
	}
	else
	{
		strcpy(argument, skill_table[sn].name);
	}

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

	pop_call();
	return;
}

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

	push_call("do_spam(%p,%p)",ch,arg);

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

		if (!IS_SET(CH(ch->desc)->pcdata->spam, 1))
		{
			send_to_char( "  A       On    You hit\n\r" , ch);
		}
		else
		{
			send_to_char( "  A       Off   You hit\n\r" , ch);
		}

		if (!IS_SET(CH(ch->desc)->pcdata->spam, 2))
		{
			send_to_char( "  B       On    You miss\n\r" , ch);
		}
		else
		{
			send_to_char( "  B       Off   You miss\n\r" , ch);
		}
		if (!IS_SET(CH(ch->desc)->pcdata->spam, 4))
		{
			send_to_char( "  C       On    They hit you\n\r" , ch);
		}
		else
		{
			send_to_char( "  C       Off   They hit you\n\r" , ch);
		}
		if( !IS_SET( CH(ch->desc)->pcdata->spam, 8))
		{
			send_to_char( "  D       On    They miss you\n\r" , ch);
		}
		else
		{
			send_to_char( "  D       Off   They miss you\n\r" , ch);
		}
		if( !IS_SET( CH(ch->desc)->pcdata->spam, 16))
		{
			send_to_char( "  E       On    Party hits\n\r" , ch);
		}
		else
		{
			send_to_char( "  E       Off   Party hits\n\r" , ch);
		}

		if( !IS_SET( CH(ch->desc)->pcdata->spam, 32))
		{
			send_to_char( "  F       On    Party misses\n\r" , ch);
		}
		else
		{
			send_to_char( "  F       Off   Party misses\n\r" , ch);
		}
		if( !IS_SET( CH(ch->desc)->pcdata->spam, 64))
		{
			send_to_char( "  G       On    They hit party\n\r" , ch);
		}
		else
		{
			send_to_char( "  G       Off   They hit party\n\r" , ch);
		}
		if( !IS_SET( CH(ch->desc)->pcdata->spam, 128))
		{
			send_to_char( "  H       On    They miss party\n\r" , ch);
		}
		else
		{
			send_to_char( "  H       Off   They miss party\n\r" , ch);
		}
		if( !IS_SET( CH(ch->desc)->pcdata->spam, 256))
		{
			send_to_char( "  I       On    Other hit\n\r" , ch);
		}
		else
		{
			send_to_char( "  I       Off   Other hit\n\r" , ch);
		}
		if( !IS_SET( CH(ch->desc)->pcdata->spam, 512))
		{
			send_to_char( "  J       On    Other miss\n\r" , ch);
		}
		else
		{
			send_to_char( "  J       Off   Other miss\n\r" , ch);
		}
		if( IS_SET( CH(ch->desc)->pcdata->spam, 1024))
		{
			send_to_char( "  K       On    Show party status line\n\r" , ch);
		}
		else
		{
			send_to_char( "  K       Off   Show party status line\n\r" , ch);
		}
		if (!IS_SET( CH(ch->desc)->pcdata->spam, 2048))
		{
			send_to_char( "  L       ON    You hear party members moving\n\r", ch);
		}
		else
		{
			send_to_char( "  L       off   You don't hear party members moving\n\r", ch);
		}
		if (!IS_SET(CH(ch->desc)->pcdata->spam, 4096))
		{
			send_to_char( "  M       ON    You hear the uttering of spells\n\r",ch);
		}
		else
		{
			send_to_char( "  M       off   You don't hear the uttering of spells\n\r",ch);
		}
		pop_call();
		return;
	}

	val = -1;

	switch (tolower(arg[0]))
	{
		case 'a':	val = 1;		break;
		case 'b':	val = 2;		break;
		case 'c':	val = 4;		break;
		case 'd':	val = 8;		break;
		case 'e': val = 16;		break;
		case 'f':	val = 32;		break;
		case 'g':	val = 64;		break;
		case 'h':	val = 128;	break;
		case 'i':	val = 256;	break;
		case 'j':	val = 512;	break;
		case 'k':	val = 1024;	break;
		case 'l':	val = 2048;	break;
		case 'm':	val = 4096;	break;
	}

	if (val == -1)
	{
		send_to_char( "That is not an option.\n\r", ch );
		pop_call();
		return;
	}

	TOGGLE_BIT(CH(ch->desc)->pcdata->spam, val);

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

	pop_call();
	return;
}

void do_assassin( CHAR_DATA *ch, char *argument )
{
	push_call("do_assassin(%p,%p)",ch,argument);

	send_to_char( "If you want to ASSASSINATE, spell it out.\n\r", ch );

	pop_call();
	return;
}

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

	push_call("do_assassinate(%p,%p)",ch,argument);

	if (IS_NPC(ch) || multi(ch, gsn_assassinate) == -1)
	{
		send_to_char( "Only ninjas can assassinate.\n\r", ch );
		pop_call();
		return;
	}

	argument = one_argument( argument, arg );

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

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

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

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

	if (IS_NPC(victim))
	{
		send_to_char( "You may not assassinate them.\n\r", ch );
		pop_call();
		return;
	}

	if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
	{
		send_to_char("Use kill instead.\n\r", ch);
		pop_call();
		return;
	}

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

	if (!can_attack (ch, victim) )
	{
		send_to_char( "You may not assassinate that person.\n\r", ch);
		pop_call();
		return;
	}

	if (victim->pcdata->just_died_ctr > 0)
	{
		send_to_char("That person is currently protected by their god.\n\r", ch);
		pop_call();
		return;
	}

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

	if (!IS_NPC(victim ) && victim->pcdata->corpse != NULL)
	{
		ch_printf(ch, "%s has been killed quite recently.\n\r", get_name(victim));
		pop_call();
		return;
	}

	/*
		Code for total and max pvnum attacks  -  Chaos 5/6/99
	*/

	if (!check_add_attack(ch, victim))
	{
		ch_printf(ch, "%s has been attacked too many times.\n\rYou should leave them alone.\n\r", get_name(victim));
		pop_call();
		return;
	}

	/*
		ok...check and see if the victim has the specified item
	*/

	argument=one_argument( argument, arg2 );

	if (arg2[0] != '\0' && number_percent() < learned(ch, gsn_assassinate))
	{
		OBJ_DATA *obj;

		if ((obj = get_obj_list(victim, arg2, victim->first_carrying)) == NULL)
		{
			send_to_char( "They don't seem to have it!\n\r", ch );
			pop_call();
			return;
		}
		if (IS_SET(obj->extra_flags, ITEM_INVENTORY) || obj->level > ch->level)
		{
			send_to_char( "You wouldn't be able to pry it away.\n\r", ch );
			pop_call();
			return;
		}
		if (ch->carry_number >= can_carry_n(ch))
		{
			send_to_char( "You have your hands full.\n\r", ch );
			pop_call();
			return;
		}
		if (ch->carry_weight >= can_carry_w(ch))
		{
			send_to_char( "You can't carry that much weight.\n\r", ch );
			pop_call();
			return;
		}
		ch->pcdata->asn_obj = obj;
	}
	else
	{
		ch->pcdata->asn_obj = NULL;
	}

	check_killer( ch, victim );

	if (number_percent() > learned(ch, gsn_muffle)/2)
	{
		sprintf(buf, "%s", get_name(victim));
		do_battle("%s battles 'Help!  I am being assassinated by %s!'", buf, get_name(ch));
	}
	else
	{
		act( "You quickly silence $N before they can call for help!", ch, NULL, victim, TO_CHAR);
		act( "You are silenced by $n before you can call for help!",  ch, NULL, victim, TO_VICT);
		check_improve(ch, gsn_muffle);
	}

	ch->pcdata->just_died_ctr = 0;

	clear_attack_list(ch);

	log_printf("ROOM [%u] ASSASSINATE %s attacking %s", ch->in_room->vnum, ch->name, victim->name);

	if (number_range(33, 100) < 100 * victim->hit / UMAX(1, victim->max_hit)
	&&  number_percent() < learned(ch, gsn_knife)
	&&  number_percent() < learned(ch, gsn_quick_draw)
	&&  number_percent() < 100*multi_skill_level(ch, gsn_quick_draw)/ch->level)
	{
		OBJ_DATA * obj;
		if ((obj = get_eq_char(ch,WEAR_WIELD)) != NULL && (obj->value[3]==11 || obj->value[3]==2))
		{
			one_hit(ch, victim, gsn_knife);
			check_improve(ch, gsn_quick_draw);
			wait_state(ch, skill_table[gsn_knife].beats);

			pop_call();
			return;
		}
	}

	wait_state(ch, PULSE_PER_SECOND);

	multi_hit( ch, victim, TYPE_UNDEFINED );

	pop_call();
	return;
}

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

	push_call("do_gouge(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && multi(ch, gsn_gouge) == -1)
	{
		ch_printf(ch, "You haven't been taught this dirty trick!\n\r");
		pop_call();
		return;
	}

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

	wait_state( ch, skill_table[gsn_gouge].beats );

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_gouge))
	{
		damage(ch, victim, 0, gsn_gouge);
		pop_call();
		return;
	}

	damage(ch, victim, number_range(5, ch->level), gsn_gouge);

	check_improve(ch, gsn_gouge);

	if (valid_fight(ch, victim))
	{
		if (!IS_AFFECTED(victim, AFF_BLIND))
		{
			if (!IS_AFFECTED(ch, AFF_TRUESIGHT))
			{
				af.type      = gsn_gouge;
				af.location  = APPLY_HITROLL;
				af.modifier  = -6;
				af.duration  = multi_skill_level(ch,gsn_gouge) / 2 / get_curr_con(victim);
				af.bittype   = AFFECT_TO_CHAR;
				af.bitvector = AFF_BLIND;
				affect_to_char( victim, &af );
				act( "You can't see a thing!", victim, NULL, NULL, TO_CHAR );
			}
			else
			{
				act( "$N seems to be able to see despite your attack!", ch, NULL, victim, TO_CHAR );
				act( "You are unaffected by $n's attack.", ch, NULL, victim, TO_VICT );
			}
		}
		wait_state( ch,     PULSE_VIOLENCE );
	}
	else
	{
		act( "Your fingers plunge into your victim's brain, causing immediate death!", ch, NULL, NULL, TO_CHAR );
	}
	pop_call();
	return;
}

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

	push_call("do_circle(%p,%p)",ch,argument);

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

	if (is_safe(ch, NULL))
	{
		pop_call();
		return;
	}

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

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

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

	if (who_fighting(victim) == ch)
	{
		act( "You can't circle around them without a distraction.", ch, NULL, victim, TO_CHAR );
		pop_call();
		return;
	}

	wait_state( ch, skill_table[gsn_circle].beats );

	if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_circle))
	{
		damage( ch, victim, 0, gsn_circle );
		pop_call();
		return;
	}

	one_hit( ch, victim, gsn_circle );

	pop_call();
	return;
}

void do_berserk( CHAR_DATA *ch, char *argument )
{
	push_call("do_berserk(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && ch->pcdata->mclass[multi(ch, gsn_berserk)] != ch->level)
	{
		send_to_char("You spit foam and roar but nobody seems to notice.\n\r", ch);
		pop_call();
		return;
	}

	if (IS_NPC(ch) || number_percent() < learned(ch, gsn_berserk))
	{
		AFFECT_DATA af;


		af.type      = gsn_berserk;
		af.duration  = 5;
		af.bittype   = AFFECT_TO_CHAR;
		af.bitvector = AFF2_BERSERK;

		af.modifier  = 0 - ch->level / 3;
		af.location  = APPLY_SAVING_SPELL;
		affect_to_char( ch, &af );

		af.modifier  = ch->level / 4;
		af.location  = APPLY_HITROLL;
		affect_to_char( ch, &af );

		af.modifier  = ch->level / 2;
		af.location  = APPLY_DAMROLL;
		affect_to_char( ch, &af );

		send_to_char( "Now you REALLY wanna KILL!\n\r",ch);
		check_improve(ch, gsn_berserk);
	}
	else
	{
		wait_state( ch, skill_table[gsn_berserk].beats );
		send_to_char("You failed to go berserk!\n\r",ch);
	}
	pop_call();
	return;
}

void do_bloodfrenzy(CHAR_DATA *ch, char *arg)
{
	push_call("do_bloodfrenzy(%p,%p)",ch,arg);

	if (which_god(ch) != GOD_DEMISE)
	{
		send_to_char("You try to look crazy, but can't keep it up for very long.\n\r", ch);
		pop_call();
		return;
	}

	if (number_percent() < learned(ch, gsn_bloodfrenzy))
	{
		AFFECT_DATA af;

		if (is_affected(ch, gsn_bloodfrenzy))
		{
			send_to_char( "Blood already maddened you!\n\r", ch );
			pop_call();
			return;
		}

		af.type      = gsn_bloodfrenzy;
		af.duration  = 12;
		af.bitvector = 0;

		af.modifier  = (1 + ch->level / 18 + ch->pcdata->reincarnation);
		af.location  = APPLY_DAMROLL;
		affect_to_char( ch, &af );

		af.modifier  = (1 + ch->level / 18);
		af.location  = APPLY_STR;
		affect_to_char( ch, &af );

		send_to_char("You feel rage spreading through your body.\n\r",ch);
		act( "$n gets a crazy look in $s eyes.", ch, NULL, NULL, TO_ROOM );
		check_improve(ch, gsn_bloodfrenzy);
	}
	else
	{
		wait_state(ch, skill_table[gsn_bloodfrenzy].beats);
		send_to_char("You failed to get mad at the sight of blood.\n\r",ch);
	}
	pop_call();
	return;
}

void do_drain( CHAR_DATA *ch, char *arg )
{
	CHAR_DATA *victim;
	char arg1[MAX_INPUT_LENGTH];

	push_call("do_drain(%p,%p)",ch,arg);

	if (learned(ch, gsn_drain) == 0)
	{
		send_to_char("The undead curse is not upon you.\n\r",ch);
		pop_call();
		return;
	}

	one_argument( arg, arg1 );

	if (arg1[0] == '\0')
	{
		if ((victim = who_fighting(ch)) == NULL)
		{
			send_to_char("You are not fighting anyone.\n\r",ch);
			pop_call();
			return;
		}
	}
	else if ((victim = get_char_room(ch, arg1)) == NULL)
	{
		send_to_char("Drain whom?\n\r",ch);
		pop_call();
		return;
	}

	if (is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	wait_state(ch, skill_table[gsn_drain].beats);


	if (!check_hit(ch, victim, GET_HITROLL(ch), TYPE_HIT))
	{
		damage(ch, victim, 0, gsn_drain);
	}
	else
	{
		int dam = GET_DAMROLL(ch);

		dam += number_range(ch->level*1, ch->level*2);

		ch->hit = UMIN(ch->max_hit, ch->hit+dam/10);

		gain_condition(ch, COND_FULL,   1);
		gain_condition(ch, COND_THIRST, 1);

		damage(ch, victim, dam, gsn_drain);
	}
	pop_call();
	return;
}


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

	push_call("do_strangle(%p,%p)",ch,argument);

	if (learned(ch, gsn_strangle) == 0)
	{
		send_to_char( "They would just get mad at you.\n\r", ch );
		pop_call();
		return;
	}

	if ((victim = get_char_room(ch, argument)) == NULL)
	{
		send_to_char("Strangle whom?\n\r",ch);
		pop_call();
		return;
	}

	if (IS_NPC(victim) && is_safe(ch, victim))
	{
		pop_call();
		return;
	}

	if (!IS_NPC(victim))
	{
		if (victim == ch)
		{
			send_to_char( "You strangle yourself.  Uch!\n\r", ch );
			pop_call();
			return;
		}

		if (is_safe(ch, NULL))
		{
			pop_call();
			return;
		}

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

		if (!can_attack (ch, victim) )
		{
			send_to_char( "You may not strangle that person.\n\r", ch);
			pop_call();
			return;
		}

		if (victim->pcdata->just_died_ctr > 0)
		{
			send_to_char("That person is currently protected by their god.\n\r", ch);
			pop_call();
			return;
		}

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

		if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF))
		{
			if (ch->pcdata->last_connect + 120 > mud->current_time)
			{
				ch_printf(ch, "You must wait %d seconds before you can strangle anyone.\n\r", ch->pcdata->last_connect + 120 - mud->current_time);
				pop_call();
				return;
			}
		}

		if (victim->pcdata->corpse != NULL)
		{
			ch_printf(ch, "%s has been killed quite recently.\n\r", get_name(victim));
			pop_call();
			return;
		}
	}

	wait_state( ch, skill_table[gsn_strangle].beats );

	if (IS_AFFECTED(victim, AFF_SLEEP))
	{
		send_to_char( "They are already unconscious.\n\r", ch );
		pop_call();
		return;
	}

	if (number_range(1, victim->level * 3 / 2) > multi_skill_level(ch, gsn_strangle) || number_percent() > learned(ch, gsn_strangle))
	{
		act("$n is trying to strangle you!", ch, NULL, victim, TO_VICT);
		act("You failed to strangle $N!",    ch, NULL, victim, TO_CHAR);

		if (IS_NPC(victim))
		{
			act( "$n suddenly looks VERY angry!", victim, NULL, NULL, TO_ROOM);
			multi_hit(victim, ch, TYPE_UNDEFINED);
		}
		pop_call();
		return;
	}

	af.type      = gsn_sleep;
	af.duration  = 1;
	af.location  = APPLY_NONE;
	af.modifier  = 0;
	af.bittype   = AFFECT_TO_CHAR;
	af.bitvector = AFF_SLEEP;
	affect_to_char( victim, &af );

	wait_state(victim, skill_table[gsn_strangle].beats * 3 / 2);

	if ( IS_AWAKE(victim) )
	{
		send_to_char( "The world blurs as your consciousness fades.\n\r", victim );
		act( "$n collapses onto the ground.", victim, NULL, NULL, TO_ROOM );
		victim->position = POS_SLEEPING;
	}

	pop_call();
	return;
}


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

	push_call("knight_adjust_hpmnmv(%p)",ch);

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

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

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

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

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

	if (ch->hit > ch->max_hit)
	{
		ch->hit = ch->max_hit;
	}
	if (ch->mana > ch->max_mana)
	{
		ch->mana = ch->max_mana;
	}
	if (ch->move > ch->max_move)
	{
		ch->move = ch->max_move;
	}
	pop_call();
	return;
}

bool can_reincarnate_attack( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("can_reincarnate_attack(%p,%p)",ch,victim);

	if (IS_NPC(ch) || IS_NPC(victim))
	{
		pop_call();
		return TRUE;
	}

	if (ch->pcdata->reincarnation*2/3 > victim->pcdata->reincarnation)
	{
		pop_call();
		return FALSE;
	}

	if (ch->pcdata->reincarnation*3/2 < victim->pcdata->reincarnation)
	{
		pop_call();
		return FALSE;
	}
	pop_call();
	return TRUE;
}

/*
	  0 1 2 3 4 5 6 7 8 9 A	reincarnate attack chart:
	0 *
	1   *
	2     * *
	3     * * *
	4       * * * *
	5         * * * *
	6         * * * * * *
	7           * * * * * *
	8             * * * * *
	9             * * * * *
	A	           * * * *
*/

bool can_attack( CHAR_DATA *ch, CHAR_DATA *victim)
{
	push_call("can_attack(%p,%p)",ch,victim);

	if (IS_NPC(ch) || IS_NPC(victim))
	{
		pop_call();
		return TRUE;
	}

	if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA && victim->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
	{
		pop_call();
		return TRUE;
	}

	if (victim->level >= LEVEL_IMMORTAL || ch->level >= LEVEL_IMMORTAL)
	{
		pop_call();
		return FALSE;
	}

	if (ch->pcdata->reincarnation < victim->pcdata->reincarnation)
	{
		if (ch->pcdata->reincarnation*3/2 < victim->pcdata->reincarnation)
		{
			pop_call();
			return FALSE;
		}
		if (victim->pcdata->reincarnation*2/3 > ch->pcdata->reincarnation)
		{
			pop_call();
			return FALSE;
		}
	}
	if (ch->pcdata->reincarnation > victim->pcdata->reincarnation)
	{
		if (ch->pcdata->reincarnation*2/3 > victim->pcdata->reincarnation)
		{
			pop_call();
			return FALSE;
		}
		if (victim->pcdata->reincarnation*3/2 < ch->pcdata->reincarnation)
		{
			pop_call();
			return FALSE;
		}
	}

	if (which_god(ch) == GOD_NEUTRAL || which_god(victim) == GOD_NEUTRAL)
	{
		pop_call();
		return FALSE;
	}

	if (ch->pcdata->clan && ch->pcdata->clan == victim->pcdata->clan)
	{
		pop_call();
		return FALSE;
	}

	if (which_god(victim) == which_god(ch))
	{
		pop_call();
		return FALSE;
	}

	if (ch->level <= 25 || victim->level <= 25)
	{
		pop_call();
		return FALSE;
	}

	if (victim->level < ch->level-10 || victim->level > ch->level+10)
	{
		pop_call();
		return FALSE;
	}

	pop_call();
	return TRUE;
}

/*
	Orish Brawling  - Chaos 8/20/98
*/

void orc_brawl( CHAR_DATA *ch, CHAR_DATA *victim)
{
	int level;
	int dmg, dmgL, dmgH;
	int tshares, pshare;

	push_call("orc_brawl(%p,%p)",ch,victim);

	level = ch->level;

	/*
		Find total shares
	*/

	if (level < 15)
	{
		tshares = 8;
	}
	else if (level < 30)
	{
		tshares = 15;
	}
	else if (level < 45)
	{
		tshares = 21;
	}
	else if (level < 60)
	{
		tshares = 26;
	}
	else if (level < 75)
	{
		tshares = 30;
	}
	else
	{
		tshares = 33;
	}
	pshare = number_range(1, tshares);

	if (pshare <= 8)
	{
		brawling_attack = 0;
		dmgL = (int) level * 0.25;
		dmgH = (int) level * 0.50;
	}
	else if( pshare <= 15 )
	{
		brawling_attack = 1;
		dmgL = (int) level * 0.50;
		dmgH = (int) level * 0.75;
	}
	else if( pshare <= 21 )
	{
		brawling_attack = 2;
		dmgL = (int) level * 0.75;
		dmgH = (int) level * 1.00;
	}
	else if( pshare <= 26 )
	{
		brawling_attack = 3;
		dmgL = (int) level * 1.00;
		dmgH = (int) level * 1.25;
	}
	else if( pshare <= 30 )
	{
		brawling_attack = 4;
		dmgL = (int) level * 1.25;
		dmgH = (int) level * 1.50;
	}
	else
	{
		brawling_attack = 5;
		dmgL = (int) level * 1.50;
		dmgH = (int) level * 1.75;
	}

	dmg = number_range(dmgL, dmgH);

	if (check_hit(ch, victim, GET_HITROLL(ch), TYPE_HIT))
	{
		damage(ch, victim, GET_DAMROLL(ch) + dmg, gsn_brawling);
	}
	else
	{
		damage(ch, victim, 0, gsn_brawling);
	}
	pop_call();
	return;
}

void stop_hate_fear( CHAR_DATA *ch )
{
	push_call("stop_hate_fear(%p)",ch);

	if (IS_NPC(ch) && *ch->npcdata->hate_fear)
	{
		STRFREE(ch->npcdata->hate_fear);
		ch->npcdata->hate_fear = STRDUPE(str_empty);
	}
	pop_call();
	return;
}

/*
	Could use some messages
*/

void found_hating( CHAR_DATA *ch, CHAR_DATA *victim )
{
	char buf[MAX_INPUT_LENGTH];

	push_call("found_hating(%p,%p)",ch,victim);

	if (!can_see(ch, victim))
	{
		if (number_bits(2) != 0)
		{
			pop_call();
			return;
		}
		if (IS_SET(ch->act, ACT_SMART))
		{
			switch (number_bits(2))
			{
				case 0:
					sprintf(buf, "I can smell your blood %s!", short_to_name(get_name(victim), 1));
					break;
				case 1:
					sprintf(buf, "Where are you %s? Come here and die!", short_to_name(get_name(victim), 1));
					break;
				case 2:
					sprintf(buf, "Just wait until I find you %s - then you'll pay!", short_to_name(get_name(victim), 1));
					break;
				case 3:
					sprintf(buf, "You're dead %s! Just as soon as I get my hands on you!", short_to_name(get_name(victim), 1));
					break;
			}
			do_say(ch, buf);
		}

		switch (number_bits(2))
		{
			case 0:
				act("$n staggers around blindly, attacking the air!", ch, NULL, NULL, TO_ROOM);
				break;
			case 1:
				act("$n lurches around the area trying to find something to attack!", ch, NULL, NULL, TO_ROOM);
				break;
			case 2:
				act("$n growls in frustration as $e tries to attack unseen enemies!", ch, NULL, NULL, TO_ROOM);
				break;
			case 3:
				act("$n snarls quietly as $e attacks thin air!", ch, NULL, NULL, TO_ROOM);
				break;
		}
		pop_call();
		return;
	}

	if (is_safe(ch, NULL))
	{
		if (number_bits(2) != 0)
		{
			pop_call();
			return;
		}
		if (IS_SET(ch->act, ACT_SMART))
		{
			switch (number_bits(2))
			{
				case 0:
					sprintf(buf, "You're a coward %s! Fight me!", short_to_name(get_name(victim), 1));
					break;
				case 1:
					sprintf(buf, "That's right %s, hide from me you coward!", short_to_name(get_name(victim), 1));
					break;
				case 2:
					sprintf(buf, "C'mon %s, fight you craven dog!", short_to_name(get_name(victim), 1));
					break;
				case 3:
					sprintf(buf, "Only a coward would hide here %s!", short_to_name(get_name(victim), 1));
					break;
			}
			do_say(ch, buf);
		}
		pop_call();
		return;
	}

	if (IS_SET(ch->act, ACT_SMART))
	{
		switch (number_bits(2))
		{
			case 0:
				sprintf(buf, "I'll get you now %s! Die!", short_to_name(get_name(victim), 1));
				break;
			case 1:
				sprintf(buf, "We were not done yet %s!", short_to_name(get_name(victim), 1));
				break;
			case 2:
				sprintf(buf, "Defend yourself %s!", short_to_name(get_name(victim), 1));
				break;
			case 3:
				sprintf(buf, "Prepare for your death %s!", short_to_name(get_name(victim), 1));
				break;
		}
		do_say(ch, buf);
	}
	else
	{
		switch (number_bits(2))
		{
			case 0:
				act("$n contorts $s face and surges to the attack!", ch, NULL, NULL, TO_ROOM);
				break;
			case 1:
				act("$n snarls and leaps to the attack!", ch, NULL, NULL, TO_ROOM);
				break;
			case 2:
				act("$n growls and lunges forwards!", ch, NULL, NULL, TO_ROOM);
				break;
			case 3:
				act("$n grinds $s teeth and leaps forwards!", ch, NULL, NULL, TO_ROOM);
				break;
		}
	}
	multi_hit(ch, victim, TYPE_UNDEFINED);

	pop_call();
	return;
}

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

	push_call("do_attack(%p,%p)",ch,argument);

	one_argument(argument, buf);

	if (buf[0] == '\0')
	{
		victim = ch;
	}
	else	if ((victim = get_player_world(ch, buf)) == NULL)
	{
		send_to_char("Syntax: attack <player>\n\r", ch);
		pop_call();
		return;
	}

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

	pop_call();
	return;
}

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

	push_call("get_attack_string(%p,%p,%p)",ch,viewer,buf);

	if (ch == NULL)
	{
		pop_call();
		return;
	}

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

	attacks=0;
	for (cnt = 0; cnt < MAX_PK_ATTACKS ; cnt++)
	{
		if (ch->pcdata->last_pk_attack_time[cnt] > 0)
		{
			attacks++;
			if( ch->pcdata->last_pk_attack_time[cnt] > mud->current_time )
			{
				sprintf( buf2, "{178}%12s till {128}%s\n\r",
					ch->pcdata->last_pk_attack_name[cnt],
					get_time_string(ch->pcdata->last_pk_attack_time[cnt]));
			}
			else
			{
				sprintf( buf2, "{078}%12s till {028}%s\n\r",
					ch->pcdata->last_pk_attack_name[cnt],
					get_time_string(ch->pcdata->last_pk_attack_time[cnt]));
			}
			leng = str_apd_max( buf, buf2, leng, MAX_STRING_LENGTH );
		}
	}
	if (attacks == 0 )
	{
		if ( viewer == ch )
		{
			sprintf( buf, "{138}  You have never been attacked.\n\r" );
		}
		else
		{
			sprintf( buf, "{138}  %s has never been attacked.\n\r", ch->name );
		}
	}
	pop_call();
	return;
}

/*
	Code for total and max pvnum attacks  -  Chaos 4/20/99
*/

bool check_add_attack( CHAR_DATA *ch, CHAR_DATA *victim )
{
	push_call("check_add_attack(%p,%p)",ch,victim);

	/*
		Killers and Thieves can always be attacked - Scandum 07/02/02
	*/

	if (!IS_NPC(ch) && !IS_NPC(victim))
	{
		int oldest_attack, total_pvnum_attacks, attacks_today, cnt;

		attacks_today = 0;
		oldest_attack = 0;
		total_pvnum_attacks = 0;

		for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++)
		{
			if (victim->pcdata->last_pk_attack_time[cnt] == 0)
			{
				oldest_attack = cnt;
			}
			else if (victim->pcdata->last_pk_attack_time[oldest_attack] > victim->pcdata->last_pk_attack_time[cnt])
			{
				oldest_attack = cnt;
			}

			if (victim->pcdata->last_pk_attack_time[cnt] > mud->current_time)
			{
				attacks_today++;
			}

			if (ch->pcdata->pvnum == victim->pcdata->last_pk_attack_pvnum[cnt]
			&& victim->pcdata->last_pk_attack_time[cnt] > mud->current_time)
			{
				total_pvnum_attacks++;
			}
		}
		if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF))
		{
			if (attacks_today >= MAX_PK_ATTACKS)
			{
				pop_call();
				return( FALSE );
			}

			if (total_pvnum_attacks >= 5)
			{
				pop_call();
				return( FALSE );
			}
			victim->pcdata->last_pk_attack_time[oldest_attack] = mud->current_time + 60 * 60 * 6;
			victim->pcdata->last_pk_attack_pvnum[oldest_attack] = ch->pcdata->pvnum;

			STRFREE(victim->pcdata->last_pk_attack_name[oldest_attack]);
			victim->pcdata->last_pk_attack_name[oldest_attack] = STRALLOC(ch->name);
		}
	}
	pop_call();
	return( TRUE );
}

/*
	Scandum 14-01-2003
*/

void clear_attack_list( CHAR_DATA *ch )
{
	int cnt;

	push_call("clear_attack_list(%p)",ch);

	for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++)
	{
		ch->pcdata->last_pk_attack_time[cnt] = 0;

		STRFREE(ch->pcdata->last_pk_attack_name[cnt]);
		ch->pcdata->last_pk_attack_name[cnt] = STRDUPE(str_empty);
	}
	pop_call();
	return;
}

void spam_attack_list( CHAR_DATA *ch )
{
	int cnt;

	push_call("spam_attack_list(%p)",ch);

	for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++)
	{
		ch->pcdata->last_pk_attack_time[cnt]  = mud->current_time + 60 * 60 * 24;
		ch->pcdata->last_pk_attack_pvnum[cnt] = 0;

		STRFREE(ch->pcdata->last_pk_attack_name[cnt]);
		ch->pcdata->last_pk_attack_name[cnt] = STRDUPE(str_empty);
	}
	pop_call();
	return;
}