| | 1 | #charset "us-ascii" |
| | 2 | |
| | 3 | /* |
| | 4 | * Copyright (c) 2000, 2006 Michael J. Roberts. All Rights Reserved. |
| | 5 | * |
| | 6 | * TADS 3 Library - main header |
| | 7 | * |
| | 8 | * This file provides definitions of macros, properties, and other |
| | 9 | * identifiers used throughout the library and in game source. |
| | 10 | * |
| | 11 | * Each source code file in the library and in a game should generally |
| | 12 | * #include this header near the top of the source file. |
| | 13 | */ |
| | 14 | |
| | 15 | #ifndef ADV3_H |
| | 16 | #define ADV3_H |
| | 17 | |
| | 18 | /* ------------------------------------------------------------------------ */ |
| | 19 | /* |
| | 20 | * Include the system headers that we depend upon. We include these here |
| | 21 | * so that each game source file will pick up the same set of system |
| | 22 | * headers in the same order, which is important for intrinsic function |
| | 23 | * set definitions. |
| | 24 | */ |
| | 25 | #include <tads.h> |
| | 26 | #include <tok.h> |
| | 27 | #include <t3.h> |
| | 28 | #include <vector.h> |
| | 29 | #include <file.h> |
| | 30 | #include <dict.h> |
| | 31 | |
| | 32 | |
| | 33 | /* ------------------------------------------------------------------------ */ |
| | 34 | /* |
| | 35 | * Establish the default dictionary for the game's player command parser |
| | 36 | * vocabulary. |
| | 37 | */ |
| | 38 | dictionary cmdDict; |
| | 39 | |
| | 40 | /* ------------------------------------------------------------------------ */ |
| | 41 | /* |
| | 42 | * canInherit - determine if there's anything to inherit from the current |
| | 43 | * method. Returns true if there's a method to inherit, nil if |
| | 44 | * 'inherited' in the current context would not invoke any code. |
| | 45 | */ |
| | 46 | #define canInherit() \ |
| | 47 | propInherited(targetprop, targetobj, definingobj, PropDefAny) |
| | 48 | |
| | 49 | |
| | 50 | /* ------------------------------------------------------------------------ */ |
| | 51 | /* |
| | 52 | * Generic part of speech for "miscellaneous word." We use this to |
| | 53 | * classify words in unstructured phrases; it can apply to any token. |
| | 54 | * Note that dictionary entries are never made with this word type, so |
| | 55 | * it's not specific to any language; this is merely for flagging words in |
| | 56 | * unstructured phrases in grammar matches. |
| | 57 | */ |
| | 58 | dictionary property miscWord; |
| | 59 | |
| | 60 | /* |
| | 61 | * Generic part of speech for SpecialTopic words. We enter special topic |
| | 62 | * keywords into the parser dictionary so that they're not flagged as |
| | 63 | * unknown words if they're used out of context. |
| | 64 | */ |
| | 65 | dictionary property specialTopicWord; |
| | 66 | |
| | 67 | |
| | 68 | /* ------------------------------------------------------------------------ */ |
| | 69 | /* |
| | 70 | * If we're compiling for debugging, automatically include the parser |
| | 71 | * debug code, which allows certain information on the parsing process |
| | 72 | * (such as grammar match trees) to be displayed each time a command is |
| | 73 | * typed. |
| | 74 | * |
| | 75 | * Note that you can turn on parser debugging independently of full |
| | 76 | * compiler debug information simply by explicitly defining PARSER_DEBUG |
| | 77 | * (with the t3make -D option, for example). |
| | 78 | */ |
| | 79 | #ifdef __DEBUG |
| | 80 | #define PARSER_DEBUG |
| | 81 | #endif |
| | 82 | |
| | 83 | /* |
| | 84 | * Define some convenience macros for parser debug operations. When |
| | 85 | * PARSER_DEBUG isn't defined, these macros expand out to nothing. |
| | 86 | */ |
| | 87 | #ifdef PARSER_DEBUG |
| | 88 | |
| | 89 | #define dbgShowGrammarList(lst) showGrammarList(lst) |
| | 90 | #define dbgShowGrammarWithCaption(headline, match) \ |
| | 91 | showGrammarWithCaption(headline, match) |
| | 92 | |
| | 93 | #else /* PARSER_DEBUG */ |
| | 94 | |
| | 95 | #define dbgShowGrammarList(lst) |
| | 96 | #define dbgShowGrammarWithCaption(headline, match) |
| | 97 | |
| | 98 | #endif /* PARSER_DEBUG */ |
| | 99 | |
| | 100 | |
| | 101 | /* ------------------------------------------------------------------------ */ |
| | 102 | /* |
| | 103 | * Parser global variables giving information on the command currently |
| | 104 | * being performed. These are valid through doAction processing. These |
| | 105 | * should never be changed except by the parser. |
| | 106 | */ |
| | 107 | |
| | 108 | /* the actor performing the current command */ |
| | 109 | #define gActor (libGlobal.curActor) |
| | 110 | |
| | 111 | /* |
| | 112 | * For convenience, define some macros that return the current direct and |
| | 113 | * indirect objects from the current action. The library only uses direct |
| | 114 | * and indirect objects, so games that define additional command objects |
| | 115 | * will have to add their own similar macros for those. |
| | 116 | */ |
| | 117 | #define gDobj (gAction.getDobj()) |
| | 118 | #define gIobj (gAction.getIobj()) |
| | 119 | |
| | 120 | /* |
| | 121 | * Get the current ResolvedTopic, and the literal text of the topic phrase |
| | 122 | * as the user typed it (but converted to lower case). These are |
| | 123 | * applicable when the current action has a topic phrase. |
| | 124 | */ |
| | 125 | #define gTopic (gAction.getTopic()) |
| | 126 | #define gTopicText (gTopic.getTopicText.toLower()) |
| | 127 | |
| | 128 | /* get the current literal phrase text, when the command has one */ |
| | 129 | #define gLiteral (gAction.getLiteral()) |
| | 130 | |
| | 131 | /* |
| | 132 | * The tentative pre-resolution lists for the direct and indirect objects. |
| | 133 | * When we're resolving an object of a multi-object command, these |
| | 134 | * pre-resolution lists are available for the later-resolved objects. |
| | 135 | * |
| | 136 | * Note that these values are list of ResolveInfo objects. The obj_ |
| | 137 | * property of a list entry gives the entry's game-world object. |
| | 138 | * |
| | 139 | * These lists do not provide the final resolution lists for the objects; |
| | 140 | * rather, they provide a tentative set of possibilities based on the |
| | 141 | * information that's available without knowing the results of resolving |
| | 142 | * the earlier-resolved objects yet. |
| | 143 | * |
| | 144 | * These are not meaningful when resolving single-object actions. |
| | 145 | */ |
| | 146 | #define gTentativeDobj (gAction.getTentativeDobj()) |
| | 147 | #define gTentativeIobj (gAction.getTentativeIobj()) |
| | 148 | |
| | 149 | /* |
| | 150 | * the actor who *issued* the current command (this is usually the player |
| | 151 | * character, because most commands are initiated by the player on the |
| | 152 | * command line, but it is also possible for one actor to send a command |
| | 153 | * to another programmatically) |
| | 154 | */ |
| | 155 | #define gIssuingActor (libGlobal.curIssuingActor) |
| | 156 | |
| | 157 | /* the Action object of the command being executed */ |
| | 158 | #define gAction (libGlobal.curAction) |
| | 159 | |
| | 160 | /* |
| | 161 | * Determine if the current global action is the specified action. Only |
| | 162 | * the action prefix is needed - so use "Take" rather than "TakeAction" |
| | 163 | * here. |
| | 164 | * |
| | 165 | * This tests to see if the current global action is an instance of the |
| | 166 | * given action class - we test that it's an instance rather than the |
| | 167 | * action class itself because the parser creates an instance of the |
| | 168 | * action when it matches the action's syntax. |
| | 169 | */ |
| | 170 | #define gActionIs(action) \ |
| | 171 | (gAction != nil && gAction.actionOfKind(action##Action)) |
| | 172 | |
| | 173 | /* is the current global action ANY of the specified actions? */ |
| | 174 | #define gActionIn(action...) \ |
| | 175 | (gAction != nil \ |
| | 176 | && (action#foreach/gAction.actionOfKind(action##Action)/||/)) |
| | 177 | |
| | 178 | /* the verification results object - this is valid during verification */ |
| | 179 | #define gVerifyResults (libGlobal.curVerifyResults) |
| | 180 | |
| | 181 | /* the command transcript object - this is valid during command execution */ |
| | 182 | #define gTranscript (mainOutputStream.curTranscript) |
| | 183 | |
| | 184 | /* |
| | 185 | * Some message processors add their own special parameters to messages, |
| | 186 | * because they want to use expansion parameters (in the "{the dobj/him}" |
| | 187 | * format) outside of the set of objects directly involved in the command. |
| | 188 | * |
| | 189 | * The Action method setMessageParam() lets you define such a parameter, |
| | 190 | * but for convenience, we define this macro for setting one or more |
| | 191 | * parameters whose names exactly match their local variable names. In |
| | 192 | * other words, if you call this macro like this: |
| | 193 | * |
| | 194 | * gMessageParams(obj, cont) |
| | 195 | * |
| | 196 | * then you'll get one parameter with the text name 'obj' whose expansion |
| | 197 | * will be the value of the local variable obj, and another with text name |
| | 198 | * 'cont' whose expansion is the value of the local variable cont. |
| | 199 | */ |
| | 200 | #define gMessageParams(var...) \ |
| | 201 | (gAction.setMessageParams(var#foreach/#@var, var/,/)) |
| | 202 | |
| | 203 | /* |
| | 204 | * Synthesize a global message parameter name for the given object and |
| | 205 | * return the synthesized name. This is useful in cases where there might |
| | 206 | * be repeated instances of global message parameters in the same action, |
| | 207 | * so it's not safe to use a fixed name string for the object. We'll |
| | 208 | * create a unique global message parameter name, associate the object with |
| | 209 | * the name, and return the name string. |
| | 210 | */ |
| | 211 | #define gSynthMessageParam(var) (gAction.synthMessageParam(var)) |
| | 212 | |
| | 213 | |
| | 214 | /* ------------------------------------------------------------------------ */ |
| | 215 | /* |
| | 216 | * Miscellaneous macros |
| | 217 | */ |
| | 218 | |
| | 219 | /* get the current player character Actor object */ |
| | 220 | #define gPlayerChar (libGlobal.playerChar) |
| | 221 | |
| | 222 | /* |
| | 223 | * the exit lister object - if the exits module isn't included in the |
| | 224 | * game, this will be nil |
| | 225 | */ |
| | 226 | #define gExitLister (libGlobal.exitListerObj) |
| | 227 | |
| | 228 | /* |
| | 229 | * the hint manager object - if the hints module isn't included in the |
| | 230 | * game, this will be nil |
| | 231 | */ |
| | 232 | #define gHintManager (libGlobal.hintManagerObj) |
| | 233 | |
| | 234 | |
| | 235 | /* ------------------------------------------------------------------------ */ |
| | 236 | /* |
| | 237 | * The current library messages object. This is the source object for |
| | 238 | * messages that don't logically relate to the actor carrying out the |
| | 239 | * comamand. It's mostly used for meta-command replies, and for text |
| | 240 | * fragments that are used to construct descriptions. |
| | 241 | * |
| | 242 | * This message object isn't generally used for parser messages or action |
| | 243 | * replies - most of those come from the objects given by the current |
| | 244 | * actor's getParserMessageObj() or getActionMessageObj(), respectively. |
| | 245 | * |
| | 246 | * By default, this is set to libMessages. The library never changes this |
| | 247 | * itself, but a game can change this if it wants to switch to a new set of |
| | 248 | * messages during a game. (If you don't need to change messages during a |
| | 249 | * game, but simply want to customize some of the default messages, you |
| | 250 | * don't need to set this variable - you can simply use 'modify |
| | 251 | * libMessages' instead. This variable is designed for cases where you |
| | 252 | * want to *dynamically* change the standard messages during the game.) |
| | 253 | */ |
| | 254 | #define gLibMessages (libGlobal.libMessageObj) |
| | 255 | |
| | 256 | |
| | 257 | /* ------------------------------------------------------------------------ */ |
| | 258 | /* |
| | 259 | * readMainCommandTokens() phase identifiers. We define a separate code |
| | 260 | * for each kind of call to readMainCommandTokens() so that we can do any |
| | 261 | * special token processing that depends on the type of command we're |
| | 262 | * reading. |
| | 263 | * |
| | 264 | * The library doesn't use the phase information itself for anything. |
| | 265 | * These phase codes are purely for the author's use in writing |
| | 266 | * pre-parsing functions and for differentiating prompts for the different |
| | 267 | * types of input, as needed. |
| | 268 | * |
| | 269 | * Games that read additional response types of their own are free to add |
| | 270 | * their own enums to identify the additional phases. Since the library |
| | 271 | * doesn't need the phase information for anything internally, it won't |
| | 272 | * confuse the library at all to add new game-specific phase codes. |
| | 273 | */ |
| | 274 | |
| | 275 | /* reading a normal command line */ |
| | 276 | enum rmcCommand; |
| | 277 | |
| | 278 | /* reading an unknown word response, to check for an "oops" command */ |
| | 279 | enum rmcOops; |
| | 280 | |
| | 281 | /* reading a response to a prompt for a missing object phrase */ |
| | 282 | enum rmcAskObject; |
| | 283 | |
| | 284 | /* reading a response to a prompt for a missing literal phrase */ |
| | 285 | enum rmcAskLiteral; |
| | 286 | |
| | 287 | /* reading a response to an interactive disambiguation prompt */ |
| | 288 | enum rmcDisambig; |
| | 289 | |
| | 290 | |
| | 291 | /* ------------------------------------------------------------------------ */ |
| | 292 | /* |
| | 293 | * Property set definitions |
| | 294 | */ |
| | 295 | |
| | 296 | #define objFor(which, action) propertyset '*' ## #@which ## #@action |
| | 297 | #define dobjFor(action) objFor(Dobj, action) |
| | 298 | #define iobjFor(action) objFor(Iobj, action) |
| | 299 | |
| | 300 | /* |
| | 301 | * Treat an object definition as equivalent to another object definition. |
| | 302 | * These can be used immediately after a dobjFor() or iobjFor() to treat |
| | 303 | * the first action as though it were the second. So, if the player types |
| | 304 | * "search box", and we want to treat the direct object the same as for |
| | 305 | * "look in box", we could make this definition for the box: |
| | 306 | * |
| | 307 | * dobjFor(Search) asDobjFor(LookIn) |
| | 308 | * |
| | 309 | * Note that no semicolon is needed after this definition, and that this |
| | 310 | * definition is completely in lieu of a regular property set for the |
| | 311 | * object action. |
| | 312 | * |
| | 313 | * In general, a mapping should NOT change the role of an object: |
| | 314 | * dobjFor(X) should not usually be mapped using asIobjFor(Y), and |
| | 315 | * iobjFor(X) shouldn't be mapped using asDobjFor(Y). The problem with |
| | 316 | * changing the role is that the handler routines often assume that the |
| | 317 | * object is actually in the role for which the handler was written; a |
| | 318 | * verify handler might refer to '{dobj}' in generating a message, for |
| | 319 | * example, so reversing the roles would give the wrong object in the role. |
| | 320 | * |
| | 321 | * Role reversals should always be avoided, but can be used if necessary |
| | 322 | * under conditions where all of the code involved in the TARGET of the |
| | 323 | * mapping can be carefully controlled to ensure that it doesn't make |
| | 324 | * assumptions about object roles, but only references 'self'. Reversing |
| | 325 | * roles in a mapping should never be attempted in general-purpose library |
| | 326 | * code, because code based on the library could override the target of the |
| | 327 | * role-reversing mapping, and the override could fail to observe the |
| | 328 | * restrictions on object role references. |
| | 329 | * |
| | 330 | * Note that role reversals can almost always be handled with other |
| | 331 | * mechanisms that handle reversals cleanly. Always consider remapTo() |
| | 332 | * first when confronted with a situation that seems to call for a |
| | 333 | * role-reversing asObjFor() mapping, as remapTo() specifically allows for |
| | 334 | * object role changes. |
| | 335 | */ |
| | 336 | #define asObjFor(obj, Action) \ |
| | 337 | { \ |
| | 338 | preCond { return preCond##obj##Action; } \ |
| | 339 | verify() { verify##obj##Action; } \ |
| | 340 | remap() { return remap##obj##Action; } \ |
| | 341 | check() { check##obj##Action; } \ |
| | 342 | action() { action##obj##Action; } \ |
| | 343 | } |
| | 344 | |
| | 345 | #define asDobjFor(action) asObjFor(Dobj, action) |
| | 346 | #define asIobjFor(action) asObjFor(Iobj, action) |
| | 347 | |
| | 348 | /* |
| | 349 | * Define mappings of everything except the action. This can be used in |
| | 350 | * cases where we want to pick up the verification, preconditions, and |
| | 351 | * check routines from another handler, but not the action. This is often |
| | 352 | * useful for two-object verbs where the action processing is entirely |
| | 353 | * provided by one or the other object, so applying it to both would be |
| | 354 | * redundant. |
| | 355 | */ |
| | 356 | #define asObjWithoutActionFor(obj, Action) \ |
| | 357 | { \ |
| | 358 | preCond { return preCond##obj##Action; } \ |
| | 359 | verify() { verify##obj##Action; } \ |
| | 360 | remap() { return remap##obj##Action(); } \ |
| | 361 | check() { check##obj##Action; } \ |
| | 362 | action() { } \ |
| | 363 | } |
| | 364 | |
| | 365 | #define asDobjWithoutActionFor(action) asObjWithoutActionFor(Dobj, action) |
| | 366 | #define asIobjWithoutActionFor(action) asObjWithoutActionFor(Iobj, action) |
| | 367 | |
| | 368 | /* |
| | 369 | * "Remap" an action. This effectively rewrites the action in the given |
| | 370 | * form. Each of the object slots can be filled either with a specific |
| | 371 | * object, or with a noun phrase role name (DirectObject, IndirectObject); |
| | 372 | * in the latter case, the object or objects from the named noun phrase |
| | 373 | * role in the *current* action (i.e., before the rewrite) will be used. |
| | 374 | * |
| | 375 | * If the new action has two or more objects (for example, if it's a |
| | 376 | * TIAction), then EXACTLY ONE of the slots must be filled with a specific |
| | 377 | * object, and all of the other slots must be filled with role names. The |
| | 378 | * specific object is the one that corresponds to the original object |
| | 379 | * that's doing the remapping in the first place - this can simply be |
| | 380 | * 'self' if the new action will operate on the same object, or it can be |
| | 381 | * a different object. The important thing is that the 'verify' method |
| | 382 | * for the defining object will be forwarded to the corresponding 'verify' |
| | 383 | * method on the corresponding object for the new action. |
| | 384 | * |
| | 385 | * This macro must be used as the ENTIRE definition block for a dobjFor() |
| | 386 | * or iobjFor(). For example, to remap a "put in" command directed to a |
| | 387 | * desk so that the command is instead applied to a drawer in the desk, we |
| | 388 | * could define the following on the desk object: |
| | 389 | * |
| | 390 | * iobjFor(PutIn) remapTo(PutIn, DirectObject, deskDrawer) |
| | 391 | */ |
| | 392 | #define remapTo(action, objs...) { remap = [action##Action, ##objs] } |
| | 393 | |
| | 394 | /* |
| | 395 | * Conditionally remap an action. If 'cond' (a conditional expression) |
| | 396 | * evaluated to true, we'll remap the action as directed; otherwise, we'll |
| | 397 | * inherit the default handling |
| | 398 | */ |
| | 399 | #define maybeRemapTo(cond, action, objs...) \ |
| | 400 | { remap = ((cond) ? [action##Action, ##objs] : inherited()) } |
| | 401 | |
| | 402 | |
| | 403 | /* |
| | 404 | * For two-object push-travel actions, such as "push sled into cave", |
| | 405 | * define a special mapping for both the direct and indirect objects: |
| | 406 | * |
| | 407 | * - Map the direct object (the object being pushed) to a simple |
| | 408 | * PushTravel action. So, for "push sled into cave," map the direct |
| | 409 | * object handling to PushTravel for the sled. This makes the handling of |
| | 410 | * the command equivalent to "push sled north" and the like. |
| | 411 | * |
| | 412 | * - Map the indirect object (the travel connector) to use the PushTravel |
| | 413 | * action's verify remapper. This is handled specially by the PushTravel |
| | 414 | * action object to handle the verification as though it were verifying |
| | 415 | * the corresponding ordinary (non-push) travel action on the indirect |
| | 416 | * object. Beyond verification, we do nothing, since the direct object of |
| | 417 | * a pushable object will handle the whole action using a nested travel |
| | 418 | * action. |
| | 419 | * |
| | 420 | * This effectively decomposes the two-object action into two coupled |
| | 421 | * single-object actions: a regular PushTravel action on the object being |
| | 422 | * pushed, and a regular whatever-kind-of-travel on the connector being |
| | 423 | * traversed. This handling has the appeal that it means that we don't |
| | 424 | * need a separate PUSH version of every kind of allowed travel on a |
| | 425 | * connector, and we don't need a special handler version for each kind of |
| | 426 | * travel on a pushable object; instead, we just use the basic PushTravel |
| | 427 | * and kind-of-travel handlers to form the combined form. Note that this |
| | 428 | * still allows separate treatment of the combined form wherever desired, |
| | 429 | * just by overriding these default handlers for the two-object action. |
| | 430 | */ |
| | 431 | #define mapPushTravelHandlers(pushAction, travelAction) \ |
| | 432 | dobjFor(pushAction) asDobjFor(PushTravel) \ |
| | 433 | mapPushTravelIobj(pushAction, travelAction) |
| | 434 | |
| | 435 | #define mapPushTravelIobj(pushAction, travelAction) \ |
| | 436 | iobjFor(pushAction) \ |
| | 437 | { \ |
| | 438 | verify() \ |
| | 439 | { gAction.verifyPushTravelIobj(self, travelAction##Action); } \ |
| | 440 | } |
| | 441 | |
| | 442 | |
| | 443 | /* ------------------------------------------------------------------------ */ |
| | 444 | /* |
| | 445 | * For an Actor, delegate an action handler to the ActorState object for |
| | 446 | * processing. You can use this any time you want to write the handlers |
| | 447 | * for a particular action in the ActorState rather than in the Actor |
| | 448 | * itself. This would be desirable if the actor's response for a |
| | 449 | * particular action varies considerably according to the actor's state. |
| | 450 | * For example, if you want an actor's response to being attacked to be |
| | 451 | * handled in the actor's current ActorState object, you could put this |
| | 452 | * code in the Actor object: |
| | 453 | * |
| | 454 | * dobjFor(AttackWith) actorStateDobjFor(AttackWith) |
| | 455 | * |
| | 456 | * Once you've done this, you'd just write a normal dobjFor(AttackWith) |
| | 457 | * handler in each of the ActorState objects associated with the actor. |
| | 458 | */ |
| | 459 | #define actorStateObjFor(obj, Action) \ |
| | 460 | { \ |
| | 461 | preCond { return curState.preCond##obj##Action; } \ |
| | 462 | verify() { curState.verify##obj##Action; } \ |
| | 463 | remap() { return curState.remap##obj##Action; } \ |
| | 464 | check() { curState.check##obj##Action; } \ |
| | 465 | action() { curState.action##obj##Action; } \ |
| | 466 | } |
| | 467 | |
| | 468 | #define actorStateDobjFor(action) actorStateObjFor(Dobj, action) |
| | 469 | #define actorStateIobjFor(action) actorStateObjFor(Iobj, action) |
| | 470 | |
| | 471 | |
| | 472 | /* ------------------------------------------------------------------------ */ |
| | 473 | /* |
| | 474 | * Object role identifiers. These are used to identify the role of a noun |
| | 475 | * phrase in a command. |
| | 476 | * |
| | 477 | * The library provides base classes for actions of zero, one, and two noun |
| | 478 | * phrases in their grammars: "look", "take book", "put book on shelf". We |
| | 479 | * thus define role identifiers for direct and indirect objects. Note that |
| | 480 | * even though we stop there, this doesn't preclude games or library |
| | 481 | * extensions from adding actions that take more than two noun phrases |
| | 482 | * ("put coin in slot with tongs"); any such extensions must simply define |
| | 483 | * their own additional role identifiers for the third or fourth (etc) noun |
| | 484 | * phrase. |
| | 485 | */ |
| | 486 | enum ActorObject, DirectObject, IndirectObject; |
| | 487 | |
| | 488 | /* |
| | 489 | * A special role for the "other" object of a two-object command. This |
| | 490 | * can be used in certain contexts (such as remapTo) where a particular |
| | 491 | * object role is implied by the context, and where the action involved |
| | 492 | * has exactly two objects; OtherObject in such contexts means |
| | 493 | * DirectObject when the implied role is IndirectObject, and vice versa. |
| | 494 | */ |
| | 495 | enum OtherObject; |
| | 496 | |
| | 497 | |
| | 498 | /* ------------------------------------------------------------------------ */ |
| | 499 | /* |
| | 500 | * Pronoun types. These are used to identify pronoun antecedents when |
| | 501 | * resolving noun phrases involving pronouns. |
| | 502 | * |
| | 503 | * We define a basic set of pronouns here that are common to most |
| | 504 | * languages. Language-specific modules are free to add their own pronoun |
| | 505 | * types as needed. |
| | 506 | * |
| | 507 | * Our basic set is: |
| | 508 | * |
| | 509 | * 'it' - the neuter singular |
| | 510 | *. 'him' - the masculine singular |
| | 511 | *. 'her' - the feminine singular |
| | 512 | *. 'them' - the ungendered plural |
| | 513 | *. 'you' - second person singular |
| | 514 | *. 'me' - first person singular |
| | 515 | * |
| | 516 | * Note that the first-person and second-person pronouns are assigned |
| | 517 | * meanings that can vary by context. When a command is issued by the |
| | 518 | * player character to the player character (i.e., the command comes from |
| | 519 | * the player and no target actor is specified), these refer to the player |
| | 520 | * character when the PC is in the appropriate referral person - if the |
| | 521 | * game calls the PC "you", then the player calls the PC "me", and vice |
| | 522 | * versa. When a command is targeted to or issued by an actor other than |
| | 523 | * the PC, then "you" refers to the command's target and "me" refers to |
| | 524 | * the command's issuer. |
| | 525 | */ |
| | 526 | enum PronounIt, PronounThem, PronounHim, PronounHer, PronounYou, PronounMe; |
| | 527 | |
| | 528 | |
| | 529 | /* ------------------------------------------------------------------------ */ |
| | 530 | /* |
| | 531 | * set the location property |
| | 532 | */ |
| | 533 | + property location; |
| | 534 | |
| | 535 | |
| | 536 | /* ------------------------------------------------------------------------ */ |
| | 537 | /* |
| | 538 | * Alternative exit definition. This can be used to define a secondary |
| | 539 | * direction that links to the same destination, via the same connector, as |
| | 540 | * another direction. It's frequently desirable to link multiple |
| | 541 | * directions to the same exit; for example, a door leading north might |
| | 542 | * also lead out, or a stairway to the north could lead up as well. |
| | 543 | * |
| | 544 | * Use this as follows in a room's property list: |
| | 545 | * |
| | 546 | *. out asExit(north) |
| | 547 | * |
| | 548 | * (Note that there's no '=' sign.) |
| | 549 | * |
| | 550 | * It's not necessary to use this macro to declare an alternative exit, |
| | 551 | * since the alternatives can all point directly to the same connector as |
| | 552 | * the original. The only thing this macro does is to make the alternative |
| | 553 | * exit unlisted - it won't be shown in the list of exits in the status |
| | 554 | * line, and it won't be shown in "you can't go that way" messages. |
| | 555 | * |
| | 556 | * Note that there's one common case where you should be careful with |
| | 557 | * asExit(): if you have a room that has an exit in some compass direction, |
| | 558 | * you might be tempted to make OUT the primary "direction" for the exit, |
| | 559 | * and treat the equivalent compass as a synonym, with a line such as |
| | 560 | * "south asExit(out)". You should avoid doing this - do it the other way |
| | 561 | * instead, with the compass direction as the primary direction and OUT as |
| | 562 | * the synonym: "out asExit(south)". The reason this is important is that |
| | 563 | * if there's a nested room inside the location (such as a chair), OUT |
| | 564 | * while in the nested room will mean to get out of the nested room. If |
| | 565 | * you make the compass direction primary and make OUT the synonym, the |
| | 566 | * compass direction will be listed as an available exit both in the |
| | 567 | * location and in any nested rooms within it. |
| | 568 | */ |
| | 569 | #define asExit(dir) = static ((dir).createUnlistedProxy()) |
| | 570 | |
| | 571 | |
| | 572 | /* ------------------------------------------------------------------------ */ |
| | 573 | /* |
| | 574 | * "Person" indices. We define these as numbers rather than enums so that |
| | 575 | * we can easily use these as list indices. |
| | 576 | */ |
| | 577 | #define FirstPerson 1 |
| | 578 | #define SecondPerson 2 |
| | 579 | #define ThirdPerson 3 |
| | 580 | |
| | 581 | |
| | 582 | /* ------------------------------------------------------------------------ */ |
| | 583 | /* |
| | 584 | * Transparency levels |
| | 585 | */ |
| | 586 | |
| | 587 | /* the sense is passed without loss of detail */ |
| | 588 | enum transparent; |
| | 589 | |
| | 590 | /* the sense is passed, but with a loss of detail associated with distance */ |
| | 591 | enum distant; |
| | 592 | |
| | 593 | /* |
| | 594 | * The sense is passed, but with attenuation of energy level. No other |
| | 595 | * obscuration of detail occurs; this is something like tinted glass that |
| | 596 | * doesn't distort the transmitted sense but reduces the amount of energy. |
| | 597 | */ |
| | 598 | enum attenuated; |
| | 599 | |
| | 600 | /* |
| | 601 | * The sense is passed, but with a loss of detail due to an obscuring |
| | 602 | * layer of material. The energy level is also attenuated. This is |
| | 603 | * something like dirty or wavy glass that distorts an image transmitted |
| | 604 | * through it but doesn't completely block out light. |
| | 605 | */ |
| | 606 | enum obscured; |
| | 607 | |
| | 608 | /* the sense is not passed at all */ |
| | 609 | enum opaque; |
| | 610 | |
| | 611 | |
| | 612 | /* ------------------------------------------------------------------------ */ |
| | 613 | /* |
| | 614 | * Size classes. An object is large, medium, or small with respect to |
| | 615 | * each sense; the size is used to determine how well the object can be |
| | 616 | * sensed at a distance or when obscured. |
| | 617 | * |
| | 618 | * What "size" means depends on the sense. For sight, the size |
| | 619 | * indicates the visual size of the object. For hearing, the size |
| | 620 | * indicates the loudness of the object. |
| | 621 | */ |
| | 622 | |
| | 623 | /* |
| | 624 | * Large - the object is large enough that its details can be sensed |
| | 625 | * from a distance or through an obscuring medium. |
| | 626 | */ |
| | 627 | enum large; |
| | 628 | |
| | 629 | /* |
| | 630 | * Medium - the object can be sensed at a distance or when obscured, but |
| | 631 | * not in any detail. Most objects fall into this category. Note that |
| | 632 | * things that are parts of large objects should normally be medium. |
| | 633 | */ |
| | 634 | enum medium; |
| | 635 | |
| | 636 | /* |
| | 637 | * Small - the object cannot be sensed at a distance at all. This is |
| | 638 | * appropriate for detailed parts of medium-class objects. |
| | 639 | */ |
| | 640 | enum small; |
| | 641 | |
| | 642 | |
| | 643 | /* ------------------------------------------------------------------------ */ |
| | 644 | /* |
| | 645 | * Path traversal operations. |
| | 646 | */ |
| | 647 | |
| | 648 | /* traverse from the starting point of the path */ |
| | 649 | enum PathFrom; |
| | 650 | |
| | 651 | /* traverse into the contents */ |
| | 652 | enum PathIn; |
| | 653 | |
| | 654 | /* traverse out to the container */ |
| | 655 | enum PathOut; |
| | 656 | |
| | 657 | /* traverse from an object to a peer at the same containment level */ |
| | 658 | enum PathPeer; |
| | 659 | |
| | 660 | /* |
| | 661 | * traverse through an object with no common container on either side of |
| | 662 | * the traversal - this is used when we are traversing an object, such as a |
| | 663 | * SenseConnector, that connects unrelated locations |
| | 664 | */ |
| | 665 | enum PathThrough; |
| | 666 | |
| | 667 | /* traverse to the ending point of the path */ |
| | 668 | enum PathTo; |
| | 669 | |
| | 670 | |
| | 671 | /* ------------------------------------------------------------------------ */ |
| | 672 | /* |
| | 673 | * Listing Options |
| | 674 | */ |
| | 675 | |
| | 676 | /* |
| | 677 | * use "tall" notation, which lists objects in a single column, one item |
| | 678 | * per line (the default is "wide" notation, which creates a sentence |
| | 679 | * with the object listing) |
| | 680 | */ |
| | 681 | #define ListTall 0x0001 |
| | 682 | |
| | 683 | /* |
| | 684 | * Recursively list the contents of each item we list. |
| | 685 | * |
| | 686 | * For a 'tall' list, this indicates that we'll show the listed contents |
| | 687 | * of each item that we list, and the listed contents of those items, and |
| | 688 | * so on, indenting each level to indicate the containment relationship. |
| | 689 | * |
| | 690 | * For a 'wide' list, this indicates that we'll show the listed contents |
| | 691 | * of each item in-line in the listing, as a parenthetic note. |
| | 692 | * |
| | 693 | * For both types of listings, when this flag is set and the indent level |
| | 694 | * is zero (indicating a top-level listing), after the main list, we'll |
| | 695 | * show a separate list for the contents of each item in our list that |
| | 696 | * isn't itself listable but has listed contents, or has contents with |
| | 697 | * listed contents, and so on to any level. For example, if we're showing |
| | 698 | * a room description, and the room contains a desk that isn't listed |
| | 699 | * because it's a fixed part of the room, we'll show a separate list of |
| | 700 | * the desk's listed contents. |
| | 701 | */ |
| | 702 | #define ListRecurse 0x0002 |
| | 703 | |
| | 704 | /* |
| | 705 | * use "long list" notation - separates items that contain sublists with |
| | 706 | * special punctuation, to set off the individual items in the longer |
| | 707 | * listing from the items in the sublists (for example, separates items |
| | 708 | * with semicolons rather than commas) |
| | 709 | */ |
| | 710 | #define ListLong 0x0004 |
| | 711 | |
| | 712 | /* |
| | 713 | * This is a recursive listing of the contents of an item. This is set by |
| | 714 | * showList() in calls it makes to recursive listing levels. |
| | 715 | */ |
| | 716 | #define ListContents 0x0008 |
| | 717 | |
| | 718 | /* |
| | 719 | * Custom option bits. Flag bits with this value and higher are reserved |
| | 720 | * for use by individual lister subclasses. |
| | 721 | * |
| | 722 | * To ensure compatibility with any future changes that involve adding |
| | 723 | * more base lister flags, subclasses are encouraged to use the following |
| | 724 | * mechanism. DO NOT use #define to define your own custom subclass |
| | 725 | * flags. Instead, define a property of your lister subclass for each |
| | 726 | * flag you need as follows: |
| | 727 | * |
| | 728 | * myCustomFlag1 = ListerCustomFlag(1) // use 1 for the first flag |
| | 729 | *. myCustomFlag2 = ListerCustomFlag(2) // etc |
| | 730 | *. nextCustomFlag = ListerCustomFlag(3) |
| | 731 | * |
| | 732 | * You DO NOT have to use the name 'myCustomFlag1' - use whatever name you |
| | 733 | * like that describes the nature of the flag. However, the last item |
| | 734 | * MUST be called 'nextCustomFlag' - this ensures that any subclasses of |
| | 735 | * your class will allocate their own flags with new values that don't |
| | 736 | * conflict with any of yours. |
| | 737 | * |
| | 738 | * Then, when a client of your Lister subclass needs to pass one of your |
| | 739 | * flag to the Lister, it should simply evaluate your 'myCustomFlagN' |
| | 740 | * property of your lister. If you'd like, you can even #define a ListXxx |
| | 741 | * macro that retrieves the value, for the convenience of your callers: |
| | 742 | * |
| | 743 | * #define ListMyclassMyCustomFlag1 (Myclass.myCustomFlag1) |
| | 744 | */ |
| | 745 | #define ListCustomFlag 0x0100 |
| | 746 | |
| | 747 | #define ListerCustomFlag(n) static ((inherited.nextCustomFlag) << ((n) - 1)) |
| | 748 | |
| | 749 | |
| | 750 | /* ------------------------------------------------------------------------ */ |
| | 751 | /* |
| | 752 | * Spelled-out number options, for spellInt() and related functions. |
| | 753 | * |
| | 754 | * Note that the interfaces to the number-spelling functions can vary by |
| | 755 | * language, and that variation can include these flags. Some language |
| | 756 | * modules might ignore some of these generic flags or define additional |
| | 757 | * language-specific flags. |
| | 758 | */ |
| | 759 | |
| | 760 | /* |
| | 761 | * Use tens of hundreds rather than thousands if possible - 1950 is |
| | 762 | * 'nineteen hundred fifty' rather than 'one thousand nine hundred |
| | 763 | * fifty'. This only works if the number (not including the millions |
| | 764 | * and billions) is in the range 1,100 to 9,999, because we don't want |
| | 765 | * to say something like 'one hundred twenty hundred' for 12,000. |
| | 766 | */ |
| | 767 | #define SpellIntTeenHundreds 0x0001 |
| | 768 | |
| | 769 | /* |
| | 770 | * use 'and' before the tens - 125 is 'one hundred and twenty-five' |
| | 771 | * rather than 'one hundred twenty-five' |
| | 772 | */ |
| | 773 | #define SpellIntAndTens 0x0002 |
| | 774 | |
| | 775 | /* |
| | 776 | * put a comma after each power group - 123456 is 'one hundred |
| | 777 | * twenty-three thousand, four hundred fifty-six' |
| | 778 | */ |
| | 779 | #define SpellIntCommas 0x0004 |
| | 780 | |
| | 781 | |
| | 782 | /* ------------------------------------------------------------------------ */ |
| | 783 | /* |
| | 784 | * Decimal number format options. These are used with the number |
| | 785 | * formatting functions to control the formatting of numbers displayed in |
| | 786 | * decimal digit format. |
| | 787 | */ |
| | 788 | |
| | 789 | /* |
| | 790 | * Use a group separator character between digit groups, using the |
| | 791 | * default setting in languageGlobals. |
| | 792 | */ |
| | 793 | #define DigitFormatGroupSep 0x0001 |
| | 794 | |
| | 795 | /* |
| | 796 | * Explicitly use a comma/period to separate digit groups, overriding |
| | 797 | * the current languageGlobals setting. |
| | 798 | */ |
| | 799 | #define DigitFormatGroupComma 0x0002 |
| | 800 | #define DigitFormatGroupPeriod 0x0004 |
| | 801 | |
| | 802 | |
| | 803 | /* ------------------------------------------------------------------------ */ |
| | 804 | /* |
| | 805 | * ResolveInfo flags |
| | 806 | */ |
| | 807 | |
| | 808 | /* the noun phrase ends with an adjective */ |
| | 809 | #define EndsWithAdj 0x0001 |
| | 810 | |
| | 811 | /* |
| | 812 | * one of the words in the noun phrase was truncated from its full |
| | 813 | * dictionary spelling |
| | 814 | */ |
| | 815 | #define VocabTruncated 0x0002 |
| | 816 | |
| | 817 | /* |
| | 818 | * One or more plurals was truncated from its full dictionary spelling. |
| | 819 | * (We specially distinguish plurals that are truncated, because in |
| | 820 | * English a plural is usually formed by adding "s" or "es" to the end of |
| | 821 | * the singular form of a noun, meaning that a given singular form is |
| | 822 | * usually a leading substring of its plural. When a singular noun is |
| | 823 | * longer than the truncation limit, which is conventionally six |
| | 824 | * characters, the singular will always match as a truncated version of |
| | 825 | * the plural, so every time someone types in a singular it'll be treated |
| | 826 | * as ambiguous between the singular and plural form. So, in the English |
| | 827 | * parser, we have a preference to ignore a truncated plural any time the |
| | 828 | * word could also be interpreted as an untruncated singular, hence we |
| | 829 | * note when we have a truncated plural.) |
| | 830 | */ |
| | 831 | #define PluralTruncated 0x0004 |
| | 832 | |
| | 833 | /* |
| | 834 | * The object came from an 'all' phrase. Normally, the only time this |
| | 835 | * makes any difference is when deciding whether or not to mention which |
| | 836 | * object we're acting upon; an 'all' object should normally be mentioned |
| | 837 | * explicitly, as though the command had involved multiple objects, |
| | 838 | * because otherwise it might not be clear to the user what object had |
| | 839 | * actually matched 'all'. |
| | 840 | */ |
| | 841 | #define MatchedAll 0x0008 |
| | 842 | |
| | 843 | /* |
| | 844 | * Always announce the object before executing the command on it. This |
| | 845 | * flag can be set for objects that match phrases whose meaning isn't |
| | 846 | * necessarily known to the player, such as "all" (which selects objects |
| | 847 | * based on the simulation state, which might not exactly match what the |
| | 848 | * player had in mind) or "any book" (which might select arbitrarily from |
| | 849 | * several possibilities, so the player can't know which we'll choose). |
| | 850 | */ |
| | 851 | #define AlwaysAnnounce 0x0010 |
| | 852 | |
| | 853 | /* |
| | 854 | * The noun phrase describing this object was ambiguous, and the object |
| | 855 | * was selected by automatic disambiguation in a context where it was |
| | 856 | * clear which object was indicated. This is used in cases where the |
| | 857 | * objects not selected were all illogical for the action context. |
| | 858 | */ |
| | 859 | #define ClearDisambig 0x0020 |
| | 860 | |
| | 861 | /* |
| | 862 | * The noun phase describing this object was ambiguous, and the object was |
| | 863 | * selected by automatic disambiguation in a context where it was not |
| | 864 | * perfectly clear which object was indicated. This is used for cases |
| | 865 | * where the objects selected were more logical than the objects not |
| | 866 | * selected, but some of the unselected objects were still logical. |
| | 867 | * |
| | 868 | * This flag doesn't mean that we chose arbitrarily, but rather that we |
| | 869 | * chose the best object or objects from a field that included additional |
| | 870 | * objects that, though not quite as good, were still valid. We flag this |
| | 871 | * case because the user *could* have meant to use one of the other valid |
| | 872 | * objects, even though we consider it most likely that the user meant to |
| | 873 | * use the one(s) we selected; so, we want to flag this so we can call the |
| | 874 | * user's attention to our choice, to make it more likely that the user |
| | 875 | * will immediately notice if we made the wrong choice. |
| | 876 | * |
| | 877 | * Note that we can't have both ClearDisambig and UnclearDisambig at the |
| | 878 | * same time, but we *can* have neither of these. If neither flag is set |
| | 879 | * for an object, it simply means that the object wasn't ambiguous to |
| | 880 | * start with. When the user explicitly picks an object interactively, |
| | 881 | * the selected object is effectively unambiguous, so it won't have either |
| | 882 | * flag set; even though it started off ambiguous, the user did all of the |
| | 883 | * work of selecting the appropriate object, leaving things unambiguous in |
| | 884 | * the end. |
| | 885 | */ |
| | 886 | #define UnclearDisambig 0x0040 |
| | 887 | |
| | 888 | /* |
| | 889 | * The noun phrase was missing from the command and this object was |
| | 890 | * supplied as an implicit default. |
| | 891 | */ |
| | 892 | #define DefaultObject 0x0080 |
| | 893 | |
| | 894 | /* |
| | 895 | * We've announced this as a defaulted object. We use this to ensure that |
| | 896 | * we only make this type of announcement once, even if the opportunity to |
| | 897 | * make the announcement comes up more than once; this can happen when |
| | 898 | * we're asking for missing objects interactively in a multi-object |
| | 899 | * command, since we might want to announce a default before prompting as |
| | 900 | * well as before execution. |
| | 901 | */ |
| | 902 | #define AnnouncedDefaultObject 0x0100 |
| | 903 | |
| | 904 | |
| | 905 | /* ------------------------------------------------------------------------ */ |
| | 906 | /* |
| | 907 | * Announcement styles for disambiguated objects. These are used in the |
| | 908 | * gameMain object (see GameMainDef) to select which type of announcement |
| | 909 | * is used when the parser disambiguates a noun phrase using the |
| | 910 | * logicalness rules. |
| | 911 | */ |
| | 912 | |
| | 913 | /* |
| | 914 | * Announce unclear disambiguation results only. When this setting is |
| | 915 | * selected, the parser makes a parenthetical announcement (e.g., "(the red |
| | 916 | * door)") when it selects an object based on likelihood rankings from |
| | 917 | * among more than one logical match. The parser makes no announcement |
| | 918 | * when exactly one logical object is in scope, even if other objects match |
| | 919 | * the noun phrase by name. |
| | 920 | */ |
| | 921 | enum AnnounceUnclear; |
| | 922 | |
| | 923 | /* |
| | 924 | * Announce clear and unclear disambiguation results, both using |
| | 925 | * parenthetical announcement ("(the red door)"). When this setting is |
| | 926 | * selected, the parser makes these announcements every time it applies the |
| | 927 | * logicalness rules or likelihood rankings to disambiguate a noun phrase. |
| | 928 | * There's no announcement when no disambiguation is needed (because the |
| | 929 | * noun phrase matches only one in-scope object). |
| | 930 | */ |
| | 931 | enum AnnounceClear; |
| | 932 | |
| | 933 | /* |
| | 934 | * Describe clear disambiguation results, rather than announcing them. The |
| | 935 | * parser makes the parenthetical announcement, as usual, for unclear |
| | 936 | * disambiguation picks, but not for clear picks (a clear pick is one where |
| | 937 | * there's only one logical object, even though the noun phrase matches |
| | 938 | * more than one object). For clear picks, however, the parser uses a |
| | 939 | * verbose version of the action reply in lieu of one of the terse default |
| | 940 | * messages. For example, rather than saying just "Taken", the parser |
| | 941 | * would reply "You take the red book." The longer messages mention the |
| | 942 | * object by name, to make it clear exactly which one was chosen. |
| | 943 | */ |
| | 944 | enum DescribeClear; |
| | 945 | |
| | 946 | |
| | 947 | /* ------------------------------------------------------------------------ */ |
| | 948 | /* |
| | 949 | * Inventory modes. "Wide" mode displays the inventory in paragraph form; |
| | 950 | * "tall" mode displays as a list, with one item per line, indenting items |
| | 951 | * to reflect containment. |
| | 952 | */ |
| | 953 | enum InventoryWide, InventoryTall; |
| | 954 | |
| | 955 | |
| | 956 | /* ------------------------------------------------------------------------ */ |
| | 957 | /* |
| | 958 | * Define an action with the given base class. This adds the *Action |
| | 959 | * suffix to the given root name, and defines a class with the given base |
| | 960 | * class. We also define the baseActionClass property to refer to myself; |
| | 961 | * this is the canonical class representing the action for all subclasses. |
| | 962 | * This information is useful because a language module might define |
| | 963 | * several grammar rule subclasses for the given class; this lets us |
| | 964 | * relate any instances of those various subclasses back to this same |
| | 965 | * canonical class for the action if necessary. |
| | 966 | */ |
| | 967 | #define DefineAction(name, baseClass...) \ |
| | 968 | class name##Action: ##baseClass \ |
| | 969 | baseActionClass = name##Action |
| | 970 | |
| | 971 | /* |
| | 972 | * Define a "system" action. System actions are meta-game commands, such |
| | 973 | * as SAVE and QUIT, that generally operate the user interface and are not |
| | 974 | * part of the game world. |
| | 975 | */ |
| | 976 | #define DefineSystemAction(name) \ |
| | 977 | DefineAction(name, SystemAction) |
| | 978 | |
| | 979 | /* |
| | 980 | * Define a concrete IAction, given the root name for the action. We'll |
| | 981 | * automatically generate a class with name XxxAction. |
| | 982 | */ |
| | 983 | #define DefineIAction(name) \ |
| | 984 | DefineAction(name, IAction) |
| | 985 | |
| | 986 | /* define a conversational IAction, such as Hello, Goodbye, Yes, No */ |
| | 987 | #define DefineConvIAction(name) \ |
| | 988 | DefineAction(name, ConvIAction) |
| | 989 | |
| | 990 | /* |
| | 991 | * Define a concrete TAction, given the root name for the action. We'll |
| | 992 | * automatically generate a class with name XxxAction, a verProp with name |
| | 993 | * verXxx, a checkProp with name checkXxx, and an actionProp with name |
| | 994 | * actionDobjXxx. |
| | 995 | */ |
| | 996 | #define DefineTAction(name) \ |
| | 997 | DefineTActionSub(name, TAction) |
| | 998 | |
| | 999 | /* |
| | 1000 | * Define a concrete TAction with a specific base class. |
| | 1001 | */ |
| | 1002 | #define DefineTActionSub(name, cls) \ |
| | 1003 | DefineAction(name, cls) \ |
| | 1004 | verDobjProp = &verifyDobj##name \ |
| | 1005 | remapDobjProp = &remapDobj##name \ |
| | 1006 | preCondDobjProp = &preCondDobj##name \ |
| | 1007 | checkDobjProp = &checkDobj##name \ |
| | 1008 | actionDobjProp = &actionDobj##name \ |
| | 1009 | |
| | 1010 | /* |
| | 1011 | * Define a concrete TIAction, given the root name for the action. We'll |
| | 1012 | * automatically generate a class with name XxxAction, a verDobjProp with |
| | 1013 | * name verDobjXxx, a verIobjProp with name verIobjxxx, a checkDobjProp |
| | 1014 | * with name checkDobjXxx, a checkIobjProp with name checkIobjXxx, an |
| | 1015 | * actionDobjProp with name actionDobjXxx, and an actionIobjProp with name |
| | 1016 | * actionIobjXxx. |
| | 1017 | */ |
| | 1018 | #define DefineTIAction(name) \ |
| | 1019 | DefineTIActionSub(name, TIAction) |
| | 1020 | |
| | 1021 | /* |
| | 1022 | * Define a concrete TIAction with a specific base class. |
| | 1023 | */ |
| | 1024 | #define DefineTIActionSub(name, cls) \ |
| | 1025 | DefineAction(name, cls) \ |
| | 1026 | verDobjProp = &verifyDobj##name \ |
| | 1027 | verIobjProp = &verifyIobj##name \ |
| | 1028 | remapDobjProp = &remapDobj##name \ |
| | 1029 | remapIobjProp = &remapIobj##name \ |
| | 1030 | preCondDobjProp = &preCondDobj##name \ |
| | 1031 | preCondIobjProp = &preCondIobj##name \ |
| | 1032 | checkDobjProp = &checkDobj##name \ |
| | 1033 | checkIobjProp = &checkIobj##name \ |
| | 1034 | actionDobjProp = &actionDobj##name \ |
| | 1035 | actionIobjProp = &actionIobj##name |
| | 1036 | |
| | 1037 | /* |
| | 1038 | * Define a concrete TopicAction, given the root name for the action. |
| | 1039 | */ |
| | 1040 | #define DefineTopicAction(name) \ |
| | 1041 | DefineAction(name, TopicAction) |
| | 1042 | |
| | 1043 | /* |
| | 1044 | * Define a concrete TopicTAction, given the root name for the action. |
| | 1045 | * 'which' gives the role the topic serves, for message generation purposes |
| | 1046 | * - this should be one of the object role enums (DirectObject, |
| | 1047 | * IndirectObject, etc) indicating which role the topic plays in the |
| | 1048 | * action's grammar. |
| | 1049 | */ |
| | 1050 | #define BaseDefineTopicTAction(name, which, cls) \ |
| | 1051 | DefineAction(name, cls) \ |
| | 1052 | verDobjProp = &verifyDobj##name \ |
| | 1053 | remapDobjProp = &remapDobj##name \ |
| | 1054 | preCondDobjProp = &preCondDobj##name \ |
| | 1055 | checkDobjProp = &checkDobj##name \ |
| | 1056 | actionDobjProp = &actionDobj##name \ |
| | 1057 | whichMessageTopic = which |
| | 1058 | |
| | 1059 | #define DefineTopicTAction(name, which) \ |
| | 1060 | BaseDefineTopicTAction(name, which, TopicTAction) |
| | 1061 | |
| | 1062 | /* |
| | 1063 | * Define a concrete ConvTopicTAction. This is just like defining a |
| | 1064 | * TopicTAction, but defines the action using the ConvTopicTAction |
| | 1065 | * subclass. |
| | 1066 | */ |
| | 1067 | #define DefineConvTopicTAction(name, which) \ |
| | 1068 | BaseDefineTopicTAction(name, which, ConvTopicTAction) |
| | 1069 | |
| | 1070 | /* |
| | 1071 | * Define a concrete LiteralAction, given the root name for the action. |
| | 1072 | */ |
| | 1073 | #define DefineLiteralAction(name) \ |
| | 1074 | DefineAction(name, LiteralAction) |
| | 1075 | |
| | 1076 | /* |
| | 1077 | * Define a concrete LiteralTAction, given the root name for the action. |
| | 1078 | * 'which' gives the role the literal phrase serves, for message generation |
| | 1079 | * purposes - this should be one of the object role enums (DirectObject, |
| | 1080 | * IndirectObject, etc) indicating which role the topic plays in the |
| | 1081 | * action's grammar. |
| | 1082 | */ |
| | 1083 | #define DefineLiteralTAction(name, which) \ |
| | 1084 | DefineAction(name, LiteralTAction) \ |
| | 1085 | verDobjProp = &verifyDobj##name \ |
| | 1086 | remapDobjProp = &remapDobj##name \ |
| | 1087 | preCondDobjProp = &preCondDobj##name \ |
| | 1088 | checkDobjProp = &checkDobj##name \ |
| | 1089 | actionDobjProp = &actionDobj##name \ |
| | 1090 | whichMessageLiteral = which |
| | 1091 | |
| | 1092 | /* ------------------------------------------------------------------------ */ |
| | 1093 | /* |
| | 1094 | * Convenience macros for setting verify results. |
| | 1095 | * |
| | 1096 | * A verify routine can use these macros to set any number of verify |
| | 1097 | * results. The VerifyResultList will keep only the result that gives the |
| | 1098 | * strongest disapproval of the action, since the verification process is |
| | 1099 | * by its nature only interested in the most negative result. |
| | 1100 | * |
| | 1101 | * These macros take advantage of the fact that we have a global |
| | 1102 | * VerifyResultList object, which gathers the results of the verification, |
| | 1103 | * so they can be used only in verify routines. The global verification |
| | 1104 | * results object is valid during each verification invocation. |
| | 1105 | */ |
| | 1106 | |
| | 1107 | /* |
| | 1108 | * Command is logical. There's generally no need to add a logical result |
| | 1109 | * explicitly, since a command is logical unless disapproved, but we |
| | 1110 | * include this for completeness. |
| | 1111 | * |
| | 1112 | * We use 100 as the default likelihood, to leave plenty of room for |
| | 1113 | * specific likelihood rankings both above and below the default level. |
| | 1114 | */ |
| | 1115 | #define logical \ |
| | 1116 | (gVerifyResults.addResult(new LogicalVerifyResult(100, '', 100))) |
| | 1117 | |
| | 1118 | /* |
| | 1119 | * Command is logical, and is ranked as indicated among logical results. |
| | 1120 | * The 'rank' value is the likelihood rank; the higher the rank, the more |
| | 1121 | * logical the command is. The rank is only used to establish an ordering |
| | 1122 | * of the logical results; if a command also has illogical results, all of |
| | 1123 | * the illogical results rank as less logical than the logical result with |
| | 1124 | * the lowest likelihood. |
| | 1125 | * |
| | 1126 | * The 'key' value is an arbitrary string value associated with the |
| | 1127 | * ranking. When two result lists both have a logical result object, and |
| | 1128 | * both logical result objects have the same likelihood level, we'll check |
| | 1129 | * the keys; if the keys match, we'll treat the two results as equivalent |
| | 1130 | * and thus not distinguishing for disambiguation. This is useful because |
| | 1131 | * it creates a crude multivariate space for ranking items for |
| | 1132 | * disambiguation. |
| | 1133 | * |
| | 1134 | * For example, suppose we have a "put in" command, and we have two |
| | 1135 | * possibilities for the target container. Neither is being held by the |
| | 1136 | * actor, so they both have a result with a logical rank of 70 with a key |
| | 1137 | * value of 'not held'. In addition, both are openable, and one is open |
| | 1138 | * and the other is closed; the closed one has an additional result with a |
| | 1139 | * logical rank of 80 and a key of 'not open'. Which do we choose? If we |
| | 1140 | * looked only at the logical rankings, both would be equivalent, since |
| | 1141 | * both have 70's as their most disapproving results. However, we see |
| | 1142 | * that the two 70's were applied for the same reason - because they share |
| | 1143 | * a common key - so we know this information isn't helpful for |
| | 1144 | * disambiguation and can be ignored. So, we find that the closed one has |
| | 1145 | * an 80, and the other has no other results (hence is by default logical |
| | 1146 | * with rank 100), thus we take the '80' as the better one. |
| | 1147 | * |
| | 1148 | * Throughout the library, we use the following conventions: |
| | 1149 | * |
| | 1150 | * 150 = especially good fit: a good candidate for the action that is |
| | 1151 | * especially likely to be used with the command. For example, a book is |
| | 1152 | * especially suitable for a "read" command. |
| | 1153 | * |
| | 1154 | * 140 = similar to 150, but slightly less ideal a fit. We use this for |
| | 1155 | * objects that are excellent fits, but for which we know certain other |
| | 1156 | * objects might be better fits. |
| | 1157 | * |
| | 1158 | * 100 = default: a perfectly good candidate for the action, with nothing |
| | 1159 | * that would make it illogical, but nothing that makes it especially |
| | 1160 | * likely, either |
| | 1161 | * |
| | 1162 | * 80 = slightly less than perfect: a good candidate, but with some |
| | 1163 | * temporary and correctable attribute that may make it less likely than |
| | 1164 | * others. This is used for attributes that can be corrected: a container |
| | 1165 | * needs to be opened for the action to succeed, but isn't currently open, |
| | 1166 | * or an article of clothing cannot be worn for the action to proceeds, |
| | 1167 | * but is currently being worn. |
| | 1168 | * |
| | 1169 | * 60/70 = slightly less than perfect, but with some attributes that can't |
| | 1170 | * be readily corrected and which make the candidate potentially less |
| | 1171 | * likely. These are used to make guesses about which might object might |
| | 1172 | * be intended when several are logical but some might be more readily |
| | 1173 | * used than others; for example, if putting an object into a container, a |
| | 1174 | * container being held might rank higher than one not being held, so the |
| | 1175 | * one not being held might be ranked a "70" likelihood. |
| | 1176 | * |
| | 1177 | * 50 = logical but not especially likely: an acceptable candidate for the |
| | 1178 | * action, but probably not the best choice for the action. This is used |
| | 1179 | * when an object can be used for the action, but would not be expected to |
| | 1180 | * do anything special with the action. |
| | 1181 | */ |
| | 1182 | #define logicalRank(rank, key) \ |
| | 1183 | (gVerifyResults.addResult(new LogicalVerifyResult(rank, key, 100))) |
| | 1184 | |
| | 1185 | /* |
| | 1186 | * Logical ranking with specific list ordering. This is the same as a |
| | 1187 | * regular logicalRank, but uses the given list ordering rather than the |
| | 1188 | * default list ordering (100). |
| | 1189 | */ |
| | 1190 | #define logicalRankOrd(rank, key, ord) \ |
| | 1191 | (gVerifyResults.addResult(new LogicalVerifyResult(rank, key, ord))) |
| | 1192 | |
| | 1193 | /* command is logical but dangerous */ |
| | 1194 | #define dangerous \ |
| | 1195 | (gVerifyResults.addResult(new DangerousVerifyResult(''))) |
| | 1196 | |
| | 1197 | /* |
| | 1198 | * command is logical but non-obvious: the object should never be taken as |
| | 1199 | * a default |
| | 1200 | */ |
| | 1201 | #define nonObvious \ |
| | 1202 | (gVerifyResults.addResult(new NonObviousVerifyResult(''))) |
| | 1203 | |
| | 1204 | /* command is currently (but not always) illogical, for the given reason */ |
| | 1205 | #define illogicalNow(msg, params...) \ |
| | 1206 | (gVerifyResults.addResult(new IllogicalNowVerifyResult(msg, ##params))) |
| | 1207 | |
| | 1208 | /* illogical because things are already as the command would make them */ |
| | 1209 | #define illogicalAlready(msg, params...) \ |
| | 1210 | (gVerifyResults.addResult( \ |
| | 1211 | new IllogicalAlreadyVerifyResult(msg, ##params))) |
| | 1212 | |
| | 1213 | /* command is always illogical */ |
| | 1214 | #define illogical(msg, params...) \ |
| | 1215 | (gVerifyResults.addResult(new IllogicalVerifyResult(msg, ##params))) |
| | 1216 | |
| | 1217 | /* illogical since we're trying to use something on itself (eg, PUT X IN X) */ |
| | 1218 | #define illogicalSelf(msg, params...) \ |
| | 1219 | (gVerifyResults.addResult(new IllogicalSelfVerifyResult(msg, ##params))) |
| | 1220 | |
| | 1221 | /* command is being performed on an inaccessible object */ |
| | 1222 | #define inaccessible(msg, params...) \ |
| | 1223 | (gVerifyResults.addResult(new InaccessibleVerifyResult(msg, ##params))) |
| | 1224 | |
| | 1225 | |
| | 1226 | /* ------------------------------------------------------------------------ */ |
| | 1227 | /* |
| | 1228 | * Convenience macros for setting command results. |
| | 1229 | */ |
| | 1230 | |
| | 1231 | /* |
| | 1232 | * Set a default report for the current command. This report will be |
| | 1233 | * shown unless a non-default report is issued, or if the default report |
| | 1234 | * is to be suppressed (for example, because the command is being |
| | 1235 | * performed implicitly as part of another command). |
| | 1236 | * |
| | 1237 | * Default reports should be used only for simple acknowledgments of the |
| | 1238 | * command's successful completion - things like "Taken" or "Dropped" or |
| | 1239 | * "Done." |
| | 1240 | * |
| | 1241 | * Default responses are suppressed for implicit commands because they are |
| | 1242 | * redundant. When a command is performed implicitly, it is conventional |
| | 1243 | * to mention the command being performed with a parenthetical: "(First |
| | 1244 | * taking the book)". In such cases, a simple acknowledgment that the |
| | 1245 | * command was successfully performed would add nothing of use but would |
| | 1246 | * merely make the output more verbose, so we omit it. |
| | 1247 | */ |
| | 1248 | #define defaultReport(msg, params...) \ |
| | 1249 | (gTranscript.addReport(new DefaultCommandReport(msg, ##params))) |
| | 1250 | |
| | 1251 | /* |
| | 1252 | * Set a default descriptive report for the current command. This report |
| | 1253 | * will be shown unless any other report is shown for the same command. |
| | 1254 | * This differs from defaultReport in that we don't suppress a default |
| | 1255 | * description for an implied command: we only suppress a default |
| | 1256 | * description when there are other reports for the same command. |
| | 1257 | * |
| | 1258 | * The purpose of the default descriptive report is to generate reports |
| | 1259 | * that say things along the lines that there's nothing special to |
| | 1260 | * describe. For example: |
| | 1261 | * |
| | 1262 | * >x desk |
| | 1263 | *. You see nothing special about it. |
| | 1264 | * |
| | 1265 | * >look in alcove |
| | 1266 | *. There's nothing in the alcove. |
| | 1267 | * |
| | 1268 | * When there's nothing else to report, these default descriptions are |
| | 1269 | * suitable as the full response to the command. However, they become |
| | 1270 | * undesirable when we have other "status" information or related special |
| | 1271 | * descriptions to display; consider: |
| | 1272 | * |
| | 1273 | * >x desk |
| | 1274 | *. You see nothing special about it. |
| | 1275 | *. Someone has jabbed a dagger into the top of the desk. |
| | 1276 | * |
| | 1277 | * >look in alcove |
| | 1278 | *. There's nothing in the alcove. |
| | 1279 | *. A vase is displayed in the alcove. |
| | 1280 | * |
| | 1281 | * >x bag |
| | 1282 | *. You see nothing special about it. It's open, and it contains |
| | 1283 | *. a red book, an iron key, and a brass key. |
| | 1284 | * |
| | 1285 | * In the first two examples above, we have special descriptions for |
| | 1286 | * objects contained in the objects being described. The special |
| | 1287 | * descriptions essentially contradict the default descriptions' claims |
| | 1288 | * that there's nothing special to mention, and also render the default |
| | 1289 | * descriptions unnecessary, in that it would be enough to show just the |
| | 1290 | * special descriptions. The third example above is similar, but the |
| | 1291 | * extra information is status information for the object being described |
| | 1292 | * rather than a special description of a contained item; as with the |
| | 1293 | * other examples, the generic default description is both contradictory |
| | 1294 | * and unnecessary. |
| | 1295 | * |
| | 1296 | * Default description reports should ONLY be used for messages that have |
| | 1297 | * the character of the examples above: generic descriptions that indicate |
| | 1298 | * explicitly that there's nothing special to report. Messages that offer |
| | 1299 | * any sort of descriptive detail should NOT be generated as default |
| | 1300 | * description reports, because it is suitable and desirable to retain an |
| | 1301 | * actual descriptive message even when other status information or |
| | 1302 | * related special descriptions are also shown. |
| | 1303 | */ |
| | 1304 | #define defaultDescReport(msg, params...) \ |
| | 1305 | (gTranscript.addReport(new DefaultDescCommandReport(msg, ##params))) |
| | 1306 | |
| | 1307 | /* |
| | 1308 | * Add an cosmetic internal spacing report. This type of report is used |
| | 1309 | * to show spacing (usually a paragraph break) within command output. |
| | 1310 | * |
| | 1311 | * The important thing about this report is that it doesn't trigger |
| | 1312 | * suppression of any default reports. This is useful when internal |
| | 1313 | * separation is added on speculation that there might be some reports to |
| | 1314 | * separate, but without certainty that there will actually be any reports |
| | 1315 | * shown; for example, when preparing to show a list of special |
| | 1316 | * descriptions, we might add some spacing just in case some special |
| | 1317 | * descriptions will be shown, saving the trouble of checking to see if |
| | 1318 | * anything actually needs to be shown. |
| | 1319 | */ |
| | 1320 | #define cosmeticSpacingReport(msg, params...) \ |
| | 1321 | (gTranscript.addReport(new CosmeticSpacingCommandReport(msg, ##params))) |
| | 1322 | |
| | 1323 | /* |
| | 1324 | * Add an "extra" report. This is an incidental message that doesn't |
| | 1325 | * affect the display of a default report. |
| | 1326 | */ |
| | 1327 | #define extraReport(msg, params...) \ |
| | 1328 | (gTranscript.addReport(new ExtraCommandReport(msg, ##params))) |
| | 1329 | |
| | 1330 | /* |
| | 1331 | * Set a main report for the current command. This report will be shown |
| | 1332 | * as the main report from the command, overriding any default report for |
| | 1333 | * the command. |
| | 1334 | */ |
| | 1335 | #define mainReport(msg, params...) \ |
| | 1336 | (gTranscript.addReport(new MainCommandReport(msg, ##params))) |
| | 1337 | |
| | 1338 | /* |
| | 1339 | * Set a "before" report for the current command. This report will be |
| | 1340 | * shown before any main report, but will override any default report for |
| | 1341 | * the command. |
| | 1342 | */ |
| | 1343 | #define reportBefore(msg, params...) \ |
| | 1344 | (gTranscript.addReport(new BeforeCommandReport(msg, ##params))) |
| | 1345 | |
| | 1346 | /* |
| | 1347 | * Set an "after" report for the current command. This report will be |
| | 1348 | * shown after any main report, but will override any default report for |
| | 1349 | * the command. |
| | 1350 | */ |
| | 1351 | #define reportAfter(msg, params...) \ |
| | 1352 | (gTranscript.addReport(new AfterCommandReport(msg, ##params))) |
| | 1353 | |
| | 1354 | /* |
| | 1355 | * Report failure. This overrides any default report, and marks the |
| | 1356 | * command as having failed. |
| | 1357 | * |
| | 1358 | * A failure report should NOT indicate any state change - this is |
| | 1359 | * important because failure reports are suppressed under some conditions |
| | 1360 | * (for example, when an NPC is performing an implied command, and the |
| | 1361 | * implied command fails, we don't show the failure report). If a failure |
| | 1362 | * is accompanied by a state change, then a mainReport() should be made in |
| | 1363 | * addition to the failure report - the main report should indicate the |
| | 1364 | * state change. |
| | 1365 | */ |
| | 1366 | #define reportFailure(msg, params...) \ |
| | 1367 | (gTranscript.addReport(new FailCommandReport(msg, ##params))) |
| | 1368 | |
| | 1369 | /* |
| | 1370 | * Report a question. This shows a report that's really an interactive |
| | 1371 | * prompt for more information, such as a prompt for a missing object. |
| | 1372 | */ |
| | 1373 | #define reportQuestion(msg, params...) \ |
| | 1374 | (gTranscript.addReport(new QuestionCommandReport(msg, ##params))) |
| | 1375 | |
| | 1376 | |
| | 1377 | /* ------------------------------------------------------------------------ */ |
| | 1378 | /* |
| | 1379 | * Thing message property overrides sometimes need to be selective about |
| | 1380 | * the role of the object. These macros let you specify that a Thing |
| | 1381 | * message override is only in effect when the Thing is the direct or |
| | 1382 | * indirect object. When the object isn't in the specified role, the |
| | 1383 | * message override will be ignored. |
| | 1384 | * |
| | 1385 | * For example, suppose you want to override an object's response to PUT |
| | 1386 | * IN, but *only* when it's the indirect object of PUT IN - *not* when the |
| | 1387 | * object is itself being put somewhere. To do this, you could give the |
| | 1388 | * object a property like this: |
| | 1389 | * |
| | 1390 | *. notAContainerMsg = iobjMsg('The vase\'s opening is too small. ') |
| | 1391 | * |
| | 1392 | * This specifies that when the object is involved in a PUT IN command that |
| | 1393 | * fails with the 'notAContainerMsg' message, the given message should be |
| | 1394 | * used - but *only* when the object is the indirect object. |
| | 1395 | */ |
| | 1396 | #define dobjMsg(msg) (gDobj == self ? msg : nil) |
| | 1397 | #define iobjMsg(msg) (gIobj == self ? msg : nil) |
| | 1398 | |
| | 1399 | |
| | 1400 | /* ------------------------------------------------------------------------ */ |
| | 1401 | /* |
| | 1402 | * Try performing a command implicitly. The action is the root name of |
| | 1403 | * the action, without the 'Action' suffix - we'll automatically add the |
| | 1404 | * suffix. 'objs' is a varying-length list of the resolved objects in the |
| | 1405 | * new action - the direct object, indirect object, and any others needed |
| | 1406 | * for the action. |
| | 1407 | */ |
| | 1408 | #define tryImplicitAction(action, objs...) \ |
| | 1409 | _tryImplicitAction(gIssuingActor, gActor, &announceImplicitAction, \ |
| | 1410 | action##Action, ##objs) |
| | 1411 | |
| | 1412 | /* |
| | 1413 | * Try performing a command implicitly, with a special descriptive |
| | 1414 | * message. 'msgProp' gives the libMessages method to invoke the announce |
| | 1415 | * the action, if the action is performed. If 'msgProp' is nil, no |
| | 1416 | * message is displayed at all. |
| | 1417 | * |
| | 1418 | * 'action' is the root name of the action, without the 'Action' suffix |
| | 1419 | * (we'll automatically add the suffix). 'objs' is a varying-length list |
| | 1420 | * of the resolved objects - direct object, indirect object, and any |
| | 1421 | * others needed. |
| | 1422 | */ |
| | 1423 | #define tryImplicitActionMsg(msgProp, action, objs...) \ |
| | 1424 | _tryImplicitAction(gIssuingActor, gActor, msgProp, \ |
| | 1425 | action##Action, ##objs) |
| | 1426 | |
| | 1427 | /* |
| | 1428 | * Replace the current action with a new action. The new action will be |
| | 1429 | * performed, and the original action will be terminated with 'exit'. |
| | 1430 | * |
| | 1431 | * 'action' is the root name of the action, without the 'Action' suffix |
| | 1432 | * (we'll add the suffix automatically). 'objs' is a varying-length list |
| | 1433 | * of the resolved objects - direct object, indirect object, etc. |
| | 1434 | */ |
| | 1435 | #define replaceAction(action, objs...) \ |
| | 1436 | _replaceAction(gActor, action##Action, ##objs) |
| | 1437 | |
| | 1438 | /* |
| | 1439 | * Replace the current action with a new action directed to a different |
| | 1440 | * actor (but from the same issuing actor). |
| | 1441 | */ |
| | 1442 | #define replaceActorAction(actor, action, objs...) \ |
| | 1443 | _replaceAction(actor, action##Action, ##objs) |
| | 1444 | |
| | 1445 | /* |
| | 1446 | * Run a nested action. |
| | 1447 | */ |
| | 1448 | #define nestedAction(action, objs...) \ |
| | 1449 | _nestedAction(nil, gActor, action##Action, ##objs) |
| | 1450 | |
| | 1451 | /* |
| | 1452 | * Run a nested action targeted to a given actor. |
| | 1453 | */ |
| | 1454 | #define nestedActorAction(actor, action, objs...) \ |
| | 1455 | _nestedAction(nil, actor, action##Action, ##objs) |
| | 1456 | |
| | 1457 | /* |
| | 1458 | * Run a new action. This is a brand new action run as a separate turn, |
| | 1459 | * not as a nested action. This doesn't replace any current action, but is |
| | 1460 | * simply a separate action. |
| | 1461 | * |
| | 1462 | * This is normally used only for internal actions that are run between |
| | 1463 | * other actions. This should not normally be used while another action is |
| | 1464 | * being processed - use nestedAction for that instead. This should also |
| | 1465 | * not normally be used to replace the current action with another - use |
| | 1466 | * replaceAction for that. |
| | 1467 | * |
| | 1468 | * Returns a CommandTranscript object, which provides information on the |
| | 1469 | * results of the action. |
| | 1470 | */ |
| | 1471 | #define newAction(action, objs...) \ |
| | 1472 | _newAction(CommandTranscript, nil, gActor, action##Action, ##objs) |
| | 1473 | |
| | 1474 | /* run a new action with a specific actor */ |
| | 1475 | #define newActorAction(actor, action, objs...) \ |
| | 1476 | _newAction(CommandTranscript, nil, actor, action##Action, ##objs) |
| | 1477 | |
| | 1478 | /* |
| | 1479 | * Ask for a direct object and retry the command using the single-object |
| | 1480 | * phrasing. This can be used in the action() routine for a no-object |
| | 1481 | * command to ask for the missing direct object. |
| | 1482 | * |
| | 1483 | * In many cases, there is simply no grammar rule for a zero-object form |
| | 1484 | * of a verb; in such cases, this macro is not needed, since the missing |
| | 1485 | * object is handled via the grammar. However, for some actions, it is |
| | 1486 | * desirable to allow the zero-object phrasing some of the time, but |
| | 1487 | * require the direct-object phrasing other times. This macro exists for |
| | 1488 | * these cases, because it allows the intransitive version of the action |
| | 1489 | * to decide, on a case-by-case basis, whether to process the no-object |
| | 1490 | * form of the command or to prompt for a direct object. |
| | 1491 | * |
| | 1492 | * newAction is the root name (without the Action suffix) of the |
| | 1493 | * transitive action to execute. For example, if we're processing a plain |
| | 1494 | * "in" command, we could use askForDobj(Enter) to ask for a direct object |
| | 1495 | * for the transitive "enter" phrasing. |
| | 1496 | */ |
| | 1497 | #define askForDobj(newAction) \ |
| | 1498 | (newAction##Action.retryWithMissingDobj(gAction, ResolveAsker)) |
| | 1499 | |
| | 1500 | /* |
| | 1501 | * Ask for an indirect object and retry the command using the two-object |
| | 1502 | * phrasing. This can be used in the action() routine of a single-object |
| | 1503 | * command to ask for the missing indirect object. |
| | 1504 | * |
| | 1505 | * In many cases, there is simply no grammar rule for a single-object form |
| | 1506 | * of a verb; in such cases, this macro is not needed, since the missing |
| | 1507 | * object is handled via the grammar. However, for some actions, it is |
| | 1508 | * desirable to allow the single-object phrasing some of the time, but |
| | 1509 | * require the two-object phrasing other times. This macro exists for |
| | 1510 | * these cases, because it allows the action() routine to decide, on a |
| | 1511 | * case-by-case basis, whether to process the single-object form of the |
| | 1512 | * command or to prompt for an indirect object. |
| | 1513 | * |
| | 1514 | * newAction is the root name (without the Action suffix) of the |
| | 1515 | * two-object form of the action. For example, if we're processing a |
| | 1516 | * single-object "unlock" command, we would use askForIobj(UnlockWith) to |
| | 1517 | * ask for an indirect object for the "unlock with" two-object phrasing. |
| | 1518 | */ |
| | 1519 | #define askForIobj(newAction) \ |
| | 1520 | (newAction##Action.retryWithMissingIobj(gAction, ResolveAsker)) |
| | 1521 | |
| | 1522 | /* |
| | 1523 | * Ask for a literal phrase and retry the command using the two-object |
| | 1524 | * phrasing. This is analogous to askForDobj() and askForIobj(), but for |
| | 1525 | * literal phrases; we effectively convert a TAction into a |
| | 1526 | * LiteralTAction. |
| | 1527 | */ |
| | 1528 | #define askForLiteral(newAction) \ |
| | 1529 | (newAction##Action.retryWithMissingLiteral(gAction)) |
| | 1530 | |
| | 1531 | /* |
| | 1532 | * Ask for a topic phrase and retry the command using the two-object |
| | 1533 | * phrasing. |
| | 1534 | */ |
| | 1535 | #define askForTopic(newAction) \ |
| | 1536 | (newAction##Action.retryWithMissingTopic(gAction)) |
| | 1537 | |
| | 1538 | /* ------------------------------------------------------------------------ */ |
| | 1539 | /* |
| | 1540 | * Command interruption signal macros. |
| | 1541 | */ |
| | 1542 | |
| | 1543 | /* a concise macro to throw an ExitSignal */ |
| | 1544 | #define exit throw new ExitSignal() |
| | 1545 | |
| | 1546 | /* a concise macro to throw an ExitActionSignal */ |
| | 1547 | #define exitAction throw new ExitActionSignal() |
| | 1548 | |
| | 1549 | /* a concise macro to throw an AbortImplicitSignal */ |
| | 1550 | #define abortImplicit throw new AbortImplicitSignal() |
| | 1551 | |
| | 1552 | |
| | 1553 | /* ------------------------------------------------------------------------ */ |
| | 1554 | /* |
| | 1555 | * Flags for LOOK AROUND styles |
| | 1556 | */ |
| | 1557 | |
| | 1558 | /* show the room name as part of the description */ |
| | 1559 | #define LookRoomName 0x0001 |
| | 1560 | |
| | 1561 | /* show the room's long desription (the roomDesc) */ |
| | 1562 | #define LookRoomDesc 0x0002 |
| | 1563 | |
| | 1564 | /* show the non-portable items (the specialDesc's) */ |
| | 1565 | #define LookListSpecials 0x0004 |
| | 1566 | |
| | 1567 | /* show the portable items */ |
| | 1568 | #define LookListPortables 0x0008 |
| | 1569 | |
| | 1570 | |
| | 1571 | /* ------------------------------------------------------------------------ */ |
| | 1572 | /* |
| | 1573 | * Template for multi-location objects. To put a MultiLoc object in |
| | 1574 | * several initial locations, simply use a template giving the list of |
| | 1575 | * locations. |
| | 1576 | */ |
| | 1577 | MultiLoc template [locationList]; |
| | 1578 | |
| | 1579 | |
| | 1580 | /* ------------------------------------------------------------------------ */ |
| | 1581 | /* |
| | 1582 | * Templates for style tags |
| | 1583 | */ |
| | 1584 | StyleTag template 'tagName' 'openText'? 'closeText'?; |
| | 1585 | |
| | 1586 | |
| | 1587 | /* ------------------------------------------------------------------------ */ |
| | 1588 | /* |
| | 1589 | * A template for footnotes - all we usually need to define in a footnote |
| | 1590 | * is its descriptive text, so this makes it easy to define one. |
| | 1591 | */ |
| | 1592 | Footnote template "desc"; |
| | 1593 | |
| | 1594 | /* footnote status levels */ |
| | 1595 | enum FootnotesOff, FootnotesMedium, FootnotesFull; |
| | 1596 | |
| | 1597 | |
| | 1598 | /* ------------------------------------------------------------------------ */ |
| | 1599 | /* |
| | 1600 | * An achievement defines its descriptive text. It can also optionally |
| | 1601 | * define the number of points it awards. |
| | 1602 | */ |
| | 1603 | Achievement template +points? "desc"; |
| | 1604 | |
| | 1605 | |
| | 1606 | /* ------------------------------------------------------------------------ */ |
| | 1607 | /* |
| | 1608 | * An event list takes a list of strings, objects, and/or functions. |
| | 1609 | */ |
| | 1610 | EventList template [eventList]; |
| | 1611 | |
| | 1612 | /* |
| | 1613 | * A shuffled event list with two lists - the first list is the sequential |
| | 1614 | * initial list, fired in the exact order specified; and the second is the |
| | 1615 | * random list, with the events that occur in shuffled order after we |
| | 1616 | * exhaust the initial list. |
| | 1617 | */ |
| | 1618 | ShuffledEventList template [firstEvents] [eventList]; |
| | 1619 | |
| | 1620 | /* a synchronized event list takes its state from another list */ |
| | 1621 | SyncEventList template ->masterObject inherited; |
| | 1622 | |
| | 1623 | /* low-level shuffled list */ |
| | 1624 | ShuffledList template [valueList]; |
| | 1625 | |
| | 1626 | |
| | 1627 | /* ------------------------------------------------------------------------ */ |
| | 1628 | /* |
| | 1629 | * Define a template for the Tip class. |
| | 1630 | */ |
| | 1631 | Tip template "desc"; |
| | 1632 | |
| | 1633 | |
| | 1634 | /* ------------------------------------------------------------------------ */ |
| | 1635 | /* |
| | 1636 | * Definitions for the menu system |
| | 1637 | */ |
| | 1638 | |
| | 1639 | /* |
| | 1640 | * The indices for the key values used to navigate menus, which are held |
| | 1641 | * in the keyList array of MenuItems. |
| | 1642 | */ |
| | 1643 | #define M_QUIT 1 |
| | 1644 | #define M_PREV 2 |
| | 1645 | #define M_UP 3 |
| | 1646 | #define M_DOWN 4 |
| | 1647 | #define M_SEL 5 |
| | 1648 | |
| | 1649 | /* some templates for defining menu items */ |
| | 1650 | MenuItem template 'title' 'heading'?; |
| | 1651 | MenuTopicItem template 'title' 'heading'? [menuContents]; |
| | 1652 | MenuLongTopicItem template 'title' 'heading'? 'menuContents'; |
| | 1653 | |
| | 1654 | /* templates for hint system objects */ |
| | 1655 | Goal template ->closeWhenAchieved? 'title' 'heading'? [menuContents]; |
| | 1656 | Hint template 'hintText' [referencedGoals]?; |
| | 1657 | |
| | 1658 | /* ------------------------------------------------------------------------ */ |
| | 1659 | /* |
| | 1660 | * Templates for topic database entries. |
| | 1661 | */ |
| | 1662 | |
| | 1663 | /* |
| | 1664 | * A TopicEntry can be defined with an optional score, followed by the |
| | 1665 | * match criteria (which can be either a single matching object, a list of |
| | 1666 | * matching objects, or a regular expression pattern string), followed by |
| | 1667 | * the optional response text (which can be given either as a double-quoted |
| | 1668 | * string or as a list of single-quoted strings to use as an EventList). |
| | 1669 | */ |
| | 1670 | TopicEntry template |
| | 1671 | +matchScore? |
| | 1672 | @matchObj | [matchObj] | 'matchPattern' |
| | 1673 | "topicResponse" | [eventList] ?; |
| | 1674 | |
| | 1675 | /* a ShuffledEventList version of the above */ |
| | 1676 | TopicEntry template |
| | 1677 | +matchScore? |
| | 1678 | @matchObj | [matchObj] | 'matchPattern' |
| | 1679 | [firstEvents] [eventList]; |
| | 1680 | |
| | 1681 | /* we can also include *both* the match object/list *and* pattern */ |
| | 1682 | TopicEntry template |
| | 1683 | +matchScore? |
| | 1684 | @matchObj | [matchObj] |
| | 1685 | 'matchPattern' |
| | 1686 | "topicResponse" | [eventList] ?; |
| | 1687 | |
| | 1688 | /* a ShuffledEventList version of the above */ |
| | 1689 | TopicEntry template |
| | 1690 | +matchScore? |
| | 1691 | @matchObj | [matchObj] |
| | 1692 | 'matchPattern' |
| | 1693 | [firstEvents] [eventList]; |
| | 1694 | |
| | 1695 | /* miscellanous topics just specify the response text or list */ |
| | 1696 | MiscTopic template "topicResponse" | [eventList]; |
| | 1697 | MiscTopic template [firstEvents] [eventList]; |
| | 1698 | |
| | 1699 | /* |
| | 1700 | * A SpecialTopic takes a keyword list or a regular expression instead of |
| | 1701 | * the regular match criteria. It also takes a suggestion name string and |
| | 1702 | * the normal response text. There's no need for a score in a special |
| | 1703 | * topic, since these are unique. |
| | 1704 | */ |
| | 1705 | SpecialTopic template |
| | 1706 | 'name' |
| | 1707 | [keywordList] | 'matchPat' |
| | 1708 | "topicResponse" | [eventList] ?; |
| | 1709 | |
| | 1710 | /* a ShuffledEventList version of the above */ |
| | 1711 | SpecialTopic template |
| | 1712 | 'name' |
| | 1713 | [keywordList] | 'matchPat' |
| | 1714 | [firstEvents] [eventList]; |
| | 1715 | |
| | 1716 | /* default topics just specify the response text */ |
| | 1717 | DefaultTopic template "topicResponse" | [eventList]; |
| | 1718 | DefaultTopic template [firstEvents] [eventList]; |
| | 1719 | |
| | 1720 | /* alternative topics just specify the response string or strings */ |
| | 1721 | AltTopic template "topicResponse" | [eventList]; |
| | 1722 | AltTopic template [firstEvents] [eventList]; |
| | 1723 | |
| | 1724 | /* a TopicGroup can specify its score adjustment */ |
| | 1725 | TopicGroup template +matchScoreAdjustment; |
| | 1726 | |
| | 1727 | /* a conversation node need a name */ |
| | 1728 | ConvNode template 'name'; |
| | 1729 | |
| | 1730 | /* |
| | 1731 | * End-of-conversation reason codes |
| | 1732 | */ |
| | 1733 | enum endConvBye; /* player typed GOODBYE */ |
| | 1734 | enum endConvTravel; /* the other character is trying to travel away */ |
| | 1735 | enum endConvBoredom; /* our attentionSpan has been exhausted */ |
| | 1736 | enum endConvActor; /* the NPC itself (not the player) is saying GOODBYE */ |
| | 1737 | |
| | 1738 | /* |
| | 1739 | * Special result code for Actor.canEndConversation() - this indicates that |
| | 1740 | * the other actor said something to force the conversation to keep going. |
| | 1741 | */ |
| | 1742 | enum blockEndConv; |
| | 1743 | |
| | 1744 | /* ------------------------------------------------------------------------ */ |
| | 1745 | /* |
| | 1746 | * Conversation manager macros |
| | 1747 | */ |
| | 1748 | |
| | 1749 | /* has a topic key been revealed through <.reveal>? */ |
| | 1750 | #define gRevealed(key) (conversationManager.revealedNameTab[key] != nil) |
| | 1751 | |
| | 1752 | /* reveal a topic key, as though through <.reveal> */ |
| | 1753 | #define gReveal(key) (conversationManager.setRevealed(key)) |
| | 1754 | |
| | 1755 | /* mark a Topic/Thing as known/seen by the player character */ |
| | 1756 | #define gSetKnown(obj) (gPlayerChar.setKnowsAbout(obj)) |
| | 1757 | #define gSetSeen(obj) (gPlayerChar.setHasSeen(obj)) |
| | 1758 | |
| | 1759 | #endif /* ADV3_H */ |