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