dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/*  -*- LPC -*-  */
/*
 * $Locker:  $
 * $Id: player.c,v 1.184 2003/07/15 07:13:27 pinkfish Exp $
 */
/**
 * The main player object.  Does all the player related stuff.
 * @author Pinkfish
 * @started December 1991
 */

#include <config.h>
#include <board.h>
#include <bounty.h>
#ifndef __DISTRIBUTION_LIB__
#include <deity.h>
#endif
#include <drinks.h>
#include <library.h>
#include <living.h>
#include <login.h>
#include <login_handler.h>
#include <log.h>
#include <quest_handler.h>
#include <command.h>
#include <mail.h>
#include <player.h>
#include <skills.h>
#include <top_ten_tables.h>
#include <tune.h>
#include <weather.h>
#include <refresh.h>
#include <nroff.h>
#include <db.h>
#include <error_handler.h>
#include <player_handler.h>
#include <playerinfo.h>
#include <group_handler.h>

// Right now if you move this below the clubs include it will break due to
// mudos class lossage :(
// This class contains all the global, nosaving variables to reduce our
// variable usage.
class player_info {
   int hb_num;
   int level;
   int level_time;
   int save_inhibit;
   int update_tmps_call_out;
   int last_save;
   object snoopee;
   mapping titles;
}
#include <clubs.h>
inherit "/global/line_ed";
inherit "/global/events";
inherit "/global/log";
inherit "/global/spells";
inherit "/global/more_string";
inherit "/global/finger";
inherit "/global/pweath";
inherit "/std/living/living";
inherit "/global/psoul";
inherit "/global/guild-race";
inherit "/global/more_file";
inherit "/global/path";
inherit "/global/start_position";
inherit "/global/family";

#define MIN_TIME_TO_SAVE 1800
#define FORGOT_CO_ORD_TIME (840553267+(8*60*60))
#define LEVEL_CACHE 60

#define ITEM_TRACKER ("/obj/handlers/item_tracker")

/* 
 * Discworld stuff
 */
private nosave class player_info _pinfo;

private int time_on;
private int max_deaths;
private int monitor;
private int _refresh_time;
private int start_time;
private int creator;
private int deaths;
private int last_log_on;
private int no_logins;
private int activity_counter;
private int _flags;
private string cap_name;
private string last_on_from;
private nosave string my_file_name;

void start_player();
void public_commands();
int save();
void set_desc(string str);
void do_load_auto();
void set_name(string str);
int check_dark(int light);
void continue_start_player();
int restart_heart_beat();
int brief_verbose(string,
                  string);
int quit_alt(int verbose);
int review();
int toggle_wimpy(string);
int do_refresh(string);
int do_cap(string);
protected void set_invis(int level);
void set_player_killer(int);
int query_player_killer();

void finished_error_check( object player, string my_name, int status, 
    mixed data );
void check_error_count();
void check_approve_list();

void create()
{
   if (query_name()) {
      return;
   }

   living::create();
   events::create();
   psoul::create();
   line_ed::create();
   more_string::create();
   start_position::create();
   add_property("determinate", "");
   spells::create();
   time_on = time();
   start_time = time();
   seteuid("PLAYER");
   Str = 13;
   Dex = 13;
   Int = 13;
   Con = 13;
   Wis = 13;
   set_max_sp(50);
   set_sp(50);
   wimpy = 20;
   max_deaths = 7;
   set_desc(0);
   add_ac("bing", "blunt", 15);
   add_ac("bing2", "sharp", 15);
   add_ac("bing3", "pierce", 15);
   add_property("player", 1);
   set_cols(79);
   set_rows(24);
   last_log_on = time();
   race_ob = RACE_STD;

   sscanf(file_name(this_object()), "%s#", my_file_name);

   //add_language("common");

   _pinfo = new (class player_info, titles: ([ ]), save_inhibit:1);
}

/**
 * @ignore yes
 */
void dest_me()
{
   if ((query_name() != "object") && objectp(this_player()) &&
       (this_player() != this_object()) &&
       (file_name(this_player()) != "/obj/shut") &&
       (explode(file_name(this_player()), "#")[0] != "/secure/login") &&
       (explode(file_name(this_player()), "#")[0] != "/secure/nlogin")) {
      user_event(this_object(), "inform",
                 (string) this_player()->query_name() +
                 " dests " + query_name(), "dest");
      tell_object(this_object(), "You were destructed by " +
                  capitalize((string) this_player()->query_name()) + ".\n");
   }
   
   if(file_size(PLAYER_HANDLER->query_player_file_name(query_name())+
                ".o.gz") > 0 &&
      PLAYER_HANDLER->query_player_disk_file_name(query_name()) &&
      PLAYER_HANDLER->query_player_file_name(query_name()) !=
      PLAYER_HANDLER->query_player_disk_file_name(query_name())) {
     unguarded((:rename,
                PLAYER_HANDLER->query_player_file_name(query_name())+".o.gz",
                PLAYER_HANDLER->query_player_disk_file_name(query_name())+
                ".o.gz" :));
   }
   ::dest_me();
}                               /* dest_me() */

/**
 * This method stops the player from being able to save.  This is done while
 * the inventory is regenerating to stop problems with inventory loss due
 * to logging off before it has finished.
 * @see allow_save()
 * @see query_save_inhibit()
 */
void disallow_save()
{
   _pinfo->save_inhibit = 1;
}

/**
 * This method allows the player to save again after they have been
 * disallowed.
 * @see disallow_save()
 * @see query_save_inhibit()
 */
void allow_save()
{
   _pinfo->save_inhibit = 0;
}

/**
 * This method returns the value of the disallowing save variable.  If this
 * is a non-zero value then the player must not be saved.
 * @see allow_save()
 * @see disallow_save()
 */
int query_save_inhibit()
{
   return _pinfo->save_inhibit;
}

/**
 * This is the date on which the character was started.  The very first
 * time the player ever logged on.
 * @return the time at which the player first logged on
 */
int query_start_time()
{
   return start_time;
}

/**
 * This method returns the current capitalised name of the player.
 * @return the current capitalised name
 * @see set_cap_name()
 */
nomask string query_cap_name()
{
   return cap_name;
}

/**
 * This method is called from within the login code to start up the
 * new player, set their name and move them into the correct
 * location on the mud.
 * @param bong the name of the player
 * @param new_flag are the a new player?
 * @param c_name their capital name
 * @param ident the ident from the authorisation code
 * @param go_invis go invsible on login
 */
