Major Differences Between TADS 2 and 3

If you're a TADS 2 user, the first thing you should know about TADS 3 is that it's not compatible with TADS 2 code. TADS 3 is a whole new system, built from the ground up. A lot of the basic knowledge you have as a TADS 2 user applies to TADS 3, but the systems aren't compatible at the source level: you can't take a game written in TADS 2 and compile it using TADS 3. The systems are too different.

Functionally, TADS 3 has a lot in common with past versions. TADS 2 has been used very successfully by many game authors, and TADS 3 builds on TADS 2's successes while breaking free of its limitations. TADS 3 is built on the same user interface technology as TADS 2, so TADS 3 games can use the familiar character-mode and HTML interpreter interfaces that TADS 2 games do. (This also simplified the porting process for TADS 3, since it could take advantage of the large number of existing ports of the TADS 2 UI code.) The debugger user interface is similar in both versions. The TADS 3 language is essentially an expanded version of the TADS 2 language.

TADS 3 does have several very big differences from past versions, though, and many minor improvements. Here's a list of some of the biggest changes.

No built-in parser. TADS 3 doesn't have a built-in parser, as TADS 2 does. Instead, TADS 3 provides a set of powerful mechanisms that simplify the creation of custom parsers, and the standard library will provide a robust and extensible English parser implementation. Moving the parser out of the system and into the library provides game authors with complete control over the parser, and even complete replacement if needed.

No built-in command loop. The style of interaction with the user is up to the game to implement. The standard library provides a default command loop implementation suitable for text adventure games, but you can customize or even entirely replace the library version as desired. This has a number of side benefits; for example, the system itself never asks the user for input (only the library does), hence all input operations are inherently under game/library control.

Garbage collection. TADS 3 has an automatic garbage collector that keeps track of which objects are accessible and which have become unreachable, and automatically deletes unreachable objects. With a garbage collector, game authors don't have to keep track of memory and explicitly delete unused objects. This saves a lot of coding work for game authors, and completely eliminates several really nasty classes of bugs that plague programs written in languages that require manual memory management.

More efficient dynamic memory allocation. TADS 3 is designed for efficient dynamic object creation. Creating an object is very fast; combined with the automatic garbage collection, this allows a more modern style of programming, where objects are used freely for ephemeral data structures.

Structured exception handling. TADS 3 has an exception handling mechanism that enables much simpler program structure and better error handling and recovery. In addition, all run-time errors generated by the virtual machine itself use the standard exception handling mechanism, which gives you control over how the game handles and recovers from from VM-level run-time errors.

True separate compilation. TADS 3 programs can be divided into any number of modules; each module can be compiled separately, and the compiled modules linked together to build the complete program. Only modules whose source has been modified need to be recompiled, speeding compilation times when building large games.

Unicode. TADS 3 uses Unicode internally for all character string operations, allowing use of any written language's characters and ensuring easy portability among all types of computers. Among other things, Unicode support allows TADS 3 to perform correct case conversions on all accented characters.

New local variables declared in for initializers. Like Java or C++, TADS 3 allows new local variables to be defined within a for statement's initializer clause.

Locals anywhere. TADS 3 allows new local variables to be declared anywhere within executable code (not just at the start of a block).

Labeled break and continue. The break and continue statements can now take an optional target label specifying which enclosing loop to break out of or continue with. Labeled break and continue targets eliminate nearly all of the remaining cases where goto is useful.

Full programmatic control over game control flow, including saving and restoring, restarting, and undo.

Improved regular expression handling, including a utility function that searches for regular expression matches in a string and replaces them with substitution text.

Improved random numbers. TADS 3 uses a better random number generator algorithm than past versions, and provides more convenient access: the random number generator can randomly pick a value from a list or from an argument list, in addition to its traditional generation of a random integer.

Vectors and Lookup Tables. The new Vector datatype provides an alternative to the traditional List datatype. Vectors are more efficient for operations where individual elements of a collection are repeatedly updated. And Lookup Tables provide a type of access known as "hashing" or "associative indexing" - they let you store a table keyed by arbitrary values, such as a strings or floating point numbers, and efficiently retrieve a value given its key.

Floating-point numbers. The new BigNumber datatype provides floating-point arithmetic with numbers of arbitrary precision. You can use the BigNumber type for extremely large integer calculations as well as high-precision floating-point arithmetic. BigNumber includes a full suite of arithmetic and transcendental functions.

