Logo Search packages:      
Sourcecode: aime version File versions  Download package

individual.cpp

/**********************************************************************
 ** individual class: This contains methods that are shared between players
 **                   and mobiles
 **
 **   
 ** Last reviewed:
 **
 **
 ** Copyright (C) 2000 George Noel (Slate)
 **
 **   This program is free software; you can redistribute it and/or modify
 **   it under the terms of the GNU General Public License as
 **   published by the Free Software Foundation; either version 2 of the 
 **   License, or any later version. 
 **
 **   This program is distributed in the hope that it will be useful, but 
 **   WITHOUT ANY WARRANTY; without even the implied warranty of 
 **   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 **   General Public License for more details. 
 ** 
 **   You should have received a copy of the GNU General Public License 
 **   along with this program (in the docs dir); if not, write to the Free
 **   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 **    
 **********************************************************************/

#ifndef INDIVIDUAL_C
#define INDIVIDUAL_C

#include "config.h"
#include "sysdep.h"
#include "mudtypes.h"
#include "strings.h"
#include "global.h"
#include "individual.h"
#include "objtype.h"
#include "merger.h"
#include "indflags.h"
#include "player.h"
#include "wearable.h"
#include "wearflags.h"
#include "newfuncts.h"
#include "specials.h"
#include "code.h"
#include "player.h"
#include "utils.h"
#include "adminflags.h"
#include "boat.h"
#include "gameflags.h"
#include "mobile.h"
#include "race.h"
#include "weapon.h"
#include "locflags.h"
#include "gameflags.h"
#include "inp_funct.h"
#include "user_dbase.h"

char *body_part_name[10] = {"head", "face", "neck", "chest", "back", 
                               "arms", "hands", "waist", "legs", "feet"};

/***********************************************************************
 ** Individual (constructor) - creates the individual object
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/
   
Individual::Individual()
{
   int i;

   left_hand = right_hand = NULL;
   indflags = new Flags(2);
   player_ranks = NULL;

   if (get_type() == OBJ_TYPE_MOBILE)
      indflags->set_flag(INDFLAG_ATTACKPLAYER);

   for (i=0; i <= WEARFLAG_FEET; i++)
      worn_on[i] = NULL;

   strength = the_config.default_strength;
   dexterity = the_config.default_dexterity;
   constitution = the_config.default_constitution;
   health = get_maxhealth();
   max_endurance = endurance = the_config.default_maxendur;
   max_magic = magic = the_config.default_maxmagic;
   intelligence = the_config.default_intel;
   wisdom = the_config.default_wisdom;
   charisma = the_config.default_charisma;
   if (get_type() == OBJ_TYPE_PLAYER)
     wimpy = the_config.default_wimpy;
   else
     wimpy = the_config.default_mob_wimpy;

   cur_loc = NULL;
   target = NULL;
}


/***********************************************************************
 ** Individual (destructor) - destroys this individual object
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/
   
Individual::~Individual()
{
   int i;
   worn_item *tmp_worn;
   fighting_ind *tmp_fighter;   

   delete_ranks();

   /* delete all the worn_item objects */
   for (i=0; i<WEARFLAG_FEET+1; i++)
   {
      tmp_worn = worn_on[i];
      while (tmp_worn != NULL)
      {
         worn_on[i] = tmp_worn->next_worn;
         delete tmp_worn;
         tmp_worn = worn_on[i];
      }
   }

   delete indflags;

   /* now make double sure that nobody is fighting us before we delete */
   if (mainstruct != NULL)
   {
      mainstruct->reset_fight_list();
      tmp_fighter = mainstruct->get_next_fighter();

      while (tmp_fighter != NULL)
      {
         if (((Individual *) tmp_fighter->the_fighter) == this)
         {
            mainstruct->remove_fighter(this);
            mainstruct->clear_fighter(this);
         }

         tmp_fighter = mainstruct->get_next_fighter();
      }
   }
}



/***********************************************************************
 ** tell_ind - does a tell to an individual on the game
 **
 ** Parameters: target - the individual who is being told
 **             the_string - the string we are telling to them
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::tell_ind(Individual *target, char *the_string)
{
   Player *target_plr = NULL;
   Player *teller_plr = NULL;
   Strings holder;
   Strings formatted;
   Flags *tmp_indflags;

   if ((target == NULL) || (the_string == NULL))
      return -1;

   /* first send all info to the target */
   if (target->get_type() == OBJ_TYPE_PLAYER)
   {
      target_plr = (Player *) target;

      formatted.format_for_comm(the_string, (strlen(get_title()) + 12), 
                                             the_config.max_line_len);
      target_plr->send_plr("&+B%s&+w tells &+Byou &+W'&+G%s&+W'&*\n", 
                                       get_title(), formatted.str_show());
   }

   tmp_indflags = target->get_indflags();

   /* next send all info to the teller */
   if (get_type() == OBJ_TYPE_PLAYER)
   {
      teller_plr = (Player *) this;
      if (tmp_indflags->get_flag(INDFLAG_CORPSE))
      {
         teller_plr->send_plr("You converse with the corpse.  "
                      "Strange, it does not respond.\n");
      }
      else
      {
         formatted.format_for_comm(the_string, (strlen(get_title()) + 12), 
                                             the_config.max_line_len);
         teller_plr->send_plr("&+BYou&+w tell &+B%s &+W'&+G%s&+W'&*\n", 
                            target->get_title(), formatted.str_show());
      }
   }

   if (teller_plr != NULL)
   {
      if (tmp_indflags->get_flag(INDFLAG_CORPSE))
      {
       holder.sprintf("%s tries to talk with a corpse.\n", 
                                       teller_plr->get_title());
      }
      else
      {
         holder.sprintf("%s holds a conversation with %s.\n", 
                teller_plr->get_title(), target->get_title());
      }
      (teller_plr->get_loc())->send_location(holder.str_show(), 
                                           teller_plr, target_plr, CAN_SEE);
      (teller_plr->get_loc())->send_location(
        "You hear the sounds of a conversation in the darkness.\n", teller_plr, 
                                                     target_plr, CANT_SEE);

   }
   return 1;
}


/***********************************************************************
 ** move_merger - moves a merger from one individual to another
 **
 ** Parameters: target - the individual who is being told
 **             the_string - the string we are telling to them
 **
 ** Returns:  1 for success, 
 *           -1 for failure,
 **          -2 for not enough mergers in the item to move
 **
 ***********************************************************************/

int Individual::move_merger(Individual *target, Merger **the_merger, 
                                                            int num_of)
{
   Merger *new_merger;
   MudObject *parent_merger;
   int    new_num;

   if (num_of > (*the_merger)->get_number_of())
      return -2;

   if (num_of == (*the_merger)->get_number_of())
   {
      remove_contained((MudObject *) *the_merger);
   }
   else
   {         
      if ((*the_merger)->get_parent() != NULL)
      {
         parent_merger = mainstruct->get_object((*the_merger)->get_parent());
         new_merger = (Merger *)  
                   (mainstruct->get_dbase())->clone_object(parent_merger);
      }
      else
         new_merger = (Merger *) 
          (mainstruct->get_dbase())->clone_object((MudObject *) *the_merger);
      new_merger->set_number_of(num_of);
      new_num = (*the_merger)->get_number_of() - num_of;
      (*the_merger)->set_number_of(new_num);
      *the_merger = new_merger;
   }

   if (target->add_contained((MudObject *) *the_merger) == 2)
   {
      return 2;
   }
   return 1;
}


/***********************************************************************
 ** wield_moveable - wields a moveable object, accounting for how many
 **                  hands it takes to wield it
 **
 ** Parameters: the_item - the item to wield
 **
 ** Returns: 1 for success, -1 for failure, -2 for not enough hands
 **
 ***********************************************************************/
   
int Individual::wield_moveable(Moveable *the_item)
{
   Weapon *the_weapon;

   if (the_item->get_type() == OBJ_TYPE_WEAPON)
   {
      the_weapon = (Weapon *) the_item;
    
      if (the_weapon->get_wield_type() == One_Handed)
      {
         if (right_hand == NULL)
            right_hand = the_item;
         else if (left_hand == NULL)
            left_hand = the_item;
         else
       {
            unwield_moveable(Right);
            right_hand = the_item;
         }
         return 1;
      }
      else
      {
         if ((left_hand != NULL) || (right_hand != NULL))
       {
            unwield_moveable(Left);
            unwield_moveable(Right);
         }

         left_hand = right_hand = the_item;
         return 1;
      }
   }
   return -1;   
}


/***********************************************************************
 ** unwield_moveable - unwields a moveable object from a particular hand.
 **                    if the object is two-handed, it unwields both
 **
 ** Parameters: the_hand - the hand we are going to unwield
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::unwield_moveable(playerhand the_hand)
{
   Weapon *the_weapon;
   Moveable *the_moveable;
   Moveable **hand_ptr;

   if (the_hand == Left)
   {
      if ((the_moveable = left_hand) == NULL)
         return -1;

      hand_ptr = &left_hand;
   }
   else
   {
      if ((the_moveable = right_hand) == NULL)
         return -1;

      hand_ptr = &right_hand;

   }
   if (the_moveable->get_type() == OBJ_TYPE_WEAPON)
   {
      the_weapon = (Weapon *) the_moveable;
      if (the_weapon->get_wield_type() == Two_Handed)
      {
         left_hand = right_hand = NULL;
         return 1;
      }
      *hand_ptr = NULL;
      return 1; 
   }

   return -1;
}


/***********************************************************************
 ** get_wielded - gets the object that is wielded in a particular hand
 **
 ** Parameters: the_hand - the hand we want to get the object from
 **
 ** Returns: a pointer to the object if found
 **
 ***********************************************************************/

Moveable *Individual::get_wielded(playerhand the_hand)
{
   if (the_hand == Left)
      return left_hand;
   else
      return right_hand;

}


/***********************************************************************
 ** get_indflags - gets the individual flags object
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the individual flags structure
 **
 ***********************************************************************/

Flags *Individual::get_indflags()
{
   return indflags;
}


/***********************************************************************
 ** is_male - is this individual male
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for male, 0 for not
 **
 ***********************************************************************/

int Individual::is_male()
{
   return (sex == SEX_MALE);
}


/***********************************************************************
 ** is_female - is this individual female
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for female, 0 for not
 **
 ***********************************************************************/

int Individual::is_female()
{
    return (sex == SEX_FEMALE);
}


/***********************************************************************
 ** is_neuter - is this individual neuter
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for neuter, 0 for not
 **
 ***********************************************************************/

int Individual::is_neuter()
{
    return (sex == SEX_NEUTER);
}


/***********************************************************************
 ** get_sex - get the individual's sex
 **
 ** Parameters: Nothing
 **
 ** Returns: 0, 1, or 2.
 **
 ***********************************************************************/

int Individual::get_sex()
{
    return sex;
}


/***********************************************************************
 ** get_sex_possessive_str - get the possessive form of the individual's 
 **                          pronoun (his, her, its)
 **
 ** Parameters: Nothing
 **
 ** Returns: his, her, or its
 **
 ***********************************************************************/

char *Individual::get_sex_possessive_str()
{
    return _(sex_possessive[sex]);
}


/***********************************************************************
 ** get_sex_str - get the name form of this sex
 **
 ** Parameters: Nothing
 **
 ** Returns: Male, Female, Neuter
 **
 ***********************************************************************/

char *Individual::get_sex_str()
{
    return _(sex_name[sex]);
}


/***********************************************************************
 ** set_sex - set the individual's sex
 **
 ** Parameters: a SEX_xxx flag
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Individual::set_sex(int inSex)
{
    sex = inSex;
}


/***********************************************************************
 ** is_visible - is this individual totally visible
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for true, 0 for false
 **
 ***********************************************************************/

int Individual::is_visible()
{
    return (vislvl == VIS_VISIBLE);
}


/***********************************************************************
 ** is_vis_game - is this individual game invis
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for true, 0 for false
 **
 ***********************************************************************/

int Individual::is_vis_game()
{
    return (vislvl == VIS_GAME);
}


/***********************************************************************
 ** is_vis_incog - is this individual incognito
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for true, 0 for false
 **
 ***********************************************************************/

int Individual::is_vis_incog()
{
    return (vislvl == VIS_INCOG);
}


/***********************************************************************
 ** is_vis_admin - is this individual admin invis
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for true, 0 for false
 **
 ***********************************************************************/

int Individual::is_vis_admin()
{
    return (vislvl == VIS_ADMIN);
}


/***********************************************************************
 ** get_vislvl - get the vislvl of the individual
 **
 ** Parameters: Nothing
 **
 ** Returns: 0, 1, 2, or 3
 **
 ***********************************************************************/

int Individual::get_vislvl()
{
    return vislvl;
}


/***********************************************************************
 ** get_vislvl_str - gets the string version of an invidivual's vislvl
 **
 ** Parameters: Nothing
 **
 ** Returns: Visible, GameInvis, Incognito, or AdminInvis
 **
 ***********************************************************************/

char *Individual::get_vislvl_str()
{
    return vis_table[vislvl];
}


/***********************************************************************
 ** set_vislvl - sets an individual's vislvl
 **
 ** Parameters: VIS_VISIBLE, VIS_GAME, VIS_INCOG, or VIS_ADMIN
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Individual::set_vislvl(int in_vislvl)
{
    vislvl = in_vislvl;
}

/***********************************************************************
 ** wear_item - places an item in the player's linked list of body parts
 **             depending on where it should go
 **
 ** Parameters: the_item - the item to place on this player
 **
 ** Returns: 1 for success, -1 for failure, -2 if it can't be worn, 
 **                         -3 for already worn
 **
 ***********************************************************************/

int Individual::wear_item(Wearable *the_item)
{
   int i;
   Flags *tmp_wearflags;
   Flags *tmp2_wearflags;
   int is_toplayer;
   worn_item *new_worn;

   if (the_item == NULL)
      return -1;

   tmp_wearflags = the_item->get_wearflags();

   /* check for shield, if so, we need to wield */
   if (tmp_wearflags->get_flag(WEARFLAG_WIELDABLE))
   {
      if (right_hand == NULL)
         right_hand = the_item;
      else if (left_hand == NULL)
         left_hand = the_item;
      else
         return -4;         
   }

   /* first make sure we can add it everywhere we need to */
   is_toplayer = tmp_wearflags->get_flag(WEARFLAG_TOPLAYER);
   for (i=0; i<=WEARFLAG_FEET; i++)
   {
      /* see if the needed spots are free */
      if (is_toplayer)
      {
         if ((tmp_wearflags->get_flag(i)) && (worn_on[i] != NULL))
       {
            tmp2_wearflags = (worn_on[i]->the_obj)->get_wearflags();
            if (tmp2_wearflags->get_flag(WEARFLAG_TOPLAYER))
               return -2;

         }
      }

      /* make sure we're not already wearing it */
      new_worn = worn_on[i];
      while (new_worn != NULL)
      {
         if (the_item == new_worn->the_obj)
           return -3;
         new_worn = new_worn->next_worn;
      }
   }

   /* now we add it to all places that it should be worn */
   for (i=0; i<=WEARFLAG_FEET; i++)
   {
      if (tmp_wearflags->get_flag(i))
      {
         new_worn = new worn_item;
         new_worn->next_worn = NULL;
         new_worn->the_obj = the_item;
         if (worn_on[i] == NULL)
       {
            worn_on[i] = new_worn;
         }
         else if (is_toplayer)
       {
            new_worn->next_worn = worn_on[i];
            worn_on[i] = new_worn;
         }
         else
       {
            tmp2_wearflags = (worn_on[i]->the_obj)->get_wearflags();
            if (tmp2_wearflags->get_flag(WEARFLAG_TOPLAYER))
          {
               new_worn->next_worn = worn_on[i]->next_worn;
               worn_on[i]->next_worn = new_worn;
            }
            else
          {
               new_worn->next_worn = worn_on[i];
               worn_on[i] = new_worn;
            }
         }
      }
   }
   (the_item->get_itemflags())->set_flag(ITEMFLAG_WORN);

   return 1;

}