void move_player_to_start(string bong,
                          int new_flag,
                          string c_name,
                          string ident,
                          int go_invis) {
  string lang;
  
   /* Only /secure/login can do this. */
   if (file_name(previous_object())[0..12] != "/secure/login" &&
       file_name(previous_object())[0..13] != "/secure/nlogin") {
      write("You don't have clearance to do that.\n");
      return;
   }
   seteuid("Root");
   set_name(bong);

   if (!new_flag) {
      unguarded((: restore_object,
                   PLAYER_HANDLER->query_player_file_name(query_name()), 1 :));
      if (go_invis) {
        switch(go_invis) {
        case -1:
          set_invis(0);
          break;
        case 2:
          if (this_object()->query_lord()) {
            set_invis(2);
            break;
          }
        case 1:
          set_invis(1);
        }
      }
   }
   disallow_save();             /* don't allow saves until the autoload has started */
   add_property("player", 1);
   cap_name = c_name;
   set_short(cap_name);
   add_property("determinate", "");
   no_logins++;
   if (!query_cols()) {
      set_cols(79);
   }
   remove_property("new player");

   if (this_player()->query_creator()) {
      seteuid(query_name());
      if (file_size("/w/" + query_name() + "/cmds") == -2)
         AddSearchPath(({ "/w/" + query_name() + "/cmds" }));
      AddSearchPath(({ DIR_PLAYER_CMDS, DIR_SECURE_PLAYER_CMDS,
                       DIR_CREATOR_CMDS, DIR_SECURE_CREATOR_CMDS,
                       DIR_PLAYTESTER_CMDS }));
   } else {
      seteuid("PLAYER");
      AddSearchPath(({ DIR_PLAYER_CMDS, DIR_SECURE_PLAYER_CMDS }));
   }
   if (!last_on_from) {
      printf("You have never logged in before.\n");
   } else {
      printf("You last logged in from %s and are currently "
             "logged in from %s (%s).\n", last_on_from,
             query_ip_name(this_object()), query_ip_number(this_object()));
   }
   last_on_from = query_ip_name(this_object()) + " (" +
      query_ip_number(this_object()) + ")";

   //
   // What the heck does this do?
   //
/*
   if ( time_on < -500 * 24 * 60 * 60 ) {
      time_on += time();
   }
 */
   if (time_on > 0) {
      time_on = 0;
   }
   time_on += time();
   if (new_flag) {
      add_property("new player!", 1);
   }
   LOGIN_HANDLER->player_logon(bong, query_property("guest"),
                               (query_ip_name()? query_ip_name() :
                                query_ip_number()));

   if(query_property("guest")) {
     this_player()->set_nationality(DEFAULT_NATIONALITY);
     this_player()->
       set_nationality_region(this_player()->find_region(DEFAULT_NATIONALITY,
                                                         DEFAULT_REGION));
     lang = DEFAULT_NATIONALITY->query_language();
     
     // Setup the default language correctly.
     this_player()->add_language(lang);
     this_player()->set_default_language(lang);
     this_player()->set_language(lang);
   }
   write(LOGIN_HANDLER->get_message("/doc/NEWS"));

   call_out((: continue_start_player :), 0);
   // remove the previously cached entry.
   PLAYER_HANDLER->remove_cache_entry(query_name());
}                               /*  move_player_to_start() */

/** @ignore yes */
protected void move_to_start_pos()
{
   ::move_to_start_pos();
   if (query_verbose("look"))
      command("look");
   else
      command("glance");

   if (!finger_set()) {
      write
         ("%^BOLD%^Please set your finger information with 'chfn'.%^RESET%^\n");
      //command("chfn");
   }

   if(no_logins == 1 && !query_property("guest")) {
     write("\n%^BOLD%^" +
           LOGIN_HANDLER->get_message("/doc/login/NEW_USER_START") +
           "%^RESET%^\n");
   }
   
   no_time_left();
   START_PLAYER->logged_on_times(no_logins);

   // Try resolving hostname one last time.
   if(query_ip_number(this_object()) == query_ip_name(this_object()))
     resolve(query_ip_number(this_object()), "");

}                               /* move_to_start_pos() */

/**
 * @ignore yes
 *
 * This function tracks a players activity to determine whether they're still
 * active or not. Ceres
 */
protected void update_activity(int logon)
{
   int time_on;

   // Lower their activity score if they haven't been on for more than a week.
   if (last_log_on > 0) {
      time_on = last_command - last_log_on;
      if (time_on > 0)
         activity_counter -= (time_on / (3600 * 24 * 7)) * 10;
   }

   if (activity_counter <= -55) {
      activity_counter = -55;
   }
   // when they logon give them a couple more activity points.
   if (logon) {
      activity_counter += 3;
   } else {                     // when they leave give them some more for each hour they were on.
      activity_counter += 2 * ((time() - last_log_on) / 3600);
   }

   // Set minima and maxima to the counter.
   if (activity_counter >= 0)
      activity_counter = 0;
}

/**
 * Return the current value of this players activity_counter
 * (used for debugging)
 */
int query_activity_counter()
{
   return activity_counter;
}

/**
 * THis method prints something if there are bug replies to see.
 */
private void display_bug_replies(int type, class error_replies* replies) {
   if (type == DB_SUCCESS) {
      if (sizeof(replies) > 0) {
         tell_object(this_object(), "\n\nYou have %^YELLOW%^" +
            sizeof(replies) + " NEW%^RESET%^ bug repl" +
            (sizeof(replies) > 1?"ies ":"y ") +
            "(read with 'bug replies').\n\n");
      }
   }
}

private void check_mccp() {
   if(!compressedp(this_object())) {
     write("\n%^BOLD%^%^RED%^You are logged in uncompressed!\n");
     write("Use of an MCCP capable mud client will reduce your load on "
           "the " + mud_name() + " system.%^RESET%^\n\n");
   }
}

/**
 * @ignore yes
 */
void continue_start_player()
{
   string title;
   mapping news_rc;
   mixed *stuff;
   object book;

   // Set the cre flag for setting up commands etc.
   if (this_object()->query_lord()) {
      creator = 1;
   }

   start_player();
   no_time_left();
   /* Remove passed out property, unless the player is
    * in a trance, e.g. when contemplating. */
   if (query_property(PASSED_OUT) && !query_property(TRANCE)) {
      call_out((: remove_property :), 10 + random(30), PASSED_OUT);
   }
   remove_property(UNKNOWN_MOVE);
   remove_property(RUNNING_MOVE);
   init_after_save();           /* for effects */
   printf("%s", fix_string(MAILER->new_mail(query_name())));
   news_rc = BOARD_HAND->query_newsrc(query_name());
   if (!news_rc) {
      news_rc = ([ ]);
   }
   stuff = BOARD_HAND->get_subjects("announcements");
   if (sizeof(stuff)) {
      if (stuff[<1][B_TIME] > news_rc["announcements"]) {
         write("\nThere are %^YELLOW%^NEW%^RESET%^ announcements.  ");
         write("You can read them with \"news\".\n\n");
         //"/cmds/player/news"->do_list();
         //printf("You can read then with \"news\".\n\n");
      }
   }

   call_out((: check_mccp :), 4);
       
   if (query_property("dead")) {
      (clone_object(DEATH_SHADOW))->setup_shadow(this_object());
      // Give them a dead book too.
      book = clone_object(DEAD_BOOK);
      book->move(this_object());
   }
   if (query_property("noregen")) {
      DEATH->person_died(query_name());
   }
   exec_alias("login", "");
   update_activity(1);
   last_log_on = time();
   title = LIBRARY->query_title(query_name());
   if (stringp(title)) {
      _pinfo->titles += ([ "quest" : title ]);
   }
   if (my_file_name != "/global/player") {
      check_error_count();
      if(my_file_name != "/global/playtester") {
        check_approve_list();
      }
   }
   if (query_property("new player!")) {
     // Clear the alt info.
     PLAYERINFO_HANDLER->player_created(query_name());
      user_event(this_object(), "inform",
                 capitalize(query_name()) +
                 " arrives on " + mud_name() + " for the first time!", "new-player");
      remove_property("new player!");
      set_last_pos(CONFIG_NEWBIE_START_LOCATION);
      START_PLAYER->start_player(this_object());
   }
   //add_language("common");
   check_family_name();
   call_out((: move_to_start_pos :), 0);
   call_out((: set_heart_beat(1) :), 1);
   // Tell them about new error replies.
   ERROR_HANDLER->do_error_replies(query_name(), 1, (: display_bug_replies :));

}                               /* continue_start_player() */

