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

player.cpp

/**********************************************************************
 ** Player class: These functions control the player activities. They
 **               create the player and open the socket. They also log
 **               in the player and load player data, as well as handle
 **               all player activities
 **
 **
 ** Reviewed last: version 0.14
 **
 **
 ** Copyright (C) 2000 George Noel (Slate), Ed Boraas
 **
 **   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 PLAYER_C
#define PLAYER_C

#include "config.h"
#include "sysdep.h"
#include "strings.h"
#include "mudtypes.h"
#include "mudobject.h"
#include "location.h"
#include "btree.h"
#include "area_dbase.h"
#include "individual.h"
#include "player.h"
#include "login.h"
#include "verb.h"
#include "parse.h"
#include "input.h"
#include "verb.h"
#include "verb_list.h"
#include "lexer.h"
#include "logs.h"
#include "errlog.h"
#include "object_list.h"
#ifdef WIN32
#include "../win32/winport.h"
#else
#include "port.h"
#endif
#include "mud.h"
#include "global.h"
#include "objtype.h"
#include "utils.h"
#include "gameflags.h"
#include "merger.h"
#include "gameflags.h"
#include "lexer.h"
#include "newfuncts.h"
#include "indflags.h"
#include "level_list.h"
#include "boat.h"
#include "mailer.h"
#include "inp_funct.h"
#include "adminflags.h"
#include "comflags.h"
#include "talent.h"
#include "race.h"

// This is the ranks at which the experience required increases
int cutoff_rank[5] = {5, 10, 20, 30, 40};

// This is the experience required for each level at the rank above
long cutoff_exp[5] = {200, 1000, 5000, 20000, 60000};

/***********************************************************************
 ** _Player (constructor) - creates a player and opens up the socket
 **                         for business. Logs in the player and loads
 **                         the player information into the player
 **                         object
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Player::Player(void)
{
   Strings holder;
   Flags   *gameflags;
   Port    *gameport;

   // Initialize some variables
   next_player = NULL;
   player_levels = NULL;

   player_quests = NULL;

   /* this should be the only place that this is set */
   obj_type = OBJ_TYPE_PLAYER;

   still_on = 1;
   quitting = 0;

   set_capacity(300);
   gameflags = get_gameflags();
   gameflags->clr_flag(GAMEFLAG_ONGAME);

   prompt = NULL;
   push_prompt("main", "&+bAIME&+W>&* ");;

   holder.sprintf("%s@%s", the_config.entry_locname.str_show(),
                                    the_config.hardcoded_areaname.str_show());
   set_loc_str(holder.str_show());


   if (input_handler.push_input_handler(main_plr_handler, &(prompt->the_prompt),
                                                            0, 0, 0) <= 0)
   {
      mainstruct->log_error("Error loading main input handler for player",
                                          "Player constructor");
      exit(0);
   }

   /* create a new connection, accepting the incoming player */
   
   gameport = mainstruct->get_game_socket();

#ifdef WIN32
   the_socket = new_Connection();

   if (gameport->accept_conn(the_socket, this) == -1)
   {
         still_on = 0;
         return;
   }
#else
   the_socket = new_Connection(gameport->get_socket(), this);
#endif

   set_initname();

   if (the_socket->lost_link())
   {
      still_on = 0;
      return;
   }

   the_socket->set_valid();

   /* initalize variables */

   set_area("player");
   set_desc("You see an ordinary player.\n");
   experience = 0;
   talent_funds = 0;
   set_vislvl(0);

   pager_lines = the_config.default_pager_lines;
   the_mail = NULL;
   cur_brief = NULL;
   talent_list = NULL;
   login_player((void *) this);
}


/***********************************************************************
 ** _Player (constructor) - creates a player and assigns a socket passed
 **                         in.  Logs in the player and loads
 **                         the player information into the player
 **                         object
 **
 ** Parameters: new_sock - the connection to use for this
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Player::Player(Connection *new_sock)
{
   Strings holder;
   Flags   *gameflags;

   // Initialize some variables
   next_player = NULL;
   player_levels = NULL;

   player_quests = NULL;

   /* this should be the only place that this is set */
   obj_type = OBJ_TYPE_PLAYER;

   still_on = 1;
   quitting = 0;

   set_capacity(300);
   gameflags = get_gameflags();
   gameflags->clr_flag(GAMEFLAG_ONGAME);

   prompt = NULL;
   push_prompt("main", "&+bAIME&+W>&* ");;

   holder.sprintf("%s@%s", the_config.entry_locname.str_show(),
                                    the_config.hardcoded_areaname.str_show());
   set_loc_str(holder.str_show());

   if (input_handler.push_input_handler(main_plr_handler, &(prompt->the_prompt),
                                                            0, 0, 0) <= 0)
   {
      mainstruct->log_error("Error loading main input handler for player",
                                          "Player constructor");
      exit(0);
   }

   /* assign the connection */
   
   the_socket = new_sock;
   the_socket->set_owner(this);

   set_initname();

   if (the_socket->lost_link())
   {
      still_on = 0;
      return;
   }

   the_socket->set_valid();

   /* initalize variables */

   set_area("player");
   set_desc("You see an ordinary player.\n");
   experience = 0;
   talent_funds = 0;
   set_vislvl(0);

   pager_lines = the_config.default_pager_lines;
   the_mail = NULL;
   cur_brief = NULL;
   talent_list = NULL;
   login_player((void *) this);
}


/***********************************************************************
 ** _Player (constructor) - creates a player but does not open a socket
 **                         or go to the login script, used for accessing
 **                         or modifying data on a saved player not on
 **
 ** Parameters: the_name - the name of the player
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Player::Player(char *the_name)
{
   Strings holder;
   Flags   *gameflags;

   /* this should be the only place that this is set */
   obj_type = OBJ_TYPE_PLAYER;

   still_on = 1;
   quitting = 0;
   experience = 0;
   talent_funds = 0;
   set_vislvl(0);
   pager_lines = the_config.default_pager_lines;

   prompt = NULL;
   push_prompt("main", "&+bAIME&+W>&* ");;

   gameflags = get_gameflags();
   gameflags->clr_flag(GAMEFLAG_ONGAME);

   holder.sprintf("%s@%s", the_config.entry_locname.str_show(),
                           the_config.hardcoded_areaname.str_show());
   set_loc_str(holder.str_show());

   set_name(the_name);

   /* initalize variables */
   next_player = NULL;
   player_levels = NULL;

   player_quests = NULL;

   set_area("player");
   set_desc("You see an ordinary player.\n");

   the_socket = NULL;
   cur_brief = NULL;
   talent_list = NULL;
   the_mail = NULL;
}


/***********************************************************************
 ** ~_Player (destructor) - cleans up the object for deletion
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Player::~Player()
{
   Location        *this_loc;
   quest_list      *tmp_quest;
   brief_stack     *tmp_brief;
   prompt_stack    *tmp_prompt;
   level_list      *tmp_levlist;

   /* releases all objects the player is carrying, placing them nowhere */
   release_all_inv();


   /* deletes all briefs */
   while (cur_brief != NULL)
   {
      tmp_brief = cur_brief->next_brief;
      delete_brief_stack(cur_brief);
      cur_brief = tmp_brief;
   }

   /* deletes all prompts */
   while (prompt != NULL)
   {
      tmp_prompt = prompt->next_prompt;
      delete_prompt_stack(prompt);
      prompt = tmp_prompt;
   }


   /* deletes all quests from the player */
   while (player_quests != NULL)
   {
      tmp_quest = player_quests->next_quest;
      delete_quest_list(player_quests);
      player_quests = tmp_quest;
   }


   /* delete all levels from the player */
   while( player_levels != NULL )
   {
      tmp_levlist = player_levels->next_level;
      delete_level_list( player_levels );
      player_levels = tmp_levlist;
   }

   /* delete the mail from the character */
   if( the_mail != NULL )
   {
      delete_Mailer( the_mail );
   }

   delete_talent_list();

   /* now we need to remove this player from the location inventory */
   if ((this_loc = get_loc()) != NULL)
   {
      this_loc->remove_contained(this);
   }
   next_player = NULL;
   if (the_socket != NULL)
      delete_Connection(the_socket);
}

bool Player::can_see_ind(Individual *the_ind)
{
    int the_num;

    if (the_ind->is_visible())
        return true;

    if (the_ind->is_vis_incog() 
    && (the_ind->get_loc())->find_contained(get_name(), &the_num)
    || get_admflags()->get_flag(ADMINFLAG_ADMINISTRATOR))
        return true;

    if (the_ind->is_vis_admin() && get_admflags()->get_flag(ADMINFLAG_ADMINISTRATOR))
        return true;

    return false;
}


/***********************************************************************
 ** release_all_inv - releases all inventory objects, making their locations
 **                   nowhere.
 **
 ** Returns: returns the number of objects released
 **
 ***********************************************************************/

int Player::release_all_inv(void)
{
   int count = 0;
   Location  *the_loc;
   MudObject *the_obj;

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

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

       remove_contained(the_obj);
       inventory.reset_current();
       the_obj = inventory.get_next();
       count++;
   }
   return count;

}



