A TADS Tip Sheet, version 0.3b - Part 1 TADS, Michael J. Roberts' Text Adventure Development System, is a very powerful and flexible programming system for developing text adventures. (interactive fiction) However with that power comes a good deal of complexity. Here are some tips that I've come up with over the past four years of TADS authoring. And I thought that there may well be beginning TADS authors out there who could use some of these tips. Feel free to mail me with any suggestions for new tips or, indeed, corrections. I can be reached at tela@tela.bc.ca. Note that this tip sheet was originally written prior to the publication of the TADS 2.2 Release Notes. Some of the material in this tipsheet is actually explained, in far more detail, in those notes, especially the rewritten Book of the Parser. - N. K. Guy, tela design. (http://www.tela.bc.ca/tela/) RESTRICTIONS: You may distribute, modify and copy this file as much as you like, but it cannot be bought or sold. Please include this notice and a list of any changes you made if you choose to redistribute it. STANDARD PARANOID ANTI-LITIGATION STUFF: I believe that the information contained in this document is reasonably accurate. However, I make *no* guarantees of *any kind* that the document is error free or will meet your needs or anything like that. You assume full risk for using or not using any information in this file. If you find something wrong, please mail me a correction and I'll fix it. I hope that's all that needs to be said on this point. Also, any mention made within this document of commercial or shareware products is purely for informational purposes, and does not imply an endorsement of any kind by anybody. VERSION HISTORY: Version 0.1. Written 4/26/93 N. K. Guy (tela@tela.bc.ca) updated to 0.1a. (banana tree example code fixed) 3/18/94 updated to 0.2 to reflect TADS 2.2.1.0 Freeware 10/19/96 updated to 0.3. Added the #pragma C+ and setit() issues, TADS Page URL. 10/28/96 updated to 0.3a. Added the numberedObject stuff. 1/15/97 updated to 0.3b. Added Ditch Day, hiddenItem/obstacle and moveInto bits. 12/23/97 WHAT IS TADS? TADS, the Text Adventure Development System, is a particularly groovy system for programming text adventure games (sometimes called "interactive fiction") on a variety of computer platforms. TADS and Graham Nelson's Inform are the two most powerful and most popular development systems for writing text adventures currently available at time of writing. TADS was originally a shareware package written and published by High Energy Software. However, in mid 1996 TADS author Michael J. Roberts publicly announced that TADS was to become a freeware product and that High Energy Software would be shutting down the bulletin board system that it used to support the program. He has made good on his promise, and has even freely released the source code that makes up the program. You no longer have to pay anyone to use TADS - it's totally free! However, Mike Roberts retains copyright to the TADS system, so you can't go and change it or try (operative word here is try) and make lots of money off it without his permission. For more information on TADS have a look at the unofficial TADS page: http://www.tela.bc.ca/tela/tads/ WHERE CAN I GET IT? You can find the latest and greatest version of TADS in a variety of places, including, if you have access to Internet FTP: ftp://ftp.gmd.de/if-archive/programming/tads/ This site, the Interactive Fiction Archive (if-archive) is at GMD, the German National Research Centre for Information Technology. It's run by volunteer maintainers Volker Blasius and David Kinder, to whom we all owe a debt of gratitude. Note that if you don't live in Germany and find the connection to be rather slow, or if you want to be a good net.citizen and minimize your use of overtaxed international links, you can access the if-archive at a number of mirror sites. For example, US users may want to try Washington University's mirror at wu-archive: ftp://ftp.wustl.edu/doc/misc/if-archive/programming/tads/ European users outside Germany could try the Finnish University and Research Network's mirror: ftp://ftp.funet.fi/pub/misc/if-archive/programming/tads/ Additionally, if you have access to Usenet news and you're interested in discussions on the topic of writing interactive fiction, check out the newsgroup: news:rec.arts.int-fiction. For discussions on the topic of playing interactive fiction games, check out the newsgroup: news:rec.games.int-fiction. Some Tips --------- READ THE MANUAL. TADS has a great manual. A wondrous manual. Michael J. Roberts clearly poured half his soul and an awful lot of time into writing it. Read it. Worship it. This may be something of an obvious tip, but spending time with it will minimize time wasted later on figuring out why something won't work. The manual is available in two forms at time of writing. The first is typeset using TeX, the powerful and deeply arcane typesetting language popular within the academic community. If you have a program that can display TeX files (or, more accurately, that can convert the TeX files into DVI files for display purposes) then you might want to get that. The TeX files can be found at: ftp://ftp.gmd.de/if-archive/programming/tads/manuals/ The second is an HTML (HyperText Markup Language) translation of the TeX files for Web browsers, converted by yours truly. This version is on the Web at: http://www.tela.bc.ca/tela/tads-manual/ I'll probably upload it to the GMD if-archive as well. And I'm sure the TeX files will be converted into all kinds of other formats over the next while. READ THE TADVER.* FILES. Your copy of TADS should have come with a file called TADSVER.xxx, where xxx is the operating system you use. This file is extremely handy - it lists all the new features and fixed problems with the latest versions of TADS. There are many useful new features that have been added to TADS since the version 2 manual was released, and this file documents them. No TADS user should be without it! Note that there are two versions of the TADSVER file - one that lists all of the new features up to version 2.1 or so, (TADSV200.xxx) and another file that lists the changes from 2.1 onwards. I've put the most recent version of the Macintosh TADSVER file online at: http://www.tela.bc.ca/tela/tads-manual/tadsver-mac.html READ SOME SOURCE CODE. One of the best ways to learn how to program is, in my opinion, to find some well-written source code and play with it for hours on end. You can learn a lot through doing this. Tearing someone else's source apart and modifying it for your own ends is a very educational activity. TADS used to ship with the full source for a small game, Ditch Day Drifter, which illustrates many important basic features of TADS. Unfortunately somewhere along the way the Ditch Day code got left out of the standard TADS distribution. If you never got a copy, there's one at this URL: ftp://ftp.gmd.de/if-archive/games/tads/ditchday.zip And if you are on the Internet and have access to the treasure trove of stuff in the if-archive at ftp.gmd.de, check out the sample source code available there. For instance, there is an Examples directory in the TADS programming area that contains a number of small source code examples written by many TADS authors. A lot of these examples are written specifically to teach people about various principles of game design. Others are written to implement commonly-used features. For example, I wrote a little set of modules that I find very useful for testing games in progress. That file, wizard.t, is available in the examples directory. Another useful file is bugs.t by Stephen Granade, which provides patches for some minor bugs in the adv.t TADS libraries. ftp://ftp.gmd.de/if-archive/programming/tads/examples/ In addition to the mini code examples there is original TADS source to a number of complete full-length games on ftp.gmd.de as well. For example, Dave Baggett, in a deeply admirable selfless gesture, has ported the classic Colossal Cave (ie: "Adventure") game to TADS and published the source code in order to help train future generations of TADS authors. He's also made the source to his epic game "Legend" available. 1995 Interactive Fiction Contest winner Magnus Olsson has put the source to his winning entry "Uncle Zebulon's Will" in the same directory, and TADS author Michael J. Roberts has put his games "Deep Space Drifter" and "Perdition's Flames" online as well. ftp://ftp.gmd.de/if-archive/games/source/tads/ There are also a lot of other files in the if-archive that, although not directly related to TADS, nevertheless contain extremely useful information. For example, Graham Nelson's Inform compiler, which generates games compatible with the classic Z-machine system designed by Infocom, has a well-written manual that contains a lot of useful tips that can be used by any text adventure author. Check out his fascinating "Craft of Adventure" document. ftp://ftp.wustl.edu/doc/misc/if-archive/info/ Now let's get into some of the technical tips. *NEVER* MODIFY GAME STATE IN VERIFY METHODS. This is a very very common problem. The way TADS uses the "verify" method in a verb can be quite confusing, and it can lead to a lot of problems. Verify methods are object methods that start with "ver". Basically, remember that TADS doesn't use the verify method solely to see if an item can be verbed appropriately. It also uses the *same method* as part of its disambiguation routine. When it does so it silently calls the method. That means it calls it, but suppresses any text that the message may try to produce. If any text is produced and hidden then the game knows that the item in question can't be verbed by the verb. The upshot of all this is that if you change the state of the game somehow and don't simply display text you can really get strange things happening when that verify method is triggered inadventently by a disambiguation routine. Here's a concrete example. This is bad: badMagicTurkey: item sdesc = "magic turkey" [ etc. etc. ] verDoTouch( actor ) = { "Good heavens! The magical turkey vanishes in a cloud of tangerine-coloured vapour! "; self.moveInto( nil ); } ; The code is bad because the disambiguation function might call that verify method sometime, and if it does so it'll suppress the text but modify the game state by moving the turkey into nil. Thus our turkey may suddenly vanish for no readily apparent reason, and the player won't be notified when it does. The fix? Simply do this: goodMagicTurkey: item [ etc. etc. ] verDoTouch( actor ) = {} doTouch( actor ) = { "Good heavens! The magical turkey vanishes in a cloud of tangerine-coloured vapour! "; self.moveInto( nil ); } ; Since our verify method has simply an empty method the runtime just moves on to the actual verb method and executes it. No problems. Check out pages 36-39 of the TADS manual (a crucial section, by the way) and particularly page 39 for more details. This is the section titled "Disambiguation" in Chapter 4. *NEVER* SET OBJECT LOCATIONS MANUALLY AT RUNTIME. This is actually explained in chapter 4 of the manual, but I feel it's worth repeating here. It's OK to specify an item's location manually in the initial game definition. For example, this is cool, insofar as euphoniums can possibly be considered to be cool: Euphonium: item location = bandRoom ; What you *don't* want to do is set an item's location manually like that within code that is executed during game play. Doing so totally messes things up, because then the contents property of the container within which the item is located is not updated correctly. So the following code is bad: Euphonium.location := Wastebasket; Instead, you want to use the moveInto() method, like this: Euphonium.moveInto( Wastebasket ); That keeps everything neatly synched up. COMMON COMPILER ERRORS. Some of the most common compile-time errors result from forgetting to add a semicolon or not closing parentheses properly. As explained on page 201 of the manual, the compiler will try to skip ahead to the next code object if it encounters a problem. Thus if you end up with an endless string of compile-time errors appearing on your screen when you try and compile you can usually safely ignore most of the errors - it was likely the first one that caused all the problems. Another common problem is accidentally adding a semicolon after an if statement, thus: if ( elvis.isDead ); { say( 'No kidding. ' ); } This will cause a compile-time error as the semicolon after the if(); statement will tell the compiler that the if statement is complete. Yet another easily made error is to name a local variable the same name as a function. You can't do that. COMMON RUNTIME ERRORS. If you forget to return a value from a method or function you'll get the dreaded 1010 error. This could also mean that you've asked the game to evaluate a property that doesn't exist. For instance, if you have something like this: if ( Me.location.isUpstairs ) and Me.location = nil, you'll have problems because TADS will try to figure out the isUpstairs property of a non-existent object. You'd be better off doing this: if ( Me.location and Me.location.isUpstairs ) Another common problem involves the number of arguments you send to a function. Let's say you've invented a nice function like this: superDuperFunction: function( parm1, parm2, parm3 ) { // ingenious code in here. } Now if you call your function using this code: superDuperFunction( nil, true, nil, nil ); you'll get the annoying TADS-1026 error. The same error will occur if you call a method with the wrong number of arguments. TO MODIFY ADV.T OR NOT TO MODIFY ADV.T? That is the question. This is one of those perennial Difficult Decisions that TADS authors have to face. There are essentially three basic approaches as I see it. 1) Don't touch adv.t at all. The only changes made are done through TADS 2.1's "modify" and "replace" features. Pros: game doesn't break when a new version of adv.t is released. Cons: as your game gets complex it gets confusing tracking all the patches you've made to adv.t. 2) Modify adv.t as needed, brazenly ignoring "modify" and "replace." Pros: the game can include a myriad features that go beyond the fairly basic adv.t defaults. Cons: it's a lot more work to maintain as every single time a new version of adv.t is released you've got to go through manually and check every bit of code to make sure it still works. 3) Skip adv.t altogether and use WorldClass instead. Pros & Cons: See next section. Either way it's good practice to document thoroughly any changes you make to either adv.t or std.t or both. TAKE A LOOK AT WORLDCLASS. David Baggett, half of the Adventions team famous for the Unnkulian Unventures, has designed a complete replacement class library system for TADS. WorldClass replaces the standard adv.t and std.t TADS libraries altogether. WorldClass is an extremely powerful and flexible class library system that lets you do some pretty impressive stuff. It's much more consistent in structure and naming, and supports a lot of very useful concepts. For instance, it lets you treat all five senses equally in a game, and can handle abstractions like knowledge of items. There are two disadvantages to WorldClass as I see it, however. The first is that it's considerably slower than adv.t on old machines. If you have a reasonably modern computer, this won't be an issue, but if you have a really ancient clunker (eg: Mac Plus, IBM PC AT) then you'll find WorldClass games take a long time thinking between moves. This is because all items in the game are considered, rather than just those in your immediate surroundings. This means that cool stuff like knowledge classes are supported, but does slow things down. Second, WorldClass is quite a bit more complicated than adv.t. It lets you do a lot more than adv.t, but does have a steeper learning curve as a result. If you want to knock off a quick mini game, you might want to stick with adv.t. But if your ambitions are a bit higher, consider spending the time to learn what WorldClass can do for you! WorldClass, including Paul Gilbert's excellent manual, is in the if-archive at: ftp://ftp.gmd.de/if-archive/programming/tads/worldclass/ Or you can check the WorldClass Programming Page: http://www.df.lth.se/~mol/progtadsworldclass.html CASE IS NORMALLY SIGNIFICANT. When you *play* a TADS game you can enter commands in upper, lower or mixed case and everything works fine. However, TADS *code* is normally case sensitive. If you're having problems with a variable or object name not being recognized double-check to make sure that the capitalization is consistent. Common problems involve properties like "islit" or "isseen" and methods like "verDoTake" and the like. WorldClass is considerably more consistent than adv.t on this score. Newer versions of the compiler do permit case insensitivity, but you'll likely find your game won't compile with this option turned on unless you check your entire source code for case issues. To be concluded next issue - o -