/***********************************************************************
 ** remove_item - removes the item from the worn lists
 **
 ** Parameters: the_item - the item to remove
 **
 ** Returns: 1 for removed, 0 for not worn
 **
 ***********************************************************************/

int Individual::remove_item(Wearable *the_item)
{
   int       i;
   worn_item *tmp_worn;
   worn_item *prev_worn = NULL;
   int       found = 0;
   Flags     *tmp_wearflags;

   tmp_wearflags = the_item->get_wearflags();

   /* first if it is a shield unwield it */
   if (tmp_wearflags->get_flag(WEARFLAG_WIELDABLE))
   {
      if (left_hand == the_item)
         left_hand = NULL;
      else if (right_hand == the_item)
         right_hand = NULL;
      else
         return 0;
      return 1;
   }


   for (i=0; i<=WEARFLAG_FEET; i++)
   {
      tmp_worn = worn_on[i];
      if ((worn_on[i] != NULL) && (worn_on[i]->the_obj == the_item))
      {
         worn_on[i] = worn_on[i]->next_worn;
         found = 1;
         delete tmp_worn;
      }
      else
      {
         while ((tmp_worn != NULL) && (tmp_worn->the_obj != the_item))
         {
            prev_worn = tmp_worn;
            tmp_worn = tmp_worn->next_worn;
         }
         if (tmp_worn != NULL)
       {
            prev_worn->next_worn = tmp_worn->next_worn;
            found = 1;
            delete tmp_worn;
         }
      }
   }
   if (found)
      (the_item->get_itemflags())->clr_flag(ITEMFLAG_WORN);

   return found;
}


/***********************************************************************
 ** is_worn - is this item worn by the player
 **
 ** Parameters: the_item - the item to look for
 **
 ** Returns: 1 for worn, 0 for not worn
 **
 ***********************************************************************/

int Individual::is_worn(Wearable *the_item)
{
   int       i;
   worn_item *tmp_worn;

   for (i=0; i<=WEARFLAG_FEET; i++)
   {
      tmp_worn = worn_on[i];
      while (tmp_worn != NULL)
      {
         if (tmp_worn->the_obj == the_item)
            return 1;
         tmp_worn = tmp_worn->next_worn;
      }
   }
   return 0;
}


/***********************************************************************
 ** display_top_worn - displays only those items that are at the top
 **                    of the stacks since they are the only ones that
 **                    we will make visible
 **
 ** Parameters: the_item - the item to remove
 **
 ** Returns: num objects displayed for success, -1 for failure
 **
 ***********************************************************************/

int Individual::display_top_worn(Player *the_player)
{
   int       i, j;
   worn_item *tmp_worn;
   Strings   holder;
   Strings   send_str;
   int       line_len = 0;
   int       count = 0;
   int       already_shown = 0;

   send_str = "They are wearing: ";
   for (i=0; i<=WEARFLAG_FEET; i++)
   {
      tmp_worn = worn_on[i];
      if (tmp_worn != NULL)
      {
         already_shown = 0;
         for (j=0; j<i; j++)
       {
            if ((worn_on[j] != NULL) && 
                (worn_on[j]->the_obj == worn_on[i]->the_obj))
          {
               already_shown = 1; 
            }
         }
         if (!already_shown)
       {
            holder.sprintf("%s%s", ((line_len == 0) ? "" : ", "), 
                                       (tmp_worn->the_obj)->get_title());

            send_str.str_cat(holder.str_show());
            count++;
         }

         if ((line_len = send_str.str_len()) >= the_config.max_line_len)
         {
            the_player->send_plr(send_str.str_show());
            the_player->send_plr("\n");
            send_str = "                  ";
            line_len = 0;
         } 
      }
   }
   if (line_len != 0)
      the_player->send_plr(send_str.str_show());
   the_player->send_plr("\n");
   return count;
}


/***********************************************************************
 ** display_all_worn - displays all items worn and where worn
 **
 ** Parameters: Nothing
 **
 ** Returns: num objects displayed for success, -1 for failure
 **
 ***********************************************************************/

int Individual::display_all_worn()
{
   int       i;
   worn_item *tmp_worn;
   Strings   holder;
   Strings   send_str;
   int       line_len = 0;
   int       count = 0;
   int       first_display;
   Player    *the_player;

   char *body_parts[] = {"Head",  "Face",  "Neck", "Chest", "Back", "Arms", 
                         "Hands", "Waist", "Legs", "Feet"};

   if (get_type() != OBJ_TYPE_PLAYER)
      return -1;

   the_player = (Player *) this;

   the_player->send_plr("Worn on body:\n");
   for (i=0; i<=WEARFLAG_FEET; i++)
   {
      tmp_worn = worn_on[i];

      first_display = 0;
      while (tmp_worn != NULL)
      {
         holder.sprintf("%s%s", ((line_len == 0) ? "" : ", "), 
                                       (tmp_worn->the_obj)->get_title());

         send_str.str_cat(holder.str_show());
         count++;

         
         if ((line_len = send_str.str_len()) >= (the_config.max_line_len - 10))
         {
            holder.sprintf("\t%s: \t%s\n", body_parts[i], 
                                              send_str.str_show());
            the_player->send_plr(holder.str_show());
            send_str.truncate(0);
            line_len = 0;
            first_display = 1;
         }
         tmp_worn = tmp_worn->next_worn;
      }
      if (line_len != 0)
      {
         if (first_display)
            holder.sprintf("\t\t%s\n", send_str.str_show());
         else
            holder.sprintf("\t%s: \t%s\n", body_parts[i], 
                                                  send_str.str_show());
         the_player->send_plr(holder.str_show());
         send_str.truncate(0);
         line_len = 0;
      }
      else if (worn_on[i] == NULL)
         the_player->send_plr("\t%s: \t -\n", body_parts[i]);
   }

   return count;
}



/***********************************************************************
 ** has_lit - individual contains an object that is lit
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 for has one, 0 for not
 **
 ***********************************************************************/

int Individual::has_lit(void)
{
   Inventory  *ind_list;
   MudObject  *next_obj;
   Item       *an_item;
   Flags      *itemflags;

   ind_list = get_inventory();
   ind_list->reset_current();
   
   next_obj = ind_list->get_next();
   while (next_obj != NULL)
   {
      if (next_obj->is_an_item())
      {
         an_item = (Item *) next_obj;
         itemflags = an_item->get_itemflags();
         if ((itemflags->get_flag(ITEMFLAG_LIT)) || 
             (itemflags->get_flag(ITEMFLAG_GLOWING)))
            return 1;
    
      }
      next_obj = ind_list->get_next();
   }
   return 0;
}


/***********************************************************************
 ** get_strength - returns the strength value
 **
 **
 ***********************************************************************/

int Individual::get_strength(void)
{
   return strength;
}


/***********************************************************************
 ** set_strength - sets the strength value
 **
 **
 ***********************************************************************/

void Individual::set_strength(int the_value)
{
   if (the_value < 0)
      return;

   if (the_value > 100)
      strength = 100;
   else
      strength = the_value;

}


/***********************************************************************
 ** set_dexterity - sets the dexterity value
 **
 **
 ***********************************************************************/

void Individual::set_dexterity(int the_value)
{
   if (the_value < 0)
      return;

   if (the_value > 100)
      dexterity = 100;
   else
      dexterity = the_value;
}


/***********************************************************************
 ** get_dexterity - returns the dexterity value
 **
 **
 ***********************************************************************/

int Individual::get_dexterity(void)
{
   return dexterity;
}


/***********************************************************************
 ** set_health - sets the health value
 **
 **
 ***********************************************************************/

void Individual::set_health(int the_value)
{
   health = the_value;
}


/***********************************************************************
 ** get_health - returns the health value
 **
 **
 ***********************************************************************/

int Individual::get_health(void)
{
   return health;
}


/***********************************************************************
 ** get_wimpy - gets the wimpy point the individual has set
 **
 **
 ***********************************************************************/

int Individual::get_wimpy()
{
   return wimpy;
}


/***********************************************************************
 ** set_wimpy - sets the flee point the individual currently has
 **
 ** Parameters: the_num - the new wimpy value
 **
 ***********************************************************************/

void Individual::set_wimpy(int the_num)
{
   if (the_num > 0)
      wimpy = the_num;
   else
      wimpy = 0;
}


/***********************************************************************
 ** set_constitution - sets the constitution value
 **
 **
 ***********************************************************************/

void Individual::set_constitution(int the_value)
{
   if (the_value < 0)
      return;

   if (the_value > 100)
      constitution = 100;
   else
      constitution = the_value;
}

/***********************************************************************
 ** get_constitution - returns the constitution value
 **
 **
 ***********************************************************************/

int Individual::get_constitution(void)
{
   return constitution;
}


/***********************************************************************
 ** get_maxhealth - returns the maxhealth value
 **
 **
 ***********************************************************************/

int Individual::get_maxhealth(void)
{
   return constitution * 5;
}


/***********************************************************************
 ** set_intel - sets the intelligence value
 **
 **
 ***********************************************************************/

void Individual::set_intel(int the_value)
{
   if (the_value < 0)
      return;

   if (the_value > 100)
      intelligence = 100;
   else
      intelligence = the_value;
}


/***********************************************************************
 ** get_intel - returns the intelligence value
 **
 **
 ***********************************************************************/

int Individual::get_intel(void)
{
   return intelligence;
}

/***********************************************************************
 ** set_wisdom - sets the wisdom value
 **
 **
 ***********************************************************************/

void Individual::set_wisdom(int the_value)
{
   if (the_value < 0)
      return;

   if (the_value > 100)
      wisdom = 100;
   else
      wisdom = the_value;
}


/***********************************************************************
 ** get_wisdom - returns the wisdom value
 **
 **
 ***********************************************************************/

int Individual::get_wisdom(void)
{
   return wisdom;
}


/***********************************************************************
 ** set_charisma - sets the charisma value
 **
 **
 ***********************************************************************/

void Individual::set_charisma(int the_value)
{
   if (the_value < 0)
      return;

   if (the_value > 100)
      charisma = 100;
   else
      charisma = the_value;
}


/***********************************************************************
 ** get_charisma - returns the charisma value
 **
 **
 ***********************************************************************/

int Individual::get_charisma(void)
{
   return charisma;
}


/***********************************************************************
 ** get_max_magic - returns the max magic the player is capable of
 **
 **
 ***********************************************************************/

int Individual::get_max_magic()
{
   return max_magic;
}


/***********************************************************************
 ** set_max_magic - sets the max magic the player is capable of
 **
 ** Parameters: the_num - the new max_magic value
 **
 ***********************************************************************/

void Individual::set_max_magic(int the_num)
{
   if (the_num > 0)
      max_magic = the_num;
}


/***********************************************************************
 ** get_max_endurance - gets the endurance the player is capable of
 **
 **
 ***********************************************************************/

int Individual::get_max_endurance()
{
   return max_endurance;
}


/***********************************************************************
 ** set_max_endurance - sets the endurance the player is capable of
 **
 ** Parameters: the_num - the new max_endurance value
 **
 ***********************************************************************/

void Individual::set_max_endurance(int the_num)
{
   if (the_num > 0)
      max_endurance = the_num;
}


/***********************************************************************
 ** get_magic - gets the current magic level the player has
 **
 **
 ***********************************************************************/

int Individual::get_magic()
{
   return magic;
}

/***********************************************************************
 ** set_magic - sets the magic level the player is currently at
 **
 ** Parameters: the_num - the new magic value
 **
 ***********************************************************************/

void Individual::set_magic(int the_num)
{
   if (the_num > 0)
      magic = the_num;
   else
      magic = 0;
}


/***********************************************************************
 ** get_endurance - gets the endurance the player has left
 **
 **
 ***********************************************************************/

int Individual::get_endurance()
{
   return endurance;
}


/***********************************************************************
 ** set_endurance - sets the endurance the player is currently at
 **
 ** Parameters: the_num - the new endurance value
 **
 ***********************************************************************/

void Individual::set_endurance(int the_num)
{
   if (the_num > 0)
      endurance = the_num;
   else
      endurance = 0;
}


/***********************************************************************
 ** request_fight - requests to fight a mobile (politely of course), and
 **                 if its ok, the mobile sets appropriate attributes. If
 **                 not, the return value states why
 **
 ** Parameters: the_aggressor - who is requesting the attack
 **
 ** Returns: 1 for the fight is on!
 **          -1 for error
 **          -2 for too many people attacking already
 **          -3 for im already fighting you
 **          -4 for I'm already dead you idiot!
 **          -5 for you are dead so can't fight
 **
 ***********************************************************************/

int Individual::request_fight(Individual *the_target)
{
   int num_attack;

   if (the_target == NULL)
      return -1;

   if ((indflags->get_flag(INDFLAG_CORPSE)) ||
       (indflags->get_flag(INDFLAG_GHOST)))
   {
      return -5;
   }

   if (((the_target->get_indflags())->get_flag(INDFLAG_CORPSE)) ||
       ((the_target->get_indflags())->get_flag(INDFLAG_GHOST)))
      return -4;

   if ((num_attack = mainstruct->get_num_attacking(the_target)) >=
                                                  the_config.max_num_attacking)
      return -2;

   if (target == the_target)
      return -3;

   the_target->start_fight(this);

   return 1;
}


/***********************************************************************
 ** start_fight - starts a fight with the person indicated
 **
 ** Parameters: the_target - who we are attacking
 **
 ** Returns: 1 for the fight is on!
 **          -1 for error
 **
 ***********************************************************************/

int Individual::start_fight(Individual *the_target)
{
   Player  *the_player = NULL;
   int     stand = 0;
   Strings holder;

   if (the_target == NULL)
      return -1;

   if (target == NULL)
      target = the_target;

   /* they shouldn't get here, but in case they do, don't let them fight
      a corpse */
   if ((target->get_indflags())->get_flag(INDFLAG_CORPSE))
      return 0;

   if (is_asleep())
   {
      indflags->clr_flag(INDFLAG_SLEEPING);
      if (get_type() == OBJ_TYPE_PLAYER)
      {
         the_player = (Player *) this;
         the_player->send_plr("You awaken and clamber to your feet.\n");
      }
      stand = 1;
   }

   if (is_sitting())
   {
      indflags->clr_flag(INDFLAG_SITTING);
      if (get_type() == OBJ_TYPE_PLAYER)
      {
         the_player = (Player *) this;
         the_player->send_plr("You clamber to your feet.\n");
      }
      stand = 1;
   }

   if (stand)
   {
      holder.sprintf("%s clambers to %s feet.\n", get_title(), 
                get_sex_possessive_str());
      (get_loc())->send_location(holder.str_show(), the_player);
   }

   indflags->set_flag(INDFLAG_FIGHTING);
   mainstruct->add_fighter(this, 0);
   return 1;
}

/***********************************************************************
 ** stop_fighting - stops fighting with all
 **
 ** Returns: 1 for the fight is done
 **          -1 for failed
 **
 ***********************************************************************/

int Individual::stop_fighting(void)
{
   target = NULL;
   if (mainstruct->get_num_attacking(this) == 0)
      indflags->clr_flag(INDFLAG_FIGHTING);
   mainstruct->remove_fighter(this);
   mainstruct->clear_fighter(this);
   return 1;
}

/***********************************************************************
 ** switch_focus - change who we are directing our blows at
 **
 ** Parameters: the_target - who we are attacking
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Individual::switch_focus(Individual *the_target)
{
   if (target == NULL)
      return;

   target = the_target;
}


/***********************************************************************
 ** get_target - gets the target of this player's attack
 **
 **
 ***********************************************************************/

