#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"

void 
do_recallc (CHAR_DATA * ch, char *argy)
{
  char recall_loc;
  int cost = 0;
  int paid = 0;
  int xp_cost = 0;
  char arg1[500];
  char bufr[500];
  DEFINE_COMMAND ("recall", do_recallc, POSITION_STANDING, 0, LOG_NORMAL, "See help recall for information.")

    arg1[0] = '\0';
  if (argy[0] != '\0')
    {
      argy = one_argy (argy, arg1);
    }
  if (IS_EVIL (ch))
    recall_loc = 1;		/* Aturia */
  else
    recall_loc = 2;
  if (argy[0] != '\0' && !str_prefix ("ytin", argy) && LEVEL (ch) > 15)
    recall_loc = 3;
  if (ch->in_room->sector_type == SECT_INSIDE ||
      ch->in_room->sector_type == SECT_WATER_SWIM || ch->in_room->sector_type == SECT_WATER_NOSWIM ||
      IN_BOAT(ch))
    {
      send_to_char ("You are either: 1. Inside, 2. In water, or 3. In a boat, and therefore you\n\r", ch);
      send_to_char ("cannot recall.\n\r", ch);
      return;
    }
  if (ch->pcdata->no_quit > 0 || ch->pcdata->no_quit_pk > 0)
    {
      char buf[200];
      int ii;
      if (ch->pcdata->no_quit>ch->pcdata->no_quit_pk) ii=ch->pcdata->no_quit; else
						      ii=ch->pcdata->no_quit_pk;
      sprintf (buf, "You must wait %d more ticks before you can recall.\n\r", ii);
      send_to_char ("Please read HELP RECALL for information on why you can't recall right now.\n\r", ch);
      send_to_char (buf, ch);
      return;
    }
  cost = (((LEVEL (ch) - 4) * (LEVEL (ch) - 3)) / 3);
  if (CHEAP_RECALL (ch))
    cost /= 4;
  if (cost < 1)
    cost = 1;
  xp_cost = (LEVEL (ch) * LEVEL (ch) * (LEVEL (ch) / 5) * 9) / 4;
  if (CHEAP_RECALL (ch))
    xp_cost /= 4;
  if (xp_cost < 5)
    xp_cost = 0;
  sprintf (bufr, "It will cost you \x1B[37;1m%d\x1B[37;0m coins and \x1B[37;1m%d\x1B[37;0m experience points to recall.\n\r", cost, xp_cost);
  send_to_char (bufr, ch);
  if (arg1[0] == '\0' || str_prefix (arg1, "yes"))
    {
      send_to_char ("Type 'recall yes' to actually recall.  See HELP RECALL for more info.\n\r", ch);
      return;
    }
  if ((ch->pcdata->bank + (ch->copper) + (ch->gold * 100)) < cost)
    {
      send_to_char ("You don't have enough money to recall!!\n\r", ch);
      return;
    }
  if ((ch->exp) < xp_cost)
    {
      send_to_char ("You don't have enough experience to recall!!\n\r", ch);
      return;
    }

  ch->exp -= xp_cost;
  if (((ch->gold * 100) + (ch->copper)) >= cost)
    {
      sub_coins (cost, ch);
    }
  else
    {
      paid = ((ch->gold * 100) + (ch->copper));
      ch->gold = 0;
      ch->copper = 0;
      cost -= paid;
      ch->pcdata->bank -= cost;
    }

  act ("$n calls upon the generosity of the gods, and recalls to town!", ch, NULL, ch, TO_NOTVICT);
  act ("You call upon the generosity of the gods, and pray for transportation back to town!", ch, NULL, ch, TO_CHAR);

  if (recall_loc == 1)
    {
      char_from_room (ch);
      char_to_room (ch, get_room_index (99));
      do_look (ch, "auto");
      return;
    }
  if (recall_loc == 2)
    {
      char_from_room (ch);
      char_to_room (ch, get_room_index (100));
      do_look (ch, "auto");
      return;
    }

  if (recall_loc == 3)
    {
      char_from_room (ch);
      char_to_room (ch, get_room_index (1004));
      do_look (ch, "auto");
      return;
    }

  return;
}

void 
do_investigate (CHAR_DATA * ch, char *argy)
{
  SINGLE_OBJECT *obj;

  DEFINE_COMMAND ("investigate", do_investigate, POSITION_STANDING, 0, LOG_NORMAL, "This command attempts to investigate reasons of death and looters of a corpse.  Based on the investigation skill.")
    check_room_more (ch->in_room);
  if (ch->pcdata->learned[gsn_invest] < 1)
    {
      send_to_char ("You don't know how to investigate!\n\r", ch);
      return;
    }
  if (argy[0] == '\0')
    {
      send_to_char ("Investigate what?\n\r", ch);
      return;
    }
  if ((obj = get_obj_list (ch, argy, ch->in_room->more->contents)) == NULL)
    {
      send_to_char ("You do not see that here.\n\r", ch);
      return;
    }
  if ((obj->pIndexData->item_type != ITEM_CORPSE_PC) &&
      (obj->pIndexData->item_type != ITEM_CORPSE_NPC))
    {
      send_to_char ("You can only investigate corpses.\n\r", ch);
      return;
    }
  ch->pcdata->tickcounts = 21;
  check_temp (ch);
  send_to_char ("You begin to investigate....\n\r", ch);
  strcpy (ch->pcdata->temp->temp_string, argy);
  NEW_POSITION(ch, POSITION_INVEST);
  return;
}

