This file contains a list of changes that have been made to TADS
since the initial 2.0 release, up through version 2.1.0.  Most
of the changes are fixes to bugs, so they don't change the documented
behavior, but a few, as explained below, add new functionality to
TADS.  Releases are listed with the most recent release first; each
release incorporates all new features and bug fixes of each prior
release unless otherwise stated.

Note:  this file stops at version 2.1.0.  Please refer to the
release notes files included with more recent releases for information
on versions after 2.1.0.


2.1.0  04/07/93  new features, enhancements, bug fixes

 - TADS finally has a way of changing objects and functions in
   adv.t without changing adv.t itself.  The new mechanism allows
   you to entirely replace a previously defined object or function
   with one of your own, and also lets you modify a previously
   defined object by adding or overriding properties.  Two new
   keywords have been added to the language to support these new
   features:  "replace" and "modify".

   Using these new features, it should be possible to make most
   of the changes to adv.t that are necessary while writing a game
   without actually changing the file adv.t itself.  This should
   make version upgrades much easier to apply, since you shouldn't
   need to reconcile any changes you have made to adv.t with the
   new version.

   High Energy Software requests that you advise us of any changes
   to adv.t that would facilitate modification and replacement of
   the objects defined in adv.t.  Examples would include common
   code fragments that could be moved into a function for easy
   replacement, and single deepverb objects that should be split
   into multiple objects.

   You can replace a previously-defined function with a new
   definition simply by prefacing your new definition with the
   keyword "replace"; for example, to replace adv.t's new
   scoreStatus function, you could do this:

      #include <adv.t>

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

   You can do the same thing with objects.  For example, to replace
   a verb in adv.t, you could do something like this:

      #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 of
   the object, 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, which retains its original definition
   (including inheritance information, vocabulary, and properties), and
   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; for example:

      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.

   In a method that you redefine with "modify", you can use "pass"
   or "inherited" to refer to the REPLACED method.  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, except indirectly through the
   new replacement object.  Here's an example of "modify" and "pass":

       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

   However, you can override this behavior for a property by
   using the replace keyword on the property.  In the example
   above, we could do this instead:

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

   This would result in the following 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.

 - It is now possible for the player to customize the colors used
   by the runtime.  A small new program, TRCOLOR, is provided to
   set up the runtime screen colors.  The program is self-explanatory;
   simply type TRCOLOR at the DOS prompt to invoke it.  Once you've
   selected your color scheme, TRCOLOR will create a small file
   called TRCOLOR.DAT (in the current directory); the runtime will
   read this file in subsequent game sessions.

   Note that you can use multiple TRCOLOR.DAT files, in much the same
   way you can use two CONFIG.TC files.  The runtime looks first for
   TRCOLOR.DAT in the current directory; if no such file is found, the
   runtime will then look in the directory where TR.EXE resides.  So,
   you can set up separate color schemes for each game you're playing,
   and have a default color scheme for games with no specific color
   scheme of their own.

 - The user interface of the MAKETRX program has been improved.
   For compatibility with existing makefiles, the old command line
   syntax is still allowed; however, you can now omit most of the
   arguments, and MAKETRX will use convenient new defaults.

   First, you can now omit the extensions on all the arguments.
   The extension assumed for the TR.EXE program is .EXE; for the
   game file it is .GAM; and for the executable output file it is .EXE.

   Second, you can now omit everything except the name of the game
   file.  If you omit the name of the TR.EXE program, MAKETRX attempts
   to find TR.EXE in the same directory as MAKETRX.EXE; so, if you
   simply keep all of your TADS executables in a single directory,
   you won't need to specify the location of TR.EXE when running MAKETRX.
   If you omit the name of the destination file, MAKETRX will use the
   same name as the game file, with the extension replaced by .EXE.

   The command line arguments to MAKETRX that are now understood are:

      maketrx gamefile
        Converts gamefile.gam into gamefile.exe, using TR.EXE from the
        same directory as MAKETRX.EXE.

      maketrx gamefile output
        Converts gamefile.gam into output.exe, using TR.EXE from the
        same directory as MAKETRX.EXE.

      maketrx \tads2\tr.exe gamefile output
        Converts gamefile.gam into output.exe, using \tads2\tr.exe.


 - The dobjGen and iobjGen mechanism has been changed slightly.
   In the original implementation, you could prevent the system
   from calling dobjGen/iobjGen by defining an appropriate verXoVerb
   property in the actual object, but NOT in a superclass.  This
   made it impossible to define a class that had exceptions to
   dobjGen/iobjGen except by explicitly testing for those verbs
   in the xobjGen routines.

   The change is that the system will now skip calling xobjGen
   if an appropriate verXoVerb/xoVerb property is defined in such
   a way that it "overrides" xobjGen for the object.  Here's an
   example:

      class cursedItem: item
          dobjGen(a, v, i, p) =
          {
              "As you touch <<self.thedesc>>, a bolt of lightning
              leaps from the object and sends you reeling away!";
          }
          iobjGen(a, v, d, p) = { self.dobjGen(a, v, d, p); }
          verDoInspect(actor) = { pass verDoInspect; }  // allow 'inspect'
      ;

   The change means that the presence of verDoInspect in the *class*
   prevents the system from calling dobjGen when the verb is "inspect",
   even for subclasses.  With the old system, since the subclass objects
   themselves didn't define verDoInspect, dobjGen would be called even
   though the verDoInspect logically overrides the dobjGen.

 - The restore() intrinsic has been extended to allow your game
   program to explicitly restore the saved game specified by the
   user as a parameter to your stand-alone game program.  This is
   currently only useful on the Macintosh, but the inclusion of
   code to test for this case will make your game work better on
   the Macintosh (and possibly other platforms in the future).

   The new functionality is invoked by calling restore(nil).  If
   a saved game was specified by the user at start-up time, the
   game will be restored, and nil will be returned.  If no file
   was specified, or an error occurred restoring the game, the
   function returns true.  To use this new behavior, we recommend
   placing the following code in your init function, before your
   introductory messages and other startup code:

      // check for a file to restore specified as a startup parameter
      if (restore(nil) = nil)
      {
          "\b[Restoring saved game]\b";
          scoreStatus(global.score, global.turnsofar);
          Me.location.lookAround(true);
          return;
      }

   Note that the run-time will still automatically restore the
   game provided as a parameter (on the Macintosh) after init returns
   if you do NOT include this code in init.  The reason for including
   this code is that it provides your game with greater control over
   the sequence of events during startup.  If you allow the run-time
   to perform the restore automatically, your entire init function will
   be executed; this may be undesirable, because it forces the user to
   view the entire introductory text even though they'll immediately
   restore a game after reading it.  If you place the restore(nil) call
   before your introductory text, the user will be spared the long text
   display; however, you'll still have complete control over any text
   that you want the user to see even when restoring a game, such as
   your copyright message.

 - New built-in function:  objwords(num), which provides a list of
   the actual words the user typed to refer to an object used in
   the current command.  The argument (num) is a number specifying
   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.  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.

   Examples:

      >take all
      objwords(1) -> ['all']
      objwords(2) -> []

      >put all in red box
      objwords(1) -> ['all']
      objwords(2) -> ['red' 'box']

      >put blue box in it
      objwords(1) -> ['blue' 'box']
      objwords(2) -> ['it']

      >put blue folder and green book in red box
      blue folder:
      objwords(1) -> ['blue' 'folder']
      objwords(2) -> ['red' 'box']
      green book:
      objwords(1) -> ['green' 'book']
      objwords(2) -> ['red' 'box']

   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.

 - The setit() function now takes nil as a parameter; this prevents
   using "it" in a command until another object has been referenced.
   nil can be used for "him" and "her" as well, as described below.

 - Enhancements to the setit() built-in function:  you can now directly
   set the 'him', 'her', and 'them' values using the setit() function.

      - To set 'them', simply call setit() with a list value:
        setit([redBook blueBook boots]);

      - To set 'him', add a second argument value of 1 to the call:
        setit(joe, 1);

      - To set 'her', add a second argument value of 2:
        setit(harriet, 2);

 - The restart() built-in function now takes an optional set of
   arguments:  a pointer to a function, and a parameter value for
   the function (if one is provided, the other is also required, but
   both can be omitted).  If they're provided, TADS calls the function
   with the provided parameter value *after* resetting the game, and
   before running the init() function.  This allows you make the game
   start slightly differently after a restart than on the initial startup.
   adv.t uses this feature to call the function initRestart, with the
   parameter value global.initRestartParam, upon restart.  The initRestart
   function defined in adv.t simply sets the flag global.restarting to
   true.  Your game can test global.restarting (in the init function or
   elsewhere) to determine whether the game has been restarted, or is
   being run for the first time.  You can also replace initRestart()
   with your own function if you wish to do something more complicated;
   in this case, if you wish to pass information to the function, you
   can simply store it in global.initRestartParam, and it will be passed
   to the function automatically by adv.t upon restarting.

 - New built-in function:  inputkey() reads a single keystroke from
   the keyboard.  The function takes no arguments.  When called,
   inputkey() will flush any pending output text, then pause the game
   until the player hits a key.  It then returns a string containing
   the single key hit by the player.  Note that the function does NOT
   provide a portable mechanism for reading non-standardized keys;
   special keys such as cursor arrow keys and function keys will return
   a string specific to the type of computer being used.  Your game
   will not be portable if you make use of any non-standardized key
   values returned by inputkey().  To ensure portability, use inputkey()
   strictly with standard ASCII keys (alphabetic, numeric, and punctuation
   keys).  It is also fully portable if you simply ignore the return value
   and use the function only to pause and wait for a key.

 - Several changes have been made for better national language
   support.  First, the DOS version now allows 8-bit characters
   (characters in the extended character set, with ASCII code
   from 128 to 255) in text displayed by the game, vocabulary
   words, and player commands.  Characters in the extended character
   set are always considered to be alphabetic, so these characters
   can only be used in input as parts of words (hence, symbols
   from the extended character set that appear as punctuation
   marks can't be used as punctuation in player commands).

 - The debugger now has "More" mode in the command window.  When
   a single display won't fit in the window (for example, a long
   stack traceback), the debugger will prompt with "[More]" each
   time the window fills up.  Hit the space bar to scroll by a
   whole screen, or the Return/Enter key to scroll by a single line.

 - The debugger has a new "call history" feature.  This feature
   captures information about every function and method call,
   including argument lists and return values (if any), and saves
   the information for future inspection.  Several new commands
   have been added to the debugger to support call history:

       c+    Enables call history, and clears previous history.
       c-    Disables call history capture.
       cc    Clears all current history information.
       c     Displays current history information.

   The reason that call history can be enabled and disabled is
   that enabling the feature slows down the debugger substantially,
   because it must store information every time a method is called.

   This feature could be useful if you're trying to figure out the
   sequence of method calls that occurs during the execution of
   a command.  At the debugger command line, type c+ to turn on
   call history; then, type g to resume your game.  Type the command
   that you want to debug, then type DEBUG at the game prompt to
   return to the debugger.  Now type c- to turn off call history,
   and c to display the history information from the command you
   just executed.  This will allow you to see every method and
   function that was called by TADS, as well as all the methods
   and functions called by your code.

   The call history display will have each function/method call indented
   by a number of spaces indicating the nesting depth; any method/function
   called by TADS will be at the left margin, any methods/functions called
   by the first one will be indented one space, any methods/functions
   called by those will be indented two spaces, and so on.  The return
   values will be indented by the same number of spaces as the function
   itself was.  Note that a return value may be separated from its
   entrypoint by several lines, because calls made by the function
   will appear between the function entry and the return value.

 - Another new national language feature is the addition of
   several new parser-called user functions that allow better
   user control over the generation of parser messages.  The
   new functions have been added because some people have found
   that the parseError() function is not sufficiently flexible
   for some situations, because it only allows changing the text
   of messages on a piecewise basis; when complete messages need
   to be built out of several pieces, it's necessary to be able to
   take over the entire process of building the message.  The new
   functions allow full control of the generation of certain messages.

   parseAskobj(v, ...):  This function is called when the parser
   needs to ask the player for a direct or indirect object to complete
   the command.  For example, if the player just types "take", and
   several objects are present that could be taken, the parser must
   ask the player what to take.  If a direct object is being requested,
   the function will have only one argument (the verb).  If an indirect
   object is being requested, the function will have *two* arguments;
   the second argument will be the preposition.  Note that the preposition
   can be nil, in which case you can assume that "to" is to be used.
   The implementation below emulates the default behavior.

       parseAskobj: function(v, ...)
       {
           "What do you want to <<v.sdesc>>";
           if (argcount = 2)
           {
               local p := getarg(2);
               " it << p ? p.sdesc : "to" >>";
           }
           "?";
       }

   parseDisambig(string, list):  This function is called by the
   parser when objects need to be disambiguated.  If this optional
   function is provided, it is called with the string that the player
   typed which is in need of disambiguation, and a list of the objects
   that match the string.  The implementation below emulates the
   parser's default behavior.

       parseDisambig: function(str, lst)
       {
           local i, tot, cnt;

           "Which << str >> do you mean, ";
           for (i := 1, cnt := length(lst) ; i <= cnt ; ++i)
           {
               lst[i].thedesc;
               if (i < cnt) ", ";
               if (i+1 = cnt) "or ";
           }
           "?";
       }

   parseError2(v, d, p, i):  The parser calls this function to
   generate the default error message stating that the verb attempted
   isn't accepted by the objects involved; this happens when either
   the indirect object doesn't define an appropriate verIoXxxx method,
   or the direct object doesn't define an appropriate verDoXxxx method.
   Only one of 'd' (direct object) or 'i' (indirect object) will be
   non-nil.  If 'i' is nil, so will 'p' (preposition).  The verb, 'v',
   will never be nil.  Note that 'p' can be nil even when 'i' is not,
   in which case you should assume that the preposition is "to".
   The implementation below behaves the same as the parser's default.

       parseError2: function(v, d, p, i)
       {
           "I don't know how to << v.sdesc >> ";
           if (d)
               "<< d.thedesc >>.";
           else
               "anything << p ? p.sdesc : "to" >> << i.thedesc >>.";
       }

   parseDefault(obj, prp):  This function is called when the parser
   is assuming a default object.  If a default direct object is being
   assumed, prp (the preposition) will be nil; otherwise, prp will have
   the object corresponding to the preposition preceding the indirect
   object.  The implementation below provides the default behavior.

       parseDefault: function(obj, prp)
       {
           "(";
           if (prp) "<< prp.sdesc>> ";
           obj.thedesc;
           ")";
       }

   Note that all three of these new functions are optional.  If any
   is omitted, the parser uses the default behavior, so existing games
   will run unchanged.  You can include any one without including the
   others; these new functions are all independent.  Note also that
   the default parser behavior continues to use parseError the same
   way it has since parseError was introduced; however, when these
   new functions are provided, the corresponding parseError calls will
   obviously no longer be made.

 - COMPATIBILITY NOTE:  By default, the .GAM files produced by
   the 2.1.0 compiler will NOT be compatible with previous
   versions of the runtime, due to several changes to the .GAM
   file format.  However, a new compiler option has been added
   that allows you to specify which .GAM file format to produce:

     -fv a   produces .GAM format compatible with 2.0.14 or earlier
     -fv b   produces game file format requiring 2.1.0 or later
     -fv *   (default) produces latest file format (currently b)

   If you want your game to be compatible with older versions of
   the runtime, use -fv a.  The 2.1.0 runtime is compatible with
   .GAM files produced by ANY version of the compiler; the runtime
   automatically detects which file format version it is reading.

   Note that using -fv a will prevent you from being able to call
   an external function from within the init function (see the bug
   fix described below).  In addition, even when using -fv a, since
   previous versions of the run-time did not provide the new built-in
   functions, your game will be incompatible with runtimes prior to
   2.1.0 -- regardless of whether you use -fv a or not -- if you
   use any new built-in functions.

   In the future, if there is another incompatible .GAM file format
   change, additional -fv options will be added to the new compiler.

 - One of the changes to the .GAM file format makes it much more
   compressible with archiving tools (such as ZIP).  Previous
   .GAM files typically compressed by only 10 to 20%; the files
   produced with file format B are generally compressible by 40
   to 50%.

 - runfuses and rundaemons had a bug that reset the run-time
   stack, causing problems if a nested method or function
   called these functions.  This has been corrected.

 - Subtracting one list from another didn't work as documented.
   This has been corrected.

 - In previous versions, external functions could not be called
   while the init function was running.  This was an unintentional
   side-effect of the way external functions were loaded, and the
   problem has been corrected.  External functions can now be called
   at any time.

 - A new warning has been added that can help you track down
   unterminated strings.  Whenever the compiler sees a line that
   begins with a semicolon or close brace (';' or '}') inside
   a string, it will issue a warning.  While this is just a guess
   that the string may be unterminated, it's often right, especially
   if you follow the general formatting style used by adv.t:  always
   end a function with a brace in the first column of a new line,
   and always end an object with a semicolon in the first column of
   a new line.

   Note that we strongly recommend that you follow this formatting
   style in your code, both for general readability and because it
   may enhance your code's compatibility with future High Energy
   Software products that use assumptions about formatting style
   that are similar to that used to generate the new unterminated
   string warning.

 - Several small enhancements and bug fixes have been made to
   adv.t:

      - A new property has been added to nestedroom objects:
        statusPrep, which displays "on" or "in" (or whatever),
        as appropriate, for messages such as "Spaceship, in chair".
        This defaults to "in" for nestedroom, and "on" for beditem.
        Other nestedroom objects you define may want to customize it.

      - There was a bug that allowed the player to throw a fixeditem
        that was (indirectly) being carried (for example, a fixeditem
        that is part of another object that can be carried) at something.
        This has been fixed.

      - The follower class did not 'exit' at the end of its actorAction.
        This has been fixed.

      - The follower class now makes use of iobjGen and dobjGen to respond
        with an appropriate message ("the actor is no longer here") to
        any command other than "follow".

      - The clothingItem class has been enhanced to allow "get out of"
        to be used to take off the item.

      - All of the verbs containing the word "look" now have synonyms
        with "l" as well:  l at, l on, l in, l under, l around, l thru,
        and so on.

      - A bug has been fixed that allowed the command "take all from foo"
        to remove the contents of "foo" even if it was closed.  The
        change is to the doDefault method in takeVerb.

      - The vehicle class has been adjusted so that the player can't
        take a vehicle or otherwise manipulate it while the player is
        currently in the vehicle -- this is important for things such
        as rubber rafts which can be used both as vehicles and ordinary
        carryable items.  dobjGen and iobjGen are used to accomplish
        this; the only allowed verbs on a vehicle while it's occupied
        by the player are inspectVerb, getOutVerb, outVerb, and putVerb
        with the vehicle as an indirect object (allowing objects to be
        put into the vehicle while it's occupied).  If you want to allow
        additional verbs in a particular vehicle, override dobjGen or
        iobjGen as appropriate, and simply return if the verb matches
        any of the verbs you wish to add:

            dobjGen(a, v, i, p) =
            {
                // allow "launch" and "land" while in the magic raft
                if (v <> launchVerb and v <> landVerb)
                    pass dobjGen;
            }

 - The compiler now detects usage (both explicit and implicit)
   of "self" in functions.  This has always been illegal, but
   in previous versions the compiler did not notice; any uses
   of "self" in functions resulted in a run-time error (often
   a mysterious error, such as a cache manager severe error and
   abnormal termination due to a reference to a non-existent
   object).  This was especially troublesome when a property
   name was used as a local variable when the local variable
   wasn't declared; since the v2 compiler assumes "self" in
   references to properties that don't include an object
   qualification, the compiler would silently turn an undefined
   variable usage into a reference to "self".  The compiler will
   now flag a new error in these cases:  TADS-344, "self" is not
   valid in this context.  If you get this error without an
   explicit reference to "self", you probably have an implicit
   reference, which means you probably are using an undeclared
   local variable.  Adding a "local" declaration for the variable
   should clear the error.

 - "Her" was not set properly, even when the isHer property was
   set to true for an object.  This has been corrected.

 - A new compiler option has been added:  -v, for "verbosity".
   This option lets you tell the compiler how much warning
   information you'd like to see.  By default, the verbosity
   level is 0 (zero), which causes certain warnings to be
   suppressed.  You can specify -v followed by a number to
   set a higher verbosity level.  So far, only the messages
   listed below are affected by -v, but the verbosity level
   for certain warnings may be changed in the future (and new
   warnings may be added at high verbosity levels).  Currently,
   the general meaning of the verbosity levels is:  0, report
   only serious errors and warnings; 1, report suspicious
   situations that may or may not indicate errors; 2, report
   all information, including general warning information that
   usually does not indicate any actual problem.

 - A new compiler option has been added:  -e file, for "error logging".
   This option captures all messages generated by the the compiler to
   the specified file.  Messages are also displayed interactively as
   normal.  WARNING: if the file specified with -e already exists, it
   is overwritten with the error information.

 - The compiler warning messages about "object not found" for the
   optional objects (preinit, preparse, parseError, commandPrompt)
   are now suppressed if the verbosity level is less than 2.
   If you specify -v2 (or -v with a higher number than 2), these
   messages will be displayed for all optional objects not found;
   otherwise, no warnings will be generated.

 - The compiler warning messages about "#include file already included"
   are now suppressed if the verbosity level is less than 1.


2.0.14  02/10/93  bug fixes, minor enhancements

 - A new backslash code has been added to the output formatter that
   causes the formatter to pass the next two bytes unchanged.
   This has been added primarily for 16-bit character sets, to allow
   two-byte characters that contain a backslash ('\', ASCII 92) as
   one of their two bytes to be passed through the formatter without
   interpretation as part of a backslash sequence.  The new code
   is "\-"; the two bytes following the \- are not interpreted by
   the formatter.  For example:

      "\-\bTesting...\nDone!";

   displays:

      \bTesting...
      Done!

   Note that the "\b" sequence is not interpreted as a blank line,
   as it would normally be, but is simply displayed, because the \-
   suppresses any interpration of the next two bytes.  The "\n",
   however, is interpreted as a newline as normal, since it is not
   quoted by a \- sequence.

 - You can now break out of an infinite loop in your game while
   running under the debugger.  On DOS, if your game goes into a loop,
   hit the Control + Break keys - the loop should immediately be
   aborted and control returned to the debugger command line.
   The Control-Break sequence also works with the runtime; it
   causes control to be returned to the player command line.
   Note that the interrupted command is automatically undone, so
   the interrupt sequence will not leave the game in an inconsistent
   state.  Note also that only long loops can be interrupted; the
   system only checks for interruptions once every several hundred
   instructions for greater efficiency.

 - The debugger will now catch run-time errors, activating the
   debugger command line when an error occurs.  The source will
   be positioned at the location of the error, as though a breakpoint
   had been set there, and the error message will be displayed.  Local
   variables can be evaluated as normal to help determine the cause of
   the error.  When you resume execution (with Trace, Step, or Go),
   the current command will be aborted and control will return to the
   player command prompt.  Note that there's no way to "fix" the error
   once it's been caught, but you can at least see exactly where the
   error occurred and determine the conditions that caused it.  Note
   also that certain types of errors, such as memory management errors,
   will not invoke the debugger; only errors that are directly caused
   by an error in your game program will trap to the debugger.

 - The debugger incorrectly reported files as "not found" in the
   list of modules produced by the "fl" command.

 - The runtime was inconsistent in its calls to ioDefault.  Sometimes
   it called ioDefault(actor, prep), and other times it called it as
   ioDefault(actor, prep, dobj) - this made it impossible to define the
   method correctly if argument checking was enabled.  This has been
   corrected so that the dobj parameter is never included.  When attempting
   to identify a default indirect object, the parser never has a direct
   object available, since the indirect object must be resolved first;
   hence, the dobj that was occasionally being passed by the parser was
   always nil.  The unnecessary extra parameter has been removed:  the
   method is now always called as ioDefault(actor, prep).

 - The compiler generated incorrect code if the implicit "self" object
   was used to reference an object (that is, a property was used without
   an object specifier).  This resulted in "invalid opcode" errors at
   run-time.

 - The compiler sometimes complained that an included file couldn't
   be found, even when the included file was explicitly loaded as part
   of a precompiled header.  This happened any time the included file
   was not in the current directory at compilation time.

 - The compiler aborted with an "assertion failure" (which indicates
   that the compiler detected that it was in an internally inconsistent
   state, which should not be attainable under any circumstances) when
   the game program used a variable or expression on the right hand
   side of a dot operator and an object on the left hand side.

2.0.13  01/16/93  enhancements and bug fixes

 - If a vocabulary word contained a single quote character, the
   word could not be matched at run-time.

 - The run-time now allows all characters from the extended character
   set (ASCII codes above 127) to be displayed.  The run-time
   previously converted some extended characters into spaces.

 - The compiler did not allow a label to precede the first goto
   that referred to the label.

 - The debugger will now stop at a breakpoint in a method that
   is inherited by an object.  For example, if a breakpoint is
   set at room.lookAround, and startroom inherits lookAround
   from the class room, the debugger will stop at startroom.lookAround.
   It does not, however, stop on startroom.lookAround if startroom
   overrides lookAround.

 - The compiler will now flag an assignment to an undeclared
   symbol as an error.  It previously assumed that the symbol
   referred to a property, with an implicit object of "self".
   This was almost never desirable, because this type of
   assignment was most often coded in error -- the game author
   usually meant to code an assignment to a local variable, but
   either misspelled the variable name or forgot to declare it.

 - remfuse/remdaemon/unnotify no longer signal an error if the
   item being removed is not active.  Several game authors have
   indicated that this error is not helpful, since it makes it
   impossible to unconditionally remove a fuse -- you have to
   check to make sure it hasn't fired yet, which create a lot
   of unnecessary overhead.

 - NEW BUILT-IN FUNCTION:  intersect(list1, list2) returns the
   intersection of two lists; that is, it returns the list of
   all of the elements of the shorter of list1 and list2 that
   are also in the other list.  For example:

       [1 2 3 4 5] and [1 3 5 7]     ->    [1 3 5]
       ['abc' 'def'] and ['abc']     ->    ['abc']

   This new function can be used to improve performance in cases
   where (effectively) one list of items is being searched for
   the presence of another list of items.

 - NEW BUILT-IN FUNCTION:  runfuses() runs all expired fuses, if any.
   Returns true if any fuses expired, nil otherwise.  This function has
   been added to allow greater control over fuse processing.  Note that
   fuses set with both the setfuse() and notify() built-in functions
   are run.  This function takes no arguments.

 - NEW BUILT-IN FUNCTION:  rundaemons() runs all daemons.  This function
   runs daemons set with both the setdaemon() and notify() functions.
   rundaemons() takes no arguments and returns no value.

 - NEW BUILT-IN FUNCTION:  getfuse allows you to determine if a fuse
   (set with either setfuse or notify) is active.  It returns nil if
   the fuse is not active (i.e., it has been activated or removed),
   or the number of turns left.

   For setfuse() fuses:   getfuse(fuse_func, parameter)
   For notify() fuses:    getfuse(object, &message)

 - NEW BUILT-IN FUNCTION:  gettime() returns the current time.  The
   time is returned as a list of numeric values for easy processing by
   your game:

     [year month day weekday yearday hour minute second elapsed]

   The specific meanings of the values are:

         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.

 - NEW FEATURE:  The parser now calls an additional method in
   each direct and indirect object under certain circumstances.
   These new methods are called dobjGen (general use of an object
   as a direct object) and iobjGen.  These methods are called
   immediately prior to the appropriate verXo<Verb> method.  The
   sequence of calls depends on the command, as detailed below.

   The purpose of these methods is to allow you to define a catch-all
   routine that is called whenever an object is used in a command.
   It is sometimes desirable to be able to take some action whenever
   an object is mentioned, regardless of the verb involved.  For
   example, you might wish to define a cursed object that damages
   the player (such as by taking away a treasure) whenever the
   object is touched or manipulated in any way; these new methods
   make it possible to do this without having to override every
   possible verb handler.

   When a command is issued with an indirect object, the parser
   checks to see if the indirect object *directly* defines the
   io<Verb> method.  If not, the parser calls iobj.iobjGen(actor,
   verb, dobj, prep).  The parser then checks to see if the direct
   object *directly* defines the verDo<Verb> method.  If not, the
   parser calls dobj.dobjGen(actor, verb, iobj, prep).

   When a command is issued with only a direct object, the parser
   checks to see if the object *directly* defines the do<Verb> method.
   If not, the parser calls dobj.dobjGen(actor, verb, nil, nil).

   Note that an object "directly defines" a method if the method
   is defined in the object itself -- that is, the object does
   not merely inherit the method from its class.

   These new methods have no return value, and need not do anything.
   If they're undefined, the behavior is exactly the same as in
   previous versions.  So, existing games should continue to run
   unchanged.

   The reason that these methods are not called when the object
   directly defines an appropriate verb handler is that these
   methods are intended as a generic catch-all verb handler.
   When a specific handler for the current verb is already defined
   in the object, there should be no need to call the generic
   handler, since the object already defines specific behavior
   for that verb.


2.0.12  No such release (for internal release coordination)  bug fixes

 - Switch statements did not properly process all datatypes.

 - Assignment operations did not work correctly on list elements.
   For example:  l := [1 2 3]; l[2] += 5; did not properly leave
   the value of l as [1 7 3].

2.0.11  12/20/92  bug fixes

 - Goto statement labels were occasionally not released properly,
   resulting in spurious internal errors.

 - The 'continue' statement did not work as documented in 'for'
   statements.  Instead of jumping to the re-initializer expression,
   as it now does, the 'continue' incorrectly jumped to the condition.

 - The run-time is slightly smaller and faster.

 - The compiler did not process locals correctly when multiple disjoint
   blocks within a function or method had locals, and a later block had
   fewer locals than a previous block (yes, it's a somewhat obscure bug).

2.0.10  No such release (to synchronize with Mac release levels)

2.0.9  12/12/92  MS-DOS bug fixes and new features

 - The file selector dialog displayed incorrect information when a
   directory name that used all 11 characters was displayed.

 - The file selector now saves and restores all default directory and
   disk information.  The current disk, and the current directory on
   each disk, will be the same when TR is terminated as it was when
   TR was first run.  (This applies to TDB as well.  It's particularly
   important for TDB, because TDB needs to have the source files in
   the current working directory if an absolute path was not specified
   with -I.)

 - NEW FEATURE:  the new user function commandPrompt, if provided by
   the user's game program, will be called prior to each player command.
   If the commandPrompt function is provided, the default ">" prompt is
   NOT displayed; if no commandPrompt function is defined, the default ">"
   is used.  This should not affect existing games at all, unless a game
   defines its own function, method, or property called commandPrompt
   having a different purpose.  The commandPrompt function returns no
   value.  The function takes a single argument:  a number, indicating
   the type of command that the system is prompting for:

      0  - normal command
      1  - command after invalid word (allowing "oops" to be used)
      2  - disambiguation (after "which x do you mean..." question)
      3  - command after askdo (after "what do you want to x?")
      4  - command after askio

   Note that the default prompt in all cases is simply ">", and in all
   cases a new command can be entered.  However, when the type code is
   2, 3, or 4, a question has just been displayed by the run-time, so
   the commandPrompt function may want to suppress any pre-command
   information or prompt text.  Case 1 is generally identical to case 0.

   NOTE:  As with the other optional user-provided functions, the
   compiler will issue a warning message if commandPrompt is not
   defined by your game.  If your game doesn't provide a commandPrompt
   function, you can ignore this warning.  The warning is provided so
   that, if you intended to provide a commandPrompt function, you will
   be informed if the compiler didn't find it (which could mean that
   you forgot to define it, or misspelled it).

 - NEW FEATURE:  A new built-in function has been added, which allows
   the game program to suppress the display of text that would normally
   be displayed with double-quoted strings or the say() function.  The
   function is called outhide(), and it takes one argument:  a flag,
   indicating whether to suppress or re-enable the display of output.
   If the flag is true, output is suppressed; if the flag is nil, output
   is re-enabled.  Any output that occurs between outhide(true) and
   outhide(nil) is discarded.  However, outhide(nil) returns a value
   indicating whether any output did in fact occur since the call to
   outhide(true); this allows you to determine if any output would have
   occurred, even though the output is not seen by the player.  Note
   that this is effectively the same mechanism used by the player command
   parser for noun disambiguation using the verDoXxx and verIoXxx
   methods, as described in the TADS author's manual.  There is no way
   to recover the text that was suppressed by outhide(); the text is
   simply discarded, so the only information available is whether any
   text was generated.

2.0.8  12/03/92  (tc/tdb 2.0.7, tr 2.0.8) MS-DOS bug fixes and minor changes

 - The display initialization code was incorrectly attempting to clear
   a zero-line region of the display.  This resulted in extremely long
   delays on some computers (due to an incorrect BIOS call made by TADS).

 - NEW FEATURE:  When the keyword $$ABEND is typed as the entire command,
   the run-time immediately terminates and returns to DOS.  This emergency
   escape is provided so that TR can be terminated if the game somehow
   gets into a state where a more graceful exit is not possible.

 - The compiler did properly detect when an undefined object was used
   as the superclass of another object.  This generally resulted in
   unpredictable behavior during execution of preinit.

 - NEW FEATURE:  The parser now calls two new optional methods in the
   game program.  These new methods are intended to help speed up the
   identification of words when many objects have the same vocabulary.
   If the new methods are not present, behavior is the same as before,
   so existing games will run unchanged.  The new methods are validDoList
   and validIoList; they are associated with the "deepverb" object for
   the current command.  They are called with three parameters:  the actor,
   the prep, and the other object (indirect object for validDoList and
   direct object for validIoList; the value of the parameter will be nil
   if not applicable).  These methods are called prior to the disambiguation
   pass (using verDoXxx/verIoXxx), and prior to testing any objects with
   validDo/validIo.

   The return value of validDoList/validIoList is a list of all of the
   valid objects for the verb.  It is fine for these methods to return
   *too many* objects, since each object is still tested with validDo
   (or validIo) and the appropriate verDoXxx/verIoXxx methods.  Generally,
   these methods should simply return a list of all of the accessible
   objects in the actor's current location (or the actor's location's
   location), plus a list of all of the "floating" objects (which use
   methods for the location properties).

   An appropriate definition for validDoList in the deepverb object
   appears below:

      validDoList(actor, prep, iobj) =
      {
          local ret;
          local loc;

          loc := actor.location;
          while (loc.location) loc := loc.location;
          ret := visibleList(actor) + visibleList(loc)
                 + global.floatingList;
          return(ret);
      }

   This same definition (with the name changed) is appropriate
   for validIoList in deepverb.  This returns a list of all of the
   objects visible in the current location, plus the global list of
   all floating objects; this should be a superset of the list of
   accessible objects in most games.  The only verbs that normally
   requires a different value of validIoList/validDoList are verbs
   such as "ask" and "tell" that allow any object (whether accessible
   or not) to be used as indirect objects; for these, simply use this
   definition:

      validIoList = nil

   This takes advantage of the reverse compatibility feature:  when the
   method returns nil, all objects with matching vocabulary are used.

   The one additional game change required to take advantage of this
   new feature is that global.floatingList must be built during
   initialization.  This can be done easily with the following loop:

      global.floatingList := [];
      for (o := firstobj(floatingItem) ; o ; o := nextobj(o, floatingItem))
          global.floatingList += o;

   This should be placed in the preinit or init function.  Note that
   all objects which have location methods should be declared to be
   of class floatingItem:

     class floatingItem: object;

   This class doesn't do anything except serve as a flag that an
   object should be placed in the floatingList.

2.0.7  12/01/92  MS-DOS bug fix release

 - The run-time occasionally missed the \ in an escape sequence in
   output strings.

 - The run-time couldn't operate in 132 column mode.

 - The run-time abnormally terminated in the file selection dialog
   when the dialog box was exactly filled.

2.0.6  11/24/92  first general MS-DOS TADS 2.0 release