/* Copyright (c) 1999, 2000 by Kevin Forchione. All Rights Reserved. */
/*
* TADS ADV.T/STD.T LIBRARY EXTENSION
* DOORS.T
* version 1.0
*
* This module implements a floatingItem object that behaves like
* two TADS doorways. This implementation is easier to work with
* and modify than the earlier doorItem class.
*
*----------------------------------------------------------------------
* REQUIREMENTS
*
* + HTML TADS 2.5.0 or later
* + Requires ADV.T and STD.T
* + Should be #included after ADV.T and STD.T.
*
*----------------------------------------------------------------------
* IMPORTANT LIBRARY INTERFACE AND MODIFICATION
*
* None.
*
*----------------------------------------------------------------------
* 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
*
* 23-Oct-99: Creation.
*/
#define __DOORS_MODULE_
#pragma C+
/*
* door: floatingItem, fixeditem, obstacle
*
* A door is an obstacle that impedes progress when it is closed.
* Unlike the doorway, a door is a floatingItem and should not have its
* location attribute coded. Instead, use the foundin list to indicate
* the rooms in which the door is to be found.
*
* To make a simple two-sided door you need only code both room
* objects in the foundin list of the door:
*
* foundin = [ hallway, kitchen ]
*
* To make a one-sided door, code the foundin list with the room
* object in which the door is to be found, and the doorto list
* with the room object to which the door leads:
*
* foundin = hallway
* doorto = kitchen
*
* If you want a door that returns rooms different from those it is
* found in, simply code both the foundin list and doorto list
* accordingly, each element of the doorto list must have a
* corresponding foundin element:
*
* foundin = [ hallway, kitchen ]
* doorto = [ foyer, hallway ]
*
* From the hallway the door leads to the foyer, but from the kitchen
* it leads to the hallway.
*/
class door: doorway, floatingItem
foundin = []
doorto = nil
location =
{
local f, actor, loc, dloc, foundList;
if (self.foundin == nil)
return nil;
actor = parserGetObj(PO_ACTOR);
if (actor == nil)
actor = parserGetMe();
loc = actor;
while(loc)
{
dloc = loc;
loc = loc.location;
}
//
// convert self.foundin into a list
//
switch(proptype(self, &foundin))
{
case DTY_NIL:
foundList = [];
break;
case DTY_OBJECT:
foundList = [ self.foundin ];
break;
case DTY_LIST:
foundList = self.foundin;
break;
default:
return nil;
}
if (find(foundList, dloc))
return dloc;
else
return nil;
}
findDest(actor) =
{
local f, loc, foundList, destList;
loc = self.location;
//
// convert self.foundin into a list
//
switch(proptype(self, &foundin))
{
case DTY_NIL:
foundList = [];
break;
case DTY_OBJECT:
foundList = [ self.foundin ];
break;
case DTY_LIST:
foundList = self.foundin;
break;
default:
return nil;
}
//
// convert self.doorto into a list
//
switch(proptype(self, &doorto))
{
case DTY_NIL:
destList = [];
break;
case DTY_OBJECT:
destList = [ self.doorto ];
break;
case DTY_LIST:
destList = self.doorto;
break;
default:
return nil;
}
//
// door is linked to room directions, but no foundin
// list exists. Simply return the noexit message.
//
if (length(foundList) == 0)
{
return self.noexit;
}
//
// We don't have a doorto list. Use the foundin list,
// which must have 2 elements.
//
if (length(destList) == 0)
{
if (length(foundList) != 2)
{
"\n[TADS-DOORS-001] When omitting the
doorto list, the foundin list should
contain 2 elements.\n";
return nil;
}
if (loc == foundList[1])
return foundList[2];
else
return foundList[1];
}
//
// We have a doorto list, each element should correspond to
// an element in the foundin list.
//
if (length(foundList) != length(destList))
{
"\n[TADS-DOORS-002] <<self.thedesc>> requires a
corresponding doorto element for each foundin
element.\n";
return nil;
}
//
// Search for the actor location in the foundin list.
//
f = find(foundList, loc);
//
// Door isn't in the actor location. return noexit.
//
if (f == nil)
{
return self.noexit;
}
//
// return the corresponding doorto element
//
return destList[f];
}
destination =
{
local actor = parserGetObj(PO_ACTOR);
if (actor == nil)
actor = parserGetMe();
//
// The door location is nil or the actor's location doesn't
// match any object in the foundin list
//
if (self.location == nil)
return self.noexit;
if (self.isopen)
return self.findDest(actor);
else if (!self.islocked
&& !self.noAutoOpen)
{
self.setIsopen(true);
"(Opening << self.thedesc >>)\n";
return self.findDest(actor);
}
else
{
"%You%'ll have to open << self.thedesc >> first. ";
setit(self);
return nil;
}
}
setIsopen(setting) =
{
/* update my status */
self.isopen = setting;
}
setIslocked(setting) =
{
/* update my status */
self.islocked = setting;
}
noexit = { "%You% can't go that way. "; return nil; }
;
/*
* lockableDoor: door
*
* This is just a normal door with the islockable and
* islocked properties set to true. Fill in the other
* properties (foundin and doorto) as usual. If
* the door has a key, set property mykey to the key object.
*/
class lockableDoor: door
islockable = true
islocked = true
;