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/
// /std/basic/close_lock
/*  -*- LPC -*-  */
/*
 * $Locker:  $
 * $Id: close_lock.c,v 1.39 2003/03/06 11:04:14 runtime Exp $
 *
 */
/**
 * This class keeps track of whether things are open or closed,
 * locked or unlocked.  Trap functions that are triggered when
 * an object is opened or unlocked are also handled.  When
 * you need an object that is locked you should remember to
 * use set_key() and set_difficulty().  When cloning an object
 * and moving other objects inside it you should remember to
 * make sure the object is open before moving things into it,
 * and then close it if neccessary.
 *
 * @author Gototh
 */
#include <move_failures.h>
#include <tasks.h>
#include <clothing.h>

#define MAX_INVENT 40
#define C_CLOSED 1
#define C_TRANS 2
#define C_OPAQUE 1

#define LOCKED        1
#define CLOSED        2
#define CLOSED_LOCKED 3

#define SKILL "covert.manipulation.sleight-of-hand"

#define STEALTH_NONE        0
#define STEALTH_FAILED      1
#define STEALTH_SUCCEEDED   2

#define TP this_player()
#define TO this_object()

int do_open();
int do_close();
int do_lock(object *keys);
int do_unlock(object *keys);

private int _locked;
private int _closed;

private string _pick_skill;

private nosave int _stuck;
private nosave int _trans;
private nosave int _difficulty;
private nosave int _autolock;

private nosave string _trap_open_func;
private nosave string _trap_lock_func;

private nosave object _trap_open_ob;
private nosave object _trap_lock_ob;

private nosave mixed _key;

/**
 * @ignore yes
 */
void create() {
  _difficulty = 5;
  _pick_skill = "covert.lockpick.doors";
} /* create() */

/**
 * This sets the object as being open.  Note that to find out
 * if an object is open we use query_closed() which will return
 * 0 if the object is open.
 *
 * @see set_closed()
 * @see query_closed()
 */

void set_open() {
    if (!_closed)
        return;
    _closed = 0;
    _locked = 0;
    if (environment()) {
      event( ({ environment(), TO, }), "open", TP);
    } else if (TO->query_my_room()) {
      event( ({ TO->query_my_room(), TO, }), "open", TP);
    }
} /* set_open() */

/**
 * This sets the object as being closed.  If you are moving
 * objects into the object, make sure that you do not set
 * the object as closed and then try to move the objects in.
 * Move the objects in and then close the object.
 *
 * @see set_open()
 * @see query_closed()
 */

void set_closed() {
    if (_closed)
        return;
    _closed = 1;
    if (environment()) {
      event( ({ environment(), TO, }), "close", TP);
    } else if (TO->query_my_room()) {
      event( ({ TO->query_my_room(), TO, }), "close", TP);
    }
} /* set_closed() */

/**
 * This function tells you whether an object is open or closed.
 * It returns 1 if the object is closed, and 0 if the object is open.
 *
 * @return Return 1 if closed, 0 if open.
 * @see set_open()
 * @see set_closed()
 */
int query_closed() {
  return _closed;
} /* query_closed() */

/**
 * This function tells you whether an object is open or closed.
 * It returns 1 if the object is open and 0 if the object is closed.
 *
 * @return Return 1 if open, 0 if closed.
 * @see set_open()
 * @see set_closed()
 */
int query_open() {
  return !_closed;
}

/**
 * This sets the object as being locked.  Remember to set the
 * object as being closed before using this.  In most cases you
 * should probably use set_key() to set the key which opens the
 * lock and use set_difficulty() to set the skill level required
 * to pick the lock.
 *
 * @see set_open()
 * @see set_closed()
 * @see set_key()
 * @see set_difficulty()
 */
void set_locked() {
    if (!_closed)
        return;
    if (_locked)
        return;
    _locked = 1;
    if (environment()) {
        event( ({ environment(), TO, }), "lock", TP);
    } else if (TO->query_my_room()) {
        event( ({ TO->query_my_room(), TO, }), "lock", TP);
    }
} /* set_locked() */

