/* Copyright (c) 1999, 2000 by Kevin Forchione.  All Rights Reserved. */
/*
*  TADS ADV.T/STD.T LIBRARY EXTENSION
*  SMARTLIST.T
*  version 1.0
*
*      This file defines the sackItem class and modified class thing that
*      allows for the implementation of a 'rucksack', into which the game
*              automatically tidies away things for the player. The sackItem class
*              will automatically move items from the player's possession to the
*              designated sackItem once the player attempts to take more than the
*              maximum bulk allocated for them.
*
*----------------------------------------------------------------------
*  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 modifies thing class doTake() method.
*
*----------------------------------------------------------------------
*  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
*
*              99-03-10 programming begun.
*/

#define __SACKITEM_MODULE_


/*
*      We modify only the totbulk logic of thing (the idea being that
*      a player can only carry so much weight regardless of whether
*      they have a sack or not.
*/
modify thing
   doTake(actor) =
   {
       local totbulk, totweight;

       totbulk := addbulk(actor.contents) + self.bulk;
       totweight := addweight(actor.contents);
       if (not actor.isCarrying(self))
           totweight := totweight + self.weight + addweight(self.contents);

       if (totweight > actor.maxweight)
           "%Your% load is too heavy. ";
       else if (totbulk > actor.maxbulk)
       {
               if ( self.moveToSackItem( actor ) )
               {
                       self.moveInto( actor );
                       "Taken. ";
               }
               else
               "%You've% already got %your% hands full. ";
       }
       else
       {
           self.moveInto(actor);
           "Taken. ";
       }
   }
   /*
    *  This is the heart of the sackItem logic. The logic does not
    *  check for multiple sackItems, it takes the first one it finds
    *  Also it does not attempt to optimise the placement of items
    *  in the sackItem, except that items that are lit or that are
    *  being worn are not chosen.
    */
   moveToSackItem( actor ) =
   {
       local c, n := [], o, s, totbulk;

       /*
    *  determine if the actor is carrying a sackItem
    */
       c := actor.contents;
       o := car( c );
               while( o )
               {

                       if ( isclass( o, sackItem ) )
                       {
                               break;
                       }
                       c := cdr( c );
                       o := car( c );
               };
               s := o;                 // sackItem value

       if ( s = nil ) return nil;

               c := actor.contents - [ s ];    // exclude the sackItem
       /*
        *      Select items that aren't being worn or that aren't lit as
        *      candidates for the sackItem.
        */
               o := car( c );
               while( o )
               {
                       if ( not o.isworn and not o.islit )
                       {
                               n := n + [ o ];
                       }
                       c := cdr( c );
                       o := car( c );
               }
   /*
    *  Determine if an object will fit in the sack and move it
    *  if it does.
    */
       o := car( n );
       while( o )
               {
                       totbulk := addbulk( s.contents ) + o.bulk;

                       if ( totbulk <= s.maxbulk )
                       {
                               o.moveInto( s );
                               "(putting <<o.thedesc>> into <<s.thedesc>> to make room)\n";
                               return true;
                       };

                       n := cdr( n );
                       o := car( n );
       }
       return nil;
   }
;

/*
*      sackItem: openable, clothingItem
*
*      This class allows an object to act like a 'rucksack', into which the
*      game automatically tidies away things for the player.
*/

class sackItem: openable, clothingItem
       maxbulk = 20
;