Individual *Individual::get_target(void)
{
   return target;
}

/***********************************************************************
 ** get_rand_weapon - gets a random weapon the individual is wielding
 **
 ***********************************************************************/

Weapon *Individual::get_rand_weapon(playerhand *the_hand)
{
  Moveable *the_wielded = NULL;
  int      rand_num;

  rand_num = 1+ (int) (2.0*(rand()/(RAND_MAX+1.0)));
  switch(rand_num)
  {
     case 1:
        the_wielded = get_wielded(Left);
      *the_hand = Left;
        break;
     case 2:  
        the_wielded = get_wielded(Right);
      *the_hand = Right;
        break;
     default:
        fault("Invalid hand chosen!\n");
        return NULL;
  }

  /* is it bare hands? If so, try the other hand */
  if ((the_wielded == NULL) || 
      (the_wielded->get_type() != OBJ_TYPE_WEAPON))
  {
     switch(rand_num)
     {
        case 2:
           the_wielded = get_wielded(Left);
         *the_hand = Left;
           break;
        case 1:  
           the_wielded = get_wielded(Right);
         *the_hand = Right;
           break;
        default:
           fault("Invalid hand chosen!\n");
           return NULL;
     }
  }
  
  if ((the_wielded == NULL) || 
      (the_wielded->get_type() != OBJ_TYPE_WEAPON))
    return NULL;

  return (Weapon *) the_wielded;
}


/***********************************************************************
 ** get_accuracy - develops an accuracy index that is used to
 **                determine if you hit or block, or if the shot 
 **                misses.  Also returns the weapon used.
 **
 ** Parameters: the_wielder - who we are calculating for
 **             the_wielded - the item to use for defending/attacking
 **             attack - is the player attacking or defending?
 **
 ** Returns: the difference index
 **
 ***********************************************************************/

int Individual::get_accuracy(Individual *the_wielder, Moveable **the_wielded, 
                       int attack)
{
   int      rand_num;
   float    str_index;
   float    dex_index;
   Weapon   *the_weapon = NULL;
   int      chance_index;
   int      difference;
   float    disadvantage = 1.0;
   Wearable *a_shield = NULL;
   playerhand the_hand;

   /* if they can't see, they can't hit squat */
   if ((the_wielder->get_type() == OBJ_TYPE_PLAYER) &&
       !((the_wielder->get_loc())->is_lit(the_wielder)))
      disadvantage = (float)0.3;

   // Pick a weapon hand and a weapon
   the_weapon = get_rand_weapon(&the_hand);

   // If they are defending, allow shields also
   if ((((*the_wielded) = the_weapon) == NULL) && (!attack))
   {
     if (((*the_wielded) = the_wielder->get_wielded(the_hand)) != NULL)
     {
        a_shield = (Wearable *) *the_wielded;
     }
   }

   /* if it still equals NULL, we just return an accuracy based on their
      dexterity and a bit of chance, from 50-100 since it is just fists */
   if ((the_weapon == NULL) && (a_shield == NULL))
   {
     *the_wielded = NULL;
      rand_num = 1+ (int) (100.0*(((float) rand())/((float) (RAND_MAX+1.0))));
      return (int) ((float) (rand_num - (50 - (the_wielder->get_dexterity()/2)))
                                                * disadvantage);
   }

   /* is it a weapon or a shield? */
   if (a_shield != NULL)
   {
      return (int) (80.0 * disadvantage);
   }

   the_weapon = (Weapon *) *the_wielded;

   /* calculate the chance of hitting, and get the difference */   
   dex_index = ((((float) (the_wielder->get_dexterity() - 25)) * 
                (((float) the_weapon->get_dep_dex()) / (float) 100.0)) / (float) 50.0);
   str_index = ((((float) (the_wielder->get_strength() - 25)) *
                (((float) the_weapon->get_dep_strength()) / (float) 100.0)) / (float) 50.0);

   chance_index = (int) (50.0 + (dex_index * 67.0) + (str_index * 67.0));

   rand_num = 1+ (int) (100.0*(((float) rand())/((float) (RAND_MAX+1.0))));

   difference = ((int) (((float) chance_index) * disadvantage)) - rand_num;
   return difference;
}

/***********************************************************************
 ** take_a_swing (depricated) - strikes at the set target, trying to do 
 **                             a little damage
 **
 ** Parameters: None
 **
 ** Returns:  0 if no longer fighting this ind
 **           1 for successfully executed
 **          -1 for failure
 **
 ***********************************************************************/

int Individual::take_a_swing(void)
{
   Location       *target_loc;
   int            rand_num;
   Moveable       *tmp_moveable = NULL;
   Weapon         *attack_wpn = NULL;
   Weapon         *defend_wpn = NULL;
   int            attack_hands = 0;
   int            defend_hands = 0;
   int            diff_attack;
   int            diff_defend;
   char           *defend_name;
   char           *wpn_name;
   int            body_part = 0;
   Player         *tmp_player = NULL;
   Strings        holder;
   int            i;
   int            target_range = 0;
   int            attacker_range = 0;
   int            damage_done;
   int            max_damage_poss = 1;
   int            prev_health;
   MudObject      *projectile = NULL;
   special_holder *proj_special = NULL;
   int            can_see;
   int            hit = 0;

   int chance_of_attack[10] = {
                      95, /* head 5 percent */
                      90, /* face 5 percent*/
                      80, /* neck 10 percent*/
                      50, /* chest 30 percent*/
                      30, /* back 20 percent */
                  20, /* arms 10 percent */
                      15, /* hands 5 percent */
                      10, /* waist 5 percent */
                       5, /* legs 5 percent */
                  0}; /* feet 5 percent */
                              
   char *body_part_name[10] = {"head", "face", "neck", "chest", "back", 
                               "arms", "hands", "waist", "legs", "feet"};

   /* if the person they were fighting is no longer available */
   if (target == NULL)
   {
      return 0;
   }

   /* if they are a corpse, we don't fight them */
   if ((target->get_indflags())->get_flag(INDFLAG_CORPSE))
      return 0;

   target_loc = target->get_loc();
   /* if theyre not here anymore, stop fighting */
   if (target_loc != get_loc())
   {
      target = NULL;
      if (mainstruct->get_num_attacking(this) == 0)
         indflags->clr_flag(INDFLAG_FIGHTING);
      return 0;
   }

   can_see = target_loc->is_lit(this);

   /* calculate the chance of hitting and assign weapon type */
   diff_attack = get_accuracy(this, &tmp_moveable, 1);

   /* does the attacker wield a long range weapon (bow, slingshot, etc) */
   if ((tmp_moveable != NULL) && 
       (tmp_moveable->get_type() == OBJ_TYPE_WEAPON) && 
       (!STRCASECMP(((Weapon *) tmp_moveable)->get_weapon_class(), "bow")))
      attacker_range = 1;

   if (tmp_moveable == NULL)
   {
      if (get_bare_weapon() == NULL)
         wpn_name = "bare fist";
      else
         wpn_name = get_bare_weapon();
      attack_hands = 1;
   }
   /* its a shield, we can't attack with this */
   else if (diff_attack == 1000)
      return 0;
   else
   { 
      attack_wpn = (Weapon *) tmp_moveable;
      wpn_name = attack_wpn->get_title();
   }

   diff_defend = get_accuracy(target, &tmp_moveable, 0);
   if (tmp_moveable == NULL)
   {
      if (target->get_bare_weapon() == NULL)
         defend_name = "bare fist";
      else
         defend_name = target->get_bare_weapon();

      defend_hands = 1;
   }      
      /* its a shield, we try to deflect */
   else if (diff_defend == 1000)
   {
      diff_defend = 50;
      defend_name = tmp_moveable->get_title();
   }
   else
   {
      defend_wpn = (Weapon *) tmp_moveable;
      defend_name = defend_wpn->get_title();
   }

   /* does the target it a long range weapon (bow, slingshot, etc) */
   if ((tmp_moveable != NULL) && 
       (tmp_moveable->get_type() == OBJ_TYPE_WEAPON) && 
       (!STRCASECMP(((Weapon *) tmp_moveable)->get_weapon_class(), "bow")))
      target_range = 1;
   
   /* if we are not fighting, start fight.  If it is a long range weapon,
      50 percent chance we won't start a fight on our own to signify they
      are out of range for an attack */
   if ((target->get_target() == NULL) &&
       ((!attacker_range) || (!target_range && 
                         (((int) (100.0*(rand()/(RAND_MAX+1.0)))) < 50))))
   {
      target->start_fight(this);
   }

   /* if it is a range weapon, we need to get the ammo being used, so
      lets grab the first object we find in the range weapon */
   if (attacker_range)
   {
      Inventory  *weapon_inv;

      weapon_inv = attack_wpn->get_inventory();
      weapon_inv->reset_current();
      projectile = weapon_inv->get_next();

      while (projectile != NULL)
      {
         if ((proj_special = projectile->find_special("on_launch_hit")) != NULL)
         {
            break;
         }
         projectile = weapon_inv->get_next();
      }
   }

   if ((attacker_range) && (projectile == NULL))
   {
      if (get_type() == OBJ_TYPE_PLAYER)
      { 
         tmp_player = (Player *) this;
 
         tmp_player->send_plr("&+CYou have no ammunition in your %s!&*\n", 
                                                     attack_wpn->get_title());
      }
      attacker_range = 0;
   }
   else if (attacker_range)
      wpn_name = projectile->get_title();


   /* if the difference is less than 0, we miss */
   if (diff_attack < 0)
   {
      int       results = 0;

      /* if they have a special set up to run if the arrow misses, we
         do the special and let it decrement the number of projectiles,
         otherwise we decrement */
      if ((attacker_range) && 
       ((proj_special = projectile->find_special("on_launch_miss")) != NULL))
      {
         in_params fill_param;

         if (get_type() == OBJ_TYPE_PLAYER)
            tmp_player = (Player *) this;
         else
            tmp_player = NULL;

         fill_param.primary_obj = (MudObject *) target;
         fill_param.secondary_obj = (MudObject *) projectile;
         fill_param.this_obj = (MudObject *) this;

         results = (proj_special->the_special)->
             run_special(tmp_player, &fill_param, &proj_special->environment);
         if (results == 0)
            return 1;
         if (results == 2)
       {
            if (get_type() == OBJ_TYPE_PLAYER)
              ((Player *) this)->send_plr("&+RYou have run out of %s!\n", 
                                            projectile->get_title());
            attack_wpn->remove_contained(projectile);
            mainstruct->delete_object(projectile);
            return 0;
         }
      }
      else if (attacker_range)
      {
         results = 1;
      }
      if (attacker_range)
         holder.sprintf("%s's %s flies wide, &+cmissing&* %s.\n", 
              get_title(), projectile->get_title(), target->get_title());
      else
         holder.sprintf("\n%s swings %s %s wide, &+cmissing&* %s.\n", 
                 get_title(), get_sex_possessive_str(), 
                     wpn_name, target->get_title());

      if (get_type() == OBJ_TYPE_PLAYER)
      {
         tmp_player = (Player *) this;

         if (attacker_range)
       {
            if (can_see)
               tmp_player->send_plr("Your %s flies wide, &+cmissing&* %s.\n", 
                              projectile->get_title(), target->get_title());
            else
               tmp_player->send_plr(
                           "Your %s flies into the darkness and vanishes.\n", 
                                projectile->get_title());
       }
         else
       {
            if (can_see)
               tmp_player->
                  send_plr("\n&+B-&*Your %s swings wide, &+cmissing&* %s.\n", 
                            wpn_name, target->get_title());
            else
               tmp_player->send_plr("\n&+B-&*Your %s swings into the darkness,"
                      " catching &+conly air&*.\n", wpn_name); 
       }
      }
      if (target->get_type() ==  OBJ_TYPE_PLAYER)
      {
        tmp_player = (Player *) target;

        if (attacker_range)
           if (target_loc->is_lit(tmp_player))
              tmp_player->send_plr("%s's %s flies wide, missing you.\n", 
                              get_title(), projectile->get_title(), 
                                                        target->get_title());
           else
              tmp_player->send_plr("\nYou hear a swoosh as something flies by.\n");
        else
           if (target_loc->is_lit(tmp_player))
              tmp_player->send_plr("\n%s swings %s %s wide, missing you.\n", 
                      get_title(), get_sex_possessive_str(), wpn_name);
           else
              tmp_player->send_plr(
                     "\nYou hear something swing through the air nearby.\n");
      }

      if ((get_type() == OBJ_TYPE_PLAYER) &&
          (target->get_type() == OBJ_TYPE_PLAYER))
      {
      }
      else
      {
         (get_loc())->send_location(holder.str_show(), tmp_player, CAN_SEE);
         (get_loc())->send_location("The sound of battle fills the darkness\n",
                                         tmp_player, CANT_SEE);
      }

      if ((results) && (projectile->is_merger()))
      {
         Merger *the_merger;

         the_merger = (Merger *) projectile;
         the_merger->set_number_of(the_merger->get_number_of() - 1);
         if (the_merger->get_number_of() == 0)
       {
            if (get_type() == OBJ_TYPE_PLAYER)
              ((Player *) this)->send_plr("&+RYou have run out of %s!\n", 
                                            the_merger->get_title());
            attack_wpn->remove_contained(the_merger);
            mainstruct->delete_object(the_merger);
         }
      }
      if ((attack_wpn != NULL) && (get_type() == OBJ_TYPE_PLAYER))
         ((Player *) this)->increase_rank_exp(2, attack_wpn, (2 - (1 * hit)));
         
      return 1;
   }


   rand_num = (int) (100.0*(rand()/(RAND_MAX+1.0)));
   for (i=0; i<10; i++)
   {
      if (rand_num >= chance_of_attack[i])
      {
         body_part = i;
         break;
      }
   }

   tmp_player = NULL;

   if (attacker_range)
      holder.sprintf("\n%s's %s streaks towards %s's %s.\n", 
              get_title(), wpn_name, 
                  target->get_title(), body_part_name[body_part]);
   else
      holder.sprintf("\n%s swings %s %s at %s's %s.\n", 
              get_title(), get_sex_possessive_str(), 
                  wpn_name, target->get_title(), body_part_name[body_part]);
   if (get_type() == OBJ_TYPE_PLAYER)
   {
      tmp_player = (Player *) this;

      if (attacker_range)
         if (can_see)
            tmp_player->send_plr("\nYour %s streaks towards %s's %s.\n", 
                                  wpn_name, target->get_title(), 
                                  body_part_name[body_part]);
         else
            tmp_player->send_plr("\nYour %s streaks into the darkness.\n",
                                 wpn_name);
      else
         if (can_see)
            tmp_player->send_plr("\nYour %s swings at %s's %s.\n", 
                            wpn_name, target->get_title(), 
                            body_part_name[body_part]);
         else
            tmp_player->send_plr("\nYour %s swings into the darkness.\n",
                                 wpn_name);

   }
   if (target->get_type() ==  OBJ_TYPE_PLAYER)
   {
      tmp_player = (Player *) target;
      if (attacker_range)
         if (target_loc->is_lit(tmp_player))
            tmp_player->send_plr("\n%s's %s streaks towards your %s.\n", 
                     get_title(), wpn_name, body_part_name[body_part]);
      else
         if (target_loc->is_lit(tmp_player))
            tmp_player->send_plr("\n%s swings %s %s at your %s.\n", 
                   get_title(), get_sex_possessive_str(), wpn_name, 
                                              body_part_name[body_part]);

   }

   if ((get_type() == OBJ_TYPE_PLAYER) &&
       (target->get_type() == OBJ_TYPE_PLAYER))
   {
      (get_loc())->send_location(holder.str_show(), (Player *) this, 
                                     (Player *) target, CAN_SEE);
   }
   else
   {
      (get_loc())->send_location(holder.str_show(), tmp_player, CAN_SEE);
   }
   
   /* we hit, not a range weapon */
   if ((diff_attack > diff_defend) || (defend_hands && !attack_hands))
   {
      char *hardness[] = {"a glancing blow", "a solid blow", "hard", 
                          "very hard", "a crushing blow"};
      int  the_hardness;
      int  results;

      hit = 1;
      if (attack_wpn != NULL)
      {
         Player *tmp_player = NULL;

         if (get_type() == OBJ_TYPE_PLAYER)
            tmp_player = (Player *) this;
         if ((results = check_specials("on_hit", target, target, this, attack_wpn, 
                                                          tmp_player)) == 3)
            return -1;
       else if (results == 2)
          return 1;
      }

      if (attacker_range)
      {
         in_params fill_param;

         if (get_type() == OBJ_TYPE_PLAYER)
            tmp_player = (Player *) this;
         else
            tmp_player = NULL;

         fill_param.primary_obj = (MudObject *) target;
         fill_param.secondary_obj = (MudObject *) projectile;
         fill_param.this_obj = (MudObject *) this;

         results = (proj_special->the_special)->
             run_special(tmp_player, &fill_param, &proj_special->environment);

         hit = 1;
         if (results == 2)
       {
            if (get_type() == OBJ_TYPE_PLAYER)
              ((Player *) this)->send_plr("&+RYou have run out of %s!&*\n", 
                                            projectile->get_title());
            attack_wpn->remove_contained(projectile);
            mainstruct->delete_object(projectile);
         }

         damage_done = proj_special->environment.counter;
      }
      else
      {
         if (attack_wpn != NULL)
         {
            damage_done = 1+ (int) (((float) attack_wpn->get_damage())*
                                                 (rand()/(RAND_MAX+1.0)));
          max_damage_poss = attack_wpn->get_damage();
         }
         else
         {
            damage_done = 1 + (int)
                       ((get_strength() / 4)*(rand()/(RAND_MAX+1.0)));
          max_damage_poss = (get_strength() / 8);
         }
      }

      /* prepare to award experience */
      prev_health = target->get_health();
      
//############################################################################
//                              BEGINNING OF DEATH BY BLOW

     if ((target->get_health() <= 0) || 
         (target->take_blow(damage_done, body_part) <= 0))
     {
        Individual *the_victim;

        the_victim = target;
        holder.sprintf("%s strikes a &+Rfatal blow&* to %s with %s %s!\n\n", 
                          get_title(), the_victim->get_title(),  
                        get_sex_possessive_str(), wpn_name); 

        if (get_type() == OBJ_TYPE_PLAYER)
        {
            tmp_player = (Player *) this;

            // award points for the damage done 
            // possibly changing how this works 
          // tmp_player->increase_exp(prev_health - target->get_health());

            tmp_player->
                  send_plr("You strike %s &+Rfatally&* with your %s.\n\n", 
                     (can_see) ? the_victim->get_title() : "someone", wpn_name);
        }

        if (the_victim->get_type() ==  OBJ_TYPE_PLAYER)
        {
            tmp_player = (Player *) the_victim;
            tmp_player->
               send_plr("%s strikes you &+rfatally&* with %s %s.\n\n", 
                  (target_loc->is_lit(tmp_player) ? get_title() : "Someone"), 
                       get_sex_possessive_str(), wpn_name);
            tmp_player->send_plr("Darkness overtakes you as life slips "
                                 "away from your bleeding form.\n");
        }

        if ((get_type() == OBJ_TYPE_PLAYER) &&
            (the_victim->get_type() == OBJ_TYPE_PLAYER))
        {
            (get_loc())->send_location(holder.str_show(), (Player *) this, 
                                (Player *) the_victim, CAN_SEE);
            (get_loc())->send_location(
                "You hear the pained death cry of someone in the darkness.\n", 
                             (Player *) this, (Player *) the_victim, CANT_SEE);
        }
        else
        {
            (get_loc())->send_location(holder.str_show(), tmp_player, CAN_SEE);
            (get_loc())->send_location(
                "You hear the pained death cry of someone in the darkness.\n", 
                                                   tmp_player, CANT_SEE);

        }


        holder.sprintf("%s falls to the ground &+rdead.&*\n",
                                             the_victim->get_title());
        (get_loc())->send_location(holder.str_show(), NULL, CAN_SEE);

        // Finalize the death of this MOB by executing it's death function. 
        the_victim->death(DEATHFLAG_BLOW, this);
        if ((attack_wpn != NULL) && (get_type() == OBJ_TYPE_PLAYER))
           ((Player *) this)->increase_rank_exp(2, attack_wpn, (2 - (1 * hit)));

        return 0; 
      }

//                               ENDING OF DEATH BY BLOW
//############################################################################

      /* award experience for damage done */
      /* this will probably be changing */
      /*      if (get_type() == OBJ_TYPE_PLAYER)
         ((Player *) this)->increase_exp(prev_health - target->get_health());
      */

      /* if it is a range weapon, we already ran the special which
         should have taken care of the following section, so return */
      if (attacker_range)
      {
         if (target->get_type() == OBJ_TYPE_PLAYER)
         {
            Player *flee_player;

            flee_player  = (Player *) target;

            if (flee_player->get_health() < flee_player->get_wimpy())
            {
               flee_player->
                  send_plr("\nYou &+Rflee&* from the fight in a panic!\n");

               run_command(flee_player, "flee");
               return 0;
            }
         }

         return 1;
      }

      tmp_player = NULL;

      the_hardness = (int) 
          ((((float) damage_done) / ((float) max_damage_poss)) * 5);
      if (the_hardness >= 5)
         the_hardness = 4;

      holder.sprintf("%s strikes %s &+r%s&* with %s %s.\n", 
                 get_title(), target->get_title(), 
                     hardness[the_hardness], 
                     get_sex_possessive_str(), wpn_name); 
 
      if (get_type() == OBJ_TYPE_PLAYER)
      {
         tmp_player = (Player *) this;
         tmp_player->send_plr("You strike %s &+B%s&* with your %s.\n", 
                               (can_see) ? target->get_title() : "someone",                                     hardness[the_hardness], wpn_name);
      }
      if (target->get_type() ==  OBJ_TYPE_PLAYER)
      {
         int percent;
         char *color;

         tmp_player = (Player *) target;

         percent = (int) (((float) tmp_player->get_health() / 
                     (float) tmp_player->get_maxhealth()) * 100.0);

         if (percent == 100)
            color = "&+C";
         else if (percent > 80)
            color = "&+c";
         else if (percent > 60)
            color = "&+Y";
         else if (percent > 40)
            color = "&+Y";
         else if (percent > 20)
             color = "&+R";
         else
            color = "&+r";

         tmp_player->send_plr("%s strikes you &+R%s&* with %s %s.\n", 
         target_loc->is_lit(tmp_player) ? get_title() : "Someone", 
           hardness[the_hardness], 
          target_loc->is_lit(tmp_player) ? get_sex_possessive_str() : "their",
           wpn_name);
      }

      if ((get_type() == OBJ_TYPE_PLAYER) &&
          (target->get_type() == OBJ_TYPE_PLAYER))
      {
         (get_loc())->send_location(holder.str_show(), (Player *) this, 
                                               (Player *) target, CAN_SEE);
         (get_loc())->send_location(
                   "You hear a crash as someone makes contact.\n", 
                              (Player *) this, (Player *) target, CANT_SEE);
      }
      else
      {
         (get_loc())->send_location(holder.str_show(), tmp_player, CAN_SEE);

         (get_loc())->send_location(
                   "You hear a crash as someone makes contact.\n", 
                                                 tmp_player, CANT_SEE);
 
      }

      if ((attack_wpn != NULL) && (get_type() == OBJ_TYPE_PLAYER))
         ((Player *) this)->increase_rank_exp(2, attack_wpn, (2 - (1 * hit)));

      if (tmp_player != NULL)
      {
         if (tmp_player->get_health() < tmp_player->get_wimpy())
         {
            tmp_player->
                    send_plr("\nYou &+Rflee&* from the fight in a panic!\n");

            run_command(tmp_player, "flee");
            return 0;
         }
      }
      
      return 1;
      
   }

   /* we were blocked */
   else
   {
      holder.sprintf("%s deflects %s's %s with %s %s.\n", 
                 target->get_title(), get_title(), wpn_name,  
                     get_sex_possessive_str(), defend_name); 
 
      if (get_type() == OBJ_TYPE_PLAYER)
      {
         tmp_player = (Player *) this;
         tmp_player->send_plr("%s deflects your %s with his %s.\n", 
                               can_see ? target->get_title() : "Someone", 
                                                        wpn_name, defend_name);
      }
      if (target->get_type() ==  OBJ_TYPE_PLAYER)
      {
         tmp_player = (Player *) target;
           tmp_player->send_plr("You deflect %s's %s with your %s.\n", 
           target_loc->is_lit(tmp_player) ? get_title() : "someone", 
                                                   wpn_name, defend_name);
      }

      if ((get_type() == OBJ_TYPE_PLAYER) &&
          (target->get_type() == OBJ_TYPE_PLAYER))
      {
         (get_loc())->send_location(holder.str_show(), (Player *) this, 
                                      (Player *) target, CAN_SEE);
         (get_loc())->send_location("You hear the loud clang of deflection.\n", 
                            (Player *) this, (Player *) target, CANT_SEE);
      }
      else
      {
         (get_loc())->send_location(holder.str_show(), tmp_player, CAN_SEE);
         (get_loc())->send_location("You hear the loud clang of deflection.\n", 
                                                  tmp_player, CANT_SEE);
      }
      if ((attack_wpn != NULL) && (get_type() == OBJ_TYPE_PLAYER))
         ((Player *) this)->increase_rank_exp(2, attack_wpn, (2 - (1 * hit)));

      return 1;
   }

   return 1;
}

