By tradition, programming language books always start with an example program that displays "hello, world" and exits. This isn't exactly a book, but the "hello, world" is still the right place to start. So, here's the obligatory sample program; copy this into a file called mygame.t:
#include "tads.h"
#include "t3.h"
_say_embed(str) { tadsSay(str); }
_main(args)
{
t3SetSay(&_say_embed);
"Hello from TADS 3!!!\b";
}
After you've saved the file, open a command line window and change your working directory to the directory containing the file (on Windows, use the CD command). Make sure your path is set up to include the directory containing your TADS 3 tools. Type this command:
t3make mygame.t
This will compile and link the program, producing a file called mygame.t3x, the "image file" containing the T3 executable version of your program. To run the program, type this:
t3run mygame.t3x
If you've used previous versions of TADS, some of this probably looks familiar, but some is new. The #include directive should be familiar, but the files included aren't – these are system headers that define intrinsic function sets (more on these later). Next comes something called _say_embed – if you've used Java or C, you'll recognize this as a function definition. Functions work the same way in TADS 3 as they did in previous versions, but the unusual syntax that TADS formerly used is gone; TADS 3 function definitions are now essentially the same as Java or C definitions, except that the return datatype and formal parameter types are still not specified. The _say_embed() function, by the way, calls tadsSay(),a function in the "tads-io" intrinsic function set (which provides something similar to the built-in functions in previous versions).
Next is another function definition, this time _main(). This is a special function (in particular, the name is special – the linker requires that the program contain a function of this name). When the program starts running, the T3 VM will call this function. The argument is a list containing a set of strings, one for each argument on the command line that started the program running.
Inside _main(), the program calls the t3SetSay() function, which is from the "t3vm" function set. This sets up the default display function. Finally, we display a string, by writing the string to display inside double quotes. This works a lot like it did in TADS 2 – when a line containing a double-quoted string is executed, the VM displays the string. The only difference is that the VM calls the default display function, which we set up as _say_embed() earlier, to perform the output.
You might be wondering where things like the init() function and the startroom object are. In TADS 3, these are no longer part of the system. (In the future, libraries will probably define these, or something very similar; at the moment, though, we're talking about the system itself, without any extensions from libraries.) Whereas earlier versions of TADS had all sorts of things they did automatically, all the TADS 3 interpreter does is load your program and call _main(). When _main() returns, the program is finished, and the TADS 3 interpreter terminates.
It might sound like TADS 3 is a big step backwards from TADS 2, since TADS 2 did so much more automatically. It's true that the game program is responsible for doing a lot more in TADS 3, but this actually makes things better – no longer will you be forced to use the command loop that was built in to TADS 2. Don't despair about the added complexity, either: as TADS 3 matures, code libraries will provide all of the functionality that was built in to the TADS 2 system, so you eventually won't have to worry about all of the low-level operations any more than you did in TADS 2 – unless you're a library author, in which case you'll find the new system to be vastly more flexible. Even if you're not a library author, the greater flexibility of TADS 3 will benefit you by making possible libraries for a much wider variety of game styles. In addition, this makes TADS 3 in some ways much simpler than TADS 2 was – the system itself makes a tiny number of demands on your game program, so you don't have to remember all of the special built-in names that TADS 2 used; all of this complexity is moved out of the system and into the library, where you can look at and change the source code.