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: playtester.c,v 1.18 2003/07/21 18:23:15 pinkfish Exp $
 * $Log: playtester.c,v $
 * Revision 1.18  2003/07/21 18:23:15  pinkfish
 * Change the object characters for pts and seniors.
 *
 * Revision 1.17  2003/04/03 19:12:59  ceres
 * Modified to deal with new login object
 *
 * Revision 1.15  2002/08/11 17:49:44  drakkos
 * Added a method to query if a location is a PT area.
 * ((
 *
 * Revision 1.14  2002/08/04 07:45:08  drakkos
 *  Forcibly unlocked by ceres
 *
 * Revision 1.13  2002/07/20 12:54:35  drakkos
 * Updated the senior PT command define.
 *
 * Revision 1.12  2002/07/19 01:45:53  pinkfish
 * Add in stuff to deal with senior pts and the mail command.
 *
 * Revision 1.11  2002/07/19 01:42:04  drakkos
 *  Forcibly unlocked by pinkfish
 *
 * Revision 1.10  2002/07/18 02:27:51  drakkos
 * Added in a forgotten ::event_move_object.
 *
 * Revision 1.9  2002/07/17 23:24:50  drakkos
 * Seperation of room and personal protection into seperate functions... room protection is called by using enable_pt_protection (so that legacy code doesn't break).  Personal protection is called using enable_personal_pt_protection.  Room protection will always over-ride personal protection to allow for creators to safely PT protect their projects without worrying about time delays and such.
 *
 * Revision 1.7  2002/07/12 17:23:27  drakkos
 * Added checks for disabling and enabling protection to make sure it doesn't get enabled twice or disabled twice.
 *
 * Revision 1.6  2002/07/11 23:39:18  pinkfish
 * Make the protection only last five minutes..
 *
 * Revision 1.5  2002/07/11 23:25:28  drakkos
 *  Forcibly unlocked by pinkfish
 *
 * Revision 1.4  2002/06/27 17:47:32  drakkos
 * Added some messages and logging for PT protection, and repressed XP earned when protection is on.
 *
 * Revision 1.3  2002/06/25 19:59:18  pinkfish
 * Fix up some old effect based things so it calls the correct
 * functions.
 *
 * Revision 1.2  2002/06/25 19:51:44  pinkfish
 * Fix up some issues with the protection stuff.
 *
 * Revision 1.1  2002/06/25 18:33:59  pinkfish
 * Initial revision
 *
 * Revision 1.6  2001/06/16 05:09:29  presto
 * Fixed warning.  (Added dummy 'object' argument to query_object_type)
 *
 * Revision 1.5  2001/03/23 23:08:20  ceres
 * Added go_invis param
 *
 * Revision 1.4  1999/02/10 04:14:12  ceres
 * Modified to get creator news from the login handler
 *
 * Revision 1.3  1998/10/30 09:10:15  pinkfish
 * Fix up the name variable to be a method call.
 *
 * Revision 1.2  1998/04/13 11:37:08  pinkfish
 * Removed all the swap stuff fomr the creator object and
 * generly cut it back :)
 *
 * Revision 1.1  1998/01/06 04:54:05  ceres
 * Initial revision
 * 
 */
/* this is the creator player object */

/**
 * This is the playtester player object.  It gives the playtesters the
 * bonus extra commands needed by happy playtesters.
 * @author Pinkfish
 * @see /global/player.c
 * @started Tue Jun 25 11:27:05 PDT 2002
 */
#include <login_handler.h>
#include <command.h>
#include <player.h>
#define PROTECTION_LOG "/log/secure/playtesters/protection_log"
#define MAX_COUNTER 2

class playtester_data {
   int protect;
   int hp;
   string log_file;
   int log_death;
   int log_damage;
   int turn_off;
   int protection_counter;
   int room_protection;
}


inherit "/global/player";

int query_in_pt_arena();

private nosave class playtester_data _pt_data;

int query_pt_area (object ob) {
  string *file;
  
  if (strsrch (base_name (ob), "_pt") != -1) {
    return 1;
  }
  if (strsrch (base_name (ob), "_dev") != -1) {
    return 1;
  }

  file = explode (base_name (ob), "/");
  
  if (file[1] == "playtesters") {
    return 1;
  }
  
  return 0;
}

void create() {
   ::create();
   _pt_data = new(class playtester_data);
}

/** @ignore yes */
void move_player_to_start(string bong, int new_pl, string c_name, string ident, int go_invis) {
  if(!sscanf(file_name(previous_object()), "/secure/login#%*s") &&
     !sscanf(file_name(previous_object()), "/secure/nlogin#%*s"))
    return 0;
#ifndef NEW_DRIVER
  //enable_wizard();
#endif
  ::move_player_to_start(bong, new_pl, c_name, ident, go_invis);
  AddSearchPath(({ DIR_PLAYTESTER_CMDS }));
  if (PLAYTESTER_HAND->query_senior_playtester(query_name())) {
     AddSearchPath(({ DIR_SENIOR_PLAYTESTER_CMDS }));
  }
  if (PLAYTESTER_HAND->query_exec_access (query_name())) {
     AddSearchPath(({ DIR_EXEC_PLAYTESTER_CMDS }));
  }
} /* move_player_to_start() */

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

/** @ignore yes */
string query_object_type(object) {
  if (PLAYTESTER_HAND->query_pt_exec(query_name())) {
    return "E";
  }
  if (PLAYTESTER_HAND->query_senior_playtester(query_name())) {
    return "P";
  }
  return "p";
} /* query_object_type() */

/**
 * This method returns the status of the protect flag.  2 means that they have 
 * their room protection enabled, 1 means that they have their personal protection
 * enabled, 0 means that they are not.
 * @return The value of the protect flag
 */
int query_pt_protection() {
  if (_pt_data->room_protection) {
    return 2;
  }
  return _pt_data->protect;
} // query_pt_protection()


/**
 * This method sets the PT as being under room protection.  Room protection does not 
 * expire and lasts until it is switched off.  It also over-rides personal protection.  
 * @return 1 on success, 0 on failure.
 */
 
int enable_pt_protection() {
  if (_pt_data->room_protection != 1) {
   log_file (PROTECTION_LOG, "%s: %s had room PT "
    "protection enabled by %s.\n", ctime(time()), this_player()->query_name(), 
    base_name (environment (this_player())));     
    tell_object (this_player(), "%^BOLD%^You have had your playtester "
      "protection enabled by an external source.  It will last until switched "
      "off by another external source.\n%^RESET%^");
    _pt_data->room_protection = 1;
    return 1;
  }
  
  return 0;
}

/**
 * This method sets the PT as no longer being under room protection.  Room protection does not 
 * expire and lasts until it is switched off.  It also over-rides personal protection.  
 * @return 1 on success, 0 on failure.
 */
int disable_pt_protection() {
  if (_pt_data->room_protection == 1) {
   log_file (PROTECTION_LOG, "%s: %s had room PT "
    "protection disabled by %s.\n", ctime(time()), this_player()->query_name(), 
    base_name (environment (this_player())));   
    tell_object (this_player(), "%^BOLD%^The playtester protection enabled "
      "by an external source has been switched off.\n%^RESET%^");
    _pt_data->room_protection = 0;
    return 1;
  }
  return 0;
}

/**
 * This method sets the protect flag so that adjust_hp and
 * do_death are masked.
 */
int enable_personal_pt_protection() {
  if (query_pt_protection()) {
    return 0;
  }
  
   _pt_data = new(class playtester_data);
   _pt_data->hp = ::query_hp();
   _pt_data->protect = 1;
   _pt_data->log_file = "/d/playtesters/log/pain";
   tell_room (environment (this_player()), this_player()->one_short() 
      + " looks as if " + this_player()->query_pronoun() + " no longer has "
      "any fear of the risks of the real world.\n", this_player());
   log_file (PROTECTION_LOG, "%s: %s enabled PT "
    "protection (%s).\n", ctime(time()), this_player()->query_name(), 
    base_name (environment (this_player())));
   if (_pt_data->turn_off) {
      remove_call_out(_pt_data->turn_off);
   }
   
   if (!query_pt_area (environment (this_player()))) {
      tell_object (this_player(), "%^BOLD%^You feel somewhat more secure, as if "
        "you can no longer be harmed by conventional weapons (This will "
        "only last a maximum of fifteen minutes).%^RESET%^\n");    
     _pt_data->protection_counter = 0;
     _pt_data->turn_off = call_out("disable_personal_pt_protection", 5 * 60);
   }
   else {
      tell_object (this_player(), "%^BOLD%^You feel somewhat more secure, as if "
        "you can no longer be harmed by conventional weapons (This will "
        "last until you switch it off or leave a PT area).%^RESET%^\n");   
  }            
   
   return 1;
} // enable_pt_protection()


/**
 * This method resets the protect flag so that adjust_hp and
 * do_death are not masked, i.e. the player can be hurt in the
 * normal(*) way.
 *
 * (*) Having "normal" ways to hurt people is quite sick...  But it's fnu!
 */
int disable_personal_pt_protection() {
  if (query_pt_protection() != 1) {
    return 0;
  }
    
  if (this_player()) {
    _pt_data->protection_counter = MAX_COUNTER;
  }
  
  if (_pt_data->protection_counter < MAX_COUNTER) {
    tell_object (this_player(), "%^BOLD%^You still have your PT protection "
      "enabled.\n%^RESET%^");
    log_file (PROTECTION_LOG, "%s: %s warned about still enabled PT "
      "protection (%s).\n", ctime(time()), this_player()->query_name(), 
      base_name (environment (this_player())));      
    _pt_data->turn_off = call_out("disable_personal_pt_protection", 5 * 60);   
    _pt_data->protection_counter = _pt_data->protection_counter + 1;
    return 0;
  }
  
   _pt_data->turn_off = 0;
   _pt_data->protect = 0;
   _pt_data->protection_counter = 0;
   log_file (PROTECTION_LOG, "%s: %s disabled PT "
    "protection (%s).\n", ctime(time()), this_player()->query_name(), 
    base_name (environment (this_player())));   
   tell_object (this_player(), "%^BOLD%^You feel less secure in your "
    "indestructability.%^RESET%^\n");
   tell_room (environment (this_player()), this_player()->one_short() 
      + " looks as if the risks of the real world are once again "
      "relevant.\n", this_player());
   return 1;
} // disable_pt_protection()



/**
 * This method sets the fake hitpoints.
 * @param hp The new value of fake hitpoints
 */
void pt_set_hp( int hp ) {
    
   _pt_data->hp = hp;
} // pt_set_hp()

/**
 * This method returns the number of fake hitpoints.
 * @return The number of fake hitpoints
 */
int pt_query_hp() {
   return _pt_data->hp;
} // pt_query_hp()


/** @ignore */
object pt_make_corpse() {
   // Make a corpse in case someone needs it...

   object corpse;

   corpse = clone_object( "/obj/corpse" );
   corpse->set_owner( 0, this_object() );
   corpse->set_ownership( query_name() );
   corpse->set_race_name( query_race() );
   if ( !query_race_ob() ) {
      corpse->set_race_ob( "/std/races/unknown" );
   } else {
      corpse->set_race_ob( query_race_ob() );
   }
   corpse->add_adjective( query_adjectives() );
   corpse->start_decay();

   return corpse;
} // pt_make_corpse()


/**
 * This method replaces the normal do_death() when testing.  It gives
 * players a message about how it would have hurt if it had been for real.
 * @param thing The object that killed us.
 * @return A corpse
 */
object pt_do_death() {
   object corpse, flowers;

   
//   if( _pt_data->log_death && stringp( _pt_data->log_file ) )
   DEATH->death_informer( this_object(), 0, _pt_data->log_file, 1 );
   
   tell_object( this_object(),
         "The Death of Playtesters sneaks up behind you and taps "
         "you on the shoulder.\n"
         "%^CYAN%^The Death of Playtesters says: MY, WE'VE BEEN A BIT "
         "CARELESS, HAVEN'T WE?%^RESET%^\n"
         "The Death of Playtesters coughs.\n"
         "%^CYAN%^The Death of Playtesters says: Sorry about the Voice.  "
         "We have to do that, you know.  Well, you should really be dead "
         "now, but the Playtesters' Union renegotiated the whole death deal "
         "with the powers that be.%^RESET%^\n" );

     
   
   // Restore player to full health
   call_out ("pt_set_hp", 0, query_max_hp());
    
   // Make a corpse and give them flowers
   corpse = pt_make_corpse();
   corpse->move( environment( ) );
   
   flowers = clone_object( "/std/object" );
   flowers->set_name( "flowers" );
   flowers->set_short( "bunch of flowers" );
   flowers->add_alias( "bunch" );
   flowers->add_adjective( ({ "bunch", "of" }) );
   flowers->set_main_plural( "bunches of flowers" );
   flowers->add_plural( ({ "bunches", "bunches of flowers" }) );
   flowers->set_long( "This is a small bunch of nice flowers.\n" );
   flowers->set_weight( 5 + random( 10 ) );
   flowers->set_value( 0 );
   flowers->set_read_mess( "Rest In Peas", "common" );
   flowers->move( corpse );
   
   return corpse;
} // pt_do_death()


/**
 * This method adjusts the fake hitpoints.
 * @param hp The value to add to fake hitpoints
 * @return hp after adjustment
 */
varargs int pt_adjust_hp( int hp, object attacker ) {
       
   _pt_data->hp += hp;

   if( ( hp < 0 || hp > 10 ) && _pt_data->log_damage && stringp( _pt_data->log_file ) )
      log_file( _pt_data->log_file, ctime( time() ) +": "+
                query_name() +" - "+ hp +" hitpoints.\n" );

   // Check if they "die"

   if( _pt_data->hp <= 0 && hp < 0) {
   
      pt_do_death();
   } else if( _pt_data->hp > ::query_max_hp() ) {
      // Make sure they don't get too many hp
      _pt_data->hp = ::query_max_hp();
   }

   // Wimpy
   if( hp < 0 && _pt_data->hp > 0 && attacker && attacker != this_object() ) {
      if( 100 * _pt_data->hp < query_wimpy() * ::query_max_hp() ) {
         run_away();
      }
   }

   return _pt_data->hp;
   
} // pt_adjust_hp()




/**
 * This method sets the log file for logging of PT fake deaths and damage.
 * The default is /d/playtesters/log/pain.
 * @param str The filename of the log file.
 */
void set_pt_log_file( string str ) {
   _pt_data->log_file = str;
} // set_pt_log_file()


/**
 * This method returns the log file for logging of PT fake deaths and damage.
 * The default is /d/playtesters/log/pain.
 * @return The filename of the log file.
 */
string query_pt_log_file() {
   return _pt_data->log_file;
} // query_pt_log_file()


/**
 * This method enables logging of PT fake deaths.
 */
void enable_death_log() {
   _pt_data->log_death = 1;
} // enable_death_log()


/**
 * This method disables logging of PT fake deaths.
 */
void disable_death_log() {
   _pt_data->log_death = 0;
} // disable_death_log()


/**
 * This method returns the status of the LOG_DEATH flag, i.e. whether
 * PT fake deaths are logged or not.
 * @return Status of LOG_DEATH flag
 */
int query_log_death() {
   return _pt_data->log_death;
} // query_log_death()


/**
 * This method enables logging of PT fake damage.
 */
void enable_damage_log() {
   _pt_data->log_damage = 1;
} // enable_damage_log()


/**
 * This method disables logging of PT fake damage.
 */
void disable_damage_log() {
   _pt_data->log_damage = 0;
} // disable_damage_log()


/**
 * This method returns the status of the LOG_DAMAGE flag, i.e. whether
 * PT fake damage is logged or not.
 * @return Status of LOG_DAMAGE flag
 */
int query_log_damage() {
   return _pt_data->log_damage;
} // query_log_damage()


/** @ignore */
object do_death( object thing ) {
   if( query_pt_protection() || query_in_pt_arena())
      return pt_do_death();
   else
      return ::do_death( thing );
} // do_death()


/** @ignore */
varargs int adjust_hp( int hp, object attacker ) {
   // If protected, adjust "fake" hitpoints
   if( query_pt_protection() ) {
     return pt_adjust_hp( hp, attacker );
   } else {
      // Not protected - hurt them
      return ::adjust_hp( hp, attacker );
   }
} // adjust_hp()


/** @ignore */
int query_hp() {
   if( query_pt_protection() )
      return pt_query_hp();
   else
      return ::query_hp();
   
} // query_hp()


/** @ignore */
mixed *stats() {
   return ::stats() + ({
      ({ "PT hitpoints", _pt_data->hp }),
      ({ "PT protection", ( query_pt_protection() ? "On" : "Off" ) })
   });
} /* stats() */

/** @ignore */
string extra_score() {
   return ::extra_score() +
         "Your playtester protection is "+
         ( query_pt_protection() ? "on" : "off" ) +".\n";
} // extra_score()

int query_in_pt_arena() {
  if (!environment(this_object())) {
    return 0;
  }
  if (environment (this_object())->query_pt_arena()) {
    return 1;
  }
  return 0;
}

int advancement_restriction() {
  if (query_pt_protection()) {
    return 1;
  }
  if (query_in_pt_arena()) {
    return 1;
  }
  return 0;
}

/** @ignore yes */
varargs int adjust_xp(int number, int shared) {
  if ( advancement_restriction() && number > 0) {
    return 0;
  }
  return ::adjust_xp(number, shared);
} /* adjust_xp() */

/** @ignore yes */
void event_move_object(mixed from, mixed to) {
  ::event_move_object (from, to);

  if (query_pt_protection()) {
    if (query_pt_area(from) && !query_pt_area (to)) {
       _pt_data->protection_counter = MAX_COUNTER;
  
      if (_pt_data->turn_off) {
        remove_call_out(_pt_data->turn_off);
      }
      tell_object (this_player(), "%^BOLD%^You are now leaving a PT area.  "
        "Your protection is still on.\n%^RESET%^");
      log_file (PROTECTION_LOG, "%s: %s left a playtester area with protection "
        "still active (%s).\n", ctime(time()), this_player()->query_name(), 
        base_name (environment (this_player())));    
     
      _pt_data->turn_off = call_out("disable_pt_protection", 5 * 60);
    }
    else if (!query_pt_area (from) && query_pt_area (to)) {

      tell_object (this_player(), "%^BOLD%^You are now entering a PT area.  "
        "Your protection will not wear off until you leave or switch it "
        "off.\n%^RESET%^");
      if (_pt_data->turn_off) {
        remove_call_out(_pt_data->turn_off);
        _pt_data->protection_counter = 0;
      }        
    }
  }       
  
} /* event_move_object() */

/** @ignore yes */
int query_player_killer() {
  if (query_in_pt_arena()) {
    return 1;
  }
  return ::query_player_killer();
}

int query_contractable() {
  return ::query_player_killer();
}