/***********************************************************************
 ** death - execute the death of this Individual.
 **
 ** Parameters: pointer to Individual attacking (in case of BLOW)         
 **             flag of attack type [BLOW, SPECIAL, SLAY]
 **
 ** Returns:  1 death occured.
 **           0 death did not occur; a Special pre-empted death. (not impl. yet)
 **          -1 for error                                        (not impl. yet)
 **
 ** ## AMERIST 07-20-00 ##
 ***********************************************************************/

/*
    DEATH()

    Death can be caused by a variation of different stimuli in the codebase

    (1) BLOW - 
        This is how most adventuers die.  In battle.  It should be extended 
        to leave a corpse (and not just a spillage of equipment.)

    (2) SPECIAL -
        MOBs and Players run across any number of deadly things are they are
        adventuring.  Rooms that instantly kill, spells that instantly kill,
        objects that instantly kill, in every case this is caused by a Special.
        In the case of a Special activated by another player that information
        should be treated as if the person died FIGHTING.  In the case that
        a Special kills the Individual that is activated by an object that
        object (the room, the cursed rod, etc.) should put its name in the 
        SEESLAIN message/log.  There should be an extention to this to define
        if it leaves a corpse or not.

    (3) SLAY - 
        The SLAY command simply blows an Individual away be it a MOB or a 
        player without even executing a death special, it also puts a message 
        out into the LOG and should spit up a SEESLAIN message stating that
        an Individial was SLAYn; perhaps an option for not leaving a corpse
        should also be added.

The death function should mostly do cleanup and codebase mechanism operations;
the function that calls the death() function should do any messages to players
and rooms about the death.  
 */

 // Easy Interface for a SPECIAL death (dealt by an object).
int Individual::death( int attack_flag, char *name /*, int corpse */ )
{
    return death( attack_flag, NULL, name );
}

// Easy Interface for a BLOW or SLAY command.
int Individual::death( int attack_flag, Individual *the_attacker /*, 
                                                                int corpse */ )
{
    return death( attack_flag, the_attacker, NULL );
}

int Individual::death( int attack_flag, Individual *the_attacker, 
                                                 char *name /*, int corpse */ )
{
    Player  *tmp_player = NULL;
    Strings holder;

    name = NULL;  // to avoid compile warnings, I assume we may use this later?

    // Adjust the message sent out to anyone with SEESLAIN set to On appropriately.
    switch(attack_flag)
    {
        case DEATHFLAG_BLOW:
          stop_fighting();
            holder.sprintf("&+Y[&+M%s&+W has been slain by &+M%s&+Y]&*\n",
                            get_title(), the_attacker->get_title());
            break;

        case DEATHFLAG_SPECIAL:
          stop_fighting();
          if (the_attacker != NULL)
            holder.sprintf("&+Y[&+M%s&+W has been slain by &+M%s&+Y]&*\n",
                       get_title(), the_attacker->get_title());
          else
            holder.sprintf("&+Y[&+M%s&+W has been slain by &+Ma special&+Y]&*\n",
                       get_title());
            break;

        case DEATHFLAG_SLAY:
            holder.sprintf("&+Y[&+M%s&+W has been smote by &+M%s&+Y]&*\n",
                            get_title(), the_attacker->get_title());
            break;

        default:
            holder.sprintf("&+Y[&+M%s&+W has been slain...&+Y]&* (unknown flag error)\n",
                            get_title());
    }

    mainstruct->send_all_players(holder.str_show(), NULL, ADMINFLAG_SEESLAIN);

    // set the mobile as a corpse
    if (get_type() == OBJ_TYPE_MOBILE)
    {
       indflags->set_flag(INDFLAG_CORPSE);
       holder = get_altname();
       holder.str_cat(" corpse body");
       set_altname(holder.str_show());
    }

    drop_unworn();
    stop_fighting();

    // This is because it was done this way in the take_a_swing algorithm
    /*    if(get_type() == OBJ_TYPE_PLAYER)
        tmp_player = ( Player *) this;
    else if((the_attacker != NULL) && 
            (the_attacker->get_type() == OBJ_TYPE_PLAYER))
          tmp_player = ( Player *) the_attacker; */
 
    // When the slay command is used it shouldn't set off any death specials.
    if( attack_flag != DEATHFLAG_SLAY )
        check_specials("on_death", this, the_attacker, NULL, this, the_attacker);

    // Remove the mobile from the database.
    if (get_type() == OBJ_TYPE_PLAYER)
    {
       Mobile      *corpse_mob;
       Mobile      *ghost_mob;
       Mobile      *ghost_clone;
       Object_List *the_dbase;
       MudObject   *tmp_obj = NULL;
       Location    *new_loc;
       Race        *the_race;
       Connection  *the_connection;
 
       tmp_player = (Player *) this;
       /* give them 10 minutes to go get their stuff before the zone
          resets */
       (mainstruct->get_dbase())->extend_reset(this, 600);

       /* now make a corpse to put in their place */
       the_dbase = mainstruct->get_dbase();
       corpse_mob = the_dbase->player_to_mobile(tmp_player);
       (corpse_mob->get_indflags())->set_flag(INDFLAG_CORPSE);

       /* swap their stuff */
       swap_worn(corpse_mob);

       /* initialize the corpse mobile for being a corpse */
       (corpse_mob->get_indflags())->set_flag(INDFLAG_CORPSE);
       holder = corpse_mob->get_altname();
       holder.str_cat(" corpse body");
       corpse_mob->set_altname(holder.str_show());
       corpse_mob->set_location(tmp_player->get_loc());
       corpse_mob->set_rot_timer(the_config.secs_to_rot);

       /* now create a ghost and place it with the corpse */
       if ((ghost_mob = (Mobile *) the_dbase->get_mudobject(
                               the_config.hardcoded_areaname.str_show(), 
                               the_config.ghost_name.str_show())) == NULL)
       {
          mainstruct->
             log_error("Could not get ghost template, death sequence failed.\n",
                                                                        "death");
          return -1;
       } 

       ghost_clone = (Mobile *) the_dbase->clone_object(ghost_mob);
       ghost_clone->set_location(tmp_player->get_loc());

       /* Not exactly what clones is for, but better than creating another
          variable */
       ghost_clone->set_clones(tmp_player->get_name());

       corpse_mob->set_clones(ghost_clone->get_name());

       ghost_clone->set_sex(tmp_player->get_sex());

       /* now log their death if appropriate */
       if (the_config.conf_flags->set_flag(CF_LOGDEATH))
       {
          holder.sprintf("%s has been slain.", get_title());
          mainstruct->log_event(holder.str_show());
       }

       // Save their character before we do anything drastic
       if (get_type() == OBJ_TYPE_PLAYER)
       (mainstruct->get_user_database())->write_user((Player *) this, 1);

       // Are they dead for good?
       if ((get_type() == OBJ_TYPE_PLAYER) &&
         (the_config.conf_flags->get_flag(CF_PERMDEATH)))
       {
       Connection *plr_conn;
       Player *tmp_plr;

       // First, move them to a temp location just to be safe
       holder.sprintf("%s@%s", the_config.backup_locname.str_show(), 
                  the_config.hardcoded_areaname.str_show());
       if ((new_loc = 
            (Location *) mainstruct->get_object(holder.str_show())) == NULL)
       {
         fault("Hardcoded location missing!\n");
       }
       set_location(new_loc);
       
       // A little scroll to give a bit of functional division between
       // death and the login prompt
       send_plr("\n\n\n");

          /* Since they are dead, they must either quit or login as a new
           character */
       
       // We create a new login player and swap connections
       tmp_plr = (Player *) this;
       plr_conn = tmp_plr->get_connection();
       tmp_plr->set_connection(NULL);
       tmp_plr->set_off();
       tmp_plr = new Player(plr_conn);
       mainstruct->add_player(tmp_plr);
       return 1;
       }

       /* now we move the player to the death start location for their race
          and display the death text */
       if (((the_race = mainstruct->get_race(tmp_player->get_race())) == NULL) ||
           ((tmp_obj = mainstruct->get_object(the_race->get_death_location())) 
                                                               == NULL) ||
           (tmp_obj->get_type() != OBJ_TYPE_LOCATION))
       {
          holder.sprintf("Could not get death loc player's race '%s'.", 
                                                     tmp_player->get_race());
          mainstruct->log_error(holder.str_show(), "death");
          holder.sprintf("%s@%s", the_config.backup_locname.str_show(), 
                                  the_config.hardcoded_areaname.str_show());
          new_loc = (Location *) mainstruct->get_object(holder.str_show());
       }
       else
          new_loc = (Location *) tmp_obj;

       the_connection = tmp_player->get_connection();
       the_connection->start_paging();
       
       tmp_player->set_location(new_loc);

       tmp_player->send_plr("%s\n", the_race->get_death_text());

       new_loc->show_location(tmp_player, 
                       (tmp_player->get_gameflags())->get_flag(GAMEFLAG_BRIEF));
       the_connection->end_paging(tmp_player);
       tmp_player->set_health(1);
    }

    if (get_type() == OBJ_TYPE_MOBILE)
       ((Mobile *) this)->set_rot_timer(the_config.secs_to_rot);

    // If this was a BLOW then this MOB was in a fight, the attacking MOB should
    //      be checked to see if its still in a fight.
    if ((attack_flag == DEATHFLAG_BLOW) && 
        (mainstruct->get_num_attacking(the_attacker) == 0))
            the_attacker->indflags->clr_flag(INDFLAG_FIGHTING);         

    return 1;
}


