/* Copyright (c) 2002, 2002 by Kevin Forchione.  All Rights Reserved. */
/*
*    TADS ADV.T/STD.T LIBRARY EXTENSION
*    FLOATING.T
*    version 1.0
*
*    This file is a library extension for TADS ADV.T
*
*    This file provides a mechanism for properly determining
*    whether a floatingItem class object should be included in
*    the deepverb validXoList().
*
*----------------------------------------------------------------------
*  REQUIREMENTS
*
*      + HTML TADS 2.2.6 or later
*      + Requires ADV.T and STD.T
*      + Should be #included after ADV.T and STD.T.
*
*----------------------------------------------------------------------
*  IMPORTANT LIBRARY INTERFACE AND MODIFICATION
*
*      This module replaces the following ADV.T functions, methods
*      and objects:
*
*          + validDoList()
*
*----------------------------------------------------------------------
*  COPYRIGHT NOTICE
*
*      You may modify and use this file in any way you want, provided that
*              if you redistribute modified copies of this file in source form, the
*      copies must include the original copyright notice (including this
*      paragraph), and must be clearly marked as modified from the original
*      version.
*
*------------------------------------------------------------------------------
*  REVISION HISTORY
*
*              03-Mar-02:      Creation.
*/

#ifndef FLOATING_T
#define FLOATING_T

#pragma C+

modify deepverb
   replace validDoList(actor, prep, iobj) =
   {
       local ret;
       local loc;
       local i, f, fo, fp, fpList = [];

       /*
         *   Create an instance of FloatingProxy for each of the
         *   floatingItem class object's in the game. These are
         *   automatically moved into the contents list of their
         *   locations and added to the floating proxy list.
         */
       for (i = 1;  i <= length(global.floatingList);  ++i)
       {
           fo = global.floatingList[i];
           fp = FloatingProxy.instantiate(fo);
           if (fp)
               fpList += fp;
       }

       /*
         *   Perform the normal ADV.T scoping process using
         *   visibleList(). Note that we *don't* simply add the
         *   global floatingList to ret. Instead, we've let visibleList()
         *   determine whether each FloatingProxy instance was
         *   in scope.
         */
       loc = actor.location;
       while (loc.location)
           loc = loc.location;
       ret = visibleList(actor, actor) + visibleList(loc, actor);

        /*
          *  For each FloatingProxy instance in the ret list we
          *  substitute the object referenced by it's myReference
          *  property.
          */
       for (i = 1; i <= length(ret); ++i)
       {
           f = find(fpList, ret[i]);
           if (f != nil)
               ret[i] = fpList[f].myReference;
       }

       /*
         *   Delete all of our FloatingProxy instances. This will
         *   also remove them from their location's contents list.
         */
       for (i = 1;  i <= length(fpList);  ++i)
       {
           fp = fpList[i];
           delete fp;
       }

       // the return list now accuractly includes floatingItem objects
       return ret;
   }
;

/*
 *   This class acts as a proxy for floatingItem class objects and
 *   is temporarily moved into the contents list of the floatingItem
 *   object's location.
 *
 *   This class carries information pertinent to the scoping mechanism
 *   of the ADV.T basic library. Any modifications made to the basic
 *   scoping mechanism may invalidate this process or require further
 *   addition to the information carried by this class.
 *
 *   For scoping purposes, the proxy is of class openable. This allows for
 *   floatingItem objects that also inherit from openable class.
 */
class FloatingProxy: openable
   myReference        = nil
   isopen                    = nil
   contentsVisible    = nil

   instantiate(obj) = {
       local x, loc = obj.location;

       /*
         *   if loc == nil, we don't create an object, and instead
         *   return nil.
         */
       if (loc == nil)
           return nil;

       // create a new instance of this class
       x = new FloatingProxy;

       /*
         *   move the new instance into the object's contents, this
         *   also sets the new instance's location property, which is
         *   something we *can't* do with a floatingItem class object.
         */
       x.moveInto(loc);

       // set the instance's reference property to the object.
       x.myReference    = obj;

       // set the instance's contents to the object's contents.
       x.contents            = obj.contents;

       /*
         *   For scoping purposes the isopen and contentsVisible
         *   properties of the new instance must be the same as
         *   those of the object.
         */
       x.isopen                = obj.isopen;
       x.contentsVisible = obj.contentsVisible;

       // return the new instance
       return x;
   }
;

#pragma C-

#endif  /* FLOATING_T */