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 <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 
  */
 
 #define objFor(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
 
 
 /* ------------------------------------------------------------------------ */
 /*
  *   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
 
 
 /* ------------------------------------------------------------------------ */
 /*
  *   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;
 
 
 /* ------------------------------------------------------------------------ */
 /*
  *   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])
 
 /* reveal a topic key, as though through <.reveal> */
 #define gReveal(key) (conversationManager.revealedNameTab[key] = true)
 
 /* mark a Topic/Thing as known/seen by the player character */
 #define gSetKnown(obj) (gPlayerChar.setKnowsAbout(obj))
 #define gSetSeen(obj) (gPlayerChar.setHasSeen(obj))
 
 #endif /* ADV3_H */
TADS 3 Library Manual
Generated on 9/8/2006 from TADS version 3.0.11