/***********************************************************************
 ** try_step_away - if we have a range weapon, try to step out of the
 **                 enemy's range
 **
 ** Parameters: None
 **
 ** Returns: 1 for stepped away, 
 **          0 for no,
 **         -1 for error
 **
 ***********************************************************************/

int Individual::try_step_away(void)
{
   Moveable   *tmp_moveable = NULL;
   int        attacker_range = 0;
   int        target_range = 0;
   Individual *target;
   Strings    holder;

   if (get_target() == NULL)
      return -1;

   target = get_target();

   if ((tmp_moveable = get_wielded(Left)) == NULL)
         tmp_moveable = get_wielded(Right);

   /* does the attacker wield a long range weapon (bow, slingshot, etc) */
   if ((tmp_moveable != NULL) && 
       (tmp_moveable->get_type() == OBJ_TYPE_WEAPON) && 
       (!STRCASECMP(((Weapon *) tmp_moveable)->get_weapon_class(), "bow")))
      attacker_range = 1;


   if ((tmp_moveable = target->get_wielded(Left)) == NULL)
      tmp_moveable = target->get_wielded(Right);

   /* does the target it a long range weapon (bow, slingshot, etc) */
   if ((tmp_moveable != NULL) && 
       (tmp_moveable->get_type() == OBJ_TYPE_WEAPON) && 
       (!STRCASECMP(((Weapon *) tmp_moveable)->get_weapon_class(), "bow")))
      target_range = 1;
   
   /* 30 percent chance we step away, unless the target has a range
      weapon as well, so then we do nothing */
   if ((target->get_target() == this) &&
       attacker_range && !target_range && 
       get_loc()->is_lit(this) &&
       (((int) (100.0*(rand()/(RAND_MAX+1.0)))) < 30))
   {
      target->clr_target();

      send_plr("You step out of range of %s.\n\n", target->get_title());

      target->send_plr("%s steps out of range of you.\n\n", get_title());
      
      holder.sprintf("%s steps out of range of %s!\n\n", 
                           get_title(), target->get_title());  

      (get_loc())->send_location(holder.str_show(), this, target);
      return 1;
   }
   return 0;
}


/***********************************************************************
 ** get_loc - gets the location of the individual
 **
 **
 ***********************************************************************/
   
Location *Individual::get_loc()
{
   return get_loc(0);
}

/***********************************************************************
 ** get_loc - gets the location of the individual
 **
 ** Parameters: override_checks - shall we override the checks for
 **                               screwed up locations?
 **
 ***********************************************************************/
   
Location *Individual::get_loc(int override_checks)
{
   override_checks = 0;

   return cur_loc;
}

/***********************************************************************
 ** get_loc_name - gets the name of the player location
 **
 ** Parameters: the_name - the name to set the player to
 **
 ** Returns:  name character string for success
 **           NULL for failure
 **
 ***********************************************************************/
   
char *Individual::get_loc_name()
{
   if (cur_loc == NULL)
      return NULL;
   return cur_loc->get_name();
}


/***********************************************************************
 ** clr_curr_loc - clears the pointer to the current location
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/
   
int Individual::clr_curr_loc(void)
{
   cur_loc = NULL;
   return 1;
}


/***********************************************************************
 ** reset_curr_loc - resets the pointer to the location before reload
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/
   
int Individual::reset_curr_loc(void)
{
   MudObject *new_loc;
   Strings   holder;

   if (get_location() == NULL)
   {
      mainstruct->log_error("locname set to null, couldn't reset loc", 
                                                          "reset_curr_loc");
      return -1;
   }

   new_loc = mainstruct->get_object(get_location());
   if ((new_loc == NULL) || (new_loc->get_type() != OBJ_TYPE_LOCATION))
   {
      holder.sprintf("Location '%s' for object '%s' is not valid!\n", 
                           get_location(), get_name());
      mainstruct->log_error(holder.str_show(), "reset_curr_loc");
      return -1;
   }
   return set_location((Location *) new_loc);
}


/***********************************************************************
 ** set_location - sets the pointer to the location specified
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/
   
int Individual::set_location(MudObject *new_loc)
{
   Strings holder;

   if (indflags->get_flag(INDFLAG_INBOAT))
   {
      cur_loc = (Location *) new_loc;
      return 1;
   }

   if (remove_from_loc() < 0)
     return -1;

   if (new_loc != NULL)
   {
      new_loc->add_contained(this);
   }
   else
      fault("Tried to assign player to NULL location\n");

   holder.sprintf("%s@%s", new_loc->get_name(), new_loc->get_area());
   set_loc_str(holder.str_show());

   cur_loc = (Location *) new_loc;

   if (get_type() == OBJ_TYPE_PLAYER)
      ((Player *) this)->set_pronouns(cur_loc->get_inventory());

   return 1;
}


/***********************************************************************
 ** remove_from_loc - takes an individual and removes it from its current
 **                   location
 **
 ** Returns:  1 if success
 **           0 if it was not in a location
 **          -1 if failure
 **
 ***********************************************************************/

int Individual::remove_from_loc()
{
  MudObject *prev_loc = cur_loc;

  if (cur_loc == NULL)
    return 0;

  if (!cur_loc->remove_contained(this))
  {
    Strings holder;
    holder.sprintf("Individual %s has previous loc, "
             "but was not contained in that loc\n", get_name());
    fault(holder.str_show());
    return 0;
  }

  return 1;
}


/***********************************************************************
 ** take_blow - calculates damage and subtracts from health
 **
 ** Parameters: None
 **
 ** Returns: damage done for success, -1 for failure
 **
 ***********************************************************************/

int Individual::take_blow(int the_damage, int body_part)
{
   worn_item *tmp_items;
   int       armor_value = 0;
   int       real_damage;
   int       bonus_armor = 0;

   if ((body_part < 0) || (body_part > WEARFLAG_FEET))
      return -1;

   /* if they hold a shield, 50 percent chance the shield absorbs the
      blow dependant on the armor value */
   if (((left_hand != NULL) && 
                             (left_hand->get_type() == OBJ_TYPE_WEARABLE)) ||
     ((right_hand != NULL) && (right_hand->get_type() == OBJ_TYPE_WEARABLE)))
   {
      Wearable *the_shield;
      int      will_absorb;

      if ((left_hand != NULL) && (left_hand->get_type() == OBJ_TYPE_WEARABLE))
         the_shield = (Wearable *) left_hand;
      else
         the_shield = (Wearable *) right_hand;

      will_absorb = (int) (2.0 * (rand()/(RAND_MAX+1.0)));

      if (will_absorb)
         bonus_armor += the_shield->get_armor();
   }
   tmp_items = worn_on[body_part];
   while (tmp_items != NULL)
   {
      armor_value = armor_value + (tmp_items->the_obj)->get_armor();
      tmp_items = tmp_items->next_worn;
   }

   armor_value += bonus_armor;

   real_damage = the_damage - armor_value;

   /* if they have lots of shielding, we do a min damage which ends up
      being 1/10 of their attempted damage done.  If that still is 0, 
      we just give em 1 damage */
   if (real_damage <= 0)
      real_damage = (int) the_damage / 10;
   if (real_damage == 0)
      real_damage = 1;

   health = health - real_damage;
   return health;
}


/***********************************************************************
 ** do_damage - calculates damage and subtracts from health, accounting
 **             for possible death
 **
 ** Parameters: attacker - the individual attacking
 **             the_damage - the damage to inflict
 **             body_part - which body part takes the damage
 **
 ** Returns: health of player after damage is done
 **
 ***********************************************************************/
// Depricated
/*
int Individual::do_damage(Individual *attacker, int the_damage, int body_part)
{
   int results;
   Strings holder;

   // if the player dies on this blow 
   if ((results = take_blow(the_damage, body_part)) <= 0)
   {
      holder.sprintf("%s falls over, dead!\n\n", get_title()); 

      if (get_type() == OBJ_TYPE_PLAYER)
         (get_loc())->send_location(holder.str_show(), (Player *) this);
      else
         (get_loc())->send_location(holder.str_show(), NULL);

      // We use the death function now

      if (get_type() == OBJ_TYPE_PLAYER)
      {
         ((Player *) this)->send_plr(
                               "Darkness envelops you...you are dead.\n");
      }
      else
      {
      //         (get_loc())->remove_contained((MudObject *) this);
      }

      death(DEATHFLAG_SPECIAL, NULL, get_name());

      return results;
   }

   if (get_type() == OBJ_TYPE_PLAYER)
   {
      Player *the_player;
      Flags  *tmp_indflags;

      the_player  = (Player *) this;

      tmp_indflags = the_player->get_indflags();
      if ((tmp_indflags->get_flag(INDFLAG_FIGHTING)) && 
          (results < the_player->get_wimpy()))
      {
         run_command(the_player, "flee");
      }
   }
   return results;
}
*/


/***********************************************************************
 ** drop_all - drops all objects in the room
 **
 ** Parameters: None
 **
 ** Returns: returns the number of objects dropped
 **
 ***********************************************************************/
   
int Individual::drop_all(void)
{
   int count = 0;
   Location  *the_loc;
   MudObject *the_obj;

   /* Lets drop all the inventory of the ind in its current location. */
   the_loc = get_loc();
   inventory.reset_current();
   the_obj = inventory.get_next();

   unwield_moveable(Left);
   unwield_moveable(Right);

   while (the_obj != NULL)
   {
       if (the_obj->get_type() == OBJ_TYPE_WEARABLE)
          remove_item((Wearable *) the_obj);

       remove_contained(the_obj);
       if (the_obj->is_a_moveable())
          ((Moveable *)the_obj)->set_moved();
       the_loc->add_contained(the_obj);
       inventory.reset_current();
       the_obj = inventory.get_next();
       count++;
   }
   return count;

}


/***********************************************************************
 ** drop_unworn - drops all objects not worn in the room
 **
 ** Parameters: None
 **
 ** Returns: returns the number of objects dropped
 **
 ***********************************************************************/
   
int Individual::drop_unworn(void)
{
   int count = 0;
   Location  *the_loc;
   MudObject *the_obj;

   /* Lets drop all the inventory of the ind in its current location. */
   the_loc = get_loc();
   inventory.reset_current();
   the_obj = inventory.get_next();

   unwield_moveable(Left);
   unwield_moveable(Right);

   while (the_obj != NULL)
   {
       if ((the_obj->get_type() != OBJ_TYPE_WEARABLE) ||
           (!is_worn((Wearable *) the_obj)))
       {
          remove_contained(the_obj);
          if (the_obj->is_a_moveable())
             ((Moveable *)the_obj)->set_moved();
        if (the_loc != NULL)
          the_loc->add_contained(the_obj);
          inventory.reset_current();
       }
       the_obj = inventory.get_next();
       count++;
   }
   return count;
}


/***********************************************************************
 ** swap_worn - takes all worn items from this individual and removes them,
 **             moving them to the inventory of the individual passed in and
 **             making them wear it
 **
 ** Parameters: the_ind - the individual to wear the items
 **
 ** Returns: returns the number of objects swapped
 **
 ***********************************************************************/
   
int Individual::swap_worn(Individual *the_ind)
{
   int count = 0;
   MudObject *the_obj;

   /* Lets drop all the inventory of the ind in its current location. */
   inventory.reset_current();
   the_obj = inventory.get_next();

   while (the_obj != NULL)
   {
       if ((the_obj->get_type() == OBJ_TYPE_WEARABLE) &&
           (is_worn((Wearable *) the_obj)))
       {
          remove_item((Wearable *) the_obj);
          remove_contained(the_obj);
          the_ind->add_contained(the_obj);
          the_ind->wear_item((Wearable *) the_obj);
          inventory.reset_current();
          count++;
       }
       the_obj = inventory.get_next();
   }
   return count;
}


/***********************************************************************
 ** clr_target - clears the target pointer
 **
 **
 ***********************************************************************/

void Individual::clr_target(void)
{
   target = NULL;
}


/***********************************************************************
 ** get_bare_weapon - gets the bare weapon string for this individual
 **
 **
 ***********************************************************************/


char *Individual::get_bare_weapon()
{
   return bare_weapon.str_show();
}


/***********************************************************************
 ** set_bare_weapon - sets the bare weapon string for this weapon
 **
 **
 ***********************************************************************/

void Individual::set_bare_weapon(char *the_name)
{
   bare_weapon = the_name;
}


