Here's a list of changes between TADS 2 and 3.
Note: Occasionally, I refer to the TADS 3 overview. The overview is a collection of HTML-pages, which is installed together with the T3 Author's Kit.
| T2 | := | = | <> | and | or | not |
|---|---|---|---|---|---|---|
| T3 | = | == | != | && | || | ! |
fearsomeWeapon: Thing
// Simple values
weaponLevel = 12
weaponClass = 'Saber of Dood'
// A simple method (which prints the description)
desc()
{
"It's a mighty fearsome +12 Saber of Dood";
// Is the weapon located 'in' the player character?
if (isIn(gPlayerChar)) ", and it's yours! Mwahaha! ";
else ". ";
}
/*
* A short-hand method, which returns '+12 Saber of Dood'
* (unless weaponLevel or weaponClass is changed, of course.)
*/
name = ('+' + weaponLevel + ' ' + weaponClass)
// The same method written in out in full
name2()
{
return '+' + weaponLevel + ' ' + weaponClass;
}
;
obj: object
/* ... */
;
Or the new C-style brace-syntax:
obj: object
{
/* ... */
}
It's only a matter of looks. That said, I recommend using the semi-colon terminated syntax, as it makes it easier to track down syntax errors relating to missing braces.
Me: Actor; // A named object.
Thing // An anonymous object.
location = Me
;
This gives us an actor and an anonymous object, and locates the
latter in the actor's inventory.
field: OutdoorRoom 'In the middle of field'
"You're standing in a broad field of corn. (Etc.)"
north = road
;
This code compiles to exactly the same thing, but doesn't use
templates:
field: OutdoorRoom
name = 'In the middle of field'
desc = "You're standing in a broad field of corn. (Etc.)"
north = road
;
myRoom: Room 'Nifty Room'
"You can't go south from here. "
south = myRoomCantGoSouth
;
myRoomCantGoSouth: NoTravelMessage
travelDesc = "I told you, you can't go south! "
;
This shows a message if the player tries to go south. So far, this
is very verbose compared to the way you'd do that in TADS 2:
myRoom: Room 'Nifty Room'
"You can't go south from here. "
south: NoTravelMessage
{
travelDesc = "I told you, you can't go south! "
}
;
We create an anonymous object of class NoTravelMessage and assign
it to the south property of myRoom. (Also, if you still think the
code is verbose, don't worry - using templates, it becomes even
smaller.)| TADS 2 | TADS 3 | |
|---|---|---|
| item / thing | Thing | |
| room | Room / OutdoorRoom | |
| darkroom | DarkRoom | Or simply set the brightness of the room = 0. Same difference. |
| nestedroom | NestedRoom | |
| charitem | Chair | |
| beditem | Bed | |
| Actor | Actor / Person | |
| basicMe | Actor / Person | Any Actor can be used as player character. |
| follower | - | |
| obstacle | TravelConnector * | (and subclasses) |
| floatingItem | MultiLoc * | (and subclasses) |
| lightsource | - | Use the brightness property. |
| hiddenItem | - | No TADS 3 equivalent. |
| fixeditem | Fixture / Immovable | |
| distantItem | Distant | |
| readable | Readable | |
| fooditem | Food | |
| dialItem | Dial | (and subclasses) |
| switchItem | Switch | |
| decoration | Decoration | |
| buttonitem | Button | |
| clothingItem | Wearable | |
| doorway | Door * | |
| lockableDoorway | - | Use Lockable, Door as superclasses. |
| vehicle | Vehicle * | |
| surface | Surface | |
| container | Container | |
| qsurface / qcontainer | - | Set contentsListed = nil. |
| openable | OpenableContainer | |
| lockable | LockableContainer | |
| keyedLockable | - | Use LockableWithKey, OpenableContainer as superclasses. |
| keyItem | Key | |
| seethruItem | - | Write your own dobjFor(LookThrough) handler. |
| transparentItem | - | Use a Container and set its material = glass. |
| basicNumObj / basicStrObj | - | Literals are handled in a completely different way in TADS 3. |
| deepverb etc. | - | See this article on creating verbs. |
So instead of length(str), you should write str.length(), and so on. Works for constants too. 'Hello'.length() returns 5.
All file-handling methods have been moved to the File-class, see the appropriate chapter in the overview.
The fuse and daemon system (getfuse, rundaemons, runfuses, setdaemon, setfuse, notify, remdaemon, remfuse, unnotify) have been completely changed. See below.
| TADS 2 | TADS 3 | |
|---|---|---|
| input/inputline | inputManager.inputLine | |
| rand / _rand | rand | The TADS 3 random number generator is the same on all platforms, and its entropy is excellent. |
| scoreFormat | - | modify statusLine and override showStatusRight(). |
| incscore | addToScore * | |
| switchPlayer | - | gPlayerChar = newPlayer; gPlayerChar.lookAround(true, nil); |
| isclass | obj.ofKind(class) | You need to ensure that obj is an object, first. |
| abort | throw new TerminateCommandException() | Note that system-verbs use a different approach. |
| exitobj | exit; / exitAction; | exitAction runs afterAction etc. exit skips them. |
| exit | - | gAction.cancelIteration(); exit; |
| askdo / askio | askForDobj(action) / askForIobj(action) | (See dobjFor(Throw) in thing.t for an example.) |
| addword / delword / getwords | - | See dynamic vocabulary, below. |
| askfile | - | See the "tads-io Function Set" chapter in the TADS 3 overview. |
| caps | "\^"; | |
| clearscreen | clearScreen | |
| cvtnum | toInteger | |
| cvtstr | toString | |
| datatype | dataType | The return values have changed. See the "tads-gen Function Set" chapter in the overview. |
| debugTrace | - | Add PARSER_DEBUG to the list of Defines for your project. |
| defined | obj.propDefined | See the "Object Intrinsic Class" chapter in the overview. |
| endCommand | - | Use a PromptDaemon. |
| execCommand | executeCommand | Or you could add the command to the actor's command que using addPendingAction. |
| find | lst.indexOf / str.find | |
| firstobj / nextobj | firstObj / nextObj | Or use forEachInstance (in _main.t). |
| firstsc | obj.getSuperclassList | |
| argcount / getarg | argcount / getArg | Or use the new variable argument count syntax. See the "Statements" chapter in the overview. |
| gettime | getTime | The optional parameter can be either GetTimeDateAndTime or GetTimeTicks. |
| incturn | - | |
| inputdialog | inputDialog | See the "tads-io Function Set" chapter in the TADS 3 overview. |
| inputevent / inputkey | inputEvent / inputKey | Use the appropriate inputManager methods. |
| logging | scriptStatus.scriptFile | |
| morePrompt | inputManager.promptForMore(nil) | |
| nocaps | "\v"; | |
| objwords | - | |
| outcapture/outhide | - | Use a MonitorFilter or StringCaptureFilter. |
| parseXXX | - | The T3 parser has similar functions. |
| parserGetMe | gPlayerChar | |
| parserSetMe | - | gPlayerChar = theActor |
| parserGetObj | - | Use the global vars (gActor, gAction, gDobj, gIobj, etc.) |
| parserTokenize | cmdTokenizer.tokenize | |
| parseUnknownVerb | - | |
| postAction | - | Use the afterAction of Things or Actions, or the BasicLocation's roomAfterAction. |
| preCommand | - | Use the beforeAction of Things or Actions, or the BasicLocation's roomBeforeAction. |
| proptype | obj.proptype | See the "Object Intrinsic Class" chapter in the overview. |
| quit | - | Throw a QuittingException. |
| reSearch, reGetGroup | rexXXX | See the "Regular Expressions" chapter in the overview. |
| restart | RestartAction.doRestartGame | |
| restore | RestoreAction.performRestore | |
| save | SaveAction.performSave | |
| setit | gPlayerChar.setIt(obj) | And setHim(obj) / setHer(obj) / setThem(lst). |
| setscore | - | See score.t. |
| skipturn | - | |
| systemInfo | Still systemInfo | But see the "tads-io Function Set" chapter in the TADS 3 overview. |
| undo | UndoAction.performUndo(nil) | |
| verbinfo | - | |
| yorn | yesOrNo | Returns true or nil. |
| TADS 2 | TADS 3 | |
|---|---|---|
| sdesc | name | In T3, this should be a single-quoted string, not a double-quoted string. |
| ldesc | desc | This remains double-quoted, though. |
| readdesc | readDesc | Double-quoted. |
| actorDesc | actorHereDesc | Double-quoted. |
| noun, adjective, etc. | vocabWords_ * | See the T3 sample game. |
| doXXX, verDoXXX, etc. | dobjFor / iobjFor * | See the T3 sample game. |
| isopen | isOpen * | To make an object initially open, set initiallyOpen = true. |
| otherside | otherSide | |
| doordest | destination | |
| reachable | - | Use the sense system to prevent the player from reaching things. |
| isThem | isPlural | (Still isHim and isHer, though.) |
| isIn | isIn | The T3 isIn does not check visibility or anything like that. |
Complete list of TADS 3 name methods (similar to T2's aName, theName, etc.)
Fuses and daemons
You start a fuse or a daemon by creating a new Daemon, Fuse,
SenseDaemon, SenseFuse, RealTimeDaemon, RealTimeFuse,
RealTimeSenseFuse, RealTimeSenseDaemon or PromptDaemon object.
E.g., new Fuse(dynamite, &boom, 10); will cause the "boom" property of the "dynamite" object to be called in 10 turns.
Likewise, new SenseDaemon(clock, &tick, 3, clock, sound); will cause the "tick" property of the "clock" object to be called every 3 turns, but any messages the daemon generates (e.g. "Tick-tock!") will be suppressed unless the player-character is able to hear the clock.
Real-time daemons and fuses work exactly like their turn-based counterparts, except that time is specified in milliseconds rather than turns.
Finally, new PromptDaemon(myObj, &myProp); will cause the "myProp" property to be evaluated on "myObj" every time a prompt is about to be shown. The statusline uses such a daemon, for instance.
To stop an event, you hang on to the event-object, and then call
eventManager.removeEvent:
myFuse = new Fuse(self, &foo, 15);
eventManager.removeEvent(myFuse);
Or you can call eventManager.removeCurrentEvent() while
executing the event.
Finally, you can also call eventManager.removeMatchingEvents.
eventManager.removeMatchingEvents(self, &foo);
Just use realTimeManager instead of eventManager, if it's a real-time event.
Dynamic vocabulary
Adding vocabulary to an object is not that hard.
First, determine which type of word you want to add.
&noun, &adjective, &literalAdjective, &adjApostS
and &plural are the ones used by the en_us-module.
function addVocab(obj, wordProp, word)
{
if (obj.(wordProp) == nil) obj.(wordProp) = [word];
else obj.(wordProp) += word;
G_dict.addWord(obj, word, wordProp);
}
Removing vocabulary from an object is left as an exercise
for the reader.Copyright 2002-13 Søren Løvborg. The text of this page is licensed under a Creative Commons Attribution-Share Alike 3.0 License.