/**
 * This sets the object as being unlocked.
 *
 * @see set_locked()
 */
void set_unlocked() {
    if (!_locked)
        return;
    _locked = 0;
    if (environment()) {
        event( ({ environment(), TO, }), "unlock", TP);
    } else if (TO->query_my_room()) {
        event( ({ TO->query_my_room(), TO, }), "unlock", TP);
    }
} /* set_unlocked() */

/**
 * This tells us whether an object is locked.  It returns 1 if
 * the object is locked and 0 is the object is unlocked.
 *
 * @see set_locked()
 * @see set_unlocked()
 * @return Return 1 if locked and 0 if unlocked.
 */

int query_locked() {
  return _locked;
} /* query_locked() */

/**
 * This tells us whether an object is unlocked.  It returns 1 if
 * the object is unlocked and 0 is the object is locked.
 *
 * @see set_locked()
 * @see set_unlocked()
 * @return Return 1 if unlocked and 0 if locked.
 */

int query_unlocked() {
  return !_locked;
} /* query_unlocked() */

/**
 * This sets the object so that it will lock automatically when closed.
 *
 * @param number 1 for autolock, 0 for no autolock.
 */
void set_autolock(int number) { _autolock = number; }

/**
 * This tells us whether an object will lock automatically when closed.
 *
 * @see set_autolock()
 * @return 1 for true 0 for false;
 */
int query_autolock() { return _autolock; }

/**
 * This sets the property of the key that will unlock the object. This can
 * be a string, or a function pointer which will evaluate to a string.
 *
 * @see set_locked()
 * @param val The property the key must have to unlock the object.
 */
void set_key(mixed val) {
    if (!stringp(val) && !functionp(val))
        return;
    _key = val;
} /* set_key() */

/**
 * This returns the property of the key that will unlock the
 * object.
 *
 * @see set_key()
 */
string query_key() {
    if (stringp(_key))
        return _key;
    if (functionp(_key))
        return evaluate(_key);
    return 0;
} /* query_key() */

/**
 * This sets the skill that will be used when attempting to
 * pick the lock.  By default it is set to "covert.lockpick.safes"
 * so it need only be changed if you want to check a different
 * skill.
 *
 * @see query_pick_skill()
 * @see set_difficulty()
 * @param str The skill to use when picking the lock.
 */

void set_pick_skill(string str) {
  _pick_skill = str;
} /* set_pick_skill() */

/**
 * This returns the name of the skill which is used when
 * determining if the object can be unlocked.
 *
 * @see set_pick_skill()
 */

string query_pick_skill() {
  return _pick_skill;
} /* query_pick_skill() */

/**
 * This sets how difficult the lock on an object is to pick.
 * By default it is set to 200.
 *
 * @see query_difficulty()
 * @param i The difficulty of the lock to pick.
 */

void set_difficulty(int i) {
  _difficulty = i;
} /* set_difficulty() */

/**
 * This returns the difficulty picking the lock on the object.
 * By default it is set to 200 unless it has been changed with
 * set_difficulty().
 *
 * @see set_difficulty()
 */

int query_difficulty() {
  return _difficulty;
} /* query_difficulty() */

/**
 * This can set an object as being stuck, or make it unstuck.
 * Stuck objects cannot be opened, closed, locked or unlocked.
 * Using set_stuck(1) will make the object stuck, and set_stuck(0)
 * will unstick it.
 *
 * @see query_stuck()
 * @param i Use 1 to make the object stuck, and 0 to unstick it.
 */

void set_stuck(int i) {
  _stuck = i;
} /* set_stuck() */

/**
 * This tells you whether an object is stuck or not.  It will
 * return 1 if the object is stuck, and 0 if the object is not
 * stuck.
 *
 * @see set_stuck()
 * @return Return 1 if the object is stuck, and 0 if it is not.
 */

int query_stuck() {
  return _stuck;
} /* query_stuck() */

/**
 * This sets the object as being transparent.
 * A transparent object is one in which you can see the
 * inventory even if it is closed.
 *
 * @see reset_transparent()
 * @see query_transparent()
 */