void 
do_actual_investigate (CHAR_DATA * ch, char *argy)
{
  SINGLE_OBJECT *obj;
  if ((obj = get_obj_list (ch, argy, ch->in_room->more->contents)) == NULL)
    {
      send_to_char ("You do not see that here.\n\r", ch);
      NEW_POSITION(ch, POSITION_STANDING);
      return;
    }
  if ((obj->pIndexData->item_type != ITEM_CORPSE_PC) &&
      (obj->pIndexData->item_type != ITEM_CORPSE_NPC))
    {
      send_to_char ("You can only investigate corpses.\n\r", ch);
      NEW_POSITION(ch, POSITION_STANDING);
      return;
    }
  if (number_range (1, 90) > ch->pcdata->learned[gsn_invest])
    {
      act ("You try to investigate, but you are unable to draw any conclusions due to your limited skill.", ch, NULL, ch, TO_CHAR);
      NEW_POSITION(ch, POSITION_STANDING);
      return;
    }
  send_to_char ("You successfully investigate, and find...\n\r", ch);
  print_reasons (ch, obj);
  if (!ch->pcdata->just_investigated)
    skill_gain (ch, gsn_invest, TRUE);
  ch->pcdata->just_investigated = TRUE;
  NEW_POSITION(ch, POSITION_STANDING);
  return;
}


void 
print_reasons (CHAR_DATA * ch, SINGLE_OBJECT * container)
{
  char buf[500];
  I_CONTAINER *cnt = (I_CONTAINER *) container->more;
  sprintf (buf, "Reason of death: %s.\n\r", (cnt->reason_for_death[0] == '\0' ? "Unknown" : capitalize (cnt->reason_for_death)));
  send_to_char (buf, ch);
  if (cnt->looted_by[0] != '\0')
    {
      if (cnt->looted_by_two[0] != '\0')
	{
	  sprintf (buf, "Looted by: %s and %s.\n\r", cnt->looted_by,
		   cnt->looted_by_two);
	}
      else
	{
	  sprintf (buf, "Looted by: %s.\n\r", cnt->looted_by);
	}
      send_to_char (buf, ch);
    }
  return;
}


void 
pc_death_penalty (CHAR_DATA * ch, CHAR_DATA * victim)
{
  int i;
  bool skill_loss = FALSE;
  if (IS_MOB (victim))
    return;
  if (IS_PLAYER (ch) && pow.skill_loss_on_pk_death)
    skill_loss = TRUE;
  if (IS_MOB (ch) && pow.skill_loss_on_mob_death)
    skill_loss = TRUE;
  if (LEVEL (victim) > 10 && skill_loss)
    {
      for (i = 0; i < SKILL_COUNT; i++)
	{
	  if (i == gsn_hide)
	    continue;
	  if (i == gsn_sneak)
	    continue;
	  if (i == gsn_backstab)
	    continue;
	  if (i == gsn_track)
	    continue;
	  if (i == gsn_dual_wield)
	    continue;
	  if (number_range (1, 3) != 2)
	    continue;
	  if (victim->pcdata->learned[i] < 5)
	    continue;
	  victim->pcdata->learned[i] -= pow.amount_lost_on_death;
	  if (victim->pcdata->learned[i] < 1)
	    victim->pcdata->learned[i] = 1;
	}
    }
  if (LEVEL (victim) < 7)
    gain_exp (victim, UMAX (-6000, -(victim->exp / 23)));
  else if (LEVEL (victim) < 11)
    gain_exp (victim, UMAX (-18000, -(victim->exp / 12)));
  else if (LEVEL (victim) < 15)
    gain_exp (victim, UMAX (-58000, -(victim->exp / 15)));
  else if (LEVEL (victim) < 20)
    gain_exp (victim, UMAX (-138655, -(victim->exp / 24)));
  else if (LEVEL (victim) < 27)
    gain_exp (victim, UMAX (-355744, -(victim->exp / 38)));
  else if (LEVEL (victim) < 33)
    gain_exp (victim, UMAX (-557007, -(victim->exp / 45)));
  else if (LEVEL (victim) < 51)
    gain_exp (victim, UMAX (-895101, -(victim->exp / 65)));
  else
    gain_exp (victim, UMAX (-1584573, -(victim->exp / 100)));
  return;
}

