Macros

Introduction — Convenient Abbreviations

A macro is a kind of convenient abbreviation. Put more technically, it is a string of text that the TADS 3 preprocessor replaces with another (usually more elaborate) string of text before the source file is passed to the compiler for compilation, so that the compiler "sees" the text that has replaced the macro. This can be used to save typing as well as easing the job of coding by allowing game authors to use a relativelty short and memorable name for something in place of a longer and more complex expression it may be harder to remember.

TADS 3 has no concept of a global variable (that is a variable with a name like turnCount) accessible from any part of game code. Instead global valuables have to be stored as object properties, such as libGlobal.totalTurns. This may be a little tricky to remember and a little long-winded to type, so the adv3Lite library defines the macro gTurns which can be used in its place. Similarly the library defines the macro gRoom as convenient shorthand for (gPlayerChar.getOutermostRoom) as a convenient way to refer to the room in which the player character is currently located (which is not necessarily the same as the player character's location if the player character is in a nested room such as a bed or chair). This makes absolutely no difference to the compiler, but it can make it quite a bit easier for you to write and read your code.

A second kind of macro found in the adv3Lite library resembles a function (and in some, though not all cases, could have been implemented as a function). For example, when a verify routine calls illogical(msg)), this is in fact a macro, which in this case expands to gAction.addVerifyResult(new VerifyResult(30, msg, nil, self)), an expression it would once again be trickier to type and less clear to read. This could have been written as a function, although in theory the macro should be slightly more efficient at run-time (since it avoids the overhead of the function call, probably minimal in practice), but there are some function-like macros that can do things a function call could not. For example, goInstead is syntactic sugar for doInstead(go, northDir), avoiding the need to add "Dir" to the end of the direction name. This macro is defined as goInstead (dirn) doInstead(Go, dirn##Dir), which makes use of token-pasting (via the ## synmbol) to add "Dir" to the end of the parameter name passed to it, something a function call could not have done.

A third kind of macro used in adv3Lite executes a command and might resemble a reserved in the TADS 3 programming language, at least in appearance. For example, the macro exit superficially resembles the reserved word break in the TADS 3 language, but while break is a keyword used to break out of certain programming structures, exit is a macro that expands to throw new ExitSignal(). This is something most game authors won't need to worry about too much under most circumstances, but it may occasionally be helpful to be aware of the difference.

A fourth kind of macro used in adv3Lite is used to create or defined certain library-specific programming structures as dobjFor(Whatever) or DefineTIAction(Whatever), again in ways that can save quite a bit of typing and make the code more readable.

The fifth kind of macro is the one that's simply an alias for a numerical value. This isn't an abbreviation, but rather more of an aid to readibility. For example, the macro TypeCode (intended as a possible return value of propType() or dataType()) evaluates to 11. While the meaning of myObj.propType(&myprop) == 11 would be quite obscure, myObj.propType(&myprop) == TypeCode is a good deal clearer (and a good deal easier to remember if you want to test whether a particular property or value contains code).

Most of the time you won't need to know too much about what's going on under the hood with these macros, provided you know how to use them. The use of the most common ones has been covered in earlier chapters. For a complete list of all the macros defined in the adv3Lite library, refer to the Macros tab of the adv3Lite Library Reference Manual. One thing you do need to knowm though, is that none of these macros will work unless they're defined in whichever source file you're working on. This is why you need to include advlite.h in each of your game source files, along with tads.h:

#charset "us-ascii" #include <tads.h> #include "advlite.h"

Some Useful g Macros

As atated above, a complete list of adv3Lite macros can be found in the adv3Lite Library Reference Manual, so there is no need to reproduce it here. Instead we give a list of some of the more useful macros with names beginning g (because they often mimic global variables, or at least global values that may be of use to game authors):