void set_transparent() {
  _trans = C_TRANS;
} /* set_transparent() */

/**
 * This method removes the current objects transparent
 * status.
 * A transparent object is one in which you can see the
 * inventory even if it is closed.  This is also
 * used for light propogration.
 *
 * @see set_transparent()
 * @see query_transparent()
 */

void reset_transparent() {
  _trans = 0;
} /* reset_transparent() */

/**
 * This method returns the current transparent
 * value of the object.
 * A transparent object is one in which you can see the
 * inventory even if it is closed.  This is also
 * used for light propogration.
 *
 * @see reset_transparent()
 * @see query_transparent()
 * @return 1 if the object is transparent
 */

int query_transparent() {
  return _trans;
} /* query_transparent() */

/**
 * This sets the function to be called when someone attempts to
 * open the object.  The function does not have to be in the
 * object's file, and can be specified using the 'ob' paramater.
 * In most cases the function will be stored in the same file,
 * so use this_object() in these cases.
 *
 * The function will be called with a single string parameter of "open" or
 * "close"
 *
 * @param ob The object in which the function is stored.
 * @param func The function to be called.
 * @see query_open_trap_func()
 * @see query_open_trap_ob()
 */

void set_open_trap(object ob, string func) {
  _trap_open_func =  func;
  _trap_open_ob = ob;
} /* set_open_trap() */

/**
 * This returns the name of the function to be called when
 * someone tries to open the object.
 *
 * @return The function to be called when the object is opened.
 * @see set_open_trap()
 * @see query_open_trap_ob()
 */

string query_open_trap_func() {
  return _trap_open_func;
} /* query_open_trap_func() */

/**
 * This returns the object on which the trap function is stored.
 * The trap function is called when someone tries to open the
 * the object.
 *
 * @return The function to be called when the object is opened.
 * @see set_open_trap()
 * @see query_open_trap_func()
 */

object query_open_trap_ob() {
  return _trap_open_ob;
} /* query_open_trap_ob() */

/**
 * This sets the function to be called when someone attempts to
 * unlock the object.  The function does not have to be in the
 * object's file, and can be specified using the 'ob' paramater.
 * In most cases the function will be stored in the same file,
 * so use this_object() in these cases.
 *
 * The function will be called with a single string parameter of "lock",
 * "unlock" or "pick"
 *
 * @param ob The object in which the function is stored.
 * @param func The function to be called.
 * @see query_lock_trap_func()
 * @see query_lock_trap_ob()
 */
void set_lock_trap(object ob, string func) {
  _trap_lock_func = func;
  _trap_lock_ob = ob;
} /* set_unlock_trap() */

/**
 * This returns the name of the function to be called when
 * some attempts to unlock the object.
 *
 * @return The function to be called when someone attempts
 * to unlock the object.
 * @see set_open_trap()
 * @see query_open_trap_ob()
 */

string query_lock_trap_func() {
  return _trap_lock_func;
} /* query_lock_trap_func() */

/**
 * This returns the object on which the trap function is stored.
 * The trap function is called when someone tries to unlock the
 * the object.
 *
 * @return The function to be called when the object is opened.
 * @see set_open_trap()
 * @see query_open_trap_func()
 */

object query_lock_trap_ob() {
  return _trap_lock_ob;
} /* query_lock_trap_ob() */

/**
 * This method returns the closed and locked status.  The status is
 * 0 if open and unlocked, 1 if locked, 2 if closed and 3 if closed
 * and locked.
 * @return closed and locked status
 */
int query_closed_locked_status() {
    if (_closed && _locked) {
        return CLOSED_LOCKED;
    }
    if (_closed) {
        return CLOSED;
    }
    if (_locked) {

        return LOCKED;
    }
    return 0;
} /* query_closed_locked_status() */

/**
 * This method adds the lock commands to the specified player.
 * It's been abstracted out of init() to make it easier for some
 * odd situations (like the t-shop).
 */
