adv3.h

documentation
#charset "us-ascii"

/* 
 *   Copyright (c) 2000, 2006 Michael J. Roberts.  All Rights Reserved. 
 *   
 *   TADS 3 Library - main header
 *   
 *   This file provides definitions of macros, properties, and other
 *   identifiers used throughout the library and in game source.
 *   
 *   Each source code file in the library and in a game should generally
 *   #include this header near the top of the source file.  
 */

#ifndef ADV3_H
#define ADV3_H

/* ------------------------------------------------------------------------ */
/*
 *   Include the system headers that we depend upon.  We include these here
 *   so that each game source file will pick up the same set of system
 *   headers in the same order, which is important for intrinsic function
 *   set definitions.  
 */
#include <tads.h>
#include <tok.h>
#include <t3.h>
#include <vector.h>
#include <strbuf.h>
#include <file.h>
#include <dict.h>


/* ------------------------------------------------------------------------ */
/*
 *   Establish the default dictionary for the game's player command parser
 *   vocabulary.
 */
dictionary cmdDict;

/* ------------------------------------------------------------------------ */
/*
 *   canInherit - determine if there's anything to inherit from the current
 *   method.  Returns true if there's a method to inherit, nil if
 *   'inherited' in the current context would not invoke any code.  
 */
#define canInherit() \
    propInherited(targetprop, targetobj, definingobj, PropDefAny)


/* ------------------------------------------------------------------------ */
/*
 *   Generic part of speech for "miscellaneous word."  We use this to
 *   classify words in unstructured phrases; it can apply to any token.
 *   Note that dictionary entries are never made with this word type, so
 *   it's not specific to any language; this is merely for flagging words in
 *   unstructured phrases in grammar matches.  
 */
dictionary property miscWord;

/*
 *   Generic part of speech for SpecialTopic words.  We enter special topic
 *   keywords into the parser dictionary so that they're not flagged as
 *   unknown words if they're used out of context.  
 */
dictionary property specialTopicWord;


/* ------------------------------------------------------------------------ */
/*
 *   If we're compiling for debugging, automatically include the parser
 *   debug code, which allows certain information on the parsing process
 *   (such as grammar match trees) to be displayed each time a command is
 *   typed.
 *   
 *   Note that you can turn on parser debugging independently of full
 *   compiler debug information simply by explicitly defining PARSER_DEBUG
 *   (with the t3make -D option, for example).  
 */
#ifdef __DEBUG
#define PARSER_DEBUG
#endif

/*
 *   Define some convenience macros for parser debug operations.  When
 *   PARSER_DEBUG isn't defined, these macros expand out to nothing.  
 */
#ifdef PARSER_DEBUG

#define dbgShowGrammarList(lst) showGrammarList(lst)
#define dbgShowGrammarWithCaption(headline, match) \
    showGrammarWithCaption(headline, match)

#else /* PARSER_DEBUG */

#define dbgShowGrammarList(lst)
#define dbgShowGrammarWithCaption(headline, match)

#endif /* PARSER_DEBUG */


/* ------------------------------------------------------------------------ */
/*
 *   Parser global variables giving information on the command currently
 *   being performed.  These are valid through doAction processing.  These
 *   should never be changed except by the parser.
 */

/* the actor performing the current command */
#define gActor (libGlobal.curActor)

/*
 *   For convenience, define some macros that return the current direct and
 *   indirect objects from the current action.  The library only uses direct
 *   and indirect objects, so games that define additional command objects
 *   will have to add their own similar macros for those.  
 */
#define gDobj (gAction.getDobj())
#define gIobj (gAction.getIobj())

/* 
 *   Get the current ResolvedTopic, and the literal text of the topic phrase
 *   as the user typed it (but converted to lower case).  These are
 *   applicable when the current action has a topic phrase.  
 */
#define gTopic (gAction.getTopic())
#define gTopicText (gTopic.getTopicText.toLower())

/* get the current literal phrase text, when the command has one */
#define gLiteral (gAction.getLiteral())

/*
 *   The tentative pre-resolution lists for the direct and indirect objects.
 *   When we're resolving an object of a multi-object command, these
 *   pre-resolution lists are available for the later-resolved objects.
 *   
 *   Note that these values are list of ResolveInfo objects.  The obj_
 *   property of a list entry gives the entry's game-world object.
 *   
 *   These lists do not provide the final resolution lists for the objects;
 *   rather, they provide a tentative set of possibilities based on the
 *   information that's available without knowing the results of resolving
 *   the earlier-resolved objects yet.
 *   
 *   These are not meaningful when resolving single-object actions.  
 */
#define gTentativeDobj (gAction.getTentativeDobj())
#define gTentativeIobj (gAction.getTentativeIobj())

/* 
 *   the actor who *issued* the current command (this is usually the player
 *   character, because most commands are initiated by the player on the
 *   command line, but it is also possible for one actor to send a command
 *   to another programmatically) 
 */
#define gIssuingActor (libGlobal.curIssuingActor)

/* the Action object of the command being executed */
#define gAction (libGlobal.curAction)

/*
 *   Determine if the current global action is the specified action.  Only
 *   the action prefix is needed - so use "Take" rather than "TakeAction"
 *   here.
 *   
 *   This tests to see if the current global action is an instance of the
 *   given action class - we test that it's an instance rather than the
 *   action class itself because the parser creates an instance of the
 *   action when it matches the action's syntax.  
 */