/***********************************************************************
 ** check_connection - goes to the connection and waits for input from
 **                    the player. Gets that input and handles it
 **
 ** Parameters: None
 **
 ** Returns: returns num chars gotten if successful
 **          0 if the socket is not valid yet
 **          -1 error with select
 **          -2 error with read
 **          -3 if empty packet found
 **          -4 if we lost connection (check errno)
 **          -5 if the socket has been removed
 **
 ***********************************************************************/

int Player::check_connection()
{
   Strings *the_input;
   int had_input = 0;
   int sock_result;
   Strings holder;

   if (((sock_result = the_socket->check_socket()) > 0) ||
       (the_socket->has_input()))
   {
      if (the_socket->has_input())
        {
            // Loop through and handle lines
            for (int i=0; i<input_handler.get_lines_per_handle(); i++)
            {
           the_input = the_socket->get_input();

           if (the_input != NULL)
           {
              holder.sprintf("                                   \r"
                             "&+g%s's input:&* %s", get_title(),
                                                       the_input->str_show());
              get_connection()->send_to_snoopers(holder.str_show());
              input_handler.exec_input_handler((MudObject *) this,
                                                     the_input->str_show());
                    delete the_input;
               }
             else
               {
                    sysmessage("Lost input.\r\n");
                break;
               }

             // If this player has lost its connection, exit out
             if (the_socket == NULL)
               {
                return -5;                      
               }

           if (!is_quitting() && is_on())
           {
                the_socket->send_to_socket(input_handler.get_prompt(), COOKED);
           }

           had_input = 1;
            }
      }

      if (the_socket->has_output())
      {
            if (!had_input && !is_quitting() && is_on())
            {
            the_socket->send_to_socket(input_handler.get_prompt(), COOKED);
        }
        the_socket->flush();
      }
      return 1;
   }
   else if (sock_result == -3)
   {
      Strings tmpholder;

      tmpholder.sprintf("Player %s went linkdead.", get_title());
      mainstruct->log_event(tmpholder.str_show());


     //      set_off();
      return -1;
   }
   else if (sock_result == 0)
      return 0;
   else
   {
      return -1;
   }

   return 0;
}

/***********************************************************************
 ** send_plr - sends a string to the player's IO stream
 **
 ** Parameters: the_str - the string to be sent
 **
 ** Returns: the num of chars sent if successful, -1 if failed
 **
 ***********************************************************************/

int Player::send_plr(char *new_str, ...)
{
   int xlen;       /* holds the total characters resulting from vsprinf */
   va_list args;   /* holds the list of arguments */
   char *tmp_str;  /* used to move along the string */
   char *arg_str;  /* used to display the argument if we want to, testing */
   int  arg_int;   /* used to hold an integer argument, for testing */
   int  arg_long;  /* used to hold a long argument, for testing */
   char arg_char;  /* used to hold a char argument, for testing */
   int  count = 0;
   int  tmp_int;
   char *dig_ptr;
   int  format = 0;

   if (the_socket == NULL)
     return 0;

   /* we have to first estimate the size of a string we need to allocate
      to put this into. This is not an easy task, so we have to search
      along the va_list structs and count the size of each. So far it is
      only set up for strings, integers, and characters. Anything else and
      youre SOL */

   va_start( args, new_str );
   tmp_str = new_str;

   while (*tmp_str)
   {

      if ((*tmp_str == '%') && (*(tmp_str+1) && (*(tmp_str+1) != '%')))
      {
         format = 0;
         tmp_str++;
         if ((*tmp_str) && (*tmp_str == '-'))
    {
       /* advance beyond it */
            tmp_str++;
    }

         if (*tmp_str && (isdigit(*tmp_str)))
    {
            dig_ptr = tmp_str;
            while (*tmp_str && (isdigit(*tmp_str)))
               tmp_str++;
            format = atoi(dig_ptr);
            count += format;
         }

         if (*tmp_str && (*tmp_str == 's'))
    {
            arg_str = va_arg(args, char *);
            if (arg_str != NULL)
               count += (strlen(arg_str));
            else
          count += 6;
         }
         else if (*tmp_str && (*tmp_str == 'd'))
    {
            arg_int = va_arg(args, int);

            count += 8;
         }
         else if (*tmp_str && (*tmp_str == 'l'))
    {
            if (*(tmp_str+1) && (*(tmp_str+1) == 'd'))
               arg_long = va_arg(args, long);

            count += 14;
         }

         else if (*tmp_str && (*tmp_str == 'c'))
    {
            arg_char = (char) va_arg(args, int);
            count += 3;
         }
         else if (*tmp_str && !isalpha(*tmp_str))
    {
            arg_str = (char *) va_arg(args, void *);
            count += 100;
         }
         else
    {
            arg_str = (char *) va_arg(args, void *);
       count += 10;
         }
      }
      tmp_str++;
      count++;
   }
   /* increment two more just for safety */
   count += 2;

   /* now we reset the varg list and create the array, so we can load them
      all into the string */
   va_start( args, new_str );
   tmp_str = new char[count];
   BZERO(tmp_str, count);
   xlen = VSNPRINTF( tmp_str, count-1, new_str, args );

   tmp_int = the_socket->send_to_socket(tmp_str);

   /* now clean up after ourselves */
   va_end( args );

   delete tmp_str;

   return tmp_int;
}

/***********************************************************************
 ** get_next_player - returns the pointer to the next player in the list
 **
 ** Parameters: None
 **
 ** Returns: pointer to next player
 **
 ***********************************************************************/

Player *Player::get_next_player()
{
   return next_player;
}

/***********************************************************************
 ** set_next_player - sets the next player in the list
 **
 ** Parameters: next_player - the next player to set to
 **
 ** Returns: None
 **
 ***********************************************************************/

void Player::set_next_player(Player *the_player)
{
   next_player = the_player;
}


/***********************************************************************
 ** set_name - sets the name of the player
 **
 ** Parameters: the_name - the name to set the player to
 **
 ** Returns:  1 for success
 **          -1 for failure
 **
 ***********************************************************************/

int Player::set_pname(char *the_name)
{
   if (the_name == NULL)
      return -1;

   set_name(the_name);
   set_title(the_name);
   return 1;
}

/***********************************************************************
 ** set_race - sets the race for the player
 **
 ** Parameters: the_race - the race to set it to
 **
 ***********************************************************************/

void Player::set_race(char *the_race)
{
   player_race = the_race;

   if (player_race.str_len() > MAXNAMELEN)
      player_race.truncate(MAXNAMELEN);
}


/***********************************************************************
 ** get_race - gets the pointer to the race string
 **
 ** Parameters: None
 **
 ** Returns:  pointer to the string for success
 **           NULL for failure
 **
 ***********************************************************************/

char *Player::get_race()
{
   return player_race.str_show();
}

/***********************************************************************
 ** is_on - is the player still connected and on
 **
 ** Parameters: None
 **
 ** Returns:   1 if player is on
 **            0 if player has quit
 **           -1 if player entry was bad
 **           -2 if player lost link
 **
 ***********************************************************************/

int Player::is_on()
{
   return still_on;
}

/***********************************************************************
 ** set_off - set the player to not on anymore
 **
 ** Parameters: None
 **
 ** Returns:   Nothing
 **
 ***********************************************************************/

void Player::set_off()
{
   still_on = 0;
   return;
}

/***********************************************************************
 ** set_quitting - returns if the player is quitting or not
 **
 ** Parameters: None
 **
 ** Returns:   1 if they are quitting
 **            0 if they are not quitting
 **
 ***********************************************************************/

int Player::is_quitting()
{
   return quitting;
}

/***********************************************************************
 ** set_quitting - set the player to quitting
 **
 ** Parameters: None
 **
 ** Returns:   Nothing
 **
 ***********************************************************************/

void Player::set_quitting()
{
   if (the_mail != NULL)
      the_mail->write_mail();

   quitting = 1;
   return;
}


/***********************************************************************
 ** get_passwd - returns the character string with the encrypted passwd
 **
 ** Parameters: None
 **
 ** Returns: a pointer to the encrypted password string
 **
 ***********************************************************************/

char *Player::get_passwd()
{
   return passwd.str_show();
}


/***********************************************************************
 ** set_passwd - allows the user to set the encrypted password string
 **
 ** Parameters: the_passwd - the string to set it to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::set_passwd(char *the_passwd)
{
   passwd = the_passwd;
   return 1;
}


/***********************************************************************
 ** echo_off - turns the echo off for the user's keystrokes
 **
 ** Parameters: Nothing
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/

int Player::echo_off()
{
   return the_socket->echo_off();
}


/***********************************************************************
 ** echo_on - turns the echo on for the user's keystrokes
 **
 ** Parameters: Nothing
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/

int Player::echo_on()
{
   return the_socket->echo_on();
}

/***********************************************************************
 ** find_host_name - finds the hostname using gethostbyname
 **                  (warning) can cause lag
 **
 ** Parameters: Nothing
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/

int Player::find_host_name()
{
   return the_socket->find_host_addr();
}


/***********************************************************************
 ** get_ip_addr - gets the ip address string
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the ip addr string
 **
 ***********************************************************************/

