adv3.hfile | source file |
Classes Summary | Functions Summary Details | Macros Summary Details | Enums Summary Details | Templates Summary Details |
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.
abortImplicit
actorStateDobjFor
actorStateIobjFor
actorStateObjFor
ADV3_H
AHREF_Plain
AlwaysAnnounce
AnnouncedDefaultObject
asDobjFor
asDobjWithoutActionFor
asExit
asIobjFor
asIobjWithoutActionFor
askForDobj
askForIobj
askForLiteral
askForTopic
asObjFor
asObjWithoutActionFor
BaseDefineTopicTAction
canInherit
ClearDisambig
cosmeticSpacingReport
dangerous
dbgShowGrammarList
dbgShowGrammarList
dbgShowGrammarWithCaption
dbgShowGrammarWithCaption
defaultDescReport
DefaultObject
defaultReport
DefineAction
DefineConvIAction
DefineConvTopicTAction
DefineIAction
DefineLiteralAction
DefineLiteralTAction
DefineSystemAction
DefineTAction
DefineTActionSub
DefineTIAction
DefineTIActionSub
DefineTopicAction
DefineTopicTAction
DigitFormatGroupComma
DigitFormatGroupPeriod
DigitFormatGroupSep
dobjFor
dobjMsg
EndsWithAdj
exit
exitAction
extraReport
FirstPerson
gAction
gActionIn
gActionIs
gActor
gDobj
gExitLister
gHintManager
gIobj
gIssuingActor
gLibMessages
gLiteral
gMessageParams
gPlayerChar
gReveal
gRevealed
gSetKnown
gSetSeen
gSynthMessageParam
gTentativeDobj
gTentativeIobj
gTopic
gTopicText
gTranscript
gVerifyResults
illogical
illogicalAlready
illogicalNow
illogicalSelf
inaccessible
iobjFor
iobjMsg
ListContents
ListCustomFlag
ListerCustomFlag
ListLong
ListRecurse
ListTall
logical
logicalRank
logicalRankOrd
LookListPortables
LookListSpecials
LookRoomDesc
LookRoomName
M_DOWN
M_PREV
M_QUIT
M_SEL
M_UP
mainReport
mapPushTravelHandlers
mapPushTravelIobj
MatchedAll
maybeRemapTo
nestedAction
nestedActorAction
newAction
newActorAction
nonObvious
objFor
objForCheck
objForCheck
openableContentsLister
PARSER_DEBUG
PluralTruncated
remapTo
replaceAction
replaceActorAction
reportAfter
reportBefore
reportFailure
reportQuestion
SecondPerson
SpellIntAndTens
SpellIntCommas
SpellIntTeenHundreds
ThirdPerson
tryImplicitAction
tryImplicitActionMsg
UnclearDisambig
VocabTruncated
ActorObject
AnnounceClear
AnnounceUnclear
attenuated
blockEndConv
DescribeClear
DirectObject
distant
endConvActor
endConvBoredom
endConvBye
endConvTravel
FootnotesFull
FootnotesMedium
FootnotesOff
IndirectObject
InventoryTall
InventoryWide
large
medium
obscured
opaque
OtherObject
PathFrom
PathIn
PathOut
PathPeer
PathThrough
PathTo
PronounHer
PronounHim
PronounIt
PronounMe
PronounThem
PronounYou
rmcAskLiteral
rmcAskObject
rmcCommand
rmcDisambig
rmcOops
small
transparent
Achievement
AltTopic
AltTopic
ConvNode
DefaultTopic
DefaultTopic
EventList
Footnote
Goal
Hint
MenuItem
MenuLongTopicItem
MenuTopicItem
MiscTopic
MiscTopic
MultiLoc
ShuffledEventList
ShuffledList
SpecialTopic
SpecialTopic
StyleTag
SyncEventList
Tip
TopicEntry
TopicEntry
TopicEntry
TopicEntry
TopicGroup
abortImplicit | adv3.h[1569] |
throw new AbortImplicitSignal()
actorStateDobjFor (action) | adv3.h[480] |
actorStateObjFor(Dobj, action)
actorStateIobjFor (action) | adv3.h[481] |
actorStateObjFor(Iobj, action)
actorStateObjFor (obj, Action) | adv3.h[471] |
{ \
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; } \
}
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.
ADV3_H | adv3.h[16] |
AHREF_Plain | adv3.h[819] |
0x0001 /* plain text hyperlink (no underline/color) */
AlwaysAnnounce | adv3.h[870] |
0x0010
AnnouncedDefaultObject | adv3.h[921] |
0x0100
asDobjFor (action) | adv3.h[357] |
asObjFor(Dobj, action)
asDobjWithoutActionFor (action) | adv3.h[377] |
asObjWithoutActionFor(Dobj, action)
asExit (dir) | adv3.h[581] |
= static ((dir).createUnlistedProxy())
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.
asIobjFor (action) | adv3.h[358] |
asObjFor(Iobj, action)
asIobjWithoutActionFor (action) | adv3.h[378] |
asObjWithoutActionFor(Iobj, action)
askForDobj (newAction) | adv3.h[1516] |
(newAction##Action.retryWithMissingDobj(gAction, ResolveAsker))
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.
askForIobj (newAction) | adv3.h[1538] |
(newAction##Action.retryWithMissingIobj(gAction, ResolveAsker))
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.
askForLiteral (newAction) | adv3.h[1547] |
(newAction##Action.retryWithMissingLiteral(gAction))
askForTopic (newAction) | adv3.h[1554] |
(newAction##Action.retryWithMissingTopic(gAction))
asObjFor (obj, Action) | adv3.h[348] |
{ \
preCond { return preCond##obj##Action; } \
verify() { verify##obj##Action; } \
remap() { return remap##obj##Action; } \
check() { check##obj##Action; } \
action() { action##obj##Action; } \
}
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.
asObjWithoutActionFor (obj, Action) | adv3.h[368] |
{ \
preCond { return preCond##obj##Action; } \
verify() { verify##obj##Action; } \
remap() { return remap##obj##Action(); } \
check() { check##obj##Action; } \
action() { } \
}
BaseDefineTopicTAction (name, which, cls) | adv3.h[1069] |
DefineAction(name, cls) \
verDobjProp = &verifyDobj##name \
remapDobjProp = &remapDobj##name \
preCondDobjProp = &preCondDobj##name \
checkDobjProp = &checkDobj##name \
actionDobjProp = &actionDobj##name \
whichMessageTopic = which
canInherit | adv3.h[47] |
propInherited(targetprop, targetobj, definingobj, PropDefAny)
ClearDisambig | adv3.h[878] |
0x0020
cosmeticSpacingReport (msg, params, ...) | adv3.h[1339] |
(gTranscript.addReport(new CosmeticSpacingCommandReport(msg, ##params)))
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.
dangerous | adv3.h[1213] |
(gVerifyResults.addResult(new DangerousVerifyResult('')))
dbgShowGrammarList (lst) | adv3.h[90] |
showGrammarList(lst)
dbgShowGrammarList (lst) | adv3.h[96] |
dbgShowGrammarWithCaption (headline, match) | adv3.h[91] |
showGrammarWithCaption(headline, match)
dbgShowGrammarWithCaption (headline, match) | adv3.h[97] |
defaultDescReport (msg, params, ...) | adv3.h[1323] |
(gTranscript.addReport(new DefaultDescCommandReport(msg, ##params)))
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.
DefaultObject | adv3.h[911] |
0x0080
defaultReport (msg, params, ...) | adv3.h[1267] |
(gTranscript.addReport(new DefaultCommandReport(msg, ##params)))
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.
DefineAction (name, baseClass, ...) | adv3.h[986] |
class name##Action: ##baseClass \
baseActionClass = name##Action
DefineConvIAction (name) | adv3.h[1006] |
DefineAction(name, ConvIAction)
DefineConvTopicTAction (name, which) | adv3.h[1086] |
BaseDefineTopicTAction(name, which, ConvTopicTAction)
DefineIAction (name) | adv3.h[1002] |
DefineAction(name, IAction)
DefineLiteralAction (name) | adv3.h[1092] |
DefineAction(name, LiteralAction)
DefineLiteralTAction (name, which) | adv3.h[1102] |
DefineAction(name, LiteralTAction) \
verDobjProp = &verifyDobj##name \
remapDobjProp = &remapDobj##name \
preCondDobjProp = &preCondDobj##name \
checkDobjProp = &checkDobj##name \
actionDobjProp = &actionDobj##name \
whichMessageLiteral = which
DefineSystemAction (name) | adv3.h[995] |
DefineAction(name, SystemAction)
DefineTAction (name) | adv3.h[1015] |
DefineTActionSub(name, TAction)
DefineTActionSub (name, cls) | adv3.h[1021] |
DefineAction(name, cls) \
verDobjProp = &verifyDobj##name \
remapDobjProp = &remapDobj##name \
preCondDobjProp = &preCondDobj##name \
checkDobjProp = &checkDobj##name \
actionDobjProp = &actionDobj##name \
DefineTIAction (name) | adv3.h[1037] |
DefineTIActionSub(name, TIAction)
DefineTIActionSub (name, cls) | adv3.h[1043] |
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
DefineTopicAction (name) | adv3.h[1059] |
DefineAction(name, TopicAction)
DefineTopicTAction (name, which) | adv3.h[1078] |
BaseDefineTopicTAction(name, which, TopicTAction)
DigitFormatGroupComma | adv3.h[811] |
0x0002
DigitFormatGroupPeriod | adv3.h[812] |
0x0004
DigitFormatGroupSep | adv3.h[805] |
0x0001
dobjFor (action) | adv3.h[309] |
objFor(Dobj, action)
dobjMsg (msg) | adv3.h[1415] |
(gDobj == self ? msg : nil)
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.
EndsWithAdj | adv3.h[828] |
0x0001
exit | adv3.h[1563] |
throw new ExitSignal()
exitAction | adv3.h[1566] |
throw new ExitActionSignal()
extraReport (msg, params, ...) | adv3.h[1346] |
(gTranscript.addReport(new ExtraCommandReport(msg, ##params)))
FirstPerson | adv3.h[589] |
1
gAction | adv3.h[159] |
(libGlobal.curAction)
gActionIn (action, ...) | adv3.h[175] |
(gAction != nil \
&& (action#foreach/gAction.actionOfKind(action##Action)/||/))
gActionIs (action) | adv3.h[171] |
(gAction != nil && gAction.actionOfKind(action##Action))
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.
gActor | adv3.h[110] |
(libGlobal.curActor)
gDobj | adv3.h[118] |
(gAction.getDobj())
gExitLister | adv3.h[227] |
(libGlobal.exitListerObj)
gHintManager | adv3.h[233] |
(libGlobal.hintManagerObj)
gIobj | adv3.h[119] |
(gAction.getIobj())
gIssuingActor | adv3.h[156] |
(libGlobal.curIssuingActor)
gLibMessages | adv3.h[255] |
(libGlobal.libMessageObj)
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.)
gLiteral | adv3.h[130] |
(gAction.getLiteral())
gMessageParams (var, ...) | adv3.h[201] |
(gAction.setMessageParams(var#foreach/#@var, var/,/))
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.
gPlayerChar | adv3.h[221] |
(libGlobal.playerChar)
gReveal (key) | adv3.h[1772] |
(conversationManager.setRevealed(key))
gRevealed (key) | adv3.h[1769] |
(conversationManager.revealedNameTab[key] != nil)
gSetKnown (obj) | adv3.h[1775] |
(gPlayerChar.setKnowsAbout(obj))
gSetSeen (obj) | adv3.h[1776] |
(gPlayerChar.setHasSeen(obj))
gSynthMessageParam (var) | adv3.h[212] |
(gAction.synthMessageParam(var))
gTentativeDobj | adv3.h[147] |
(gAction.getTentativeDobj())
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.
gTentativeIobj | adv3.h[148] |
(gAction.getTentativeIobj())
gTopic | adv3.h[126] |
(gAction.getTopic())
gTopicText | adv3.h[127] |
(gTopic.getTopicText.toLower())
gTranscript | adv3.h[183] |
(mainOutputStream.curTranscript)
gVerifyResults | adv3.h[180] |
(libGlobal.curVerifyResults)
illogical (msg, params, ...) | adv3.h[1233] |
(gVerifyResults.addResult(new IllogicalVerifyResult(msg, ##params)))
illogicalAlready (msg, params, ...) | adv3.h[1228] |
(gVerifyResults.addResult( \
new IllogicalAlreadyVerifyResult(msg, ##params)))
illogicalNow (msg, params, ...) | adv3.h[1224] |
(gVerifyResults.addResult(new IllogicalNowVerifyResult(msg, ##params)))
illogicalSelf (msg, params, ...) | adv3.h[1237] |
(gVerifyResults.addResult(new IllogicalSelfVerifyResult(msg, ##params)))
inaccessible (msg, params, ...) | adv3.h[1241] |
(gVerifyResults.addResult(new InaccessibleVerifyResult(msg, ##params)))
iobjFor (action) | adv3.h[310] |
objFor(Iobj, action)
iobjMsg (msg) | adv3.h[1416] |
(gIobj == self ? msg : nil)
ListContents | adv3.h[728] |
0x0008
ListCustomFlag | adv3.h[757] |
0x0100
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)
ListerCustomFlag (n) | adv3.h[759] |
static ((inherited.nextCustomFlag) << ((n) - 1))
ListLong | adv3.h[722] |
0x0004
ListRecurse | adv3.h[714] |
0x0002
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.
ListTall | adv3.h[693] |
0x0001
logical | adv3.h[1134] |
(gVerifyResults.addResult(new LogicalVerifyResult(100, '', 100)))
We use 100 as the default likelihood, to leave plenty of room for specific likelihood rankings both above and below the default level.
logicalRank (rank, key) | adv3.h[1201] |
(gVerifyResults.addResult(new LogicalVerifyResult(rank, key, 100)))
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.
logicalRankOrd (rank, key, ord) | adv3.h[1209] |
(gVerifyResults.addResult(new LogicalVerifyResult(rank, key, ord)))
LookListPortables | adv3.h[1587] |
0x0008
LookListSpecials | adv3.h[1584] |
0x0004
LookRoomDesc | adv3.h[1581] |
0x0002
LookRoomName | adv3.h[1578] |
0x0001
M_DOWN | adv3.h[1665] |
4
M_PREV | adv3.h[1663] |
2
M_QUIT | adv3.h[1662] |
1
M_SEL | adv3.h[1666] |
5
M_UP | adv3.h[1664] |
3
mainReport (msg, params, ...) | adv3.h[1354] |
(gTranscript.addReport(new MainCommandReport(msg, ##params)))
mapPushTravelHandlers (pushAction, travelAction) | adv3.h[443] |
dobjFor(pushAction) asDobjFor(PushTravel) \
mapPushTravelIobj(pushAction, travelAction)
- 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.
mapPushTravelIobj (pushAction, travelAction) | adv3.h[447] |
iobjFor(pushAction) \
{ \
verify() \
{ gAction.verifyPushTravelIobj(self, travelAction##Action); } \
}
MatchedAll | adv3.h[860] |
0x0008
maybeRemapTo (cond, action, objs, ...) | adv3.h[411] |
{ remap = ((cond) ? [action##Action, ##objs] : inherited()) }
nestedAction (action, objs, ...) | adv3.h[1467] |
_nestedAction(nil, gActor, action##Action, ##objs)
nestedActorAction (actor, action, objs, ...) | adv3.h[1473] |
_nestedAction(nil, actor, action##Action, ##objs)
newAction (action, objs, ...) | adv3.h[1490] |
_newAction(CommandTranscript, nil, gActor, action##Action, ##objs)
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.
newActorAction (actor, action, objs, ...) | adv3.h[1494] |
_newAction(CommandTranscript, nil, actor, action##Action, ##objs)
nonObvious | adv3.h[1220] |
(gVerifyResults.addResult(new NonObviousVerifyResult('')))
objFor (which, action) | adv3.h[305] |
objForCheck(which, action) \
propertyset '*' ## #@which ## #@action
objForCheck (which, action) | adv3.h[299] |
sentinel##which##action = __objref(action##Action, warn)
objForCheck (which, action) | adv3.h[302] |
openableContentsLister | adv3.h[1793] |
openableDescContentsLister
PARSER_DEBUG | adv3.h[81] |
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).
PluralTruncated | adv3.h[850] |
0x0004
remapTo (action, objs, ...) | adv3.h[404] |
{ remap = [action##Action, ##objs] }
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)
replaceAction (action, objs, ...) | adv3.h[1454] |
_replaceAction(gActor, action##Action, ##objs)
'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.
replaceActorAction (actor, action, objs, ...) | adv3.h[1461] |
_replaceAction(actor, action##Action, ##objs)
reportAfter (msg, params, ...) | adv3.h[1370] |
(gTranscript.addReport(new AfterCommandReport(msg, ##params)))
reportBefore (msg, params, ...) | adv3.h[1362] |
(gTranscript.addReport(new BeforeCommandReport(msg, ##params)))
reportFailure (msg, params, ...) | adv3.h[1385] |
(gTranscript.addReport(new FailCommandReport(msg, ##params)))
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.
reportQuestion (msg, params, ...) | adv3.h[1392] |
(gTranscript.addReport(new QuestionCommandReport(msg, ##params)))
SecondPerson | adv3.h[590] |
2
SpellIntAndTens | adv3.h[785] |
0x0002
SpellIntCommas | adv3.h[791] |
0x0004
SpellIntTeenHundreds | adv3.h[779] |
0x0001
ThirdPerson | adv3.h[591] |
3
tryImplicitAction (action, objs, ...) | adv3.h[1427] |
_tryImplicitAction(gIssuingActor, gActor, &announceImplicitAction, \
action##Action, ##objs)
tryImplicitActionMsg (msgProp, action, objs, ...) | adv3.h[1442] |
_tryImplicitAction(gIssuingActor, gActor, msgProp, \
action##Action, ##objs)
'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.
UnclearDisambig | adv3.h[905] |
0x0040
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.
VocabTruncated | adv3.h[834] |
0x0002
ActorObject DirectObject IndirectObject
| adv3.h[498] |
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.
AnnounceClear
| adv3.h[950] |
AnnounceUnclear
| adv3.h[940] |
attenuated
| adv3.h[610] |
blockEndConv
| adv3.h[1761] |
DescribeClear
| adv3.h[963] |
distant
| adv3.h[603] |
endConvActor
| adv3.h[1755] |
endConvBoredom
| adv3.h[1754] |
endConvBye
| adv3.h[1752] |
endConvTravel
| adv3.h[1753] |
FootnotesFull FootnotesMedium FootnotesOff
| adv3.h[1614] |
InventoryTall InventoryWide
| adv3.h[972] |
large
| adv3.h[639] |
medium
| adv3.h[646] |
obscured
| adv3.h[618] |
opaque
| adv3.h[621] |
OtherObject
| adv3.h[507] |
PathFrom
| adv3.h[661] |
PathIn
| adv3.h[664] |
PathOut
| adv3.h[667] |
PathPeer
| adv3.h[670] |
PathThrough
| adv3.h[677] |
PathTo
| adv3.h[680] |
PronounHer PronounHim PronounIt PronounMe PronounThem PronounYou
| adv3.h[538] |
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.
rmcAskLiteral
| adv3.h[286] |
rmcAskObject
| adv3.h[283] |
rmcCommand
| adv3.h[277] |
rmcDisambig
| adv3.h[289] |
rmcOops
| adv3.h[280] |
small
| adv3.h[652] |
transparent
| adv3.h[600] |
Achievement | adv3.h[1622] |
+points? "desc";
AltTopic | adv3.h[1740] |
"topicResponse" | [eventList];
AltTopic | adv3.h[1741] |
[firstEvents] [eventList];
ConvNode | adv3.h[1747] |
'name';
DefaultTopic | adv3.h[1736] |
"topicResponse" | [eventList];
DefaultTopic | adv3.h[1737] |
[firstEvents] [eventList];
EventList | adv3.h[1629] |
[eventList];
Footnote | adv3.h[1611] |
"desc";
Goal | adv3.h[1674] |
->closeWhenAchieved? 'title' 'heading'? [menuContents];
Hint | adv3.h[1675] |
'hintText' [referencedGoals]?;
MenuItem | adv3.h[1669] |
'title' 'heading'?;
MenuLongTopicItem | adv3.h[1671] |
'title' 'heading'? 'menuContents';
MenuTopicItem | adv3.h[1670] |
'title' 'heading'? [menuContents];
MiscTopic | adv3.h[1715] |
"topicResponse" | [eventList];
MiscTopic | adv3.h[1716] |
[firstEvents] [eventList];
MultiLoc | adv3.h[1596] |
[locationList];
ShuffledEventList | adv3.h[1637] |
[firstEvents] [eventList];
ShuffledList | adv3.h[1643] |
[valueList];
SpecialTopic | adv3.h[1724] |
'name' [keywordList] | 'matchPat' "topicResponse" | [eventList] ?;
SpecialTopic | adv3.h[1730] |
'name' [keywordList] | 'matchPat' [firstEvents] [eventList];
StyleTag | adv3.h[1603] |
'tagName' 'openText'? 'closeText'?;
SyncEventList | adv3.h[1640] |
->masterObject inherited;
Tip | adv3.h[1650] |
"desc";
TopicEntry | adv3.h[1689] |
+matchScore? @matchObj | [matchObj] | 'matchPattern' "topicResponse" | [eventList] ?;
TopicEntry | adv3.h[1695] |
+matchScore? @matchObj | [matchObj] | 'matchPattern' [firstEvents] [eventList];
TopicEntry | adv3.h[1701] |
+matchScore? @matchObj | [matchObj] 'matchPattern' "topicResponse" | [eventList] ?;
TopicEntry | adv3.h[1708] |
+matchScore? @matchObj | [matchObj] 'matchPattern' [firstEvents] [eventList];
TopicGroup | adv3.h[1744] |
+matchScoreAdjustment;