home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Perseus
/
PERSEUS.iso
/
spiele
/
tads12.exe
/
DITCH.T
< prev
next >
Wrap
Text File
|
1991-07-08
|
114KB
|
3,858 lines
/* Copyright (c) 1990 by Michael J. Roberts. All Rights Reserved. */
/*
Ditch Day Drifter
Interactive Fiction by Michael J. Roberts.
Developed with TADS: The Text Adventure Development System.
This game is a sample TADS source file. It demonstrates many of the
features of TADS. The TADS language is fully documented in the TADS
Author's Manual, which is available only to registered owners of the
Text Adventure Development System. While this file is intended to
illustrate most of the important features of TADS, it is provided
partially for evaluation purposes, to help you to make an informed
decision as to whether TADS suits your needs, and to partially to
complement the TADS Author's Manual; this file is not intended to be
a substitute for the full documentation of the system. If you find
that TADS is useful to you, please register your copy.
Please read LICENSE.DOC for information about using and copying this
file, and about registering your copy of TADS.
*/
/*
* First, insert the file containing the standard adventure definitions.
*/
#include <adv.t>
/*
* Pre-declare some functions, so the compiler knows they are functions.
* (This is only really necessary when a function will be referenced
* as a daemon or fuse before it is defined; however, it doesn't hurt
* anything to pre-declare all of them.)
*/
die: function;
scoreRank: function;
init: function;
terminate: function;
pardon: function;
sleepDaemon: function;
eatDaemon: function;
darkTravel: function;
setlamps: function;
/*
* The die() function is called when the player dies. It tells the
* player how well he has done (with his score), and asks if he'd
* like to start over (the alternative being quitting the game).
*/
die: function
{
"\b*** You have died ***\b";
scoreRank();
/*
* Check if the player (Me) purchased insurance. If so, issue
* an appropriate message.
*/
if ( Me.isinsured )
"\bI'm sure that Lloyd is even now paying out a big lump sum for
your early demise. However, that is of little use to you now. ";
/*
* Tell the user the options available, and then ask for some
* input. Keep asking until we get something we recognize.
*/
"\bYou may restore a saved game, start over, or quit. ";
while ( 1 )
{
local resp;
"\nPlease enter RESTORE, RESTART, or QUIT: >";
resp := upper(input()); /* get input, convert to uppercase */
if ( resp = 'RESTORE' )
{
resp := askfile( 'File to restore' ); /* find filename */
if ( resp = nil ) "Restore failed. ";
else if ( restore( resp )) "Restore failed. ";
else
{
/*
* We've successfully restored a game. Reset the status
* line's score/turn counter, and resume play.
*/
setscore( global.score, global.turnsofar );
abort;
}
}
else if ( resp = 'RESTART' )
{
/*
* We're going to start over. Reset the status line's
* score/turn counter and start from the beginning.
*/
setscore( 0, 0 );
restart();
}
else if ( resp = 'QUIT' )
{
/*
* We're quitting the game. Do any final activity necessary,
* and exit.
*/
terminate();
quit();
abort;
}
}
}
/*
* The scoreRank() function displays how well the player is doing.
* In addition to displaying the numerical score and number of turns
* played so far, we'll classify the score with a rank such as "sophomore."
*
* Note that "global.maxscore" defines the maximum number of points
* possible in the game.
*/
scoreRank: function
{
local s;
s := global.score;
"In a total of "; say( global.turnsofar );
" turns, you have achieved a score of ";
say( s ); " points out of a possible "; say( global.maxscore );
", which gives you a rank of ";
if ( s < 10 ) "high-school hopeful";
else if ( s < 25 ) "freshman";
else if ( s < 40 ) "sophomore";
else if ( s < 60 ) "junior";
else if ( s < global.maxscore ) "senior";
else "graduate";
". ";
}
/*
* The init() function is run at the very beginning of the game.
* We display some introductory text, then move the player (Me) to the
* initial location and set up some background activity.
*/
init: function
{
"\tYou wake up to the sound of voices in the hall. You are confused for
a moment; it's only 8 AM, far too early for anyone to be getting up.
Then, it dawns on you: it's ditch day here at the fictitious California
Institute of Technology in the mythical city of Pasadena, California.
Ditch Day, that strange tradition wherein seniors bar their doors with
various devices and underclassmen attempt to defeat these devices (for
no other apparent reason than that the devices are there), has arrived.\b";
version.sdesc; // display the game's name and version number
"\b";
setdaemon( turncount, nil ); // start the turn counter daemon
setdaemon( sleepDaemon, nil ); // start the sleep daemon
setdaemon( eatDaemon, nil ); // start the hunger daemon
Me.location := startroom; // move player to initial location
startroom.lookAround( true ); // show player where he is
}
/*
* preinit() is called after compiling the game, before it is written
* to the binary game file. It performs all the initialization that can
* be done statically before storing the game in the file, which speeds
* loading the game, since all this work has been done ahead of time.
*
* This routine puts all lamp objects (those objects with islamp = true) into
* the list global.lamplist. This list is consulted when determining whether
* a dark room contains any light sources.
*/
preinit: function
{
local o;
global.lamplist := [];
o := firstobj();
while( o <> nil )
{
if ( o.islamp ) global.lamplist := global.lamplist + o;
o := nextobj( o );
}
}
/*
* The terminate() function is called just before the game ends. We
* just display a good-bye message.
*/
terminate: function
{
"\bThanks for participating in Ditch Day!\n";
}
/*
* The pardon() function is called any time the player enters a blank
* line.
*/
pardon: function
{
"I beg your pardon? ";
}
/*
* This function is a daemon, started by init(), that monitors how long
* it has been since the player slept. It provides warnings for a while
* before the player gets completely exhausted, and causes the player
* to pass out and sleep when it has been too long. The only penalty
* exacted if the player passes out is that he drops all his possessions.
* Some games might also wish to consider the effects of several hours
* having passed; for example, the time-without-food count might be
* increased accordingly.
*/
sleepDaemon: function( parm )
{
local a, s;
global.awakeTime := global.awakeTime + 1;
a := global.awakeTime;
s := global.sleepTime;
if ( a = s or a = s+10 or a = s+20 )
"\bYou're feeling a bit drowsy; you should find a
comfortable place to sleep. ";
else if ( a = s+25 or a = s+30 )
"\bYou really should find someplace to sleep soon, or
you'll probably pass out from exhaustion. ";
else if ( a >= s+35 )
{
global.awakeTime := 0;
if ( Me.location.isbed or Me.location.ischair )
{
"\bYou find yourself unable to stay awake any longer.
Fortunately, you are ";
if ( Me.location.isbed ) "on "; else "in ";
Me.location.adesc; ", so you gently slip off into
unconsciousness.
\b* * * * *
\bYou awake some time later, feeling refreshed. ";
}
else
{
local itemRem, thisItem;
"\bYou find yourself unable to stay awake any longer.
You pass out, falling to the ground.
\b* * * * *
\bYou awaken, feeling somewhat the worse for wear.
You get up and dust yourself off. ";
itemRem := Me.contents;
while (car( itemRem ))
{
thisItem := car( itemRem );
if ( not thisItem.isworn ) thisItem.moveInto( Me.location );
itemRem := cdr( itemRem );
}
}
}
}
/*
* This function is a daemon, set running by init(), which monitors how
* long it has been since the player has had anything to eat. It will
* provide warnings for some time prior to the player's expiring from
* hunger, and will kill the player if he should go too long without
* heeding these warnings.
*/
eatDaemon: function( parm )
{
local e, l;
global.lastMealTime := global.lastMealTime + 1;
e := global.eatTime;
l := global.lastMealTime;
if ( l = e or l = e+5 or l = e+10 )
"\bYou're feeling a bit peckish. Perhaps it would be a good
time to find something to eat. ";
else if ( l = e+15 or l = e+20 or l = e+25 )
"\bYou're feeling really hungry. You should find some food
soon or you'll pass out from lack of nutrition. ";
else if ( l=e+30 or l = e+35 )
"\bYou really can't go much longer without food. ";
else if ( l >= e+40 )
{
"\bYou simply can't go on any longer without food. You perish from
lack of nutrition. ";
die();
}
}
/*
* The numObj object is used to convey a number to the game whenever
* the player uses a number in his command. For example, "turn dial
* to 621" results in an indirect object of numObj, with its "value"
* property set to 621. Just pick up the default definition from adv.t.
*/
numObj: basicNumObj;
/*
* strObj works like numObj, but for strings. So, a player command of
* type "hello" on the keyboard
* will result in a direct object of strObj, with its "value" property
* set to the string 'hello'.
*
* Note that, because a string direct object is used in the save, restore,
* and script commands, this object must handle those commands. We'll just
* pick up the default definition from adv.t.
*/
strObj: basicStrObj;
/*
* The "global" object is the dumping ground for any data items that
* don't fit very well into any other objects.
*/
global: object
turnsofar = 0 // no turns have transpired so far
score = 0 // no points have been accumulated yet
maxscore = 80 // maximum possible score
verbose = nil // we are currently in TERSE mode
awakeTime = 0 // time that has elapsed since the player slept
sleepTime = 600 // interval between sleeping times (longest time awake)
lastMealTime = 0 // time that has elapsed since the player ate
eatTime = 250 // interval between meals (longest time without food)
lamplist = [] // list of all known light providers in the game
;
/*
* The "version" object defines, via its "sdesc" property, the name and
* version number of the game.
*/
version: object
sdesc = "Ditch Day Drifter
\nInteractive Fiction by Michael J.\ Roberts
\bRelease 1.0
\nCopyright (c) 1990 by Michael J.\ Roberts. All Rights Reserved.
\nDeveloped with TADS: The Text Adventure Development System. "
;
/*
* "Me" is the player's actor. Pick up the default definition, basicMe,
* from "adv.t".
*/
Me: basicMe
;
/*
* darkTravel() is called whenever the player attempts to move from a dark
* location into another dark location. We don't do much of anything;
* some games might impose a probability of walking into the slavering
* jaws of a grue, whatever that might be.
*/
darkTravel: function
{
"You stumble around in the dark, and don't get anywhere. ";
}
/*
* The player will start in the room called "startroom", by virtue
* of being placed there by the "init" function.
*
* All rooms have an sdesc (short description), which is displayed on
* the status line and on entry to the room (even if the room has been
* seen before). In addition, the ldesc (long description) is printed
* when the player enters the room for the first time or types "look."
* Directions (north, south, east, west, ne, nw, se, sw, in, out)
* specify where the exits go. If a direction is not specified, no
* exit is in that direction.
*/
startroom: room
sdesc = "Room 3" // short description
ldesc = "This is your room. You live a fairly austere life, being a
poor college student. The only notable features are the bed
(unmade, of course) and a small wooden desk. An exit is west. "
west = alley1 // room that lies west
out = alley1 // the exit
;
/*
* The desk is a surface, which means you can put stuff on top of it.
* Note that the drawer is a separate object.
*/
room3desk: surface, fixeditem
sdesc = "small wooden desk"
noun = 'desk'
adjective = 'small' 'wooden' 'wood'
location = startroom
ldesc =
{
"It's the small desk that comes with all of the rooms in the house.
The desktop is pitifully small, especially considering that you often
need to have several physics texts and tables of integrals open
simultaneously. The desk has a small drawer (";
if ( room3drawer.isopen ) "open"; else "closed";
"). ";
}
/*
* For convenience, redirect any open/close activity to the
* drawer. Since the desk can't be opened and closed, we can
* reasonably expect that the player is really referring to the
* drawer if he tries to open or close the desk.
*/
verDoOpen( actor ) = { room3drawer.verDoOpen( actor ); }
doOpen( actor ) = { room3drawer.doOpen( actor ); }
verDoClose( actor ) = { room3drawer.verDoClose( actor ); }
doClose( actor ) = { room3drawer.doClose( actor ); }
;
/*
* A container can contain stuff. An openable is a special type of container
* that can be opened and closed. Though it's technically part of the desk,
* it's a fixeditem (==> it can't be taken), so we can just as well make it
* part of startroom; note that this is in fact necessary, since if it were
* located in the desk, it would appear to be ON the desk (since the desk is
* a surface).
*/
room3drawer: openable, fixeditem
isopen = nil
sdesc = "drawer"
noun = 'drawer'
location = startroom
;
/*
* A qcontainer is a "quiet container." It acts like a container in all
* ways, except that its contents aren't displayed in a room's message.
* We want the player to have to think to examine the wastebasket more
* carefully to find out what's in it, so we'll make it a qcontainer.
* Which is fairly natural: when looking around a room, you don't usually
* notice what's in a waste basket, even though you may notice the waste
* basket itself.
*
* The sdesc is just the name of the object, as displayed by the game
* (as in "You see a wastebasket here"). The noun and adjective lists
* specify how the user can refer to the object; only enough need be
* specified by the user to uniquely identify the object for the purpose
* of the command. Hence, you can specify as many words as you want without
* adding any burden to the user---the more words the better. The location
* specifies the object (a room in this case) where the object is
* to be found.
*/
wastebasket: qcontainer
sdesc = "waste basket"
noun = 'basket' 'wastebasket'
adjective = 'waste'
location = startroom
moveInto( obj ) =
{
/*
* If this object is ever removed from its original location,
* turn off the "quiet" attribute.
*/
self.isqcontainer := nil;
pass moveInto;
}
;
/*
* A beditem is something you can lie down on.
*/
bed: beditem
noun = 'bed'
location = startroom
ldesc = "It's a perfectly ordinary bed. It's particularly ordinary
(for around here, anyway) in that it hasn't been made in a very
long time. "
/*
* verDoLookunder is called when the player types "look under bed"
* to verify that this object can be used as a direct object (Do) for
* that verb (Lookunder). If no message is printed, it means that
* it can be used.
*/
verDoLookunder( actor ) = {}
/*
* ...and then, if verification succeeded, doLookunder is called to
* actually apply the verb (Lookunder) to this direct object (do).
*/
doLookunder( actor ) =
{
if ( dollar.isfound ) // already found the dollar?
"You don't find anything of interest. ";
else
{
dollar.isfound := true;
"You find a dollar bill! You pocket the bill.
(Okay, so it's an obvious adventure game puzzle, but I'm sure
you would have been disappointed if nothing had been there.) ";
dollar.moveInto( Me );
}
}
/*
* Verification and action for the "Make" verb.
*/
verDoMake( actor ) = {}
doMake( actor ) =
{
"It was a nice thought, but you suddenly realize that you never
learned how. ";
}
;
/*
* We wish to add the verb "make." We need to specify the sdesc (printed
* by the system under certain circumstances), the vocabulary word itself
* (as it will be entered by the user), and the suffix of the method that
* will be called in direct objects. By specifying a doAction of 'Make',
* we are establishing that verDoMake and doMake messages will be sent to
* the direct object of the verb.
*/
makeVerb: deepverb
sdesc = "make"
verb = 'make'
doAction = 'Make'
;
/*
* An "item" is the most basic class of objects that a user can carry
* around. An item has no special properties. The "iscrawlable"
* attribute that we're setting here is used in the north-south crawl
* in the steam tunnels (later in the game); setting it to "true"
* means that the player can carry this object through the crawl.
*/
dollar: item
sdesc = "one dollar bill"
noun = 'bill'
adjective = 'dollar' 'one' '1'
iscrawlable = true
;
room4: room
sdesc = "Room 4"
ldesc = "This is room 4, where the weird senior across the hall
lives. An exit is to the east, and a strange passage leads down. "
east = alley1
out = alley1
down =
{
/*
* This is a bit of code attached to a direction. We can do
* anything we want in code like this, so long as we return a
* room (or nil) when we're done. In this case, we just want
* to display a message when the player travels this way.
*/
"The passage takes you down a winding stairway to a previously
unseen entrance to...\b";
return( shiproom );
}
;
/*
* A readable is an object that can be read, such as a note, a sign, a
* book, or a memo. By default, reading the object displays its ldesc.
* However, if a separate readdesc is specified, "look at note" and
* "read note" could display different messages.
*/
winNote: readable
iscrawlable = true
sdesc = "note"
ldesc = "Congratulations! You've broken the stack! Please take this
fine WarpMaster 2000(tm) warp motivator, with my compliments. I'll
see you in \"Deep Space Drifter\"! "
noun = 'note'
location = room4
;
shiproom: room
sdesc = "Spaceship Room"
ldesc = "This is a very large cave dominated by a tall spaceship.
High above, a vertical tunnel leads upward; it is evidently a launch
tube for the spaceship. The exit is north. "
north = chuteroom
in = shipinterior
up =
{
"The tunnel is far too high above to climb. ";
return( nil );
}
;
/*
* The receptacle is both a fixeditem (something that can't be taken and
* carried around) and a container, so both superclasses are specified.
*/
shiprecept: fixeditem, container
sdesc = "socket"
noun = 'socket'
location = shiproom
ioPutIn( actor, do ) =
{
/*
* We only want to allow the warp motivator to be put in here.
* Check any object going in and disallow it if it's anything else.
*/
if ( do = motivator )
{
"It fits snugly. ";
do.moveInto( self );
}
else "It doesn't fit. ";
}
;
spaceship: fixeditem
sdesc = "spaceship"
noun = 'spaceship' 'ship'
adjective = 'space'
location = shiproom
ldesc =
{
"The spaceship is a tall gray metal cylinder with a pointed nosecone
high above, and three large fins at the bottom. A large socket ";
if ( motivator.location = shiprecept )
"on the side contains a warp motivator. ";
else
"is on the side (the socket is currently empty). The socket
is labelled \"insert warp motivator here.\" ";
"You can enter the spaceship through an open door. ";
}
verDoEnter( actor ) = {}
doEnter( actor ) = { self.doBoard( actor ); }
verDoBoard( actor ) = {}
doBoard( actor ) =
{
actor.travelTo( shipinterior );
}
;
shipinterior: room
sdesc = "Spaceship"
out = shiproom
ldesc = "You are in the cockpit of the spaceship. The control panel is
quite simple; the only feature that interests you at the moment is
a button labelled \"Launch.\" "
;
/*
* This is a fake "ship" that the player can refer to while inside the
* spaceship. This allows commands such as "look at ship" and "get out"
* to work properly while within the ship.
*/
shipship: fixeditem
location = shipinterior
sdesc = "spaceship"
noun = 'ship' 'spaceship'
adjective = 'space'
ldesc = { shipinterior.ldesc; }
verDoUnboard( actor ) = {}
doUnboard( actor ) =
{
Me.travelTo( shipinterior.out );
}
;
/*
* A buttonitem can be pushed. It's automatically a fixeditem, and
* always defines the noun 'button'. The doPush method specifies what
* happens when the button is pushed.
*/
launchbutton: buttonitem
sdesc = "launch button"
adjective = 'launch'
location = shipinterior
doPush( actor ) =
{
if ( motivator.location = shiprecept )
{
incscore( 10 );
"The ship's engines start to come to life. \"Launch sequence
engaged,\" the mechanical computer voice announces. ";
if ( lloyd.location = Me.location )
"\n\tLloyd heads for the door. \"Sorry,\" he says, \"I can't
go with you. Your policy specifically excludes coverage
during missions in deep space, and, frankly, it's too risky
for my tastes. Besides, I don't appear in 'Deep Space
Drifter.'\" Lloyd waves goodbye, and rolls out of the
spaceship.\n\t";
"The hatch closes automatically, sealing you into the
space vessel. The engines become louder and louder.
The computer voice announces, \"Launch
in five... four... three... two... one... liftoff!\"
The engines blast the ship into orbit.
\n\tYou realize that the time has come to set course for
\"Deep Space Drifter,\" another fine TADS adventure from
High Energy Software.\b";
scoreRank();
terminate();
quit();
abort;
}
else
{
"The ship's computer voice announces from a hidden speaker,
\"Error: no warp motivator installed.\" ";
}
}
;
motivator: treasure
sdesc = "warp motivator"
noun = 'motivator' 'warpmaster'
takevalue = 20
adjective = 'warp'
location = room4
ldesc = "It's a WarpMaster 2000(tm), the top-of-the-line model. "
;
foodthing: fooditem
noun = 'food'
sdesc = "food"
adesc = "some food"
ldesc = "It's a non-descript food item of the type the Food Service
typically prepares. "
location = room3drawer
;
/*
* An openable is a container, with the additional property that it can
* be opened and closed. To simplify things, we don't have a separate
* cap; use of the cap is implied in the "open" and "close" commands.
*/
bottle: openable
sdesc = "two-liter plastic bottle"
noun = 'bottle'
location = wastebasket
adjective = 'two-liter' 'plastic' 'two' 'liter'
isopen = nil
ldesc =
{
"The bottle is ";
if ( self.isfull ) "full of liquid nitrogen. ";
else "empty. ";
"It's "; if ( self.isopen ) "open. "; else "closed. ";
if ( funnel.location = self )
"There's a funnel in the bottle's mouth. ";
}
ioPutIn( actor, do ) =
{
if ( not self.isopen )
{
"It might help to open the bottle first. ";
}
else if ( do = ln2 )
{
if ( funnel.location = self )
{
"You manage to get some liquid nitrogen into the bottle. ";
bottle.isfull := true;
}
else
{
"You can't manage to get any liquid nitrogen into the
tiny opening. ";
}
}
else if ( do = funnel )
{
"A perfect fit! ";
funnel.moveInto( self );
}
else "That won't fit in the bottle. ";
}
verIoPourIn( actor ) = {}
ioPourIn( actor, do ) = { self.ioPutIn( actor, do ); }
doClose( actor ) =
{
if ( funnel.location = self )
"You'll have to take the funnel out first. ";
else if ( self.isfull )
{
"It takes some effort to close the bottle, since the rapidly
evaporating nitrogen occupies much more volume as a gas than
as a liquid. However, you manage to close it. ";
notify( self, #explodeWarning, 3 );
self.isopen := nil;
}
else
{
"Okay, it's closed. ";
self.isopen := nil;
}
}
/*
* explodeWarning is sent to the bottle as a "notification," which is
* a message that's scheduled to occur some number of turns in the
* future. In this case, closing the bottle while it has liquid
* nitrogen inside will set the explodeWarning notification.
*/
explodeWarning =
{
if ( not self.isopen )
{
if ( self.isIn( Me.location ))
{
"\bThe bottle is starting to make lots of noise, as though
the plastic were being stretched to its limit. ";
}
notify( self, #explode, 3 );
}
}
/*
* explode is set as a notification by explodeWarning. This routine
* actually causes the explosion. Since the bottle explodes, we will
* remove it from the game (by moving it into "nil"). If the bottle
* is in the right place, we'll also do some useful things.
*/
explode =
{
if ( not self.isopen )
{
"\b";
if ( self.location = banksafe )
{
if ( Me.location = bankvault )
{
"There is a terrible explosion from within the safe.
The door blasts open with a clang and a huge cloud of
water vapor. ";
if ( lloyd.location = bankvault )
"\n\tLloyd throws himself between you and the
vault. \"Please be careful!\" he admonishes.
\"The payment for Accidental Death due to Explosion
is enormous!\" ";
}
else
"You hear a distant, muffled explosion. ";
banksafe.isopen := true;
banksafe.isblasted := true;
}
else if ( self.isIn( Me.location ))
{
"The bottle explodes with a deafening boom and a huge
cloud of water vapor. As with most explosions, standing
in such close proximity was not advisable; it was, in
fact, fatal. ";
die();
abort;
}
else
{
"You hear a distant explosion. ";
}
self.moveInto( nil );
}
}
;
/*
* We're defining our own "class" of objects here. Up to now, we've been
* using classes defined in "adv.t", which you will recall we included at
* the top of the file. This class has some useful properties. For one,
* it has an attribute (istreasure) that tells us that the object is
* indeed a treasure (used in the slot in room 4's door to ensure that
* an object can be put in the slot). In addition, it supplements the
* doTake routine: when a treasure is taken for the first time, we'll
* add the object's "takevalue" to the overall score.
*/
class treasure: item
istreasure = true
takevalue = 5 // default point value when object is taken
putvalue = 5 // default point value when object is put in slot
doTake( actor ) =
{
if ( not self.hasScored ) // have we scored yet?
{
incscore( self.takevalue ); // add our "takevalue" to the score
self.hasScored := true; // note that we have scored
}
pass doTake; // continue with the normal doTake from "item"
}
;
alley1: room
sdesc = "Alley One"
ldesc =
{
"You are in the eternal twilight of Alley One, one of the twisty
little passages (all different) making up the student house in
which you live. Your room (room 3) is to the east. To the west
is a door (";
if ( alley1door.isopen ) "open"; else "closed";
"), affixed to which is a large sign. An exit is south, and the
hallway continues north. ";
}
east = startroom
north = alley1n
west =
{
/*
* Sometimes, we'll want to run some code when the player walks
* in a particular direction rather than just go to a new room.
* This is how. Returning "nil" means that the player can't go
* this way.
*/
if ( alley1door.isopen )
{
return( room4 );
}
else
{
"The door is closed and locked. You might read the
sign on the door for more information. ";
return( nil );
}
}
south = breezeway
out = breezeway
;
alley1n: room
sdesc = "Alley One"
ldesc = "You are at the north end of alley 1. A small room is
to the west. "
south = alley1
west = alley1comp
;
alley1comp: room
sdesc = "Computer Room"
ldesc =
{
"You are in a small computer room. Not surprisingly, the room
contains a personal computer. The exit is east. ";
if ( not self.isseen ) notify( compstudents, #converse, 0 );
}
east = alley1n
;
alley1pc: fixeditem
sdesc = "personal computer"
noun = 'computer'
adjective = 'personal'
location = alley1comp
ldesc = "The computer is in use by a couple of your fellow undergraduates.
Closer inspection of the screen shows that they seem to be playing a
text adventure. You've never really understood the appeal of those games
yourself, but you quickly surmise that the game is part of one of the
seniors' stacks. "
verIoTypeOn( actor ) = {}
ioTypeOn( actor, do ) =
{
"The computer is already in use. Common courtesy demands that you
wait your turn. ";
}
verDoTurnoff( actor ) = {}
doTurnoff( actor ) =
{
"The students won't let you, since they're busy using the computer. ";
}
;
compstudents: Actor
location = alley1comp
sdesc = "students"
adesc = "a couple of students"
ldesc = "The students are busy using the computer. "
actorAction( v, d, p, i ) =
{
"They're too wrapped up in what they're doing. ";
exit;
}
doAskAbout( actor, io ) =
{
"They're too busy to answer. ";
}
noun = 'students' 'undergraduates'
actorDesc = "A couple of your fellow undergraduates are here, using
the computer. They seem quite absorbed in what they're doing. "
state = 0
converse =
{
if ( Me.location = self.location )
{
"\b";
if ( self.state = 0 )
"\"Where are we going to find the dollar bill?\" one
of the students asks the other. They sit back and stare
at the screen, lost in thought. ";
else if ( self.state = 1 )
"\"Hey!\" says one of the students. \"Did you look under
the bed?\" The other student shakes his head. \"No way,
that would be a stupid puzzle!\" ";
else if ( self.state = 2 )
"One of the students using the computer types a long
string of commands, and finally types \"look under bed.\"
\"Wow! The dollar bill actually was under the bed! How
lame!\" ";
else
"The students continue to play with the computer. ";
self.state := self.state + 1;
}
}
;
class lockedDoor: fixeditem, keyedLockable
isopen = nil
islocked = true
noun = 'door'
sdesc = "door"
ldesc =
{
if ( self.isopen ) "It's open. ";
else if ( self.islocked ) "It's closed and locked. ";
else "It's closed. ";
}
verIoPutIn( actor ) = { "You can't put anything in that! "; }
;
alley1door: lockedDoor
location = alley1
ldesc =
{
if ( self.isopen ) "It's open. ";
else
"The door is closed and locked. There is a slot in the door,
and above that, a large sign is affixed to the door. ";
}
;
alley1sign: fixeditem, readable
noun = 'sign'
sdesc = "sign"
location = alley1
ldesc = "The sign says:
\b\t\tWelcome to Ditch Day!
\bThis stack is a treasure hunt. Gather all of the treasures, and you
break the stack.
To satisfy the requirements of this stack, you must find the
items listed below, and deposit them in the slot in the door. When
all items have been put in the slot, the stack will be solved and
the door will open automatically. The items to find are:
\b\tThe Great Seal of the Omega
\n\tMr.\ Happy Gear
\n\tA Million Random Digits
\n\tA DarbCard
\bThese items are hidden amongst the expanses of the Great
Undergraduate Excavation project. Happy hunting!
\bFor first-time participants, please note that
this is a \"finesse stack.\" You are not permitted to attempt to break
the stack by brute force. Instead, you must follow the rules above. "
;
alley1slot: fixeditem, container
noun = 'slot'
sdesc = "slot"
location = alley1
itemcount = 0
ioPutIn( actor, do ) =
{
if ( do.istreasure )
{
"\^<< do.thedesc >> disappears into the slot. ";
do.moveInto( nil );
incscore( do.putvalue );
self.itemcount := self.itemcount + 1;
if ( self.itemcount = 4 )
{
"As the treasure disappears into the slot, you hear a
klaxon from the other side of the door. An elaborate
series of clicks and clanks follows, then the door swings
open. ";
alley1door.islocked := nil;
alley1door.isopen := true;
}
}
else
{
"The slot will only accept items on the treasure list. ";
}
}
;
breezeway: room
sdesc = "Breezeway"
ldesc = "You are in a short passage that connects a courtyard,
to the east, to the outside of the building, which lies to the
west. A hallway leads north. "
north = alley1
east = courtyard
west = orangeWalk1
;
courtyard: room
sdesc = "Courtyard"
ldesc = "You are in a large outdoor courtyard.
An arched passage is to the west.
A passage leads east, and a stairway leads down. "
east = lounge
down = hall1
west = breezeway
;
lounge: room
sdesc = "Lounge"
ldesc = "You are in the lounge. A passage leads west, and a dining
room lies to the north. "
north = diningRoom
west = courtyard
out = courtyard
;
diningRoom: room
sdesc = "Dining Room"
ldesc = "You are in the dining room. There is a wooden table in
the center of the room. The lounge lies to the south,
and a passage to the east leads into the kitchen. "
east = kitchen
south = lounge
;
diningTable: surface, fixeditem
sdesc = "wooden table"
noun = 'table'
adjective = 'wooden'
location = diningRoom
;
fishfood: fooditem
noun = 'module'
adjective = 'fish' 'protein'
sdesc = "fish protein module"
ldesc = "It's a small pyramid-shaped white object, which is widely
considered to consist primarily of fish protein. The food service
typically resorts to such unappetizing fare toward the end of the
year. "
location = diningTable
;
kitchen: room
sdesc = "Kitchen"
ldesc = "You are in the kitchen. A ToxiCola(tm) machine is here.
A passage leads into the dining room to the west. "
west = diningRoom
out = diningRoom
;
toxicolaMachine: fixeditem, container
noun = 'machine' 'compartment'
adjective = 'toxicola'
sdesc = "ToxiCola machine"
ldesc =
{
"The machine dispenses ToxiCola, one of the big losers in the
Cola Wars. But, hey, it's cheap, so the food service installed it.
The machine consists of a compartment large enough for a cup,
and a button for dispensing ToxiCola into the cup. ";
if ( cup.location = self )
"The compartment contains a cup. ";
}
location = kitchen
ioPutIn( actor, do ) =
{
if ( do <> cup )
"That won't fit in the compartment. ";
else pass ioPutIn;
}
;
cup: container
sdesc = "coffee cup"
noun = 'cup'
adjective = 'coffee'
isFull = nil
ldesc =
{
if ( self.isFull ) "It's full of a viscous brown fluid. ";
else "It's empty. ";
}
location = diningTable
ioPutIn( actor, do ) =
{
if ( do = ln2 ) "The liquid nitrogen evaporates on contact. ";
else "It won't fit in the cup. ";
}
;
toxicola: fixeditem
sdesc = "toxicola"
noun = 'toxicola' 'cola'
ldesc = "It's a thick brown fluid. It appears to be quite flat. "
doTake( actor ) =
{
"You'll have to leave it in the cup. ";
}
verDoDrink( actor ) = {}
doDrink( actor ) =
{
"You drink the ToxiCola, despite your better judgment. It
initially sparks a sugar and caffeine rush, but that rapidly
fades, to be replaced by a strange dull throbbing. You enter
a semi-conscious state for several hours. It finally passes,
but you're not sure if it's been hours, weeks, or years. ";
cup.isFull := nil;
self.moveInto( nil );
}
;
toxicolaButton: buttonitem
location = kitchen
sdesc = "button"
doPush( actor ) =
{
if ( cup.location = toxicolaMachine )
{
if ( cup.isFull )
"ToxiCola spills over the already full cup, and drains
away. ";
else
{
"The horrible brown viscous fluid you have come to
know as ToxiCola fills the cup. ";
cup.isFull := true;
toxicola.moveInto( cup );
}
}
else
{
"Horrible viscous brown fluid spills into the empty
compartment, and drains away. ";
}
}
;
orangeWalk1: room
sdesc = "Orange Walk"
ldesc = "You are on a walkway lined with orange trees. The walkway
continues to the north, and an arched passage leads into a building
to the east. "
east = breezeway
north = orangeWalk2
;
/*
* We want a "class" of objects for the orange trees lining the
* orange walk. They don't do anything, so they're "decoration."
*/
class orangeTree: decoration
sdesc = "orange trees"
ldesc = "The orange trees are perfectly ordinary. "
adesc = "an orange tree"
noun = 'tree' 'trees'
adjective = 'orange'
verDoClimb( actor ) = {}
doClimb( actor ) =
{
"You climb into one of the orange trees, and quickly find the
view from the few feet higher to be highly uninteresting. You
soon climb back down. ";
}
;
orangeTree1: orangeTree
location = orangeWalk1
;
orangeWalk2: room
sdesc = "Orange Walk"
ldesc = "You are on a walkway lined with orange trees. The walkway
continues to the south, and leads into a large grassy square to the
north. "
north = quad
south = orangeWalk1
;
orangeTree2: orangeTree
location = orangeWalk2
;
quad: room
sdesc = "Quad"
ldesc = "You are on the quad, a large grassy square in the
center of campus. The bookstore lies to the northwest; the
health center lies to the northeast; Buildings and Grounds
lies to the north; and walkways lead west and south.
\n\tSome students dressed in radiation suits are staging a bogus
toxic leak, undoubtedly to fulfill the requirements of one of the
stacks. They are wandering around, looking very busy. Many reporters
are standing at a safe distance, looking terrified.
The supposed clean-up crew is pouring lots of liquid nitrogen onto
the ground, resulting in huge clouds of water vapor. "
south = orangeWalk2
nw = bookstore
west = walkway
ne = healthCenter
north = BandG
;
BandG: room
sdesc = "B&G"
ldesc = "You are in the Buildings and Grounds office. The exit is to
the south. "
south = quad
out = quad
;
bngmemo: readable
sdesc = "scrap of paper"
iscrawlable = true
noun = 'scrap' 'paper'
location = BandG
ldesc = "Most of the paper has been torn away; the part that remains
seems to have a list of numerical codes of some kind on it:
\b\t293 -- north tunnel lighting
\n\t322 -- station 2 lighting
\n\t612 -- behavior lab
\bThe rest is missing. "
;
healthCenter: room
sdesc = "Health Center"
ldesc = "You are in the health center. Like the rest of campus, this
place is deserted because of Ditch Day. The large desk would normally
have a receptionist behind it, but today, no one is in sight. "
sw = quad
out = quad
;
healthDesk: fixeditem, surface
sdesc = "desk"
noun = 'desk'
adjective = 'large'
location = healthCenter
;
healthMemo: readable
sdesc = "health memo"
iscrawlable = true
noun = 'memo'
plural = 'memos'
adjective = 'health'
location = healthDesk
ldesc =
"From:\t\tDirector of the Health Center
\nTo:\t\tAll Health Center Personnel
\nSubject:\tToxiCola toxicity
\bMany students have visited the Health Center recently, complaining
that the ToxiCola that is served in the student houses has not been
properly caffeinated. The students are complaining of drowsiness,
dizziness, and other symptoms that are normally associated with an
insufficient intake of caffeine.
\n\tUpon investigation, we have learned that the ToxiCola dispensers
in the student houses have become contaminated with a substance that
induces these effects. The substance has not yet been identified, but
the concentration seems to be increasing. All Health Center personnel
are urgently directed to advise students to avoid the ToxiCola if at
all possible. Students should be informed that their student health
insurance coverage will cover any purchases of other caffeinated
beverages that they need for their studies. "
;
students: decoration
sdesc = "students"
adesc = "a group of students"
noun = 'student' 'students'
location = quad
ldesc = "The students are making quite a good show of the simulated
nuclear waste spill. They're all wearing white clean-room suits with
official-looking \"Radiation Control District\" badges. They're
scampering about purposefully, keeping the crowd of reporters back
at a safe distance. "
;
presscorp: decoration
sdesc = "reporters"
adesc = "a group of reporters"
noun = 'reporter' 'reporters'
location = quad
;
flask: container
sdesc = "flask"
ldesc = "The flask appears to have lots of liquid nitrogen in it;
it's hard to tell just how much, since the opening is perpetually
clouded over with thick plumes of water vapor. "
noun = 'flask'
location = quad
ioPutIn( actor, do ) =
{
"You know from experience that it wouldn't be a good idea to
put "; do.thedesc; " into the liquid nitrogen, since the LN2 is
really, really cold. ";
}
;
pourVerb: deepverb
sdesc = "pour"
verb = 'pour'
doAction = 'Pour'
ioAction( inPrep ) = 'PourIn'
ioAction( onPrep ) = 'PourOn'
;
ln2: item
sdesc = "liquid nitrogen"
adesc = "some liquid nitrogen" // "a liquid nitrogen" doesn't compute
ldesc = "You can't see much, thanks to the thick clouds of water
vapor that inevitably form over such a cold substance. "
noun = 'nitrogen' 'ln2'
adjective = 'liquid'
location = flask
doTake( actor ) =
{
"You're better off leaving the liquid nitrogen in the flask. ";
}
verDoPour( actor ) = {}
verDoPourIn( actor, io ) = {}
doPour( actor ) =
{
askio( inPrep );
}
;
walkway: room
sdesc = "Walkway"
ldesc = "You are on a walkway. A large grassy square lies to the east;
buildings lie to the north and south. The walkway continues west. "
east = quad
north = behaviorLab
south = security
west = walkway2
;
walkway2: room
sdesc = "Walkway"
ldesc = "You are on a walkway, which continues to the east. Buildings
are to the north and south. "
east = walkway
south = explosiveLab
north = biobuilding
;
biobuilding: room
sdesc = "Biology Building"
ldesc = "You are in the biology building. The exit is south. "
south = walkway2
out = walkway2
;
bionotes: readable
sdesc = "notebook"
location = biobuilding
noun = 'notebook'
ldesc = "The notebook explains various lab techniques used in cloning
organisms. Since the invention of the CloneMaster, which requires only
a sample of genetic material from a subject (such as some blood, or a
bit of skin, or the like) and the basic skills required to operate a
household blender, most of the techniques are obsolete. Some of the data,
however, are interesting. For example, the notebook outlines the procedure
for reversing the sex of a clone; the introduction of chemicals identified
herein only as Genetic Factor XQ3, Polymerase Blue, and Compound T99 at
the start of the cloning process aparently does the trick. Most of the
rest of the document is a discussion of the human immune system; the
author comes to the conclusion that the human immune system, though a
novel idea, is far too improbable to ever actually be implemented. "
;
explosiveLab: room
sdesc = "Explosive Lab"
ldesc = "It's not that the lab itself is explosive (though it has blown
up a couple times in the past); rather, they study explosives here.
Unfortunately, all the good stuff has been removed by other Ditch Day
participants who got up earlier than you did. The exit is north. "
north = walkway2
out = walkway2
;
ln2doc: readable
sdesc = "thesis"
noun = 'thesis'
location = explosiveLab
ldesc = "The thesis is about Thermal Expansion Devices. It explains about
a new class of explosives that are made possible by low-temperature
fluid technology (i.e., liquid nitrogen) and high-tension polymer
containment vessels (i.e., plastic bottles). A great deal of jargon and
complicated theories are presented, presumably to fool the faculty
advisor into thinking the author actually did something useful with his
research funds; after wading through the nonsense, you find that the
paper is merely talking about putting liquid nitrogen into a plastic
soft-drink bottle, closing the bottle, then letting nature take its
course. Since the nitrogen will tend to evaporate at room temperature,
but will have no place to go, the bottle will eventually explode.
\bOn the cover page, you notice this important warning: \"Kids! Don't
try this at home! Liquid nitrogen is extremely cold, and can cause severe
injuries; it should only be handled by trained professionals. Never
put liquid nitrogen in a closed container.\" "
;
bookstore: room
sdesc = "Bookstore"
ldesc = "You are in the bookstore. The shelves are quite empty; no doubt
everything has been bought up by seniors in attempts to build their
stacks and underclassmen in attempts to break them. The exit is to the
southeast. "
out = { return( self.se ); }
se =
{
/*
* We need to check that the battery has been paid for, if it's
* been taken. If not, don't let 'em out.
*/
if ( battery.isIn( Me ) and not battery.isPaid )
{
"The clerk notices that you want to buy the battery. \"That'll be
five dollars,\" she says, waiting patiently. ";
return( nil );
}
else return( quad );
}
;
battery: item
location = bookstore
isPaid = nil
sdesc = "battery"
noun = 'battery'
verDoPayfor( actor ) =
{
if ( actor.location <> bookstore )
"I don't see anyone to pay! ";
}
doPayfor( actor ) =
{
clerk.doPay( actor );
}
verIoPayFor( actor ) = {}
ioPayFor( actor, do ) =
{
if ( do <> clerk )
{
"You can't pay "; do.thedesc; " for that! ";
}
else clerk.doPay( actor );
}
;
forPrep: Prep
sdesc = "for"
preposition = 'for'
;
payVerb: deepverb
sdesc = "pay"
verb = 'pay'
doAction = 'Pay'
ioAction( forPrep ) = 'PayFor'
;
payforVerb: deepverb
verb = 'pay for'
sdesc = "pay for"
doAction = 'Payfor'
;
money: item
sdesc = "five dollar bill"
noun = 'bill' 'money'
adjective = 'five' 'dollar' '5'
iscrawlable = true
;
clerk: Actor
noun = 'clerk'
location = bookstore
sdesc = "Clerk"
ldesc = "The clerk is a kindly lady to whom you have paid many hundreds
of dollars for books and other college necessities. "
actorDesc = "A clerk is near the exit, prepared to ring up any purchases
you might want to make (not that there's much left here to buy). "
verIoGiveTo( actor ) = {}
ioGiveTo( actor, do ) =
{
if ( do = money or do = dollar ) self.doPay( actor );
else if ( do = darbcard )
{
"The clerk shakes her head. \"Sorry,\" she says, \"we only
accept cash.\" ";
}
else if ( do = cup and cup.isFull )
{
"\"I never drink that stuff,\" the clerk says, \"and neither
should you! Do you have any idea what's in there? I probably
don't know half as much chemistry as you, but I know better
than to drink that.\" ";
}
else
{
"She doesn't appear interested. ";
}
}
verDoPay( actor ) = {}
doPay( actor ) =
{
if ( not battery.isIn( Me ))
{
"The clerk looks confused. \"I don't see what you're
paying for,\" she says. She then looks amused, realizing
that the students here somtimes get a little ahead of
themselves. ";
}
else if ( battery.isPaid )
{
"The clerk looks confused and says, \"You've already paid!\"
She then looks amused, realizing that the students here can
be a bit absent-minded at times. ";
}
else if ( not money.isIn( Me ))
{
if ( dollar.isIn( Me ))
{
"The clerk reminds you that the battery is five dollars.
All you have is one dollar. She looks amused; \"They can
do calculus in their sleep but they can't add,\" she jokes. ";
}
else
{
"You unfortunately don't have anything with which to pay the
clerk. ";
}
}
else
{
"The clerk accepts your money and says \"Thank you, have a nice
day.\"";
battery.isPaid := true;
money.moveInto( nil );
}
}
;
behaviorLab: room
sdesc = "Behavior Lab"
ldesc = "You are in the behavior lab. The exit is to the south,
and a locked door is to the north. The door is labelled \"Maze -
Experimental Subjects Only.\" In addition, a passage labelled
\"Viewing Room\" leads east. "
south = walkway
out = walkway
east = mazeview
north =
{
"The door is closed and locked. Besides, do you really want to
be an \"Experimental Subject\"?";
return( nil );
}
;
mazeview: room
sdesc = "Maze Viewing Room"
ldesc =
{
"The entire north wall of this room is occupied by a window
overlooking a vast human-sized labyrinth. No experimental subjects
(i.e., students) seem to be wandering through the maze at the
moment, ";
if ( not mazeStart.isseen )
"but you have the strange feeling that you will have to find
your way through the maze some day. You read with a sense of
foreboding the plaque affixed to the wall:\b";
else
"so your attention wanders to the plaque on the wall:\b";
mazeplaque.ldesc;
}
west = behaviorLab
;
mazewindow: fixeditem
sdesc = "window"
noun = 'window'
location = mazeview
verDoLookthru( actor ) = {}
doLookthru( actor ) = { self.ldesc; }
ldesc =
{
"The window looks out onto a vast human-sized labyrinth.
The maze is currently devoid of experimental subjects";
if ( not mazeStart.isseen )
", but you have the strange feeling that you'll have to find
your way through the maze someday";
". ";
}
;
mazeplaque: fixeditem, readable
sdesc = "plaque"
noun = 'plaque'
location = mazeview
ldesc = "*** The Behavioral Biology Laboratory Psycho-Magnetic Maze ***
\bThe Psycho-Magnetic Maze that is visible through the window has been
constructed to determine how the human directional sense interacts with
strong electromagnetic and nuclear fields. Through careful tuning of
these fields, we have found that human subjects often become completely
disoriented in the maze, resulting in hours of random and
desperate wandering, and much amusement to those of us in the observation
room. "
;
behaviorDoor: lockedDoor
ldesc = "The door is closed and locked, and labelled \"Experimental
Subjects Only.\""
location = behaviorLab
;
security: room
sdesc = "Security Office"
ldesc = "You are in the campus security office, the very nerve-center of
the elite Kaltech Kops. The officers all
appear to be absent; undoubtedly they are all scurrying hither and
yon trying to deal with the ditch-day festivities. There is a desk
in the center of the room. The exit is to
the north. "
north = walkway
out = walkway
;
securityDesk: fixeditem, surface
sdesc = "desk"
noun = 'desk'
location = security
;
securityMemo: readable
sdesc = "security memo"
iscrawlable = true
noun = 'memo'
plural = 'memos'
adjective = 'security'
location = securityDesk
ldesc =
"From:\t\tDirector of Security
\nTo:\t\tAll Security Personnel
\nSubject:\tGreat Undergraduate Excavation
\bIt has come to the attention of the Kaltech Kops that the student
activity in the steam tunnels, known as the \"Great Undergraduate
Excavation\" project, has escalated vastly in recent years. Due to
objections from city officials about noise from underground and the
fear local residents have expressed that their property will be
undermined, this office has taken action to halt all GUE activity.
Effective immediately, a security officer will be posted at all
known steam tunnel entrances, and shall under no circumstances allow
students to enter. "
;
flashlight: container
islamp = true
sdesc = "flashlight"
noun = 'flashlight' 'light'
adjective = 'flash'
location = security
ioPutIn( actor, do ) =
{
if ( do <> battery )
{
"You can't put "; do.thedesc; " into the flashlight. ";
}
else pass ioPutIn;
}
Grab( obj ) =
{
/*
* Grab( obj ) is invoked whenever an object 'obj' that was
* previously located within me is removed. If the battery is
* removed, the flashlight turns off.
*/
if ( obj = battery ) self.islit := nil;
}
ldesc =
{
if ( battery.location = self )
{
if ( self.islit )
"The flashlight (which contains a battery) is turned on
and is providing a warm, reassuring beam of light. ";
else
"The flashlight (which contains a battery) is currently off. ";
}
else
{
"The flashlight is off. It seems to be missing a battery. ";
}
}
verDoTurnon( actor ) =
{
if ( self.islit ) "It's already on! ";
}
doTurnon( actor ) =
{
if ( battery.location = self )
{
"The flashlight is now on. ";
self.islit := true;
}
else "The flashlight won't turn on without a battery. ";
}
verDoTurnoff( actor ) =
{
if ( not self.islit ) "It's not on. ";
}
doTurnoff( actor ) =
{
"Okay, the flashlight is now turned off. ";
self.islit := nil;
}
;
goToSleep: function
{
}
hall1: room
sdesc = "Hallway"
ldesc = "You are at the west end of a basement hallway. A stairway
leads up. "
up = courtyard
east = hall2
;
hall2: room
sdesc = "Hallway"
ldesc = "You are in an east-west hallway in the basement. Another hallway
goes off to the north. "
west = hall1
east = hall3
north = hall4
;
hall3: room
sdesc = "Hallway"
ldesc = "You are at the east end of a hallway in the basement.
A passage leads north. "
west = hall2
north = laundry
;
laundry: room
sdesc = "Laundry Room"
ldesc = "You are in the laundry room. There is a washing machine
against one wall. The exit is to the south. "
south = hall3
out = hall3
;
washingMachine: fixeditem, openable
sdesc = "washing machine"
isopen = nil
location = laundry
noun = 'machine' 'washer'
adjective = 'washing'
;
jeans: item
sdesc = "blue jeans"
location = washingMachine
noun = 'jeans' 'pants'
adjective = 'blue'
ldesc =
{
if ( self.isseen ) "It's an ordinary pair of jeans. ";
else
{
"It looks like an ordinary pair of jeans, though not
your size. As you inspect them, you notice a key fall
out of them and to the ground. ";
masterKey.moveInto( Me.location );
self.isseen := true;
}
}
verDoLookin( actor ) = {}
doLookin( actor ) = { self.ldesc; }
verDoWear( actor ) = { "They're not your size. "; }
;
masterKey: keyItem
iscrawlable = true
sdesc = "master key"
noun = 'key'
adjective = 'master'
doTake( actor ) =
{
if ( not self.isseen )
{
"*Some* adventure games would try to impose their authors'
misguided sense of ethics on you at this point, telling you
that you don't feel like picking up the key, or you don't have
time to do that, or that it's against the rules to even possess
a master key, much less steal one from some other student's
pants that you happened to find in a laundry, or even more
likely that you are unable to take the key while wearing that
dress. However, you're the player, and you're in charge around
here, so I'll let you make your own judgments about what's
ethical and proper here... ";
self.isseen := true;
}
pass doTake;
}
;
hall4: room
sdesc = "Hallway"
ldesc = "You are in a north-south hallway in the basement. "
south = hall2
north = hall5
;
hall5: room
sdesc = "Hallway"
ldesc = "You are at a corner in the basement hallway. You can go east
or south. "
south = hall4
east = hall6
;
hall6: room
sdesc = "Hallway"
ldesc = "You are at the east end of a basement hallway. To the north is
a \"storage room,\" which everyone knows is actually an entrance
to the steam tunnels. "
west = hall5
north = storage
;
storage: room
sdesc = "Storage Room"
ldesc =
{
"You are in a large storage room. There really hasn't been
anything stored here for a long time (at least, not anything that
anybody wants to ever see again). The exit is to the south. To
the north lies a door, which is ";
if ( tunnelDoor.isopen ) "open"; else "closed"; ". A small card
table is sitting in front of the door. ";
}
south = hall6
north =
{
if ( guard.isActive )
{
"The guard won't let you enter the tunnel. ";
return( nil );
}
else if ( not tunnelDoor.isopen )
{
"A closed door stands in your way. ";
setit( tunnelDoor ); /* "it" now refers to the closed door */
return( nil );
}
else return( tunnel1 );
}
enterRoom( actor ) =
{
if ( guard.isActive )
{
notify( guard, #patrol, 0 );
}
pass enterRoom;
}
leaveRoom( actor ) =
{
if ( guard.isActive )
{
unnotify( guard, #patrol );
}
pass leaveRoom;
}
;
tunnelDoor: lockedDoor
location = storage
mykey = masterKey
;
guard: Actor
sdesc = "guard"
noun = 'guard' 'him'
ldesc =
{
"The guard is a member of the Kaltech Kops, the elite corps of
dedicated men and women that keeps the campus safe from undesirables
(i.e., the students). ";
if ( not self.isActive )
"Currently, the guard is fast asleep, which is quite typical. ";
}
adjective = 'security'
isActive = true
location = storage
actorDesc =
{
if ( self.isActive )
"A guard is sitting at the card table in front of the door.
He watches you carefully, evidently thinking that you might
be planning to try to go through the door. ";
else
"A guard is slumped over a small card table in front of the
steam tunnel entrance, evidently fast asleep. How typical. ";
}
verIoGiveTo( actor ) =
{
if ( not self.isActive )
"The guard appears to be fast asleep. ";
}
ioGiveTo( actor, do ) =
{
if ( do = dollar or do = money )
"The guard looks at you sternly. \"You should be ashamed of
yourself, trying to bribe a member of the elite Kaltech Kops!\"
he admonishes you, refusing your offer. ";
else if ( do <> cup or not cup.isFull )
"The guard doesn't appear interested. ";
else
{
self.isActive := nil;
unnotify( self, #patrol );
"The guard happily accepts your offer; \"ToxiCola! My favorite!\"
he says appreciatively, not knowing the evil deed
that you have in mind. He quickly drinks the entire cup of
ToxiCola. \"Wow! Just the caffeine pickup I needed,\" he says
happily.
\n\tAfter a few moments, though, he looks rather queasy. \"That
caffeine just doesn't last long enough,\" he says just before
he passes out, slumping over the card table. ";
cup.isFull := nil;
toxicola.moveInto( nil );
cup.moveInto( cardtable );
incscore( 10 );
}
}
patrolMessage =
[
// random message 1
'The guard eyes you warily.'
// random message 2
'The guard looks at his empty glass, probably wishing he had
something to drink.'
// random message 3
'The guard flips purposefully through the pages of his memo pad.'
// random message 4
'The guard writes something down on his memo pad, glancing up from
time to time to eye you suspiciously.'
// random message 5
'The guard picks up his empty glass and starts to drink, then
realizes it is empty and puts it back down.'
]
patrol =
{
if ( self.location = Me.location )
{
"\b";
say( self.patrolMessage[rand( 5 )]);
}
}
;
cardtable: fixeditem, surface
noun = 'table'
adjective = 'card'
location = storage
sdesc = "card table"
;
emptyglass: container
noun = 'glass'
adjective = 'empty'
sdesc = "empty glass"
adesc = "an empty glass"
location = cardtable
doTake( actor ) =
{
if ( guard.isActive )
"The guard won't let you take the glass. \"Get your own,\"
he says. ";
else pass doTake;
}
ioPutIn( actor, do ) =
{
if ( do = ln2 ) "The liquid nitrogen evaporates on contact. ";
else "It won't fit in the glass. ";
}
;
tunnelSounds: function( parm )
{
if ( Me.location.istunnel )
{
"\b";
say( tunnelroom.randomsound[rand( 5 )]);
}
setfuse( tunnelSounds, rand( 5 ), nil );
}
class tunnelroom: room
istunnel = true
sdesc = "Steam Tunnel"
randomsound = [
// random sound 1
'The rumbling sound suddenly becomes very loud, then, after
a few moments, dies down to background levels again.'
// random sound 2
'A series of clanking noises, like marbles rolling through the
steam pipes, starts in the distance, then comes
closer and closer, until it seems to pass right overhead. It disappears
into the distance.'
// random sound 3
'A very loud bang suddenly reverberates through the tunnel.'
// random sound 4
'One of the pipes starts to hiss wildly. After a few moments, it
fades back into the background sounds.'
// random sound 5
'A loud buzzing sound, like an overloaded electrical circuit,
emanates from somewhere nearby. After a few moments it is gone.'
]
;
tunnelpipes: fixeditem
sdesc = "pipes"
noun = 'pipe' 'pipes'
ldesc = "The pipes range from very small copper tubes only an inch around
to huge asbestos-covered cylinders over two feet in diameter. Many of
the larger pipes are marked \"STEAM - 300 PSI.\" "
locationOK = true
location =
{
if ( Me.location.istunnel ) return( Me.location );
else return( nil );
}
;
tunnel1: tunnelroom
ldesc = "You are in a steam tunnel. It is very hot and dry in here.
The place has a strange musty odor; the air is very still, but there
are distant sounds of all sorts that vibrate through the pipes. The
pipes all seem to be hissing quietly, and a low rumbling sound constantly
reverberates through the tunnel. Occasionally a distant clang or thud
or crack emanates from the pipes.
\n\tThe steam tunnel runs east and west. A small passage leads south. "
east = tunnel2
west = tunnel3
south = storage
enterRoom( actor ) =
{
if ( not self.isseen ) setfuse( tunnelSounds, rand( 5 ), nil );
pass enterRoom;
}
;
tunnel2: tunnelroom
ldesc = "You are at the east end of the steam tunnel. "
west = tunnel1
;
tunnelStorage: room
sdesc = "Storage Room"
ldesc = "You are in a small storage room. The exit lies north. "
north = tunnel13
;
tunnel3: tunnelroom
ldesc = "You are in an east-west section of the steam tunnels. "
east = tunnel1
west = tunnel4
;
tunnel4: tunnelroom
ldesc = "You are at a T-intersection of two sections of steam
tunnel; tunnels go off to the north, south, and east. "
east = tunnel3
north = tunnel5
south = tunnel6
;
darktunnel: darkroom, tunnelroom
controlon = nil
islit =
{
if ( self.controlon ) return( true );
else pass islit;
}
;
tunnel5: darktunnel
ldesc = "You are at a corner in the steam tunnel: you can go
west and south. "
west = tunnel7
south = tunnel4
;
tunnel6: tunnelroom
ldesc = "You are at a corner in the steam tunnel: you can go
west and north. "
west = tunnel8
north = tunnel4
;
tunnel7: darktunnel
ldesc = "You are in an east-west section of the steam tunnel.
A very small passage between some steam pipes leads north, but
it would be a tight squeeze. "
east = tunnel5
west = tunnel9
north =
{
return(crawltest( tunnel12,
'You lay down on one of the pipes and start to snake
through the passage. For a moment, you think you\'re
stuck, but you manage to wriggle your way through. You
emerge on the north side of the narrow crawl.' ));
}
;
tunnel8: tunnelroom
controlon = true
ldesc =
{
"You are in an east-west section of the steam tunnel. On the
wall is a control unit. ";
if ( not self.controlon )
{
"It is quite dark in this section of the tunnel; the only
illumination is coming from the control unit's display";
if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
and flashlight.islit )
" (and from the flashlight, of course)";
". ";
}
}
east = tunnel6
west = tunnel10
;
controlunit: fixeditem
sdesc = "control unit"
noun = 'unit'
adjective = 'control'
location = tunnel8
ldesc =
{
"The control unit is quite modern and high-tech looking, in
stark contrast to the tunnels around it. It consists of a keypad
which allows entry of arbitrary numbers, a large green button,
and a display screen. The unit is labelled \"Station 2.\" ";
controldisp.ldesc;
}
objref =
{
local l;
l := self.value;
if ( l = 322 ) return( tunnel8 );
else if ( l = 612 ) return( mazeroom );
else if ( l = 293 ) return( darktunnel );
else return( nil );
}
value = 322
;
controlpad: fixeditem
sdesc = "keypad"
noun = 'keypad' 'pad'
adjective = 'key'
location = tunnel8
ldesc = "It's one of those cheesy membrane keypads, like on a microwave
oven or the new Enterprise's control panels. It allows you to type numbers
made up of digits from 0 to 9. "
verIoTypeOn( actor ) = {}
ioTypeOn( actor, do ) =
{
if ( do <> numObj )
"The keypad only allows entry of numbers. ";
else
{
"As you type the number sequence, the display screen is
updated. ";
controlunit.value := numObj.value;
controldisp.ldesc;
}
}
;
controlbutton: buttonitem
sdesc = "button"
adjective = 'green'
location = tunnel8
doPush( actor ) =
{
local r;
r := controlunit.objref;
if ( r )
{
"The display is updated as you press the button. ";
r.controlon := not r.controlon;
controldisp.ldesc;
if ( r = tunnel8 )
{
"The lights in the tunnel ";
if ( r.controlon )
"come on. ";
else
{
"go out, leaving only the display screen's light ";
if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
and flashlight.islit )
"(and the flashlight, of course) ";
"for illumination. ";
}
}
}
else "The unit beeps; nothing else appears to happen. ";
}
;
controldisp: fixeditem
sdesc = "display screen"
noun = 'screen'
adjective = 'display'
location = tunnel8
ldesc =
{
local l, r;
l := controlunit.value;
r := controlunit.objref;
"The screen is currently displaying: \""; say( l ); ": ";
if ( r )
{
if ( r.controlon ) "ON"; else "OFF";
}
else "???";
"\". ";
}
;
tunnel9: darktunnel
ldesc = "You are at a corner in the steam tunnel. You can go east
or south. "
east = tunnel7
south = tunnel11
;
tunnel10: tunnelroom
ldesc = "You are at a corner in the steam tunnel. You can go east
or north. "
east = tunnel8
north = tunnel11
;
tunnel11: tunnelroom
ldesc = "You are in a north-south section of the steam tunnels. Set
into one wall is a large chute. "
north = tunnel9
south = tunnel10
;
chute: fixeditem, container
sdesc = "chute"
noun = 'chute'
location = tunnel11
ldesc = "The chute is large enough for anything you're carrying,
but not nearly big enough for you. You can't tell where it goes,
except down. "
ioPutIn( actor, do ) =
{
"You put "; do.thedesc; " into the chute, and it slides away
into the darkness. After a few moments, you hear a soft thud. ";
do.moveInto( chuteroom );
}
;
crawltest: function( rm, msg )
{
local i;
i := 1;
while ( i <= length( Me.contents ))
{
if ( not Me.contents[i].iscrawlable )
{
"You'll never get through carrying ";
Me.contents[i].thedesc; ". ";
return( nil );
}
i := i + 1;
}
say( msg ); "\b";
return( rm );
}
tunnel12: tunnelroom
ldesc =
{
if ( self.isseen )
"You are in an east-west section of the steam tunnels. A narrow
passage between some steam pipes might allow you to go south. ";
else
"You are in another steam tunnel, but this one is substantially
different from the tunnels you have been in so far. This tunnel
is much wider, less cluttered; it looks like it was built more
recently than the south tunnels. The tunnel itself runs east
and west, and passing back to the south is evidently possible,
given your presence here. ";
}
east = tunnel13
west = pitTop
south =
{
return(crawltest( tunnel7, 'Going through the crawl
southbound is just as difficult as it was coming north,
you observe.' ));
}
;
tunnel13: tunnelroom
ldesc = "You are at the east end of a steam tunnel. A passage leads
north, and another one leads south. "
west = tunnel12
north = maze0
south = tunnelStorage
;
maze0: room
sdesc = "Outside Maze"
ldesc =
{
"You are in a small room, with exits north and south. The
passage to the north has a small sign reading \"Behavior Lab Maze\";
the room is filled with strange equipment, which you surmise is
connected in some way to the maze. ";
if ( mazeroom.controlon )
"The equipment is buzzing loudly. Standing
near it makes you feel vaguely dizzy. ";
if ( not self.isseen )
{
"\n\tYou sigh in resignation as you realize that you have reached
the obligatory Adventure Game Maze, and ";
if ( mazeview.isseen )
"wish that this were a graphical adventure, so your trip to
the maze viewing room had resulted in a map you could refer
to now. Fortunately, you do recall noting that the passages
in the maze all lead east-west or north-south. ";
else
"wonder what this maze's unique twist will be. Surely, it
won't just be a boring old labyrinth... ";
}
}
south = tunnel13
north = maze1
;
mazeequip: decoration
noun = 'equipment' 'coil' 'coils' 'pipe' 'pipes' 'wire' 'wires'
adjective = 'electric' 'electrical'
sdesc = "equipment"
location = maze0
ldesc =
{
"The equipment resembles some of the particle accelerators that
you have seen. It has several huge electric coils, all arranged
around a series of foot-diameter pipes. A tangled web of enormous
wires connects various parts of the equipment together and other
wires feed it power. ";
if ( mazeroom.controlon )
"The equipment is buzzing loudly. Standing near it makes
you feel vaguely dizzy. ";
}
;
mazeroom: room
controlon = true
sdesc = "Lost in the Maze"
lookAround( verbosity ) =
{
self.statusLine;
self.nrmLkAround( self.controlon ? true : verbosity );
}
ldesc =
{
if ( self.controlon )
"You can't quite seem to get your bearings. There are some
passages leading away, but you can't quite tell how many or
in which direction they leads. ";
else
{
local cnt, tot, i;
tot := 0;
i := 1;
while ( i <= 4 )
{
if ( self.dirlist[i] ) tot := tot + 1;
i := i + 1;
}
"You are in a room in the maze; they all look alike.
You can go ";
i := 1;
cnt := 0;
while ( i <= 4 )
{
if ( self.dirlist[i] )
{
if ( cnt > 0 )
{
if ( tot = 2 ) " and ";
else if ( cnt+1 = tot ) ", and ";
else ", ";
}
cnt := cnt + 1;
say( ['north' 'south' 'east' 'west'][i] );
}
i := i + 1;
}
". ";
}
}
mazetravel( rm ) =
{
if ( self.controlon )
{
local r;
"You can't figure out which direction is which; the more you
stumble about, the more the room seems to spin around. After a
few steps, you're not sure if you've actually gone anywhere,
since all these rooms look alike...\b";
/*
* We know we can only go one of four directions, but generate
* a random number up to 6; if we generate 5 or 6, we won't go
* anywhere, but we won't let on that this is the case.
*/
r := rand( 6 );
/*
* Note that we want to confuse the player in active-maze mode
* as much as possible, so we don't want any clues as to whether
* there was any travel in this direction or not. So, return
* "self" rather than "nil," since we won't get any message if
* we return "nil," but we'll get the current room's message if
* we return "self;" since all the messages are the same, this
* won't provide any information.
*/
if ( r < 5 )
{
r := self.dirlist[ r ];
if ( r ) return( r );
else return( self );
}
else return( self );
}
else
{
if ( rm )
return( rm );
else
{
"You can't go that way. ";
return( nil );
}
}
}
north = ( self.mazetravel( self.dirlist[1] ))
south = ( self.mazetravel( self.dirlist[2] ))
east = ( self.mazetravel( self.dirlist[3] ))
west = ( self.mazetravel( self.dirlist[4] ))
up = ( self.mazetravel( 0 ))
down = ( self.mazetravel( 0 ))
in = ( self.mazetravel( 0 ))
out = ( self.mazetravel( 0 ))
ne = ( self.mazetravel( 0 ))
nw = ( self.mazetravel( 0 ))
se = ( self.mazetravel( 0 ))
sw = ( self.mazetravel( 0 ))
;
maze1: mazeroom
dirlist = [ 0 maze0 maze2 0 ]
;
maze2: mazeroom
dirlist = [ maze9 0 maze3 maze1 ]
;
maze3: mazeroom
dirlist = [ maze8 0 maze4 maze2 ]
;
maze4: mazeroom
dirlist = [ 0 0 maze5 maze3 ]
;
maze5: mazeroom
dirlist = [ maze6 0 0 maze4 ]
;
maze6: mazeroom
dirlist = [ 0 maze5 0 maze7 ]
;
maze7: mazeroom
dirlist = [ maze30 0 maze9 maze8 ]
;
maze8: mazeroom
dirlist = [ maze29 maze3 maze7 0 ]
;
maze9: mazeroom
dirlist = [ 0 maze2 0 maze10 ]
;
maze10: mazeroom
dirlist = [ 0 0 maze9 maze11 ]
;
maze11: mazeroom
dirlist = [ 0 maze35 maze10 maze12 ]
;
maze12: mazeroom
dirlist = [ 0 0 maze11 0 ]
;
maze13: mazeroom
dirlist = [ maze24 maze18 0 0 ]
;
maze14: mazeroom
dirlist = [ 0 maze17 0 maze15 ]
;
maze15: mazeroom
dirlist = [ 0 maze16 maze14 0 ]
;
maze16: mazeroom
dirlist = [ maze15 maze23 maze17 0 ]
;
maze17: mazeroom
dirlist = [ maze14 maze22 maze18 maze16 ]
;
maze18: mazeroom
dirlist = [ maze13 maze21 0 maze17 ]
;
maze19: mazeroom
dirlist = [ 0 maze20 maze35 0 ]
;
maze20: mazeroom
dirlist = [ maze19 0 0 maze21 ]
;
maze21: mazeroom
dirlist = [ maze18 0 maze20 0 ]
;
maze22: mazeroom
dirlist = [ maze17 0 0 0 ]
;
maze23: mazeroom
dirlist = [ maze16 0 0 0 ]
;
maze24: mazeroom
dirlist = [ 0 maze13 maze25 0 ]
;
maze25: mazeroom
dirlist = [ maze33 0 maze26 maze24 ]
;
maze26: mazeroom
dirlist = [ maze32 0 0 maze25 ]
;
maze27: mazeroom
dirlist = [ maze31 0 0 0 ]
;
maze28: mazeroom
dirlist = [ 0 0 maze29 0 ]
;
maze29: mazeroom
dirlist = [ 0 maze8 maze30 maze28 ]
;
maze30: mazeroom
dirlist = [ 0 maze7 0 maze29 ]
;
maze31: mazeroom
dirlist = [ 0 maze27 0 maze32 ]
;
maze32: mazeroom
dirlist = [ 0 maze26 maze31 0 ]
;
maze33: mazeroom
dirlist = [ 0 maze25 0 maze34 ]
;
maze34: mazeroom
dirlist = [ 0 0 maze33 mazeStart ]
;
maze35: mazeroom
dirlist = [ maze11 0 0 maze19 ]
;
mazeStart: room
sdesc = "Start of Maze"
ldesc = "You are at the start of the maze. A passage into the
maze is to the east, and a heavy one-way door marked \"Exit\" is to the
south. "
east = maze34
south = behaviorLab
;
mazedoor: fixeditem
sdesc = "door"
noun = 'door'
adjective = 'exit' 'one-way' 'heavy'
verDoOpen( actor ) = { "No need; just walk on through. "; }
location = mazeStart
;
chuteroom: room
sdesc = "Chute Room"
ldesc = "You are in a small room with exits to the northwest
and south. The bottom of a large chute opens into the room. "
nw = pitBottom
south = shiproom
;
chute2: fixeditem, container
sdesc = "chute"
noun = 'chute'
location = chuteroom
ioPutIn( actor, do ) =
{
"This is the bottom of the chute; you can't put objects
into it. ";
}
;
pitTop: tunnelroom
sdesc = "Top of Pit"
ldesc =
{
"You are in a large open area in the steam tunnels. In
the center of the room is a large pit, around which is a protective
railing. A steam tunnel is to the east. ";
if ( rope.tieItem = railing )
"A rope is tied to the railing, and extends down into the pit. ";
}
east = tunnel12
down =
{
if ( rope.tieItem = railing )
{
"You climb down the rope...\b";
return( pitBottom );
}
else
{
"You'd probably break your neck if you tried to jump
into the pit. ";
return( nil );
}
}
;
tieVerb: deepverb
sdesc = "tie"
verb = 'tie'
prepDefault = toPrep
ioAction( toPrep ) = 'TieTo'
;
railing: fixeditem
sdesc = "rail"
noun = 'rail' 'railing'
location = pitTop
verIoTieTo( actor ) = {}
ioTieTo( actor, do ) =
{
"You tie one end of the rope to the railing, and lower the other
end into the pit. It appears to extend to the bottom of the pit. ";
rope.tieItem := self;
rope.moveInto( pitTop );
rope.isfixed := true;
}
;
climbupVerb: deepverb
verb = 'climb up'
sdesc = "climb up"
doAction = 'Climbup'
;
climbdownVerb: deepverb
verb = 'climb down'
sdesc = "climb down"
doAction = 'Climbdown'
;
rope: item
sdesc = "rope"
isListed = ( not self.isfixed )
noun = 'rope'
location = tunnelStorage
ldesc =
{
if ( self.tieItem )
{
"It's tied to "; self.tieItem.thedesc; ". ";
}
else pass ldesc;
}
verDoTieTo( actor, io ) =
{
if ( self.tieItem )
{
"It's already tied to "; self.tieItem.thedesc; "! ";
}
}
doTake( actor ) =
{
if ( self.tieItem )
{
"(You untie it first, of course.) ";
self.tieItem := nil;
self.isfixed := nil;
}
pass doTake;
}
verDoClimb( actor ) =
{
if ( self.tieItem = nil )
"Climbing down the rope in its present configuration would
get you nowhere. ";
}
doClimb( actor ) =
{
"You climb down the rope...\b";
Me.travelTo( pitBottom );
}
verDoClimbdown( actor ) = {}
doClimbdown( actor ) = { self.doClimb( actor ); }
;
pitBottom: room
sdesc = "Huge Cavern"
ldesc = "You are in a huge and obviously artificial cavern. The cave
has apparently been dug out over a long period of time; some parts
look very old, and other areas look comparatively recent. A small bronze
plaque affixed to one of the older walls reads, \"Great Undergraduate
Excavation - 1982.\"
From high above, a small opening in
the ceiling casts a dim glow over the vast chamber. A rope extends
from the opening above. Passages of various ages lead north, south,
east, west, southeast, and southwest. "
up =
{
"It's a long climb, but you somehow manage it.\b";
return( pitTop );
}
se = chuteroom
east = biohall1
south = bank
north = cave
sw = insOffice
west = machineshop
;
pitplaque: fixeditem, readable
noun = 'plaque'
sdesc = "bronze plaque"
adjective = 'bronze' 'small'
location = pitBottom
ldesc = "Great Undergraduate Excavation\n\t\t\t1982"
;
insOffice: room
sdesc = "Insurance Office"
ldesc =
{
"You are in an insurance office. Like most insurance offices,
the area is rather non-descript. The exit is northeast. ";
if ( not self.isseen )
{
"\n\tAs you walk into the office, a large metallic robot, very
much like the traditional sci-fi film robot, but wearing a dark
polyester business suit, zips up to you. \"Hi, I'm Lloyd the
Friendly Insurance Robot,\" he says in a mechanical British
accent. \"You look like you could use some insurance! Here, let
me prepare a policy for you.\"
\n\tLloyd scurries around the room, gathering papers and
studying charts, occasionally zipping up next to you and
measuring your height and other dimensions, making all kinds
of notes, and generally scampering about. After a few minutes,
he comes up to you, showing you a piece of paper.
\n\t\"I have the perfect policy for you. Just one dollar will
buy you a hundred thousand worth of insurance!\" He watches
you anxiously. ";
notify( lloyd, #offerins, 0 );
}
}
ne = pitBottom
out = pitBottom
;
/*
* Lloyd the Friendly Insurance Robot is a full-featured actor. He will
* initially just wait in his office until paid for a policy, but will
* thereafter follow the player around relentlessly. Lloyd doesn't
* interact much, though; he just hangs around and does wacky things.
*/
lloyd: Actor
noun = 'lloyd' 'him'
sdesc = "Lloyd"
adesc = "Lloyd"
thedesc = "Lloyd"
ldesc = "Lloyd the Friendly Insurance Robot is a strange combination
of the traditional metallic robot and an insurance salesman; over his
bulky metal frame is a polyester suit. "
actorAction( v, d, p, i ) =
{
if ( v = helloVerb )
"\"Hello,\" Lloyd responds cheerfully. ";
else if ( v = followVerb and d = Me )
{
if ( self.offering )
"\"Sorry, but I must stay here until I've made a sale.\" ";
else
"\"I will follow you,\" Lloyd says. \"That will allow me
to pay any claim you make immediately should the need arise.
It's just one of the ways we keep our overhead so low.\" ";
}
else
"\"I'm sorry, that's not in your policy.\" ";
exit;
}
verDoAskAbout( actor, io ) = {}
doAskAbout( actor, io ) =
{
if ( io = policy )
"\"Your policy perfectly fits your needs, according to my
calculations,\" Lloyd says. \"I'm afraid it's much too
complicated to go into in any detail right now, but you have
my assurances that you won't be disappointed.\" ";
else
"\"I'm afraid I don't know much about that,\" Lloyd says
apologetically. ";
}
actorDesc =
{
if ( self.offering )
"Lloyd is here, offering you an insurance policy for only
one dollar. ";
else
"Lloyd the Friendly Insurance Robot is here. ";
}
offering = true
offermsg =
[
'Lloyd waits patiently for you to make up your mind about the
insurance policy.'
'Lloyd watches you expectantly, hoping you will buy the insurance
policy.'
'Lloyd shows you the insurance policy again. "Only a dollar," he
says.'
'Lloyd looks at you intently. "What can I do to make you buy this
insurance policy right now?" he asks rhetorically.'
'Lloyd reviews the policy to make sure it looks just right, and
offers it to you again.'
]
offerins =
{
if ( self.location = Me.location )
{
"\b";
say(self.offermsg[rand( 5 )]);
}
}
followmsg =
[
'Lloyd watches attentively to make sure you don\'t hurt yourself.'
'Lloyd hums one of his favorite insurance songs.'
'Lloyd gets out some actuarial tables and does some computations.'
'Lloyd looks through his papers.'
'Lloyd checks the area to make sure it\'s safe.'
]
follow =
{
if ( Me.location = machinestorage ) return;
"\b";
if ( self.location <> Me.location )
{
if ( Me.location = railcar )
"Lloyd hops into the railcar, showing remarkable agility
for such a large mechanical device. ";
else if ( self.location = railcar )
"Lloyd hops out of the railcar. ";
else if ( Me.location = pitTop and self.location = pitBottom )
"Amazingly, Lloyd scrambles up the rope and joins you. ";
else if ( Me.location = pitBottom and self.location = pitTop )
"Lloyd descends smoothly down the rope and joins you. ";
else if (( Me.location = tunnel7 and self.location = tunnel12 )
or ( Me.location = tunnel12 and self.location = tunnel7 ))
"Somehow, Lloyd manages to squeeze through the crawl. ";
else if ( Me.location = quad )
"Lloyd follows you. When he sees the apparent radioactive
waste spill, he is quite alarmed. After a moment, though,
he deduces that the spill is a staged part of the Ditch Day
festivities, and he calms down. ";
else if ( Me.location = storage )
"Lloyd enters the storage room. Upon seeing the guard, he
rolls over and starts giving his insurance pitch. After a
moment, he notices the guard is unconscious. \"It's just as
well,\" Lloyd confides; \"security work is awfully risky, and
his rates would have been quite high.\" ";
else
"Lloyd follows you. ";
self.moveInto( Me.location );
}
else
{
say(self.followmsg[rand( 5 )]);
}
}
verIoGiveTo( actor ) = {}
ioGiveTo( actor, do ) =
{
if ( do = dollar )
self.doPay( actor );
else if ( do = darbcard )
"Lloyd looks at you apologetically. \"So sorry, I must insist
on cash,\" he says. ";
else
"Lloyd doesn't appear interested. ";
}
verDoPay( actor ) = {}
doPay( actor ) =
{
if ( not self.offering )
{
"Lloyd looks at you, confused. \"I've already sold you all
the insurance you need!\" ";
}
else if ( dollar.isIn( actor ))
{
"Lloyd graciously accepts the payment, and hands you a copy
of your policy. \"You might wonder how we keep costs so low,\"
Lloyd says. \"It's simple: we're highly automated, which keeps
labor costs low; I run the whole company, which keeps the
bureaucratic overhead low; and, most importantly, I follow you
everywhere you go for the duration of the policy, ensuring that
you're paid on the spot should anything happen, which means we
don't have to waste money investigating claims!\" ";
unnotify( self, #offerins );
notify( self, #follow, 0 );
dollar.moveInto( nil );
policy.moveInto( Me );
self.offering := nil;
}
else
{
"You don't have any money with which to pay Lloyd. ";
}
}
location = insOffice
;
policy: readable
sdesc = "insurance policy"
adesc = "an insurance policy"
iscrawlable = true
noun = 'policy'
adjective = 'insurance'
location = lloyd
ldesc =
{
"The insurance policy lists the payment schedule for hundreds
of types of injuries; the list is far too lengthy to go into in any
detail here, but rest assured, ";
if ( lloyd.offering )
"it looks like an excellent deal. ";
else
"you're highly satisified with what you
got for your dollar. You feel extremely well protected. ";
}
;
machineshop: room
sdesc = "Machine Shop"
ldesc = "You are in the machine shop. It appears that this huge
chamber was once used to build and maintain the equipment that
was used to create the Great Undergraduate Excavation. Though
most of the equipment is gone now, one very large and strange
machine dominates the center of the room.
The exit is east, and a small passage leads north. "
east = pitBottom
out = pitBottom
north = machinestorage
;
machine: fixeditem
sdesc = "machine"
noun = 'machine'
location = machineshop
ldesc = "The machine is unlike anything you've seen before; it's not
at all clear what its purpose is. The only feature that looks like it
might do anything useful is a large red button labelled \"DANGER!\" "
;
machinebutton: buttonitem
location = machineshop
sdesc = "red button"
adjective = 'red'
doPush( actor ) =
{
"As you push the button, the machine starts making horrible noises
and flinging huge metal rods in all directions. Enormous clouds of
smoke rise from the machine as it flails about. After a few minutes
of this behavior, you think to step back from the machine. You're
not fast enough, though; before you can escape it, a stray metal
bar flings itself against your thumb, creating a sensation not unlike
intense pain. ";
if ( lloyd.location = self.location )
{
"\n\t";
if ( self.isscored )
"Lloyd looks at you apologetically. \"I don't want to sound
patronizing, but you knew it would do that. I'm afraid I can't
accept a claim for that injury, as it was effectively
self-inflicted.\" He looks at you sadly. \"I do sympathize,
though. That must be quite painful,\" he understates. ";
else
{
self.isscored := true;
"Lloyd rolls over and looks at your thumb. \"That looks
awful,\" he says as you jump about, holding your thumb.
Lloyd produces a thick pile of paper and starts leafing
through it. \"Temporary loss of use of one thumb... ah,
yes, here it is. That injury pays five dollars.\" Lloyd puts
away his papers and produces a crisp new five dollar bill,
which you accept (with your other hand). ";
money.moveInto( Me );
}
}
}
;
machinestorage: darkroom
sdesc = "Storage Closet"
ldesc = "You are in a small storage closet off the machine shop.
The exit is south. "
south = machineshop
out = machineshop
;
happygear: treasure
location = machinestorage
noun = 'gear'
adjective = 'mr.' 'mr' 'happy' 'mister'
sdesc = "Mr.\ Happy Gear"
thedesc = "Mr.\ Happy Gear"
adesc = "Mr.\ Happy Gear"
ldesc = "It's an ordinary gear, about an inch in diameter; the only
notable feature is that it has holes cut in such a manner that it
looks like a happy face. "
;
bank: room
sdesc = "Bank"
ldesc = "You're in what was once the Great Undergraduate Excavation's
bank. It doesn't appear to get much use any more. The exit is north,
and a small passage leads south. "
north = pitBottom
south = bankvault
out = pitBottom
;
bankvault: room
sdesc = "Vault Room"
ldesc = "The feature dominating this room is the bank's safe.
The only exit is north. "
north = bank
out = bank
;
banksafe: fixeditem, openable
sdesc = "safe"
noun = 'safe' 'door' 'vault'
location = bankvault
isopen = nil
ldesc =
{
if ( self.isblasted )
{
"The safe looks as though it has suffered some sort of
intense trauma lately; the door is just barely hanging on
its hinges, leaving the contents of the safe quite exposed. ";
pass ldesc;
}
else
{
"The safe is huge, like the type you might find in a bank.
The only notable features are a huge metal door (quite closed),
and a large slot labelled \"Night Deposit Slot.\" ";
}
}
doOpen( actor ) =
{
if ( self.isblasted ) pass doOpen;
else
"You can't open such a secure safe without resorting
to some sort of drastic action. ";
}
;
darbcard: treasure
sdesc = "DarbCard"
noun = 'darbcard' 'card'
adjective = 'darb'
location = banksafe
;
bankslot: fixeditem, container
sdesc = "night deposit slot"
noun = 'slot'
adjective = 'night' 'deposit'
location = bankvault
ldesc = "The slot is very large, big enough to put a large sack of
money into. Unfortunately, you won't have much luck extracting anything
from the slot, since it has been carefully constructed to allow items
to enter, but not leave. "
ioPutIn( actor, do ) =
{
"\^<< do.thedesc >> disappears into the deposit slot. ";
do.moveInto( banksafe );
}
;
cave: room
sdesc = "Tunnel"
ldesc = "You're in a north-south tunnel. The tunnel slopes steeply
downward to the north. "
north = railway1
down = railway1
south = pitBottom
up = pitBottom
;
railway1: room
sdesc = "Subway Station"
ldesc = "You're in a very large musty chamber deep underground. In the
center of the room is a small rail car. Strangely, the car is sitting on
the floor; there are no rails under the car, or, indeed, in the station
at all. You look around, and notice about three meters up the east wall
is a round tunnel. A passage leads south. "
south = cave
destination = railway2
tunneltime = 3
east =
{
"The tunnel is too high up the wall. You won't be able to enter
it without benefit of the railcar. ";
return( nil );
}
;
class rtunnel: fixeditem
sdesc = "tunnel"
noun = 'tunnel'
verDoEnter( actor ) = {}
doEnter( actor ) =
{
railway1.east;
}
;
rtunnel1: rtunnel
location = railway1
;
rtunnel2: rtunnel
location = railway2
;
railway2: room
sdesc = "Subway Station"
ldesc = "You're in a subway station. About three meters up the west
wall is a tunnel; a passage (at ground level) leads south. A railcar
is sitting on the floor in the center of the room. "
south = computercenter
destination = railway1
tunneltime = 3
west =
{
"The tunnel is too high up the wall. You won't be able to enter
it without benefit of the railcar. ";
return( nil );
}
;
computercenter: room
sdesc = "Computer Center"
ldesc = "You're in a computer room. Unfortunately, all the equipment
here is hopelessly out of date and doesn't interest you in the least.
The exit is north. "
north = railway2
;
compequip: decoration
sdesc = "computer equipment"
noun = 'equipment'
adjective = 'computer'
location = computercenter
ldesc = "The equipment is all very outdated. It's not the least bit
interesting. "
;
randombook: treasure, readable
sdesc = "book"
ldesc = "The book is entitled \"A Million Random Digits.\" In flipping
through the book, you find that it is, in fact, a million random digits,
nicely tabulated and individually numbered from 0 to 999,999 (computer
people always start numbering at 0). "
noun = 'book' 'digits'
adjective = 'million' 'random' 'digits' 'numbers'
location = computercenter
;
railtunnel: room
sdesc = "Tunnel"
ldesc = "The tunnel is rather non-descript. "
;
railcar: vehicle, fixeditem, container
location = railway1
isdroploc = true // stuff dropped while on board ends up in railcar
sdesc = "rail car"
noun = 'car' 'railcar'
adjective = 'rail'
ldesc =
{
"This is a small rail car, big enough for a couple of people.
It has a small control panel, which consists of a green button,
a gauge, and a small hole labelled \"Coolant.\" ";
if ( funnel.location = railhole )
"The hole seems to contain a funnel. ";
railmeter.ldesc;
}
travel =
{
if ( self.location <> railtunnel )
{
"\bThe car rises to about three meters off the floor. It then
starts to accelerate toward the tunnel, and plunges into the
tunnel with a rush of air. ";
self.destination := self.location.destination;
self.tunneltime := self.location.tunneltime;
self.moveInto( railtunnel );
}
else if ( self.tunneltime > 0 )
{
"\bThe car races down the tunnel at terrifying speed. ";
self.tunneltime := self.tunneltime - 1;
}
else
{
"\bThe car starts to decelerate sharply. After a few more seconds,
it emerges into a station and glides to a halt. It slowly
descends to the ground; once settled, the hum of its engine
gradually disappears. ";
self.isActive := nil;
self.moveInto( self.destination );
unnotify( self, #travel );
}
}
checkunboard =
{
if ( self.isActive )
{
"Please wait until the railcar has come to a complete and
final stop, and the captain has turned off the \"Fasten Seat
Belt\" sign. (Actually, I made up the part about the \"Fasten
Seat Belt\" sign, but you'll have to wait until the car
has stopped nonetheless.) ";
return( nil );
}
else return( true );
}
out =
{
if ( self.checkunboard ) pass out;
else return( nil );
}
doUnboard( actor ) =
{
if ( self.checkunboard ) pass doUnboard;
}
;
railmeter: fixeditem
location = railcar
sdesc = "gauge"
noun = 'gauge' 'meter'
ldesc =
{
"The gauge is not labelled with any units you recognize, but
the arc is divided into regions colored green, yellow, and red. The
needle is currently in the ";
if ( railcar.iscooled ) "green"; else "red";
" section of the scale. ";
}
;
railhole: fixeditem, container
location = railcar
sdesc = "hole"
noun = 'hole'
adjective = 'coolant'
ldesc =
{
if ( funnel.location = self )
"A funnel is in the hole. ";
else if ( railcar.iscooled )
"Wisps of water vapor rise from the hole. ";
else
"The hole is labelled \"Coolant.\" It's about an inch
or so in diameter. ";
}
verIoPourIn( actor ) = {}
ioPourIn( actor, do ) = { self.ioPutIn( actor, do ); }
ioPutIn( actor, do ) =
{
if ( do = funnel )
{
"A perfect fit! ";
funnel.moveInto( self );
}
else if ( do = ln2 )
{
if ( funnel.location = self )
{
if ( railcar.iscooled )
"It's already full of liquid nitrogen! ";
else
{
"You carefully pour the liquid nitrogen into the
funnel. It doesn't take very much before the tank
is full. ";
railcar.iscooled := true;
}
}
else
{
"The hole is too small; most if not all of the liquid
nitrogen you pour spills all around, rather than into
the hole. ";
}
}
else
{
"It won't fit in the hole. ";
}
}
;
railbutton: buttonitem
location = railcar
sdesc = "green button"
adjective = 'green'
doPush( actor ) =
{
if ( Me.location <> railcar )
{
"Get in the railcar first. ";
}
else if ( railcar.isbroken )
{
"Nothing happens. ";
}
else if ( railcar.isActive )
{
"Nothing happens. Perhaps this is because you have
already pushed the button quite recently. ";
}
else if ( railcar.iscooled )
{
"A low-frequency hum sounds from within the railcar. After
a few moments, it starts to levitate off the track. ";
notify( railcar, #travel, 0 );
railcar.isActive := true;
}
else
{
"A low-frequency hum sounds from within the railcar. It grows
in strength, and soon starts to vibrate the whole car. You smell
the familiar odor of burning electronic components. Suddenly,
a bright light flashes underneath the railcar, a cloud of thick
black smoke rises, and the humming stops. It appears you have
toasted the railcar. ";
railcar.isbroken := true;
}
}
;
biohall1: room
sdesc = "Hall"
ldesc = "You are in an east-west hallway. A passage labelled \"Bio Lab\"
leads south. "
west = pitBottom
east = biohall2
south = biolab
;
biolab: room
sdesc = "Bio Lab"
ldesc =
{
"You are in the Biology Lab. All sorts of strange equipment is
scattered around the room. A lab bench is in the center of the room,
and on one wall is a cabinet (which is ";
if ( biocabinet.isopen ) "open"; else "closed";
"). A passage leads north. ";
}
north = biohall1
;
bioEquipment: decoration
sdesc = "strange equipment"
noun = 'equipment'
adjective = 'strange'
location = biolab
ldesc = "The equipment is entirely unfamiliar to you. "
;
biobench: fixeditem, surface
noun = 'bench'
adjective = 'lab'
sdesc = "lab bench"
location = biolab
ldesc =
{
"The bench is topped with one of those strange black rubber surfaces
that seemingly all scientific lab benches have. ";
pass ldesc;
}
;
funnel: container
sdesc = "funnel"
noun = 'funnel'
location = biobench
ioPutIn( actor, do ) =
{
if ( do = ln2 )
{
if ( self.location = railhole or self.location = bottle )
self.location.ioPutIn( actor, do );
else
"The liquid nitrogen pours through the funnel, lands
nowhere in particular, and evaporates. ";
}
else
{
"It wouldn't accomplish anything to put ";
do.thedesc; " into the funnel. ";
}
}
ldesc =
{
if ( self.location = bottle or self.location = railhole )
{
"The funnel is stuck into "; self.location.adesc; ". ";
}
else
"It's a normal white plastic funnel, about six inches
across at its wide end and about half an inch at its
narrow end. ";
}
verIoPourIn( actor ) = {}
ioPourIn( actor, do ) = { self.ioPutIn( actor, do ); }
;
biohall2: room
sdesc = "Hall"
ldesc =
{
"You are at the east end of an east-west hallway. A doorway
leads east. ";
if ( not self.isseen )
{
notify( biocreature, #menace, 0 );
}
}
west = biohall1
east =
{
if ( biocreature.location = self )
{
if ( slime.location = nil )
{
"The creature grabs you and pushes you back, depositing
a huge glob of slime on you in the process. ";
slime.moveInto( Me );
slime.isworn := true;
}
else "The creature won't let you pass. ";
return( nil );
}
else return( biooffice );
}
;
slime: clothingItem
noun = 'glob' 'slime'
sdesc = "glob of slime"
doWear( actor ) =
{
"No, thank you. ";
}
;
biocreature: Actor
location = biohall2
sdesc = "creature"
noun = 'creature'
ldesc = "It looks like the result of a biological experiment that
failed (or succeeded, depending on who performed the experiment). "
actorDesc = "An enormous creature is blocking the hallway to the east.
He (please don't press for details as to how you know, but \"he\"
is the appropriate pronoun here) appears to be part human, but
exactly what part is not clear. The creature's leathery skin is
a bright green, and is largely covered with a thick transluscent
slime. "
menaceMessage =
[
'The creature roars a huge roar in your general direction.'
'The creature menaces you.'
'In a tender moment, the creature produces a magazine and opens up
the centerfold. He looks longingly at the picture. After a few
moments, he notices you again, and puts away the magazine; as he\'s
putting it away, you see that it\'s a copy of "Playmutant."'
'The creature looks at you warily.'
'The creature growls at you, showing his enormous pointy fangs.'
]
menace =
{
if ( self.location = Me.location )
{
"\b";
say( self.menaceMessage[rand( 5 )]);
}
}
;
biooffice: room
sdesc = "Bio Office"
ldesc = "You are in the Biology Office. A large desk dominates the
room. The exit is west. "
west = biohall2
;
biodesk: fixeditem, surface
noun = 'desk'
adjective = 'large'
location = biooffice
sdesc = "desk"
;
biocabinet: openable, fixeditem
noun = 'cabinet'
location = biolab
sdesc = "cabinet"
isopen = nil
;
class chemitem: item
location = biocabinet
noun = 'chemical'
plural = 'chemicals'
adesc = { "some "; self.sdesc; }
ldesc =
{
"It's a small lump of goo. The only identification is
a label reading \""; self.sdesc; ".\" ";
}
;
gfxq3: chemitem
noun = 'GF-XQ3'
sdesc = "GF-XQ3"
;
gfxq9: chemitem
noun = 'GF-XQ9'
sdesc = "GF-XQ9"
;
polyred: chemitem
noun = 'red'
adjective = 'poly'
sdesc = "Poly Red"
;
polyblue: chemitem
noun = 'blue'
adjective = 'poly'
sdesc = "Poly Blue"
;
compoundT99: chemitem
noun = 't99'
adjective = 'compound'
sdesc = "Compound T99"
;
compoundT30: chemitem
noun = 't30'
adjective = 'compound'
sdesc = "Compound T30"
;
clonemaster: container
noun = 'master' 'clonemaster'
adjective = 'clone'
location = biobench
sdesc = "CloneMaster"
ldesc =
{
"The CloneMaster is a simple machine. It consists of a button
marked \"Clone,\" and a small receptacle. ";
clonerecept.ldesc;
}
ioPutIn( actor, do ) = { clonerecept.ioPutIn( actor, do ); }
verDoTakeOut( actor, io ) = { clonerecept.verIoTakeOut( actor, io ); }
;
clonerecept: fixeditem, container
sdesc = "receptacle"
noun = 'receptacle'
location = clonemaster
ldesc =
{
"The receptacle is somewhat like that of a kitchen blender. ";
pass ldesc;
}
;
clonebutton: buttonitem
sdesc = "clone button"
adjective = 'clone'
doPush( actor ) =
{
if ( slime.location = clonerecept )
{
"The CloneMaster clicks and whirs for several seconds. ";
if ( gfxq3.location = clonerecept and
polyblue.location = clonerecept and
compoundT99.location = clonerecept
and length( clonerecept.contents ) = 4 )
{
"A monstrous female version (again, don't ask how you know
it's female) leaps from the tiny machine";
if ( Me.location = biocreature.location )
{
". The two monsters look at each other with passion in
their mutant eyes. They run to each other with open arms,
seemingly in slow motion. They embrace, engage in some
mushy behavior, and then run away together to elope. ";
biocreature.moveInto( nil );
unnotify( biocreature, #menace );
}
else
", looks around, and, seeing nothing of
interest, runs off. ";
}
else
"An exact duplicate of the monstrous creature whose slime
you placed in the CloneMaster leaps forth from the tiny
machine. He looks at you menacingly for a moment, then
runs off into the distance, never to be seen again. ";
slime.moveInto( nil );
}
else "Nothing happens. ";
}
location = clonemaster
;
omega: treasure
sdesc = "Great Seal of the Omega"
noun = 'seal' 'omega' 'stamp'
adjective = 'great' 'rubber'
location = biodesk
ldesc = "The Great Seal is a large rubber stamp, about an inch and
a half square. The stamp consists of a large circle that is filled by a
giant capital omega, under which is the word \"Approved.\" Around the
outside of the circle, the words \"The Great Seal of the Omega\" are
inscribed. "
;
rope2: fixeditem
sdesc = "rope"
noun = 'rope'
location = pitBottom
ldesc = "The rope extends from the opening in the ceiling high above. "
verDoTake( actor ) =
{
"The rope seems to be tied to something from above (which would
probably explain why it's extending up to the ceiling in the
first place, you deduce in a rare moment of lucid thinking). ";
}
verDoClimbup( actor ) = {}
doClimbup( actor ) = { self.doClimb( actor ); }
verDoClimb( actor ) = {}
doClimb( actor ) =
{
"It's a long climb, but you somehow manage it.\b";
Me.travelTo( pitTop );
}
;