/**
 * @ignore yes
 */
void check_error_count() {
   string my_name; 
    
   my_name = query_name(); 

   DB_HANDLER->make_sql_request( "errors", "atuin", "", 
      "SELECT COUNT(Id) AS idc FROM errors WHERE Directory = '/w/" + 
      my_name + "' AND Status = 'OPEN'", 
       (: finished_error_check, this_object(), my_name :) ); 
} /* check_error_count() */

/**
 * @ignore yes
 */
void finished_error_check( object player, string my_name, int status, 
    mixed data ) {

   int num;
   int ret;

   if ( file_size("/w/" + my_name + "/" + PLAYER_ERROR_LOG) > 0 ) {
       num = file_length("/w/" + my_name + "/" + PLAYER_ERROR_LOG);
       tell_object( player, "%^YELLOW%^You have %^RED%^" + num + 
           "%^YELLOW%^ director" + (num == 1 ? "y" : "ies") + 
           " with %^RED%^ERRORS%^YELLOW%^ in /w/" + my_name + "/" + 
           PLAYER_ERROR_LOG + ".%^RESET%^\n");
   }

   if ( status == DB_SUCCESS && sizeof( data ) > 0 ) { 
      if ( ( ret = data[0]["idc"] ) > 0 ) {
         tell_object( player, "%^YELLOW%^You have %^RED%^" + ret + 
            " ERROR" +  (ret == 1 ? "" : "S") + "%^YELLOW%^ in /w/" + 
            my_name +  ".%^RESET%^\n");
      }
   }
} /* finished_error_check() */ 

/** @ignore yes */
void check_approve_list() {
  string str;
  mapping assignments;
  int count;
  
  assignments = master()->query_directory_assignments();
  foreach(str in keys(assignments)) {
    if(member_array(this_object()->query_name(), assignments[str]) != -1 &&
       file_size(str + "/to_approve")) {
      count = sizeof(get_dir(str + "/to_approve/*")) - 2;
      if(count > 0)
        tell_object(this_object(), "%^YELLOW%^" + str + " has %^RED%^" +
                    count + "%^YELLOW%^ item" + (count > 1 ? "s" : "") +
                    " awaiting approval.%^RESET%^\n");
    }
  }
}

/**
 * @ignore yes
 */
void start_player()
{
   if (this_object()->query_creator() && my_file_name != "/global/player") {
      this_player()->all_commands();
      this_player()->app_commands();
      this_player()->wiz_commands();
   }
   call_out((: do_load_auto :), 1);
   reset_get();
   enable_commands();
   public_commands();
   command_commands();
   parser_commands();
   force_commands();
   race_guild_commands();
   soul_commands();
   event_commands();
   finger_commands();
   communicate_commands();
   living_commands();
   logging_commands();
   editor_commands();
   if (this_player()->query_creator()) {
      set_living_name(query_name());
   }
   set_no_check(1);
   set_con(Con);
   set_dex(Dex);
   set_int(Int);
   set_str(Str);
   set_wis(Wis);
   reset_all();
   set_current_path(query_home_dir());
   if (wimpy > 100) {
      wimpy = 25;
   }
   if (contmp || dextmp || inttmp || strtmp || wistmp) {
      _pinfo->update_tmps_call_out = call_out((: update_tmps :), 900);
   }
}

/* added chrisy 6 june 93 to stop net-dead players getting killed */
/**
 * @ignore yes
 * This is an over ride of something in /std/living
 */
int adjust_hp(int number,
              object attacker,
              object weapon,
              string attack)
{
   if (!interactive(this_object()))
      return query_hp();
   return::adjust_hp(number, attacker, weapon, attack);
}                               /* adjust_hp() */

/**
 * Starts the autoloading process.  This is called just after a player
 * logs in to start up the auto loading process.
 */
void do_load_auto()
{
   load_auto_load_alt(query_auto_load_string(), this_object(), this_object(),
                      (: tell_object(this_object(),
                                     "\n%^CYAN%^Inventory regeneration complete.%^RESET%^\n") :));
   set_auto_load_string(0);
   allow_save();
}                               /* do_load_auto() */

/**
 * @ignore yes 
 */
void public_commands()
{
   add_command("restart", this_object(), "", (: restart_heart_beat() :));
   add_command("save", this_object(), "", (: save() :));
   add_command("quit", this_object(), "", (: quit_alt(-1) :));
   add_command("quit", this_object(), "brief", (: quit_alt(0) :));
   add_command("quit", this_object(), "verbose", (: quit_alt(1) :));
   add_command("review", this_object(), "", (: review() :));
   add_command("wimpy", this_object(), "", (: toggle_wimpy(0) :));
   add_command("wimpy", this_object(), "<word'number'>",
               (: toggle_wimpy($4[0]) :));
   add_command("refresh", this_object(), "<word'totally'>",
               (: do_refresh($4[0]) :));
   add_command("cap", this_object(), "<word'name'>", (: do_cap($4[0]) :));
}                               /* public_commands() */

/**
 * Force the player to glance.  Forces the player to glance in a
 * certain direction.
 * @param str the direction to glance in
 * @return 0 ifg the command failed, non zer if it succeeded
 */
int glance(string str)
{
   return command("glance" + (str ? " " + str : ""));
}                               /* glance() */

/**
 * Force the player to look.  Forces the player to look at something
 * or just around.  If the input is set to "" then they look around.
 * @param str what to look at
 * @return 0 if it failed, non zero on success
 * @see efun::command()
 */
int look_me(string str)
{
   return command(str ? "look" + str : "look");
}                               /* look_me() */

/**
 * @ignore yes
 */
int review()
{
   write("Entry  : " + query_msgin() + "\n");
   write("Exit   : " + query_msgout() + "\n");
   write("MEntry : " + query_mmsgin() + "\n");
   write("MExit  : " + query_mmsgout() + "\n");
   write("Editor : " + query_editor() + "\n");
   return 1;
}                               /* review() */


/**
 * Forces the player to examine something.  This does the same as the look_me
 * function.
 * @see look_me()
 * @return 0 on a failure, non zero on success.
 * @param arg the thing to look at.
 */
int examine(string arg)
{
   return look_me(arg ? " at " + arg : "");
}                               /* examine() */

/**
 * @ignore yes
 */
varargs string short(int dark,
                     int verbose)
{
   string str;
   string family;
   string title;

   if (!interactive(this_object())) {
      str = "the net dead statue of ";
   } else {
      str = "";
   }

   family = query_family_name();
   if (!family) {
      family = "";
   } else {
      family = " " + family;
   }

   if (verbose)
      title = query_player_title();
   if (!title) {
      title = "";
   } else {
      title = title + " ";
   }

   return str + title + living::short(dark) + family;
}                               /* short() */

/**
 * This method changes the current value of the wimpy variables.
 * @param str the new value of the wimpy variable
 * @return 0 on failure and 1 on success
 */