char *Player::get_ip_addr()
{
   return the_socket->get_ip_addr();
}

/***********************************************************************
 ** get_host_addr - gets the host address string
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the host address string
 **
 ***********************************************************************/

char *Player::get_host_addr()
{
   return the_socket->get_host_addr();
}


/***********************************************************************
 ** get_comflags - returns the command flags structure
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the command flags structure
 **
 ***********************************************************************/

Flags *Player::get_comflags()
{
   return &command_flags;
}


/***********************************************************************
 ** get_admflags - returns the admin flags structure
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the admin flags structure
 **
 ***********************************************************************/

Flags *Player::get_admflags()
{
   return &admin_flags;
}


/***********************************************************************
 ** get_gameflags - returns the game flags structure
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the game flags structure
 **
 ***********************************************************************/

Flags *Player::get_gameflags()
{
   return &game_flags;
}


/***********************************************************************
 ** set_comflags - sets the comflags for this player
 **
 ** Parameters: the_flags - the comflags we are setting to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::set_comflags(save_flags *the_flags)
{
   command_flags.copy_from_save_struct(the_flags);

   return 1;
}

/***********************************************************************
 ** set_talent_funds - sets the amount of talent points the player has
 **                    to use up
 **
 ** Parameters: new_num - the new value to set the talent funds to
 **
 ***********************************************************************/

void Player::set_talent_funds(int new_num)
{
   if (new_num < 0)
      return;

   talent_funds = new_num;
}

/***********************************************************************
 ** get_talent_funds - gets the amount of talent points the player has
 **                    to use up
 **
 ***********************************************************************/

int Player::get_talent_funds()
{
   return talent_funds;
}


/***********************************************************************
 ** set_admflags - sets the admin flags for this player
 **
 ** Parameters: the_flags - the adminflags we are setting to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::set_admflags(save_flags *the_flags)
{
   admin_flags.copy_from_save_struct(the_flags);

   return 1;
}


/***********************************************************************
 ** set_gameflags - sets the gameflags for this player
 **
 ** Parameters: the_flags - the gameflags we are setting to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::set_gameflags(save_flags *the_flags)
{
   game_flags.copy_from_save_struct(the_flags);

   return 1;
}


/***********************************************************************
 ** get_connection - gets the connection socket
 **
 **
 ***********************************************************************/

Connection *Player::get_connection()
{
   return the_socket;
}


/***********************************************************************
 ** check_player - checks the player for input, output, and any events
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure, -2 if the player should be
 **          deleted
 **
 ***********************************************************************/

int Player::check_player(void)
{
   int conn_result;
   int counter = 0;

#ifdef WIN32
   // If we have windows, we need to take into account multiple threads that could
   // access the connection concurrently.  Handle this by locking the connection
   while (the_socket->set_locked() == FALSE)
   {
         // If the socket got stuck on, ignore the lock...cheating but I couldn't figure out
         // why if you take over a connection in the windows port, it won't unlock properly
         // Maybe someday need to look into this
         if (counter > 50)
               break;

         Sleep(7);
         counter++;
   }

#endif
   if ((conn_result = check_connection()) < 0)
   {
      if (conn_result == -5)
        {
#ifdef WIN32
              the_socket->unlock();
#endif
              return -2;
        }

      if ((time(0) - the_socket->lost_link()) > the_config.secs_till_timeout)
      {
         Strings tmpholder;

         tmpholder.sprintf("Player %s lost link and has timed out.",
                                                                 get_title());
         mainstruct->log_event(tmpholder.str_show());

         set_off();
#ifdef WIN32
             the_socket->unlock();
#endif
         return -1;
      }
   }

   if (is_quitting())
   {
      set_off();
#ifdef WIN32
       the_socket->unlock();
#endif
      return -1;
   }

   /* if the mud is shutting down, we remove all players */
   if (mainstruct->is_shutdown())
   {
      send_plr("Mud shutting down, closing connection.\n");
      set_off();
#ifdef WIN32
        the_socket->unlock();
#endif

      return -1;
   }

#ifdef WIN32
      the_socket->unlock();
#endif

   return 1;
}


/***********************************************************************
 ** get_input_handler - gets the input handler for this player
 **
 ** Parameters: None
 **
 ** Returns: a pointer to the input handler
 **
 ***********************************************************************/

Inp_Handler *Player::get_input_handler(void)
{
   return &input_handler;
}

/***********************************************************************
 ** set_initname - sets the initial login name of login_<socketnum> so
 **                that each login name is unique until they give us a
 **                name that we can use
 **
 ** Parameters: None
 **
 ** Returns: a pointer to the name for success, -1 for failure
 **
 ***********************************************************************/

char *Player::set_initname(void)
{
   Strings holder;

   holder.sprintf("login_%d", the_socket->get_socknum());
   set_pname(holder.str_show());
   return get_name();
}


/***********************************************************************
 ** game_put_obj - puts an object into another object
 **
 ** Parameters: the_obj - the object we are putting
 **             to_obj - where we are putting the object from
 **             has_to - is the player holding the object we put to
 **             num_of - for mergers, the num of objects we are putting
 **             is_in_loc - is the object in the location before put
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::game_put_obj(MudObject *the_obj, MudObject *to_obj, int has_to,
                         int num_of, int is_in_loc)
{
   Strings holder;
   MudObject *from_obj;
   char *sex1;
   char *sex2;

   if (is_in_loc)
      from_obj = (MudObject *) get_loc();
   else
      from_obj = (MudObject *) this;

   if (the_obj->get_type() == OBJ_TYPE_BOAT)
   {
      if (((Boat *) the_obj)->contains_players())
      {
         send_plr("It has someone in it!\n");
         return -1;
      }
   }

   /* 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 (!the_obj->is_merger())
      {
         if (the_obj->get_type() == OBJ_TYPE_WEARABLE)
            remove_item((Wearable *) the_obj);
         from_obj->remove_contained(the_obj);
      }
      else
      {
         the_merger = (Merger *) the_obj;

         if (num_of > the_merger->get_number_of())
    {
            send_plr("There are not that many here.\n");
            return -1;
         }

         if (to_obj->get_capacity() < (to_obj->get_size_held() +
                               (((Moveable *) the_obj)->get_size() * num_of)))
         {
            send_plr("It won't hold that many.\n");
            return -2;
         }

         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 (to_obj->get_capacity() < (to_obj->get_size_held() +
                                     ((Moveable *) the_obj)->get_size()))
      {
         send_plr("It won't fit in the %s.\n", to_obj->get_title());
         return -2;
      }

      if (the_obj->get_type() == OBJ_TYPE_WEARABLE)
         remove_item((Wearable *) the_obj);
      from_obj->remove_contained(the_obj);
   }


   send_plr("You put the %s in the %s.\n",
                   the_obj->get_title(), to_obj->get_title());

   if (has_to)
   {
      if (is_male())
         sex1 = "his";
      else if (is_female())
         sex1 = "her";
      else
          sex1 = "its";
   }
      else
         sex1 = "the";

   if (!is_in_loc)
   {
      if (is_male())
         sex2 = "his";
      else if (is_female())
         sex2 = "her";
      else
          sex2 = "its";
   }
      else
         sex2 = "the";

   holder.sprintf("%s puts %s %s in %s %s.\n",
           get_name(), sex2, the_obj->get_title(), sex1,
                                            to_obj->get_title());

   (get_loc())->send_location(holder.str_show(),this, CAN_SEE);
   if (to_obj->add_contained(the_obj) == 2)
      mainstruct->delete_object(the_obj);

   return 1;
}


/***********************************************************************
 ** flush_player - flushes the output of this player
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Player::flush_player(void)
{
   the_socket->flush();
}


/***********************************************************************
 ** swap_connection - swaps the connection of this player with another
 **                   player.  Essentially changes the ownership of the
 **                   player with another
 **
 ** Parameters: swap_player - who we are swapping with
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::swap_connection(Player *swap_player)
{
   Connection *tmp_connection;
   Flags      *game_flags;

   game_flags = swap_player->get_gameflags();
   tmp_connection = the_socket;
   the_socket = swap_player->get_connection();
   if (game_flags->get_flag(GAMEFLAG_COLOR))
      the_socket->set_color(1);

   swap_player->set_connection(tmp_connection);
   the_socket->set_owner(this);
   return 1;
}

/***********************************************************************
 ** set_connection - sets this connection to a new connection
 *
 **
 ***********************************************************************/

void Player::set_connection(Connection *new_connection)
{
   the_socket = new_connection;
}


/***********************************************************************
 ** display_prompt - displays the prompt to the player and flushes output
 **
 **
 ***********************************************************************/

void Player::display_prompt(void)
{
   the_socket->send_to_socket(input_handler.get_prompt(), COOKED);
   flush_player();
}