void 
do_fatal (CHAR_DATA * victim, CHAR_DATA * ch, int dt)
{
  int chance_num;
  chance_num = number_range (1, 18);
  if (chance_num == 1 && can_groundfight (victim))
    {
      if (dt == 1001 || dt == 1)
	{
	  act ("Your slash rips into $N's neck, and tears it open!", ch, NULL, victim, TO_CHAR);
	  act ("$n's mighty slash rips your neck open!", ch, NULL, victim, TO_VICT);
	  act ("$n's slash slices $N's neck wide open!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1002 || dt == 2)
	{
	  act ("You puncture a hole in $N's neck with your pierce!", ch, NULL, victim, TO_CHAR);
	  act ("$n's stab punctures a large hole in your neck!", ch, NULL, victim, TO_VICT);
	  act ("$n pierces a large hole in $N's neck!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1003 || dt == 3)
	{
	  act ("Your powerful attack rips open $N's neck!", ch, NULL, victim, TO_CHAR);
	  act ("$n's attack tears into your neck!", ch, NULL, victim, TO_VICT);
	  act ("$n's attack rips open $N's neck!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1005 || dt == 5)
	{
	  act ("Your pound crushes $N's windpipe! Ouch!", ch, NULL, victim, TO_CHAR);
	  act ("$n's powerful pound crushes your windpipe!", ch, NULL, victim, TO_VICT);
	  act ("$n pounds $N's neck, crushing $S windpipe!", ch, NULL, victim, TO_NOTVICT);
	}
      else
	{
	  act ("$n catches you across the neck. Your neck is torn open!", ch, NULL, victim, TO_VICT);
	  act ("$n catches $N across the neck. Ouch!", ch, NULL, victim, TO_NOTVICT);
	  act ("You catch $N across the neck; that's gotta hurt!", ch, NULL, victim, TO_CHAR);
	}
      victim->hit = 1;
      if (IS_PLAYER (victim))
	upd_hps (victim);
    }
  if (chance_num == 2)
    {
      if (dt == 1001 || dt == 1)
	{
	  act ("Your slash tears deep into $N's body!", ch, NULL, victim, TO_CHAR);
	  act ("$n's slash tears deep into your body!!", ch, NULL, victim, TO_VICT);
	  act ("$n's slash tears deep into $N's body!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1002 || dt == 2)
	{
	  act ("You stab a hole right through $N's gut!", ch, NULL, victim, TO_CHAR);
	  act ("$n stabs a hole right through your gut!", ch, NULL, victim, TO_VICT);
	  act ("$n stabs a hole right through $N's gut!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1003 || dt == 3)
	{
	  act ("Your powerful attack sends $N's eyeball flying!", ch, NULL, victim, TO_CHAR);
	  act ("Your eyeball is torn from your socket by $n's attack!", ch, NULL, victim, TO_VICT);
	  act ("$n tears an eyeball off of $N with $s attack!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1005 || dt == 5)
	{
	  act ("You can feel $N's skull cave in under your pound!", ch, NULL, victim, TO_CHAR);
	  act ("You can feel your skull cave in under $n's pound!", ch, NULL, victim, TO_VICT);
	  act ("$n crushes $N's skull with a mighty pound!", ch, NULL, victim, TO_NOTVICT);
	}
      else
	{
	  act ("$n's attack sends $N flying backwards in pain!", ch, NULL, victim, TO_NOTVICT);
	  act ("Your attack sends $N flying backwards in pain!", ch, NULL, victim, TO_CHAR);
	  act ("$n's attack sends you flying backwards in pain!", ch, NULL, victim, TO_VICT);
	}
      victim->hit = 1;
      if (IS_PLAYER (victim))
	upd_hps (victim);
    }
  if (chance_num == 3)
    {
      if (dt == 1001 || dt == 1)
	{
	  act ("Your slash penetrates deep into $N's skull!", ch, NULL, victim, TO_CHAR);
	  act ("$n's slash penetrates deep into your skull!!", ch, NULL, victim, TO_VICT);
	  act ("$n's slash penetrates deep into $N's skull!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1002 || dt == 2)
	{
	  act ("Your stab hits $N right in the temple!", ch, NULL, victim, TO_CHAR);
	  act ("$n's stab pierces your temple and enters your brain!", ch, NULL, victim, TO_VICT);
	  act ("$n stabs a deep hole into $N's temple!", ch, NULL, victim, TO_NOTVICT);
	}
      else if (dt == 1003 || dt == 3)
	{
	  return;
	}
      else if (dt == 1005 || dt == 5)
	{
	  act ("You can hear $N's neck break as your pound connects!", ch, NULL, victim, TO_CHAR);
	  act ("Your neak breaks under the force of $n's attack!", ch, NULL, victim, TO_VICT);
	  act ("$n breaks $N's neck with a powerful pound!", ch, NULL, victim, TO_NOTVICT);
	}
      else
	{
	  return;
	}
      victim->hit = 1;
      if (IS_PLAYER (victim))
	upd_hps (victim);
    }
  return;
}

void 
make_corpse (CHAR_DATA * ch)
{
  char buf[STD_LENGTH];
  SINGLE_OBJECT *corpse = NULL;
  SINGLE_OBJECT *obj;
  SINGLE_OBJECT *obj_next;
  char *name;
  name = NULL;
  corpse = NULL;

  if (IS_MOB (ch) && IS_CORPSE_MOB (ch))
    {
      name = NAME (ch);
      corpse = create_object (get_obj_index (OBJ_VNUM_CORPSE_NPC), 0);
      corpse->timer = number_range (2, 15);
      ((I_CONTAINER *) (corpse->more))->key_vnum=ch->pIndexData->vnum;
    }
  else if (IS_PLAYER (ch))
    {
      name = NAME (ch);
      corpse = create_object (get_obj_index (OBJ_VNUM_CORPSE_PC), 0);
      corpse->timer = number_range (100, 150);
    }

  if (corpse && reasonfd[0] != '\0')
    {
      strcpy (((I_CONTAINER *) corpse->more)->reason_for_death, reasonfd);
    }
  reasonfd[0] = '\0';

  if (!(IS_MOB (ch) && !IS_CORPSE_MOB (ch)))
    {
      sprintf (buf, STR (corpse, short_descr), name);
      if (corpse->short_descr)
	free_string (corpse->short_descr);
      corpse->short_descr = str_dup (buf);
      sprintf (buf, STR (corpse, description), name);
      if (corpse->description)
	free_string (corpse->description);
      corpse->description = str_dup (buf);
    }
  if (IS_PLAYER (ch) || (IS_MOB (ch) && ch->pIndexData->pShop == NULL))
    {
      if (IS_MOB (ch) && !IS_CORPSE_MOB (ch))
	{
	  check_room_more (ch->in_room);
	  ch->in_room->more->copper += ch->copper;
	  ch->in_room->more->gold += ch->gold;
	}
      else {
	((I_CONTAINER *) corpse->more)->money += tally_coins (ch);
	ch->gold=0;
	ch->copper=0;
	}
    }
  for (obj = ch->carrying; obj != NULL; obj = obj_next)
    {
      obj_next = obj->next_content;
      if (IS_PLAYER (ch) && IS_SET (obj->extra_flags, ITEM_SAVE))
	{
	  if (obj->wear_loc != -1)
	    unequip_char (ch, obj);
	  continue;
	}
      obj_from (obj);
      if (IS_MOB (ch) && !IS_CORPSE_MOB (ch))
	obj_to (obj, ch->in_room);
      else if (IS_SET (obj->extra_flags, ITEM_INVENTORY) || (IS_PLAYER (ch) && IS_SET (obj->extra_flags, ITEM_NODROP)))
	free_it (obj);
      else
	obj_to (obj, corpse);
    }
  if (!(IS_MOB (ch) && !IS_CORPSE_MOB (ch)))
    {
      ch->gold = 0;
      ch->copper = 0;
      obj_to (corpse, ch->in_room);
    }
  return;
}

void 
death_cry (CHAR_DATA * ch, bool flaggy)
{
  ROOM_DATA *was_in_room;
  char *msg;
  int door;
  int vnum;
  vnum = 0;
  if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_REPTILE)
    {
      msg = "$n turns into a bloody red mess of blood and gore.";
    }
  else if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_UNDEAD)
    {
      msg = "$n turns to dust before your eyes.";
    }
  else if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_GHOST)
    {
      msg = "$n disappears into thin air...";
    }
  else if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_FISH)
    {
      msg = "$n turns the water red and sinks beneath the surface...";
    }
  else if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_PLANT)
    {
      msg = "$n turns into a lifeless pile of weeds.";
    }
  else if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_STATUE)
    {
      msg = "$n crumbles into a pile of dust.";
    }
  else if (IS_MOB (ch) && ch->pIndexData->mobtype == MOB_BIRD)
    {
      msg = "$n falls to the ground, dead.";
    }
  else if (flaggy == FALSE || !can_yell (ch))
    {
      msg = "You hear $n's death cry.";
    }
  else
    switch (number_bits (4))
      {
      default:
	msg = "You hear $n's death cry.";
	break;
      case 0:
	msg = "$n hits the ground ... DEAD.";
	break;
      case 1:
	msg = "$n splatters blood on your armor.";
	break;
      case 2:
	msg = "You smell $n's sphincter releasing in death.";
	vnum = OBJ_VNUM_INTESTINES;
	break;
      case 3:
	msg = "A fountain of blood forms as $n's head falls to the ground";
	vnum = OBJ_VNUM_SEVERED_HEAD;
	break;
      case 4:
	msg = "$n's heart is torn from $s chest.";
	vnum = OBJ_VNUM_TORN_HEART;
	break;
      case 5:
	msg = "A stream of blood forms as $n's arm is sliced from $s dead body.";
	vnum = OBJ_VNUM_SLICED_ARM;
	break;
      case 6:
	msg = "Blood runs everywhere as $n's leg is sliced from $s dead body.";
	vnum = OBJ_VNUM_SLICED_LEG;
	break;
      }
  act (msg, ch, NULL, NULL, TO_ROOM);
  if (vnum != 0)
    {
      char buf[STD_LENGTH];
      SINGLE_OBJECT *obj;
      char *name;
      name = NAME (ch);
      obj = create_object (get_obj_index (vnum), 0);
      obj->timer = number_range (4, 7);
      sprintf (buf, STR (obj, short_descr), name);
      /*if (obj->short_descr && obj->short_descr!=NULL) free_string( obj->short_descr );
       */ obj->short_descr = str_dup (buf);
      sprintf (buf, STR (obj, description), name);
      /*if (obj->description && obj->description!=NULL) free_string( obj->description );
       */ obj->description = str_dup (buf);
      obj_to (obj, ch->in_room);
    }
  if (IS_MOB (ch))
    msg = "You hear something's death cry.";
  else
    msg = "You hear someone's death cry.";
  was_in_room = ch->in_room;
  for (door = 0; door <= 5; door++)
    {
      EXIT_DATA *pexit;
      if ((pexit = was_in_room->exit[door]) != NULL
	  && pexit->to_room != NULL
	  && pexit->to_room != was_in_room)
	{
	  ch->in_room = pexit->to_room;
	  act (msg, ch, NULL, NULL, TO_ROOM);
	}
    }
  ch->in_room = was_in_room;
  return;
}

void 
raw_kill (CHAR_DATA * victim, bool used_sword)
{
  CHAR_DATA *tmpch;
  CHAR_DATA *tmpchnx;
  check_ced (victim);
  check_fgt (victim);
  victim->ced->attackers[0] = NULL;
  victim->ced->attackers[1] = NULL;
  victim->ced->attackers[2] = NULL;
  victim->ced->attackers[3] = NULL;
  stop_fighting (victim, TRUE);
  
  if (victim->fgt && FIGHTING (victim) && FIGHTING (victim) != NULL && FIGHTING (FIGHTING (victim))
      && FIGHTING (FIGHTING (victim)) != NULL && FIGHTING (FIGHTING (victim)) == victim)
    {
      check_fgt (victim->fgt->fighting);
      victim->fgt->fighting->fgt->fighting = NULL;
      NEW_POSITION(victim->fgt->fighting, POSITION_STANDING);
    }
  if (victim->fgt) victim->fgt->fighting = NULL;
  death_cry (victim, used_sword);
  if (IS_PLAYER (victim) && LEVEL (victim) > 1 && victim->pcdata->carry_number > 0)
    save_corpse (victim);
  for (tmpch = char_list; tmpch != NULL; tmpch = tmpchnx)
    {
      tmpchnx = tmpch->next;
      
      if (FIGHTING(tmpch) == victim)
	{
	CHAR_DATA *cd;
	for (cd=char_list; cd!=NULL; cd=cd->next) {
		if (cd==victim) continue;
		/* check if anyone is fighting HIM/HER */
		if (FIGHTING(cd)==tmpch) {
			tmpch->fgt->fighting=cd;
		}
	}
	if (FIGHTING(tmpch)==victim) { /* if STILL only fighting vict */
		tmpch->fgt->fighting = NULL;	  
	  NEW_POSITION(tmpch, POSITION_STANDING);
	}

	}
	  if (IS_PLAYER (tmpch))
	continue;
      if (victim->in_room && tmpch->in_room && victim->in_room->area == tmpch->in_room->area &&
	  tmpch->pIndexData->yeller_number != 0 && tmpch->ced && tmpch->ced->has_yelled && HUNTING (tmpch) == NULL &&
	  FIGHTING (tmpch) == NULL)
	tmpch->ced->has_yelled = FALSE;
      if (HUNTING (tmpch) && !str_cmp (tmpch->fgt->hunting, NAME (victim)))
	{
	  if (HUNTING (tmpch))
	    {
	      free_string (tmpch->fgt->hunting);
	      tmpch->fgt->hunting = NULL;
	    }
	  /*Mobs that 'move back' to their post go here */
#ifdef NEW_WORLD
	  if (tmpch->pIndexData->vnum == 1012)
	    {
	      static char tmpp[20];
	      if (number_range (1, 2) == 1)
		{
		  sprintf (tmpp, "%d", 1154);
		  check_fgt (tmpch);
		  tmpch->fgt->hunting = str_dup (tmpp);
		}
	      else
		{
		  sprintf (tmpp, "%d", 1155);
		  check_fgt (tmpch);
		  tmpch->fgt->hunting = str_dup (tmpp);
		}
	    }
#endif
	  /*End mobs that 'move back' to their post */
	}
    }
  for (tmpch=char_list; tmpch!=NULL; tmpch=tmpch->next) {
	if (FIGHTING(tmpch)==victim) {
		tmpch->fgt->fighting=NULL;
		tmpch->position=POSITION_STANDING;
		}
	}

  if (MOUNTED_BY (victim) != NULL)
    {
      check_fgt (victim->fgt->mounted_by);
      act ("$n dies, and you fall to the ground.",
	   victim, NULL, victim->fgt->mounted_by, TO_VICT);
      act ("$n dies, causing $N to fall to the ground!", victim, NULL, victim->fgt->mounted_by, TO_NOTVICT);
      check_fgt(victim->fgt->mounted_by);
	victim->fgt->mounted_by->fgt->riding = NULL;
      NEW_POSITION(victim->fgt->mounted_by, POSITION_RESTING);
      victim->fgt->mounted_by = NULL;
    }
  if (RIDING (victim) != NULL)
    {
      act ("$n falls off you, dead.",
	   victim, NULL, victim->fgt->riding, TO_VICT);
      check_fgt (victim->fgt->riding);
      victim->fgt->riding->fgt->mounted_by = NULL;
      victim->fgt->riding = NULL;
    }
  if (IS_MOB (victim))
    {
      make_corpse (victim);
      victim->pIndexData->killed++;
      extract_char (victim, TRUE);
      return;
    }
  make_corpse (victim);
  extract_char (victim, FALSE);
  while (victim->affected)
    affect_remove (victim, victim->affected);
  if (IS_PLAYER (victim))
    victim->affected_by = victim->pcdata->nat_abilities;
  victim->armor = 100;
  NEW_POSITION(victim, POSITION_RESTING);
  victim->hit = UMAX (5, victim->hit);
  upd_hps (victim);
  victim->move = UMAX (5, victim->move);
  upd_mps (victim);
  save_char_obj (victim);
  return;
}

void 
group_gain (CHAR_DATA * ch, CHAR_DATA * victim)
{
  CHAR_DATA *gch;
  int dummyvar;
  char g_exp[500];
  CHAR_DATA *lch;
  int xp;
  int members;
  int highest;
  if (victim == ch)
    return;
  highest = LEVEL (ch);
  members = 0;
  check_room_more (ch->in_room);
  for (gch = ch->in_room->more->people; gch != NULL; gch = gch->next_in_room)
    {
      if (is_same_group (gch, ch))
	{
	  members++;
	  if (LEVEL (gch) > highest)
	    highest = LEVEL (gch);
	}
    }
  if (members == 0)
    {
      bug ("Group_gain: members.", members);
      members = 1;
    }
  lch = (LEADER (ch) != NULL) ? LEADER (ch) : ch;
  if (members > 1)
    xp = (int) (((float) victim->exp *
		 (
		   (float)
		   (1.0 + ((float) ((float) members / 10.0)))
		 )
		) /
		(float) members);
  else
    xp = (victim->exp);
/*more EXP for players */
  if (members < 11)
    {
/*HERE*/
      if (members < 6)
	if (LEVEL (victim) > 7)
	  xp += 100;
      if (members < 3)
	if (LEVEL (victim) > 10)
	  xp += 200;
      if (members < 7)
	if (LEVEL (victim) > 12)
	  xp += 200;
      if (members < 6)
	if (LEVEL (victim) > 15)
	  xp += 400;
      if (members < 9)
	if (LEVEL (victim) > 20)
	  xp += 600;
      if (members < 5)
	if (LEVEL (victim) > 25)
	  xp += 1100;
      if (members < 8)
	if (LEVEL (victim) > 30)
	  xp += 2000;
      if (members < 4)
	if (LEVEL (victim) > 40)
	  xp += 5000;
      if (members < 7)
	if (LEVEL (victim) > 50)
	  xp += 9000;
      if (members < 10)
	if (LEVEL (victim) > 60)
	  xp += 15000;
      if (members < 5)
	if (LEVEL (victim) > 70)
	  xp += 24000;
      if (members < 8)
	if (LEVEL (victim) > 80)
	  xp += 35000;
      if (members < 11)
	if (LEVEL (victim) > 90)
	  xp += 51000;
      if (members < 10)
	if (LEVEL (victim) > 100)
	  xp += 60000;
    }
  if (members > 8 && xp > 40000)
    xp -= 6000;
  if (members > 4 && xp > 70000)
    xp -= 8000;
  if (members > 8 && xp > 50000)
    xp -= 8000;
  if (members > 4 && xp > 90000)
    xp -= 8000;
  if (members > 8 && xp > 80000)
    xp -= 10000;
  if (members > 5 && xp > 60000)
    xp -= 15000;
  if (members > 15)
    xp /= 4;
  if (members > 20)
    xp /= 4;
  if (members > 25)
    xp /= 4;

/* Calculate percentages here */
  if (IS_MOB(victim)) {
	if (victim->pIndexData && victim->pIndexData->hpmult >= 1000) {
		xp = (xp * (victim->pIndexData->hpmult / 1000)) / 10;
	}
}


  for (gch = ch->in_room->more->people; gch != NULL; gch = gch->next_in_room)
    {
      SINGLE_OBJECT *obj;
      SINGLE_OBJECT *obj_next;
      int txp;
      if (!is_same_group (gch, ch) || IS_MOB (gch))
	continue;
      if (IS_PLAYER (victim) && !IS_MOB (ch))
	{
	  if (IS_SET (ch->pcdata->raceflag, RC_EVILRACE) && !IS_SET (victim->pcdata->raceflag, RC_EVILRACE))
	    {
	      check_add_trophy (gch, victim);
	      gch->pcdata->killpoints++;
	      if (LEVEL (gch) <= LEVEL (victim))
		gch->pcdata->killpoints += 2;
	      if (LEVEL (gch) <= LEVEL (victim) - 5)
		gch->pcdata->killpoints += 2;
	      if (LEVEL (gch) <= LEVEL (victim) - 12)
		gch->pcdata->killpoints += 2;
	      if (LEVEL (gch) - 3 <= LEVEL (victim))
		gch->pcdata->killpoints++;
	      xp = (LEVEL (victim)) * 1906;
	      if (LEVEL (victim) > 5)
		xp += 900;
	      if (LEVEL (victim) > 10)
		xp += 3600;
	      if (LEVEL (victim) > 12)
		xp += 6600;
	      if (LEVEL (victim) > 15)
		xp += 9500;
	      if (LEVEL (victim) > 18)
		xp += 12200;
	      if (LEVEL (victim) > 22)
		xp += 16800;
	      if (LEVEL (victim) > 26)
		xp += 19000;
	      if (LEVEL (victim) > 30)
		xp += 23800;
	      if (LEVEL (victim) > 37)
		xp += 27800;
	      if (LEVEL (victim) > 44)
		xp += 36000;
	      if (LEVEL (victim) > 50)
		xp += 51000;
	      if (LEVEL (victim) > 60)
		xp += 65000;
	      xp /= 2;
	      xp /= members;
	    }
	  else if (!IS_SET (ch->pcdata->raceflag, RC_EVILRACE) && IS_SET (victim->pcdata->raceflag, RC_EVILRACE))
	    {
	      check_add_trophy (gch, victim);
	      gch->pcdata->killpoints++;
	      if (LEVEL (gch) <= LEVEL (victim))
		gch->pcdata->killpoints += 2;
	      if (LEVEL (gch) <= LEVEL (victim) - 5)
		gch->pcdata->killpoints += 2;
	      if (LEVEL (gch) <= LEVEL (victim) - 12)
		gch->pcdata->killpoints += 2;
	      if (LEVEL (gch) - 3 <= LEVEL (victim))
		gch->pcdata->killpoints++;
	      xp = (LEVEL (victim)) * 1906;
	      if (LEVEL (victim) > 5)
		xp += 700;
	      if (LEVEL (victim) > 10)
		xp += 1600;
	      if (LEVEL (victim) > 12)
		xp += 4600;
	      if (LEVEL (victim) > 15)
		xp += 6000;
	      if (LEVEL (victim) > 18)
		xp += 8200;
	      if (LEVEL (victim) > 22)
		xp += 11800;
	      if (LEVEL (victim) > 26)
		xp += 15000;
	      if (LEVEL (victim) > 30)
		xp += 19800;
	      if (LEVEL (victim) > 37)
		xp += 23800;
	      if (LEVEL (victim) > 44)
		xp += 28000;
	      if (LEVEL (victim) > 50)
		xp += 41000;
	      if (LEVEL (victim) > 60)
		xp += 50000;
	      xp /= 2;
	      xp /= members;
	    }
	  else
	    xp = 1;
	}
      txp = xp;
      if (IS_MOB (gch))
	continue;
      if (members > 1)
	{
	  if (highest > 40 && LEVEL (gch) < 25)
	    xp /= 8;
	  else if (highest > 30 && LEVEL (gch) < 20)
	    xp /= 7;
	  else if (highest > 20 && LEVEL (gch) < 13)
	    xp /= 6;
	  else if (highest > 16 && LEVEL (gch) < 8)
	    xp /= 5;
	  else if (highest > 13 && LEVEL (gch) < 6)
	    xp /= 5;
	  else if (highest > 8 && LEVEL (gch) < 3)
	    xp /= 4;
	  if (LEVEL (gch) < 30 && (highest - LEVEL (gch)) > 7)
	    xp /= 2;
	  if (LEVEL (gch) < 38 && (highest - LEVEL (gch)) > 12)
	    xp /= 3;
	  if (LEVEL (gch) < 47 && (highest - LEVEL (gch)) > 16)
	    xp /= 3;
	  if ((highest - LEVEL (gch)) > 20)
	    xp /= 3;
	  if ((highest - LEVEL (gch)) > 24)
	    xp /= 3;
	  if ((highest - LEVEL (gch)) > 28)
	    xp /= 4;
	  {
	    gch->pcdata->totalkills++;
	    if (LEVEL (gch) > 15 && LEVEL (gch) < (LEVEL (victim) + 29))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 25 && LEVEL (gch) < (LEVEL (victim) + 37))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 45 && LEVEL (gch) < (LEVEL (victim) + 44))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 55 && LEVEL (gch) < (LEVEL (victim) + 53))
	      gch->pcdata->killpoints++;
	    dummyvar = xp_compute (gch, victim);	/*handles alignment only */
	  }
	}
      else
	{
	  {
	    gch->pcdata->totalkills++;
	    dummyvar = xp_compute (gch, victim);	/*handles alignment only */
	    if (LEVEL (gch) > 12 && LEVEL (gch) < (LEVEL (victim) + 9))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 25 && LEVEL (gch) < (LEVEL (victim) + 14))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 35 && LEVEL (gch) < (LEVEL (victim) + 22))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 55 && LEVEL (gch) < (LEVEL (victim) + 29))
	      gch->pcdata->killpoints++;
	    if (LEVEL (gch) > 75 && LEVEL (gch) < (LEVEL (victim) + 36))
	      gch->pcdata->killpoints++;
	  }
	}
      if (IS_PLAYER (gch) && IS_PLAYER (victim) && ((!IS_EVIL (gch) && !IS_EVIL (victim)) ||
				       (IS_EVIL (gch) && IS_EVIL (victim))))
	xp = 1;

#ifdef NEW_WORLD
      if (IS_MOB (victim) && IS_PLAYER (gch))
	{
/*        if (IS_EVIL(gch)) xp=0; else */
	  if (victim->pIndexData->vnum < 7000)
	    {
	      gch->pcdata->killed_mobs[victim->pIndexData->vnum]++;
	      xp -= (xp * ((ch->pcdata->killed_mobs[victim->pIndexData->vnum] - 1) / 3)) / 100;
	      if (xp < 20)
		xp = number_range (1, 20);
	    }
	}
      /*if (IS_EVIL(gch)) 
         sprintf(g_exp,"You've gained %d experience for fighting.\n\r",gch->pcdata->voting_on);
         else */
#endif
      sprintf (g_exp, "You've gained %d experience for the kill, and %d for fighting.\n\r", xp, gch->pcdata->voting_on);
      send_to_char (g_exp, gch);
      gch->pcdata->voting_on = 0;
      gain_exp (gch, xp);
      xp = txp;
      for (obj = ch->carrying; obj != NULL; obj = obj_next)
	{
	  obj_next = obj->next_content;
	  if (obj->wear_loc == WEAR_NONE)
	    continue;
	  if ((IS_OBJ_STAT (obj, ITEM_ANTI_EVIL) && IS_EVIL (ch))
	      || (IS_OBJ_STAT (obj, ITEM_ANTI_GOOD) && IS_GOOD (ch))
	      || (IS_OBJ_STAT (obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL (ch)))
	    {
	      act ("YOU are zapped by $p.", ch, obj, NULL, TO_CHAR);
	      act ("$n is zapped by $p.", ch, obj, NULL, TO_ROOM);
	      unequip_char (ch, obj);
	      obj_from (obj);
	      obj_to (obj, ch->in_room);
	    }
	}
    }
  return;
}

#ifdef NEW_WORLD
void 
do_berserk (CHAR_DATA * ch, char *argy)
{
  CHAR_DATA *victim;
  DEFINE_COMMAND ("berserk", do_berserk, POSITION_FIGHTING, 0, LOG_NORMAL, "This is a barbarian skill.  It does not need to be practiced.")

    if (!IS_PROF (ch, PROF_BARBARIAN) || LEVEL (ch) < 42)
    {
      send_to_char ("Huh?\n\r", ch);
      return;
    }
  if (!FIGHTING (ch) || ch->position != POSITION_FIGHTING)
    {
      send_to_char ("You must be engaged in combat to use this skill!\n\r", ch);
      return;
    }
  if (ch->fgt && ch->fgt->ears > 9)
    {
      send_to_char ("You can't berserk right now.\n\r", ch);
      return;
    }
  if (ch->move < 32 || ch->hit < 20)
    {
      send_to_char ("You are too exhausted to go berserk!\n\r", ch);
      return;
    }
  victim = FIGHTING (ch);

  if (!ch->fgt || is_fighting_near(ch,victim)==-1) {
	send_to_char("You must be next to your opponent to go berserk.\n\r",ch);
	return;
	}

  if (ch->fgt && ch->fgt->field_ticks>0) {
	setnext(ch,"berserk");
	return;
	}



  SUBMOVE(ch,32);
  SUBHIT(ch,14);
  upd_mps (ch);
  WAIT_STATE (ch, 9 * PULSE_VIOLENCE);
  act ("You go berserk, flailing wildly like a crazed beast!!", ch, NULL, victim, TO_CHAR);
  act ("$n goes berserk, flailing wildly like a crazed beast!!", ch, NULL, victim, TO_ROOM);

 hitop=FALSE; 

  multi_hit (ch, victim, TYPE_UNDEFINED);
  if (victim->data_type != 50)
    multi_hit (ch, victim, TYPE_UNDEFINED);
  if (victim->data_type != 50)
    multi_hit (ch, victim, TYPE_UNDEFINED);
  if (victim->data_type != 50)
    multi_hit (ch, victim, TYPE_UNDEFINED);
  if (victim->data_type != 50)
    multi_hit (ch, victim, TYPE_UNDEFINED);
 if (hitop && ch->fgt && ch->fgt->field && victim && victim->fgt && victim->fgt->field) {
	java_hit_field(ch->fgt->field,ch,ch->fgt->pos_x,ch->fgt->pos_y,
		       victim->fgt->pos_x,victim->fgt->pos_y);
	}
	hitop=FALSE;

  return;
}

void 
do_sing (CHAR_DATA * ch, char *argy)
{
  SPELL_DATA *song;
  DEFINE_COMMAND ("sing", do_sing, POSITION_RESTING, 0, LOG_NORMAL, "This is a bard command which allows a bard to sing a specified song.")

    if (!IS_PROF (ch, PROF_BARD))
    {
      send_to_char ("You are not a bard!  Nobody wants to hear your voice!\n\r", ch);
      return;
    }
  if (argy[0] == '\0')
    {
      send_to_char ("Sing what song?\n\r", ch);
      return;
    }
  if ((song = skill_lookup (argy, -1)) == NULL)
    {
      send_to_char ("You do not know that song!\n\r", ch);
      return;
    }
  if (!(song->values[0] & PROF_BARD))
    {
      send_to_char ("You do not know that song!\n\r", ch);
      return;
    }
  if (song->spell_level > LEVEL (ch))
    {
      send_to_char ("You do not know that song!\n\r", ch);
      return;
    }
  if (song->casting_time != 1)
    {
      send_to_char ("You do not know that song!\n\r", ch);
      return;
    }
  if (song->min_int >= ch->move)
    {
      send_to_char ("You are too tired to sing that song.\n\r", ch);
      return;
    }
  ch->move -= song->min_int;
  WAIT_STATE (ch, (12 * PULSE_VIOLENCE));
  general_spell (song, LEVEL (ch), ch, ch);
  return;
}
#endif