home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-02-06 | 75.9 KB | 1,611 lines |
- TADS 2.1.2.2
- Unix Patchlevel 1
- 29-Jan-94
-
- Unix-specific changes applied to latest TADS source. Unix versions 2.1.0.0
- pl2 through pl4 were never released, so please read the notes for those as
- well -- this is the first release version that incorporates those changes.
-
- The window-resizing code seems to have been broken. Resizing the window
- sends the run-time into space. I'm looking into it. For now, don't change
- the window size while playing.
-
- adv.t and std.t have been updated to 2.1.2.2 as well.
-
-
- TADS 2.1.0.0
- Unix Patchlevel 4
- 16-Nov-93
-
- Changed the runtime and compiler so that the heapsize is always set to the
- maximum. An explicit -mh setting will override this. Note that you cannot
- make the heap bigger than 64K, since TADS has to run under DOS in real
- mode, where data structures can only be 64K or smaller.
-
-
- TADS 2.1.0.0
- Unix Patchlevel 3
- 25-Oct-93
-
- The adv.t and std.t files have been updated to 2.1.0.0. The ones in the
- earlier archives were actually the 2.0.13 ones. (Doh!)
-
- Now tadsr tries to save the game to file "fatal#####.sav" when it gets a
- fatal signal, where ##### is the process ID. Sometimes this file will be
- unuseable; other times it'll work fine -- it depends on where the signal
- occurs during execution.
-
- Two environment variables now affect the behavior of the runtime:
-
- TADSSAVE: directory for save files
- TADSGAME: directory for game files
-
- These pathnames will be prepended to any save or game file that does not
- already have a slash in it. For example, if
-
- TADSGAME=~you/games
-
- and you type
-
- tadsr foo
-
- the run-time will look for the file ~you/games/foo.gam. Note that if you
- want to prevent this, you have to explictly put a ./ in the filename, or
- unset the TADSGAME environment variable. The same goes for TADSSAVE.
-
- Since some windowing systems clear the screen when the end-of-visual
- terminal code is sent out, tadsr now waits for a keypress before it
- terminates. There is no way to disable this -- the run-time now ignores
- the -p flag entirely. You can always see usage (and game endings) now,
- however, which is a plus!
-
- The Emacs-style command line editing now handles ^D (delete character after
- cursor) and ^K (delete to end of line).
-
- Since most Unix boxes have loads of real memory and even more virtual
- memory, I increased the size of the scrollback buffer eightfold. It's now
- 256K. This should be enough for marathon play sessions.
-
- There are some known problems with the compiler -- core dumps on at least
- one big game, and core dumps when dealing with precompiled headers and
- modify/replace in another case. I haven't been able to track these down,
- but they aren't restricted to one architecture.
-
- One thing that's been reported as a bug but isn't: If you have the margin
- bell on in your xterm you'll get lots of rings as TADS updates the screen.
- The solution: turn off the margin bell!
-
-
- TADS 2.1.0.0
- Unix Patchlevel 2
-
- Output handling has been improved again. Terminal settings are restored
- properly upon suspend (^Z) or resume. I improved a few other things that I
- don't remember now. :)
-
-
- TADS 2.1.0.0
- Unix Patchlevel 1
-
- The programs should now be quite stable on all supported platforms.
- Term handling has been vastly improved, so that the run-time should be
- comfortable over a 2400 baud connection. The compiler now avoids
- all the screen handling stuff and just uses stdio for all output.
-
- Starting with this release, Unix versions will be given patchlevel
- numbers in addition to the standard High Energy version number.
- There's one patch number of the general Unix sources, and another for
- the specific platform the binaries were compiled for.
-
- General Unix notes:
-
- The .GAM files are now 100% portable across platforms. You can compile
- a game on a PC clone or Mac and then run the resulting .GAM directly
- under Unix (and vice versa). Kudos to High Energy for that!
-
- There is no maketrx program for the Unix versions. Now that TADS is
- running on a much wider range of machines, creating binaries specific
- to a particular machine seems rather foolish, so I have not kept
- support for doing that in the this port.
-
- The TADS run-time uses termcap routines for all output. You will
- therefore need to run it on a terminal with window scrolling capability
- (i.e., most modern terminals). If you find that the programs don't
- work properly with your terminal, please let me know -- termcap hacking
- is very error-prone, so I may have made a mistake in there somewhere.
- Before assuming that the problem is with the TADS run-time, however,
- try other programs on your system that use termcap, like vi. (Emacs
- has its own term handling code, so it's not a good test.)
-
- There a few things special to the Unix versions:
-
- o (Limited) Emacs-style command line editing:
-
- ^F ahead one character
- ^B back one character
- ^A beginning of line
- ^E end of line
- ^P previous command in command list
- ^N next command in command list
- ^K kill to end of line
- ^D delete character after cursor
-
- o ESC enters scrollback mode (instead of F1). Scrollback control
- keys are listed on the top line.
-
- o Press ^L at any time to redraw the entire screen (if you
- get a burst of line noise, for example)
-
- o Press ^Z (or whatever your SIGTSTP key is) to suspend the
- run-time.
-
- o tadsr recognizes SIGWINCH so that you can resize your
- terminal window. Text above the current line won't be
- reformatted when you do this, but all subsequent text
- will be formatted to fill the screen.
-
- NOTE: Resize doesn't work in an OpenWindows cmdtool.
-
- The output handling is still not absoultely optimal, but it's probably
- as good as it's going to get since the machine-independent TADS source
- imposes certain requirements on the behavior of the windowing functions.
-
- Finally, please report bugs directly to the person listed as the
- maintainer for the port in the banner, not to High Energy. That person
- is the only one (besides, perhaps, me) who's going to be fixing any
- problems specific to the Unix ports.
-
- Dave Baggett
- dmb@ai.mit.edu
-
- *-----------------------------------------------------------------------------*
- General TADS notes (From the DOS version)
- *-----------------------------------------------------------------------------*
-
- This file contains a list of changes that have been made to TADS
- since the initial 2.0 release. 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.
-
- 2.1.2 11/22/93 enhancements, bug fixes
-
- - You can now detect when the player uses multiple direct objects
- with a verb, and reject such commands. Whenever the player uses
- multiple direct objects with a command (or uses "all", even if it
- results in a single object being used), the parser calls the
- verb object's rejectMultiDobj(prep) method. If you don't wish to
- take any special action for multiple direct objects used with a
- particular verb, simply return nil from this method (or don't
- define the method at all for the verb). If you want to prevent
- multiple direct objects from being used, however, you should display
- an appropriate message, and return true. The parser will skip the
- command entirely. Note that the parser doesn't display any additional
- message when rejectMultiDobj(prep) returns true; the method should
- display whatever message is desired. The "prep" parameter is the
- preposition object used with the command; it will be nil if no
- indirect object is present. An example:
-
- modify inspectVerb
- rejectMultiDobj(prep) =
- {
- "You can only look at one thing at a time.";
- return true;
- }
-
- The verb's rejectMultiDobj(prep) method is called immediately
- before the actor's actorAction method. Note that the parser will
- continue processing any remaining commands on the line, and will
- then run daemons and fuses as normal, even if rejectMultiDobj(prep)
- returns true; if you want to stop the current turn altogether, use
- abort.
-
- - The player command parser now gives you greater control over object
- validation error reporting. In previous versions, if an object was
- visible but did not pass the validIo/validDo test, the parser called
- the object's cantReach method to report the error (see the note below
- about an additional change to object.cantReach processing).
-
- Now, however, the parser will call verb.cantReach instead, if the
- command's deepverb object defines (or inherits) a cantReach method.
- If the verb does not have a cantReach method at all, the parser
- will use the old behavior instead. The new cantReach method should
- be defined as follows:
-
- myVerb: deepverb
- verb = 'whatever'
- cantReach(actor, dolist, iolist, prep) =
- {
- // your code here
- }
- ;
-
- This method doesn't return a value; it simply displays the appropriate
- message explaining why the object can't be used with the command.
- verb.cantReach is used only when the objects are visible (that is,
- object.isVisible(actor) returned true for each object in the list).
-
- Only one of dolist or iolist will be non-nil. If the direct object
- of the command refers to one or more objects that are visible but
- can't be used (according to validDo), dolist will be a list of all
- such objects, and iolist will be nil. Otherwise, iolist will be a
- list of such objects used for the indirect object, and dolist will
- be nil.
-
- adv.t has not been changed to use verb.cantReach. This change has
- been made to provide finer control for game authors implementing
- their own verbs and object validation procedures.
-
- - The player command parser had an odd quirk when ambiguous nouns
- were used with transparent items. If the player used a command
- containing a noun that referred to multiple objects that were
- visible but were not valid for the verb (for example: "take trophy"
- in a room containing a closed glass trophy case containing a bowling
- trophy and a tennis trophy), the parser asked the normal disambiguation
- question. This was not really necessary, because the parser already
- knew that the objects were invalid. This has been changed; the parser
- now simply uses the cantReach message for *each* object that is
- visible and matches the vocabulary, using the usual multiple-word
- format:
- bowling trophy: You'll have to open the glass case first.
- tennis trophy: You'll have to open the glass case first.
-
- This new behavior should have no effect on your game code. Note
- that it is entirely irrelevant if you use the new verb.cantReach
- feature described above.
-
- - The compiler sports a new case sensitivity option. By default,
- the compiler is case-sensitive, as it has been in past versions.
- However, the new toggle option allows you to change this. Specify
- -case- to turn off case sensitivity (the default is -case+). Note
- that this is a toggle option, so simply using -case will reverse
- the current case sensitivity (which is useful if you use a CONFIG.TC
- file that sets a non-default case option). When case sensitivity
- is turned off, the compiler will treat upper- and lower-case letters
- in symbols (names of objects, properties, functions, and local
- variables) as equivalent. Hence, foodItem = fooditem = FoodItem,
- and so on.
-
- If you create a pre-compiled header with -w, any compilation which
- reads that binary header with -l will use the same case sensitivity
- as was in effect when the header was pre-compiled. The -case option
- is ignored when a pre-compiled header is loaded. Likewise, the
- debugger uses the same case sensitivity that was in effect when the
- game being debugged was compiled.
-
- - The debugger's command set is no longer case-sensitive (hence,
- BP = Bp = bP = bp).
-
- - adv.t has a new darkVerb class. This is a type of deepVerb that
- can be used in the dark. The darkroom class has been changed to
- accept any verb of class darkVerb in its roomAction and roomCheck
- methods. The travel verbs and system verbs have all been made
- darkVerb objects, so darkroom only needs to check the single
- verb type.
-
- In a related change, turnOnVerb and dropVerb have been changed to
- be darkVerb objects, allowing the player to turn on an object or
- drop it in the dark. The verDoTurnon method in switchItem has
- been changed so that it checks to see if the player is in a dark
- room; if so, the item can only be turned on if the player is already
- carrying the object. This allows the player to turn on a light
- source that's already being carried, but doesn't allow the player
- to pick up a light source in a dark room.
-
- - The compiler issues a new warning message (TADS-452) if you
- use the same verb with two deepverb objects. The parser can only
- choose a single deepverb object for any verb typed by the player,
- so you should never define the same 'verb' vocabulary word in more
- than one deepverb object. In past versions, the compiler did not
- flag this as a warning.
-
- - Several improvements have been made for numbers in player
- commands. First, multiple numbers are now allowed in a single
- commands; for example, the player can now say "press 1, 2, 3,
- 4 on keypad," and the numbers are set in numObj.value, one by
- one. Second, the sdesc, adesc, and thedesc properties of
- basicNumObj have been improved to show the number's value.
-
- - Similar improvements to those for numbers have been made for
- strings. Multiple strings are now allowed in a single command,
- and the basicStrObj properties sdesc, adesc, and thedesc have
- been improved to show the string's value.
-
- - specialWords has been enhanced. First, in past versions, if a
- game contained multiple specialWords statements, the word lists
- were additive -- all specialWords lists were used in the game.
- This has been changed so that each specialWords statement replaces
- any previous list in effect. However, you now can explicitly add
- to the specialWords list, without removing any of the previously
- defined words, by using "modify specialWords". When you use
- 'modify', you can use nil in any word slot if you do not wish
- to add any words for that slot. Finally, you can use "replace
- specialWords" to make the replacement explicit; this is the default
- if neither 'modify' nor 'replace' is specified, but the compiler
- will now issue a warning (which is harmless) if you use specialWords
- without 'replace' or 'modify' and a previous specialWords list is
- already in effect.
-
- - The words "one" and "ones" (or their equivalent for your game,
- if you've changed them with specialWords) are no longer considered
- reserved words within normal commands. This allows you to use
- objects such as a "one dollar bill"; previous versions rejected
- player commands containing "one" or "ones". These words are now
- considered special only during the parsing of a response to a
- disambiguation question, when they can be used in place of a
- noun ("the red one" can be used in answer to "Which book do you
- mean...").
-
- - The hider class has been changed so that 'it' or 'them' (as
- appropriate) are set to the object or objects found when
- searching the hider.
-
- - The verDoPutIn and verDoPutOn messages in thing and surface
- (respectively) have been improved for the somewhat obscure case
- of attempted circular containment - that is, putting an object
- into a container, when the container is already in the first object
- (either directly or by virtue of being inside another object which
- is inside the first object, or inside an object which is inside an
- object which is inside the first object, and so on). The new
- method thing.circularMessage(iobj) is called in these cases to
- display an appropriate message; the default implementation of this
- method displays the complete list of containers of the direct
- object out to the indirect object. For example, if you have a
- crate which contains a box, and you try to "put crate in box",
- the message is "You can't put the crate in the box, because
- the box is already in the crate."
-
- - The default doTake method has been changed to include the weight
- of any contents of the item being taken, in addition to the item
- itself, to determine if the actor's inventory is too heavy.
- The old doTake method only included the weight of the object
- being taken, not counting its contents.
-
- - The Actor class has been changed to add a travelTo method. You
- can now move any actor (Me included) with travelTo(destination).
- The default Actor.travelTo method moves the actor; it announces
- the departure of the actor if the actor was in the same location as
- Me before leaving (and the location is lit); and it announces the
- arrival of the actor if the actor is moving into the same location
- as the player (and the location is lit). The departure message
- is generated with a call to self.sayLeaving, and the arrival
- message is generated with self.sayArriving. The default versions
- of these methods simply display "Thedesc leaves the area" and
- "Thedesc enters the area", respectively; you can override these
- methods if a more specific message is desired.
-
- - When modifying a class object with 'modify', the modified object
- was not a class unless the 'class' keyword was included with the
- 'modify' statement ("modify class foo" rather than "modify foo").
- This has been corrected; a modified class is still a class.
-
- - outhide(true) now returns a status indicator, which is a value that
- can be used in a subsequent call to outhide() to return output
- hiding to the state it was in before the outhide(true). This
- allows you to nest text hiding. When you use the nested form
- (which you do simply by using the return value of outhide(true) as
- the parameter - in place of nil - to the subsequent call to outhide()),
- the value returned by the second outhide() indicates whether any
- text output occurred ONLY BETWEEN THE NESTED CALLS. For example:
-
- old_stat1 := outhide(true);
- "This is some hidden text.";
- old_stat2 := outhide(true);
- // write no text here
- new_stat2 := outhide(old_stat2);
- new_stat1 := outhide(old_stat1);
-
- Because outhide(old_stat2) indicates whether any output occurred
- during the NESTED outhide(true), new_stat2 = nil. However, new_stat1
- = true, since output occurred after the first outhide(true). Consider
- another sequence:
-
- old_stat1 := outhide(true);
- // write no text here
- old_stat2 := outhide(true);
- "This is some hidden text.";
- new_stat2 := outhide(old_stat2);
- new_stat1 := outhide(old_stat1);
-
- In this case, both new_stat1 and new_stat2 will be true, because
- hidden output occurred within both nested sections.
-
- The general form of a nested hidden output section looks like this:
-
- {
- local original_hide_stat;
- local nested_stat;
-
- hide_stat := outhide(true);
- // do whatever you want to do while output is hidden
- nested_stat := outhide(original_hide_stat);
- }
-
- Now nested_stat will indicate whether any output occurred during
- the nested outhide() - that is, between the outhide(true) and
- the outhide(original_hide_stat). In addition, output hiding will
- be returned to the same state it was in prior to the original
- outhide(true).
-
- - The random number generator has been improved. Many people have
- complained about the many undesirable properties of the old
- generator, especially when small upper limits were used. The
- interface to the new random number generator is the same as
- before - call rand(upper_limit), which will return a uniformly
- distributed random number from 1 to upper_limit, inclusive.
-
- Note that the old random number generator will still be used if
- you don't call randomize(). This allows test scripts (which require
- a fixed sequence of random numbers in order to be repeatable) that
- were written with older versions to continue to operate unchanged.
- If you want numbers from the improved generator, be sure to call
- randomize().
-
- - When 'modify' was used on an object, the compiler sometimes did
- not correctly apply the original object's vocabulary and location
- to the new object. This has been corrected.
-
- - restore() and undo() have been changed so that they always cancel
- all pending commands on the command line. In the past, if the
- player typed several commands, and something happened (such as
- the player character dying) during one of the commands that led to
- an undo() or restore(), the remaining commands were still
- executed. This has been fixed.
-
- - If you explicitly set an object's location to nil in its object
- definition, and the object inherited a location from a superclass,
- the system incorrectly placed the object in the contents list of
- the object named in the location inherited from the object's
- superclass. This has been corrected.
-
- - "abort" can now be used within a daemon or fuse, and the
- expected behavior will occur. In the past, "abort" within
- a fuse (or daemon) merely exited from the current fuse,
- but the remaining fuses and daemons were still executed.
- Now, "abort" will cause the entire turn to end; no more
- fuses or daemons will be executed on the current turn.
-
-
- 2.1.1 09/09/93 enhancements
-
- - You can now access objwords(1) while deciding whether to use a
- default direct object in doDefault. This is useful mostly if
- you want to prevent players from being able to use "all" with
- certain verbs, but still want to generate a default direct object
- for the verbs. To do this, you can detect when objwords(1) = ['A']
- ('A' is the parser's internal code for "all", which saves you the
- trouble of checking for "everything" and shorter abbreviations as
- well as "all"):
-
- doDefault(actor, prep, iobj) =
- {
- if (objwords(1) = ['A'])
- {
- global.allMessage := 'You can\'t use "all" with this verb.';
- return [];
-
- /* your normal default object code goes here */
- }
-
- If you wish, you can also suppress the default message that the
- parser will generate ("I don't see what you're referring to").
- To do this, you'll have to write your own parseError() function
- and detect when an "all" violation has occurred (cleverly using the
- global.allMessage, which we set above for this purpose):
-
- parseError: function(str, num)
- {
- // if there's an allMessage waiting, use it instead of the default
- if (global.allMessage <> nil)
- {
- local r;
-
- r := global.allMessage;
- global.allMessage := nil;
- return r;
- }
- else
- return nil;
- }
-
- - The compiler's error message format has been changed slightly
- to work better with editors and workbench programs that scan error
- logs to go to lines with errors. The format is now:
-
- file(line): error TADS-xxxx: message
-
- For example:
-
- deep.t(1151): error TADS-300: expected colon
-
-
- - The parser now accepts sentences of the form VERB PREP IOBJ DOBJ,
- where the PREP is *not* part of the verb. For example, GIVE TO THE
- MAN THE BALL. This change has two benefits. First, while this
- type of sentence is not common in English, some other languages
- allow this type of phrasing, so the parser is now somewhat more
- adaptable to non-English languages. Second, this allows for
- object defaulting and command completion when specifying just the
- indirect object, which was not possible before. For example, if
- the player types ASK FOR A BEER, the parser will be able to attempt
- to provide a default (if one is available), or at least ask for the
- direct object. Previous versions would simply say "I don't understand
- that sentence." Note that the parser still attempts to combine the
- verb and preposition into a single phrase; the new action happens
- only when the verb and preposition don't go together (that is, they
- haven't been defined together as a "verb =" property of a deepverb).
- For example, suppose that a line like this appears in a deepverb:
-
- verb = 'pick up'
-
- In this case, PICK UP THE BOX will use THE BOX as the direct object,
- just as in previous versions. Only when the verb-preposition combination
- is not specifically defined in a verb will the new phrasing be used.
-
- - When no preposition is specified between the direct and indirect objects,
- the parser will now evaluate a new property, nilPrep, in the deepverb
- object. This property should return the preposition object that should
- be used as the preposition between the objects. Previous versions of
- TADS always looked for an object that defined the word 'to' as a
- "preposition =" property. While 'to' is almost always the correctly
- the correct preposition to substitute in English, it's obviously the
- wrong word in other languages; furthermore, the correct word in other
- languages is sometimes a function of verb. If no nilPrep property is
- defined for the deepverb, the parser will still use the object whose
- "preposition =" property matches the word 'to'.
-
- - The class transparentItem in adv.t has been modified so it works better
- when you define an object that inherits from both transparentItem and
- container or openable. First, an ldesc has been added so that the
- contents of a transparentItem are listed by default with the ldesc.
- Second, the "look in" command now works on a transparentItem. In
- addition, the openable class has been changed so that the "look in"
- command can be used when an openable is also a transparentItem, even
- when the openable is closed (because you should be able to see the
- contents of a transparentItem regardless of whether it's open or closed).
- Thanks to Ron Hale-Evans for pointing out this problem and finding the
- solution.
-
- 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(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
-
-