/***********************************************************************
 ** write_inventory - writes the items in the player's inventory to a
 **                   file so their stuff is saved when they quit the
 **                   game
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::write_inventory(FILE *the_file)
{
   MudObject  *tmp_obj;
   Strings    act_name;

   inventory.reset_current();
   tmp_obj = inventory.get_next();

   /* if they carry nothing, just return */
   if (tmp_obj == NULL)
      return 0;

   fprintf(the_file, "inv\n");
   /* write all the objects to file */
   while (tmp_obj != NULL)
   {
      if (tmp_obj->get_parent() == NULL)
         act_name = tmp_obj->get_name();
      else
         act_name = tmp_obj->get_parent();

      if ((tmp_obj->get_type() == OBJ_TYPE_WEAPON) ||
          (tmp_obj->get_type() == OBJ_TYPE_WEARABLE))
      {
    /* if they are wielding something in their left hand, mark it so */
         if (((Moveable *) tmp_obj) == get_wielded(Left))
    {
            fprintf(the_file, "!%s@%s\n", act_name.str_show(),
                                                       tmp_obj->get_area());
         }
         else if (((Moveable *) tmp_obj) == get_wielded(Right))
    {
            if (get_wielded(Right) != get_wielded(Left))
               fprintf(the_file, "!%s@%s\n", act_name.str_show(),
                                                    tmp_obj->get_area());
         }

         /* if they are wearing something, mark it so */
         else if (tmp_obj->get_type() == OBJ_TYPE_WEARABLE)
    {
            if (is_worn((Wearable *) tmp_obj))
       {
               fprintf(the_file, "*%s@%s\n", act_name.str_show(),
                                                      tmp_obj->get_area());
            }
            else
       {
               fprintf(the_file, "%s@%s\n", act_name.str_show(),
                                                    tmp_obj->get_area());
            }
         }
         else
            fprintf(the_file, "%s@%s\n", act_name.str_show(),
                                                    tmp_obj->get_area());
      }
      else if (tmp_obj->is_merger())
      {
         fprintf(the_file, "%s@%s(%ld)\n", act_name.str_show(),
                  tmp_obj->get_area(), ((Merger*)tmp_obj)->get_number_of());
      }
      else
         fprintf(the_file, "%s@%s\n", act_name.str_show(),
                                                  tmp_obj->get_area());

      tmp_obj->write_contents(the_file);

      tmp_obj = inventory.get_next();
   }
   fprintf(the_file, "#\n");

   return 1;
}


/***********************************************************************
 ** read_inventory - reads the items specified in this player's user file
 **                  and creates the objects, placing them in the player's
 **                  inventory
 **
 ** Parameters: the_file - the file we read in the inventory from
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::read_inventory(FILE *the_file)
{
   MudObject    *tmp_obj;
   token_record *the_token;
   int          wielded;
   int          worn;
   Strings      holder;

   the_token = get_token(the_file, '\0');
   while ((the_token->token_type != T_POUND) && (the_token->token_type > 0))
   {
      wielded = worn = 0;

      if (the_token->token_type == T_EXPOINT)
      {
         wielded = 1;
         the_token = get_token(the_file, '\0');
      }
      else if (the_token->token_type == T_MULT)
      {
         worn = 1;
         the_token = get_token(the_file, '\0');
      }

      tmp_obj = read_carried(the_file, &the_token);

      if (tmp_obj == NULL)
      {
         holder.sprintf("Error reading object for player '%s' inventory.\n",
                                          get_name());
         mainstruct->log_error(holder.str_show(), "read_inventory");
         continue;
      }

      if ((worn) || ((wielded) && (tmp_obj->get_type() == OBJ_TYPE_WEARABLE)))
      {
         wear_item((Wearable *) tmp_obj);
      }
      if (wielded)
      {
         wield_moveable((Moveable *) tmp_obj);
      }
      if (tmp_obj->is_a_moveable())
         ((Moveable *) tmp_obj)->set_moved();

      add_contained(tmp_obj);
   }

   return 1;
}


/***********************************************************************
 ** read_carried - reads in an item from the carried file and clones an
 **                object based on the info read in
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

MudObject *Player::read_carried(FILE *the_file, token_record **the_token)
{
   MudObject    *tmp_obj;
   MudObject    *new_obj;
   Object_List  *obj_dbase;

   if ((tmp_obj = mainstruct->get_object((*the_token)->the_string)) == NULL)
   {
      *the_token = get_token(the_file, '\0');
      if ((*the_token)->token_type == T_LPAREN)
      {
         *the_token = get_token(the_file, '\0');
         *the_token = get_token(the_file, '\0');
         *the_token = get_token(the_file, '\0');
      }
      return NULL;
   }

   obj_dbase = mainstruct->get_dbase();

   new_obj = obj_dbase->clone_object(tmp_obj);
   if (new_obj->is_a_moveable())
   {
      ((Moveable *) new_obj)->set_moved();
   }

   *the_token = get_token(the_file, '\0');
   if (tmp_obj->is_merger())
   {
      Merger *the_merger;

      the_merger = (Merger *) new_obj;
      if ((*the_token)->token_type == T_LPAREN)
      {
         *the_token = get_token(the_file, '\0');
    if (!isdigit(*((*the_token)->the_string)))
            return NULL;

         the_merger->set_number_of(atol((*the_token)->the_string));
         *the_token = get_token(the_file, '\0');
         *the_token = get_token(the_file, '\0');
      }
      else
      {
         the_merger->set_number_of(1);
      }
   }
   if ((*the_token)->token_type == T_LSQUIG)
   {
      MudObject *contained_in;

      *the_token = get_token(the_file, '\0');
      while (((*the_token)->token_type > 0) &&
             ((*the_token)->token_type != T_RSQUIG))
      {
         contained_in = read_carried(the_file, the_token);
         if (contained_in != NULL)
            new_obj->add_contained(contained_in);
      }
      *the_token = get_token(the_file, '\0');
   }
   return new_obj;
}



/***********************************************************************
 ** display_abilities - displays all the abilities that the player has
 **                     to the player
 **
 ** Parameters: None
 **
 ***********************************************************************/

void Player::display_abilities()
{
   rank_list    *tmp_rank;
   int          count = 0;
   char         tmp_chars[MAXNAMELEN + 50];
   int          i;

   send_plr("&+GCurrent abilities:&*\n\n");
   send_plr("&+CSpells&*\n");
   send_plr("&+B-------------------------------&*\n");
   tmp_rank = get_ranks();
   while (tmp_rank != NULL)
   {
      for (i=0; i<5; i++)
      {
         if (cutoff_rank[i] > tmp_rank->the_rank)
            break;
      }

      if (tmp_rank->the_type == OBJ_TYPE_SPELL)
      {
         sprintf(tmp_chars, "&+G   %-10s &+cRank: &+W%-5d &+c(%d%%)&*\n",
              tmp_rank->rank_name.str_show(), tmp_rank->the_rank,
           (int) ((((float) tmp_rank->the_exp_prob) / 
                                     ((float) cutoff_exp[i])) * 100.0));
         send_plr("%s", tmp_chars);
         count++;
      }
      tmp_rank = tmp_rank->next_rank;
   }
   if (!count)
      send_plr("           Nothing.\n");
   count = 0;

   send_plr("\n\n&+CSkills&*\n");
   send_plr("&+B-------------------------------&*\n");
   tmp_rank = get_ranks();
   while (tmp_rank != NULL)
   {
      for (i=0; i<5; i++)
      {
         if (cutoff_rank[i] > tmp_rank->the_rank)
            break;
      }

      if (tmp_rank->the_type == OBJ_TYPE_SKILL)
      {
         sprintf(tmp_chars, "&+G   %-10s &+cRank: &+W%-5d &+c(%d%%)&*\n",
              tmp_rank->rank_name.str_show(), tmp_rank->the_rank,
           (int) ((((float) tmp_rank->the_exp_prob) / 
                                     ((float) cutoff_exp[i])) * 100.0));

         send_plr("%s", tmp_chars);
         count++;
       }
      tmp_rank = tmp_rank->next_rank;
   }

   if (!count)
      send_plr("           Nothing.\n");
   send_plr("\n\n");

}


/***********************************************************************
 ** display_weapons - displays all the weapons that the player has to 
 **                   the player
 **
 ** Parameters: None
 **
 ***********************************************************************/

void Player::display_weapons()
{
   rank_list    *tmp_rank;
   int          count = 0;
   char         tmp_chars[MAXNAMELEN + 50];
   int          i;

   send_plr("&+GCurrent weapon proficiencies:&*\n\n");
   send_plr("&+B-------------------------------&*\n");
   tmp_rank = get_ranks();
   while (tmp_rank != NULL)
   {
      for (i=0; i<5; i++)
      {
         if (cutoff_rank[i] > tmp_rank->the_rank)
            break;
      }

      if (tmp_rank->the_type == 0)
      {
         sprintf(tmp_chars, "&+G   %-10s &+cRank: &+W%-5d &+c(%d%%)&*\n",
              tmp_rank->rank_name.str_show(), tmp_rank->the_rank,
           (int) ((((float) tmp_rank->the_exp_prob) / 
                                     ((float) cutoff_exp[i])) * 100.0));

         send_plr("%s", tmp_chars);
         count++;
      }
      tmp_rank = tmp_rank->next_rank;
   }
   if (!count)
      send_plr("           Nothing.\n");
   send_plr("\n\n");
}