int toggle_wimpy(string str)
{
   int number;
   if (!str) {
      if (this_object()->query_wimpy())
         write("You are in wimpy mode, you will run away at " +
               this_object()->query_wimpy() +
               "% of your max hps.\n");
      else
         write("You are in brave mode.\n");
      write("Usage: wimpy <num> (caution read help wimpy)\n");
      return 1;
   }
   if (sscanf(str, "%d", number) != 1)
      return notify_fail("You must set your wimpy to a number.\n");
   if ((number < 0) || (number > 30))
      return notify_fail("Your wimpy must be between 0 and 30%.\n");
   this_object()->set_wimpy(number);
   printf("Wimpy set to %d%%\n", wimpy);
   return 1;
}                               /* toggle_wimpy() */


/**
 * This method returns any extra information associated with the score.  This
 * method will mostly be overridden by shadows which wish to place more
 * information into the score command.
 * @return the extra information to place in the score
 */
string extra_score()
{
   return "";
}

/**
 * This method is deprecated.
 *
 * @return always returns 1
 * @see save_me()
 */
nomask int save() {
#ifdef UNUSED
  if(query_verb() == "save") {
    if(_pinfo->last_save > time() - 900) {
      tell_object(this_object(), "You saved only a few minutes ago.\n");
      return 1;
    }
    _pinfo->last_save = time();
  } 
#endif

  /*
   * easier on me - Pinkfish.
   * ..
   */
  if (((time() - time_on) < MIN_TIME_TO_SAVE) &&
      !LIBRARY->query_quest_points(query_name()) &&
      !query_property("authorised player")) {
    if (query_verb() == "save") {
      tell_object(this_object(), "You're too young to save... sorry.\n");
    }
    return 1;
  }
  
  tell_object(this_object(), "Saving...\n");
  this_object()->save_me();
  return 1;
}

/**
 * Saves the player.  Saves the player to disc, doing all the autoload
 * stuff and such like.
 * @see save()
 */
void save_me() {
   mixed old;

#ifdef NOT_SAVEING_PLAYERS
   if (!this_object()->query_creator()) {
      write("Not saving for players currently.\n");
      return;
   }
#endif
   if (query_auto_loading())
      return;

   if (query_property("guest")) {
      if (query_verb() == "save")
         tell_object(this_object(), "But not saving for guests... Sorry.\n");
      return;
   }

   /* If this is called before auto_loading has even started, log and abort
    * Olorin 31-Mar-97
    */
   if (query_save_inhibit()) {
      return;
   }

   if (guild_ob) {
      guild_ob->player_save(this_object());
   }
   if (race_ob) {
      race_ob->player_save(this_object());
   }
   old = geteuid();

   check_last_pos();

   /* for effects */
   effect_freeze();
   effects_saving();
   /* Recreating the autoload stuff. */
   create_auto_load(all_inventory(), 1);
   if (interactive(this_object())) {
      last_on_from = query_ip_name(this_object()) + " (" +
         query_ip_number(this_object()) + ")";
   }
   //
   // Keep the time_on calculation as close to the saving as possible.
   //
   time_on -= time();
   //if (query_creator()) {
      catch(unguarded((: save_object,
                      PLAYER_HANDLER->query_player_file_name(query_name()), 3 :)));
/*
   } else {
      catch(unguarded((: save_object,
                      PLAYER_HANDLER->query_player_file_name(query_name()), 1 :)));
   }
 */
   time_on += time();
   ITEM_TRACKER->save_all_item_states(this_object()->query_name());
   effect_unfreeze();
//   if (this_object()->query_creator()) {
   /* Clear the autoload string after saving to save memroy. */
   set_auto_load_string(0);
//   }
}                               /* save_me() */

void save_with_auto_load(mixed al)
{
   mixed old;

#ifdef NOT_SAVEING_PLAYERS
   if (!this_object()->query_creator()) {
      write("Not saving for players currently.\n");
      return;
   }
#endif
   if (query_property("guest")) {
      write("But not saving for guests... sorry.\n");
      return;
   }
   if (((time() - time_on) < MIN_TIME_TO_SAVE) && query_verb() == "save") {
     tell_object(this_object(), "You're too young to save... sorry.\n");
     return;
   }
   
   /* If this is called before auto_loading has even started, log and abort
    * Olorin 31-Mar-97
    */
   if (query_save_inhibit()) {
      return;
   }
   if (guild_ob) {
      guild_ob->player_save(this_object());
   }
   if (race_ob) {
      race_ob->player_save(this_object());
   }
   old = geteuid();

   /* for effects */
   effect_freeze();
   effects_saving();
   set_auto_load_string(al);
   if (((time() - time_on) >= MIN_TIME_TO_SAVE) ||
       LIBRARY->query_quest_points(query_name())) {
     //
      // Put the time_on calculation as close to the save as possible.
      //
      time_on -= time();
      //if (query_creator()) {
         catch(unguarded((: save_object,
                         PLAYER_HANDLER->query_player_file_name(query_name()),
                         3 :)));
/*
      } else {
         catch(unguarded((: save_object,
                         PLAYER_HANDLER->query_player_file_name(query_name()),
                         1 :)));
      }
 */
      time_on += time();
   }
   effect_unfreeze();
}                               /* save_with_auto_load() */

/**
 * This is the quit code called by the command 'quit'
 * @return 1 if successful, 0 if failed
 * @see quit()
 * @see do_quit()
 */
int quit_alt(int verbose)
{
   object frog;

   if (verbose == -1) {
      verbose = query_verbose("quit");
   }

   if (query_auto_loading()) {
      if (!interactive(this_object())) {
         dest_me();
      } else {
         write
            ("You cannot quit yet: your inventory is still being generated.\n");
      }
      return 1;
   }

   if (sizeof(filter_array((object *) this_object()->query_attacker_list(),
                           (: living($1) :))) &&
       this_player() == this_object() && interactive(this_object())) {
      write
         ("You cannot quit while in combat.  Use 'stop' to stop fighting.\n");
      return 1;
   }

   check_last_pos();

   update_activity(0);
   last_log_on = time();

   // Added to help people tell when the player quits.
   catch(this_object()->event_quit(this_object()));
   catch(environment(this_object())->event_quit(this_object()));

   catch(editor_check_do_quit());
   write("A small gecko takes your hand and rushes you to the departure "
         "lounge.\n");
   say(query_cap_name() + " leaves the game.\n");
   catch(move("/room/departures"));

   user_event(this_object(), "inform",
              query_cap_name() + " leaves " + mud_name() + "", "logon", this_object());

   catch(LOGIN_HANDLER->player_logout(query_name()));
   if (race_ob) {
      catch(race_ob->player_quit(this_object()));
   }
   if (guild_ob) {
      catch(guild_ob->player_quit(this_object()));
   }

   frog = clone_object("/obj/monster/greco");
   frog->move("/room/departures");
   frog->get_rid_of(this_object(), verbose);
   return 1;
}                               /* quit_alt() */

/**
 * quits the player.
 * @return zero if it failed, non zero on success
 * @see quit()
 * @see quit_alt()
 */
int do_quit()
{
   return quit_alt(-1);
}                               /* do_quit() */

/**
 * A forced quit.
 * This is the function called by external objects to quit
 * a player. It avoids checks for things like being in combat.
 *
 * @return 0 if it failed, non zero if it succeeded.
 * @see do_quit()
 * @see quit_alt()
 * @see efun::command()
 */