void add_close_lock_commands(object player) {
  if(!player)
    return;

    player->add_command("open", TO,
        "<direct:object:me-here>",
        (: do_open() :) );
    player->add_command("close", TO,
        "<direct:object:me-here>",
        (: do_close() :) );
    if (TO->query_key()) {
        player->add_command("lock", TO,
            "<direct:object:me-here>",
            (: do_lock(0) :) );
        player->add_command("lock", TO,
            "<direct:object:me-here> with <indirect:object:me>",
            (: do_lock($1) :) );
        player->add_command("unlock", TO,
            "<direct:object:me-here>",
            (: do_unlock(0) :) );
        player->add_command("unlock", TO,
            "<direct:object:me-here> with <indirect:object:me>",
            (: do_unlock($1) :) );
    }
} /* add_close_lock_commands() */

/**
 * @ignore yes
 */

void init() {
    add_close_lock_commands(this_player());
} /* init() */

/**
 * @ignore yes
 */
string short_status() {
    return "";
} /* short_status() */

/**
 * @ignore yes
 */
string long_status() {
    // If it is stuck in one state don't bother telling us the state.
    if (TO->query_stuck())
        return "";

    switch (query_closed_locked_status()) {
        case CLOSED_LOCKED:
            return "It is closed and locked.\n";
        case CLOSED:
            return "It is closed.\n";
        default:
            return "It is open.\n";
    }
} /* long_status() */

/**
 * @ignore yes
 */
int check_stealth() {
    mapping hide_invis;
    int hiding, sneaking, difficulty, light, my_light, items_blocking;

    hide_invis = (mapping) TP->query_hide_invis();
    hiding = undefinedp(hide_invis["hiding"]) ? 0 : 1;
    sneaking = TP->query_sneak_level() ? 1 : 0;

    if (!hiding && !sneaking)
        return STEALTH_NONE;

    my_light = TP->query_light();
    light = environment(TP)->query_light();

    difficulty = light + (4 * my_light) / (light + 1);

    items_blocking = sizeof(CLOTHING_HANDLER->query_items_blocking(TO, TP));

    if (items_blocking) {
        difficulty += 50 * items_blocking;
    }

    debug_printf( "Difficulty = %d.\n Skill = %s\n Bonus = %d\n",
                  difficulty, SKILL, TP->query_skill_bonus( SKILL ) );
    switch (TASKER->perform_task(TP, SKILL, difficulty, TM_FREE)) {
        case AWARD:
            write("%^YELLOW%^" + ({
                "You discover something that lets your fingers move more nimbly.",
                "You find yourself capable of deceiving the eye with greater ease "
                "than before.",
                "You realise how to deceive the eye more effectively."
                })[ random(3) ] + "%^RESET%^\n" );
        case SUCCEED :
            return STEALTH_SUCCEEDED;
        default :
            return STEALTH_FAILED;
    }
} /* check_stealth() */

/**
 * @ignore yes
 */
