room

std
OBJECT
        /std/room


LAST UPDATE
        Mateese@OSB, 98/07/11

SYNOPSIS
        inherit "/std/room";

        #include <config.h>
        #include <properties.h>
        #include <rooms.h>

DESCRIPTION
        A room (to be interpreted in a physical sense) is an outer
        encumbrance for an inner space into which objects can be
        placed. Thus it features all the descriptional properties of a
        normal thing, but in a special 'internal' variant.

        The room needn't be totally enclosed: it's hull can have
        holes, called 'exits', leading to other rooms. Each exit is
        specified by the command the player has to give to move
        through that exit.
        Though serving an unlimited traffic is the most common
        state of life for exits, there are situations in which exits
        shall be closed for a certain time. This is done by placing
        blocking objects, called 'doors', right before the exit and
        catching the exit command if a trespass is to be denied.

        Though the room itself is not directly involved into the
        door-exit-handling, it imposes a defined protocol on legal
        doors, and it holds a list of the currently active doors and
        their states (see also door(S)). This list makes it possible
        to adapt the room's description to the current door state.

        A special demand for free spaces are that they need to be
        lighted. Rooms are able to emit light on their own, but can
        also connect to a weather-server (standard is NIGHTDAY,
        defined in nightday.h) to get light from the sun.


        --- std/room ---

        The perceptional routines Long(), Short(), Smell()
        and Noise() from /std/room/description are redefined here
        to return the approbiate details given as arguments.

          void create (void|int noreplace)
            Calls the inherited create() functions of /std/base and
            /std/room/restrictions.
            It also calls /std/base:replace_pgm() if <noreplace> is
            not specified or zero, so be alert when doing dynamic
            rooms or to-inherit rooms just consisting of an create()!

          string Long (void|string what)
            Returns the internal long description, or that of the
            detail <what> if given.

          string ExaLong (void|string what)
            Returns the internal long description under closer
            examination, or that of the detail <what> if given.

          string Noise (void|string what)
            Returns the internal noise description, or that of the
            detailed noise <what> if given.

          string Smell (void|string what)
            Returns the internal smell description, or that of the
            detailed smell <what> if given.

          string Read (void|string what)
            Returns the internal read description, or that of the
            detailed message <what> if given.

        --- std/room/description ---

          string P_INT_SHORT   "IntShort"
          string P_INT_LONG    "IntLong"
            The short and long description of the inner appearance.
            Both properties are analogue to their P_SHORT/P_LONG
            counterparts.

          string P_INT_NOISE   "IntNoise"
          string P_INT_SMELL   "IntSmell"
            The smell and the noise noticable within the room.

          string|closure P_HELP_MSG  "HelpMsg"
            A string containing a short informational text about the
            object (or room). It is queried by the player 'help' command.
            Instead of a string, a closure may be used as value.
            Upon query, the closure is executed and has to return the
            informational text to be displayed.
            If a player ask for help on an object with not P_HELP_MSG
            set, a BUG report is generated. This can be avoided by
            setting the P_HELP_MSG to the empty string (default for rooms).
            In this case, the player will see a default text.

        To retrieve the complete description of the whole room
        (appearance and contents), use:

          string GetIntDesc ( void|int    nolong
                            , mixed       exclude
                            , void|object player
                            )
            Return a printable string describing the whole room and
            its current contents excliding the current player (it is
            at least the ""-string).
            If <nolong> is not zero, the returned string does not
            contain the P_INT_LONG.
            The functions also inserts exits and doors if the player
            is obvious mode.

            <exclude> is one or more objects to be ignored in the inventory
            listing, if given. If it is a closure, it is called for
            each inventory object and has to return non-zero if the
            object is to be excluded.
            <player> denotes the living who queries the GetIntDesc()
            and defaults to this_player().

          string GetExaIntDesc ( mixed       exclude
                               , void|object player
                               )
            Like GetIntDesc(), this returns the long description suitable
            for an examination, not just a simple look.
            As the main difference to GetIntDesc() is in the long
            description, the parameter <nolong> would be superfluous.


        Get(Exa)IntDesc() allows an arbitrary string to be insert between
        the room's own description and the list of contents:

          string P_PRECONTENT  "PreContent"
            If set to a string, this is printed by GetIntDesc() just
            prior to the list of contents.

        The notion of outside-of-here (though important mostly for
        Locate() and the look commands) may be modified using these
        non-builtin properties:

          string P_PREOUTSIDE  "PreOutside"
            If set to a string, it will be printed by the look
            commands when recursing from the current room to its
            outside. If not set, a default string will be used.

          object P_OUTSIDE     "Outside"
            For object locations, this non-builtin(!) property denotes
            the room which is to be considered 'outside'.
            E.g. for a chair this would be the room outside the room
            holding the chair.
            If not set, environment() will be used.

        The player objects do not query the physical description
        properties directly, but instead using these functions:

          string IntLong (void|string what)
            Returns the internal long description.

          string ExaIntLong (void|string what)
            Returns the internal long description under closer
            examination. If there is no special description for this,
            "You see nothing special.\n"+IntLong(what) is returned.

          string IntShort (void|string what)
            Returns the internal short description.

          string IntNoise (void|string what)
            Returns the internal noise description.

          string IntSmell (void|string what)
            Returns the internal smell description.

          string Content ( void|string  what
                         , mixed        exclude
                         , void|object  player
                         )
            Return a listing of the inventory, prefixed by
            P_PRECONTENT if this set.
            If <exclude> is given, it determines the objects not to be listed
            in the inventory. If given at all, this_player() is always
            ignored. If it is a closure, it is called for
            each inventory object and has to return non-zero if the
            object is to be excluded (see MakeExcl()).
            <player> denotes the living who queries the Content()
            and defaults to this_player().
            The result is a multilined string, but may "" or 0 for
            totally empty rooms.

          object * MakeExcl (mixed exclude[, mixed add])
            Auxiliary function, used by Content() to prepare the <exclude>
            argument. This function is provided so that other people
            can overload Content() more easily.
            The function takes the <exclude> argument and makes it an
            array of objects. <exclude> can be a closure, in which case
            it is called for each inventory object and has to return
            non-zero if the object is to be exluded. It can also be
            a single object or an array of objects to be excluded.
            If given, <add> is added to the created exclude array.
            <add> can be a single object or an array of objects.
            The final array is returned as result.

        The argument 'what' is either 0 if the player issued a general
        perception command (like 'look') or a string containing the
        object "<thing>" of a directed perception command (like 'smell
        <thing>'). This is used on top level(!) to implement details.

        The value returned by these functions is in fact not just the
        property value, but instead the property value extended by the
        extra data (if any). The single extra data for these functions
        must be strings, which are concatenated to the value of the
        property before the result is returned.

        For the plain /std/room these functions return just the
        contents of the associated properties. This may not be valid
        for derived objects.

        To mark a room as being part of a killzone, implement:

          int QueryKillZone ()
            This function has to return non-zero if the room is part of
            a killing zone.
            There mustn't be a 'SetKillZone()' function, and this must
            be a hardcoded property!

        Not really a description, the room may be marked as being
        explorable (assuming that its accepted as such by the Quest
        Department):

          mixed P_EXPLORABLE  "Explorable"
            This property contains the value 1 if the mere entering of
            the room counts as 'act of exploration', 
            or the name of the detail whose scrutinization counts,
            or 0 if nothing is to be explored (or if its programmed
            manually). Alternatively it contains an array of the
            aforementioned values.
            If you want details react just on a specific action,
            prepend its string with "look:", "listen:", "smell:" or
            "read:" (notice that the _verbs_ form the prefix!).

          mixed AddExplorable (mixed new)
            Add <new> to the current settion of P_EXPLORABLE.
            <new> may be a single string or an array of strings.

          int DoExplore (mixed arg)
            Check if <arg> is explorable and call
            this_player()->SetExplored() on success.
            Result is 0 on failure and non-zero on success.

        IMPORTANT: Explorable rooms must be checked in with the 
        /p/daemons/explorer controlling object.

        Nightfall needs more explorable rooms and details, so don't hesitate!


        --- std/room/restrictions ---

        The restrictions part serves all those purposes where
        information, light, data or objects flow in or out of the
        room.


          int P_INDOORS      "Indoors"
            A flag denoting if the room is indoors (!= 0)
            or outdoors (== 0).

          string P_SERVER    "Server"
            The object_name() of the weather server to use, if the room
            is outdoors.

          mixed P_OUTDOORS   "Outdoors"
            If 0, the room is an indoors room.
            Else the value of the property denotes the weather-server
            in charge for this room.
            When set to a numeric value != 0, it is interpreted and
            set as the default weather server NIGHTDAY.
            This is no real property, but instead projected onto
            P_INDOORS and P_SERVER.

          mixed FilterWeatherData (object client, mixed *data, int newstate)
            If the weather server notifies players and clients about
            weather changes, it filters the weather <data> through all
            environments of each <client>. <newstate> is the state the
            server will upon completion of the notification.
            The room may apply changes to the given <data> array and
            return it (default is that no changes are done).
            If it returns 0, nothing of the data will be displayed to
            the client.
            It is still up to the weather server to finally display
            the data.

          int P_BRIGHT   "Bright"
            The amount of light the room emits to the inside.

          int P_INT_LIGHT    "IntLight"
            The total amount of light emitted within the room.
            This is a sum of the rooms own brightness, the incoming
            sunlight and the light the content emits.
            When set, the P_INT_BRIGHT is modified to achieve the new
            lightlevel.
            For this property, the two calls have additional functionality:

              int QueryIntLight (int nosun)
                With <nosun> = 0, this returns just total amount of
                light 'visible' emitted in the room.
                If <nosun> is non-zero, the function returns the total
                amount of light emitted withing the room w/o incoming
                sunlight.

              int SetIntLight (int l, int nosun)
                This sets the total amount of light 'visible' in the
                room (by modifying P_INT_BRIGHT).
                If <nosun> = 0, <l> is the new total amount to
                achieve.
                If <nosun> is non-zero, <l> is the new amount of light
                to be emitted independant of the sun (thus making
                SetIntLight(n, 0) == SetIntLight(n-QuerySunLight(),1)).

          int P_SUNBRIGHT   "SunBright"
            Determines the bright of the normal sun, default value
            is MAX_SUNBRIGHT.

          int QuerySunLight ( void )
            Returns the amount of incoming sunlight (0 for indoor
            rooms), as queried from the weather server.
            If you want to have dimmed sunlight in your room (e.g. for
            a forest) this is the function to overload.
            The value returned is already scaled by P_SUNBRIGHT/MAX_SUNBRIGHT.

          int P_CANSEE   "CanSee"
            If this property is set to non-zero, every living in the room
            is able to see, not regarding the light.
            The actual evaluation is done in the lfun CanSeeHere():
            
              int CanSeeHere(void|object living)
                Check if <living> can see even if the lighting is too dark
                or too bright. Result is 1 if the living can always see,
                and 0 if the normal light limits apply.
                The default behaviour is to check the P_CANSEE property.
            CanSeeHere() is called as part of the normal CanSee/CantSee()
            processing in /std/living/description.


        Note that after initialisation the room has an automatic lighting
        of 75% of MAX_SUNBRIGHT. This lighting will vanish with any change
        of P_INDOORS, P_OUTDOORS, P_INT_LIGHT or P_BRIGHT.


          mixed * QueryDayData ()
            If the room is an outdoors room, the StateData for the
            current daystate is returned, else 0.

          int QueryDayState ()
            If the room is an outdoors room, the DayState is
            returned, else 0.

          string QueryDayDesc ()
            If the room is an outdoors room, the description of the
            current daystate is returned, else 0.

          int P_MAX_WEIGHT   "MaxWeight"
            The max amount of weight the room may contain (note that a
            pure room has no weight of its own!).
            It may be set any time, but no lower than the current
            contents weight.
            It is set on creation to 2**30.

          int P_MAX_INV      "MaxInv"
            The max number of items the room may contain.
            If set to 0, any number is allowed.

          int QueryWeightContent ( void )
            Return the total weight of the objects within the room.

          int MayAddWeight ( int w )
            Return non-zero, if it is possible to change the actual
            weight of the contents by <w>.

          int MayAddItem ( )
            Return non-zero, if it is possible to add another item to
            the rooms inventory, as determined by P_MAX_INV.

          void AddIntWeight ( int w )
            Add weight <w> to the weight of the contents.

          int P_TPORT        "TPort"
            Specifies what teleports are forbidden:
              TPORT_NO  : no teleporting is allowed
              TPORT_IN  : teleporting in is allowed.
              TPORT_OUT : teleporting out is allowed.
              TPORT_BOTH: all teleports are allowed.
            The values are included from <magic.h>.

          string P_TPORT_REASON  "TPortReason"
            This non-builtin(!) property may hold the reason why
            teleporting is forbidden.


        To forbid or allow the use of magic in a room, use:

          mapping P_MAGIC_PROTECTION  "MagicProtection"
            This mapping is indexed by the types of magic (see
            <magic.h>), and has to contain a "Sorry"-message for each
            kind which is not allowed in this room.

          string AddMagicProtection (int type, string message)
            Forbid the use of <type> magic, and set <message> as the
            text to print if someone tries to.
            Result is the set string.

          mapping ForbidAllMagic (void|string str)
            Forbids the use of any magic. If <str> is given, it is
            used as the message to print, else a default message is
            set.
            Result is the update P_MAGIC_PROTECTION.

          string QueryIsMagicForbidden (int type)
            Check if magic of <type> is forbidden. If not, return 0,
            else the "sorry" string which would be printed.


        The light propagation uses these functions:

          protected void emit_intlight (int l)
            The room emits <l> more light to its inside.
            Call the lfun light_from_outside() for all contained
            objects with <l> as parameter, and increment P_INTLIGHT
            by <l>.
            Do not call this function manually!

          protected void light_from_inside (int l)
            Some contained object emits <l> more light. Increment
            P_INTLIGHT by this amount, and call
            light_from_outside(<l>) for all other contained objects.
            Do not call this function manually!


        Searching an item in a room can be quite cumbersome, esp. if
        the light has to be considered, so this has to be used:

          object*|object Locate ( void|mixed what
                                , void|int mode
                                , void|object * also)

        For a detailed documentation, see /doc/concepts/search.

        An auxiliary function used by Locate() is

          object * filterWornWielded (object * objs)
            The function is passed a list of <objs> and returns a list
            of those, which are neither worn nor wielded nor equipment.
            In general, it has to return those objects which shall not
            be subject of a generic 'fooey all' action.


        To support the vision system, the room implements these
        functions which are called as part of the show() and see()
        simul_efuns:

          object * GetViewers (void|object|object * excl)
            This function returns an array of all objects in the room
            which are able to see. By default these are all livings
            with the right vision settings.
            If specified, <excl> denotes one or more objects which are
            to be ignored in the check. These objects are not
            returned with the result.

          int _view_filter (object elem)
            This function is called for each checked <elem> in the
            room by GetViewers(). It has to return non-zero if the
            object can see.
            By default these are livings with the proper vision
            setting.

          int filter_message( int class, string * msg )
            This function, which is default not there, is used to filter
            the messages of CMSG_ROOM that are sent to players in that 
            room. The function _MUST_ return a valid message class, if
            the message should remain unchanged it has to return class.
            The msg is an array consisting of two entries, the first is
            the message for those who see in the room, the second the one
            for those who see not (which might be 0). Important is that 
            always an array is passed to that function, even if MMSG_SEE
            is not set. But, if MMSG_SEE is not set the second array parameter
            is unused.
            Common use might be to modify MMSG_SEE or to add MMSG_DISCARD.

          object * display (string|string * msg, void|object|object* excl)
            * OBSOLETE FUNCTION - USE msg_room (simul efun) instead! *
            This function displays <msg> to all seeing objects in the
            room, except those specified in <excl>.
            <msg> may be one string for the 'seeable' message only, or
            an array of two strings for both the 'seeable' and the
            'non-seeable' message.
            Result is an array of all recipients.

          int _display_filter (object rec, mixed * msg)
            * OBSOLETE FUNCTION - use filter_message instead! *
            display() uses this function to allow special treatment
            for selected clients. The function has to return non-zero
            if it notified <rec> itself of the <msg>, else 0 (the
            default).
            <msg> is the message to display and is always an array,
            and MUST NOT be modified, unless you make a copy.


        When livings move into or out of the room, the room will
        announce this. To do this, /std/room/restrictions defines own
        notify_{enter,leave}-functions which do the announcement.
        Also, if the living comes from somewhere using an other
        weather server, it will get a description of the current sky.
        The livings P_OUTDOORS will be updated as well.

        If the living is invisible, nothing is announced to the room.

        Livings normally use M_GO or M_TELEPORT, but some are moved
        using M_SPECIAL.

        M_SPECIAL make use of the <extra> arg, which is then a single
        string or an array of strings (both may be empty).
        Ideally, <extra> = ({ "<out_msg>", "<in_msg>", "<living_msg>" }),
        though the room itself cares just for the first two ones.
        Each of the messages may be just a string, used for visible
        messages, or an message array for visible/non-visible messages.

        If <extra> is just a string, it is taken for all visible messages.

        If a living moves via M_GO or M_TELEPORT, <out_msg> and
        <in_msg> are taken from its properties (M)MSGOUT and (M)MSGIN.
        However, if <extra> is specified together with M_TELEPORT, the
        messages are generated as for an M_SPECIAL move.

        M_GO also allows the <extra>-Parameter to be used for the
        visible moving messages. If specified, the
        approbiate msg from it will be added to the general
        enter/leave message as ' <msg>'. Thus a complete
        enter-message would be "<name> <MSGIN> <extra_msg>.\n".

        However, all messages must not end with ".\n".

        For the initialisation, the lfun

          void create(void)

        is implemented here.


        --- /std/room/details ---

        It is possible to equip the room with lots of details without
        the creation of an own object for each detail. Instead, the
        room will 'fake' those objects.

        Details are divided into 'normal' details for which the
        information is stored in the room, and 'special' for which the
        room gets the information by a call to an arbitrary function.

        The details cooperate with /std/room/description:DoExplore()
        to implement the explorer facilities.

        Note: If there are doors known to the room, the detail 'doors'
              will automatically be set to return a list of all visible
              and active doors - when queried with GetDetail().
        Note: If the details 'sky' or 'heaven' are not set, outdoor
              rooms will return the current weather description.
              For compatibility, this is done by a call to
                string fsky(string str)
              which returns the description. On this call, <str> is
              set to the detail queried ("sky" or "heaven").


        NOTE: The functions AddDetail, AddNoise, AddSmell, AddReadMsg are
              mapped internally now to vitems (virtual items), even with 
              their remove-functions (RemoveDetail,...). For more
              informations see 'man vitems'. One call to AddVItem can
              replaced some single calls of the functions mentioned above.
              Vitems are added with AddVItem() - see manual page of vitems!
              You can do a lot of more than adding simple details with
              vitems, but see for the manual page for more.


          mapping P_DETAILS   "Details"
            All details of the room.
            Keys are the detail-ids, the data is the description
            string (or an array of two strings for the distinction
            'look at' and 'examine'), or a function/closure returning
            the actual description string/string array.

          void AddDetail ( string|string *id
                         , string|string *|closure desc
                         , void|string exadesc)
            Sets the description for the detail <id> to <desc>.
            If <id> is an array of strings, each entry in that array
            is taken as separate id, thus given a hole set of ids the
            same description.
            If both <desc> and <exadesc> are given as simple strings,
            the detail will be set as ({ <desc>, <exadesc> }).
            if <desc> is a closure, it is called with the detail looked
            at as argument and has to return the description.
            If <desc> is ({ "#call_other", <obj>, <funcname>, ...}),
            it will be compiled into the appropriate closure and stored.
            
          void RemoveDetail (string|string *id)
            Removes the description for the one or more specified <id>s.

          string|string* GetDetail (string id)
            Return the description for the detail <id>, may it be
            normal or special.If no such <id> was defined, 0 is
            returned.

        The same exists for noises:

          mapping P_NOISES   "Noises"
          void AddNoise (string|string *id, string|closure desc)
          void RemoveNoise (string|string *id)
          string|string* GetNoise (string id)

        and smells:

          mapping P_SMELLS   "Smells"
          void AddSmell (string|string *id, string|closure desc)
          void RemoveSmell (string|string *id)
          string|string* GetSmell (string id)

        and of course they can be read as well:

          mapping P_READ_MSGS   "ReadMsgs"
          void AddReadMsg (string|string *id, string|closure desc)
          void RemoveReadMsg (string|string *id)
          string|string* GetReadMsg (string id)


        Note: if the mapping set for the details/smells/... contains
        arrays as keys, these arrays are flattened.
        Thus, Set(P_DETAILS, ([ ({ "foo", "bar" }): "Nothing happens.\n"]))
        is equivalent to Set(P_DETAILS, ([ "foo":"Nothing happens.\n",
        "bar":"Nothing happens.\n" ]))


        To perform the magic, the lfun

          int id (mixed try_id)

        is implemented here.

        To make the details work, the GetXXX() functions have to be
        combined with the IntLong()/IntSmell()/IntNoise() function on
        top level (see std/room/description).


        --- std/room/items ---

        The room has provisions for easy creating and configuring of
        items, and also offers a special treatment for money.

        The items are created and moved into the room. Every reset all
        items are checked, and depending on the refresh action
        specified at creation several measures might be taken:

          REFRESH_NONE
            Nothing is done at all (the default).
          REFRESH_DESTRUCT
            If the item was destructed, it is recreated.
          REFRESH_REMOVE
            If the item was removed from the room, it is recreated.
          REFRESH_HOME
            If the item was removed from the room, it is put into the
            room again, else it is recreated.
            In fact, this is (REFRESH_DESTRUCT|REFRESH_MOVE_HOME).
          REFRESH_ALWAYS
            Combines REFRESH_DESTRUCT and REFRESH_REMOVE.

        The aforementioned actions may be combined with one of the
        following subactions (by |'ing the constants together).

          REFRESH_MOVE_HOME
            If the item was removed from the room, it is put into the
            room again.
          REFRESH_RESET
            If the item exists, it's reset() is called.
          REFRESH_PROPS
            All properties of the item are reinitialized.
          REFRESH_FUNC
            A specified function is called upon refresh of an object.


        If an item is newly created, it is done in this sequence:
         - the item is cloned
         - it's properties are set
         - it is moved into the room
         - item->Aloha() is called (see below)

          mixed * P_ITEMS   "Items"
            The array of all item specifications.
            Each entry describes one item and is itself an array with
            these fields:

              string|string*  [RITEM_FILE]
                The filename of the blueprint to clone, or an array
                of filenames.
                If the value is an array, the actual filename to clone
                from is selected by random from the array. 0-entries
                are valid and lead to the cloning of no item.
                [Idea by Kassandra @ Morgengrauen].
                Instead of the object_name, the/each entry may be a closure
                which is then called to return the newly cloned.
              int     [RITEM_REFRESH]
                The refresh actions.
              mapping(*) [ ]
                The mapping for initialization of the item's
                properties. Alternatively, this can be an array of
                mappings, if some of the item's properties need to be
                initialised in a special order. Properties not mentioned here
                are not changed.
                This entry may be omitted.
              string|closure [ ]
                Function to call if the object was refreshed.
                Arguments are: (<obj>, [RITEM_REFRESH], <nr>)
                <obj> is the object refreshed, <nr> it's sequential number
                counted from 0.
                This entry may be omitted.
              object  [<n]
                ...
              object  [<1]
                The actually created (n-1) items.

            Note that the length of each entry varies.

          object * AddItem ( string|string*        file
                           , void|int              refresh
                           , void|mapping|mapping* prop
                           , void|int              n
                           , void|string|closure   fun)
            Add a <n> items (at least 1) cloned from the blueprint <file>
            to the room and mark them for later refresh according to
            <refresh>, with <fun> to call on refresh.
            If <prop> is given, each newly created item will undergo
            an item->SetProperties(<prop>).
            Adding the item implies an initial 'refresh' of it.
            Result is an array with the added items, or 0 if none
            were added (resp. or if they were of the REFRESH_NONE type).
            This array is a copy of the entry placed in P_ITEMS and
            thus consists of:
              ({ filename, refreshmode, ..., 1st item, 2nd item, ... })


          object * AddItem ( closure|closure*    cfun
                           , void|int            refresh
                           , void|mapping        prop
                           , void|int            n
                           , void|string|closure fun)
            Same as the 'normal' AddItem, except that the filenames of
            the objects are now indirectly determined by the specified
            function(s) 'cfun'. These functions are called upon
            creation of the item and have either to return the
            filename of the object to clone, or have to clone the
            object itself and return that.

          void RemoveItem ( string *|string file )
            Remove the data for <file> from P_ITEMS.
            If <file> is a string, just the entry for <file> is
            removed.
            If <file> is an array of strings, all entries containing
            at least all entries of <file> are removed.
            Note that the function does not destruct the actual items.


        For an easier initialization of an object, a pseudoproperty
        exists:

          mixed * P_ITEMS_REFRESH   "ItemsRefresh"
            Setting this property set P_ITEMS to the given data, and
            performs an initial refresh of all items. Additionally,
            all still-carried P_ITEMS already existing are destructed.
            Note that the number of items to create is indirectly
            given by the size of each of the item entries.
            Result is P_ITEMS after the complete refresh.
            This is a write-only property.


        To equip a room with money, set the builtin property

          mixed P_MONEY  "Money"

        to the desired value. This can be a simple integer, denoting
        the absolute value to be given in standard coins, or a mapping
        denoting each coin and its amount of (e.g. (["silver":12]) ).
        The money is refreshed both when set and with each reset() by a
        call to

          int RefreshMoney()

        which checks if the room contains less worth of money than set
        in P_MONEY, creating additional money when needed. It does not
        reduce the amount of contained money.


        To perform the above tasks, the lfuns

          void reset ()
          void Aloha (int flag)

        is implemented here. The Aloha() function (if called with a
        negative argument) just calls reset(), which then will perform
        the refresh. This is to make sure that a reset in the
        outermost room will cause a 'deep reset' of all contained objects.


        To give newly created items the opportunity for additional
        setup, the lfun Aloha() is called in them after they have been
        cloned _and_ moved into the room:

          void Aloha (int flag)
            Perform additional object specific setups.
            'flag' is 0 if this is the first creation of the object
            (as part of the AddItem()), it is positive if the object
            is recreated because of an refresh, and it is negative if
            the object needed no refreshment (put is member of the
            P_ITEMS array).

        Doors and combat equipment make heavy use of Aloha().


        --- /std/room/exits ---

        Rooms can have exits, which lead to other rooms. To make
        creating obvious exits easy, there exist functions to handle
        this. The roomfilenames can be absolute with leading "/", or
        with leading "~", or with leading "+" for searching in the
        current rooms domain, or relative (with leading '.') to be
        searched in the directory of the current room.

        Also exist the possibility of 'special exits': here no
        destination filename is specified, but instead the names of a
        function and its object, so the function is invoked to do the
        moving.
        The object filename may be specified in a relative notation as
        well.

        It is possible to mark an exit as 'checked': whenever it is
        used (moving, opening doors, door blocking the way because
        it's closed), the function CheckAction() is called and may
        forbid the action. This is an alternative to using "special
        exits" (exits with an user-provided function) to control
        access to neighboring rooms.


          mapping P_EXITS   "Exits"
            The mapping of all specified exits.
            Key is the command, data is the following cluster:
              mixed  EXIT_DEST   : the destination room, function name,
                                   or function closure
              mixed  EXIT_OBJ    : 0 or the functions object.
              object EXIT_DOOR   : the associated door object.
              int    EXIT_HIDDEN : flag if the exit is hidden. See HideExit()!
              int    EXIT_CHECK  : flag if the exit is checked. See CheckExit()!
            If set to 0, no exits exist.

        The settings of EXIT_DEST and EXIT_OBJ may be these:
          - EXIT_OBJ = 0, EXIT_DEST: expanded filename of the dest room
          - EXIT_OBJ = 0, EXIT_DEST: the dest room object
          - EXIT_OBJ = 0, EXIT_DEST: function closure for this direction
          - EXIT_OBJ : expanded filename of function object, or object itself
            EXIT_DEST: name of the function to call for this direction

        Exits which are not controlled by a function (normal exits)
        always lead out of the room. They can't be triggered from outside.

        If the exit (special or not) is controlled by a door,
        EXIT_DOOR holds the door object in question.
        This field is not to be set! The room takes care of it!

        EXIT_HIDDEN is normally zero, but if set to non-zero, the exit
        is no longer visible as 'obvious', even when it has an open
        door before it. Nevertheless it can be used.

        EXIT_CHECK is normally zero, but if set to non-zero, using the
        exit undergoes extra checks. See CheckExit().

        The Exit data is internally kept in two mappings: one holding
        EXIT_DEST, the other the other data fields. They may be
        accessed directly using:

          mapping P_EXITS_DEST   "ExitsDest"
            A single mapping containing the EXIT_DEST or P_EXITS,
            indexed by the exit direction.
            It contains an entry for every exit.

          mapping P_EXITS_DATA   "ExitsData"
            A mapping holding [EXIT_OBJ..] or P_EXITS.
            Index within an entry by subtracting EXIT_OBJ from the
            symbolic index, like [dir, EXIT_DOOR-EXIT_OBJ].
            This mapping contains entries for just those exits needing
            extra data.
            Use this data only if you know what you're doing!
            The mapping returned might be empty, so subindexing won't work
            in that cases!

          mapping QueryPlainExits ()
            The functions returns that subset of P_EXITS_DEST which are
            just simple exits (all data are filenames of the destination
            rooms). The result is always a mapping, even if the properties
            themselves are 0.

          mixed * QueryExit (string dir)
            Return the data for the exit leading <dir> in an array, or 0.
            If the exit is a 'special' exit, [EXIT_DEST] is 0,
            and [EXIT_OBJ] is either the function closure, or ({ object,
            functionname }) of the function to call.

          mixed QueryTarget (string dir)
            Returns the string or object of the room which will lead
            into the direction 'dir'. In case of special exits this
            might be the 'most likely' room. This function should be
            used for aiming, farsighting, etc but not fort moving NPCs
            or players.

        If a room has just simple exits, P_EXITS_DEST may be used for
        convinient setting. If not, add the non-simple exits using
        AddExit() (see below).

          string P_NOWAY_MSG  "NowayMsg"
            The default string to be told to players which attempt to leave
            in a direction for which no exit has been added. If 0, the
            string "No way\n" is used.
            The room expects this to be a builtin property and passes
            the command line as argument to QueryNowayMsg().

          mapping P_NOWAY_MSGS  "NowayMsgs"
            A mapping of strings to be told to players which attempt
            to leave in a direction for which no exit has been added.
            The direction is the mapping index, the data for each
            index the message to be told.

          void AddNowayMsg (string | string * verb, string msg)
          void RemoveNowayMsg (string | string * verb)
            Add resp. remove messages for the given verb(s) from
            P_NOWAY_MSGS.

          string QueryNowayMsg (void | string verb, string arg)
            If no argument is given, return the default P_NOWAY_MSG
            message, else the no-way-message for the given <verb> and
            <arg>. This is again the P_NOWAY_MSG, unless for the
            <verb> a message has been defined in P_NOWAY_MSGS.

          void AddExit ( string *|string     command
                       , string|object       room)
            Add an exit into direction <command> to the specified <room>.
            <command> may be specified as an array of strings if all
            are to describe the same exit.

          void AddExit ( string *|string     command
                       , string              fun_name
                       , void|object|string  obj
                       , string|closure target)
            Add an exit into direction <command>, with <fun_name> being
            the name of the function to execute in <obj> (default is
            this_object()) to perform the movement.
            <command> may be specified as an array of strings if all
            are to describe the same exit. Target is the room or a function
            returning the room where the direction will most likely end up.
            This will be used for aiming, looking into other rooms, etc.
            The function will get the arguments (direction,EXIT_QUERY_ONLY)

          void AddExit (string *|string command
                        , closure fun
                        , string|closure target)
            Add an exit into direction <command> by setting <fun> as
            the function to perform the movement.
            <command> may be specified as an array of strings if all
            are to describe the same exit. The target argument works like
            described above. If target is ommited the function 'fun' will
            be called with the same arguments (direction,EXIT_QUERY_ONLY)

          void RemoveExit ( string *|string command )
            Remove the exit(s) denoted by <command>.

          int HideExit (string|string * dir, int newstate)
            Hide or unhide the exit to <dir> (which can also be a list
            of exits).
            Result is the old state (in case of a list of exits: just
            the state of the last exit).
            If the exit in <dir>ection is not controlled by a door, a
              setting of HIDE_OPEN or HIDE_ALWAYS hides the exit.
            If the exit in <dir>ection is controlled by a door, the
              value set is used to set the doors P_HIDEEXIT property and
              then acknowledges these values:
                HIDE_NOT    : the exit is listed.
                HIDE_OPEN   : the exit is listed only when door is closed.
                HIDE_CLOSED : the exit is listed only when door is open.
                HIDE_ALWAYS : the exit is not listed (this is in fact
                              just HIDE_OPEN|HIDE_CLOSED).
              If HIDE_BOTH is ored (|) to the value set, the remote
              doors property is updated as well.

          int CheckExit (string|string * dir, int newstate)
            Check or uncheck the exit to <dir> (which can also be a list
            of exits).
            Result is the old state (in case of a list of exits: just
            the state of the last exit).
            Possible values are:
              DACT_NOT    : no check necessary.
              DACT_HIDE   : check if the exit is hidden.
              DACT_CHECK  : check always.
              DACT_UNHIDE : check if the exit is not hidden.
            If a door controls this exit, its effect on hiding the
            exit is regarded.
            See UseExit() and CheckAction().

          string * P_EXIT_STRINGS   "ExitStrings"
            An array of up to four strings which are used by Exits()
            resp. MakeExitString() to construct the exit description.
            If this property is not set or incomplete, the following
            default is internally used:
              ({ "There is", "exit", "There are", "exits" })
            Exits() and MakeExitString() are described using this
            setting.


          string Exits(void|int brief, void|object player)
            This returns a descriptional string (possibly consisting
            of multiple lines) of all defined exits.
            The long form (<brief> is zero) is:
              'There are <n> exits: <exit1>, <exit2>, ..., and <exitn>',
            The short form (<brief> is non-zero) is:
              '<exit1>,<exit2>,...<exitn>'
            with the names of standard exits abbreviated ("n" instead
            of "north", "nw" instead of "northwest").
            <player> denotes the living who queries the Exits()
            and defaults to this_player().
            Not contained are exits for which active doors exist which
            return a QueryStatusString() or are not open.
            Also not contained are hidden exits if the player is neither a
            wizard nor a ghost.

          mixed * ExitList()
            Return an array of two arrays of strings.
            The first array are the directions of obvious exits, the
            second array are the direction of hidden exits.

          string MakeExitString (int brief, string * dirs, void|string kind)
            Return a string describing the list of exits leading
            <dirs> in a format suiting for Exits().
            If specified, each exit is written as "<kind> exit".

          int UseExit(string verb, string arg, int method)
            Lead the actual player through the exit <verb> with command
            <arg>ument. If it is a normal exit, move method <method>
            is used. Result is normal command success code.
            Use this function to avoid manual resolving of normal
            or special exits.

          int CheckAction (string action, string verb, string arg, int method)
            The command '<verb> <arg>' is applied to the room, with
            its type determined by <action>:
              <action> = 'exit': the player tries to leave through one
                of the exits, using move-method <method>.
            /obj/doors also add the actions 'block', 'door', 'lock'
            and 'knock'.
            The function has to return non-zero if the action shall
            succeed, and zero if the action shall fail.
            Default is that every action succeeds, unless it's the
            action 'block' and the player is a ghost (i.e. ghosts are
            not blocked).
            If the exit has no checking enabled, this function won't
            be called for it.
            This function may be called by doors if the room is set as
            P_CHECKOBJ in them.

        As mentioned above, the room keeps track of the doors blocking
        its exits. Doors MUST call these functions!

          mapping P_DOORS   "Doors"
            A mapping containing all acknowledged doors.
            Key is the door object, data are clusters with the
            entries:
              string DOOR_DIR
                The command this door blocks.
              int    DOOR_STATE
                The state (LOCK_xxx) of the door.

          void NewDoor (string dir, int state, void|object door)
            Add a new door to the door list.
            The <door> (default: previous_object()) controls the exit
            for the command(s) <dir> and is currently in <state>.
            Note that the /std/door calls NewDoor() as part of its
            Aloha() initialisation.

          void SetDoorData (string dir, int state, void|object door)
            Update the information <dir> and <state> for the <door>
            (default is previous_object()).
            (Mostly only <state> will change).
            <dir> may be an array of directions if one door serves
            them all.

          void RemoveDoorData (void|object door)
            Removes the <door> (default: previous_object()) from the
            list of active doors.
            This doesn't imply that the door left the room - just that
            it no longer controls the exit.

          void SetDoorState (int state, void|object door)
            Set the new locking <state> for <door> (default:
            previous_object()). This modifies just the internal data.

          int SetDoor (string doorid, int new)
            Compatibility: Set the door determined by <doorid> (which
            is either the direction or the doors id) to the state <new>.
            Return the newstate, or -1 if there is no such door.

          mixed * DoorInfo (mixed door)
            Return the entry for <door> (specified by the object, by
            the exit command or by the doors id) from P_DOORS.
            The entry contains an additional field 'object DOOR_OBJECT'
            specifying the door object.
            If there is no such <door>, 0 is returned.

          object AddDoor ( string                dir
                         , string|object|closure dest
                         , mapping               props
                         , void|string           doorobj )
            Add a door (and exit) for exit <dir> leading to <dest>
            (see AddExit()). The door object is <doorobj>, default is
            "/obj/door". The object is added as REFRESH_REMOVE item
            with <props> holding the data to initialise the added
            door.
            <props> has to hold all data necessary for the door
            (P_SHORT, P_LOCKSTATE, P_DOORCODE etc). It need not
            contains P_DIRECTION or P_OTHERROOM, as these are filled
            in by the function. However, a contained P_OTHERROOM would
            not be overwritten.
            If <props> contains P_IDS, its entry is extended by the ids of
            the <doorobj>
            Result is the added door object.

          object AddDoor ( string                dir
                         , string|object|closure dest
                         , string                doorid
                         , string                doorlong
                         , mixed *|string        keyid
                         , int                   state )
            Compatibility: Add an /obj/door (and exit) for exit <dir> leading
            to <dest> (see AddExit()). The object is added as
            REFRESH_REMOVE item and initialised as P_SHORT:"a
            <doorid>", P_LONG:<doorlong>, P_DOORCODE:<doorid>,
            P_LOCKSTATE:<state>, P_KEYCODE:<keyid>[0],
            P_KEYIDS:<keyid>[1..], and door->AddId(<doorid>).
            If <keyid> is just a string, only P_KEYIDS is initialised.
            If <keyid> is 0, no key data is initialised.
            The P_CHECKOBJ is set to the room adding the door.
            Result is the added door object.

          int HideDoor (string dir, int newstate)
            Set the P_HIDEDOOR property of the door in direction <dir>
            to <newstate>, and return the old setting.
            That property determines whether a door should be listed
            in the 'Obvious Doors' description of rooms or not.
            Possible settings are:
              HIDE_NOT    : the door is listed.
              HIDE_CLOSED : the door is listed only when open.
              HIDE_OPEN   : the door is listed only when closed.
              HIDE_ALWAYS : the door is not listed.
            If HIDE_BOTH is ored (|) to the value set, the remote
            doors property is updated as well.
            Use this property if the door is not visible in one of its
            states, or listed in the rooms long description.

          int CheckDoor (string dir, int newstate)
            Set the P_CHECKDOOR property of the door in direction <dir>
            to <newstate>, and return the old setting.
            That property determines whether a door should apply
            additional checks on actions or not.
            Possible settings are:
              DACT_NOT    : no check necessary.
              DACT_HIDE   : check if the door is hidden.
              DACT_CHECK  : check always.
              DACT_UNHIDE : check if the door is not hidden.
            If DACT_BOTH is ored (|) to the value set, the remote
            doors property is updated as well.
            Setting this property has an effect only if some code
            actually evaluates it.
            Setting P_CHECKOBJ of the door to the roomobject will
            result in the room's CheckAction() being called.


          string Doors (void|int verbose, void|object player)
            This returns a descriptional string (consisting of
            multiple lines) of all defined doors.
            It is of the form:
              'There are <n> doors:
               <door status string 1>
                  ...
               <door status string n>'.
            if <verbose> is non-zero, also "There are no doors.\n"
            is possible, else "" is returned if no doors are there.
            Doors returning no QueryStatusString() or the empty
            string "" are not listed.
            <player> denotes the living who queries the Doors()
            and defaults to this_player().
            Hidden doors are not listed unless the player is a wizard
            or a ghost.

          mixed * DoorList()
            Return an array of two arrays of door objects.
            The first array are the obvious doors, the second array
            are the hidden doors.

          string MakeDoorString (int brief, object * doors, void|string kind)
            Return a string describing the list of <doors> leading
            <dirs> in a format suiting for Doors().
            If specified, each door is written as "<kind> <door>".


        Note: Both Exits() and Doors() are to be called by the
              player object directly, or by GetIntDesc().
              They should not be called by IntLong() or Content().


        As a feature, the room can also invoke arbitrary functions
        when a specified command is given.

          mapping P_COMMANDS   "Commands"
            The list of all command verbs and their function names.
            Key is the verb, data the function name.

          void AddRoomCmd (string|string* verb, string|closure function)
            Adds a verb with associated function to the room. When
            <verb> or one of the elements of the array <verb> is
            typed, the function <function> in the room is invoked.
            The function should return 1 on success or 0 in case
            the room doesn't accept the combination of <verb>
            and arguments to <verb> (See "commands" in the concepts
            documentation).

          void RemoveRoomCmd (string|string* verb)
            Removes one or more verbs from the room, deactivating the
            commands.
            The deactivation is valid only for newly arriving livings.

        To activate the exit- and room-commands, the lfun

          void init (void)

        is implemented here.

        Auxiliary functions are:

          string map_brief_exit (string dir)
            Returns a shorted version of <dir>, if possible, like 'nw'
            for 'northwest'.


        --- /std/room/cleaning ---

        This implements the special remove() and clean_up() for rooms.
        Rooms treat the contents in a special way: items, which are
        cloned using /std/room/items do not count as 'contained',
        since they can be recreated.
        On the other hand, some created objects need the room for
        refresh (like for REFRESH_HOME), so the existance of such
        items prevent the room from clean_up().

          int remove (void)
            This just destructs the room.

          int clean_up (int ref)
            Overloads the default handling of /std/base.

        The clean_up() handling is different from those of /std/base.
         - If P_CLEAN_UP is zero, the object stays and the function
           returns 1 to be asked again later.
         - A cloned room with environment returns 0, and will thus not
           clean up anytime.
         - A room with items which needs the room to exist (e.g.
           REFRESH_RESET items) force the room to stay and return
           with 1 to try again later.
         - If there are alien objects in the room, they are called
           with clean_up(-1) to let them clean_up() themselves. If
           after this some of them still exist, the room will not
           clean up and return with 1 to try again later.
         - Else the room will destruct all its inventory and itself.
           The inventory destruction will first be attempted by
           calling clean_up(-1) in each item, and the then still
           remaining items will be remove()d the hard way.

        The handling of added items is in detail this:
         - If items of _RESET or _INIT have been removed from the
           room, the room does not clean up this call.
         - An REFRESH_HOME item is moved back into the room, and
           cleanup continues.
         - Other added items do not change cleanup handling.

        --- /std/room/secrets ---

        Handles the secrets in a room. A secret is a detail which
      a player will be shown automatically if his perception skill is
      high enough. For example it will be possible to give a hint to
      a secret door to players with good skill.

        varargs int AddSecret(string secret, int difficulty,mixed desc)
          Add a Secret to a room. Its short name is 'name'. Usual "door" or 
          "exit" or "trap door". 
          The 'difficulty' detemines how difficult a Secret is to detect (0-1000).
          It is related to the perception skill 
          The next argument is the description  of that secret, i.e. what a player
          will see when detecting it. It can be a string or string array  or a
          closure returning a string. If given a string array the text shown to
          the player depends on the output of the skill check. A low value will
          show the first string of the array and higher values will show latter
          strings providing more inforamtion for the player.
          The closure function will get 'secret' && 'player' && 'skillvalue'
          as arguments, i.e.
            varargs string MyFun(string secret,object player,int skillvalue)
         where secret is the name given to the secret in AddSecret skillvalue
         a number 0..1000 showing how well the player did detect the secret

       int RemoveSecret(string secret)
         Removes a secret from the list of secrets in this room



BUGS
        /std/room/items should be able to recognize items lying around and
        reuse them instead of cloning new ones (useful for npcs).


INHERITANCE TREE
        room
          |-std/base
          |-std/room/cleaning
          |-std/room/items
          |-std/room/details
          |-std/room/exits
          |-std/room/description
          `-std/room/restrictions


SEE ALSO
        perception(C), search(C),
	base(S), thing(S), container(S), door(S), light(C), inroom(O)