int quit()
{
   if (query_auto_loading() || query_save_inhibit()) {
      tell_object(this_object(),
                  "Forced to quit whilst auto loading.  Not saving.\n");
      ::dest_me();
      return 1;
   }

   check_last_pos();

   update_activity(0);
   last_log_on = time();

   catch(editor_check_do_quit());

   // Added to help people tell when the player quits.
   catch(this_object()->event_quit(this_object()));
   catch(environment(this_object())->event_quit(this_object()));

   tell_object(this_object(), "Thanks for playing.  See you next time.\n");
   say(query_cap_name() + " leaves the game.\n");

   user_event(this_object(), "inform",
              query_cap_name() + " leaves " + mud_name() + "", "logon", this_object());

   catch(LOGIN_HANDLER->player_logout(query_name()));
   if (race_ob) {
      catch(race_ob->player_quit(this_object()));
   }
   if (guild_ob) {
      catch(guild_ob->player_quit(this_object()));
   }
    
   catch(save_me());

   foreach( object inv in all_inventory( this_object() ) ) {
      reset_eval_cost(); 
      catch( inv->set_tracked_item_status_reason("QUIT") );
      catch( inv->dest_me() );
   }

   catch(ITEM_TRACKER->
         save_all_item_states_delete_cache(this_object()->query_name()));
   effects_quiting();
   
   // One more for good luck. 
   reset_eval_cost(); 

   if (catch(dest_me())) {
      destruct(this_object());
   }
   return 1;
}                               /* quit() */

/**
 * This method returns the mapping of all the title associated with this
 * player.
 * @return the current mapping of titles
 * @see query_title()
 * @see set_title()
 * @see remove_title()
 */
mapping query_titles()
{
   return copy(_pinfo->titles);
}

/**
 * This method returns the list of titles associated with this player.
 * @return the list of titles
 * @see query_titles()
 * @see set_title()
 * @see remove_title()
 */
string query_title()
{
   return implode(m_values(_pinfo->titles), ", ");
}

/**
 * This method sets the current title type to be of a certain name.
 * @param type the type of title to set
 * @param title the string to set it to
 * @see query_title()
 * @see set_title()
 * @see remove_title()
 */
void set_title(string type,
               string title)
{
   _pinfo->titles[type] = title;
}

/**
 * This method removes the title of the given type from the title mapping.
 * @param type the type of title to remove
 * @see query_title()
 * @see set_title()
 * @see remove_title()
 */
void remove_title(string type)
{
   map_delete(_pinfo->titles, type);
}

/**
 * This method returns the number of times the player has died.
 * @return the number of times the player has died
 * @see adjust_deaths()
 * @see adjust_max_deaths()
 */
int query_deaths()
{
   return deaths;
}

/**
 * This method changes the number of times the player has died.  This
 * can only be positive.
 * @param i the amount of deaths to adjust by, must be +ve
 * @see query_deaths()
 * @see adjust_max_deaths()
 */
void adjust_deaths(int i)
{
   if (i > 0) {
      deaths += i;
   }
}

/* nomask protected void set_name(string str) { */
/** @ignore yes */
nomask void set_name(string str) {
  if (query_name() && query_name() != "object") {
    return;
  }
  if (file_name(previous_object())[0..12] != "/secure/login" &&
      file_name(previous_object())[0..13] != "/secure/nlogin") {
    return;
  }
  ::set_name(str);
  set_living_name(query_name());
  set_main_plural(query_name());
}                               /* set_name() */

/**
 * @ignore yes
 * No ide what this is doing here?
 */
void init_static_arg(mapping map)
{
   return;
}

/**
 * @ignore yes
 */
void init_dynamic_arg(mapping, object) {
  return;
}

/** @ignore yes */
string long(string str,
            int dark)
{
   string s;
   string tmp;
   string title;
   string nationality;

   title = query_player_title();
   if (!title) {
      title = "";
   } else {
      title = title + " ";
   }

   s = "You see " + title + query_short();
   tmp = query_family_name();
   if (tmp) {
      s += " " + query_family_name();
   }
   if (guild_ob) {
      s += " " + (string) guild_ob->query_title(this_object()) + ".\n";
   } else {
      s += ".\n";
   }
   if (race_ob) {
      s += (string) race_ob->query_desc(this_object());
   }

   nationality = query_nationality_description(this_player());
   if (nationality  &&  nationality != "") {
      s += nationality + "\n";
   }

   if (dark == 2 || dark == -2) {
      s += "It is too ";
      if (dark == -2) {
         s += "dark";
      } else {
         s += "bright";
      }
      s += " to see their description or what " +
         query_pronoun() + " are wearing or carrying.\n";
      s += calc_extra_look();
   } else {
      if (query_desc() && query_desc() != "") {
         s += capitalize(query_pronoun()) + " " + query_desc() +
              query_main_zone_desc(query_wearing()) + "\n";
      }
      s += capitalize(query_pronoun()) + " " +
         this_object()->health_string() + ".\n";
      s +=
         capitalize(query_pronoun()) + " is " + query_position_short() +
         ".\n";
      s += calc_extra_look();
      s += weather_extra_look();
      s += query_living_contents(0);
   }
   return s;
}                               /* long() */

/**
 * This method is called when the player dies.  It creates the corpse
 * and handles all the bits and pieces that should be dealth with
 * when a player dies.
 * <p>
 * If this method returns 0 then the automatic death handling code
 * in the living object is used instead of this.
 * @return always returns 1
 */
mixed second_life()
{
   object corpse;
   string death_mess;

   add_property("dead", time());

   if (!DEATH->someone_died(this_object())) {
      deaths++;
   }

   effects_thru_death();
   corpse = make_corpse();
   reset_protectors();

   if (deaths > max_deaths) {
      death_mess = query_property ("death mess");
      tell_object(this_object(), "You have died your final death.  " +
                "Your name will be inscribed in the Hall of Legends.\n");
      
      if (death_mess && sizeof (death_mess)) {
        death_mess = strip_colours (death_mess);
        death_mess = replace (death_mess, ({"\n", "", "\a", ""}));
        
        shout(capitalize(query_name()) + " has died for the last time.  " +
          death_mess + "\n");
      }
      else {                
        shout(capitalize(query_name()) + " has died for the last time.  " +
             capitalize(query_pronoun()) + " is mourned.\n");
      }
      
      LIBRARY->complete_death(query_name());
      corpse->move(PLAYER_MORGUE);
   } else
      corpse->move(environment());

   call_out((: save_me :), 0);
   if (find_object(OFFLER) && (deaths <= max_deaths)) {
      OFFLER->person_died(query_name());
   } else {
      DEATH->person_died(query_name());
   }
   clone_object(DEATH_SHADOW)->setup_shadow(this_object());
   if (guild_ob) {
      guild_ob->member_died(this_object());
   }
   gp = 0;
   hp = 0;
   set_sp(0);
   set_max_sp(50);
   xp = 0;
   //spells = ([ ]);
   reset_spells();
   reset_processes();
   contmp = dextmp = inttmp = strtmp = wistmp = 0;
   remove_call_out(_pinfo->update_tmps_call_out);
   adjust_tmp_con(-2);
   adjust_tmp_dex(-2);
   adjust_tmp_int(-2);
   adjust_tmp_str(-2);
   adjust_tmp_wis(-2);
   return corpse;
}                               /* second_life() */

/**
 * This method removes the ghost from the player.  This stops them
 * being a ghost and turns them back into a real person.
 * @see second_life()
 */