Anonymous objects, object templates, and relative containment declarations. The TADS 3 language has several new object declaration features that allow for very concise and convenient object definitions. You can define an object anonymously, which eliminates the need to name every decoration and detail object; you can create "templates," which let you assign common properties without listing their names; and you can declare an object's location relative to a recently declared object without naming the container object.

Sublists, subsets, sorting, and other advanced collection features. New utility methods on collection types let you do things such as extract an arbitrary range of indices from a list, extract all of the values from a list that meet given criteria, sort the entries in a list according to criteria you specify, apply a transformation to all of the values in a list, or find a list entry matching some criteria.

Easier variable-argument handling. TADS 3 has new syntax that lets you handle arguments to a varying-argument function as a list, and to pass a list value as a varying-argument list to a function.

Anonymous functions. The TADS 3 language provides a mechanism that lets you define an in-line, unnamed function that can be passed as a callback to routines that perform iteration, enumeration, or notification. This powerful construct allows for much more concise code for many situations.

Syntax improvements. A few elements of the TADS language syntax have been modified for more consistency with Java and C++. In particular, the function definitions and method definitions now more closely resemble Java and C++ definitions. In addition, constructors can now accept arguments through the new operator.

Full ANSI C preprocessing. The TADS 3 compiler supports virtually all of the features of the ANSI C preprocessor: macros with substitution parameters, token pasting, stringizing, #if, #elif, #line. The TADS 3 preprocessor even obeys the ANSI C rules for recursive and circular macro expansions, lets you define variable-argument macros, and has extensions to the ANSI rules for even more powerful varargs macros.

An enhanced library. All of the features above are just the new language and virtual machine features - we haven't even started to describe the new library. The library provides an advanced sense model with sight, sound, smell, and touch, as well as extensibility with new game-specific senses; sense-passing among multiple rooms; a more sophisticated turn-based time system; modularity of messages (for different default message styles) and input grammar definitions (for easy translation to other natural languages besides English); a more modular design overall, for easier implementation of library extensions; a much-improved execution model; consistent naming conventions; and a lot more.

Real-time events. Most TADS 3 interpreters have enhanced support for real-time events, including timed command-line input. The library provides high-level features that make real-time events very easy to work with - real-time events look almost exactly like ordinary turn-based fuses and daemons.

Enhanced windowing features. Most of the TADS 3 interpreters support a new windowing API that replaces the HTML-based <BANNER> scheme in TADS 2. Unlike the <:BANNER> system, the new windowing API works on most character-mode platforms, so you can create sophisticated user interfaces that work the same way across a wider range of systems. The new API also gives you a separate "output stream" for each sub-window area, which is important for real-time event integration. The default "status line" in the library is built on the new window system, giving you enormous flexibility in customizing the status display.

Improvements for Players

Most of the features above are things only programmers could love. So how do all the new capabilities translate to better games for players?

At one level, there's nothing that makes a TADS 3 game inherently better than a TADS 2 game. The quality of a game depends much more on its storytelling, its interactivity, its humor, its drama - in short, on things that have nothing to do with technology. It's perfectly possible to create a great game in TADS 2 and a lousy game in TADS 3, and vice versa.

That said, though, TADS 3 has some improvements that players will easily notice - things that translate directly into features that virtually every TADS 3 game gets "for free" from the basic system. The TADS 3 command parser is more powerful - it understands more verbs and more command phrasings and more ways of referring to objects, so many players will find TADS 3 games easier to play, with less time spent wrestling with the parser. The library is smart about "implied" actions, such as picking something up before using it, or unlocking a door before opening it; this makes the player's experience more pleasant by eliminating a lot of the "busywork" that text adventures have traditionally foisted on players.

Most of the advantages of TADS 3, though, aren't things that the player will ever directly see. Instead, they're things that make the author's job easier, and things that give the author more flexibility and power in realizing her creative vision. One simple example is that it's very easy in TADS 3 to define a "decoration" - an object that isn't important in the game, but which is mentioned as scenery. That's a benefit for the author, but it indirectly translates into a benefit for the player: since it's so much quicker to create decorations, authors will probably create more of them, giving the player a more responsive, interactive game world to explore. Another example is that the command parser can be extensively customized and extended in TADS 3; for the player, this can translate into a parser that does a better job understanding the special commands and special phrasings that are important to the game.