int do_unlock(object *keys) {
    object *gkeys = ({ });
    string key = TO->query_key();
    int inv = 0;
    if (!_locked) {
        TP->add_failed_mess(TO,
            "$D $V$0=isn't,aren't$V$ locked.\n",
            ({ }) );
        return 0;
    }
    if (_stuck) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ stuck.\n",
            ({ }) );
        return 0;
    }
    if (!_closed) {
        TP->add_failed_mess(TO,
            "$D $V$0=isn't,aren't$V$ closed.\n",
            ({ }) );
        return 0;
    }
    if (!key) {
        TP->add_failed_mess(TO,
            "$D $V$0=doesn't,don't$V$ have a lock.\n",
            ({ }) );
        return 0;
    }

    if (key != "by hand") {
        if (!keys || !sizeof(keys)) {
            keys = all_inventory(TP);
            inv = 1;
        }
        gkeys = filter(keys, (: $1->query_property( $(key) ) :) );
        if (!sizeof(gkeys)) {
            if (!inv) {
                TP->add_failed_mess(TO,
                    "You cannot $V $D with $I.\n",
                        keys);
                return 0;
            }
            TP->add_failed_mess(TO,
                "You cannot $V $D.\n",
                ({ }) );
            return 0;
        }
        gkeys[0]->use_key(TO);
    }

    if (_trap_lock_func && _trap_lock_ob) {
        if (!call_other(_trap_lock_ob, _trap_lock_func, "unlock", TO, TP)) {
            return 0;
        }
    }

    set_unlocked();
    switch (check_stealth()) {
        case STEALTH_SUCCEEDED:
          if (sizeof (gkeys)) {
            TP->add_succeeded_mess(TO, ({
                "$N $V $D with $I, managing to stay unnoticed.\n",
                "", }),
                ({ ( gkeys[0] ) }) );
          } else {
            TP->add_succeeded_mess(TO, ({
                "$N $V $D, managing to stay unnoticed.\n",
                "", }),
                ({ }) );
          }

            break;
        case STEALTH_FAILED:
            TP->add_succeeded_mess(TO,
                "$N unsuccessfully tr$y to " + query_verb() + " $D while "
                "staying unnoticed.\n", ({ }) );
            break;
        default:
            if (sizeof (gkeys)) {
              TP->add_succeeded_mess(TO,
                 "$N $V $D with $I.\n", ({ gkeys[0] }) );
            } else {
              TP->add_succeeded_mess (TO, "$N $V $D.\n", ({ }));
            }
            break;
    }
    return 1;
} /* do_unlock() */

/**
 * @ignore yes
 */
int do_lock(object *keys) {
    object *gkeys = ({ });
    string key = TO->query_key();
    int inv = 0;
    if (_locked) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ already locked.\n",
            ({ }) );
        return 0;
    }
    if (_stuck) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ stuck.\n",
            ({ }) );
        return 0;
    }
    if (!_closed && !do_close()) {
        TP->add_failed_mess(TO,
            "$D $V$0=isn't,aren't$V$ closed.\n",
            ({ }) );
        return 0;
    }
    if (!key) {
        TP->add_failed_mess(TO,
            "$D $V$0=doesn't,don't$V$ have a lock.\n",
            ({ }) );
        return 0;
    }

    if (key != "by hand") {
        if (!keys || !sizeof(keys)) {
            keys = all_inventory(TP);
            inv = 1;
        }
        gkeys = filter(keys, (: $1->query_property( $(key) ) :) );
        if (!sizeof(gkeys)) {
            if (!inv) {
                TP->add_failed_mess(TO, "You cannot lock $D with $I.\n", keys);
                return 0;
            }
            TP->add_failed_mess(TO, "You cannot lock $D.\n", ({ }) );
            return 0;
        }
        gkeys[0]->use_key(TO);
    }

    if (_trap_lock_func && _trap_lock_ob) {
        if (!call_other(_trap_lock_ob, _trap_lock_func, "lock", TO, TP)) {
            return 0;
        }
    }

    set_locked();
    switch (check_stealth()) {
    case STEALTH_SUCCEEDED:
          if (sizeof (gkeys)) {
            TP->add_succeeded_mess(TO, ({
                "$N lock$s $D with $I, managing to stay unnoticed.\n",
                "", }),
                ({ ( gkeys[0] ) }) );
          } else {
            TP->add_succeeded_mess(TO, ({
                "$N lock$s $D, managing to stay unnoticed.\n",
                "", }),
                ({ }) );
          }
        break;
      case STEALTH_FAILED:
        TP->add_succeeded_mess(TO, "$N unsuccessfully tr$y to " +
                               "lock $D while staying unnoticed.\n",
                               ({ }) );
        break;
      default:
        if (sizeof (gkeys)) {
          TP->add_succeeded_mess(TO,
                                 "$N lock$s $D with $I.\n", ({ gkeys[0] }) );
        } else {
          TP->add_succeeded_mess (TO, "$N lock$s $D.\n", ({ }));
        }
        break;
    }
    return 1;
} /* do_lock() */

/**
 * @ignore yes
 */
int pick_lock(object player) {
    if (_trap_lock_ob
     && !call_other(_trap_lock_ob, _trap_lock_func, "pick", TO, player)) {
        return 0;
    }
    set_locked();
    return 1;
} /* pick_lock() */