/***********************************************************************
 ** get_weight_capacity - gets how much weight the player can carry
 **
 ** Parameters: the_num - the new capacity value
 **
 ***********************************************************************/

int Player::get_weight_capacity()
{
   return (get_strength() * the_config.weight_str_mult);
}



/***********************************************************************
 ** repeat_last_command - repeats the execution of the last command
 **
 ** Returns: 1 if successful, 0 if no input, -1 if failed
 **
 ***********************************************************************/

int Player::repeat_last_command()
{
   return input_handler.repeat_last_command((MudObject *) this);
}




/***********************************************************************
 ** get_pager_lines - get the number of lines this pager is set to view
 **                   before getting a "press enter to continue" prompt
 **
 **
 ***********************************************************************/

int Player::get_pager_lines()
{
   return pager_lines;
}


/***********************************************************************
 ** set_pager_lines - sets the pager lines value (see get_pager_lines)
 **
 ** Parameters: new_val - the new pager lines value
 **
 ***********************************************************************/

void Player::set_pager_lines(int new_val)
{
   if (new_val > 0)
      pager_lines = new_val;
   else
      pager_lines = 0;
}


/***********************************************************************
 ** get_exp - gets the experience points the player has earned
 **
 **
 ***********************************************************************/

long Player::get_exp()
{
   return experience;
}


/***********************************************************************
 ** set_exp - sets the experience points the player currently has
 **
 ** Parameters: the_num - the new experience value
 **
 ***********************************************************************/

void Player::set_exp(long the_num)
{
   if (the_num > 0)
      experience = the_num;
   else
      experience = 0;
}

/***********************************************************************
 ** get_chatlines - gets the chat lines this player can use
 **
 **
 ***********************************************************************/

char *Player::get_chatlines()
{
   return chatlines.str_show();
}


/***********************************************************************
 ** set_chatlines - sets the chat lines this player can use
 **
 ** Parameters: the_string - the string to set it to
 **
 ***********************************************************************/

void Player::set_chatlines(char *the_string)
{
   chatlines = the_string;
}


/***********************************************************************
 ** increase_exp - sets the experience points a little higher
 **
 ** Parameters: the_num - the amount to increase it
 **
 ***********************************************************************/

void Player::increase_exp(long the_num)
{
   if (the_num < 0)
      return;

   experience += the_num;
}


/***********************************************************************
 ** get_birthday - gets the time this player first logged on
 **
 **
 ***********************************************************************/

time_t Player::get_birthday()
{
   return birthday;
}


/***********************************************************************
 ** set_birthday - sets the time this player first logged on
 **
 ** Parameters: the_num - the new birday value
 **
 ***********************************************************************/

void Player::set_birthday(time_t the_num)
{
   birthday = the_num;
}


/***********************************************************************
 ** add_initial_obj - adds initial objects to the player's inventory, such
 **                   as the tutorial scrolls
 **
 ***********************************************************************/

void Player::add_initial_obj()
{
   int         i = 0;
   MudObject   *tmp_obj;
   MudObject   *new_obj;
   Object_List *tmp_dbase;
   Strings     holder;
   char        *init_obj[] = {"intro@courtland",   "navigation@courtland",
                              "objects@courtland", "communicating@courtland",
                              "shops@courtland",   "combat@courtland",
                              "next@courtland",    NULL};

   tmp_dbase = mainstruct->get_dbase();
   while (init_obj[i] != NULL)
   {
      if ((tmp_obj = mainstruct->get_object(init_obj[i])) == NULL)
      {
         holder.sprintf("Could not add mudobject %s, doesn't exist",
                                         init_obj[i]);
         mainstruct->log_error(holder.str_show(), "add_initial_obj");
         i++;
         continue;
      }

      if (!tmp_obj->is_a_moveable())
      {
         holder.sprintf("Could not add mudobject %s, not a moveable",
                                         init_obj[i]);
         mainstruct->log_error(holder.str_show(), "add_initial_obj");
         i++;
         continue;
      }

      if ((new_obj = tmp_dbase->clone_object(tmp_obj)) == NULL)
      {
         holder.sprintf("Error cloning mudobject %s", init_obj[i]);
         mainstruct->log_error(holder.str_show(), "add_initial_obj");
         i++;
         continue;
      }

      add_contained(new_obj);
      if (new_obj->is_a_moveable())
         ((Moveable *) new_obj)->set_moved();
      i++;
   }
}


/***********************************************************************
 ** change_level - changes the level of this player for a specified chain
 **
 ** Parameters: chain_name - the name of the chain we are changing the
 **                          level for
 **             lvl_num - the level number to change to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::change_level(char *chain_name, int lvl_num)
{
   level_list *tmp_level;

   tmp_level = player_levels;
   while ((tmp_level != NULL) && (STRCASECMP(tmp_level->chain.str_show(),
                                                            chain_name)))
      tmp_level = tmp_level->next_level;

   /* it doesn't exist, add it */
   if (tmp_level == NULL)
   {
      level_list *new_level;

      new_level = new_level_list();
      new_level->next_level = player_levels;
      player_levels = new_level;
      new_level->chain = chain_name;
      new_level->lvl_num = lvl_num;
      return 1;
   }

   tmp_level->lvl_num = lvl_num;
   return 1;
}



/***********************************************************************
 ** check_levels - checks the chain to see what level we are there and
 **                returns it
 **
 ** Parameters: the_chain - the chain to search for
 **
 ** Returns: current level in this chain for success, 0 for no chain found
 **
 ***********************************************************************/

int Player::check_levels(char *the_chain)
{
   level_list *tmp_level;

   tmp_level = player_levels;
   while ((tmp_level != NULL) && (STRCASECMP(tmp_level->chain.str_show(),
                                             the_chain)))
   {
      tmp_level = tmp_level->next_level;
   }

   if (tmp_level == NULL)
      return 0;
   return tmp_level->lvl_num;
}


/***********************************************************************
 ** write_levels - writes the levels 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 Player::write_levels(FILE *the_file)
{
   level_list *tmp_level;

   tmp_level = player_levels;
   if (tmp_level == NULL)
      return 0;

   fprintf(the_file, "lev\n");
   /* write all the levels to file */
   while (tmp_level != NULL)
   {
      fprintf(the_file, "^%s^\n", tmp_level->chain.str_show());
      fprintf(the_file, "%d\n", tmp_level->lvl_num);
      tmp_level = tmp_level->next_level;
   }
   fprintf(the_file, "#\n");

   return 1;
}



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

int Player::read_levels(FILE *the_file)
{
   token_record *the_token;
   Strings      holder;
   Strings      lvl_chain;
   int          lvl_num;

   the_token = get_token(the_file, '\0');
   while ((the_token->token_type != T_POUND) && (the_token->token_type > 0))
   {

      /* get the next item, it should be a '^', if not, raise error */
      if (the_token->token_type != T_CARROT)
      {
         holder.sprintf(
           "Invalid format for attribute level chain in player %s datafile",
                                                               get_name());
         mainstruct->log_error(holder.str_show(), "read_level");
         return -1;
      }

      the_token = get_token(the_file, '^');
      lvl_chain = the_token->the_string;

      /* Set lvl_num value */
      the_token = get_token(the_file, '\0');
      if (the_token->token_type != T_NUMERICAL)
      {
         holder.sprintf("Invalid format for lvl_num for player data file %s",
                                                               get_name());
         mainstruct->log_error(holder.str_show(), "load_level");
         return -1;
      }
      lvl_num = atoi(the_token->the_string);

      change_level(lvl_chain.str_show(), lvl_num);

      the_token = get_token(the_file, '\0');
   }

   return 1;
}


/***********************************************************************
 ** get_idle - gets the amount of time this player has been idle
 **
 ** Parameters: None
 **
 ** Returns:  time value (long int)
 **
 ***********************************************************************/

time_t Player::get_idle()
{
   return the_socket->get_idle();
}


/***********************************************************************
 ** show_levels - displays the levels strings of the player to another
 **
 ** Parameters: the_player - the player to display to
 **
 ** Returns: 1 for success, -1 for failure, 0 for no write
 **
 ***********************************************************************/

int Player::show_levels(Player *the_player)
{
   level_list *tmp_list;
   Level      *tmp_level;
   Level_List *level_dbase;

   level_dbase = mainstruct->get_levels();

   tmp_list = player_levels;
   while (tmp_list != NULL)
   {
      if ((tmp_level = level_dbase->get_level(tmp_list->chain.str_show(),
                                      tmp_list->lvl_num)) != NULL)
      {
         the_player->send_plr("   &+W(&+m%s &+B: &+Y%d&+W) &*%s\n",
                           tmp_list->chain.str_show(), tmp_list->lvl_num,
                                               tmp_level->get_level_str());
      }
      tmp_list = tmp_list->next_level;
   }
   return 1;
}



/***********************************************************************
 ** describe - describes the player to another player
 **
 ** Parameters: the_player - the person to send all the data to
 **
 ***********************************************************************/

