/* 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 */