/***********************************************************************
 ** copy_individual_attrib - copies all the individual attributes over from 
 **                          another individual
 **
 ** Parameters: copy_from - the object we copy attributes from
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::copy_individual_attrib(Individual *copy_from)
{
  rank_list *tmp_rank;

   /******* set the individual attributes *****/
   set_constitution(copy_from->get_constitution());
   set_health(copy_from->get_maxhealth());
   set_strength(copy_from->get_strength());
   set_dexterity(copy_from->get_dexterity());
   indflags->copy_flags(copy_from->get_indflags());

   tmp_rank = copy_from->get_ranks();
   while (tmp_rank != NULL)
   {
     add_rank(tmp_rank->rank_name.str_show(), tmp_rank->the_type,
            tmp_rank->the_rank, tmp_rank->the_exp_prob);
     tmp_rank = tmp_rank->next_rank;
   }

   return 1;
}


/***********************************************************************
 ** display_health - displays the health of the individual in a string
 **
 ** Parameters: the_player - the player to display to
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Individual::display_health(Player *the_player)
{
   char *health_level[] = {"is near death", "is severely injured",
             "is badly hurt", "is bleeding profusely", 
             "has several deep wounds", "has minor cuts and scrapes", 
           "has superficial wounds", "is in excellent health"};
   int  health_num;

   /* print the health of hte mobile */
   health_num = (int) ((((float) get_health()) / 
                             ((float) get_maxhealth())) * 7.0);
   
   if (health_num > 7)
      the_player->send_plr("%s is almost immortal!\n", get_title());
   else
      the_player->send_plr("%s %s.\n", get_title(), 
                                                health_level[health_num]);

}


/***********************************************************************
 ** is_asleep - returns 1 for asleep and 0 for awake
 **
 **
 ***********************************************************************/

int Individual::is_asleep()
{
   return indflags->get_flag(INDFLAG_SLEEPING);
}


/***********************************************************************
 ** is_sitting - returns 1 for sitting and 0 for standing
 **
 **
 ***********************************************************************/

int Individual::is_sitting()
{
   return indflags->get_flag(INDFLAG_SITTING);
}


/***********************************************************************
 ** game_get_obj - gets an object in the game and puts it in the individual's
 **                inventory, passing the appropriate messages around
 **
 ** Parameters: the_obj - the object we are getting
 **             from_obj - where we are getting the object from
 **             num_of - for mergers, the num of objects we are getting 
 **             is_held - is the player holding the from object
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/
   
int Individual::game_get_obj(MudObject *the_obj, MudObject *from_obj, 
                                                 int num_of, int is_held)
{
   Strings holder;
   char *sex;
   int  is_player = 0;
   Player *the_player = NULL;
   int  results;

   if (get_type() == OBJ_TYPE_PLAYER)
   {
      the_player = (Player *) this;
      is_player = 1;
   }

   if (the_obj->is_an_item())
   {
      Flags  *tmp_itemflags;

      tmp_itemflags = ((Item *)the_obj)->get_itemflags();
      if (the_obj->get_type() == OBJ_TYPE_ROPE)
      {
         if (tmp_itemflags->get_flag(ITEMFLAG_ISTIED))
       {
            if (is_player)
          {
               the_player->send_plr("You need to untie it first.\n");
            }
            return -1;
         }
      }
      else if (the_obj->get_type() == OBJ_TYPE_BOAT)
      {
         if (((Boat *) the_obj)->contains_players())
       {
            the_player->send_plr("It has someone in it!\n");
            return -1;
         }
      }
   }

   if (is_player)
   {
      if (from_obj->is_an_individual())
      {
         if (the_obj->get_type() == OBJ_TYPE_WEARABLE)
         {
            Wearable *the_wearable;

            the_wearable = (Wearable *) the_obj;
            if (((Individual *) from_obj)->is_worn(the_wearable))
          {
               the_player->send_plr("The %s is worn and must be removed.\n",
                                         the_wearable->get_title());
               return 0;
          }
         }
      }

      if ((results = check_specials("pre_get", the_obj, NULL, NULL, 
                                               the_obj, the_player)) == 3)
                return 0;
   }

   if (!the_obj->is_a_moveable())
   {
     send_plr(_("It won't budge.\n"));
     return 0;
   }

   /* Check if can carry */
   /* move to players inventory */
   if (num_of > 0)
   {
      Merger *the_merger;
      Merger *new_merger;
      MudObject *parent_merger;
      int    new_num;
      Strings parentname;

      if (is_player)
      {
         if (get_capacity() < (get_size_held() + 
                               (((Moveable *) the_obj)->get_size() * num_of)))
         {
            the_player->send_plr("You can't carry that many.\n");
            return -2;
         }

         if (the_player->get_weight_capacity() < (get_weight_held() + 
                            (((Moveable *) the_obj)->get_weight() * num_of)))
         {
            the_player->send_plr("You can't carry that many, "
                                                  "they are too heavy.\n");
            return -2;
         }
      }

      if (!the_obj->is_merger())
      {
         from_obj->remove_contained(the_obj);
      }
      else
      {
         the_merger = (Merger *) the_obj;
       
         if (num_of > the_merger->get_number_of())
       {
            if (is_player)
               the_player->send_plr("There are not that many here.\n");

            return -1;
         }
         if (num_of == the_merger->get_number_of())
       {
            from_obj->remove_contained(the_obj);
         }
         else
       {         
            if (the_merger->get_parent() != NULL)
          {
               parent_merger = 
                           mainstruct->get_object(the_merger->get_parent());
               new_merger = (Merger *)  
                   (mainstruct->get_dbase())->clone_object(parent_merger);
            }
            else
               new_merger = (Merger *) 
                          (mainstruct->get_dbase())->clone_object(the_obj);
            new_merger->set_number_of(num_of);
            the_obj = (MudObject *) new_merger;
            new_num = the_merger->get_number_of() - num_of;
            the_merger->set_number_of(new_num);
         }
      }
   }
   else
   {
      if (is_player)
      {
         if (get_capacity() < (get_size_held() + 
                                     ((Moveable *) the_obj)->get_size()))
         {
            the_player->send_plr("You can't carry that, "
                                      "you're carrying too much bulk.\n");
            return -2;
         }

         if (the_player->get_weight_capacity() < (get_weight_held() + 
               (((Moveable *) the_obj)->get_weight_held())) + 
                ((Moveable *) the_obj)->get_weight())
         {
            the_player->send_plr("You can't carry that, "
                                      "you're carrying too much weight.\n");
            return -2;
         }
      }
      from_obj->remove_contained(the_obj);
   }


   if (from_obj->get_type() == OBJ_TYPE_LOCATION)
   {
      if (is_player)
         the_player->send_plr("You get the %s.\n", the_obj->get_title());
      holder.sprintf("%s gets the %s.\n", 
                             get_title(), the_obj->get_title());
   }
   else
   {
      if (is_player)
         the_player->send_plr("You get the %s from the %s.\n", 
                            the_obj->get_title(), from_obj->get_title());
   
      if (is_held)
      {
        sex = get_sex_possessive_str();
      }
      else
         sex = "the";
      
      holder.sprintf("%s gets the %s from %s %s.\n", 
           get_title(), the_obj->get_title(), sex, 
                                            from_obj->get_title());
   }
   
   (get_loc())->send_location(holder.str_show(), the_player, CAN_SEE);
 
   if (add_contained(the_obj) == 2)
      mainstruct->delete_object(the_obj);

   ((Moveable *) the_obj)->set_moved();

   if (is_player)
   {
      if ((results = check_specials("post_get", the_obj, NULL, NULL, 
                                                the_obj, the_player)) == 3)
                return 0;

   }
   
   return 1;
}


/***********************************************************************
 ** write_object - writes a individual to a file.  This write raises an
 **                error as we should not be writing just individuals ever
 **
 ** Parameters: the_file - the file we would write to
 **             build_format - is it in builder format
 **
 ***********************************************************************/

void Individual::write_object(FILE *the_file, int build_format)
{
   build_format = 0;
   the_file = NULL;
   mainstruct->log_error("Tried to write individual to file.", "write_object");
}


/***********************************************************************
 ** get_brief - this should never be run
 **
 ***********************************************************************/

char *Individual::get_brief()
{
   return NULL;
}



/***********************************************************************
 ** get_mem_size_ind - gets how much memory is being taken up by the
 **                    individual part of this object
 **
 ** Returns: mem size in bytes
 **
 ***********************************************************************/

int Individual::get_mem_size_ind()
{
   int size = 0;
   int i;
   worn_item *tmp_worn;

   size += bare_weapon.get_mem_size_dynamic();

   for (i=0; i<WEARFLAG_FEET + 1; i++)
   {
      tmp_worn = worn_on[i];
      while (tmp_worn != NULL)
      {
         size += sizeof(*tmp_worn);
         tmp_worn = tmp_worn->next_worn;
      }
   }

   return size;
}


/***********************************************************************
 ** reset_individual: resets the individual's variables to default
 **
 ***********************************************************************/

void Individual::reset_individual( void )
{
   strength = the_config.default_strength;
   dexterity = the_config.default_dexterity;
   constitution = the_config.default_constitution;
   health = get_maxhealth();
   intelligence = the_config.default_intel;
   wisdom = the_config.default_wisdom;
   charisma = the_config.default_charisma;
}

/***********************************************************************
 ** attack - attacks another individual, this function should not be called
 **
 ***********************************************************************/

int Individual::attack(Individual *target)
{
  return -1;
}


/***********************************************************************
 ** use_weapon - uses the weapon against the opponent, taking into account
 **              skill with weapon, chance of missing, chance of blocking,
 **              and many other things
 **
 ***********************************************************************/

int Individual::use_weapon(Individual *target)
{
  int      body_part;
  Location *target_loc;
  int      can_see;
  Moveable *the_wielded = NULL;
  Moveable *defend_with = NULL;
  Weapon   *the_weapon = NULL;
  int      acc_attack;
  int      acc_defend;
  int      results;
  Merger   *projectile = NULL;
  Strings  holder;
  char *hardness[] = {"a glancing blow", "a solid blow", "hard", 
                          "very hard", "a crushing blow"};
  int  the_hardness;
  int  damage_done;
  int  max_damage_poss;
  char *att_wpn_name = get_bare_weapon();
  char *def_wpn_name;

  if (target == NULL)
  {
    return 0;
  }

  def_wpn_name = target->get_bare_weapon();
  
  if (att_wpn_name == NULL)
    att_wpn_name = "bare hands";
  if (def_wpn_name == NULL)
    def_wpn_name = "bare hands";

  /* if the person they were fighting is no longer available */
  if (target == NULL)
  {
     return 0;
  }

  /* if they are a corpse, we don't fight them */
  if ((target->get_indflags())->get_flag(INDFLAG_CORPSE))
     return 0;

  target_loc = target->get_loc();
  /* if theyre not here anymore, stop fighting */
  if (target_loc != get_loc())
  {
    stop_fighting();
    return 0;
  }

  can_see = target_loc->is_lit(this);

  // Now we pick a body part, or they catch air
  body_part = select_body_part(&the_wielded, &acc_attack);
  the_weapon = (Weapon *) the_wielded;
  // printf("attack acc %s: %d\n", get_title(), acc_attack);

  if (the_weapon != NULL)
    att_wpn_name = the_weapon->get_title();

  // Use the weapon so if a range weapon, it should decrement one ammo
  if ((the_weapon != NULL) && 
      (the_weapon->swing(this, target, &projectile) == 0))
  {
    send_plr("You don't seem to have anything loaded in the %s!\n",
                   att_wpn_name);

    // If they have run out, make sure their target gets to finish them!!
    if (target->get_target() == NULL)
      target->start_fight(this);

    return 0;
  }

   /* if we are not fighting, start fight.  If it is a long range weapon,
      50 percent chance we won't start a fight on our own to signify they
      are out of range for an attack */
   if ((target->get_target() == NULL) &&
       ((projectile == NULL) || ((projectile != NULL) && 
                         (((int) (100.0*(rand()/(RAND_MAX+1.0)))) < 50))))
   {
      target->start_fight(this);
   }
  
  // If they caught air, we are done, and maybe they are
  if (body_part == -1)
  {
    // Set up what to send to the room
    if (projectile != NULL)
       holder.sprintf("%s's %s flies wide, &+cmissing&* %s.\n", 
            get_title(), projectile->get_title(), target->get_title());
    else
       holder.sprintf("\n%s swings %s %s wide, &+cmissing&* %s.\n", 
                 get_title(), get_sex_possessive_str(), 
                     att_wpn_name, target->get_title());
    
    if (projectile != NULL)
    {
       if (can_see)
          send_plr("Your %s flies wide, &+cmissing&* %s.\n", 
                              projectile->get_title(), target->get_title());
       else
          send_plr("Your %s flies into the darkness and vanishes.\n", 
                                projectile->get_title());

       if (target_loc->is_lit(target))
          target->send_plr("%s's %s flies wide, missing you.\n", 
                              get_title(), projectile->get_title(), 
                                                        target->get_title());
       else
          target->send_plr("\nYou hear a swoosh as something flies by.\n");

    }
    else
    {
       if (can_see)
          send_plr("\n&+B-&*Your %s swings wide, &+cmissing&* %s.\n", 
                            att_wpn_name, target->get_title());
       else
          send_plr("\n&+B-&*Your %s swings into the darkness,"
                      " catching &+conly air&*.\n", att_wpn_name); 

       if (target_loc->is_lit(target))
          target->send_plr("\n%s swings %s %s wide, missing you.\n", 
                      get_title(), get_sex_possessive_str(), 
                     att_wpn_name);
       else
          target->send_plr(
                     "\nYou hear something swing through the air nearby.\n");
    }

    (get_loc())->send_location(holder.str_show(), this, target, CAN_SEE);
    (get_loc())->send_location("The sound of battle fills the darkness\n",
                                                      this, target, CANT_SEE);

    return 0;
  }

  // Now tell them that it is heading at their target
   if (projectile != NULL)
   {
      holder.sprintf("\n%s's %s streaks towards %s's %s.\n", 
              get_title(), att_wpn_name, 
                  target->get_title(), body_part_name[body_part]);
      if (can_see)
         send_plr("\nYour %s streaks towards %s's %s.\n", 
                                  projectile->get_title(), target->get_title(), 
                                  body_part_name[body_part]);
      else
         send_plr("\nYour %s streaks into the darkness.\n",
                                projectile->get_title());
   }
   else
   {
      holder.sprintf("\n%s swings %s %s at %s's %s.\n", 
              get_title(), get_sex_possessive_str(), 
                  att_wpn_name, target->get_title(), body_part_name[body_part]);
      if (can_see)
         send_plr("\nYour %s swings at %s's %s.\n", 
                            att_wpn_name, target->get_title(), 
                            body_part_name[body_part]);
      else
         send_plr("\nYour %s swings into the darkness.\n", att_wpn_name);
   }

   (get_loc())->send_location(holder.str_show(), this, target, CAN_SEE);

   // If this is a range weapon, it can't be deflected.  If not, check
   // for deflection
   if (projectile == NULL)
   {
     // Next, we determine if it is parried
     acc_defend = get_accuracy(target, &defend_with, 0);
     // printf("defend acc %s: %d\n", target->get_title(), acc_defend);

     if (defend_with != NULL)
       def_wpn_name = defend_with->get_title();

     // If they defend better than we attack, it is parried
     if ((acc_attack < acc_defend) && (defend_with != NULL))
     {
       holder.sprintf("%s deflects %s's %s with %s %s.\n", 
                 target->get_title(), get_title(), att_wpn_name,  
                     get_sex_possessive_str(), def_wpn_name); 
 
       send_plr("%s deflects your %s with his %s.\n", 
                               can_see ? target->get_title() : "Someone", 
                              att_wpn_name, def_wpn_name);
       target->send_plr("You deflect %s's %s with your %s.\n", 
           target_loc->is_lit(target) ? get_title() : "someone", 
                              att_wpn_name, def_wpn_name);
       (get_loc())->send_location(holder.str_show(), this, target, CAN_SEE);
       (get_loc())->send_location("You hear the loud clang of deflection.\n", 
                                                      this, target, CANT_SEE);
       if ((the_weapon != NULL) && (get_type() == OBJ_TYPE_PLAYER))
         ((Player *) this)->increase_rank_exp(2, the_weapon, 1);
       return 1;
     }
   }

  // Finally, if we have made it this far, we hit!  Do the damage

  // If they are not using fists, check for an on_hit special
  if (the_weapon != NULL)
  {
     Player *tmp_player = NULL;

     if (get_type() == OBJ_TYPE_PLAYER)
        tmp_player = (Player *) this;
     if ((results = check_specials("on_hit", target, target, this, the_weapon, 
                                                          tmp_player)) == 3)
        return -1;
     else if (results == 2)
      return 1;
  }
      
  if (projectile != NULL)
  {
     if (get_type() == OBJ_TYPE_PLAYER)
     {
       if ((results = check_specials("on_launch_hit", projectile, target, 
                           this, projectile, ((Player*) this))) == 3)
       return -1;
       else if (results == 2)
       return 1;
     }

  }
  else
  {
     int percent;
     char *color;

     if (the_weapon != NULL)
     {
        damage_done = 1+ (int) (((float) the_weapon->get_damage())*
                                        (((float) acc_attack) / 100.0));
      max_damage_poss = the_weapon->get_damage();
     }
     else
     {
        damage_done = 1 + (int)
                      ((get_strength() / 4)*(rand()/(RAND_MAX+1.0)));
        max_damage_poss = (get_strength() / 4);
     }

     the_hardness = (int) 
          ((((float) damage_done) / ((float) max_damage_poss)) * 5);
     if (the_hardness >= 5)
        the_hardness = 4;

     holder.sprintf("%s strikes %s &+r%s&* with %s %s.\n", 
                 get_title(), target->get_title(), 
                     hardness[the_hardness], 
                     get_sex_possessive_str(), att_wpn_name); 
     send_plr("You strike %s &+B%s&* with your %s.\n", 
                               (can_see) ? target->get_title() : "someone",                                     hardness[the_hardness], att_wpn_name);

     percent = (int) (((float) target->get_health() / 
                     (float) target->get_maxhealth()) * 100.0);

     if (percent == 100)
        color = "&+C";
     else if (percent > 80)
        color = "&+c";
     else if (percent > 60)
        color = "&+Y";
     else if (percent > 40)
        color = "&+Y";
     else if (percent > 20)
        color = "&+R";
     else
        color = "&+r";

     target->send_plr("%s strikes you &+R%s&* with %s %s.\n", 
         target_loc->is_lit(target) ? get_title() : "Someone", 
           hardness[the_hardness], 
          target_loc->is_lit(target) ? get_sex_possessive_str() : "their",
           att_wpn_name);
         (get_loc())->send_location(holder.str_show(), this, target, CAN_SEE);
         (get_loc())->send_location(
                   "You hear a crash as someone makes contact.\n", 
               this, target, CANT_SEE);
     target->take_blow(damage_done, body_part);
       
  }

  if ((the_weapon != NULL) && (get_type() == OBJ_TYPE_PLAYER))
      ((Player *) this)->increase_rank_exp(2, the_weapon, 2);

  // Check for death
  if ((projectile == NULL) && (target->check_for_death(DEATHFLAG_BLOW, this)))
    return 1;

  // Check for flee, but only if they haven't died already
  if ((!target->get_indflags()->get_flag(INDFLAG_CORPSE)) &&
      (target->target->check_for_flee()))
    return 0;

  return 1;
}