void Player::describe(Player *the_player)
{
   MudObject *tmp_container;
   Strings   container_name;

   the_player->send_plr("\n&+GPlayer: \t\t&+M%s&*\n", get_name());
   tmp_container = get_contained_by();
   if (tmp_container == NULL)
      container_name = "nowhere";
   else
      container_name.sprintf("%s@%s", tmp_container->get_name(),
                                         tmp_container->get_area());

   the_player->send_plr("&+GCurrentLoc: \t\t&+M%s&*\n",
                                                 container_name.str_show());
   the_player->send_plr("&+GWield(Left): \t\t&+M%s&*\n",
            (get_wielded(Left) == NULL) ? "None" :
                                   get_wielded(Left)->get_title());

   the_player->send_plr("&+GWield(Right): \t\t&+M%s&*\n",
            (get_wielded(Right) == NULL) ? "None" :
                                   get_wielded(Right)->get_title());

   the_player->send_plr("&+GStrength: \t\t&+w%d&*\n", get_strength());
   the_player->send_plr("&+GDexterity: \t\t&+w%d&*\n", get_dexterity());
   the_player->send_plr("&+GIntel: \t\t\t&+w%d&*\n", get_intel());
   the_player->send_plr("&+GWisdom: \t\t&+w%d&*\n", get_wisdom());
   the_player->send_plr("&+GCharisma: \t\t&+w%d&*\n", get_charisma());
   the_player->send_plr("&+GHealth: \t\t&+w%d\\&+W%d&*\n",
                                          get_health(), get_maxhealth());
   the_player->send_plr("&+GExperience: \t\t&+Y%ld&*\n", get_exp());
   the_player->send_plr("&+GMagic: \t\t\t&+c%d\\&+C%d&*\n",
                                          get_magic(), get_max_magic());
   the_player->send_plr("&+GEndurance: \t\t&+g%d\\&+G%d&*\n",
                                  get_endurance(), get_max_endurance());
   the_player->send_plr("&+GChatLines: \t\t&+g%s&*\n", get_chatlines());
   the_player->send_plr("\n");
}

/***********************************************************************
 ** write_quests - writes the quests 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 Player::write_quests(FILE *the_file)
{
   quest_list *tmp_quest;

   tmp_quest = player_quests;
   if (tmp_quest == NULL)
      return 0;

   fprintf(the_file, "que\n");
   /* write all the quests to file */
   while (tmp_quest != NULL)
   {
      fprintf(the_file, "%s\n", tmp_quest->the_quest.str_show());
      tmp_quest = tmp_quest->next_quest;
   }
   fprintf(the_file, "#\n");

   return 1;
}


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

int Player::read_quests(FILE *the_file)
{
   Quest        *tmp_quest;
   token_record *the_token;
   Strings      holder;
   Object_List  *tmp_dbase;

   tmp_dbase = mainstruct->get_dbase();
   the_token = get_token(the_file, '\0');
   while ((the_token->token_type != T_POUND) && (the_token->token_type > 0))
   {
      if ((tmp_quest = tmp_dbase->get_quest_obj(the_token->the_string))
                                                                  == NULL)
      {
         holder.sprintf("Quest %s in user %s file not recognized.",
                                       the_token->the_string, get_name());
         mainstruct->log_error(holder.str_show(), "read_quests");
      }
      else
      {
         add_quest(tmp_quest->get_name());
      }
      the_token = get_token(the_file, '\0');
   }

   return 1;
}


/***********************************************************************
 ** add_quest - adds a quest to this player
 **
 ** Parameters: the_name - the name of the quest to add
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::add_quest(char *the_name)
{
   quest_list *new_quest;
   quest_list *tmp_quest;

   if (the_name == NULL)
      return -1;

   new_quest = new_quest_list();
   new_quest->the_quest = the_name;
   new_quest->next_quest = NULL;

   tmp_quest = player_quests;
   player_quests = new_quest;
   player_quests->next_quest = tmp_quest;
   return 1;
}


/***********************************************************************
 ** remove_quest - removes a quest from this player
 **
 ** Parameters: the_name - the name of the quest to add
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::remove_quest(char *the_name)
{
   quest_list *tmp_quest;
   quest_list *prev_quest = NULL;

   if (player_quests == NULL)
      return -1;

   tmp_quest = player_quests;
   while (STRCASECMP(tmp_quest->the_quest.str_show(), the_name))
   {
      prev_quest = tmp_quest;
      tmp_quest = tmp_quest->next_quest;
      if (tmp_quest == NULL)
         return -1;
   }
   if (prev_quest == NULL)
   {
      tmp_quest = player_quests;
      player_quests = player_quests->next_quest;
      delete_quest_list(tmp_quest);
   }
   else
   {
      prev_quest->next_quest = tmp_quest->next_quest;
      delete_quest_list(tmp_quest);
   }
   return 1;
}


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

int Player::find_quest(char *the_name)
{
   quest_list *tmp_quest;

   if (player_quests == NULL)
      return 0;

   tmp_quest = player_quests;
   while (STRCASECMP(tmp_quest->the_quest.str_show(), the_name))
   {
      tmp_quest = tmp_quest->next_quest;
      if (tmp_quest == NULL)
         return 0;
   }
   return 1;
}


/***********************************************************************
 ** display_quests - displays all the quests that the player has
 **                  to the player
 **
 ** Parameters: None
 **
 ***********************************************************************/

void Player::display_quests()
{
   quest_list  *tmp_quest;
   Object_List *the_dbase;
   Area_Dbase  *quest_list;
   Entity      *the_obj;
   Quest       *the_quest;
   int          count = 0;


   send_plr("&+GCompleted Quests:&*\n");
   send_plr("&+B----------------------&*\n");
   tmp_quest = player_quests;
   while (tmp_quest != NULL)
   {
      send_plr("   %s&*\n", tmp_quest->the_quest.str_show());
      count++;
      tmp_quest = tmp_quest->next_quest;
   }


   if (!count)
      send_plr("   Nothing.\n");
   send_plr("\n\n");

   count = 0;
   send_plr("&+GNot Completed:&*\n");
   send_plr("&+B-------------------&*\n");
   the_dbase = mainstruct->get_dbase();
   quest_list = the_dbase->get_area("quests");

   if (quest_list == NULL)
   {
      send_plr("Error, could not get quest list.\n");
      return;
   }

   quest_list->reset_list();
   the_obj = quest_list->get_next_obj();
   while (the_obj != NULL)
   {
      if (the_obj->get_type() != OBJ_TYPE_QUEST)
      {
         send_plr("Error, object found in quest zone not a quest.\n");
         return;
      }

      the_quest = (Quest *) the_obj;

      if (!find_quest(the_quest->get_name()))
      {
         send_plr("   %s\n", the_quest->get_name());
         count++;
      }

      the_obj = quest_list->get_next_obj();
   }

   if (!count)
      send_plr("   Nothing.\n");
   send_plr("\n\n");

   return;
}


/***********************************************************************
 ** set_pronouns - sets the pronouns based on what it finds in an inventory
 **
 ** Parameters: the_inv - the inventory to look through
 **
 ***********************************************************************/

void Player::set_pronouns(Inventory *the_inv)
{
   MudObject  *the_obj;
   Individual *ind_him = NULL;
   Individual *ind_her = NULL;
   Individual *ind_it = NULL;
   MudObject  *obj_it = NULL;


   him.truncate(0);
   her.truncate(0);
   it.truncate(0);

   the_inv->reset_current();
   the_obj = the_inv->get_next();
   while (the_obj != NULL)
   {
      if (the_obj->is_an_individual())
      {
         if (((Individual *) the_obj)->is_male())
            ind_him = ((Individual *) the_obj);
         else if (((Individual *) the_obj)->is_female())
            ind_her = ((Individual *) the_obj);
         else
             ind_it = ((Individual *) the_obj);
      }
      else
         obj_it = the_obj;

      the_obj = the_inv->get_next();
   }

   if (ind_him != NULL)
      him = ind_him->get_title();
   if (ind_her != NULL)
      her = ind_her->get_title();
   if (ind_it != NULL)
      it  = ind_it->get_title();
   if (obj_it != NULL)
      it = obj_it->get_title();
}


/***********************************************************************
 ** check_pronouns - checks for name of pronoun in input and assigns the
 **                  applicable pronoun to the string passed in
 **
 ** Parameters: the_input - the player input
 **             the_output - the string we write to
 **
 ***********************************************************************/

void Player::check_pronouns(char *the_input, Strings *the_output)
{
   if ((the_input == NULL) || (the_output == NULL))
      return;

   if (!STRCASECMP(the_input, "him"))
      the_output->str_copy(him.str_show());
   else if (!STRCASECMP(the_input, "her"))
      the_output->str_copy(her.str_show());
   else if (!STRCASECMP(the_input, "it"))
      the_output->str_copy(it.str_show());
   else
      the_output->str_copy(the_input);
   return;
}


/***********************************************************************
 ** create_mail - creates the mail object and loads header mode
 **
 ** Parameters: None
 **
 ***********************************************************************/