void remove_ghost()
{
   if (deaths > max_deaths) {
      if (this_player() != this_object()) {
         tell_object(this_object(), this_player()->query_cap_name() +
                     " tried to raise you, but you are completely dead.\n");
         tell_object(this_player(), query_cap_name() +
                     " is completely dead, you cannot raise " +
                     query_objective() + ".\n");
      } else {
         tell_object(this_object(), "You are completely dead.  You cannot " +
                     "be raised.\n");
         say(query_cap_name() +
             " struggles to appear in a solid form, but fails.\n");
         return;
      }
   }
   remove_property("dead");
   tell_object(this_object(), "You reappear in a more solid form.\n");
   if (guild_ob) {
      guild_ob->member_resurrected(this_object());
   }
   say(query_cap_name() + " appears in more solid form.\n");
   if (query_hp() < 0) {
      set_hp(1);
   }
   set_personal_temp(0);

   this_object()->dest_death_shadow();
   save_me();
   all_inventory()->recovery_from_death();
}                               /* remove_ghost() */

/**
 * Called when the player goes net dead.  This is called
 * by the driver when a player goes net dead.  Turns them into
 * a statue and stuff.
 */
void net_dead()
{
   if (!environment() || file_name(environment()) == "/room/departures") {
      // Don't do anything here...
      return;
   }

   if ((query_name() == "guest") || (query_name() == "root")) {
      say(query_name() + " vanishes in a puff of logic.\n");
      quit();
   } else {
      say(query_name() + " goes white, looks very chalky and turns into a " +
          "statue.\n");
      user_event(this_object(), "inform",
                 capitalize(query_name()) + " has lost " +
                 query_possessive() + " link", "link-death", this_object());
      check_last_pos();
      LOGIN_HANDLER->player_net_dead(query_name());
      /* Called to save the player when they go net dead. */
      save_me();
   }
   event(environment(), "net_dead", this_object());
}                               /* net_dead() */

/**
 * Checks to see if they have idled out.  This is called from within
 * the heart beat code.
 * @see heart_beat()
 */
void idle_out()
{
   say(cap_name + " has been idle for too long; " + query_pronoun() +
       " vanishes in a puff of boredom.\n");
   write("You idled out, sorry.\n");
   quit();
}                               /* idle_out() */

/**
 * The main heart beat function.  This is called by the driver
 * every 2 seconds on the player.  Does all the maintence
 *  stuff like fixing up hps and stuff like that.
 */
void heart_beat()
{
   catch {
      int idle_time;

      events::print_messages();
      flush_queue();

      if (!interactive(this_object())) {
         idle_time = time() - last_command;
      } else {
         idle_time = query_idle(this_object());
      }

      if (query_creator()) {
         idle_time = idle_time / 3;
         /* Time out for creators is 3 times that of players... */
      }

      if (idle_time > FULL_IDLE) {
         if ((LOGIN_HANDLER->is_discworld_full() || idle_time > MAX_IDLE) &&
             (!interactive(this_object())
              || my_file_name != "/global/lord")) {
            call_out((: idle_out :), 2);
         }
      }

      if (interactive(this_object())) {

         living::heart_beat();
         adjust_sp(1);
         adjust_xp(3);
         living::update_volumes();

         this_object()->do_spell_effects(0);

         // reset it every hour to stop it rolling over.
         if (_pinfo->hb_num++ > 1800)
            _pinfo->hb_num = 0;

         // Do these checks less frequently.
         if (!(_pinfo->hb_num % 120)) {

            calc_personal_temp();
            adjust_max_sp(1);
         }
      }
   };
}                               /* heart_beat() */

/**
 * Is rthe monitor turned on?  The hit point monitor which is
 * displyed during combat...
 *
 * @return 1 if it is on, 0 if not
 */
int query_monitor()
{
   return monitor;
}

/**
 * Set the hit point minitor.  This sets the value of the hit point
 * monitor flag.  If it is set to 0, the monitor is turned off.  If
 * it is set to 1 the monitor is turned on, higher values cause the monitor
 * to be displayed every N heartbeats.
 *
 * @param i the new value for the hit point monitor flag
 */
void set_monitor(int i) {
  monitor = i;
}

protected void write_prompt()
{
   efun::tell_object(this_object(), "> ");
   return;
}

#ifdef UNUSED
protected void write_prompt()
{
   string prompt;
   int tmp,
     i;
   string stuff;

   if (!(monitor & 2) || !this_object()->query_creator())
      efun::tell_object(this_object(), "> ");
   else {
      prompt = "";
      stuff = this_player()->query_property("prompt");
      for (i = 0; i < strlen(stuff); i++) {
         switch (stuff[i]) {
         case 'h':             // Hp %
            tmp = ((query_hp() * 100) / query_max_hp());
            prompt += "Hp:";
            switch (tmp) {
            case 50..100:
               prompt += "%^GREEN%^";
               break;
            case 20..49:
               prompt += "%^YELLOW%^";
               break;
            default:
               prompt += "%^RED%^";
            }
            prompt += tmp + "%^RESET%^";
            break;

         case 'H':             // Hp %
            tmp = ((query_hp() * 100) / query_max_hp());
            prompt += "Hp:";
            switch (tmp) {
            case 50..100:
               prompt += "%^GREEN%^";
               break;
            case 20..49:
               prompt += "%^YELLOW%^";
               break;
            default:
               prompt += "%^RED%^";
            }
            prompt += query_hp() + "%^RESET%^";
            break;

         case 'g':             // Gp %
            tmp = (query_gp() * 100) / query_max_gp();
            prompt += "Gp:";
            switch (tmp) {
            case 50..100:
               prompt += "%^GREEN%^";
               break;
            case 20..49:
               prompt += "%^YELLOW%^";
               break;
            default:
               prompt += "%^RED%^";
            }
            prompt += tmp + "%^RESET%^";
            break;

         case 'G':             // Gp
            tmp = (query_gp() * 100) / query_max_gp();
            prompt += "Gp:";
            switch (tmp) {
            case 50..100:
               prompt += "%^GREEN%^";
               break;
            case 20..49:
               prompt += "%^YELLOW%^";
               break;
            default:
               prompt += "%^RED%^";
            }
            prompt += query_gp() + "%^RESET%^";
            break;

         case 's':             // Sp %
            tmp = (query_sp() * 100) / query_max_sp();
            prompt += "Sp:";
            switch (tmp) {
            case 50..100:
               prompt += "%^GREEN%^";
               break;
            case 20..49:
               prompt += "%^YELLOW%^";
               break;
            default:
               prompt += "%^RED%^";
            }
            prompt += tmp + "%^RESET%^";
            break;

         case 'S':             // Sp
            tmp = (query_sp() * 100) / query_max_sp();
            prompt += "Sp:";
            switch (tmp) {
            case 50..100:
               prompt += "%^GREEN%^";
               break;
            case 20..49:
               prompt += "%^YELLOW%^";
               break;
            default:
               prompt += "%^RED%^";
            }
            prompt += query_sp() + "%^RESET%^";
            break;

         case 'X':
         case 'x':
            prompt += "Xp:" + query_xp();
            break;

         default:
            if (sizeof(prompt) > 0 && prompt[sizeof(prompt) - 1] != stuff[i])
               prompt += sprintf("%c", stuff[i]);
         }
      }
      prompt += "> ";
      efun::tell_object(this_object(), fix_string(prompt));
   }
}
#endif

/**
 * Called when the player wimpys out of a place.  This does all the run
 * away stuff anfd things like that.
 * @return 1 if succeeded in running away, 0 if not
 */