/***********************************************************************
 ** check_for_death - determine if this player has died and if so, send
 **                   appropriate messages and handle it
 **
 ** Returns: 1 if they are dead, 0 if still alive
 **
 ***********************************************************************/

int Individual::check_for_death(int deathflag, Individual *attacker)
{
  Location *the_loc;
  Strings holder;

  if (get_health() <= 0)
  {
    the_loc = get_loc();
    holder.sprintf("%s falls to the ground, &+Rdead.&*\n", get_title());
    the_loc->send_location(holder.str_show(), this, CAN_SEE);
    the_loc->send_location("You hear a thump of someone falling to the ground.", 
                     this, CANT_SEE);
    send_plr("You have &+Rdied&*.\n");
    death(deathflag, attacker);
    return 1;
  }

  return 0;
}


/***********************************************************************
 ** check_for_flee - checks to see if the player flees
 **
 ** Returns: 1 if they flee, 0 if still alive
 **
 ***********************************************************************/

int Individual::check_for_flee()
{
   if (get_health() < get_wimpy())
   {
      send_plr
      ("You have reached the extent of your courage and decide to flee!\n");
      move_dir(NULL, 1);
      
      return 1;
   }
   return 0;
   
}

/***********************************************************************
 ** select_body_part - randomly selects a body part to strike at or
 **                    determining if they totally miss
 **
 ** Parameters: the_wielded - parameter for passing back the weapon used
 **                           for passing back the accuracy of the attack
 **
 ***********************************************************************/

int Individual::select_body_part(Moveable **the_wielded, int *acc_attack)
{
  int i;
  int rand_num;
  int chance_of_attack[10] = {
                      95, /* head 5 percent */
                      90, /* face 5 percent*/
                      80, /* neck 10 percent*/
                      50, /* chest 30 percent*/
                      30, /* back 20 percent */
                  20, /* arms 10 percent */
                      15, /* hands 5 percent */
                      10, /* waist 5 percent */
                       5, /* legs 5 percent */
                  0}; /* feet 5 percent */

   /* calculate the chance of hitting and assign weapon type */
   *acc_attack = get_accuracy(this, the_wielded, 1);

   // If accuracy less than 20, they miss
   if ((*acc_attack) < 20)
     return -1;

   rand_num = (int) (100.0*(rand()/(RAND_MAX+1.0)));
   for (i=0; i<10; i++)
   {
      if (rand_num >= chance_of_attack[i])
      {
         return i;
      }
   }
   return -1;
}


/***********************************************************************
 ** send_plr - as this is not a player, does nothing if called
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::send_plr(char *new_str, ...)
{
  return -1;
}


/***********************************************************************
 ** move_dir - moves in a certain direction
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::move_dir(char *dir, int flee)
{
   Location       *cur_loc;
   Location       *next_loc;
   Location       *tmp_loc;
   Strings        holder, holder2;
   int            results;
   Flags          *tmp_indflags;
   Flags          *tmp_gameflags;
   Flags          *tmp_locflags;
   Strings        direction_holder;
   char           *dir_word;
   MudObject      *tmp_obj;
   Inventory      *the_inventory;
   int            in_boat = 0;
   Boat           *the_boat = NULL;
   Strings        passengers;
   Mobile         *tmp_mob;
   int            dir_num = -1;
   int            used_extra_dir = 0;
   int            endurance_required;
   char *dir_str[10] = {N_("North"), N_("South"), N_("East"), N_("West"), 
                  N_("Up"), N_("Down"), N_("Northeast"), N_("Northwest"), 
                  N_("Southeast"), N_("Southwest")};

   cur_loc = get_loc();

   tmp_indflags = get_indflags();

   if (is_asleep())
   {
      send_plr(_("You stir in your sleep.\n"));
      return 0;
   }

   if (is_busy())
   {
      send_plr(_("You are too busy to move.\n"));
      return 0;
   }


   if (tmp_indflags->get_flag(INDFLAG_INBOAT))
   {
      in_boat = 1;
      tmp_obj = mainstruct->get_object(get_location());
      if ((tmp_obj == NULL) ||
          (tmp_obj->get_type() != OBJ_TYPE_BOAT))
      {
         send_plr(_("Code error found, tell an admin!\n"));
         holder.sprintf(_("Individual '%s' marked in boat but loc not set to boat"), 
                  get_title());
         mainstruct->log_error(holder.str_show(), "gocom");
         return -1;
      }

      the_boat = (Boat *) tmp_obj;
   }

   if ((!in_boat) && (is_sitting()))
   {
      send_plr(_("You can't move while sitting!\n"));
      return 0;
   }

   if (flee)
   {
      if ((dir == NULL) || (strlen(dir) == 0))
      {
         dir = cur_loc->get_random_exit(&direction_holder);
         if (dir == NULL)
       {
            send_plr(_("You have nowhere to flee to!\n"));
            return 0;
         }
      }
   }
   else
   {
      if (tmp_indflags->get_flag(INDFLAG_FIGHTING))
      {
         send_plr(_("You can't just walk out of a fight!\n"));
         return 0;
      }
   }

   switch(*dir)
   {

      case 'n':

         if ((!STRCASECMP(dir, _("nw"))) ||
                                   (!STRCASECMP(dir, _("northwest"))))
       {
            dir_num = NORTHWEST;
         }
         else if ((!STRCASECMP(dir, _("ne"))) ||
                                      (!STRCASECMP(dir, _("northeast"))))
       {
            dir_num = NORTHEAST;
         }
         else if (!STRNCASECMP(dir, "north", strlen(dir)))
       {
            dir_num = NORTH;
         }
         else
       {
            dir_num = -2;
       }
         break;
      case 's':
         if ((!STRCASECMP(dir, _("sw"))) ||
                                     (!STRCASECMP(dir, _("southwest"))))
       {
            dir_num = SOUTHWEST;
         }
         else if ((!STRCASECMP(dir, _("se"))) ||
                                      (!STRCASECMP(dir, _("southeast"))))
       {
            dir_num = SOUTHEAST;
         }
         else if (!STRNCASECMP(dir, "south", strlen(dir)))
       {
            dir_num = SOUTH;
         }
         else
       {
            dir_num = -2;
       }
         break;
      case 'e':
         if (!((*(dir+1)) && isalpha(*(dir + 1))) ||
             (!STRCASECMP(dir, _("east"))))
            dir_num = EAST;
         else
       {
            dir_num = -2;
       }
         break;
      case 'w':
         if (!((*(dir+1)) && isalpha(*(dir + 1))) ||
             (!STRCASECMP(dir, _("west"))))
            dir_num = WEST;
         else
       {
            dir_num = -2;
       }
         break;
      case 'u':
         if (!((*(dir+1)) && isalpha(*(dir + 1))) ||
             (!STRCASECMP(dir, _("up"))))
            dir_num = UP;
         else
       {
            dir_num = -2;
       }
         break;
      case 'd':
         if (!((*(dir+1)) && isalpha(*(dir + 1))) ||
             (!STRCASECMP(dir, _("down"))))
            dir_num = DOWN;
         else
       {
            dir_num = -2;
       }
         break;
      default:
         dir_num = -2;
         break;
   }

   /* if their direction was not a traditional direction, find it */
   if (dir_num == -2)
   {
      next_loc = cur_loc->get_custom_exit(dir, cur_loc->get_area(),
                                                                 &results);
      dir_word = dir;
      used_extra_dir = 1;
   }
   else
   {
      next_loc = cur_loc->get_exit(dir_num, cur_loc->get_area(), &results);
      dir_word = _(dir_str[dir_num]);
   }

   if (get_type() == OBJ_TYPE_PLAYER)
   {
     Player *the_player = (Player *) this;
     int results;

     holder.sprintf(_("pre_%s"), dir_word);

     if ((results = check_specials(holder.str_show(), cur_loc, the_player, next_loc,
                                                cur_loc, the_player)) == 3)
       return 0;
     if ((cur_loc->check_contained_spec(holder.str_show(), the_player,
                         next_loc, the_player, OBJ_TYPE_MOBILE)) == 3)
       return 0;

     if (check_specials(_("pre_move"), cur_loc, the_player, next_loc,
                                                 cur_loc, the_player) == 3)
       return 0;

     if ((cur_loc->check_contained_spec(_("pre_move"), the_player,
                          next_loc, the_player, 0)) == 3)
       return 0;
   }

   if (next_loc == NULL)
   {
      if (results == 2)
         send_plr(_("That way is blocked.\n"));
      else
         send_plr(_("You can't go that way.\n"));
      return 0;
   }

   /* see if they have the endurance to travel that far.  Endurance required
      is 1/2 the current room size + 1/2 the new room size (assuming they
      start in the middle and end in the middle of their destination */
   {
      float endur_old, endur_new;

      endur_old = ((((float) cur_loc->get_room_size()) / (float)2.0) /
                   (((float) the_config.endurance_divisor) /
                                cur_loc->get_terrain_mult()));

      endur_new = ((((float) next_loc->get_room_size()) / (float)2.0) /
                   (((float) the_config.endurance_divisor) /
                                     next_loc->get_terrain_mult()));

      endurance_required = (int) (endur_old + endur_new);
   }

   if (endurance_required > get_endurance())
   {
      send_plr(_("You are too tired to make that journey.\n"));
      return 0;
   }

   tmp_locflags = next_loc->get_locflags();
   if ((tmp_locflags->get_flag(LOCFLAG_AQUATIC)) &&
       (!in_boat))
   {
      send_plr(_("You need a boat to go on water.\n"));
      return 0;
   }

   if ((in_boat) && (!tmp_locflags->get_flag(LOCFLAG_AQUATIC)) &&
                    (!tmp_locflags->get_flag(LOCFLAG_SHORE)))
   {
      send_plr(_("You need to leave the %s first.\n"),
                                                      the_boat->get_title());
      return 0;
   }

   if (in_boat)
      the_boat->get_passengers(this, &passengers);

   /* say that we are leaving the room */
   if (flee)
   {
      stop_fighting();
      if (!in_boat)
      {
         holder.sprintf(_("%s flees %s.\n"), get_title(), dir_word);
         holder2.sprintf(
              _("You hear the sound of running footsteps disappearing %s.\n"),
                                                                     dir_word);
      }
      else
      {
         holder.sprintf(_("%s %s madly away out the %s exit"),
              get_title(), the_boat->get_move_str(), dir_word);
         holder2.sprintf(_("Someone %s frantically, the sound disappearing %s.\n"),
                                   the_boat->get_move_str(), dir_word);

         if (passengers.str_show() != NULL)
       {
          holder.str_cat(_(" carrying "));
            holder.str_cat(passengers.str_show());
         }
         holder.str_cat(".\n");
      }
   }
   else
   {
      if (!in_boat)
      {
         if (used_extra_dir)
       {
            holder.sprintf(_("%s leaves via the %s exit.\n"),
                                                        get_name(), dir_word);
       }
         else
       {
            holder.sprintf(_("%s goes %s.\n"), get_name(), dir_word);
       }
         holder2.sprintf(
          _("Footsteps emerge from the darkness, disappearing via the %s exit.\n"),
                                                         dir_word);
      }
      else
      {
         holder.sprintf("%s %s %s", get_title(), the_boat->get_move_str(), 
                  dir_word);

         holder2.sprintf(
                    _("Someone %s out of the room, leaving via the %s exit.\n"),
                                         the_boat->get_move_str(), dir_word);

         if (passengers.str_show() != NULL)
       {
          holder.str_cat(_(" carrying "));
            holder.str_cat(passengers.str_show());
         }
         holder.str_cat(".\n");
      }
   }

   /* if theyre fleeing, set them up so they are not fighting, and drop some
      stuff */
   if (flee)
   {
      MudObject  *the_obj;
      int        rand_num;
      int        dropped_stuff = 0;

      if (in_boat)
         the_boat->stop_passengers_fighting();
      else
      {
         stop_fighting();
         mainstruct->clear_fighter(this);
      }

      /* here we drop some random stuff */
      the_inventory = get_inventory();

      the_inventory->reset_current();
      the_obj = the_inventory->get_next();
      while (the_obj != NULL)
      {
         if (((the_obj->get_type() != OBJ_TYPE_WEARABLE) ||
              (!is_worn((Wearable*) the_obj))) &&
             ((((MudObject *) get_wielded(Left)) != the_obj) &&
              (((MudObject *) get_wielded(Right)) != the_obj)))

       {
            rand_num = (int) ((2.0) * (rand()/(RAND_MAX+1.0)));
            if (rand_num)
          {
               dropped_stuff = 1;
               the_obj->set_location(cur_loc);
            }
         }
         the_obj = the_inventory->get_next();
      }
      if (dropped_stuff)
         send_plr(_("You drop some items in your escape.\n"));
   }

   cur_loc->send_location(holder.str_show(), this, CAN_SEE);
   cur_loc->send_location(holder2.str_show(), this, CANT_SEE);

   /* tell the target room that we have arrived */
   if (flee)
   {
      if (!in_boat)
      {
         holder.sprintf(_("%s runs into the room.\n"), get_name());
         holder2.sprintf(
                _("The sound of running footsteps emerge from the darkness\n"
                "into the room.\n"));

      }
      else
      {
         holder.sprintf(_("%s %s madly into the room"), get_title(),
              the_boat->get_move_str());

         holder2.sprintf(_("Someone %s madly into the room.\n"),
                       the_boat->get_move_str());
         if (passengers.str_show() != NULL)
       {
          holder.str_cat(_(" carrying "));
            holder.str_cat(passengers.str_show());
         }
         holder.str_cat(".\n");

      }
   }
   else
   {
      if (!in_boat)
      {
         holder.sprintf(_("%s enters the room.\n"), get_name());
         holder2.sprintf(
                _("The sound of footsteps indicate the arrival of someone.\n"));
      }
      else
      {
         holder.sprintf("%s %s in", get_title(),
              the_boat->get_move_str());

         holder2.sprintf(_("Someone %s into the room.\n"),
                                                  the_boat->get_move_str());
         if (passengers.str_show() != NULL)
       {
          holder.str_cat(_(" carrying "));
            holder.str_cat(passengers.str_show());
         }
         holder.str_cat(".\n");
      }
   }

   next_loc->send_location(holder.str_show(), this, CAN_SEE);
   next_loc->send_location(holder2.str_show(), this, CANT_SEE);

   /* finally, move the player */
   if (in_boat)
   {
      the_boat->move_location(next_loc);
   }
   else
   {
      if (set_location(next_loc) == -1)
      {
         mainstruct->log_error(_("Could not set player location!"), "gocom");
         return -1;
      }
      if (get_type() == OBJ_TYPE_PLAYER)
      {
       tmp_gameflags = ((Player *) this)->get_gameflags();
         next_loc->show_location((Player *) this, 
                         tmp_gameflags->get_flag(GAMEFLAG_BRIEF));
      }
   }

   /* see if anyone in the room attacks them, or to see if their ghost
      is here to merge with them */
   the_inventory = next_loc->get_inventory();
   the_inventory->reset_current();
   tmp_obj = the_inventory->get_next();
   while (tmp_obj != NULL)
   {
      if (tmp_obj->get_type() == OBJ_TYPE_MOBILE)
      {
         tmp_mob = (Mobile *) tmp_obj;

         if ((tmp_mob->get_indflags())->get_flag(INDFLAG_GHOST))
       {
          /* if this is their ghost, merge them back together */
            if (!STRCASECMP(tmp_mob->get_clones(), get_name()))
          {
               tmp_loc = tmp_mob->get_loc();
               tmp_loc->remove_contained(tmp_mob);
               (mainstruct->get_dbase())->delete_obj(tmp_mob);
               tmp_obj = the_inventory->get_next();
               holder.sprintf(_("The ghost merges effortlessly into %s's body.\n"),
                                                get_title());
               tmp_loc->send_location(holder.str_show(), this, CAN_SEE);
               send_plr(
                _("The ghost merges into your body.  You now feel whole again.\n"));
               continue;
          }
       }
         else
            tmp_mob->check_aggression(this);
      }
      tmp_obj = the_inventory->get_next();
   }

   set_endurance(get_endurance() - endurance_required);

   if (get_type() == OBJ_TYPE_PLAYER)
   {
      if (check_specials(_("onentry"), next_loc, next_loc, NULL,
                                             ((Player *) this), ((Player *) this)) == 3)
         return 0;
   }

   return 1;

}

