lock

std
OBJECT
	/std/lock


LAST UPDATE
	Mateese, 09-Aug-96 01:15 MET


SYNOPSIS
	#include <lock.h>
	#include <search.h>

	inherit "std/lock";


DESCRIPTION
	This is the standard lock. It implements the basic mechanics
	of a locking mechanism, along with some auxiliary functions.
	It is not meant for stand-alone use, but instead of
	inheritance to make a thing lockable.

	The lock implements the three states 'open' (LOCK_OPEN),
	'closed' (LOCK_CLOSED) and 'locked', accessible as the builtin
	property 

	  int P_LOCKSTATE  "LockState"

	Changes in the LockState are reflected in the inheriting
	objects adjectives.

 	NOTE: Even when inherited, SetLockState() is the ONLY way to
  	      change the state!
	      This is to allow the inheriting object to get notified
	      about any lock-state change by simple overloading of the
	      SetLockState() function.

	Besides this, a lock features also these builtin properties

	  mixed P_KEYCODE  "KeyCode"
	    Defines the (one!) keycode this lock accepts.
	    Default is 0, which means 'no code'.

	  string * P_KEYIDS   "KeyIds"
	    This is an array of strings, determinating all key ids this
	    lock accepts.

	  string LockStateText ()
	    Depending on P_LOCK_STATE, one of the texts "open", "closed"
	    or "locked" is returned.
	    Use only this function to get a string for the P_LOCK_STATE!

	  int P_PICK_CHANCE  "PickChance"
	    This value describes the percent chance a thieve (or similar
	    being) has to pick the lock without having the right key.
	    Default value is 100, a value of 0 disables any picking.
	    Note that it's the task of the being (resp. its
	    guildobject) to check the chance - the lock just stores
	    it.

	  string LockDescription(void|string id)
	    This function returns a description of the lock, mainly based on
	    it's P_PICKCHANCE.
	    The lock's create() sets this function as the SubDetail "lock".
	  

	If no KeyIds are specified, the lock can't be locked, just
	opened and closed. If KeyIds are specified, the class
	attribute LOCKABLE is added to the object.

	The lock has to be initialized by a call to

	  void create ().

	The create() calls the function AddSubDetail("lock") and stores
	a reference to LockDescription() for the detail description.

	The state of the lock can be changed anytime via SetLockState(),
	but to perform the additional checks against the keys, this
	functions has to be used:

	mixed TurnLock (int unlock, object key, void | mixed keycode)
	  Lock (<unlock> == 0) or unlock (<unlock> != 1) this lock with the
	  given <key> using the given <keycode>.
	  The keycode defaults to that of the key.
	  If this function changes the state of the lock, it does this
	  by calling SetLockState().

	  Results:
	    0 = LOCK_OK      : operation successful
	        LOCK_NOCHANGE: lock was already (un)locked.
	        LOCK_NOTLOCK : lock is not lockable (is either open
	                       or has no KeyIds defined)
	        LOCK_KEYWRONG: key doesn't fit
	        LOCK_KEYDENY : key denies operation w/0 special message
	        <string>     : Denial message from the key.


	To ease programming, following functions are also implemented:

	int ValidKey (object key)
	  Return non-zero if the <key> has one of the defined KeyIds.
	  You'll get a runtime-error if no KeyIds are defined.
  

	object *FindKey (mixed key)
	  Search in the players inventory for objects which match
	  <key> and are valid keys according to KeyIds.
	  You'll get a runtime-error if no KeyIds are defined.

	  Result:
	    An array of the found valid key objects (could be empty if
	    no key fit), or 0 if the player has no 'key'.


	The interface to the player can hardly be standardized, since
	the commands and messages are depending of the object
	inheriting the lock, not the lock itself.
	Thus, only under-the-hood work can be supported.

	int | object* ParseArgs (string arg, int mandatory, int where)
	  Parse a commandline for a '<thing>' or '<thing> with <key>'
	  pattern and validize that '<thing>' is this object (searched
	  according to <where>, default is SEARCH_ENV_INV: in the
	  environment of the player, then in its inventory).
  	  If '<key>' is specified, all matching keys in the players
  	  are selected, else all keys.
  	  In <mandatory> mode, the player _must_ have a (matching) key
  	  else the function will notify an error.

	  Results:
	          0: An error occured. An approbiate notify_fail() has
		     also been issued. 
	    <array>: Valid keys found (may be empty).


	int TryLocking (object *keys, void|int unlock)
	  Try to lock (<unlock> == 0) or to unlock (<unlock> != 0) the
	  lock with one of the given <keys>.
	  Except for key-denial-messages, no own messages are issued.

	  Results:
	    <int>: The index of the successfully used key.
	       -1: Failure.


	The modification of the appearance of the lock using object
	may be programmed using these:

	string ModifyInvShort (string text)
	  To be called with the InvShort() of the lock using object as
	  <text>, this function returns <text> modified according to
	  the P_LOCK_STATE. If the lock is closed or locked, <text> is
	  not modified; if the lock is open, either "an open <text>"
	  or "<text> (open)" is returned.

	string ModifyLong (string text)
	  To be called with the (Int)Long() of the lock using object
	  as <text>. 
	  The function returns "<text>It is `LockStateText()`.\n"

	The /std/lock implements basic functions for the lock commands
	'open', 'close', 'lock' and 'unlock'. The commands may be used
	as following:

	  "open <object>"
	    Opens the lock. If it is locked, and the player has the
	    right key, it is unlocked first.
	  "open <object> with <key>": 
	    Opens the lock. If it is locked, and the player specified the
	    right key, it is unlocked first.
	  "close <object>"
	  "close <object> with <key>"
	    Closes the lock.
	  "lock <object>"
	     Locks the lock if the player has the right key.
	     If it is open, it is closed first.
	  "lock <object> with <key>"
	     Locks the lock if the player has specified the right key.
	     If it is open, it is closed first.
	  "unlock <object>"
	     Unlocks the lock if the player has the right key.
	  "unlock <object> with <key>"
	     Unlocks the lock if the player has specified the right key.

	The commands are bound in

	  void init ()

	to the functions

	  int fopen (string str, void|int where)
	    Implements "open" and "close", returns 1 on success.
	    <where> is passed to ParseArgs().

	  int flock (string str, void|int where)
	    Implements "lock" and "unlock", returns 1 on success.
	    <where> is passed to ParseArgs().


	To notify the players about the actions done, both fopen() and
	flock() call DoActionFor().

	  int DoActionFor ( int action, int type, void|object *keys
                          , void|int kix)
            Notify the players about the action, determined by
            <action> and <type>, using write(), show() and notify_fail().
	    If the result is 1 or 0, the command is terminated with
	    that result, if the result is <= 0, the command execution
	    may continue (if possible).
	    The given function returns messages suitable for most
	    objects.

	<action>s are according to the possible commands:
	LOCK_DO_OPEN, LOCK_DO_CLOSE, LOCK_DO_LOCK, LOCK_DO_UNLOCK.
	<type> determines what happened:
	  LOCK_ACT_ALREADY: the action commanded need not be
	    performed, e.g. closeing an already closed chest.
	  LOCK_ACT_LOCK: the lock is locked/unlocked using 
	    the key <keys>[<kix>].
	  LOCK_ACT_OPEN: the lock is opened/closed.
	  LOCK_ACT_NOKEY: the lock needs to be locked or unlocked, but
	    the player has no keys.
	  LOCK_ACT_WRONGKEY: the lock needs to be locked or unlocked, but
	    the player has not the right key.

	Note that some <types> may happen en passant: locking an open
	chest results in action LOCK_DO_LOCK with both types
	LOCK_ACT_OPEN and LOCK_ACT_LOCK in consecutive calls.


INHERITANCE TREE
	lock


SEE ALSO
	locks(C), thing(S), door(O), chest(O), key(O)