void Player::create_mail()
{
   the_mail = new_Mailer(get_title(), Header);

   if (the_mail == NULL)
      printf("not created.\n");
}


/***********************************************************************
 ** load_mail - loads the mail for this player
 **
 ** Parameters: the_mode - the mode to load the mail to
 **
 ***********************************************************************/

int Player::load_mail(load_type the_mode)
{
   if (the_mail == NULL)
      return -1;

   return the_mail->load_mail(the_mode);
}


/***********************************************************************
 ** get_mailer - gets a pointer to the mailer for this player
 **
 ***********************************************************************/

Mailer *Player::get_mailer(void)
{
   return the_mail;
}


/***********************************************************************
 ** show_pronouns - displays the pronouns to a player
 **
 ***********************************************************************/

void Player::show_pronouns(Player *the_player)
{
   the_player->send_plr("&+WCurrent loaded pronouns&*\n");
   the_player->send_plr("&+B-------------------------&*\n");
   the_player->send_plr("\n&+GHim: &*%s\n", him.str_show());
   the_player->send_plr("\n&+GHer: &*%s\n", her.str_show());
   the_player->send_plr("\n&+GIt: &*%s\n\n", it.str_show());
}


/***********************************************************************
 ** push_brief - pushes a new brief onto the stack
 **
 ** Parameters: brief_name - a name used to keep track of this brief
 **             the_brief - the brief string to display
 **
 ***********************************************************************/

void Player::push_brief(char *brief_name, char *the_brief)
{
   brief_stack *new_brief;

   new_brief = new_brief_stack();
   new_brief->next_brief = cur_brief;
   new_brief->brief_name = brief_name;
   new_brief->the_brief = the_brief;

   cur_brief = new_brief;
}


/***********************************************************************
 ** remove_brief - removes a brief from inside the stack
 **
 ** Parameters: brief_name - a name used to find the brief to remove
 **
 ** Returns: 1 for found and deleted, 0 for not found
 **
 ***********************************************************************/

int Player::remove_brief(char *brief_name)
{
   brief_stack *tmp_brief;
   brief_stack *del_brief = NULL;

   tmp_brief = cur_brief;
   while ((tmp_brief != NULL) &&
          (STRCASECMP(tmp_brief->brief_name.str_show(), brief_name)))
   {
      del_brief = tmp_brief;
      tmp_brief = tmp_brief->next_brief;
   }

   if (tmp_brief == NULL)
      return 0;

   if (del_brief == NULL)
   {
      cur_brief = cur_brief->next_brief;
      delete_brief_stack(tmp_brief);
   }
   else
   {
      del_brief->next_brief = tmp_brief->next_brief;
      delete_brief_stack(tmp_brief);
   }
   return 1;
}


/***********************************************************************
 ** get_brief - gets the top brief on the stack
 **
 ***********************************************************************/

char *Player::get_brief()
{
   if (cur_brief == NULL)
   {
      return NULL;
   }

   return cur_brief->the_brief.str_show();
}


/***********************************************************************
 ** get_brief - gets the top brief on the stack
 **
 ***********************************************************************/

char *Player::get_brief(char *brief_name)
{
   brief_stack *tmp_brief;

   tmp_brief = cur_brief;
   while ((tmp_brief != NULL) &&
          (STRCASECMP(tmp_brief->brief_name.str_show(), brief_name)))
   {
      tmp_brief = tmp_brief->next_brief;
   }
   if (tmp_brief == NULL)
      return NULL;

   return tmp_brief->the_brief.str_show();
}


/***********************************************************************
 ** push_prompt - pushes a new prompt onto the stack
 **
 ** Parameters: prompt_name - a name used to keep track of this prompt
 **             the_prompt - the prompt string to display
 **
 ***********************************************************************/

void Player::push_prompt(char *prompt_name, char *the_prompt)
{
   prompt_stack *new_prompt;

   new_prompt = new_prompt_stack();
   new_prompt->next_prompt = prompt;
   new_prompt->prompt_name = prompt_name;
   new_prompt->the_prompt = the_prompt;

   if (new_prompt->the_prompt.str_len() > MAXPROMPTLEN)
      new_prompt->the_prompt.truncate(MAXPROMPTLEN);

   prompt = new_prompt;
   input_handler.swap_prompt(&(new_prompt->the_prompt));
}


/***********************************************************************
 ** remove_prompt - removes a prompt from inside the stack
 **
 ** Parameters: prompt_name - a name used to find the brief to remove
 **
 ** Returns: 1 for found and deleted, 0 for not found
 **
 ***********************************************************************/

int Player::remove_prompt(char *prompt_name)
{
   prompt_stack *tmp_prompt;
   prompt_stack *del_prompt = NULL;

   tmp_prompt = prompt;
   while ((tmp_prompt != NULL) &&
          (STRCASECMP(tmp_prompt->prompt_name.str_show(), prompt_name)))
   {
      del_prompt = tmp_prompt;
      tmp_prompt = tmp_prompt->next_prompt;
   }

   if (tmp_prompt == NULL)
      return 0;

   if ((tmp_prompt == prompt) && (prompt->next_prompt == NULL))
   {
      mainstruct->log_error("Attempt to remove 'main' prompt for player.",
                                              "remove_prompt");
      return -1;
   }

   if (del_prompt == NULL)
   {
      prompt = prompt->next_prompt;
      input_handler.swap_prompt(&(prompt->the_prompt));
      delete_prompt_stack(tmp_prompt);
   }
   else
   {
      del_prompt->next_prompt = tmp_prompt->next_prompt;
      delete_prompt_stack(tmp_prompt);
   }
   return 1;
}


/***********************************************************************
 ** get_prompt - gets the top prompt on the stack
 **
 ***********************************************************************/

char *Player::get_prompt()
{
   if (prompt == NULL)
      return NULL;

   return prompt->the_prompt.str_show();
}


/***********************************************************************
 ** get_prompt - gets the top prompt on the stack
 **
 ***********************************************************************/

char *Player::get_prompt(char *prompt_name)
{
   prompt_stack *tmp_prompt;

   tmp_prompt = prompt;
   while ((tmp_prompt != NULL) &&
          (STRCASECMP(tmp_prompt->prompt_name.str_show(), prompt_name)))
   {
      tmp_prompt = tmp_prompt->next_prompt;
   }
   if (tmp_prompt == NULL)
      return NULL;

   return tmp_prompt->the_prompt.str_show();
}

/***********************************************************************
 ** set_prompt - sets the prompt for the player
 **
 ** Parameters: the_name - the prompt to set it to
 **
 ** Returns:  1 for success
 **          -1 for failure: no string sent in
 **
 ***********************************************************************/

int Player::set_prompt(char *the_prompt)
{
   if ((the_prompt == NULL) || (prompt == NULL))
      return -1;

   prompt->the_prompt = the_prompt;

   if (prompt->the_prompt.str_len() > MAXPROMPTLEN)
      prompt->the_prompt.truncate(MAXPROMPTLEN);

   return 1;
}



/***********************************************************************
 ** is_busy - is the player busy doing something
 **
 ** Parameters: None
 **
 ** Returns:   1 if player is busy
 **            0 if player is not busy
 **
 ***********************************************************************/

int Player::is_busy()
{
   return game_flags.get_flag(GAMEFLAG_BUSY);
}


/***********************************************************************
 ** increase_rank_exp - increases the experience in that rank
 **
 ** Parameters: difficulty - the difficulty of this rank perform or cast
 **             the_object - the ability or weapon to increase
 **             divide_by - divide by one or two (failure or success)
 **
 ***********************************************************************/

void Player::increase_rank_exp(int difficulty, Entity *the_object,
                                                             int divide_by)
{
   int       the_exp;
   int       the_rank;
   int       new_exp;
   int       no_change = 0;
   int       the_type;
   float     decr_amt;
   long      global_exp;
   Strings   rank_name;

   if ((the_object->get_type() == OBJ_TYPE_SPELL) ||
       (the_object->get_type() == OBJ_TYPE_SKILL))
   {
      rank_name = the_object->get_name();
      the_type = the_object->get_type();
   }
   else if (the_object->get_type() == OBJ_TYPE_WEAPON)
   {
      the_type = 0;
      rank_name = ((Weapon *) the_object)->get_weapon_class();
   }

   if (rank_name.str_show() == NULL)
      return;       

   if (!find_rank(rank_name.str_show()))
   {
      add_rank(rank_name.str_show(), the_type, 0, 0);
   }

   the_exp = get_rank_exp_prob(rank_name.str_show());
   the_rank = get_rank_number(rank_name.str_show());

   /* first we calculate the decrease amount based on how much they
      have learned already, per global experience */
   decr_amt = ((the_config.max_global_exp - get_exp()) /
                                      ((float) the_config.max_global_exp));

   /* now we get the max experience they will get for this one, based
      on the difficulty divided by 1 if they succeeded, a 2 if failed */
   new_exp = (int) (difficulty / divide_by);

   /* now we decrease the experience gained based in the decrease
      amount calculated earlier */
   new_exp = (int) (((float) new_exp + 1) * decr_amt);

   /* now set the values */
   the_exp += new_exp;

   global_exp = get_exp();
   set_exp(global_exp + ((long) new_exp));

   /* check to see if we increase the rank */
   if ((the_rank <= cutoff_rank[0]) && (the_exp > cutoff_exp[0]))
   {
      the_rank++;
      the_exp -= cutoff_exp[0];
   }
   else if ((the_rank <= cutoff_rank[1]) && (the_exp > cutoff_exp[1]))
   {
      the_rank++;
      the_exp -= cutoff_exp[1];
   }
   else if ((the_rank <= cutoff_rank[2]) && (the_exp > cutoff_exp[2]))
   {
      the_rank++;
      the_exp -= cutoff_exp[2];
   }
   else if ((the_rank <= cutoff_rank[3]) && (the_exp > cutoff_exp[3]))
   {
      the_rank++;
      the_exp -= cutoff_exp[3];
   }
   else if ((the_rank > cutoff_rank[4]) && (the_exp > cutoff_exp[4]))
   {
      the_rank++;
      the_exp -= cutoff_exp[4];
   }
   else
      no_change = 1;

   if (!no_change)
      set_rank_number(rank_name.str_show(), the_rank);
   set_rank_exp_prob(rank_name.str_show(), the_exp);
}


