home *** CD-ROM | disk | FTP | other *** search
/ Perseus / PERSEUS.iso / spiele / tads12.exe / ADV.T next >
Text File  |  1991-09-22  |  100KB  |  3,499 lines

  1. /* Copyright (c) 1988, 1991 by Michael J. Roberts.  All Rights Reserved. */
  2. /*
  3.    adv.t  - standard adventure definitions for TADS games
  4.    Version 1.2
  5.  
  6.    This file is part of TADS:  The Text Adventure Development System.
  7.    Please see the file LICENSE.DOC (which should be part of the TADS
  8.    distribution) for information on using this file, and for information
  9.    on reaching High Energy Software, the developers of TADS.
  10.  
  11.    This file defines the basic classes and functions used by most TADS
  12.    adventure games.  It is generally #include'd at the start of each game
  13.    source file.
  14. */
  15.  
  16. /*
  17.  *   Define compound prepositions.  Since prepositions that appear in
  18.  *   parsed sentences must be single words, we must define any logical
  19.  *   prepositions that consist of two or more words here.  Note that
  20.  *   only two words can be pasted together at once; to paste more, use
  21.  *   a second step.  For example,  'out from under' must be defined in
  22.  *   two steps:
  23.  *
  24.  *     compoundWord 'out' 'from' 'outfrom';
  25.  *     compoundWord 'outfrom' 'under' 'outfromunder';
  26.  *
  27.  *   Listed below are the compound prepositions that were built in to
  28.  *   version 1.0 of the TADS run-time.
  29.  */
  30. compoundWord 'on' 'to' 'onto';           /* on to --> onto */
  31. compoundWord 'in' 'to' 'into';           /* in to --> into */
  32. compoundWord 'in' 'between' 'inbetween'; /* and so forth */
  33. compoundWord 'down' 'in' 'downin';
  34. compoundWord 'down' 'on' 'downon';
  35. compoundWord 'up' 'on' 'upon';
  36. compoundWord 'out' 'of' 'outof';
  37. compoundWord 'off' 'of' 'offof';
  38.  
  39. /*
  40.  *   Format strings:  these associate keywords with properties.  When
  41.  *   a keyword appears in output between percent signs (%), the matching
  42.  *   property of the current command's actor is evaluated and substituted
  43.  *   for the keyword (and the percent signs).  For example, if you have:
  44.  *
  45.  *      formatstring 'you' fmtYou;
  46.  *
  47.  *   and the command being processed is:
  48.  *
  49.  *      fred, pick up the paper
  50.  *
  51.  *   and the "fred" actor has fmtYou = "he", and this string is output:
  52.  *
  53.  *      "%You% can't see that here."
  54.  *
  55.  *   Then the actual output is:  "He can't see that here."
  56.  *
  57.  *   The format strings are chosen to look like normal output (minus the
  58.  *   percent signs, of course) when the actor is Me.
  59.  */
  60. formatstring 'you' fmtYou;
  61. formatstring 'your' fmtYour;
  62. formatstring 'you\'re' fmtYoure;
  63. formatstring 'youm' fmtYoum;
  64. formatstring 'you\'ve' fmtYouve;
  65. formatstring 's' fmtS;
  66. formatstring 'es' fmtEs;
  67. formatstring 'have' fmtHave;
  68. formatstring 'do' fmtDo;
  69. formatstring 'are' fmtAre;
  70.  
  71. /*
  72.  *   Forward-declare functions.  This is not required in most cases,
  73.  *   but it doesn't hurt.  Providing these forward declarations ensures
  74.  *   that the compiler knows that we want these symbols to refer to
  75.  *   functions rather than objects.
  76.  */
  77. checkDoor: function;
  78. checkReach: function;
  79. itemcnt: function;
  80. listcont: function;
  81. listcontcont: function;
  82. turncount: function;
  83. addweight: function;
  84. addbulk: function;
  85. incscore: function;
  86. darkTravel: function;
  87. scoreRank: function;
  88. terminate: function;
  89. die: function;
  90. init: function;
  91. pardon: function;
  92. preinit: function;
  93. sleepDaemon: function;
  94. eatDaemon: function;
  95. goToSleep: function;
  96. initSearch: function;
  97.  
  98. /*
  99.  *   checkDoor:  if the door d is open, this function silently returns
  100.  *   the room r.  Otherwise, print a message ("The door is closed.") and
  101.  *   return nil.
  102.  */
  103. checkDoor: function( d, r )
  104. {
  105.     if ( d.isopen ) return( r );
  106.     else
  107.     {
  108.         setit( d );
  109.     caps(); d.thedesc; " is closed. ";
  110.     return( nil );
  111.     }
  112. }
  113.  
  114. /*
  115.  *   checkReach:  determines whether the object obj can be reached by
  116.  *   actor in location loc, using the verb v.  This routine returns true
  117.  *   if obj is a special object (numObj or strObj), if obj is in actor's
  118.  *   inventory or actor's location, or if it's in the 'reachable' list
  119.  *   for loc.
  120.  */
  121. checkReach: function( loc, actor, v, obj )
  122. {
  123.     if ( obj=numObj or obj=strObj ) return;
  124.     if ( not ( actor.isCarrying( obj ) or obj.isIn( actor.location )))
  125.     {
  126.         if (find( loc.reachable, obj ) <> nil ) return;
  127.         "%You% can't reach "; obj.thedesc; " from "; loc.thedesc; ". ";
  128.         exit;
  129.     }
  130. }
  131.  
  132. /*
  133.  *  itemcnt: function( list )
  134.  *
  135.  *  Returns a count of the "listable" objects in list.  An
  136.  *  object is listable (that is, it shows up in a room's description)
  137.  *  if its isListed property is true.  This function is
  138.  *  useful for determining how many objects (if any) will be listed
  139.  *  in a room's description.
  140. */
  141. itemcnt: function( list )
  142. {
  143.     local cnt, tot, i;
  144.     tot := length( list );
  145.     cnt := 0;
  146.     i := 1;
  147.     while ( i <= tot )
  148.     {
  149.         if ( list[i].isListed ) cnt := cnt+1;
  150.         i := i+1;
  151.     }
  152.     return( cnt );
  153. }
  154.  
  155. /*
  156.  *  listcont: function( obj )
  157.  *
  158.  *  This function displays the contents of an object, separated by
  159.  *  commas.  The thedesc properties of the contents are used.
  160.  *  It is up to the caller to provide the introduction to the list
  161.  *  (usually something to the effect of "The box contains" is
  162.  *  displayed before calling listcont) and finishing the
  163.  *  sentence (usually by displaying a period).  An object is listed
  164.  *  only if its isListed property is true.
  165. */
  166. listcont: function( obj )
  167. {
  168.     local i, count, tot, list, cur, disptot;
  169.     count := 0;
  170.     list := obj.contents;
  171.     tot := length( list );
  172.     disptot := itemcnt( list );
  173.     i := 1;
  174.     while ( i <= tot )
  175.     {
  176.         cur := list[i];
  177.         if ( cur.isListed )
  178.         {
  179.             if ( count > 0 )
  180.             {
  181.                 if ( count+1 < disptot )
  182.                     ", ";
  183.                 else if (count = 1)
  184.                     " and ";
  185.                 else
  186.                     ", and ";
  187.             }
  188.             count := count + 1;
  189.             cur.adesc;               // list this object
  190.             if ( cur.isworn ) " (being worn)";
  191.             else if ( cur.islamp and cur.islit ) " (providing light)";
  192.         }
  193.         i := i + 1;
  194.     }
  195. }
  196.  
  197. /*
  198.  *   showcontcont:  list the contents of the object, plus the contents of
  199.  *   an fixeditem's contained by the object.  A complete sentence is shown.
  200.  *   This is an internal routine used by listcontcont and listfixedcontcont.
  201.  */
  202. showcontcont: function( obj )
  203. {
  204.     if (itemcnt( obj.contents ))
  205.     {
  206.         if ( obj.issurface and not obj.isqsurface )
  207.         {
  208.             "Sitting on "; obj.thedesc;" is "; listcont( obj );
  209.             ". ";
  210.         }
  211.         else if ( obj.contentsVisible and not obj.isqcontainer )
  212.         {
  213.             caps();
  214.             obj.thedesc; " seems to contain ";
  215.             listcont( obj );
  216.             ". ";
  217.         }
  218.     }
  219.     if ( obj.contentsVisible and not obj.isqcontainer )
  220.         listfixedcontcont( obj );
  221. }
  222.  
  223. /*
  224.  *  listfixedcontcont: function( obj )
  225.  *
  226.  *  List the contents of the contents of any fixeditem objects
  227.  *  in the contents list of the object obj.  This routine
  228.  *  makes sure that all objects that can be taken are listed somewhere
  229.  *  in a room's description.  This routine recurses down the contents
  230.  *  tree, following each branch until either something has been listed
  231.  *  or the branch ends without anything being listable.  This routine
  232.  *  displays a complete sentence, so no introductory or closing text
  233.  *  is needed.
  234. */
  235. listfixedcontcont: function( obj )
  236. {
  237.     local list, i, tot, thisobj;
  238.  
  239.     list := obj.contents;
  240.     tot := length( list );
  241.     i := 1;
  242.     while ( i <= tot )
  243.     {
  244.         thisobj := list[i];
  245.         if ( thisobj.isfixed and thisobj.contentsVisible and
  246.       not thisobj.isqcontainer )
  247.             showcontcont( thisobj );
  248.     i := i + 1;
  249.     }
  250. }
  251.  
  252. /*
  253.  *  listcontcont: function( obj )
  254.  *
  255.  *  This function lists the contents of the contents of an object.
  256.  *  It displays full sentences, so no introductory or closing text
  257.  *  is required.  Any item in the contents list of the object
  258.  *  obj whose contentsVisible property is true has
  259.  *  its contents listed.  An Object whose isqcontainer or
  260.  *  isqsurface property is true will not have its
  261.  *  contents listed.
  262. */
  263. listcontcont: function( obj )
  264. {
  265.     local list, i, tot;
  266.     list := obj.contents;
  267.     tot := length( list );
  268.     i := 1;
  269.     while ( i <= tot )
  270.     {
  271.         showcontcont( list[i] );
  272.     i := i + 1;
  273.     }
  274. }
  275.  
  276. /*
  277.  *  turncount: function( parm )
  278.  *
  279.  *  This function can be used as a daemon (normally set up in the init
  280.  *  function) to update the turn counter after each turn.  This routine
  281.  *  increments global.turnsofar, and then calls setscore to
  282.  *  update the status line with the new turn count.
  283. */
  284. turncount: function( parm )
  285. {
  286.     incturn();
  287.     global.turnsofar := global.turnsofar + 1;
  288.     setscore( global.score, global.turnsofar );
  289. }
  290.  
  291. /*
  292.  *  addweight: function( list )
  293.  *
  294.  *  Adds the weights of the objects in list and returns the sum.
  295.  *  The weight of an object is given by its weight property.  This
  296.  *  routine includes the weights of all of the contents of each object,
  297.  *  and the weights of their contents, and so forth.
  298. */
  299. addweight: function( l )
  300. {
  301.     local tot, i, c, totweight;
  302.  
  303.     tot := length( l );
  304.     i := 1;
  305.     totweight := 0;
  306.     while ( i <= tot )
  307.     {
  308.         c := l[i];
  309.         totweight := totweight + c.weight;
  310.         if (length( c.contents ))
  311.             totweight := totweight + addweight( c.contents );
  312.         i := i + 1;
  313.     }
  314.     return( totweight );
  315. }
  316.  
  317. /*
  318.  *  addbulk: function( list )
  319.  *
  320.  *  This function returns the sum of the bulks (given by the bulk
  321.  *  property) of each object in list.  The value returned includes
  322.  *  only the bulk of each object in the list, and not of the contents
  323.  *  of the objects, as it is assumed that an object does not change in
  324.  *  size when something is put inside it.  You can easily change this
  325.  *  assumption for special objects (such as a bag that stretches as
  326.  *  things are put inside) by writing an appropriate bulk method
  327.  *  for that object.
  328. */
  329. addbulk: function( list )
  330. {
  331.     local i, tot, totbulk, rem, cur;
  332.  
  333.     tot := length( list );
  334.     i := 1;
  335.     totbulk := 0;
  336.     while( i <= tot )
  337.     {
  338.         cur := list[i];
  339.         if ( not cur.isworn )
  340.             totbulk := totbulk + cur.bulk;
  341.         i := i + 1;
  342.     }
  343.     return( totbulk );
  344. }
  345.  
  346. /*
  347.  *  incscore: function( amount )
  348.  *
  349.  *  Adds amount to the total score, and updates the status line
  350.  *  to reflect the new score.  The total score is kept in global.score.
  351.  *  Always use this routine rather than changing global.score
  352.  *  directly, since this routine ensures that the status line is
  353.  *  updated with the new value.
  354. */
  355. incscore: function( amount )
  356. {
  357.     global.score := global.score + amount;
  358.     setscore( global.score, global.turnsofar );
  359. }
  360.  
  361. /*
  362.  *  initSearch: function
  363.  *
  364.  *  Initializes the containers of objects with a searchLoc, underLoc,
  365.  *  and behindLoc by setting up searchCont, underCont, and
  366.  *  behindCont lists, respectively.  You should call this function once in
  367.  *  your preinit (or init, if you prefer) function to ensure that
  368.  *  the underable, behindable, and searchable objects are set up correctly.
  369. */
  370. initSearch: function
  371. {
  372.     local o;
  373.     
  374.     o := firstobj();
  375.     while (o <> nil)
  376.     {
  377.     if (o.searchLoc)
  378.         o.searchLoc.searchCont := o.searchLoc.searchCont + o;
  379.     else if (o.underLoc)
  380.         o.underLoc.underCont := o.underLoc.underCont + o;
  381.     else if (o.behindLoc)
  382.         o.behindLoc.behindCont := o.behindLoc.behindCont + o;
  383.     o := nextobj(o);
  384.     }
  385. }
  386.  
  387. /*
  388.  *  nestedroom: room
  389.  *
  390.  *  A special kind of room that is inside another room; chairs and
  391.  *  some types of vehicles, such as inflatable rafts, fall into this
  392.  *  category.  Note that a room can be within another room without
  393.  *  being a nestedroom, simply by setting its location property
  394.  *  to another room.  The nestedroom is different from an ordinary
  395.  *  room, though, in that it's an "open" room; that is, when inside it,
  396.  *  the actor is still really inside the enclosing room for purposes of
  397.  *  descriptions.  Hence, the player sees "Laboratory, in the chair."
  398.  *  In addition, a nestedroom is an object in its own right,
  399.  *  visible to the player; for example, a chair is an object in a
  400.  *  room in addition to being a room itself.
  401. */
  402. nestedroom: room
  403.     islit =
  404.     {
  405.         if ( self.location ) return( self.location.islit );
  406.         return( nil );
  407.     }
  408.     statusLine =
  409.     {
  410.         self.location.sdesc; ", in "; self.thedesc; "\n\t";
  411.     }
  412.     lookAround( verbosity ) =
  413.     {
  414.         self.statusLine;
  415.     self.location.nrmLkAround( verbosity );
  416.     }
  417.     roomDrop( obj ) =
  418.     {
  419.         if ( self.location = nil or self.isdroploc ) pass roomDrop;
  420.     else self.location.roomDrop( obj );
  421.     }
  422. ;
  423.  
  424. /*
  425.  *  chairitem: fixeditem, nestedroom, surface
  426.  *
  427.  *  Acts like a chair:  actors can sit on the object.  While sitting
  428.  *  on the object, an actor can't go anywhere until standing up, and
  429.  *  can only reach objects that are on the chair and in the chair's
  430.  *  reachable list.  By default, nothing is in the reachable
  431.  *  list.  Note that there is no real distinction made between chairs
  432.  *  and beds, so you can sit or lie on either; the only difference is
  433.  *  the message displayed describing the situation.
  434. */
  435. chairitem: fixeditem, nestedroom, surface
  436.     reachable = []          // list of all containers reachable from here;
  437.                             //  normally, you can only reach carried items
  438.                             //  from a chair, but this makes special allowances
  439.     ischair = true          // it is a chair by default; for beds or other
  440.                             //  things you lie down on, make it false
  441.     roomAction( actor, v, do, prep, io ) =
  442.     {
  443.         if ( do<>nil and v<>inspectVerb )
  444.             checkReach( self, actor, v, do );
  445.         if ( io<>nil and v<>askVerb and v<>tellVerb )
  446.             checkReach( self, actor, v, io );
  447.     pass roomAction;
  448.     }
  449.     enterRoom( actor ) = {}
  450.     noexit =
  451.     {
  452.         "%You're% not going anywhere until %you% get%s% out of ";
  453.     self.thedesc; ". ";
  454.         return( nil );
  455.     }
  456.     verDoBoard( actor ) = { self.verDoSiton( actor ); }
  457.     doBoard( actor ) = { self.doSiton( actor ); }
  458.     verDoSiton( actor ) =
  459.     {
  460.         if ( actor.location = self )
  461.         {
  462.             "%You're% already on "; self.thedesc; "! ";
  463.         }
  464.     }
  465.     doSiton( actor ) =
  466.     {
  467.         "Okay, %you're% now sitting on "; self.thedesc; ". ";
  468.         actor.travelTo( self );
  469.     }
  470.     verDoLieon( actor ) =
  471.     {
  472.         self.verDoSiton( actor );
  473.     }
  474.     doLieon( actor ) =
  475.     {
  476.         self.doSiton( actor );
  477.     }
  478. ;
  479.  
  480. /*
  481.  *  beditem: chairitem
  482.  *
  483.  *  This object is the same as a chairitem, except that the player
  484.  *  is described as lying on, rather than sitting in, the object.
  485. */
  486. beditem: chairitem
  487.     ischair = nil
  488.     isbed = true
  489.     sdesc = "bed"
  490. ;
  491.  
  492. /*
  493.  *  thing: object
  494.  *
  495.  *  The basic class for objects in a game.  The property contents
  496.  *  is a list that specifies what is in the object; this property is
  497.  *  automatically set up by the system after the game is compiled to
  498.  *  contain a list of all objects that have this object as their
  499.  *  location property.  The contents property is kept
  500.  *  consistent with the location properties of referenced objects
  501.  *  by the moveInto method; always use moveInto rather than
  502.  *  directly setting a location property for this reason.  The
  503.  *  adesc method displays the name of the object with an indefinite
  504.  *  article; the default is to display "a" followed by the sdesc,
  505.  *  but objects that need a different indefinite article (such as "an"
  506.  *  or "some") should override this method.  Likewise, thedesc
  507.  *  displays the name with a definite article; by default, thedesc
  508.  *  displays "the" followed by the object's sdesc.  The sdesc
  509.  *  simply displays the object's name ("short description") without
  510.  *  any articles.  The ldesc is the long description, normally
  511.  *  displayed when the object is examined by the player; by default,
  512.  *  the ldesc displays a "It looks like an ordinary sdesc."
  513.  *  The isIn( object ) method returns true if the
  514.  *  object's location is the specified object or the object's
  515.  *  location is an object whose contentsVisible property is
  516.  *  true and that object's isIn( object ) method is
  517.  *  true.  Note that if isIn is true, it doesn't
  518.  *  necessary mean the object is reachable, because isIn is
  519.  *  true if the object is merely visible within the location.
  520.  *  The thrudesc method displays a message for when the
  521.  *  player looks through the object (objects such as windows would
  522.  *  use this property).  The moveInto( object ) method
  523.  *  moves the object to be inside the specified object; always use
  524.  *  moveInto to move an object rather than setting its location
  525.  *  directly, so that the appropriate contents lists are updated.
  526.  *  To make an object disappear, move it into nil.
  527. */
  528. thing: object
  529.     isListed = true         // shows up in room/inventory listings
  530.     contents = []
  531.     verGrab( obj ) = {}
  532.     Grab( obj ) = {}
  533.     adesc =
  534.     {
  535.         "a "; self.sdesc;   // default is "a <name>"; "self" is current object
  536.     }
  537.     thedesc =
  538.     {
  539.         "the "; self.sdesc; // default is "the <name>"
  540.     }
  541.     ldesc = { "It looks like an ordinary "; self.sdesc; " to me."; }
  542.     readdesc = { "%You% can't read "; self.adesc; ". "; }
  543.     actorAction( v, d, p, i ) =
  544.     {
  545.         "You have lost your mind. ";
  546.         exit;
  547.     }
  548.     contentsVisible = { return( true ); }
  549.     contentsReachable = { return( true ); }
  550.     isIn( obj ) =
  551.     {
  552.         local myloc;
  553.  
  554.         myloc := self.location;
  555.         if ( myloc )
  556.         {
  557.             if ( myloc = obj ) return( true );
  558.             if ( myloc.contentsVisible ) return( myloc.isIn( obj ));
  559.         }
  560.         return( nil );
  561.     }
  562.     thrudesc = { "%You% can't see much through "; self.thedesc; ".\n"; }
  563.     moveInto( obj ) =
  564.     {
  565.         local loc;
  566.  
  567.     /*
  568.      *   For the object containing me, and its container, and so forth,
  569.      *   tell it via a Grab message that I'm going away.
  570.      */
  571.     loc := self.location;
  572.     while ( loc )
  573.     {
  574.         loc.Grab( self );
  575.         loc := loc.location;
  576.     }
  577.  
  578.         if ( self.location )
  579.             self.location.contents := self.location.contents - self;
  580.         self.location := obj;
  581.         if ( obj ) obj.contents := obj.contents + self;
  582.     }
  583.     verDoSave( actor ) =
  584.     {
  585.         "Please specify the name of the game to save in double quotes,
  586.         for example, SAVE \"GAME1\". ";
  587.     }
  588.     verDoRestore( actor ) =
  589.     {
  590.         "Please specify the name of the game to restore in double quotes,
  591.         for example, SAVE \"GAME1\". ";
  592.     }
  593.     verDoScript( actor ) =
  594.     {
  595.         "You should type the name of a file to write the transcript to
  596.         in quotes, for example, SCRIPT \"LOG1\". ";
  597.     }
  598.     verDoSay( actor ) =
  599.     {
  600.         "You should say what you want to say in double quotes, for example,
  601.         SAY \"HELLO\". ";
  602.     }
  603.     verDoPush( actor ) =
  604.     {
  605.         "Pushing "; self.thedesc; " doesn't do anything. ";
  606.     }
  607.     verDoWear( actor ) =
  608.     {
  609.         "%You% can't wear "; self.thedesc; ". ";
  610.     }
  611.     verDoTake( actor ) =
  612.     {
  613.         if ( self.location = actor )
  614.         {
  615.             "%You% already %have% "; self.thedesc; "! ";
  616.         }
  617.         else self.verifyRemove( actor );
  618.     }
  619.     verifyRemove( actor ) =
  620.     {
  621.       /*
  622.      *   Check with each container to make sure that the container
  623.      *   doesn't object to the object's removal.
  624.      */
  625.         local loc;
  626.  
  627.         loc := self.location;
  628.         while ( loc )
  629.         {
  630.             if ( loc <> actor ) loc.verGrab( self );
  631.             loc := loc.location;
  632.         }
  633.     }
  634.     isVisible( vantage ) =
  635.     {
  636.         local loc;
  637.  
  638.         loc := self.location;
  639.         if ( loc = nil ) return( nil );
  640.  
  641.         /* if it's in the vantage, it's visible */
  642.         if ( loc = vantage ) return( true );
  643.  
  644.         /*
  645.          *   if its location's contents are visible, and its location is
  646.          *   itself visible, it's visible
  647.          */
  648.         if ( loc.contentsVisible and loc.isVisible( vantage )) return( true );
  649.  
  650.         /*
  651.          *   If the vantage has a location, and the vantage's location's
  652.          *   contents are visible (if you can see me I can see you), and
  653.          *   the object is visible from the vantage's location, the object
  654.          *   is visible
  655.          */
  656.         if ( vantage.location <> nil and vantage.location.contentsVisible and
  657.          self.isVisible( vantage.location ))
  658.             return( true );
  659.  
  660.         /* all tests failed:  it's not visible */
  661.         return( nil );
  662.     }
  663.     cantReach( actor ) =
  664.     {
  665.         if ( self.location = nil )
  666.         {
  667.             if ( actor.location.location )
  668.                "%You% can't reach that from << actor.location.thedesc >>. ";
  669.             return;
  670.         }
  671.         if ( not self.location.isopenable or self.location.isopen )
  672.             self.location.cantReach( actor );
  673.         else "%You%'ll have to open << self.location.thedesc >> first. ";
  674.     }
  675.     isReachable( actor ) =
  676.     {
  677.         local loc;
  678.  
  679.         /* if the object is in the room's 'reachable' list, it's reachable */
  680.         if (find( actor.location.reachable, self ) <> nil )
  681.             return( true );
  682.  
  683.         /*
  684.          *   If the object's container's contents are reachable, and the
  685.          *   container is reachable, the object is reachable.
  686.          */
  687.         loc := self.location;
  688.     if (find( actor.location.reachable, self ) <> nil )
  689.         return( true );
  690.     if ( loc = nil ) return( nil );
  691.     if ( loc = actor or loc = actor.location ) return( true );
  692.     if ( loc.contentsReachable )
  693.         return( loc.isReachable( actor ));
  694.     return( nil );
  695.         return( nil );
  696.     }
  697.     doTake( actor ) =
  698.     {
  699.         local totbulk, totweight;
  700.  
  701.         totbulk := addbulk( actor.contents ) + self.bulk;
  702.         totweight := addweight( actor.contents );
  703.         if ( not actor.isCarrying( self ))
  704.             totweight := totweight + self.weight;
  705.  
  706.         if ( totweight > actor.maxweight )
  707.             "%Your% load is too heavy. ";
  708.         else if ( totbulk > actor.maxbulk )
  709.             "%You've% already got %your% hands full. ";
  710.         else
  711.         {
  712.             self.moveInto( actor );
  713.             "Taken. ";
  714.         }
  715.     }
  716.     verDoDrop( actor ) =
  717.     {
  718.         if ( not actor.isCarrying( self ))
  719.         {
  720.             "%You're% not carrying "; self.thedesc; "! ";
  721.         }
  722.         else self.verifyRemove( actor );
  723.     }
  724.     doDrop( actor ) =
  725.     {
  726.         actor.location.roomDrop( self );
  727.     }
  728.     verDoUnwear( actor ) =
  729.     {
  730.         "%You're% not wearing "; self.thedesc; "! ";
  731.     }
  732.     verIoPutIn( actor ) =
  733.     {
  734.         "I don't know how to put anything into "; self.thedesc; ". ";
  735.     }
  736.     verDoPutIn( actor, io ) =
  737.     {
  738.         if ( io = nil ) return;
  739.  
  740.         if ( self.location = io )
  741.         {
  742.             caps(); self.thedesc; " is already in "; io.thedesc; "! ";
  743.         }
  744.         else if ( io = self or io.isIn( self ))
  745.         {
  746.             "%You% can't put "; self.thedesc; " in itself! ";
  747.         }
  748.         else self.verifyRemove( actor );
  749.     }
  750.     doPutIn( actor, io ) =
  751.     {
  752.         self.moveInto( io );
  753.         "Done. ";
  754.     }
  755.     verIoPutOn( actor ) =
  756.     {
  757.         "There's no good surface on "; self.thedesc; ". ";
  758.     }
  759.     verDoPutOn( actor, io ) =
  760.     {
  761.         if ( io = nil ) return;
  762.  
  763.         if ( self.location = io )
  764.         {
  765.             caps(); self.thedesc; " is already on "; io.thedesc; "! ";
  766.         }
  767.         else if ( io = self or io.isIn( self ))
  768.         {
  769.             "%You% can't put "; self.thedesc; " on itself! ";
  770.         }
  771.         else self.verifyRemove( actor );
  772.     }
  773.     doPutOn( actor, io ) =
  774.     {
  775.         self.moveInto( io );
  776.         "Done. ";
  777.     }
  778.     verIoTakeOut( actor ) = {}
  779.     ioTakeOut( actor, do ) =
  780.     {
  781.         do.doTakeOut( actor, self );
  782.     }
  783.     verDoTakeOut( actor, io ) =
  784.     {
  785.         if ( io <> nil and not self.isIn( io ))
  786.         {
  787.             caps(); self.thedesc; " isn't in "; io.thedesc; ". ";
  788.         }
  789.     }
  790.     doTakeOut( actor, io ) =
  791.     {
  792.         self.doTake( actor );
  793.     }
  794.     verIoTakeOff( actor ) = {}
  795.     ioTakeOff( actor, do ) =
  796.     {
  797.         do.doTakeOff( actor, self );
  798.     }
  799.     verDoTakeOff( actor, io ) =
  800.     {
  801.         if ( io <> nil and not self.isIn( io ))
  802.         {
  803.             caps(); self.thedesc; " isn't on "; io.thedesc; "! ";
  804.         }
  805.     }
  806.     doTakeOff( actor, io ) =
  807.     {
  808.         self.doTake( actor );
  809.     }
  810.     verIoPlugIn( actor ) =
  811.     {
  812.         "%You% can't plug anything into "; self.thedesc; ". ";
  813.     }
  814.     verDoPlugIn( actor, io ) =
  815.     {
  816.         "%You% can't plug "; self.thedesc; " into anything. ";
  817.     }
  818.     verIoUnplugFrom( actor ) =
  819.     {
  820.         "It's not plugged into "; self.thedesc; ". ";
  821.     }
  822.     verDoUnplugFrom( actor, io ) =
  823.     {
  824.         if ( io <> nil ) { "It's not plugged into "; io.thedesc; ". "; }
  825.     }
  826.     verDoLookin( actor ) =
  827.     {
  828.         "There's nothing in "; self.thedesc; ". ";
  829.     }
  830.     verDoLookthru( actor ) =
  831.     {
  832.         "%You% can't see anything through "; self.thedesc; ". ";
  833.     }
  834.     verDoLookunder( actor ) =
  835.     {
  836.         "There's nothing under "; self.thedesc; ". ";
  837.     }
  838.     verDoInspect( actor ) = {}
  839.     doInspect( actor ) =
  840.     {
  841.         self.ldesc;
  842.     }
  843.     verDoRead( actor ) =
  844.     {
  845.         "I don't know how to read "; self.thedesc; ". ";
  846.     }
  847.     verDoLookbehind( actor ) =
  848.     {
  849.         "There's nothing behind "; self.thedesc; ". ";
  850.     }
  851.     verDoTurn( actor ) =
  852.     {
  853.         "Turning "; self.thedesc; " doesn't have any effect. ";
  854.     }
  855.     verDoTurnWith( actor, io ) =
  856.     {
  857.         "Turning "; self.thedesc; " doesn't have any effect. ";
  858.     }
  859.     verDoTurnTo( actor, io ) =
  860.     {
  861.         "Turning "; self.thedesc; " doesn't have any effect. ";
  862.     }
  863.     verIoTurnTo( actor ) =
  864.     {
  865.         "I don't know how to do that. ";
  866.     }
  867.     verDoTurnon( actor ) =
  868.     {
  869.         "I don't know how to turn "; self.thedesc; " on. ";
  870.     }
  871.     verDoTurnoff( actor ) =
  872.     {
  873.         "I don't know how to turn "; self.thedesc; " off. ";
  874.     }
  875.     verIoAskAbout( actor ) = {}
  876.     ioAskAbout( actor, do ) =
  877.     {
  878.         do.doAskAbout( actor, self );
  879.     }
  880.     verDoAskAbout( actor, io ) =
  881.     {
  882.         "Surely, %you% can't think "; self.thedesc; " knows anything
  883.         about it! ";
  884.     }
  885.     verIoTellAbout( actor ) = {}
  886.     ioTellAbout( actor, do ) =
  887.     {
  888.         do.doTellAbout( actor, self );
  889.     }
  890.     verDoTellAbout( actor, io ) =
  891.     {
  892.         "It doesn't look as though "; self.thedesc; " is interested. ";
  893.     }
  894.     verDoUnboard( actor ) =
  895.     {
  896.         if ( actor.location <> self )
  897.         {
  898.             "%You're% not in "; self.thedesc; "! ";
  899.         }
  900.         else if ( self.location=nil )
  901.         {
  902.             "%You% can't get out of "; self.thedesc; "! ";
  903.         }
  904.     }
  905.     doUnboard( actor ) =
  906.     {
  907.         if ( self.fastenitem )
  908.     {
  909.         "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
  910.         " first. ";
  911.     }
  912.     else
  913.     {
  914.             "Okay, %you're% no longer in "; self.thedesc; ". ";
  915.             self.leaveRoom( actor );
  916.         actor.moveInto( self.location );
  917.     }
  918.     }
  919.     verDoAttackWith( actor, io ) =
  920.     {
  921.         "Attacking "; self.thedesc; " doesn't appear productive. ";
  922.     }
  923.     verIoAttackWith( actor ) =
  924.     {
  925.         "It's not very effective to attack with "; self.thedesc; ". ";
  926.     }
  927.     verDoEat( actor ) =
  928.     {
  929.         caps(); self.thedesc; " doesn't appear appetizing. ";
  930.     }
  931.     verDoDrink( actor ) =
  932.     {
  933.         caps(); self.thedesc; " doesn't appear appetizing. ";
  934.     }
  935.     verDoGiveTo( actor, io ) =
  936.     {
  937.         if ( not actor.isCarrying( self ))
  938.         {
  939.             "%You're% not carrying "; self.thedesc; ". ";
  940.         }
  941.         else self.verifyRemove( actor );
  942.     }
  943.     doGiveTo( actor, io ) =
  944.     {
  945.         self.moveInto( io );
  946.         "Done. ";
  947.     }
  948.     verDoPull( actor ) =
  949.     {
  950.         "Pulling "; self.thedesc; " doesn't have any effect. ";
  951.     }
  952.     verDoThrowAt( actor, io ) =
  953.     {
  954.         if ( not actor.isCarrying( self ))
  955.         {
  956.             "%You're% not carrying "; self.thedesc; ". ";
  957.         }
  958.         else self.verifyRemove( actor );
  959.     }
  960.     doThrowAt( actor, io ) =
  961.     {
  962.         "%You% miss%es%. ";
  963.         self.moveInto( actor.location );
  964.     }
  965.     verIoThrowAt( actor ) =
  966.     {
  967.         if ( actor.isCarrying( self ))
  968.         {
  969.             "%You% could at least drop "; self.thedesc; " first. ";
  970.         }
  971.     }
  972.     ioThrowAt( actor, do ) =
  973.     {
  974.         do.doThrowAt( actor, self );
  975.     }
  976.     verDoThrowTo( actor, io ) =
  977.     {
  978.         if ( not actor.isCarrying( self ))
  979.         {
  980.             "%You're% not carrying "; self.thedesc; ". ";
  981.         }
  982.         else self.verifyRemove( actor );
  983.     }
  984.     doThrowTo( actor, io ) =
  985.     {
  986.         "%You% miss%es%. ";
  987.         self.moveInto( actor.location );
  988.     }
  989.     verDoThrow( actor ) =
  990.     {
  991.         if ( not actor.isCarrying( self ))
  992.         {
  993.             "%You're% not carrying "; self.thedesc; ". ";
  994.         }
  995.         else self.verifyRemove( actor );
  996.     }
  997.     doThrow( actor ) =
  998.     {
  999.         "Thrown. ";
  1000.         self.moveInto( actor.location );
  1001.     }
  1002.     verDoShowTo( actor, io ) =
  1003.     {
  1004.     }
  1005.     doShowTo( actor, io ) =
  1006.     {
  1007.         if ( io <> nil ) { caps(); io.thedesc; " isn't impressed. "; }
  1008.     }
  1009.     verIoShowTo( actor ) =
  1010.     {
  1011.         caps(); self.thedesc; " isn't impressed. ";
  1012.     }
  1013.     verDoClean( actor ) =
  1014.     {
  1015.         caps(); self.thedesc; " looks a bit cleaner now. ";
  1016.     }
  1017.     verDoCleanWith( actor, io ) = {}
  1018.     doCleanWith( actor, io ) =
  1019.     {
  1020.         caps(); self.thedesc; " looks a bit cleaner now. ";
  1021.     }
  1022.     verDoMove( actor ) =
  1023.     {
  1024.         "Moving "; self.thedesc; " doesn't reveal anything. ";
  1025.     }
  1026.     verDoMoveTo( actor, io ) =
  1027.     {
  1028.         "Moving "; self.thedesc; " doesn't reveal anything. ";
  1029.     }
  1030.     verIoMoveTo( actor ) =
  1031.     {
  1032.         "That doesn't get us anywhere. ";
  1033.     }
  1034.     verDoMoveWith( actor, io ) =
  1035.     {
  1036.         "Moving "; self.thedesc; " doesn't reveal anything. ";
  1037.     }
  1038.     verIoMoveWith( actor ) =
  1039.     {
  1040.         caps(); self.thedesc; " doesn't seem to help. ";
  1041.     }
  1042.     verDoTypeOn( actor, io ) =
  1043.     {
  1044.         "You should say what you want to type in double quotes, for
  1045.         example, TYPE \"HELLO\" ON KEYBOARD. ";
  1046.     }
  1047.     verDoTouch( actor ) =
  1048.     {
  1049.         "Touching "; self.thedesc; " doesn't seem to have any effect. ";
  1050.     }
  1051.     verDoPoke( actor ) =
  1052.     {
  1053.         "Poking "; self.thedesc; " doesn't seem to have any effect. ";
  1054.     }
  1055.     genMoveDir = { "%You% can't seem to do that. "; }
  1056.     verDoMoveN( actor ) = { self.genMoveDir; }
  1057.     verDoMoveS( actor ) = { self.genMoveDir; }
  1058.     verDoMoveE( actor ) = { self.genMoveDir; }
  1059.     verDoMoveW( actor ) = { self.genMoveDir; }
  1060.     verDoMoveNE( actor ) = { self.genMoveDir; }
  1061.     verDoMoveNW( actor ) = { self.genMoveDir; }
  1062.     verDoMoveSE( actor ) = { self.genMoveDir; }
  1063.     verDoMoveSW( actor ) = { self.genMoveDir; }
  1064.     verDoSearch( actor ) =
  1065.     {
  1066.         "%You% find%s% nothing of interest. ";
  1067.     }
  1068. ;
  1069.  
  1070. /*
  1071.  *  item: thing
  1072.  *
  1073.  *  A basic item which can be picked up by the player.  It has no weight
  1074.  *  (0) and minimal bulk (1).  The weight property should be set
  1075.  *  to a non-zero value for heavy objects.  The bulk property
  1076.  *  should be set to a value greater than 1 for bulky objects, and to
  1077.  *  zero for objects that are very small and take essentially no effort
  1078.  *  to hold---or, more precisely, don't detract at all from the player's
  1079.  *  ability to hold other objects (for example, a piece of paper).
  1080. */
  1081. item: thing
  1082.     weight = 0
  1083.     bulk = 1
  1084. ;
  1085.  
  1086. /*
  1087.  *  hider: item
  1088.  *
  1089.  *  This is a basic class of object that can hide other objects in various
  1090.  *  ways.  The underHider, behindHider, and searchHider classes
  1091.  *  are examples of hider subclasses.  The searchObj(actor,
  1092.  *  list) is given the list of hidden items contained in the object (for
  1093.  *  example, this would be the underCont property, in the case of a
  1094.  *  underHider), and "finds" the object or objects. Its action is dependent
  1095.  *  upon a couple of other properties of the hider object.  The
  1096.  *  serialSearch property, if true, indicates that items in the
  1097.  *  list are to be found one at a time; if nil (the default), the
  1098.  *  entire list is found on the first try.  The autoTake property,
  1099.  *  if true, indicates that the actor automatically takes the item
  1100.  *  or items found; if nil, the item or items are moved to the
  1101.  *  actor's location.  The searchObj method returns the list
  1102.  *  with the found object or objects removed; the caller should assign
  1103.  *  this returned value back to the appropriate property (for example,
  1104.  *  underHider will assign the return value to underCont).
  1105.  *  
  1106.  *  Note that because the hider is hiding something, this class
  1107.  *  overrides the normal verDoSearch method to display the
  1108.  *  message, "You'll have to be more specific about how you want
  1109.  *  to search that."  The reason is that the normal verDoSearch
  1110.  *  message ("You find nothing of interest") leads players to believe
  1111.  *  that the object was exhaustively searched, and we want to avoid
  1112.  *  misleading the player.  On the other hand, we don't want a general
  1113.  *  search to be exhaustive for most hider objects.  So, we just
  1114.  *  display a message letting the player know that the search was not
  1115.  *  enough, but we don't give away what they have to do instead.
  1116. */
  1117. hider: item
  1118.     verDoSearch(actor) =
  1119.     {
  1120.     "%You%'ll have to be more specific about how %you% want%s%
  1121.     to search that. ";
  1122.     }
  1123.     searchObj(actor, list) =
  1124.     {
  1125.     local found, dest, i, tot;
  1126.  
  1127.     /* see how much we get this time */
  1128.     if (self.serialSearch)
  1129.     {
  1130.         found := [] + car(list);
  1131.         list := cdr(list);
  1132.     }
  1133.     else
  1134.     {
  1135.         found := list;
  1136.         list := nil;
  1137.     }
  1138.  
  1139.     /* figure destination */
  1140.     dest := actor;
  1141.     if (not self.autoTake) dest := dest.location;
  1142.     
  1143.     /* note what we found, and move it to destination */
  1144.     "%You% find%s% ";
  1145.     tot := length(found);
  1146.     i := 1;
  1147.     while (i <= tot)
  1148.     {
  1149.         found[i].adesc;
  1150.         if (i+1 < tot) ", ";
  1151.         else if (i = 1 and tot = 2) " and ";
  1152.         else if (i+1 = tot and tot > 2) ", and ";
  1153.         
  1154.         found[i].moveInto(dest);
  1155.         i := i + 1;
  1156.     }
  1157.  
  1158.     /* say what happened */
  1159.     if (self.autoTake) ", which %you% take%s%. ";
  1160.     else "! ";
  1161.  
  1162.     if (list<>nil and length(list)=0) list := nil;
  1163.     return(list);
  1164.     }
  1165.     serialSearch = nil             /* find everything in one try by default */
  1166.     autoTake = true               /* actor takes item when found by default */
  1167. ;
  1168.  
  1169. /*
  1170.  *  underHider: hider
  1171.  *
  1172.  *  This is an object that can have other objects placed under it.  The
  1173.  *  objects placed under it can only be found by looking under the object;
  1174.  *  see the description of hider for more information.  Note that you
  1175.  *  should set the underLoc property of each object to be under this
  1176.  *  underHider object to point to this object.
  1177.  *  
  1178.  *  Note that an underHider doesn't allow the player to put anything
  1179.  *  under the object during the game.  Instead, it's to make it easy for the
  1180.  *  game writer to set up hidden objects while implementing the game.  All you
  1181.  *  need to do to place an object under another object is declare the object
  1182.  *  the other object is under as an underHider, then declare the object
  1183.  *  to go underneath normally except that it has an underLoc property
  1184.  *  rather than a location property.  The behindHider and
  1185.  *  searchHider objects work similarly.
  1186. */
  1187. underHider: hider
  1188.     underCont = []         /* list of items under me (set up by initSearch) */
  1189.     verDoLookunder(actor) = {}
  1190.     doLookunder(actor) =
  1191.     {
  1192.     if (self.underCont = nil)
  1193.         "There's nothing else under <<self.thedesc>>. ";
  1194.     else
  1195.         self.underCont := self.searchObj(actor, self.underCont);
  1196.     }
  1197. ;
  1198.  
  1199. /*
  1200.  *  behindHider: hider
  1201.  *
  1202.  *  This is just like an underHider, except that objects are hidden
  1203.  *  behind this object.  Objects to be behind this object should have their
  1204.  *  behindLoc property set to point to this object.
  1205. */
  1206. behindHider: hider
  1207.     behindCont = []
  1208.     verDoLookbehind(actor) = {}
  1209.     doLookbehind(actor) =
  1210.     {
  1211.     if (self.behindCont = nil)
  1212.         "There's nothing else behind <<self.thedesc>>. ";
  1213.     else
  1214.         self.behindCont := self.searchObj(actor, self.behindCont);
  1215.     }
  1216. ;
  1217.     
  1218. /*
  1219.  *  searchHider: hider
  1220.  *
  1221.  *  This is just like an underHider, except that objects are hidden
  1222.  *  within this object in such a way that the object must be looked in
  1223.  *  or searched.  Objects to be hidden in this object should have their
  1224.  *  searchLoc property set to point to this object.  Note that this
  1225.  *  is different from a normal container, in that the objects hidden within
  1226.  *  this object will not show up until the object is explicitly looked in
  1227.  *  or searched.
  1228. */
  1229. searchHider: hider
  1230.     searchCont = []
  1231.     verDoSearch(actor) = {}
  1232.     doSearch(actor) =
  1233.     {
  1234.     if (self.searchCont = nil)
  1235.         "There's nothing else in <<self.thedesc>>. ";
  1236.     else
  1237.         self.searchCont := self.searchObj(actor, self.searchCont);
  1238.     }
  1239.     verDoLookin(actor) =
  1240.     {
  1241.     if (self.searchCont = nil)
  1242.         pass verDoLookin;
  1243.     }
  1244.     doLookin(actor) =
  1245.     {
  1246.     if (self.searchCont = nil)
  1247.         pass doLookin;
  1248.     else
  1249.         self.searchCont := self.searchObj(actor, self.searchCont);
  1250.     }
  1251. ;
  1252.     
  1253.  
  1254. /*
  1255.  *  fixeditem: thing
  1256.  *
  1257.  *  An object that cannot be taken or otherwise moved from its location.
  1258.  *  Note that a fixeditem is sometimes part of a movable object;
  1259.  *  this can be done to make one object part of another, ensuring that
  1260.  *  they cannot be separated.  By default, a fixeditem is not
  1261.  *  described automatically in a room's description (i.e., the isListed
  1262.  *  property is set to nil, because it is generally described separately
  1263.  *  as part of the room's ldesc.  
  1264. */
  1265. fixeditem: thing            // An immovable object
  1266.     isListed = nil          // not listed in room/inventory displays
  1267.     isfixed = true          // Item can't be taken
  1268.     weight = 0              // no actual weight
  1269.     bulk = 0
  1270.     verDoTake( actor ) =
  1271.     {
  1272.         "%You% can't have "; self.thedesc; ". ";
  1273.     }
  1274.     verDoTakeOut( actor, io ) =
  1275.     {
  1276.         self.verDoTake( actor );
  1277.     }
  1278.     verDoDrop( actor ) =
  1279.     {
  1280.         "%You% can't drop "; self.thedesc; ". ";
  1281.     }
  1282.     verDoTakeOff( actor, io ) =
  1283.     {
  1284.         self.verDoTake( actor );
  1285.     }
  1286.     verDoPutIn( actor, io ) =
  1287.     {
  1288.         "%You% can't put "; self.thedesc; " anywhere. ";
  1289.     }
  1290.     verDoPutOn( actor, io ) =
  1291.     {
  1292.         "%You% can't put "; self.thedesc; " anywhere. ";
  1293.     }
  1294.     verDoMove( actor ) =
  1295.     {
  1296.         "%You% can't move "; self.thedesc; ". ";
  1297.     }
  1298. ;
  1299.  
  1300. /*
  1301.  *  readable: item
  1302.  *
  1303.  *  An item that can be read.  The readdesc property is displayed
  1304.  *  when the item is read.  By default, the readdesc is the same
  1305.  *  as the ldesc, but the readdesc can be overridden to give
  1306.  *  a different message.
  1307. */
  1308. readable: item
  1309.     verDoRead( actor ) =
  1310.     {
  1311.     }
  1312.     doRead( actor ) =
  1313.     {
  1314.         self.readdesc;
  1315.     }
  1316.     readdesc =
  1317.     {
  1318.         self.ldesc;
  1319.     }
  1320. ;
  1321.  
  1322. /*
  1323.  *  fooditem: item
  1324.  *
  1325.  *  An object that can be eaten.  When eaten, the object is removed from
  1326.  *  the game, and global.lastMealTime is decremented by the
  1327.  *  foodvalue property.  By default, the foodvalue property
  1328.  *  is global.eatTime, which is the time between meals.  So, the
  1329.  *  default fooditem will last for one "nourishment interval."
  1330. */
  1331. fooditem: item
  1332.     verDoEat( actor ) =
  1333.     {
  1334.         self.verifyRemove( actor );
  1335.     }
  1336.     doEat( actor ) =
  1337.     {
  1338.         "That was delicious! ";
  1339.         global.lastMealTime := global.lastMealTime - self.foodvalue;
  1340.         self.moveInto( nil );
  1341.     }
  1342.     foodvalue = { return( global.eatTime ); }
  1343. ;
  1344.  
  1345. /*
  1346.  *  dialItem: fixeditem
  1347.  *
  1348.  *  This class is used for making "dials," which are controls in
  1349.  *  your game that can be turned to a range of numbers.  You must
  1350.  *  define the property maxsetting as a number specifying the
  1351.  *  highest number to which the dial can be turned; the lowest number
  1352.  *  on the dial is always 1.  The setting property is the dial's
  1353.  *  current setting, and can be changed by the player by typing the
  1354.  *  command "turn dial to number."  By default, the ldesc
  1355.  *  method displays the current setting.
  1356. */
  1357. dialItem: fixeditem
  1358.     maxsetting = 10 // it has settings from 1 to this number
  1359.     setting = 1     // the current setting
  1360.     ldesc =
  1361.     {
  1362.         caps(); self.thedesc; " can be turned to settings
  1363.         numbered from 1 to << self.maxsetting >>. It's
  1364.         currently set to << self.setting >>. ";
  1365.     }
  1366.     verDoTurn( actor ) = {}
  1367.     doTurn( actor ) =
  1368.     {
  1369.         askio( toPrep );
  1370.     }
  1371.     verDoTurnTo( actor, io ) = {}
  1372.     doTurnTo( actor, io ) =
  1373.     {
  1374.         if ( io = numObj )
  1375.         {
  1376.             if ( numObj.value < 1 or numObj.value > self.maxsetting )
  1377.             {
  1378.                 "There's no such setting! ";
  1379.             }
  1380.             else if ( numObj.value <> self.setting )
  1381.             {
  1382.                 self.setting := numObj.value;
  1383.                 "Okay, it's now turned to "; say( self.setting ); ". ";
  1384.             }
  1385.             else
  1386.             {
  1387.                 "It's already set to "; say( self.setting ); "! ";
  1388.             }
  1389.         }
  1390.         else
  1391.         {
  1392.             "I don't know how to turn "; self.thedesc;
  1393.             " to that. ";
  1394.         }
  1395.     }
  1396. ;
  1397.  
  1398. /*
  1399.  *  switchItem: fixeditem
  1400.  *
  1401.  *  This is a class for things that can be turned on and off by the
  1402.  *  player.  The only special property is isActive, which is nil
  1403.  *  if the switch is turned off and true when turned on.  The object
  1404.  *  accepts the commands "turn it on" and "turn it off,'' as well as
  1405.  *  synonymous constructions, and updates isActive accordingly.
  1406. */
  1407. switchItem: fixeditem
  1408.     verDoSwitch( actor ) = {}
  1409.     doSwitch( actor ) =
  1410.     {
  1411.         self.isActive := not self.isActive;
  1412.         "Okay, "; self.thedesc; " is now switched ";
  1413.         if ( self.isActive ) "on"; else "off";
  1414.         ". ";
  1415.     }
  1416.     verDoTurnon( actor ) =
  1417.     {
  1418.         if ( self.isActive ) "It's already turned on! ";
  1419.     }
  1420.     doTurnon( actor ) =
  1421.     {
  1422.         self.isActive := true;
  1423.         "Okay, it's now turned on. ";
  1424.     }
  1425.     verDoTurnoff( actor ) =
  1426.     {
  1427.         if ( not self.isActive ) "It's already turned off! ";
  1428.     }
  1429.     doTurnoff( actor ) =
  1430.     {
  1431.         self.isActive := nil;
  1432.         "Okay, it's now turned off. ";
  1433.     }
  1434. ;
  1435.  
  1436. /*
  1437.  *  room: thing
  1438.  *
  1439.  *  A location in the game.  By default, the islit property is
  1440.  *  true, which means that the room is lit (no light source is
  1441.  *  needed while in the room).  You should create a darkroom
  1442.  *  object rather than a room with islit set to nil if you
  1443.  *  want a dark room, because other methods are affected as well.
  1444.  *  The isseen property records whether the player has entered
  1445.  *  the room before; initially it's nil, and is set to true
  1446.  *  the first time the player enters.  The roomAction( actor,
  1447.  *  verb, directObject, preposition, indirectObject ) method is
  1448.  *  activated for each player command; by default, all it does is
  1449.  *  call the room's location's roomAction method if the room
  1450.  *  is inside another room.  The lookAround( verbosity )
  1451.  *  method displays the room's description for a given verbosity
  1452.  *  level; true means a full description, nil means only
  1453.  *  the short description (just the room name plus a list of the
  1454.  *  objects present).  roomDrop( object ) is called when
  1455.  *  an object is dropped within the room; normally, it just moves
  1456.  *  the object to the room and displays "Dropped."  The firstseen
  1457.  *  method is called when isseen is about to be set true
  1458.  *  for the first time (i.e., when the player first sees the room);
  1459.  *  by default, this routine does nothing, but it's a convenient
  1460.  *  place to put any special code you want to execute when a room
  1461.  *  is first entered.  The firstseen method is called after
  1462.  *  the room's description is displayed.
  1463. */
  1464. room: thing
  1465.     /*
  1466.      *   'reachable' is the list of explicitly reachable objects, over and
  1467.      *   above the objects that are here.  This is mostly used in nested
  1468.      *   rooms to make objects in the containing room accessible.  Most
  1469.      *   normal rooms will leave this as an empty list.
  1470.      */
  1471.     reachable = []
  1472.     
  1473.     /*
  1474.      *   roomCheck is true if the verb is valid in the room.  This
  1475.      *   is a first pass; generally, its only function is to disallow
  1476.      *   certain commands in a dark room.
  1477.      */
  1478.     roomCheck( v ) = { return( true ); }
  1479.     islit = true            // rooms are lit unless otherwise specified
  1480.     isseen = nil            // room has not been seen yet
  1481.     enterRoom( actor ) =    // sent to room as actor is entering it
  1482.     {
  1483.         self.lookAround(( not self.isseen ) or global.verbose );
  1484.         if ( self.islit )
  1485.     {
  1486.         if (not self.isseen) self.firstseen;
  1487.         self.isseen := true;
  1488.     }
  1489.     }
  1490.     roomAction( a, v, d, p, i ) =
  1491.     {
  1492.         if ( self.location ) self.location.roomAction( a, v, d, p, i );
  1493.     }
  1494.  
  1495.     /*
  1496.      *   Whenever a normal object (i.e., one that does not override the
  1497.      *   default doDrop provided by 'thing') is dropped, the actor's
  1498.      *   location is sent roomDrop(object being dropped).  By default, 
  1499.      *   we move the object into this room.
  1500.      */
  1501.     roomDrop( obj ) =
  1502.     {
  1503.         "Dropped. ";
  1504.     obj.moveInto( self );
  1505.     }
  1506.  
  1507.     /*
  1508.      *   Whenever an actor leaves this room, we run through the leaveList.
  1509.      *   This is a list of objects that have registered themselves with us
  1510.      *   via addLeaveList().  For each object in the leaveList, we send
  1511.      *   a "leaving" message, with the actor as the parameter.  It should
  1512.      *   return true if it wants to be removed from the leaveList, nil
  1513.      *   if it wants to stay.
  1514.      */
  1515.     leaveList = []
  1516.     addLeaveList( obj ) =
  1517.     {
  1518.         self.leaveList := self.leaveList + obj;
  1519.     }
  1520.     leaveRoom( actor ) =
  1521.     {
  1522.         local tmplist, thisobj, i, tot;
  1523.  
  1524.         tmplist := self.leaveList;
  1525.     tot := length( tmplist );
  1526.     i := 1;
  1527.         while ( i <= tot )
  1528.         {
  1529.         thisobj := tmplist[i];
  1530.             if ( thisobj.leaving( actor ))
  1531.                 self.leaveList := self.leaveList - thisobj;
  1532.             i := i + 1;
  1533.         }
  1534.     }
  1535.     /*
  1536.      *   lookAround describes the room.  If verbosity is true, the full
  1537.      *   description is given, otherwise an abbreviated description (without
  1538.      *   the room's ldesc) is displayed.
  1539.      */
  1540.     nrmLkAround( verbosity ) =      // lookAround without location status
  1541.     {
  1542.         local l, cur, i, tot;
  1543.  
  1544.         if ( verbosity )
  1545.         {
  1546.             "\n\t"; self.ldesc;
  1547.  
  1548.             l := self.contents;
  1549.         tot := length( l );
  1550.         i := 1;
  1551.             while ( i <= tot )
  1552.             {
  1553.             cur := l[i];
  1554.                 if ( cur.isfixed ) cur.heredesc;
  1555.                 i := i + 1;
  1556.             }
  1557.         }
  1558.         "\n\t";
  1559.         if (itemcnt( self.contents ))
  1560.         {
  1561.             "You see "; listcont( self ); " here. ";
  1562.         }
  1563.         listcontcont( self ); "\n";
  1564.  
  1565.         l := self.contents;
  1566.     tot := length( l );
  1567.     i := 1;
  1568.         while ( i <= tot )
  1569.         {
  1570.         cur := l[i];
  1571.             if ( cur.isactor )
  1572.             {
  1573.                 if ( cur <> Me )
  1574.                 {
  1575.                     "\n\t";
  1576.                     cur.actorDesc;
  1577.                 }
  1578.             }
  1579.             i := i + 1;
  1580.         }
  1581.     }
  1582.     statusLine =
  1583.     {
  1584.         self.sdesc; "\n\t";
  1585.     }
  1586.     lookAround( verbosity ) =
  1587.     {
  1588.         self.statusLine;
  1589.         self.nrmLkAround( verbosity );
  1590.     }
  1591.     
  1592.     /*
  1593.      *   Direction handlers.  The directions are all set up to
  1594.      *   the default, which is no travel allowed.  To make travel
  1595.      *   possible in a direction, just assign a room to the direction
  1596.      *   property.
  1597.      */
  1598.     north = { return( self.noexit ); }
  1599.     south = { return( self.noexit ); }
  1600.     east  = { return( self.noexit ); }
  1601.     west  = { return( self.noexit ); }
  1602.     up    = { return( self.noexit ); }
  1603.     down  = { return( self.noexit ); }
  1604.     ne    = { return( self.noexit ); }
  1605.     nw    = { return( self.noexit ); }
  1606.     se    = { return( self.noexit ); }
  1607.     sw    = { return( self.noexit ); }
  1608.     in    = { return( self.noexit ); }
  1609.     out   = { return( self.noexit ); }
  1610.     
  1611.     /*
  1612.      *   noexit displays a message when the player attempts to travel
  1613.      *   in a direction in which travel is not possible.
  1614.      */
  1615.     noexit = { "%You% can't go that way. "; return( nil ); }
  1616. ;
  1617.  
  1618. /*
  1619.  *  darkroom: room
  1620.  *
  1621.  *  A dark room.  The player must have some object that can act as a
  1622.  *  light source in order to move about and perform most operations
  1623.  *  while in this room.  Note that the room's lights can be turned
  1624.  *  on by setting the room's lightsOn property to true;
  1625.  *  do this instead of setting islit, because islit is
  1626.  *  a method which checks for the presence of a light source.
  1627. */
  1628. darkroom: room              // An enterable area which might be dark
  1629.     islit =                 // true ONLY if something is lighting the room
  1630.     {
  1631.         local rem, cur, tot, i;
  1632.  
  1633.     if ( self.lightsOn ) return( true );
  1634.  
  1635.     rem := global.lamplist;
  1636.     tot := length( rem );
  1637.     i := 1;
  1638.     while ( i <= tot )
  1639.     {
  1640.         cur := rem[i];
  1641.         if ( cur.isIn( self ) and cur.islit ) return( true );
  1642.         i := i + 1;
  1643.     }
  1644.     return( nil );
  1645.     }
  1646.     roomAction( actor, v, do, prep, io ) =
  1647.     {
  1648.         if ( not self.islit and not v.isTravelVerb and not v.issysverb )
  1649.     {
  1650.         "%You% can't see a thing. ";
  1651.         exit;
  1652.     }
  1653.     else pass roomAction;
  1654.     }
  1655.     statusLine =
  1656.     {
  1657.         if ( self.islit ) pass statusLine;
  1658.     else "In the dark.";
  1659.     }
  1660.     lookAround( verbosity ) =
  1661.     {
  1662.         if ( self.islit ) pass lookAround;
  1663.     else "It's pitch black. ";
  1664.     }
  1665.     noexit =
  1666.     {
  1667.         if ( self.islit ) pass noexit;
  1668.     else
  1669.     {
  1670.         darkTravel();
  1671.         return( nil );
  1672.     }
  1673.     }
  1674.     roomCheck( v ) =
  1675.     {
  1676.         if ( self.islit or v.issysverb or v.isTravelVerb ) return( true );
  1677.     else
  1678.     {
  1679.         "It's pitch black.\n";
  1680.         return( nil );
  1681.     }
  1682.     }
  1683. ;
  1684.  
  1685. /*
  1686.  *  theFloor is a special item that appears in every room (hence
  1687.  *  the non-standard location property).  This object is included
  1688.  *  mostly for completeness, so that the player can refer to the
  1689.  *  floor; otherwise, it doesn't do much.  Dropping an item on the
  1690.  *  floor, for example, moves it to the current room.
  1691.  */
  1692. theFloor: beditem
  1693.     noun = 'floor' 'ground'
  1694.     sdesc = "ground"
  1695.     adesc = "the ground"
  1696.     location =
  1697.     {
  1698.         if ( Me.location = self )
  1699.             return( self.sitloc );
  1700.         else
  1701.             return( Me.location );
  1702.     }
  1703.     locationOK = true        // suppress warning about location being a method
  1704.     doSiton( actor ) =
  1705.     {
  1706.         "Okay, %you're% now sitting on "; self.thedesc; ". ";
  1707.         self.sitloc := actor.location;
  1708.         actor.moveInto( self );
  1709.     }
  1710.     doLieon( actor ) =
  1711.     {
  1712.         self.doSiton( actor );
  1713.     }
  1714.     ioPutOn( actor, do ) =
  1715.     {
  1716.         do.doDrop( actor );
  1717.     }
  1718.     ioPutIn( actor, do ) =
  1719.     {
  1720.         do.doDrop( actor );
  1721.     }
  1722. ;
  1723.  
  1724. /*
  1725.  *  Actor: fixeditem, movableActor
  1726.  *
  1727.  *  A character in the game.  The maxweight property specifies
  1728.  *  the maximum weight that the character can carry, and the maxbulk
  1729.  *  property specifies the maximum bulk the character can carry.  The
  1730.  *  actorAction( verb, directObject, preposition, indirectObject )
  1731.  *  method specifies what happens when the actor is given a command by
  1732.  *  the player; by default, the actor ignores the command and displays
  1733.  *  a message to this effect.  The isCarrying( object )
  1734.  *  method returns true if the object is being carried by
  1735.  *  the actor.  The actorDesc method displays a message when the
  1736.  *  actor is in the current room; this message is displayed along with
  1737.  *  a room's description when the room is entered or examined.  The
  1738.  *  verGrab( object ) method is called when someone tries to
  1739.  *  take an object the actor is carrying; by default, an actor won't
  1740.  *  let other characters take its possessions.
  1741.  *  
  1742.  *  If you want the player to be able to follow the actor when it
  1743.  *  leaves the room, you should define a follower object to shadow
  1744.  *  the character, and set the actor's myfollower property to
  1745.  *  the follower object.  The follower is then automatically
  1746.  *  moved around just behind the actor by the actor's moveInto
  1747.  *  method.
  1748.  *  
  1749.  *  The isHim property should return true if the actor can
  1750.  *  be referred to by the player as "him," and likewise isHer
  1751.  *  should be set to true if the actor can be referred to as "her."
  1752.  *  Note that both or neither can be set; if neither is set, the actor
  1753.  *  can only be referred to as "it," and if both are set, either "him''
  1754.  *  or "her" will be accepted.
  1755. */
  1756. Actor: fixeditem, movableActor
  1757. ;
  1758.  
  1759. /*
  1760.  *  movableActor: qcontainer
  1761.  *
  1762.  *  Just like an Actor object, except that the player can
  1763.  *  manipulate the actor like an ordinary item.  Useful for certain
  1764.  *  types of actors, such as small animals.
  1765. */
  1766. movableActor: qcontainer // A character in the game
  1767.     isListed = nil          // described separately from room's contents
  1768.     weight = 10             // actors are pretty heavy
  1769.     bulk = 10               // and pretty bulky
  1770.     maxweight = 50          // Weight that can be carried at once
  1771.     maxbulk = 20            // Number of objects that can be carried at once
  1772.     isactor = true          // flag that this is an actor
  1773.     actorAction( v, d, p, i ) =
  1774.     {
  1775.         caps(); self.thedesc; " doesn't appear interested. ";
  1776.         exit;
  1777.     }
  1778.     isCarrying( obj ) = { return( obj.isIn( self )); }
  1779.     actorDesc =
  1780.     {
  1781.         caps(); self.adesc; " is here. ";
  1782.     }
  1783.     verGrab( item ) =
  1784.     {
  1785.         caps(); self.thedesc; " is carrying "; item.thedesc;
  1786.         " and won't let %youm% have it. ";
  1787.     }
  1788.     verDoFollow( actor ) =
  1789.     {
  1790.         "But "; self.thedesc; " is right here! ";
  1791.     }
  1792.     moveInto( obj ) =
  1793.     {
  1794.         if ( self.myfollower ) self.myfollower.moveInto( self.location );
  1795.     pass moveInto;
  1796.     }
  1797.     // these properties are for the format strings
  1798.     fmtYou = "he"
  1799.     fmtYour = "his"
  1800.     fmtYoure = "he's"
  1801.     fmtYoum = "him"
  1802.     fmtYouve = "he's"
  1803.     fmtS = "s"
  1804.     fmtEs = "es"
  1805.     fmtHave = "has"
  1806.     fmtDo = "does"
  1807.     fmtAre = "is"
  1808. ;
  1809.  
  1810. /*
  1811.  *  follower: Actor
  1812.  *
  1813.  *  This is a special object that can "shadow" the movements of a
  1814.  *  character as it moves from room to room.  The purpose of a follower
  1815.  *  is to allow the player to follow an actor as it leaves a room by
  1816.  *  typing a "follow" command.  Each actor that is to be followed must
  1817.  *  have its own follower object.  The follower object should
  1818.  *  define all of the same vocabulary words (nouns and adjectives) as the
  1819.  *  actual actor to which it refers.  The follower must also
  1820.  *  define the myactor property to be the Actor object that
  1821.  *  the follower follows.  The follower will always stay
  1822.  *  one room behind the character it follows; no commands are effective
  1823.  *  with a follower except for "follow."
  1824. */
  1825. class follower: Actor
  1826.     sdesc = { self.myactor.sdesc; }
  1827.     isfollower = true
  1828.     ldesc = { caps(); self.thedesc; " is no longer here. "; }
  1829.     actorAction( v, d, p, i ) = { self.ldesc; }
  1830.     actorDesc = {}
  1831.     myactor = nil   // set to the Actor to be followed
  1832.     verDoFollow( actor ) = {}
  1833.     doFollow( actor ) =
  1834.     {
  1835.         actor.travelTo( self.myactor.location );
  1836.     }
  1837. ;
  1838.  
  1839. /*
  1840.  *  basicMe: Actor
  1841.  *
  1842.  *  A default implementation of the Me object, which is the
  1843.  *  player character.  adv.t defines basicMe instead of
  1844.  *  Me to allow your game to override parts of the default
  1845.  *  implementation while still using the rest, and without changing
  1846.  *  adv.t itself.  To use basicMe unchanged as your player
  1847.  *  character, include this in your game:  "Me: basicMe;".
  1848.  *  
  1849.  *  The basicMe object defines all of the methods and properties
  1850.  *  required for an actor, with appropriate values for the player
  1851.  *  character.  The nouns "me" and "myself'' are defined ("I''
  1852.  *  is not defined, because it conflicts with the "inventory"
  1853.  *  command's minimal abbreviation of "i" in certain circumstances,
  1854.  *  and is generally not compatible with the syntax of most player
  1855.  *  commands anyway).  The sdesc is "you"; the thedesc
  1856.  *  and adesc are "yourself," which is appropriate for most
  1857.  *  contexts.  The maxbulk and maxweight properties are
  1858.  *  set to 10 each; a more sophisticated Me might include the
  1859.  *  player's state of health in determining the maxweight and
  1860.  *  maxbulk properties.
  1861. */
  1862. class basicMe: Actor
  1863.     roomCheck( v ) = { return( self.location.roomCheck( v )); }
  1864.     noun = 'me' 'myself'
  1865.     sdesc = "you"
  1866.     thedesc = "yourself"
  1867.     adesc = "yourself"
  1868.     ldesc = "You look about the same as always. "
  1869.     maxweight = 10
  1870.     maxbulk = 10
  1871.     verDoFollow( actor ) =
  1872.     {
  1873.         if ( actor = self ) "You can't follow yourself! ";
  1874.     }
  1875.     actorAction( verb, dobj, prep, iobj ) = 
  1876.     {
  1877.     }
  1878.     travelTo( room ) =
  1879.     {
  1880.         if ( room )
  1881.         {
  1882.         if ( room.isobstacle )
  1883.         {
  1884.             self.travelTo( room.destination );
  1885.         }
  1886.         else if ( not ( self.location.islit or room.islit ))
  1887.         {
  1888.             darkTravel();
  1889.         }
  1890.         else
  1891.         {
  1892.                 if ( self.location ) self.location.leaveRoom( self );
  1893.                 self.location := room;
  1894.                 room.enterRoom( self );
  1895.         }
  1896.         }
  1897.     }
  1898.     moveInto( room ) =
  1899.     {
  1900.         self.location := room;
  1901.     }
  1902.     // these properties are for the format strings
  1903.     fmtYou = "you"
  1904.     fmtYour = "your"
  1905.     fmtYoure = "you're"
  1906.     fmtYoum = "you"
  1907.     fmtYouve = "you've"
  1908.     fmtS = ""
  1909.     fmtEs = ""
  1910.     fmtHave = "have"
  1911.     fmtDo = "do"
  1912.     fmtAre = "are"
  1913. ;
  1914.  
  1915. /*
  1916.  *  decoration: fixeditem
  1917.  *
  1918.  *  An item that doesn't have any function in the game, apart from
  1919.  *  having been mentioned in the room description.  These items
  1920.  *  are immovable and can't be manipulated in any way, but can be
  1921.  *  referred to and inspected.  Liberal use of decoration items
  1922.  *  can improve a game's playability by helping the parser recognize
  1923.  *  all the words the game uses in its descriptions of rooms.
  1924. */
  1925. decoration: fixeditem
  1926. ;
  1927.  
  1928. /*
  1929.  *  buttonitem: fixeditem
  1930.  *
  1931.  *  A button (the type you push).  The individual button's
  1932.  *  doPush( actor ) method, which must be specified in
  1933.  *  the button, carries out the function of the button.  Note that
  1934.  *  all buttons have the noun "button" defined.
  1935. */
  1936. class buttonitem: fixeditem
  1937.     noun = 'button'
  1938.     plural = 'buttons'
  1939.     verDoPush( actor ) = {}
  1940. ;
  1941.  
  1942. /*
  1943.  *  clothingItem: item
  1944.  *
  1945.  *  Something that can be worn.  By default, the only thing that
  1946.  *  happens when the item is worn is that its isworn property
  1947.  *  is set to true.  If you want more to happen, override the
  1948.  *  doWear( actor ) property.  Note that, when a clothingItem
  1949.  *  is being worn, certain operations will cause it to be removed (for
  1950.  *  example, dropping it causes it to be removed).  If you want
  1951.  *  something else to happen, override the checkDrop method;
  1952.  *  if you want to disallow such actions while the object is worn,
  1953.  *  use an exit statement in the checkDrop method.
  1954. */
  1955. class clothingItem: item
  1956.     checkDrop =
  1957.     {
  1958.         if ( self.isworn )
  1959.     {
  1960.         "(Taking off "; self.thedesc; " first)\n";
  1961.     }
  1962.     }
  1963.     doDrop( actor ) =
  1964.     {
  1965.         self.checkDrop;
  1966.     pass doDrop;
  1967.     }
  1968.     doPutIn( actor, io ) =
  1969.     {
  1970.         self.checkDrop;
  1971.     pass doPutIn;
  1972.     }
  1973.     doPutOn( actor, io ) =
  1974.     {
  1975.         self.checkDrop;
  1976.     pass doPutOn;
  1977.     }
  1978.     doGiveTo( actor, io ) =
  1979.     {
  1980.         self.checkDrop;
  1981.     pass doGiveTo;
  1982.     }
  1983.     doThrowAt( actor, io ) =
  1984.     {
  1985.         self.checkDrop;
  1986.     pass doThrowAt;
  1987.     }
  1988.     doThrowTo( actor, io ) =
  1989.     {
  1990.         self.checkDrop;
  1991.     pass doThrowTo;
  1992.     }
  1993.     doThrow( actor ) =
  1994.     {
  1995.         self.checkDrop;
  1996.     pass doThrow;
  1997.     }
  1998.     moveInto( obj ) =
  1999.     {
  2000.         /*
  2001.      *   Catch any other movements with moveInto; this won't stop the
  2002.      *   movement from happening, but it will prevent any anamolous
  2003.      *   consequences caused by the object moving but still being worn.
  2004.      */
  2005.         self.isworn := nil;
  2006.     pass moveInto;
  2007.     }
  2008.     verDoWear( actor ) =
  2009.     {
  2010.         if ( self.isworn )
  2011.         {
  2012.             "%You're% already wearing "; self.thedesc; "! ";
  2013.         }
  2014.         else if ( not actor.isCarrying( self ))
  2015.         {
  2016.             "%You% %do%n't have "; self.thedesc; ". ";
  2017.         }
  2018.     }
  2019.     doWear( actor ) =
  2020.     {
  2021.         "Okay, %you're% now wearing "; self.thedesc; ". ";
  2022.         self.isworn := true;
  2023.     }
  2024.     verDoUnwear( actor ) =
  2025.     {
  2026.         if ( not self.isworn )
  2027.         {
  2028.             "%You're% not wearing "; self.thedesc; ". ";
  2029.         }
  2030.     }
  2031.     doUnwear( actor ) =
  2032.     {
  2033.         "Okay, %you're% no longer wearing "; self.thedesc; ". ";
  2034.         self.isworn := nil;
  2035.     }
  2036. ;
  2037.  
  2038. /*
  2039.  *  obstacle: object
  2040.  *
  2041.  *  An obstacle is used in place of a room for a direction
  2042.  *  property.  The destination property specifies the room that
  2043.  *  is reached if the obstacle is successfully negotiated; when the
  2044.  *  obstacle is not successfully negotiated, destination should
  2045.  *  display an appropriate message and return nil.
  2046. */
  2047. obstacle: object
  2048.     isobstacle = true
  2049. ;
  2050.  
  2051. /*
  2052.  *  doorway: fixeditem, obstacle
  2053.  *
  2054.  *  A doorway is an obstacle that impedes progress when it is closed.
  2055.  *  When the door is open (isopen is true), the user ends up in
  2056.  *  the room specified in the doordest property upon going through
  2057.  *  the door.  Since a doorway is an obstacle, use the door object for
  2058.  *  a direction property of the room containing the door.
  2059.  *  
  2060.  *  If noAutoOpen is not set to true, the door will automatically
  2061.  *  be opened when the player tries to walk through the door, unless the
  2062.  *  door is locked (islocked = true).  If the door is locked,
  2063.  *  it can be unlocked simply by typing "unlock door", unless the
  2064.  *  mykey property is set, in which case the object specified in
  2065.  *  mykey must be used to unlock the door.  Note that the door can
  2066.  *  only be relocked by the player under the circumstances that allow
  2067.  *  unlocking, plus the property islockable must be set true.
  2068.  *  By default, the door is closed; set isopen to true if the door
  2069.  *  is to start out open (and be sure to open the other side as well).
  2070.  *  
  2071.  *  otherside specifies the corresponding doorway object in the
  2072.  *  destination room (doordest), if any.  If otherside is
  2073.  *  specified, its isopen and islocked properties will be
  2074.  *  kept in sync automatically.
  2075. */
  2076. doorway: fixeditem, obstacle
  2077.     isdoor = true           // Item can be opened and closed
  2078.     destination =
  2079.     {
  2080.         if ( self.isopen ) return( self.doordest );
  2081.     else if ( not self.islocked and not self.noAutoOpen )
  2082.     {
  2083.         self.isopen := true;
  2084.         if ( self.otherside ) self.otherside.isopen := true;
  2085.         "(Opening << self.thedesc >>)\n";
  2086.         return( self.doordest );
  2087.     }
  2088.     else
  2089.     {
  2090.         "%You%'ll have to open << self.thedesc >> first. ";
  2091.         setit( self );
  2092.         return( nil );
  2093.     }
  2094.     }
  2095.     verDoOpen( actor ) =
  2096.     {
  2097.         if ( self.isopen ) "It's already open. ";
  2098.     else if ( self.islocked ) "It's locked. ";
  2099.     }
  2100.     doOpen( actor ) =
  2101.     {
  2102.         "Opened. ";
  2103.     self.isopen := true;
  2104.     if ( self.otherside ) self.otherside.isopen := true;
  2105.     }
  2106.     verDoClose( actor ) =
  2107.     {
  2108.         if ( not self.isopen ) "It's already closed. ";
  2109.     }
  2110.     doClose( actor ) =
  2111.     {
  2112.         "Closed. ";
  2113.     self.isopen := nil;
  2114.     if ( self.otherside ) self.otherside.isopen := nil;
  2115.     }
  2116.     verDoLock( actor ) =
  2117.     {
  2118.         if ( self.islocked ) "It's already locked! ";
  2119.     else if ( not self.islockable ) "It can't be locked. ";
  2120.     else if ( self.isopen ) "%You%'ll have to close it first. ";
  2121.     }
  2122.     doLock( actor ) =
  2123.     {
  2124.         if ( self.mykey = nil )
  2125.     {
  2126.         "Locked. ";
  2127.         self.islocked := true;
  2128.         if ( self.otherside ) self.otherside.islocked := true;
  2129.     }
  2130.     else
  2131.             askio( withPrep );
  2132.     }
  2133.     verDoUnlock( actor ) =
  2134.     {
  2135.         if ( not self.islocked ) "It's not locked! ";
  2136.     }
  2137.     doUnlock( actor ) =
  2138.     {
  2139.         if ( self.mykey = nil )
  2140.     {
  2141.         "Unlocked. ";
  2142.         self.islocked := nil;
  2143.         if ( self.otherside ) self.otherside.islocked := nil;
  2144.     }
  2145.     else
  2146.         askio( withPrep );
  2147.     }
  2148.     verDoLockWith( actor, io ) =
  2149.     {
  2150.         if ( self.islocked ) "It's already locked. ";
  2151.     else if ( not self.islockable ) "It can't be locked. ";
  2152.     else if ( self.mykey = nil )
  2153.         "%You% %do%n't need anything to lock it. ";
  2154.     else if ( self.isopen ) "%You%'ll have to close it first. ";
  2155.     }
  2156.     doLockWith( actor, io ) =
  2157.     {
  2158.         if ( io = self.mykey )
  2159.     {
  2160.         "Locked. ";
  2161.         self.islocked := true;
  2162.         if ( self.otherside ) self.otherside.islocked := true;
  2163.     }
  2164.     else "It doesn't fit the lock. ";
  2165.     }
  2166.     verDoUnlockWith( actor, io ) =
  2167.     {
  2168.         if ( not self.islocked ) "It's not locked! ";
  2169.     else if ( self.mykey = nil )
  2170.         "%You% %do%n't need anything to unlock it. ";
  2171.     }
  2172.     doUnlockWith( actor, io ) =
  2173.     {
  2174.         if ( io = self.mykey )
  2175.     {
  2176.         "Unlocked. ";
  2177.         self.islocked := nil;
  2178.         if ( self.otherside ) self.otherside.islocked := nil;
  2179.     }
  2180.     else "It doesn't fit the lock. ";
  2181.     }
  2182.     ldesc =
  2183.     {
  2184.     if ( self.isopen ) "It's open. ";
  2185.     else
  2186.     {
  2187.         if ( self.islocked ) "It's closed and locked. ";
  2188.         else "It's closed. ";
  2189.     }
  2190.     }
  2191. ;
  2192.  
  2193. /*
  2194.  *  lockableDoorway: doorway
  2195.  *
  2196.  *  This is just a normal doorway with the islockable and
  2197.  *  islocked properties set to true.  Fill in the other
  2198.  *  properties (otherside and doordest) as usual.  If
  2199.  *  the door has a key, set property mykey to the key object.
  2200. */
  2201. lockableDoorway: doorway
  2202.     islockable = true
  2203.     islocked = true
  2204. ;
  2205.  
  2206. /*
  2207.  *  vehicle: item, nestedroom
  2208.  *
  2209.  *  This is an object that an actor can board.  An actor cannot go
  2210.  *  anywhere while on board a vehicle; the actor must get out first.
  2211. */
  2212. vehicle: item, nestedroom
  2213.     reachable = []
  2214.     isvehicle = true
  2215.     verDoEnter( actor ) = { self.verDoBoard( actor ); }
  2216.     doEnter( actor ) = { self.doBoard( actor ); }
  2217.     verDoBoard( actor ) =
  2218.     {
  2219.         if ( actor.location = self )
  2220.         {
  2221.             "%You're% already in "; self.thedesc; "! ";
  2222.         }
  2223.     }
  2224.     doBoard( actor ) =
  2225.     {
  2226.         "Okay, %you're% now in "; self.thedesc; ". ";
  2227.         actor.moveInto( self );
  2228.     }
  2229.     noexit =
  2230.     {
  2231.         "%You're% not going anywhere until %you% get%s% out of ";
  2232.       self.thedesc; ". ";
  2233.         return( nil );
  2234.     }
  2235.     out = ( self.location )
  2236. ;
  2237.  
  2238. /*
  2239.  *  surface: item
  2240.  *
  2241.  *  Objects can be placed on a surface.  Apart from using the
  2242.  *  preposition "on" rather than "in'' to refer to objects
  2243.  *  contained by the object, a surface is identical to a
  2244.  *  container.  Note: an object cannot be both a
  2245.  *  surface and a container, because there is no
  2246.  *  distinction between the two internally.
  2247. */
  2248. surface: item
  2249.     issurface = true        // Item can hold objects on its surface
  2250.     ldesc =
  2251.     {
  2252.         if (itemcnt( self.contents ))
  2253.         {
  2254.             "On "; self.thedesc; " %you% see%s% "; listcont( self ); ". ";
  2255.         }
  2256.         else
  2257.         {
  2258.             "There's nothing on "; self.thedesc; ". ";
  2259.         }
  2260.     }
  2261.     verIoPutOn( actor ) = {}
  2262.     ioPutOn( actor, do ) =
  2263.     {
  2264.         do.doPutOn( actor, self );
  2265.     }
  2266. ;
  2267.  
  2268. /*
  2269.  *  container: item
  2270.  *
  2271.  *  This object can contain other objects.  The iscontainer property
  2272.  *  is set to true.  The default ldesc displays a list of the
  2273.  *  objects inside the container, if any.  The maxbulk property
  2274.  *  specifies the maximum amount of bulk the container can contain.
  2275. */
  2276. container: item
  2277.     maxbulk = 10            // maximum bulk the container can contain
  2278.     isopen = true           // in fact, it can't be closed at all
  2279.     iscontainer = true      // Item can contain other items
  2280.     ldesc =
  2281.     {
  2282.         if ( self.contentsVisible and itemcnt( self.contents ) <> 0 )
  2283.         {
  2284.             "In "; self.thedesc; " %you% see%s% "; listcont( self ); ". ";
  2285.         }
  2286.         else
  2287.         {
  2288.             "There's nothing in "; self.thedesc; ". ";
  2289.         }
  2290.     }
  2291.     verIoPutIn( actor ) =
  2292.     {
  2293.     }
  2294.     ioPutIn( actor, do ) =
  2295.     {
  2296.         if (addbulk( self.contents ) + do.bulk > self.maxbulk )
  2297.         {
  2298.             "%You% can't fit that in "; self.thedesc; ". ";
  2299.         }
  2300.         else
  2301.         {
  2302.         do.doPutIn( actor, self );
  2303.         }
  2304.     }
  2305.     verDoLookin( actor ) = {}
  2306.     doLookin( actor ) =
  2307.     {
  2308.         self.ldesc;
  2309.     }
  2310. ;
  2311.  
  2312. /*
  2313.  *  openable: container
  2314.  *
  2315.  *  A container that can be opened and closed.  The isopenable
  2316.  *  property is set to true.  The default ldesc displays
  2317.  *  the contents of the container if the container is open, otherwise
  2318.  *  a message saying that the object is closed.
  2319. */
  2320. openable: container
  2321.     contentsReachable = { return( self.isopen ); }
  2322.     contentsVisible = { return( self.isopen ); }
  2323.     isopenable = true
  2324.     ldesc =
  2325.     {
  2326.         caps(); self.thedesc;
  2327.         if ( self.isopen ) " is open. ";
  2328.         else " is closed. ";
  2329.         pass ldesc;
  2330.     }
  2331.     isopen = true
  2332.     verDoOpen( actor ) =
  2333.     {
  2334.         if ( self.isopen )
  2335.     {
  2336.         caps(); self.thedesc; " is already open! ";
  2337.     }
  2338.     }
  2339.     doOpen( actor ) =
  2340.     {
  2341.         if (itemcnt( self.contents ))
  2342.     {
  2343.         "Opening "; self.thedesc; " reveals "; listcont( self ); ". ";
  2344.     }
  2345.     else "Opened. ";
  2346.     self.isopen := true;
  2347.     }
  2348.     verDoClose( actor ) =
  2349.     {
  2350.         if ( not self.isopen )
  2351.     {
  2352.         caps(); self.thedesc; " is already closed! ";
  2353.     }
  2354.     }
  2355.     doClose( actor ) =
  2356.     {
  2357.         "Closed. ";
  2358.     self.isopen := nil;
  2359.     }
  2360.     verIoPutIn( actor ) =
  2361.     {
  2362.         if ( not self.isopen )
  2363.     {
  2364.         caps(); self.thedesc; " is closed. ";
  2365.     }
  2366.     }
  2367.     verDoLookin( actor ) =
  2368.     {
  2369.         if ( not self.isopen ) "It's closed. ";
  2370.     }
  2371. ;
  2372.  
  2373. /*
  2374.  *  qcontainer: container
  2375.  *
  2376.  *  A "quiet" container:  its contents are not listed when it shows
  2377.  *  up in a room description or inventory list.  The isqcontainer
  2378.  *  property is set to true.
  2379. */
  2380. qcontainer: container
  2381.     isqcontainer = true
  2382. ;
  2383.  
  2384. /*
  2385.  *  lockable: openable
  2386.  *
  2387.  *  A container that can be locked and unlocked.  The islocked
  2388.  *  property specifies whether the object can be opened or not.  The
  2389.  *  object can be locked and unlocked without the need for any other
  2390.  *  object; if you want a key to be involved, use a keyedLockable.
  2391. */
  2392. lockable: openable
  2393.     doOpen( actor ) =
  2394.     {
  2395.         if ( self.islocked )
  2396.         {
  2397.             "It's locked. ";
  2398.         }
  2399.         else pass doOpen;
  2400.     }
  2401.     verDoLock( actor ) =
  2402.     {
  2403.         if ( self.islocked )
  2404.         {
  2405.             "It's already locked! ";
  2406.         }
  2407.     }
  2408.     doLock( actor ) =
  2409.     {
  2410.         if ( self.isopen )
  2411.         {
  2412.             "%You%'ll have to close "; self.thedesc; " first. ";
  2413.         }
  2414.         else
  2415.         {
  2416.             "Locked. ";
  2417.             self.islocked := true;
  2418.         }
  2419.     }
  2420.     verDoUnlock( actor ) =
  2421.     {
  2422.         if ( not self.islocked ) "It's not locked! ";
  2423.     }
  2424.     doUnlock( actor ) =
  2425.     {
  2426.         "Unlocked. ";
  2427.         self.islocked := nil;
  2428.     }
  2429.     verDoLockWith( actor, io ) =
  2430.     {
  2431.         if ( self.islocked ) "It's already locked. ";
  2432.     }
  2433.     verDoUnlockWith( actor, io ) =
  2434.     {
  2435.         if ( not self.islocked ) "It's not locked! ";
  2436.     }
  2437. ;
  2438.  
  2439. /*
  2440.  *  keyedLockable: lockable
  2441.  *
  2442.  *  This subclass of lockable allows you to create an object
  2443.  *  that can only be locked and unlocked with a corresponding key.
  2444.  *  Set the property mykey to the keyItem object that can
  2445.  *  lock and unlock the object.
  2446. */
  2447. keyedLockable: lockable
  2448.     mykey = nil     // set 'mykey' to the key which locks/unlocks me
  2449.     doLock( actor ) =
  2450.     {
  2451.         askio( withPrep );
  2452.     }
  2453.     doUnlock( actor ) =
  2454.     {
  2455.         askio( withPrep );
  2456.     }
  2457.     doLockWith( actor, io ) =
  2458.     {
  2459.         if ( self.isopen )
  2460.         {
  2461.             "%You% can't lock << self.thedesc >> when it's open. ";
  2462.         }
  2463.         else if ( io = self.mykey )
  2464.         {
  2465.             "Locked. ";
  2466.             self.islocked := true;
  2467.         }
  2468.         else "It doesn't fit the lock. ";
  2469.     }
  2470.     doUnlockWith( actor, io ) =
  2471.     {
  2472.         if ( io = self.mykey )
  2473.         {
  2474.             "Unlocked. ";
  2475.             self.islocked := nil;
  2476.         }
  2477.         else "It doesn't fit the lock. ";
  2478.     }
  2479. ;
  2480.  
  2481. /*
  2482.  *  keyItem: item
  2483.  *
  2484.  *  This is an object that can be used as a key for a keyedLockable
  2485.  *  object.  It otherwise behaves as an ordinary item.
  2486. */
  2487. keyItem: item
  2488.     verIoUnlockWith( actor ) = {}
  2489.     ioUnlockWith( actor, do ) =
  2490.     {
  2491.         do.doUnlockWith( actor, self );
  2492.     }
  2493.     verIoLockWith( actor ) = {}
  2494.     ioLockWith( actor, do ) =
  2495.     {
  2496.         do.doLockWith( actor, self );
  2497.     }
  2498. ;
  2499.  
  2500. /*
  2501.  *  transparentItem: item
  2502.  *
  2503.  *  An object whose contents are visible, even when the object is
  2504.  *  closed.  Whether the contents are reachable is decided in the
  2505.  *  normal fashion.  This class is useful for items such as glass
  2506.  *  bottles, whose contents can be seen when the bottle is closed
  2507.  *  but cannot be reached.
  2508. */
  2509. class transparentItem: item
  2510.     contentsVisible = { return( true ); }
  2511.     verGrab( obj ) =
  2512.     {
  2513.         if ( self.isopenable and not self.isopen )
  2514.             "%You% will have to open << self.thedesc >> first. ";
  2515.     }
  2516.     doOpen( actor ) =
  2517.     {
  2518.         self.isopen := true;
  2519.         "Opened. ";
  2520.     }
  2521. ;
  2522.  
  2523. /*
  2524.  *  basicNumObj: object
  2525.  *
  2526.  *  This object provides a default implementation for numObj.
  2527.  *  To use this default unchanged in your game, include in your
  2528.  *  game this line:  "numObj: basicNumObj".
  2529. */
  2530. basicNumObj: object              // when a number is used in a player command,
  2531.     value = 0               //  this is set to its value
  2532.     sdesc = "that"
  2533.     adesc = "that"
  2534.     thedesc = "that"
  2535.     verDoTypeOn( actor, io ) = {}
  2536.     doTypeOn( actor, io ) = { "\"Tap, tap, tap, tap...\" "; }
  2537.     verIoTurnTo( actor ) = {}
  2538.     ioTurnTo( actor, do ) = { do.doTurnTo( actor, self ); }
  2539. ;
  2540.  
  2541. /*
  2542.  *  basicStrObj: object
  2543.  *
  2544.  *  This object provides a default implementation for strObj.
  2545.  *  To use this default unchanged in your game, include in your
  2546.  *  game this line:  "strObj: basicStrObj".
  2547. */
  2548. basicStrObj: object              // when a string is used in a player command,
  2549.     value = ''              //  this is set to its value
  2550.     sdesc = "that"
  2551.     adesc = "that"
  2552.     thedesc = "that"
  2553.     verDoTypeOn( actor, io ) = {}
  2554.     doTypeOn( actor, io ) = { "\"Tap, tap, tap, tap...\" "; }
  2555.     verDoSave( actor ) = {}
  2556.     doSave( actor ) =
  2557.     {
  2558.         if (save( self.value ))
  2559.             "Save failed. ";
  2560.         else
  2561.             "Saved. ";
  2562.     abort;
  2563.     }
  2564.     verDoRestore( actor ) = {}
  2565.     doRestore( actor ) =
  2566.     {
  2567.         if (restore( self.value ))
  2568.             "Restore failed. ";
  2569.         else
  2570.     {
  2571.             "Restored. ";
  2572.         setscore( global.score, global.turnsofar );
  2573.     }
  2574.         abort;
  2575.     }
  2576.     verDoScript( actor ) = {}
  2577.     doScript( actor ) =
  2578.     {
  2579.         logging( self.value );
  2580.         "Writing script file. ";
  2581.         abort;
  2582.     }
  2583.     verDoSay( actor ) = {}
  2584.     doSay( actor ) =
  2585.     {
  2586.         "Okay, \""; say( self.value ); "\".";
  2587.     }
  2588. ;
  2589.  
  2590. /*
  2591.  *  deepverb: object
  2592.  *
  2593.  *  A "verb object" that is referenced by the parser when the player
  2594.  *  uses an associated vocabulary word.  A deepverb contains both
  2595.  *  the vocabulary of the verb and a description of available syntax.
  2596.  *  The verb property lists the vocabulary words known as verbs;
  2597.  *  one word (such as 'take') or a pair (such as 'pick up')
  2598.  *  can be used.  In the latter case, the second word must be a
  2599.  *  preposition, and may move to the end of the sentence in a player's
  2600.  *  command, as in "pick it up."  The action( actor )
  2601.  *  method specifies what happens when the verb is used without any
  2602.  *  objects; its absence specifies that the verb cannot be used without
  2603.  *  an object.  The doAction specifies the root of the message
  2604.  *  names (in single quotes) sent to the direct object when the verb
  2605.  *  is used with a direct object; its absence means that a single object
  2606.  *  is not allowed.  Likewise, the ioAction( preposition )
  2607.  *  specifies the root of the message name sent to the direct and
  2608.  *  indirect objects when the verb is used with both a direct and
  2609.  *  indirect object; its absence means that this syntax is illegal.
  2610.  *  Several ioAction properties may be present:  one for each
  2611.  *  preposition that can be used with an indirect object with the verb.
  2612.  *  
  2613.  *  The validDo( actor, object, seqno ) method returns true
  2614.  *  if the indicated object is valid as a direct object for this actor.
  2615.  *  The validIo( actor, object, seqno ) method does likewise
  2616.  *  for indirect objects.  The seqno parameter is a "sequence
  2617.  *  number," starting with 1 for the first object tried for a given
  2618.  *  verb, 2 for the second, and so forth; this parameter is normally
  2619.  *  ignored, but can be used for some special purposes.  For example,
  2620.  *  askVerb does not distinguish between objects matching vocabulary
  2621.  *  words, and therefore accepts only the first from a set of ambiguous
  2622.  *  objects.  These methods do not normally need to be changed; by
  2623.  *  default, they return true if the object is accessible to the
  2624.  *  actor.
  2625.  *  
  2626.  *  The doDefault( actor, prep, indirectObject ) and
  2627.  *  ioDefault( actor, prep ) methods return a list of the
  2628.  *  default direct and indirect objects, respectively.  These lists
  2629.  *  are used for determining which objects are meant by "all" and which
  2630.  *  should be used when the player command is missing an object.  These
  2631.  *  normally return a list of all objects that are applicable to the
  2632.  *  current command.
  2633. */
  2634. deepverb: object                // A deep-structure verb.
  2635.     validDo( actor, obj, seqno ) =
  2636.     {
  2637.         return( obj.isReachable( actor ));
  2638.     }
  2639.     invalidObj( actor, obj, name ) =
  2640.     {
  2641.         if ( not obj.isVisible( actor ))
  2642.             "I don't see any << name >> here. ";
  2643.         else
  2644.             "%You% can't do that with << obj.thedesc >>. ";
  2645.     }
  2646.     validIo( actor, obj, seqno ) =
  2647.     {
  2648.         return( obj.isReachable( actor ));
  2649.     }
  2650.     doDefault( actor, prep, io ) =
  2651.     {
  2652.         return( actor.contents + actor.location.contents );
  2653.     }
  2654.     ioDefault( actor, prep ) =
  2655.     {
  2656.         return( actor.contents + actor.location.contents );
  2657.     }
  2658. ;
  2659.  
  2660. /*
  2661.  *   Various verbs.
  2662.  */
  2663. inspectVerb: deepverb
  2664.     verb = 'inspect' 'examine' 'look at' 'x'
  2665.     sdesc = "inspect"
  2666.     doAction = 'Inspect'
  2667.     validDo( actor, obj, seqno ) =
  2668.     {
  2669.         return( obj.isVisible( actor ));
  2670.     }
  2671. ;
  2672. askVerb: deepverb
  2673.     verb = 'ask'
  2674.     sdesc = "ask"
  2675.     prepDefault = aboutPrep
  2676.     ioAction( aboutPrep ) = 'AskAbout'
  2677.     validIo( actor, obj, seqno ) = { return( seqno = 1 ); }
  2678. ;
  2679. tellVerb: deepverb
  2680.     verb = 'tell'
  2681.     sdesc = "tell"
  2682.     prepDefault = aboutPrep
  2683.     ioAction( aboutPrep ) = 'TellAbout'
  2684.     validIo( actor, obj, seqno ) = { return( seqno = 1 ); }
  2685. ;
  2686. followVerb: deepverb
  2687.     sdesc = "follow"
  2688.     verb = 'follow'
  2689.     doAction = 'Follow'
  2690. ;
  2691. digVerb: deepverb
  2692.     verb = 'dig' 'dig in'
  2693.     sdesc = "dig in"
  2694.     prepDefault = withPrep
  2695.     ioAction( withPrep ) = 'DigWith'
  2696. ;
  2697. jumpVerb: deepverb
  2698.     verb = 'jump' 'jump over' 'jump off'
  2699.     doAction = 'Jump'
  2700.     action = { "Wheeee!"; }
  2701. ;
  2702. pushVerb: deepverb
  2703.     verb = 'push' 'press'
  2704.     sdesc = "push"
  2705.     doAction = 'Push'
  2706. ;
  2707. attachVerb: deepverb
  2708.     verb = 'attach' 'connect'
  2709.     sdesc = "attach"
  2710.     prepDefault = toPrep
  2711.     ioAction( toPrep ) = 'AttachTo'
  2712. ;
  2713. wearVerb: deepverb
  2714.     verb = 'wear' 'put on'
  2715.     sdesc = "wear"
  2716.     doAction = 'Wear'
  2717. ;
  2718. dropVerb: deepverb
  2719.     verb = 'drop' 'put down'
  2720.     sdesc = "drop"
  2721.     ioAction( onPrep ) = 'PutOn'
  2722.     doAction = 'Drop'
  2723.     doDefault( actor, prep, io ) =
  2724.     {
  2725.         return( actor.contents );
  2726.     }
  2727. ;
  2728. removeVerb: deepverb
  2729.     verb = 'take off'
  2730.     sdesc = "take off"
  2731.     doAction = 'Unwear'
  2732.     ioAction( fromPrep ) = 'RemoveFrom'
  2733. ;
  2734. openVerb: deepverb
  2735.     verb = 'open'
  2736.     sdesc = "open"
  2737.     doAction = 'Open'
  2738. ;
  2739. closeVerb: deepverb
  2740.     verb = 'close'
  2741.     sdesc = "close"
  2742.     doAction = 'Close'
  2743. ;
  2744. putVerb: deepverb
  2745.     verb = 'put' 'place'
  2746.     sdesc = "put"
  2747.     prepDefault = inPrep
  2748.     ioAction( inPrep ) = 'PutIn'
  2749.     ioAction( onPrep ) = 'PutOn'
  2750.     doDefault( actor, prep, io ) =
  2751.     {
  2752.         return( takeVerb.doDefault( actor, prep, io ) + actor.contents );
  2753.     }
  2754. ;
  2755. takeVerb: deepverb                   // This object defines how to take things
  2756.     verb = 'take' 'pick up' 'get' 'remove'
  2757.     sdesc = "take"
  2758.     ioAction( offPrep ) = 'TakeOff'
  2759.     ioAction( outPrep ) = 'TakeOut'
  2760.     ioAction( fromPrep ) = 'TakeOut'
  2761.     ioAction( inPrep ) = 'TakeOut'
  2762.     ioAction( onPrep ) = 'TakeOff'
  2763.     doAction = 'Take'
  2764.     doDefault( actor, prep, io ) =
  2765.     {
  2766.         local ret, rem, cur, rem2, cur2, tot, i, tot2, j;
  2767.     
  2768.     ret := [];
  2769.         
  2770.     /*
  2771.      *   For "take all out/off of <iobj>", return the (non-fixed)
  2772.      *   contents of the indirect object.  Same goes for "take all in
  2773.      *   <iobj>", "take all on <iobj>", and "take all from <iobj>".
  2774.      */
  2775.     if (( prep=outPrep or prep=offPrep or prep=inPrep or prep=onPrep
  2776.      or prep=fromPrep ) and io<>nil )
  2777.     {
  2778.         rem := io.contents;
  2779.         i := 1;
  2780.         tot := length( rem );
  2781.         while ( i <= tot )
  2782.         {
  2783.             cur := rem[i];
  2784.             if ( not cur.isfixed ) ret := ret + cur;
  2785.         i := i + 1;
  2786.         }
  2787.             return( ret );
  2788.     }
  2789.  
  2790.         /*
  2791.      *   In the general case, return everything that's not fixed
  2792.      *   in the actor's location, or everything inside fixed containers
  2793.      *   that isn't itself fixed.
  2794.      */
  2795.         rem := actor.location.contents;
  2796.     tot := length( rem );
  2797.     i := 1;
  2798.         while ( i <= tot )
  2799.         {
  2800.         cur := rem[i];
  2801.             if ( cur.isfixed )
  2802.             {
  2803.                 if ((( cur.isopenable and cur.isopen ) or
  2804.                   ( not cur.isopenable )) and ( not cur.isactor ))
  2805.                 {
  2806.                     rem2 := cur.contents;
  2807.             tot2 := length( rem2 );
  2808.             j := 1;
  2809.                     while ( j <= tot2 )
  2810.                     {
  2811.                 cur2 := rem2[j];
  2812.                         if ( not cur2.isfixed and not cur2.notakeall )
  2813.             {
  2814.                 ret := ret + cur2;
  2815.             }
  2816.                         j := j + 1;
  2817.                     }
  2818.                 }
  2819.             }
  2820.             else if ( not cur.notakeall )
  2821.         {
  2822.             ret := ret + cur;
  2823.         }
  2824.  
  2825.         i := i + 1;            
  2826.         }
  2827.         return( ret );
  2828.     }
  2829. ;
  2830. plugVerb: deepverb
  2831.     verb = 'plug'
  2832.     sdesc = "plug"
  2833.     prepDefault = inPrep
  2834.     ioAction( inPrep ) = 'PlugIn'
  2835. ;
  2836. lookInVerb: deepverb
  2837.     verb = 'look in' 'look on'
  2838.     sdesc = "look in"
  2839.     doAction = 'Lookin'
  2840. ;
  2841. screwVerb: deepverb
  2842.     verb = 'screw'
  2843.     sdesc = "screw"
  2844.     ioAction( withPrep ) = 'ScrewWith'
  2845.     doAction = 'Screw'
  2846. ;
  2847. unscrewVerb: deepverb
  2848.     verb = 'unscrew'
  2849.     sdesc = "unscrew"
  2850.     ioAction( withPrep ) = 'UnscrewWith'
  2851.     doAction = 'Unscrew'
  2852. ;
  2853. turnVerb: deepverb
  2854.     verb = 'turn' 'rotate' 'twist'
  2855.     sdesc = "turn"
  2856.     ioAction( toPrep ) = 'TurnTo'
  2857.     ioAction( withPrep ) = 'TurnWith'
  2858.     doAction = 'Turn'
  2859. ;
  2860. switchVerb: deepverb
  2861.     verb = 'switch'
  2862.     sdesc = "switch"
  2863.     doAction = 'Switch'
  2864. ;
  2865. flipVerb: deepverb
  2866.     verb = 'flip'
  2867.     sdesc = "flip"
  2868.     doAction = 'Flip'
  2869. ;
  2870. turnOnVerb: deepverb
  2871.     verb = 'activate' 'turn on' 'switch on'
  2872.     sdesc = "turn on"
  2873.     doAction = 'Turnon'
  2874. ;
  2875. turnOffVerb: deepverb
  2876.     verb = 'turn off' 'deactiv' 'switch off'
  2877.     sdesc = "turn off"
  2878.     doAction = 'Turnoff'
  2879. ;
  2880. lookVerb: deepverb
  2881.     verb = 'look' 'l' 'look around'
  2882.     action( actor ) =
  2883.     {
  2884.         actor.location.lookAround( true );
  2885.     }
  2886. ;
  2887. sitVerb: deepverb
  2888.     verb = 'sit on' 'sit in' 'sit' 'sit down' 'sit downin' 'sit downon'
  2889.     sdesc = "sit on"
  2890.     doAction = 'Siton'
  2891. ;
  2892. lieVerb: deepverb
  2893.     verb = 'lie' 'lie on' 'lie in' 'lie down' 'lie downon' 'lie downin'
  2894.     sdesc = "lie on"
  2895.     doAction = 'Lieon'
  2896. ;
  2897. getOutVerb: deepverb
  2898.     verb = 'get out' 'get outof' 'get off' 'get offof'
  2899.     sdesc = "get out of"
  2900.     doAction = 'Unboard'
  2901.     doDefault( actor, prep, io ) =
  2902.     {
  2903.         if ( actor.location and actor.location.location )
  2904.             return( [] + actor.location );
  2905.         else return( [] );
  2906.     }
  2907. ;
  2908. boardVerb: deepverb
  2909.     verb = 'get in' 'get into' 'board' 'get on'
  2910.     sdesc = "get on"
  2911.     doAction = 'Board'
  2912. ;
  2913. againVerb: deepverb         // Required verb:  repeats last command.  No
  2914.                             // action routines are necessary; this one's
  2915.                             // handled internally by the parser.
  2916.     verb = 'again' 'g'
  2917. ;
  2918. waitVerb: deepverb
  2919.     verb = 'wait' 'z'
  2920.     action( actor ) =
  2921.     {
  2922.         "Time passes...\n";
  2923.     }
  2924. ;
  2925. iVerb: deepverb
  2926.     verb = 'inventory' 'i'
  2927.     action( actor ) =
  2928.     {
  2929.         if (length( actor.contents ))
  2930.         {
  2931.             "%You% %have% "; listcont( actor ); ". ";
  2932.             listcontcont( actor );
  2933.         }
  2934.     else
  2935.             "%You% %are% empty-handed.\n";
  2936.     }
  2937. ;
  2938. lookThruVerb: deepverb
  2939.     verb = 'look through' 'look thru'
  2940.     sdesc = "look through"
  2941.     doAction = 'Lookthru'
  2942. ;
  2943. attackVerb: deepverb
  2944.     verb = 'attack' 'kill' 'hit'
  2945.     sdesc = "attack"
  2946.     prepDefault = withPrep
  2947.     ioAction( withPrep ) = 'AttackWith'
  2948. ;
  2949. climbVerb: deepverb
  2950.     verb = 'climb'
  2951.     sdesc = "climb"
  2952.     doAction = 'Climb'
  2953. ;
  2954. eatVerb: deepverb
  2955.     verb = 'eat' 'consume'
  2956.     sdesc = "eat"
  2957.     doAction = 'Eat'
  2958. ;
  2959. drinkVerb: deepverb
  2960.     verb = 'drink'
  2961.     sdesc = "drink"
  2962.     doAction = 'Drink'
  2963. ;
  2964. giveVerb: deepverb
  2965.     verb = 'give' 'offer'
  2966.     sdesc = "give"
  2967.     prepDefault = toPrep
  2968.     ioAction( toPrep ) = 'GiveTo'
  2969. ;
  2970. pullVerb: deepverb
  2971.     verb = 'pull'
  2972.     sdesc = "pull"
  2973.     doAction = 'Pull'
  2974. ;
  2975. readVerb: deepverb
  2976.     verb = 'read'
  2977.     sdesc = "read"
  2978.     doAction = 'Read'
  2979. ;
  2980. throwVerb: deepverb
  2981.     verb = 'throw' 'toss'
  2982.     sdesc = "throw"
  2983.     prepDefault = atPrep
  2984.     ioAction( atPrep ) = 'ThrowAt'
  2985.     ioAction( toPrep ) = 'ThrowTo'
  2986. ;
  2987. standOnVerb: deepverb
  2988.     verb = 'stand on'
  2989.     sdesc = "stand on"
  2990.     doAction = 'Standon'
  2991. ;
  2992. standVerb: deepverb
  2993.     verb = 'stand' 'stand up' 'get up'
  2994.     sdesc = "stand"
  2995.     action( actor ) =
  2996.     {
  2997.         if ( actor.location=nil or actor.location.location = nil )
  2998.             "%You're% already standing! ";
  2999.         else
  3000.         {
  3001.         actor.location.doUnboard( actor );
  3002.         }
  3003.     }
  3004. ;
  3005. helloVerb: deepverb
  3006.     verb = 'hello' 'hi' 'greetings'
  3007.     action( actor ) =
  3008.     {
  3009.         "Nice weather we've been having.\n";
  3010.     }
  3011. ;
  3012. showVerb: deepverb
  3013.     verb = 'show'
  3014.     sdesc = "show"
  3015.     prepDefault = toPrep
  3016.     ioAction( toPrep ) = 'ShowTo'
  3017. ;
  3018. cleanVerb: deepverb
  3019.     verb = 'clean'
  3020.     sdesc = "clean"
  3021.     ioAction( withPrep ) = 'CleanWith'
  3022.     doAction = 'Clean'
  3023. ;
  3024. sayVerb: deepverb
  3025.     verb = 'say'
  3026.     sdesc = "say"
  3027.     doAction = 'Say'
  3028. ;
  3029. yellVerb: deepverb
  3030.     verb = 'yell' 'shout' 'yell at' 'shout at'
  3031.     action( actor ) =
  3032.     {
  3033.         "%Your% throat is a bit sore now. ";
  3034.     }
  3035. ;
  3036. moveVerb: deepverb
  3037.     verb = 'move'
  3038.     sdesc = "move"
  3039.     ioAction( withPrep ) = 'MoveWith'
  3040.     ioAction( toPrep ) = 'MoveTo'
  3041.     doAction = 'Move'
  3042. ;
  3043. fastenVerb: deepverb
  3044.     verb = 'fasten' 'buckle' 'buckle up'
  3045.     sdesc = "fasten"
  3046.     doAction = 'Fasten'
  3047. ;
  3048. unfastenVerb: deepverb
  3049.     verb = 'unfasten' 'unbuckle'
  3050.     sdesc = "unfasten"
  3051.     doAction = 'Unfasten'
  3052. ;
  3053. unplugVerb: deepverb
  3054.     verb = 'unplug'
  3055.     sdesc = "unplug"
  3056.     ioAction( fromPrep ) = 'UnplugFrom'
  3057.     doAction = 'Unplug'
  3058. ;
  3059. lookUnderVerb: deepverb
  3060.     verb = 'look under' 'look beneath'
  3061.     sdesc = "look under"
  3062.     doAction = 'Lookunder'
  3063. ;
  3064. lookBehindVerb: deepverb
  3065.     verb = 'look behind'
  3066.     sdesc = "look behind"
  3067.     doAction = 'Lookbehind'
  3068. ;
  3069. typeVerb: deepverb
  3070.     verb = 'type'
  3071.     sdesc = "type"
  3072.     prepDefault = onPrep
  3073.     ioAction( onPrep ) = 'TypeOn'
  3074. ;
  3075. lockVerb: deepverb
  3076.     verb = 'lock'
  3077.     sdesc = "lock"
  3078.     ioAction( withPrep ) = 'LockWith'
  3079.     doAction = 'Lock'
  3080.     prepDefault = withPrep
  3081. ;
  3082. unlockVerb: deepverb
  3083.     verb = 'unlock'
  3084.     sdesc = "unlock"
  3085.     ioAction( withPrep ) = 'UnlockWith'
  3086.     doAction = 'Unlock'
  3087.     prepDefault = withPrep
  3088. ;
  3089. detachVerb: deepverb
  3090.     verb = 'detach' 'disconnect'
  3091.     prepDefault = fromPrep
  3092.     ioAction( fromPrep ) = 'DetachFrom'
  3093.     doAction = 'Detach'
  3094.     sdesc = "detach"
  3095. ;
  3096. sleepVerb: deepverb
  3097.     action( actor ) =
  3098.     {
  3099.         if ( actor.cantSleep )
  3100.             "%You% %are% much too anxious worrying about %your% continued
  3101.             survival to fall asleep now. ";
  3102.         else if ( global.awakeTime+1 < global.sleepTime )
  3103.             "%You're% not tired. ";
  3104.         else if ( not ( actor.location.isbed or actor.location.ischair ))
  3105.             "I don't know about you, but I can never sleep
  3106.             standing up. %You% should find a nice comfortable
  3107.             bed somewhere. ";
  3108.         else
  3109.         {
  3110.             "%You% quickly drift%s% off into dreamland...\b";
  3111.             goToSleep();
  3112.         }
  3113.     }
  3114.     verb = 'sleep'
  3115. ;
  3116. pokeVerb: deepverb
  3117.     verb = 'poke' 'jab'
  3118.     sdesc = "poke"
  3119.     doAction = 'Poke'
  3120. ;
  3121. touchVerb: deepverb
  3122.     verb = 'touch'
  3123.     sdesc = "touch"
  3124.     doAction = 'Touch'
  3125. ;
  3126. moveNVerb: deepverb
  3127.     verb = 'move north' 'move n' 'push north' 'push n'
  3128.     sdesc = "move north"
  3129.     doAction = 'MoveN'
  3130. ;
  3131. moveSVerb: deepverb
  3132.     verb = 'move south' 'move s' 'push south' 'push s'
  3133.     sdesc = "move south"
  3134.     doAction = 'MoveS'
  3135. ;
  3136. moveEVerb: deepverb
  3137.     verb = 'move east' 'move e' 'push east' 'push e'
  3138.     sdesc = "move east"
  3139.     doAction = 'MoveE'
  3140. ;
  3141. moveWVerb: deepverb
  3142.     verb = 'move west' 'move w' 'push west' 'push w'
  3143.     sdesc = "move west"
  3144.     doAction = 'MoveW'
  3145. ;
  3146. moveNEVerb: deepverb
  3147.     verb = 'move northeast' 'move ne' 'push northeast' 'push ne'
  3148.     sdesc = "move northeast"
  3149.     doAction = 'MoveNE'
  3150. ;
  3151. moveNWVerb: deepverb
  3152.     verb = 'move northwest' 'move nw' 'push northwest' 'push nw'
  3153.     sdesc = "move northwest"
  3154.     doAction = 'MoveNW'
  3155. ;
  3156. moveSEVerb: deepverb
  3157.     verb = 'move southeast' 'move se' 'push southeast' 'push se'
  3158.     sdesc = "move southeast"
  3159.     doAction = 'MoveSE'
  3160. ;
  3161. moveSWVerb: deepverb
  3162.     verb = 'move southwest' 'move sw' 'push southwest' 'push sw'
  3163.     sdesc = "move southwest"
  3164.     doAction = 'MoveSW'
  3165. ;
  3166. centerVerb: deepverb
  3167.     verb = 'center'
  3168.     sdesc = "center"
  3169.     doAction = 'Center'
  3170. ;
  3171. searchVerb: deepverb
  3172.     verb = 'search'
  3173.     sdesc = "search"
  3174.     doAction = 'Search'
  3175. ;
  3176.  
  3177. /*
  3178.  *   Travel verbs  - these verbs allow the player to move about.
  3179.  *   All travel verbs have the property isTravelVerb set true.
  3180.  */
  3181. class travelVerb: deepverb
  3182.     isTravelVerb = true
  3183. ;
  3184. eVerb: travelVerb
  3185.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3186.     verb = 'e' 'east' 'go east'
  3187.     travelDir( actor ) = { return( actor.location.east ); }
  3188. ;
  3189. sVerb: travelVerb
  3190.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3191.     verb = 's' 'south' 'go south'
  3192.     travelDir( actor ) = { return( actor.location.south ); }
  3193. ;
  3194. nVerb: travelVerb
  3195.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3196.     verb = 'n' 'north' 'go north'
  3197.     travelDir( actor ) = { return( actor.location.north ); }
  3198. ;
  3199. wVerb: travelVerb
  3200.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3201.     verb = 'w' 'west' 'go west'
  3202.     travelDir( actor ) = { return( actor.location.west ); }
  3203. ;
  3204. neVerb: travelVerb
  3205.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3206.     verb = 'ne' 'northeast' 'go ne' 'go northeast'
  3207.     travelDir( actor ) = { return( actor.location.ne ); }
  3208. ;
  3209. nwVerb: travelVerb
  3210.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3211.     verb = 'nw' 'northwest' 'go nw' 'go northwest'
  3212.     travelDir( actor ) = { return( actor.location.nw ); }
  3213. ;
  3214. seVerb: travelVerb
  3215.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3216.     verb = 'se' 'southeast' 'go se' 'go southeast'
  3217.     travelDir( actor ) = { return( actor.location.se ); }
  3218. ;
  3219. swVerb: travelVerb
  3220.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3221.     verb = 'sw' 'southwest' 'go sw' 'go southwest'
  3222.     travelDir( actor ) = { return( actor.location.sw ); }
  3223. ;
  3224. inVerb: travelVerb
  3225.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3226.     verb = 'in' 'go in' 'enter'
  3227.     sdesc = "enter"
  3228.     doAction = 'Enter'
  3229.     travelDir( actor ) = { return( actor.location.in ); }
  3230. ;
  3231. outVerb: travelVerb
  3232.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3233.     verb = 'out' 'go out' 'exit' 'leave'
  3234.     travelDir( actor ) = { return( actor.location.out ); }
  3235. ;
  3236. dVerb: travelVerb
  3237.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3238.     verb = 'd' 'down' 'go down'
  3239.     travelDir( actor ) = { return( actor.location.down ); }
  3240. ;
  3241. uVerb: travelVerb
  3242.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3243.     verb = 'u' 'up' 'go up'
  3244.     travelDir( actor ) = { return( actor.location.up ); }
  3245. ;
  3246.  
  3247. /*
  3248.  *   sysverb:  A system verb.  Verbs of this class are special verbs that
  3249.  *   can be executed without certain normal validations.  For example,
  3250.  *   a system verb can be executed in a dark room.  System verbs are
  3251.  *   for operations such as saving, restoring, and quitting, which are
  3252.  *   not really part of the game.
  3253.  */
  3254. sysverb: deepverb
  3255.     issysverb = true
  3256. ;
  3257. quitVerb: sysverb
  3258.     verb = 'quit'
  3259.     action( actor ) =
  3260.     {
  3261.         local yesno;
  3262.  
  3263.         scoreRank();
  3264.         "\bDo you really want to quit? (YES or NO) > ";
  3265.         yesno := yorn();
  3266.         "\b";
  3267.         if ( yesno = 1 )
  3268.         {
  3269.             terminate();    // allow user good-bye message
  3270.         quit();
  3271.         }
  3272.         else
  3273.         {
  3274.             "Okay. ";
  3275.         }
  3276.     abort;
  3277.     }
  3278. ;
  3279. verboseVerb: sysverb
  3280.     verb = 'verbose'
  3281.     action( actor ) =
  3282.     {
  3283.         "Okay, now in VERBOSE mode.\n";
  3284.         global.verbose := true;
  3285.     Me.location.lookAround( true );
  3286.     abort;
  3287.     }
  3288. ;
  3289. terseVerb: sysverb
  3290.     verb = 'brief' 'terse'
  3291.     action( actor ) =
  3292.     {
  3293.         "Okay, now in TERSE mode.\n";
  3294.         global.verbose := nil;
  3295.     abort;
  3296.     }
  3297. ;
  3298. scoreVerb: sysverb
  3299.     verb = 'score' 'status'
  3300.     action( actor ) =
  3301.     {
  3302.         scoreRank();
  3303.     abort;
  3304.     }
  3305. ;
  3306. saveVerb: sysverb
  3307.     verb = 'save'
  3308.     sdesc = "save"
  3309.     doAction = 'Save'
  3310.     action( actor ) =
  3311.     {
  3312.         local savefile;
  3313.     
  3314.     savefile := askfile( 'File to save game in' );
  3315.     if ( savefile = nil or savefile = '' )
  3316.         "Failed. ";
  3317.     else if (save( savefile ))
  3318.         "Saved failed. ";
  3319.     else
  3320.         "Saved. ";
  3321.     abort;
  3322.     }
  3323. ;
  3324. restoreVerb: sysverb
  3325.     verb = 'restore'
  3326.     sdesc = "restore"
  3327.     doAction = 'Restore'
  3328.     action( actor ) =
  3329.     {
  3330.         local savefile;
  3331.     
  3332.     savefile := askfile( 'File to restore game from' );
  3333.     if ( savefile = nil or savefile = '' )
  3334.         "Failed. ";
  3335.     else if (restore( savefile ))
  3336.         "Restore failed. ";
  3337.     else
  3338.     {
  3339.         setscore( global.score, global.turnsofar );
  3340.         "Restored. ";
  3341.     }
  3342.     abort;
  3343.     }
  3344. ;
  3345. scriptVerb: sysverb
  3346.     verb = 'script'
  3347.     doAction = 'Script'
  3348.     action( actor ) =
  3349.     {
  3350.         local scriptfile;
  3351.     
  3352.     scriptfile := askfile( 'File to write transcript to' );
  3353.     if ( scriptfile = nil or scriptfile = '' )
  3354.         "Failed. ";
  3355.     else
  3356.     {
  3357.         logging( scriptfile );
  3358.         "Writing script file. ";
  3359.     }
  3360.     abort;
  3361.     }
  3362. ;
  3363. unscriptVerb: sysverb
  3364.     verb = 'unscript'
  3365.     action( actor ) =
  3366.     {
  3367.         logging( nil );
  3368.         "Script closed.\n";
  3369.         abort;
  3370.     }
  3371. ;
  3372. restartVerb: sysverb
  3373.     verb = 'restart'
  3374.     action( actor ) =
  3375.     {
  3376.         local yesno;
  3377.         while ( true )
  3378.         {
  3379.             "Are you sure you want to start over? (YES or NO) > ";
  3380.             yesno := yorn();
  3381.             if ( yesno = 1 )
  3382.             {
  3383.                 "\n";
  3384.         setscore( 0, 0 );
  3385.                 restart();
  3386.                 abort;
  3387.             }
  3388.             else if ( yesno = 0 )
  3389.             {
  3390.                 "\nOkay.\n";
  3391.                 abort;
  3392.             }
  3393.         }
  3394.     }
  3395. ;
  3396. versionVerb: sysverb
  3397.     verb = 'version'
  3398.     action( actor ) =
  3399.     {
  3400.         version.sdesc;
  3401.         abort;
  3402.     }
  3403. ;
  3404. debugVerb: sysverb
  3405.     verb = 'debug'
  3406.     action( actor ) =
  3407.     {
  3408.     if (debugTrace())
  3409.         "You can't think this game has any bugs left in it... ";
  3410.     abort;
  3411.     }
  3412. ;
  3413.  
  3414. /*
  3415.  *  Prep: object
  3416.  *
  3417.  *  A preposition.  The preposition property specifies the
  3418.  *  vocabulary word.
  3419. */
  3420. Prep: object
  3421. ;
  3422.  
  3423. /*
  3424.  *   Various prepositions
  3425.  */
  3426. aboutPrep: Prep
  3427.     preposition = 'about'
  3428.     sdesc = "about"
  3429. ;
  3430. withPrep: Prep
  3431.     preposition = 'with'
  3432.     sdesc = "with"
  3433. ;
  3434. toPrep: Prep
  3435.     preposition = 'to'
  3436.     sdesc = "to"
  3437. ;
  3438. onPrep: Prep
  3439.     preposition = 'on' 'onto' 'downon' 'upon'
  3440.     sdesc = "on"
  3441. ;
  3442. inPrep: Prep
  3443.     preposition = 'in' 'into' 'downin'
  3444.     sdesc = "in"
  3445. ;
  3446. offPrep: Prep
  3447.     preposition = 'off' 'offof'
  3448.     sdesc = "off"
  3449. ;
  3450. outPrep: Prep
  3451.     preposition = 'out' 'outof'
  3452.     sdesc = "out"
  3453. ;
  3454. fromPrep: Prep
  3455.     preposition = 'from'
  3456.     sdesc = "from"
  3457. ;
  3458. betweenPrep: Prep
  3459.     preposition = 'between' 'inbetween'
  3460.     sdesc = "between"
  3461. ;
  3462. overPrep: Prep
  3463.     preposition = 'over'
  3464.     sdesc = "over"
  3465. ;
  3466. atPrep: Prep
  3467.     preposition = 'at'
  3468.     sdesc = "at"
  3469. ;
  3470. aroundPrep: Prep
  3471.     preposition = 'around'
  3472.     sdesc = "around"
  3473. ;
  3474. thruPrep: Prep
  3475.     preposition = 'through' 'thru'
  3476.     sdesc = "through"
  3477. ;
  3478. dirPrep: Prep
  3479.     preposition = 'north' 'south' 'east' 'west' 'up' 'down' 'northeast' 'ne'
  3480.                   'northwest' 'nw' 'southeast' 'se' 'southwest' 'sw'
  3481.     sdesc = "north"         // Shouldn't ever need this, but just in case
  3482. ;
  3483. underPrep: Prep
  3484.     preposition = 'under' 'beneath'
  3485.     sdesc = "under"
  3486. ;
  3487. behindPrep: Prep
  3488.     preposition = 'behind'
  3489.     sdesc = "behind"
  3490. ;
  3491.  
  3492. /*
  3493.  *   articles:  the "built-in" articles.  "The," "a," and "an" are
  3494.  *   defined.
  3495.  */
  3496. articles: object
  3497.     article = 'the' 'a' 'an'
  3498. ;
  3499.