int run_away()
{
   int number;
   become_flummoxed();
   number =::run_away();
   if (number)
      tell_object(this_object(), "Your feet run away with you!\n");
   else
      tell_object(this_object(), "You try to run away, but no matter how "
                  "you scrabble, you can't find any way out.\n");
   return number;
}                               /* run_away() */

/**
 * The amount of time on line.  This is the total amount of time online
 * in seconds from when they first started playing.  The return from
 * this method is *negative*, you will need to make it positive to use it
 * most likely.
 * @return the total log on time in seconds (the return value is *negative*)
 */
nomask int query_time_on()
{
   return time_on - time();
}

/**
 * This method determins if the player is mature or not yet.  It is based
 *  on the amount of time on.
 * @return 1 if the player is mature, 0 if they are not
 */
int query_mature()
{
   return (MATURITY * 60 * 60 + time_on < time());
}

/**
 * Can the player see?  Checks to see if the player can see at the passed
 * in light level.
 * @return 1 if they can see, 0 if they cannot
 */
int check_dark(int light)
{
   int i;

   if (race_ob)
      if (catch(i = (int) race_ob->query_dark(light)))
         race_ob = RACE_STD;
      else
         return i;
   return (int) RACE_STD->query_dark(light);
}                               /* check_dark() */

/**
 * Returns the players level.  Uses their current guild to determine their
 * guild level.
 * @return their guild level
 */
int query_level()
{
   string tmp;

   if (_pinfo->level_time < (time() - LEVEL_CACHE)) {
      if (guild_ob) {
         _pinfo->level = (int) guild_ob->query_level(this_object());
      } else {
         /*
          * If they do not have a guild object, see if they have a backup
          * set.  Otherwise use the warriors guild as the level setter.
          */
         tmp = query_property("backup guild");
         if (tmp) {
            _pinfo->level = tmp->query_level(this_object());
         } else
            _pinfo->level = CONFIG_DEFAULT_GUILD->query_level(this_object());
      }
      _pinfo->level_time = time();
   }

   return _pinfo->level;
}                               /* query_level() */

/**
 * Restarts their heartbeat if it has got turned off for some reason.
 * @return always returns 1
 */
int restart_heart_beat()
{
   set_heart_beat(1);
   write("Ok, heart_beat restarted.\n");
   return 1;
}

/**
 * @ignore yes
 */
nomask void set_snoopee(object ob)
{
   _pinfo->snoopee = ob;
}

/**
 * Returns the object snooping us.  If someone is snooping the player it
 * returns the object doing the snooping.  If no one is snooping the player
 * it returns 0.
 * @return the object snooping the player
 * @see efun::snoop()
 */
nomask object query_snoopee()
{
   return _pinfo->snoopee;
}

/**
 * @ignore yes
 */
void set_creator(int i)
{
   if (previous_object() != master()) {
      write("Illegal attempt to set creator!\n");
      log_file("ILLEGAL", this_player(1)->query_name() + " (" +
               file_name(this_player(1)) +
               ") Illegal attempt to set_creator " + "at " + ctime(time()) +
               " from " + file_name(previous_object()) + "\n");
      return;                   /* THIS WAS MISSING !!!  Turrican 4-11-95 */
   }
   creator = i;
   set_home_dir("/w/" + query_name());
   save_me();
}                               /* set_creator() */

/**
 * Prevent the object from shadowing us?  This checks to see if we should
 * prevent this object from shadowing the player.
 * @return 1 if we are prventing the shadow
 */
int query_prevent_shadow(object ob)
{
   if (function_exists("query_prevent_shadow", ob) ||
       function_exists("query_name", ob) ||
       function_exists("query_creator", ob) ||
       function_exists("query_lord", ob) ||
       function_exists("query_hidden", ob) ||
       function_exists("dest_me", ob) ||
       function_exists("query_object_type", ob) ||
       function_exists("query_lord", ob) || function_exists("save_me", ob))
/* added by sojan to fix security holes */
      return 1;
   return 0;
}

/**
 * Returns the maxium number of deaths.  This is the maxium number of times they
 * can die before they are totaly dead.
 * @return the maxiumm number fo deaths
 */
int query_max_deaths()
{
   return max_deaths;
}

/**
 * Sets the maximum number of deaths.  This sets the maximum number of times a player can
 * die.
 * @param i the nukber of deaths to set it to
 * @see adjust_max_deaths()
 */
protected void set_max_deaths(int i)
{
   max_deaths = i;
}

/**
 * Changes the current number of maxium deaths.  This adjust
 * the number of times a player can die before they are totaly dead.
 * @return the current total maximum deaths
 * @param i the amount of deaths to adjust by, must be +ve
 */
int adjust_max_deaths(int i)
{
   if (i > 0) {
      return (max_deaths += i);
   }
}

/**
 * @ignore yes
 */
varargs int move(mixed dest,
                 string msgin,
                 string msgout)
{
   int i;
   object env = environment();

   i = living::move(dest, msgin, msgout);
   if (!i) {
      me_moveing(env);
   }
   return i;
}                               /* move() */

/**
 * @ignore yes
 */
nomask protected int do_refresh(string str) {
   if (query_property("guest")) {
      return notify_fail("Guests cannot refresh, sorry.\n");
   }
   if (!str || str != "totally") {
      return notify_fail("Please read the docs before using this command.\n");
   }
   write("%^BOLD%^WARNING!  This will restart your character.%^RESET%^\n\n" +
         "Are you sure you wish to refresh yourself totally? ");
   input_to("refresh_docs");
   return 1;
}

/**
 * @ignore yes
 */
protected int refresh_docs(string str) {
   string helpfile = "";
   str = lower_case(str);
   if (str[0] != 'y') {
      write("Ok, not refreshing.\n");
      return 1;
   }
   NROFF_HAND->create_nroff( "/doc/helpdir/refresh", helpfile );
   helpfile = NROFF_HAND->cat_file( helpfile );
   write ( helpfile[0..670] );
   write("\n\n%^BOLD%^Having read the documentation, are you still sure you "
         "wish to refresh totally?%^RESET%^\n");
   input_to("refresh3");
   return 1;
}

/**
 * @ignore yes
 */