/***********************************************************************
 ** is_busy - if not a player, runs this function.  Always returns 0
 ***********************************************************************/

int Individual::is_busy()
{
  return 0;
}

/***********************************************************************
 ** is_alive - is this individual alive?
 ***********************************************************************/

int Individual::is_alive()
{
   if ((indflags->get_flag(INDFLAG_CORPSE)) ||
       (indflags->get_flag(INDFLAG_GHOST)))
     return 0;
   return 1;
}


/***********************************************************************
 ** add_rank - adds a rank to this player
 **
 ** Parameters: the_name - the name of the rank to add
 **             type     - the type of rank
 **             the_rank - the rank of the player with this rank
 **             the_exp  - the experience achieved since last rank
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::add_rank(char *the_name, int type, int the_rank, int the_exp)
{
   rank_list *new_rank;
   rank_list *tmp_rank;

   if (the_name == NULL)
      return -1;

   if ((type != OBJ_TYPE_SPELL) && (type != OBJ_TYPE_SKILL) && (type != 0))
      return -1;

   new_rank = new_rank_list();
   new_rank->rank_name = the_name;
   new_rank->the_type = type;
   new_rank->the_rank = the_rank;
   new_rank->the_exp_prob = the_exp;
   new_rank->next_rank = NULL;

   tmp_rank = player_ranks;
   player_ranks = new_rank;
   player_ranks->next_rank = tmp_rank;
   return 1;
}


/***********************************************************************
 ** remove_rank - removes an rank from this player
 **
 ** Parameters: the_name - the name of the rank to add
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::remove_rank(char *the_name)
{
   rank_list *tmp_rank;
   rank_list *prev_rank = NULL;

   if (player_ranks == NULL)
      return -1;

   tmp_rank = player_ranks;
   while (STRCASECMP(tmp_rank->rank_name.str_show(), the_name))
   {
      prev_rank = tmp_rank;
      tmp_rank = tmp_rank->next_rank;
      if (tmp_rank == NULL)
         return -1;
   }
   if (prev_rank == NULL)
   {
      tmp_rank = player_ranks;
      player_ranks = player_ranks->next_rank;
      delete_rank_list(tmp_rank);
   }
   else
   {
      prev_rank->next_rank = tmp_rank->next_rank;
      delete_rank_list(tmp_rank);
   }
   return 1;
}


/***********************************************************************
 ** find_ability - finds if a player has an ability
 **
 ** Parameters: the_name - the name of the ability to find
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::find_ability(char *the_name)
{
   rank_list *tmp_ability;

   if (player_ranks == NULL)
      return 0;

   tmp_ability = player_ranks;
   while ((STRCASECMP(tmp_ability->rank_name.str_show(), the_name)) ||
          ((tmp_ability->the_type != OBJ_TYPE_SPELL) && 
           (tmp_ability->the_type != OBJ_TYPE_SKILL)))
   {
      tmp_ability = tmp_ability->next_rank;
      if (tmp_ability == NULL)
         return 0;
   }
   return 1;
}


/***********************************************************************
 ** find_rank - finds if a player has a rank
 **
 ** Parameters: the_name - the name of the rank to find
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::find_rank(char *the_name)
{
   rank_list *tmp_rank;

   if (player_ranks == NULL)
      return 0;

   tmp_rank = player_ranks;
   while (STRCASECMP(tmp_rank->rank_name.str_show(), the_name))
   {
      tmp_rank = tmp_rank->next_rank;
      if (tmp_rank == NULL)
         return 0;
   }
   return 1;
}


/***********************************************************************
 ** get_rank_number - gets the numerical rank of the rank indicated
 **
 ** Parameters: the_name - the name of the rank to find
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::get_rank_number(char *the_name)
{
   rank_list *tmp_rank;

   if (player_ranks == NULL)
      return 0;

   tmp_rank = player_ranks;
   while (STRCASECMP(tmp_rank->rank_name.str_show(), the_name))
   {
      tmp_rank = tmp_rank->next_rank;
      if (tmp_rank == NULL)
         return -1;
   }
   return tmp_rank->the_rank;
}


/***********************************************************************
 ** set_rank_number - sets the numerical rank of the rank indicated
 **
 ** Parameters: the_name - the name of the rank to find
 **             the_num - the number to set the rank to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::set_rank_number(char *the_name, int the_num)
{
   rank_list *tmp_rank;

   if (player_ranks == NULL)
      return 0;

   if (the_num < 0)
      return -1;

   tmp_rank = player_ranks;
   while (STRCASECMP(tmp_rank->rank_name.str_show(), the_name))
   {
      tmp_rank = tmp_rank->next_rank;
      if (tmp_rank == NULL)
         return -1;
   }
   tmp_rank->the_rank = the_num;
   return 1;
}


/***********************************************************************
 ** get_rank_exp - gets the experience of the rank indicated
 **
 ** Parameters: the_name - the name of the rank to find
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::get_rank_exp_prob(char *the_name)
{
   rank_list *tmp_rank;

   if (player_ranks == NULL)
      return 0;

   tmp_rank = player_ranks;
   while (STRCASECMP(tmp_rank->rank_name.str_show(), the_name))
   {
      tmp_rank = tmp_rank->next_rank;
      if (tmp_rank == NULL)
         return -1;
   }
   return tmp_rank->the_exp_prob;
}


/***********************************************************************
 ** set_rank_exp - sets the experience of the rank indicated
 **
 ** Parameters: the_name - the name of the rank to find
 **             the_num - the number to set the exp to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::set_rank_exp_prob(char *the_name, int the_num)
{
   rank_list *tmp_rank;

   if (player_ranks == NULL)
      return 0;

   if (the_num < 0)
      return -1;

   tmp_rank = player_ranks;
   while (STRCASECMP(tmp_rank->rank_name.str_show(), the_name))
   {
      tmp_rank = tmp_rank->next_rank;
      if (tmp_rank == NULL)
         return -1;
   }
   tmp_rank->the_exp_prob = the_num;
   return 1;
}


/***********************************************************************
 ** add_rank_list - adds a list of ranks in a space delineated
 **                 string to the player
 **
 ** Parameters: the_list - the list of ranks to add
 **
 ** Returns: num added for success, -1 for failure
 **
 ***********************************************************************/

int Individual::add_rank_list(char *the_list)
{
   Strings tmp_str;
   int     counter = 1;
   Ability *tmp_ability;
   Strings holder;

   tmp_str.assign_word(the_list, counter);
   while (tmp_str.str_show() != NULL)
   {
      /* if we can't find an ability, it must be a weapon */
      if ((tmp_ability =
                  mainstruct->get_ability(tmp_str.str_show())) == NULL)
      {
         add_rank(tmp_str.str_show(), 0, 0, 0);
      }
      else
         add_rank(tmp_ability->get_name(), tmp_ability->get_type(), 0, 0);

      counter++;
      tmp_str.assign_word(the_list, counter);
   }
   return counter-1;
}

/***********************************************************************
 ** delete_ranks - delete all ranks from this individual
 ***********************************************************************/

void Individual::delete_ranks()
{
   rank_list       *tmp_rank;
   
   /* deletes all ranks from the player */
   while (player_ranks != NULL)
   {
      tmp_rank = player_ranks->next_rank;
      delete_rank_list(player_ranks);
      player_ranks = tmp_rank;
   }
}


/***********************************************************************
 ** write_ranks - writes the ranks this player has to the player
 **               file to save for later
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure, 0 for no write
 **
 ***********************************************************************/

int Individual::write_ranks(FILE *the_file)
{
   rank_list *tmp_rank;

   tmp_rank = get_ranks();
   if (get_type() == OBJ_TYPE_PLAYER)
   {
      if (tmp_rank == NULL)
      return 0;

      fprintf(the_file, "rank\n");
   }

   /* write all the ranks to file */
   while (tmp_rank != NULL)
   {
      fprintf(the_file, "%s %d %d\n", tmp_rank->rank_name.str_show(),
                        tmp_rank->the_rank, tmp_rank->the_exp_prob);
      tmp_rank = tmp_rank->next_rank;
   }
   fprintf(the_file, "#\n");

   return 1;
}


/***********************************************************************
 ** read_ranks - reads in the player's ranks from the user file
 **
 ** Parameters: the_file - the file we read in the inventory from
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::read_ranks(FILE *the_file)
{
   Ability      *tmp_ability = NULL;
   Strings      rank_name;
   token_record *the_token;
   Strings      holder;
   int          has_errors = 0;
   int          the_rank;
   int          the_exp;
   int          rank_type = 0;


   the_token = get_token(the_file, '\0');
   while ((the_token->token_type != T_POUND) && (the_token->token_type > 0))
   {
      if ((get_type() == OBJ_TYPE_MOBILE) || 
        ((tmp_ability = mainstruct->get_ability(the_token->the_string)) == NULL))
      {
         rank_name = the_token->the_string;
         rank_type = 0;
      }
      else
      {
         rank_type = tmp_ability->get_type();
         rank_name = tmp_ability->get_name();
      }

      /* Set rank value */
      the_token = get_token(the_file, '\0');
      if (the_token->token_type != T_NUMERICAL)
      {
         holder.sprintf("Rank %s in individual %s missing rank value",
                                 rank_name.str_show(), get_name());
         mainstruct->log_error(holder.str_show(), "read_ranks");
         has_errors = 1;
      }
      the_rank = atoi(the_token->the_string);

      /* Set exp value */
      the_token = get_token(the_file, '\0');
      if (the_token->token_type != T_NUMERICAL)
      {
         holder.sprintf("Rank %s in individual %s missing exp value",
                       rank_name.str_show(), get_name());
         mainstruct->log_error(holder.str_show(), "read_ranks");
         has_errors = 1;
      }
      the_exp = atoi(the_token->the_string);

      if (!has_errors)
      {
         add_rank(rank_name.str_show(), rank_type, the_rank, the_exp);
      }
      the_token = get_token(the_file, '\0');
   }

   return 1;
}

/***********************************************************************
 ** get_ranks - gets a pointer to the rank list
 ***********************************************************************/

rank_list *Individual::get_ranks()
{
  return player_ranks;
}


/***********************************************************************
 ** display_ranks - displays the ranks in this individual to a builder
 **
 ** Parameters: the_builder - the builder to display to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Individual::display_ranks(Builder *the_builder)
{
  rank_list *tmp_rank;
  int counter = 1;

  the_builder->send_bldr("Proficiencies for: %s\n\n", get_name());
  tmp_rank = player_ranks;
  if (tmp_rank == NULL)
    the_builder->send_bldr("None.\n\n");
  while (tmp_rank != NULL)
  {
    the_builder->send_bldr("&+GProficiency [&+B%d&+G]:&*\n", counter);
    the_builder->send_bldr("   &+GProfName: \t\t&+g%s&*\n", 
                     tmp_rank->rank_name.str_show());
    the_builder->send_bldr("   &+GRank: \t\t&+w%d&*\n", tmp_rank->the_rank);
    the_builder->send_bldr("   &+GProbability: \t&+w%d&*\n\n", tmp_rank->the_exp_prob);
    counter++;
    tmp_rank = tmp_rank->next_rank;
  }
  return counter;
}


/***********************************************************************
 ** get_rankname_by_num - gets the rank given a sequence in the list
 **                       where 1 is the first element
 **
 ** Parameters: sequence - the sequence number of the element
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

char *Individual::get_rankname_by_num(int sequence)
{
  rank_list *tmp_rank;
  int i;

  tmp_rank = player_ranks;
  for (i=1; i<sequence; i++)
  {
    if (tmp_rank == NULL)
      return NULL;

    tmp_rank = tmp_rank->next_rank;
  }
  return tmp_rank->rank_name.str_show();
}


#endif

Generated by  Doxygen 1.6.0   Back to index