/***********************************************************************
 ** get_mem_size - gets how much memory this special is taking up
 **
 ** Returns: mem size in bytes
 **
 ***********************************************************************/

int Player::get_mem_size()
{
   int size = 0;

   size = sizeof(this);
   size += get_mem_size_dynamic();
   return size;
}

/***********************************************************************
 ** get_mem_size_dynamic - gets how much memory is taken up by pointers
 **                        pointing to other objects, not including the
 **                        sizeof(this)
 **
 ** Returns: mem size in bytes
 **
 ***********************************************************************/

int Player::get_mem_size_dynamic()
{
   int  size = 0;

   size += get_mem_size_ind();
   size += get_mem_size_mudobj();
   size += get_mem_size_entity();

   return size;
}


/***********************************************************************
 ** get_misc_string - returns the miscellaneous string for the player
 **
 ** Returns: misc_string
 **
 ***********************************************************************/

Strings *Player::get_misc_string( void )
{
   return &misc_string;
}


/***********************************************************************
 ** reset_player: resets all of the player's variables to default
 **
 ***********************************************************************/
void Player::reset_player( void )
{
   quest_list      *tmp_quest;
   brief_stack     *tmp_brief;
   prompt_stack    *tmp_prompt;
   level_list      *tmp_levlist;

   reset_individual( );

   get_admflags( )->clr_all( admflagnames );
   get_comflags( )->clr_all( comflagnames );
   set_desc( "You see an ordinary player.\n" );
   set_capacity( 300 );
   set_max_endurance(the_config.default_maxendur);
   set_endurance(the_config.default_maxendur);
   set_max_magic(the_config.default_maxmagic);
   set_magic(the_config.default_maxmagic);
   set_wimpy(the_config.default_wimpy);
   pager_lines = the_config.default_pager_lines;
   experience = 0;

   /* releases all objects the player is carrying, placing them nowhere */
   release_all_inv();


   delete_ranks();

   /* deletes all briefs */
   while (cur_brief != NULL)
   {
      tmp_brief = cur_brief->next_brief;
      delete_brief_stack(cur_brief);
      cur_brief = tmp_brief;
   }

   /* deletes all prompts */
   while (prompt != NULL)
   {
      tmp_prompt = prompt->next_prompt;
      delete_prompt_stack(prompt);
      prompt = tmp_prompt;
   }
   push_prompt("main", "&+bAIME&+W>&* ");;

   /* deletes all quests from the player */
   while (player_quests != NULL)
   {
      tmp_quest = player_quests->next_quest;
      delete_quest_list(player_quests);
      player_quests = tmp_quest;
   }

   /* delete all levels from the player */
   while( player_levels != NULL )
   {
      tmp_levlist = player_levels->next_level;
      delete_level_list( player_levels );
      player_levels = tmp_levlist;
   }

   /* delete the mail from the character */
   if( the_mail != NULL )
   {
      delete_Mailer( the_mail );
   }
}

/***********************************************************************
 ** load_talent_list - loads the talent list in this player from the
 **                    object_list dbase
 **
 ** Parameters: None
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::load_talent_list()
{
   Area_Dbase  *talent_area;
   Object_List *obj_dbase;
   Entity      *tmp_entity;
   Talent      *tmp_talent;
   Talent      *new_talent;

   obj_dbase = mainstruct->get_dbase();
   if ((talent_area = obj_dbase->get_area("talents")) == NULL)
   {
      mainstruct->log_error("Area 'talents' should be in object_list but is not.",
                                                             "load_talent_list");
      send_plr("Error, could not read talents.\n");
      return -1;
   }

   if (talent_list != NULL)
      delete talent_list;

   talent_list = new Area_Dbase("talents_player");

   talent_area->reset_list();
   tmp_entity = talent_area->get_next_obj();
   while (tmp_entity != NULL)
   {
      if (tmp_entity->get_type() != OBJ_TYPE_TALENT)
         return -1;

      tmp_talent = (Talent *) tmp_entity;

      new_talent = new Talent(tmp_talent->get_name());
      new_talent->copy_object(tmp_talent);

      talent_list->add_areaobject(new_talent);
      tmp_entity = talent_area->get_next_obj();
   }
   return 1;
}


/***********************************************************************
 ** display_talents - displays the talents this player can choose from
 **
 ** Parameters: None
 **
 ** Returns: num displayed for success, -1 for failure
 **
 ***********************************************************************/

int Player::display_talents()
{
   Entity     *tmp_obj;
   Talent     *tmp_talent;
   Strings    talent_name;
   Strings    tmp_line;
   Strings    holder;
   int        num_in_line = 0;
   int        count = 0;
   Strings    allow_talent;
   int        show_all = 0;
   Race       *plr_race;

   if (talent_list == NULL)
   {
      mainstruct->log_error(
          "Area 'talents' should be in Player object but is not.",
                                                             "display_talent");
      send_plr("Error, could not read talents.\n");
      return -1;
   }

   talent_list->reset_list();

   send_plr("\n\nYou have &+W%d&* talent funds to spend.\n",
                                                           get_talent_funds());
   send_plr("&+WAvailable Talents:&*\n");
   send_plr("&+B-----------------------------------------------------------&*\n");
   send_plr("&+B| &+GName                &+B| &+GCost &+B| &+GName                &+B| &+GCost &+B|\n");
   send_plr("&+B-----------------------------------------------------------&*\n");

   if ((plr_race = mainstruct->get_race(get_race())) == NULL)
   {
     holder.sprintf("Could not get player race '%s'", get_race());
     mainstruct->log_error(holder.str_show(), "display_talents");
     return -1;
   }

   allow_talent = plr_race->get_allow_talent();
   if (!STRCASECMP(allow_talent.str_show(), "all"))
     show_all = 1;

   while ((tmp_obj = talent_list->get_next_obj()) != NULL)
   {
      if (tmp_obj->get_type() != OBJ_TYPE_TALENT)
      {
         holder.sprintf("Object '%s' found in Player talents area not a talent.",
                                          tmp_obj->get_name());
         mainstruct->log_error(holder.str_show(), "display_talents");
         return -1;
      }
      tmp_talent = (Talent *) tmp_obj;

      if (show_all || (allow_talent.find_in_str(tmp_talent->get_name())))
      {

      talent_name = tmp_talent->get_name();
      if (talent_name.str_len() > 19)
        talent_name.truncate(19);
      talent_name.upper(0);
      tmp_line.sprintf("&+B| &+g%-19s&* &+B| %3d  ", talent_name.str_show(),
                                                     tmp_talent->get_cost());
      holder.str_cat(tmp_line.str_show());
      num_in_line++;
      if (num_in_line == 2)
      {
        send_plr("&+g%s&+B|&*\n", holder.str_show());
        holder.truncate(0);
        num_in_line = 0;
      }
      count++;
      }
   }
   if (num_in_line > 0)
   {
      send_plr("&+g%s&+B|                     |      |&*\n", holder.str_show());
   }
   send_plr("&+B-----------------------------------------------------------&*\n");
   send_plr("\n");
   send_plr("Type '? <talent>' to see a description of the talent.\n");

   return count;
}

/***********************************************************************
 ** get_talent_list - gets the area that holds those talents available
 **                   to this player
 **
 ***********************************************************************/

Area_Dbase *Player::get_talent_list()
{
   return talent_list;
}

/***********************************************************************
 ** delete_talent_list - deletes the talent list area object
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::delete_talent_list()
{
   if (talent_list == NULL)
      return -1;

   delete talent_list;
   talent_list = NULL;
   return 1;
}


/***********************************************************************
 ** attack - attacks another individual by using the weapon
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Player::attack(Individual *target)
{
  if ((get_target() == NULL) || (get_target()->get_loc() != get_loc()))
  {
    stop_fighting();
    return 0;
  }

  return use_weapon(target);
}

#endif



Generated by  Doxygen 1.6.0   Back to index