/**
 * This is called when someone successfully unlocks the object.
 * If there is a trap, and the trap function returns true, the
 * object will not be opened.  If the trap function returns
 * false, the object will still be opened even if the trap is
 * sprung.
 *
 * @param player The player who is unlocking the object.
 *
 * @return Returns 1 if the object was unlocked, and 0 otherwise.
 */
int pick_unlock(object player) {
    if (_trap_lock_ob
     && !call_other(_trap_lock_ob, _trap_lock_func, "pick", TO, player)) {
        return 0;
    }
    set_unlocked();
    return 1;
} /* pick_unlock() */

/**
 * @ignore yes
 */
int do_open() {
    if (!_closed) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ already open.\n",
            ({ }) );
        return 0;
    }
    if (_stuck) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ stuck.\n",
            ({ }) );
        return 0;
    }
    if (_locked && !do_unlock(0)) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ locked.\n",
            ({ }) );
        return 0;
    }

    if (_trap_open_func && _trap_open_ob) {
        if (!call_other(_trap_open_ob, _trap_open_func, "open", TO, TP)) {
            return 0;
        }
    }

    set_open();
    if (!TO->query_door_name()) {
        switch (check_stealth()) {
            case STEALTH_SUCCEEDED:
                TP->add_succeeded_mess(TO, ({
                    "$N $V $D, managing to stay unnoticed.\n",
                    "", }),
                    ({ }) );
                break;
            case STEALTH_FAILED:
                TP->add_succeeded_mess(TO,
                    "$N unsuccessfully tr$y to " + query_verb() + " $D while "
                    "staying unnoticed.\n", ({ }) );
                break;
            default:
                TP->add_succeeded_mess(TO,
                    "$N $V $D.\n",
                    ({ }) );
                break;
        }
    }
    return 1;
} /* do_open() */

/**
 * @ignore yes
 */
int do_close() {
    if (_closed) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ already closed.\n",
            ({ }) );
        return 0;
    }
    if (_stuck) {
        TP->add_failed_mess(TO,
            "$D $V$0=is,are$V$ stuck.\n",
            ({ }) );
        return 0;
    }
    if (_trap_open_func && _trap_open_ob) {
        if (!call_other(_trap_open_ob, _trap_open_func, "close", TO,TP)) {
            return 0;
        }
    }

    set_closed();
    if (_autolock)
        set_locked();
    if (!TO->query_door_name()) {
        switch (check_stealth()) {
            case STEALTH_SUCCEEDED:
                TP->add_succeeded_mess(TO, ({
                    "$N $V $D, managing to stay unnoticed.\n",
                    "", }),
                    ({ }) );
                break;
            case STEALTH_FAILED:
                TP->add_succeeded_mess(TO,
                    "$N unsuccessfully tr$y to " + query_verb() + " $D while "
                    "staying unnoticed.\n", ({ }) );
                break;
            default:
                TP->add_succeeded_mess(TO,
                    "$N $V $D.\n",
                    ({ }) );
                break;
        }
    }
    return 1;
} /* do_close() */

/**
 * @ignore yes
 */
string *parse_command_adjectiv_id_list() {
    switch( query_closed_locked_status() ) {
        case CLOSED_LOCKED:
            return ({ "closed", "locked" });
        case CLOSED:
            return ({ "closed", "unlocked" });
        case LOCKED:
            return ({ "open", "locked" });
        default:
            return ({ "open", "unlocked" });
    }
} /* parse_command_adjectiv_id_list() */

/**
 * @ignore yes
 */
mixed *stats() {
  return ({
    ({"closed", query_closed()}),
    ({"transparent", query_transparent()}),
    ({"key", query_key()}),
    ({"difficulty", query_difficulty()}),
    ({"locked", query_locked()}),
    ({"stuck", query_stuck()}),
    ({"open trapped", _trap_open_func != 0}),
    ({"lock trapped", _trap_lock_func != 0}),
    ({"pick skill", query_pick_skill()}),});
} /* stats() */
/* EOF */