| 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 | |
Xet Storage Details
- Size:
- 50.2 kB
- Xet hash:
- f6853abd4dd0ef6820d2d040cd760d5f6d7edacdd416da2eb0f91e11f5955422
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.