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.