             Parser Summary and Quick Reference

------------------------------------------------------------
      This file is part of the TADS Author's Manual.
Copyright (c) 1987 - 2001 by Michael J. Roberts. All rights
                          reserved.

              Edited by N. K. Guy, tela design.

------------------------------------------------------------
Chapter Seven

------------------------------------------------------------
Parser Summary and Quick Reference

     This section summarizes the entire sequence of
     function and method calls that the parser makes
     in the course of parsing and executing a command.

Reading a Command Line

     The first thing the parser does at the start of
     each turn is read a new command line.

       commandPrompt(0);
       // the parser next reads a line of input from the keyboard
       commandAfterRead(0);

     If commandPrompt() isn't defined, the parser
     simply displays its default prompt, a blank line
     followed by a greater-than sign (">"). If
     commandAfterRead() isn't defined, the parser does
     nothing extra.

preparse

     After reading the command line, the parser
     invokes preparse(), if defined.

       preparse(commandString);

Parsing

     Next, the parser breaks the command into words,
     then divides the command into sentences if
     multiple sentences, separated with "then",
     periods, semicolons, or other unambiguous
     sentence separators, are present. The parser then
     parses and executes each sentence individually.

     The first step in parsing a sentence is checking
     for an actor. If the sentence starts with a noun
     phrase followed by a comma, the parser takes the
     noun phrase to refer to an actor.

     After reading the noun phrase specifying the
     actor, the parser finds the other parts of the
     command: the verb and its associated preposition
     (for example, the parser considers the word "up"
     in "pick up" to be the verb preposition, because
     it's effectively part of the verb); the direct
     object; the preposition introducing the indirect
     object (for example, the word "on" in "put box on
     shelf"); and the indirect object. Apart from the
     verb, all of these parts are optional.

     Throughout this parsing phase, the parser invokes
     the game-defined parseNounPhrase(), if present,
     to allow the game to perform custom noun phrase
     parsing.

       parseNounPhrase(wordlist, typelist, currentIndex,
                       complainOnNoMatch, isActorCheck);

     If the parser cannot identify a suitable verb, or
     if the sentence structure does not match a syntax
     pattern that the parser recognizes, the parser
     invokes the game-defined parseUnknownVerb()
     function, if defined.

       parseUnknownVerb(actor, wordlist, typelist, errnum);

Execution Sequence

     Once the parser has finished parsing the command,
     the parser executes the command. On a command
     line with more than one command, the parser
     executes the first command before starting to
     parse the second.

     To execute the command, the parser first invokes
     the preparseCmd() function, if defined by the
     game, passing a list of the strings making up the
     tokens of the command.

       preparseCmd(wordlist);

     Next, the parser identifies the deepverb object
     for the command's verb. Once the verb is
     identified, the parser invokes the roomCheck
     method in the current player character's Actor
     object.

       parserGetMe().roomCheck(verb);

     The parser now resolves and disambiguates any
     noun phrases in the command. (Note that the noun
     phrases were already parsed earlier, during the
     parsing phase; at this point, the parser resolves
     the words of the noun phrases to the game objects
     to which they refer.) To perform disambiguation,
     the parser invokes validDoList, validIoList,
     validDo, validIo, and the verification methods,
     verIoVerb (for an indirect object) and verDoVerb
     (for a direct object). If a noun phrase involving
     "all" was used, the parser will invoke the
     doDefault or ioDefault methods in the deepverb
     object to obtain the list of all available
     objects.

     The parser will also invoke the methods
     disambigDobj and disambigIobj, as appropriate, on
     the deepverb object.

       verb.disambigDobj(actor, prep, iobj, verprop, wordlist, objlist, flaglist,
                         numberWanted, isAmbiguous, silent);

       verb.disambigIobj(actor, prep, dobj, verprop, wordlist, objlist, flaglist,
                         numberWanted, isAmbiguous, silent);

     The parser next identifies the verb template
     (i.e., the verification and action methods for
     the verb).

     If the verb has only templates for more objects
     than the player provided, the parser attempts to
     obtain the missing objects. (For example, the
     verb "take" requires a direct object; if the
     player types "take" without any object, the
     parser will try to obtain a direct object.)
     First, the parser tries using the default object
     mechanism, by calling the doDefault or ioDefault
     method in the deepverb object. If this fails to
     supply exactly one default object, the parser
     asks the player to provide the missing object.

     Next, if the player's command used multiple
     direct objects, or used a noun phrase involving
     "all" for the direct object, the parser will
     invoke the rejectMultiDobj method in the deepverb
     object.

       verb.rejectMultiDobj(preposition);

Starting Execution

     The parser next invokes the preCommand function,
     if defined:

       preCommand(actor, verb, dobj_list, prep, iobj)

     This function can simply return to proceed with
     the command, or it can use exit to skip to the
     fuses and daemons, or it can use abort to skip
     directly to endCommand, bypassing fuses and
     daemons.

Direct Object Loop

     The parser now executes a series of method calls
     on the direct objects in the command. For a
     command with multiple direct objects, the parser
     executes all of the steps below on the first
     direct object, then executes all of the steps on
     the second direct object, and so on.

     If the current direct object is not the first in
     the command, the parser at this point
     re-validates the current direct object and
     indirect object. This re-validation is not
     necessary for the first direct object in the
     command, because the object resolution phase
     already did this for all of the objects, and
     nothing in the game state has changed since then,
     hence that earlier validation is still
     applicable. However, the game state might change
     in the course of executing the command for the
     first direct object, so the parser must
     re-validate all subsequent objects. To
     re-validate, the parser calls the deepverb
     object's validDo method for the direct object,
     and the validIo method for the indirect object.
     If validation fails, the parser displays an error
     (using the cantReach method if the object is
     visible, otherwise using parser error 38, "You
     don't see that here any more") and aborts the
     command.

       verb.validDo(actor, directObject, 1)
       verb.validIo(actor, indirectObject, 1)

     The parser now executes the methods calls below
     for the current direct and indirect object.

     If one of the methods below executes an abort
     statement, the parser terminates execution of the
     command entirely. If one of the methods executes
     an exit statement, the parser skips directly to
     the postAction function, then to the end-of-turn
     phase, then proceeds to parse and execute any
     remaining command on the command line. If one of
     the methods invokes exitobj, the parser skips the
     remaining steps for the current direct object
     only, calls postAction, then proceeds to execute
     all of the steps below on the next direct object
     in the current command.

       verb.verbAction(actor, directObject, preposition, indirectObject);
       actor.actorAction(verb, directObject, preposition, indirectObject);
       actor.location.roomAction(actor, verb, directObject, preposition, indirectObject);

       if (indirectObject != nil)
       {
         indirectObject.iobjCheck(actor, verb, directObject, preposition);
         if (indirectObject does not directly define ioVerb or verIoVerb)
           indirectObject.iobjGen(actor, verb, directObject, preposition);
       }

       if (directObject != nil)
       {
         directObject.iobjCheck(actor, verb, indirectObject, preposition);
         if (directObject does not directly define doVerb or verDoVerb)
           directObject.iobjGen(actor, verb, indirectObject, preposition);
       }

       if (directObject != nil && indirectObject != nil)
       {
         // if directObject doesn't define or inherit verDoVerb,
         // or if indirectObject doesn't define or inherit verIoVerb,
         // display an error ("I don't know how to...") and stop now

         if (verb has flag [disambigDobjFirst])
           directObject.verDoVerb(actor);
         else
           directObject.verDoVerb(actor, indirectObject);

         // stop now if any output occurred in verDoVerb

         if (verb has flag [disambigDobjFirst])
           indirectObject.verIoVerb(actor, directObject);
         else
           indirectObject.verIoVerb(actor);

         // stop now if any output occurred in verIoVerb

         indirectObject.ioVerb(actor, directObject);
       }
       else if (directObject != nil)
       {
         // if directObject doesn't define or inherit verDoVerb,
         // display an error ("I don't know how to...") and stop now

         directObject.verDoVerb(actor);

         // stop now if any output occurred in verDoVerb

         directObject.doVerb(actor);
       }
       else
       {
         verb.action(actor);
       }

     Regardless of how the above sequence finishes (by
     successfully execution of all methods, or by
     execution of exit, exitobj, or abort), the parser
     next invokes the game-defined function
     postAction:

       postAction(actor, verb, dobj, prep, iobj, status);

     The "status" code indicates how the command was
     terminated:

    +------------+--------------------------------------+
    | EC_SUCCESS | Successful completion of all methods |
    +------------+--------------------------------------+
    | EC_EXIT    | exit executed                        |
    +------------+--------------------------------------+
    | EC_EXITOBJ | exitobj executed                     |
    +------------+--------------------------------------+
    | EC_ABORT   | abort executed                       |
    +------------+--------------------------------------+

Fuses and Daemons

     If none of the methods that the parser invoked so
     far executed an abort statement, the parser
     executes all pending fuses and daemons. Each
     daemon is executed once, and each fuse whose
     timer has reached zero is executed and then
     deleted.

endCommand

     Finally, the parser invokes the game-defined
     function endCommand():

       endCommand(actor, verb, dobj_list, prep, iobj, status);

     The "status" parameter has the same meaning as it
     does in the parser's call to postAction(). The
     other parameters have the same values they did in
     the call to preCommand() at the start of the
     command.

     The parser invokes endCommand() for every command
     that enters the execution phase (in other words,
     for every command that does not end with an error
     prior to execution, such as in syntax analysis or
     noun-phrase resolution). The parser calls
     endCommand() even when the execution phase is
     terminated with exit, exitobj, or abort.

------------------------------------------------------------
Summary of Properties, Methods, Objects, and Functions

     As described throughout this manual, the parser
     calls certain methods that objects in your game
     can define, and calls certain functions that your
     game can provide. All of these methods and
     functions are described in detail elsewhere in
     the manual. This section summarizes these
     properties and function; for full information,
     refer to the appropriate section elsewhere in the
     manual.

------------------------------------------------------------
Properties and Methods

     --------------------------------------------------
     *>action(actor)

          Called in a deepverb object during
          command execution to execute a command
          with no objects.

     --------------------------------------------------
     *>actorAction(verb, dobj, prep, iobj)

          Called in the actor object during
          command execution.

     --------------------------------------------------
     *>adesc

          Used to display an object's short
          description with an indefinite article.

     --------------------------------------------------
     *>adjective

          Defines words as adjectives, and
          associates them with the object.

     --------------------------------------------------
     *>anyvalue(num)

          The parser calls this method on an
          object with a generic numeric adjective
          (adjective = '#') when the player uses
          "any" in a noun phrase involving the
          object. This method returns a number to
          use for the arbitrary choice the parser
          must make.

     --------------------------------------------------
     *>article

          Defines words as articles.

     --------------------------------------------------
     *>cantReach(actor)

          Called in an object (only if cantReach
          isn't defined in the verb) when the
          object is visible but not accessible;
          this method is meant to display an
          explanation of this condition.

     --------------------------------------------------
     *>cantReach(actor, dolist, iolist, prep)

          Called in a verb when the list of
          objects (only one of dolist or iolist
          will be non-nil) is visible but not
          accessible; this method is meant to
          display an explanation.

     --------------------------------------------------
     *>construct

          Called immediately after an object is
          created with the new operator.
          Minimally, this method should install
          the object into its container's
          contents list.

     --------------------------------------------------
     *>contents

          The list of an object's contents.

     --------------------------------------------------
     *>destruct

          Called immediately before an object is
          destroyed with the delete operator.
          Minimally, this method should remove
          the object from its container's
          contents list, and should make sure
          that the object is not referenced from
          any other lists or properties.

     --------------------------------------------------
     *>disambigDobj(actor, prep, iobj, verprop,
     wordlist, objlist, flaglist, numberWanted,
     isAmbiguous, silent)

          The parser calls this method in the
          deepverb object to resolve an ordinary
          noun phrase used as a direct object.
          The parser calls this method for every
          ordinary noun phrase used as a direct
          object, whether or not the noun phrase
          is actually ambiguous.

     --------------------------------------------------
     *>disambigIobj(actor, prep, dobj, verprop,
     wordlist, objlist, flaglist, numberWanted,
     isAmbiguous, silent)

          The parser calls this method in the
          deepverb object to resolve an ordinary
          noun phrase used as an indirect object.
          The parser calls this method for every
          ordinary noun phrase used as an
          indirect object, whether or not the
          noun phrase is actually ambiguous.

     --------------------------------------------------
     *>doAction

          Direct Object Action; associated with a
          deepverb object. Defines the verb
          template for a single-object command
          for a verb, and specifies the suffix
          for to be used for the action and
          verification methods for the verb
          (doSuffix and verDoSuffix,
          respectively).

     --------------------------------------------------
     *>dobjCheck(actor, verb, iobj, prep)

          General direct object check, called
          during command execution before dobjGen
          would be called.

     --------------------------------------------------
     *>dobjGen(actor, verb, iobj, prep)

          General direct object handler, called
          during command execution on the direct
          object prior to processing the verb's
          verification and action methods. The
          parser does not call this method if the
          object "overrides" it by explicitly
          defining, rather than merely
          inheriting, a verification method
          (verDoVerb) or action method (doVerb)
          for the verb.

     --------------------------------------------------
     *>doDefault(actor, prep, iobj)

          Direct Object Default. Associated with
          a deepverb object. Returns the list of
          default objects for the verb.

     --------------------------------------------------
     *>ioAction(prep)

          Indirect Object Action; associated with
          a deepverb object. Defines the verb
          template for a two-object command for a
          verb with the given preposition, and
          specifies the suffix for to be used for
          the action and verification methods for
          the verb (io Suffix and verIoSuffix,
          respectively).

     --------------------------------------------------
     *>iobjCheck(actor, verb, iobj, prep)

          General indirect object check, called
          during command execution just before
          iobjGen would be called.

     --------------------------------------------------
     *>iobjGen(actor, verb, dobj, prep)

          General indirect object handler, called
          during command execution on the
          indirect object prior to processing the
          verb's verification and action methods.
          The parser does not call this method if
          the object "overrides" it by explicitly
          defining, rather than merely
          inheriting, a verification method
          (verIoVerb) or action method (ioVerb)
          for the verb.

     --------------------------------------------------
     *>ioDefault(actor, prep)

          Indirect Object Default; associated
          with a deepverb object. Returns the
          list of default objects for the verb.

     --------------------------------------------------
     *>isEquivalent

          Used to determine if an object should
          be treated as equivalent to other
          objects of its immediate superclass. If
          this property is true, the parser
          treats all objects of the same
          immediate superclass as this object as
          interchangeable during disambiguation.

     --------------------------------------------------
     *>isHim

          If true, the object can be the
          antecedant for the pronoun "him." This
          also affects certain default messages
          that adv.t displays for the object.

     --------------------------------------------------
     *>isHer

          If true, the object can be the
          antecedant for the pronoun "her." This
          also affects certain default messages
          that adv.t displays for the object.

     --------------------------------------------------
     *>isThem

          Added: TADS 2.5.2

          If true, the object can be the
          antecedant for the pronoun "them." This
          also affects certain default messages
          that adv.t displays for the object. In
          other words, the parser recognizes the
          isThem property for the purposes of
          deciding on the pronoun to display when
          prompting for an indirect object. Prior
          to version 2.5.2, the parser only
          recognized the isHim and isHer
          properties, and used the pronoun "it"
          if neither of these properties were
          consistently defined for the objects
          matching the direct object. As of 2.5.2
          the parser uses the pronoun "them" if
          the matching objects all have isThem
          set to true.

     --------------------------------------------------
     *>isVisible(vantage)

          Used to determine if an object is
          visible from the given object. The
          parser uses this to determine how to
          complain when an object isn't
          accessible: if it's visible, but not
          accessible, the parser will use
          cantReach to complain, otherwise it
          will simply say "I can't see that
          here."

     --------------------------------------------------
     *>location

          The object which contains the object.

     --------------------------------------------------
     *>locationOK

          If this property is true, it tells the
          compiler that you know that the
          location property is not an object
          constant, and the compiler therefore
          suppresses the warning it would
          otherwise generate.

     --------------------------------------------------
     *>multisdesc

          Used by the parser to display the
          current object when iterating through a
          list of direct objects in a command.
          Note that the parser will not call this
          method if the object defines or
          inherits a prefixdesc method.

     --------------------------------------------------
     *>newNumbered(actor, verb, num)

          The parser calls this method on an
          object with a generic numeric adjective
          (adjective = '#') when the player uses
          the object in a noun phrase. This
          method returns the object to use as the
          resolution of the noun phrase; num
          gives the number that the player used
          in the noun phrase (for example, in
          "look in box 55", num will be the
          number 55).

     --------------------------------------------------
     *>nilPrep

          Associated with a deepverb object; used
          by the parser to determine the
          preposition to use when a command of
          the form VERB IOBJ DOBJ is entered. If
          undefined, the preposition object
          associated with the word "to" is used
          by default.

     --------------------------------------------------
     *>noun

          Defines words as nouns, and associates
          them with the object.

     --------------------------------------------------
     *>parseUnknownDobj(actor, prep, iobj, wordlist)

          The parser calls this method to resolve
          a noun phrase (the token strings of
          which are given by wordlist) which
          contains an unknown word to a direct
          object. This method is invoked on the
          deepverb object for the command's verb.

     --------------------------------------------------
     *>parseUnknownIobj(actor, prep, iobj, wordlist)

          The parser calls this method to resolve
          a noun phrase (the token strings of
          which are given by wordlist) which
          contains an unknown word to an indirect
          object. This method is invoked on the
          deepverb object for the command's verb.

     --------------------------------------------------
     *>plural

          Defines words as plurals, and
          associates them with the object.

     --------------------------------------------------
     *>pluraldesc

          Displays a description of the object in
          the plural. The parser, and certain
          utility functions in adv.t, use this to
          display a collective name for a group
          of indistinguishable objects ("five
          gold coins").

     --------------------------------------------------
     *>preferredActor

          Used by the parser to determine if an
          object is a "preferred" actor; if this
          property is true, the object is chosen
          as the actor in cases where the actor
          is ambiguous and none of the other
          objects are preferred actors.

     --------------------------------------------------
     *>prefixdesc(show, current_index, count,
     multi_flags)

          Called by the parser before the
          execution phase for each direct object
          in a command, to display a prefix for
          the object before its execution results
          are displayed. The parser calls this
          method for each direct object in a
          command, regardless of whether the
          command has a single direct object or
          multiple direct objects. The parser
          calls this method in preference to
          multisdesc.

     --------------------------------------------------
     *>prepDefault

          Associated with a deepverb object. The
          parser uses this property to find the
          default preposition object to use when
          the player enters a partial command
          that starts with the verb and a direct
          object, but omits the preposition and
          indirect object.

     --------------------------------------------------
     *>preposition

          Defines words as prepositions, and
          associates them with the object.

     --------------------------------------------------
     *>rejectMultiDobj(prep)

          Associated with a deepverb object. If
          this method returns true, the verb
          doesn't allow multiple direct objects
          or "all."

     --------------------------------------------------
     *>roomAction(actor, verb, dobj, prep, iobj)

          Called in the actor's location during
          command execution.

     --------------------------------------------------
     *>roomCheck(verb)

          Called in the actor at the beginning of
          execution, before object
          disambiguation.

     --------------------------------------------------
     *>sdesc

          Short description. Used by the parser
          to display an object's name.

     --------------------------------------------------
     *>statusLine

          Called in the actor's location to
          update the statue line.

     --------------------------------------------------
     *>thedesc

          Displays the object's name with a
          definite article.

     --------------------------------------------------
     *>validActor

          Called by the parser to determine if
          the object is valid as an actor. This
          method doesn't check to see if the
          object is logical to use as an actor,
          but simply if the object is accessible
          as the target of a command.

     --------------------------------------------------
     *>validDo(actor, obj, seqno)

          Associated with a deepverb object.
          Returns true if the object is
          accessible as a direct object for the
          verb.

     --------------------------------------------------
     *>validDoList(actor, prep, iobj)

          Associated with a deepverb object.
          Returns a list of possibly-valid direct
          objects for the verb. The objects
          returned will be tested for validity
          with validDo, so the list can contain
          invalid objects as well, but it must
          contain all of the valid direct objects
          for the verb.

     --------------------------------------------------
     *>validIo(actor, obj, seqno)

          Associated with a deepverb object.
          Returns true if the object is
          accessible as an indirect object for
          the verb.

     --------------------------------------------------
     *>validIoList(actor, prep, dobj)

          Associated with a deepverb object.
          Returns a list of possibly-valid
          indirect objects for the verb. The
          objects returned will be tested for
          validity with validIo, so the list can
          contain invalid objects as well, but it
          must contain all of the valid indirect
          objects for the verb.

     --------------------------------------------------
     *>value

          The parser sets this property of the
          strObj or numObj object to the actual
          value of the string or number
          (respectively) entered in a command.

     --------------------------------------------------
     *>verb

          Defines words as verbs, and associates
          them with the object. Strings in this
          list can consist of one or two words;
          the second word must also be separately
          defined as a preposition.

     --------------------------------------------------
     *>verbAction(actor, dobj, prep, iobj)

          The parser calls this method on the
          deepverb object for the command, just
          before calling the actorAction method
          on the command's actor.

------------------------------------------------------------
Objects

     --------------------------------------------------
     *>againVerb

          The deepverb object with the vocabulary
          for "again." The parser internally
          handles the "again" processing when
          this verb's vocabulary word is entered
          as the command.

     --------------------------------------------------
     *>Me

          The default player actor object. When a
          command is not explicitly directed to
          another actor, this object is the actor
          to which the command is sent. When the
          game is first loaded, the parser uses
          Me as the default player character, but
          the game can change this using the
          parserSetMe() built-in function.

     --------------------------------------------------
     *>numObj

          A special object which is used as the
          direct object when a number is entered
          in a command (such as in "enter 30 on
          calculator," in which numObj is the
          direct object). The value property is
          set to the number actually entered in
          the command.

     --------------------------------------------------
     *>strObj

          A special object which is used as the
          direct object when a quoted string is
          entered in a command (such as in 'type
          "hello" on keyboard,' in which strObj
          is the direct object). The value
          property is set to the string actually
          entered in the command.

     --------------------------------------------------
     *>takeVerb

          Formerly required, but no longer
          directly used by the parser.

------------------------------------------------------------
Functions

     --------------------------------------------------
     *>commandPrompt(type)

          The parser calls this function, if
          defined, to display the prompt before
          asking for a command. The type code
          specifies the type of input being
          requested: 0 is a normal command; 1 is
          a command entered after the parser
          complains about an unknown word; 2 is a
          command entered in response to a
          disambiguation question; 3 is a command
          entered when the parser asks for a
          direct object; and 4 is a command
          entered when the parser asks for an
          indirect object.

     --------------------------------------------------
     *>commandAfterRead(type)

          The parser calls this function, if
          defined, immediately after the player
          finishes entering each command line.
          This function can reverse any text
          effects that commandPrompt established
          just before the command line. The type
          code has the same value as in the
          preceding commandPrompt call.

          This new function is intended to make
          it easier to customize certain aspects
          of your game's user interface. In
          particular, if you're using special
          formatting for the player command in
          the HTML interpreter (for example, you
          want to use a special typeface or font
          color for player commands), you can use
          commandAfterRead to turn off the
          special formatting you turned on in
          commandPrompt. Each call to
          commandPrompt is matched by an
          equivalent call to commandAfterRead, so
          you can always count on being able to
          undo any formatting changes you make in
          commandPrompt by placing the matching
          formatting commands in commandAfterRead.

     --------------------------------------------------
     *>endCommand(actor, verb, dobj_list, prep, iobj,
     status)

          The parser invokes this function, if
          defined, at the end of the command,
          after executing daemons and fuses.

     --------------------------------------------------
     *>init

          The system calls this immediately after
          loading the game, and again whenever
          the game is restarted. This function
          can perform any startup operations,
          such as setting fuses and daemons, and
          displaying an introductory message.
          Note that the system does not call
          init() when the player starts the TADS
          interpreter and specifies on the
          command line (or local equivalent) a
          saved game position to restore; in this
          case, the system instead calls
          initRestore(). (However, if
          initRestore() isn't defined, the system
          does call init() in all cases.)

     --------------------------------------------------
     *>initRestore(savedGameFileName)

          The system calls this function when the
          player starts the TADS interpreter and
          specifies a game to restore on the
          command line (or local equivalent). The
          purpose of this function is to allow
          the game to skip any introductory text
          that init() would normally display when
          starting a new game; since the player
          is explicitly jumping to a saved
          position, the player presumably doesn't
          need to see the introductory text
          again. If this function isn't defined,
          the system simply calls init() as
          though the game had been started
          without a saved game file.

     --------------------------------------------------
     *>pardon

          The parser calls this function whenever
          the player enters an empty command. You
          can display an error message, if you
          wish.

     --------------------------------------------------
     *>parseAskobj(verb, ...)

          The parser calls this function, if
          defined, to prompt for a missing direct
          or indirect object. If parseAskobjActor
          is defined, parseAskobj is ignored. If
          two arguments are provided, an indirect
          object is being requested, and the
          second argument is a preposition (which
          may be nil); otherwise, a direct object
          is being requested.

     --------------------------------------------------
     *>parseAskobjActor(actor, verb, ...)

          The parser calls this function, if
          defined, to prompt for a missing direct
          or indirect object. If three arguments
          are provided, an indirect object is
          being requested, and the third argument
          is a preposition (which may be nil);
          otherwise, a direct object is being
          requested.

     --------------------------------------------------
     *>parseAskobjIndirect(actor, verb, prep,
     objectList)

          The parser calls this function, if
          defined, to prompt for a missing
          indirect object. This is the parser's
          first choice when prompting for an
          indirect object; the parser calls this
          function in preference to
          parseAskobjActor() or parseAskobj().

     --------------------------------------------------
     *>parseDefault(obj, prep)

          The parser calls this function, if
          defined, to display a message
          indicating that the object (and the
          preposition, if not nil) are being used
          by default.

     --------------------------------------------------
     *>parseDisambig(nameString, objList)

          The parser calls this function, if
          defined, to prompt for more information
          when the player enters an ambiguous
          object name. The nameString is the
          string of words entered by the player
          (given as a single-quoted string), and
          the objList is a list of the objects
          matching the name.

     --------------------------------------------------
     *>parseError(num, str)

          The parser calls this function, if
          defined, to get the text of an error
          message. num is the message number, and
          str is the text of the message that the
          parser would display by default if this
          function weren't defined. Note that the
          parser never calls this function if
          your game defines a parseErrorParam
          function.

     --------------------------------------------------
     *>parseErrorParam(num, str, ...)

          The parser calls this function, if
          defined, to get the text of an error
          message. num is the message number, and
          str is the text of the message that the
          parser would display by default if this
          function weren't defined. Additional
          parameters are specify the values for
          any "%s" (string) or "%d" (number)
          sequences in the default message
          string.

     --------------------------------------------------
     *>parseError2(verb, dobj, prep, iobj)

          The parser calls this function, if
          defined, to display a message
          indicating that the verb can't be
          applied to these objects (because one
          of the objects doesn't define or
          inherit a verification method for the
          verb).

     --------------------------------------------------
     *>parseNounPhrase(wordlist, typelist,
     currentIndex, complainOnNoMatch, isActorCheck)

          The parser calls this function, if
          defined, to parse each noun phrase.
          This function can do its own noun
          phrase parsing for custom noun phrase
          syntax, or can defer to the standard
          built-in noun phrase parser.

     --------------------------------------------------
     *>parseUnknownVerb(actor, wordlist, typelist,
     errnum)

          The parser calls this function, if
          defined, to parse a sentence that the
          parser doesn't recognize. The parser
          invokes this function if the command
          does not have a valid verb, or if the
          sentence does not fit a syntax pattern
          that the parser accepts.

     --------------------------------------------------
     *>preCommand(actor, verb, dobj_list, prep, iobj)

          The parser invokes this function, if
          defined, at the start of the execution
          phase.

     --------------------------------------------------
     *>postAction(actor, verb, dobj, prep, iobj,
     status)

          The parser invokes this function, if
          defined, at the end of the execution
          phase. The parser calls this function
          once for each direct object in a
          command with multiple direct objects.
          The parser invokes this function even
          when the execution phase terminates
          with exit, exitobj, or abort.

     --------------------------------------------------
     *>preinit

          Called by the compiler, after
          compilation is complete, to perform any
          desired initialization. This function
          can't set any fuses or daemons, or
          display any messages; these functions
          are not saved in the compiled game
          file, so they must wait until the init
          function, which is invoked at run-time.
          The preinit function is intended to
          perform any time-consuming computation
          - for example, setting up lists of
          objects or initializing property values
          - that would otherwise be done in init
          every time the game is started. By
          performing these functions in preinit,
          the work can be done at compile-time,
          saving players from having to wait for
          it each time they run the game. Note
          that this function won't be called
          until run-time if the game is compiled
          for debugging; while this doesn't
          affect the behavior of the game (apart
          from slowing down run-time startup), it
          allows you to use the debugger to step
          through your preinit function.

     --------------------------------------------------
     *>preparse(cmd)

          The parser calls this function with a
          (single-quoted) string giving the full
          text of the command line each time the
          player enters a new command.

     --------------------------------------------------
     *>preparseCmd(wordList)

          The parser calls this function with a
          list of (single-quoted) strings giving
          the words of the current command. This
          function is called for each individual
          command on a command line.

------------------------------------------------------------










                     Language Reference

------------------------------------------------------------
      This file is part of the TADS Author's Manual.
Copyright (c) 1987 - 2001 by Michael J. Roberts. All rights
                          reserved.

              Edited by N. K. Guy, tela design.

------------------------------------------------------------
Chapter Eight

------------------------------------------------------------
Language Reference

This section describes in detail all of the keywords,
operators, syntactic elements, built-in functions, and
special considerations of the TADS language.

------------------------------------------------------------
Typographical Conventions

     This section uses abstract syntax diagrams to
     describe the language. In these diagrams, several
     typographical conventions are used:

     italics are used to represent a description of an
     item that must be replaced with an actual
     instance of the item. [Square Brackets] are used
     to indicate that the enclosed item or items are
     optional. Typewriter text is to be used verbatim.
     The same applies to any other punctuation shown.

------------------------------------------------------------
Version Information

     TADS has gained many new functions and features
     over the years, but tracking what features were
     available with which version of the software was
     problematic. Since the release of version 2.2.4,
     however, TADS has had the ability to check to see
     what version of the interpreter (runtime)
     software is being used. For that reason all new
     functions and features added with 2.2.4 and
     higher are marked in this documentation. If no
     version number is listed you can assume that the
     item in question was available to all versions of
     TADS prior to 2.2.4.

------------------------------------------------------------
Components of TADS

     The TADS development system includes a compiler,
     a run-time system or interpreter, and several
     TADS source files containing basic adventure
     definitions.

     When you write a TADS program, you use a text
     editor (which is not included with TADS) to
     prepare a source file, then you compile the file.
     The compiler checks the entire program for syntax
     errors, then creates another file containing a
     binary representation of your source file; this
     form is more efficient to execute, so your game
     will require less memory and run faster.

     After you have compiled your program, you use the
     interpreter to run the game. The interpreter
     contains the player command parser and other code
     for user interaction.

------------------------------------------------------------
Input File Format

     The TADS compiler accepts plain text (standard
     ASCII) files as input. The compiler considers any
     amount of whitespace to be the same as a single
     space, and spaces, tabs, and newlines all count
     as whitespace. Whitespace can occur between any
     two syntactic elements, but need only appear
     between two identifiers or keywords that have no
     other intervening punctuation. The compiler knows
     that punctuation is never part of a keyword or
     identifier, and can manage to break apart
     punctuation when it's all run together without
     spaces. For readability, liberal use of
     whitespace is recommended.

------------------------------------------------------------
Including Other Files

     The #include directive allows one file to insert
     the contents of another:

       #include "file.t"
       #include <file.t>

     Here, file.t is the name of an operating system
     file to be included. An included file can include
     another, and so forth, down to ten levels of
     nested files. Note that the pound sign, #, must
     be in the first column of the line; no leading
     spaces are allowed. The include file adv.t\ is
     normally included at the start of a game file to
     define the many items that are needed in a normal
     adventure. These definitions are quite general,
     but specific games might modify them to customize
     the game.

     Note that when the filename is enclosed in double
     quotes, the compiler searches for the file first
     in the current directory, then in the directories
     in the include path (as set with the -i compiler
     switch on most operating systems). When the
     filename is enclosed in angle brackets, the
     compiler searches only in the directories in the
     include path - the current directory is not
     searched. Generally, a system include file (such
     as adv.t) should be enclosed in angle brackets,
     while your files should be in the current
     directory and enclosed in double quotes.

     Note also that the #include directive cannot be
     preceded by a space character. The # symbol must
     be the first character on the line. If you copy
     and paste sample code from a Web browser window
     be sure to check for this common problem, or else
     your code simply will not compile.

------------------------------------------------------------
Multiple Inclusions of the Same File

     The TADS compiler automatically keeps track of
     each file you have included, and ignores
     redundant #include directives. Note that this
     feature is based on the filename as specified in
     your program; if you refer to the same file by
     different names (for example, by specifying a
     path on one inclusion, but using angle brackets
     to let TADS find the file on the second), the
     compiler will not be able to identify the
     duplicate file, and will include it twice,
     resulting in countless unnecessary errors. For
     this reason, you are encouraged to use angle
     brackets to specify include files, rather than
     using specific paths in your source file. Doing
     so will help ensure that your source files are
     portable to different computers, as well, since
     each operating system uses its own conventions
     for specifying file paths.

     Note that the include files that make up a
     pre-compiled binary file, loaded with the
     compiler's -l option, are recorded in the binary
     file. Thus, there is no need for you to remove
     the #include directive in your source file just
     because you are using the pre-compiled version of
     that include file. For more information on using
     pre-compiled include files, see the section on
     using the compiler.

------------------------------------------------------------
Comments

     Outside of a quoted string, two consecutive
     slashes, //, indicate that the rest of the line
     is a comment. Everything up to the next newline
     is ignored.

     Alternatively, C-style comments can be used;
     these start with /* and end with */; this type of
     comment can span multiple lines.

     Examples:

       // This line is a comment.

       /*
       This is a comment
       which goes across
       several lines.
       */

------------------------------------------------------------
Identifiers

     Identifiers must start with a letter (upper or
     lower case), and may contain letters, numbers,
     dollar signs, and underscores. Identifiers can be
     up to 39 characters long. Upper and lower case
     letters are distinct.

------------------------------------------------------------
Scope of Identifiers

     All objects and functions are named by global
     identifiers. No identifier may be used to
     identify different things; that is, no two
     objects can have the same name, an identifier
     naming a function can't also be used for an
     object, and so forth.

     Property names are also global identifiers. A
     name used for a property can't be used for a
     function or object, or vice versa. However,
     unlike functions and objects, the same property
     name can be used in many different objects. Since
     a property name is never used alone, but always
     in conjunction with an object, the TADS compiler
     is able to determine which object's property is
     being referenced even if the same name is used in
     many objects.

     Function arguments and local variables are
     visible only in the function in which they
     appear. It is permissible to re-use a global
     identifier as a function argument or local
     variable, in which case the variable supersedes
     the global meaning within the function. However,
     this is discouraged, as it can be a bit confusing.

------------------------------------------------------------
Object Definitions

     A basic object definition has the form:

       identifer: object [property-list] ;

     This defines an object which has no superclass.
     An object can be defined as having a superclass
     with the alternative form of object definition:

       identifier: class-name [, class-name [...]] [property-list] ;

     Here, the class-name is an identifier which is
     defined elsewhere in the program as an object or
     class (either with or without a superclass), and
     is the new object's superclass; if more than one
     superclass is present, a comma separates each
     superclass in the list. The new object named by
     identifier inherits all the properties of the
     superclass or superclasses. If a property in the
     optional property-list is also in the property
     list of the superclass (or its superclass, and so
     forth), the new property overrides the inherited
     one.

     If a property is inherited from more than one of
     its superclasses (and is not overridden in the
     object's own property list), the property is
     inherited from the superclass that appears
     earliest in the list. For example, suppose you
     define an object like this:

       vase: container, fixeditem
       ;

     If both container and fixeditem define a method
     named m1, and vase itself doesn't define an m1
     method, then m1 is inherited from container,
     because it appears earlier in the superclass list
     than fixeditem.

     There is a more complicated case that can occur,
     but it is very unusual. You will probably never
     encounter this, so skip this section if you find
     it confusing. Suppose that in the example above,
     both container and fixeditem have the superclass
     item, and that item and fixeditem define method
     m2, and that neither container nor vase define
     m2. Now, since container inherits m2 from item,
     it might seem that vase should inherit m2 from
     container and thus from item. However, this is
     not the case; since the m2 defined in fixeditem
     overrides the one defined in item, vase inherits
     the m2 from fixeditem rather than the one from
     item. Hence, the rule, fully stated, is: the
     inherited property in the case of multiple
     inheritance is that property of the earliest
     (leftmost) superclass in the object's superclass
     list that is not overridden by a subsequent
     superclass.

------------------------------------------------------------
Property Lists

     A property list takes on this form:

       property-definition [property-list]

     (This is a formal way of saying that you can
     string together any number of property
     definitions in a property list, one after the
     other.) A property definition looks like this:

       identifier = data-item

     Note that no semicolon comes after the property
     definition. A semicolon terminates the entire
     object definition, not individual property
     definitions.

------------------------------------------------------------
Property Data Items

     A data item can be a number, a double-quoted
     string, a single-quoted string, a list, an
     object, nil, or true.

------------------------------------------------------------
Numbers

     A number is just a string of digits. The default
     base is decimal; you can also enter octal and
     hexadecimal numbers. An octal number simply
     starts with a leading zero, so 035 is an octal
     number having the decimal value 29. A hexadecimal
     number starts with 0x, as in 0x3a9.

     Numbers can vary from -2147483647 to 2147483647
     (decimal), inclusive. Only integers are allowed;
     numbers cannot have a decimal point or a
     fractional part.

------------------------------------------------------------
Double-quoted Strings

     A double-quoted string is an arbitrary string of
     characters enclosed in double quotation marks,
     such as,

       "This is a double-quoted string."

     Stretches of whitespace in such strings are
     compressed to single spaces. This includes
     newlines; double-quoted strings can go on past
     the end of a line, and keep going for several
     lines. For example, this is perfectly legal:

       "This is a string
       that goes on for

       several lines."

     Note that TADS converts all of that blank space,
     including the blank lines, down to a single space
     between each word. Thus, you can enter your text
     without having to worry about formatting it; TADS
     will do all the work of filling up each output
     line when your program runs.

     Sometimes, you will want to format your output in
     a specific way, overriding the standard output
     formatting. Since TADS converts all whitespace in
     your strings (including newlines) to spaces, you
     have to specify any special formatting you want
     explicitly. TADS provides several special
     character sequences you can use to obtain these
     effects.

  +--------+--------------------------------------------+
  | \t     | Tab to the next stop. Tab stops are every  |
  |        | four spaces. This is useful if you want    |
  |        | stretches of blank space within a line.    |
  |        | The HTML-TADS equivalent is the tag <TAB   |
  |        | MULTIPLE=4>.                               |
  +--------+--------------------------------------------+
  | \n     | A newline (carriage return). Ends the      |
  |        | current line, and skips to a new one.      |
  |        | Note that repeating this sequence has no   |
  |        | effect, since the output formatter         |
  |        | ignores redundant \n sequences. This is    |
  |        | normally convenient, because it means you  |
  |        | don't have to worry about several newline  |
  |        | sequences being displayed by different     |
  |        | objects filling the display with unwanted  |
  |        | blank lines. If you want to force one or   |
  |        | more blank lines, use \b. The HTML-TADS    |
  |        | equivalent is the tag <BR HEIGHT=0>.       |
  +--------+--------------------------------------------+
  | \b     | Ends the current line, and then outputs a  |
  |        | blank line. Multiple \b sequences will     |
  |        | result in multiple blank lines. The        |
  |        | HTML-TADS equivalent is the tag <P>.       |
  |        | Almost. Multiple <P>s don't insert         |
  |        | multiple blank lines.                      |
  +--------+--------------------------------------------+
  | \"     | A double quotation mark. Note that this    |
  |        | is a neutral quotation mark. If you want   |
  |        | curved (typographical) quotation marks     |
  |        | you need to use HTML-TADS.                 |
  +--------+--------------------------------------------+
  | \'     | A single quotation mark. Note that this    |
  |        | is a neutral apostrophe. If you want       |
  |        | curved (typographical) apostrophes or      |
  |        | single quotes you need to use HTML-TADS.   |
  +--------+--------------------------------------------+
  | \\     | A backslash.                               |
  +--------+--------------------------------------------+
  | \<     | A left angle bracket. This is not          |
  |        | required to produce a single angle         |
  |        | bracket (although it will do so), but you  |
  |        | will need to use this on second and        |
  |        | subsequent angle brackets in a stream of   |
  |        | contiguous angle brackets, to prevent      |
  |        | TADS from thinking you want to embed an    |
  |        | expression in your string (see below).     |
  |        | Hence, if you want to display <<<<<, you   |
  |        | will have to type this in your program:    |
  |        | "<\<\<\<\<". Note also that is displayed   |
  |        | as a left angle bracket in the HTML TADS   |
  |        | system, and will not be interpreted as a   |
  |        | tag.                                       |
  +--------+--------------------------------------------+
  | \^     | (That is, a backslash followed by a        |
  |        | circumflex or "up arrow" or "hat,"         |
  |        | entered with the shifted "6" key on most   |
  |        | keyboards.) This sequence causes the next  |
  |        | character in the output to be              |
  |        | capitalized. This sequence is generally    |
  |        | used just before invoking a function or    |
  |        | method that will display text that will    |
  |        | be at the start of a sentence. By using    |
  |        | this sequence prior to the text, you       |
  |        | ensure that the first letter of the        |
  |        | sentence is capitalized, even if the       |
  |        | function or method displaying the text     |
  |        | doesn't know it should be capitalized.     |
  |        | For example: "\^<< obj.adesc >> is         |
  |        | sitting on the table." Note that the       |
  |        | caps() built-in function has the same      |
  |        | effect.                                    |
  +--------+--------------------------------------------+
  | \v     | This sequence is the opposite of "\^".     |
  |        | Whereas "\^" converts the next character   |
  |        | displayed to a capital letter, "\v"        |
  |        | converts the next character to a small     |
  |        | letter. Displaying "\v" is equivalent to   |
  |        | calling the nocaps() built-in function.    |
  +--------+--------------------------------------------+
  | \space | (That is, a backslash followed by a        |
  |        | space.) A quoted space. This is useful in  |
  |        | certain cases to achieve special           |
  |        | formatting effects, because it overrides   |
  |        | the output formatter's suppression of      |
  |        | multiple spaces, and it also suppresses    |
  |        | the double-space that sometimes follows    |
  |        | punctuation marks such as periods in       |
  |        | certain versions of the TADS interpreter.  |
  |        | For example, if you want to print          |
  |        | someone's name with a middle initial, you  |
  |        | don't want two spaces after the initial.   |
  |        | Since some versions of the runtime print   |
  |        | the two spaces automatically you would     |
  |        | thus enter: "Michael J.\ Roberts" to       |
  |        | ensure that the name is displayed          |
  |        | correctly with all versions of the         |
  |        | interpreter. Note also that some versions  |
  |        | of the TADS interpreter will print either  |
  |        | one or two spaces after a punctuation      |
  |        | mark, depending on a preferences setting.  |
  +--------+--------------------------------------------+
  | \(     | Begin highlighting. Text after the \( is   |
  |        | displayed with a special attribute, which  |
  |        | varies by system. On some machines it      |
  |        | will appear in a different color than      |
  |        | ordinary text, while on others it may      |
  |        | appear in a boldfaced font. On some        |
  |        | systems it may have no effect at all.      |
  |        | This is intended to be used for            |
  |        | emphasizing text the same way that         |
  |        | boldface or italics would emphasize text   |
  |        | in a book. Note that highlighting does     |
  |        | not "nest"; that is, if a \( sequence      |
  |        | occurs while highlighting is already       |
  |        | active, the second sequence has no         |
  |        | additional effect. This functionality      |
  |        | predates the HTML TADS software, which     |
  |        | offers richer and more flexible            |
  |        | text-formatting options.                   |
  +--------+--------------------------------------------+
  | \)     | End highlighting. Text after the \)        |
  |        | without the special highlighting           |
  |        | attribute. Note that a single \) sequence  |
  |        | turns off highlighting, no matter how      |
  |        | many \( sequences preceded it.             |
  +--------+--------------------------------------------+
  | \-     | Pass two bytes. The sequence is a          |
  |        | backslash followed by a hyphen, and tells  |
  |        | the formatter to pass the following two    |
  |        | bytes as-is, without any interpretation.   |
  |        | This is useful for multi-byte character    |
  |        | sets (such as on a Japanese-localized      |
  |        | Macintosh), where a single character may   |
  |        | be represented by two bytes. For the most  |
  |        | part, you can freely mix single- and       |
  |        | double-byte characters within text         |
  |        | strings without any special work.          |
  |        | However, some double-byte characters       |
  |        | contain the ASCII code for a backslash as  |
  |        | one of their two bytes; in these cases,    |
  |        | the output formatter incorrectly           |
  |        | interprets the byte whose code is "\" as   |
  |        | introducing an escape sequence. By         |
  |        | preceding such characters with "\-", you   |
  |        | can prevent the parser from interpreting   |
  |        | the byte with the backslash code as an     |
  |        | escape sequence, so the character will be  |
  |        | displayed correctly.                       |
  +--------+--------------------------------------------+
  | \H+    | Turn on the HTML parser. This character    |
  |        | sequence is used to enable the HTML        |
  |        | functionality of HTML-TADS. For more       |
  |        | information consult the HTML-TADS          |
  |        | documentation.                             |
  +--------+--------------------------------------------+
  | \H-    | Turn off the HTML parser.                  |
  +--------+--------------------------------------------+

     There is no specific limit on the length of a
     double-quote string, although the compiler may
     impose some limits depending on the context in
     which the string appears.

     A double-quoted string is always displayed
     whenever evaluated. When a double-quoted string
     appears in code, executing that code results in
     displaying the string. Likewise, when a property
     has a double-quoted string as its value, the
     string is displayed whenever the property is
     evaluated.

     HTML-TADS supports many more formatting options
     than regular TADS, but does so using HTML tags
     rather than TADS character sequences. Consult the
     HTML-TADS documentation for more information.

------------------------------------------------------------
Embedding Expressions in Strings

     TADS has a convenient feature which allows you to
     embed expressions in strings, without actually
     stopping the string. Any time TADS encounters two
     consecutive left angle brackets in a string, it
     will momentarily stop the string, and evaluate
     what comes after the angle brackets as an
     expression whose value is to be displayed. The
     expression ends, and the string resumes, when two
     right angle brackets are encountered. This makes
     property definitions that need to look up another
     property very convenient to define; for example,

       itsHere = "<< self.thedesc >> is here."

     The statement above is equivalent to this more
     verbose version:

       itsHere =
       {
         self.thedesc; " is here.";
       }

     An embedded expression can evaluate to a number,
     a single-quoted string, or a double-quoted
     string. Other datatypes are not allowed. A string
     may have any number of embedded expressions
     within it. An embedded expression may only
     contain an expression; statements (such as if)
     are not allowed, and semicolons may not be used
     to separate multiple expressions - use commas
     instead.

     This feature has certain limitations. It is
     illegal to use a string in an embedded expression
     which itself has an embedded expression. This
     feature can be used only in double-quoted
     strings; single-quoted strings cannot contain
     embedded expressions.

     Because some game authors may wish to use two or
     more consecutive left angle brackets in their
     strings, the special sequence `\<' is provided.
     See the section on special character sequences,
     above, for more information.

     Note that this feature is fully compatible with
     HTML TADS and does not cause any problems, even
     though it uses the < and > symbols. This is
     because these symbols are interpreted by the
     compiler at compile-time and never appear in the
     actual game text, where they could be
     misinterpreted by the runtime.

------------------------------------------------------------
Single-quoted Strings

     Single-quoted strings are essentially the same as
     double-quoted strings in appearance, except, of
     course, that they are enclosed in single quote
     marks. The sequence \' is available to produce a
     single quote in the string itself.

     Single-quoted strings do not display when
     evaluated; instead, they are treated as values.
     Certain built-in functions are available to
     manipulate these strings, such as say, which
     displays such a string value.

     Note also that all vocabulary words appear as
     single-quoted strings (or lists of single-quoted
     strings).

------------------------------------------------------------
Lists

     A list is an aggregate of other data items. It is
     entered as a set of data items enclosed in square
     brackets (note that these square brackets are the
     actual punctutation, not indicators of
     optionality):

       [ data-list ]

     A data-list can be nothing at all, in which case
     the list is empty, as in

       [ ]

     Or, it can be one or more data items (numbers,
     strings, objects, lists). Generally, it is only
     useful to construct lists with the same datatype
     for all members, but this is not required by the
     language.

     Examples of lists:

       [ 1 2 3 ]
       [ 'hello' 'goodbye' ]
       [ [1 2 3] [4 5 6] [7 8 9] ]
       [ vase goldSkull pedestal ]

     List elements need not be constants, unless the
     entire list needs to be a constant. For example,
     a list used as a property value must be a
     constant, so all of the elements must be
     constants (hence, local variables and
     non-constant expressions cannot be used).
     However, a list used in code, such as a list
     assigned to a local variable, can contain
     non-constant expressions within the list
     elements. For example, the following function
     dynamically constructs a list from three
     expressions:

       f: function(x, y, z)
       {
         return([x+1 y+1 z+1]);
       }

     The non-constant list elements are legal because
     the list construction appears in code. Note that
     the routine above has the same effect as this
     code:

       f: function(x, y, z)
       {
         return((([ ] + (x+1)) + (y+1)) + (z+1));
       }

     The second example starts with an empty list,
     then adds an element whose value is (x+1), then
     adds a second element whose value is (y+1), and
     so on. The two examples construct exactly the
     same list. However, you should use the first
     construct where possible, because it is much more
     efficient: the first example constructs only a
     single list, whereas the second must construct
     four lists, one at a time. The first example is
     faster and consumes less memory at execution time.

------------------------------------------------------------
*>nil
*>true

     Two special datatypes, nil and true, are
     pre-defined. These are generally used as "truth
     values"; nil means false and true means true. For
     example, 1 > 3 evaluates to nil, whereas 1 < 3 is
     true. In addition, nil means the absence of a
     value; taking the car of an empty list returns
     nil, as does evaluating a property of an object
     when the property is neither defined nor
     inherited by the object.

     For truth values, you should use nil and true
     rather than numeric equivalents, since nil and
     true provide much more explicit
     self-documentation of your program.

------------------------------------------------------------
Expressions

     A property definition can contain an expression
     rather than a simple constant. When a property
     value is an expression, the expression must be
     enclosed in parentheses. The expression is
     evaluated each time the property is evaluated. An
     example of using an expression for a property
     value:

       exprObj: object
         x = 1
         y = 2
         z = (self.x + self.y)
       ;

     Whenever exprObj.z is evaluated, the sum of the
     current values of exprObj.y and exprObj.z is
     returned.

     Note that a property defined in this manner can
     take parameters, just like methods (described
     below). For example:

       exprObj2: object
         w(a, b) = (a * b)
       ;

     When exprObj2.w is evaluated, it requires two
     parameters, which are multiplied together to give
     the value of the property. For example,
     evaluating exprObj2.w(3, 4) produces a value of
     12.

     Note that the property z above could have been
     written without the "self." prefix on x and y:

       z = (x + y)

     This is because properties, if used without an
     object name, are assumed to belong to the current
     self object.

------------------------------------------------------------
Methods

     Code can be used in a property definition just
     like any other datatype. When you associate code
     with an object, the code is called a method.
     Another way of looking at it is that a method is
     code inside an object. When the method is
     evaluated or triggered, the code is executed. The
     return value is the value of the method, but
     often it is useful for the code to produce side
     effects as well.

     Method code is enclosed in braces, { and }.
     Anything valid in a function may appear in code
     associated with a method. The method may have
     local variables, and it can receive arguments. If
     the method has arguments, the argument list
     (which is identical to a function's argument
     list) appears after the method name. For example:

       obj1: object
         f(x) =
         {
           return(x + 1);
         }
       ;

     When such a method is evaluated, the argument
     list is specified after the method name, as in:

       f1: function
       {
         say(obj1.f(123));
       }

------------------------------------------------------------
Functions

     A function is a standalone piece of code that,
     unlike a method, isn't part of an object. A
     function definition has this form:

       identifier: function [ ( argument-list ) ]
       {
         function-body
       }

     The argument-list is optional; functions need not
     take arguments if there's no need to send any
     data to it. But if the function does take one or
     more arguments, the list looks like this:

       identifier [, argument-list ]

     The identifiers may be used just like local
     variables within the function.

     The punctuation in the above syntactic
     description may be a little much, so an example
     might be helpful:

       addlist: function(list)    // add up the numbers in the list
       {
         local sum, count, i;
         i := 1;                  // index the first item in the list
         sum := 0;                // initialize the sum to zero
         count := length(list);   // get the number of items in the list
         while (i < count)        // as long as there's more to do...
         {
           sum := sum + list[i];  // add next element
           i := i + 1;            // go on to the next list element
         }
         return(sum);
       }

------------------------------------------------------------
Functions with Variable Argument Lists

     It is possible to define a function that takes a
     variable number of arguments. In the function
     definition, you can specify a minimum number of
     arguments that are always passed to the function
     (which can be no arguments at all, if you wish),
     and then specify that more arguments can
     optionally follow. This is done with the
     "ellipsis" token, "...", as the final "argument"
     in the function's argument list. For example, to
     define a function that takes any number of
     arguments:

       f: function(...)
       {
       }

     To define a function that always takes at least
     one argument, but could take additional arguments:

       g: function(fmt, ...)
       {
       }

     In a function taking a variable number of
     arguments, you can determine how many arguments
     were actually passed to the function by
     inspecting the pseudo-variable argcount. This
     pseudo-variable's value is simply the number of
     arguments to the current function.

     To retrieve an argument, use the getarg(argnum)
     built-in function. The argument argnum is the
     number of the argument you want to retrieve;
     getarg(1) returns the first argument, getarg(2)
     returns the second, and so forth. Note that in a
     function which has some explicit arguments,
     followed by an ellipsis, getarg(1) still returns
     the first argument, even though it has a name in
     the argument list. For example, in the function g
     above, getarg(1) returns the value of the
     argument fmt.

     Another built-in function, datatype(value), can
     be used to determine the datatype of an argument.
     See the description of the datatype function
     later in this chapter for more information.

     As an example, the function below displays any
     number of values.

       displist: function(...)
       {
         local i;
         for (i := 1 ; i <= argcount ; i++)
         {
           say(getarg(i));
           " ";
         }
         "\n";
       }

------------------------------------------------------------
Forward-Declaration of Functions

     An alternative form of the function statement
     allows you to forward-declare a name as a
     function, without actually defining the function.
     The format of a forward declaration is:

       identifier: function;

     Note that this does not define the function; it
     merely tells the compiler that a function
     definition for the specified identifier will
     appear later in the file. This reserves the
     identifier for use as a function name, and
     prevents the compiler from assuming the
     identifier refers to an object.

     Forward declarations are not necessary except
     where setdaemon() and the like will be used. When
     a function is actually called, the syntax of the
     call tells TADS that the name refers to a
     function even when TADS hasn't seen the function
     definition yet. In setdaemon() and similar calls,
     though, no special syntax is present to tell TADS
     what the identifier refers to, so the compiler
     assumes it will refer to an object.

------------------------------------------------------------
Writing Code

     In this section we cover the details of the
     language that goes inside functions and methods.
     Function and method code consists of a series of
     statements; the statements are executed
     sequentially in the order they appear in the
     source program. The following pages provide
     details about the statements that may be used.

     Each statement in TADS code is terminated with a
     semicolon.

------------------------------------------------------------
*>local

     At the start of a function or property
     definition, you can define local variables for
     the current code block. This is done with a
     statement such as this:

       local identifier-list ;

     The identifier-list has the form:

       identifier [ initializer ] [, identifier-list ]

     An initializer, which is optional, has the form:

       := expression

     where the expression is any valid expression,
     which can contain arguments to the function or
     method, as well as any local variables defined
     prior to the local variable being initialized
     with the expression. The expression is evaluated,
     and the resulting value is assigned to the local
     variable prior to evaluating the next
     initializer, if any, and prior to executing the
     first statement after the local declaration.
     Local variables with initializers and local
     variables without initializers can be freely
     intermixed in a single statement; any local
     variables without initializers are automatically
     set to nil by the run-time system.

     The identifiers defined in this fashion are
     visible only inside the function in which the
     local statement appears. Furthermore, the local
     statement supersedes any global meaning of the
     identifiers within the function.

     A local statement can occur in any block (that
     is, any statements grouped together with braces),
     and a single block can have multiple local
     statements; all local statements in a block must
     precede the first executable statement of the
     bloc. In other words, the only thing that can
     appear before a local statement is another local
     statement.

     An example of declaring local variables, using
     multiple local statements, and using initializers
     is below.

       f: function(a, b)
       {
         local i, j;                                           /* no initializers */
         local k := 1, m, n := 2;         /* some with initializers, some without */
         local q := 5*k, r := m + q;        /* OK to use q after it's initialized */
         for (i := 1 ; i < q ; i++)
         {
           local x, y;                     /* locals can be at start of any block */
           say(i);
         }
       }

------------------------------------------------------------
Expressions

     TADS expressions are entered in algebraic
     notation. Operators have different meanings on
     different datatypes. The basic list follows.

  +---+-------------------------------------------------+
  | & | Takes the "address" of a function or property.  |
  |   | In other words, this expression allows you to   |
  |   | refer to a function or property without         |
  |   | evaluating (triggering) it.                     |
  |   |                                                 |
  |   | The & operator must be immediately followed by  |
  |   | the name of a property or the name of a         |
  |   | function. You can assign this value to a local  |
  |   | variable or a property, or you can pass it to   |
  |   | a function or method. The address value can     |
  |   | then be used to call the function or property.  |
  |   | See "Indirect Function and Method Calls" later  |
  |   | in this chapter. (Note: older versions of TADS  |
  |   | used the # operator to take the address of a    |
  |   | function. This operator is still understood by  |
  |   | the system, but we recommend that you use & in  |
  |   | new code instead.)                              |
  +---+-------------------------------------------------+

  +----+------------------------------------------------+
  | .  | (Period or full stop.) Takes a property of an  |
  |    | object. On the left of the dot is an           |
  |    | expression that evaluates to an object, and    |
  |    | on the right is a property name. If the        |
  |    | property is a method that requires arguments,  |
  |    | these arguments are listed in parentheses      |
  |    | after the property name, just as with          |
  |    | function arguments. A local variable or an     |
  |    | expression enclosed in parentheses may appear  |
  |    | on the right hand side; the local or           |
  |    | expression must evaluate to a property         |
  |    | pointer.                                       |
  +----+------------------------------------------------+
  | [] | List indexing; applied to the right side of a  |
  |    | list-valued expression. An expression which    |
  |    | evaluates to a number must appear between the  |
  |    | square brackets. If the index (i.e., the       |
  |    | value between the square brackets) is n, the   |
  |    | nth element of the list is returned by this    |
  |    | operator. The first element in the list is     |
  |    | number 1. For example, ['one' 'two'            |
  |    | 'three'][1+1] evaluates to the string 'two'.   |
  |    | Note that a run-time error results if n is     |
  |    | outside the bounds of the list; that is, n is  |
  |    | less than 1 or greater than the number of      |
  |    | elements in the list (as returned by the       |
  |    | length() built-in function.                    |
  +----+------------------------------------------------+
  | ++ | Increment; adds one to a numeric variable or   |
  |    | property. The expression to which ++ is        |
  |    | applied must be suitable for assignment        |
  |    | (i.e., it must be something that you can use   |
  |    | on the left-hand side of the assignment        |
  |    | operator, ":="). The ++ operator can be        |
  |    | either a prefix or postfix operator - that     |
  |    | is, it can be placed either before or after    |
  |    | its operand. If it's placed before the         |
  |    | operand, as in ++i, the operand is             |
  |    | incremented, and the value of the expression   |
  |    | is the value of the operand after the          |
  |    | increment. If it's placed after the operand,   |
  |    | as in i++, the value of the expression is the  |
  |    | value of the operand before the increment.     |
  |    | So, if the variable i has the value 3, ++i     |
  |    | has the value 4, while i++ has the value 3.    |
  |    | Think about it by reading the expression       |
  |    | left-to-right, and noting that the value of    |
  |    | the expression is the value of i when you      |
  |    | read it, and the increment is applied when     |
  |    | you read the ++ operator. So, with ++i, you    |
  |    | first read the increment operator, which adds  |
  |    | 1 to i, then you note the value of i, which    |
  |    | by now is 4. With i++, you first read i and    |
  |    | note its value, which is still 3, then you     |
  |    | see the ++ operator, leaving 4 in i.           |
  +----+------------------------------------------------+
  | -- | Decrement; subtracts one from a numeric        |
  |    | variable or property. This acts exactly like   |
  |    | the ++ operator, except that it decrements     |
  |    | its operand rather than incrementing it.       |
  +----+------------------------------------------------+

  +-----+-----------------------------------------------+
  | not | Logical negation. Turns true into nil and     |
  |     | vice versa. This operator can only be         |
  |     | applied to the values true and nil.           |
  +-----+-----------------------------------------------+
  | -   | Arithmetic negation. As a unary prefix        |
  |     | operator (that is, an operator that precedes  |
  |     | its single operand), the minus sign negates   |
  |     | the number following it.                      |
  +-----+-----------------------------------------------+

  +---+-------------------------------------------------+
  | * | Numeric multiplication. Multiplies the numbers  |
  |   | on either side of the asterisk together.        |
  +---+-------------------------------------------------+
  | / | Numeric division. The number on the left of     |
  |   | the slash is divided by the number on the       |
  |   | right. Note that TADS numbers are all           |
  |   | integers; the remainder of the division is      |
  |   | discarded. Hence, 7/2 has a value of 3.         |
  +---+-------------------------------------------------+

  +---+-------------------------------------------------+
  | + | Adds numbers, concatenates lists, concatenates  |
  |   | strings. If both the left and right are         |
  |   | numbers, the result is numeric addition. If     |
  |   | one or the other is a list, but not both, the   |
  |   | non-list is added as the last element of the    |
  |   | list. If both operands are lists, the items     |
  |   | from the list on the right side are appended    |
  |   | to the list on the left; for example, [1 2 3]   |
  |   | + [4 5] yields the list [1 2 3 4 5]. If both    |
  |   | are strings, the right string is concatenated   |
  |   | to the left string. Other datatypes are         |
  |   | illegal.                                        |
  +---+-------------------------------------------------+
  | - | Subtracts numbers, removes items from lists.    |
  |   | If both operands are numbers, the right         |
  |   | operand is subtracted from the left. If the     |
  |   | left element is a list, the right item is       |
  |   | removed from the list if it appears in the      |
  |   | list on the left (nothing happens if not); if   |
  |   | the right item is also a list, each element     |
  |   | from the right list that appears in the left    |
  |   | list is removed from the left list. Other       |
  |   | datatypes are illegal.                          |
  +---+-------------------------------------------------+

  +----+------------------------------------------------+
  | =  | Equality. The datatypes on either side must    |
  |    | be the same, but can't be lists. One           |
  |    | exception: anything can be compared for        |
  |    | equality to nil. Evaluates to true if the      |
  |    | items are the same, nil otherwise.             |
  +----+------------------------------------------------+
  | <> | Inequality. True if the operands on both       |
  |    | sides are not the same (although the datatype  |
  |    | of each operand must be the same).             |
  +----+------------------------------------------------+
  | >  | Greater than. Like the other comparison        |
  |    | operators, this may only be applied to         |
  |    | numbers and strings. Evaluates to true or      |
  |    | nil. Note that, when applied to strings, the   |
  |    | comparison is based on the collation sequence  |
  |    | of the character set of the computer you are   |
  |    | using, such as ASCII.                          |
  +----+------------------------------------------------+
  | <  | Less than.                                     |
  +----+------------------------------------------------+
  | >= | Greater than or equal to.                      |
  +----+------------------------------------------------+
  | <= | Less than or equal to.                         |
  +----+------------------------------------------------+

  +-----+-----------------------------------------------+
  | and | Logical product: both the left and right      |
  |     | sides must be true, in which case the value   |
  |     | is true; otherwise, the value is nil. Note    |
  |     | that if the left operand is nil, the right    |
  |     | operand is not evaluated at all, since the    |
  |     | value of the expression will be nil           |
  |     | regardless of the value of the right operand. |
  +-----+-----------------------------------------------+

  +----+------------------------------------------------+
  | or | Logical sum: one or the other of the left or   |
  |    | right operators must be true for the value to  |
  |    | be true; otherwise the value is nil. Note      |
  |    | that if the left operand is true, the right    |
  |    | operand is not evaluated at all, since the     |
  |    | value of the expression will be true           |
  |    | regardless of the value of the right operand.  |
  +----+------------------------------------------------+

  +-----+-----------------------------------------------+
  | ? : | Conditional. This is a tertiary operator;     |
  |     | that is, it takes three operands, of the      |
  |     | form cond ? true-expr : false-expr. First,    |
  |     | the cond is evaluated; if it evaluates to     |
  |     | true or a non-zero number, then the           |
  |     | true-expr is evaluated, and its value is the  |
  |     | value of the entire conditional expression.   |
  |     | If the cond is false, the false-expr is       |
  |     | evaluated, and its value is the value of the  |
  |     | entire expression. Note that either           |
  |     | true-expr or false-expr is evaluated - not    |
  |     | both. This allows you to use this operator    |
  |     | when the expressions have side effects, such  |
  |     | as displaying strings.                        |
  +-----+-----------------------------------------------+

  +----+------------------------------------------------+
  | := | Assignment. The variable or property on the    |
  |    | left of the operator is assigned the value on  |
  |    | the right side. This is the lowest priority    |
  |    | operator, and operates right to left, unlike   |
  |    | the other operators. Hence, a := b := 3        |
  |    | assigns the value 3 to b, then to a. Note      |
  |    | that an assignment is an expression, which     |
  |    | returns the assigned value; hence, the value   |
  |    | of (a := 3) + 4 is 7, with the side effect     |
  |    | that the variable a has been set to 3.         |
  +----+------------------------------------------------+
  | += | Add and assign. This is simply short-hand      |
  |    | notation. The expression a += b has exactly    |
  |    | the same effect as the expression a := a + b,  |
  |    | except that the += operator makes the          |
  |    | expression easier to write. The value of the   |
  |    | expression is a + b, which is the same as the  |
  |    | value of a after the assignment.               |
  +----+------------------------------------------------+
  | -= | Subtract and assign. This is short-hand        |
  |    | notation. The expression a -= b has the same   |
  |    | effect as a := a - b.                          |
  +----+------------------------------------------------+
  | *= | Multiply and assign. The expression a *= b     |
  |    | has the same effect as a := a * b.             |
  +----+------------------------------------------------+
  | /= | Divide and assign. The expression a /= b has   |
  |    | the same effect as a := a / b.                 |
  +----+------------------------------------------------+

  +---+-------------------------------------------------+
  | , | Conjunction. The comma operator simply allows   |
  |   | you to start a new expression within an         |
  |   | expression. On the left hand side is an         |
  |   | expression, and on the right hand side is       |
  |   | another expression. The two expressions are     |
  |   | independent; the comma operator performs no     |
  |   | computation on either expression. The value of  |
  |   | a pair of expressions separated by a comma is   |
  |   | the value of the second (right-hand)            |
  |   | expression. The comma operator is useful        |
  |   | mostly in contexts where an expression is       |
  |   | required, but you wish to evaluate several      |
  |   | otherwise independent expressions for their     |
  |   | side effects. For example, in the               |
  |   | initialization portion of a for statement, you  |
  |   | often wish to initialize several variables;     |
  |   | you can do this by separating the               |
  |   | initializations with commas. See the            |
  |   | description for statement later in this         |
  |   | chapter. Note: the comma operator is different  |
  |   | from a comma that appears in a function's or    |
  |   | method's argument list. In the argument list,   |
  |   | the comma simply separates different            |
  |   | expressions that are the arguments; in a        |
  |   | normal expression, however, the comma           |
  |   | separates parts of the same expression.         |
  +---+-------------------------------------------------+

     The operators are shown above in their order of
     evaluation, from first to last. Hence,
     conjunctions are done last, after all
     higher-precedence operators have been evaluated.
     Note that there are some groups of operators in
     the list above; for example, all of the
     comparison operators are grouped together. This
     indicates that these operators have the same
     precedence. Operators of the same precedence
     associate left to right; for example, 3-4+5 is
     evaluated as (3-4)+5. The exception is the
     assignment operator, which groups right to left;
     that is, in the expression a := b := 2, b is
     first set to 2, then a is set to b.

     You can use parentheses to force a different
     order of evaluation of your expression.

------------------------------------------------------------
Assignments

     An assignment is not a special type of statement;
     it is merely an expression which uses an
     assignment operator:

       item := expression;

     The item is a local variable, a list element, or
     an object's property. When assigning to a
     property of an object, the object reference may
     itself be an expression. Likewise, when assigning
     to a list element, the list and index may both be
     expressions. Note, however, that lists cannot be
     expanded by assigning to an element past the end
     of the list; the index must refer to an existing
     member of the list to be replaced. A few examples
     of assignments:

       a: function(b, c)
       {
         local d, e, lst;
         d := b + c;                                     // assign a local variable
         obj3.prop1 := 20;                                // assign obj3's property
         prop1 e := obj3;                   // assign an object to a local variable
         e.prop1 := obj2;                // assign obj3's property prop1 the object
         obj2 e.prop1.prop2 := 20;    // assign obj2's property prop2 the number 20
         fun1(3).prop3 := 1 + d;     // assign prop3 of the object returned by fun1
         lst := [1 2 3 4 5];                 // set up a local variable with a list
         lst[3] := 9;                                     // lst is now [1 2 9 4 5]
         lst[5] := 10;                                 // and it's [1 2 9 4 10] now
         /* lst[6] := 7 would be illegal - the list is only 5 elements long */
       }

------------------------------------------------------------
C-Style Operators

     TADS users who are also C programmers often find
     the substantial similarity between TADS and C to
     be convenient, but also find the slight
     differences to be a source of confusion when
     switching between the two languages. TADS offers
     the option to use C-style operators. Note that if
     you're not an experienced C programmer you
     probably won't need to read this section.

     First, TADS supports the full complement of C
     operators.

  +---------+-------------------------------------------+
  | a % b   | Returns the remainder of dividing a by b  |
  +---------+-------------------------------------------+
  | a %= b  | Assigns (a % b) to a                      |
  +---------+-------------------------------------------+
  | a != b  | Equivalent to (a <> b)                    |
  +---------+-------------------------------------------+
  | !a      | Equivalent to (not a)                     |
  +---------+-------------------------------------------+
  | a & b   | Bitwise AND                               |
  +---------+-------------------------------------------+
  | a &= b  | sets a to (a & b) (the bitwise AND of a   |
  |         | and b)                                    |
  +---------+-------------------------------------------+
  | a | b   | bitwise OR                                |
  +---------+-------------------------------------------+
  | a |= b  | sets a to (a | b) (the bitwise OR of a    |
  |         | and b)                                    |
  +---------+-------------------------------------------+
  | a && b  | equivalent to (a and b)                   |
  +---------+-------------------------------------------+
  | a || b  | equivalent to (a or b)                    |
  +---------+-------------------------------------------+
  | a ^ b   | bitwise XOR of a and b                    |
  +---------+-------------------------------------------+
  | a ^= b  | sets a to (a ^ b) (the bitwise XOR of a   |
  |         | and b)                                    |
  +---------+-------------------------------------------+
  | ~a      | bitwise negation of a                     |
  +---------+-------------------------------------------+
  | a << b  | a shifted left by b bits                  |
  +---------+-------------------------------------------+
  | a <<= b | sets a to (a b) (shifts a left by b bits) |
  +---------+-------------------------------------------+
  | a >> b  | a shifted right by b bits                 |
  +---------+-------------------------------------------+
  | a >>= b | sets a to (a b) (shifts a right by b      |
  |         | bits)                                     |
  +---------+-------------------------------------------+

     Some of these operators, such as !, &&, and ||,
     are merely synonyms for existing operators. The
     "bitwise" operators act on numeric values rather
     than logical values; they treat their operands as
     bit vectors, and apply the operation to each bit
     of the numbers. For example, 3 & 2 has the value
     2, since the bit patterns are "011" and "010,"
     respectively. The bit-shift operations are
     equivalent to multiplying or dividing by a power
     of 2: 1 << 5 has the value 32, since it's
     equivalent to multiplying 1 by 2 raised to the
     5th power.

     Second, TADS has a mode which uses the C-style
     assignment operator. Normally, the TADS
     assignment operator is :=, and the equality
     operator is =. In C, these operators are = and ==
     respectively. If you prefer, you can tell TADS to
     use the C-style operators instead of the TADS
     version. By default, TADS still uses its own
     version of the operators. There are two ways to
     switch into C-style operator mode: by using a
     command-line option, or by using a #pragma
     compiler directive in your source code.

     To compile an entire game in C mode, use the -C+
     command line option (Macintosh users will find a
     menu item for C-style operators under the
     "Options" menu; check this item to enable C
     operators, and uncheck it to use standard TADS
     operators). Using the -C+ compiler option enables
     C operator mode for the entire game's source
     code. (The -C- option explicitly turns off C
     operator mode. This is the default mode.)

     To specify that a particular file is to be
     compiled in C mode, you can use the directive
     #pragma C+. The similar directive #pragma C-
     specifies that TADS operator mode is to be used.
     These directives can appear anywhere in a source
     file (outside of comments and strings); they must
     be alone on the line, and must not be preceded by
     any whitespace on the line.

     A #pragma setting affects only the current source
     file, and any files it includes. The header files
     included with TADS (adv.t and std.t) both use
     TADS operators, so they explicitly specify
     #pragma C-. However, because these directives are
     limited to the header files, you can freely
     include adv.t from a file that uses C operator
     mode without having to worry about setting the
     mode to or from TADS mode. Simply #include adv.t
     exactly as you did before - even if your source
     file uses C mode, adv.t will compile correctly,
     because it sets the operator mode back to TADS
     for its own contents, and TADS automatically
     restores the enclosing file's mode at the end of
     adv.t.

     Note that the C-style operator mode setting
     affects only the assignment and equality
     operators. You can use all of the other C
     operators (such as the bitwise operators) in
     either mode - all of these symbols were invalid
     in previous versions of TADS, so there's no
     danger that they'll be misinterpreted for old
     games.

     When the compiler is using C-style assignment
     operators, it issues a warning, "possibly
     incorrect assignment," whenever it finds a
     statement in this format:

       if ( a = 1 ) ...

     While this statement is legal, with C-style
     operators it has the effect of assigning the
     value 1 to a; since the value of an assignment is
     the value assigned, this if will always succeed.
     It's a common error for C programmers (even
     highly experienced ones) to write this type of
     statement when they really want to compare the
     values. In fact, I originally chose to use ":="
     as the assignment operator in TADS to reduce the
     likelihood of this type of error. Now that TADS
     can be switched to C syntax for assignments and
     comparisons, I've added the "possibly incorrect
     assignment" warning to help catch these. The
     compiler will flag assignments made in if, while,
     and do statements, and in the condition clause of
     for statements. To suppress this warning, you can
     explicitly test the value of the assignment like
     this:

       if ( ( a = 1 ) != 0 ) ...

     There are a couple of minor complications with
     some of the C-style operators.

     First, the >> operator can't be used in an
     expression embedded in a string with the << >>
     construct, because it would be taken for the >>
     that terminates the embedded expression. Even
     adding parentheses won't help, because the
     compiler recognizes the << >> construct before it
     looks at any expression in progress. So, this
     type of code won't work:

       myprop = "x divided by 128 is << (x >> 7) >>! " // wrong

     You would have to code this instead as:

       myprop = { "x divided by 128 is "; x >> 7; "! "; } // right

     Second, the & operator now has a binary
     interpretation in addition to its unary
     interpretation. For the most part, this won't
     create any confusion, but there's one situation
     in which it might: in lists. You might have lists
     in your games that look like this:

       mylist = [ &prop1 &prop2 &prop3 ]

     In past versions, since the & operator could only
     be a unary operator, this construct was
     unambiguous. However, now that & can be a binary
     operator, this could be interpreted either as
     three expressions involving unary & operators, or
     as a single expression involving one unary &
     operator and two binary & operators.

     For compatibility with past versions, TADS will
     interpret the & operators as unary operators.
     When it finds this construct, though, it will
     warn you that it is ambiguous. (The new warning
     is TADS-357, operator `&' interpreted as unary in
     list.) You can suppress this warning in one of
     two ways. First, you can render the list
     unambiguous. To do this, use a comma between each
     pair of list elements:

       mylist = [ &prop1, &prop2, &prop3 ]

     Note that if you actually want the binary
     interpretation, you should simply enclose the
     expression in parentheses:

       mylist = [ ( 2 & 3 & 4 ) ]

     The other way you can suppress this message is
     with the new -v-abin compiler option, which tells
     the compiler not to generate the warning. The
     compiler still interprets the operator the same
     way when you specify -v-abin - it just doesn't
     tell you about it.

     Note that TADS will treat any operator which has
     both a unary and binary interpretation as a unary
     operator when it finds it within a list, and will
     generate the TADS-357 warning. For the -
     operator, this is a change from past versions,
     which used the binary interpretation when in a
     list. I don't anticipate that this will be a
     compatibility problem, because the old binary
     interpretation was almost never desirable, and I
     think users avoided it. However, if you have an
     older game, you may wish to compile without the
     -v-abin option at least once, and check any lines
     where the TADS-357 warning is generated for - or
     + operators, to determine if your game's behavior
     will change with the new version. Any TADS-357
     warnings generated for the & operator can be
     safely ignored for a game written with a previous
     version of TADS.

------------------------------------------------------------
Function Calls

     A function call is simply an expression involving
     a call to a function.

       function-name( [ argument-list ] );

     The function-name is the name of a function
     defined elsewhere. The argument list, if
     provided, is passed to the function for its
     parameters. (Naturally, the arguments passed to a
     function should match in number those defined in
     the function's definition.) Each parameter can be
     an arbitrary expression, and the individual
     arguments are separated by commas.

     Whether there's an argument list or not, the
     parentheses are required; they tell the compiler
     that you wish to call the function. (You may
     wonder where you would ever want to use a
     function's name other than when calling the
     function. A few special built-in functions, such
     as setdaemon, which will be discussed in detail
     later, allow you to specify a function that is to
     be called eventually, but not right away. In
     these cases, you need to be able to refer to a
     function without actually calling it. In these
     cases, you use the function's name without
     parentheses.)

     If the function returns a value, the value is
     discarded in this form of the call. A function
     called in this manner is invoked for its side
     effects rather than its return value.

     An example:

       showlist(a+100, 'The list is: ', list1);

------------------------------------------------------------
Indirect Function and Method Calls

     You can call a function or method "indirectly" -
     that is, you can use a pointer to a function or
     method to call the function or method. Another
     way of looking at it is you can refer to the
     function or method without actually evaluating
     (triggering it). This can sometimes be useful in
     setting up a general routine which calls other
     routines based on parameters passed into it.

     To call a function with a function pointer,
     simply use an expression yielding a function
     pointer, within parentheses, where you'd normally
     use a function name. For example:

       g: function(a, b, c)
       {
         return(a + b + c);
       }

       f: function
       {
         local fptr, x;
         fptr := &g;            /* get address of function g */
         x := (fptr)(1, 2, 3);  /* call function with pointer */
       }

     A property pointer is used in essentially the
     same way.

       f: function(actor, obj)
       {
         local propPtr := &doTake;  /* get pointer to doTake property */
         obj.(propPtr)(actor);      /* call property through pointer */
       }

     For example, suppose you wish to implement a way
     of asking characters in a game about various
     objects in the game. One way you could do this is
     by defining a general "ask" routine that takes
     the character and the object as arguments. Set
     things up so that each object defines a property
     saying what each actor knows about that object.
     Then, each actor specifies via a "property
     pointer" which property to evaluate in an object
     to find out what the actor knows about the
     object. If an object doesn't define this
     property, the actor doesn't know anything about
     that object.

     So, our general "ask" routine is very simple (or
     concise, anyway):

       ask: function(actor, obj)
       {
         local propPtr;

         /* find out what property to evaluate in the object */
         propPtr := actor.askPropPtr;

         /* see if it's defined in the object */
         if (defined(obj, propPtr))
         {
           /* it is defined - call the property indirectly */
           obj.(propPtr);
         }
         else
         {
           /* it's not defined - use default message */
           actor.dontKnow;
         }
       }

     Now, each actor simply has to define a property
     that each object uses to specify what the actor
     knows about the object, and place the address of
     this property the actor's askPropPtr property.
     The actor also needs to define the default
     message in the dontKnow property. Here's an
     example:

       joe: Actor
         sdesc = "joe"
         noun = 'joe'
         dontKnow = "Joe just scratches his head and shrugs. "
         askJoe = "You probably don't want to get Joe started on his life story. "
         askPropPtr = askJoe
       ;

     Finally, each object must define an appropriate
     askJoe property if Joe knows anything about that
     object. Likewise, it will define other properties
     for what other actors know about it. This way,
     all of the information about an object, including
     what the various characters in the game know
     about it, can be kept with the object itself. In
     addition, the general "ask" routine is extremely
     simple. The overall concept behind the mechanism
     is somewhat complicated, but the finished product
     is very simple and easy to use and expand.

------------------------------------------------------------
*>return

     A function can return a value to its caller by
     using a statement such as:

       return [ expression ];

     With or without the expression, execution of the
     function is terminated and the caller resumes
     execution where it left off. If the expression is
     provided, the caller receives the expression as
     the function's value.

     Here's an example of a function that computes the
     sum of the elements of a list, and returns the
     sum as the value of the function.

       listsum: function(lst)
       {
         local i, sum, len := length(lst);
         for (i := 1, sum := 0 ; i <= len ; i++)
           sum += lst[i];
         return(sum);
       }

     Note that the brackets are optional. Thus the
     following form is perfectly legal:

       return nil;

     In fact, recent versions of adv.t use the
     bracketless style as the preferred form.

------------------------------------------------------------
*>if
*>else

     The general form of the conditional in TADS is:

       if ( expression ) statement
       [ else statement ]

     Here and elsewhere, a statement can be either a
     single statement or a series of statements
     enclosed in braces. The expression should
     evaulate to either a number, in which case zero
     counts as false and anything else counts as true,
     or to a truth value, true or nil.

     Note that the optional else clause is grouped
     with the most recent if statement when if
     statements are nested. For example,

       if (self.islit)
         if (film.location = Me)
           "Oops! You've exposed the film! ";
         else
           "It's dark in here. ";

     The author of this code obviously intended the
     else clause to go with the first if, but remember
     that an else goes with the most recent if, so it
     actually is grouped with the second if statement.
     This problem can be easily rectified by using
     braces to make the grouping explicit:

       if (self.islit)
       {
         if (film.location = Me)
         {
           "Oops! You've exposed the film! ";
         }
         else
         {
           "It's dark in here. ";
         }
       }

------------------------------------------------------------
*>switch
*>case
*>default

     The switch statement lets you set up the
     equivalent of a large if-else tree, but is
     considerably easier to read and is more efficient
     to execute. A switch statement allows you to test
     a particular value against several alternatives,
     and execute a group of statements accordingly.

     The form of the switch statement is:

       switch ( expression )
       {
         [ case-list ]
         [ default-clause ]
       }

     The form of the case-list is:

       case constant-expression :
         [ statements ]
         [ case-list ]

     The form of the default-clause is:

       default:
         [ statements ]

     In the diagrams, statements means that zero or
     more statements can follow a case or default. You
     do not need to supply any case labels at all, and
     the default is also optional.

     The expression evaluates to a number, string,
     object, list, or true or nil. The value of the
     expression is then tested against each case
     value. If the value matches one of the case
     values, the statements following the matching
     case are executed. If the value does not match
     any case value, and a default case is defined,
     the statements following the default are
     executed. If the value does not match any case
     value, and there is no default case, the entire
     switch statement is skipped, and execution
     resumes following the closing brace of the switch.

     Note that execution is not interrupted when
     another case is enountered. Instead, it just
     continues into the statements following the case
     label. If you wish to stop executing statements
     in the switch at the end of the statements for a
     single case, you must use the break statement.

     The break statement has a special meaning within
     a switch statement: it indicates that execution
     should break out of the switch statement and
     resume following the closing brace of the switch.

     Here's an example of a switch statement.

     f: function(x)
     {
       switch(x)
       {
         case 1:
           "x is one";
           break;
         case 2:
         case 3:
           "x is either 2 or 3";
           break;
         case 4:
           "x is 4";
         case 5:
           "x is either 4 or 5";
         case 6:
           "x is 4, 5, or 6";
           break;
         case 7:
           "x is 7";
           break;
         default:
           "x is not in 1 through 7";
       }
     }

------------------------------------------------------------
*>while

     The while statement defines a loop: a set of
     statements that is executed repeatedly as long as
     a certain condition is true.

       while ( expression ) statement

     As with the if statement, the statement may be a
     single statement or a set of statements enclosed
     in braces. The expression should be a number (in
     which case 0 is false and anything else is true),
     or a truth value (true or nil).

     The expression is evaluated before the first time
     through the loop; if the expression is false at
     that time, the statement or statements in the
     loop are skipped. Otherwise, the statement or
     statements are executed once, and the expression
     is evaluated again; if the expression is still
     true, the loop executes one more time and the
     cycle is repeated. Once the expression is false,
     execution resumes at the next statement after the
     loop.

------------------------------------------------------------
*>do

     The do-while statement defines a slightly
     different type of loop than the while statement.
     This type of loop also executes until a
     controlling expression becomes false (0 or nil),
     but evaluates the controlling expression after
     each iteration of the loop. This ensures that the
     loop is executed at least once, since the
     expression isn't tested for the first time until
     after the first iteration of the loop.

     The general form of this statement is:

       do statement while ( expression );

     The statement may be a single statement or a set
     of statements enclosed in braces. The expression
     should be a number (in which case 0 is false and
     anything else is true), or a truth value (true or
     nil).

------------------------------------------------------------
*>for

     The for statement defines a very powerful and
     general type of loop. You can always use while to
     construct any loop that you can construct with
     for, but the for statement is often a much more
     compact and readable notation for the same effect.

     The general form of this statement is:

       for ( init-expr ; cond-expr ; reinit-expr ) statement

     As with other looping constructs, the statement
     can be either a single statement, or a block of
     statements enclosed in braces.

     The first expression, init-expr, is the
     "initialization expression." This expression is
     evaluated once, before the first iteration of the
     loop. It is used to initialize the variables
     involved in the loop.

     The second expression, cond-expr, is the
     condition of the loop. It serves the same purpose
     as the controlling expression of a while
     statement. Before each iteration of the loop, the
     cond-expr is evaluated. If the value is true (a
     non-zero number, or true), the body of the loop
     is executed; otherwise, the loop is terminated,
     and execution resumes at the statement following
     the loop body. Note that, like the while
     statement's controlling expression, the cond-expr
     of a for statement is evaluated prior to the
     first time through the loop (but after the
     init-expr has been evaluated), so a for loop will
     execute zero times if the cond-expr is false
     prior to the first iteration.

     The third expression, reinit-expr, is the
     "re-initialization expression." This expression
     is evaluated after each iteration of the loop.
     Its value is ignored; the only purpose of this
     expression is to change the loop variables as
     necessary for the next iteration of the loop.
     Usually, the re-initialization expression will
     increment a counter or perform some similar
     function.

     Any or all of the three expressions may be
     omitted. Omitting the expression condition is
     equivalent to using true as the expression
     condition; hence, a loop that starts "for ( ;; )"
     will iterate forever (or until a break statement
     is executed within the loop). A for statement
     that omits the initialization and
     re-initialization expressions is the same as a
     while loop.

     Here's an example of using a for statement. This
     function implements a simple loop that computes
     the sum of the elements of a list.

       sumlist: function(lst)
       {
         local len := length(lst), sum, i;
         for (sum := 0, i := 1 ; i <= len ; i++)
           sum += lst[i];
       }

     Note that an equivalent loop could be written
     with an empty loop body, by performing the
     summation in the re-initialization expression. We
     could also move the initialization of len within
     the initialization expression of the loop.

       sumlist: function(lst)
       {
         local len, sum, i;
         for (len := length(lst), sum := 0, i := 1 ; i <= len ;
           sum += lst[i], i++);
       }

------------------------------------------------------------
*>break

     A program can get out of a loop early using the
     break statement:

       break;

     This is useful for terminating a loop at a
     midpoint. Execution resumes at the statement
     immediately following the innermost loop in which
     the break appears.

     The break statement also is used to exit a switch
     statement. In a switch statement, a break causes
     execution to resume at the statement following
     the closing brace of the switch statement.

------------------------------------------------------------
*>continue

     The continue statement does roughly the opposite
     of the break statement; it resumes execution back
     at the start of the innermost loop in which it
     appears. The continue statement may be used in
     for, while, and do-while loops.

     In a for loop, continue causes execution to
     resume at the re-initialization step. That is,
     the third expression (if present) in the for
     statement is evaluated, then the second
     expression (if present) is evaluated; if the
     second expression's value is non-nil or the
     second expression isn't present, execution
     resumes at the first statement within the
     statement block following the for, otherwise at
     the next statement following the block.

------------------------------------------------------------
*>goto

     The goto statement is used to transfer control
     unconditionally to another point within the same
     function or method. The target of a goto is a
     label; a label is defined by placing its name,
     followed by a colon (:), preceding a statement.

     Note that labels have function- or method-scope;
     that is, they are visible within the entire
     function or method in which they are defined.
     This is different from local variables, which are
     visible only within the block (the group of
     statements enclosed in braces) in which they are
     defined. Labels are not visible outside the
     function or method in which they are defined.

     An example of using goto:

       f: function
       {
         while (true)
         {
           for (x := 1 ; x < 5 ; x++)
           {
             /* do some stuff */
             if (myfunc(3) < 0)  /* did an error result? */
               goto exitfunc;    /* error - quit now */
             /* do some more stuff */
           }
         }
         /* come here if something goes wrong */
         exitfunc: ;
       }

     This use of goto avoids the need for testing a
     flag in the outer (while) loop, which makes the
     code a little simpler and easier to understand.

     The goto statement is widely considered among
     civilized computer scientists to be an evil and
     malevolent feature of ancient and unusable
     languages, and the esteem of TADS within serious
     computer language design circles has undoubtedly
     been fatally injured by the inclusion of this
     construct. So, you may wish to use this statement
     sparingly, if at all, especially if you're hoping
     to impress a civilized computer scientist with
     your coding efforts. However, many software
     engineers look upon goto as a highly useful
     statement when in the hands of a seasoned
     professional, and scoff at the blanket indictment
     by the more-elegant-than-thou academic
     establishment, most of whom probably haven't
     written a line of code since their TA's were
     chastising them for using goto in their Pascal
     programs, excepting perhaps some algorithms
     written in pseudo-code that always end in "the
     rest is left as an exercise for the reader"
     anyway. The author of TADS doesn't wish to take
     sides in this heated controversy, but hopes that
     both camps will be pleased, by gaining either the
     utility of using goto with wild abandon or the
     sense of virtue of knowing they could have used
     it but overcame the unclean temptation. With
     TADS, the choice is yours.

------------------------------------------------------------
*>pass

     A method can decide to inherit the behavior of
     its parent class by using the pass statement:

       pass method-name;

     The method-name must be the same as the name of
     the method that the pass statement occurs in.
     When a pass statement is executed, the method
     that would have been inherited if the object had
     not overridden it is called with the same
     arguments, if any, as the method called in the
     first place. The self object is unchanged; that
     is, the superclass method is run, but self is the
     object that was originally sent the message being
     passed.

------------------------------------------------------------
*>abort
*>exit

     During processing of a player's command, the game
     can terminate the normal sequence of events and
     return to the get another command from the player
     in three different ways. The abort statement
     stops all processing, and gets the next command;
     it is normally used by "system" functions, such
     as saving the game, that should not count as a
     turn, and therefore shouldn't run any daemons or
     fuses. The exit statement, on the other hand,
     skips everything up to the fuses and daemons and
     so is used when an actor wishes to stop further
     processing, and other similar cases. Finally, the
     exitobj function does what exit does except that
     it skips the remaining processing only for the
     current object in a command and proceeds to the
     next object.

     Note that messages to objects scheduled with the
     notify() function are treated the same as other
     daemons and fuses, so these are also skipped by
     the abort statement.

     You can use the abort statement within a daemon
     or fuse, and it will work as expected, by
     terminating the current routine and skipping any
     remaining fuses or daemons on this turn. (this
     wasn't allowed in older versions of TADS)

------------------------------------------------------------
*>askdo
*>askio

     These statements interrupt processing of a turn
     like abort, skipping fuses and daemons, but allow
     the user to enter more information. The askdo
     command asks the user to enter a direct object;
     the system displays a message asking the user for
     an object. The user can either enter an object in
     response to the request, or can simply type a new
     command. For example, if the verb is "take,"
     executing an askdo command will cause the system
     to display "What do you want to take?" and wait
     for an object or a new command. The askio command
     is similar, but it takes a preposition as a
     parameter; this preposition is added to the
     command, and the system prompts the player for an
     indirect object. For example, if the verb is
     "unlock," and the following command is executed:

       askio(withPrep);

     then the system displays "What do you want to
     unlock it with?" and prompts the player for an
     object or a new command. The askio command can
     only be used when a direct object is already
     present.

     In either case, if the player responds to the
     request with an object, the command is tried
     again from the start. If the player types a new
     command, the command that resulted in the askdo
     or askio is discarded. Note that control never
     comes back to the statement after the askdo or
     askio command, regardless of user input; in
     either case, command processing starts from the
     top.

     Note that, in some cases, the system won't
     actually ask the player for a new object.
     Instead, the system will attempt to find a
     default object, using exactly the same mechanisms
     that it uses to find default objects normally
     (see the section on the parser's default object
     mechanisms in chapter four).

------------------------------------------------------------
*>self

     When code associated with a property is being
     executed, a special object is defined, called
     self. This special object refers to the object
     whose property is being evaulated. This may not
     sound too useful, but consider the case of an
     object whose superclass defines a property which
     refers to other properties of the object:

       class book: object
         description =
         {
           "The book is << self.color >>.";
         }
       ;

       redbook: book
         color = "red"
       ;

       bluebook: book
         color = "blue"
       ;

     In this example, the general object, book, knows
     how to describe a book given its color. The books
     that are defined, the redbook and bluebook
     objects, take advantage of this by simply
     defining their color, and letting the description
     property of their superclass be used to describe
     them. So, when you attempt to evaluate
     redbook.description, you get

       The book is red.

------------------------------------------------------------
*>inherited

     A special pseudo-object called inherited allows
     you to call a method in the current self object's
     superclass. This pseudo-object is similar to the
     pass statement, but much more useful in several
     ways. First, with inherited, you can simply call
     the superclass method, and regain control when it
     returns; with pass, the current method never
     regains control. Second, you can use inherited in
     an expression, so any value returned by the
     superclass method can be determined and used by
     the current method. Third, you can pass arguments
     to the property invoked with the inherited
     pseudo-object.

     You can use inherited in an expression anywhere
     that you can use self.

     Here is an example of using inherited.

       myclass: object
         sdesc = "myclass"
         prop1(a, b) =
         {
           "This is myclass's prop1.  self = << self.sdesc >>,
           a = << a >>, and b = << b >>.\n";
           return(123);
         }
       ;

       myobj: myclass
         sdesc = "myobj"
         prop1(d, e, f) =
         {
           local x;
           "This is myobj's prop1.  self = << self.sdesc >>,
           d = << d >>, e = << e >>, and f = << f >>.\n";
           x := inherited.prop1(d, f) * 2;
           "Back in myobj's prop1.  x = << x >>\n";
         }
       ;

     When you call myobj.prop1(1, 2, 3), the following
     will be displayed:

       This is myobj's prop1. self = myobj, d = 1, e = 2, and f = 3.
       This is myclass's prop1. self = myobj, a = 1, and b = 3.
       Back in myobj's prop1. x = 246.

     Note one feature of inherited that is the same as
     pass: the self object that is in effect while the
     superclass method is being executed is the same
     as the self object in the calling (subclass)
     method. This makes inherited very different from
     calling the superclass method directly (i.e., by
     using the superclass object's name in place of
     inherited).

     TADS 2.2.4 added a new syntax that lets you
     specify the name of the superclass after the
     `inherited' keyword, but is otherwise similar to
     the normal `inherited' syntax:

       inherited fixeditem.doTake(actor);

     This specifies that you want the method to
     inherit the doTake implementation from the
     fixeditem superclass, regardless of whether TADS
     might normally have chosen another superclass as
     the overridden method. This is useful for
     situations involving multiple inheritance where
     you want more control over which of the base
     classes of an object should provide a particular
     behavior for the subclass.

------------------------------------------------------------
*>argcount

     The pseudo-variable argcount returns the number
     of arguments to the current function. This can be
     used for functions that take a variable number of
     arguments to learn the number of arguments that
     need to be processed. Note that argcount isn't
     really a variable, so you can't assign a value to
     it, but otherwise you can use it as though it
     were an ordinary variable.

------------------------------------------------------------
*>replace
*>modify

     Most game authors find that, when writing a
     substantial game, they can't avoid modifying
     adv.t. While there's nothing intrinsically wrong
     with this, it creates a problem when a new
     version of TADS is released, because you must
     either continue to use the old version of adv.t,
     which means that any bug fixes or enhancements in
     the new version are not available, or take the
     time to reconcile your changes to your custom
     adv.t with those made in the standard version.
     The replace and modify mechanism can help you
     deal with this problem.

     These keywords allow you to make changes to
     objects that have been previously defined. In
     other words, you can #include the standard adv.t
     file, and then make changes to the objects that
     the compiler has already finished compiling.
     Using these keywords, you can make three types of
     changes to previously-defined objects: you can
     replace a function entirely, you can replace an
     object entirely, or you can add to or change the
     methods already defined in an object.

     To replace a function that's already been
     defined, you simply preface your replacement
     definition with the keyword replace. Following
     the keyword replace is an otherwise normal
     function definition. The following example
     replaces the scoreStatus function defined in
     adv.t with a new function that customizes the
     status line score display.

       #include <adv.t>

       replace scoreStatus: function( points, turns )
       {
         setscore( cvtstr( pts ) + ' points/' + cvtstr( turns ) + ' moves' );
       }

     You can do exactly the same thing with objects.
     For example, you can entirely replace the
     fastenVerb defined in adv.t:

       #include <adv.t>

       /* we don't want "buckle", so replace adv.t's fastenVerb */
       replace fastenVerb: deepverb
         verb = 'fasten'
         sdesc = "fasten"
         prepDefault = toPrep
         ioAction( toPrep ) = 'FastenTo'
       ;

     Replacing an object entirely deletes the previous
     definition, including all inheritance information
     and vocabulary. The only properties of a replaced
     object are those defined in the replacement; the
     original definition is entirely discarded.

     You can also modify an object, retaining its
     original definition (including inheritance
     information, vocabulary, and properties). This
     allows you to add new properties and vocabulary.
     You can also override properties, simply by
     redefining them in the new definition.

     The most common addition to an object from adv.t
     will probably be new verb associations and added
     vocabulary.

       modify pushVerb
         verb = 'nudge'
         ioAction( withPrep ) = 'PushWith'
       ;

     Note several things about this example. First, no
     superclass information can be specified in a
     modify statement; this is because the superclass
     list for the modified object is the same as for
     the original object. Second, note that vocabulary
     has been added. The additional vocabulary does
     not replace the original vocabulary, but simply
     adds to the previously-defined vocabulary.
     Further note that verb association
     pseudo-properties, such as doAction and ioAction,
     are legal in a modify definition. Any new
     doAction or ioAction definitions are added to the
     original set of definitions.

     In a method that you redefine with modify, you
     can use pass and inherited to refer to the
     replaced method in the original definition of the
     object. In essence, using modify renames the
     original object, and then creates a new object
     under the original name; the new object is
     created as a subclass of the original (now
     unnamed) object. (There is no way to refer to the
     original object directly; you can only refer to
     it indirectly through the new replacement
     object.) Here's an example of using pass with
     modify.

       class testClass: object
         sdesc = "testClass"
       ;

       testObj: testClass
         sdesc =
         {
           "testObj...";
           pass sdesc;
         }
       ;

       modify testObj
         sdesc =
         {
           "modified testObj...";
           pass sdesc;
         }
       ;

     Evaluating testObj.sdesc results in this display:

       modified testObj...testObj...testClass

     You can also replace a property entirely, erasing
     all traces of the original definition of a
     property. The original definition is entirely
     forgotten - using pass or inherited will refer to
     the method inherited by the original object. To
     do this, use the replace keyword with the
     property itself. In the example above, we could
     do this instead:

       modify testObj
         replace sdesc =
         {
           "modified testObj...";
           pass sdesc;
         }
       ;

     This would result in a different display for
     testObj.sdesc:

       modified testObj...testClass

     The replace keyword before the property
     definition tells the compiler to completely
     delete the previous definitions of the property.
     This allows you to completely replace the
     property, and not merely override it, meaning
     that pass and inherited will refer to the
     property actually inherited from the superclass,
     and not the original definition of the property.

------------------------------------------------------------
Built-in Functions

     The system has a set of built-in functions to
     facilitate writing programs. The functions are
     described in this section. They operate just like
     ordinary functions, with the exception that
     built-in functions which don't take arguments
     don't require parentheses; this simplifies coding
     of some special cases.

------------------------------------------------------------
*>addword

Call: addword(obj, &prop, word)

     Adds the word (a single-quoted string value) to
     the object as the given part of speech. The prop
     parameter can be noun, adjective, plural, verb,
     article, or preposition. You can add words to any
     object, including objects defined statically in
     your game, as well as objects created dynamically
     at run-time.

     For examples of using this function, see the
     section on Dynamic Vocabulary.

------------------------------------------------------------
*>askfile

Call: askfile(prompt_text, prompt_type_code,
file_type_code, flag)

Added: Type code parameters added with TADS 2.3.0. Flag
value added with TADS 2.5.0

     This function asks the user to enter a filename,
     in a system-dependent manner. The system's
     standard file dialogue, if the computer has one,
     will be used; otherwise, the user may simply be
     prompted to type a filename. The prompt (a
     single-quoted string value) may or may not be
     used, depending on system conventions; for
     systems without any defined standard file
     dialogue, it will be displayed to prompt the user
     for a filename.

     This function is primarily useful for operations
     such as saving and restoring games which require
     that the user enters a system filename. Prompt
     strings passed to askfile can contain \n and \t
     sequences. These sequences are converted properly
     for display in the dialogue.

     TADS 2.3 added two additional, optional
     parameters that let you specify what type of
     prompt to show and what type of file to request.
     These arguments are hints to the system-specific
     code that displays the "open file" dialogue; by
     specifying this new information, you help the
     system code show the correct type of dialogue.

     The prompt_type_code tells the open-file dialogue
     whether you're opening an existing file or saving
     a file. On some systems (Windows and Macintosh
     included), the user interface uses one type of
     dialogue for opening an existing file, and a
     different type of dialogue for saving a file; you
     can use this parameter to select the appropriate
     dialogue type on systems that make this
     distinction. This parameter can have one of the
     following values, defined in adv.t:

       ASKFILE_PROMPT_OPEN - open an existing
                             file for reading
       ASKFILE_PROMPT_SAVE - open a file for
                             saving information

     On some systems, the open-file dialogue will
     filter the files it displays so that the player
     only sees files of the particular type being
     requested. The file_type_code parameter lets you
     specify the type of file you're interested in, so
     that the dialogue can use the appropriate
     filtering on systems that support this. The
     file_type_code can be one of the following
     values, defined in adv.t:

       FILE_TYPE_GAME - a game data file (.gam)
       FILE_TYPE_SAVE - a saved game (.sav)
       FILE_TYPE_LOG - a transcript (log) file
       FILE_TYPE_DATA - general data file
                        (used for fopen())
       FILE_TYPE_CMD - command input file
       FILE_TYPE_TEXT - text file
       FILE_TYPE_BIN - binary data file
       FILE_TYPE_UNKNOWN - unknown file type

     If you leave out the type code arguments in a
     call to askfile(), the function will behave as it
     did with previous versions of TADS. This means
     that your prompt string must contain the word
     "save" or "write" in order to show a "save file"
     dialogue rather than an "open file" dialogue on
     those systems that differentiate between these
     dialogue types.

     The optional fourth argument added with TADS
     2.5.0 lets you specify additional flags to the
     askfile function. The possible flag values,
     defined in adv.t, are:

  +--------------------+--------------------------------+
  | ASKFILE_EXT_RESULT | Return extended result codes   |
  |                    | (described below). If this     |
  |                    | flag is provided, the          |
  |                    | function returns extended      |
  |                    | results; if this flag is not   |
  |                    | specified, the function        |
  |                    | returns the traditional        |
  |                    | results.                       |
  +--------------------+--------------------------------+

     In order to specify the new flag value argument,
     you must specify the prompt type and file type
     arguments as well; if you omitted the prompt or
     file type argument, the askfile function would
     not be able to tell that you meant the last
     argument as the flags value.

     If you omit the flags argument, askfile uses a
     default value of zero, which makes the function
     behave the same as in past versions. Because
     older code never specifies a flags value, the
     function will always behave compatibly with past
     versions when called from older code.

     Before the release of 2.5.0, askfile returned a
     string on success, or nil for any type of
     failure. However, this didn't permit the caller
     to determine exactly what kind of failure
     occurred, and in particular did not allow the
     caller to distinguish between an actual error and
     the player cancelling the file selector dialogue.
     When ASKFILE_EXT_RESULT is specified, the
     function will return additional information that
     allows the caller to distinguish these cases.

     When the ASKFILE_EXT_RESULT flag is specified,
     askfile returns a list that contains two
     elements. The first element is a number which
     indicates the status of the file selection; the
     second element is a string if a file was
     successfully chosen, or nil if not. The possible
     values for the first element of the returned
     list, defined in adv.t, are:

  +-----------------+-----------------------------------+
  | ASKFILE_SUCCESS | A file was successfully chosen.   |
  |                 | The second element of the list    |
  |                 | contains a string giving the      |
  |                 | chosen filename.                  |
  +-----------------+-----------------------------------+
  | ASKFILE_FAILURE | An error occurred prompting for   |
  |                 | a filename. This usually          |
  |                 | indicates that the file selector  |
  |                 | dialogue could not be shown for   |
  |                 | some reason (insufficient         |
  |                 | memory, for example).             |
  +-----------------+-----------------------------------+
  | ASKFILE_CANCEL  | The user canceled the file        |
  |                 | selector dialogue. On the         |
  |                 | Macintosh, for example, this      |
  |                 | means that the user clicked the   |
  |                 | "Cancel" button. This indicates   |
  |                 | that the user does not wish to    |
  |                 | proceed with whatever operation   |
  |                 | is in progress, so the operation  |
  |                 | should be aborted. Since the      |
  |                 | user explicitly chose to cancel   |
  |                 | the operation, the program        |
  |                 | should not indicate that an       |
  |                 | error occurred, but simply that   |
  |                 | the operation will be terminated  |
  |                 | in accordance with the user's     |
  |                 | request.                          |
  +-----------------+-----------------------------------+

     Here's an example, from the "restore" command's
     implementation in adv.t, of using the extended
     results.

       local savefile;

       savefile := askfile('File to restore game from',
                           ASKFILE_PROMPT_OPEN, FILE_TYPE_SAVE,
                           ASKFILE_EXT_RESULT);
       switch(savefile[1])
       {
         case ASKFILE_SUCCESS:
           return mainRestore(savefile[2]);

         case ASKFILE_CANCEL:
           "Cancelled. ";
           return nil;

         case ASKFILE_FAILURE:
         default:
           "Failed. ";
           return nil;
       }

------------------------------------------------------------
*>caps

Call: caps()

     Forces the next non-space character to be
     displayed to be capitalized. This is useful for
     formatting output when it is not known in advance
     whether an item will be displayed at the start of
     a sentence or not.

     Note that displaying the sequence "\^" has the
     same effect as calling caps().

     Do not confuse this function with the
     upper(string) built-in function, which converts
     all of the letters in a string to upper-case. The
     caps() function takes no arguments, and affects
     only the next character output.

------------------------------------------------------------
*>car

Call: car(list)

     Returns the first element of a list, or nil if
     the list is empty.

     Note that the same value can be retrieved with
     the expession list[1], which uses the list
     indexing operator to retrieve the first element
     of list. The primary difference between using
     car() and the list indexing operator is the style
     of your program; using car() and cdr() to
     decompose a list, you can iterate or recurse
     until you run out of list to process, at which
     time car() will return nil. With the list
     indexing operator, however, you need to know in
     advance how many elements are in the list; this
     information can be learned with the length()
     built-in function. The choice of one of these
     methods over another is a matter of personal
     preference.

------------------------------------------------------------
*>cdr

Call: cdr(list)

     Returns the end of a list; that is, the list of
     everything after the list's car(). With car() and
     cdr() you can decompose a list into its
     individual elements.

------------------------------------------------------------
*>clearscreen

Call: clearscreen()

     Clears the screen. This function may have no
     effect when called under some versions of the
     TADS interpreter. For example, when the DOS
     runtime is operating in plain ASCII mode,
     clearscreen() will have no effect. Other
     interpreters clear the screen by displaying a
     screenful of blank spaces, allowing you to view
     previously-displayed text in the scrollback.
     Others may simply reset the text window, so you
     lose everything that was in the scrollback.

     This function has a special meaning in
     multimedia-enabled versions of the TADS
     interpreter. The function clears the screen but
     retains the contents of the screen as a chapter.
     You can thus flip from one chapter to the next by
     using the appropriate menu items.

------------------------------------------------------------
*>cvtnum

Call: cvtnum(string)

     This function converts a string that contains the
     text version of a number into a numeric value.
     For example, cvtnum('1234') returns the number
     1234. Note that the special strings `true' and
     `nil' are also accepted by the function, and are
     converted to the logical values true and nil,
     respectively.

------------------------------------------------------------
*>cvtstr

Call: cvtstr(value)

     This function converts a numeric or logical value
     into its string representation. For example,
     cvtstr(1234) returns the string `1234',
     cvtstr(true) returns the string `true', and
     cvtstr(nil) returns the string `nil'.

------------------------------------------------------------
*>datatype

Call: datatype(value)

     This function returns the type of a value. It is
     useful primarily with functions that take a
     variable number of arguments, but could also be
     useful for inspecting lists whose contents vary.

     This function returns a numeric value based on
     the datatype.

     1 - Number
     2 - Object
     3 - String
     5 - nil
     7 - List
     8 - true
     10 - Function Pointer
     13 - Property Pointer

------------------------------------------------------------
*>debugTrace

Call: debugTrace(1, flag)

     This form of debugTrace lets you turn a new
     player command parser diagnostic mode on and off.
     If flag is true, this function activates the
     diagnostic mode; if flag is nil, it turns the
     diagnostic mode off.

     When the diagnostic mode is active, the parser
     generates a series of progress messages as it
     analyzes the player's command. These messages
     provide information on how the parser interprets
     the words in the command. When first reading a
     sentence, the parser displays all possible parts
     of speech for each word. As the parser further
     analyzes the sentence, it displays information on
     each noun phrase: the words involved, the part of
     speech that the parser uses for each word in the
     noun phrase (when a word can be used as multiple
     parts of speech, the parser chooses one part of
     speech as it reads the noun phrase), and the
     objects that match the words in the noun phrase.

     The parser diagnostic mode may help you track
     down problems in which the parser refuses to
     recognize certain noun phrases that you would
     expect to be valid. Since the parser chooses
     among ambiguous interpretations of words, it's
     frequently helpful to understand exactly how the
     parser is interpreting your commands; this new
     debugging mode should make it easier to gain this
     understanding.

     This mode is available in the standard runtime as
     well as the debugger, so debugTrace(1, flag)
     always succeeds. The function returns no value.

------------------------------------------------------------
*>defined

Call: defined(object, propPointer, flag)

Added: Flag argument added with TADS 2.5.1.

     This function allows you to determine if a
     property is defined or inherited by an object, or
     if the object doesn't have any value for the
     property. This function returns true if the the
     object has a definition for the property (either
     explicitly in the object, or inherited from a
     superclass), or nil if the object doesn't have
     any definition for the property.

     Note that the propPointer argument must be a
     property pointer. You can obtain a property
     pointer using the & operator with a property
     name. For example, to determine if the player's
     current location has an ldesc property defined,
     you would do this:

       x := defined(Me.location, &ldesc);

     In this example, x is true if the current
     location has an ldesc property defined, and nil
     otherwise.

     The third argument is optional. If provided, it
     returns more specific information about the
     property definition, and it can be one of the
     following values, defined in adv.t:

  +-------------------+---------------------------------+
  | DEFINED_ANY       | This is the default, and has    |
  |                   | the same effect as omitting     |
  |                   | the flag argument. The          |
  |                   | function returns true if the    |
  |                   | object defines or inherits the  |
  |                   | property, nil if not.           |
  +-------------------+---------------------------------+
  | DEFINED_DIRECTLY  | The function returns true only  |
  |                   | if the object directly defines  |
  |                   | the property. If the object     |
  |                   | doesn't define the property at  |
  |                   | all, or merely inherits the     |
  |                   | definition from a superclass,   |
  |                   | the function returns nil.       |
  +-------------------+---------------------------------+
  | DEFINED_INHERITS  | The function returns true only  |
  |                   | if the object inherits the      |
  |                   | property. If the object         |
  |                   | doesn't define the property,    |
  |                   | or defines the property         |
  |                   | directly rather than            |
  |                   | inheriting it from a            |
  |                   | superclass, the function        |
  |                   | returns nil.                    |
  +-------------------+---------------------------------+
  | DEFINED_GET_CLASS | The function returns the class  |
  |                   | where the property is defined.  |
  |                   | If the object directly defines  |
  |                   | the property, the function      |
  |                   | returns the object itself. If   |
  |                   | the object inherits the         |
  |                   | property from a superclass,     |
  |                   | the function returns the        |
  |                   | superclass from which the       |
  |                   | property is inherited. If the   |
  |                   | object doesn't define or        |
  |                   | inherit the property, the       |
  |                   | function returns nil.           |
  +-------------------+---------------------------------+

     For example, to determine if the object redBook
     directly defines verDoTake, you could use this
     code:

       if (defined(redBook, &verDoTake, DEFINED_DIRECTLY))
         "verDoTake is overridden directly in redBook. ";

------------------------------------------------------------
*>delword

Call: delword(obj , &prop, word)

     Deletes the word (a single-quoted string value)
     from the object's vocabulary for the given part
     of speech. The prop parameter can be noun,
     adjective, plural, verb, article, or preposition.
     You can delete words from any object, including
     objects defined statically in your game, as well
     as objects created dynamically at run-time.
     Furthermore, you can delete words that were added
     dynamically, as well as words that were
     statically defined in your game.

     For examples of using this function, see the
     section on Dynamic Vocabulary.

------------------------------------------------------------
*>endCommand

Call: endCommand(actor, verb, dobj_list, prep, iobj,
status)

Added: TADS 2.5.0

     This function lets you write code that the parser
     calls at the end of a turn, just after running
     all of the fuses and daemons for the turn.

     The parser invokes the endCommand after all of
     the fuses and daemons have finished running at
     the end of a turn. The function is called once
     per command, not per object. In a command with
     multiple direct objects, this function is called
     only once, just as fuses and daemons are called
     only once for the entire command.

     The "status" parameter has the same meaning as
     the status code parameter to postAction. The
     other parameters have the same values as they did
     in the call to preCommand that the parser makes
     at the start of the execution phase for the
     command.

     endCommand is always invoked at the end of a
     turn. If an abort statement is executed in the
     course of a turn, the parser skips directly to
     endCommand, because abort skips the daemons and
     fuses. This means that endCommand is executed at
     the end of a turn even when fuses and daemons are
     skipped.

     The endCommand function returns no value.

------------------------------------------------------------
*>execCommand

Call: execCommand(actor, verb, dobj, prep, iobj, flags)

Added: TADS 2.4.0

     This function gives a game program direct access
     to the parser's command execution system. The
     function doesn't provide direct access to the
     string-parsing portion of the parser, but to the
     command execution portion, which takes the
     objects involved in the command and executes the
     command, performing object validation (validDo,
     validIo), room notification (roomAction), actor
     notification (actorAction), direct and indirect
     object checks (dobjCheck and iobjCheck), general
     object handling (dobjGen and iobjGen), object
     validation (verIoVerb and verDoVerb), and object
     action processing (ioVerb, doVerb, or
     verb.action, as appropriate).

     For full documentation on execCommand consult
     Chapter Five.

------------------------------------------------------------
*>exitobj

Call: exitobj()

Added: TADS 2.4.0

     This function provides a new method for skipping
     the remaining processing for a command at any
     point. It's very similar to the "exit" statement,
     but differs in one respect: whereas the "exit"
     statement terminates all further processing for a
     command and skips directly to the fuses and
     daemons, "exitobj" skips the remaining processing
     only for the current object in a command and
     proceeds to the next object.

     This difference is significant when the player
     types in a command involving multiple objects.
     For example, suppose that you define a roomAction
     method in the current room as follows:

       roomAction(actor, verb, dobj, prep, iobj) =
       {
         /*
          *  when the player touches anything not already in their inventory,
          *  make it vanish
          */
         if (dobj != nil && !dobj.isIn(actor))
         {
           "\^<<dobj.thedesc>> disappears in a flash of light!\n";
           dobj.moveInto(nil);
           exit;
         }
       }

     Now consider the following transcript:

       >take ball
       The ball disappears in a flash of light!

       >take hammer and chisel
       The hammer disappears in a flash of light!

     The first response makes sense, but the second
     isn't exactly what you wanted. The problem is
     that the "exit" statement tells the parser to
     skip processing of any objects other than the
     current one.

     To change this, you can simply change the "exit"
     statement in the code listing above to "exitobj".
     The result will be more sensible:

       >take hammer and chisel
       The hammer disappears in a flash of light!
       The chisel disappears in a flash of light!

     "exitobj" is useful when you want to skip the
     remaining processing for a command for the
     current object, but you still want the command to
     be considered successful. "exit" is more suited
     for situations where the outcome of the command
     is something less than total success, and you
     want to skip further processing of other objects
     involved in the command. "exitobj" is
     particularly useful with the execCommand()
     built-in function (see above), because it allows
     you to completely redirect the processing of a
     command, skipping all or part of the normal
     processing for the original command without
     telling the parser that the original command was
     unsuccessful.

     You an use exitobj anywhere you can use exit.

------------------------------------------------------------
*>fclose

Call: fclose(filehandle)

     Closes the file indicated by filehandle. Once the
     file is closed, no further operations on
     filehandle are valid. For more information see
     the section on file operations.

------------------------------------------------------------
*>find

Call: find(value, target)

     If value is a list; the function returns the
     offset (starting at 1 for the first element) in
     the list of the target item within the value
     list. If the target is not found, nil is
     returned. For example, find([4 5 6], 5) returns
     2.

     If value is a string, in which case target must
     also be a string, the function will return the
     offset within the string value of the substring
     target, or nil if the substring is not found. The
     offset of the first character in the target
     string is 1. For example, find('abcdefghij',
     'cde') returns 3.

------------------------------------------------------------
*>firstobj

Call: firstobj()

Alternative Call: firstobj(class)

     This function is used in conjunction with
     nextobj(object) to loop over all non-class
     objects in the game. The firstobj() function
     returns the first non-class object, and
     nextobj(object) is used to retrieve subsequent
     objects in a loop. The order of the objects
     returned by these functions is arbitrary, but
     calling firstobj() and then sequentially calling
     nextobj(object) until nil is returned will
     guarantee that each non-class object is retrieved
     exactly once.

     These functions are useful primarily during
     initialization to construct lists of all objects
     satisfying certain search criteria; these lists
     can be used later in the game to expedite
     searches for objects with such criteria. For
     example, code that determines if a room is dark
     will have to always check to see if a
     light-providing object, such as a lamp or a
     burning candle, is present. It will be faster
     during game play to check only those objects
     known to be light-providing than to check all
     objects in the game; to accomplish this, we could
     set a property called islamp to true in every
     potential light-providing object, then construct
     a list of all such objects during initialization
     with the example code below.

       getlamps: function
       {
         local obj, l;
         l := [];
         obj := firstobj();
         while(obj <> nil)
         {
           if (obj.islamp) l := l + obj;
           obj := nextobj(obj);
         }
         global.lamplist := l;
       }

     After initialization, then, it is only necessary
     to check for the presence of one of the objects
     in the list global.lamplist, rather than checking
     all objects in the game, to determine if a room
     is lit or not.

     Note that firstobj() will return nil if the game
     has no non-class objects. Likewise,
     nextobj(object) returns nil when the last
     non-class object has been retrieved.

     The alternative form of this function, with a
     single argument giving a class object, allows you
     to restrict the objects returned by firstobj()
     and nextobj() to those that are subclasses of a
     particular class. This can save a great deal of
     time by ignoring objects that are not important
     to your search. For the example above, you could
     make the loop execute much more quickly by
     rewriting it as follows.

       getlamps: function
       {
         local obj, l;
         l := [];
         obj := firstobj(lampitem);
         while(obj <> nil)
         {
           l := l + obj;
           obj := nextobj(obj, lampitem);
         }
         global.lamplist := l;
       }

     Note that the test for obj.islamp is no longer
     necessary, because only objects that are
     subclasses of the class lampitem will be used in
     the loop. By iterating over a much smaller set of
     objects, the loop will execute substantially
     faster.

------------------------------------------------------------
*>firstsc

Call: firstsc(obj)

     Returns the first superclass of the given object.
     Returns nil if the object has no superclass
     (which will only be the case if the object was
     defined as being of type object).

     This function is provided primarily to facilitate
     handling equivalent objects. In conjunction with
     the isEquivalent property, this function lets you
     determine if two objects are indistinguishable
     from one another. If two objects have the same
     immediate superclass, and they both have the
     isEquivalent property set to true, the two
     objects are equivalent.

------------------------------------------------------------
*>fopen

Call: fopen(filename, mode)

Added: Text mode compatibility added with TADS 2.2.4

     Opens the file, either text or binary, whose name
     is given by the single-quoted string value
     filename. Files written in text mode can be used
     by other applications (text editors, Web
     browsers, etc.) as ordinary text files, but
     binary mode files should only be used by TADS.
     The file is opened in a manner according to the
     mode argument, which is a single-quoted string
     value:

          `b' - open as a binary file. If you
          don't specify the file mode, binary is
          assumed as the default mode, for
          compatibility with past versions.

          `r' - open file for reading; file must
          already exist.

          `r+' - open file for reading and
          writing; the file is created if it
          doesn't already exist. Not currently
          allowed in text mode.

          `t' - open as a text file. You can use
          the text mode in conjunction with `r'
          (read) and `w' (write) modes - `t' is
          not currently allowed with `r+' or `w+'
          modes. Note that text file
          functionality was added with version
          2.2.4 of TADS.

          `w' - create a new file for writing;
          the file is deleted if it already
          exists.

          `w+' - create a new file for reading
          and writing; the file is deleted if it
          already exists. Not currently allowed
          in text mode.

     The function returns a file handle that is used
     in subsequent file operations (fwrite(), fread(),
     fclose(), and the like) to refer to the open
     file.

     If the operation fails, fopen() returns nil. This
     function can fail for a number of reasons; for
     example, if you attempt to open a file that
     doesn't exist with mode `r', the operation will
     fail because this mode can only be used to open
     an existing file.

     For more information on file operations, consult
     the section at the end of this chapter.

------------------------------------------------------------
*>fread

Call: fread(filehandle)

Added: Text mode compatibility added with TADS 2.2.4

     Reads the next data item from the text or binary
     file and returns its value. The value will be of
     the same type as that originally written at the
     current position in the file with fwrite(). If an
     error occurs, this function returns nil; this
     usually indicates that you are attempting to read
     past the end of the file.

     When operating in text mode (see fopen() ),
     fread() always reads a line of text from the
     file. If the end of the file is not reached, the
     line returned will end with a `\n' sequence (as
     with fwrite(), fread() translates newlines
     according to local conventions, and always
     returns the TADS `\n' sequence to represent a
     newline in the file). If fread() encounters the
     end of the file in the middle of a line, it will
     return the text up to the end of the file, with
     no trailing newline. The subsequent call will
     return nil to indicate that the end of the file
     has been reached.

------------------------------------------------------------
*>fseek

Call: fseek(filehandle, byteposition)

     Seeks to a byte position in the file. The
     byteposition value should be a value previously
     returned by ftell(), since other values may not
     correspond to a value in the file.

------------------------------------------------------------
*>fseekeof

Call: fseekeof(filehandle)

     Positions the file at its end.

------------------------------------------------------------
*>ftell

Call: ftell(filehandle)

     Returns the current seek position in the file,
     given as a number of bytes from the beginning of
     the file.

------------------------------------------------------------
*>fwrite

Call: fwrite(filehandle, value)

Added: Text file compatibility added with TADS 2.2.4

     Writes the given value to the text or binary
     file. The value argument must be a number, a
     single-quoted string, or true. Returns nil on
     success, true on failure; a true return value
     usually indicates that the disk is full.

     When a file is opened in text mode, (see
     fopen()), fwrite() can only be used with string
     values. Strings passed to fwrite() can contain
     the escape characters `\t', `\n', and `\\'; other
     escapes are not allowed. `\t' is translated to a
     tab, `\n' is translated to a newline (using the
     appropriate local conventions for the current
     system), and `\\' is translated to a single
     backslash. fwrite() does not add any newlines to
     the text you provide, so you must explicitly
     include any newlines you want to write to the
     file.

     Because TADS obeys local newline conventions,
     fwrite() always produces the correct sequence of
     characters for the current machine when you
     include `\n' in a string, so you don't have to
     worry about how newlines are handled on each
     platform.

     See the section on file handling at the end of
     this chapter for more information about security
     modes when writing files in TADS.

------------------------------------------------------------
*>getarg

Call: getarg(argnumber)

     This function returns the argument given by
     argnumber, which is a number from 1 to the number
     of arguments to the function (which can be
     learned with the pseudo-variable argcount).
     getarg(1) returns the first argument to the
     current function, getarg(2) returns the second
     argument, and so forth, up to getarg(argcount).
     This function can be used to retrieve the
     arguments to functions taking a variable number
     of arguments.

------------------------------------------------------------
*>getwords

     Call: getwords(obj, &prop)

     This function returns a list of single-quoted
     strings giving the vocabulary words defined for
     the given part of speech for the specified
     object. The prop parameter can be noun,
     adjective, plural, verb, article, or preposition.

     For examples of using this function, see the
     section on Dynamic Vocabulary at the end of this
     chapter.

------------------------------------------------------------
*>getfuse

Call: getfuse(funcptr, parm)

     This function lets you determine if the indicated
     fuse is still active, and if so, how many turns
     are left until it is activated. If the fuse is
     not active (either it has already fired, or it
     has been removed with a call to remfuse), this
     function returns nil. Otherwise, it returns the
     number of turns before the fuse is activated.

     Alternative Call: getfuse(obj, &msg)

     This form of getfuse lets you check on a fuse set
     with the notify function. If the fuse has already
     been fired, or has been removed with unnotify,
     this function returns nil. Otherwise, it returns
     the number of turns before the fuse is activated.

------------------------------------------------------------
*>gettime

Call: gettime(optional argument)

Added: Additional information support added with TADS 2.3.0

     Returns the current system clock time. The time
     is returned as a list of numeric values for easy
     processing.

  +---------+-------------------------------------------+
  | year    | calendar year (e.g., 1992).               |
  +---------+-------------------------------------------+
  | month   | month number (January = 1, February = 2,  |
  |         | etc.)                                     |
  +---------+-------------------------------------------+
  | day     | number of the day within the current      |
  |         | month                                     |
  +---------+-------------------------------------------+
  | weekday | day of the week (1 = Sunday, 2 = Monday,  |
  |         | etc.)                                     |
  +---------+-------------------------------------------+
  | yearday | day of the year (1 = Jan 1)               |
  +---------+-------------------------------------------+
  | hour    | hour of the day on 24-hour clock          |
  |         | (midnight = 0, noon = 12, 3 PM = 15,      |
  |         | etc.)                                     |
  +---------+-------------------------------------------+
  | minute  | minute within the hour (0 to 59)          |
  +---------+-------------------------------------------+
  | second  | second within the minute (0 to 59)        |
  +---------+-------------------------------------------+
  | elapsed | the number of seconds since January 1,    |
  |         | 1970, 00:00:00 GMT. This last value is    |
  |         | useful for computing the difference       |
  |         | between two points in time.               |
  +---------+-------------------------------------------+

     In addition, TADS 2.3 added the ability to return
     additional system real-time clock information.
     The function optionally takes an argument
     specifying what type of information to return.
     Constants for the argument values are defined in
     adv.t:

     GETTIME_DATE_AND_TIME - this returns the
     traditional date and time information that
     gettime() returned in the past. This is the same
     information that the function returns if called
     with no arguments (thus ensuring that existing
     code that calls gettime() will continue to work
     unchanged).

     GETTIME_TICKS - this returns the number of
     milliseconds since an arbitrary zero point, which
     is usually some system event, such as starting
     the current session of the TADS interpreter, or
     turning on the computer. The actual zero point is
     arbitrary, but it will remain fixed for a
     particular session, so you can use this form of
     gettime() to compute relative times between
     events over a short period of time. For example,
     if you're reading events with the new
     inputevent() function, you can use this time
     value to set a limit on how long you read events.
     For example:

       local max_time, cur_time, evt;

       /* process events for no more than 5 seconds (5000 milliseconds) */
       max_time := gettime(GETTIME_TICKS) + 5000;
       for (;;)
       {
         /* check to see if we've reached our time limit */
         cur_time := gettime(GETTIME_TICKS);
         if (cur_time >= max_time)
           break;

         /* get events, but time out if we exceed our time limit */
         evt := inputevent(max_time - cur_time);

         /* process the event */
         switch(evt[1])
         // and so on
       }

------------------------------------------------------------
*>incturn

Call: incturn()

     Increments the turn counter. Normally, a daemon
     is present to call this function once per player
     command. The turn counter is used to time the
     execution of fuses, so the user must call
     incturn() once per turn.

     This function is not called automatically by the
     system, since the turn counter should not be
     incremented after certain events. For example,
     most system commands, such as saving a game,
     should not count as a turn. This function is
     provided so that the game program can decide when
     to increment the counter.

Alternative Call: incturn(num)

     This form allows you to run a series of turns all
     at once. You can specify a numeric argument to
     incturn(); the argument gives the number of turns
     that should pass. An argument of 1 is equivalent
     to calling incturn() with no arguments.

     When an argument higher than 1 is specified, the
     function runs all of the fuses that are set to
     turn down within the number of turns specified,
     but not after that number of turns. Note that the
     normal incturn() doesn't actually execute any
     fuses, but simply burns all fuses down by one
     turn.

     For example, if you call incturn(2), the system
     will first run any fuses that are set to burn
     down after 1 turn, then will shorten all
     remaining fuses by one turn. Similarly,
     incturn(3) first runs any fuses that are set to
     burn down after 1 turn, then runs any fuses set
     to burn down after 2 turns, then shortens any
     remaining fuses by 2 turns.

     Fuses set with setfuse() and notify() are both
     affected by this routine. Note that this function
     has no effect on daemons.

------------------------------------------------------------
*>input

Call: input()

     This function stops and waits for the user to
     enter a line of text (terminated by the return
     key and edited as normal for command lines), and
     returns a string containing the text the user
     enters. This function does not display any
     prompt, so it is up to the game program to prompt
     the user before calling this function.

     As a stylistic point, this function should
     normally be avoided except for special system
     functions, since the game will present a more
     consistent interface if the command line is used
     for most player input. One possible use is given
     by the example below. (Note that this code is
     somewhat simplified; in an actual game, you would
     also want to call setscore() at the appropriate
     points, and provide other useful feedback.)

       die: function
       {
         "*** You have died ***
          \bDo you wish to RESTART, RESTORE, or QUIT? >";
         while (true)
         {
           local response;
           response := upper(input());
           if (response = 'RESTART') restart();
           else if (response = 'RESTORE')
           {
             response := askfile();
             if (restore(response)) "Failed. ";
             else abort;
           }
           else if (response = 'QUIT')
           {
             quit();
             abort;
           }
           else "Please enter RESTORE, RESTART, or QUIT: >";
         }
       }

------------------------------------------------------------
*>inputdialog

Call: inputdialog(icon, prompt, response_list, default_idx,
cancel_idx)

Added: TADS 2.5.0

     This function lets you ask the player a
     multiple-choice question. On graphical systems,
     inputdialog() displays a system dialogue box, and
     lets the user respond by clicking a button. On
     text systems, this function displays a textual
     prompt and lets the user respond with the
     keyboard.

     The "icon" parameter indicates which icon, if
     any, to display. The icon will only be displayed
     on graphical systems; text-only systems ignore
     this parameter. These icon constants are defined
     in adv.t:

  +---------------------+-------------------------------+
  | INDLG_ICON_NONE     | Do not use any icon.          |
  +---------------------+-------------------------------+
  | INDLG_ICON_WARNING  | Show a "warning" icon. This   |
  |                     | indicates a potential or      |
  |                     | minor problem. (On Windows,   |
  |                     | this displays an              |
  |                     | exclamation-point icon.)      |
  +---------------------+-------------------------------+
  | INDLG_ICON_INFO     | Show an "information" icon.   |
  |                     | This indicates to the user    |
  |                     | that the dialogue is being    |
  |                     | displayed to inform them of   |
  |                     | the status of an operation.   |
  |                     | (On Windows, this displays    |
  |                     | an icon with a small letter   |
  |                     | "i" in a circle.)             |
  +---------------------+-------------------------------+
  | INDLG_ICON_QUESTION | Show a "question" icon. This  |
  |                     | indicates that additional     |
  |                     | information from the user is  |
  |                     | required. (On Windows, this   |
  |                     | displays a question-mark      |
  |                     | icon.)                        |
  +---------------------+-------------------------------+
  | INDLG_ICON_ERROR    | Show an "error" icon. This    |
  |                     | indicates that a problem has  |
  |                     | occurred. (On Windows, this   |
  |                     | displays a stop-sign icon.)   |
  +---------------------+-------------------------------+

     The "prompt" parameter is the message string to
     display. For graphical systems, this message is
     displayed in a dialogue box; for text systems,
     it's simply displayed on the terminal.

     The "response_list" is a list of strings giving
     the valid responses. Each entry in the list is a
     string giving one possible response. On graphical
     systems, one button is displayed in the dialogue
     for each response string; the response string is
     the button's label. On text systems, the
     responses are displayed to the player after the
     prompt string.

     Each string in the response list can optionally
     include an ampersand character ("&") before the
     character that serves as a keyboard short-cut for
     the response. The ampersand is not displayed in
     the button label or response list displayed to
     the player. For example, the response list string
     `&Yes' makes the "Y" key a short-cut for the
     button, which is labeled "Yes" in the dialogue.
     On some systems the short-cut key will be
     indicated visually in the dialogue; on Windows,
     for example, the "Y" in the "Yes" button would be
     underlined to indicate that the letter "Y" is the
     short-cut for the button. If no ampersand appears
     in a response list item, the item has no
     short-cut.

     On text-only systems, the keyboard short-cut will
     be indicated visually by enclosing the short-cut
     letter in parentheses when displaying the list of
     possible responses to the player. If a response
     item has no short-cut key, the player must enter
     a sufficiently long leading substring of the
     response item so that the response is unambiguous
     with the other valid responses.

     Each element of the list can be a number, rather
     than a string. If an element is a number, it
     specifies that the button should use a
     pre-defined standard label. You should use
     standard labels when possible, because these
     labels will follow local system conventions and
     will be localized to the player's language
     settings; these labels are read from external
     resources on platforms with appropriate operating
     system support, so they can be localized easily.
     To select a standard label, use one of the
     following values, defined in adv.t:

  +------------------+----------------------------------+
  | INDLG_LBL_OK     | "OK", or local system or         |
  |                  | language equivalent              |
  +------------------+----------------------------------+
  | INDLG_LBL_CANCEL | "Cancel"                         |
  +------------------+----------------------------------+
  | INDLG_LBL_YES    | "Yes"                            |
  +------------------+----------------------------------+
  | INDLG_LBL_NO     | "No"                             |
  +------------------+----------------------------------+

     The strings shown above do not necessarily
     reflect the actual button text that the player
     will see, because the actual label will vary by
     platform and by language. Whatever label is
     displayed, though, will convey to the user the
     same meaning.

     You can also select an entire standard set of
     buttons, rather than specifying each button
     individually. If the response_list parameter is a
     number, rather than a list, it indicates that a
     standard set of buttons is to be used, selected
     from a pre-defined list. The advantage of using
     one of these pre-defined button sets when
     possible is that the buttons will automatically
     follow local system conventions and be localized
     to the player's language settings, on platforms
     with appropriate operating system support. To
     select a pre-defined button set, use one of the
     following values, defined in adv.t, for the
     response_list parameter:

  +-------------------+---------------------------------+
  | INDLG_OK          | The dialogue will display an    |
  |                   | "OK" button, properly           |
  |                   | localized.                      |
  +-------------------+---------------------------------+
  | INDLG_OKCANCEL    | The dialogue will display an    |
  |                   | "OK" button and a "Cancel"      |
  |                   | button, properly localized.     |
  +-------------------+---------------------------------+
  | INDLG_YESNO       | The dialogue will display an    |
  |                   | "Yes" button and a "No"         |
  |                   | button, properly localized.     |
  +-------------------+---------------------------------+
  | INDLG_YESNOCANCEL | The dialogue will display a     |
  |                   | "Yes" button, a "No" button,    |
  |                   | and a "Cancel" button,          |
  |                   | properly localized.             |
  +-------------------+---------------------------------+

     The "default_idx" parameter gives the index in
     the response list of the default response. If the
     user presses the "Return" key, or performs any
     other action appropriate to the system user
     interface that by local convention accepts the
     default response to a dialogue, this response
     will be used. The first list entry is at index 1.
     Pass nil in this parameter if there is no default
     response, in which case TADS will require the
     user to select a specific button. (Note that, on
     some systems, passing nil for this parameter will
     not make a noticeable difference; on Windows, for
     example, one of the buttons will always have
     keyboard focus, so pressing the Return key will
     always select one of the buttons.)

     The "cancel_idx" parameter gives the index in the
     response list of the cancellation response. Most
     GUI systems have a standard way of cancelling a
     dialogue; the Escape key has this effect on
     Windows, for example, as does the Command-Period
     key combination on the Macintosh. If the user
     performs the appropriate system-specific action
     to cancel the dialogue, this response is used.
     The first list entry is at index 1. Pass nil in
     this parameter if there is no cancel response, in
     which case TADS will not allow the player to
     cancel the dialogue.

     The dialogue returns the index of the response
     that the player selects: 1 for the first response
     in the response list, 2 for the second entry in
     the list, and so on. For the standard response
     lists (INDLG_YESNO and so on), the response are
     in the order described for the constant name:
     INDLG_YESNO has a "Yes" button at index 1 and a
     "No" button at index 2, for example.

     Here's an example of using this function.

       ret := inputdialog(INDLG_ICON_WARNING, 'What would you like to do next?',
                          ['&Restore', 'Re&start', '&Quit'],
                          nil, 3);
       switch(ret)
       {
         case 1:
           /* restore a game... */
           break;

         case 2:
           /* restart the game */
           restart();
           break;

         case 3:
           /* quit */
           quit();
           break;
       }

     On a graphical system, this would display a
     dialogue with the message text "What would you
     like to do next?", and three buttons: one with
     the label "Restore", one with the label
     "Restart", and one with the label "Quit". If the
     user presses the "R" key, the "Restore" button
     would be selected; if the user presses "S", the
     "Restart" button would be selected; if the user
     presses "Q", or cancels the dialogue (by pressing
     the Escape key on a Windows machine, for
     example), the "Quit" button would be selected.

     On a text-only system, TADS would display this
     text on the terminal, on a new line (TADS would
     output a "\n" sequence to start a new line):

       What would you like to do next? (R)estore/Re(s)tart/(Q)uit >

     TADS would then wait for the player to enter a
     line of text (as with the input() built-in
     function). If the player enters one letter, TADS
     would check the letter against each response's
     short-cut, and return the one that matches. If
     the player enters more than one letter, TADS
     would check the string against the leading
     substring of each possible response; if the
     string matches one of the responses
     unambiguously, TADS would return that response.
     If the player enters something invalid or
     ambiguous, TADS would redisplay the prompt and
     await another response.

     inputdialog() has certain limits. The prompt
     string can be no longer than 256 characters.
     There can be no more than ten responses, and the
     total length of the text in all of the responses
     must not exceed 256 characters. In addition, to
     ensure portability, you should choose a
     reasonably short label for each button; some
     systems use buttons of a fixed size, so a long
     label name might not fit in the available space
     on some systems. Whenever possible, use a single
     word for each button label.

------------------------------------------------------------
*>inputevent

Call: inputevent(timeout)

Alternative call: inputevent()

Added: TADS 2.3.0

     This function multiple types of events and can
     also apply a timeout to limit the how long it
     waits for an event to occur.

     The inputevent() function takes zero or one
     arguments. With no arguments, inputevent() simply
     waits until an event occurs. With one argument,
     which must be a number, inputevent() waits until
     an event occurs, or until the number of
     milliseconds specified by the argument has
     elapsed without an event occurring, in which case
     the function "times out" and returns without any
     event having occurred.

     Note that the timeout value, if given, may not
     always be obeyed to the exact millisecond.
     Different types of computers have different
     system clock resolutions, and additionally
     multi-user and multi-tasking systems often have
     unpredictable latencies for event processing. As
     a result, if you specify a timeout value, the
     actual time that elapses before the function
     times out and returns may be slightly longer than
     the specified timeout value. Any additional
     latency should be no more than a few hundred
     milliseconds in most cases, so this shouldn't be
     noticeable for most purposes.

     The function returns a list value describing the
     event that occurred. The first element of the
     list is a number that specifies the type of the
     event. The rest of the list varies according to
     the event type. Constants for the event codes are
     defined in adv.t. The possible event codes are:

  +-----------------------+-----------------------------+
  | INPUT_EVENT_KEY       | The user pressed a key.     |
  |                       | The second element of the   |
  |                       | list returned by            |
  |                       | inputevent() in this case   |
  |                       | is a string containing the  |
  |                       | key that the user pressed.  |
  |                       | The string is the same      |
  |                       | that would be returned by   |
  |                       | inputkey() for the same     |
  |                       | keystroke.                  |
  +-----------------------+-----------------------------+
  | INPUT_EVENT_HREF      | The user clicked on an      |
  |                       | link. This event is only    |
  |                       | returned by an HTML TADS    |
  |                       | interpreter, never by a     |
  |                       | character-mode TADS         |
  |                       | interpreter. The second     |
  |                       | element of the return list  |
  |                       | is a string containing the  |
  |                       | text of the HREF that the   |
  |                       | user clicked.               |
  +-----------------------+-----------------------------+
  | INPUT_EVENT_TIMEOUT   | No event occurred before    |
  |                       | the specified timeout       |
  |                       | elapsed. The return list    |
  |                       | contains no additional      |
  |                       | elements.                   |
  +-----------------------+-----------------------------+
  | INPUT_EVENT_EOF       | This indicates that the     |
  |                       | TADS interpreter is         |
  |                       | terminating or an error     |
  |                       | occurred reading an event.  |
  +-----------------------+-----------------------------+
  | INPUT_EVENT_NOTIMEOUT | This is not actually an     |
  |                       | event, but an error         |
  |                       | indicating that the         |
  |                       | current system does not     |
  |                       | support the timeout         |
  |                       | feature of inputevent().    |
  |                       | If this occurs, you can     |
  |                       | still use inputevent(),     |
  |                       | but you cannot specify a    |
  |                       | timeout. The DOS TADS       |
  |                       | interpreters (TR, TRX,      |
  |                       | TR32) all support           |
  |                       | timeouts, as does HTML      |
  |                       | TADS for Windows.           |
  |                       | Interpreters on most        |
  |                       | systems should be able to   |
  |                       | support this feature, but   |
  |                       | a few systems may not be    |
  |                       | able to.                    |
  +-----------------------+-----------------------------+

------------------------------------------------------------
*>inputkey

Call: inputkey()

Added: Extended keys added with TADS 2.3.0, others added
2.5.0

     Reads a single keystroke from the keyboard, and
     returns a string consisting of the character
     read. inputkey() takes no arguments. When called,
     the function first flushes any pending output
     text, then pauses the game until the player hits
     a key. Once a key is hit, a string containing the
     character is returned. inputkey() takes its input
     directly from the keyboard. It does not look at
     the command line

     In addition, the function returns a portable
     representation for certain extended keys. Before
     TADS 2.3, keys outside of the normal ASCII
     character set were almost impossible to use with
     inputkey(), because TADS returned a useless "raw"
     format for extended keys, such as cursor
     navigation keys and function keys. TADS now uses
     a portable string format to represent many common
     keys.

     Each extended key is represented as a string
     containing a key name enclosed in square
     brackets. The key name are:

  +--------------+--------------------------------------+
  | [up]         | Up arrow                             |
  +--------------+--------------------------------------+
  | [down]       | Down arrow                           |
  +--------------+--------------------------------------+
  | [right]      | Right arrow                          |
  +--------------+--------------------------------------+
  | [left]       | Left arrow                           |
  +--------------+--------------------------------------+
  | [end]        | End of line                          |
  +--------------+--------------------------------------+
  | [home]       | Home                                 |
  +--------------+--------------------------------------+
  | [del-eol]    | Delete to end of line                |
  +--------------+--------------------------------------+
  | [del-line]   | Delete line                          |
  +--------------+--------------------------------------+
  | [del]        | Del (delete character)               |
  +--------------+--------------------------------------+
  | [page up]    | Page up                              |
  +--------------+--------------------------------------+
  | [page down]  | Page down                            |
  +--------------+--------------------------------------+
  | [top]        | Top of file                          |
  +--------------+--------------------------------------+
  | [bottom]     | Bottom of file                       |
  +--------------+--------------------------------------+
  | [fN]         | Function key N (N is replaced by a   |
  |              | number, 1 through 10)                |
  +--------------+--------------------------------------+
  | [tab]        | Tab                                  |
  +--------------+--------------------------------------+
  | [word-left]  | Word left                            |
  +--------------+--------------------------------------+
  | [word-right] | Word right                           |
  +--------------+--------------------------------------+
  | [del-word]   | Delete word                          |
  +--------------+--------------------------------------+
  | [bksp]       | Backspace                            |
  +--------------+--------------------------------------+
  | [esc]        | Escape                               |
  +--------------+--------------------------------------+
  | [ctrl-X]     | Control-X (X is replaced by a        |
  |              | lower-case letter: Control-C is      |
  |              | [ctrl-c])                            |
  +--------------+--------------------------------------+
  | [alt-X]      | Alt-X or Meta-X (X is replaced by a  |
  |              | lower-case letter: Alt-F is [alt-f]) |
  +--------------+--------------------------------------+

     In addition, "control" keys (i.e., keys entered
     by holding down the "control" or "ctrl" key on
     the keyboard and pressing an alphabetic key) are
     returned as "[ctrl-X]", where "X" is the
     lower-case letter key; and "alt" keys are
     returned as "[alt-X]". Finally, the "Return" and
     "Enter" keys are returned as "\n", and the tab
     key is returned as "\t".

     Even though these key names are portable, be
     aware that not every computer has all of these
     keys, so you can't count on the player actually
     being able to enter them. The only keys that you
     can always count on being present are the regular
     ASCII keys, Enter/Return, Tab, and Backspace. So,
     if you're using these extended keys, you should
     always be sure to provide an alternative for each
     extended key using an ordinary key. For example,
     if you want to implement a menu system that uses
     the up and down arrow keys to navigate through a
     set of choices, you could use "N" (for "next")
     and "P" (for "previous") as synonyms for [down]
     and [up], respectively.

     The arrow keys ([up], [down], [left], and
     [right]) are probably the most portable of the
     extended keys, since most computers and terminals
     have some sort of arrow keys. The function keys
     ([f1] through [f10]) are also available on many
     systems, although some systems use some or all of
     the function keys for special purposes; for
     example, Windows uses the F10 key to begin
     navigating the menu bar, so your game will never
     receive the [f10] extended key when running on
     Windows. The ALT and CONTROL keys are also very
     non-portable.

     Here's an example of using the arrow keys.

       numberVerb: deepverb
         verb = 'number'
         action(actor) =
         {
           local num;
           local done;
           local changed;

           "Press the Up or Down arrow keys, or the + or - keys,
            to change the number.  Press Enter when finished.\b";

           num := 5;
           changed := true;
           for (done = nil ; !done ; )
           {
             if (changed)
             {
               "\nCurrent value = <<num>>";
               changed := nil;
             }

             switch(inputkey())
             {
               case '\n':
                 done := true;
                 break;

               case '+':
               case '[up]':
                 ++num;
                 changed := true;
                 break;

               case '-':
               case '[down]':
                 --num;
                 changed := true;
                 break;
             }
           }

           "\bThe final value was <<num>>. ";
         }
       ;

------------------------------------------------------------
*>intersect

Call: intersect( list1, list2 )

     Returns the intersection of two lists - that is,
     the list of items in both of the two lists
     provided as arguments. For example:

       intersect( [ 1 2 3 4 5 6 ], [ 2 4 6 8 10 ] )

     yields the list [ 2 4 6 ]

     Note that the behavior for lists with repeated
     items is not fully defined with respect to the
     number of each repeated item that will appear in
     the result list. In the current implementation,
     the number of repeated items that is present in
     the shorter of the two source lists will be the
     number that appears in the result list; however,
     this behavior may change in the future, so you
     should try not to depend on it.

------------------------------------------------------------
*>isclass

Call: isclass(object, class)

     This function determines if an object is a
     subclass of a given class. It returns true if
     object is a subclass of class, nil otherwise.
     Note that the function scans the entire class
     tree, so class need not be in the immediate
     superclass list for object, but can be a
     superclass of a superclass of object, or a
     superclass of a superclass of a superclass, and
     so on.

     This function should be used to determine if an
     object is a member of a class, rather than using
     a special property value that the object inherits
     from the class. Using isclass is more efficient
     than using a special inherited property value,
     because the property value doesn't need to be
     stored, and because it is much faster to scan the
     inheritance tree than to check each object in the
     tree for the property value.

------------------------------------------------------------
*>length

Call: length(item)

     If the item is a string, length() returns the
     number of characters in the string. If item is a
     list, length() returns the number of elements in
     the list.

------------------------------------------------------------
*>logging

Call: logging(value)

     If the value is a string, it specifies the name
     of an operating system file which will be created
     (or truncated to zero length if it already
     exists) and to which subsequent information
     displayed on the screen is duplicated. That is, a
     complete log of the play will be copied to the
     file for later inspection.

     If the value is nil, it indicates that a log
     file, if in effect, should be closed and logging
     halted.

     Logging is automatically terminated when the
     player quits the game, but other operations
     (including saving, restoring, and restarting a
     game) do not affect logging.

     This function has no return value.

------------------------------------------------------------
*>lower

Call: lower(string)

     This function returns a copy of string with all
     of the upper-case letters converted to
     lower-case. See also the upper(string) function.

------------------------------------------------------------
*>morePrompt

Call: morePrompt()

Added: TADS 2.2.4

     This function allows your game to explicitly
     display the system MORE prompt. You can use this
     for such special effects as a dramatic pause
     prior to a chapter change. The function takes no
     arguments and returns no value.

------------------------------------------------------------
*>nextobj

Call: nextobj(object)

Alternative Call: nextobj(object, class)

     This function is used to retrieve the next object
     in a search started with firstobj(). The object
     is the value returned by the call to firstobj()
     or by the previous nextobj(object) call. The next
     non-class object after object is returned, and
     nil is returned if object was the last non-class
     object.

     The alternative form, with a second argument
     giving a class object, returns the next object
     that is a subclass of the given class. This can
     be used to restrict the search to a particular
     class of objects.

     For an example of the use of this function, see
     the description of the firstobj() built-in
     function.

------------------------------------------------------------
*>nocaps

Call: nocaps()

     This function is the opposite of caps() - it
     specifies that the next character displayed will
     be converted to lower case. Note that you can use
     the escape sequence "\v" to achieve the same
     effect.

     Note that calls to caps() and nocaps() override
     one another; if you call caps(), and then
     immediately call nocaps(), the next character
     displayed will be lower-case - the call to caps()
     is forgotten after the call to nocaps().

------------------------------------------------------------
*>notify

Call: notify(object, &message, turns)

     This function sets up to send the message to the
     object after the given number of turns has
     elapsed, or, if turns is zero, after each turn.
     Note the & before the message parameter; this is
     required to indicate that the message is to be
     stored rather than being sent immediately.

     The message is simply the name of a method
     defined by the object. The method receives no
     parameters when it is called.

     There is a limit of 200 simultaneously pending
     notifications.

     With a non-zero number of turns, the notify()
     function is similar to the setfuse() function, in
     that it waits a given number of turns and then
     sends the specified message to the given object.
     With turns set to zero, notify is similar to
     setdaemon(), in that the message is sent to the
     object after each turn. Note that the notify()
     function is generally the better function to use,
     since most fuses and daemons are directed at
     objects, and it is better to keep all code that
     affects the object in the object's definition,
     rather than move some into a separate function.

     See also the unnotify() function, which cancels
     the effect of the notify() function.

     An example of the notify() function is shown
     below. In the example, we define two objects: a
     bomb, and a button on the bomb. When the button
     is pushed, it calls notify() to specify that the
     explode method in the object bomb is to be called
     in three turns. Notice that we call the bomb's
     `explode' method with an ampersand. That means
     we're simply taking its address - we aren't
     evaluating it at this point. It will actually be
     evaluated when the notifier is called, in three
     turns.

       bomb: item
         location = bombroom
         sdesc = "bomb"
         noun = 'bomb'
         ldesc =
         {
           "The bomb seems to have a small button marked
            \"detonator\" on it. ";
           if (self.isActive) "It's ticking loudly. ";
         }
         explode =
         {
           "The bomb explodes! ";
           self.moveInto(nil);
         }
       ;

       bombButton: buttonItem
         location = bomb
         sdesc = "detonator button"
         adjective = 'detonator'
         doPush(actor) =
         {
           "The bomb starts ticking. ";
           notify(bomb, &explode, 3);  // Bomb explodes in three turns
           bomb.isActive := true;
         }
       ;

------------------------------------------------------------
*>objwords

Call: objwords( num )

     Provides a list of the actual words the user
     typed to refer to an object used in the current
     command. The argument num specifies which object
     you're interested in: 1 for the direct object, or
     2 for the indirect object. The return value is a
     list of strings; the strings are the words used
     in the command (converted to lower case, stripped
     of any spaces or punctuation). If a special word
     such as "it," "them," or "all" was used to
     specify the object, the list will have a single
     element, which is the special word used.

     For example, if the player types "take all," then
     objwords(1) will return [ 'all' ] and [ objwords2
     ] will return []. Note that objwords(1) will
     return [ 'all' ] even if the player typed a
     variation on "all," such as "take everything" or
     "take all but the book."

     If the player types "put all in red box," the
     objwords(1) returns [ 'all' ] and objwords(2)
     returns [ 'red' 'box' ].

     If the player uses multiple direct objects, the
     function will return the current object's words
     only. For example, if the player types "put blue
     folder and green book in red box," objwords( 1 )
     will return [ 'blue' 'folder' ] while the first
     direct object is being processed, and [ 'green'
     'book' ] while the second object is being
     processed.

     This function could potentially be useful in such
     cases as "ask actor about object," because it
     allows you to determine much more precisely what
     the player is asking about than would otherwise
     be possible.

     You can call objwords() during a verb
     verification or action method (verDoVerb,
     verIoVerb, doVerb, ioVerb), and during a
     doDefault method. Note that the return value is
     slightly different during a doDefault method: if
     the word"all" is used in the command, the
     function will return the list [ 'A' ] rather than
     [ 'all' ], due to the internal order of
     processing of the word list.

     objwords( 1 ) words with doDefault

     You can also call objwords( 1 ) from within the
     doDefault method, as described above. Until
     version 2.2, you could call objwords( 1 ) only
     from verb verification and action methods.

------------------------------------------------------------
*>outcapture

Call: outcapture( stat )

     TADS lets you capture the text displays that are
     generated by double-quoted strings and by the
     say() built-in function. This feature allows you
     to examine the values of methods such as ldesc
     and sdesc. Since these methods display text,
     there is no direct way of manipulating their text
     as strings. The output capture feature makes it
     possible for you to examine and manipulate any
     text that ordinarily would simply be displayed.

     To use this feature, you first tell TADS that you
     wish to begin capturing output by calling the
     built-in outcapture function:

       stat := outcapture( true );

     This begins capturing output. The return value is
     a status code that you use in a subsequent call
     to turn off output capturing. This status code
     allows output capturing calls to be "nested,"
     since the status code allows the capturing status
     that was in effect on a call to begin capturing
     to be restored on the subsequent call to end
     capturing. This status code is for use by TADS
     only - the only thing you do with it is use it in
     the subsequent call to end capturing.

     While output is being captured, any text that
     would normally be displayed is instead saved by
     the system. The user does not see any text
     displayed while capturing is in effect. After you
     begin capturing, simply call any methods whose
     displays you want to examine. For example, you
     could call redbook.sdesc if you want to examine
     the short description of the object redbook.

     After you've finished calling the methods whose
     displays you want to examine, end capturing by
     calling outcapture() again, passing as the
     argument the status code returned by the first
     call:

       str := outcapture( stat );

     This second call tells TADS to stop capturing
     output. The return value of this function is a
     (single-quoted) string containing all of the text
     that was displayed since the corresponding call
     to outcapture(true).

     When text is being captured, TADS expands all
     format strings (strings such as "%you%"), and
     processes "\^" and "\v" sequences (which convert
     the next character to upper- and lower-case,
     respectively). However, all other escape
     sequences (such as "\n" and "\t") are left in the
     string intact.

     You can display the string returned from the call
     to outcapture(stat) using the say() built-in
     function. This should result in the same text
     display that would have occurred if you hadn't
     turned on capturing.

     You can nest calls to outcapture(). As explained
     above, the status code returned from the first
     call is used to restore the capturing status of
     the previous call. The string returned by a call
     to turn off capturing includes only text that was
     generated after the corresponding call to turn on
     capturing. Because calls to outcapture() can be
     nested, you don't have to worry when using text
     capturing about whether any methods you're
     calling also use the function.

     Note that the system automatically turns off
     output capturing whenever it prompts the user for
     a command, for a missing direct or indirect
     object, or for disambiguation information. When
     the system turns off capturing, it clears the
     captured text, so any subsequent calls to turn
     off capturing return empty strings. You therefore
     can only capture text within a single command
     line.

------------------------------------------------------------
*>outhide

Call: outhide( flag )

     Turns hidden output on or off, simulating the way
     the parser disambiguates objects. The parameter
     flag is either true or nil. When you call
     outhide(true), the system starts hiding output.
     Subsequent output is suppressed - it is not seen
     by the player. When you call outhide(nil), the
     system stops hiding output - subsequent output is
     once again displayed. outhide(nil) also returns a
     value indicating whether any (suppressed) output
     was generated since the call to outhide(true),
     which allows you to determine whether any output
     would have resulted from the calls made between
     outhide(true) and outhide(nil).

     This is the same mechanism used by the parser
     during disambiguation, so it should not be called
     by a verDoVerb or verIoVerb method. This function
     is provided to allow you to make calls to
     verDoVerb and verIoVerb to determine if they will
     allow a particular verb with an object, just as
     the parser does.

     There is no way to recover the text generated
     while output is being hidden. The only
     information available is whether any text was
     generated.

Alternative Call: outhide(flag) - nested calls

     When you call outhide(true), the function returns
     a status indicator, which is a value that can be
     used in a subsequent call to outhide() to restore
     output hiding to the state it was in before the
     outhide(true). This allows you to nest text
     hiding - you can hide output in a subroutine or
     method call, without interfering with the routine
     that called you or any routines you call.

     To use the nested form, save the return value of
     outhide(true), and then use the saved value as
     the parameter - in place of nil - to the
     subsequent call to outhide(). The value returned
     by the second outhide() indicates whether any
     text output occurred between the nested calls.
     For example:

       local old_stat1, old_stat2;
       local new_stat1, new_stat2;
       old_stat1 := outhide(true);
       "This is some hidden test.";
       old_stat2 := outhide(true);
       // don't write any text here
       new_stat2 := outhide(old_stat2);
       new_stat1 := outhide(old_stat1);

     Because outhide(old_stat2) indicates whether any
     output occurred during the nested outhide(true),
     new_stat2 is nil. However, new_stat1 is true,
     since output occurred after the first
     outhide(true). Consider another sequence:

       old_stat1 := outhide(true);
       // write no text here
       old_stat2 := outhide(true);
       "This is some hidden text.";
       new_stat2 := outhide(old_stat2);
       new_stat1 := outhide(old_stat1);

     In this case, both new_stat1 and new_stat2 will
     be true, because hidden output occurred within
     both nested sections (even though only a single
     message was displayed, it was within both nested
     sections).

     The general form of a nested outhide() section
     is:

     {
       local old_stat;
       local new_stat;

       old_stat := outhide(true);
       // do whatever you want here
       // output will be hidden
       new_stat := outhide(old_stat);
     }

     The new_stat will indicate whether any output
     occurred between the outhide(true) and the
     outhide(old_stat). In addition, output hiding
     will be restored to the same state as it was
     prior to the outhide(true).

------------------------------------------------------------
*>parseAskobjIndirect

Call: parseAskobjIndirect(actor, verb, prep, noun_info)

Added: TADS 2.5.1

     This function provides more control over the
     message that the parser uses to ask the player to
     supply an indirect object when none is provided
     in the command but the verb requires one. It
     supplements the existing parseAskobj() and
     parseAskobjActor() functions, and is fully
     documented in Chapter Six.

------------------------------------------------------------
*>parseNounList

Call: parseNounList(wordlist, typelist, startingIndex,
complainOnNoMatch, multi, checkActor)

Added: TADS 2.4.0

     This function allows the game to invoke the
     parser's internal function to parse a noun list.
     This can be used in conjunction with the
     parseUnknownVerb to allow the function to
     interpret part of the word list as a noun list.
     The function is documented in Chapter Five.

------------------------------------------------------------
*>parseNounPhrase

Call: parseNounPhrase(wordlist, typelist, current_index,
complain_on_no_match, is_actor_check)

Added: TADS 2.4.0

     This parser hook lets the game program parse noun
     phrases and perform the initial resolution to
     possible matching objects. For more information
     on this function consult the parseNounPhrase
     section in Chapter Six.

------------------------------------------------------------
*>parserDictLookup

Call: parserDictLookup(tokenList, typeList)

Added: TADS 2.4.0

     This function lets you perform a parser
     dictionary look-up to obtain the list of objects
     that define a set of vocabulary words. This
     function can be used to perform your own
     noun-phrase parsing, and is documented fully in
     Chapter Five.

------------------------------------------------------------
*>parserGetMe

Call: parserGetMe( )

Added: TADS 2.2.4

     The parser provides a way to change the player
     character dynamically during game play. The
     parser in earlier versions of TADS used the
     object named "Me" to represent the player
     character; there was no way to change this. This
     made it difficult to write a game with different
     personas for the player character.

     TADS now lets you specify other player
     characters, and you can use the built-in function
     parserGetMe() to get the parser's current player
     character object. This function takes no
     arguments.

     Note that adv.t and std.t no longer refer to the
     "Me" object directly in code related to the
     player character's status (such as inventory or
     room location descriptions). Instead, adv.t and
     std.t use the new parserGetMe() function to get
     the player character object.

     If you use parserSetMe() (see below) in your
     game, you should be careful not to refer to the
     "Me" object directly in contexts where you really
     want the current player character object. Use
     parserGetMe() instead to get the correct object
     from the parser. Note that existing games should
     not be affected by this change; if you don't call
     parserSetMe(), then parserGetMe() will always
     return the "Me" object, so you can safely use a
     fixed "Me" object.

------------------------------------------------------------
*>parserGetObj

Call: parserGetObj(argument)

Added: TADS 2.4.0

     This function lets the game program learn the
     objects involved in the current command. The
     function takes a single argument, which indicates
     which object you want, using the following
     constants (defined in adv.t):

       PO_ACTOR - the current command's actor
       PO_VERB - the deepverb object for the
                 command's verb
       PO_DOBJ - the direct object
       PO_PREP - the preposition object
                 introducing the indirect object
       PO_IOBJ - the indirect object

     The return value is an object, or nil if there is
     no such object for the current command. For
     example, a command with no indirect object will
     return nil for PO_PREP and PO_IOBJ.

     Other aspects of this function are documented in
     detail in Chapter 6.

------------------------------------------------------------
*>parserGetTokTypes

Call: parserGetTokTypes(tokenList)

Added: TADS 2.4.0

     This function lets you obtain a list of token
     types given a list of tokens. You can use this
     function to get the types of the tokens in a list
     returned by parserTokenize(), for example. It's
     documented fully in Chapter Five.

------------------------------------------------------------
*>parserSetMe

Call: parserSetMe(newMe)

Added: TADS 2.2.4

     As noted above, you can switch the player
     character when you desire. The parser still uses
     "Me" as the initial player character, but you can
     change to a different object at any time using
     the new built-in function parserSetMe(newMe). The
     argument to parserSetMe() is the new object to
     use to represent the player character.

------------------------------------------------------------
*>parserResolveObjects

Call: parserResolveObjects(actor, verb, prep, otherobj,
usageType, verprop, tokenList, objList, silent)

Added: TADS 2.4.0

     This function lets you access the parser's object
     resolution and disambiguation subsystem
     programmatically. You can use the object resolver
     in conjunction with parseNounList() or with your
     own noun-list parser to implement your own
     command parsing system. It's documented in
     Chapter Five.

------------------------------------------------------------
*>parserTokenize

Call: parserTokenize(commandString)

Added: TADS 2.4.0

     This function lets the game invoke the parser's
     tokenizer to obtain a token list for a string of
     text. The function is documented extensively in
     Chapter Five.

------------------------------------------------------------
*>parseUnknownVerb

Call: parseUnknownVerb(actor, wordlist, typelist, errnum)

Added: TADS 2.4.0

     This parser hook lets the game take control
     whenever the parser encounters an unknown verb,
     or unknown sentence syntax. `actor' is the
     current actor object. The `wordlist' parameter is
     a list with the strings of the words in the
     command, in the same format as the list that is
     passed to preparseCmd. The `errnum' parameter is
     the parser error number for the condition that
     caused the call to parseUnknownVerb; this is the
     same error number that is passed to parseError
     (and related functions).

     The `typelist' argument is a list of the types of
     the words in the `wordlist' parameter. Each
     element of `typelist' gives the word type of the
     corresponding element of `wordlist' (so
     typelist[3] gives the type of the word in
     wordlist[3], for example). Each type is a number,
     which can contain any number of the values below
     combined with the bitwise OR operator ("|"). To
     test for a particular type, use an expression
     like this: ((typelist[3] & PRSTYP_NOUN) != 0).

     For more information consult the parseUnknownVerb
     section in Chapter Six.

------------------------------------------------------------
*>postAction

Call: postAction(actor, verb, dobj, prep, iobj, status)

Added: TADS 2.5.0

     This function lets you write code that the parser
     calls immediately after the "action" method, and
     before any fuses or daemons.

     The parser calls postAction once for each object
     in a command with multiple direct objects, just
     after it calls the "action" method for the
     object. If the command is terminated early with
     exit, exitobj, or abort, the parser invoked
     postAction immediately after the exit, exitobj,
     or abort statement executes.

     The first five parameters specify the current
     command; any of the objects except "actor" and
     "verb" can be nil. The "status" parameter has the
     same meaning as the return codes from the
     execCommand built-in function; it can be one of
     the following values, defined in adv.t:

  +------------+----------------------------------------+
  | EC_SUCCESS | The command executed successfully,     |
  |            | which indicates that everything up     |
  |            | through and including the command's    |
  |            | "action" method (verb.action,          |
  |            | dobj.doAction, or iobj.ioAction, as    |
  |            | appropriate).                          |
  +------------+----------------------------------------+
  | EC_EXIT    | An exit statement was executed.        |
  +------------+----------------------------------------+
  | EC_EXITOBJ | An exitobj statement was executed.     |
  +------------+----------------------------------------+
  | EC_ABORT   | An exit statement was executed.        |
  +------------+----------------------------------------+

     The postAction function returns no value.

------------------------------------------------------------
*>preCommand

Call: preCommand(actor, verb, dobj_list, prep, iobj)

Added: TADS 2.5.0

     At the start of the execution phase, before
     calling verbAction() for the first direct object
     in the command, the parser invokes this function.

     The "actor", "verb", "prep", and "iobj"
     parameters are objects giving the actor, verb,
     preposition, and indirect object in the command,
     respectively. The "dobj_list" parameter is a list
     of the direct objects in the command, in the same
     order as they appear in the command.

     This function can use exit to skip to fuses and
     daemons, or it can use abort to cancel the
     command entirely, in which case the parser will
     skip directly to the endCommand function (see
     below). If this function simply returns, the
     parser continues processing the command as
     normal.

------------------------------------------------------------
*>proptype

Call: proptype(object, propPointer)

     This function determines the datatype of a
     property of an object, without actually
     evaluating the property. This can be useful if
     you want to find out what kind of value the
     property has, without activating any side effects
     of evaluating the property (for example,
     displaying a double-quoted string contained by
     the property).

     The return value is a number, and the possible
     values are a superset of those returned by the
     datatype() built-in function.

       1 - Number
       2 - Object
       3 - String
       5 - nil
       6 - Code (executable statements
           enclosed in braces)
       7 - List
       8 - true
       9 - Double-quoted string
       10 - Function Pointer
       13 - Property Pointer

     Note that the propPointer argument must be a
     property pointer. You can get a property pointer
     by using the & operator on a property name. For
     example, to determine the type of the north
     property of the player's current location, you
     would do this:

       x := proptype(Me.location, &north);

     Note that using proptype() is very different from
     using the datatype() built-in function on the
     value of the property, because proptype() does
     not evaluate the property in order to determine
     its type. This has several implications. First,
     and most importantly, it allows you to avoid side
     effects of evaluating the property (such as
     displaying a double-quoted string value) if you
     don't desire the side effects. Second, it means
     that you will find out if a property contains
     code, but you will not learn what type of value
     (if any) the code will return.

------------------------------------------------------------
*>quit

Call: quit()

     Terminates the game. Actually, this function
     flags that the game is to be ended the next time
     a command will be parsed, so normal return codes
     should be passed back when using quit(). Hence,
     after calling quit(), you should always
     immediately execute an abort statement. See the
     example given in the description of the input()
     built-in function for an illustration of the use
     of quit().

------------------------------------------------------------
*>rand

Call: rand(upper-limit)

     This function returns a random number from 1 to
     the upper-limit given. (The upper-limit must be a
     positive number.) See also the discussion of
     randomize(), below.

------------------------------------------------------------
*>randomize

Call: randomize()

     This function "seeds" the random number generator
     with a new value. The value is
     implementation-defined, and comes from such a
     source as the system clock. Until randomize() is
     called, the random number generator will always
     produce a fixed sequence of random numbers; once
     randomized, however, the sequence is
     unpredictable. For testing purposes, you can
     leave the call to randomize() out of your
     program, because the game will always run
     repeatably. Once the game is working, you can
     simply put a call to randomize() in your init()
     function in order to make the game unpredictable
     for your players.

------------------------------------------------------------
*>reGetGroup

Call: reGetGroup()

Added: TADS 2.3.0

     Note: this function is dependent upon the
     reSearch() function. Please read the
     documentation on that first.

     reGetGroup(), lets you retrieve the matching text
     for parenthesized groups within regular
     expressions. reGetGroup() returns information
     about the last call to reSearch(). The function
     takes one argument, which is a number giving the
     group number to retrieve: the first parenthesized
     expression is group 1, the second is group 2, and
     so on. (When groups are nested, the position of
     the open parenthesis is used to determine the
     group numbering. The leftmost open parenthesis is
     numbered as group 1.)

     reGetGroup() returns nil if there is no such
     group in the most recent regular expression or if
     the last call to reSearch() did not match the
     expression. Otherwise, reGetGroup() returns a
     list with three elements identifying the group.
     The first element is a number giving the
     character position within the original search
     string of the start of the text that matched the
     group. The second element is the length of the
     text that matched the group. The third element is
     the actual text that matched the group.

     Here's a code example:

       ret := reSearch('d(.*)h', 'abcdefghi');
       if (ret != nil)
       {
         grp := reGetGroup(1);
         if (grp != nil)
           "Start = <<grp[1]>>, len = <<grp[2]>>, text = \"<<grp[3]>>\". ";
       }

     This will display the following:

       Start = 5, len = 3, text = "efg".

     You can use regular expression grouping to carry
     out complicated transformations on strings with
     relatively little code. Since you determine
     exactly where in a string a particular group in a
     regular expression occurs, you can take the group
     text out of the string and put it back into the
     string in a different order or with other changes.

     For example, suppose you want to write a
     preparse() function that finds sentences of the
     form "tell <actor> to <command> " and converts
     them to the normal TADS actor command format,
     "<actor>, <command> ". You can use regular
     expression grouping to find this pattern of text
     and build the new command from pieces of the
     original:

       ret := reSearch('^ *tell%> *(.*)%<to%> *(.*)', cmd);
       if (ret != nil)
         cmd := reGetGroup(1)[3] + ', ' + reGetGroup(2)[3];

     Or, suppose you have a telephone in your game,
     and you want to let the player dial numbers on
     the phone using normal North American telephone
     number notation, including an area code. The TADS
     parser won't normally let you do this, since it
     would try to parse the number as several words.
     You could solve this problem using preparse:
     after the player enters a command, find anything
     that looks like a telephone number, and enclose
     it in quotation marks; this will make the parser
     treat the phone number as a quoted string, so you
     can write your "dial" verb so that it uses strObj
     as the direct object. Here's how you could write
     the preparse routine:

       ret := reSearch('(%([0-9][0-9][0-9]%) *)?'
                       + '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]', cmd);
       if (ret != nil)
         cmd := substr(cmd, 1, ret[1] - 1) + ' "' + ret[3] + '" '
                + substr(cmd, ret[1] + ret[2], length(cmd));

------------------------------------------------------------
*>remdaemon

Call: remdaemon(function, value)

     Removes a daemon set previously with setdaemon().
     The daemon will no longer be called.

     Note that if a given function has been set as a
     daemon multiple times, a call to remdaemon() only
     removes the first such daemon; hence, you must
     call remdaemon() as many times as you called
     setdaemon() on a particular function if you wish
     to cancel all calls to it. Note also that the
     value given must match the value used in the
     original call to setdaemon(); this allows you to
     set a daemon several times, with different
     contexts (the context being given by the value),
     and selectively remove the daemons later. Also,
     removing a daemon that isn't running does nothing.

------------------------------------------------------------
*>remfuse

Call: remfuse(function, value)

     See also the setfuse() built-in function. This
     function removes a fuse previously set, or does
     nothing if the named function has not been set as
     a fuse. The fuse will not be executed if removed
     prior to burning down. Note that if a function
     has been set as a fuse multiple times, remfuse()
     will remove only the first such fuse set; hence,
     you must call remfuse() on a function as many
     times as you called setfuse() on the function if
     you wish to cancel all calls to it. Note also
     that the value given must match the value used in
     the original call to setdaemon(); this allows you
     to set a fuse several times, with different
     contexts (the context being given by the value),
     and selectively remove the fuses later. Removing
     a fuse that isn't set does nothing.

------------------------------------------------------------
*>reSearch

Call: reSearch(pattern, string_to_search)

Added: TADS 2.3.0

     TADS has a built-in regular expression matching
     facility. Regular expressions provide a powerful
     and simple way to search for a complex pattern
     within a text string. This feature is
     particularly useful for writing preparse() and
     preparseCmd() functions, since it allows you to
     perform complex pattern matching and replacing
     with very little code.

     The function reSearch() searches for the first
     occurrence of a regular expression pattern within
     a string. It returns nil if the pattern is not
     found. If the pattern is found, the function
     returns a list, the first element of which is a
     number giving the character position within the
     string of the start of the match (the first
     character is at position 1), the second element
     giving the number of characters in the match, and
     the third element a string giving the actual text
     of the match.

     The pattern is specified using regular expression
     syntax similar to that used by "grep" and other
     similar utilities. Here are the basic building
     blocks of the regular expression syntax:

     +------+-----------------------------------------+
     | |    | Alternation: matches the expression on  |
     |      | the left or the expression on the       |
     |      | right. This operator affects as many    |
     |      | characters as it can, out to the        |
     |      | nearest parentheses.                    |
     +------+-----------------------------------------+
     | ( )  | Groups an expression.                   |
     +------+-----------------------------------------+
     | +    | Indicates that the immediately          |
     |      | preceding character or parenthesized    |
     |      | expression repeats one or more times.   |
     +------+-----------------------------------------+
     | *    | Indicates that the immediately          |
     |      | preceding character or parenthesized    |
     |      | expression repeats zero or more times.  |
     +------+-----------------------------------------+
     | ?    | Indicates that the immediately          |
     |      | preceding character or parenthesized    |
     |      | expression can occur zero or one time.  |
     +------+-----------------------------------------+
     | .    | (a period/full stop) Wildcard: matches  |
     |      | any single character.                   |
     +------+-----------------------------------------+
     | ^    | Matches the beginning of the string.    |
     +------+-----------------------------------------+
     | $    | Matches the end of the string.          |
     +------+-----------------------------------------+
     | %    | Quotes the following character,         |
     |      | removing the special meaning of these   |
     |      | characters: | . ( ) * ? + ^ $ % [ Also  |
     |      | introduces the special sequences        |
     |      | listed later.                           |
     +------+-----------------------------------------+
     | [ ]  | Indicates a character list or range     |
     |      | expression. Matches any one of the      |
     |      | listed characters. A range can be       |
     |      | specified by following a character      |
     |      | with `-' and another character; this    |
     |      | matches all of the characters between   |
     |      | and including these two characters.     |
     |      | For example, [a-z] matches any one      |
     |      | lower-case letter, and [0-9] matches    |
     |      | any one digit. Ranges and single        |
     |      | characters can be combined; for         |
     |      | example, [a-zA-Z] matches any letter,   |
     |      | upper- or lower-case. To include the    |
     |      | character `]' in a list, make it the    |
     |      | first character after the opening       |
     |      | bracket; to include `-', make it the    |
     |      | next character after that. For          |
     |      | example, []] matches just `]', [-]      |
     |      | matches just `-', and []-] matches `-'  |
     |      | and `]'.                                |
     +------+-----------------------------------------+
     | [^ ] | Exclusionary character list or range.   |
     |      | This matches any character except the   |
     |      | ones listed. For example, [^0-9]        |
     |      | matches anything single character       |
     |      | except a digit.                         |
     +------+-----------------------------------------+
     | %1   | This matches the same text that         |
     |      | matched the first parenthesized         |
     |      | expression. For example, consider the   |
     |      | pattern `(a*).*%1'. The string          |
     |      | `aaabbbaaa' will match, because the     |
     |      | first three characters match the        |
     |      | parenthesized `a*' expression, which    |
     |      | causes `%1' to match the last three     |
     |      | characters; the middle three            |
     |      | characters are matched by the `.*'      |
     |      | expression.                             |
     +------+-----------------------------------------+
     | %2   | Matches the text matching the second    |
     |      | parenthesized expression.               |
     +------+-----------------------------------------+
     |      | And so on through...                    |
     +------+-----------------------------------------+
     | %9   | Matches the text matching the ninth     |
     |      | parenthesized expression.               |
     +------+-----------------------------------------+
     | %<   | Matches at the beginning of a word.     |
     |      | Words are considered to be contiguous   |
     |      | groups of letters and numbers.          |
     +------+-----------------------------------------+
     | %>   | Matches at the end of a word. For       |
     |      | example, `%<and%>' matches the "and"    |
     |      | in `ball and box' and `and then', but   |
     |      | not in `rubber band' or `the android'.  |
     |      | Note that %< and %> do not actually     |
     |      | contribute any characters to the match  |
     |      | - they simply ensure that they fall on  |
     |      | a word boundary. So, searching for      |
     |      | `%<and%>' in `ball and box' matches     |
     |      | the string `and' - the spaces are not   |
     |      | included in the match.                  |
     +------+-----------------------------------------+
     | %w   | Matches any word character (a letter    |
     |      | or a digit).                            |
     +------+-----------------------------------------+
     | %W   | Matches any non-word character          |
     |      | (anything but a letter or digit).       |
     +------+-----------------------------------------+
     | %b   | Matches at any word boundary            |
     |      | (beginning or end of a word).           |
     +------+-----------------------------------------+
     | %B   | Matches except at a word boundary.      |
     +------+-----------------------------------------+

     Any character other than those listed above
     simply matches the exact same character. For
     example, `a' matches `a'.

     Here are some examples of simple regular
     expressions, to help clarify the meanings of the
     basic building blocks:

     +-----------+------------------------------------+
     | abc|def   | either `abc' or `def'              |
     +-----------+------------------------------------+
     | (abc)     | `abc'                              |
     +-----------+------------------------------------+
     | abc+      | `abc', `abcc', `abccc', etc.       |
     +-----------+------------------------------------+
     | abc*      | `ab', `abc', `abcc', `abccc', etc. |
     +-----------+------------------------------------+
     | abc?      | `ab' or `abc'                      |
     +-----------+------------------------------------+
     | .         | any single character               |
     +-----------+------------------------------------+
     | ^abc      | `abc', but only at the start of    |
     |           | the string                         |
     +-----------+------------------------------------+
     | abc$      | `abc', but only at the end of the  |
     |           | string                             |
     +-----------+------------------------------------+
     | %^abc     | literally `^abc'                   |
     +-----------+------------------------------------+
     | [abcx-z]  | `a', `b', `c', `x', `y', or `z'    |
     +-----------+------------------------------------+
     | []-]      | `]' or `-'                         |
     +-----------+------------------------------------+
     | [^abcx-z] | any character except `a', `b',     |
     |           | `c', `x', `y', or `z'              |
     +-----------+------------------------------------+
     | [^]-q]    | any character except `]', `-', or  |
     |           | `q'                                |
     +-----------+------------------------------------+

     Here are some more complicated examples:

       (%([0-9][0-9][0-9]%) *)?[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]

     This matches a North American-style telephone
     number, either with or without an area code in
     parentheses. If an area code is present, it can
     optionally be separated by spaces from the rest
     of the number: `(415)555-1212', `555-1212',
     `(415) 555-1212'.

       [-+]?([0-9]+%.?|([0-9]*)%.[0-9]+)([eE][-+]?[0-9]+)?

     This matches a floating-point number in the
     notation used by C and some other programming
     languages: either a string of digits optionally
     ending with a decimal point, or zero or more
     digits followed by a decimal point followed by
     one or more digits; optionally followed by an
     exponent specified with the letter "E" (upper- or
     lower-case), an optional sign (`+' or `-'), and
     one or more digits; all of this can be preceded
     by an optional sign. This matches: `3e9',
     `.5e+10', `+100', `-100.', `100.0', `-5e-9',
     `-23.e+50'.

       ^ *tell%>(.*)%<to%>(.*)

     This matches the word "tell" at the beginning of
     the string, preceded only by zero or more spaces,
     followed by any text, followed by the word "to",
     followed by any more text. This matches `tell bob
     to go north' and `tell teeterwaller to give me
     the mask'.

     Here's a code example:

       ret := reSearch('d.*h', 'abcdefghi');
       if (ret = nil)
         "No match.";
       else
         "Start = <<ret[1]>>, length = <<ret[2]>>, text = \"<<ret[3]>>\". ";

     When run, this code will display the following:

       Start = 4, length = 5, text = "defgh".

------------------------------------------------------------
*>resourceExists

Call: resourceExists(resource)

Added: TADS 2.5.1

     This function allows you to determine whether a
     named resource (such as a JPEG image or an MP3
     audio file) can be loaded. This function takes as
     its single argument a string giving the name of a
     resource to find; the function returns true if
     the resource can be loaded, nil if not. The
     function returns nil if the interpreter is simply
     not capable of loading resources at all (the
     text-only interpreters thus always return nil for
     this function), or if the resource can't be
     found. The function returns true only if the
     interpreter is capable of loading resources at
     all, and the resource is available.

     If you're writing a multimedia game for the HTML
     interpreters, but you also want your game to work
     on text-only systems, you can use this function
     for finer control over the presentation on the
     text systems; you might, for example, want to
     provide additional text to make up for missing
     graphics or sounds. You can also use this
     function if you're planning to distribute your
     game in different subset versions in order to
     provide players with different options for
     download and install sizes; if you make some of
     your graphics optional (by bundling some into a
     separate ".RSn" resource file, for example), you
     can use resourceExists() to detect at run-time
     which resources the player has chosen to install,
     and customize the presentation accordingly.

     Here's an example that checks to see if a JPEG
     image is available for display:

       if (!resourceExists('images/title.jpg'))
       {
         // the title graphic isn't available - display a text version
         ...
       }

------------------------------------------------------------
*>restart

Call: restart()

     This function starts the game over again from the
     beginning. It does not return.

Alternative Call: restart( funcptr, param )

     This form of restart() allows you to specify a
     function to be called after restarting the game,
     but before the init() function is invoked. This
     new feature has been added because it would
     otherwise be impossible to pass any information
     across a restart operation: the restart()
     function does not return, and all game state is
     reset to its initial state by restart().

     You can use this function if you want a restarted
     game to have different startup behavior than the
     game has when it's first started. Note that adv.t
     passes a pointer to the initRestart function
     (defined in adv.t when it invokes restart() in
     response to a "restart" command; the adv.t
     implementation of initRestart() simply sets the
     flag global.restarting to true to indicate that
     the game is being restarted rather than first
     entered.

     The param value is simply passed as the parameter
     to the function to be called, and this allows you
     to pass information through the reset. For
     example, if you start the game with a
     questionnaire asking the player's name, sex, and
     age, you could pass a list containing the
     player's responses to your restart function, and
     have the restart function store the information
     without making the player answer the
     questionnaire again. The call to restart() in
     adv.t uses global.initRestartParam as the
     parameter for the initRestart() function; so, if
     you provide your own version of initRestart()
     that makes use of the parameter information, you
     can simply store the necessary information in
     global.initRestartParam to ensure that it's
     passed to your function at the appropriate time.

------------------------------------------------------------
*>restore

Call: restore(filename)

Added: Return values altered 2.5.0

     The filename is a string specifying an operating
     system file which was created with the save()
     function. The state of the previously saved game
     is restored, so that the players can continue
     where they left off.

     If successful, nil is returned; otherwise, an
     error occurred restoring the game from the file,
     and a numeric code wil be returned. Note that the
     game to be restored must have been saved by the
     identical version of the TADS software and of the
     game itself. The system will refuse to restore a
     game saved by a different version of the TADS
     software, or by a different version of your game
     program (as determined by a timestamp stored in
     the game by the compiler).

     As of TADS 2.5.0 the return value in the event of
     an error is a number. Different values are
     returned for different error conditions, which
     makes it possible to provide better information
     to the player about the specific problem that
     caused the operation to fail. The return values,
     defined in adv.t, are:

  +------------------------+----------------------------+
  | RESTORE_SUCCESS        | Success                    |
  +------------------------+----------------------------+
  | RESTORE_FILE_NOT_FOUND | The file to be restored    |
  |                        | does not exist (or could   |
  |                        | not be opened for some     |
  |                        | other reason).             |
  +------------------------+----------------------------+
  | RESTORE_NOT_SAVE_FILE  | The file is not a valid    |
  |                        | saved game.                |
  +------------------------+----------------------------+
  | RESTORE_BAD_FMT_VSN    | The file was saved by an   |
  |                        | incompatible version of    |
  |                        | the TADS Interpreter       |
  +------------------------+----------------------------+
  | RESTORE_BAD_GAME_VSN   | The file was saved by a    |
  |                        | different game, or by a    |
  |                        | different version of the   |
  |                        | same game.                 |
  +------------------------+----------------------------+
  | RESTORE_READ_ERROR     | An error occurred reading  |
  |                        | the file. This could       |
  |                        | indicate that the file     |
  |                        | was corrupted, or that     |
  |                        | the physical medium        |
  |                        | containing the file is     |
  |                        | damaged.                   |
  +------------------------+----------------------------+
  | RESTORE_NO_PARAM_FILE  | No parameter file has      |
  |                        | been specified. This is    |
  |                        | returned only when         |
  |                        | restore(nil) is called to  |
  |                        | attempt to load the file   |
  |                        | specified by a start-up    |
  |                        | parameter; it indicates    |
  |                        | that there is in fact no   |
  |                        | parameter file to load.    |
  +------------------------+----------------------------+

     For compatibility with older versions of TADS,
     RESTORE_SUCCESS is defined as 0, and all of the
     other values are non-zero. In most cases, this
     should allow existing code (that assumes the
     nil/true return value) to continue working
     without changes, since if (restore(fname)) will
     continue to have the same effect with this
     change. Only old code that explicitly compared
     the return value to nil or true will need to be
     changed.

Alternative Call: restore( nil )

     This form of the restore() function allows you to
     choose the time during startup that the player's
     saved game is restored when the player started
     your game with a saved game already specified.
     When you call restore(nil), the system checks to
     see if a saved game was specified by the player
     at startup, and if so, immediately restores the
     game and returns nil. If no game was specified,
     the function returns true.

     It is possible for a player to start a game in
     this manner only on windowed GUI TADS runtimes,
     such as those that run on the Macintosh and under
     Windows, but the new restore() functionality will
     work correctly on all platforms. On the
     Macintosh, the operating system allows an
     application to be started by opening one of the
     application's documents from the desktop. When
     this happens the application is started and
     informed that the user wishes to open the
     specified file. Saved game files on the Macintosh
     are associated with the game executable that
     created them in such a way that the game is
     executed when a saved game is opened. This is
     simply a convenience feature on the Macintosh
     that allows a player to run a game and restore a
     saved position in a single operation.

     You can use restore(nil) in your init function to
     choose the point at which the saved game is
     restored. If your game has extensive introductory
     text, you could call restore(nil) (and return if
     the function returns nil) prior to displaying the
     introductory text, since the player has
     presumably already seen it anyway.

     The reason that the system doesn't restore the
     saved game prior to calling your init function is
     that you may want parts of your init function to
     be invoked regardless of whether a game is going
     to be restored or not. For example, you may wish
     to display your copyright message, or ask a
     question for copy protection, every time the game
     starts, even when a saved game is going to be
     restored.

     If you do not make a call to restore(nil) in your
     init function, the system will automatically
     restore the saved game specified by the player at
     startup immediately after your init function
     returns. Hence, omitting the call to restore(nil)
     doesn't do any harm; this function is provided to
     give you greater control

------------------------------------------------------------
*>rundaemons

Call: rundaemons()

     Runs all of the daemons. The function runs
     daemons set both with setdaemon() and notify().
     This function returns no value.

------------------------------------------------------------
*>runfuses

Call: runfuses()

     Runs all expired fuses, if any. Returns true if
     any fuses expired, nil otherwise. This function
     runs fuses set both with setfuse() and notify().

------------------------------------------------------------
*>save

Call: save(filename)

     The filename is a string specifying an operating
     system file to be used to save the current status
     of the game. Everything about the game is saved
     in the file, so that the exact point in the game
     can be later restored with the restore() function.

     If successful, nil is returned; otherwise, an
     error occurred saving the file.

------------------------------------------------------------
*>say

Call: say(value)

     The value can be either a number or a string. If
     it's a number, its decimal value is printed. A
     string is displayed as it is.

     There is no return value.

------------------------------------------------------------
*>setdaemon

Call: setdaemon(function, value)

     Sets a daemon. Each turn, all outstanding daemons
     are called once, after all player command
     processing is completed. The value given is
     passed to the function as its sole parameter each
     time the function is called.

     Note: the function must be known when the
     compiler reads this statement, which means the
     function must have been defined or at least
     called prior to the setdaemon() call in the
     source file. You can forward-declare a function
     by using a statement like this:

       test: function;

     Note that the actual definition of the function
     test will appear later in the file; the statement
     above only declares it as a function so it can be
     used in the setdaemon() or similar call.

     At most 100 daemons can be running
     simultaneously; a run-time error will result if a
     call to setdaemon() is made when 100 daemons are
     already running. There is no return value.

     See also the notify() function.

------------------------------------------------------------
*>setfuse

Call: setfuse(function, time, value)

     Sets a fuse of the specified length. The function
     is the identifier naming a function. The time is
     a positive number specifying the number of turns
     before the fuse burns down. After the specified
     number of turns, function is called with value as
     its sole parameter.

     Note: the function must be known as a function
     when the compiler reads this statement, which
     means the function must have been defined or at
     least called prior to the setfuse() call in the
     source file. See the note in the description of
     setdaemon(), above, for more information.

     There is limit of 100 simultaneously pending
     fuses; a run-time error results if setfuse() is
     called when 100 fuses are already pending. There
     is no return value from setfuse().

     Note that fuses differ from daemons in that a
     fuse is only called once, at a time determined
     when the fuse is set; once called, it is
     automatically removed from the list of pending
     fuses. Daemons, on the other hand, are called
     once per turn until explicitly removed.

------------------------------------------------------------
*>setit

Call: setit(object)

     Sets the antecedant of "it," as used in a
     player's command, to the specified object. This
     is useful if a complaint refers to an object
     which will draw the player's attention; consider
     the following dialogue:

       >go north
       The metal door is closed.

       >open it
       There is a padlock preventing you from opening the door.

       >unlock it
       What do you want to unlock the padlock with?

       >the key
       The padlock swings open.

     In this example, setit() has been used each time
     a complaint refers to an object which the user
     might wish to manipulate due to the complaint.

     There is no return value.

Alternative Call: setit( nil )

     You can use nil as the argument to setit(). This
     prevents the player from using "it" in subsequent
     commands.

Alternative Call: setit( obj, num )

     You can also specify which pronoun you want to
     set. The optional parameter num specifies the
     pronoun: 1 for "him" and 2 for "her." When num is
     not specified, setit() sets "it" as usual. Note
     that nil can be used for the obj argument to
     clear "him" or "her."

Alternative Call: setit( list )

     Finally, you can set "them" directly, simply by
     passing a list of objects (rather than a single
     object) to setit(). Calling setit() with a list
     argument has the side effect of clearing "it."

------------------------------------------------------------
*>setscore

Call: setscore(score, turns)

Alternative Call: setscore(stringval)

     This function is used to inform the system of the
     current score and turn count. On versions of TADS
     that have a status line, this function updates
     the values on the status line. On versions of
     TADS without a status line, this call is ignored.

     Your game should call this function whenever the
     score or turncounter change, so that the status
     line is always kept up to date. Note that this
     means that it should be called after using
     restore() to load an old game, and before calling
     restart() to start over from the beginning, in
     addition to being called whenever the player
     earns points or completes a turn. Generally, if
     you use the function incscore() defined in adv.t
     to add points to the score, and you use a
     standard turn counter function (such as the
     turncount() function defined in adv.t), you will
     not have to worry about calling setscore() too
     often.

     The alternative form of the setscore() call
     allows you to display any text string in the
     score/turn counter area of the status line. In
     older versions of TADS, only the first form could
     be used, and the status line display was fixed
     with the score/turn counter format. In new
     versions, however, you can place whatever string
     you want on the right portion of the status line,
     simply by passing the string you wish to display
     to the setscore() function. You could, for
     example, display the time of day (within your
     game), or you could display the player's rank,
     experience, or other statistics rather than the
     score. The text string used in setscore() is
     displayed right-justified on the status line.

     Note that several routines in adv.t (about four
     in all) call the numeric form of setscore(). If
     you use the string version, you should change the
     setscore() calls in adv.t to call a routine that
     you provide that displays the status line in the
     format you prefer.

------------------------------------------------------------
*>setversion

Call: setversion(version)

     Note: This function is no longer needed, although
     TADS continues to support it for compatibility
     with existing games written with very old
     versions of TADS.

     In older version of TADS, this function was used
     to identify the version of your game that created
     a saved game file. It was necessary to use
     setversion so that a saved position file created
     by one version of your game couldn't accidentally
     be used with another version of your game,
     because the information in a saved position file
     is only usable by the same version of a game that
     created it. The compiler now automatically
     generates a unique version identifier whenever
     your game is compiled, eliminating the need for
     you to do this manually. You no longer need to
     call this function, and it has no effect if you
     do.

------------------------------------------------------------
*>skipturn

Call: skipturn(num)

     This function is similar to incturn(num). This
     function skips the given number of turns, which
     must be at least 1. The difference between
     skipturn() and incturn() is that skipturn()
     doesn't run any of the fuses that burn down
     during the turns being skipped - instead, it
     simply removes them without running them.

     Fuses set with setfuse() and notify() are both
     affected by this routine. Note that this function
     has no effect on daemons.

------------------------------------------------------------
*>substr

Call: substr(string, offset, length)

     This function returns the substring of string
     starting at the character position given by
     offset (the first character's position is 1) and
     containing up to length characters. For example,
     substr('abcdefghi', 4, 3) returns the string
     'def'. If the given offset is past the end of
     string, a null string is returned; hence,
     substr('abcdef', 10, 3) returns a null string.
     (Note that a null string, specified by two single
     quotes, ", is not the same as nil.) If the string
     is too short to satisfy the requested length, the
     substring from the given offset to the end of the
     string is returned; for example, substr(
     'abcdefg', 4, 10 ) returns the string 'defg'.

------------------------------------------------------------
*>systemInfo

Call: systemInfo( __SYSINFO_xxx )

Added: TADS 2.2.4. __SYSINFO_HTML_MODE and
__SYSINFO_MPEG_AUDIO were added with 2.3.0.

     This built-in function allows your game to
     determine programmatically whether the TADS
     run-time that is currently executing the game has
     certain capabilities. This function is called
     like this:

       result = systemInfo( __SYSINFO_xxx );

     where __SYSINFO_xxx is one of a number of
     pre-defined constants, listed below, defined
     automatically by the compiler. The result tells
     you about the particular run-time that is
     executing your game, so you can customize the
     game, if you wish, for certain system
     capabilities. For example, you might want to
     change some text in your game slightly depending
     on whether sound effects can be played. It's also
     useful if you need to know whether a given
     function (for example, regular expression
     parsing) is available.

     Before calling systemInfo() with any of the
     constant codes, you must check to see if
     systemInfo() itself is supported. Versions of the
     run-time prior to 2.2.4 do not support this
     function, so the return codes are meaningless.
     Fortunately, you can determine if systemInfo() is
     itself supported using the following code
     fragment:

       if (systemInfo(__SYSINFO_SYSINFO) = true)
       {
         /*
          *  systemInfo IS supported by this run-time - other
          *  systemInfo codes will return meaningful results
          */
       }
       else
       {
         /*
          *  systemInfo is NOT supported by this run-time
          */
       }

     Only one version of HTML TADS (version 2.2.3) was
     ever released without systemInfo support, and
     this was the first public beta release. So, it
     should be fairly safe to assume that any system
     that doesn't support systemInfo() doesn't support
     any of the multimedia features.

     The predefined __SYSINFO_xxx codes are:

+------------------------+---------------------------------+
| __SYSINFO_VERSION      | Returns a string with the       |
|                        | run-time version number. This   |
|                        | will be a string such as        |
|                        | `2.2.4'.                        |
+------------------------+---------------------------------+
| __SYSINFO_HTML         | Returns 1 if HTML markup is     |
|                        | supported, 0 if not. 0          |
|                        | indicates that this is a        |
|                        | standard text-mode run-time     |
|                        | system. If this returns 0,      |
|                        | then JPEG, PNG, WAV, MIDI,      |
|                        | WAV/MIDI overlap, WAV overlap,  |
|                        | and the images, sounds, music,  |
|                        | and links preference items can  |
|                        | all be assumed to be            |
|                        | unsupported, since these        |
|                        | features are only provided by   |
|                        | HTML TADS.                      |
|                        |                                 |
|                        | Note that __SYSINFO_HTML        |
|                        | returns 0 (HTML not supported)  |
|                        | for the character-mode          |
|                        | run-time, even for the newer    |
|                        | versions of the run-time that   |
|                        | do provide some limited HTML    |
|                        | support, because this           |
|                        | information code is intended    |
|                        | to indicate whether the full    |
|                        | HTML feature set is supported.  |
|                        | The character-mode version      |
|                        | only supports a limited subset  |
|                        | of HTML features, so it         |
|                        | indicates that HTML is not      |
|                        | supported.                      |
+------------------------+---------------------------------+
| __SYSINFO_HTML_MODE    | Returns true if the             |
|                        | interpreter is currently        |
|                        | interpreting HTML markups, nil  |
|                        | if not. Note that this new      |
|                        | code has nothing to do with     |
|                        | whether the interpreter is a    |
|                        | full multimedia system (such    |
|                        | as HTML TADS) or a text-only    |
|                        | system (such as the DOS "TR"    |
|                        | interpreters); this code        |
|                        | instead indicates only whether  |
|                        | or not a "\H+" sequence is      |
|                        | currently in effect.            |
+------------------------+---------------------------------+
| __SYSINFO_OS_NAME      | Returns a string with the name  |
|                        | of the operating system on      |
|                        | which the run-time is           |
|                        | currently executing. (The name  |
|                        | is the same as the string that  |
|                        | the compiler uses to            |
|                        | pre-define the                  |
|                        | __TADS_SYSTEM_NAME              |
|                        | preprocessor symbol, but this   |
|                        | lets you determine what system  |
|                        | is executing at run-time,       |
|                        | rather than the system that     |
|                        | was used to compile the game.)  |
+------------------------+---------------------------------+
| __SYSINFO_JPEG         | Returns 1 if JPEG images are    |
|                        | supported, 0 if not.            |
+------------------------+---------------------------------+
| __SYSINFO_PNG          | Returns 1 if PNG images are     |
|                        | supported, 0 if not.            |
+------------------------+---------------------------------+
| __SYSINFO_PNG_TRANS    | Tests for PNG transparency      |
|                        | support. Some newer versions    |
|                        | of the HTML interpreter         |
|                        | support PNG transparency,       |
|                        | which allows parts of a PNG     |
|                        | image to be designated as       |
|                        | transparent so that the         |
|                        | background shows through.       |
|                        | systemInfo(__SYSINFO_PNG_TRANS) |
|                        | returns true if transparency    |
|                        | is supported when displaying    |
|                        | PNG images, nil if not. This    |
|                        | will never return true under    |
|                        | interpreters that don't         |
|                        | support PNG images at all.      |
|                        | Note that this flag indicates   |
|                        | only simple transparency        |
|                        | support, which allows pixels    |
|                        | to be designated as fully       |
|                        | opaque or fully transparent,    |
|                        | and does not imply support of   |
|                        | full alpha blending; some       |
|                        | interpreters (such as the       |
|                        | Windows HTML interpreter        |
|                        | 2.5.4) support only simple      |
|                        | transparency but not alpha      |
|                        | blending. This code was added   |
|                        | with TADS 2.5.4 and is not      |
|                        | supported with earlier          |
|                        | versions.                       |
+------------------------+---------------------------------+
| __SYSINFO_PNG_ALPHA    | Tests for PNG "alpha blending"  |
|                        | support, which allows           |
|                        | individual pixels of a PNG      |
|                        | image to be designated as       |
|                        | partially transparent.          |
|                        | Currently, none of the          |
|                        | interpreters support alpha      |
|                        | blending in PNG images; this    |
|                        | flag has been added for         |
|                        | possible future use. This code  |
|                        | was added with TADS 2.5.4 and   |
|                        | is not supported with earlier   |
|                        | versions.                       |
+------------------------+---------------------------------+
| __SYSINFO_WAV          | Returns 1 if WAV sounds are     |
|                        | supported, 0 if not.            |
+------------------------+---------------------------------+
| __SYSINFO_MIDI         | Returns 1 if MIDI music is      |
|                        | supported, 0 if not.            |
+------------------------+---------------------------------+
| __SYSINFO_MIDI_WAV_OVL | Returns 1 if MIDI and WAV       |
|                        | sounds can be played back       |
|                        | simultaneously (overlapped), 0  |
|                        | if not. If this returns 0, it   |
|                        | means that WAV playback will    |
|                        | suspend MIDI playback.          |
+------------------------+---------------------------------+
| __SYSINFO_WAV_OVL      | Returns 1 if multiple WAV       |
|                        | sounds can be played back       |
|                        | simultaneously (overlapped), 0  |
|                        | if not. If this returns 0, it   |
|                        | means that any WAV played back  |
|                        | in a foreground layer will      |
|                        | suspend a WAV being played in   |
|                        | any background layer.           |
+------------------------+---------------------------------+
| __SYSINFO_MPEG_AUDIO   | Returns 1 if MPEG 2.0 audio     |
|                        | support of any kind is          |
|                        | present, 0 if not. It is        |
|                        | possible that some systems may  |
|                        | support some types of MPEG      |
|                        | audio, but not all three        |
|                        | layers. This feature code       |
|                        | indicates whether MPEG audio    |
|                        | of any kind is supported; the   |
|                        | specific layer codes below can  |
|                        | be used to check for each       |
|                        | individual layer.               |
+------------------------+---------------------------------+
| __SYSINFO_MPEG_AUDIO_1 | Returns 1 if MPEG 2.0 layer I   |
|                        | is supported                    |
+------------------------+---------------------------------+
| __SYSINFO_MPEG_AUDIO_2 | Returns 1 if MPEG 2.0 layer II  |
|                        | is supported                    |
+------------------------+---------------------------------+
| __SYSINFO_MPEG_AUDIO_3 | Returns 1 if MPEG 2.0 layer     |
|                        | III is supported. This media    |
|                        | type is commonly known as       |
|                        | `MP3'.                          |
+------------------------+---------------------------------+
| __SYSINFO_PREF_IMAGES  | Returns 1 if the user           |
|                        | preferences are set to allow    |
|                        | images to be displayed, 0 if    |
|                        | not. Note that, even if this    |
|                        | preference is set so that       |
|                        | images are not displayed, the   |
|                        | preferences for JPEG and PNG    |
|                        | images will still return 1 for  |
|                        | each of those image types that  |
|                        | are supported by the platform.  |
|                        | The image format codes          |
|                        | (__SYSINFO_PNG and              |
|                        | __SYSINFO_JPEG) indicate        |
|                        | whether the image formats are   |
|                        | supported at all, whereas this  |
|                        | preference code indicates       |
|                        | whether images are currently    |
|                        | allowed for display.            |
+------------------------+---------------------------------+
| __SYSINFO_PREF_SOUNDS  | Returns 1 if the user           |
|                        | preferences are set to allow    |
|                        | digitized sound effects (WAV    |
|                        | files) to play back, 0 if not.  |
+------------------------+---------------------------------+
| __SYSINFO_PREF_MUSIC   | Returns 1 if the user           |
|                        | preferences are set to allow    |
|                        | music (MIDI files) to play      |
|                        | back, 0 if not.                 |
+------------------------+---------------------------------+
| __SYSINFO_PREF_LINKS   | Returns 0 if the user           |
|                        | preferences are set so that     |
|                        | links are not highlighted at    |
|                        | all (in which case they'll be   |
|                        | displayed as ordinary text;     |
|                        | they won't be highlighted as    |
|                        | links and won't be active for   |
|                        | the mouse); returns 1 if links  |
|                        | are highlighted and active;     |
|                        | and returns 2 if links are set  |
|                        | to a "hot key" mode, in which   |
|                        | case links aren't highlighted   |
|                        | except when the user is         |
|                        | holding down a special key to   |
|                        | explicitly illuminate the       |
|                        | links.                          |
+------------------------+---------------------------------+

     Version 2.5.2 also introduced the ability to add
     live Internet links. The systemInfo() function
     accepts several capability codes that let you
     discover whether the system is capable of
     following URL-style <A HREF> hypertext links in
     HTML-formatted text. The codes are:

  +------------------------+----------------------------+
  | __SYSINFO_LINKS_HTTP   | Checks if the system can   |
  |                        | follow HTTP (Hypertext     |
  |                        | transfer protocol) links   |
  |                        | to display Web pages.      |
  |                        | HTTP URLs start with       |
  |                        | "http:".                   |
  +------------------------+----------------------------+
  | __SYSINFO_LINKS_FTP    | Checks if the system can   |
  |                        | follow FTP (file transfer  |
  |                        | protocol) links, which     |
  |                        | start with "ftp:".         |
  +------------------------+----------------------------+
  | __SYSINFO_LINKS_NEWS   | Checks if the system can   |
  |                        | follow links to Usenet     |
  |                        | newsgroups. News URLs      |
  |                        | start with "news:".        |
  +------------------------+----------------------------+
  | __SYSINFO_LINKS_MAILTO | Checks if the system can   |
  |                        | follow links to send       |
  |                        | email, which start with    |
  |                        | "mailto:".                 |
  +------------------------+----------------------------+
  | __SYSINFO_LINKS_TELNET | Checks if the system can   |
  |                        | follow telnet links,       |
  |                        | which start with           |
  |                        | "telnet:".                 |
  +------------------------+----------------------------+

     For example, suppose you want to display a link
     to a web page you've created for your game, so
     that players can check for updates and hints on
     your web site. You can use __SYSINFO_LINKS_HTTP
     to check the user's TADS interpreter for HTTP
     link capability. If the interpreter can follow
     HTTP links, you can show your link with a
     friendly display, and fall back on spelling out
     the URL when the interpreter can't directly
     follow the link.

       "You can check for updates to this game at ";
       if (systemInfo(__SYSINFO_LINKS_HTTP))
         "<A HREF='http://www.mysite.com/mygame.htm'>my web site</A>";
       else
         "my web site (http://www.mysite.com/mygame.htm)"
       ". This site also has hints and some background
        information about the game. ";

------------------------------------------------------------
*>timeDelay

Call: timeDelay(time)

Added: TADS 2.3.0

     This built-in function lets you pause the game
     for a specified time interval. You can use this
     function in the middle of displaying a long text
     passage, for example, to create a dramatic pause
     effect, without making the user press a key to
     continue. The function takes a single argument
     giving the number of milliseconds to pause the
     game. For example, to pause the game for five
     seconds, use this:

       timeDelay( 5000 );

------------------------------------------------------------
*>undo

Call: undo()

     This function undoes all changes made since the
     last "savepoint" in the undo records. A savepoint
     is entered at the beginning of each turn
     automatically by the player command parser.
     Calling undo() once restores the game to its
     state at the very beginning of the current turn.
     Calling undo() again returns it to the state at
     the beginning of the previous turn, and so forth.

     You should call undo() once in any situation
     where you only want to undo the current turn. For
     example, in a routine that gives the player
     options after being killed by an action taken on
     the current turn, you'd only want to call undo()
     once if the player elects to undo the action that
     killed him, since it's just the current turn that
     needs to be taken back.

     You should call undo() twice in your verb that
     implements an "undo" command, if you have one in
     your game. The first call undoes the current turn
     (the "undo" command itself), and the second call
     undoes the previous turn - this is appropriate
     behavior, since the "undo" command should back up
     one turn. The default undoVerb defined in adv.t
     implements exactly this behavior.

     The undo() function returns true if the undo
     operation was successful, or nil if no more undo
     information is available. A return value of nil
     means either that the player has already undone
     turns all the way back to the beginning of the
     game, or that he has undone turns as far back as
     the undo records go. The default undo area size
     will hold about a hundred turns in a typical
     game, but the actual number of turns that can be
     undone will vary by game, depending on the amount
     of work that needs to be undone. The undo
     mechanism will always keep as many of the most
     recent turns as possible, discarding the oldest
     turns in the undo log when it runs out of space.

------------------------------------------------------------
*>unnotify

Call: unnotify(object, &message)

     This function cancels the effect of a previous
     call to notify() with the same object and
     message. Note that the & before message is
     required.

     See also the notify() function.

------------------------------------------------------------
*>upper

Call: upper(string)

     This function returns a copy of string with all
     of the lower-case letters converted to
     upper-case. Do not confuse this function with the
     caps() built-in function, which affects only the
     next character displayed.

------------------------------------------------------------
*>verbinfo

Call: verbinfo(deepverb)

Alternative Call: verbinfo(deepverb, prep)

     This function lets you retrieve information on
     the doAction and ioAction definitions for the
     given deepverb object. This function returns a
     list giving the verification and actor property
     pointers for the appropriate verb template. Refer
     to the section on getting verb information for
     details on this function.

------------------------------------------------------------
*>yorn

Call: yorn()

     Waits for the user to type a character, and
     returns 1 if the player typed "Y", 0 if the
     player typed "N", and -1 for anything else. A
     suitable prompt should be issued prior to calling
     this function.

------------------------------------------------------------
Dynamic Object Creation

*>new
*>delete

     TADS allows you to create and delete objects
     dynamically at run-time. This is done through two
     operators: new and delete. To create a new
     object, use this syntax:

       x := new bookItem;

     This dynamically creates a new object whose
     superclass is bookItem. When this statement is
     executed, the runtime creates a new object,
     assigns its superclass to be bookItem, and
     executes the construct method in the new object;
     this method can perform any creation-time setup
     that you wish to do. The default construct method
     in the class thing in adv.t simply moves the new
     object into its location - this is necessary so
     that the contents list of the location is updated
     to include the new object.

     An expression involving the operator new applied
     to a class can be used wherever an object
     expression can be used. When the expression is
     evaluated, a new object of the given class is
     created.

     Note that you can create a new object that has no
     superclass by using the keyword object:

       x := new object;

     If you're familiar with C++ constructors, you
     should note an important difference between the
     construct method and C++ constructors. A C++
     constructor in a derived class will automatically
     call the construct in the base class (except for
     a virtual base class). The TADS construct method
     does not automatically call superclass construct
     methods; instead, construct works exactly the
     same as any other TADS method. You can, of
     course, call the superclass construct method
     explicitly using the inherited mechanism, just as
     with any other method. The same is true of the
     destruct method (described below).

     A new object inherits all of the vocabulary of
     its superclass.

     To destroy an object create with new, use this
     syntax:

       delete x;

     This first calls the destruct method of the
     object to notify it that it is about to be
     deleted, then destroys the object. Further
     references to the object are illegal, since its
     memory has been released (and thus may be given
     to an other object). The default destruct method
     in the class thing in adv.t moves the object into
     nil, which removes it from its container's
     contents list - this is necessary so that the
     reference to the object in that list is removed.

     Only objects created with new can be destroyed
     with delete. Objects that are defined statically
     in your game's source file cannot be deleted at
     run-time.

     Object creation and deletion works correctly with
     the UNDO mechanism. If the player uses UNDO after
     a move that created an object, the object will be
     destroyed; likewise, if a player uses UNDO after
     a turn that deletes an object, the object will be
     re-created with the same property values it had
     prior to deletion.

     Similarly, dynamically-created objects are
     preserved across SAVE and RESTORE operations.

     Note that TADS does not perform any garbage
     collection on dynamically-created objects. The
     system is not capable of determining whether an
     object is accessible or not. Hence, if you lose
     track of any objects you create with new, they
     will remain part of the game forever - they will
     even be saved along with saved games and restored
     when the games are restored. You must be careful
     to keep track of all objects you create to avoid
     filling all available memory (and the swap file)
     with unreachable objects. Even though TADS will
     eventually swap inaccessible objects out of
     memory, the objects will consume object
     identifiers, which are a limited resource: only
     65535 objects can be created within a game,
     including both static and dynamically-created
     objects.

------------------------------------------------------------
Indistinguishable Objects

*>isEquivalent
*>listcont
*>itemcnt
*>isIndistinguishable
*>sayPrefixCount

     The ability to create new objects at run-time
     leads to some interesting problems involving
     indistinguishable objects. Although you could use
     addword() to make your newly-created objects
     distinguishable from one another, this will not
     always be desirable. For example, if you create
     new gold pieces that serve as currency, you will
     probably not want them to be uniquely named.

     To support indistinguishable objects, especially
     those created dynamically at run-time, the system
     has a property that you can set to indicate to
     the parser that an object does not need to be
     distinguished from others of the same class. The
     property is isEquivalent. When isEquivalent
     returns true for an object, all other objects
     with the same immediate superclass are considered
     interchangeable by the parser. When a player uses
     one of these objects in a command, the parser
     will simply pick one arbitrarily and use it,
     without asking the player which one.

     If a player uses a noun that is ambiguous with
     multiple equivalent items and one or more other
     items, the parser will need to disambiguate the
     objects as usual. In such cases, the parser's
     question will list the distinguishable items only
     once. For example, assume we have five gold coins
     that are all equivalent (in other words, they all
     have isEquivalent set to true, and they all are
     immediate subclasses of the same class). Assume
     further that a silver coin and a bronze coin are
     also present in the room.

       Treasure Room

       You see a bronze coin, five gold coins, and a silver coin here.

       >get coin

       Which coin do you mean, the bronze coin, a gold coin, or the silver coin?

     Note that the objects which appear only once are
     listed with "the" (using the property thedesc),
     while the indistinguishable objects are listed
     only once, with "a" (using adesc).

     The functions listcont and itemcnt in adv.t list
     equivalent objects intelligently. The functions
     isIndistinguishable and sayPrefixCount are used
     to count and list indistinguishable objects
     correctly. The contents of the Treasure Room are
     listed in the example above in the new format.
     Refer to these functions in adv.t for examples of
     recognizing objects as equivalent, counting
     equivalent objects, and treating a set of
     equivalent objects together as a set.

     Note that listcont uses the property pluraldesc
     to display the name of an object when more than
     one equivalent object is present. In the example
     above, pluraldesc was used to list the gold
     coins. This property is in the class thing in
     adv.t, but you may need to override it for some
     objects - the default implementation simply
     displays the sdesc plus the letter "s."

------------------------------------------------------------
Preprocessor Directives

     TADS lets you define preprocessor symbols. The
     #define directive creates a preprocessor symbol
     definition:

       #define TEST "This is a test! "

     This defines the symbol TEST, and specifies that
     this symbol is to be replaced by the text "This
     is a test!" whenever it appears (outside of
     strings or comments) in your source code. Note
     that the definition of a symbol need not be a
     string - the entire text of the rest of the line
     is assigned to the symbol.

     You can use a preprocessor symbol that you've
     defined simply by putting the symbol in your
     code:

       sdesc =
       {
         TEST;
       }

     When the compiler encounters the preprocessor
     symbol, it replaces the symbol with its
     definition, so the compiler treats this the same
     as:

       sdesc =
       {
         "This is a test! ";
       }

     You can delete a preprocessor symbol that you've
     defined using the #undef directive:

       #undef TEST

     The compiler automatically defines a number of
     preprocessor symbols:

  +----------------------+------------------------------+
  | __TADS_VERSION_MAJOR | Defined as the major         |
  |                      | version number of the        |
  |                      | current compiler. (Note      |
  |                      | that this symbol starts      |
  |                      | with two underscore          |
  |                      | characters, as do most of    |
  |                      | the symbols that the         |
  |                      | compiler defines for you.)   |
  |                      | Currently, this is defined   |
  |                      | as 2.                        |
  +----------------------+------------------------------+
  | __TADS_VERSION_MINOR | The minor version number;    |
  |                      | currently 5.                 |
  +----------------------+------------------------------+
  | __TADS_SYSTEM_NAME   | A single-quoted string       |
  |                      | giving the name of the       |
  |                      | current system. For DOS      |
  |                      | systems, this is 'MSDOS';    |
  |                      | for Macintosh systems, this  |
  |                      | is 'Macintosh'. TADS also    |
  |                      | defines the value of this    |
  |                      | symbol as a symbol itself -  |
  |                      | on MSDOS systems, the        |
  |                      | compiler defines the symbol  |
  |                      | MSDOS, and on Macintosh      |
  |                      | systems, the compiler        |
  |                      | defines Macintosh. (The      |
  |                      | value of the system name     |
  |                      | symbol is simply 1; its      |
  |                      | purpose is to allow for      |
  |                      | conditional compilation, so  |
  |                      | the value isn't important.)  |
  +----------------------+------------------------------+
  | __DEBUG              | Defined if the game is       |
  |                      | being compiled for           |
  |                      | debugging (with the -ds      |
  |                      | command line option). By     |
  |                      | testing this symbol with     |
  |                      | #ifdef, you can easily       |
  |                      | include parts of your game   |
  |                      | (such as special "magic"     |
  |                      | verbs that you use for       |
  |                      | debugging) only in testing   |
  |                      | versions of your game,       |
  |                      | without having to worry      |
  |                      | about removing them          |
  |                      | manually when producing the  |
  |                      | final version of the game    |
  |                      | for players. The value of    |
  |                      | this symbol is 1 if it's     |
  |                      | defined; the purpose of      |
  |                      | this symbol is to allow for  |
  |                      | conditional compilation, so  |
  |                      | its value isn't important.   |
  +----------------------+------------------------------+
  | __DATE__             | Defined as a single-quoted   |
  |                      | string giving the date when  |
  |                      | the current compilation      |
  |                      | began, in the format 'Jan    |
  |                      | 01 1994'.                    |
  +----------------------+------------------------------+
  | __TIME__             | Defined as a single-quoted   |
  |                      | string giving the time when  |
  |                      | the current compilation      |
  |                      | began, in the 24-hour        |
  |                      | format '01:23:45'. The time  |
  |                      | isn't updated during the     |
  |                      | course of a compilation -    |
  |                      | it's always the time when    |
  |                      | compilation began.           |
  +----------------------+------------------------------+
  | __FILE__             | Defined as a single-quoted   |
  |                      | string giving the name of    |
  |                      | the current source file      |
  |                      | being compiled.              |
  +----------------------+------------------------------+
  | __LINE__             | Defined as a number giving   |
  |                      | the line number currently    |
  |                      | being compiled.              |
  +----------------------+------------------------------+

     You can define symbols from the compiler command
     line. The -D option lets you specify a symbol to
     define, and optionally a value. Specify the
     symbol, then an equals sign, then the value; if
     you omit the equals sign, the default value is 1.
     For example, to define the symbol DEMO from the
     command line, you could use this command:

       tc -DDEMO mygame

     You can also specifically delete preprocessor
     symbols that the compiler defines (other than
     __FILE__ or __LINE__). You can also undefine any
     symbols defined earlier on the command line with
     -D options, which may be useful if you're using a
     configuration file that defines certain symbol.
     To undefine a symbol, use the -U option:

       tc -UDEMO mygame

     If the symbol DEMO was defined earlier on the
     command line, the definition is deleted.

     The Macintosh compiler has a new preprocessor
     options dialogue box that you can access from the
     "Options" menu. You can use this dialogue to
     enter symbols to define; in the text box, simply
     list the symbols (one per line) that you wish to
     define. If you want to assign values to these
     symbols, use an equals sign, followed by the
     value. Another text box in the same dialogue lets
     you list pre-defined symbols that you want to
     delete; simply list the symbols to be deleted,
     one per line.

     You can test for the existence of a preprocessor
     symbol with #ifdef ("if defined") and you can
     test to see if a preprocessor symbol is undefined
     with the #ifndef ("if not defined") directive.
     These directives let you conditionally include
     code in your program, depending on whether or not
     a symbol is defined. For example:

       #ifdef TEST
       sdesc = { TEST; }
       #endif

     The code between the #ifdef and the #endif is
     included only if the preprocessor symbol TEST is
     defined. There's also a #else directive, which
     lets you include a block of lines if the most
     recent condition failed.

     Conditional compilation is particularly useful
     with the symbols you define from the command line
     with the -D option, since it allows you to write
     your game in such a way that certain features are
     enabled when you use a particular set of -D
     options. This allows you to use a single set of
     source files, but produce a variety of different
     .GAM files. For example, if you want to be able
     to generate a subset of your game as a demo, you
     could use conditional compilation to include or
     discard sections of the game depending on whether
     you're compiling the demo or the full game.
     Similarly, you could use conditional compilation
     to include certain features only when you're
     compiling a debugging version of your game; note
     that the compiler makes this even easier, because
     it defines the symbol __DEBUG when you're
     compiling with debugging symbols.

     I've also added the #error directive. This
     directive lets you generate an error from within
     your game. Any text following the #error on the
     line is displayed to the user as the text of the
     error message. For example:

       #ifndef TEST
       #error TEST is not defined!
       #endif

------------------------------------------------------------
File Operations

     TADS has support for reading and writing files
     from within your game program. This feature is
     intended to let you save information
     independently of the game-saving mechanism, which
     only really allows you to transfer information
     between sessions of a game. The file functions
     can save files in a proprietary binary format,
     which can be used to store TADS data, or as plain
     text files, which can be opened and read by any
     text editor, word processor or Web browser
     application.

     Operations on files are all performed through a
     file handle. This is a special value, generated
     by TADS, that you use to refer to a file. TADS
     creates a file handle when you open a file; once
     you've opened a file and obtained its file
     handle, you can read and write the file. Once
     you're done with the file, you close the file,
     which deletes the file handle.

     To open a file, use the fopen() function. This
     function takes two arguments: a (single-quoted)
     string giving the name of the file to open, using
     local file system conventions, and a "mode." The
     mode argument is one or two of these
     single-quoted string values:

       `b' - open as a binary file. If you
             don't specify the file mode, binary is
             assumed as the default mode, for
             compatibility with past versions.

       `r' - open file for reading; file must
             already exist.

       `r+' - open file for reading and
              writing; the file is created if it
              doesn't already exist. Not currently
              allowed in text mode.

       `t' - open as a text file. You can use
             the text mode in conjunction with `r'
             (read) and `w' (write) modes - `t' is
             not currently allowed with `r+' or `w+'
             modes. Note that text file
             functionality was added with version
             2.2.4 of TADS.

       `w' - create a new file for writing;
             the file is deleted if it already
             exists.

       `w+' - create a new file for reading
              and writing; the file is deleted if it
              already exists. Not currently allowed
              in text mode.

     For maximum portability you should avoid using
     volume names, directories, folders, or other path
     information in filenames, because any such
     information might be specific to your computer.

     The return value of fopen() is a file handle -
     you must save the file handle so you can use it
     later to perform operations on the file. If the
     operation fails, and the file cannot be opened as
     requested, fopen() returns nil. Opening a file
     could fail for a number of reasons. For example,
     if you attempt to open a non-existent file with
     mode `r', fopen() will return nil, because this
     mode requires that the file already exists.

     This example opens a new file called TEST.OUT for
     writing:

       fnum := fopen( 'test.out', 'w' );

     To close an open file, use fclose():

       fclose( fnum );

     Once you've closed a file, the file handle is no
     longer valid. TADS may re-use the same file
     handle on a subsequent fopen() call. Note that
     the TADS runtime allows only a limited number of
     files (currently 10) to be open simultaneously,
     so you should close a file when you're done with
     it.

     To write to a file, use fwrite(). This function
     takes a file handle, and a value to write; the
     value can be a string, a number, or true. The
     value can't be nil (this is because the fread()
     function returns nil to indicate failure; if you
     could write nil to a file, there would be no way
     to distinguish reading a valid nil from an error
     condition). fwrite() stores the value, along with
     information on its type.

     The fwrite() function returns nil on success,
     true on failure. If the function returns true, it
     usually means that the disk is full.

       if ( fwrite( fnum, 'string value!' ) or fwrite( fnum, 123 ) )
         "Error writing file!";

     If the file is open for reading, you can read
     from the file with the fread() function. This
     function takes a file handle, and it returns a
     value it reads from the file. The value returned
     is of the same type as the value originally
     written at this position in the file with
     fwrite(). If this function returns nil, it
     indicates that an error occurred; this usually
     means that no more information is in the file
     (which is the case once you've read to the end of
     the file).

       res := fread( fnum );
       say( res );

     You can get the current byte position in the file
     with the ftell() function:

       "The current seek position is "; ftell( fnum ); ". ";

     The ftell() function returns a number giving the
     byte position that will be read or written by the
     next file operation.

     You can set the file position with fseek() and
     fseekeof(). The fseek() function moves the file
     position to a particular byte position, relative
     to the beginning of the file. For example, this
     seeks to the very beginning of a file:

       fseek( fnum, 0 );

     The fseekeof() function positions the file at its
     end (EOF stands for "end of file"):

       fseekeof( fnum );

     Note that you must be careful with fseek(). You
     should only seek to positions that you obtained
     with the ftell() function; other positions may be
     in the middle of a string or a number in the
     file, so seeking to an arbitrary location and
     writing could render the file unusable by
     partially overwriting existing data.

     Of the two formats, TADS binary files were not
     designed with any provisions for creating or
     reading formatted files, or for exchanging
     information with programs other than TADS games.
     TADS' binary format is portable across platforms
     - you can take a binary file written using DOS
     TADS and read it on the Macintosh with Mac TADS;
     however, the TADS format isn't designed to be
     interchanged with other programs.

     If you want portable files, save your files in
     the text format. These files are plain ASCII and
     can be used by any other application on your
     computer.

     Some game players may be uncomfortable about the
     possibility that a malicious game author could
     harm their systems by writing a game that, for
     example, modifies their AUTOEXEC.BAT files. To
     address any concerns that players may have, TADS
     2.2.4 and higher provide a "file safety level"
     setting. This is an optional setting that allows
     the player to control the amount of access that a
     game has to files on the system at run-time.

     The file safety level is set through a command
     line option (note that HTML TADS and HyperTADS
     provide this setting through the "Preferences"
     dialogue). Use the new -s option to specify one
     of the possible safety levels:

       -s0 - (default) minimum safety - read
             and write in any directory
       -s1 - read in any directory, write in
             current directory
       -s2 - read-only access in any directory
       -s3 - read-only access in current
             directory only
       -s4 - maximum safety - no file I/O
             allowed

     If the game attempts a file operation that is not
     allowed by the current safety level, the fopen()
     function returns nil to indicate that the file
     open failed.

     These options affect only explicit file I/O
     operations performed by the game. Operations
     handled by the system, such as saving and
     restoring games and logging a transcript to a
     file, are not affected by the file safety level
     setting.

Our life is frittered away by detail Simplify, simplify.
HENRY DAVID THOREAU, Where I Lived, and What I Lived For
(1854)

The statements was interesting but tough.
MARK TWAIN, Adventures of Huckleberry Finn (1884)

------------------------------------------------------------










                    Adventure Definitions

------------------------------------------------------------
      This file is part of the TADS Author's Manual.
Copyright (c) 1987 - 2001 by Michael J. Roberts. All rights
                          reserved.

              Edited by N. K. Guy, tela design.

------------------------------------------------------------
Appendix A

------------------------------------------------------------
Adventure Definitions

     The TADS run-time system provides a great deal of
     support for text adventure games, but it doesn't
     pre-define very much specific to adventures. To
     make the game author's job easier, the file adv.t
     provides definitions for a great many basic
     objects and classes that underlie most adventure
     games. These classes are very general, and most
     games will customize them further, but they
     vastly reduce the amount of work required to
     write a game. This section describes these
     classes, what they do, and how to use them to
     write a game.

     Note that in addition to everything listed in the
     following pages, adv.t also defines the articles
     "a," "an," and "the."

     These definitions become part of your game when
     you include the standard adventure definitions
     file adv.t in your source file.

     Note, however, that this appendix provides only a
     partial description of each object class in
     adv.t. For a more complete understanding of how
     they work check out the adv.t file itself. It's
     fully commented, and reading the source code is
     always a good way to learn the details.

------------------------------------------------------------
Objects, Classes, and Functions

     This section lists the objects and functions
     defined in the standard adventure definitions
     file adv.t.

     The descriptions of the objects indicate the
     object's superclass or superclasses. For complete
     information on an object, you need to refer to
     the description of its superclasses as well. The
     descriptions also indicate the main properties
     defined in the object; in customizing the object,
     you will generally need to override one or more
     of these properties. For example, most
     descendants of thing will specify an sdesc to
     provide the object with a name.

     The function descriptions provide information on
     how to call the functions, what they do, and what
     they return.

     For clarity, the objects are described in
     inheritance order; that is, the lower-level
     (parent) classes are described first, then the
     descendants of those classes, then the
     descendants of those, and so on. (This is the
     same order in which they appear in adv.t.)

     --------------------------------------------------
     *>itemcnt

     itemcnt: function(list ): Returns a count of the
     "listable" objects in list. An object is listable
     (that is, it shows up in a room's description) if
     its isListed property is true. This function is
     useful for determining how many objects (if any)
     will be listed in a room's description.

     --------------------------------------------------
     *>listcont

     listcont: function(obj ): This function displays
     the contents of an object, separated by commas.
     The thedesc properties of the contents are used.
     It is up to the caller to provide the
     introduction to the list (usually something to
     the effect of "The box contains" is displayed
     before calling listcont) and finishing the
     sentence (usually by displaying a period). An
     object is listed only if its isListed property is
     true.

     --------------------------------------------------
     *>listfixedcontcont

     listfixedcontcont: function(obj ): List the
     contents of the contents of any fixeditem objects
     in the contents list of the object obj. This
     routine makes sure that all objects that can be
     taken are listed somewhere in a room's
     description. This routine recurses down the
     contents tree, following each branch until either
     something has been listed or the branch ends
     without anything being listable. This routine
     displays a complete sentence, so no introductory
     or closing text is needed.

     --------------------------------------------------
     *>listcontcont

     listcontcont: function(obj ): This function lists
     the contents of the contents of an object. It
     displays full sentences, so no introductory or
     closing text is required. Any item in the
     contents list of the object obj whose
     contentsVisible property is true has its contents
     listed. An Object whose isqcontainer or
     isqsurface property is true will not have its
     contents listed.

     --------------------------------------------------
     *>scoreStatus

     scoreStatus: function(parm ): This function
     simply calls setscore() with the same arguments.
     All other calls to setscore() in adv.t have been
     replaced by calls to scoreStatus(), which makes
     it easy to provide a new scoring format simply by
     using the replace keyword to substitute your own
     implementation of scoreStatus() for the one in
     adv.t. Also, note scoreFormat below.

     --------------------------------------------------
     *>scoreFormat

     Added: TADS 2.5.2.

     The way that adv.t displays the status line was
     changed slightly in version 2.5.2, in order to
     simplify coding of special formats. A new
     function, scoreFormat(), is now responsible for
     formatting the string to display in the right
     half of the status line. scoreFormat() takes the
     current score and the current turn counter as
     arguments, and returns a string to display in the
     right half of the status line. The default
     implementation in adv.t simply returns a string
     consisting of the score, a slash (`/'), and the
     turn count, which provides the same format that
     adv.t has traditionally used for the status line.

     The older function scoreStatus() calls
     scoreFormat() to generate the display. In
     addition, the code in room.statusLine that
     generates the HTML version of the status line now
     calls scoreFormat() as well. This makes
     scoreFormat() the single point in adv.t where the
     right half of the status line is formatted.

     The advantage of this new mechanism is that you
     can customize the display of the right half of
     the status line for both text-only and
     HTML-enabled games simply by replacing the
     scoreFormat() function.

     Of course, HTML-enabled games are not limited to
     using the traditional status line display; if you
     want a completely custom status line display when
     running under an HTML-enabled interpreter, you
     can replace adv.t's room.statusLine and generate
     your own <BANNER> display. The scoreFormat()
     mechanism, however, is convenient when you simply
     want to customize the right half of the status
     line, but still use the traditional single-line
     status format.

     --------------------------------------------------
     *>turncount

     turncount: function(parm ): This function can be
     used as a daemon (normally set up in the init
     function) to update the turn counter after each
     turn. This routine increments global.turnsofar,
     and then calls setscore to update the status line
     with the new turn count.

     --------------------------------------------------
     *>addweight

     addweight: function(list ): Adds the weights of
     the objects in list and returns the sum. The
     weight of an object is given by its weight
     property. This routine includes the weights of
     all of the contents of each object, and the
     weights of their contents, and so forth.

     --------------------------------------------------
     *>addbulk

     addbulk: function(list ): This function returns
     the sum of the bulks (given by the bulk property)
     of each object in list. The value returned
     includes only the bulk of each object in the
     list, and not of the contents of the objects, as
     it is assumed that an object does not change in
     size when something is put inside it. You can
     easily change this assumption for special objects
     (such as a bag that stretches as things are put
     inside) by writing an appropriate bulk method for
     that object.

     --------------------------------------------------
     *>incscore

     incscore: function(amount ): Adds amount to the
     total score, and updates the status line to
     reflect the new score. The total score is kept in
     global.score. Always use this routine rather than
     changing global.score directly, since this
     routine ensures that the status line is updated
     with the new value.

     --------------------------------------------------
     *>initSearch

     initSearch: function. Initializes the containers
     of objects with a searchLoc, underLoc, and
     behindLoc by setting up searchCont, underCont,
     and behindCont lists, respectively. You should
     call this function once in your preinit (or init,
     if you prefer) function to ensure that the
     underable, behindable, and searchable objects are
     set up correctly.

     --------------------------------------------------
     *>initRestart

     initRestart(param): function. This function is
     used when adv.t calls the restart() built-in
     function to start the game over from the
     beginning. The initRestart() in adv.t simply sets
     the property global.restarting to true. Your game
     can inspect this flag in the init() function (or
     elsewhere) to take a different course of action
     when restarting a game than when starting up for
     the first time. The parameter is not used by
     adv.t implementation of the function, but if you
     replace the initRestart function defined in
     adv.t, you might find the parameter useful for
     passing information through the restart.

     The "restart" verb passes a pointer to the
     initRestart function when it calls the restart()
     built-in function. This causes initRestart() to
     be invoked after the game has been restarted, but
     before init(). Note that the call to restart()
     passes global.initRestartParam as the parameter
     to the initRestart function. If you replace
     initRestart() with your own function, and you
     need to pass some information to this function,
     simply store the necessary information in
     global.initRestartParam at any time before
     restarting, and the information will
     automatically be passed to initRestart() when
     it's invoked.

     --------------------------------------------------
     *>nestedroom

     nestedroom: room. A special kind of room that is
     inside another room; chairs and some types of
     vehicles, such as inflatable rafts, fall into
     this category. Note that a room can be within
     another room without being a nestedroom, simply
     by setting its location property to another room.
     The nestedroom is different from an ordinary
     room, though, in that it's an "open" room; that
     is, when inside it, the actor is still really
     inside the enclosing room for purposes of
     descriptions. Hence, the player sees "Laboratory,
     in the chair." In addition, a nestedroom is an
     object in its own right, visible to the player;
     for example, a chair is an object in a room in
     addition to being a room itself.

     The property statusPrep displays an appropriate
     preposition for status line displays while the
     player is in the nested room. The property
     outOfPrep displays the correct preposition when
     leaving the nested room. The default values are
     statusPrep = "in" and outOfPrep = "out of". The
     class beditem provides default values of "on" and
     "out of" instead. If you're defining new
     subclasses of nestedroom, you can override these
     properties to provide the most appropriate
     messages for the subclasses.

     --------------------------------------------------
     *>chairitem

     chairitem: fixeditem, nestedroom, surface. Acts
     like a chair: actors can sit on the object. While
     sitting on the object, an actor can't go anywhere
     until standing up, and can only reach objects
     that are on the chair and in the chair's
     reachable list. By default, nothing is in the
     reachable list. Note that there is no real
     distinction made between chairs and beds, so you
     can sit or lie on either; the only difference is
     the message displayed describing the situation.

     --------------------------------------------------
     *>beditem

     beditem: chairitem. This object is the same as a
     chairitem, except that the player is described as
     lying on, rather than sitting in, the object.

     --------------------------------------------------
     *>thing

     thing: object. The basic class for objects in a
     game. The property contents is a list that
     specifies what is in the object; this property is
     automatically set up by the system after the game
     is compiled to contain a list of all objects that
     have this object as their location property. The
     contents property is kept consistent with the
     location properties of referenced objects by the
     moveInto method; always use moveInto rather than
     directly setting a location property for this
     reason. The adesc method displays the name of the
     object with an indefinite article; the default is
     to display "a" followed by the sdesc, but objects
     that need a different indefinite article (such as
     "an" or "some") should override this method.
     Likewise, thedesc displays the name with a
     definite article; by default, thedesc displays
     "the" followed by the object's sdesc.

     The sdesc simply displays the object's name
     ("short description") without any articles. The
     pluraldesc simply adds an "s" to the end of the
     sdesc property. The pluraldesc property is used
     by listcont() when multiple equivalent objects
     are present in a list. (for details, see the
     information on the changes to listcont()
     described in the section on indistinguishable
     objects.) The ldesc is the long description,
     normally displayed when the object is examined by
     the player; by default, the ldesc displays "It
     looks like an ordinary sdesc." The isIn(object)
     method returns true if the object's location is
     the specified object or the object's location is
     an object whose contentsVisible property is true
     and that object's isIn(object) method is true.
     Note that if isIn is true, it doesn't necessarily
     mean the object is reachable, because isIn is
     true if the object is merely visible within the
     location. The thrudesc method displays a message
     for when the player looks through the object
     (objects such as windows would use this
     property). The moveInto(object) method moves the
     object to be inside the specified object. To make
     an object disappear, move it into nil.

     --------------------------------------------------
     *>item

     item: thing. A basic item which can be picked up
     by the player. It has no weight (0) and minimal
     bulk (1). The weight property should be set to a
     non-zero value for heavy objects. The bulk
     property should be set to a value greater than 1
     for bulky objects, and to zero for objects that
     are very small and take essentially no effort to
     hold - or, more precisely, don't detract at all
     from the player's ability to hold other objects
     (for example, a piece of paper).

     --------------------------------------------------
     *>lightsource

     lightsource: item. A portable lamp, candle,
     match, or other source of light. The light source
     can be turned on and off with the islit property.
     If islit is true, the object provides light,
     otherwise it's just an ordinary object.

     --------------------------------------------------
     *>hiddenItem

     hiddenItem: object. This is an object that is
     hidden with one of the hider classes. A
     hiddenItem object doesn't have any special
     properties in its own right, but all objects
     hidden with one of the hider classes must be of
     class hiddenItem so that initSearch can find
     them.

     --------------------------------------------------
     *>hider

     hider: item. This is a basic class of object that
     can hide other objects in various ways. The
     underHider, behindHider, and searchHider classes
     are examples of hider subclasses. The class
     defines the method searchObj(actor, list), which
     is given the list of hidden items contained in
     the object (for example, this would be the
     underCont property, in the case of an
     underHider), and "finds" the object or objects.
     Its action is dependent upon a couple of other
     properties of the hider object. The serialSearch
     property, if true, indicates that items in the
     list are to be found one at a time; if nil (the
     default), the entire list is found on the first
     try. The autoTake property, if true, indicates
     that the actor automatically takes the item or
     items found; if nil, the item or items are moved
     to the actor's location. The searchObj method
     returns the list with the found object or objects
     removed; the caller should assign this returned
     value back to the appropriate property (for
     example, underHider will assign the return value
     to underCont).

     Note that because the hider is hiding something,
     this class overrides the normal verDoSearch
     method to display the message, "You'll have to be
     more specific about how you want to search that."
     The reason is that the normal verDoSearch message
     ("You find nothing of interest") leads players to
     believe that the object was exhaustively
     searched, and we want to avoid misleading the
     player. On the other hand, we don't want a
     general search to be exhaustive for most hider
     objects. So, we just display a message letting
     the player know that the search was not enough,
     but we don't give away what they have to do
     instead.

     The objects hidden with one of the hider classes
     must be of class hiddenItem.

     --------------------------------------------------
     *>underHider

     underHider: hider. This is an object that can
     have other objects placed under it. The objects
     placed under it can only be found by looking
     under the object; see the description of hider
     for more information. You should set the underLoc
     property of each hidden object to point to the
     underHider.

     Note that an underHider doesn't allow the player
     to put anything under the object during the game.
     Instead, it's to make it easy for the game writer
     to set up hidden objects while implementing the
     game. All you need to do to place an object under
     another object is declare the top object as an
     underHider, then declare the hidden object
     normally, except use underLoc rather than
     location to specify the location of the hidden
     object. The behindHider and searchHider objects
     work similarly.

     The objects hidden with underHider must be of
     class hiddenItem.

     --------------------------------------------------
     *>behindHider

     behindHider: hider. This is just like an
     underHider, except that objects are hidden behind
     this object. Objects to be behind this object
     should have their behindLoc property set to point
     to this object.

     The objects hidden with behindHider must be of
     class hiddenItem.

     --------------------------------------------------
     *>searchHider

     searchHider: hider. This is just like an
     underHider, except that objects are hidden within
     this object in such a way that the object must be
     looked in or searched. Objects to be hidden in
     this object should have their searchLoc property
     set to point to this object. Note that this is
     different from a normal container, in that the
     objects hidden within this object will not show
     up until the object is explicitly looked in or
     searched.

     The items hidden with searchHider must be of
     class hiddenItem.

     --------------------------------------------------
     *>fixeditem

     fixeditem: thing. An object that cannot be taken
     or otherwise moved from its location. Note that a
     fixeditem is sometimes part of a movable object;
     this can be done to make one object part of
     another, ensuring that they cannot be separated.
     By default, the functions that list a room's
     contents do not automatically describe fixeditem
     objects (because the isListed property is set to
     nil). Instead, the game author will generally
     describe the fixeditem objects separately as part
     of the room's ldesc.

     --------------------------------------------------
     *>distantItem

     distantItem: fixeditem. This class is essentially
     the same as a fixeditem, except that it's
     intended to be used for objects that are not
     actually part of a room, but are visible from the
     room. For example, the player might be able to
     see a distant mountain from a certain location,
     even though the player can't do anything to the
     mountain (except look at it). A distantItem
     object can be inspected, but any other attempts
     to manipulate the object will receive the
     response "It's too far away."

     --------------------------------------------------
     *>readable

     readable: item. An item that can be read. The
     readdesc property is displayed when the item is
     read. By default, the readdesc is the same as the
     ldesc, but the readdesc can be overridden to give
     a different message.

     --------------------------------------------------
     *>fooditem

     fooditem: item. An object that can be eaten. When
     eaten, the object is removed from the game, and
     global.lastMealTime is decremented by the
     foodvalue property. By default, the foodvalue
     property is global.eatTime, which is the time
     between meals. So, the default fooditem will last
     for one "nourishment interval."

     --------------------------------------------------
     *>dialItem

     dialItem: fixeditem. This class is used for
     making "dials," which are controls in your game
     that can be turned to a range of numbers. You
     must define the property maxsetting as a number
     specifying the highest number to which the dial
     can be turned; the lowest number on the dial is
     always 1. The setting property is the dial's
     current setting, and can be changed by the player
     by typing the command "turn dial to number." By
     default, the ldesc method displays the current
     setting.

     --------------------------------------------------
     *>switchItem

     switchItem: fixeditem. This is a class for things
     that can be turned on and off by the player. The
     only special property is isActive, which is nil
     if the switch is turned off and true when turned
     on. The object accepts the commands "turn it on"
     and "turn it off," as well as synonymous
     constructions, and updates isActive accordingly.

     --------------------------------------------------
     *>room

     room: thing. A location in the game. By default,
     the islit property is true, which means that the
     room is lit (no light source is needed while in
     the room). You should create a darkroom object
     rather than a room with islit set to nil if you
     want a dark room, because other methods are
     affected as well. The isseen property records
     whether the player has entered the room before;
     initially it's nil, and is set to true the first
     time the player enters. The roomAction(actor,
     verb, directObject, preposition, indirectObject)
     method is activated for each player command; by
     default, all it does is call the room's
     location's roomAction method if the room is
     inside another room. The lookAround(verbosity)
     method displays the room's description for a
     given verbosity level; true means a full
     description, nil means only the short description
     (just the room name plus a list of the objects
     present). roomDrop(object) is called when an
     object is dropped within the room; normally, it
     just moves the object to the room and displays
     "Dropped." The firstseen method is called when
     isseen is about to be set true for the first time
     (i.e., when the player first sees the room); by
     default, this routine does nothing, but it's a
     convenient place to put any special code you want
     to execute when a room is first entered. The
     firstseen method is called after the room's
     description is displayed.

     --------------------------------------------------
     *>darkroom

     darkroom: room. A dark room. The player must have
     some object that can act as a light source in
     order to move about and perform most operations
     while in this room. Note that the room's lights
     can be turned on by setting the room's lightsOn
     property to true; do this instead of setting
     islit, because islit is a method which checks for
     the presence of a light source.

     --------------------------------------------------
     *>Actor

     Actor: fixeditem, movableActor. A character in
     the game. The maxweight property specifies the
     maximum weight that the character can carry, and
     the maxbulk property specifies the maximum bulk
     the character can carry. The actorAction(verb,
     directObject, preposition, indirectObject) method
     specifies what happens when the actor is given a
     command by the player; by default, the actor
     ignores the command and displays a message to
     this effect. The isCarrying(object) method
     returns true if the object is being carried by
     the actor. The actorDesc method displays a
     message when the actor is in the current room;
     this message is displayed along with a room's
     description when the room is entered or examined.
     The verGrab(object) method is called when someone
     tries to take an object the actor is carrying; by
     default, an actor won't let other characters take
     its possessions.

     If you want the player to be able to follow the
     actor when it leaves the room, you should define
     a follower object to shadow the character, and
     set the actor's myfollower property to the
     follower object. The follower is then
     automatically moved around just behind the actor
     by the actor's moveInto method.

     The isHim property should return true if the
     actor can be referred to by the player as "him,"
     and likewise isHer should be set to true if the
     actor can be referred to as "her." Note that both
     or neither can be set; if neither is set, the
     actor can only be referred to as "it," and if
     both are set, any of "him," "her," or "it" will
     be accepted.

     --------------------------------------------------
     *>movableActor

     movableActor: qcontainer. Just like an Actor
     object, except that the player can manipulate the
     actor like an ordinary item. Useful for certain
     types of actors, such as small animals.

     --------------------------------------------------
     *>follower

     follower: Actor. This is a special object that
     can "shadow" the movements of a character as it
     moves from room to room. The purpose of a
     follower is to allow the player to follow an
     actor as it leaves a room by typing a "follow"
     command. Each actor that is to be followed must
     have its own follower object. The follower object
     should define all of the same vocabulary words
     (nouns and adjectives) as the actual actor to
     which it refers. The follower must also define
     the myactor property to be the Actor object that
     the follower follows. The follower will always
     stay one room behind the character it follows; no
     commands are effective with a follower except for
     "follow."

     The follower class's actorAction method executes
     an exit statement. In addition, the follower
     class uses dobjGen and iobjGen to provide
     sensible responses to most verbs.

     --------------------------------------------------
     *>basicMe

     basicMe: Actor. A default implementation of the
     Me object, which is the player character. adv.t
     defines basicMe instead of Me to allow your game
     to override parts of the default implementation
     while still using the rest, and without changing
     adv.t itself. To use basicMe unchanged as your
     player character, include this in your game: "Me:
     basicMe;".

     The basicMe object defines all of the methods and
     properties required for an actor, with
     appropriate values for the player character. The
     nouns "me" and "myself" are defined ("I" is not
     defined, because it conflicts with the
     "inventory" command's minimal abbreviation of "i"
     in certain circumstances, and is generally not
     compatible with the syntax of most player
     commands anyway). The sdesc is "you"; the thedesc
     and adesc are "yourself," which is appropriate
     for most contexts. The maxbulk and maxweight
     properties are set to 10 each; a more
     sophisticated Me might include the player's state
     of health in determining the maxweight and
     maxbulk properties.

     --------------------------------------------------
     *>decoration

     decoration: fixeditem. An item that doesn't have
     any function in the game, apart from having been
     mentioned in the room description. These items
     are immovable and can't be manipulated in any
     way, but can be referred to and inspected.
     Liberal use of decoration items can improve a
     game's playability by helping the parser
     recognize all the words the game uses in its
     descriptions of rooms.

     --------------------------------------------------
     *>buttonitem

     buttonitem: fixeditem. A button (the type you
     push). The individual button's action method
     doPush(actor), which must be specified in the
     button, carries out the function of the button.
     Note that all buttons have the noun "button"
     defined.

     --------------------------------------------------
     *>clothingItem

     clothingItem: item. Something that can be worn.
     By default, the only thing that happens when the
     item is worn is that its isworn property is set
     to true. If you want more to happen, override the
     doWear(actor) property. Note that, when a
     clothingItem is being worn, certain operations
     will cause it to be removed (for example,
     dropping it causes it to be removed). If you want
     something else to happen, override the checkDrop
     method; if you want to disallow such actions
     while the object is worn, use an exit statement
     in the checkDrop method.

     --------------------------------------------------
     *>obstacle

     obstacle: object. An obstacle is used in place of
     a room for a direction property. The destination
     property specifies the room that is reached if
     the obstacle is successfully negotiated; when the
     obstacle is not successfully negotiated,
     destination should display an appropriate message
     and return nil.

     --------------------------------------------------
     *>doorway

     doorway: fixeditem, obstacle. A doorway is an
     obstacle that impedes progress when it is closed.
     When the door is open (isopen is true), the user
     ends up in the room specified in the doordest
     property upon going through the door. Since a
     doorway is an obstacle, use the door object for a
     direction property of the room containing the
     door.

     If noAutoOpen is not set to true, the door will
     automatically be opened when the player tries to
     walk through the door, unless the door is locked
     (islocked = true). If the door is locked, it can
     be unlocked simply by typing "unlock door",
     unless the mykey property is set, in which case
     the object specified in mykey must be used to
     unlock the door. Note that the door can only be
     relocked by the player under the circumstances
     that allow unlocking, plus the property
     islockable must be set to true. By default, the
     door is closed; set isopen to true if the door is
     to start out open (and be sure to open the other
     side as well).

     otherside specifies the corresponding doorway
     object in the destination room (doordest), if
     any. If otherside is specified, its isopen and
     islocked properties will be kept in sync
     automatically.

     --------------------------------------------------
     *>lockableDoorway

     lockableDoorway: doorway. This is just a normal
     doorway with the islockable and islocked
     properties set to true. Fill in the other
     properties (otherside and doordest) as usual. If
     the door has a key, set property mykey to the key
     object.

     --------------------------------------------------
     *>vehicle

     vehicle: item, nestedroom. This is an object that
     an actor can board. An actor cannot go anywhere
     while on board a vehicle (except where the
     vehicle goes); the actor must get out first.

     --------------------------------------------------
     *>surface

     surface: item. Objects can be placed on a
     surface. Apart from using the preposition "on"
     rather than "in" to refer to objects contained by
     the object, a surface is identical to a
     container. Note: an object cannot be both a
     surface and a container, because there is no
     distinction between the two internally.

     --------------------------------------------------
     *>container

     container: item. This object can contain other
     objects. The iscontainer property is set to true.
     The default ldesc displays a list of the objects
     inside the container, if any. The maxbulk
     property specifies the maximum amount of bulk the
     container can contain.

     --------------------------------------------------
     *>openable

     openable: container. A container that can be
     opened and closed. The isopenable property is set
     to true. The default ldesc displays the contents
     of the container if the container is open,
     otherwise a message saying that the object is
     closed.

     --------------------------------------------------
     *>qcontainer

     qcontainer: container. A "quiet" container: its
     contents are not listed when it shows up in a
     room description or inventory list. The
     isqcontainer property is set to true.

     --------------------------------------------------
     *>lockable

     lockable: openable. A container that can be
     locked and unlocked. The islocked property
     specifies whether the object can be opened or
     not. The object can be locked and unlocked
     without the need for any other object; if you
     want a key to be involved, use a keyedLockable.

     --------------------------------------------------
     *>keyedLockable

     keyedLockable: lockable. This subclass of
     lockable allows you to create an object that can
     only be locked and unlocked with a corresponding
     key. Set the property mykey to the keyItem object
     that can lock and unlock the object.

     --------------------------------------------------
     *>keyItem

     keyItem: item. This is an object that can be used
     as a key for a keyedLockable or lockableDoorway
     object. It otherwise behaves as an ordinary item.

     --------------------------------------------------
     *>seethruItem

     seethruItem:item. This is a class for objects
     that the player can look through, and is intended
     for items such as windows or magnifying glasses.
     If the player looks through the object (with a
     command such as "look through the window"), the
     object calls its thrudesc method to display an
     appropriate description of what the player sees.
     You should customize this method to display an
     appropriate message for each seethruItem you
     create. The default method displays "You can't
     see much through the window," which obviously
     won't always be what you want.

     Note that seethruItem is not the same as the
     transparentItem below. The class transparentItem
     is for objects whose contents are visible,
     whereas seethruItem is for objects that the
     player can look through. Use seethruItem for
     windows, binoculars, magnifying glasses, and
     other non-containers. Use transparentItem for
     glass bottles and other transparent containers.

     --------------------------------------------------
     *>transparentItem

     transparentItem: item. An object whose contents
     are visible, even when the object is closed.
     Whether the contents are reachable is decided in
     the normal fashion. This class is useful for
     items such as glass bottles, whose contents can
     be seen when the bottle is closed but cannot be
     reached.

     --------------------------------------------------
     *>basicNumObj

     basicNumObj: object. This object provides a
     default implementation for numObj. To use this
     default unchanged in your game, include in your
     game this line: "numObj: basicNumObj".

     --------------------------------------------------
     *>basicStrObj

     basicStrObj: object. This object provides a
     default implementation for strObj. To use this
     default unchanged in your game, include in your
     game this line: "strObj: basicStrObj".

     --------------------------------------------------
     *>deepverb

     deepverb: object. A "verb object" that is
     referenced by the parser when the player uses an
     associated vocabulary word. A deepverb contains
     both the vocabulary of the verb and a description
     of available syntax. The verb property lists the
     verb vocabulary words; one word (such as 'take')
     or a pair (such as 'pick up') can be used. In the
     latter case, the second word must be a
     preposition, and may move to the end of the
     sentence in a player's command, as in "pick it
     up." The action(actor) method specifies what
     happens when the verb is used without any
     objects; its absence specifies that the verb
     cannot be used without an object. The doAction
     specifies the root of the message names (in
     single quotes) sent to the direct object when the
     verb is used with a direct object; its absence
     means that a single object is not allowed.
     Likewise, the ioAction(preposition) specifies the
     root of the message name sent to the direct and
     indirect objects when the verb is used with both
     a direct and indirect object; its absence means
     that this syntax is illegal. Several ioAction
     properties may be present: one for each
     preposition that can be used with an indirect
     object with the verb.

     The validDo(actor, object, seqno) method returns
     true if the indicated object is valid as a direct
     object for this actor. The validIo(actor, object,
     seqno) method does likewise for indirect objects.
     The seqno parameter is a "sequence number,"
     starting with 1 for the first object tried for a
     given verb, 2 for the second, and so forth; this
     parameter is normally ignored, but can be used
     for some special purposes. For example, askVerb
     does not distinguish between objects matching
     vocabulary words, and therefore accepts only the
     first from a set of ambiguous objects. These
     methods do not normally need to be changed; by
     default, they return true if the object is
     accessible to the actor.

     The doDefault(actor, prep, indirectObject) and
     ioDefault(actor, prep) methods return a list of
     the default direct and indirect objects,
     respectively. These lists are used for
     determining which objects are meant by "all" and
     which should be used when the player command is
     missing an object. These normally return a list
     of all objects that are applicable to the current
     command.

     All of the system verbs in adv.t that use the
     abort statement have been designed in such a
     fashion that it's quite easy to augment their
     behavior with the modify statement. All of the
     processing other than the abort is not in the
     doVerb (or action) method but is elsewhere. For
     example, the action method in saveVerb looks like
     this:

       action( actor ) =
       {
         self.saveGame( actor );
         abort;
       }

     The saveGame method in saveVerb performs all of
     the processing related to the actual save
     function itself. The benefit of this design is
     that you can modify the saveGame method, and
     inherit the standard behavior, without having to
     worry about an abort statement interfering with
     the order of operations. For example:

       modify restoreVerb
         restoreGame( actor ) =
         {
           // restore the game, and check for success
           if ( inherited.restoreGame( actor ) )
           {
             // re-randomize the puzzle
             "The carnival hawker flashes a mischievous
              smile at you.  \"There's no use trying to
              guess the answer,\" he says.  \"I changed
              around the shells while you were busy
              restoring!\"";
             puzzle.answer := rand( 100 );
           }
         }
       ;

     --------------------------------------------------
     *>Prep

     Prep: object. A preposition. The preposition
     property specifies the vocabulary word.

------------------------------------------------------------
Verbs in the Adventure Definitions File

     In the list below, the alternative vocabulary
     words for the verb are listed with slashes (/)
     between them; the alternate syntaxes are listed
     with commas between. When the verb takes objects,
     the root of the message the parser generates in
     shown in parentheses following the syntax
     description; these are prefaced with do, verDo,
     io, and verIo, as appropriate. See the section on
     the parser in chapter 4 for details.

          againVerb: again/g

          askVerb: ask direct-object about
          indirect-object (AskAbout)

          attachVerb: attach direct-object to
          indirect-object (AttachTo)

          attackVerb: attack/kill/hit
          direct-object with indirect-object
          (AttackWith)

          boardVerb: get in/get into/board
          direct-object (Board)

          centerVerb: center direct-object
          (Center)

          cleanVerb: clean direct-object (Clean),
          clean direct-object with
          indirect-object (CleanWith)

          climbVerb: climb direct-object (Climb)

          closeVerb: close direct-object (Close)

          digVerb: dig/dig in direct-object with
          indirect-object (DigWith)

          drinkVerb: drink direct-object (Drink)

          dropVerb: drop/put down direct-object
          (Drop), drop/put down direct-object on
          indirect-object (PutOn)

          dVerb: down/d

          eatVerb: eat direct-object (Eat)

          eVerb: east/e

          fastenVerb: fasten direct-object
          (Fasten)

          getOutVerb: get out/get out of/get
          off/get off of direct-object (Unboard)

          giveVerb: give/offer direct-object to
          indirect-object (GiveTo)

          helloVerb: hello/hi/greetings

          inspectVerb: inspect/examine/look at/x
          direct-object (Inspect)

          inVerb: in/go in/enter

          iVerb: inventory/i

          jumpVerb: jump, jump direct-object
          (Jump)

          lieVerb: lie/lie on/lie in/lie down/lie
          down on/lie down in direct-object
          (Lieon)

          lockVerb: lock direct-object (Lock),
          lock direct-object with indirect-object
          (LockWith)

          lookBehindVerb: look behind
          direct-object (LookBehind)

          lookInVerb: look in direct-object
          (Lookin)

          lookThruVerb: look through/look thru
          direct-object (Lookthru)

          lookUnderVerb: look under/look beneath
          direct-object (LookUnder)

          lookVerb: l/look/look around

          moveNVerb: move north/move n/push
          north/push n direct-object (MoveN)
          Note: moveSVerb, moveEVerb, moveWVerb,
          moveNEVerb, moveNWVerb, moveSEVerb, and
          moveSWVerb are defined similarly.

          moveVerb: move direct-object (Move),
          move direct-object to indirect-object
          (MoveTo), move direct-object with
          indirect-object (MoveWith)

          nVerb: north/n

          neVerb: northeast/ne

          nwVerb: northwest/nw

          openVerb: open direct-object (Open)

          outVerb: out/go out/exit

          plugVerb: plug direct-object into
          indirect-object (PlugIn)

          pokeVerb: poke direct-object (Poke)

          pullVerb: pull direct-object (Pull)

          pushVerb: push direct-object (Push)

          putVerb: put/place direct-object in
          indirect-object (PutIn), put/place
          direct-object on indirect-object (PutOn)

          quitVerb: quit

          readVerb: read direct-object (Read)

          removeVerb: take off direct-object
          (Unwear)

          restartVerb: restart

          restoreVerb: restore direct-object
          (Restore)

          standOnVerb: stand on indirect-object
          (Standon)

          standVerb: stand/stand up/get up

          saveVerb: save direct-object (Save)

          sayVerb: say direct-object (Say)

          scoreVerb: score/status

          scriptVerb: script direct-object
          (Script)

          screwVerb: screw direct-object (Screw),
          screw direct-object with
          indirect-object (ScrewWith)

          seVerb: southeast/se

          showVerb: show direct-object to
          indirect-object (ShowTo)

          sitVerb: sit on/sit in/sit/sit down/sit
          down in/sit down on direct-object
          (Siton)

          sleepVerb: sleep

          sVerb: south/s

          swVerb: southwest/sw

          takeVerb: take/pick up/get/remove
          direct-object (Take), take/pick
          up/get/remove direct-object out of
          indirect-object (TakeOut), take/pick
          up/get/remove direct-object off/off of
          indirect-object (TakeOff)

          tellVerb: tell direct-object about
          indirect-object (TellAbout)

          terseVerb: terse

          throwVerb: throw/toss direct-object at
          indirect-object (ThrowAt)

          touchVerb: touch direct-object (Touch)

          turnOffVerb: turn off/deactivate/switch
          off direct-object (Turnoff)

          turnOnVerb: activate/turn on/switch on
          direct-object (Turnon)

          turnVerb: turn direct-object (Turn),
          turn direct-object with indirect-object
          (TurnWith), turn direct-object to
          indirect-object (TurnTo)

          typeVerb: type direct-object on
          indirect-object (TypeOn)

          undoVerb: undo

          unfastenVerb: unfasten/unbuckle
          direct-object (Unfasten)

          unlockVerb: unlock direct-object
          (Unlock), unlock direct-object with
          indirect-object (UnlockWith)

          unplugVerb: unplug direct-object
          (Unplug), unplug direct-object from
          indirect-object (UnplugFrom)

          unscrewVerb: unscrew direct-object
          (Unscrew), unscrew direct-object with
          indirect-object (UnscrewWith)

          unscriptVerb: unscript

          uVerb: up/u

          verboseVerb: verbose

          versionVerb: version

          waitVerb: wait/z

          wearVerb: wear direct-object (Wear)

          wVerb: west/w

          yellVerb: yell

------------------------------------------------------------
Prepositions in the Adventure Definitions

     Each preposition is shown with its object, and
     the list of vocabulary words associated with the
     object, with slashes between equivalent words.
     Note that the two-word prepositions, such as
     "down on," are actually written as one word, such
     as "downon," in the definition file, because the
     parser collapses two-word prepositions into a
     single word by removing the intervening space.

          aboutPrep: about

          aroundPrep: around

          atPrep: at

          behindPrep: behind

          betweenPrep: between/in between

          dirPrep:
          north/south/east/west/up/down/northe/ne/
          northw/nw/southe/se/southw/sw

          inPrep: in/into/in to/down in

          fromPrep: from

          offPrep: off/off of

          onPrep: on/onto/on to/down on/upon

          outPrep: out/out of

          overPrep: over

          thruPrep: through/thru

          toPrep: to

          withPrep: with

I hate definitions.
BENJAMIN DISRAELI, Vivian Grey (1826)

------------------------------------------------------------
