home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tads110.zip / DITCH.T < prev    next >
Text File  |  1990-09-15  |  114KB  |  3,857 lines

  1. /*  Copyright (c) 1990 by Michael J. Roberts.  All Rights Reserved. */
  2. /*
  3.     Ditch Day Drifter
  4.     Interactive Fiction by Michael J. Roberts.
  5.     
  6.     Developed with TADS: The Text Adventure Development System.
  7.     
  8.     This game is a sample TADS source file.  It demonstrates many of the
  9.     features of TADS.  The TADS language is fully documented in the TADS
  10.     Author's Manual, which is available only to registered owners of the
  11.     Text Adventure Development System.  While this file is intended to
  12.     illustrate most of the important features of TADS, it is provided
  13.     partially for evaluation purposes, to help you to make an informed
  14.     decision as to whether TADS suits your needs, and to partially to
  15.     complement the TADS Author's Manual; this file is not intended to be
  16.     a substitute for the full documentation of the system.  If you find
  17.     that TADS is useful to you, please register your copy.
  18.     
  19.     Please read LICENSE.DOC for information about using and copying this
  20.     file, and about registering your copy of TADS.
  21. */
  22.  
  23. /*
  24.  *   First, insert the file containing the standard adventure definitions.
  25.  */
  26. #include <adv.t>
  27.  
  28. /*
  29.  *   Pre-declare some functions, so the compiler knows they are functions.
  30.  *   (This is only really necessary when a function will be referenced
  31.  *   as a daemon or fuse before it is defined; however, it doesn't hurt
  32.  *   anything to pre-declare all of them.)
  33.  */
  34. die: function;
  35. scoreRank: function;
  36. init: function;
  37. terminate: function;
  38. pardon: function;
  39. sleepDaemon: function;
  40. eatDaemon: function;
  41. darkTravel: function;
  42. setlamps: function;
  43.  
  44. /*
  45.  *   The die() function is called when the player dies.  It tells the
  46.  *   player how well he has done (with his score), and asks if he'd
  47.  *   like to start over (the alternative being quitting the game).
  48.  */
  49. die: function
  50. {
  51.     "\b*** You have died ***\b";
  52.     scoreRank();
  53.  
  54.     /*
  55.      *   Check if the player (Me) purchased insurance.  If so, issue
  56.      *   an appropriate message.
  57.      */
  58.     if ( Me.isinsured )
  59.         "\bI'm sure that Lloyd is even now paying out a big lump sum for
  60.     your early demise. However, that is of little use to you now. ";
  61.  
  62.     /*
  63.      *   Tell the user the options available, and then ask for some
  64.      *   input.  Keep asking until we get something we recognize.
  65.      */
  66.     "\bYou may restore a saved game, start over, or quit. ";
  67.     while ( 1 )
  68.     {
  69.         local resp;
  70.  
  71.     "\nPlease enter RESTORE, RESTART, or QUIT: >";
  72.         resp := upper(input());     /* get input, convert to uppercase */
  73.         if ( resp = 'RESTORE' )
  74.     {
  75.         resp := askfile( 'File to restore' );       /* find filename */
  76.         if ( resp = nil ) "Restore failed. ";
  77.         else if ( restore( resp )) "Restore failed. ";
  78.         else
  79.         {
  80.             /*
  81.          *   We've successfully restored a game.  Reset the status
  82.          *   line's score/turn counter, and resume play.
  83.          */
  84.             setscore( global.score, global.turnsofar );
  85.         abort;
  86.         }
  87.     }
  88.         else if ( resp = 'RESTART' )
  89.     {
  90.         /*
  91.          *   We're going to start over.  Reset the status line's
  92.          *   score/turn counter and start from the beginning.
  93.          */
  94.         setscore( 0, 0 );
  95.             restart();
  96.     }
  97.     else if ( resp = 'QUIT' )
  98.         {
  99.         /*
  100.          *   We're quitting the game.  Do any final activity necessary,
  101.          *   and exit.
  102.          */
  103.         terminate();
  104.             quit();
  105.         abort;
  106.         }
  107.     }
  108. }
  109.  
  110. /*
  111.  *   The scoreRank() function displays how well the player is doing.
  112.  *   In addition to displaying the numerical score and number of turns
  113.  *   played so far, we'll classify the score with a rank such as "sophomore."
  114.  *
  115.  *   Note that "global.maxscore" defines the maximum number of points
  116.  *   possible in the game.
  117.  */
  118. scoreRank: function
  119. {
  120.     local s;
  121.     
  122.     s := global.score;
  123.     
  124.     "In a total of "; say( global.turnsofar );
  125.     " turns, you have achieved a score of ";
  126.     say( s ); " points out of a possible "; say( global.maxscore );
  127.     ", which gives you a rank of ";
  128.     
  129.     if ( s < 10 ) "high-school hopeful";
  130.     else if ( s < 25 ) "freshman";
  131.     else if ( s < 40 ) "sophomore";
  132.     else if ( s < 60 ) "junior";
  133.     else if ( s < global.maxscore ) "senior";
  134.     else "graduate";
  135.     
  136.     ". ";
  137. }
  138.  
  139. /*
  140.  *   The init() function is run at the very beginning of the game.
  141.  *   We display some introductory text, then move the player (Me) to the
  142.  *   initial location and set up some background activity.
  143.  */
  144. init: function
  145. {
  146.     "\tYou wake up to the sound of voices in the hall. You are confused for
  147.     a moment; it's only 8 AM, far too early for anyone to be getting up.
  148.     Then, it dawns on you: it's ditch day here at the fictitious California
  149.     Institute of Technology in the mythical city of Pasadena, California.
  150.     Ditch Day, that strange tradition wherein seniors bar their doors with
  151.     various devices and underclassmen attempt to defeat these devices (for
  152.     no other apparent reason than that the devices are there), has arrived.\b";
  153.     
  154.     version.sdesc;                // display the game's name and version number
  155.     "\b";
  156.     
  157.     setdaemon( turncount, nil );               // start the turn counter daemon
  158.     setdaemon( sleepDaemon, nil );                    // start the sleep daemon
  159.     setdaemon( eatDaemon, nil );                     // start the hunger daemon
  160.     Me.location := startroom;                // move player to initial location
  161.     startroom.lookAround( true );                    // show player where he is
  162. }
  163.  
  164. /*
  165.  *   preinit() is called after compiling the game, before it is written
  166.  *   to the binary game file.  It performs all the initialization that can
  167.  *   be done statically before storing the game in the file, which speeds
  168.  *   loading the game, since all this work has been done ahead of time.
  169.  *
  170.  *   This routine puts all lamp objects (those objects with islamp = true) into
  171.  *   the list global.lamplist.  This list is consulted when determining whether
  172.  *   a dark room contains any light sources.
  173.  */
  174. preinit: function
  175. {
  176.     local o;
  177.     
  178.     global.lamplist := [];
  179.     o := firstobj();
  180.     while( o <> nil )
  181.     {
  182.         if ( o.islamp ) global.lamplist := global.lamplist + o;
  183.         o := nextobj( o );
  184.     }
  185. }
  186.  
  187. /*
  188.  *   The terminate() function is called just before the game ends.  We
  189.  *   just display a good-bye message.
  190.  */
  191. terminate: function
  192. {
  193.     "\bThanks for participating in Ditch Day!\n";
  194. }
  195.  
  196. /*
  197.  *   The pardon() function is called any time the player enters a blank
  198.  *   line.
  199.  */
  200. pardon: function
  201. {
  202.     "I beg your pardon? ";
  203. }
  204.  
  205. /*
  206.  *   This function is a daemon, started by init(), that monitors how long
  207.  *   it has been since the player slept.  It provides warnings for a while
  208.  *   before the player gets completely exhausted, and causes the player
  209.  *   to pass out and sleep when it has been too long.  The only penalty
  210.  *   exacted if the player passes out is that he drops all his possessions.
  211.  *   Some games might also wish to consider the effects of several hours
  212.  *   having passed; for example, the time-without-food count might be
  213.  *   increased accordingly.
  214.  */
  215. sleepDaemon: function( parm )
  216. {
  217.     local a, s;
  218.  
  219.     global.awakeTime := global.awakeTime + 1;
  220.     a := global.awakeTime;
  221.     s := global.sleepTime;
  222.  
  223.     if ( a = s or a = s+10 or a = s+20 )
  224.         "\bYou're feeling a bit drowsy; you should find a
  225.         comfortable place to sleep. ";
  226.     else if ( a = s+25 or a = s+30 )
  227.         "\bYou really should find someplace to sleep soon, or
  228.         you'll probably pass out from exhaustion. ";
  229.     else if ( a >= s+35 )
  230.     {
  231.       global.awakeTime := 0;
  232.       if ( Me.location.isbed or Me.location.ischair )
  233.       {
  234.         "\bYou find yourself unable to stay awake any longer.
  235.         Fortunately, you are ";
  236.         if ( Me.location.isbed ) "on "; else "in ";
  237.         Me.location.adesc; ", so you gently slip off into
  238.         unconsciousness.
  239.         \b* * * * *
  240.         \bYou awake some time later, feeling refreshed. ";
  241.       }
  242.       else
  243.       {
  244.         local itemRem, thisItem;
  245.         "\bYou find yourself unable to stay awake any longer.
  246.         You pass out, falling to the ground.
  247.         \b* * * * *
  248.         \bYou awaken, feeling somewhat the worse for wear.
  249.         You get up and dust yourself off. ";
  250.         itemRem := Me.contents;
  251.         while (car( itemRem ))
  252.         {
  253.             thisItem := car( itemRem );
  254.             if ( not thisItem.isworn ) thisItem.moveInto( Me.location );
  255.         itemRem := cdr( itemRem );
  256.         }
  257.       }
  258.     }
  259. }
  260.  
  261. /*
  262.  *   This function is a daemon, set running by init(), which monitors how
  263.  *   long it has been since the player has had anything to eat.  It will
  264.  *   provide warnings for some time prior to the player's expiring from
  265.  *   hunger, and will kill the player if he should go too long without
  266.  *   heeding these warnings.
  267.  */
  268. eatDaemon: function( parm )
  269. {
  270.     local e, l;
  271.  
  272.     global.lastMealTime := global.lastMealTime + 1;
  273.     e := global.eatTime;
  274.     l := global.lastMealTime;
  275.  
  276.     if ( l = e or l = e+5 or l = e+10 )
  277.         "\bYou're feeling a bit peckish. Perhaps it would be a good
  278.         time to find something to eat. ";
  279.     else if ( l = e+15 or l = e+20 or l = e+25 )
  280.         "\bYou're feeling really hungry. You should find some food
  281.         soon or you'll pass out from lack of nutrition. ";
  282.     else if ( l=e+30 or l = e+35 )
  283.         "\bYou really can't go much longer without food. ";
  284.     else if ( l >= e+40 )
  285.     {
  286.         "\bYou simply can't go on any longer without food. You perish from
  287.         lack of nutrition. ";
  288.         die();
  289.     }
  290. }
  291.  
  292. /*
  293.  *   The numObj object is used to convey a number to the game whenever
  294.  *   the player uses a number in his command.  For example, "turn dial
  295.  *   to 621" results in an indirect object of numObj, with its "value"
  296.  *   property set to 621.  Just pick up the default definition from adv.t.
  297.  */
  298. numObj: basicNumObj;
  299.  
  300. /*
  301.  *   strObj works like numObj, but for strings.  So, a player command of
  302.  *     type "hello" on the keyboard
  303.  *   will result in a direct object of strObj, with its "value" property
  304.  *   set to the string 'hello'.
  305.  *
  306.  *   Note that, because a string direct object is used in the save, restore,
  307.  *   and script commands, this object must handle those commands.  We'll just
  308.  *   pick up the default definition from adv.t.
  309.  */
  310. strObj: basicStrObj;
  311.  
  312. /*
  313.  *   The "global" object is the dumping ground for any data items that
  314.  *   don't fit very well into any other objects.
  315.  */
  316. global: object
  317.     turnsofar = 0                            // no turns have transpired so far
  318.     score = 0                            // no points have been accumulated yet
  319.     maxscore = 80                                     // maximum possible score
  320.     verbose = nil                             // we are currently in TERSE mode
  321.     awakeTime = 0               // time that has elapsed since the player slept
  322.     sleepTime = 600     // interval between sleeping times (longest time awake)
  323.     lastMealTime = 0              // time that has elapsed since the player ate
  324.     eatTime = 250         // interval between meals (longest time without food)
  325.     lamplist = []              // list of all known light providers in the game
  326. ;
  327.  
  328. /*
  329.  *   The "version" object defines, via its "sdesc" property, the name and
  330.  *   version number of the game.
  331.  */
  332. version: object
  333.     sdesc = "Ditch Day Drifter
  334.      \nInteractive Fiction by Michael J.\ Roberts
  335.      \bRelease 1.0
  336.      \nCopyright (c) 1990 by Michael J.\ Roberts. All Rights Reserved.
  337.      \nDeveloped with TADS: The Text Adventure Development System. "
  338. ;
  339.  
  340. /*
  341.  *   "Me" is the player's actor.  Pick up the default definition, basicMe,
  342.  *   from "adv.t".
  343.  */
  344. Me: basicMe
  345. ;
  346.  
  347. /*
  348.  *   darkTravel() is called whenever the player attempts to move from a dark
  349.  *   location into another dark location.  We don't do much of anything;
  350.  *   some games might impose a probability of walking into the slavering
  351.  *   jaws of a grue, whatever that might be.
  352.  */
  353. darkTravel: function
  354. {
  355.     "You stumble around in the dark, and don't get anywhere. ";
  356. }
  357.  
  358. /*
  359.  *   The player will start in the room called "startroom", by virtue
  360.  *   of being placed there by the "init" function.
  361.  *
  362.  *   All rooms have an sdesc (short description), which is displayed on
  363.  *   the status line and on entry to the room (even if the room has been
  364.  *   seen before).  In addition, the ldesc (long description) is printed
  365.  *   when the player enters the room for the first time or types "look."
  366.  *   Directions (north, south, east, west, ne, nw, se, sw, in, out)
  367.  *   specify where the exits go.  If a direction is not specified, no
  368.  *   exit is in that direction.
  369.  */
  370. startroom: room
  371.     sdesc = "Room 3"                                // short description
  372.     ldesc = "This is your room. You live a fairly austere life, being a
  373.      poor college student. The only notable features are the bed
  374.      (unmade, of course) and a small wooden desk.  An exit is west. "
  375.     west = alley1                                   // room that lies west
  376.     out = alley1                                    // the exit
  377. ;
  378.  
  379. /*
  380.  *   The desk is a surface, which means you can put stuff on top of it.
  381.  *   Note that the drawer is a separate object.
  382.  */
  383. room3desk: surface, fixeditem
  384.     sdesc = "small wooden desk"
  385.     noun = 'desk'
  386.     adjective = 'small' 'wooden' 'wood'
  387.     location = startroom
  388.     ldesc =
  389.     {
  390.         "It's the small desk that comes with all of the rooms in the house.
  391.     The desktop is pitifully small, especially considering that you often
  392.     need to have several physics texts and tables of integrals open
  393.     simultaneously. The desk has a small drawer (";
  394.     if ( room3drawer.isopen ) "open"; else "closed";
  395.     "). ";
  396.     }
  397.     /*
  398.      *   For convenience, redirect any open/close activity to the
  399.      *   drawer.  Since the desk can't be opened and closed, we can
  400.      *   reasonably expect that the player is really referring to the
  401.      *   drawer if he tries to open or close the desk.
  402.      */
  403.     verDoOpen( actor ) = { room3drawer.verDoOpen( actor ); }
  404.     doOpen( actor ) = { room3drawer.doOpen( actor ); }
  405.     verDoClose( actor ) = { room3drawer.verDoClose( actor ); }
  406.     doClose( actor ) = { room3drawer.doClose( actor ); }
  407. ;
  408.  
  409. /*
  410.  *   A container can contain stuff.  An openable is a special type of container
  411.  *   that can be opened and closed.  Though it's technically part of the desk,
  412.  *   it's a fixeditem (==> it can't be taken), so we can just as well make it
  413.  *   part of startroom; note that this is in fact necessary, since if it were
  414.  *   located in the desk, it would appear to be ON the desk (since the desk is
  415.  *   a surface).
  416.  */
  417. room3drawer: openable, fixeditem
  418.     isopen = nil
  419.     sdesc = "drawer"
  420.     noun = 'drawer'
  421.     location = startroom
  422. ;
  423.  
  424. /*
  425.  *   A qcontainer is a "quiet container."  It acts like a container in all
  426.  *   ways, except that its contents aren't displayed in a room's message.
  427.  *   We want the player to have to think to examine the wastebasket more
  428.  *   carefully to find out what's in it, so we'll make it a qcontainer.
  429.  *   Which is fairly natural:  when looking around a room, you don't usually
  430.  *   notice what's in a waste basket, even though you may notice the waste
  431.  *   basket itself.
  432.  *
  433.  *   The sdesc is just the name of the object, as displayed by the game
  434.  *   (as in "You see a wastebasket here").  The noun and adjective lists
  435.  *   specify how the user can refer to the object; only enough need be
  436.  *   specified by the user to uniquely identify the object for the purpose
  437.  *   of the command.  Hence, you can specify as many words as you want without
  438.  *   adding any burden to the user---the more words the better.  The location
  439.  *   specifies the object (a room in this case) where the object is
  440.  *   to be found.
  441.  */
  442. wastebasket: qcontainer
  443.     sdesc = "waste basket"
  444.     noun = 'basket' 'wastebasket'
  445.     adjective = 'waste'
  446.     location = startroom
  447.     moveInto( obj ) =
  448.     {
  449.         /*
  450.      *   If this object is ever removed from its original location,
  451.      *   turn off the "quiet" attribute.
  452.      */
  453.         self.isqcontainer := nil;
  454.     pass moveInto;
  455.     }
  456. ;
  457.  
  458. /*
  459.  *   A beditem is something you can lie down on.
  460.  */
  461. bed: beditem
  462.     noun = 'bed'
  463.     location = startroom
  464.     ldesc = "It's a perfectly ordinary bed. It's particularly ordinary
  465.      (for around here, anyway) in that it hasn't been made in a very
  466.      long time. "
  467.     
  468.     /*
  469.      *   verDoLookunder is called when the player types "look under bed"
  470.      *   to verify that this object can be used as a direct object (Do) for
  471.      *   that verb (Lookunder).  If no message is printed, it means that
  472.      *   it can be used.
  473.      */
  474.     verDoLookunder( actor ) = {}
  475.     
  476.     /*
  477.      *   ...and then, if verification succeeded, doLookunder is called to
  478.      *   actually apply the verb (Lookunder) to this direct object (do).
  479.      */
  480.     doLookunder( actor ) =
  481.     {
  482.         if ( dollar.isfound )       // already found the dollar?
  483.         "You don't find anything of interest. ";
  484.     else
  485.     {
  486.         dollar.isfound := true;
  487.         "You find a dollar bill! You pocket the bill.
  488.         (Okay, so it's an obvious adventure game puzzle, but I'm sure
  489.         you would have been disappointed if nothing had been there.) ";
  490.         dollar.moveInto( Me );
  491.     }
  492.     }
  493.     
  494.     /*
  495.      *   Verification and action for the "Make" verb.
  496.      */
  497.     verDoMake( actor ) = {}
  498.     doMake( actor ) =
  499.     {
  500.         "It was a nice thought, but you suddenly realize that you never
  501.     learned how. ";
  502.     }
  503. ;
  504.  
  505. /*
  506.  *   We wish to add the verb "make."  We need to specify the sdesc (printed
  507.  *   by the system under certain circumstances), the vocabulary word itself
  508.  *   (as it will be entered by the user), and the suffix of the method that
  509.  *   will be called in direct objects.  By specifying a doAction of 'Make',
  510.  *   we are establishing that verDoMake and doMake messages will be sent to
  511.  *   the direct object of the verb.
  512.  */
  513. makeVerb: deepverb
  514.     sdesc = "make"
  515.     verb = 'make'
  516.     doAction = 'Make'
  517. ;
  518.  
  519. /*
  520.  *   An "item" is the most basic class of objects that a user can carry
  521.  *   around.  An item has no special properties.  The "iscrawlable"
  522.  *   attribute that we're setting here is used in the north-south crawl
  523.  *   in the steam tunnels (later in the game); setting it to "true"
  524.  *   means that the player can carry this object through the crawl.
  525.  */
  526. dollar: item
  527.     sdesc = "one dollar bill"
  528.     noun = 'bill'
  529.     adjective = 'dollar' 'one' '1'
  530.     iscrawlable = true
  531. ;
  532.  
  533. room4: room
  534.     sdesc = "Room 4"
  535.     ldesc = "This is room 4, where the weird senior across the hall
  536.      lives. An exit is to the east, and a strange passage leads down. "
  537.     east = alley1
  538.     out = alley1
  539.     down =
  540.     {
  541.         /*
  542.      *   This is a bit of code attached to a direction.  We can do
  543.      *   anything we want in code like this, so long as we return a
  544.      *   room (or nil) when we're done.  In this case, we just want
  545.      *   to display a message when the player travels this way.
  546.      */
  547.         "The passage takes you down a winding stairway to a previously
  548.     unseen entrance to...\b";
  549.         return( shiproom );
  550.     }
  551. ;
  552.  
  553. /*
  554.  *   A readable is an object that can be read, such as a note, a sign, a
  555.  *   book, or a memo.  By default, reading the object displays its ldesc.
  556.  *   However, if a separate readdesc is specified, "look at note" and
  557.  *   "read note" could display different messages.
  558.  */
  559. winNote: readable
  560.     iscrawlable = true
  561.     sdesc = "note"
  562.     ldesc = "Congratulations! You've broken the stack! Please take this
  563.      fine WarpMaster 2000(tm) warp motivator, with my compliments. I'll
  564.      see you in \"Deep Space Drifter\"! "
  565.     noun = 'note'
  566.     location = room4
  567. ;
  568.  
  569. shiproom: room
  570.     sdesc = "Spaceship Room"
  571.     ldesc = "This is a very large cave dominated by a tall spaceship.
  572.      High above, a vertical tunnel leads upward; it is evidently a launch
  573.      tube for the spaceship. The exit is north. "
  574.     north = chuteroom
  575.     in = shipinterior
  576.     up =
  577.     {
  578.         "The tunnel is far too high above to climb. ";
  579.     return( nil );
  580.     }
  581. ;
  582.  
  583. /*
  584.  *   The receptacle is both a fixeditem (something that can't be taken and
  585.  *   carried around) and a container, so both superclasses are specified.
  586.  */
  587. shiprecept: fixeditem, container
  588.     sdesc = "socket"
  589.     noun = 'socket'
  590.     location = shiproom
  591.     ioPutIn( actor, do ) =
  592.     {
  593.         /*
  594.      *   We only want to allow the warp motivator to be put in here.
  595.      *   Check any object going in and disallow it if it's anything else.
  596.      */
  597.         if ( do = motivator )
  598.     {
  599.         "It fits snugly. ";
  600.         do.moveInto( self );
  601.     }
  602.     else "It doesn't fit. ";
  603.     }
  604. ;
  605.  
  606. spaceship: fixeditem
  607.     sdesc = "spaceship"
  608.     noun = 'spaceship' 'ship'
  609.     adjective = 'space'
  610.     location = shiproom
  611.     ldesc =
  612.     {
  613.         "The spaceship is a tall gray metal cylinder with a pointed nosecone
  614.     high above, and three large fins at the bottom. A large socket ";
  615.     if ( motivator.location = shiprecept )
  616.         "on the side contains a warp motivator. ";
  617.     else
  618.         "is on the side (the socket is currently empty). The socket
  619.         is labelled \"insert warp motivator here.\" ";
  620.     "You can enter the spaceship through an open door. ";
  621.     }
  622.     verDoEnter( actor ) = {}
  623.     doEnter( actor ) = { self.doBoard( actor ); }
  624.     verDoBoard( actor ) = {}
  625.     doBoard( actor ) =
  626.     {
  627.         actor.travelTo( shipinterior );
  628.     }
  629. ;
  630.  
  631. shipinterior: room
  632.     sdesc = "Spaceship"
  633.     out = shiproom
  634.     ldesc = "You are in the cockpit of the spaceship. The control panel is
  635.      quite simple; the only feature that interests you at the moment is
  636.      a button labelled \"Launch.\" "
  637. ;
  638.  
  639. /*
  640.  *   This is a fake "ship" that the player can refer to while inside the
  641.  *   spaceship.  This allows commands such as "look at ship" and "get out"
  642.  *   to work properly while within the ship.
  643.  */
  644. shipship: fixeditem
  645.     location = shipinterior
  646.     sdesc = "spaceship"
  647.     noun = 'ship' 'spaceship'
  648.     adjective = 'space'
  649.     ldesc = { shipinterior.ldesc; }
  650.     verDoUnboard( actor ) = {}
  651.     doUnboard( actor ) =
  652.     {
  653.         Me.travelTo( shipinterior.out );
  654.     }
  655. ;
  656.  
  657. /*
  658.  *   A buttonitem can be pushed.  It's automatically a fixeditem, and
  659.  *   always defines the noun 'button'.  The doPush method specifies what
  660.  *   happens when the button is pushed.
  661.  */
  662. launchbutton: buttonitem
  663.     sdesc = "launch button"
  664.     adjective = 'launch'
  665.     location = shipinterior
  666.     doPush( actor ) =
  667.     {
  668.         if ( motivator.location = shiprecept )
  669.     {
  670.         incscore( 10 );
  671.         "The ship's engines start to come to life. \"Launch sequence
  672.         engaged,\" the mechanical computer voice announces. ";
  673.         if ( lloyd.location = Me.location )
  674.             "\n\tLloyd heads for the door. \"Sorry,\" he says, \"I can't
  675.         go with you. Your policy specifically excludes coverage
  676.         during missions in deep space, and, frankly, it's too risky
  677.         for my tastes. Besides, I don't appear in 'Deep Space
  678.         Drifter.'\" Lloyd waves goodbye, and rolls out of the
  679.         spaceship.\n\t";
  680.         "The hatch closes automatically, sealing you into the
  681.         space vessel. The engines become louder and louder.
  682.         The computer voice announces, \"Launch
  683.         in five... four... three... two... one... liftoff!\"
  684.         The engines blast the ship into orbit.
  685.         \n\tYou realize that the time has come to set course for
  686.         \"Deep Space Drifter,\" another fine TADS adventure from
  687.         High Energy Software.\b";
  688.         
  689.         scoreRank();
  690.         terminate();
  691.         quit();
  692.         abort;
  693.     }
  694.     else
  695.     {
  696.         "The ship's computer voice announces from a hidden speaker,
  697.         \"Error: no warp motivator installed.\" ";
  698.     }
  699.     }
  700. ;
  701.  
  702. motivator: treasure
  703.     sdesc = "warp motivator"
  704.     noun = 'motivator' 'warpmaster'
  705.     takevalue = 20
  706.     adjective = 'warp'
  707.     location = room4
  708.     ldesc = "It's a WarpMaster 2000(tm), the top-of-the-line model. "
  709. ;
  710.  
  711. foodthing: fooditem
  712.     noun = 'food'
  713.     sdesc = "food"
  714.     adesc = "some food"
  715.     ldesc = "It's a non-descript food item of the type the Food Service
  716.      typically prepares. "
  717.     location = room3drawer
  718. ;
  719.  
  720. /*
  721.  *   An openable is a container, with the additional property that it can
  722.  *   be opened and closed.  To simplify things, we don't have a separate
  723.  *   cap; use of the cap is implied in the "open" and "close" commands.
  724.  */
  725. bottle: openable
  726.     sdesc = "two-liter plastic bottle"
  727.     noun = 'bottle'
  728.     location = wastebasket
  729.     adjective = 'two-liter' 'plastic' 'two' 'liter'
  730.     isopen = nil
  731.     ldesc =
  732.     {
  733.         "The bottle is ";
  734.         if ( self.isfull ) "full of liquid nitrogen. ";
  735.     else "empty. ";
  736.  
  737.     "It's "; if ( self.isopen ) "open. "; else "closed. ";
  738.     
  739.     if ( funnel.location = self )
  740.         "There's a funnel in the bottle's mouth. ";
  741.     }
  742.     ioPutIn( actor, do ) =
  743.     {
  744.         if ( not self.isopen )
  745.     {
  746.         "It might help to open the bottle first. ";
  747.     }
  748.         else if ( do = ln2 )
  749.     {
  750.         if ( funnel.location = self )
  751.         {
  752.             "You manage to get some liquid nitrogen into the bottle. ";
  753.         bottle.isfull := true;
  754.         }
  755.         else
  756.         {
  757.             "You can't manage to get any liquid nitrogen into the
  758.              tiny opening. ";
  759.             }
  760.     }
  761.     else if ( do = funnel )
  762.     {
  763.         "A perfect fit! ";
  764.         funnel.moveInto( self );
  765.     }
  766.     else "That won't fit in the bottle. ";
  767.     }
  768.     verIoPourIn( actor ) = {}
  769.     ioPourIn( actor, do ) = { self.ioPutIn( actor, do ); }
  770.     doClose( actor ) =
  771.     {
  772.         if ( funnel.location = self )
  773.         "You'll have to take the funnel out first. ";
  774.     else if ( self.isfull )
  775.     {
  776.         "It takes some effort to close the bottle, since the rapidly
  777.         evaporating nitrogen occupies much more volume as a gas than
  778.         as a liquid. However, you manage to close it. ";
  779.         notify( self, #explodeWarning, 3 );
  780.         self.isopen := nil;
  781.     }
  782.     else
  783.     {
  784.         "Okay, it's closed. ";
  785.         self.isopen := nil;
  786.     }
  787.     }
  788.     
  789.     /*
  790.      *   explodeWarning is sent to the bottle as a "notification," which is
  791.      *   a message that's scheduled to occur some number of turns in the
  792.      *   future.  In this case, closing the bottle while it has liquid
  793.      *   nitrogen inside will set the explodeWarning notification.
  794.      */
  795.     explodeWarning =
  796.     {
  797.         if ( not self.isopen )
  798.     {
  799.         if ( self.isIn( Me.location ))
  800.         {
  801.             "\bThe bottle is starting to make lots of noise, as though
  802.             the plastic were being stretched to its limit. ";
  803.         }
  804.         notify( self, #explode, 3 );
  805.     }
  806.     }
  807.     
  808.     /*
  809.      *   explode is set as a notification by explodeWarning.  This routine
  810.      *   actually causes the explosion.  Since the bottle explodes, we will
  811.      *   remove it from the game (by moving it into "nil").  If the bottle
  812.      *   is in the right place, we'll also do some useful things.
  813.      */
  814.     explode =
  815.     {
  816.         if ( not self.isopen )
  817.     {
  818.         "\b";
  819.         if ( self.location = banksafe )
  820.         {
  821.             if ( Me.location = bankvault )
  822.         {
  823.             "There is a terrible explosion from within the safe.
  824.              The door blasts open with a clang and a huge cloud of
  825.              water vapor. ";
  826.              
  827.             if ( lloyd.location = bankvault )
  828.                 "\n\tLloyd throws himself between you and the
  829.             vault. \"Please be careful!\" he admonishes.
  830.             \"The payment for Accidental Death due to Explosion
  831.             is enormous!\" ";
  832.         }
  833.         else
  834.             "You hear a distant, muffled explosion. ";
  835.         
  836.         banksafe.isopen := true;
  837.         banksafe.isblasted := true;
  838.         }
  839.         else if ( self.isIn( Me.location ))
  840.         {
  841.             "The bottle explodes with a deafening boom and a huge
  842.             cloud of water vapor. As with most explosions, standing
  843.         in such close proximity was not advisable; it was, in
  844.         fact, fatal. ";
  845.         die();
  846.         abort;
  847.         }
  848.         else
  849.         {
  850.             "You hear a distant explosion. ";
  851.         }
  852.         
  853.         self.moveInto( nil );
  854.     }
  855.     }
  856. ;
  857.  
  858. /*
  859.  *   We're defining our own "class" of objects here.  Up to now, we've been
  860.  *   using classes defined in "adv.t", which you will recall we included at
  861.  *   the top of the file.  This class has some useful properties.  For one,
  862.  *   it has an attribute (istreasure) that tells us that the object is
  863.  *   indeed a treasure (used in the slot in room 4's door to ensure that
  864.  *   an object can be put in the slot).  In addition, it supplements the
  865.  *   doTake routine:  when a treasure is taken for the first time, we'll
  866.  *   add the object's "takevalue" to the overall score.
  867.  */
  868. class treasure: item
  869.     istreasure = true
  870.     takevalue = 5       // default point value when object is taken
  871.     putvalue = 5        // default point value when object is put in slot
  872.     doTake( actor ) =
  873.     {
  874.         if ( not self.hasScored )       // have we scored yet?
  875.     {
  876.         incscore( self.takevalue ); // add our "takevalue" to the score
  877.         self.hasScored := true;     // note that we have scored
  878.     }
  879.     pass doTake;        // continue with the normal doTake from "item"
  880.     }
  881. ;
  882.  
  883. alley1: room
  884.     sdesc = "Alley One"
  885.     ldesc =
  886.     {
  887.         "You are in the eternal twilight of Alley One, one of the twisty
  888.     little passages (all different) making up the student house in
  889.     which you live. Your room (room 3) is to the east. To the west
  890.     is a door (";
  891.     if ( alley1door.isopen ) "open"; else "closed";
  892.     "), affixed to which is a large sign. An exit is south, and the
  893.     hallway continues north. ";
  894.     }
  895.     east = startroom
  896.     north = alley1n
  897.     west =
  898.     {
  899.         /*
  900.      *   Sometimes, we'll want to run some code when the player walks
  901.      *   in a particular direction rather than just go to a new room.
  902.      *   This is how.  Returning "nil" means that the player can't go
  903.      *   this way.
  904.      */
  905.     if ( alley1door.isopen )
  906.     {
  907.         return( room4 );
  908.     }
  909.     else
  910.     {
  911.             "The door is closed and locked. You might read the
  912.         sign on the door for more information. ";
  913.         return( nil );
  914.     }
  915.     }
  916.     south = breezeway
  917.     out = breezeway
  918. ;
  919.  
  920. alley1n: room
  921.     sdesc = "Alley One"
  922.     ldesc = "You are at the north end of alley 1.  A small room is
  923.      to the west. "
  924.     south = alley1
  925.     west = alley1comp
  926. ;
  927.  
  928. alley1comp: room
  929.     sdesc = "Computer Room"
  930.     ldesc = 
  931.     {
  932.         "You are in a small computer room. Not surprisingly, the room
  933.          contains a personal computer. The exit is east. ";
  934.     if ( not self.isseen ) notify( compstudents, #converse, 0 );
  935.     }
  936.     east = alley1n
  937. ;
  938.  
  939. alley1pc: fixeditem
  940.     sdesc = "personal computer"
  941.     noun = 'computer'
  942.     adjective = 'personal'
  943.     location = alley1comp
  944.     ldesc = "The computer is in use by a couple of your fellow undergraduates.
  945.      Closer inspection of the screen shows that they seem to be playing a
  946.      text adventure. You've never really understood the appeal of those games
  947.      yourself, but you quickly surmise that the game is part of one of the
  948.      seniors' stacks. "
  949.     verIoTypeOn( actor ) = {}
  950.     ioTypeOn( actor, do ) =
  951.     {
  952.         "The computer is already in use. Common courtesy demands that you
  953.     wait your turn. ";
  954.     }
  955.     verDoTurnoff( actor ) = {}
  956.     doTurnoff( actor ) =
  957.     {
  958.         "The students won't let you, since they're busy using the computer. ";
  959.     }
  960. ;
  961.  
  962. compstudents: Actor
  963.     location = alley1comp
  964.     sdesc = "students"
  965.     adesc = "a couple of students"
  966.     ldesc = "The students are busy using the computer. "
  967.     actorAction( v, d, p, i ) =
  968.     {
  969.         "They're too wrapped up in what they're doing. ";
  970.     exit;
  971.     }
  972.     doAskAbout( actor, io ) =
  973.     {
  974.         "They're too busy to answer. ";
  975.     }
  976.     noun = 'students' 'undergraduates'
  977.     actorDesc = "A couple of your fellow undergraduates are here, using
  978.      the computer. They seem quite absorbed in what they're doing. "
  979.     state = 0
  980.     converse =
  981.     {
  982.         if ( Me.location = self.location )
  983.     {
  984.         "\b";
  985.         if ( self.state = 0 )
  986.             "\"Where are we going to find the dollar bill?\" one
  987.         of the students asks the other. They sit back and stare
  988.         at the screen, lost in thought. ";
  989.         else if ( self.state = 1 )
  990.             "\"Hey!\" says one of the students. \"Did you look under
  991.         the bed?\" The other student shakes his head. \"No way,
  992.         that would be a stupid puzzle!\" ";
  993.         else if ( self.state = 2 )
  994.             "One of the students using the computer types a long
  995.         string of commands, and finally types \"look under bed.\"
  996.         \"Wow! The dollar bill actually was under the bed! How
  997.         lame!\" ";
  998.         else
  999.             "The students continue to play with the computer. ";
  1000.     
  1001.         self.state := self.state + 1;
  1002.     }
  1003.     }
  1004. ;
  1005.  
  1006. class lockedDoor: fixeditem, keyedLockable
  1007.     isopen = nil
  1008.     islocked = true
  1009.     noun = 'door'
  1010.     sdesc = "door"
  1011.     ldesc =
  1012.     {
  1013.         if ( self.isopen ) "It's open. ";
  1014.     else if ( self.islocked ) "It's closed and locked. ";
  1015.     else "It's closed. ";
  1016.     }
  1017.     verIoPutIn( actor ) = { "You can't put anything in that! "; }
  1018. ;
  1019.  
  1020. alley1door: lockedDoor
  1021.     location = alley1
  1022.     ldesc =
  1023.     {
  1024.         if ( self.isopen ) "It's open. ";
  1025.     else
  1026.             "The door is closed and locked. There is a slot in the door,
  1027.             and above that, a large sign is affixed to the door. ";
  1028.     }
  1029. ;
  1030.  
  1031. alley1sign: fixeditem, readable
  1032.     noun = 'sign'
  1033.     sdesc = "sign"
  1034.     location = alley1
  1035.     ldesc = "The sign says:
  1036.      \b\t\tWelcome to Ditch Day!
  1037.      \bThis stack is a treasure hunt. Gather all of the treasures, and you
  1038.      break the stack.
  1039.      To satisfy the requirements of this stack, you must find the
  1040.      items listed below, and deposit them in the slot in the door. When
  1041.      all items have been put in the slot, the stack will be solved and
  1042.      the door will open automatically. The items to find are:
  1043.      \b\tThe Great Seal of the Omega
  1044.      \n\tMr.\ Happy Gear
  1045.      \n\tA Million Random Digits
  1046.      \n\tA DarbCard
  1047.      \bThese items are hidden amongst the expanses of the Great
  1048.      Undergraduate Excavation project. Happy hunting!
  1049.      \bFor first-time participants, please note that
  1050.      this is a \"finesse stack.\" You are not permitted to attempt to break
  1051.      the stack by brute force. Instead, you must follow the rules above. "
  1052. ;
  1053.  
  1054. alley1slot: fixeditem, container
  1055.     noun = 'slot'
  1056.     sdesc = "slot"
  1057.     location = alley1
  1058.     itemcount = 0
  1059.     ioPutIn( actor, do ) =
  1060.     {
  1061.         if ( do.istreasure )
  1062.     {
  1063.         "\^<< do.thedesc >> disappears into the slot. ";
  1064.         do.moveInto( nil );
  1065.         incscore( do.putvalue );
  1066.         self.itemcount := self.itemcount + 1;
  1067.         if ( self.itemcount = 4 )
  1068.         {
  1069.             "As the treasure disappears into the slot, you hear a
  1070.         klaxon from the other side of the door. An elaborate
  1071.         series of clicks and clanks follows, then the door swings
  1072.         open. ";
  1073.         alley1door.islocked := nil;
  1074.         alley1door.isopen := true;
  1075.         }
  1076.     }
  1077.     else
  1078.     {
  1079.         "The slot will only accept items on the treasure list. ";
  1080.     }
  1081.     }
  1082. ;
  1083.  
  1084. breezeway: room
  1085.     sdesc = "Breezeway"
  1086.     ldesc = "You are in a short passage that connects a courtyard,
  1087.      to the east, to the outside of the building, which lies to the
  1088.      west. A hallway leads north. "
  1089.     north = alley1
  1090.     east = courtyard
  1091.     west = orangeWalk1
  1092. ;
  1093.  
  1094. courtyard: room
  1095.     sdesc = "Courtyard"
  1096.     ldesc = "You are in a large outdoor courtyard.
  1097.      An arched passage is to the west.
  1098.      A passage leads east, and a stairway leads down. "
  1099.     east = lounge
  1100.     down = hall1
  1101.     west = breezeway
  1102. ;
  1103.  
  1104. lounge: room
  1105.     sdesc = "Lounge"
  1106.     ldesc = "You are in the lounge. A passage leads west, and a dining
  1107.      room lies to the north. "
  1108.     north = diningRoom
  1109.     west = courtyard
  1110.     out = courtyard
  1111. ;
  1112.  
  1113. diningRoom: room
  1114.     sdesc = "Dining Room"
  1115.     ldesc = "You are in the dining room. There is a wooden table in
  1116.      the center of the room. The lounge lies to the south,
  1117.      and a passage to the east leads into the kitchen. "
  1118.     east = kitchen
  1119.     south = lounge
  1120. ;
  1121.  
  1122. diningTable: surface, fixeditem
  1123.     sdesc = "wooden table"
  1124.     noun = 'table'
  1125.     adjective = 'wooden'
  1126.     location = diningRoom
  1127. ;
  1128.  
  1129. fishfood: fooditem
  1130.     noun = 'module'
  1131.     adjective = 'fish' 'protein'
  1132.     sdesc = "fish protein module"
  1133.     ldesc = "It's a small pyramid-shaped white object, which is widely
  1134.      considered to consist primarily of fish protein. The food service
  1135.      typically resorts to such unappetizing fare toward the end of the
  1136.      year. "
  1137.     location = diningTable
  1138. ;
  1139.  
  1140. kitchen: room
  1141.     sdesc = "Kitchen"
  1142.     ldesc = "You are in the kitchen.  A ToxiCola(tm) machine is here.
  1143.      A passage leads into the dining room to the west. "
  1144.     west = diningRoom
  1145.     out = diningRoom
  1146. ;
  1147.  
  1148. toxicolaMachine: fixeditem, container
  1149.     noun = 'machine' 'compartment'
  1150.     adjective = 'toxicola'
  1151.     sdesc = "ToxiCola machine"
  1152.     ldesc =
  1153.     {
  1154.         "The machine dispenses ToxiCola, one of the big losers in the
  1155.          Cola Wars.  But, hey, it's cheap, so the food service installed it.
  1156.          The machine consists of a compartment large enough for a cup,
  1157.          and a button for dispensing ToxiCola into the cup. ";
  1158.      if ( cup.location = self )
  1159.         "The compartment contains a cup. ";
  1160.     }
  1161.     location = kitchen
  1162.     ioPutIn( actor, do ) =
  1163.     {
  1164.         if ( do <> cup )
  1165.         "That won't fit in the compartment. ";
  1166.     else pass ioPutIn;
  1167.     }
  1168. ;
  1169.  
  1170. cup: container
  1171.     sdesc = "coffee cup"
  1172.     noun = 'cup'
  1173.     adjective = 'coffee'
  1174.     isFull = nil
  1175.     ldesc =
  1176.     {
  1177.         if ( self.isFull ) "It's full of a viscous brown fluid. ";
  1178.     else "It's empty. ";
  1179.     }
  1180.     location = diningTable
  1181.     ioPutIn( actor, do ) =
  1182.     {
  1183.         if ( do = ln2 ) "The liquid nitrogen evaporates on contact. ";
  1184.     else "It won't fit in the cup. ";
  1185.     }
  1186. ;
  1187.  
  1188. toxicola: fixeditem
  1189.     sdesc = "toxicola"
  1190.     noun = 'toxicola' 'cola'
  1191.     ldesc = "It's a thick brown fluid. It appears to be quite flat. "
  1192.     doTake( actor ) =
  1193.     {
  1194.         "You'll have to leave it in the cup. ";
  1195.     }
  1196.     verDoDrink( actor ) = {}
  1197.     doDrink( actor ) =
  1198.     {
  1199.         "You drink the ToxiCola, despite your better judgment. It
  1200.     initially sparks a sugar and caffeine rush, but that rapidly
  1201.     fades, to be replaced by a strange dull throbbing. You enter
  1202.     a semi-conscious state for several hours. It finally passes,
  1203.     but you're not sure if it's been hours, weeks, or years. ";
  1204.     cup.isFull := nil;
  1205.     self.moveInto( nil );
  1206.     }
  1207. ;
  1208.  
  1209. toxicolaButton: buttonitem
  1210.     location = kitchen
  1211.     sdesc = "button"
  1212.     doPush( actor ) =
  1213.     {
  1214.         if ( cup.location = toxicolaMachine )
  1215.     {
  1216.         if ( cup.isFull )
  1217.             "ToxiCola spills over the already full cup, and drains
  1218.         away. ";
  1219.         else
  1220.         {
  1221.             "The horrible brown viscous fluid you have come to
  1222.         know as ToxiCola fills the cup. ";
  1223.         cup.isFull := true;
  1224.         toxicola.moveInto( cup );
  1225.         }
  1226.     }
  1227.     else
  1228.     {
  1229.         "Horrible viscous brown fluid spills into the empty
  1230.         compartment, and drains away. ";
  1231.     }
  1232.     }
  1233. ;
  1234.  
  1235. orangeWalk1: room
  1236.     sdesc = "Orange Walk"
  1237.     ldesc = "You are on a walkway lined with orange trees. The walkway
  1238.      continues to the north, and an arched passage leads into a building
  1239.      to the east. "
  1240.     east = breezeway
  1241.     north = orangeWalk2
  1242. ;
  1243.  
  1244. /*
  1245.  *   We want a "class" of objects for the orange trees lining the
  1246.  *   orange walk.  They don't do anything, so they're "decoration."
  1247.  */
  1248. class orangeTree: decoration
  1249.     sdesc = "orange trees"
  1250.     ldesc = "The orange trees are perfectly ordinary. "
  1251.     adesc = "an orange tree"
  1252.     noun = 'tree' 'trees'
  1253.     adjective = 'orange'
  1254.     verDoClimb( actor ) = {}
  1255.     doClimb( actor ) =
  1256.     {
  1257.         "You climb into one of the orange trees, and quickly find the
  1258.     view from the few feet higher to be highly uninteresting. You
  1259.     soon climb back down. ";
  1260.     }
  1261. ;
  1262.  
  1263. orangeTree1: orangeTree
  1264.     location = orangeWalk1
  1265. ;
  1266.  
  1267. orangeWalk2: room
  1268.     sdesc = "Orange Walk"
  1269.     ldesc = "You are on a walkway lined with orange trees. The walkway
  1270.      continues to the south, and leads into a large grassy square to the
  1271.      north. "
  1272.     north = quad
  1273.     south = orangeWalk1
  1274. ;
  1275.  
  1276. orangeTree2: orangeTree
  1277.     location = orangeWalk2
  1278. ;
  1279.  
  1280. quad: room
  1281.     sdesc = "Quad"
  1282.     ldesc = "You are on the quad, a large grassy square in the
  1283.      center of campus.  The bookstore lies to the northwest; the
  1284.      health center lies to the northeast; Buildings and Grounds
  1285.      lies to the north; and walkways lead west and south.
  1286.      \n\tSome students dressed in radiation suits are staging a bogus
  1287.      toxic leak, undoubtedly to fulfill the requirements of one of the
  1288.      stacks.  They are wandering around, looking very busy.  Many reporters
  1289.      are standing at a safe distance, looking terrified.
  1290.      The supposed clean-up crew is pouring lots of liquid nitrogen onto
  1291.      the ground, resulting in huge clouds of water vapor. "
  1292.     south = orangeWalk2
  1293.     nw = bookstore
  1294.     west = walkway
  1295.     ne = healthCenter
  1296.     north = BandG
  1297. ;
  1298.  
  1299. BandG: room
  1300.     sdesc = "B&G"
  1301.     ldesc = "You are in the Buildings and Grounds office. The exit is to
  1302.      the south. "
  1303.     south = quad
  1304.     out = quad
  1305. ;
  1306.  
  1307. bngmemo: readable
  1308.     sdesc = "scrap of paper"
  1309.     iscrawlable = true
  1310.     noun = 'scrap' 'paper'
  1311.     location = BandG
  1312.     ldesc = "Most of the paper has been torn away; the part that remains
  1313.      seems to have a list of numerical codes of some kind on it:
  1314.      \b\t293 -- north tunnel lighting
  1315.      \n\t322 -- station 2 lighting
  1316.      \n\t612 -- behavior lab
  1317.      \bThe rest is missing. "
  1318. ;
  1319.  
  1320. healthCenter: room
  1321.     sdesc = "Health Center"
  1322.     ldesc = "You are in the health center. Like the rest of campus, this
  1323.      place is deserted because of Ditch Day. The large desk would normally
  1324.      have a receptionist behind it, but today, no one is in sight. "
  1325.     sw = quad
  1326.     out = quad
  1327. ;
  1328.  
  1329. healthDesk: fixeditem, surface
  1330.     sdesc = "desk"
  1331.     noun = 'desk'
  1332.     adjective = 'large'
  1333.     location = healthCenter
  1334. ;
  1335.  
  1336. healthMemo: readable
  1337.     sdesc = "health memo"
  1338.     iscrawlable = true
  1339.     noun = 'memo'
  1340.     plural = 'memos'
  1341.     adjective = 'health'
  1342.     location = healthDesk
  1343.     ldesc =
  1344.        "From:\t\tDirector of the Health Center
  1345.       \nTo:\t\tAll Health Center Personnel
  1346.       \nSubject:\tToxiCola toxicity
  1347.       \bMany students have visited the Health Center recently, complaining
  1348.       that the ToxiCola that is served in the student houses has not been
  1349.       properly caffeinated.  The students are complaining of drowsiness,
  1350.       dizziness, and other symptoms that are normally associated with an
  1351.       insufficient intake of caffeine.
  1352.       \n\tUpon investigation, we have learned that the ToxiCola dispensers
  1353.       in the student houses have become contaminated with a substance that
  1354.       induces these effects. The substance has not yet been identified, but
  1355.       the concentration seems to be increasing. All Health Center personnel
  1356.       are urgently directed to advise students to avoid the ToxiCola if at
  1357.       all possible. Students should be informed that their student health
  1358.       insurance coverage will cover any purchases of other caffeinated
  1359.       beverages that they need for their studies. "
  1360. ;
  1361.  
  1362. students: decoration
  1363.     sdesc = "students"
  1364.     adesc = "a group of students"
  1365.     noun = 'student' 'students'
  1366.     location = quad
  1367.     ldesc = "The students are making quite a good show of the simulated
  1368.      nuclear waste spill. They're all wearing white clean-room suits with
  1369.      official-looking \"Radiation Control District\" badges. They're
  1370.      scampering about purposefully, keeping the crowd of reporters back
  1371.      at a safe distance. "
  1372. ;
  1373.  
  1374. presscorp: decoration
  1375.     sdesc = "reporters"
  1376.     adesc = "a group of reporters"
  1377.     noun = 'reporter' 'reporters'
  1378.     location = quad
  1379. ;
  1380.  
  1381. flask: container
  1382.     sdesc = "flask"
  1383.     ldesc = "The flask appears to have lots of liquid nitrogen in it;
  1384.      it's hard to tell just how much, since the opening is perpetually
  1385.      clouded over with thick plumes of water vapor. "
  1386.     noun = 'flask'
  1387.     location = quad
  1388.     ioPutIn( actor, do ) =
  1389.     {
  1390.         "You know from experience that it wouldn't be a good idea to
  1391.     put "; do.thedesc; " into the liquid nitrogen, since the LN2 is
  1392.     really, really cold. ";
  1393.     }
  1394. ;
  1395.  
  1396. pourVerb: deepverb
  1397.     sdesc = "pour"
  1398.     verb = 'pour'
  1399.     doAction = 'Pour'
  1400.     ioAction( inPrep ) = 'PourIn'
  1401.     ioAction( onPrep ) = 'PourOn'
  1402. ;
  1403.  
  1404. ln2: item
  1405.     sdesc = "liquid nitrogen"
  1406.     adesc = "some liquid nitrogen"      // "a liquid nitrogen" doesn't compute
  1407.     ldesc = "You can't see much, thanks to the thick clouds of water
  1408.      vapor that inevitably form over such a cold substance. "
  1409.     noun = 'nitrogen' 'ln2'
  1410.     adjective = 'liquid'
  1411.     location = flask
  1412.     doTake( actor ) =
  1413.     {
  1414.         "You're better off leaving the liquid nitrogen in the flask. ";
  1415.     }
  1416.     verDoPour( actor ) = {}
  1417.     verDoPourIn( actor, io ) = {}
  1418.     doPour( actor ) =
  1419.     {
  1420.         askio( inPrep );
  1421.     }
  1422. ;
  1423.  
  1424. walkway: room
  1425.     sdesc = "Walkway"
  1426.     ldesc = "You are on a walkway.  A large grassy square lies to the east;
  1427.      buildings lie to the north and south. The walkway continues west. "
  1428.     east = quad
  1429.     north = behaviorLab
  1430.     south = security
  1431.     west = walkway2
  1432. ;
  1433.  
  1434. walkway2: room
  1435.     sdesc = "Walkway"
  1436.     ldesc = "You are on a walkway, which continues to the east. Buildings
  1437.      are to the north and south. "
  1438.     east = walkway
  1439.     south = explosiveLab
  1440.     north = biobuilding
  1441. ;
  1442.  
  1443. biobuilding: room
  1444.     sdesc = "Biology Building"
  1445.     ldesc = "You are in the biology building. The exit is south. "
  1446.     south = walkway2
  1447.     out = walkway2
  1448. ;
  1449.  
  1450. bionotes: readable
  1451.     sdesc = "notebook"
  1452.     location = biobuilding
  1453.     noun = 'notebook'
  1454.     ldesc = "The notebook explains various lab techniques used in cloning
  1455.      organisms. Since the invention of the CloneMaster, which requires only
  1456.      a sample of genetic material from a subject (such as some blood, or a
  1457.      bit of skin, or the like) and the basic skills required to operate a
  1458.      household blender, most of the techniques are obsolete. Some of the data,
  1459.      however, are interesting. For example, the notebook outlines the procedure
  1460.      for reversing the sex of a clone; the introduction of chemicals identified
  1461.      herein only as Genetic Factor XQ3, Polymerase Blue, and Compound T99 at
  1462.      the start of the cloning process aparently does the trick. Most of the
  1463.      rest of the document is a discussion of the human immune system; the
  1464.      author comes to the conclusion that the human immune system, though a
  1465.      novel idea, is far too improbable to ever actually be implemented. "
  1466. ;
  1467.  
  1468. explosiveLab: room
  1469.     sdesc = "Explosive Lab"
  1470.     ldesc = "It's not that the lab itself is explosive (though it has blown
  1471.      up a couple times in the past); rather, they study explosives here.
  1472.      Unfortunately, all the good stuff has been removed by other Ditch Day
  1473.      participants who got up earlier than you did. The exit is north. "
  1474.     north = walkway2
  1475.     out = walkway2
  1476. ;
  1477.  
  1478. ln2doc: readable
  1479.     sdesc = "thesis"
  1480.     noun = 'thesis'
  1481.     location = explosiveLab
  1482.     ldesc = "The thesis is about Thermal Expansion Devices. It explains about
  1483.      a new class of explosives that are made possible by low-temperature
  1484.      fluid technology (i.e., liquid nitrogen) and high-tension polymer
  1485.      containment vessels (i.e., plastic bottles). A great deal of jargon and
  1486.      complicated theories are presented, presumably to fool the faculty
  1487.      advisor into thinking the author actually did something useful with his
  1488.      research funds; after wading through the nonsense, you find that the
  1489.      paper is merely talking about putting liquid nitrogen into a plastic
  1490.      soft-drink bottle, closing the bottle, then letting nature take its
  1491.      course. Since the nitrogen will tend to evaporate at room temperature,
  1492.      but will have no place to go, the bottle will eventually explode.
  1493.      \bOn the cover page, you notice this important warning: \"Kids! Don't
  1494.      try this at home! Liquid nitrogen is extremely cold, and can cause severe
  1495.      injuries; it should only be handled by trained professionals. Never
  1496.      put liquid nitrogen in a closed container.\" "
  1497. ;
  1498.  
  1499. bookstore: room
  1500.     sdesc = "Bookstore"
  1501.     ldesc = "You are in the bookstore. The shelves are quite empty; no doubt
  1502.      everything has been bought up by seniors in attempts to build their
  1503.      stacks and underclassmen in attempts to break them. The exit is to the
  1504.      southeast. "
  1505.     out = { return( self.se ); }
  1506.     se =
  1507.     {
  1508.         /*
  1509.      *   We need to check that the battery has been paid for, if it's
  1510.      *   been taken.  If not, don't let 'em out.
  1511.      */
  1512.         if ( battery.isIn( Me ) and not battery.isPaid )
  1513.     {
  1514.         "The clerk notices that you want to buy the battery. \"That'll be
  1515.         five dollars,\" she says, waiting patiently. ";
  1516.         return( nil );
  1517.     }
  1518.     else return( quad );
  1519.     }
  1520. ;
  1521.  
  1522. battery: item
  1523.     location = bookstore
  1524.     isPaid = nil
  1525.     sdesc = "battery"
  1526.     noun = 'battery'
  1527.     verDoPayfor( actor ) =
  1528.     {
  1529.         if ( actor.location <> bookstore )
  1530.         "I don't see anyone to pay! ";
  1531.     }
  1532.     doPayfor( actor ) =
  1533.     {
  1534.         clerk.doPay( actor );
  1535.     }
  1536.     verIoPayFor( actor ) = {}
  1537.     ioPayFor( actor, do ) =
  1538.     {
  1539.         if ( do <> clerk )
  1540.     {
  1541.         "You can't pay "; do.thedesc; " for that! ";
  1542.     }
  1543.     else clerk.doPay( actor );
  1544.     }
  1545. ;
  1546.  
  1547. forPrep: Prep
  1548.     sdesc = "for"
  1549.     preposition = 'for'
  1550. ;
  1551.  
  1552. payVerb: deepverb
  1553.     sdesc = "pay"
  1554.     verb = 'pay'
  1555.     doAction = 'Pay'
  1556.     ioAction( forPrep ) = 'PayFor'
  1557. ;
  1558.  
  1559. payforVerb: deepverb
  1560.     verb = 'pay for'
  1561.     sdesc = "pay for"
  1562.     doAction = 'Payfor'
  1563. ;
  1564.  
  1565. money: item
  1566.     sdesc = "five dollar bill"
  1567.     noun = 'bill' 'money'
  1568.     adjective = 'five' 'dollar' '5'
  1569.     iscrawlable = true
  1570. ;
  1571.  
  1572. clerk: Actor
  1573.     noun = 'clerk'
  1574.     location = bookstore
  1575.     sdesc = "Clerk"
  1576.     ldesc = "The clerk is a kindly lady to whom you have paid many hundreds
  1577.      of dollars for books and other college necessities. "
  1578.     actorDesc = "A clerk is near the exit, prepared to ring up any purchases
  1579.      you might want to make (not that there's much left here to buy). "
  1580.     verIoGiveTo( actor ) = {}
  1581.     ioGiveTo( actor, do ) =
  1582.     {
  1583.         if ( do = money or do = dollar ) self.doPay( actor );
  1584.     else if ( do = darbcard )
  1585.     {
  1586.         "The clerk shakes her head. \"Sorry,\" she says, \"we only
  1587.         accept cash.\" ";
  1588.     }
  1589.     else if ( do = cup and cup.isFull )
  1590.     {
  1591.         "\"I never drink that stuff,\" the clerk says, \"and neither
  1592.         should you! Do you have any idea what's in there? I probably
  1593.         don't know half as much chemistry as you, but I know better
  1594.         than to drink that.\" ";
  1595.     }
  1596.     else
  1597.     {
  1598.         "She doesn't appear interested. ";
  1599.     }
  1600.     }
  1601.     verDoPay( actor ) = {}
  1602.     doPay( actor ) =
  1603.     {
  1604.         if ( not battery.isIn( Me ))
  1605.     {
  1606.         "The clerk looks confused. \"I don't see what you're
  1607.         paying for,\" she says. She then looks amused, realizing
  1608.         that the students here somtimes get a little ahead of
  1609.         themselves. ";
  1610.     }
  1611.     else if ( battery.isPaid )
  1612.     {
  1613.         "The clerk looks confused and says, \"You've already paid!\"
  1614.         She then looks amused, realizing that the students here can
  1615.         be a bit absent-minded at times. ";
  1616.     }
  1617.         else if ( not money.isIn( Me ))
  1618.     {
  1619.         if ( dollar.isIn( Me ))
  1620.         {
  1621.             "The clerk reminds you that the battery is five dollars.
  1622.         All you have is one dollar. She looks amused; \"They can
  1623.         do calculus in their sleep but they can't add,\" she jokes. ";
  1624.         }
  1625.         else
  1626.         {
  1627.             "You unfortunately don't have anything with which to pay the
  1628.             clerk. ";
  1629.         }
  1630.     }
  1631.     else
  1632.     {
  1633.         "The clerk accepts your money and says \"Thank you, have a nice
  1634.         day.\"";
  1635.         battery.isPaid := true;
  1636.         money.moveInto( nil );
  1637.     }
  1638.     }
  1639. ;
  1640.  
  1641. behaviorLab: room
  1642.     sdesc = "Behavior Lab"
  1643.     ldesc = "You are in the behavior lab.  The exit is to the south,
  1644.      and a locked door is to the north. The door is labelled \"Maze -
  1645.      Experimental Subjects Only.\" In addition, a passage labelled
  1646.      \"Viewing Room\" leads east. "
  1647.     south = walkway
  1648.     out = walkway
  1649.     east = mazeview
  1650.     north =
  1651.     {
  1652.         "The door is closed and locked. Besides, do you really want to
  1653.     be an \"Experimental Subject\"?";
  1654.     return( nil );
  1655.     }
  1656. ;
  1657.  
  1658. mazeview: room
  1659.     sdesc = "Maze Viewing Room"
  1660.     ldesc =
  1661.     {
  1662.         "The entire north wall of this room is occupied by a window
  1663.          overlooking a vast human-sized labyrinth. No experimental subjects
  1664.          (i.e., students) seem to be wandering through the maze at the
  1665.      moment, ";
  1666.      
  1667.     if ( not mazeStart.isseen )
  1668.         "but you have the strange feeling that you will have to find
  1669.         your way through the maze some day. You read with a sense of
  1670.         foreboding the plaque affixed to the wall:\b";
  1671.     else
  1672.             "so your attention wanders to the plaque on the wall:\b";
  1673.         
  1674.         mazeplaque.ldesc;
  1675.     }
  1676.     west = behaviorLab
  1677. ;
  1678.  
  1679. mazewindow: fixeditem
  1680.     sdesc = "window"
  1681.     noun = 'window'
  1682.     location = mazeview
  1683.     verDoLookthru( actor ) = {}
  1684.     doLookthru( actor ) = { self.ldesc; }
  1685.     ldesc =
  1686.     {
  1687.         "The window looks out onto a vast human-sized labyrinth.
  1688.          The maze is currently devoid of experimental subjects";
  1689.     if ( not mazeStart.isseen )
  1690.         ", but you have the strange feeling that you'll have to find
  1691.         your way through the maze someday";
  1692.     ". ";
  1693.     }
  1694. ;
  1695.  
  1696. mazeplaque: fixeditem, readable
  1697.     sdesc = "plaque"
  1698.     noun = 'plaque'
  1699.     location = mazeview
  1700.     ldesc = "*** The Behavioral Biology Laboratory Psycho-Magnetic Maze ***
  1701.      \bThe Psycho-Magnetic Maze that is visible through the window has been
  1702.      constructed to determine how the human directional sense interacts with
  1703.      strong electromagnetic and nuclear fields. Through careful tuning of
  1704.      these fields, we have found that human subjects often become completely
  1705.      disoriented in the maze, resulting in hours of random and
  1706.      desperate wandering, and much amusement to those of us in the observation
  1707.      room. "
  1708. ;
  1709.  
  1710. behaviorDoor: lockedDoor
  1711.     ldesc = "The door is closed and locked, and labelled \"Experimental
  1712.      Subjects Only.\""
  1713.     location = behaviorLab
  1714. ;
  1715.  
  1716. security: room
  1717.     sdesc = "Security Office"
  1718.     ldesc = "You are in the campus security office, the very nerve-center of
  1719.      the elite Kaltech Kops.  The officers all
  1720.      appear to be absent; undoubtedly they are all scurrying hither and
  1721.      yon trying to deal with the ditch-day festivities.  There is a desk
  1722.      in the center of the room.  The exit is to
  1723.      the north. "
  1724.     north = walkway
  1725.     out = walkway
  1726. ;
  1727.  
  1728. securityDesk: fixeditem, surface
  1729.     sdesc = "desk"
  1730.     noun = 'desk'
  1731.     location = security
  1732. ;
  1733.  
  1734. securityMemo: readable
  1735.     sdesc = "security memo"
  1736.     iscrawlable = true
  1737.     noun = 'memo'
  1738.     plural = 'memos'
  1739.     adjective = 'security'
  1740.     location = securityDesk
  1741.     ldesc =
  1742.        "From:\t\tDirector of Security
  1743.       \nTo:\t\tAll Security Personnel
  1744.       \nSubject:\tGreat Undergraduate Excavation
  1745.       \bIt has come to the attention of the Kaltech Kops that the student
  1746.       activity in the steam tunnels, known as the \"Great Undergraduate
  1747.       Excavation\" project, has escalated vastly in recent years. Due to
  1748.       objections from city officials about noise from underground and the
  1749.       fear local residents have expressed that their property will be
  1750.       undermined, this office has taken action to halt all GUE activity.
  1751.       Effective immediately, a security officer will be posted at all
  1752.       known steam tunnel entrances, and shall under no circumstances allow
  1753.       students to enter. "
  1754. ;
  1755.  
  1756. flashlight: container
  1757.     islamp = true
  1758.     sdesc = "flashlight"
  1759.     noun = 'flashlight' 'light'
  1760.     adjective = 'flash'
  1761.     location = security
  1762.     ioPutIn( actor, do ) =
  1763.     {
  1764.         if ( do <> battery )
  1765.     {
  1766.         "You can't put "; do.thedesc; " into the flashlight. ";
  1767.     }
  1768.     else pass ioPutIn;
  1769.     }
  1770.     Grab( obj ) =
  1771.     {
  1772.         /*
  1773.      *   Grab( obj ) is invoked whenever an object 'obj' that was
  1774.      *   previously located within me is removed.  If the battery is
  1775.      *   removed, the flashlight turns off.
  1776.      */
  1777.         if ( obj = battery ) self.islit := nil;
  1778.     }
  1779.     ldesc =
  1780.     {
  1781.         if ( battery.location = self )
  1782.     {
  1783.         if ( self.islit )
  1784.             "The flashlight (which contains a battery) is turned on
  1785.         and is providing a warm, reassuring beam of light. ";
  1786.         else
  1787.             "The flashlight (which contains a battery) is currently off. ";
  1788.     }
  1789.     else
  1790.     {
  1791.         "The flashlight is off. It seems to be missing a battery. ";
  1792.     }
  1793.     }
  1794.     verDoTurnon( actor ) =
  1795.     {
  1796.         if ( self.islit ) "It's already on! ";
  1797.     }
  1798.     doTurnon( actor ) =
  1799.     {
  1800.         if ( battery.location = self )
  1801.     {
  1802.         "The flashlight is now on. ";
  1803.         self.islit := true;
  1804.     }
  1805.     else "The flashlight won't turn on without a battery. ";
  1806.     }
  1807.     verDoTurnoff( actor ) =
  1808.     {
  1809.         if ( not self.islit ) "It's not on. ";
  1810.     }
  1811.     doTurnoff( actor ) =
  1812.     {
  1813.         "Okay, the flashlight is now turned off. ";
  1814.     self.islit := nil;
  1815.     }
  1816. ;
  1817.  
  1818. goToSleep: function
  1819. {
  1820. }
  1821.  
  1822. hall1: room
  1823.     sdesc = "Hallway"
  1824.     ldesc = "You are at the west end of a basement hallway. A stairway
  1825.      leads up. "
  1826.     up = courtyard
  1827.     east = hall2
  1828. ;
  1829.  
  1830. hall2: room
  1831.     sdesc = "Hallway"
  1832.     ldesc = "You are in an east-west hallway in the basement.  Another hallway
  1833.      goes off to the north. "
  1834.     west = hall1
  1835.     east = hall3
  1836.     north = hall4
  1837. ;
  1838.  
  1839. hall3: room
  1840.     sdesc = "Hallway"
  1841.     ldesc = "You are at the east end of a hallway in the basement.
  1842.      A passage leads north. "
  1843.     west = hall2
  1844.     north = laundry
  1845. ;
  1846.  
  1847. laundry: room
  1848.     sdesc = "Laundry Room"
  1849.     ldesc = "You are in the laundry room. There is a washing machine
  1850.      against one wall. The exit is to the south. "
  1851.     south = hall3
  1852.     out = hall3
  1853. ;
  1854.  
  1855. washingMachine: fixeditem, openable
  1856.     sdesc = "washing machine"
  1857.     isopen = nil
  1858.     location = laundry
  1859.     noun = 'machine' 'washer'
  1860.     adjective = 'washing'
  1861. ;
  1862.  
  1863. jeans: item
  1864.     sdesc = "blue jeans"
  1865.     location = washingMachine
  1866.     noun = 'jeans' 'pants'
  1867.     adjective = 'blue'
  1868.     ldesc =
  1869.     {
  1870.         if ( self.isseen ) "It's an ordinary pair of jeans. ";
  1871.     else
  1872.     {
  1873.         "It looks like an ordinary pair of jeans, though not
  1874.         your size. As you inspect them, you notice a key fall
  1875.         out of them and to the ground. ";
  1876.         masterKey.moveInto( Me.location );
  1877.         self.isseen := true;
  1878.     }
  1879.     }
  1880.     verDoLookin( actor ) = {}
  1881.     doLookin( actor ) = { self.ldesc; }
  1882.     verDoWear( actor ) = { "They're not your size. "; }
  1883. ;
  1884.  
  1885. masterKey: keyItem
  1886.     iscrawlable = true
  1887.     sdesc = "master key"
  1888.     noun = 'key'
  1889.     adjective = 'master'
  1890.     doTake( actor ) =
  1891.     {
  1892.         if ( not self.isseen )
  1893.     {
  1894.         "*Some* adventure games would try to impose their authors'
  1895.         misguided sense of ethics on you at this point, telling you
  1896.         that you don't feel like picking up the key, or you don't have
  1897.         time to do that, or that it's against the rules to even possess
  1898.         a master key, much less steal one from some other student's
  1899.         pants that you happened to find in a laundry, or even more
  1900.         likely that you are unable to take the key while wearing that
  1901.         dress. However, you're the player, and you're in charge around
  1902.         here, so I'll let you make your own judgments about what's
  1903.         ethical and proper here... ";
  1904.         self.isseen := true;
  1905.     }
  1906.     pass doTake;
  1907.     }
  1908. ;
  1909.  
  1910. hall4: room
  1911.     sdesc = "Hallway"
  1912.     ldesc = "You are in a north-south hallway in the basement. "
  1913.     south = hall2
  1914.     north = hall5
  1915. ;
  1916.  
  1917. hall5: room
  1918.     sdesc = "Hallway"
  1919.     ldesc = "You are at a corner in the basement hallway. You can go east
  1920.      or south. "
  1921.     south = hall4
  1922.     east = hall6
  1923. ;
  1924.  
  1925. hall6: room
  1926.     sdesc = "Hallway"
  1927.     ldesc = "You are at the east end of a basement hallway. To the north is
  1928.      a \"storage room,\" which everyone knows is actually an entrance
  1929.      to the steam tunnels. "
  1930.     west = hall5
  1931.     north = storage
  1932. ;
  1933.  
  1934. storage: room
  1935.     sdesc = "Storage Room"
  1936.     ldesc =
  1937.     {
  1938.         "You are in a large storage room. There really hasn't been
  1939.          anything stored here for a long time (at least, not anything that
  1940.          anybody wants to ever see again). The exit is to the south. To
  1941.      the north lies a door, which is ";
  1942.      if ( tunnelDoor.isopen ) "open"; else "closed"; ". A small card
  1943.      table is sitting in front of the door. ";
  1944.     }
  1945.     south = hall6
  1946.     north =
  1947.     {
  1948.         if ( guard.isActive )
  1949.     {
  1950.         "The guard won't let you enter the tunnel. ";
  1951.             return( nil );
  1952.     }
  1953.     else if ( not tunnelDoor.isopen )
  1954.     {
  1955.         "A closed door stands in your way. ";
  1956.         setit( tunnelDoor );       /* "it" now refers to the closed door */
  1957.         return( nil );
  1958.     }
  1959.     else return( tunnel1 );
  1960.     }
  1961.     enterRoom( actor ) =
  1962.     {
  1963.         if ( guard.isActive )
  1964.     {
  1965.         notify( guard, #patrol, 0 );
  1966.     }
  1967.     pass enterRoom;
  1968.     }
  1969.     leaveRoom( actor ) =
  1970.     {
  1971.         if ( guard.isActive )
  1972.     {
  1973.         unnotify( guard, #patrol );
  1974.     }
  1975.     pass leaveRoom;
  1976.     }
  1977. ;
  1978.  
  1979. tunnelDoor: lockedDoor
  1980.     location = storage
  1981.     mykey = masterKey
  1982. ;
  1983.  
  1984. guard: Actor
  1985.     sdesc = "guard"
  1986.     noun = 'guard' 'him'
  1987.     ldesc =
  1988.     {
  1989.         "The guard is a member of the Kaltech Kops, the elite corps of
  1990.     dedicated men and women that keeps the campus safe from undesirables
  1991.     (i.e., the students). ";
  1992.     if ( not self.isActive )
  1993.         "Currently, the guard is fast asleep, which is quite typical. ";
  1994.     }
  1995.     adjective = 'security'
  1996.     isActive = true
  1997.     location = storage
  1998.     actorDesc =
  1999.     {
  2000.     if ( self.isActive )
  2001.         "A guard is sitting at the card table in front of the door.
  2002.         He watches you carefully, evidently thinking that you might
  2003.         be planning to try to go through the door. ";
  2004.     else
  2005.         "A guard is slumped over a small card table in front of the
  2006.         steam tunnel entrance, evidently fast asleep. How typical. ";
  2007.     }
  2008.     verIoGiveTo( actor ) =
  2009.     {
  2010.         if ( not self.isActive )
  2011.         "The guard appears to be fast asleep. ";
  2012.     }
  2013.     ioGiveTo( actor, do ) =
  2014.     {
  2015.         if ( do = dollar or do = money )
  2016.         "The guard looks at you sternly. \"You should be ashamed of
  2017.         yourself, trying to bribe a member of the elite Kaltech Kops!\"
  2018.         he admonishes you, refusing your offer. ";
  2019.         else if ( do <> cup or not cup.isFull )
  2020.         "The guard doesn't appear interested. ";
  2021.     else
  2022.     {
  2023.         self.isActive := nil;
  2024.         unnotify( self, #patrol );
  2025.         "The guard happily accepts your offer; \"ToxiCola! My favorite!\"
  2026.         he says appreciatively, not knowing the evil deed
  2027.         that you have in mind. He quickly drinks the entire cup of
  2028.         ToxiCola. \"Wow! Just the caffeine pickup I needed,\" he says
  2029.         happily.
  2030.         \n\tAfter a few moments, though, he looks rather queasy. \"That
  2031.         caffeine just doesn't last long enough,\" he says just before
  2032.         he passes out, slumping over the card table. ";
  2033.         cup.isFull := nil;
  2034.         toxicola.moveInto( nil );
  2035.         cup.moveInto( cardtable );
  2036.         incscore( 10 );
  2037.     }
  2038.     }
  2039.     patrolMessage =
  2040.     [
  2041.         // random message 1
  2042.     'The guard eyes you warily.'
  2043.     // random message 2
  2044.     'The guard looks at his empty glass, probably wishing he had
  2045.     something to drink.'
  2046.     // random message 3
  2047.     'The guard flips purposefully through the pages of his memo pad.'
  2048.     // random message 4
  2049.     'The guard writes something down on his memo pad, glancing up from
  2050.     time to time to eye you suspiciously.'
  2051.     // random message 5
  2052.     'The guard picks up his empty glass and starts to drink, then
  2053.     realizes it is empty and puts it back down.'
  2054.     ]
  2055.     patrol =
  2056.     {
  2057.         if ( self.location = Me.location )
  2058.     {
  2059.             "\b";
  2060.             say( self.patrolMessage[rand( 5 )]);
  2061.     }
  2062.     }
  2063. ;
  2064.  
  2065. cardtable: fixeditem, surface
  2066.     noun = 'table'
  2067.     adjective = 'card'
  2068.     location = storage
  2069.     sdesc = "card table"
  2070. ;
  2071.  
  2072. emptyglass: container
  2073.     noun = 'glass'
  2074.     adjective = 'empty'
  2075.     sdesc = "empty glass"
  2076.     adesc = "an empty glass"
  2077.     location = cardtable
  2078.     doTake( actor ) =
  2079.     {
  2080.         if ( guard.isActive )
  2081.         "The guard won't let you take the glass. \"Get your own,\"
  2082.         he says. ";
  2083.     else pass doTake;
  2084.     }
  2085.     ioPutIn( actor, do ) =
  2086.     {
  2087.         if ( do = ln2 ) "The liquid nitrogen evaporates on contact. ";
  2088.     else "It won't fit in the glass. ";
  2089.     }
  2090. ;
  2091.  
  2092. tunnelSounds: function( parm )
  2093. {
  2094.     if ( Me.location.istunnel )
  2095.     {
  2096.         "\b";
  2097.     say( tunnelroom.randomsound[rand( 5 )]);
  2098.     }
  2099.     setfuse( tunnelSounds, rand( 5 ), nil );
  2100. }
  2101.  
  2102. class tunnelroom: room
  2103.     istunnel = true
  2104.     sdesc = "Steam Tunnel"
  2105.     randomsound = [
  2106.     // random sound 1
  2107.       'The rumbling sound suddenly becomes very loud, then, after
  2108.        a few moments, dies down to background levels again.'
  2109.     // random sound 2
  2110.       'A series of clanking noises, like marbles rolling through the
  2111.       steam pipes, starts in the distance, then comes
  2112.       closer and closer, until it seems to pass right overhead. It disappears
  2113.       into the distance.'
  2114.     // random sound 3
  2115.       'A very loud bang suddenly reverberates through the tunnel.'
  2116.     // random sound 4
  2117.       'One of the pipes starts to hiss wildly. After a few moments, it
  2118.       fades back into the background sounds.'
  2119.     // random sound 5
  2120.       'A loud buzzing sound, like an overloaded electrical circuit,
  2121.       emanates from somewhere nearby. After a few moments it is gone.'
  2122.     ]
  2123. ;
  2124.  
  2125. tunnelpipes: fixeditem
  2126.     sdesc = "pipes"
  2127.     noun = 'pipe' 'pipes'
  2128.     ldesc = "The pipes range from very small copper tubes only an inch around
  2129.      to huge asbestos-covered cylinders over two feet in diameter.  Many of
  2130.      the larger pipes are marked \"STEAM - 300 PSI.\" "
  2131.     locationOK = true
  2132.     location =
  2133.     {
  2134.         if ( Me.location.istunnel ) return( Me.location );
  2135.     else return( nil );
  2136.     }
  2137. ;
  2138.  
  2139. tunnel1: tunnelroom
  2140.     ldesc = "You are in a steam tunnel. It is very hot and dry in here.
  2141.      The place has a strange musty odor; the air is very still, but there
  2142.      are distant sounds of all sorts that vibrate through the pipes. The
  2143.      pipes all seem to be hissing quietly, and a low rumbling sound constantly
  2144.      reverberates through the tunnel. Occasionally a distant clang or thud
  2145.      or crack emanates from the pipes.
  2146.      \n\tThe steam tunnel runs east and west. A small passage leads south. "
  2147.     east = tunnel2
  2148.     west = tunnel3
  2149.     south = storage
  2150.     enterRoom( actor ) =
  2151.     {
  2152.         if ( not self.isseen ) setfuse( tunnelSounds, rand( 5 ), nil );
  2153.     pass enterRoom;
  2154.     }
  2155. ;
  2156.  
  2157. tunnel2: tunnelroom
  2158.     ldesc = "You are at the east end of the steam tunnel. "
  2159.     west = tunnel1
  2160. ;
  2161.  
  2162. tunnelStorage: room
  2163.     sdesc = "Storage Room"
  2164.     ldesc = "You are in a small storage room. The exit lies north. "
  2165.     north = tunnel13
  2166. ;
  2167.  
  2168. tunnel3: tunnelroom
  2169.     ldesc = "You are in an east-west section of the steam tunnels. "
  2170.     east = tunnel1
  2171.     west = tunnel4
  2172. ;
  2173.  
  2174. tunnel4: tunnelroom
  2175.     ldesc = "You are at a T-intersection of two sections of steam
  2176.      tunnel; tunnels go off to the north, south, and east. "
  2177.     east = tunnel3
  2178.     north = tunnel5
  2179.     south = tunnel6
  2180. ;
  2181.  
  2182. darktunnel: darkroom, tunnelroom
  2183.     controlon = nil
  2184.     islit =
  2185.     {
  2186.         if ( self.controlon ) return( true );
  2187.     else pass islit;
  2188.     }
  2189. ;
  2190.  
  2191. tunnel5: darktunnel
  2192.     ldesc = "You are at a corner in the steam tunnel: you can go
  2193.      west and south. "
  2194.     west = tunnel7
  2195.     south = tunnel4
  2196. ;
  2197.  
  2198. tunnel6: tunnelroom
  2199.     ldesc = "You are at a corner in the steam tunnel: you can go
  2200.      west and north. "
  2201.     west = tunnel8
  2202.     north = tunnel4
  2203. ;
  2204.  
  2205. tunnel7: darktunnel
  2206.     ldesc = "You are in an east-west section of the steam tunnel.
  2207.      A very small passage between some steam pipes leads north, but
  2208.      it would be a tight squeeze. "
  2209.     east = tunnel5
  2210.     west = tunnel9
  2211.     north =
  2212.     {
  2213.         return(crawltest( tunnel12,
  2214.          'You lay down on one of the pipes and start to snake
  2215.           through the passage. For a moment, you think you\'re
  2216.           stuck, but you manage to wriggle your way through. You
  2217.           emerge on the north side of the narrow crawl.' ));
  2218.     }
  2219. ;
  2220.  
  2221. tunnel8: tunnelroom
  2222.     controlon = true
  2223.     ldesc =
  2224.     {
  2225.         "You are in an east-west section of the steam tunnel. On the
  2226.          wall is a control unit. ";
  2227.     if ( not self.controlon )
  2228.     {
  2229.         "It is quite dark in this section of the tunnel; the only
  2230.          illumination is coming from the control unit's display";
  2231.          
  2232.         if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
  2233.          and flashlight.islit )
  2234.             " (and from the flashlight, of course)";
  2235.     
  2236.         ". ";
  2237.     }
  2238.     }
  2239.     east = tunnel6
  2240.     west = tunnel10
  2241. ;
  2242.  
  2243. controlunit: fixeditem
  2244.     sdesc = "control unit"
  2245.     noun = 'unit'
  2246.     adjective = 'control'
  2247.     location = tunnel8
  2248.     ldesc =
  2249.     {
  2250.         "The control unit is quite modern and high-tech looking, in
  2251.          stark contrast to the tunnels around it. It consists of a keypad
  2252.          which allows entry of arbitrary numbers, a large green button,
  2253.      and a display screen. The unit is labelled \"Station 2.\" ";
  2254.     controldisp.ldesc;
  2255.     }
  2256.     objref =
  2257.     {
  2258.         local l;
  2259.     
  2260.     l := self.value;
  2261.     
  2262.     if ( l = 322 ) return( tunnel8 );
  2263.     else if ( l = 612 ) return( mazeroom );
  2264.     else if ( l = 293 ) return( darktunnel );
  2265.     else return( nil );
  2266.     }
  2267.     value = 322
  2268. ;
  2269.  
  2270. controlpad: fixeditem
  2271.     sdesc = "keypad"
  2272.     noun = 'keypad' 'pad'
  2273.     adjective = 'key'
  2274.     location = tunnel8
  2275.     ldesc = "It's one of those cheesy membrane keypads, like on a microwave
  2276.      oven or the new Enterprise's control panels. It allows you to type numbers
  2277.      made up of digits from 0 to 9. "
  2278.     verIoTypeOn( actor ) = {}
  2279.     ioTypeOn( actor, do ) =
  2280.     {
  2281.         if ( do <> numObj )
  2282.         "The keypad only allows entry of numbers. ";
  2283.     else
  2284.     {
  2285.         "As you type the number sequence, the display screen is
  2286.         updated. ";
  2287.         controlunit.value := numObj.value;
  2288.         controldisp.ldesc;
  2289.     }
  2290.     }
  2291. ;
  2292.  
  2293. controlbutton: buttonitem
  2294.     sdesc = "button"
  2295.     adjective = 'green'
  2296.     location = tunnel8
  2297.     doPush( actor ) =
  2298.     {
  2299.         local r;
  2300.     
  2301.     r := controlunit.objref;
  2302.     if ( r )
  2303.     {
  2304.         "The display is updated as you press the button. ";
  2305.         r.controlon := not r.controlon;
  2306.         controldisp.ldesc;
  2307.         if ( r = tunnel8 )
  2308.         {
  2309.             "The lights in the tunnel ";
  2310.             if ( r.controlon )
  2311.             "come on. ";
  2312.         else
  2313.         {
  2314.             "go out, leaving only the display screen's light ";
  2315.             if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
  2316.              and flashlight.islit )
  2317.                 "(and the flashlight, of course) ";
  2318.             "for illumination. ";
  2319.         }
  2320.         }
  2321.     }
  2322.     else "The unit beeps; nothing else appears to happen. ";
  2323.     }
  2324. ;
  2325.  
  2326. controldisp: fixeditem
  2327.     sdesc = "display screen"
  2328.     noun = 'screen'
  2329.     adjective = 'display'
  2330.     location = tunnel8
  2331.     ldesc =
  2332.     {
  2333.         local l, r;
  2334.     
  2335.     l := controlunit.value;
  2336.     r := controlunit.objref;
  2337.         "The screen is currently displaying: \""; say( l ); ": ";    
  2338.     if ( r )
  2339.     {
  2340.         if ( r.controlon ) "ON"; else "OFF";
  2341.     }
  2342.     else "???";
  2343.     
  2344.     "\". ";
  2345.     }
  2346. ;
  2347.  
  2348. tunnel9: darktunnel
  2349.     ldesc = "You are at a corner in the steam tunnel.  You can go east
  2350.      or south. "
  2351.     east = tunnel7
  2352.     south = tunnel11
  2353. ;
  2354.  
  2355. tunnel10: tunnelroom
  2356.     ldesc = "You are at a corner in the steam tunnel. You can go east
  2357.      or north. "
  2358.     east = tunnel8
  2359.     north = tunnel11
  2360. ;
  2361.  
  2362. tunnel11: tunnelroom
  2363.     ldesc = "You are in a north-south section of the steam tunnels. Set
  2364.      into one wall is a large chute. "
  2365.     north = tunnel9
  2366.     south = tunnel10
  2367. ;
  2368.  
  2369. chute: fixeditem, container
  2370.     sdesc = "chute"
  2371.     noun = 'chute'
  2372.     location = tunnel11
  2373.     ldesc = "The chute is large enough for anything you're carrying,
  2374.      but not nearly big enough for you. You can't tell where it goes,
  2375.      except down. "
  2376.     ioPutIn( actor, do ) =
  2377.     {
  2378.         "You put "; do.thedesc; " into the chute, and it slides away
  2379.     into the darkness. After a few moments, you hear a soft thud. ";
  2380.     do.moveInto( chuteroom );
  2381.     }
  2382. ;
  2383.  
  2384. crawltest: function( rm, msg )
  2385. {
  2386.     local i;
  2387.     
  2388.     i := 1;
  2389.     while ( i <= length( Me.contents ))
  2390.     {
  2391.         if ( not Me.contents[i].iscrawlable )
  2392.     {
  2393.         "You'll never get through carrying ";
  2394.         Me.contents[i].thedesc; ". ";
  2395.         return( nil );
  2396.     }
  2397.         i := i + 1;
  2398.     }
  2399.     say( msg ); "\b";
  2400.     return( rm );
  2401. }
  2402.  
  2403. tunnel12: tunnelroom
  2404.     ldesc =
  2405.     {
  2406.         if ( self.isseen )
  2407.             "You are in an east-west section of the steam tunnels. A narrow
  2408.             passage between some steam pipes might allow you to go south. ";
  2409.     else
  2410.         "You are in another steam tunnel, but this one is substantially
  2411.         different from the tunnels you have been in so far. This tunnel
  2412.         is much wider, less cluttered; it looks like it was built more
  2413.         recently than the south tunnels. The tunnel itself runs east
  2414.         and west, and passing back to the south is evidently possible,
  2415.         given your presence here. ";
  2416.     }
  2417.     east = tunnel13
  2418.     west = pitTop
  2419.     south =
  2420.     {
  2421.         return(crawltest( tunnel7, 'Going through the crawl
  2422.      southbound is just as difficult as it was coming north,
  2423.      you observe.' ));
  2424.     }
  2425. ;
  2426.  
  2427. tunnel13: tunnelroom
  2428.     ldesc = "You are at the east end of a steam tunnel. A passage leads
  2429.      north, and another one leads south. "
  2430.     west = tunnel12
  2431.     north = maze0
  2432.     south = tunnelStorage
  2433. ;
  2434.  
  2435. maze0: room
  2436.     sdesc = "Outside Maze"
  2437.     ldesc =
  2438.     {
  2439.         "You are in a small room, with exits north and south. The
  2440.          passage to the north has a small sign reading \"Behavior Lab Maze\";
  2441.          the room is filled with strange equipment, which you surmise is
  2442.          connected in some way to the maze. ";
  2443.      
  2444.     if ( mazeroom.controlon )
  2445.         "The equipment is buzzing loudly. Standing
  2446.          near it makes you feel vaguely dizzy. ";
  2447.     
  2448.     if ( not self.isseen )
  2449.     {
  2450.         "\n\tYou sigh in resignation as you realize that you have reached
  2451.         the obligatory Adventure Game Maze, and ";
  2452.         if ( mazeview.isseen )
  2453.             "wish that this were a graphical adventure, so your trip to
  2454.         the maze viewing room had resulted in a map you could refer
  2455.         to now. Fortunately, you do recall noting that the passages
  2456.         in the maze all lead east-west or north-south. ";
  2457.             else
  2458.             "wonder what this maze's unique twist will be. Surely, it
  2459.         won't just be a boring old labyrinth... ";
  2460.     }
  2461.     }
  2462.     south = tunnel13
  2463.     north = maze1
  2464. ;
  2465.  
  2466. mazeequip: decoration
  2467.     noun = 'equipment' 'coil' 'coils' 'pipe' 'pipes' 'wire' 'wires'
  2468.     adjective = 'electric' 'electrical'
  2469.     sdesc = "equipment"
  2470.     location = maze0
  2471.     ldesc =
  2472.     {
  2473.         "The equipment resembles some of the particle accelerators that
  2474.     you have seen. It has several huge electric coils, all arranged
  2475.     around a series of foot-diameter pipes. A tangled web of enormous
  2476.     wires connects various parts of the equipment together and other
  2477.     wires feed it power. ";
  2478.     
  2479.         if ( mazeroom.controlon )
  2480.         "The equipment is buzzing loudly. Standing near it makes
  2481.         you feel vaguely dizzy. ";
  2482.     }
  2483. ;
  2484.  
  2485. mazeroom: room
  2486.     controlon = true
  2487.     sdesc = "Lost in the Maze"
  2488.     lookAround( verbosity ) =
  2489.     {
  2490.         self.statusLine;
  2491.     self.nrmLkAround( self.controlon ? true : verbosity );
  2492.     }
  2493.     ldesc =
  2494.     {
  2495.         if ( self.controlon )
  2496.         "You can't quite seem to get your bearings. There are some
  2497.         passages leading away, but you can't quite tell how many or
  2498.         in which direction they leads. ";
  2499.     else
  2500.     {
  2501.         local cnt, tot, i;
  2502.         
  2503.         tot := 0;
  2504.         i := 1;
  2505.         while ( i <= 4 )
  2506.         {
  2507.             if ( self.dirlist[i] ) tot := tot + 1;
  2508.             i := i + 1;
  2509.         }
  2510.  
  2511.         "You are in a room in the maze; they all look alike.
  2512.         You can go ";
  2513.         
  2514.         i := 1;
  2515.         cnt := 0;
  2516.         while ( i <= 4 )
  2517.         {
  2518.             if ( self.dirlist[i] )
  2519.         {
  2520.             if ( cnt > 0 )
  2521.             {
  2522.                 if ( tot = 2 ) " and ";
  2523.             else if ( cnt+1 = tot ) ", and ";
  2524.             else ", ";
  2525.             }
  2526.             cnt := cnt + 1;
  2527.             
  2528.             say( ['north' 'south' 'east' 'west'][i] );
  2529.         }
  2530.             i := i + 1;
  2531.         }
  2532.         ". ";
  2533.     }
  2534.     }
  2535.     mazetravel( rm ) =
  2536.     {
  2537.         if ( self.controlon )
  2538.     {
  2539.         local r;
  2540.         
  2541.         "You can't figure out which direction is which; the more you
  2542.         stumble about, the more the room seems to spin around. After a
  2543.         few steps, you're not sure if you've actually gone anywhere,
  2544.         since all these rooms look alike...\b";
  2545.         
  2546.         /*
  2547.          *   We know we can only go one of four directions, but generate
  2548.          *   a random number up to 6; if we generate 5 or 6, we won't go
  2549.          *   anywhere, but we won't let on that this is the case.
  2550.          */
  2551.         r := rand( 6 );
  2552.         
  2553.         /*
  2554.          *   Note that we want to confuse the player in active-maze mode
  2555.          *   as much as possible, so we don't want any clues as to whether
  2556.          *   there was any travel in this direction or not.  So, return
  2557.          *   "self" rather than "nil," since we won't get any message if
  2558.          *   we return "nil," but we'll get the current room's message if
  2559.          *   we return "self;" since all the messages are the same, this
  2560.          *   won't provide any information.
  2561.          */
  2562.         if ( r < 5 )
  2563.         {
  2564.             r := self.dirlist[ r ];
  2565.         if ( r ) return( r );
  2566.         else return( self );
  2567.         }
  2568.         else return( self );
  2569.     }
  2570.     else
  2571.     {
  2572.         if ( rm )
  2573.             return( rm );
  2574.         else
  2575.         {
  2576.             "You can't go that way. ";
  2577.             return( nil );
  2578.         }
  2579.     }
  2580.     }
  2581.     north = ( self.mazetravel( self.dirlist[1] ))
  2582.     south = ( self.mazetravel( self.dirlist[2] ))
  2583.     east = ( self.mazetravel( self.dirlist[3] ))
  2584.     west = ( self.mazetravel( self.dirlist[4] ))
  2585.     up = ( self.mazetravel( 0 ))
  2586.     down = ( self.mazetravel( 0 ))
  2587.     in = ( self.mazetravel( 0 ))
  2588.     out = ( self.mazetravel( 0 ))
  2589.     ne = ( self.mazetravel( 0 ))
  2590.     nw = ( self.mazetravel( 0 ))
  2591.     se = ( self.mazetravel( 0 ))
  2592.     sw = ( self.mazetravel( 0 ))
  2593. ;
  2594.  
  2595. maze1: mazeroom
  2596.     dirlist = [ 0 maze0 maze2 0 ]
  2597. ;
  2598.  
  2599. maze2: mazeroom
  2600.     dirlist = [ maze9 0 maze3 maze1 ]
  2601. ;
  2602.  
  2603. maze3: mazeroom
  2604.     dirlist = [ maze8 0 maze4 maze2 ]
  2605. ;
  2606.  
  2607. maze4: mazeroom
  2608.     dirlist = [ 0 0 maze5 maze3 ]
  2609. ;
  2610.  
  2611. maze5: mazeroom
  2612.     dirlist = [ maze6 0 0 maze4 ]
  2613. ;
  2614.  
  2615. maze6: mazeroom
  2616.     dirlist = [ 0 maze5 0 maze7 ]
  2617. ;
  2618.  
  2619. maze7: mazeroom
  2620.     dirlist = [ maze30 0 maze9 maze8 ]
  2621. ;
  2622.  
  2623. maze8: mazeroom
  2624.     dirlist = [ maze29 maze3 maze7 0 ]
  2625. ;
  2626.  
  2627. maze9: mazeroom
  2628.     dirlist = [ 0 maze2 0 maze10 ]
  2629. ;
  2630.  
  2631. maze10: mazeroom
  2632.     dirlist = [ 0 0 maze9 maze11 ]
  2633. ;
  2634.  
  2635. maze11: mazeroom
  2636.     dirlist = [ 0 maze35 maze10 maze12 ]
  2637. ;
  2638.  
  2639. maze12: mazeroom
  2640.     dirlist = [ 0 0 maze11 0 ]
  2641. ;
  2642.  
  2643. maze13: mazeroom
  2644.     dirlist = [ maze24 maze18 0 0 ]
  2645. ;
  2646.  
  2647. maze14: mazeroom
  2648.     dirlist = [ 0 maze17 0 maze15 ]
  2649. ;
  2650.  
  2651. maze15: mazeroom
  2652.     dirlist = [ 0 maze16 maze14 0 ]
  2653. ;
  2654.  
  2655. maze16: mazeroom
  2656.     dirlist = [ maze15 maze23 maze17 0 ]
  2657. ;
  2658.  
  2659. maze17: mazeroom
  2660.     dirlist = [ maze14 maze22 maze18 maze16 ]
  2661. ;
  2662.  
  2663. maze18: mazeroom
  2664.     dirlist = [ maze13 maze21 0 maze17 ]
  2665. ;
  2666.  
  2667. maze19: mazeroom
  2668.     dirlist = [ 0 maze20 maze35 0 ]
  2669. ;
  2670.  
  2671. maze20: mazeroom
  2672.     dirlist = [ maze19 0 0 maze21 ]
  2673. ;
  2674.  
  2675. maze21: mazeroom
  2676.     dirlist = [ maze18 0 maze20 0 ]
  2677. ;
  2678.  
  2679. maze22: mazeroom
  2680.     dirlist = [ maze17 0 0 0 ]
  2681. ;
  2682.  
  2683. maze23: mazeroom
  2684.     dirlist = [ maze16 0 0 0 ]
  2685. ;
  2686.  
  2687. maze24: mazeroom
  2688.     dirlist = [ 0 maze13 maze25 0 ]
  2689. ;
  2690.  
  2691. maze25: mazeroom
  2692.     dirlist = [ maze33 0 maze26 maze24 ]
  2693. ;
  2694.  
  2695. maze26: mazeroom
  2696.     dirlist = [ maze32 0 0 maze25 ]
  2697. ;
  2698.  
  2699. maze27: mazeroom
  2700.     dirlist = [ maze31 0 0 0 ]
  2701. ;
  2702.  
  2703. maze28: mazeroom
  2704.     dirlist = [ 0 0 maze29 0 ]
  2705. ;
  2706.  
  2707. maze29: mazeroom
  2708.     dirlist = [ 0 maze8 maze30 maze28 ]
  2709. ;
  2710.  
  2711. maze30: mazeroom
  2712.     dirlist = [ 0 maze7 0 maze29 ]
  2713. ;
  2714.  
  2715. maze31: mazeroom
  2716.     dirlist = [ 0 maze27 0 maze32 ]
  2717. ;
  2718.  
  2719. maze32: mazeroom
  2720.     dirlist = [ 0 maze26 maze31 0 ]
  2721. ;
  2722.  
  2723. maze33: mazeroom
  2724.     dirlist = [ 0 maze25 0 maze34 ]
  2725. ;
  2726.  
  2727. maze34: mazeroom
  2728.     dirlist = [ 0 0 maze33 mazeStart ]
  2729. ;
  2730.  
  2731. maze35: mazeroom
  2732.     dirlist = [ maze11 0 0 maze19 ]
  2733. ;
  2734.  
  2735. mazeStart: room
  2736.     sdesc = "Start of Maze"
  2737.     ldesc = "You are at the start of the maze. A passage into the
  2738.      maze is to the east, and a heavy one-way door marked \"Exit\" is to the
  2739.      south. "
  2740.     east = maze34
  2741.     south = behaviorLab
  2742. ;
  2743.  
  2744. mazedoor: fixeditem
  2745.     sdesc = "door"
  2746.     noun = 'door'
  2747.     adjective = 'exit' 'one-way' 'heavy'
  2748.     verDoOpen( actor ) = { "No need; just walk on through. "; }
  2749.     location = mazeStart
  2750. ;
  2751.  
  2752. chuteroom: room
  2753.     sdesc = "Chute Room"
  2754.     ldesc = "You are in a small room with exits to the northwest
  2755.      and south. The bottom of a large chute opens into the room. "
  2756.     nw = pitBottom
  2757.     south = shiproom
  2758. ;
  2759.  
  2760. chute2: fixeditem, container
  2761.     sdesc = "chute"
  2762.     noun = 'chute'
  2763.     location = chuteroom
  2764.     ioPutIn( actor, do ) =
  2765.     {
  2766.         "This is the bottom of the chute; you can't put objects
  2767.     into it. ";
  2768.     }
  2769. ;
  2770.  
  2771. pitTop: tunnelroom
  2772.     sdesc = "Top of Pit"
  2773.     ldesc =
  2774.     {
  2775.         "You are in a large open area in the steam tunnels. In
  2776.          the center of the room is a large pit, around which is a protective
  2777.          railing. A steam tunnel is to the east. ";
  2778.     if ( rope.tieItem = railing )
  2779.         "A rope is tied to the railing, and extends down into the pit. ";
  2780.     }
  2781.     east = tunnel12
  2782.     down =
  2783.     {
  2784.         if ( rope.tieItem = railing )
  2785.     {
  2786.         "You climb down the rope...\b";
  2787.         return( pitBottom );
  2788.     }
  2789.     else
  2790.     {
  2791.         "You'd probably break your neck if you tried to jump
  2792.         into the pit. ";
  2793.             return( nil );
  2794.     }
  2795.     }
  2796. ;
  2797.  
  2798. tieVerb: deepverb
  2799.     sdesc = "tie"
  2800.     verb = 'tie'
  2801.     prepDefault = toPrep
  2802.     ioAction( toPrep ) = 'TieTo'
  2803. ;
  2804.  
  2805. railing: fixeditem
  2806.     sdesc = "rail"
  2807.     noun = 'rail' 'railing'
  2808.     location = pitTop
  2809.     verIoTieTo( actor ) = {}
  2810.     ioTieTo( actor, do ) =
  2811.     {
  2812.         "You tie one end of the rope to the railing, and lower the other
  2813.     end into the pit. It appears to extend to the bottom of the pit. ";
  2814.     rope.tieItem := self;
  2815.     rope.moveInto( pitTop );
  2816.     rope.isfixed := true;
  2817.     }
  2818. ;
  2819.  
  2820. climbupVerb: deepverb
  2821.     verb = 'climb up'
  2822.     sdesc = "climb up"
  2823.     doAction = 'Climbup'
  2824. ;
  2825.  
  2826. climbdownVerb: deepverb
  2827.     verb = 'climb down'
  2828.     sdesc = "climb down"
  2829.     doAction = 'Climbdown'
  2830. ;
  2831.  
  2832. rope: item
  2833.     sdesc = "rope"
  2834.     noun = 'rope'
  2835.     location = tunnelStorage
  2836.     ldesc =
  2837.     {
  2838.         if ( self.tieItem )
  2839.     {
  2840.         "It's tied to "; self.tieItem.thedesc; ". ";
  2841.     }
  2842.     else pass ldesc;
  2843.     }
  2844.     verDoTieTo( actor, io ) =
  2845.     {
  2846.         if ( self.tieItem )
  2847.     {
  2848.         "It's already tied to "; self.tieItem.thedesc; "! ";
  2849.     }
  2850.     }
  2851.     doTake( actor ) =
  2852.     {
  2853.         if ( self.tieItem )
  2854.     {
  2855.         "(You untie it first, of course.) ";
  2856.         self.tieItem := nil;
  2857.         self.isfixed := nil;
  2858.     }
  2859.     pass doTake;
  2860.     }
  2861.     verDoClimb( actor ) =
  2862.     {
  2863.         if ( self.tieItem = nil )
  2864.         "Climbing down the rope in its present configuration would
  2865.         get you nowhere. ";
  2866.     }
  2867.     doClimb( actor ) =
  2868.     {
  2869.         "You climb down the rope...\b";
  2870.         Me.travelTo( pitBottom );
  2871.     }
  2872.     verDoClimbdown( actor ) = {}
  2873.     doClimbdown( actor ) = { self.doClimb( actor ); }
  2874. ;
  2875.  
  2876. pitBottom: room
  2877.     sdesc = "Huge Cavern"
  2878.     ldesc = "You are in a huge and obviously artificial cavern. The cave
  2879.      has apparently been dug out over a long period of time; some parts
  2880.      look very old, and other areas look comparatively recent. A small bronze
  2881.      plaque affixed to one of the older walls reads, \"Great Undergraduate
  2882.      Excavation - 1982.\"
  2883.      From high above, a small opening in
  2884.      the ceiling casts a dim glow over the vast chamber. A rope extends
  2885.      from the opening above. Passages of various ages lead north, south,
  2886.      east, west, southeast, and southwest. "
  2887.     up =
  2888.     {
  2889.         "It's a long climb, but you somehow manage it.\b";
  2890.         return( pitTop );
  2891.     }
  2892.     se = chuteroom
  2893.     east = biohall1
  2894.     south = bank
  2895.     north = cave
  2896.     sw = insOffice
  2897.     west = machineshop
  2898. ;
  2899.  
  2900. pitplaque: fixeditem, readable
  2901.     noun = 'plaque'
  2902.     sdesc = "bronze plaque"
  2903.     adjective = 'bronze' 'small'
  2904.     location = pitBottom
  2905.     ldesc = "Great Undergraduate Excavation\n\t\t\t1982"
  2906. ;
  2907.  
  2908. insOffice: room
  2909.     sdesc = "Insurance Office"
  2910.     ldesc =
  2911.     {
  2912.         "You are in an insurance office. Like most insurance offices,
  2913.     the area is rather non-descript. The exit is northeast. ";
  2914.     if ( not self.isseen )
  2915.     {
  2916.         "\n\tAs you walk into the office, a large metallic robot, very
  2917.         much like the traditional sci-fi film robot, but wearing a dark
  2918.         polyester business suit, zips up to you. \"Hi, I'm Lloyd the
  2919.         Friendly Insurance Robot,\" he says in a mechanical British
  2920.         accent. \"You look like you could use some insurance! Here, let
  2921.         me prepare a policy for you.\"
  2922.         \n\tLloyd scurries around the room, gathering papers and
  2923.         studying charts, occasionally zipping up next to you and
  2924.         measuring your height and other dimensions, making all kinds
  2925.         of notes, and generally scampering about. After a few minutes,
  2926.         he comes up to you, showing you a piece of paper.
  2927.         \n\t\"I have the perfect policy for you. Just one dollar will
  2928.         buy you a hundred thousand worth of insurance!\" He watches
  2929.         you anxiously. ";
  2930.         
  2931.         notify( lloyd, #offerins, 0 );
  2932.     }
  2933.     }
  2934.     ne = pitBottom
  2935.     out = pitBottom
  2936. ;
  2937.  
  2938. /*
  2939.  *   Lloyd the Friendly Insurance Robot is a full-featured actor. He will
  2940.  *   initially just wait in his office until paid for a policy, but will
  2941.  *   thereafter follow the player around relentlessly.  Lloyd doesn't
  2942.  *   interact much, though; he just hangs around and does wacky things.
  2943.  */
  2944. lloyd: Actor
  2945.     noun = 'lloyd' 'him'
  2946.     sdesc = "Lloyd"
  2947.     adesc = "Lloyd"
  2948.     thedesc = "Lloyd"
  2949.     ldesc = "Lloyd the Friendly Insurance Robot is a strange combination
  2950.      of the traditional metallic robot and an insurance salesman; over his
  2951.      bulky metal frame is a polyester suit. "
  2952.     actorAction( v, d, p, i ) =
  2953.     {
  2954.         if ( v = helloVerb )
  2955.         "\"Hello,\" Lloyd responds cheerfully. ";
  2956.     else if ( v = followVerb and d = Me )
  2957.     {
  2958.         if ( self.offering )
  2959.             "\"Sorry, but I must stay here until I've made a sale.\" ";
  2960.         else
  2961.             "\"I will follow you,\" Lloyd says. \"That will allow me
  2962.         to pay any claim you make immediately should the need arise.
  2963.         It's just one of the ways we keep our overhead so low.\" ";
  2964.     }
  2965.     else
  2966.         "\"I'm sorry, that's not in your policy.\" ";
  2967.     exit;
  2968.     }
  2969.     verDoAskAbout( actor, io ) = {}
  2970.     doAskAbout( actor, io ) =
  2971.     {
  2972.         if ( io = policy )
  2973.         "\"Your policy perfectly fits your needs, according to my
  2974.         calculations,\" Lloyd says. \"I'm afraid it's much too
  2975.         complicated to go into in any detail right now, but you have
  2976.         my assurances that you won't be disappointed.\" ";
  2977.     else
  2978.         "\"I'm afraid I don't know much about that,\" Lloyd says
  2979.         apologetically. ";
  2980.     }
  2981.     actorDesc =
  2982.     {
  2983.         if ( self.offering )
  2984.         "Lloyd is here, offering you an insurance policy for only
  2985.         one dollar. ";
  2986.     else
  2987.         "Lloyd the Friendly Insurance Robot is here. ";
  2988.     }
  2989.     offering = true
  2990.     offermsg =
  2991.     [
  2992.         'Lloyd waits patiently for you to make up your mind about the
  2993.      insurance policy.'
  2994.     'Lloyd watches you expectantly, hoping you will buy the insurance
  2995.      policy.'
  2996.     'Lloyd shows you the insurance policy again. "Only a dollar," he
  2997.      says.'
  2998.     'Lloyd looks at you intently. "What can I do to make you buy this
  2999.      insurance policy right now?" he asks rhetorically.'
  3000.     'Lloyd reviews the policy to make sure it looks just right, and
  3001.      offers it to you again.'
  3002.     ]
  3003.     offerins =
  3004.     {
  3005.         if ( self.location = Me.location )
  3006.     {
  3007.         "\b";
  3008.         say(self.offermsg[rand( 5 )]);
  3009.     }
  3010.     }
  3011.     followmsg =
  3012.     [
  3013.         'Lloyd watches attentively to make sure you don\'t hurt yourself.'
  3014.     'Lloyd hums one of his favorite insurance songs.'
  3015.     'Lloyd gets out some actuarial tables and does some computations.'
  3016.     'Lloyd looks through his papers.'
  3017.     'Lloyd checks the area to make sure it\'s safe.'
  3018.     ]
  3019.     follow =
  3020.     {
  3021.         if ( Me.location = machinestorage ) return;
  3022.     
  3023.     "\b";
  3024.         if ( self.location <> Me.location )
  3025.     {
  3026.         if ( Me.location = railcar )
  3027.             "Lloyd hops into the railcar, showing remarkable agility
  3028.         for such a large mechanical device. ";
  3029.         else if ( self.location = railcar )
  3030.             "Lloyd hops out of the railcar. ";
  3031.         else if ( Me.location = pitTop and self.location = pitBottom )
  3032.             "Amazingly, Lloyd scrambles up the rope and joins you. ";
  3033.         else if ( Me.location = pitBottom and self.location = pitTop )
  3034.             "Lloyd descends smoothly down the rope and joins you. ";
  3035.         else if (( Me.location = tunnel7 and self.location = tunnel12 )
  3036.          or ( Me.location = tunnel12 and self.location = tunnel7 ))
  3037.             "Somehow, Lloyd manages to squeeze through the crawl. ";
  3038.         else if ( Me.location = quad )
  3039.             "Lloyd follows you. When he sees the apparent radioactive
  3040.         waste spill, he is quite alarmed. After a moment, though,
  3041.         he deduces that the spill is a staged part of the Ditch Day
  3042.         festivities, and he calms down. ";
  3043.         else if ( Me.location = storage )
  3044.             "Lloyd enters the storage room. Upon seeing the guard, he
  3045.             rolls over and starts giving his insurance pitch. After a
  3046.         moment, he notices the guard is unconscious. \"It's just as
  3047.         well,\" Lloyd confides; \"security work is awfully risky, and
  3048.         his rates would have been quite high.\" ";
  3049.         else
  3050.             "Lloyd follows you. ";
  3051.         
  3052.         self.moveInto( Me.location );
  3053.     }
  3054.     else
  3055.     {
  3056.         say(self.followmsg[rand( 5 )]);
  3057.     }
  3058.     }
  3059.     verIoGiveTo( actor ) = {}
  3060.     ioGiveTo( actor, do ) =
  3061.     {
  3062.         if ( do = dollar )
  3063.         self.doPay( actor );
  3064.     else if ( do = darbcard )
  3065.         "Lloyd looks at you apologetically. \"So sorry, I must insist
  3066.         on cash,\" he says. ";
  3067.     else
  3068.         "Lloyd doesn't appear interested. ";
  3069.     }
  3070.     verDoPay( actor ) = {}
  3071.     doPay( actor ) =
  3072.     {
  3073.         if ( not self.offering )
  3074.     {
  3075.         "Lloyd looks at you, confused. \"I've already sold you all
  3076.         the insurance you need!\" ";
  3077.     }
  3078.         else if ( dollar.isIn( actor ))
  3079.     {
  3080.         "Lloyd graciously accepts the payment, and hands you a copy
  3081.         of your policy. \"You might wonder how we keep costs so low,\"
  3082.         Lloyd says. \"It's simple: we're highly automated, which keeps
  3083.         labor costs low; I run the whole company, which keeps the
  3084.         bureaucratic overhead low; and, most importantly, I follow you
  3085.         everywhere you go for the duration of the policy, ensuring that
  3086.         you're paid on the spot should anything happen, which means we
  3087.         don't have to waste money investigating claims!\" ";
  3088.         
  3089.         unnotify( self, #offerins );
  3090.         notify( self, #follow, 0 );
  3091.         dollar.moveInto( nil );
  3092.         policy.moveInto( Me );
  3093.         self.offering := nil;
  3094.     }
  3095.     else
  3096.     {
  3097.         "You don't have any money with which to pay Lloyd. ";
  3098.     }
  3099.     }
  3100.     location = insOffice
  3101. ;
  3102.  
  3103. policy: readable
  3104.     sdesc = "insurance policy"
  3105.     adesc = "an insurance policy"
  3106.     iscrawlable = true
  3107.     noun = 'policy'
  3108.     adjective = 'insurance'
  3109.     location = lloyd
  3110.     ldesc =
  3111.     {
  3112.         "The insurance policy lists the payment schedule for hundreds
  3113.     of types of injuries; the list is far too lengthy to go into in any
  3114.     detail here, but rest assured, ";
  3115.     if ( lloyd.offering )
  3116.         "it looks like an excellent deal. ";
  3117.     else
  3118.         "you're highly satisified with what you
  3119.         got for your dollar. You feel extremely well protected. ";
  3120.     }
  3121. ;
  3122.  
  3123. machineshop: room
  3124.     sdesc = "Machine Shop"
  3125.     ldesc = "You are in the machine shop. It appears that this huge
  3126.      chamber was once used to build and maintain the equipment that
  3127.      was used to create the Great Undergraduate Excavation.  Though
  3128.      most of the equipment is gone now, one very large and strange
  3129.      machine dominates the center of the room.
  3130.      The exit is east, and a small passage leads north. "
  3131.     east = pitBottom
  3132.     out = pitBottom
  3133.     north = machinestorage
  3134. ;
  3135.  
  3136. machine: fixeditem
  3137.     sdesc = "machine"
  3138.     noun = 'machine'
  3139.     location = machineshop
  3140.     ldesc = "The machine is unlike anything you've seen before; it's not
  3141.      at all clear what its purpose is. The only feature that looks like it
  3142.      might do anything useful is a large red button labelled \"DANGER!\" "
  3143. ;
  3144.  
  3145. machinebutton: buttonitem
  3146.     location = machineshop
  3147.     sdesc = "red button"
  3148.     adjective = 'red'
  3149.     doPush( actor ) =
  3150.     {
  3151.         "As you push the button, the machine starts making horrible noises
  3152.     and flinging huge metal rods in all directions. Enormous clouds of
  3153.     smoke rise from the machine as it flails about. After a few minutes
  3154.     of this behavior, you think to step back from the machine.  You're
  3155.     not fast enough, though; before you can escape it, a stray metal
  3156.     bar flings itself against your thumb, creating a sensation not unlike
  3157.     intense pain. ";
  3158.     
  3159.         if ( lloyd.location = self.location )
  3160.     {
  3161.         "\n\t";
  3162.             if ( self.isscored )
  3163.             "Lloyd looks at you apologetically. \"I don't want to sound
  3164.         patronizing, but you knew it would do that. I'm afraid I can't
  3165.         accept a claim for that injury, as it was effectively
  3166.         self-inflicted.\" He looks at you sadly. \"I do sympathize,
  3167.         though. That must be quite painful,\" he understates. ";
  3168.         else
  3169.         {
  3170.             self.isscored := true;
  3171.         "Lloyd rolls over and looks at your thumb. \"That looks
  3172.         awful,\" he says as you jump about, holding your thumb.
  3173.         Lloyd produces a thick pile of paper and starts leafing
  3174.         through it. \"Temporary loss of use of one thumb... ah,
  3175.         yes, here it is. That injury pays five dollars.\" Lloyd puts
  3176.         away his papers and produces a crisp new five dollar bill,
  3177.         which you accept (with your other hand). ";
  3178.         money.moveInto( Me );
  3179.         }
  3180.     }
  3181.     }
  3182. ;
  3183.  
  3184. machinestorage: darkroom
  3185.     sdesc = "Storage Closet"
  3186.     ldesc = "You are in a small storage closet off the machine shop.
  3187.      The exit is south. "
  3188.     south = machineshop
  3189.     out = machineshop
  3190. ;
  3191.  
  3192. happygear: treasure
  3193.     location = machinestorage
  3194.     noun = 'gear'
  3195.     adjective = 'mr.' 'mr' 'happy' 'mister'
  3196.     sdesc = "Mr.\ Happy Gear"
  3197.     thedesc = "Mr.\ Happy Gear"
  3198.     adesc = "Mr.\ Happy Gear"
  3199.     ldesc = "It's an ordinary gear, about an inch in diameter; the only
  3200.      notable feature is that it has holes cut in such a manner that it
  3201.      looks like a happy face. "
  3202. ;
  3203.  
  3204. bank: room
  3205.     sdesc = "Bank"
  3206.     ldesc = "You're in what was once the Great Undergraduate Excavation's
  3207.      bank. It doesn't appear to get much use any more. The exit is north,
  3208.      and a small passage leads south. "
  3209.     north = pitBottom
  3210.     south = bankvault
  3211.     out = pitBottom
  3212. ;
  3213.  
  3214. bankvault: room
  3215.     sdesc = "Vault Room"
  3216.     ldesc = "The feature dominating this room is the bank's safe.
  3217.      The only exit is north. "
  3218.     north = bank
  3219.     out = bank
  3220. ;
  3221.  
  3222. banksafe: fixeditem, openable
  3223.     sdesc = "safe"
  3224.     noun = 'safe' 'door' 'vault'
  3225.     location = bankvault
  3226.     isopen = nil
  3227.     ldesc =
  3228.     {
  3229.         if ( self.isblasted )
  3230.     {
  3231.         "The safe looks as though it has suffered some sort of
  3232.         intense trauma lately; the door is just barely hanging on
  3233.         its hinges, leaving the contents of the safe quite exposed. ";
  3234.         pass ldesc;
  3235.     }
  3236.     else
  3237.     {
  3238.         "The safe is huge, like the type you might find in a bank.
  3239.         The only notable features are a huge metal door (quite closed),
  3240.         and a large slot labelled \"Night Deposit Slot.\" ";
  3241.     }
  3242.     }
  3243.     doOpen( actor ) =
  3244.     {
  3245.         if ( self.isblasted ) pass doOpen;
  3246.     else
  3247.         "You can't open such a secure safe without resorting
  3248.          to some sort of drastic action. ";
  3249.     }
  3250. ;
  3251.  
  3252. darbcard: treasure
  3253.     sdesc = "DarbCard"
  3254.     noun = 'darbcard' 'card'
  3255.     adjective = 'darb'
  3256.     location = banksafe
  3257. ;
  3258.  
  3259. bankslot: fixeditem, container
  3260.     sdesc = "night deposit slot"
  3261.     noun = 'slot'
  3262.     adjective = 'night' 'deposit'
  3263.     location = bankvault
  3264.     ldesc = "The slot is very large, big enough to put a large sack of
  3265.      money into. Unfortunately, you won't have much luck extracting anything
  3266.      from the slot, since it has been carefully constructed to allow items
  3267.      to enter, but not leave. "
  3268.     ioPutIn( actor, do ) =
  3269.     {
  3270.         "\^<< do.thedesc >> disappears into the deposit slot. ";
  3271.     do.moveInto( banksafe );
  3272.     }
  3273. ;
  3274.  
  3275. cave: room
  3276.     sdesc = "Tunnel"
  3277.     ldesc = "You're in a north-south tunnel. The tunnel slopes steeply
  3278.      downward to the north. "
  3279.     north = railway1
  3280.     down = railway1
  3281.     south = pitBottom
  3282.     up = pitBottom
  3283. ;
  3284.  
  3285. railway1: room
  3286.     sdesc = "Subway Station"
  3287.     ldesc = "You're in a very large musty chamber deep underground. In the
  3288.      center of the room is a small rail car. Strangely, the car is sitting on
  3289.      the floor; there are no rails under the car, or, indeed, in the station
  3290.      at all. You look around, and notice about three meters up the east wall
  3291.      is a round tunnel. A passage leads south. "
  3292.     south = cave
  3293.     destination = railway2
  3294.     tunneltime = 3
  3295.     east =
  3296.     {
  3297.         "The tunnel is too high up the wall. You won't be able to enter
  3298.     it without benefit of the railcar. ";
  3299.         return( nil );
  3300.     }
  3301. ;
  3302.  
  3303. class rtunnel: fixeditem
  3304.     sdesc = "tunnel"
  3305.     noun = 'tunnel'
  3306.     verDoEnter( actor ) = {}
  3307.     doEnter( actor ) =
  3308.     {
  3309.         railway1.east;
  3310.     }
  3311. ;
  3312.  
  3313. rtunnel1: rtunnel
  3314.     location = railway1
  3315. ;
  3316.  
  3317. rtunnel2: rtunnel
  3318.     location = railway2
  3319. ;
  3320.  
  3321. railway2: room
  3322.     sdesc = "Subway Station"
  3323.     ldesc = "You're in a subway station. About three meters up the west
  3324.      wall is a tunnel; a passage (at ground level) leads south. A railcar
  3325.      is sitting on the floor in the center of the room. "
  3326.     south = computercenter
  3327.     destination = railway1
  3328.     tunneltime = 3
  3329.     west =
  3330.     {
  3331.         "The tunnel is too high up the wall. You won't be able to enter
  3332.     it without benefit of the railcar. ";
  3333.         return( nil );
  3334.     }
  3335. ;
  3336.  
  3337. computercenter: room
  3338.     sdesc = "Computer Center"
  3339.     ldesc = "You're in a computer room. Unfortunately, all the equipment
  3340.      here is hopelessly out of date and doesn't interest you in the least.
  3341.      The exit is north. "
  3342.     north = railway2
  3343. ;
  3344.  
  3345. compequip: decoration
  3346.     sdesc = "computer equipment"
  3347.     noun = 'equipment'
  3348.     adjective = 'computer'
  3349.     location = computercenter
  3350.     ldesc = "The equipment is all very outdated. It's not the least bit
  3351.      interesting. "
  3352. ;
  3353.  
  3354. randombook: treasure, readable
  3355.     sdesc = "book"
  3356.     ldesc = "The book is entitled \"A Million Random Digits.\" In flipping
  3357.      through the book, you find that it is, in fact, a million random digits,
  3358.      nicely tabulated and individually numbered from 0 to 999,999 (computer
  3359.      people always start numbering at 0). "
  3360.     noun = 'book' 'digits'
  3361.     adjective = 'million' 'random' 'digits' 'numbers'
  3362.     location = computercenter
  3363. ;
  3364.  
  3365. railtunnel: room
  3366.     sdesc = "Tunnel"
  3367.     ldesc = "The tunnel is rather non-descript. "
  3368. ;
  3369.  
  3370. railcar: vehicle, fixeditem, container
  3371.     location = railway1
  3372.     isdroploc = true        // stuff dropped while on board ends up in railcar
  3373.     sdesc = "rail car"
  3374.     noun = 'car' 'railcar'
  3375.     adjective = 'rail'
  3376.     ldesc =
  3377.     {
  3378.         "This is a small rail car, big enough for a couple of people.
  3379.          It has a small control panel, which consists of a green button,
  3380.      a gauge, and a small hole labelled \"Coolant.\" ";
  3381.      if ( funnel.location = railhole )
  3382.         "The hole seems to contain a funnel. ";
  3383.      railmeter.ldesc;
  3384.     }
  3385.     travel =
  3386.     {
  3387.         if ( self.location <> railtunnel )
  3388.     {
  3389.         "\bThe car rises to about three meters off the floor. It then
  3390.         starts to accelerate toward the tunnel, and plunges into the
  3391.         tunnel with a rush of air. ";
  3392.         self.destination := self.location.destination;
  3393.         self.tunneltime := self.location.tunneltime;
  3394.         self.moveInto( railtunnel );
  3395.     }
  3396.     else if ( self.tunneltime > 0 )
  3397.     {
  3398.         "\bThe car races down the tunnel at terrifying speed. ";
  3399.         self.tunneltime := self.tunneltime - 1;
  3400.     }
  3401.     else
  3402.     {
  3403.         "\bThe car starts to decelerate sharply. After a few more seconds,
  3404.         it emerges into a station and glides to a halt. It slowly
  3405.         descends to the ground; once settled, the hum of its engine
  3406.         gradually disappears. ";
  3407.         self.isActive := nil;
  3408.         self.moveInto( self.destination );
  3409.         unnotify( self, #travel );
  3410.     }
  3411.     }
  3412.     checkunboard =
  3413.     {
  3414.         if ( self.isActive )
  3415.     {
  3416.         "Please wait until the railcar has come to a complete and
  3417.         final stop, and the captain has turned off the \"Fasten Seat
  3418.         Belt\" sign. (Actually, I made up the part about the \"Fasten
  3419.         Seat Belt\" sign, but you'll have to wait until the car
  3420.         has stopped nonetheless.) ";
  3421.         return( nil );
  3422.     }
  3423.     else return( true );
  3424.     }
  3425.     out =
  3426.     {
  3427.         if ( self.checkunboard ) pass out;
  3428.     else return( nil );
  3429.     }
  3430.     doUnboard( actor ) =
  3431.     {
  3432.         if ( self.checkunboard ) pass doUnboard;
  3433.     }
  3434. ;
  3435.  
  3436. railmeter: fixeditem
  3437.     location = railcar
  3438.     sdesc = "gauge"
  3439.     noun = 'gauge' 'meter'
  3440.     ldesc =
  3441.     {
  3442.         "The gauge is not labelled with any units you recognize, but
  3443.      the arc is divided into regions colored green, yellow, and red. The
  3444.      needle is currently in the ";
  3445.         if ( railcar.iscooled ) "green"; else "red";
  3446.     " section of the scale. ";
  3447.     }
  3448. ;
  3449.  
  3450. railhole: fixeditem, container
  3451.     location = railcar
  3452.     sdesc = "hole"
  3453.     noun = 'hole'
  3454.     adjective = 'coolant'
  3455.     ldesc =
  3456.     {
  3457.         if ( funnel.location = self )
  3458.         "A funnel is in the hole. ";
  3459.         else if ( railcar.iscooled )
  3460.         "Wisps of water vapor rise from the hole. ";
  3461.     else
  3462.         "The hole is labelled \"Coolant.\" It's about an inch
  3463.         or so in diameter. ";
  3464.     }
  3465.     verIoPourIn( actor ) = {}
  3466.     ioPourIn( actor, do ) = { self.ioPutIn( actor, do ); }
  3467.     ioPutIn( actor, do ) =
  3468.     {
  3469.         if ( do = funnel )
  3470.     {
  3471.         "A perfect fit! ";
  3472.         funnel.moveInto( self );
  3473.     }
  3474.     else if ( do = ln2 )
  3475.     {
  3476.         if ( funnel.location = self )
  3477.         {
  3478.             if ( railcar.iscooled )
  3479.             "It's already full of liquid nitrogen! ";
  3480.         else
  3481.         {
  3482.             "You carefully pour the liquid nitrogen into the
  3483.             funnel.  It doesn't take very much before the tank
  3484.             is full. ";
  3485.             railcar.iscooled := true;
  3486.         }
  3487.         }
  3488.         else
  3489.         {
  3490.             "The hole is too small; most if not all of the liquid
  3491.         nitrogen you pour spills all around, rather than into
  3492.         the hole. ";
  3493.         }
  3494.     }
  3495.     else
  3496.     {
  3497.         "It won't fit in the hole. ";
  3498.     }
  3499.     }
  3500. ;
  3501.  
  3502. railbutton: buttonitem
  3503.     location = railcar
  3504.     sdesc = "green button"
  3505.     adjective = 'green'
  3506.     doPush( actor ) =
  3507.     {
  3508.         if ( Me.location <> railcar )
  3509.     {
  3510.         "Get in the railcar first. ";
  3511.     }
  3512.     else if ( railcar.isbroken )
  3513.     {
  3514.         "Nothing happens. ";
  3515.     }
  3516.     else if ( railcar.isActive )
  3517.     {
  3518.         "Nothing happens. Perhaps this is because you have
  3519.         already pushed the button quite recently. ";
  3520.     }
  3521.         else if ( railcar.iscooled )
  3522.     {
  3523.         "A low-frequency hum sounds from within the railcar. After
  3524.         a few moments, it starts to levitate off the track. ";
  3525.         notify( railcar, #travel, 0 );
  3526.         railcar.isActive := true;
  3527.     }
  3528.     else
  3529.     {
  3530.         "A low-frequency hum sounds from within the railcar. It grows
  3531.         in strength, and soon starts to vibrate the whole car. You smell
  3532.         the familiar odor of burning electronic components. Suddenly,
  3533.         a bright light flashes underneath the railcar, a cloud of thick
  3534.         black smoke rises, and the humming stops. It appears you have
  3535.         toasted the railcar. ";
  3536.         railcar.isbroken := true;
  3537.     }
  3538.     }
  3539. ;
  3540.  
  3541. biohall1: room
  3542.     sdesc = "Hall"
  3543.     ldesc = "You are in an east-west hallway. A passage labelled \"Bio Lab\"
  3544.      leads south. "
  3545.     west = pitBottom
  3546.     east = biohall2
  3547.     south = biolab
  3548. ;
  3549.  
  3550. biolab: room
  3551.     sdesc = "Bio Lab"
  3552.     ldesc =
  3553.     {
  3554.         "You are in the Biology Lab. All sorts of strange equipment is
  3555.     scattered around the room. A lab bench is in the center of the room,
  3556.     and on one wall is a cabinet (which is ";
  3557.     if ( biocabinet.isopen ) "open"; else "closed";
  3558.     "). A passage leads north. ";
  3559.     }
  3560.     north = biohall1
  3561. ;
  3562.  
  3563. bioEquipment: decoration
  3564.     sdesc = "strange equipment"
  3565.     noun = 'equipment'
  3566.     adjective = 'strange'
  3567.     location = biolab
  3568.     ldesc = "The equipment is entirely unfamiliar to you. "
  3569. ;
  3570.  
  3571. biobench: fixeditem, surface
  3572.     noun = 'bench'
  3573.     adjective = 'lab'
  3574.     sdesc = "lab bench"
  3575.     location = biolab
  3576.     ldesc =
  3577.     {
  3578.         "The bench is topped with one of those strange black rubber surfaces
  3579.     that seemingly all scientific lab benches have. ";
  3580.     pass ldesc;
  3581.     }
  3582. ;
  3583.  
  3584. funnel: container
  3585.     sdesc = "funnel"
  3586.     noun = 'funnel'
  3587.     location = biobench
  3588.     ioPutIn( actor, do ) =
  3589.     {
  3590.         if ( do = ln2 )
  3591.     {
  3592.         if ( self.location = railhole or self.location = bottle )
  3593.             self.location.ioPutIn( actor, do );
  3594.         else
  3595.             "The liquid nitrogen pours through the funnel, lands
  3596.         nowhere in particular, and evaporates. ";
  3597.     }
  3598.     else
  3599.     {
  3600.         "It wouldn't accomplish anything to put ";
  3601.         do.thedesc; " into the funnel. ";
  3602.     }
  3603.     }
  3604.     ldesc =
  3605.     {
  3606.         if ( self.location = bottle or self.location = railhole )
  3607.     {
  3608.         "The funnel is stuck into "; self.location.adesc; ". ";
  3609.     }
  3610.     else
  3611.         "It's a normal white plastic funnel, about six inches
  3612.         across at its wide end and about half an inch at its
  3613.         narrow end. ";
  3614.     }
  3615.     verIoPourIn( actor ) = {}
  3616.     ioPourIn( actor, do ) = { self.ioPutIn( actor, do ); }
  3617. ;
  3618.  
  3619. biohall2: room
  3620.     sdesc = "Hall"
  3621.     ldesc =
  3622.     {
  3623.         "You are at the east end of an east-west hallway. A doorway
  3624.      leads east. ";
  3625.     if ( not self.isseen )
  3626.     {
  3627.         notify( biocreature, #menace, 0 );
  3628.     }
  3629.     }
  3630.     west = biohall1
  3631.     east =
  3632.     {
  3633.         if ( biocreature.location = self )
  3634.     {
  3635.         if ( slime.location = nil )
  3636.         {
  3637.             "The creature grabs you and pushes you back, depositing
  3638.         a huge glob of slime on you in the process. ";
  3639.         slime.moveInto( Me );
  3640.         slime.isworn := true;
  3641.         }
  3642.             else "The creature won't let you pass. ";
  3643.         return( nil );
  3644.     }
  3645.     else return( biooffice );
  3646.     }
  3647. ;
  3648.  
  3649. slime: clothingItem
  3650.     noun = 'glob' 'slime'
  3651.     sdesc = "glob of slime"
  3652.     doWear( actor ) =
  3653.     {
  3654.         "No, thank you. ";
  3655.     }
  3656. ;
  3657.  
  3658. biocreature: Actor
  3659.     location = biohall2
  3660.     sdesc = "creature"
  3661.     noun = 'creature'
  3662.     ldesc = "It looks like the result of a biological experiment that
  3663.       failed (or succeeded, depending on who performed the experiment). "
  3664.     actorDesc = "An enormous creature is blocking the hallway to the east.
  3665.       He (please don't press for details as to how you know, but \"he\"
  3666.       is the appropriate pronoun here) appears to be part human, but
  3667.       exactly what part is not clear. The creature's leathery skin is
  3668.       a bright green, and is largely covered with a thick transluscent
  3669.       slime. "
  3670.     menaceMessage =
  3671.     [
  3672.         'The creature roars a huge roar in your general direction.'
  3673.     'The creature menaces you.'
  3674.     'In a tender moment, the creature produces a magazine and opens up
  3675.      the centerfold. He looks longingly at the picture. After a few
  3676.      moments, he notices you again, and puts away the magazine; as he\'s
  3677.      putting it away, you see that it\'s a copy of "Playmutant."'
  3678.     'The creature looks at you warily.'
  3679.     'The creature growls at you, showing his enormous pointy fangs.'
  3680.     ]
  3681.     menace =
  3682.     {
  3683.         if ( self.location = Me.location )
  3684.     {
  3685.             "\b";
  3686.             say( self.menaceMessage[rand( 5 )]);
  3687.     }
  3688.     }
  3689. ;
  3690.  
  3691. biooffice: room
  3692.     sdesc = "Bio Office"
  3693.     ldesc = "You are in the Biology Office. A large desk dominates the
  3694.      room. The exit is west. "
  3695.     west = biohall2
  3696. ;
  3697.  
  3698. biodesk: fixeditem, surface
  3699.     noun = 'desk'
  3700.     adjective = 'large'
  3701.     location = biooffice
  3702.     sdesc = "desk"
  3703. ;
  3704.  
  3705. biocabinet: openable, fixeditem
  3706.     noun = 'cabinet'
  3707.     location = biolab
  3708.     sdesc = "cabinet"
  3709.     isopen = nil
  3710. ;
  3711.  
  3712. class chemitem: item
  3713.     location = biocabinet
  3714.     noun = 'chemical'
  3715.     plural = 'chemicals'
  3716.     adesc = { "some "; self.sdesc; }
  3717.     ldesc =
  3718.     {
  3719.         "It's a small lump of goo. The only identification is
  3720.          a label reading \""; self.sdesc; ".\" ";
  3721.     }
  3722. ;
  3723.     
  3724. gfxq3: chemitem
  3725.     noun = 'GF-XQ3'
  3726.     sdesc = "GF-XQ3"
  3727. ;
  3728.  
  3729. gfxq9: chemitem
  3730.     noun = 'GF-XQ9'
  3731.     sdesc = "GF-XQ9"
  3732. ;
  3733.  
  3734. polyred: chemitem
  3735.     noun = 'red'
  3736.     adjective = 'poly'
  3737.     sdesc = "Poly Red"
  3738. ;
  3739.  
  3740. polyblue: chemitem
  3741.     noun = 'blue'
  3742.     adjective = 'poly'
  3743.     sdesc = "Poly Blue"
  3744. ;
  3745.  
  3746. compoundT99: chemitem
  3747.     noun = 't99'
  3748.     adjective = 'compound'
  3749.     sdesc = "Compound T99"
  3750. ;
  3751.  
  3752. compoundT30: chemitem
  3753.     noun = 't30'
  3754.     adjective = 'compound'
  3755.     sdesc = "Compound T30"
  3756. ;
  3757.  
  3758. clonemaster: container
  3759.     noun = 'master' 'clonemaster'
  3760.     adjective = 'clone'
  3761.     location = biobench
  3762.     sdesc = "CloneMaster"
  3763.     ldesc =
  3764.     {
  3765.         "The CloneMaster is a simple machine. It consists of a button
  3766.     marked \"Clone,\" and a small receptacle. ";
  3767.      clonerecept.ldesc;
  3768.     }
  3769.     ioPutIn( actor, do ) = { clonerecept.ioPutIn( actor, do ); }
  3770.     verDoTakeOut( actor, io ) = { clonerecept.verIoTakeOut( actor, io ); }
  3771. ;
  3772.  
  3773. clonerecept: fixeditem, container
  3774.     sdesc = "receptacle"
  3775.     noun = 'receptacle'
  3776.     location = clonemaster
  3777.     ldesc =
  3778.     {
  3779.         "The receptacle is somewhat like that of a kitchen blender. ";
  3780.         pass ldesc;
  3781.     }
  3782. ;
  3783.  
  3784. clonebutton: buttonitem
  3785.     sdesc = "clone button"
  3786.     adjective = 'clone'
  3787.     doPush( actor ) =
  3788.     {
  3789.         if ( slime.location = clonerecept )
  3790.     {
  3791.         "The CloneMaster clicks and whirs for several seconds. ";
  3792.         if ( gfxq3.location = clonerecept and
  3793.          polyblue.location = clonerecept and
  3794.          compoundT99.location = clonerecept
  3795.          and length( clonerecept.contents ) = 4 )
  3796.         {
  3797.             "A monstrous female version (again, don't ask how you know
  3798.          it's female) leaps from the tiny machine";
  3799.             if ( Me.location = biocreature.location )
  3800.         {
  3801.             ". The two monsters look at each other with passion in
  3802.             their mutant eyes. They run to each other with open arms,
  3803.             seemingly in slow motion. They embrace, engage in some
  3804.             mushy behavior, and then run away together to elope. ";
  3805.             biocreature.moveInto( nil );
  3806.             unnotify( biocreature, #menace );
  3807.         }
  3808.         else
  3809.             ", looks around, and, seeing nothing of
  3810.             interest, runs off. ";
  3811.         }
  3812.         else
  3813.             "An exact duplicate of the monstrous creature whose slime
  3814.         you placed in the CloneMaster leaps forth from the tiny
  3815.         machine. He looks at you menacingly for a moment, then
  3816.         runs off into the distance, never to be seen again. ";
  3817.         
  3818.         slime.moveInto( nil );
  3819.     }
  3820.     else "Nothing happens. ";
  3821.     }
  3822.     location = clonemaster
  3823. ;
  3824.  
  3825. omega: treasure
  3826.     sdesc = "Great Seal of the Omega"
  3827.     noun = 'seal' 'omega' 'stamp'
  3828.     adjective = 'great' 'rubber'
  3829.     location = biodesk
  3830.     ldesc = "The Great Seal is a large rubber stamp, about an inch and
  3831.      a half square. The stamp consists of a large circle that is filled by a
  3832.      giant capital omega, under which is the word \"Approved.\" Around the
  3833.      outside of the circle, the words \"The Great Seal of the Omega\" are
  3834.      inscribed. "
  3835. ;
  3836.  
  3837. rope2: fixeditem
  3838.     sdesc = "rope"
  3839.     noun = 'rope'
  3840.     location = pitBottom
  3841.     ldesc = "The rope extends from the opening in the ceiling high above. "
  3842.     verDoTake( actor ) =
  3843.     {
  3844.         "The rope seems to be tied to something from above (which would
  3845.     probably explain why it's extending up to the ceiling in the
  3846.     first place, you deduce in a rare moment of lucid thinking). ";
  3847.     }
  3848.     verDoClimbup( actor ) = {}
  3849.     doClimbup( actor ) = { self.doClimb( actor ); }
  3850.     verDoClimb( actor ) = {}
  3851.     doClimb( actor ) =
  3852.     {
  3853.         "It's a long climb, but you somehow manage it.\b";
  3854.     Me.travelTo( pitTop );
  3855.     }
  3856. ;
  3857.