protected int refresh2(string str, int noevent) {
   object ob;
   string group;

   str = lower_case(str);
   if (str[0] != 'n' && str[0] != 'y') {
      write
         ("Pardon?  I do not understand.  Do you want to refresh yourself? ");
      input_to("refresh2");
      return 1;
   }
   if (str[0] == 'n') {
      write("Ok, not refreshing.\n");
      return 1;
   }
   write("Doing refresh.\n");
   Str = 13;
   Con = 13;
   Int = 13;
   Wis = 13;
   Dex = 13;
   inttmp = dextmp = wistmp = strtmp = contmp = 0;
   race_ob = CONFIG_DEFAULT_RACE;
   if (guild_ob)
      catch(guild_ob->delete_member(query_name()));

   if (!noevent) {
      REFRESH_HANDLER->player_refreshed(this_object(), PARTIAL_REFRESH);
   }
   guild_ob = 0;
   set_al(0);
   if (query_deity()) {
#ifndef __DISTRIBUTION_LIB__
      catch(DEITY->delete_worshipper(query_deity(), query_name()));
      catch(DEITY->delete_priest(query_deity(), query_name()));
#endif
   }
   set_deity(0);
   set_skills(0);

   /* Remove them as a playtester. */
   PLAYTESTER_HAND->remove_playtester(query_name());

   //
   // If they have a family, remove them from that too.
   //
   if (query_family_name()) {
      CLUB_HANDLER->remove_member(query_family_name(), query_name());
      set_family_name(0);
   }

   reset_effects();
   reset_spells();
   reset_processes();
   setup_default_titles();
   guild_ob = 0;
   set_guild_data(0);
   xp = 0;
   deaths = 0;
   max_deaths = 7;
   _refresh_time = time();
   totaly_zap_bonus_cache();
   known_commands = ({ "skills", "rearrange", "gp", "newbie" });
   reset_starts();
   race_guild_commands();
   totaly_zap_stat_cache();
   drink_info = allocate(D_SIZEOF);
   map_prop = ([ "determinate" : "",
                 "player" : 1,
                 "skills version" :
                 (string) "/obj/handlers/change_skills"->query_version() ]);
   this_object()->remove_ghost();
   set_nationality(0);
   set_nationality_region(0);
   set_language("general");
   set_default_language("general");
   reset_all();

   group = this_player()->query_group();
   if (group) {
      GROUP->remove_member(group, this_player(), " refreshed themselves.");
   }

   set_last_pos(CONFIG_NEWBIE_START_LOCATION);
   START_PLAYER->give_junk(this_object());

   // Remove people from the hunting list.
   foreach (ob in query_attacker_list()) {
      catch(ob->stop_fight(this_object()));
      catch(stop_fight(ob));
   }
   
   call_out((: move_to_start_pos :), 0);

   if (!noevent) {
      write("Done refreshing.\n");
      say(cap_name + " refreshes " + query_objective() + "self.\n");
      save_me();
   }
   return 1;
}                               /* refresh2() */

/**
 * @ignore yes
 */
protected int refresh3(string str)
{
   object *items,
    *ritems,
     item;

   str = lower_case(str);
   if (str[0] != 'n' && str[0] != 'y') {
      write("Pardon?  I do not understand.  Do you want to refresh " +
            "yourself totally? ");
      input_to("refresh3");
      return 1;
   }
   if (str[0] == 'n') {
      write("Ok, not refreshing.\n");
      return 1;
   }
   write("Ok, refreshing totally.\n");
   ritems = filter(all_inventory(environment()),
                   (: $1->query_property("dropped") &&
                      $1->query_property("dropped")[0] == query_name() :));
   move(CONFIG_NEWBIE_START_LOCATION);
   refresh2("y", 1);
   set_player_killer(0);
   _pinfo->titles = ([ ]);
   REFRESH_HANDLER->player_refreshed(this_object(), TOTAL_REFRESH);
   "/secure/related_files"->delete_related_files(query_name(),
                                                 0, TOTAL_REFRESH);

   items = ritems + all_inventory();
   foreach(item in items) {
      item->dest_me();
   }

   foreach(item in children("/obj/corpse")) {
      if (item->query_owner() == this_object()->query_name()) {
        item->move("/room/rubbish");
      }
   }

   // Remove from clubs and families.
   foreach (string club in query_player_clubs()) {
      catch(CLUB_HANDLER->remove_member(club, this_player()->query_name()));
   }
   if (query_family_name()) {
      catch(CLUB_HANDLER->remove_member(query_family_name(),
                                  this_player()->query_name()));
      call_out("check_family_name", 2);
   }

   write("Done refreshing.\n");
   say(cap_name + " refreshes " + query_objective() + "self.\n");
   save_me();
   return 1;
}

/**
 * This method returns the one letter object type which is used in the
 * finger command to display the type of object.
 * @return the one letter object type
 */
string query_object_type(object player)
{
   if ("/obj/handlers/playtesters"->query_playtester(query_name())) {
      return "p";
   }
   return " ";
}                               /* query_object_type() */

/**
 * @ignore yes
 * Sets the cap name, part of a command..
 */
int do_cap(string str)
{
   if (!str)
      return notify_fail("Syntax: " + query_verb() + " <cap_name>\n");
   if (lower_case(str) != query_name())
      return
         notify_fail
         ("You must have the same letters in your capitalized name.\n");
   cap_name = str;
   write("Capitalized name set to " + cap_name + ".\n");
   return 1;
}                               /* do_cap() */

/** @ignore yes */
void set_my_ident(string str)
{
   return;
}

/** @ignore yes */
string query_my_ident()
{
   return 0;
}

/**
 * @ignore yes
 */
void event_enter(object thing,
                 string mess,
                 object from)
{
   events::event_enter(thing, mess, from);
   living::event_enter(thing, mess, from);
}                               /* event_enter() */

/**
 * @ignore yes
 */
void event_exit(object thing,
                string mess,
                object to)
{
   events::event_exit(thing, mess, to);
   living::event_exit(thing, mess, to);
}                               /* event_exit() */

/**
 * @ignore yes
 */
string *parse_command_id_list()
{
   if (query_player_killer()) {
      return ({ "killer" }) +
             living::parse_command_id_list() + family::parse_command_id_list();
   } else {
      return living::parse_command_id_list() + family::parse_command_id_list();
   }
}                               /* parse_command_id_list() */

/**
 * @ignore yes
 */
string *parse_command_plural_id_list()
{
   if (query_player_killer()) {
      return ({ "killers" }) + living::parse_command_plural_id_list() +
         family::parse_command_plural_id_list();
   } else {
      return living::parse_command_plural_id_list() +
         family::parse_command_plural_id_list();
   }
}                               /* parse_command_plural_id_list() */

/**
 * @ignore yes
 */
string *parse_command_adjectiv_id_list()
{
   return living::parse_command_adjectiv_id_list() +
         family::parse_command_adjectiv_id_list();
}                               /* parse_command_adjectiv_id_list() */

/**
 * This method returns the time at which the player last logged on.
 * @return the last logged on time
 */
int query_last_log_on()
{
   return last_log_on;
}

/* This is the time since the last refresh... */
/**
 * This method returns the time at which the player last refreshed.
 * @return the last refresh time
 */
int query_refresh_time()
{
   return _refresh_time;
}

/**
 * This method returns the number of times the player has logged onto
 * Discworld.
 * @return the number of logins
 */
int query_no_logins()
{
   return no_logins;
}                               /* query_no_logins() */

/**
 * This method returns if the object is a creator or not.
 * @return 1 if the object is a creator, 0 if not
 */
int query_creator()
{
   return 0;
}

/**
 * @ignore yes
 */
int _living(){return 1;}

/**
 * Used to set the invisibility level upon login.
 * @param level the invisiblity level
 */
protected void set_invis(int level) {
} /* set_invis() */

/**
 * This method checks to see if the person is a player killer or not.
 * @return 1 if they are a player killer, 0 if not
 */
int query_player_killer() {
   return _flags & PLAYER_KILLER_FLAG;
} /* query_player_killer() */

/**
 * This method sets the player killer flag on the player.
 * @param flag 1 for pker, 0 for not
 */
void set_player_killer(int flag) {
   if (flag) {
      _flags |= PLAYER_KILLER_FLAG;
   } else {
      _flags &= ~PLAYER_KILLER_FLAG;
   }
}

/**
 * This method puts the person into or out of role playing mode.
 * @param i 1 sets role playing mode, 0 unsets it.
 */
void set_role_playing(int i) {
  if(i) 
    add_property(RPMODE, 1);
  else
    remove_property(RPMODE);
}

/**
 * This method checks to see if the person is in role playing mode or not.
 * @return 1 if they are in role playing mode, 0 if not.
 */
int query_role_playing() {
  return query_property(RPMODE);
}