Beginnings

A work of Interactive Fiction has to start somewhere, and preferably with something a little more informative than a blank screen with a command prompt. In any case, for the game to work properly you need to define at least a basic set of data about the game and some of its starting conditions. We saw a brief example of this in the section on defining a minimal game, but now we should cover the topic a little more formally and in more depth.

The versionInfo Object

Your game should normally define a versionInfo object (of the GameID class) to:

  1. Specify basic information about your game (its name, author, etc.)
  2. Define the response to informational commands like ABOUT and CREDITS.

The properties and methods of versionInfo you'll typically need to define are:

So, for example, a typical versionInfo definition might look like this:

versionInfo: GameID
    IFID = '0D9D2F69-90D5-4BDA-A21F-5B64C878D0AB'
    name = 'Fire!'
    byline = 'by Eric Eve'
    htmlByline = 'by <a href="mailto:eric.eve@nospam.com">
                  Eric Eve</a>'
    version = '1'
    authorEmail = 'Eric Eve <eric.eve@nospam.com>'
    desc = 'A test game for the adv3lite library.'
    htmlDesc = 'A test game for the adv3lite library.'
    
    showAbout()
    {
        aboutMenu.display();
        
        "This is a demonstration/test game for the adv3Lite library. It should
        be possible to reach a winning solution using a basic subset of common
        IF commands.<.p>";
    }
    
    showCredit()
    {
        "Fire! by Eric Eve\b
        adv3Lite library by Eric Eve with substantial chunks borrowed from the
        Mercury and adv3 libraries by Mike Roberts. ";               
    }
;

In addition, you can override the following settings if you don't like the defaults inherited from GameInfoModuleID:

For further details consult the comments on the GameInfoModuleID in the modid.t file and/or consult the article on "Bibliographical Metadata" in the TADS 3 Technical Manual (although this was written for the adv3 library, everything in the Metadata article should apply equally well to adv3Lite).


The gameMain Object

You game must define a gameMain object, which should be of the GameMainDef class. At a basic minimum it must define the initialPlayerChar property to identify the object that is to represent the player character at the start of the game (typically this is called me, though you can call it anything you like). A minimal gameMain definition will therefore look like this:

gameMain: GameMainDef
   initialPlayerChar = me //although this isn't necessary if you define your player character with the Player class
;

In practice you'll normally want to define rather more than this on your gameMain object. The other properties and methods you may want to define include:

If you look at the definition of GameMainDef in misc.t you'll see a number of other methods and properties. Some of these, such as newGame(), restoreAndRunGame(filename), setGameTitle() and getSaveDesc(userDesc) are probably left as the library defines them unless you really have a need to override them and you know what you're doing. The rest are not guaranteed to work in the current version of the adv3Lite library and are probably best left alone (they have been left in from the adv3 version of GameMainDef for possible implementation in a later version of adv3Lite).

A fairly typical gameMain definition might thus look something like this:

gameMain: GameMainDef
    initialPlayerChar = me
    
    showIntro()
    {       
        cls();
                        
        george.startFollowing;
        
        "<b><font color='red'>FIRE!</font></b>  You woke up just now, choking
            from the smoke that was already starting to fill your bedroom,
            threw something on and hurried downstairs -- narrowly missing
            tripping over the beach ball so thoughtgfully left on the landing
            by your <i>dear</i> nephew Jason -- you <i>knew</i> having him to
            stay yesterday would be trouble -- perhaps he's even responsible
            for the fire (not that he's around any more to blame -- that's one
            less thing to worry about anyway).\b
            So, here you are, in the hall, all ready to dash out of the house
            before it burns down around you. There's just one problem: in your
            hurry to get downstairs you left your front door key in your
            bedroom.<.p>";
    }
   
;

Notes

When defining a showAboutBox() method you'd typically make it display a string beginning and ending with the <ABOUTBOX> and </ABOUTBOX> tags. A very basic setAboutBox() method that picks up all the relevant text from the versionInfo object might look like this:

  setAboutBox()
    {
        "<ABOUTBOX><CENTER><FONT size=+2 color=red><b><<versionInfo.name>>
        </b></FONT>\b
         <<versionInfo.byline>>\b
        Version <<versionInfo.version>></CENTER></ABOUTBOX>";
    }

