#charset "us-ascii"
/*
Tads-3 Container with Lid
Steve Breslin, 2004
email:
[email protected]
====
Licence:
Everyone is free to use this, but please provide me with all
improvements and modifications.
====
This extension provides a ContainerWithLid class which you can use to
implement any kind of container which you want to close with a separate
object (the lid). You can make bottles with caps, boxes with lids, etc.
It's quite easy to use this extension: simply include it in your
project, and write an object which inherits from ContainerWithLid; then
include in the container's lidList any object which can "lid" the
container.
*/
#include <adv3.h>
#include <en_us.h>
// example objects:
largeBottle: ContainerWithLid 'large bottle' 'large bottle'
"It's a large bottle.\n"
lidList = [largeCap]
location = me
;
largeCap: Thing 'large cap' 'large cap'
"It's a large cap.\n"
location = me
bulk = 2
;
smallBottle: ContainerWithLid 'small bottle' 'small bottle'
"It's a small bottle.\n"
lidList = [smallCap]
location = me
;
smallCap: Thing 'small cap' 'small cap'
"It's a small cap.\n"
location = me
bulk = 1
;
class ContainerWithLid: ComplexContainer, PreinitObject
/* A list of objects which can be used to close this object.
*/
lidList = []
/* We need to provide our special subContainer and subSurface for
* each instance of the ContainerWithLid class.
*/
execute()
{
if (subContainer && subContainer.location != self)
{
subContainer = subContainer.createInstance();
subContainer.moveInto(self);
subContainer.lexicalParent = self;
}
if (subSurface && subSurface.location != self)
{
subSurface = subSurface.createInstance();
subSurface.moveInto(self);
subSurface.lexicalParent = self;
}
}
/* The subSurface is where the lid goes */
subSurface : ComplexComponent, Surface
{
/* This handles putting a lid on the ContainerWithLid object */
iobjFor(PutOn)
{
check()
{
/* if there's already something on the surface, we
* assume it's a lid. So we don't allow another lid.
*/
if (contents.length) {
reportFailure('There\'s already a lid on it.\n');
exit;
}
/* If the object isn't in our list of acceptable lids,
* the lid doesn't fit.
*/
if (!location.lidList.indexOf(gDobj)) {
reportFailure('It doesn\'t fit.\n');
exit;
}
inherited();
}
/* place the lid on the surface, and close the container */
action()
{
"You close <<theName>> with <<gDobj.theName>>. ";
gDobj.moveInto(self);
location.subContainer.makeOpen(nil);
}
}
/* if an object is removed from the surface, assume it's the
* lid. with the lid removed, the object is open.
*/
notifyRemove(obj)
{
inherited(obj);
location.subContainer.makeOpen(true);
}
}
/* The subContainer is where the contents of the object go,
* excepting the lid of course.
*/
subContainer : ComplexComponent, OpenableContainer
{
/* When someone tries simply to close the object, we redirect
* processing, asking "what (lid) do you want to put on the
* container?"
*/
dobjFor(Close)
{
action()
{
PutOnAction.retryWithMissingDobj(gAction, ResolveAsker);
}
}
/* We don't actually want the lid to go on the subContainer,
* but on the subSurface.
*/
iobjFor(PutOn) remapTo(PutOn, DirectObject, location.subSurface)
/* Opening the container means taking the cap from the
* container.
*/
dobjFor(Open)
{
action()
{
if (location.subSurface.contents)
{
"You remove
<<location.subSurface.contents[1].theName>> from
<<theName>>.\n";
replaceAction(Take, location.subSurface.contents[1]);
}
}
}
/* We're initially open if there's no lid on the subSurface. */
initiallyOpen()
{
return (location.subSurface.contents == []);
}
/* Only things smaller than the lid can fit through the
* container's mouth.
*/
canFitObjThruOpening(obj)
{
return (location.lidList[1].getBulk == 0
|| obj.getBulk < location.lidList[1].getBulk);
}
}
;
/* treat "cap X with Y" and "close X with Y" the same as "put Y on X"
*/
VerbRule(CapWith)
('cap' | 'close') singleIobj 'with' singleDobj
: PutOnAction
verbPhrase = 'cap/capping (what) (with what)'
;
/* treat "cap X" the same as "close X" */
VerbRule(Cap)
'cap' singleDobj
: CloseAction
verbPhrase = 'cap/capping (what)'
;