#define gActionIs(action) \
    (gAction != nil && gAction.actionOfKind(action##Action))

/* is the current global action ANY of the specified actions? */
#define gActionIn(action...) \
    (gAction != nil \
     && (action#foreach/gAction.actionOfKind(action##Action)/||/))

/* the verification results object - this is valid during verification */
#define gVerifyResults (libGlobal.curVerifyResults)

/* the command transcript object - this is valid during command execution */
#define gTranscript (mainOutputStream.curTranscript)

/*
 *   Some message processors add their own special parameters to messages,
 *   because they want to use expansion parameters (in the "{the dobj/him}"
 *   format) outside of the set of objects directly involved in the command.
 *   
 *   The Action method setMessageParam() lets you define such a parameter,
 *   but for convenience, we define this macro for setting one or more
 *   parameters whose names exactly match their local variable names.  In
 *   other words, if you call this macro like this:
 *   
 *   gMessageParams(obj, cont)
 *   
 *   then you'll get one parameter with the text name 'obj' whose expansion
 *   will be the value of the local variable obj, and another with text name
 *   'cont' whose expansion is the value of the local variable cont.  
 */
#define gMessageParams(var...) \
    (gAction.setMessageParams(var#foreach/#@var, var/,/))

/*
 *   Synthesize a global message parameter name for the given object and
 *   return the synthesized name.  This is useful in cases where there might
 *   be repeated instances of global message parameters in the same action,
 *   so it's not safe to use a fixed name string for the object.  We'll
 *   create a unique global message parameter name, associate the object with
 *   the name, and return the name string.  
 */
#define gSynthMessageParam(var) (gAction.synthMessageParam(var))


/* ------------------------------------------------------------------------ */
/*
 *   Miscellaneous macros
 */

/* get the current player character Actor object */
#define gPlayerChar (libGlobal.playerChar)

/* 
 *   the exit lister object - if the exits module isn't included in the
 *   game, this will be nil 
 */
#define gExitLister (libGlobal.exitListerObj)

/*
 *   the hint manager object - if the hints module isn't included in the
 *   game, this will be nil 
 */
#define gHintManager (libGlobal.hintManagerObj)


/* ------------------------------------------------------------------------ */
/*
 *   The current library messages object.  This is the source object for
 *   messages that don't logically relate to the actor carrying out the
 *   comamand.  It's mostly used for meta-command replies, and for text
 *   fragments that are used to construct descriptions.
 *   
 *   This message object isn't generally used for parser messages or action
 *   replies - most of those come from the objects given by the current
 *   actor's getParserMessageObj() or getActionMessageObj(), respectively.
 *   
 *   By default, this is set to libMessages.  The library never changes this
 *   itself, but a game can change this if it wants to switch to a new set of
 *   messages during a game.  (If you don't need to change messages during a
 *   game, but simply want to customize some of the default messages, you
 *   don't need to set this variable - you can simply use 'modify
 *   libMessages' instead.  This variable is designed for cases where you
 *   want to *dynamically* change the standard messages during the game.)  
 */
#define gLibMessages (libGlobal.libMessageObj)


/* ------------------------------------------------------------------------ */
/*
 *   readMainCommandTokens() phase identifiers.  We define a separate code
 *   for each kind of call to readMainCommandTokens() so that we can do any
 *   special token processing that depends on the type of command we're
 *   reading.
 *   
 *   The library doesn't use the phase information itself for anything.
 *   These phase codes are purely for the author's use in writing
 *   pre-parsing functions and for differentiating prompts for the different
 *   types of input, as needed.
 *   
 *   Games that read additional response types of their own are free to add
 *   their own enums to identify the additional phases.  Since the library
 *   doesn't need the phase information for anything internally, it won't
 *   confuse the library at all to add new game-specific phase codes.  
 */

/* reading a normal command line */
enum rmcCommand;

/* reading an unknown word response, to check for an "oops" command */
enum rmcOops;

/* reading a response to a prompt for a missing object phrase */
enum rmcAskObject;

/* reading a response to a prompt for a missing literal phrase */
enum rmcAskLiteral;

/* reading a response to an interactive disambiguation prompt */
enum rmcDisambig;


/* ------------------------------------------------------------------------ */
/*
 *   Property set definitions 
 */

/* in debug mode, flag objFor definitions for non-existent actions */
#ifdef __DEBUG
# define objForCheck(which, action) \
    sentinel##which##action = __objref(action##Action, warn)
#else
# define objForCheck(which, action)
#endif

#define objFor(which, action) \
    objForCheck(which, action) \
    propertyset '*' ## #@which ## #@action

#define dobjFor(action) objFor(Dobj, action)
#define iobjFor(action) objFor(Iobj, action)

/*
 *   Treat an object definition as equivalent to another object definition.
 *   These can be used immediately after a dobjFor() or iobjFor() to treat
 *   the first action as though it were the second.  So, if the player types
 *   "search box", and we want to treat the direct object the same as for
 *   "look in box", we could make this definition for the box:
 *   
 *   dobjFor(Search) asDobjFor(LookIn)
 *   
 *   Note that no semicolon is needed after this definition, and that this
 *   definition is completely in lieu of a regular property set for the
 *   object action.
 *   
 *   In general, a mapping should NOT change the role of an object:
 *   dobjFor(X) should not usually be mapped using asIobjFor(Y), and
 *   iobjFor(X) shouldn't be mapped using asDobjFor(Y).  The problem with
 *   changing the role is that the handler routines often assume that the
 *   object is actually in the role for which the handler was written; a
 *   verify handler might refer to '{dobj}' in generating a message, for
 *   example, so reversing the roles would give the wrong object in the role.
 *   
 *   Role reversals should always be avoided, but can be used if necessary
 *   under conditions where all of the code involved in the TARGET of the
 *   mapping can be carefully controlled to ensure that it doesn't make
 *   assumptions about object roles, but only references 'self'.  Reversing
 *   roles in a mapping should never be attempted in general-purpose library
 *   code, because code based on the library could override the target of the
 *   role-reversing mapping, and the override could fail to observe the
 *   restrictions on object role references.
 *   
 *   Note that role reversals can almost always be handled with other
 *   mechanisms that handle reversals cleanly.  Always consider remapTo()
 *   first when confronted with a situation that seems to call for a
 *   role-reversing asObjFor() mapping, as remapTo() specifically allows for
 *   object role changes.  
 */
#define asObjFor(obj, Action) \
    { \
        preCond { return preCond##obj##Action; } \
        verify() { verify##obj##Action; } \
        remap() { return remap##obj##Action; } \
        check() { check##obj##Action; } \
        action() { action##obj##Action; } \
    }

#define asDobjFor(action) asObjFor(Dobj, action)
#define asIobjFor(action) asObjFor(Iobj, action)

/* 
 *   Define mappings of everything except the action.  This can be used in
 *   cases where we want to pick up the verification, preconditions, and
 *   check routines from another handler, but not the action.  This is often
 *   useful for two-object verbs where the action processing is entirely
 *   provided by one or the other object, so applying it to both would be
 *   redundant.  
 */
#define asObjWithoutActionFor(obj, Action) \
    { \
        preCond { return preCond##obj##Action; } \
        verify() { verify##obj##Action; } \
        remap() { return remap##obj##Action(); } \
        check() { check##obj##Action; } \
        action() {  } \
    }

#define asDobjWithoutActionFor(action) asObjWithoutActionFor(Dobj, action)
#define asIobjWithoutActionFor(action) asObjWithoutActionFor(Iobj, action)

/*
 *   "Remap" an action.  This effectively rewrites the action in the given
 *   form.  Each of the object slots can be filled either with a specific
 *   object, or with a noun phrase role name (DirectObject, IndirectObject);
 *   in the latter case, the object or objects from the named noun phrase
 *   role in the *current* action (i.e., before the rewrite) will be used.
 *   
 *   If the new action has two or more objects (for example, if it's a
 *   TIAction), then EXACTLY ONE of the slots must be filled with a specific
 *   object, and all of the other slots must be filled with role names.  The
 *   specific object is the one that corresponds to the original object
 *   that's doing the remapping in the first place - this can simply be
 *   'self' if the new action will operate on the same object, or it can be
 *   a different object.  The important thing is that the 'verify' method
 *   for the defining object will be forwarded to the corresponding 'verify'
 *   method on the corresponding object for the new action.
 *   
 *   This macro must be used as the ENTIRE definition block for a dobjFor()
 *   or iobjFor().  For example, to remap a "put in" command directed to a
 *   desk so that the command is instead applied to a drawer in the desk, we
 *   could define the following on the desk object:
 *   
 *   iobjFor(PutIn) remapTo(PutIn, DirectObject, deskDrawer) 
 */
#define remapTo(action, objs...) { remap = [action##Action, ##objs] }

/*
 *   Conditionally remap an action.  If 'cond' (a conditional expression)
 *   evaluated to true, we'll remap the action as directed; otherwise, we'll
 *   inherit the default handling 
 */
#define maybeRemapTo(cond, action, objs...) \
    { remap = ((cond) ? [action##Action, ##objs] : inherited()) }


/*
 *   For two-object push-travel actions, such as "push sled into cave",
 *   define a special mapping for both the direct and indirect objects:
 *   
 *   - Map the direct object (the object being pushed) to a simple
 *   PushTravel action.  So, for "push sled into cave," map the direct
 *   object handling to PushTravel for the sled.  This makes the handling of
 *   the command equivalent to "push sled north" and the like.
 *   
 *   - Map the indirect object (the travel connector) to use the PushTravel
 *   action's verify remapper.  This is handled specially by the PushTravel
 *   action object to handle the verification as though it were verifying
 *   the corresponding ordinary (non-push) travel action on the indirect
 *   object.  Beyond verification, we do nothing, since the direct object of
 *   a pushable object will handle the whole action using a nested travel
 *   action.
 *   
 *   This effectively decomposes the two-object action into two coupled
 *   single-object actions: a regular PushTravel action on the object being
 *   pushed, and a regular whatever-kind-of-travel on the connector being
 *   traversed.  This handling has the appeal that it means that we don't
 *   need a separate PUSH version of every kind of allowed travel on a
 *   connector, and we don't need a special handler version for each kind of
 *   travel on a pushable object; instead, we just use the basic PushTravel
 *   and kind-of-travel handlers to form the combined form.  Note that this
 *   still allows separate treatment of the combined form wherever desired,
 *   just by overriding these default handlers for the two-object action.  
 */
#define mapPushTravelHandlers(pushAction, travelAction) \
    dobjFor(pushAction) asDobjFor(PushTravel) \
    mapPushTravelIobj(pushAction, travelAction)

#define mapPushTravelIobj(pushAction, travelAction) \
    iobjFor(pushAction) \
    { \
        verify() \
            { gAction.verifyPushTravelIobj(self, travelAction##Action); } \
    }


/* ------------------------------------------------------------------------ */
/*
 *   For an Actor, delegate an action handler to the ActorState object for
 *   processing.  You can use this any time you want to write the handlers
 *   for a particular action in the ActorState rather than in the Actor
 *   itself.  This would be desirable if the actor's response for a
 *   particular action varies considerably according to the actor's state.
 *   For example, if you want an actor's response to being attacked to be
 *   handled in the actor's current ActorState object, you could put this
 *   code in the Actor object:
 *   
 *   dobjFor(AttackWith) actorStateDobjFor(AttackWith)
 *   
 *   Once you've done this, you'd just write a normal dobjFor(AttackWith)
 *   handler in each of the ActorState objects associated with the actor.  
 */
#define actorStateObjFor(obj, Action) \
    { \
        preCond { return curState.preCond##obj##Action; } \
        verify() { curState.verify##obj##Action; } \
        remap() { return curState.remap##obj##Action; } \
        check() { curState.check##obj##Action; } \
        action() { curState.action##obj##Action; } \
    }

#define actorStateDobjFor(action) actorStateObjFor(Dobj, action)
#define actorStateIobjFor(action) actorStateObjFor(Iobj, action)


/* ------------------------------------------------------------------------ */
/*
 *   Object role identifiers.  These are used to identify the role of a noun
 *   phrase in a command.
 *   
 *   The library provides base classes for actions of zero, one, and two noun
 *   phrases in their grammars: "look", "take book", "put book on shelf".  We
 *   thus define role identifiers for direct and indirect objects.  Note that
 *   even though we stop there, this doesn't preclude games or library
 *   extensions from adding actions that take more than two noun phrases
 *   ("put coin in slot with tongs"); any such extensions must simply define
 *   their own additional role identifiers for the third or fourth (etc) noun
 *   phrase.
 */
enum ActorObject, DirectObject, IndirectObject;

/*
 *   A special role for the "other" object of a two-object command.  This
 *   can be used in certain contexts (such as remapTo) where a particular
 *   object role is implied by the context, and where the action involved
 *   has exactly two objects; OtherObject in such contexts means
 *   DirectObject when the implied role is IndirectObject, and vice versa. 
 */
enum OtherObject;


/* ------------------------------------------------------------------------ */
/*
 *   Pronoun types.  These are used to identify pronoun antecedents when
 *   resolving noun phrases involving pronouns.
 *   
 *   We define a basic set of pronouns here that are common to most
 *   languages.  Language-specific modules are free to add their own pronoun
 *   types as needed.
 *   
 *   Our basic set is:
 *   
 *   'it' - the neuter singular
 *.  'him' - the masculine singular
 *.  'her' - the feminine singular
 *.  'them' - the ungendered plural
 *.  'you' - second person singular
 *.  'me' - first person singular
 *   
 *   Note that the first-person and second-person pronouns are assigned
 *   meanings that can vary by context.  When a command is issued by the
 *   player character to the player character (i.e., the command comes from
 *   the player and no target actor is specified), these refer to the player
 *   character when the PC is in the appropriate referral person - if the
 *   game calls the PC "you", then the player calls the PC "me", and vice
 *   versa.  When a command is targeted to or issued by an actor other than
 *   the PC, then "you" refers to the command's target and "me" refers to
 *   the command's issuer.  
 */
enum PronounIt, PronounThem, PronounHim, PronounHer, PronounYou, PronounMe;


/* ------------------------------------------------------------------------ */
/* 
 *   set the location property 
 */
+ property location;


/* ------------------------------------------------------------------------ */
/*
 *   Alternative exit definition.  This can be used to define a secondary
 *   direction that links to the same destination, via the same connector, as
 *   another direction.  It's frequently desirable to link multiple
 *   directions to the same exit; for example, a door leading north might
 *   also lead out, or a stairway to the north could lead up as well.
 *   
 *   Use this as follows in a room's property list:
 *   
 *.     out asExit(north)
 *   
 *   (Note that there's no '=' sign.)
 *   
 *   It's not necessary to use this macro to declare an alternative exit,
 *   since the alternatives can all point directly to the same connector as
 *   the original.  The only thing this macro does is to make the alternative
 *   exit unlisted - it won't be shown in the list of exits in the status
 *   line, and it won't be shown in "you can't go that way" messages.
 *   
 *   Note that there's one common case where you should be careful with
 *   asExit(): if you have a room that has an exit in some compass direction,
 *   you might be tempted to make OUT the primary "direction" for the exit,
 *   and treat the equivalent compass as a synonym, with a line such as
 *   "south asExit(out)".  You should avoid doing this - do it the other way
 *   instead, with the compass direction as the primary direction and OUT as
 *   the synonym: "out asExit(south)".  The reason this is important is that
 *   if there's a nested room inside the location (such as a chair), OUT
 *   while in the nested room will mean to get out of the nested room.  If
 *   you make the compass direction primary and make OUT the synonym, the
 *   compass direction will be listed as an available exit both in the
 *   location and in any nested rooms within it.  
 */
#define asExit(dir) = static ((dir).createUnlistedProxy())


/* ------------------------------------------------------------------------ */
/*
 *   "Person" indices.  We define these as numbers rather than enums so that
 *   we can easily use these as list indices.  
 */
#define FirstPerson   1
#define SecondPerson  2
#define ThirdPerson   3


/* ------------------------------------------------------------------------ */
/*
 *   Transparency levels 
 */

/* the sense is passed without loss of detail */
enum transparent;

/* the sense is passed, but with a loss of detail associated with distance */
enum distant;

/*
 *   The sense is passed, but with attenuation of energy level.  No other
 *   obscuration of detail occurs; this is something like tinted glass that
 *   doesn't distort the transmitted sense but reduces the amount of energy. 
 */
enum attenuated;

/* 
 *   The sense is passed, but with a loss of detail due to an obscuring
 *   layer of material.  The energy level is also attenuated.  This is
 *   something like dirty or wavy glass that distorts an image transmitted
 *   through it but doesn't completely block out light.  
 */
enum obscured;

/* the sense is not passed at all */
enum opaque;


/* ------------------------------------------------------------------------ */
/*
 *   Size classes.  An object is large, medium, or small with respect to
 *   each sense; the size is used to determine how well the object can be
 *   sensed at a distance or when obscured.
 *   
 *   What "size" means depends on the sense.  For sight, the size
 *   indicates the visual size of the object.  For hearing, the size
 *   indicates the loudness of the object.  
 */

/* 
 *   Large - the object is large enough that its details can be sensed
 *   from a distance or through an obscuring medium.
 */
enum large;

/* 
 *   Medium - the object can be sensed at a distance or when obscured, but
 *   not in any detail.  Most objects fall into this category.  Note that
 *   things that are parts of large objects should normally be medium.  
 */
enum medium;

/*
 *   Small - the object cannot be sensed at a distance at all.  This is
 *   appropriate for detailed parts of medium-class objects.  
 */
enum small;


/* ------------------------------------------------------------------------ */
/*
 *   Path traversal operations. 
 */

/* traverse from the starting point of the path */
enum PathFrom;

/* traverse into the contents */
enum PathIn;

/* traverse out to the container */
enum PathOut;

/* traverse from an object to a peer at the same containment level */
enum PathPeer;

/* 
 *   traverse through an object with no common container on either side of
 *   the traversal - this is used when we are traversing an object, such as a
 *   SenseConnector, that connects unrelated locations 
 */
enum PathThrough;

/* traverse to the ending point of the path */
enum PathTo;


/* ------------------------------------------------------------------------ */
/*
 *   Listing Options 
 */

/* 
 *   use "tall" notation, which lists objects in a single column, one item
 *   per line (the default is "wide" notation, which creates a sentence
 *   with the object listing) 
 */
#define ListTall      0x0001

/*
 *   Recursively list the contents of each item we list.  
 *   
 *   For a 'tall' list, this indicates that we'll show the listed contents
 *   of each item that we list, and the listed contents of those items, and
 *   so on, indenting each level to indicate the containment relationship.
 *   
 *   For a 'wide' list, this indicates that we'll show the listed contents
 *   of each item in-line in the listing, as a parenthetic note.
 *   
 *   For both types of listings, when this flag is set and the indent level
 *   is zero (indicating a top-level listing), after the main list, we'll
 *   show a separate list for the contents of each item in our list that
 *   isn't itself listable but has listed contents, or has contents with
 *   listed contents, and so on to any level.  For example, if we're showing
 *   a room description, and the room contains a desk that isn't listed
 *   because it's a fixed part of the room, we'll show a separate list of
 *   the desk's listed contents.  
 */
#define ListRecurse   0x0002

/* 
 *   use "long list" notation - separates items that contain sublists with
 *   special punctuation, to set off the individual items in the longer
 *   listing from the items in the sublists (for example, separates items
 *   with semicolons rather than commas) 
 */
#define ListLong      0x0004

/* 
 *   This is a recursive listing of the contents of an item.  This is set by
 *   showList() in calls it makes to recursive listing levels.
 */
#define ListContents  0x0008

/*
 *   Custom option bits.  Flag bits with this value and higher are reserved
 *   for use by individual lister subclasses.
 *   
 *   To ensure compatibility with any future changes that involve adding
 *   more base lister flags, subclasses are encouraged to use the following
 *   mechanism.  DO NOT use #define to define your own custom subclass
 *   flags.  Instead, define a property of your lister subclass for each
 *   flag you need as follows:
 *   
 *   myCustomFlag1 = ListerCustomFlag(1) // use 1 for the first flag
 *.  myCustomFlag2 = ListerCustomFlag(2) // etc
 *.  nextCustomFlag = ListerCustomFlag(3)
 *   
 *   You DO NOT have to use the name 'myCustomFlag1' - use whatever name you
 *   like that describes the nature of the flag.  However, the last item
 *   MUST be called 'nextCustomFlag' - this ensures that any subclasses of
 *   your class will allocate their own flags with new values that don't
 *   conflict with any of yours.
 *   
 *   Then, when a client of your Lister subclass needs to pass one of your
 *   flag to the Lister, it should simply evaluate your 'myCustomFlagN'
 *   property of your lister.  If you'd like, you can even #define a ListXxx
 *   macro that retrieves the value, for the convenience of your callers:
 *   
 *   #define ListMyclassMyCustomFlag1 (Myclass.myCustomFlag1) 
 */
#define ListCustomFlag 0x0100

#define ListerCustomFlag(n) static ((inherited.nextCustomFlag) << ((n) - 1))


/* ------------------------------------------------------------------------ */
/*
 *   Spelled-out number options, for spellInt() and related functions.
 *   
 *   Note that the interfaces to the number-spelling functions can vary by
 *   language, and that variation can include these flags.  Some language
 *   modules might ignore some of these generic flags or define additional
 *   language-specific flags.  
 */

/* 
 *   Use tens of hundreds rather than thousands if possible - 1950 is
 *   'nineteen hundred fifty' rather than 'one thousand nine hundred
 *   fifty'.  This only works if the number (not including the millions
 *   and billions) is in the range 1,100 to 9,999, because we don't want
 *   to say something like 'one hundred twenty hundred' for 12,000.  
 */
#define SpellIntTeenHundreds    0x0001

/*
 *   use 'and' before the tens - 125 is 'one hundred and twenty-five'
 *   rather than 'one hundred twenty-five' 
 */
#define SpellIntAndTens         0x0002

/*
 *   put a comma after each power group - 123456 is 'one hundred
 *   twenty-three thousand, four hundred fifty-six' 
 */
#define SpellIntCommas          0x0004


/* ------------------------------------------------------------------------ */
/*
 *   Decimal number format options.  These are used with the number
 *   formatting functions to control the formatting of numbers displayed in
 *   decimal digit format.  
 */

/*
 *   Use a group separator character between digit groups, using the
 *   default setting in languageGlobals.
 */
#define DigitFormatGroupSep     0x0001

/* 
 *   Explicitly use a comma/period to separate digit groups, overriding
 *   the current languageGlobals setting.
 */
#define DigitFormatGroupComma   0x0002
#define DigitFormatGroupPeriod  0x0004


/* ------------------------------------------------------------------------ */
/*
 *   aHref() flags 
 */
#define AHREF_Plain  0x0001    /* plain text hyperlink (no underline/color) */


/* ------------------------------------------------------------------------ */
/*
 *   ResolveInfo flags 
 */

/* the noun phrase ends with an adjective */
#define EndsWithAdj      0x0001

/* 
 *   one of the words in the noun phrase was truncated from its full
 *   dictionary spelling 
 */
#define VocabTruncated   0x0002

/*
 *   One or more plurals was truncated from its full dictionary spelling.
 *   (We specially distinguish plurals that are truncated, because in
 *   English a plural is usually formed by adding "s" or "es" to the end of
 *   the singular form of a noun, meaning that a given singular form is
 *   usually a leading substring of its plural.  When a singular noun is
 *   longer than the truncation limit, which is conventionally six
 *   characters, the singular will always match as a truncated version of
 *   the plural, so every time someone types in a singular it'll be treated
 *   as ambiguous between the singular and plural form.  So, in the English
 *   parser, we have a preference to ignore a truncated plural any time the
 *   word could also be interpreted as an untruncated singular, hence we
 *   note when we have a truncated plural.)  
 */
#define PluralTruncated  0x0004

/*
 *   The object came from an 'all' phrase.  Normally, the only time this
 *   makes any difference is when deciding whether or not to mention which
 *   object we're acting upon; an 'all' object should normally be mentioned
 *   explicitly, as though the command had involved multiple objects,
 *   because otherwise it might not be clear to the user what object had
 *   actually matched 'all'.  
 */
#define MatchedAll       0x0008

/*
 *   Always announce the object before executing the command on it.  This
 *   flag can be set for objects that match phrases whose meaning isn't
 *   necessarily known to the player, such as "all" (which selects objects
 *   based on the simulation state, which might not exactly match what the
 *   player had in mind) or "any book" (which might select arbitrarily from
 *   several possibilities, so the player can't know which we'll choose).  
 */
#define AlwaysAnnounce   0x0010

/*
 *   The noun phrase describing this object was ambiguous, and the object
 *   was selected by automatic disambiguation in a context where it was
 *   clear which object was indicated.  This is used in cases where the
 *   objects not selected were all illogical for the action context.  
 */
#define ClearDisambig    0x0020

/*
 *   The noun phase describing this object was ambiguous, and the object was
 *   selected by automatic disambiguation in a context where it was not
 *   perfectly clear which object was indicated.  This is used for cases
 *   where the objects selected were more logical than the objects not
 *   selected, but some of the unselected objects were still logical.
 *   
 *   This flag doesn't mean that we chose arbitrarily, but rather that we
 *   chose the best object or objects from a field that included additional
 *   objects that, though not quite as good, were still valid.  We flag this
 *   case because the user *could* have meant to use one of the other valid
 *   objects, even though we consider it most likely that the user meant to
 *   use the one(s) we selected; so, we want to flag this so we can call the
 *   user's attention to our choice, to make it more likely that the user
 *   will immediately notice if we made the wrong choice.
 *   
 *   Note that we can't have both ClearDisambig and UnclearDisambig at the
 *   same time, but we *can* have neither of these.  If neither flag is set
 *   for an object, it simply means that the object wasn't ambiguous to
 *   start with.  When the user explicitly picks an object interactively,
 *   the selected object is effectively unambiguous, so it won't have either
 *   flag set; even though it started off ambiguous, the user did all of the
 *   work of selecting the appropriate object, leaving things unambiguous in
 *   the end.  
 */
#define UnclearDisambig  0x0040

/*
 *   The noun phrase was missing from the command and this object was
 *   supplied as an implicit default.
 */
#define DefaultObject    0x0080

/*
 *   We've announced this as a defaulted object.  We use this to ensure that
 *   we only make this type of announcement once, even if the opportunity to
 *   make the announcement comes up more than once; this can happen when
 *   we're asking for missing objects interactively in a multi-object
 *   command, since we might want to announce a default before prompting as
 *   well as before execution.  
 */
#define AnnouncedDefaultObject  0x0100


/* ------------------------------------------------------------------------ */
/*
 *   Announcement styles for disambiguated objects.  These are used in the
 *   gameMain object (see GameMainDef) to select which type of announcement
 *   is used when the parser disambiguates a noun phrase using the
 *   logicalness rules.  
 */

/* 
 *   Announce unclear disambiguation results only.  When this setting is
 *   selected, the parser makes a parenthetical announcement (e.g., "(the red
 *   door)") when it selects an object based on likelihood rankings from
 *   among more than one logical match.  The parser makes no announcement
 *   when exactly one logical object is in scope, even if other objects match
 *   the noun phrase by name. 
 */
enum AnnounceUnclear;

/*
 *   Announce clear and unclear disambiguation results, both using
 *   parenthetical announcement ("(the red door)").  When this setting is
 *   selected, the parser makes these announcements every time it applies the
 *   logicalness rules or likelihood rankings to disambiguate a noun phrase.
 *   There's no announcement when no disambiguation is needed (because the
 *   noun phrase matches only one in-scope object).  
 */
enum AnnounceClear;

/*
 *   Describe clear disambiguation results, rather than announcing them.  The
 *   parser makes the parenthetical announcement, as usual, for unclear
 *   disambiguation picks, but not for clear picks (a clear pick is one where
 *   there's only one logical object, even though the noun phrase matches
 *   more than one object).  For clear picks, however, the parser uses a
 *   verbose version of the action reply in lieu of one of the terse default
 *   messages.  For example, rather than saying just "Taken", the parser
 *   would reply "You take the red book."  The longer messages mention the
 *   object by name, to make it clear exactly which one was chosen.  
 */
enum DescribeClear;


/* ------------------------------------------------------------------------ */
/*
 *   Inventory modes.  "Wide" mode displays the inventory in paragraph form;
 *   "tall" mode displays as a list, with one item per line, indenting items
 *   to reflect containment.  
 */
enum InventoryWide, InventoryTall;


/* ------------------------------------------------------------------------ */
/*
 *   Define an action with the given base class.  This adds the *Action
 *   suffix to the given root name, and defines a class with the given base
 *   class.  We also define the baseActionClass property to refer to myself;
 *   this is the canonical class representing the action for all subclasses.
 *   This information is useful because a language module might define
 *   several grammar rule subclasses for the given class; this lets us
 *   relate any instances of those various subclasses back to this same
 *   canonical class for the action if necessary.  
 */
#define DefineAction(name, baseClass...) \
    class name##Action: ##baseClass \
    baseActionClass = name##Action

/*
 *   Define a "system" action.  System actions are meta-game commands, such
 *   as SAVE and QUIT, that generally operate the user interface and are not
 *   part of the game world.  
 */
#define DefineSystemAction(name) \
    DefineAction(name, SystemAction)

/*
 *   Define a concrete IAction, given the root name for the action.  We'll
 *   automatically generate a class with name XxxAction. 
 */
#define DefineIAction(name) \
    DefineAction(name, IAction)

/* define a conversational IAction, such as Hello, Goodbye, Yes, No */
#define DefineConvIAction(name) \
    DefineAction(name, ConvIAction)

/*
 *   Define a concrete TAction, given the root name for the action.  We'll
 *   automatically generate a class with name XxxAction, a verProp with name
 *   verXxx, a checkProp with name checkXxx, and an actionProp with name
 *   actionDobjXxx.  
 */
#define DefineTAction(name) \
    DefineTActionSub(name, TAction)

/*
 *   Define a concrete TAction with a specific base class.  
 */
#define DefineTActionSub(name, cls) \
    DefineAction(name, cls) \
    verDobjProp = &verifyDobj##name \
    remapDobjProp = &remapDobj##name \
    preCondDobjProp = &preCondDobj##name \
    checkDobjProp = &checkDobj##name \
    actionDobjProp  = &actionDobj##name \

/*
 *   Define a concrete TIAction, given the root name for the action.  We'll
 *   automatically generate a class with name XxxAction, a verDobjProp with
 *   name verDobjXxx, a verIobjProp with name verIobjxxx, a checkDobjProp
 *   with name checkDobjXxx, a checkIobjProp with name checkIobjXxx, an
 *   actionDobjProp with name actionDobjXxx, and an actionIobjProp with name
 *   actionIobjXxx.  
 */
#define DefineTIAction(name) \
    DefineTIActionSub(name, TIAction)

/*
 *   Define a concrete TIAction with a specific base class.  
 */
#define DefineTIActionSub(name, cls) \
    DefineAction(name, cls) \
    verDobjProp = &verifyDobj##name \
    verIobjProp = &verifyIobj##name \
    remapDobjProp = &remapDobj##name \
    remapIobjProp = &remapIobj##name \
    preCondDobjProp = &preCondDobj##name \
    preCondIobjProp = &preCondIobj##name \
    checkDobjProp = &checkDobj##name \
    checkIobjProp = &checkIobj##name \
    actionDobjProp  = &actionDobj##name \
    actionIobjProp = &actionIobj##name

/*
 *   Define a concrete TopicAction, given the root name for the action. 
 */
#define DefineTopicAction(name) \
    DefineAction(name, TopicAction)

/*
 *   Define a concrete TopicTAction, given the root name for the action.
 *   'which' gives the role the topic serves, for message generation purposes
 *   - this should be one of the object role enums (DirectObject,
 *   IndirectObject, etc) indicating which role the topic plays in the
 *   action's grammar.  
 */
#define BaseDefineTopicTAction(name, which, cls) \
    DefineAction(name, cls) \
    verDobjProp = &verifyDobj##name \
    remapDobjProp = &remapDobj##name \
    preCondDobjProp = &preCondDobj##name \
    checkDobjProp = &checkDobj##name \
    actionDobjProp = &actionDobj##name \
    whichMessageTopic = which

#define DefineTopicTAction(name, which) \
    BaseDefineTopicTAction(name, which, TopicTAction)

/*
 *   Define a concrete ConvTopicTAction.  This is just like defining a
 *   TopicTAction, but defines the action using the ConvTopicTAction
 *   subclass.  
 */
#define DefineConvTopicTAction(name, which) \
    BaseDefineTopicTAction(name, which, ConvTopicTAction)

/*
 *   Define a concrete LiteralAction, given the root name for the action.  
 */
#define DefineLiteralAction(name) \
    DefineAction(name, LiteralAction)

/*
 *   Define a concrete LiteralTAction, given the root name for the action.
 *   'which' gives the role the literal phrase serves, for message generation
 *   purposes - this should be one of the object role enums (DirectObject,
 *   IndirectObject, etc) indicating which role the topic plays in the
 *   action's grammar.  
 */
#define DefineLiteralTAction(name, which) \
    DefineAction(name, LiteralTAction) \
    verDobjProp = &verifyDobj##name \
    remapDobjProp = &remapDobj##name \
    preCondDobjProp = &preCondDobj##name \
    checkDobjProp = &checkDobj##name \
    actionDobjProp = &actionDobj##name \
    whichMessageLiteral = which

/* ------------------------------------------------------------------------ */
/*
 *   Convenience macros for setting verify results.
 *   
 *   A verify routine can use these macros to set any number of verify
 *   results.  The VerifyResultList will keep only the result that gives the
 *   strongest disapproval of the action, since the verification process is
 *   by its nature only interested in the most negative result.
 *   
 *   These macros take advantage of the fact that we have a global
 *   VerifyResultList object, which gathers the results of the verification,
 *   so they can be used only in verify routines.  The global verification
 *   results object is valid during each verification invocation.  
 */

/* 
 *   Command is logical.  There's generally no need to add a logical result
 *   explicitly, since a command is logical unless disapproved, but we
 *   include this for completeness.
 *   
 *   We use 100 as the default likelihood, to leave plenty of room for
 *   specific likelihood rankings both above and below the default level.  
 */
#define logical \
    (gVerifyResults.addResult(new LogicalVerifyResult(100, '', 100)))

/* 
 *   Command is logical, and is ranked as indicated among logical results.
 *   The 'rank' value is the likelihood rank; the higher the rank, the more
 *   logical the command is.  The rank is only used to establish an ordering
 *   of the logical results; if a command also has illogical results, all of
 *   the illogical results rank as less logical than the logical result with
 *   the lowest likelihood.
 *   
 *   The 'key' value is an arbitrary string value associated with the
 *   ranking.  When two result lists both have a logical result object, and
 *   both logical result objects have the same likelihood level, we'll check
 *   the keys; if the keys match, we'll treat the two results as equivalent
 *   and thus not distinguishing for disambiguation.  This is useful because
 *   it creates a crude multivariate space for ranking items for
 *   disambiguation.
 *   
 *   For example, suppose we have a "put in" command, and we have two
 *   possibilities for the target container.  Neither is being held by the
 *   actor, so they both have a result with a logical rank of 70 with a key
 *   value of 'not held'.  In addition, both are openable, and one is open
 *   and the other is closed; the closed one has an additional result with a
 *   logical rank of 80 and a key of 'not open'.  Which do we choose?  If we
 *   looked only at the logical rankings, both would be equivalent, since
 *   both have 70's as their most disapproving results.  However, we see
 *   that the two 70's were applied for the same reason - because they share
 *   a common key - so we know this information isn't helpful for
 *   disambiguation and can be ignored.  So, we find that the closed one has
 *   an 80, and the other has no other results (hence is by default logical
 *   with rank 100), thus we take the '80' as the better one.
 *   
 *   Throughout the library, we use the following conventions:
 *   
 *   150 = especially good fit: a good candidate for the action that is
 *   especially likely to be used with the command.  For example, a book is
 *   especially suitable for a "read" command.
 *   
 *   140 = similar to 150, but slightly less ideal a fit.  We use this for
 *   objects that are excellent fits, but for which we know certain other
 *   objects might be better fits.
 *   
 *   100 = default: a perfectly good candidate for the action, with nothing
 *   that would make it illogical, but nothing that makes it especially
 *   likely, either
 *   
 *   80 = slightly less than perfect: a good candidate, but with some
 *   temporary and correctable attribute that may make it less likely than
 *   others.  This is used for attributes that can be corrected: a container
 *   needs to be opened for the action to succeed, but isn't currently open,
 *   or an article of clothing cannot be worn for the action to proceeds,
 *   but is currently being worn.
 *   
 *   60/70 = slightly less than perfect, but with some attributes that can't
 *   be readily corrected and which make the candidate potentially less
 *   likely.  These are used to make guesses about which might object might
 *   be intended when several are logical but some might be more readily
 *   used than others; for example, if putting an object into a container, a
 *   container being held might rank higher than one not being held, so the
 *   one not being held might be ranked a "70" likelihood.
 *   
 *   50 = logical but not especially likely: an acceptable candidate for the
 *   action, but probably not the best choice for the action.  This is used
 *   when an object can be used for the action, but would not be expected to
 *   do anything special with the action.  
 */
#define logicalRank(rank, key)  \
    (gVerifyResults.addResult(new LogicalVerifyResult(rank, key, 100)))

/*
 *   Logical ranking with specific list ordering.  This is the same as a
 *   regular logicalRank, but uses the given list ordering rather than the
 *   default list ordering (100).
 */
#define logicalRankOrd(rank, key, ord) \
    (gVerifyResults.addResult(new LogicalVerifyResult(rank, key, ord)))

/* command is logical but dangerous */
#define dangerous \
    (gVerifyResults.addResult(new DangerousVerifyResult('')))

/* 
 *   command is logical but non-obvious: the object should never be taken as
 *   a default 
 */
#define nonObvious \
    (gVerifyResults.addResult(new NonObviousVerifyResult('')))

/* command is currently (but not always) illogical, for the given reason */
#define illogicalNow(msg, params...) \
    (gVerifyResults.addResult(new IllogicalNowVerifyResult(msg, ##params)))

/* illogical because things are already as the command would make them */
#define illogicalAlready(msg, params...) \
    (gVerifyResults.addResult( \
        new IllogicalAlreadyVerifyResult(msg, ##params)))

/* command is always illogical */
#define illogical(msg, params...) \
    (gVerifyResults.addResult(new IllogicalVerifyResult(msg, ##params)))

/* illogical since we're trying to use something on itself (eg, PUT X IN X) */
#define illogicalSelf(msg, params...) \
    (gVerifyResults.addResult(new IllogicalSelfVerifyResult(msg, ##params)))

/* command is being performed on an inaccessible object */
#define inaccessible(msg, params...) \
    (gVerifyResults.addResult(new InaccessibleVerifyResult(msg, ##params)))


/* ------------------------------------------------------------------------ */
/*
 *   Convenience macros for setting command results.
 */

/*
 *   Set a default report for the current command.  This report will be
 *   shown unless a non-default report is issued, or if the default report
 *   is to be suppressed (for example, because the command is being
 *   performed implicitly as part of another command).
 *   
 *   Default reports should be used only for simple acknowledgments of the
 *   command's successful completion - things like "Taken" or "Dropped" or
 *   "Done."
 *   
 *   Default responses are suppressed for implicit commands because they are
 *   redundant.  When a command is performed implicitly, it is conventional
 *   to mention the command being performed with a parenthetical: "(First
 *   taking the book)".  In such cases, a simple acknowledgment that the
 *   command was successfully performed would add nothing of use but would
 *   merely make the output more verbose, so we omit it.  
 */
#define defaultReport(msg, params...) \
    (gTranscript.addReport(new DefaultCommandReport(msg, ##params)))

/*
 *   Set a default descriptive report for the current command.  This report
 *   will be shown unless any other report is shown for the same command.
 *   This differs from defaultReport in that we don't suppress a default
 *   description for an implied command: we only suppress a default
 *   description when there are other reports for the same command.
 *   
 *   The purpose of the default descriptive report is to generate reports
 *   that say things along the lines that there's nothing special to
 *   describe.  For example:
 *   
 *   >x desk
 *.  You see nothing special about it.
 *   
 *   >look in alcove
 *.  There's nothing in the alcove.
 *   
 *   When there's nothing else to report, these default descriptions are
 *   suitable as the full response to the command.  However, they become
 *   undesirable when we have other "status" information or related special
 *   descriptions to display; consider:
 *   
 *   >x desk
 *.  You see nothing special about it.
 *.  Someone has jabbed a dagger into the top of the desk.
 *   
 *   >look in alcove
 *.  There's nothing in the alcove.
 *.  A vase is displayed in the alcove.
 *   
 *   >x bag
 *.  You see nothing special about it.  It's open, and it contains
 *.  a red book, an iron key, and a brass key.
 *   
 *   In the first two examples above, we have special descriptions for
 *   objects contained in the objects being described.  The special
 *   descriptions essentially contradict the default descriptions' claims
 *   that there's nothing special to mention, and also render the default
 *   descriptions unnecessary, in that it would be enough to show just the
 *   special descriptions.  The third example above is similar, but the
 *   extra information is status information for the object being described
 *   rather than a special description of a contained item; as with the
 *   other examples, the generic default description is both contradictory
 *   and unnecessary.
 *   
 *   Default description reports should ONLY be used for messages that have
 *   the character of the examples above: generic descriptions that indicate
 *   explicitly that there's nothing special to report.  Messages that offer
 *   any sort of descriptive detail should NOT be generated as default
 *   description reports, because it is suitable and desirable to retain an
 *   actual descriptive message even when other status information or
 *   related special descriptions are also shown.  
 */
#define defaultDescReport(msg, params...) \
    (gTranscript.addReport(new DefaultDescCommandReport(msg, ##params)))

/*
 *   Add an cosmetic internal spacing report.  This type of report is used
 *   to show spacing (usually a paragraph break) within command output.
 *   
 *   The important thing about this report is that it doesn't trigger
 *   suppression of any default reports.  This is useful when internal
 *   separation is added on speculation that there might be some reports to
 *   separate, but without certainty that there will actually be any reports
 *   shown; for example, when preparing to show a list of special
 *   descriptions, we might add some spacing just in case some special
 *   descriptions will be shown, saving the trouble of checking to see if
 *   anything actually needs to be shown.  
 */
#define cosmeticSpacingReport(msg, params...) \
    (gTranscript.addReport(new CosmeticSpacingCommandReport(msg, ##params)))

/*
 *   Add an "extra" report.  This is an incidental message that doesn't
 *   affect the display of a default report. 
 */
#define extraReport(msg, params...) \
    (gTranscript.addReport(new ExtraCommandReport(msg, ##params)))

/*
 *   Set a main report for the current command.  This report will be shown
 *   as the main report from the command, overriding any default report for
 *   the command.  
 */
#define mainReport(msg, params...) \
    (gTranscript.addReport(new MainCommandReport(msg, ##params)))

/*
 *   Set a "before" report for the current command.  This report will be
 *   shown before any main report, but will override any default report for
 *   the command.  
 */
#define reportBefore(msg, params...) \
    (gTranscript.addReport(new BeforeCommandReport(msg, ##params)))

/*
 *   Set an "after" report for the current command.  This report will be
 *   shown after any main report, but will override any default report for
 *   the command.  
 */
#define reportAfter(msg, params...) \
    (gTranscript.addReport(new AfterCommandReport(msg, ##params)))

/*
 *   Report failure.  This overrides any default report, and marks the
 *   command as having failed.
 *   
 *   A failure report should NOT indicate any state change - this is
 *   important because failure reports are suppressed under some conditions
 *   (for example, when an NPC is performing an implied command, and the
 *   implied command fails, we don't show the failure report).  If a failure
 *   is accompanied by a state change, then a mainReport() should be made in
 *   addition to the failure report - the main report should indicate the
 *   state change.  
 */
#define reportFailure(msg, params...) \
    (gTranscript.addReport(new FailCommandReport(msg, ##params)))

/*
 *   Report a question.  This shows a report that's really an interactive
 *   prompt for more information, such as a prompt for a missing object. 
 */
#define reportQuestion(msg, params...) \
    (gTranscript.addReport(new QuestionCommandReport(msg, ##params)))


/* ------------------------------------------------------------------------ */
/*
 *   Thing message property overrides sometimes need to be selective about
 *   the role of the object.  These macros let you specify that a Thing
 *   message override is only in effect when the Thing is the direct or
 *   indirect object.  When the object isn't in the specified role, the
 *   message override will be ignored.
 *   
 *   For example, suppose you want to override an object's response to PUT
 *   IN, but *only* when it's the indirect object of PUT IN - *not* when the
 *   object is itself being put somewhere.  To do this, you could give the
 *   object a property like this:
 *   
 *.    notAContainerMsg = iobjMsg('The vase\'s opening is too small. ')
 *   
 *   This specifies that when the object is involved in a PUT IN command that
 *   fails with the 'notAContainerMsg' message, the given message should be
 *   used - but *only* when the object is the indirect object.  
 */
#define dobjMsg(msg) (gDobj == self ? msg : nil)
#define iobjMsg(msg) (gIobj == self ? msg : nil)


/* ------------------------------------------------------------------------ */
/*
 *   Try performing a command implicitly.  The action is the root name of
 *   the action, without the 'Action' suffix - we'll automatically add the
 *   suffix.  'objs' is a varying-length list of the resolved objects in the
 *   new action - the direct object, indirect object, and any others needed
 *   for the action.  
 */
#define tryImplicitAction(action, objs...) \
    _tryImplicitAction(gIssuingActor, gActor, &announceImplicitAction, \
    action##Action, ##objs)

/*
 *   Try performing a command implicitly, with a special descriptive
 *   message.  'msgProp' gives the libMessages method to invoke the announce
 *   the action, if the action is performed.  If 'msgProp' is nil, no
 *   message is displayed at all.
 *   
 *   'action' is the root name of the action, without the 'Action' suffix
 *   (we'll automatically add the suffix).  'objs' is a varying-length list
 *   of the resolved objects - direct object, indirect object, and any
 *   others needed.  
 */
#define tryImplicitActionMsg(msgProp, action, objs...) \
    _tryImplicitAction(gIssuingActor, gActor, msgProp, \
                       action##Action, ##objs)

/*
 *   Replace the current action with a new action.  The new action will be
 *   performed, and the original action will be terminated with 'exit'.
 *   
 *   'action' is the root name of the action, without the 'Action' suffix
 *   (we'll add the suffix automatically).  'objs' is a varying-length list
 *   of the resolved objects - direct object, indirect object, etc.  
 */
#define replaceAction(action, objs...) \
    _replaceAction(gActor, action##Action, ##objs)

/*
 *   Replace the current action with a new action directed to a different
 *   actor (but from the same issuing actor).  
 */
#define replaceActorAction(actor, action, objs...) \
    _replaceAction(actor, action##Action, ##objs)

/*
 *   Run a nested action.
 */
#define nestedAction(action, objs...) \
    _nestedAction(nil, gActor, action##Action, ##objs)

/*
 *   Run a nested action targeted to a given actor.
 */
#define nestedActorAction(actor, action, objs...) \
    _nestedAction(nil, actor, action##Action, ##objs)

/*
 *   Run a new action.  This is a brand new action run as a separate turn,
 *   not as a nested action.  This doesn't replace any current action, but is
 *   simply a separate action.
 *   
 *   This is normally used only for internal actions that are run between
 *   other actions.  This should not normally be used while another action is
 *   being processed - use nestedAction for that instead.  This should also
 *   not normally be used to replace the current action with another - use
 *   replaceAction for that.
 *   
 *   Returns a CommandTranscript object, which provides information on the
 *   results of the action.  
 */
#define newAction(action, objs...) \
    _newAction(CommandTranscript, nil, gActor, action##Action, ##objs)

/* run a new action with a specific actor */
#define newActorAction(actor, action, objs...) \
    _newAction(CommandTranscript, nil, actor, action##Action, ##objs)

/*
 *   Ask for a direct object and retry the command using the single-object
 *   phrasing.  This can be used in the action() routine for a no-object
 *   command to ask for the missing direct object.  
 *   
 *   In many cases, there is simply no grammar rule for a zero-object form
 *   of a verb; in such cases, this macro is not needed, since the missing
 *   object is handled via the grammar.  However, for some actions, it is
 *   desirable to allow the zero-object phrasing some of the time, but
 *   require the direct-object phrasing other times.  This macro exists for
 *   these cases, because it allows the intransitive version of the action
 *   to decide, on a case-by-case basis, whether to process the no-object
 *   form of the command or to prompt for a direct object.
 *   
 *   newAction is the root name (without the Action suffix) of the
 *   transitive action to execute.  For example, if we're processing a plain
 *   "in" command, we could use askForDobj(Enter) to ask for a direct object
 *   for the transitive "enter" phrasing. 
 */
#define askForDobj(newAction) \
    (newAction##Action.retryWithMissingDobj(gAction, ResolveAsker))

/*
 *   Ask for an indirect object and retry the command using the two-object
 *   phrasing.  This can be used in the action() routine of a single-object
 *   command to ask for the missing indirect object.
 *   
 *   In many cases, there is simply no grammar rule for a single-object form
 *   of a verb; in such cases, this macro is not needed, since the missing
 *   object is handled via the grammar.  However, for some actions, it is
 *   desirable to allow the single-object phrasing some of the time, but
 *   require the two-object phrasing other times.  This macro exists for
 *   these cases, because it allows the action() routine to decide, on a
 *   case-by-case basis, whether to process the single-object form of the
 *   command or to prompt for an indirect object.
 *   
 *   newAction is the root name (without the Action suffix) of the
 *   two-object form of the action.  For example, if we're processing a
 *   single-object "unlock" command, we would use askForIobj(UnlockWith) to
 *   ask for an indirect object for the "unlock with" two-object phrasing.  
 */
#define askForIobj(newAction) \
    (newAction##Action.retryWithMissingIobj(gAction, ResolveAsker))

/*
 *   Ask for a literal phrase and retry the command using the two-object
 *   phrasing.  This is analogous to askForDobj() and askForIobj(), but for
 *   literal phrases; we effectively convert a TAction into a
 *   LiteralTAction.  
 */
#define askForLiteral(newAction) \
    (newAction##Action.retryWithMissingLiteral(gAction))

/*
 *   Ask for a topic phrase and retry the command using the two-object
 *   phrasing. 
 */
#define askForTopic(newAction) \
    (newAction##Action.retryWithMissingTopic(gAction))

/* ------------------------------------------------------------------------ */
/*
 *   Command interruption signal macros.  
 */

/* a concise macro to throw an ExitSignal */
#define exit throw new ExitSignal()

/* a concise macro to throw an ExitActionSignal */
#define exitAction throw new ExitActionSignal()

/* a concise macro to throw an AbortImplicitSignal */
#define abortImplicit throw new AbortImplicitSignal()


/* ------------------------------------------------------------------------ */
/*
 *   Flags for LOOK AROUND styles 
 */

/* show the room name as part of the description */
#define LookRoomName       0x0001

/* show the room's long desription (the roomDesc) */
#define LookRoomDesc       0x0002

/* show the non-portable items (the specialDesc's) */
#define LookListSpecials   0x0004

/* show the portable items */
#define LookListPortables  0x0008


/* ------------------------------------------------------------------------ */
/*
 *   Template for multi-location objects.  To put a MultiLoc object in
 *   several initial locations, simply use a template giving the list of
 *   locations.  
 */
MultiLoc template [locationList];


/* ------------------------------------------------------------------------ */
/*
 *   Templates for style tags 
 */
StyleTag template 'tagName' 'openText'? 'closeText'?;


/* ------------------------------------------------------------------------ */
/*
 *   A template for footnotes - all we usually need to define in a footnote
 *   is its descriptive text, so this makes it easy to define one.  
 */
Footnote template "desc";

/* footnote status levels */
enum FootnotesOff, FootnotesMedium, FootnotesFull;


/* ------------------------------------------------------------------------ */
/*
 *   An achievement defines its descriptive text.  It can also optionally
 *   define the number of points it awards.  
 */
Achievement template +points? "desc";


/* ------------------------------------------------------------------------ */
/* 
 *   An event list takes a list of strings, objects, and/or functions.
 */
EventList template [eventList];

/* 
 *   A shuffled event list with two lists - the first list is the sequential
 *   initial list, fired in the exact order specified; and the second is the
 *   random list, with the events that occur in shuffled order after we
 *   exhaust the initial list.  
 */
ShuffledEventList template [firstEvents] [eventList];

/* a synchronized event list takes its state from another list */
SyncEventList template ->masterObject inherited;

/* low-level shuffled list */
ShuffledList template [valueList];


/* ------------------------------------------------------------------------ */
/*
 *   Define a template for the Tip class.
 */
Tip template "desc";


/* ------------------------------------------------------------------------ */
/*
 *   Definitions for the menu system
 */

/* 
 *   The indices for the key values used to navigate menus, which are held
 *   in the keyList array of MenuItems.  
 */
#define M_QUIT      1
#define M_PREV      2
#define M_UP        3
#define M_DOWN      4
#define M_SEL       5

/* some templates for defining menu items */
MenuItem template 'title' 'heading'?;
MenuTopicItem template 'title' 'heading'? [menuContents];
MenuLongTopicItem template 'title' 'heading'? 'menuContents';

/* templates for hint system objects */
Goal template ->closeWhenAchieved? 'title' 'heading'? [menuContents];
Hint template 'hintText' [referencedGoals]?;

/* ------------------------------------------------------------------------ */
/*
 *   Templates for topic database entries.  
 */

/*
 *   A TopicEntry can be defined with an optional score, followed by the
 *   match criteria (which can be either a single matching object, a list of
 *   matching objects, or a regular expression pattern string), followed by
 *   the optional response text (which can be given either as a double-quoted
 *   string or as a list of single-quoted strings to use as an EventList).
 */
TopicEntry template
   +matchScore?
   @matchObj | [matchObj] | 'matchPattern'
   "topicResponse" | [eventList] ?;

/* a ShuffledEventList version of the above */
TopicEntry template
   +matchScore?
   @matchObj | [matchObj] | 'matchPattern'
   [firstEvents] [eventList];

/* we can also include *both* the match object/list *and* pattern */
TopicEntry template
   +matchScore?
   @matchObj | [matchObj]
   'matchPattern'
   "topicResponse" | [eventList] ?;

/* a ShuffledEventList version of the above */
TopicEntry template
   +matchScore?
   @matchObj | [matchObj]
   'matchPattern'
   [firstEvents] [eventList];

/* miscellanous topics just specify the response text or list */
MiscTopic template "topicResponse" | [eventList];
MiscTopic template [firstEvents] [eventList];

/* 
 *   A SpecialTopic takes a keyword list or a regular expression instead of
 *   the regular match criteria.  It also takes a suggestion name string and
 *   the normal response text.  There's no need for a score in a special
 *   topic, since these are unique.  
 */
SpecialTopic template
   'name'
   [keywordList] | 'matchPat'
   "topicResponse" | [eventList] ?;

/* a ShuffledEventList version of the above */
SpecialTopic template
   'name'
   [keywordList] | 'matchPat'
   [firstEvents] [eventList];

/* default topics just specify the response text */
DefaultTopic template "topicResponse" | [eventList];
DefaultTopic template [firstEvents] [eventList];

/* alternative topics just specify the response string or strings */
AltTopic template "topicResponse" | [eventList];
AltTopic template [firstEvents] [eventList];

/* a TopicGroup can specify its score adjustment */
TopicGroup template +matchScoreAdjustment;

/* a conversation node need a name */
ConvNode template 'name';

/*
 *   End-of-conversation reason codes 
 */
enum endConvBye;                                    /* player typed GOODBYE */
enum endConvTravel;         /* the other character is trying to travel away */
enum endConvBoredom;                /* our attentionSpan has been exhausted */
enum endConvActor;     /* the NPC itself (not the player) is saying GOODBYE */

/*
 *   Special result code for Actor.canEndConversation() - this indicates that
 *   the other actor said something to force the conversation to keep going. 
 */
enum blockEndConv;

/* ------------------------------------------------------------------------ */
/*
 *   Conversation manager macros
 */

/* has a topic key been revealed through <.reveal>? */
#define gRevealed(key) (conversationManager.revealedNameTab[key] != nil)

/* reveal a topic key, as though through <.reveal> */
#define gReveal(key) (conversationManager.setRevealed(key))

/* mark a Topic/Thing as known/seen by the player character */
#define gSetKnown(obj) (gPlayerChar.setKnowsAbout(obj))
#define gSetSeen(obj) (gPlayerChar.setHasSeen(obj))


/* ------------------------------------------------------------------------ */
/*
 *   For compatibility with versions before 3.1.1, define
 *   openableContentsLister as a synonym for openableDescContentsLister.  The
 *   former was renamed to the latter in 3.1.1 because the original name was
 *   inconsistent with the corresponding listers for other classes.  In
 *   principle, openableContentsLister is meant to be the 'contentsLister'
 *   (for displaying the openable's contents in room descriptions, etc) for
 *   an Openable, while openableDescContentsLister is its
 *   'descContentsLister' (for displaying the openable's contents in its own
 *   EXAMINE description).  Fortunately we don't have a need for a special
 *   contentsLister for Openable, so we can avoid breaking existing code by
 *   mapping the old name to the new name.
 */
#define openableContentsLister openableDescContentsLister


#endif /* ADV3_H */
TADS 3 Library Manual
Generated on 5/16/2013 from TADS version 3.1.3