For tenses other than past or present, override Narrator.tense to be one of Present ('Bob opens the box'), Past ('Bob opened the box'), Perfect ('Bob has opened the box'), PastPerfect ('Bob had opened the box'), Future ('Bob will open the box'), or FuturePefect ('Bob will have opened the box'). By default the library defines Narrator.tense as (gameMain.usePastTense ? Past : Present).

The showIntro() method is primarily for showing the game's introduction. It may also be a convenient place to put small amounts of start-up code used for initializing the game state (such as starting a Daemon running), but for initialization code you should also consider using PreinitObject and InitObject, which are definined in the System Library, and which you can read about in the "Program Initialization" section of the TADS 3 System Manual.


Defining the Player Character

Every TADS 3 game written with the adv3Lite library must define one object to be the player character (the character from whose viewpoint the game is played); the easiest way to do this is to define the initial player character using the Player class. It is possible to change the player character in the course of play, although many if not most games will probably stick to the same player character throughout; in any case a game must define which object is the player character at the start of play, in other words, the initial player character. If you do plan to change the player character during the course of the game, you should define every object that is going to represent the player character at one time or another (apart from the initial one) as an Actor. The player character should be defined as a Player object. Which object represents the initial player character can also be defined either by setting the initialPlayerChar property on the gameMain object, or by setting isInitialPlayerChar = true on the object in question; the Player class does that for you automatically. If both are done, the initialPlayerChar object defined on the gameMain object will take precedence.

To unpack that somewhat terse summary, we may begin by noting that if you create a new adv3Lite new game using the new Project Wizard in TADS 3 Workbench, the Wizard will create a minimal template game that does all this work for you thus:

#charset "us-ascii"

#include <tads.h>
#include "advlite.h"

versionInfo: GameID
    IFID = '$IFID$'
    name = '$TITLE$'
    byline = 'by $AUTHOR$'
    htmlByline = 'by <a href="mailto:$EMAIL$">$AUTHOR$</a>'
    version = '1'
    authorEmail = '$AUTHOR$ <$EMAIL$>'
    desc = '$DESC$'
    htmlDesc = '$HTMLDESC$'
;

gameMain: GameMainDef
    /* Define the initial player character; this is compulsory */
    initialPlayerChar = me
;


/* The starting location; this can be called anything you like */

startroom: Room 'The Starting Location'
    "Add your description here. "
;

/* 
 *   The player character object. This doesn't have to be called me, but me is a
 *   convenient name. If you change it to something else, rememember to change
 *   gameMain.initialPlayerChar accordingly.
 */

+ me: Player 'you'            
 // person = 1 or 3 for a first-person or third-person game       
;

Except that the versionInfo object will be filled in with the data you entered in the wizard. This way of declaring the initial player character has a couple of advantages: (1) it makes it clear just by looking at the gameMain object which object is the initial player character (you don't have to go hunting for it further down in the source code; (2) it makes it clear that the player character object is simply a Thing with a few extra properties set and in particular (3) it calls attention to the person property which you may want to change for a first-person or third-person game. If you've created a new game via the Workbench wizard this has no real downside, since the wizard will have done virtually all the work for you.

If you are starting a new game without using the wizard (perhaps because you aren't using Workbench) you can save yourself a small amount of typing by using the Player class instead of the Thing class to define the player character object:

The player character object can be called anything, me is just the conventional name to use. In game code the player character should be referenced as gPlayerChar.

Actor and Player

The Actor class defined in thing.t has hardly any of the functionality of the full Actor class defined in the Actormodule. The basic thing.t Actor class exists mostly for internal library purposes (to allow certain parts of the core library to reference an Actor class) and to provide a suitable superclass for the Player class. For an example of the sort of very simmple NPC that might be defined using this class (if you were using adv3Liter, say) see the discussion in the setion on modules.

The Player class should be used to define the initial player character. Only one such object should be defined in your game. Using the Player code for this purpose ensures that your initial player character has the right properties defined to act as such, and removes the need to define the initialPlayerChar property on gameMain. If the Actor module is present (as it is likely to be in most advLite games, although not in adv3Liter), the Player will then descend from the full Actor class, meaning amongst other things that if your player character changes during the course of your game, your initial player character will be a fully-fledged actor (which is essential if the new player character is to interact with him or her).