| | 1 | <html> |
| | 2 | <title>Recent Changes to the TADS 3 Library</title> |
| | 3 | |
| | 4 | <style type="text/css"><!-- |
| | 5 | |
| | 6 | div.sepbar { |
| | 7 | width: 100%; |
| | 8 | padding-left: 5px; |
| | 9 | padding-right: 5px; |
| | 10 | padding-top: 3px; |
| | 11 | padding-bottom: 3px; |
| | 12 | margin-bottom: 1.5em; |
| | 13 | margin-top: 1.5em; |
| | 14 | background: #c0c0f0; |
| | 15 | color: #000040; |
| | 16 | font-size: 125%; |
| | 17 | text-align: center; |
| | 18 | } |
| | 19 | |
| | 20 | div.firstentry { |
| | 21 | padding: 0em .5ex 1em .5ex; |
| | 22 | margin: 0px .5ex 0px .5ex; |
| | 23 | border-top: none; |
| | 24 | } |
| | 25 | |
| | 26 | div.entry { |
| | 27 | padding: 1em .5ex 1em .5ex; |
| | 28 | margin: 0px .5ex 0px .5ex; |
| | 29 | border-top: 1px solid #c0c0c0; |
| | 30 | } |
| | 31 | |
| | 32 | --></style> |
| | 33 | |
| | 34 | <body> |
| | 35 | |
| | 36 | <h1>Recent Changes to the TADS 3 Library</h1> |
| | 37 | |
| | 38 | <p>This is a list of changes to adv3, the TADS 3 library. |
| | 39 | Changes are listed in reverse chronological order (the most recent |
| | 40 | changes are first). |
| | 41 | |
| | 42 | <ul> |
| | 43 | <li><a href='#3018a'>3.0.18.1</a> |
| | 44 | <li><a href='#3018'>3.0.18</a> |
| | 45 | <li><a href='#3017a'>3.0.17.1</a> |
| | 46 | <li><a href='#3017'>3.0.17</a> |
| | 47 | <li><a href='#3016'>3.0.16</a> |
| | 48 | <li><a href='#3015c'>3.0.15.3</a> |
| | 49 | <li><a href='#3015b'>3.0.15.2</a> |
| | 50 | <li><a href='#3015a'>3.0.15.1</a> |
| | 51 | <li><a href='#3015'>3.0.15</a> |
| | 52 | <li><a href='#3014'>3.0.14</a> |
| | 53 | <li><a href='#3013'>3.0.13</a> |
| | 54 | <li><a href='#3012'>3.0.12</a> |
| | 55 | <li><a href='#3011'>3.0.11</a> |
| | 56 | <li><a href='#3010'>3.0.10</a> |
| | 57 | <li><a href='#309'>3.0.9</a> |
| | 58 | <li><a href='#308'>3.0.8</a> |
| | 59 | <li><a href='#307'>3.0.7</a> |
| | 60 | <li><a href='#306q'>3.0.6q</a> |
| | 61 | <li><a href='#306p'>3.0.6p</a> |
| | 62 | <li><a href='#306o'>3.0.6o</a> |
| | 63 | <li><a href='#306n'>3.0.6n</a> |
| | 64 | <li><a href='#306m'>3.0.6m</a> |
| | 65 | <li><a href='#306l'>3.0.6l</a> |
| | 66 | <li><a href='#306k'>3.0.6k</a> |
| | 67 | <li><a href='#306j'>3.0.6j</a> |
| | 68 | <li><a href='#306i'>3.0.6i</a> |
| | 69 | <li><a href='#306h'>3.0.6h</a> |
| | 70 | <li><a href='#306g'>3.0.6g</a> |
| | 71 | <li><a href='#306f'>3.0.6f</a> |
| | 72 | <li><a href='#306ae'>3.0.6a-e</a> |
| | 73 | <li><a href='#305'>3.0.5</a> |
| | 74 | <li><a href='#304'>3.0.4 and earlier</a> |
| | 75 | </ul> |
| | 76 | |
| | 77 | <!------------------------------- 3.0.18.1 ---------------------------------> |
| | 78 | <div class="sepbar"><a name='3018a'></a>3.0.18.1</div> |
| | 79 | <p><b><i>Released 5/5/2009</i></b> |
| | 80 | <p> |
| | 81 | |
| | 82 | <!-------------------> |
| | 83 | <div class=firstentry> |
| | 84 | |
| | 85 | A typo in the English message for refuseCommand has been fixed. |
| | 86 | |
| | 87 | </div> |
| | 88 | |
| | 89 | |
| | 90 | <!------------------------------- 3.0.18 ---------------------------------> |
| | 91 | <div class="sepbar"><a name='3018'></a>3.0.18</div> |
| | 92 | <p><b><i>Released 4/28/2009</i></b> |
| | 93 | <p> |
| | 94 | |
| | 95 | <!-------------------> |
| | 96 | <div class=firstentry> |
| | 97 | |
| | 98 | More of the lister classes have been reorganized along the same lines |
| | 99 | as the BaseContentsLister refactoring in version 3.0.17. In particular: |
| | 100 | |
| | 101 | <ul> |
| | 102 | <li>surfaceLookInLister, undersideLookUnderLister, and rearLookBehindLister |
| | 103 | are now trivial classes based on the new class LookWhereContentsLister. |
| | 104 | For consistency, thingLookInLister is based on the new class as well, |
| | 105 | but is non-trivial due to its different wording. |
| | 106 | |
| | 107 | <li>surfaceInlineContentsLister, undersideInlineContentsLister, and |
| | 108 | rearInlineContentsLister are now trivial classes based on the new class |
| | 109 | BaseInlineContentsLister. For consistency, inlineContentsLister |
| | 110 | is also based on the new base class, but is non-trivial due to |
| | 111 | its different wording. |
| | 112 | |
| | 113 | </ul> |
| | 114 | |
| | 115 | </div> |
| | 116 | |
| | 117 | <!-------------------> |
| | 118 | <div class=entry> |
| | 119 | |
| | 120 | When an action remapping is inherited from a base class, a subclass or |
| | 121 | instance can now define a verify() method for the original action. In |
| | 122 | the past, only the <b>new</b> action's verify() was called - the |
| | 123 | remapping bypassed any dobjFor() or iobjFor() definitions for the |
| | 124 | old action. This made it impossible to tweak the subclass handling |
| | 125 | for verbs that were remapped in base classes. |
| | 126 | |
| | 127 | <p>With this change, the verify() for the <b>new and old</b> actions |
| | 128 | are <b>both</b> called, <b>if</b> there's a verify() for the old |
| | 129 | action defined on a subclass of the class where the remap() itself is |
| | 130 | defined. In other words, if the verify() "overrides" the remap(), the |
| | 131 | subclassed verify() is invoked. |
| | 132 | |
| | 133 | <p>Because the verify() methods for both the old and new actions are |
| | 134 | called, you can't actually override the new action's verify() call. |
| | 135 | But verify() results are cumulative, so you <i>can</i> use it to |
| | 136 | adjust the logicalness of the action, or to make the action illogical. |
| | 137 | |
| | 138 | </div> |
| | 139 | |
| | 140 | <!-------------------> |
| | 141 | <div class=entry> |
| | 142 | |
| | 143 | The parser can now has an option to generate more descriptive messages |
| | 144 | when noun phrases are disambiguated using the logicalness rules. |
| | 145 | |
| | 146 | <p>Disambiguation occurs when the player uses a noun phrase that |
| | 147 | matches more than one in-scope object. For example, if the current |
| | 148 | room contains a red door and a blue door, and the player types OPEN |
| | 149 | DOOR, the noun phrase DOOR could refer to either of the two door |
| | 150 | objects. The parser must decide which of the two objects the player |
| | 151 | is referring to; this process is called disambiguation. The parser |
| | 152 | does this by applying the various logical, logicalRank, illogicalNow, |
| | 153 | illogicalAlready, and related rules defined on the matching objects in |
| | 154 | the library and in your game code. |
| | 155 | |
| | 156 | <p>There are two kinds of disambiguation results: "clear" and |
| | 157 | "unclear". When exactly one of the objects involved is logical, it's |
| | 158 | a clear disambiguation result: we consider it safe to assume that the |
| | 159 | player was referring to that exact object, since the other choices |
| | 160 | simply don't make sense. When more than one object is logical, |
| | 161 | though, the parser can sometimes still pick one automatically (i.e., |
| | 162 | without generating an extra question asking the player to specify |
| | 163 | which one she intended) based on the "likelihood" rankings given by |
| | 164 | logicalRank rules. A pick based on likelihood rankings is an unclear |
| | 165 | result, because the player could plausibly have been referring to one |
| | 166 | of the other logical matches. |
| | 167 | |
| | 168 | <p>For unclear results, the parser has always generated a |
| | 169 | parenthetical announcement saying which object it chose. This is to |
| | 170 | alert the player to the parser's choice, so that any misunderstanding |
| | 171 | is immediately apparent. |
| | 172 | |
| | 173 | <p>However, in past versions, the parser didn't say anything to |
| | 174 | explicate clear disambiguation results. In practice, even clear |
| | 175 | results can sometimes disagree with the player's intentions, for the |
| | 176 | simple reason that the player sometimes misunderstands the current |
| | 177 | state of the objects. So some authors have found that it's better to |
| | 178 | make some kind of object announcement in every case, regardless of how |
| | 179 | clear the parser thinks the resolution is. |
| | 180 | |
| | 181 | <p>The parser now provides two new modes, in addition to the |
| | 182 | traditional mode, for announcing clear disambiguation results. These |
| | 183 | new modes are selected via the new gameMain property ambigAnnounceMode. |
| | 184 | You can set this in your gameMain object to select the behavior you |
| | 185 | prefer. The settings are: |
| | 186 | |
| | 187 | <ul> |
| | 188 | |
| | 189 | <li>AnnounceUnclear: The parser makes a parenthetical announcement |
| | 190 | (such as "(the red door)") only when a disambiguation result is |
| | 191 | unclear. It doesn't make any announcements for clear disambiguation |
| | 192 | results, or when only one in-scope object matches a noun phrase. |
| | 193 | This is the traditional behavior that the library used before the |
| | 194 | new options were added. |
| | 195 | |
| | 196 | <li>AnnounceClear: The parser makes a parenthetical announcement |
| | 197 | for <i>any</i> disambiguation result, whether clear or unclear. |
| | 198 | No announcement is generated when there's no disambiguation, though |
| | 199 | (that is, the noun phrase itself matches only one in-scope object). |
| | 200 | |
| | 201 | <li>DescribeClear: For unclear disambiguation, the parser makes the |
| | 202 | traditional parenthetical announcement. For clear disambiguation, |
| | 203 | the parser skips the parenthetical announcement, but it uses more |
| | 204 | detailed default reply messages in lieu of the ultra-terse defaults, |
| | 205 | such as "Taken" or "Dropped". For example, instead of just "Taken", |
| | 206 | the parser replies "You take the dusty old tome." The longer messages |
| | 207 | mention the objects involved by name, so they provide the same |
| | 208 | information as the parenthetical announcements, but in a somewhat |
| | 209 | less conspicuous and mechanistic way. |
| | 210 | |
| | 211 | </ul> |
| | 212 | |
| | 213 | <p>Note that the new default behavior differs from the old behavior |
| | 214 | from before this feature was added. If you prefer the old behavior, |
| | 215 | you must explicitly set gameMain.ambigAnnounceMode to AnnounceUnclear. |
| | 216 | |
| | 217 | <p>The short-vs-long message selection for the DescribeClear option is |
| | 218 | done through a couple of new MessageHelper methods, shortTMsg() and |
| | 219 | shortTIMsg(). If you're adding new messages of your own, you can use |
| | 220 | these methods to do the same type of selection. |
| | 221 | |
| | 222 | </div> |
| | 223 | |
| | 224 | <!-------------------> |
| | 225 | <div class=entry> |
| | 226 | |
| | 227 | The parser can now accept short-hand replies to disambiguation queries |
| | 228 | involving a locational qualifier, using nothing more than an adjective |
| | 229 | or noun from one of the location names. For example: |
| | 230 | |
| | 231 | <p><pre> |
| | 232 | <take torch |
| | 233 | Which torch do you mean, the torch in the left sconce, or the torch in |
| | 234 | the right sconce? |
| | 235 | |
| | 236 | >left |
| | 237 | Taken. |
| | 238 | </pre> |
| | 239 | |
| | 240 | <p>In the past, it was necessary for the response to be explicit about |
| | 241 | the location qualification: THE TORCH IN THE LEFT SCONCE, THE ONE IN |
| | 242 | THE LEFT, etc. In particular, the response had to actually use the |
| | 243 | locational phrasing to refer to the distinguishing location. This is |
| | 244 | no longer necessary; a player can now simply name one of the |
| | 245 | locations, and can even abbreviate to a single distinguishing word |
| | 246 | from the location name. |
| | 247 | |
| | 248 | <p>To support this change, the DisambigResolver now keeps track of the |
| | 249 | Distinguisher that was used to generate the question (the prompting |
| | 250 | message - "Which torch do you mean...?"). This lets the resolver look |
| | 251 | for qualifying phrases relevant to the distinguishing characteristic |
| | 252 | called out in the prompt. |
| | 253 | |
| | 254 | <p>The Distinguisher, meanwhile, has a couple of new methods that let |
| | 255 | it provide the added information: objInScope() lets the distinguisher |
| | 256 | add qualifying objects to the scope list, and matchName() lets the |
| | 257 | distinguisher recognize qualifying objects in addition to the original |
| | 258 | ambiguous objects. The locational and ownership distinguishers |
| | 259 | defined in the library provide suitable definitions for these new |
| | 260 | methods. Games that define their own custom Distinguisher subclasses |
| | 261 | might want to add these methods if they also make use of ancillary |
| | 262 | qualifier objects. |
| | 263 | |
| | 264 | </div> |
| | 265 | |
| | 266 | <!-------------------> |
| | 267 | <div class=entry> |
| | 268 | |
| | 269 | In the English library, PathPassage adjusts the logicalness of |
| | 270 | the verbs Enter and Go Through downward (to logical rank 50). These |
| | 271 | verbs aren't usually used with path-like objects in English; |
| | 272 | this logicalness adjustment tells the parser to pick other objects |
| | 273 | first in cases of ambiguity. |
| | 274 | |
| | 275 | </div> |
| | 276 | |
| | 277 | <!-------------------> |
| | 278 | <div class=entry> |
| | 279 | |
| | 280 | The new conversationManager method setRevealed(key) adds the given key |
| | 281 | to the revealed topic table. The library now calls this method any |
| | 282 | time it needs to add a key to the table (whereas it used to manipulate |
| | 283 | the table directly). |
| | 284 | |
| | 285 | <p>These changes don't affect any existing behavior - existing code |
| | 286 | will continue to work unchanged. The purpose of the changes is to |
| | 287 | provide a single point for overriding the default library behavior via |
| | 288 | 'modify'. In particular, you can override setRevealed() to store |
| | 289 | additional information about the revealed topic in its table entry, |
| | 290 | beyond the mere fact of the revelation. You could, for example, store |
| | 291 | the location where the key was revealed, or a time stamp marking when |
| | 292 | it was revealed. |
| | 293 | |
| | 294 | </div> |
| | 295 | |
| | 296 | <!-------------------> |
| | 297 | <div class=entry> |
| | 298 | |
| | 299 | A new ConvNode method, noteActiveReason(reason), extends the older |
| | 300 | noteActive() method by providing information on why the node is being |
| | 301 | activated. The 'reason' parameter is a string indicating what |
| | 302 | triggered the node change: |
| | 303 | |
| | 304 | <ul> |
| | 305 | <li>'convnode' - processing a <.convnode> tag |
| | 306 | <li>'convend' - processing a <.convend> tag |
| | 307 | <li>'initiateConversation' - a call to Actor.initiateConversation() |
| | 308 | <li>'endConversation' - a call to Actor.endConversation() |
| | 309 | </ul> |
| | 310 | |
| | 311 | <p>By default, this new method simply ignores the reason code and |
| | 312 | calls the noteActive() method. This ensures that existing code will |
| | 313 | work unchanged. |
| | 314 | |
| | 315 | <p>If you need the reason information when activating the node, |
| | 316 | override noteActiveReason(). Otherwise, you can override noteActive() |
| | 317 | as in the past. |
| | 318 | |
| | 319 | <p>The new reason code information is supplied when the caller changes |
| | 320 | the node by calling the new Actor method setConvNodeReason(). This is |
| | 321 | essentially an extended version of the existing setConvNode() method. |
| | 322 | The new method takes an additional argument giving the reason code, |
| | 323 | which it passes to noteActiveReason(). |
| | 324 | |
| | 325 | <p>Note that the reason code will be nil if the node change is |
| | 326 | initiated by calling Actor.setConvNode() directly. All of the library |
| | 327 | calls to setConvNode() have been replaced by calls to |
| | 328 | setConvNodeReason(), so unless your game code is calling setConvNode() |
| | 329 | directly, the reason code will always be set properly. For |
| | 330 | compatibility with existing code, setConvNode() can still be called; |
| | 331 | it works as before, simply passing a nil reason code. |
| | 332 | |
| | 333 | </div> |
| | 334 | |
| | 335 | <!-------------------> |
| | 336 | <div class=entry> |
| | 337 | |
| | 338 | <a name="3018-byetopic-convnode"></a>In the past, when an actor used |
| | 339 | conversational states (ConversationReadyState, InConversationState), |
| | 340 | terminating the conversation didn't take into account any ByeTopic |
| | 341 | objects in the current ConvNode within the conversation. This was |
| | 342 | because the conversation states have some special transition handling |
| | 343 | that overrides the usual code where the ConvNode ByeTopic would be |
| | 344 | found. The conversation states now take care to check the ConvNode |
| | 345 | in effect at the end of the conversation, so ByeTopic objects within |
| | 346 | a ConvNode should now interact properly with conversation states. |
| | 347 | |
| | 348 | </div> |
| | 349 | |
| | 350 | <!-------------------> |
| | 351 | <div class=entry> |
| | 352 | |
| | 353 | The transformation from "X, GIVE ME Y" to "ASK X FOR Y" that was |
| | 354 | introduced in 3.0.17 caused a run-time error if "Y" was a valid word |
| | 355 | but didn't resolve to an object. This has been corrected. |
| | 356 | (<a href="http://bugdb.tads.org/view.php?id=0000021">bugdb.tads.org #0000021</a>) |
| | 357 | |
| | 358 | |
| | 359 | </div> |
| | 360 | |
| | 361 | <!-------------------> |
| | 362 | <div class=entry> |
| | 363 | |
| | 364 | In the past, when EXAMINE was used with ItemizingCollectiveGroup, the |
| | 365 | output omitted any object that wasn't listable through the room |
| | 366 | contents lister. This was a problem for objects such as Fixtures, |
| | 367 | which normally aren't displayed in a room listing. |
| | 368 | |
| | 369 | <p>ItemizingCollectiveGroup now calls a new method on self, |
| | 370 | examineUnlisted(x), to list each object <i>x</i> that isn't listed |
| | 371 | via the room contents lister. By default, this new method performs |
| | 372 | a nested EXAMINE command on the unlisted object to show its full |
| | 373 | description. |
| | 374 | |
| | 375 | </div> |
| | 376 | |
| | 377 | <!-------------------> |
| | 378 | <div class=entry> |
| | 379 | |
| | 380 | In Settable, the message routing properties have been changed |
| | 381 | slightly. In the past, the message properties okaySetToMsg and |
| | 382 | setToInvalidMsg were doubly redirected: okaySetToMsg had the value |
| | 383 | &okaySetToMsg, and setToInvalidMsg had the value |
| | 384 | &setToInvalidMsg. The TurnTo action handler that used these |
| | 385 | messages evaluated the properties directly, to get the property |
| | 386 | pointers, which the library then processed in the usual way. |
| | 387 | |
| | 388 | <p>The point of this arrangement was that subclasses of Settable (Dial |
| | 389 | in particular) could easily redirect these messages to different |
| | 390 | library messages, just by overriding the properties. However, this |
| | 391 | was inconsistent with the message scheme most other objects use, in |
| | 392 | that you couldn't override okaySetToMsg(val) in the Settable itself to |
| | 393 | yield the message text, which is how the message scheme works for |
| | 394 | most other objects. |
| | 395 | |
| | 396 | <p>The new version keeps the redirection step, but renames it to allow |
| | 397 | the standard override scheme to be used. The new property okaySetToMsgProp |
| | 398 | evaluates to &okaySetToMsg, and setToInvalidMsgProp evaluates to |
| | 399 | &setToInvalidMsg. This means that you can override okaySetToMsg(val) |
| | 400 | and setToInvalidMsg(val) using the standard pattern. |
| | 401 | |
| | 402 | <p>(<a href="http://bugdb.tads.org/view.php?id=0000045">bugdb.tads.org #0000045</a>) |
| | 403 | |
| | 404 | </div> |
| | 405 | |
| | 406 | <!-------------------> |
| | 407 | <div class=entry> |
| | 408 | |
| | 409 | Underside and RearContainer now provide tryMovingObjInto() method |
| | 410 | definitions. The new methods try the obvious implied commands |
| | 411 | suitable for these objects: Underside tries an implied PutUnder, and |
| | 412 | RearContainer tries an implicit PutBehind. |
| | 413 | |
| | 414 | </div> |
| | 415 | |
| | 416 | <!-------------------> |
| | 417 | <div class=entry> |
| | 418 | |
| | 419 | The BannerWindow method updateForRestore() is now called during a |
| | 420 | Restore or Undo operation for every banner, even when the banner is |
| | 421 | already displayed. In the past, this method wasn't called on banner |
| | 422 | windows that were already present; it was only called when the window |
| | 423 | had to be created in the course of the Restore/Undo. It's now called |
| | 424 | uniformly for all banners. |
| | 425 | |
| | 426 | </div> |
| | 427 | |
| | 428 | <!------------------------------- 3.0.17.1 ---------------------------------> |
| | 429 | <div class="sepbar"><a name='3017a'></a>3.0.17.1</div> |
| | 430 | <p><b><i>Released 8/12/2008</i></b> |
| | 431 | <p> |
| | 432 | |
| | 433 | <!-------------------> |
| | 434 | <div class=firstentry> |
| | 435 | |
| | 436 | <i>This version has no library changes; this release is to correct |
| | 437 | a TADS 3 compiler problem introduced in 3.0.17.</i> |
| | 438 | |
| | 439 | </div> |
| | 440 | |
| | 441 | |
| | 442 | <!------------------------------- 3.0.17 ---------------------------------> |
| | 443 | <div class="sepbar"><a name='3017'></a>3.0.17</div> |
| | 444 | <p><b><i>Released 8/9/2008</i></b> |
| | 445 | <p> |
| | 446 | |
| | 447 | <!-------------------> |
| | 448 | <div class=firstentry> |
| | 449 | |
| | 450 | <b>Risk of incompatibility:</b> The standard handling for the TakeFrom |
| | 451 | action has been changed slightly. The changes generally make it |
| | 452 | easier to code objects by unifying the handling of Take and TakeFrom |
| | 453 | for most objects, but some slight adjustments to existing code might |
| | 454 | be required - see below. |
| | 455 | |
| | 456 | <p>First, Thing.dobjFor(TakeFrom)'s action() handler now actually |
| | 457 | replaces the TakeFrom with a Take action. In the past, the handler |
| | 458 | merely invoked the Take action() handler. For the most part, this had |
| | 459 | the same effect as replacing the action, but not always; some |
| | 460 | arrangements of subclasses and overrides caused subtle differences. |
| | 461 | Actually replacing the action ensures that a successful TakeFrom is |
| | 462 | handled <i>exactly</i> like a regular Take, which means that custom |
| | 463 | behavior for Take will automatically apply exactly the same way to |
| | 464 | TakeFrom without any explicit TakeFrom overrides. Of course, you can |
| | 465 | still override dobjFor(TakeFrom) separately if you do want it to |
| | 466 | behave differently from Take. |
| | 467 | |
| | 468 | <p>Second, Immovable.dobjFor(Take) now fails the action in the check() |
| | 469 | handler rather than the action handler, which allows us to remove |
| | 470 | Immovable.dobjFor(TakeFrom) entirely. In the past, TakeFrom was |
| | 471 | separately overridden to ensure that the indirect object wouldn't |
| | 472 | attempt to carry out the action, but this is no longer necessary, |
| | 473 | since the basic Take check() phase (which TakeFrom's check() phase |
| | 474 | invokes) will fail the command. |
| | 475 | |
| | 476 | <p>These two changes should essentially eliminate the need to override |
| | 477 | TakeFrom when all you want to do is make it behave the same as Take. |
| | 478 | TakeFrom should now always follow Take's lead, so if you simply want |
| | 479 | TakeFrom and Take to behave the same way, just override Take and |
| | 480 | you're set. |
| | 481 | |
| | 482 | <p>Some existing code might not work properly with the changes to |
| | 483 | Immovable. In particular, you'll need to look at any objects of class |
| | 484 | Immovable (or any subclass of Immovable) where you've overridden the |
| | 485 | dobjFor(Take) action() handler. In the past, overriding the action() |
| | 486 | handler for Take was enough to override Immovable's handling of the |
| | 487 | command, since Immovable failed the command in the action() handler |
| | 488 | and did nothing in the check() handler. With the change, the check() |
| | 489 | handler cancels the action. This means that your overridden action() |
| | 490 | handler might never be invoked. The solution is simply to insert an |
| | 491 | empty dobjFor(Take) check() handler in your object: |
| | 492 | |
| | 493 | <p> |
| | 494 | <pre> |
| | 495 | boulder: Immovable 'boulder' 'boulder' "It's a big boulder. " |
| | 496 | dobjFor(Take) |
| | 497 | { |
| | 498 | verify() |
| | 499 | { /* my original verify routine... */ } |
| | 500 | check() { } // THIS HAD TO BE ADDED DUE TO THE LIBRARY CHANGE !!! |
| | 501 | action() |
| | 502 | { /* my original action routine... */ } |
| | 503 | } |
| | 504 | ; |
| | 505 | </pre> |
| | 506 | |
| | 507 | <p>If you're not sure whether you have any objects needing this change, |
| | 508 | you can add this bit of code to your game, and then run the game and |
| | 509 | type IMMTEST to get a list of objects that you should inspect: |
| | 510 | |
| | 511 | <p> |
| | 512 | <pre> |
| | 513 | VerbRule(immtest) 'immtest' : IAction |
| | 514 | execAction() |
| | 515 | { |
| | 516 | "Immovables with dobjFor(Take) action() overrides:\n"; |
| | 517 | forEachInstance(Immovable, new function(x) |
| | 518 | { |
| | 519 | if (overrides(x, Immovable, &actionDobjTake)) |
| | 520 | "\t!!! <<x.name>>\n"; |
| | 521 | }); |
| | 522 | } |
| | 523 | ; |
| | 524 | </div> |
| | 525 | |
| | 526 | <!-------------------> |
| | 527 | <div class=entry> |
| | 528 | |
| | 529 | Krister Fundin's Tips extension has now been integrated into the |
| | 530 | library as a standard feature. This system makes it easy to create |
| | 531 | custom one-time tips of the sort that the library has traditionally |
| | 532 | used for things like the explanation of the NOTIFY command the first |
| | 533 | time the game's score changes. The library now uses the Tips system |
| | 534 | for its standard tips, and the system is readily extensible with |
| | 535 | custom, game-specific tips. A new chapter in the <i>Technical |
| | 536 | Manual</i> describes the system. |
| | 537 | |
| | 538 | </div> |
| | 539 | |
| | 540 | <!-------------------> |
| | 541 | <div class=entry> |
| | 542 | |
| | 543 | |
| | 544 | It's now possible to determine if a script file is currently being |
| | 545 | read, and if so, the modes being used to read it. To get this |
| | 546 | information, call <tt>setScriptFile(ScriptReqGetStatus)</tt>. If |
| | 547 | input is currently being read from a script, the function returns an |
| | 548 | integer value giving a combination of <tt>ScriptFileXxx</tt> flags |
| | 549 | describing the reading mode; for example, the return value will be |
| | 550 | <tt>(ScriptFileQuiet | ScriptFileNonstop)</tt> for a script being read |
| | 551 | in quiet, non-stop mode. Note that a return value of 0 (zero) |
| | 552 | indicates that a script <b>is</b> being read, but that none of the |
| | 553 | mode flags are applicable - that is, the script is being read in the |
| | 554 | default modes, with output and "more" prompts displayed. If a script |
| | 555 | is <b>not</b> currently being read, the return value is nil. |
| | 556 | |
| | 557 | <p>The new flag <tt>ScriptFileEvent</tt> will be included in the |
| | 558 | return value if applicable. This lets you determine whether the |
| | 559 | script being read is an event script or a plain command-line script. |
| | 560 | Note that this new flag is "query only" - if you include it in the |
| | 561 | 'flags' argument in a call to setScriptFile() to start reading a |
| | 562 | script, the function ignores it, since the script reader determines |
| | 563 | the type of the script to be read automatically by examining the |
| | 564 | file's contents. The purpose of this flag is to let you find out how |
| | 565 | the script reader is treating the file, rather than letting you tell |
| | 566 | the script reader how to treat the file. |
| | 567 | |
| | 568 | <p>Note that this new form of setScriptFile() is only supported in VM |
| | 569 | versions 3.0.17 and higher. If you call |
| | 570 | <tt>setScriptFile(ScriptReqGetStatus)</tt> on an earlier VM, a |
| | 571 | run-time error result, because older implementations of the function |
| | 572 | accept only a filename string or nil as the first argument. You can |
| | 573 | use try-catch to handle this situation - a run-time error indicates |
| | 574 | that this form of the function isn't supported, in which case the |
| | 575 | script status information is not available. |
| | 576 | |
| | 577 | </div> |
| | 578 | |
| | 579 | <!-------------------> |
| | 580 | <div class=entry> |
| | 581 | |
| | 582 | Two new actions have been added: RecordEvents and RecordEventsString. |
| | 583 | These are variations on the Record and RecordString actions that |
| | 584 | record event scripts (rather than ordinary command scripts, as Record |
| | 585 | and RecordString do). The English library defines verb syntax for |
| | 586 | these new actions ("record events", "record events on", and "record |
| | 587 | events '<i>filename</i>'"). |
| | 588 | |
| | 589 | </div> |
| | 590 | |
| | 591 | <!-------------------> |
| | 592 | <div class=entry> |
| | 593 | |
| | 594 | A new parsing mechanism makes it possible to rewrite commands based on |
| | 595 | "global" conditions. Unlike remapTo, which lets you associate |
| | 596 | remapping rules with the objects involved in the command, the new |
| | 597 | mechanism lets you rewrite a command even before the objects are |
| | 598 | resolved. There are cases where it's important to be able to apply |
| | 599 | the rewrite before any object resolution has taken place, because the |
| | 600 | resolution process itself can vary substantially depending on the type |
| | 601 | of action being performed. remapTo has to wait until after objects |
| | 602 | are resolved, which is sometimes too late. |
| | 603 | |
| | 604 | <p>This new mechanism is implemented via a new class, GlobalRemapping. |
| | 605 | To create a rewrite rule, you create a GlobalRemapping object, and |
| | 606 | define its getRemapping() method. This method looks at the action to |
| | 607 | determine if it's of interest, using whatever criteria you want. In |
| | 608 | most cases, this means checking the action type to see if it's an |
| | 609 | action you want to rewrite, and possibly checking to see if certain |
| | 610 | objects are involved as well. |
| | 611 | |
| | 612 | <p>The library defines one GlobalRemapping object, giveMeToAskFor, |
| | 613 | which rewrites commands of the form "X, GIVE ME Y" to the alternative |
| | 614 | format "ME, ASK X FOR Y". The library formerly <i>tried</i> to |
| | 615 | perform this same rewriting via an iobjFor(GiveTo) check() method in |
| | 616 | Actor, but this approach didn't work in many cases due to interference |
| | 617 | from several other checks made earlier in the execution process. The |
| | 618 | old check() scheme has been deleted in favor of the new mechanism. |
| | 619 | |
| | 620 | <p>For full details, see the new chapter on Global Command Remapping |
| | 621 | in the <i>Technical Manual</i>. |
| | 622 | |
| | 623 | </div> |
| | 624 | |
| | 625 | <!-------------------> |
| | 626 | <div class=entry> |
| | 627 | |
| | 628 | A new set of Action methods makes it possible to temporarily override |
| | 629 | the meaning of a pronoun, for as long as the action is in effect. |
| | 630 | Action.setPronounOverride() creates an override, which associates an |
| | 631 | object with a particular pronoun type (PronounMe, PronounYou, etc). |
| | 632 | This new meaning overrides the usual meaning, but only for the |
| | 633 | duration of the action. Action.getPronounOverride() looks for an |
| | 634 | override defined with setPronounOverride() for this action. |
| | 635 | |
| | 636 | <p>This new mechanism is designed mainly to support GlobalRemapping. |
| | 637 | In particular, a remapping that changes the target actor usually needs |
| | 638 | to override the meaning of "you" in the rewritten action, so that |
| | 639 | "you", "your", and "yours" are interpreted as referring to the |
| | 640 | <i>original</i> target actor rather than the target actor of the |
| | 641 | rewritten format. |
| | 642 | |
| | 643 | <p>For details, see the new chapter "Global Command Remapping" in |
| | 644 | the <i>Technical Manual</i>. |
| | 645 | |
| | 646 | </div> |
| | 647 | |
| | 648 | <!-------------------> |
| | 649 | <div class=entry> |
| | 650 | |
| | 651 | The classes BaseSurfaceContentsLister, BaseRearContentsLister, and |
| | 652 | BaseUndersideContentsLister are now all based on a new class, |
| | 653 | BaseContentsLister. This new class unifies the code that was formerly |
| | 654 | defined separately in the three subclasses - |
| | 655 | BaseSurfaceContentsLister, BaseRearContentsLister, and |
| | 656 | BaseUndersideContentsLister are now trivial subclasses with no |
| | 657 | overrides of their own. (They're still present as separate classes, |
| | 658 | (1) for the sake of compatibility with existing code, and (2) because |
| | 659 | the distinct classes could still be useful for other types of |
| | 660 | container-type-specific overrides beyond what the library defines.) |
| | 661 | |
| | 662 | <p>The three subclasses exist to provide customized wording in the |
| | 663 | contents listings generated for the corresponding specialized |
| | 664 | container types. However, the variation in the wording provided by |
| | 665 | the library definitions was always very simple - the only thing that |
| | 666 | varies is the preposition used to describe the relationship between |
| | 667 | the container and its contents ("on" for a Surface, "under" for an |
| | 668 | Underside object, "behind" for a RearContainer or RearSurface). As it |
| | 669 | turns out, the needed preposition is available as a property of the |
| | 670 | container object, namely objInPrep. This makes it possible to unify |
| | 671 | the code for the three classes by referring to this property rather |
| | 672 | than hard-coding the preposition - by doing this, the code for the |
| | 673 | three subclasses becomes identical, which allows it to be consolidated |
| | 674 | in a common base class. |
| | 675 | |
| | 676 | <p>The advantage of this change is that it's no longer necessary to |
| | 677 | change a specialized container's contents-lister class simply because |
| | 678 | you want to change the preposition used to describe the relationship |
| | 679 | between contents and container. In the past, you had to change |
| | 680 | <i>both</i> objInPrep and the contents lister. Now, changing |
| | 681 | objInPrep is enough - since the default contents listers refer to |
| | 682 | objInPrep, changes to objInPrep will automatically flow through to the |
| | 683 | wording in contents listings. |
| | 684 | |
| | 685 | <p>Because the class structure is the same as before, existing code |
| | 686 | should work unchanged, and you can still use contents lister |
| | 687 | customizations to achieve effects beyond the simple wording changes |
| | 688 | that objInPrep provides, if needed. |
| | 689 | |
| | 690 | </div> |
| | 691 | |
| | 692 | <!-------------------> |
| | 693 | <div class=entry> |
| | 694 | |
| | 695 | <p>The new class ActorHelloTopic makes it easier to |
| | 696 | create a greeting message for cases where the NPC initiates a |
| | 697 | conversation through a script. Place an ActorHelloTopic object |
| | 698 | anywhere a HelloTopic would go to create a greeting specifically |
| | 699 | for the case of an NPC-initiated conversation. |
| | 700 | |
| | 701 | <p>[Update for 3.0.18: disregard the following. These changes |
| | 702 | were not effected as described, and weren't quite what was intended. |
| | 703 | See <a href="#3018-byetopic-convnode">this entry</a> for an update.] |
| | 704 | |
| | 705 | <p><i> |
| | 706 | ByeTopic objects can now be used with actors who use conversational |
| | 707 | states (ConversationReadyState, InConversationState). In the past, |
| | 708 | the conversational states largely bypassed the topic-based Goodbye |
| | 709 | processing, so goodbyes had to be written with the specialized goodbye |
| | 710 | methods on the state objects. This made the conversation states |
| | 711 | harder to use, since it created special cases you had to be aware of. |
| | 712 | Now, you can set up a goodbye message by locating a ByeTopic within |
| | 713 | the InConversationState or within any ConvNode. |
| | 714 | </i> |
| | 715 | |
| | 716 | </div> |
| | 717 | |
| | 718 | |
| | 719 | <!-------------------> |
| | 720 | <div class=entry> |
| | 721 | |
| | 722 | The class ComplexComponent now defines stagingLocations as the lexical |
| | 723 | parent's (which is normally the ComplexContainer's) location. This |
| | 724 | makes it easier to embed a nested room (a platform, booth, etc) as a |
| | 725 | component of a complex container object, by allowing inbound travel |
| | 726 | into the nested room to bypass the complex container and move directly |
| | 727 | between the enclosing location and the component/nested room. As with |
| | 728 | other aspects of complex containers, the container and component are |
| | 729 | meant to look and act like a single object, from the player's |
| | 730 | perspective, so it's not desirable to treat the container and |
| | 731 | component as separate objects for the purposes of nested room travel. |
| | 732 | |
| | 733 | <p>Along the same lines, ComplexContainer now tries to remap the |
| | 734 | actions StandOn, SitOn, LieOn, Board, and Enter to a suitable |
| | 735 | component. These actions are now automatically remapped to the object |
| | 736 | returned from the new method getNestedRoomDest(), if any. If that |
| | 737 | method returns nil, the actions are not remapped after all. |
| | 738 | |
| | 739 | <p>The new getNestedRoomDest() method of ComplexContainer looks for a |
| | 740 | suitable component to use as the destination of a nested room travel |
| | 741 | command. By default, it first looks to see if the sub-surface |
| | 742 | component is a NestedRoom object, and if so, returns that; otherwise, |
| | 743 | it checks the sub-container component, and returns that if that's a |
| | 744 | NestedRoom; otherwise it returns nil. This default behavior makes |
| | 745 | everything automatic for cases where you have exactly one component |
| | 746 | that's a nested room. If you want to define more than one nested room |
| | 747 | within a complex container (for example, a large crate that you can |
| | 748 | STAND ON and also GET IN), you will need to override |
| | 749 | getNestedRoomDest() to return the appropriate destination by verb, or |
| | 750 | you can simply override the dobjFor(action) remapTo() definition to |
| | 751 | point remap to the correct component. |
| | 752 | |
| | 753 | </div> |
| | 754 | |
| | 755 | <!-------------------> |
| | 756 | <div class=entry> |
| | 757 | |
| | 758 | A bug in the parser sometimes caused "truncated plurals" to be |
| | 759 | selected ahead of exact matches in a player's answer to a |
| | 760 | disambiguation question. By design, the parser prefers an exact match |
| | 761 | to a singular noun ahead of a partial match to a plural (for example, |
| | 762 | with the default six-letter truncation, the word "object" in command |
| | 763 | input would match either the singular "object" or the plural |
| | 764 | "objects", but the parser assume the singular word was intended |
| | 765 | because it's an exact match for the input). However, this principle |
| | 766 | was being ignored in this case due to the bug. This has now been |
| | 767 | corrected. |
| | 768 | (<a href="http://bugdb.tads.org/view.php?id=0000006">bugdb.tads.org #0000006</a>) |
| | 769 | |
| | 770 | </div> |
| | 771 | |
| | 772 | <!-------------------> |
| | 773 | <div class=entry> |
| | 774 | |
| | 775 | In the past, if a ConvNode was activated via the <.convnode> |
| | 776 | tag, and the ConvNode's noteActive() method displayed any text, the |
| | 777 | text displayed within noteActive() appeared out of order in the final |
| | 778 | output relative to the text containing the <.convnode> tag. |
| | 779 | This happened because <.convnode> is processed within an output |
| | 780 | filter, so the entire string containing the <.convnode> had to |
| | 781 | be processed by the filter before any of it was actually displayed; if |
| | 782 | any text was displayed in the course of recursively called routines |
| | 783 | such as noteActive(), that text would as a result show up first in the |
| | 784 | final output. |
| | 785 | |
| | 786 | <p>The <.convnode> output filter now captures any text that's |
| | 787 | displayed in the course of activating a new ConvNode, and re-inserts |
| | 788 | the text into the stream at the proper point. This ensures that the |
| | 789 | text appears in the correct sequence, so it's now safe to display text |
| | 790 | from within a noteActive() routine. |
| | 791 | (<a href="http://bugdb.tads.org/view.php?id=0000003">bugdb.tads.org #0000003</a>) |
| | 792 | |
| | 793 | </div> |
| | 794 | |
| | 795 | <!-------------------> |
| | 796 | <div class=entry> |
| | 797 | |
| | 798 | In the past, TIAction verbs (those taking a direct object and an |
| | 799 | indirect object, such as PUT IN or UNLOCK WITH) had the side effect of |
| | 800 | clearing the parser's memory of gender-specific pronoun antecedents. |
| | 801 | For example, after typing "LOOK AT BOB; UNLOCK THE DOOR WITH HIS KEY", |
| | 802 | the parser would forget that "him" refers to Bob, even though there |
| | 803 | wasn't anyone else mentioned in the second command to supersede the |
| | 804 | meaning of "him". This has been fixed. |
| | 805 | (<a href="http://bugdb.tads.org/view.php?id=0000020">bugdb.tads.org #0000020</a>) |
| | 806 | |
| | 807 | </div> |
| | 808 | |
| | 809 | <!-------------------> |
| | 810 | <div class=entry> |
| | 811 | |
| | 812 | The Room class now applies a lower level of disambiguation |
| | 813 | "likelihood" for the Examine action to a remote room than for a room |
| | 814 | containing the actor. In the past, the class applied a |
| | 815 | lower-than-default likelihood for a room containing the actor, on the |
| | 816 | assumption that a player who types EXAMINE FOO probably means to |
| | 817 | examine a nearby object rather than the enclosing room, when both are |
| | 818 | called FOO. However, there's a third possibility, which is that |
| | 819 | there's a remote room (i.e., a separate top-level room that's |
| | 820 | connected to the current location by a sense connection) in scope |
| | 821 | that's <i>also</i> called FOO. In these cases, we'd still want to |
| | 822 | select the nearby object over either room; but in cases where we only |
| | 823 | have the two rooms to decide between, it seems most likely that the |
| | 824 | player would want to refer to the enclosing room rather than the |
| | 825 | remote one. This new distinction in the likelihood levels of |
| | 826 | enclosing and remote rooms accomplishes this: the most likely |
| | 827 | selection is still a nearby non-room object, the next most likely is |
| | 828 | the enclosing room, and the least likely is a remote room. |
| | 829 | |
| | 830 | |
| | 831 | </div> |
| | 832 | |
| | 833 | |
| | 834 | |
| | 835 | <!------------------------------- 3.0.16 ---------------------------------> |
| | 836 | <div class="sepbar"><a name='3016'></a>3.0.16</div> |
| | 837 | <p><b><i>Released 4/10/2008</i></b> |
| | 838 | <p> |
| | 839 | |
| | 840 | <!-------------------> |
| | 841 | <div class=firstentry> |
| | 842 | |
| | 843 | The new class SimpleLister provides simplified interfaces for creating |
| | 844 | formatted lists of items. This class is useful when you just want to |
| | 845 | create a textual listing, using the standard serial-comma generation |
| | 846 | and so on, without all the hassle of specifying a sense environment, |
| | 847 | point of view, etc. The class also has a method that creates a text |
| | 848 | string for a listing (rather than displaying the list directly, which |
| | 849 | is what the base Lister normally does). |
| | 850 | |
| | 851 | <p>Two concrete instances of SimpleLister are provided, to further |
| | 852 | simplify particular listings: objectLister, which can be used to |
| | 853 | format a list of simulation objects; and stringLister, which can be |
| | 854 | used to format a list of string values. |
| | 855 | |
| | 856 | </div> |
| | 857 | |
| | 858 | <!-------------------> |
| | 859 | <div class=entry> |
| | 860 | |
| | 861 | Commands of the form "X, Y", where both X and Y were words not in the |
| | 862 | game's dictionary, caused a run-time error ("nil object reference"). |
| | 863 | This was due to a library bug in the code that resolves the actor |
| | 864 | object when giving orders to an actor ("BOB, GO EAST"). This has been |
| | 865 | corrected. |
| | 866 | |
| | 867 | </div> |
| | 868 | |
| | 869 | <!-------------------> |
| | 870 | <div class=entry> |
| | 871 | |
| | 872 | The Goal object has a new property, goalFullyDisplayed, that the hint |
| | 873 | system automatically sets to true upon displaying the last hint in the |
| | 874 | Goal's menu list. This can be used, for example, to close a hint for |
| | 875 | a red herring after the player's seen the full list of hints; this |
| | 876 | might be desirable to remove clutter from the menu, since the player |
| | 877 | probably won't worry about an object again once it's been revealed |
| | 878 | that it's just a red herring. |
| | 879 | |
| | 880 | </div> |
| | 881 | |
| | 882 | <!-------------------> |
| | 883 | <div class=entry> |
| | 884 | |
| | 885 | The templates for TravelMessage, NoTravelMessage, and DeadEndConnector |
| | 886 | now accept an event list (given as a list in square brackets) in lieu |
| | 887 | of a double-quoted message string. These classes were already mixable |
| | 888 | (via multiple inheritance) with EventList, so this change simply makes |
| | 889 | it more convenient to define instances when using this capability. |
| | 890 | |
| | 891 | </div> |
| | 892 | |
| | 893 | <!-------------------> |
| | 894 | <div class=entry> |
| | 895 | |
| | 896 | Top-level rooms (i.e., Room objects) didn't properly handle ENTER |
| | 897 | commands (e.g., ENTER HALLWAY) when attempted from a separate |
| | 898 | top-level room connected via a sense connector. The ENTER handling |
| | 899 | for Room incorrectly assumed that only one top-level room was in scope |
| | 900 | at a time, which isn't true when rooms have sense connections. The |
| | 901 | handler also failed to handle the simpler situation where the actor |
| | 902 | was in a nested room within the target room. |
| | 903 | |
| | 904 | <p>The Room dobjFor(Enter) handler has been improved to handle |
| | 905 | such situations. The new handling is as follows: |
| | 906 | |
| | 907 | <ul> |
| | 908 | |
| | 909 | <li>If the actor is already <i>directly</i> in the target room (for |
| | 910 | example, the player types ENTER HALLWAY while already in the hall), |
| | 911 | the behavior is as before ("You're already in the hallway"). |
| | 912 | |
| | 913 | <li>If the actor is <i>indirectly</i> in the target room (for example, |
| | 914 | the PC is sitting in a chair in the hall, and types ENTER HALLWAY), |
| | 915 | the command is replaced with GET OUT OF <i>outermost nested room |
| | 916 | containing actor within target room</i>. |
| | 917 | |
| | 918 | <li>If the actor is in a separate top-level room, <i>and</i> there's |
| | 919 | a travel connector from the actor's current location to the target |
| | 920 | room, the command is replaced with TRAVEL VIA <i>connector</i>. |
| | 921 | |
| | 922 | <li>Otherwise, the command fails with the message &whereToGoMsg |
| | 923 | ("You'll have to say which way to go"). |
| | 924 | |
| | 925 | </ul> |
| | 926 | |
| | 927 | </div> |
| | 928 | |
| | 929 | <!-------------------> |
| | 930 | <div class=entry> |
| | 931 | |
| | 932 | In the past, when NestedRoom.checkMovingActorInto() decided it had to |
| | 933 | perform an implied action to move the actor into the nested room, the |
| | 934 | routine assumed that the action failed if the actor didn't end up in |
| | 935 | the nested room <i>and</i> in the room's default posture. This |
| | 936 | condition does hold for the library NestedRoom subclasses when the |
| | 937 | defaults are inherited, but overriding either the default posture or |
| | 938 | the implied command for a particular instance can make the condition |
| | 939 | fail. When the condition fails, the routine infers that the implied |
| | 940 | action failed, and terminates the whole command. |
| | 941 | |
| | 942 | <p>This condition - specifically, the test for posture - is overly |
| | 943 | strict. The routine isn't documented as guaranteeing the default |
| | 944 | posture, and in fact it never did guarantee the default posture |
| | 945 | anyway, as the implied action was always bypassed if the actor's |
| | 946 | location was initially correct, regardless of posture. |
| | 947 | |
| | 948 | <p>So, the condition has now been changed to remove the default |
| | 949 | posture check. The implied command (if any) is now considered |
| | 950 | successful if the actor is directly in the nested room afterward. |
| | 951 | |
| | 952 | </div> |
| | 953 | |
| | 954 | <!-------------------> |
| | 955 | <div class=entry> |
| | 956 | |
| | 957 | Two changes to BasicChair simplify the way the "get in" commands for |
| | 958 | the object and its subclasses are implemented. |
| | 959 | |
| | 960 | <p><b>First</b>, the tryMovingIntoNested() routines in BasicChair and |
| | 961 | its subclasses have been unified into a single base-class method. In |
| | 962 | the past, each BasicChair subclass overrode tryMovingIntoNested() to |
| | 963 | perform the implied action matching the subclass type - SitOn for |
| | 964 | BasicChair, LieOn for BasicBed, StandOn for BasicPlatform. |
| | 965 | |
| | 966 | <p>Now, the overrides have been removed, and the functionality has |
| | 967 | been been unified into a single method on BasicChair that the |
| | 968 | subclasses all inherit. The BasicChair version of the method handles |
| | 969 | all of the subclasses by deferring to the default posture object (as |
| | 970 | returned from the defaultPosture property). |
| | 971 | |
| | 972 | <p><b>Second</b>, the dobjFor(Board) definitions have been unified |
| | 973 | in a single BasicChair definition, rather than requiring overrides |
| | 974 | in each subclass as in the past. As with tryMovingIntoNested(), |
| | 975 | the dobjFor(Board) definition in BasicChair now calls upon the |
| | 976 | default posture object to carry out the appropriate command. This |
| | 977 | removes the need to override dobjFor(Board) in each subclass. |
| | 978 | |
| | 979 | <p>The benefit of these changes is that there's less to override when |
| | 980 | creating a custom type of BasicChair subclass. Setting the |
| | 981 | defaultPosture also automatically takes care of setting the implied |
| | 982 | action for "get in" and the mapped action for "board", since |
| | 983 | tryMovingIntoNested() and dobjFor(Board) now choose the sub-action |
| | 984 | that matches the default posture. Of course, if for some reason you |
| | 985 | want these actions to differ from what the default posture selects, |
| | 986 | you can still override tryMovingIntoNested() and/or dobjFor(Board) to |
| | 987 | achieve whatever special effects you want. For typical objects where |
| | 988 | the two match, though, these changes means less work is needed to keep |
| | 989 | everything in sync. |
| | 990 | |
| | 991 | </div> |
| | 992 | |
| | 993 | <!-------------------> |
| | 994 | <div class=entry> |
| | 995 | |
| | 996 | The "standing" posture object's setActorToPosture() method has been |
| | 997 | changed slightly. In the past, the routine performed an intransitive |
| | 998 | Stand action, which causes the actor to stand up in whatever location |
| | 999 | it's currently occupying. This was at odds with the specification of |
| | 1000 | the method: the routine should not only make the actor stand up, but |
| | 1001 | make the actor stand in a given location; the old version ignored the |
| | 1002 | target location. The routine now does use the target location, and |
| | 1003 | executes a transitive StandOn action with the target location as |
| | 1004 | direct object. |
| | 1005 | |
| | 1006 | <p>The old implementation was the way it was because the transitive |
| | 1007 | StandOn action didn't always work properly when applied to top-level |
| | 1008 | rooms. However, the handling of StandOn for top-level rooms has since |
| | 1009 | been improved, so this is now a viable implementation. This makes the |
| | 1010 | method work consistently with its specification and with the |
| | 1011 | corresponding methods in the other pre-defined posture objects. |
| | 1012 | |
| | 1013 | </div> |
| | 1014 | |
| | 1015 | <!-------------------> |
| | 1016 | <div class=entry> |
| | 1017 | |
| | 1018 | The Decoration class now overrides the SEARCH action so that it uses |
| | 1019 | the standard Thing handling, to be consistent with the way LOOK IN is |
| | 1020 | handled. In the past, SEARCH instead was handled by the Decoration |
| | 1021 | catch-all verb handler, which shows the generic "that's not important" |
| | 1022 | message. This led to different default Decoration behavior for SEARCH |
| | 1023 | vs LOOK IN, which was inconsistent with the library's usual default |
| | 1024 | treatment of the two actions as synonymous. |
| | 1025 | |
| | 1026 | </div> |
| | 1027 | |
| | 1028 | <!-------------------> |
| | 1029 | <div class=entry> |
| | 1030 | |
| | 1031 | The English library's typographical output filter object |
| | 1032 | (typographicalOutputFilter) ordinarily adds an "en" space (a space |
| | 1033 | that's slightly wider than a normal inter-word space) after any |
| | 1034 | sentence-ending punctuation, such as a period or question mark. This |
| | 1035 | produces looser spacing between sentences, which some people find |
| | 1036 | easier to read. However, it had an undesirable side effect, which was |
| | 1037 | to add the same spacing after honorific abbreviations like Mr. and |
| | 1038 | Mrs. - these look exactly like sentence endings, as far as the simple |
| | 1039 | substitution rule was concerned. |
| | 1040 | |
| | 1041 | <p>The filter now specifically looks for a pre-defined set of |
| | 1042 | abbreviations, and suppresses the extra spacing when it finds one. |
| | 1043 | The abbreviations are given by the property |
| | 1044 | typographicalOutputFilter.abbreviations - to change or add to the set |
| | 1045 | of abbreviations, modify typographicalOutputFilter to change this |
| | 1046 | property. (Note that this property is only evaluated once, at program |
| | 1047 | start-up, so changing it on the fly won't have any effect. If you do |
| | 1048 | want to modify the set of abbreviations dynamically, you'll have to |
| | 1049 | instead update typographicalOutputFilter.abbrevPat to use a new |
| | 1050 | RexPattern object with the new set of abbreviations.) |
| | 1051 | |
| | 1052 | </div> |
| | 1053 | |
| | 1054 | <!-------------------> |
| | 1055 | <div class=entry> |
| | 1056 | |
| | 1057 | DistanceConnector now allows moving objects through the connector via |
| | 1058 | moveInto - in particular, DistanceConnector now overrides |
| | 1059 | checkMoveThrough() to return a "success" indication. |
| | 1060 | In the past, DistanceConnector inherited checkMoveThrough() from |
| | 1061 | SenseConnector, which disallowed a move via moveInto() if the distance |
| | 1062 | connector was involved. |
| | 1063 | |
| | 1064 | <p>In the abstract, there's usually no good reason that an object |
| | 1065 | can't be moved through a distance connector. The only reason to |
| | 1066 | disallow it might be that the distance involved is so great that it |
| | 1067 | would take an impractical amount of time to complete the move. |
| | 1068 | |
| | 1069 | <p>More to the point, though, player commands will generally disallow |
| | 1070 | this kind of operation for reasons of reachability - a touchObj |
| | 1071 | precondition is involved for any basic command that moves an object |
| | 1072 | from one container to another (TAKE, DROP, PUT IN, PUT ON, etc), and |
| | 1073 | that precondition will fail separately because the distance object is |
| | 1074 | unreachable. Because of this, a moveInto() involving a distance |
| | 1075 | connector is almost certainly due to a programmatic (scripted) |
| | 1076 | operation, rather than a basic player command. In the past, you could |
| | 1077 | work around this by calling moveIntoForTravel() instead of moveInto(), |
| | 1078 | but this was a needless complication. This change allows moveInto() |
| | 1079 | to succeed even if a distance connector is involved. |
| | 1080 | |
| | 1081 | </div> |
| | 1082 | |
| | 1083 | <!-------------------> |
| | 1084 | <div class=entry> |
| | 1085 | |
| | 1086 | The ShuffledEventList object has a new property, suppressRepeats, that |
| | 1087 | lets you control whether or not a given event can occur twice in a |
| | 1088 | row. This property corresponds to the suppressRepeats property of |
| | 1089 | the ShuffledList object. |
| | 1090 | |
| | 1091 | <p>By default, this is set to true, which yields the former behavior. |
| | 1092 | You can set this to nil if you don't want to suppress repeats. With |
| | 1093 | very small lists (of three or four elements), the suppression of |
| | 1094 | repeats sometimes makes the result sequence look fairly un-random, |
| | 1095 | because the no-repeats constraint reduces the number of available |
| | 1096 | permutations. If you see output for a small event list that doesn't |
| | 1097 | look random enough, you might try setting suppressRepeats to nil to |
| | 1098 | see if that produces more pleasing results. |
| | 1099 | |
| | 1100 | </div> |
| | 1101 | |
| | 1102 | <!-------------------> |
| | 1103 | <div class=entry> |
| | 1104 | |
| | 1105 | ShuffledList now ignores suppressRepeats for a two-element list. If |
| | 1106 | the list has only two elements, and repeats aren't allowed, the list |
| | 1107 | will necessarily yield the predictable sequence A-B-A-B..., which |
| | 1108 | defeats the purpose of the shuffled list. |
| | 1109 | |
| | 1110 | </div> |
| | 1111 | |
| | 1112 | <!-------------------> |
| | 1113 | <div class=entry> |
| | 1114 | |
| | 1115 | The Lockable class's dobjFor(Open) check() method now inherits the |
| | 1116 | default handling. Since Lockable is designed to be used as a mix-in |
| | 1117 | class, this addition ensures that any additional Open checks inherited |
| | 1118 | from other superclasses are properly invoked. |
| | 1119 | |
| | 1120 | </div> |
| | 1121 | |
| | 1122 | <!-------------------> |
| | 1123 | <div class=entry> |
| | 1124 | |
| | 1125 | The comment pre-parser object (commentPreParser) now sets a runOrder |
| | 1126 | value that's lower than the default, so that it runs before other |
| | 1127 | pre-parsers that inherit the default runOrder. In most cases, it's |
| | 1128 | unnecessary (and even potentially problematic) to run comments through |
| | 1129 | other pre-parsers, since most are designed to parse the usual sorts of |
| | 1130 | command syntax, not the free-form text allowed in comments. Running |
| | 1131 | the comment pre-parser first effectively bypasses other pre-parsers |
| | 1132 | when a comment is encountered, since the comment pre-parser halts |
| | 1133 | further processing of the command when it detects that the command is |
| | 1134 | actually a comment. |
| | 1135 | |
| | 1136 | </div> |
| | 1137 | |
| | 1138 | <!-------------------> |
| | 1139 | <div class=entry> |
| | 1140 | |
| | 1141 | In the past, if an actor returned nil from obeyCommand(), the parser |
| | 1142 | ignored the command for the purposes of the AGAIN command. A |
| | 1143 | subsequent AGAIN command in this case simply repeated the |
| | 1144 | <i>previous</i> command - the one just before the refused order. This |
| | 1145 | has been corrected; the parser now remembers a command for AGAIN even |
| | 1146 | if the actor to whom the command is directed refuses it. |
| | 1147 | |
| | 1148 | </div> |
| | 1149 | |
| | 1150 | <!-------------------> |
| | 1151 | <div class=entry> |
| | 1152 | |
| | 1153 | Thing.setGlobalParamName() didn't correctly delete any previous name |
| | 1154 | from the global table. (This would only have been a problem if you |
| | 1155 | used the method more than once on a particular object, to change the |
| | 1156 | object's global parameter name on the fly, which seems highly |
| | 1157 | unlikely.) This has been corrected. |
| | 1158 | |
| | 1159 | </div> |
| | 1160 | |
| | 1161 | |
| | 1162 | <!------------------------------- 3.0.15.3 ---------------------------------> |
| | 1163 | <div class="sepbar"><a name='3015c'></a>3.0.15.3</div> |
| | 1164 | <p><b><i>Released 11/2/2007</i></b> |
| | 1165 | <p> |
| | 1166 | <!-------------------> |
| | 1167 | <div class=firstentry> |
| | 1168 | <i>There are no library changes in this release.</i> |
| | 1169 | </div> |
| | 1170 | |
| | 1171 | |
| | 1172 | <!------------------------------- 3.0.15.2 ---------------------------------> |
| | 1173 | <div class="sepbar"><a name='3015b'></a>3.0.15.2</div> |
| | 1174 | <p><b><i>Released 9/13/2007</i></b> |
| | 1175 | <p> |
| | 1176 | |
| | 1177 | <!-------------------> |
| | 1178 | <div class=firstentry> |
| | 1179 | |
| | 1180 | NonObviousVerifyResult.resultRank is now defined as the same value as |
| | 1181 | IllogicalVerifyResult.resultRank. This makes the parser treat |
| | 1182 | illogical and non-obvious objects as equivalent in cases of ambiguity, |
| | 1183 | so that the parser won't choose one over the other. In the past, |
| | 1184 | non-obvious objects were ranked lower than illogical objects, which |
| | 1185 | caused the parser to choose an illogical object over a non-obvious |
| | 1186 | object in cases of ambiguity. This didn't quite make sense; for the |
| | 1187 | purposes of choosing among ambiguous objects, non-obvious objects |
| | 1188 | really should be treated as equivalent to ordinarily illogical |
| | 1189 | objects, since the point of the non-obvious designation is that the |
| | 1190 | object appears at first glance to be illogical for a given verb. |
| | 1191 | |
| | 1192 | </div> |
| | 1193 | |
| | 1194 | <!-------------------> |
| | 1195 | <div class=entry> |
| | 1196 | |
| | 1197 | The parser now incorporates Michel Nizette's vocabLikelihood |
| | 1198 | extension. This extension lets each object set an "intrinsic |
| | 1199 | likelihood" value that affects how the parser chooses among ambiguous |
| | 1200 | objects. When the parser can't tell the difference between two |
| | 1201 | objects using the normal 'verify' procedure, it compares the |
| | 1202 | vocabLikelihood properties of the two objects, and chooses the one |
| | 1203 | with the higher value if they differ. This makes it easier to |
| | 1204 | fine-tune the disambiguation process to reduce unnecessary prompting. |
| | 1205 | |
| | 1206 | </div> |
| | 1207 | |
| | 1208 | <!-------------------> |
| | 1209 | <div class=entry> |
| | 1210 | |
| | 1211 | SensoryEmanation.endEmanation() now resets displayCount to nil. |
| | 1212 | displayCount was documented as being automatically reset when a period |
| | 1213 | of continuous presence ended, but in the past no actual resetting was |
| | 1214 | done. We set the value to nil, rather than to 0 or 1, to make it more |
| | 1215 | obvious (when debugging, for example) that the object is not currently |
| | 1216 | in scope. |
| | 1217 | |
| | 1218 | </div> |
| | 1219 | |
| | 1220 | <!-------------------> |
| | 1221 | <div class=entry> |
| | 1222 | |
| | 1223 | The English library now defines suitable custom objInPrep, |
| | 1224 | actorInPrep, and actorOutOfPrep values for Surface, Underside, and |
| | 1225 | RearContainer. This ensures that the default messages produce |
| | 1226 | reasonable relational descriptions when referring to the contents of |
| | 1227 | these specialized container types. (In the past, only |
| | 1228 | Surface.objInPrep was suitably customized.) |
| | 1229 | |
| | 1230 | </div> |
| | 1231 | |
| | 1232 | <!-------------------> |
| | 1233 | <div class=entry> |
| | 1234 | |
| | 1235 | BasicOpenable.tryImplicitRemoveObstructor() now only attempts an |
| | 1236 | implied Open if the object is closed. When the object is already |
| | 1237 | open, the routine now does nothing. This change is necessary because |
| | 1238 | objects can conceivably create an obstruction even if they're already |
| | 1239 | open: once the object's open, if it's still creating an obstruction, |
| | 1240 | another implied Open would be pointless (and, in fact, could cause |
| | 1241 | an infinite loop). |
| | 1242 | |
| | 1243 | </div> |
| | 1244 | |
| | 1245 | <!-------------------> |
| | 1246 | <div class=entry> |
| | 1247 | |
| | 1248 | The new Thing method isOrIsIn(obj) returns true if 'self' is either |
| | 1249 | inside 'obj' or equal to 'obj'. This is useful for cases where you |
| | 1250 | want to check if a given object is anywhere within another object's |
| | 1251 | containment tree, <i>including</i> the other object itself. |
| | 1252 | |
| | 1253 | </div> |
| | 1254 | |
| | 1255 | <!-------------------> |
| | 1256 | <div class=entry> |
| | 1257 | |
| | 1258 | When a MultiLoc object is the point-of-view object in a sense |
| | 1259 | calculation, it now connects all of its multiple containers to the |
| | 1260 | scope in addDirectConnections(). In the past, a MultiLoc's containers |
| | 1261 | were only considered part of the scope when the point of view was |
| | 1262 | <i>inside</i> the MultiLoc, but it makes sense for the MultiLoc itself |
| | 1263 | to be the same way, since it inherently "sees" all of its containers. |
| | 1264 | |
| | 1265 | </div> |
| | 1266 | |
| | 1267 | <!-------------------> |
| | 1268 | <div class=entry> |
| | 1269 | |
| | 1270 | LocateInParent is now defined as a class. (It was always meant to be, |
| | 1271 | but the definition lacked an explicit 'class' keyword in past version.) |
| | 1272 | |
| | 1273 | </div> |
| | 1274 | |
| | 1275 | |
| | 1276 | <!------------------------------- 3.0.15.1 ---------------------------------> |
| | 1277 | <div class="sepbar"><a name='3015a'></a>3.0.15.1</div> |
| | 1278 | <p><b><i>Released 7/19/2007</i></b> |
| | 1279 | <p> |
| | 1280 | |
| | 1281 | <!-------------------> |
| | 1282 | <div class=firstentry> |
| | 1283 | |
| | 1284 | <b>Compatibility warning:</b> The message property cannotTalkToSelf |
| | 1285 | has been renamed to cannotTalkToSelfMsg, for consistency with other |
| | 1286 | message property names. (You should search your existing game code |
| | 1287 | and update any references to the old name to use the new name |
| | 1288 | instead.) |
| | 1289 | |
| | 1290 | </div> |
| | 1291 | |
| | 1292 | <!-------------------> |
| | 1293 | <div class=entry> |
| | 1294 | |
| | 1295 | <p>The new gameMain property beforeRunsBeforeCheck lets you control |
| | 1296 | the relative ordering of the "check" phase and "before" notifiers. |
| | 1297 | |
| | 1298 | <p>In the past, the library always ran the "before" notifiers - |
| | 1299 | beforeAction and roomBeforeAction - <i>before</i> running the check() |
| | 1300 | handlers for the objects involved in the action. To ensure |
| | 1301 | compatibility, the default setting for the new property is |
| | 1302 | beforeRunsBeforeCheck = true - this causes "before" to run before |
| | 1303 | check(), as it always has. |
| | 1304 | |
| | 1305 | <p>However, in many ways, it's more logical and practical to run the |
| | 1306 | check() phase first first, and <i>then</i> run the "before" notifiers. |
| | 1307 | This ordering allows the "before" handlers to assume that the action |
| | 1308 | is more or less committed to running to completion, since they know |
| | 1309 | that the check() phase has already tested the action and allowed |
| | 1310 | it to proceed. The most common use of "before" handlers is to carry |
| | 1311 | out side effects of an action, so by running all of the check() tests |
| | 1312 | first, the "before" handlers can more confidently invoke their side |
| | 1313 | effects, without worrying that the action will later fail due to a |
| | 1314 | check() condition. |
| | 1315 | |
| | 1316 | <p>Now, you can never truly call an action "committed" until it's been |
| | 1317 | fully carried out, since even a "before" handler can conceivably |
| | 1318 | cancel a command (with "exit", for instance). You could set up a |
| | 1319 | situation where an action is affected by two "before" handlers, and |
| | 1320 | the one that runs later cancels the command - thus invalidating any |
| | 1321 | assumption in the first one that the command is committed. However, |
| | 1322 | this is relatively unusual, and in any case it's under your control: |
| | 1323 | if you don't use "before" handlers to cancel commands, it won't occur. |
| | 1324 | |
| | 1325 | <p>If you want to use the new alternative ordering, where "check" runs |
| | 1326 | before the "before" notifications, simply set beforeRunsBeforeCheck to |
| | 1327 | nil in your gameMain object. Some authors have tested this ordering |
| | 1328 | with existing games and found it to work well with existing code, but |
| | 1329 | be aware that you could trigger subtle changes - you might have |
| | 1330 | unknowingly created dependencies on the relative ordering of check() |
| | 1331 | and "before" that will only show up under certain conditions. We |
| | 1332 | therefore recommend using the new alternative ordering only for new |
| | 1333 | code or for projects that are relatively early in their development |
| | 1334 | cycle, to ensure thorough testing of the new ordering. |
| | 1335 | |
| | 1336 | </div> |
| | 1337 | |
| | 1338 | <!-------------------> |
| | 1339 | <div class=entry> |
| | 1340 | |
| | 1341 | ThingState now allows tokens to be shared among multiple states |
| | 1342 | associated with the same object. In the past, state words had to be |
| | 1343 | unique among an object's states: it wasn't possible to have a set of |
| | 1344 | states such as "unpainted", "painted red", and "painted blue", because |
| | 1345 | it was invalid for "painted" to appear in two states. This sort of |
| | 1346 | sharing is now allowed. |
| | 1347 | |
| | 1348 | <p>The old rule was that a word could match an object only if the word |
| | 1349 | didn't appear in any of the object's <b>other</b> (i.e., non-current) |
| | 1350 | ThingState token lists. The new rule is that a word can match an |
| | 1351 | object if (a) the word appears in the object's <b>current</b> |
| | 1352 | ThingState token list, <b>or</b> (b) the word <b>doesn't</b> appear in |
| | 1353 | any of the object's <b>other</b> ThingState token lists. Condition |
| | 1354 | (a) is what's new; it allows words to be shared among states by |
| | 1355 | allowing a word to match the current state as long as it's in the |
| | 1356 | current state's list, regardless of whether it appears in other |
| | 1357 | states' lists. |
| | 1358 | |
| | 1359 | </div> |
| | 1360 | |
| | 1361 | <!-------------------> |
| | 1362 | <div class=entry> |
| | 1363 | |
| | 1364 | In the English library, when a command triggers a chain of several |
| | 1365 | implied actions, the announcement for the implied actions now adds |
| | 1366 | the word "then" in each conjunction: "(first standing up, <b>then</b> |
| | 1367 | taking the box, <b>then</b> opening it)". In the past, "then" |
| | 1368 | appeared only in the final conjunction; most people find it reads |
| | 1369 | more naturally to use "then" in each conjunction. |
| | 1370 | |
| | 1371 | </div> |
| | 1372 | |
| | 1373 | <!-------------------> |
| | 1374 | <div class=entry> |
| | 1375 | |
| | 1376 | The English library now uses the adjustDefaultObjectPrep() mechanism |
| | 1377 | to generate implied action announcements. This means that verbs like |
| | 1378 | SitOn and GetOutOf will use object-specific prepositions when they're |
| | 1379 | announced as implied actions: "(first sitting on the bench)" vs |
| | 1380 | "(first sitting in the car)". |
| | 1381 | |
| | 1382 | </div> |
| | 1383 | |
| | 1384 | <!-------------------> |
| | 1385 | <div class=entry> |
| | 1386 | |
| | 1387 | The actions GetOutOf and GetOffOf now adjust the prepositions in their |
| | 1388 | generated verb phrases according to the actorOutOfPrep definition for |
| | 1389 | the direct object. |
| | 1390 | |
| | 1391 | </div> |
| | 1392 | |
| | 1393 | <!-------------------> |
| | 1394 | <div class=entry> |
| | 1395 | |
| | 1396 | AccompanyingInTravelState.initiateTopic() now defers to the next state |
| | 1397 | object. Since the in-travel state is designed to be ephemeral, it's |
| | 1398 | unlikely that one of these would actually contain its own initiated |
| | 1399 | topics, so in almost all cases the desired topic would come from the |
| | 1400 | state that the actor will be in following the travel. |
| | 1401 | |
| | 1402 | </div> |
| | 1403 | |
| | 1404 | <!-------------------> |
| | 1405 | <div class=entry> |
| | 1406 | |
| | 1407 | The library now defines a simple template for ShuffledList. The new |
| | 1408 | template takes a single list parameter giving the value list. |
| | 1409 | |
| | 1410 | </div> |
| | 1411 | |
| | 1412 | <!-------------------> |
| | 1413 | <div class=entry> |
| | 1414 | |
| | 1415 | ListGroupCustom now defines groupDisplaysSublist = nil by default. |
| | 1416 | This type of group is intended mainly for cases where you want to |
| | 1417 | display a collective message to describe the group, rather than |
| | 1418 | listing its elements individually, so we usually don't want the |
| | 1419 | inclusion of a ListGroupCustom message to trigger the "long list" |
| | 1420 | format (i.e., with semicolons) in the overall list. This change |
| | 1421 | makes this behvior the default. |
| | 1422 | |
| | 1423 | </div> |
| | 1424 | |
| | 1425 | <!-------------------> |
| | 1426 | <div class=entry> |
| | 1427 | |
| | 1428 | Non-physical CollectiveGroup objects (i.e., those with 'nil' |
| | 1429 | locations) didn't work when the associated individuals were MultiLoc |
| | 1430 | or SenseConnector objects. This has been corrected. |
| | 1431 | |
| | 1432 | </div> |
| | 1433 | |
| | 1434 | <!-------------------> |
| | 1435 | <div class=entry> |
| | 1436 | |
| | 1437 | Actor.knowAbout() now considers an object to be known if it's |
| | 1438 | <i>currently</i> in sight. In the past, an object was known if it was |
| | 1439 | specifically marked as known, or it was marked as having been |
| | 1440 | previously seen. For the most part, an object that's currently |
| | 1441 | visible will also be marked as having been previously seen, since this |
| | 1442 | marking occurs whenever a Look command or travel to a new location |
| | 1443 | lists an object. However, if an object comes into scope (via |
| | 1444 | moveInto) while an actor is in a given location, the object won't be |
| | 1445 | marked as having been seen until the next Look command or subsequent |
| | 1446 | travel away from and then back to the location. |
| | 1447 | |
| | 1448 | <p>This change corrects a subtle problem that involved possessive |
| | 1449 | phrases in commands. In the past, an object that just came into scope |
| | 1450 | was excluded from matching a possessive noun phrase under certain |
| | 1451 | circumstances, such as in the response to a disambiguation question. |
| | 1452 | This should no longer occur. |
| | 1453 | |
| | 1454 | </div> |
| | 1455 | |
| | 1456 | <!-------------------> |
| | 1457 | <div class=entry> |
| | 1458 | |
| | 1459 | In the past, the library <i>seemed</i> to allow commands like PUSH TV |
| | 1460 | INTO BOX (i.e., commands to push a pushable object into a nested |
| | 1461 | room), but on closer inspection it didn't really carry them out: |
| | 1462 | instead, it carried out only the underlying basic travel command, |
| | 1463 | without actually moving the object supposedly being pushed around. |
| | 1464 | The library now rejects PUSH INTO <i>nested room</i> commands with a |
| | 1465 | new message, &cannotPushObjectNested ("You can't push the TV |
| | 1466 | there"). |
| | 1467 | |
| | 1468 | <p>The library rejects these commands by default because we think |
| | 1469 | it'll be relatively rare that games will need to allow them. Given |
| | 1470 | that, it didn't seem worth complicating things by adding a bunch of |
| | 1471 | new methods to provide generalized support, and we also didn't want to |
| | 1472 | introduce that much new code at the current point in the release |
| | 1473 | cycle. |
| | 1474 | |
| | 1475 | <p>However, the library does now provide a new hook that will make it |
| | 1476 | easier for games to implement PUSH INTO <i>nested</i> commands if they |
| | 1477 | need to. The new hook will also make it possible to implement riding |
| | 1478 | vehicles into nested rooms, which wasn't previously possible. The new |
| | 1479 | hook is a new Traveler method, travelerTravelWithin(). |
| | 1480 | |
| | 1481 | <p>This new method is called on the Traveler object when a nested-room |
| | 1482 | travel command (GET IN, STAND ON, SIT ON, LIE ON, PUSH X INTO, etc) is |
| | 1483 | performed. In simple cases, the Traveler is simply the Actor |
| | 1484 | performing command. However, if the actor is riding in a Vehicle, the |
| | 1485 | Traveler is the Vehicle object; and if the command is a PUSH travel |
| | 1486 | command, such as PUSH TV INTO BOX, the Traveler is a special ephemeral |
| | 1487 | object, of class PushTraveler, created just for the command. |
| | 1488 | |
| | 1489 | <p>The library provides default implementations of the new hook method |
| | 1490 | for Actor, Vehicles, and PushTraveler. For Actor, the method simply |
| | 1491 | does the same thing that travelWithin() used to do, so existing code |
| | 1492 | will work as it did before. For Vehicle, the method calls the same |
| | 1493 | method on the Actor, so again it will work as it used to. For |
| | 1494 | PushTraveler, the method simply terminates the command with the new |
| | 1495 | message &cannotPushObjectNested. |
| | 1496 | |
| | 1497 | <p>If you want to allow pushing objects into nested rooms, you'll need |
| | 1498 | to modify PushTraveler.travelerTravelWithin() to do basically the same |
| | 1499 | thing that PushTraveler.travelerTravelTo() does. You'll probably want |
| | 1500 | to set up a new set of notification methods parallel to |
| | 1501 | beforeMovePushable() and movePushable() - you could just use those |
| | 1502 | same routines, but you'll probably want to set up new custom |
| | 1503 | nested-room versions instead, since the conditions and messages will |
| | 1504 | probably need to be different for nested rooms from those used for |
| | 1505 | room-to-room travel. |
| | 1506 | |
| | 1507 | <p>Note that you could also take advantage of the new method to allow |
| | 1508 | an actor to ride a vehicle into a nested room. The default handling |
| | 1509 | in Vehicle defers to the underlying Actor, and the actor performs the |
| | 1510 | travel as though the Vehicle were any other nested room - which means |
| | 1511 | that the actor gets out of the vehicle, then gets into the new nested |
| | 1512 | room. If you instead wanted this type of command to mean "ride |
| | 1513 | vehicle into nested room," you can override travelerTravelWithin() on |
| | 1514 | the vehicle, so that the method moves the Vehicle itself into the new |
| | 1515 | nested room. (You'll also have to set up preconditions that move the |
| | 1516 | vehicle to the proper staging locations using the same rules that are |
| | 1517 | used for actors, which could take a little work - that's the main |
| | 1518 | reason the library doesn't support it out of the box yet.) |
| | 1519 | |
| | 1520 | </div> |
| | 1521 | |
| | 1522 | <!-------------------> |
| | 1523 | <div class=entry> |
| | 1524 | |
| | 1525 | In the past, if an NPC was using AccompanyingState to follow around |
| | 1526 | the player character, and the pair went through an AutoClosingDoor, |
| | 1527 | the door was reported as having closed twice during the turn - |
| | 1528 | once for each actor going through. AutoClosingDoor now skips the |
| | 1529 | auto-closing step if the actor going through is in an accompanying |
| | 1530 | state. |
| | 1531 | |
| | 1532 | </div> |
| | 1533 | |
| | 1534 | <!-------------------> |
| | 1535 | <div class=entry> |
| | 1536 | |
| | 1537 | The parser's "OOPS" mechanism had a problematic interaction with |
| | 1538 | literal phrases that showed up under certain conditions. In |
| | 1539 | particular, if the player entered a command that caused some kind of |
| | 1540 | follow-up question, such as a disambiguation query ("which book do you |
| | 1541 | mean...") or missing-object prompt ("what do you want to unlock it |
| | 1542 | with?"), <b>and</b> the player chose to ignore the follow-up question |
| | 1543 | and instead just enter a new command, <b>and</b> the new command |
| | 1544 | contained a literal phrase ("type asdf on keypad", say), the OOPS |
| | 1545 | mechanism was overly aggressive in deciding the command contained a |
| | 1546 | typo. |
| | 1547 | |
| | 1548 | <p>The root of the problem was that follow-up questions are parsed |
| | 1549 | according to their own special grammars, which are much more limited |
| | 1550 | than the full grammar used at the main command prompt. Normally, when |
| | 1551 | the player responds with something that doesn't match one of these |
| | 1552 | special grammars, the parser assumes the player intended to bypass the |
| | 1553 | follow-up question and just enter a new command. However, if parser |
| | 1554 | manages to find a non-dictionary word in the player's input, it |
| | 1555 | invokes the OOPS mechanism to see if the player actually intended to |
| | 1556 | answer the follow-up question but made a typographical error entering |
| | 1557 | the response. The problem is that if the player entered a |
| | 1558 | literal-phrase verb, the presence of a non-dictionary word |
| | 1559 | <i>doesn't</i> necessarily imply a typographical error. For normal |
| | 1560 | commands (as opposed to follow-up questions), this isn't an issue, |
| | 1561 | because the parser finds the literal when matching against the full |
| | 1562 | grammar. For follow-up questions, though, the parser never noticed |
| | 1563 | the literal-phrase interpretation of the input, since it wasn't |
| | 1564 | matching against the full grammar, so it prematurely decided that the |
| | 1565 | input as mis-typed. |
| | 1566 | |
| | 1567 | <p>The OOPS mechanism now makes an extra check when presented with a |
| | 1568 | non-dictionary word in the response to a follow-up question. Before |
| | 1569 | deciding that the input really does contain a typo, the OOPS mechanism |
| | 1570 | first checks the input to see if it matches anything in the full |
| | 1571 | command-line grammar; if the parser finds a match, it assumes that the |
| | 1572 | entry was meant as a brand new command, and so it bypasses the |
| | 1573 | follow-up question and re-parses the input as a new command. |
| | 1574 | |
| | 1575 | </div> |
| | 1576 | |
| | 1577 | <!-------------------> |
| | 1578 | <div class=entry> |
| | 1579 | |
| | 1580 | In the past, calling getOrigTokenList() on an EventAction object |
| | 1581 | caused a run-time error. This was because EventActions don't have the |
| | 1582 | token list data that the parser normally attaches when creating an |
| | 1583 | Action to represent a parsed command line, which in turn is because |
| | 1584 | these actions aren't created from command parsing but are instead |
| | 1585 | "synthetic" actions, created internally by the library for bookkeeping |
| | 1586 | purposes. (This same problem might have affected other synthetic |
| | 1587 | actions as well, but it's only known to have shown up with |
| | 1588 | EventActions.) |
| | 1589 | |
| | 1590 | <p>This has been corrected. Action.getOrigTokenList() now checks to |
| | 1591 | make sure there's a parser token list attached to the action, and if |
| | 1592 | not, the method return the parent action's token list; and if there's |
| | 1593 | no parent action, the method simply returns an empty list. |
| | 1594 | |
| | 1595 | </div> |
| | 1596 | |
| | 1597 | <!-------------------> |
| | 1598 | <div class=entry> |
| | 1599 | |
| | 1600 | HermitActorState now sets its property limitSuggestsion to true by |
| | 1601 | default, to prevent the TOPICS command from displaying any topic |
| | 1602 | suggestions from the actor or conversation node. This is desirable |
| | 1603 | because the hermit state effectively blocks any topics defined outside |
| | 1604 | the state: the whole point of the state is that it makes the actor |
| | 1605 | essentially unresponsive to conversational overtures. So there's |
| | 1606 | generally no point in offering topic suggestions while the actor is in |
| | 1607 | the state. |
| | 1608 | |
| | 1609 | <p>In some cases, you might want to override this for a particular |
| | 1610 | hermit state object. In particular, if it's not outwardly obvious |
| | 1611 | that the actor will be unresponsive, you might still want to allow |
| | 1612 | suggestions, since the player has no way of knowing that the actor |
| | 1613 | won't respond to questions until she attempts asking them. Similarly, |
| | 1614 | if the hermit state is expected to persist for a short time only, you |
| | 1615 | might want to continue to allow suggestions so that the player knows |
| | 1616 | there are useful topics to explore when the actor becomes responsive |
| | 1617 | again. |
| | 1618 | |
| | 1619 | </div> |
| | 1620 | |
| | 1621 | <!-------------------> |
| | 1622 | <div class=entry> |
| | 1623 | |
| | 1624 | ByeTopic now overrides impliesGreeting to suppress any implied HELLO |
| | 1625 | greeting. This means that if the player explicitly says GOODBYE to an |
| | 1626 | NPC, and no conversation is in progress, the goodbye response will be |
| | 1627 | displayed by itself, without an implied greeting exchange. In the |
| | 1628 | past, ByeTopic inherited the default 'true' value for impliesGreeting, |
| | 1629 | so saying GOODBYE to an NPC outside of a conversation caused an |
| | 1630 | implied greeting, followed immediately by the explicit goodbye |
| | 1631 | response. In most cases, this ended up looking pretty strange - not |
| | 1632 | only was the self-canceling HELLO-GOODBYE exchange odd on its face, |
| | 1633 | but in most cases the implied greeting also looked redundant from the |
| | 1634 | player's perspective, because a player tended to say GOODBYE |
| | 1635 | explicitly only when she was under the impression that some kind of |
| | 1636 | conversational interaction was already under way. |
| | 1637 | |
| | 1638 | </div> |
| | 1639 | |
| | 1640 | <!-------------------> |
| | 1641 | <div class=entry> |
| | 1642 | |
| | 1643 | In the past, conversation-flow problems sometimes occurred if a topic |
| | 1644 | changed its "isConversational" status as a side effect of showing the |
| | 1645 | response for the topic. This was because |
| | 1646 | ActorTopicDatabase.showTopicResponse() waited until after invoking the |
| | 1647 | response to determine whether the response should affect the |
| | 1648 | conversation flow, so the status change side effect caused |
| | 1649 | showTopicResponse() to use the new setting - meant for the next |
| | 1650 | response - rather than the setting for the response it actually |
| | 1651 | showed. This has been corrected; showTopicResponse() now makes its |
| | 1652 | determination based on the isConversational status as it stands just |
| | 1653 | before invoking the response. |
| | 1654 | |
| | 1655 | </div> |
| | 1656 | |
| | 1657 | <!-------------------> |
| | 1658 | <div class=entry> |
| | 1659 | |
| | 1660 | The finishGameMsg() function now explicitly runs the score notifier |
| | 1661 | daemon before it displays the end-of-game message. This ensures that |
| | 1662 | the usual score-change message is displayed if any points were awarded |
| | 1663 | in the course of the action that triggered the end of the game. |
| | 1664 | Without the explicit invocation, the notifier daemon wouldn't |
| | 1665 | typically get a chance to show a notification for the final point |
| | 1666 | award: the notification is normally shown just before the next command |
| | 1667 | prompt after points are awarded, and at the end of the game there's |
| | 1668 | not usually another command prompt forthcoming. |
| | 1669 | |
| | 1670 | </div> |
| | 1671 | |
| | 1672 | <!-------------------> |
| | 1673 | <div class=entry> |
| | 1674 | |
| | 1675 | In the English library, inlineListingContentsLister didn't always |
| | 1676 | generate correct verb agreement for its prefix message for a "wide" |
| | 1677 | listing ("You are carrying tongs (which <b>contains</b> ...)"). |
| | 1678 | This has been corrected. |
| | 1679 | |
| | 1680 | </div> |
| | 1681 | |
| | 1682 | <!-------------------> |
| | 1683 | <div class=entry> |
| | 1684 | |
| | 1685 | In the past, searching a RoomPart nominally containing a RoomPartItem |
| | 1686 | sometimes caused a "nil object reference" run-time error. This was |
| | 1687 | due to a missing point-of-view object setting; the code where the |
| | 1688 | error occurred now applies a default POV of the command actor when |
| | 1689 | no explicit POV is set. |
| | 1690 | |
| | 1691 | </div> |
| | 1692 | |
| | 1693 | <!-------------------> |
| | 1694 | <div class=entry> |
| | 1695 | |
| | 1696 | Container and Openable objects now apply a touchObj precondition to |
| | 1697 | the Search action. This requires that the actor be able to reach the |
| | 1698 | object in order to search it. This change is intended to better |
| | 1699 | enforce the idea that searching a container involves some actual |
| | 1700 | physical manipulation, such as shifting the contents around to look |
| | 1701 | behind or under things, momentarily removing contents to see what's |
| | 1702 | underneath, and so on. The actor at least has to be able to reach the |
| | 1703 | object to perform this kind of manipulation. |
| | 1704 | |
| | 1705 | </div> |
| | 1706 | |
| | 1707 | <!-------------------> |
| | 1708 | <div class=entry> |
| | 1709 | |
| | 1710 | In the past, AGAIN didn't work properly when used to repeat a FOLLOW |
| | 1711 | command involving an NPC using the "guided tour" mechanism (the |
| | 1712 | TourGuide and GuidedTourState classes). This was due to a subtle |
| | 1713 | turn-timer problem with AGAIN that affected commands like FOLLOW that |
| | 1714 | use nested or replacement actions in the course of their execution. |
| | 1715 | This problem was observed in the FOLLOW/AGAIN situation, but could |
| | 1716 | also have affected other commands. The root problem has been |
| | 1717 | corrected. |
| | 1718 | |
| | 1719 | </div> |
| | 1720 | |
| | 1721 | |
| | 1722 | |
| | 1723 | <!------------------------------- 3.0.15 ---------------------------------> |
| | 1724 | <div class="sepbar"><a name='3015'></a>3.0.15</div> |
| | 1725 | <p><b><i>Released 3/8/2007</i></b> |
| | 1726 | <p> |
| | 1727 | |
| | 1728 | <!-------------------> |
| | 1729 | <div class=firstentry> |
| | 1730 | |
| | 1731 | The Follow action has always adjusted the scope list to include any |
| | 1732 | NPCs that the target actor remembers having seen leave, whether or not |
| | 1733 | they're still within sight. This allows you to FOLLOW a character |
| | 1734 | who's no longer present - the whole point of FOLLOW would be defeated |
| | 1735 | if this weren't possible, after all. However, in the past, this scope |
| | 1736 | list expansion created duplicate entries in the scope list if an actor |
| | 1737 | with a "follow memory" was also still physically present - the actor |
| | 1738 | was added to the scope list once for ordinary visibility, then again |
| | 1739 | for the "follow memory." This duplication caused problems in some |
| | 1740 | situations, since other parts of the library expect the scope list to |
| | 1741 | contain only unique entries. The Follow action now ensures that the |
| | 1742 | list remains unique after its additions. |
| | 1743 | |
| | 1744 | </div> |
| | 1745 | |
| | 1746 | <!------------------------------- 3.0.14 ---------------------------------> |
| | 1747 | <div class="sepbar"><a name='3014'></a>3.0.14</div> |
| | 1748 | <p><b><i>Released 2/9/2007</i></b> |
| | 1749 | <p> |
| | 1750 | There are no library changes in TADS 3.0.14. |
| | 1751 | |
| | 1752 | |
| | 1753 | <!------------------------------- 3.0.13 ---------------------------------> |
| | 1754 | <div class="sepbar"><a name='3013'></a>3.0.13</div> |
| | 1755 | <p><b><i>Released 1/19/2007</i></b> |
| | 1756 | <p> |
| | 1757 | |
| | 1758 | <!-------------------> |
| | 1759 | <div class=firstentry> |
| | 1760 | |
| | 1761 | The adv3 English library has a new option setting for the parser's |
| | 1762 | truncation length. The truncation length has always been customizable |
| | 1763 | in the low-level system objects that the parser uses to look up and |
| | 1764 | match vocabulary words, but the library didn't formerly provide a good |
| | 1765 | way for games to override <i>its</i> truncation length setting. In |
| | 1766 | effect, the truncation length was hard-coded into the English library, |
| | 1767 | and the only way for authors to change it was to edit en_us.t; most |
| | 1768 | authors would rather not do that because of the hassle of merging |
| | 1769 | their own changes into future library updates. |
| | 1770 | |
| | 1771 | <p>The new setting is in gameMain.parserTruncLength. The default |
| | 1772 | setting is 6 characters - this is the same as the English parser's old |
| | 1773 | hard-wired setting, so existing code will behave the same as it did in |
| | 1774 | the past. |
| | 1775 | |
| | 1776 | <p>As part of this change, the new method |
| | 1777 | languageGlobals.setStringComparator() lets you change the active |
| | 1778 | string comparator dynamically. You can use this method if you want to |
| | 1779 | change the truncation length, or other comprator settings, on the fly |
| | 1780 | during the game. |
| | 1781 | |
| | 1782 | </div> |
| | 1783 | |
| | 1784 | <!-------------------> |
| | 1785 | <div class=entry> |
| | 1786 | |
| | 1787 | The English library now allows a TAction VerbRule to specify a custom |
| | 1788 | preposition for a default object announcement, overriding the |
| | 1789 | preposition coded in the verbPhrase. This is useful for a few verbs |
| | 1790 | where the preposition tends to vary according to the direct object. |
| | 1791 | For example, SIT might use ON in some cases but IN for other cases: |
| | 1792 | "on the stool" vs "in the car." |
| | 1793 | |
| | 1794 | <p>To accomplish this, TAction.announceDefaultObject() first parses |
| | 1795 | the verbPhrase to get the standard preposition, then calls a new |
| | 1796 | method on self, adjustDefaultObjectPrep(prep, obj). 'prep' is the |
| | 1797 | default preposition from the verbPhrase, and 'obj' is the direct |
| | 1798 | object of the command. The routine returns the new preposition |
| | 1799 | string. The default implementation simply returns 'prep', but |
| | 1800 | the StandOn, SitOn, and LieOn actions override this to return the |
| | 1801 | direct object's actorInPrep. |
| | 1802 | |
| | 1803 | </div> |
| | 1804 | |
| | 1805 | <!-------------------> |
| | 1806 | <div class=entry> |
| | 1807 | |
| | 1808 | InitiateTopics can now be located within ActorState objects. In the |
| | 1809 | past, InitiateTopics were only found when they were directly within an |
| | 1810 | Actor or a TopicGroup within an actor. The library now looks for |
| | 1811 | InitiateTopics in the current actor state object as well, which is |
| | 1812 | more consistent with other topic types. |
| | 1813 | |
| | 1814 | </div> |
| | 1815 | |
| | 1816 | <!-------------------> |
| | 1817 | <div class=entry> |
| | 1818 | |
| | 1819 | inputManager.pauseForMore() now re-activates the transcript if it was |
| | 1820 | active before the pause. In the past, this function simply flushed |
| | 1821 | output and left the transcript deactivated. This was problematic for |
| | 1822 | certain library subsystems that depend upon the transcript being |
| | 1823 | active throughout a command. Now, the function flushes the |
| | 1824 | transcript's pending output up to the pause, then reactivates the |
| | 1825 | transcript after the pause, so that transcript capture proceeds as |
| | 1826 | normal throughout the rest of the command. |
| | 1827 | |
| | 1828 | </div> |
| | 1829 | |
| | 1830 | <!-------------------> |
| | 1831 | <div class=entry> |
| | 1832 | |
| | 1833 | In the past, the library generally assumed that NestedRoom objects |
| | 1834 | would only be located inside either Rooms or other NestedRooms, but |
| | 1835 | never inside ordinary Things. However, in practice it's often useful |
| | 1836 | to be able to put a nested room inside something that's not itself |
| | 1837 | a nested room. |
| | 1838 | |
| | 1839 | <p>A number of small library changes should now make NestedRooms |
| | 1840 | work properly when located inside ordinary Thing objects. The |
| | 1841 | changes are mostly internal and should have no impact on existing |
| | 1842 | code, but for reference, here's what's changed: |
| | 1843 | |
| | 1844 | <ul> |
| | 1845 | |
| | 1846 | <li>The methods getRoomPartLocation(), getLocTraveler(), |
| | 1847 | atmosphereList(), roomDaemon(), getDropDestination(), and |
| | 1848 | effectiveFollowLocation() have been moved to Thing, with essentially |
| | 1849 | no changes. These are the methods the library calls on containers of |
| | 1850 | nested rooms, so moving them to Thing allows any game object to |
| | 1851 | contain a nested room. |
| | 1852 | |
| | 1853 | <li>The definitions of most of the above methods have been removed |
| | 1854 | from BasicLocation, since BasicLocation now simply inherits the Thing |
| | 1855 | definitions. The definitions of roomDaemon() and atmosphereList() |
| | 1856 | have been moved to Room instead, since those definitions were intended |
| | 1857 | for top-level rooms. |
| | 1858 | |
| | 1859 | <li>Room now defines checkActorOutOfNested() to find and defer to |
| | 1860 | the child object containing the actor. This ensures that the check |
| | 1861 | is forwarded to the nested room containing the actor. |
| | 1862 | |
| | 1863 | </ul> |
| | 1864 | |
| | 1865 | <p>In addition to the changes above, NestedRoom no longer assumes that |
| | 1866 | its immediate location is the destination when an actor within the |
| | 1867 | nested room leaves the nested room. Instead, NestedRoom now |
| | 1868 | consistently uses the value given by exitDestination. Further, |
| | 1869 | NestedRoom.exitDestination itself no longer uses the immediate |
| | 1870 | container as its default setting, but instead uses the default staging |
| | 1871 | location as given by the defaultStagingLocation method. |
| | 1872 | |
| | 1873 | </div> |
| | 1874 | |
| | 1875 | <!-------------------> |
| | 1876 | <div class=entry> |
| | 1877 | |
| | 1878 | A change in 3.0.10 introduced a parsing problem with distinguishing |
| | 1879 | nouns from plurals when the words were right at the parser's |
| | 1880 | truncation length. To be more precise, if you defined a noun that was |
| | 1881 | exactly the truncation length, <i>and</i> you also defined a plural |
| | 1882 | for that noun as the noun plus "s" (or, actually, as the noun plus any |
| | 1883 | other letters), then the parser would incorrectly interpret the noun |
| | 1884 | word in player input as though it were plural. |
| | 1885 | |
| | 1886 | <p>For example, the default truncation length is 6 characters, so this |
| | 1887 | problem occurred with "button" and "buttons" defined as a noun and |
| | 1888 | plural, respectively. In this case, if you had two or more objects in |
| | 1889 | scope with vocabulary like 'red button*buttons', and the player typed |
| | 1890 | something like "x button", the parser incorrectly treated the "button" |
| | 1891 | in the player's input as though it were plural, so it applied the |
| | 1892 | Examine command iteratively to all of the buttons in scope, rather |
| | 1893 | than asking the player which singular button they intended to examine. |
| | 1894 | |
| | 1895 | <p>This problem has now been corrected. |
| | 1896 | |
| | 1897 | </div> |
| | 1898 | |
| | 1899 | <!-------------------> |
| | 1900 | <div class=entry> |
| | 1901 | |
| | 1902 | The message definition for cannotSetToMsg was missing from the English |
| | 1903 | message list (in en_us/msg_neu.t). The message is now there. |
| | 1904 | |
| | 1905 | </div> |
| | 1906 | |
| | 1907 | <!-------------------> |
| | 1908 | <div class=entry> |
| | 1909 | |
| | 1910 | A command of the form PUSH <i>pushable</i> INTO <i>object</i>, where |
| | 1911 | the second object was some random, non-enterable thing, yielded an |
| | 1912 | unformatted message ("{that/he dobj} {is} not something you can |
| | 1913 | enter"). The underlying problem was that the action remapping invoked |
| | 1914 | by PushTravelViaIobjAction didn't properly set up the object |
| | 1915 | parameters for the remapped verb, leaving the message system unable to |
| | 1916 | find the direct object. This has been corrected. |
| | 1917 | |
| | 1918 | </div> |
| | 1919 | |
| | 1920 | <!-------------------> |
| | 1921 | <div class=entry> |
| | 1922 | |
| | 1923 | The Attachable class had a problem that caused a run-time error when |
| | 1924 | the player entered a command of the form DETACH <i>object</i>, where |
| | 1925 | <i>object</i> was an Attachable and the command had no indirect |
| | 1926 | object. The problem came from a name conflict between an Attachable |
| | 1927 | method called cannotDetachMsg(obj), which took one parameter, and a |
| | 1928 | library messages property of the same name, which takes no parameters. |
| | 1929 | When the message resolution system tried to retrieve the library |
| | 1930 | message from the direct object, it invoked the zero-parameter version |
| | 1931 | of the property, which caused the run-time error due to the parameter |
| | 1932 | mismatch with the one-parameter version implemented in Attachable. |
| | 1933 | |
| | 1934 | <p>To fix this problem, the method in Attachable has been renamed to |
| | 1935 | cannotDetachMsgFor(obj). The library message has the same name as |
| | 1936 | before. |
| | 1937 | |
| | 1938 | <p>Any existing code that overrode the Attachable method will have to |
| | 1939 | adjust for the name change. That said, it seems almost impossible for |
| | 1940 | this change to affect existing code, since the very bug that we're |
| | 1941 | talking about here would have prevented the override from working |
| | 1942 | properly in the first place. |
| | 1943 | |
| | 1944 | </div> |
| | 1945 | |
| | 1946 | <!-------------------> |
| | 1947 | <div class=entry> |
| | 1948 | |
| | 1949 | A library bug caused a run-time error ("stack overflow") on commands |
| | 1950 | like REMOVE ME or REMOVE <i>nested room containing me</i>. This has |
| | 1951 | been corrected. |
| | 1952 | |
| | 1953 | <p>(The specific problem is as follows. The library assumes that a |
| | 1954 | REMOVE X command will result in the actor taking X, and so as a sanity |
| | 1955 | check calculates how much weight the actor would be holding if that |
| | 1956 | were allowed. When X is the actor or contains the actor, the |
| | 1957 | hypothetical weight check created a circular containment situation; |
| | 1958 | the stack overflow came from the library's attempt to recursively |
| | 1959 | visit all of the hypothetical contents of the actor, which is of |
| | 1960 | course an infinite loop in a circular containment situation. To avoid |
| | 1961 | this problem, the library now ignores hypotheticals that would create |
| | 1962 | circular containment. It's safe to ignore these hypothetical tests |
| | 1963 | because commands that perform them should always be disallowed anyway, |
| | 1964 | since actual circular containment is never allowed.) |
| | 1965 | |
| | 1966 | </div> |
| | 1967 | |
| | 1968 | <!-------------------> |
| | 1969 | <div class=entry> |
| | 1970 | |
| | 1971 | A library bug caused a run-time error ("nil object reference") on |
| | 1972 | entering a command of the form <i>object</i>, <i>unknown word</i>, |
| | 1973 | where <i>object</i> was any in-scope non-Actor object. This has |
| | 1974 | been corrected. |
| | 1975 | |
| | 1976 | <p>(The problem came about because the parser attempted to treat such |
| | 1977 | a command as though it were directed to an NPC. This is some special |
| | 1978 | handling that applies when the command has a syntax error; the point |
| | 1979 | is to let the author customize the parsing error messages for orders |
| | 1980 | given to particular actors. However, when <i>object</i> isn't an |
| | 1981 | actor, this is problematic, because the library assumes that it can |
| | 1982 | call certain Actor methods on the object in question. The fix is that |
| | 1983 | the library will only apply this handling in cases where the object is |
| | 1984 | actually an Actor; in other cases, it won't assume that the command |
| | 1985 | was intended as an order to an NPC, so it will simply use the default |
| | 1986 | parsing error messages.) |
| | 1987 | |
| | 1988 | </div> |
| | 1989 | |
| | 1990 | |
| | 1991 | <!------------------------------- 3.0.12 ---------------------------------> |
| | 1992 | <div class="sepbar"><a name='3012'></a>3.0.12</div> |
| | 1993 | <p><b><i>TADS 3.0 General Release version - Released 9/15/2006</i></b> |
| | 1994 | <p> |
| | 1995 | |
| | 1996 | <!-------------------> |
| | 1997 | <div class=firstentry> |
| | 1998 | |
| | 1999 | The library didn't properly handle situations where an NPC order |
| | 2000 | involved multiple objects and a failed implied sub-action. If an |
| | 2001 | implied action failed for one of the objects involved, the implied |
| | 2002 | action was assumed to have failed for all <i>subsequent</i> |
| | 2003 | objects in the multiple object list as well, even if the subsequent |
| | 2004 | implied actions actually succeeded. This resulted in self-contradictory |
| | 2005 | transcripts, where an implied action was reported as successful, but |
| | 2006 | then was followed by a message that the implied action had failed: |
| | 2007 | |
| | 2008 | <p><pre> |
| | 2009 | Bob takes the coin. |
| | 2010 | Bob must be holding the coin first. |
| | 2011 | </pre> |
| | 2012 | |
| | 2013 | <p>The problem was that the implied action mechanism was incorrectly |
| | 2014 | considering the failure status for the entire top-level command when |
| | 2015 | determining if the subsequent implied actions failed. Instead, it |
| | 2016 | should have been checking the status of the implied actions |
| | 2017 | themselves. It now does this by looking for a failure report within |
| | 2018 | the implied action's reports, rather than looking for a failure |
| | 2019 | anywhere within the entire transcript. |
| | 2020 | |
| | 2021 | </div> |
| | 2022 | |
| | 2023 | <!-------------------> |
| | 2024 | <div class=entry> |
| | 2025 | |
| | 2026 | SpaceOverlay.getWeight() now omits the object's "contents" from the |
| | 2027 | weight calculation if the contents are to be abandoned when the object |
| | 2028 | is moved. If the contents are to be abandoned, it means that they're |
| | 2029 | not actually attached to or contained within the space overlay, but |
| | 2030 | are simply colocated with it; they thus have no contribution to the |
| | 2031 | overlay's total weight. If the contents are <i>not</i> to be |
| | 2032 | abandoned on moving the overlay object, they're effectively attached |
| | 2033 | to it, so they do contribute to its weight as normal. |
| | 2034 | |
| | 2035 | </div> |
| | 2036 | |
| | 2037 | <!-------------------> |
| | 2038 | <div class=entry> |
| | 2039 | |
| | 2040 | CaptureFilter is now a subclass of OutputFilter (it was formerly just |
| | 2041 | an 'object'); and SwitchableCaptureFilter is a subclass of |
| | 2042 | CaptureFilter (it also was just an 'object'). This should make no |
| | 2043 | difference functionally, as an output filter is only required to |
| | 2044 | implement the filterText() method, but is desirable anyway in that it |
| | 2045 | makes an ofKind(OutputFilter) test recognize these object types as |
| | 2046 | output filter subclasses. |
| | 2047 | |
| | 2048 | </div> |
| | 2049 | |
| | 2050 | |
| | 2051 | <!------------------------------- 3.0.11 ---------------------------------> |
| | 2052 | <div class="sepbar"><a name='3011'></a>3.0.11</div> |
| | 2053 | <p><b><i>Released 9/8/2006</i></b> |
| | 2054 | <p> |
| | 2055 | |
| | 2056 | <div class=firstentry> |
| | 2057 | |
| | 2058 | <i>Very</i> slight compatibility risk: NameAsOther (and thus |
| | 2059 | NameAsParent) no longer maps the "in" names to its target object. The |
| | 2060 | "in" names are the names generated when an object is described as |
| | 2061 | contained within the NameAsOther. In the past, these were mapped to |
| | 2062 | the target object along with all of the ordinary names for the object. |
| | 2063 | However, this was the wrong behavior for ComplexComponent, which |
| | 2064 | inherits from NameAsOther, because the containment relationship |
| | 2065 | between a ComplexContainer and its contents is defined by the |
| | 2066 | container subclass mixed with ComplexComponent in the object's |
| | 2067 | superclass list, <i>not</i> by the target object, which in this case |
| | 2068 | is the ComplexContainer of which the ComplexComponent is a part. |
| | 2069 | |
| | 2070 | <p>Although it's conceivable that some other applications of |
| | 2071 | NameAsOther would actually want the old behavior, it seems highly |
| | 2072 | unlikely, so we don't expect any practical compatibility list. |
| | 2073 | |
| | 2074 | <p>However, we have provided a new mix-in class, ChildNameAsOther, |
| | 2075 | that adds mappings for all of the "in" names to the target object. |
| | 2076 | So, if you have a NameAsOther that depends upon the old "in" name |
| | 2077 | mapping, just add ChildNameAsOther to the object's superclass list |
| | 2078 | (right after NameAsOther or NameAsParent), and you'll get the same |
| | 2079 | behavior as before. |
| | 2080 | |
| | 2081 | </div> |
| | 2082 | |
| | 2083 | <!-------------------> |
| | 2084 | <div class=entry> |
| | 2085 | |
| | 2086 | In 3.0.10, the ImpByeTopic was differentiated into a couple of |
| | 2087 | subclasses to allow handling implicit goodbyes differently when |
| | 2088 | desired (see <a href='#ImpByeTopicSubclasses'>below</a>). However, |
| | 2089 | this change didn't handle one type of goodbye correctly, namely the |
| | 2090 | NPC-initiated goodbye, via npc.endConversation(). The change |
| | 2091 | incorrectly made it so that those goodbyes were treated the same as |
| | 2092 | explicit <i>player</i>-initiated goodbyes. |
| | 2093 | |
| | 2094 | <p>Prior to the 3.0.10 change, NPC-initiated goodbyes were subsumed |
| | 2095 | into the undifferentiated "implicit goodbye" category, and they |
| | 2096 | should clearly remain in that category; they simply need to be |
| | 2097 | differentiated like the other implicit goodbyes were in the 3.0.10 |
| | 2098 | change. |
| | 2099 | |
| | 2100 | <p>To this end, the new topic class ActorByeTopic has been added; this |
| | 2101 | is analogous to BoredByeTopic and LeaveByeTopic, and is used when the |
| | 2102 | NPC terminated the conversation via npc.endConversation(). In the |
| | 2103 | absence of an active ActorByeTopic, the active ImpByeTopic will be |
| | 2104 | used instead. This restores compatibility with pre-3.0.10 code (where |
| | 2105 | there was no differentiation among "implied goodbye" types, and |
| | 2106 | npc.endConversation() events were handled as implied goodbyes), while |
| | 2107 | providing a specific topic type to handle this one type of goodbyes. |
| | 2108 | |
| | 2109 | </div> |
| | 2110 | |
| | 2111 | <!-------------------> |
| | 2112 | <div class=entry> |
| | 2113 | |
| | 2114 | The English library's "instructions" module (instruct.t) now uses HTML |
| | 2115 | markups to display typographical quotes and apostrophes ("curly |
| | 2116 | quotes") throughout the text of the standard instructions. Thanks to |
| | 2117 | Greg Boettcher for making this improvement. |
| | 2118 | |
| | 2119 | </div> |
| | 2120 | |
| | 2121 | <!-------------------> |
| | 2122 | <div class=entry> |
| | 2123 | |
| | 2124 | The detailed-naming scheme for object announcements (see <a |
| | 2125 | href='#getInScopeDistinguisher'>below</a>) introduced in 3.0.10 has |
| | 2126 | been made optional, and disabled by default. Testing reveals that the |
| | 2127 | mechanism as currently designed is too twitchy for some people's |
| | 2128 | taste, so we've disabled it by default for the time being; however, |
| | 2129 | the code is all intact, for those who want to use it as-is or tweak it |
| | 2130 | for their needs. To enable the detailed announcement naming, set |
| | 2131 | gameMain.useDistinguishersInAnnouncements to true. |
| | 2132 | |
| | 2133 | </div> |
| | 2134 | |
| | 2135 | <!-------------------> |
| | 2136 | <div class=entry> |
| | 2137 | |
| | 2138 | The BannerWindow system had a flaw in the way it re-initialized |
| | 2139 | banners after a RESTART. The problem showed up in cases where there |
| | 2140 | were dependency orderings among the windows, so that one window's |
| | 2141 | initBannerWindow() had to call another's initBannerWindow() in order |
| | 2142 | to create the windows in the correct order. The problem didn't always |
| | 2143 | happen even in cases of ordering dependencies, since it also depended |
| | 2144 | on the arbitrary ordering of the VM's internal object lists. When it |
| | 2145 | happened, the problem manifested itself by creating extra copies of an |
| | 2146 | affected banner window at each RESTART. This has now been corrected. |
| | 2147 | |
| | 2148 | </div> |
| | 2149 | |
| | 2150 | <!-------------------> |
| | 2151 | <div class=entry> |
| | 2152 | |
| | 2153 | In banner.t, the formerly anonymous InitObject that handles banner |
| | 2154 | initialization (and post-RESTART re-initialization) now has a name, |
| | 2155 | bannerInit. This is so that games can use "modify" and "replace" with |
| | 2156 | the object, and also so they can refer to it from the execBeforeMe |
| | 2157 | properties of other InitObjects, for initialization dependency |
| | 2158 | ordering purposes. |
| | 2159 | |
| | 2160 | </div> |
| | 2161 | |
| | 2162 | <!-------------------> |
| | 2163 | <div class=entry> |
| | 2164 | |
| | 2165 | "Follow mode" for NPCs ("Bob, follow me") didn't work correctly when |
| | 2166 | the actor being followed moved between two top-level rooms connected |
| | 2167 | by a sight sense connector. This has been corrected. (The problem |
| | 2168 | was that the code that carried out the "follow" attempted to move the |
| | 2169 | follower using a "local travel" action - something like STAND ON STAGE |
| | 2170 | or ENTER BOOTH - any time the target actor was still in sight. The |
| | 2171 | follower now attempts local travel only if the target is still in |
| | 2172 | sight <i>and</i> the target is within the same top-level room; |
| | 2173 | otherwise, the follow uses a suitable full-fledged travel action.) |
| | 2174 | |
| | 2175 | </div> |
| | 2176 | |
| | 2177 | <!-------------------> |
| | 2178 | <div class=entry> |
| | 2179 | |
| | 2180 | In Actor.actorActionFollow(), if the actor is already in "follow" mode |
| | 2181 | for the requested other actor, a message is now displayed to this |
| | 2182 | effect (alreadyFollowModeMsg: "I'm already following Bob"). This |
| | 2183 | won't be a factor by default, since the library automatically cancels |
| | 2184 | "follow" mode any time a new command is issued to an actor |
| | 2185 | <i>before</i> attempting to enact the new command. However, games |
| | 2186 | might want to override this auto-cancel behavior, in which case they |
| | 2187 | might encounter this situation in actorActionFollow(). In the past, |
| | 2188 | the routine did nothing at all - it didn't even show a message, so the |
| | 2189 | generally undesirable "Nothing happens" was displayed by default. |
| | 2190 | |
| | 2191 | </div> |
| | 2192 | |
| | 2193 | <!-------------------> |
| | 2194 | <div class=entry> |
| | 2195 | |
| | 2196 | In the past, an actor that started in an InConversationState triggered |
| | 2197 | a run-time error at start-up, due to an initialization order problem |
| | 2198 | in the library. This has been corrected. (In particular, an actor's |
| | 2199 | boredAgendaItem property is now initialized via a perInstance() |
| | 2200 | definition rather than in initializeActor(). This ensures that the |
| | 2201 | property is initialized before it's needed. In the past, the order of |
| | 2202 | initializations sometimes resulted in the library trying to use the |
| | 2203 | actor's BoredAgendaItem object before it was initialized, leading to a |
| | 2204 | "nil object reference" error.) |
| | 2205 | |
| | 2206 | </div> |
| | 2207 | |
| | 2208 | <!-------------------> |
| | 2209 | <div class=entry> |
| | 2210 | |
| | 2211 | Room's condition for remapping the GetOutOf action to the Out action |
| | 2212 | has changed slightly. In the past, this remapping was performed only |
| | 2213 | if the 'out' direction had an <i>apparent destination</i>, which is |
| | 2214 | only the case when the actor attempting the travel already knows the |
| | 2215 | destination (such as from past experience or at-hand information). |
| | 2216 | This condition wasn't quite right, though. Instead, the condition |
| | 2217 | should have been simply that the 'out' direction has an apparent |
| | 2218 | <i>connector</i> - that is, there's a visible way to travel in the |
| | 2219 | 'out' direction. Room has been changed to use the new condition. |
| | 2220 | |
| | 2221 | </div> |
| | 2222 | |
| | 2223 | <!-------------------> |
| | 2224 | <div class=entry> |
| | 2225 | |
| | 2226 | The template (in en_us/en_us.h) for DeadEndConnector now makes the |
| | 2227 | apprentDestName entry optional. This allows using the template to |
| | 2228 | define a dead-end connector that merely displays a message when |
| | 2229 | traversed, without giving it a name. |
| | 2230 | |
| | 2231 | </div> |
| | 2232 | |
| | 2233 | <!-------------------> |
| | 2234 | <div class=entry> |
| | 2235 | |
| | 2236 | In the English library, PathPassage now limits its remapping of the |
| | 2237 | Take action to the TravelVia action to cases where the entered verb |
| | 2238 | phrase was literally "take." This prevents other phrasings, such as |
| | 2239 | "pick up path" or "get path," from being interpreted as attempts to |
| | 2240 | travel along a path. |
| | 2241 | |
| | 2242 | </div> |
| | 2243 | |
| | 2244 | <!-------------------> |
| | 2245 | <div class=entry> |
| | 2246 | |
| | 2247 | The message sayTravelingRemotely in the English library has been |
| | 2248 | corrected to add the word "to" before the destination name. |
| | 2249 | |
| | 2250 | </div> |
| | 2251 | |
| | 2252 | |
| | 2253 | <!------------------------------- 3.0.10 ---------------------------------> |
| | 2254 | <div class="sepbar"><a name='3010'></a>3.0.10</div> |
| | 2255 | <p><b><i>Released 8/17/2006</i></b> |
| | 2256 | <p> |
| | 2257 | |
| | 2258 | <div class=firstentry> |
| | 2259 | |
| | 2260 | <b>Incompatibility warning:</b> <i>(This note concerns a change that |
| | 2261 | was made in 3.0.9 but inadvertantly omitted from the 3.0.9 release |
| | 2262 | notes. We're mentioning it now in case anyone was affected by it |
| | 2263 | and needs help adjusting their code for the change.)</i> |
| | 2264 | |
| | 2265 | <p>In version 3.0.9, gameMain.verboseMode was changed from a simple |
| | 2266 | true/nil property to an object of class BinarySettingsItem. Any |
| | 2267 | existing game code that attempted to turn verbose mode on or off by |
| | 2268 | setting gameMain.verboseMode to true or nil will now encounter a run-time |
| | 2269 | error the first time the player enters a travel command. |
| | 2270 | |
| | 2271 | <p>If you want to set the default verbosity mode explicitly in your |
| | 2272 | game, you can't do it any more by setting gameMain.verboseMode to true |
| | 2273 | or nil. Instead, you can add a line like this to a start-up routine, |
| | 2274 | such as gameMain.newGame(): |
| | 2275 | |
| | 2276 | <p> |
| | 2277 | <pre> |
| | 2278 | gameMain.verboseMode.isOn = true; // turn on verbose mode |
| | 2279 | </pre> |
| | 2280 | |
| | 2281 | <p>Note that the verbosity mode is now part of the "global |
| | 2282 | preferences" mechanism, so in most cases it's best for games not to |
| | 2283 | change it explicitly, instead leaving it up to the player to decide on |
| | 2284 | the setting. In the past, some authors liked to set a verbosity mode |
| | 2285 | that they felt was most suitable for the game. Now that the player |
| | 2286 | can specify a set of default preferences that they wish to apply to |
| | 2287 | all games, it's better for authors not to presume to change the |
| | 2288 | player's default settings without a good reason. As with any other |
| | 2289 | rule, there are bound to be exceptions, so if you have a really good |
| | 2290 | reason to override the player's preferences then you should feel free |
| | 2291 | to do so. But if you're tempted to override the player's preferences |
| | 2292 | just because <i>you</i> like it a particular way, you might want to |
| | 2293 | reconsider. |
| | 2294 | |
| | 2295 | </div> |
| | 2296 | |
| | 2297 | <!-------------------> |
| | 2298 | <div class=entry> |
| | 2299 | |
| | 2300 | Minor incompatibility warning: The Lockable class now has |
| | 2301 | initiallyLocked set to true. This means that <i>all</i> Lockable |
| | 2302 | objects now start out locked by default (i.e., unless your game code |
| | 2303 | specifically overrides initiallyLocked to set it to nil for a given |
| | 2304 | Lockable). In the past, Lockable didn't define initiallyLocked at all |
| | 2305 | (so it defaulted to nil), but Door and IndirectLockable defined it as |
| | 2306 | true - so some Lockables formerly started out locked by default while |
| | 2307 | others were unlocked by default. This change should be generally |
| | 2308 | beneficial, since (1) it simplifies matters by making the initial lock |
| | 2309 | status consistent across all Lockables, and (2) the vast majority of |
| | 2310 | Lockables start out locked anyway, so "locked" is the better default. |
| | 2311 | |
| | 2312 | <p>If you have any Lockables in existing code that you specifically |
| | 2313 | intended to start out unlocked, and you didn't explicitly set |
| | 2314 | initiallyLocked to nil in those objects, you'll have to do so now. |
| | 2315 | |
| | 2316 | </div> |
| | 2317 | |
| | 2318 | <!-------------------> |
| | 2319 | <div class=entry> |
| | 2320 | |
| | 2321 | Minor incompatibility warning: The method Action.callVerifyPrecond has |
| | 2322 | been renamed to callVerifyPreCond - that is, the 'c' in 'precond' is |
| | 2323 | now capitalized. This change is for better naming consistency, since |
| | 2324 | all of the other symbol names in the library that include the |
| | 2325 | substring "precond" capitalize the C. This routine is intended mostly |
| | 2326 | for internal use within the library, so it should affect little or no |
| | 2327 | existing game code. |
| | 2328 | |
| | 2329 | </div> |
| | 2330 | |
| | 2331 | <!-------------------> |
| | 2332 | <div class=entry> |
| | 2333 | |
| | 2334 | Minor incompatibility warning: The NOTE command has been removed, and |
| | 2335 | replaced by a new comment syntax that lets the player enter a comment |
| | 2336 | by starting a command line with a punctuation-mark prefix. |
| | 2337 | |
| | 2338 | <p>The default comment prefix is now an asterisk ("*"). You can |
| | 2339 | change this to any prefix string you'd like by modifying the |
| | 2340 | commentPrefix property of the commentPreParser object. You can also |
| | 2341 | control whether or not leading whitespace is allowed before the |
| | 2342 | comment prefix (it is by default) by modifying commentPreParser's |
| | 2343 | leadPat property. |
| | 2344 | |
| | 2345 | <p>Using NOTE as the comment prefix was problematic because NOTE is a |
| | 2346 | common enough word that games often want to use it in an object's |
| | 2347 | name, and this creates situations where a user might want to start an |
| | 2348 | input line with NOTE with the intention of referring to an object, not |
| | 2349 | of entering a comment. It was essentially impossible in some of these |
| | 2350 | cases to reliably determine which the player meant. The new approach |
| | 2351 | avoids these problems by using syntax that should be unambiguous in |
| | 2352 | nearly all games. |
| | 2353 | |
| | 2354 | <p>In the past, there was a StringPreParser object in the English |
| | 2355 | library that helped the NOTE command by quoting the note text in some |
| | 2356 | cases. This preparser has been removed, and a new preparser has been |
| | 2357 | added in its place, but this time in the general library, in misc.t. |
| | 2358 | The new object is called commentPreParser, and it performs all of the |
| | 2359 | comment handling itself, without the need for a separate NOTE action. |
| | 2360 | |
| | 2361 | <p>As part of this change, NoteAction and NoteIAction have been |
| | 2362 | eliminated. In the unlikely event that you used 'modify' to change |
| | 2363 | the behavior of these actions, you'll have to rework your code. Look |
| | 2364 | at the commentPreParser object for details of the new arrangement. |
| | 2365 | |
| | 2366 | </div> |
| | 2367 | |
| | 2368 | <!-------------------> |
| | 2369 | <div class=entry> |
| | 2370 | |
| | 2371 | Minor incompatibility warning: Each actor now has its own separate |
| | 2372 | lookup table of ConvNode names. This means that you don't have to |
| | 2373 | worry about making ConvNode names unique globally - you only have to |
| | 2374 | make sure that names are unique within a single actor's set of nodes. |
| | 2375 | |
| | 2376 | <p>This shouldn't affect existing game code, except for cases where |
| | 2377 | you refer directly to conversationManager.convNodeTab. You should |
| | 2378 | scan your source for occurrences of "convNodeTab" and change any that |
| | 2379 | you find to "actor.convNodeTab", where "actor" is the Actor who owns |
| | 2380 | the table. The most likely place for game code to refer to |
| | 2381 | convNodeTab is in a "modify conversationManager" definition. |
| | 2382 | |
| | 2383 | </div> |
| | 2384 | |
| | 2385 | <!-------------------> |
| | 2386 | <div class=entry> |
| | 2387 | |
| | 2388 | Minor incompatibility warning: Thing.getExtraScopeItems() is now |
| | 2389 | required to return a list - nil is no longer a valid return value |
| | 2390 | for this method. Use an empty list instead of nil to indicate that |
| | 2391 | there's nothing to add to the current scope. The old nil return |
| | 2392 | code was inconsistent and unnecessary, as an empty list always |
| | 2393 | functionally meant the same thing anyway. |
| | 2394 | |
| | 2395 | <p>It's very unlikely that this change will affect any existing |
| | 2396 | game code, since any game code that overrides this method almost |
| | 2397 | certainly did so to add something to the scope. However, you |
| | 2398 | do a quick search through your game code for getExtraScopeItems(), |
| | 2399 | and make sure that you don't have any nil returns; if you do, |
| | 2400 | simply change them to empty lists ("return [];"). |
| | 2401 | |
| | 2402 | </div> |
| | 2403 | |
| | 2404 | <!-------------------> |
| | 2405 | <div class=entry> |
| | 2406 | |
| | 2407 | Minor incompatibility warning: Thing.getListedContentsInExamine() has |
| | 2408 | been renamed to getContentsForExamine(), and its operation changed |
| | 2409 | slightly. The old name was a bit misleading, in that the method |
| | 2410 | actually needs to return all of the visible contents of the object, |
| | 2411 | whether or not they're marked as listable. Unlistable contents need |
| | 2412 | to be included in this list so that their listable contents can be |
| | 2413 | included recursively. This is the operational change: in the past, |
| | 2414 | only listable contents were included in the returned list; now, all |
| | 2415 | visible contents are included. |
| | 2416 | |
| | 2417 | <p>This change corrects an inconsistency that occurred in cases where |
| | 2418 | an object had fixed-in-place contents that themselves had contents. |
| | 2419 | In the past, directly examining such an object didn't mention anything |
| | 2420 | about the contents of the second-level containers, while a simple LOOK |
| | 2421 | <i>did</i> include the inner contents. The change makes the two cases |
| | 2422 | consistent. |
| | 2423 | |
| | 2424 | <p>This change should have little or no effect on existing code, since |
| | 2425 | the former getListedContentsInExamine() method is an internal method |
| | 2426 | that's unlikely to have been called or overridden in game code. If |
| | 2427 | you overrode this routine, though, you'll need to apply the name |
| | 2428 | change to your code, and make any adjustments for the slight change in |
| | 2429 | the method's semantics. |
| | 2430 | |
| | 2431 | </div> |
| | 2432 | |
| | 2433 | <!-------------------> |
| | 2434 | <div class=entry> |
| | 2435 | |
| | 2436 | Minor incompatibility warning: the "equivalent object" mechanism has |
| | 2437 | changed substantially, although existing game code shouldn't be |
| | 2438 | affected unless it was modifying the equivalence mechanism itself. |
| | 2439 | |
| | 2440 | <p>In the past, equivalence was based on the superclass of the object. |
| | 2441 | Two objects were equivalent if (a) they both had isEquivalent set to |
| | 2442 | true, and (b) they had identical superclass lists. This approach to |
| | 2443 | equivalence was occasionally problematic, particularly when using |
| | 2444 | "proxy" objects to modify the behavior of objects involved in |
| | 2445 | equivalence groups. In addition, the superclass approach was somewhat |
| | 2446 | counterintuitive: the whole point of the equivalence mechanism is to |
| | 2447 | treat objects with identical names as interchangeable, but using |
| | 2448 | superclasses as the basis of the equivalence had nothing to do with |
| | 2449 | the naming. |
| | 2450 | |
| | 2451 | <p>The new scheme is based on a new property called equivalenceKey, |
| | 2452 | which is defined in the language module. In the English library, the |
| | 2453 | default setting of this new property is the disambigName of the |
| | 2454 | object. So, equivalence groups are now simply based on the basic |
| | 2455 | disambiguation name of the object. This is much more consistent with |
| | 2456 | the disambiguation mechanism itself, because it means that the parser |
| | 2457 | decides whether objects are interchangeable using essentially the same |
| | 2458 | logic that the player uses intuitively: if the game always refers to |
| | 2459 | two objects by the same name, they're interchangeable. |
| | 2460 | |
| | 2461 | <p>Another advantage of the new scheme is that it's much more |
| | 2462 | customizable than the old scheme. Since the basis of the equivalence |
| | 2463 | decision is now distinguished as a separate property (equivalenceKey), |
| | 2464 | you can control equivalence groups simply by overriding the property. |
| | 2465 | You could even effectively restore the old scheme by defining |
| | 2466 | equivalenceKey as getSuperclassList() - this would make the immediate |
| | 2467 | superclass list of an object the basis of its equivalence grouping, |
| | 2468 | producing the same behavior as in the past. |
| | 2469 | |
| | 2470 | <p>Note that if you change an object's equivalenceKey dynamically |
| | 2471 | during play - or if you change its underlying disambigName property - |
| | 2472 | the object's listing group <b>won't</b> be automatically updated. If |
| | 2473 | you do make such a change and you want to update the object's listing |
| | 2474 | group, just call initializeEquivalent() on the object. (Under the old |
| | 2475 | scheme, there was really no way to change an object's grouping - even |
| | 2476 | if you changed its name, it was still grouped based on its class, |
| | 2477 | which could have caused strange results in listings. The new scheme |
| | 2478 | at least allows for this kind of change, although it requires this |
| | 2479 | manual step to keep the list grouping settings in sync.) |
| | 2480 | |
| | 2481 | </div> |
| | 2482 | |
| | 2483 | <!-------------------> |
| | 2484 | <div class=entry> |
| | 2485 | |
| | 2486 | In the past, when EXAMINE was applied to a Room, the Room simply |
| | 2487 | turned the command into a nested LOOK AROUND command. This has |
| | 2488 | changed slightly. Now, the Room directly does the work that LOOK |
| | 2489 | AROUND would do, without the nested command, and with the difference |
| | 2490 | that the initial line with the room name in boldface isn't included in |
| | 2491 | the output. (This is accomplished by omitting the LookRoomName flag |
| | 2492 | from the 'verbose' flags for the Actor.lookAround() call.) |
| | 2493 | |
| | 2494 | <p>There are two reasons for this change. First, when the player |
| | 2495 | explicitly types EXAMINE <i>room name</i>, it's somewhat redundant to |
| | 2496 | include the room name in the output. Second, when the player types |
| | 2497 | EXAMINE ALL or EXAMINE <i>list of things</i>, the standard |
| | 2498 | multi-object-command output format already prefaces the results for |
| | 2499 | each item in the list with the name of the item ("kitchen:"), which |
| | 2500 | made the room name line especially redundant in this case. |
| | 2501 | |
| | 2502 | </div> |
| | 2503 | |
| | 2504 | <!-------------------> |
| | 2505 | <div class=entry> |
| | 2506 | |
| | 2507 | An object can now be associated with more than one CollectiveGroup. |
| | 2508 | This allows an object to be a member of multiple disjoint groups. |
| | 2509 | For example, you could create a group for "treasure," and a group |
| | 2510 | for "jewelry," and put some objects in both groups, while leaving |
| | 2511 | others in one group or the other. |
| | 2512 | |
| | 2513 | <p>To define multiple CollectiveGroups for a given object, use the new |
| | 2514 | property 'collectiveGroups' on the objects that you want to associate |
| | 2515 | with the groups. Set this property to a list with the CollectiveGroup |
| | 2516 | objects to associate with the given object. |
| | 2517 | |
| | 2518 | <p>You can still use the single-valued 'collectiveGroup' property, so |
| | 2519 | existing game code will continue to work unchanged. However, |
| | 2520 | 'collectiveGroup' is now obsolescent, so you should not use it for new |
| | 2521 | code - use 'collectiveGroups' instead. For compatibility with |
| | 2522 | existing code, the library's default definition of |
| | 2523 | Thing.collectiveGroups is a method that returns an empty list if |
| | 2524 | collectiveGroup is nil, or a one-element list containing the |
| | 2525 | collectiveGroup value if the value is not nil. Since this is slightly |
| | 2526 | ineffecient, support for the old 'collectiveGroup' will probably |
| | 2527 | eventually be removed, at which point the default for |
| | 2528 | 'collectiveGroups' will simply be an empty list. |
| | 2529 | |
| | 2530 | </div> |
| | 2531 | |
| | 2532 | <!-------------------> |
| | 2533 | <div class=entry> |
| | 2534 | |
| | 2535 | Several new classes bring functionality parallel to |
| | 2536 | RestrictedContainer to surfaces, undersides, and rear containers and |
| | 2537 | surfaces. The new classes are RestrictedSurface, RestrictedUnderside, |
| | 2538 | RestrictedRearContainer, and RestrictedRearSurface. These new classes |
| | 2539 | (along with RestrictedContainer itself) are all based on the new |
| | 2540 | mix-in class RestrictedHolder, which defines generic containment |
| | 2541 | restriction rules that can be applied to any container subtype. |
| | 2542 | |
| | 2543 | <p>The new classes work just like RestrictedContainer did, and |
| | 2544 | RestrictedContainer itself hasn't changed its behavior (it's been |
| | 2545 | refactored slightly for the new base class, but this is just an |
| | 2546 | internal change that shouldn't affect any existing code). To |
| | 2547 | accommodate the new types of restriction, suitable new library "player |
| | 2548 | action" messages have been added (cannotPutOnRestrictedMsg, |
| | 2549 | cannotPutUnderRestrictedMsg, cannotPutBehindRestrictedMsg). |
| | 2550 | |
| | 2551 | </div> |
| | 2552 | |
| | 2553 | <!-------------------> |
| | 2554 | <div class=entry> |
| | 2555 | |
| | 2556 | In the past, the default Search action handling was the same as for |
| | 2557 | LookIn. Now, the Search handling is slightly different for Container |
| | 2558 | and Openable. |
| | 2559 | |
| | 2560 | <p>First, Openable adds an objOpen precondition for Search if the |
| | 2561 | actor isn't inside the object; for LookIn, this is skipped if the |
| | 2562 | object is transparent. |
| | 2563 | |
| | 2564 | <p>Second, in the Search check() method, Container requires that the |
| | 2565 | object be openable or transparent to the "touch" sense, or that the |
| | 2566 | actor is inside the container. LookIn is similar, but only requires |
| | 2567 | that the container to be non-opaque in the <b>"sight"</b> sense. |
| | 2568 | |
| | 2569 | <p>The reason for these changes is that Search implies a more thorough, |
| | 2570 | physical examination than LookIn does. To most people, an explicit |
| | 2571 | search involves physically poking through an object's contents, while |
| | 2572 | "look in" is more passive, implying just having a look inside. |
| | 2573 | |
| | 2574 | </div> |
| | 2575 | |
| | 2576 | <!-------------------> |
| | 2577 | <div class=entry> |
| | 2578 | |
| | 2579 | In the past, the Thing handlers for PUT UNDER and PUT BEHIND included |
| | 2580 | touchObj preconditions on the direct object instead of objHeld |
| | 2581 | preconditions. These have been changed to objHeld conditions; since |
| | 2582 | these verbs generally require physically moving the direct object, the |
| | 2583 | correct precondition is that the direct object be held, just as for |
| | 2584 | the other PUT verbs. |
| | 2585 | |
| | 2586 | </div> |
| | 2587 | |
| | 2588 | <!-------------------> |
| | 2589 | <div class=entry> |
| | 2590 | |
| | 2591 | A new Action method, getEnteredVerbPhrase(), returns the action's |
| | 2592 | original verb phrase text as typed by the player. The return value is |
| | 2593 | a string giving the verb phrase in a canonical format: specifically, |
| | 2594 | the result is all in lower-case, and each noun phrase in the player's |
| | 2595 | input is replaced by a placeholder token: '(dobj)' for the direct |
| | 2596 | object, '(iobj)' for the indirect object, '(topic)' for a topic |
| | 2597 | phrase, and '(literal)' for a literal text phrase. Only the verb |
| | 2598 | phrase is included in the result - there's no target actor phrase, and |
| | 2599 | no sentence-ending punctuation included. The noun phrase replacements |
| | 2600 | apply to the <i>entire</i> noun phrases, so the single placeholder |
| | 2601 | '(dobj)' could represent an entire list of direct objects. For |
| | 2602 | example, if the player types "BOB, PUT THE BOOK AND PENCIL IN THE BOX |
| | 2603 | AND GIVE IT TO ME", calling getEnteredVerbPhrase() on the PutIn action |
| | 2604 | would yield 'put (dobj) in (iobj)', and calling the method on the |
| | 2605 | GiveTo would yield 'give (dobj) to (iobj)'. |
| | 2606 | |
| | 2607 | <p>There are two reasons why the method returns the canonical format |
| | 2608 | rather than the full text of the entire command. First, the full text |
| | 2609 | is already readily available, via gAction.getOrigText(), so there's no |
| | 2610 | need for a new method to retrieve this information. Second, and more |
| | 2611 | importantly, the canonical format isoaltes the verb phrase structure |
| | 2612 | of the player's input, independently of any noun phrases, making it |
| | 2613 | easy to determine exactly which verb phrasing the player actually used. |
| | 2614 | |
| | 2615 | <p>This method is most useful in cases where the library's verb rules |
| | 2616 | define two or more different phrasings for the same Action, and you |
| | 2617 | need to be able to distinguish exactly which variant the player |
| | 2618 | entered. For the most part, this is unnecessary: when the library's |
| | 2619 | verb rules include synonyms, it's because the different phrasings |
| | 2620 | usually have exactly the same abstract meaning, hence it's enough to |
| | 2621 | know which Action matched the grammar. In some cases, though, a |
| | 2622 | particular verb applied to a particular object has an idiomatic |
| | 2623 | meaning different from the usual meaning for other objects, and in |
| | 2624 | those cases the generic synonyms often fail to be idiomatic synonyms. |
| | 2625 | |
| | 2626 | <p>For example, the library defines "get (dobj)" and "take (dobj)" as |
| | 2627 | synonyms for the Take action, because GET and TAKE can almost always |
| | 2628 | be used interchangeably. However, if you were defining an "aspirin" |
| | 2629 | object, you might want to treat the command "take aspirin" as meaning |
| | 2630 | "eat aspirin," but you would still want "get aspirin" to mean "pick up |
| | 2631 | aspirin." You could handle this by overriding the dobjFor(Take) |
| | 2632 | action() method on the aspirin object, comparing |
| | 2633 | gAction.getEnteredVerbPhrase() to 'take (dobj)', and calling |
| | 2634 | replaceAction(Eat, self) if it's a match. |
| | 2635 | |
| | 2636 | </div> |
| | 2637 | |
| | 2638 | <!-------------------> |
| | 2639 | <div class=entry> |
| | 2640 | |
| | 2641 | The new Action method getPredicate() returns the verb phrase match |
| | 2642 | tree object that the parser resolved to the Action. The English |
| | 2643 | library uses Action objects as predicate match tree objects, so in the |
| | 2644 | English version this simply yields the original Action. However, |
| | 2645 | non-English libraries can use separate objects for verb phrase match |
| | 2646 | tree objects, so if you need any information from the verb phrase's |
| | 2647 | grammar tree (for example, if you need to call getOrigText() or |
| | 2648 | getOrigTokenList()), you should use action.getPredicate() rather than |
| | 2649 | using the action object directly. (This does <b>not</b> apply to the |
| | 2650 | new method getEnteredVerbPhrase() above - that method is explicitly |
| | 2651 | defined on the Action, not the grammar object. getEnteredVerbPhrase() |
| | 2652 | itself calls getPredicate() to get the grammar information, so you can |
| | 2653 | simply call getEnteredVerbPhrase() directly on the Action object.) |
| | 2654 | |
| | 2655 | </div> |
| | 2656 | |
| | 2657 | <!-------------------> |
| | 2658 | <div class=entry> |
| | 2659 | |
| | 2660 | The library looks to a new global variable, gLibMessages, to determine |
| | 2661 | which object to use as the "library message" source. (This is the |
| | 2662 | object used for messages that don't logically relate to the current |
| | 2663 | actor; generally, these messages are replies to meta-commands, or text |
| | 2664 | fragments used to construct descriptions.) |
| | 2665 | |
| | 2666 | <p>In the past, the library simply used the libMessages object |
| | 2667 | directly as the source of these messages. Now, the library instead |
| | 2668 | uses the current value of gLibMessages as the message source. The |
| | 2669 | default value of gLibMessages is libMessages, and the library never |
| | 2670 | changes this value itself, so the default behavior is exactly the same |
| | 2671 | as before. |
| | 2672 | |
| | 2673 | <p>The purpose of this change is to allow a game to switch to a new |
| | 2674 | set of library messages dynamically during play. For example, if your |
| | 2675 | game is structured into chapters with different points of view, you |
| | 2676 | might want to use a distinctive writing styles for the different |
| | 2677 | chapters, in which case you'd want to change all of the library |
| | 2678 | messages at each chapter transition. To do this, simply set |
| | 2679 | gLibMessages to refer to a new object at each point when you want to |
| | 2680 | switch message sources; subsequent messages will come from your new |
| | 2681 | source object. Note that it's not necessary to do this if you only |
| | 2682 | want to customize messages statically (i.e., throughout the entire |
| | 2683 | game); for that, you can just 'modify libMessages'. |
| | 2684 | |
| | 2685 | </div> |
| | 2686 | |
| | 2687 | <!-------------------> |
| | 2688 | <div class=entry> |
| | 2689 | |
| | 2690 | In the past, the Floor class replied to THROW <i>object</i> AT FLOOR |
| | 2691 | with the same default message ("you should just put it down instead") |
| | 2692 | in all cases. This reply is no longer used in cases where the Floor |
| | 2693 | is unreachable; instead, the standard THROW handling applies, since |
| | 2694 | the player couldn't accomplish the same thing with DROP. |
| | 2695 | |
| | 2696 | </div> |
| | 2697 | |
| | 2698 | <!-------------------> |
| | 2699 | <div class=entry> |
| | 2700 | |
| | 2701 | RoomPart.getHitFallDestination() will now take into account any |
| | 2702 | explicit 'location' setting in the RoomPart when determining the |
| | 2703 | destination. In the past, an explicit 'location' setting was ignored, |
| | 2704 | and a valid destination could only be found if the RoomPart was in the |
| | 2705 | same top-level room as the actor. Now, if the RoomPart has an |
| | 2706 | explicit non-nil location setting, that takes precedence in |
| | 2707 | determining the destination. This is useful when creating connected |
| | 2708 | top-level locations with room parts that you want capable of serving |
| | 2709 | as THROW targets. |
| | 2710 | |
| | 2711 | </div> |
| | 2712 | |
| | 2713 | <!-------------------> |
| | 2714 | <div class=entry> |
| | 2715 | |
| | 2716 | When throwing an object at a target, and the target happens also to be |
| | 2717 | the place where the object is described as landing when thrown at that |
| | 2718 | target (i.e., the target is the nominal drop destination of its own |
| | 2719 | the "hit-fall" destination), a new default message is used, of the |
| | 2720 | form "The projectile lands on the target." In the past, the message |
| | 2721 | was the awkward "The projectile hits the target without any obvious |
| | 2722 | effect, and falls to the target." This was most likely to occur when |
| | 2723 | the target was something like a floor or ground object, since that's |
| | 2724 | the only case where the target is likely to also be the nominal drop |
| | 2725 | destination. This change is in the routine |
| | 2726 | DropTypeThrow.standardReport(). |
| | 2727 | |
| | 2728 | </div> |
| | 2729 | |
| | 2730 | <!-------------------> |
| | 2731 | <div class=entry> |
| | 2732 | |
| | 2733 | GIVE TO, SHOW TO, and THROW TO now use different messages depending on |
| | 2734 | whether the indirect object is an actor or an inanimate object. For |
| | 2735 | ordinary Things, the message is now of the form "You can't give |
| | 2736 | anything to X"; for Actors, the message is "The X does not appear |
| | 2737 | interested." In the past, the latter message was used for all |
| | 2738 | objects, animate or not. Imputing "interest" to an inanimate object |
| | 2739 | could be read as either intentionally snide (as though the library |
| | 2740 | were sarcastically calling the player dense for trying such an |
| | 2741 | obviously stupid thing) or simply wrong (as though the library didn't |
| | 2742 | know the difference); since msg_neu is supposed to affect a neutral |
| | 2743 | narrative tone, neither alternative is desirable. |
| | 2744 | |
| | 2745 | <p>In addition, showing or giving an Actor to itself is now handled |
| | 2746 | with a separate message ("Showing X to itself would accomplishing |
| | 2747 | nothing"). |
| | 2748 | |
| | 2749 | </div> |
| | 2750 | |
| | 2751 | <!-------------------> |
| | 2752 | <div class=entry> |
| | 2753 | |
| | 2754 | REMOVE <i>dobj</i> now uses a separate reply if the object is already |
| | 2755 | being held: "There's nothing to remove the X from." In the past, the |
| | 2756 | command was unconditionally turned into TAKE <i>dobj</i>, which showed |
| | 2757 | "(from you)" as the implied indirect object part, which was a bit |
| | 2758 | awkward. |
| | 2759 | |
| | 2760 | </div> |
| | 2761 | |
| | 2762 | <!-------------------> |
| | 2763 | <div class=entry> |
| | 2764 | |
| | 2765 | When the THROW <i>direction</i> command is used with a nonportable |
| | 2766 | object (as in THROW DESK EAST), the result is now the same as for |
| | 2767 | commands like MOVE and PUSH: "The desk cannot be moved." |
| | 2768 | |
| | 2769 | </div> |
| | 2770 | |
| | 2771 | <!-------------------> |
| | 2772 | <div class=entry> |
| | 2773 | |
| | 2774 | The default response for THROW DOWN has been changed to use the same |
| | 2775 | message as for DROP when applied to an object that's not currently |
| | 2776 | being held: "You're not carrying that." |
| | 2777 | |
| | 2778 | </div> |
| | 2779 | |
| | 2780 | <!-------------------> |
| | 2781 | <div class=entry> |
| | 2782 | |
| | 2783 | In statusLine.beginStatusLine(), in the StatusModeApi case, there was |
| | 2784 | some leftover old code ("<body bgcolor=statusbg text=statustext>") |
| | 2785 | right after the call to setColorScheme() that effectively undid the |
| | 2786 | color settings made in setColorScheme(). The old code has been deleted. |
| | 2787 | |
| | 2788 | </div> |
| | 2789 | |
| | 2790 | <!-------------------> |
| | 2791 | <div class=entry> |
| | 2792 | |
| | 2793 | The library now uses the same default message in response to a command |
| | 2794 | to throw the player character in a direction (as in THROW ME EAST) as |
| | 2795 | it does as for THROW ME AT <i>something</i>. |
| | 2796 | |
| | 2797 | </div> |
| | 2798 | |
| | 2799 | <!-------------------> |
| | 2800 | <div class=entry> |
| | 2801 | |
| | 2802 | A new Thing method, adjustThrowDestination(), gives a prospective |
| | 2803 | landing site for a thrown object a chance to redirect the landing to |
| | 2804 | another object. getHitFallDestination() now treats the result it |
| | 2805 | calculates using getDropDestination() as tentative, and calls this new |
| | 2806 | method on the tentative result object to determine the actual |
| | 2807 | destination. The default implementation of the new method in Thing |
| | 2808 | simply returns 'self', which confirms the tentative destination as the |
| | 2809 | actual destination. BulkLimiter overrides the new method to redirect |
| | 2810 | the landing site to the BulkLimiter's location's drop destination if |
| | 2811 | the thrown object would overflow the BulkLimiter's capacity. |
| | 2812 | |
| | 2813 | <p>This change corrects a problem that occurred when a thrown object |
| | 2814 | landed in a BulkLimiter that was already near capacity. In the past, |
| | 2815 | the BulkLimiter applied its capacity control by effectively blocking |
| | 2816 | the THROW before it happened. With the change, the THROW will be |
| | 2817 | allowed to proceed, and the thrown object will land in the nearest |
| | 2818 | suitable container of the original target. |
| | 2819 | |
| | 2820 | <p>Note that any game code that overrides getHitFallDestination() |
| | 2821 | should be sure to call adjustThrowDestination() on its tentative |
| | 2822 | return value. Games usually won't have any reason to override |
| | 2823 | getHitFallDestination(), so this change shouldn't affect most existing |
| | 2824 | code. |
| | 2825 | |
| | 2826 | |
| | 2827 | </div> |
| | 2828 | |
| | 2829 | <!-------------------> |
| | 2830 | <div class=entry> |
| | 2831 | |
| | 2832 | In ActorState, the beforeTravel() method no longer ends the current |
| | 2833 | conversation if the actor is merely moving between nested locations |
| | 2834 | within the same top-level location. These aren't usually true |
| | 2835 | departures that should trigger conversation termination, so the method |
| | 2836 | no longer treats them as such. |
| | 2837 | |
| | 2838 | </div> |
| | 2839 | |
| | 2840 | <!-------------------> |
| | 2841 | <div class=entry> |
| | 2842 | |
| | 2843 | A new travel connector class, DeadEndConnector, can be used for |
| | 2844 | situations where travel through the connector is impossible, but for |
| | 2845 | reasons that can only be learned by attempting to go through the |
| | 2846 | connector. For example, this can be used for a passage that turns out |
| | 2847 | to be blocked by a cave-in that isn't visible from the passage |
| | 2848 | entrance, or in a situation where you describe the actor as wandering |
| | 2849 | around in a direction for a while but giving up and returning to the |
| | 2850 | point of origin. |
| | 2851 | |
| | 2852 | <p>DeadEndConnector supplements FakeConnector, which is most useful |
| | 2853 | for exits that look like connections but can't be traversed for |
| | 2854 | reasons that are apparent before the travel is ever physically |
| | 2855 | attempted - in particular, for motivational reasons ("You can't leave |
| | 2856 | town without finding your missing brother"). DeadEndConnector differs |
| | 2857 | from FakeConnector in that DeadEndConnector acts as though the |
| | 2858 | physical travel were actually occurring. It fires all of the normal |
| | 2859 | travel notifications, so any side effects that would occur on ordinary |
| | 2860 | travel will also occur with a DeadEndConnector. |
| | 2861 | |
| | 2862 | </div> |
| | 2863 | |
| | 2864 | <!-------------------> |
| | 2865 | <div class=entry> |
| | 2866 | |
| | 2867 | "Push travel" has been changed slightly to handle situations where the |
| | 2868 | object being pushed has side effects that affect the description of |
| | 2869 | the destination location. The most common situation where this arises |
| | 2870 | is when the object being pushed is (or contains) a light source, but |
| | 2871 | it could happen in many other custom-coded situations. |
| | 2872 | |
| | 2873 | <p>In the past, the object being pushed wasn't moved to its new |
| | 2874 | location until after the new location had been described. The point |
| | 2875 | of this sequencing was to exclude the pushed object from the new |
| | 2876 | location's description, simply by keeping it out of the new location |
| | 2877 | until after the description was displayed. This exclusion is |
| | 2878 | desirable because it would otherwise look as though the pushed object |
| | 2879 | were already in the new location on the player character's arrival, |
| | 2880 | which would be confusing. However, it prevented any side effects of |
| | 2881 | the pushed object's presence from being taken into account in the new |
| | 2882 | location's description. If the pushed object was a light source, for |
| | 2883 | example, and the new location was otherwise unlit, the new location |
| | 2884 | was described as dark. |
| | 2885 | |
| | 2886 | <p>Now, the library tentatively moves the pushable object to the |
| | 2887 | destination of the travel, and marks the object (via the new |
| | 2888 | Actor.excludeFromLookAround mechanism) for exclusion from the location |
| | 2889 | description. It then moves the actor and shows the description of the |
| | 2890 | new location. Finally, it moves the pushable back to the origin |
| | 2891 | location, and then moves a second time, this time for real, to the |
| | 2892 | destination location. |
| | 2893 | |
| | 2894 | <p>(The reason for moving the pushable twice - first tentatively, |
| | 2895 | before the travel, then again "for real," after the travel - is that |
| | 2896 | the method that makes the final move is overridable and so might |
| | 2897 | actually do something other than move the pushable to the travel |
| | 2898 | destination. Even if it leaves the object unmoved, though, or moves |
| | 2899 | it to a different final destination, the tentative first move is still |
| | 2900 | a valid intermediate step. At the point we're generating the |
| | 2901 | description of the new room, the player character is <i>in the |
| | 2902 | process</i> of pushing the pushable into the new room - the PC is |
| | 2903 | notionally walking along with the pushable at that stage. If the |
| | 2904 | overridable final-move method wants to do something different, it can |
| | 2905 | do so; it will simply have to describe the change, which it had to do |
| | 2906 | in the past anyway. At that point, the PC will already be in the new |
| | 2907 | location, and so will in fact have pushed the pushable this far; |
| | 2908 | anything that happens in the overridable method happens <i>after</i> |
| | 2909 | the intermediate stage where we generated the description, so any side |
| | 2910 | effects of the pushable's tentative presence were valid at that point, |
| | 2911 | no matter what happens afterwards.) |
| | 2912 | |
| | 2913 | </div> |
| | 2914 | |
| | 2915 | <!-------------------> |
| | 2916 | <div class=entry> |
| | 2917 | |
| | 2918 | In the English library, the Push-Travel commands (PUSH X NORTH, PUSH X |
| | 2919 | UP RAMP, etc) now only accept single direct objects. In the past, the |
| | 2920 | grammar phrasings allowed direct object lists, but actually pushing |
| | 2921 | multiple objects into a new room is a practical impossibility, so |
| | 2922 | there's no point in accepting it in the grammar. |
| | 2923 | |
| | 2924 | </div> |
| | 2925 | |
| | 2926 | <!-------------------> |
| | 2927 | <div class=entry> |
| | 2928 | |
| | 2929 | The mechanism for describing "local" NPC travel has been enhanced. |
| | 2930 | Local NPC travel is travel where an NPC moves from one top-level |
| | 2931 | location to another, and both top-level locations are in view of the |
| | 2932 | PC. In these cases, special handling is needed because the NPC isn't |
| | 2933 | truly arriving or departing in the usual sense; the NPC is instead |
| | 2934 | moving closer to, further away from, or laterally with respect to, the |
| | 2935 | PC. |
| | 2936 | |
| | 2937 | <p>In the past, the local NPC travel mechanism did everything via the |
| | 2938 | "local arrival" message: the NPC generated only this one special |
| | 2939 | message at the destination end of the travel. The new mechanism adds |
| | 2940 | two messages analogous to the local arrival message: a "local |
| | 2941 | departure" message and a "remote travel" message. Here's how they're |
| | 2942 | used: |
| | 2943 | |
| | 2944 | <ul> |
| | 2945 | |
| | 2946 | <li>If the PC is moving <i>closer</i> to the PC, the <b>local |
| | 2947 | arrival</b> message is displayed at the destination end of the travel. |
| | 2948 | "Closer" means that the NPC is moving from a top-level location that |
| | 2949 | <i>doesn't</i> contain the PC to a top-level location that does |
| | 2950 | contain the PC. |
| | 2951 | |
| | 2952 | <li>If the PC is moving <i>further away</i> from the PC, the <b>local |
| | 2953 | departure</b> message is displayed at the origin end of the travel. |
| | 2954 | "Further away" means that the NPC is moving from the top-level |
| | 2955 | location that contains the PC to a different top-level location that |
| | 2956 | doesn't. |
| | 2957 | |
| | 2958 | <li>If the PC is moving <i>laterally</i>, the <b>remote travel</b> |
| | 2959 | message is displayed at the destination end of the travel. |
| | 2960 | "Laterally" means that the NPC is moving between two top-level |
| | 2961 | locations, neither of which contain the PC. Note that there's no good |
| | 2962 | basis for preferring to show the message on the origin or destination |
| | 2963 | side of the travel in this case, since the generic situation is so |
| | 2964 | symmetrical, but at the same time it's necessary to choose one or the |
| | 2965 | other because we don't want two messages for this kind of travel. So, |
| | 2966 | we have to make an arbitrary choice, and the library chooses to show |
| | 2967 | the message on the destination side. |
| | 2968 | |
| | 2969 | </ul> |
| | 2970 | |
| | 2971 | <p>These new rules obviously require some new methods. Here's the |
| | 2972 | new arrangement of methods: |
| | 2973 | |
| | 2974 | <ul> |
| | 2975 | |
| | 2976 | <li>The local arrival message is embodied in |
| | 2977 | TravelConnector.describeLocalArrival(), which by default calls |
| | 2978 | Traveler.sayArrivingLocally(), which by default calls |
| | 2979 | libMessages.sayArrivingLocally(). Note that these aren't new - this |
| | 2980 | part of the mechanism carries forward unchanged from past versions. |
| | 2981 | However, their <i>usage</i> has changed, in that the library in the |
| | 2982 | past called the local arrival messages in <i>all</i> cases of local |
| | 2983 | travel, but now calls it only in <i>certain</i> cases, as described |
| | 2984 | above, and calls the local-departure or remote-travel methods in other |
| | 2985 | cases that formerly all folded into the local-arrival case. |
| | 2986 | |
| | 2987 | <li>The local departure message is embodied in |
| | 2988 | TravelConnector.describeLocalDeparture(), which by default calls |
| | 2989 | Traveler.sayDepartingLocally(), which by default calls |
| | 2990 | libMessages.sayDepartingLocally(). These methods are new. |
| | 2991 | |
| | 2992 | <li>The remote travel message is embodied in |
| | 2993 | TravelConnector.describeRemoteTravel(), which by default calls |
| | 2994 | Traveler.sayTravelingRemotely(), which by default calls |
| | 2995 | libMessages.sayTravelingRemotely(). These methods are new. |
| | 2996 | |
| | 2997 | </ul> |
| | 2998 | |
| | 2999 | <li>Existing code should continue to work correctly with the new |
| | 3000 | framework, although with one caveat: if you customized a |
| | 3001 | describeLocalArrival() or sayArrivingLocally() method, you might want |
| | 3002 | to add corresponding customizations for the new local-departure and/or |
| | 3003 | remote-travel methods. If you don't, your local-arrival customization |
| | 3004 | will still work in the cases where it applies under the new rules, but |
| | 3005 | it won't be invoked in all the cases it was in the past. |
| | 3006 | |
| | 3007 | </div> |
| | 3008 | |
| | 3009 | <!-------------------> |
| | 3010 | <div class=entry> |
| | 3011 | |
| | 3012 | AccompanyingInTravelState now describes local travel using its |
| | 3013 | standard departure message. This ensures that the correct messages |
| | 3014 | are displayed when accompanying an actor in local travel or travel |
| | 3015 | between two connected top-level locations (such as locations linked by |
| | 3016 | distance). |
| | 3017 | |
| | 3018 | </div> |
| | 3019 | |
| | 3020 | <!-------------------> |
| | 3021 | <div class=entry> |
| | 3022 | |
| | 3023 | TravelAction.actionOfKind(cls) now properly handles the case where |
| | 3024 | 'cls' is the base TravelAction class. (In the past, asking about |
| | 3025 | TravelAction itself caused a run-time error.) |
| | 3026 | |
| | 3027 | </div> |
| | 3028 | |
| | 3029 | <!-------------------> |
| | 3030 | <div class=entry> |
| | 3031 | |
| | 3032 | The various SettingsItem objects defined in the library are now all |
| | 3033 | named objects. In the past, some of these (such as |
| | 3034 | gameMain.verboseMode) were defined as embedded objects; this made it |
| | 3035 | more difficult to modify their behavior, since it wasn't possible to |
| | 3036 | use 'modify' to alter the objects directly. The behavior should be |
| | 3037 | exactly the same as in the past; the only difference is that the |
| | 3038 | objects are now easier to customize. |
| | 3039 | |
| | 3040 | </div> |
| | 3041 | |
| | 3042 | <!-------------------> |
| | 3043 | <div class=entry> |
| | 3044 | |
| | 3045 | The putDestMessage that was defined in defaultFloor and defaultGround |
| | 3046 | has been moved to the base Floor class instead - this message should |
| | 3047 | be common to most floor/ground type objects, not just for the default |
| | 3048 | ones in the library. |
| | 3049 | |
| | 3050 | </div> |
| | 3051 | |
| | 3052 | <!-------------------> |
| | 3053 | <div class=entry> |
| | 3054 | |
| | 3055 | The method standing.tryMakingPosture(loc) now generates the command |
| | 3056 | STAND ON <i>loc</i>, rather than simply STAND as it did in the past. |
| | 3057 | This makes the behavior consistent with the sitting and lying postures. |
| | 3058 | |
| | 3059 | </div> |
| | 3060 | |
| | 3061 | <!-------------------> |
| | 3062 | <div class=entry> |
| | 3063 | |
| | 3064 | Room can now be used as the direct object of STAND ON, SIT ON, and LIE |
| | 3065 | ON. These are handled simply by remapping the commands to the room's |
| | 3066 | "floor" object (specifically, the object returned from the room's |
| | 3067 | roomFloor method). This is in part to accommodate the change above to |
| | 3068 | standing.tryMakingPosture(), and in part to provide better automatic |
| | 3069 | handling for player commands like SIT IN YARD. |
| | 3070 | |
| | 3071 | </div> |
| | 3072 | |
| | 3073 | <!-------------------> |
| | 3074 | <div class=entry> |
| | 3075 | |
| | 3076 | RoomPart now applies some additional disambiguation filtering in cases |
| | 3077 | where two or more top-level locations are linked by a sense connector. |
| | 3078 | When a resolve list contains multiple RoomPart objects, and some of |
| | 3079 | those RoomParts are local and some remote, RoomPart will reduce the |
| | 3080 | list to include only the local RoomParts. (A "local" object is one |
| | 3081 | within the same top-level location as the actor; a "remote" object is |
| | 3082 | one that's in a separate top-level location that's linked by a sense |
| | 3083 | connector.) |
| | 3084 | |
| | 3085 | </div> |
| | 3086 | |
| | 3087 | <!-------------------> |
| | 3088 | <div class=entry> |
| | 3089 | |
| | 3090 | If a RoomPart has an explicit 'location' setting, that location will |
| | 3091 | no longer add the RoomPart redundantly to the location's 'contents' |
| | 3092 | list. In the past, the RoomPart would show up twice in the contents |
| | 3093 | list, because it was added once by virtue of being in the RoomParts |
| | 3094 | list, and again by virtue of its 'location' setting. |
| | 3095 | |
| | 3096 | <p>In addition, when a RoomPart has an explicit 'location' setting, it |
| | 3097 | will now automatically add itself to that location's 'roomParts' list. |
| | 3098 | This means that you don't have to manually set both properties, which |
| | 3099 | saves a little work and also makes your game easier to maintain, since |
| | 3100 | you won't have to remember to make coordinated changes to both |
| | 3101 | settings in your source code if you change the room part later. |
| | 3102 | |
| | 3103 | </div> |
| | 3104 | |
| | 3105 | <!-------------------> |
| | 3106 | <div class=entry> |
| | 3107 | |
| | 3108 | RoomPart and TravelConnectorLink now have a default sightSize of |
| | 3109 | 'large'. This means that it's possible to examine these objects at a |
| | 3110 | distance. Room parts are things like walls and ceilings that tend to |
| | 3111 | be large and to contain large-scale details that would be |
| | 3112 | realistically discernible at a distance - the details are typically |
| | 3113 | things like doors and windows. Similarly, TravelConnectorLink (which |
| | 3114 | you'd mainly use via its subclasses Enterable and Exitable) is for |
| | 3115 | things like building exteriors, which likewise tend to have |
| | 3116 | large-scale details. |
| | 3117 | |
| | 3118 | <p>In cases where you create a RoomPart or an Enterable or Exitable |
| | 3119 | that has fine-grained details that would be too small to see at a |
| | 3120 | distance, <i>and</i> the object is visible from a separate top-level |
| | 3121 | location linked by distance, you might want to override this to set |
| | 3122 | the sightSize back to medium. When there's no distance-linked |
| | 3123 | top-level location, this shouldn't be an issue, since there'd be no |
| | 3124 | way to examine the object from a distance to begin with. |
| | 3125 | |
| | 3126 | </div> |
| | 3127 | |
| | 3128 | <!-------------------> |
| | 3129 | <div class=entry> |
| | 3130 | |
| | 3131 | RoomPartItem now overrides useSpecialDescInRoom() and |
| | 3132 | useSpecialDescInContents() to return nil, and no longer overrides |
| | 3133 | useSpecialDesc and useInitSpecialDesc. |
| | 3134 | |
| | 3135 | <p>In the past, RoomPartItem overrode useSpecialDesc and |
| | 3136 | useInitSpecialDesc (setting them to nil) in order to prevent room part |
| | 3137 | items from being included in LOOK descriptions, but this had the bad |
| | 3138 | side effect of preventing showSpecialDesc() from showing the |
| | 3139 | initSpecialDesc. This change uses the more precise methods to select |
| | 3140 | exactly where the special desc should be shown, without affecting the |
| | 3141 | selection of which special desc to show. |
| | 3142 | |
| | 3143 | </div> |
| | 3144 | |
| | 3145 | <!-------------------> |
| | 3146 | <div class=entry> |
| | 3147 | |
| | 3148 | Thing.isListedInContents now calls useSpecialDescInContents(location) |
| | 3149 | to make its determination. In the past, it called useSpecialDesc |
| | 3150 | directly; this was incorrect because it didn't properly take into |
| | 3151 | account the differentiation among contexts that the various |
| | 3152 | useSpecialDescInXxx methods provide. |
| | 3153 | |
| | 3154 | </div> |
| | 3155 | |
| | 3156 | <!-------------------> |
| | 3157 | <div class=entry> |
| | 3158 | |
| | 3159 | The exit-list generator (exitLister.showExitsWithLister) now considers |
| | 3160 | two destination locations to be equivalent based on the destination |
| | 3161 | room object rather than the destination room name. This means that |
| | 3162 | two distinct exit locations will now be listed separately even if they |
| | 3163 | have the same name. For example, in the past, if the east and west |
| | 3164 | exits led to separate rooms that both happened to be named "the |
| | 3165 | hallway," the listing formerly read "east (or west), to the hallway", |
| | 3166 | but will now read "east, to the hallway; west, to the hallway". The |
| | 3167 | old approach of merging list entries based on name alone produced odd |
| | 3168 | results in some cases, and didn't have any obvious benefits; the new |
| | 3169 | approach should produce more predictable results. |
| | 3170 | |
| | 3171 | </div> |
| | 3172 | |
| | 3173 | <!-------------------> |
| | 3174 | <div class=entry> |
| | 3175 | |
| | 3176 | TIAction has a new method, retryWithAmbiguousIobj(), that lets an |
| | 3177 | action handler specifically ask for disambiguation from a list of |
| | 3178 | possibilities. This is the TIAction equivalent of the TAction method |
| | 3179 | retryWithAmbiguousDobj(), and works the same way; the only difference |
| | 3180 | is that the disambiguation list applies to the indirect object rather |
| | 3181 | than to the direct object. |
| | 3182 | |
| | 3183 | </div> |
| | 3184 | |
| | 3185 | <!-------------------> |
| | 3186 | <div class=entry> |
| | 3187 | |
| | 3188 | The TAction and TIAction methods retryWithAmbiguousDobj() and |
| | 3189 | retryWithAmbiguousIobj() can now be called before the "iteration" |
| | 3190 | phase of the command execution, specifically during |
| | 3191 | Action.beforeActionMain(), and they'll work properly: they'll ask |
| | 3192 | their disambiguation question, then apply it to the entire iteration |
| | 3193 | for the other object list. For example, if you call |
| | 3194 | retryWithAmbiguousIobj() during beforeActionMain() to prompt for a new |
| | 3195 | indirect object for a PUT IN command, the player's response will |
| | 3196 | automatically be applied to the whole direct object list if the player |
| | 3197 | specified multiple direct objects. In the past, it wasn't possible to |
| | 3198 | call these "retry" methods during beforeActionMain(), so if they were |
| | 3199 | used during commands with multiple objects in the other object slot, |
| | 3200 | the result was that the "retry" - and its question to the user - was |
| | 3201 | repeated for each object in the list. |
| | 3202 | |
| | 3203 | <p>(This new flexibility involves two supporting changes. First, the |
| | 3204 | various initForMissingXxx() methods in various Action subclasses now |
| | 3205 | detect that the iteration over the object list hasn't begun yet, and |
| | 3206 | they simply retain the entire object list (rather than the current |
| | 3207 | iteration item, as they did in the past) for the retry. Second, to |
| | 3208 | support the first change, the class PreResolvedAmbigProd now accepts |
| | 3209 | an entire object list instead of just a single iteration element. |
| | 3210 | These are internal methods that game code is unlikely to call |
| | 3211 | directly, so the only visible effect of these changes should be the |
| | 3212 | new flexibility in how the "retry" methods can be used.) |
| | 3213 | |
| | 3214 | </div> |
| | 3215 | |
| | 3216 | <!-------------------> |
| | 3217 | <div class=entry> |
| | 3218 | |
| | 3219 | In the past, initializeThing() was sometimes called multiple times in |
| | 3220 | the course of dynamically creating an object (with 'new'). This |
| | 3221 | happened when creating objects based on classes that inherited from |
| | 3222 | Thing more than once (classes like this include Flashlight, Passage, |
| | 3223 | Room, Chair, Bed, Platform, NominalPlatform, Booth, and |
| | 3224 | UntakeableActor). This happened because the default constructor for |
| | 3225 | any object based on multiple base classes simply inherits each of the |
| | 3226 | base class constructors, one after the other; when more than one base |
| | 3227 | class itself inherits from Thing, this results in multiple inherited |
| | 3228 | invocations of the Thing constructor, which in the past resulted in |
| | 3229 | multiple invocations of initializeThing() for the new object. |
| | 3230 | |
| | 3231 | <p>Now, initializeThing() is only called once. The Thing constructor |
| | 3232 | now tests a flag before calling initializeThing; it only calls the |
| | 3233 | method if the flag isn't set, and it sets the flag after calling the |
| | 3234 | method. This ensures that subsequent inherited constructor calls |
| | 3235 | simply skip the call to initializeThing(). The constructor also skips |
| | 3236 | the call to its own inherited base class constructor when the flag is |
| | 3237 | set; this ensures that the vocabulary initializations in VocabObject |
| | 3238 | are only invoked once per object. |
| | 3239 | |
| | 3240 | </div> |
| | 3241 | |
| | 3242 | <!-------------------> |
| | 3243 | <div class=entry> |
| | 3244 | |
| | 3245 | Room has a few command-handling enhancements, for rooms that have |
| | 3246 | associated vocabulary. LOOK IN <i>room</i> is now treated the same as |
| | 3247 | EXAMINE <i>room</i>; LOOK UNDER and LOOK BEHIND are refused ("You |
| | 3248 | can't look under that"); SMELL and LISTEN TO <i>room</i> are now |
| | 3249 | equivalent to simply SMELL and LISTEN; BOARD and ENTER are treated as |
| | 3250 | redundant ("You're already in that"); and GET OUT OF is a little |
| | 3251 | smarter about remapping, so that it only remaps to GO OUT if there |
| | 3252 | actually is an OUT direction defined for the room, and fails with an |
| | 3253 | error if not ("You'll have to say which way to go"). |
| | 3254 | |
| | 3255 | </div> |
| | 3256 | |
| | 3257 | <!-------------------> |
| | 3258 | <div class=entry> |
| | 3259 | |
| | 3260 | NestedRoom.makeStandingUp() now leaves the actor's posture unchanged |
| | 3261 | if the travel to the new location fails. It does this by noting the |
| | 3262 | original posture before the travel attempt, and checking after the |
| | 3263 | travel attempt to see if the actor is still in the starting nested |
| | 3264 | room; if so, the routine restores the saved posture. This ensures |
| | 3265 | that a failed travel attempt won't cause a posture change in the |
| | 3266 | original nested location. |
| | 3267 | |
| | 3268 | </div> |
| | 3269 | |
| | 3270 | <!-------------------> |
| | 3271 | <div class=entry> |
| | 3272 | |
| | 3273 | NominalPlatform now overrides hideFromDefault() to always return true. |
| | 3274 | Nominal platforms are meant to be used as internal objects and not to |
| | 3275 | appear as simulation objects, so it's generally not desirable for them |
| | 3276 | to be used as defaults. |
| | 3277 | |
| | 3278 | </div> |
| | 3279 | |
| | 3280 | <!-------------------> |
| | 3281 | <div class=entry> |
| | 3282 | |
| | 3283 | AccompanyingState had a problem that caused infinite recursion |
| | 3284 | (leading to a stack overflow) when an actor in an AccompanyingState |
| | 3285 | was explicitly moved via scriptedTravelTo(). The problem was simply |
| | 3286 | that the actor attempted to accompany itself on its own travel, and |
| | 3287 | that accompanying travel triggered a further accompanying travel, and |
| | 3288 | so on. This has been corrected: actors in accompanying travel states |
| | 3289 | now explicitly ignore their own travel for the purposes of |
| | 3290 | accompanying travel. |
| | 3291 | |
| | 3292 | </div> |
| | 3293 | |
| | 3294 | <!-------------------> |
| | 3295 | <div class=entry> |
| | 3296 | |
| | 3297 | The library uses a separate default message in cases where an Actor is |
| | 3298 | holding an object used in ENTER, BOARD, SIT ON, etc. In the past, the |
| | 3299 | message was the rather awkward "You can't do that while the chair in |
| | 3300 | in Bob." The new message is phrased "...while Bob is holding the |
| | 3301 | chair" instead. The default message for non-Actors is unchanged. |
| | 3302 | |
| | 3303 | </div> |
| | 3304 | |
| | 3305 | <!-------------------> |
| | 3306 | <div class=entry> |
| | 3307 | |
| | 3308 | FOLLOW caused a run-time error if the follower was holding the |
| | 3309 | NPC to be followed. This was because effectiveFollowLocation |
| | 3310 | wasn't defined for ordinary objects. This has been corrected |
| | 3311 | by defining Thing.effectiveFollowLocation to return the location's |
| | 3312 | effectiveFollowLocation, or just 'self' if the object has no |
| | 3313 | location. |
| | 3314 | |
| | 3315 | </div> |
| | 3316 | |
| | 3317 | <!-------------------> |
| | 3318 | <div class=entry> |
| | 3319 | |
| | 3320 | <a name='ImpByeTopicSubclasses'></a> |
| | 3321 | |
| | 3322 | There are two new subclasses of ImpByeTopic, to allow you to |
| | 3323 | differentiate between the two implicit ways of ending a conversation. |
| | 3324 | BoredByeTopic handles cases where the NPC ends the conversation |
| | 3325 | because of "boredom" (that is, inactivity in the conversation that |
| | 3326 | exceeds the NPC's attentionSpan setting), while LeaveByeTopic handles |
| | 3327 | cases where the PC simply walks away from the NPC in mid-conversation. |
| | 3328 | |
| | 3329 | <p>BoredByeTopic and LeaveByeTopic extend the hierarchy that already |
| | 3330 | existed with ByeTopic and ImpByeTopic. If there's an active |
| | 3331 | ImpByeTopic and no active BoredByeTopic or LeaveByeTopic objects at |
| | 3332 | the time of an implied "goodbye", the ImpByeTopic will be used for |
| | 3333 | both cases (this also happens to be exactly the way the library worked |
| | 3334 | in the past, before the two new subclasses were added, so this change |
| | 3335 | won't disturb existing code). If there's an active BoredByeTopic as |
| | 3336 | well as an active ImpByeTopic, the BoredByeTopic will be selected over |
| | 3337 | the ImpByeTopic to handle "boredom" goodbyes; likewise, if there's an |
| | 3338 | active LeaveByeTopic, it will be selected over an active ImpByeTopic |
| | 3339 | to handle goodbyes triggered by the PC's departure. |
| | 3340 | |
| | 3341 | </div> |
| | 3342 | |
| | 3343 | <!-------------------> |
| | 3344 | <div class=entry> |
| | 3345 | |
| | 3346 | The "boredom" mechanism in InConversationState has been changed |
| | 3347 | slightly. In the past, it was implemented directly in the takeTurn() |
| | 3348 | method of InConversationState. Now, it's handled with an AgendaItem |
| | 3349 | instead - specifically, a new subclass called BoredomAgendaItem, which |
| | 3350 | the Actor and InConversationState classes manage automatically. This |
| | 3351 | change should have no effect on existing code, since the new code |
| | 3352 | implements the same behavior as the old version. The benefit of this |
| | 3353 | change is that it makes it easier for a game to customize the boredom |
| | 3354 | behavior, since it's now part of the more general "agenda" mechanism |
| | 3355 | instead of being buried in ad hoc code inside the conversation state |
| | 3356 | class. |
| | 3357 | |
| | 3358 | </div> |
| | 3359 | |
| | 3360 | <!-------------------> |
| | 3361 | <div class=entry> |
| | 3362 | |
| | 3363 | The suggested topic lister had a problem that showed up when several |
| | 3364 | topic suggestions were present with the same listing name, and some of |
| | 3365 | the topics were inactive while others were active. The lister |
| | 3366 | automatically removes redundant entries from suggestion lists by |
| | 3367 | removing multiple items with the same name, but in the past, the |
| | 3368 | lister sometimes incorrectly removed the <i>active</i> elements |
| | 3369 | instead of the inactive ones, effectively eliminating the suggestion |
| | 3370 | entirely from the list. This has been corrected: the lister now only |
| | 3371 | removes a redundant suggestion if there's another <i>active</i> |
| | 3372 | suggestion with the same listing name. |
| | 3373 | |
| | 3374 | </div> |
| | 3375 | |
| | 3376 | <!-------------------> |
| | 3377 | <div class=entry> |
| | 3378 | |
| | 3379 | InitiateTopic no longer sets any pronoun antecedents when triggered. |
| | 3380 | (It did set its match object as a pronoun antecedent in the past. |
| | 3381 | This was undesirable because an InitiateTopic is triggered by internal |
| | 3382 | calculations in the game, not by anything the player has done.) |
| | 3383 | |
| | 3384 | </div> |
| | 3385 | |
| | 3386 | <!-------------------> |
| | 3387 | <div class=entry> |
| | 3388 | |
| | 3389 | ConvAgendaItem now checks to make sure the player character is present |
| | 3390 | before declaring itself ready. This ensures that an NPC won't attempt |
| | 3391 | a conversational agenda item unless the PC is actually present to hear |
| | 3392 | what the NPC has to say. (This change is in ConvAgendaItem.isReady.) |
| | 3393 | |
| | 3394 | </div> |
| | 3395 | |
| | 3396 | <!-------------------> |
| | 3397 | <div class=entry> |
| | 3398 | |
| | 3399 | Actor.executeAgenda() formerly marked an agenda item as done if |
| | 3400 | invoking the item threw any sort of exception. Now, this is only done |
| | 3401 | on a run-time error (a RuntimeError exception); in cases of other |
| | 3402 | exceptions, the item's doneness isn't changed. The original purpose |
| | 3403 | of the doneness change was to reduce debugging hassles in cases where |
| | 3404 | an agenda item encountered an error; in such cases, if the item wasn't |
| | 3405 | marked as done, the scheduler would end up invoking the item in an |
| | 3406 | infinite loop, because it would look perpetually ready to run. |
| | 3407 | However, doing this on <i>all</i> exceptions interfered with certain |
| | 3408 | non-error cases where exceptions were used to jump out of the action |
| | 3409 | handling. Limiting the caught exceptions to runtime errors should |
| | 3410 | retain most of the intended benefits while avoiding the problems with |
| | 3411 | a more general error catcher here. |
| | 3412 | |
| | 3413 | </div> |
| | 3414 | |
| | 3415 | <!-------------------> |
| | 3416 | <div class=entry> |
| | 3417 | |
| | 3418 | Actor.initiateConversation() now handles a nil 'state' argument |
| | 3419 | slightly differently. In the past, if 'state' was nil, the actor's |
| | 3420 | state was simply left unchanged. Now, the method will switch the |
| | 3421 | actor to the state returned from the current state's |
| | 3422 | getImpliedConvState() method. In most cases, the net effect is |
| | 3423 | exactly as before - i.e., the actor's state is left unchanged - |
| | 3424 | because the default getImpliedConvState() simply returns 'self'. |
| | 3425 | However, ConversationReadyState overrides getImpliedConvState() to |
| | 3426 | return the associated InConversationState. This change makes it |
| | 3427 | easier to initiate a conversation when using an actor with |
| | 3428 | conversational states, since it will generally pick the correct |
| | 3429 | conversational state automatically. |
| | 3430 | |
| | 3431 | <p>Note that the ActorState method getImpliedConvState() is new with |
| | 3432 | this change. |
| | 3433 | |
| | 3434 | </div> |
| | 3435 | |
| | 3436 | <!-------------------> |
| | 3437 | <div class=entry> |
| | 3438 | |
| | 3439 | Due to a bug, <.convnode> tags displayed inside npcGreetingMsg |
| | 3440 | methods weren't handled properly if the greeting was displayed due to |
| | 3441 | NPC initiation of the conversation (via npcInitiateConversation()). |
| | 3442 | This has been corrected. |
| | 3443 | |
| | 3444 | </div> |
| | 3445 | |
| | 3446 | <!-------------------> |
| | 3447 | <div class=entry> |
| | 3448 | |
| | 3449 | ConvNode.canEndConversation() can now return a special value, |
| | 3450 | blockEndConv, that indicates that the actor said something to force |
| | 3451 | the conversation to keep going. You should always use this if you |
| | 3452 | display a message in the routine <i>and</i> you want to prevent the |
| | 3453 | conversation from ending. Returning blockEndConv is <i>almost</i> the |
| | 3454 | same as returning nil from the method, but has the additional side |
| | 3455 | effect that the caller will call noteConvAction() on the other actor, |
| | 3456 | to prevent this actor from generating any further scripted remarks on |
| | 3457 | the same turn. |
| | 3458 | |
| | 3459 | </div> |
| | 3460 | |
| | 3461 | <!-------------------> |
| | 3462 | <div class=entry> |
| | 3463 | |
| | 3464 | When the library displays a parser error message for a command |
| | 3465 | directed to an NPC, it now shows the error message in a neutral sense |
| | 3466 | context. This ensures that the message is displayed even if the NPC |
| | 3467 | is in a remote location (this could be the case if we're talking over |
| | 3468 | the phone, for example). In the past, the parser message was |
| | 3469 | generated in the NPC's sense context, so the NPC was in a remote |
| | 3470 | location that wasn't in scope to the PC, the parser message was |
| | 3471 | suppressed, resulting in a "Nothing happens" message or the like. |
| | 3472 | |
| | 3473 | </div> |
| | 3474 | |
| | 3475 | <!-------------------> |
| | 3476 | <div class=entry> |
| | 3477 | |
| | 3478 | When a command of the form "actor, xxx" is entered, and the portion |
| | 3479 | after the "actor" phrase is unparseable, the parser now attempts to |
| | 3480 | parse at least the "actor" part to determine if the command is being |
| | 3481 | directed to an NPC. In the past, the parser didn't do this; the actor |
| | 3482 | phrase is part of the basic sentence grammar, so if the parser failed |
| | 3483 | to match the rest of the basic sentence grammar, it didn't bother |
| | 3484 | trying to figure out if a target actor was included. To find the |
| | 3485 | target actor, the parser now makes a second attempt at parsing a |
| | 3486 | command to see if it matches a very basic sentence syntax that only |
| | 3487 | includes the target actor specification; if it can match the syntax, |
| | 3488 | and resolve the noun phrase to an in-scope actor, the parser takes |
| | 3489 | the result to be the target actor. |
| | 3490 | |
| | 3491 | <p>The main result of this change is that a few of the low-level |
| | 3492 | parser message methods - askUnknownWord, specialTopicInactive, |
| | 3493 | commandNotUnderstood - are now invoked on the target actor when one is |
| | 3494 | present in the command. In the past, because the parser didn't even |
| | 3495 | figure out that a target actor was present in these cases, these |
| | 3496 | methods were always invoked on the player character actor. With this |
| | 3497 | change, it's now possible to customize a NPC's responses for unknown |
| | 3498 | words and command phrasings individually by NPC. |
| | 3499 | |
| | 3500 | </div> |
| | 3501 | |
| | 3502 | <!-------------------> |
| | 3503 | <div class=entry> |
| | 3504 | |
| | 3505 | The library now gives a replacement action zero time if it's replacing |
| | 3506 | an action that itself has zero time. This corrects some timing |
| | 3507 | anomalies (particularly with respect to NPCs) that showed up in |
| | 3508 | certain unusual cases where replaceAction() was used in the course |
| | 3509 | of an action that itself was being run as a nested action. |
| | 3510 | |
| | 3511 | </div> |
| | 3512 | |
| | 3513 | <!-------------------> |
| | 3514 | <div class=entry> |
| | 3515 | |
| | 3516 | A new parser option lets you cancel remaining commands on the command |
| | 3517 | line when an action fails. |
| | 3518 | |
| | 3519 | <p>To implement this, Action.afterActionMain() checks to see if the |
| | 3520 | action failed, as indicated by a 'reportFailure()' message in the |
| | 3521 | course of the action handling. If the action failed, <i>and</i> |
| | 3522 | gameMain.cancelCmdLineOnFailure is set to true, afterActionMain() |
| | 3523 | throws a CancelCommandLineException. This exception is in turn caught |
| | 3524 | in executeCommand(), which cancels any remaining commands on the |
| | 3525 | command line and simply proceeds to the next turn. |
| | 3526 | |
| | 3527 | <p>In addition, the new playerMessages method |
| | 3528 | explainCancelCommandLine() lets you display an explanation when a |
| | 3529 | command line is canceled due to the failure of a command. |
| | 3530 | executeCommand() invokes this new method when it handles a |
| | 3531 | CancelCommandLineException if there are in fact any remaining tokens |
| | 3532 | on the command line. (This check for remaining tokens skips the |
| | 3533 | explanation when there's nothing left on the command line to cancel, |
| | 3534 | as the cancellation obviously has no effect in such cases.) This new |
| | 3535 | message method doesn't display anything by default; it's just a hook |
| | 3536 | that you can use if you want to provide an explanation. Note that |
| | 3537 | you'll probably want to show this explanation only once per game, |
| | 3538 | rather than every time a command is canceled (you can use a flag |
| | 3539 | property to do this - if the flag is nil, show the message and set the |
| | 3540 | flag to true; otherwise skip the message). |
| | 3541 | |
| | 3542 | <p>The default setting for gameMain.cancelCmdLineOnFailure is nil. |
| | 3543 | This provides the traditional handling, which simply continues executing |
| | 3544 | any remaining commands on the command line even when an action fails. |
| | 3545 | |
| | 3546 | <p>The reason this new feature is an option rather than simply being |
| | 3547 | the default new policy is that neither possibility is ideal in every |
| | 3548 | case. On the one hand, continuing to execute commands after an action |
| | 3549 | has failed can lead to confusing results: the failure of the earlier |
| | 3550 | command can leave things in a state other than what the player was |
| | 3551 | anticipating, which could change the behavior of subsequent commands. |
| | 3552 | So the argument in favor of canceling remaining commands is that it |
| | 3553 | avoids this possible source of player confusion by halting processing |
| | 3554 | once it appears that the player's thinking is out of sync with the |
| | 3555 | game's internal state. On the other hand, exactly what constitutes |
| | 3556 | failure might not always be apparent to the player, so halting halfway |
| | 3557 | through a command line might sometimes appear arbitrary to the player, |
| | 3558 | or even buggy. The argument in favor of continuing to plow through |
| | 3559 | the rest of the command line like nothing happened, then, is that it's |
| | 3560 | simple and consistent. A prime virtue of any UI is predictability, so |
| | 3561 | that the user has an easier time forming a working mental model of the |
| | 3562 | software, and the most predictable behavior is to unconditionally |
| | 3563 | execute everything on the command line. Further, given that |
| | 3564 | multi-level UNDO is available by default in tads3 games, any |
| | 3565 | unintended effects from extra commands can always be manually undone |
| | 3566 | as soon as the player realizes what happened. The arguments on both |
| | 3567 | sides are valid, so the library leaves it up to the author to set the |
| | 3568 | game's policy. (It's even been suggested that this ought to be left |
| | 3569 | up to the player, via a command that selects the mode, but I think |
| | 3570 | this would be overkill, so for now this is just an author-controlled |
| | 3571 | option. Games are free to add their own command to let the player |
| | 3572 | control it, of course; it's just a matter of flipping the |
| | 3573 | cancelCmdLineOnFailure setting at run-time.) |
| | 3574 | |
| | 3575 | </div> |
| | 3576 | |
| | 3577 | <!-------------------> |
| | 3578 | <div class=entry> |
| | 3579 | |
| | 3580 | The Action class has a new method, checkAction(), that is called just |
| | 3581 | before the existing execAction() method. TAction and TIAction define |
| | 3582 | the new method, and perform the calls to the direct and indirect |
| | 3583 | object 'check' methods in this new method rather than in execAction(), |
| | 3584 | as was done in the past. |
| | 3585 | |
| | 3586 | <p>This change should have no effect on existing code, since it's a |
| | 3587 | simple internal rearrangement. The benefit is that it's now possible |
| | 3588 | for game code to call the 'check' phase of a verb explicitly, without |
| | 3589 | also invoking the 'execute' phase. |
| | 3590 | |
| | 3591 | </div> |
| | 3592 | |
| | 3593 | <!-------------------> |
| | 3594 | <div class=entry> |
| | 3595 | |
| | 3596 | OopsIAction is now defined as an IAction. (In the past, it was based |
| | 3597 | directly on Action, which was problematic if an OopsIAction grammar |
| | 3598 | match was used in certain contexts, such as |
| | 3599 | CommandRanking.sortByRanking.) |
| | 3600 | |
| | 3601 | </div> |
| | 3602 | |
| | 3603 | <!-------------------> |
| | 3604 | <div class=entry> |
| | 3605 | |
| | 3606 | ObjectPreCondition now uses the same ordering as the underlying |
| | 3607 | condition. |
| | 3608 | |
| | 3609 | </div> |
| | 3610 | |
| | 3611 | <!-------------------> |
| | 3612 | <div class=entry> |
| | 3613 | |
| | 3614 | During calls to the "verify" methods for remapped actions (i.e., |
| | 3615 | actions mapped to different actions using remapTo), the library now |
| | 3616 | sets gAction to the remapped action. In the past, during the initial |
| | 3617 | remap testing stage, the library left gAction with the original action |
| | 3618 | that triggered the remapping. This gives game code more consistent |
| | 3619 | information during the verify phase. |
| | 3620 | |
| | 3621 | </div> |
| | 3622 | |
| | 3623 | <!-------------------> |
| | 3624 | <div class=entry> |
| | 3625 | |
| | 3626 | VocabObject now defines the methods isOwnedBy(obj) and |
| | 3627 | getNominalOwner(). This allows player input to refer to non-physical |
| | 3628 | objects, such as topics, using possessive syntax. |
| | 3629 | |
| | 3630 | </div> |
| | 3631 | |
| | 3632 | <!-------------------> |
| | 3633 | <div class=entry> |
| | 3634 | |
| | 3635 | The INSTRUCTIONS command is now ignored for the purposes of UNDO and |
| | 3636 | AGAIN. |
| | 3637 | |
| | 3638 | </div> |
| | 3639 | |
| | 3640 | <!-------------------> |
| | 3641 | <div class=entry> |
| | 3642 | |
| | 3643 | The parser no longer chooses Unthings as default objects in cases |
| | 3644 | where noun phrases are missing in player input. (This is handled via |
| | 3645 | Unthing.hideFromDefault().) |
| | 3646 | |
| | 3647 | </div> |
| | 3648 | |
| | 3649 | <!-------------------> |
| | 3650 | <div class=entry> |
| | 3651 | |
| | 3652 | The new Thing method setGlobalParamName() lets you add a global |
| | 3653 | message parameter name dynamically. In the past, there was no |
| | 3654 | straightforward way to do this; you had to manually update the message |
| | 3655 | builder's internal table of names in order to add a new name. This |
| | 3656 | method takes care of all of the necessary internal table updates. |
| | 3657 | |
| | 3658 | <p>You only need to use this method if you want to add or change a |
| | 3659 | parameter name dynamically at run-time. The library still |
| | 3660 | automatically initializes the message builder's tables for |
| | 3661 | globalParamName settings defined at compile-time. |
| | 3662 | |
| | 3663 | </div> |
| | 3664 | |
| | 3665 | <!-------------------> |
| | 3666 | <div class=entry> |
| | 3667 | |
| | 3668 | The parser now marks a plural-phrase match for a direct or indirect |
| | 3669 | object as "unclearly disambiguated" if the phrase also matches a |
| | 3670 | singular noun for an object that's also in scope. This flag makes |
| | 3671 | the parser generate an extra message to notify the player that the |
| | 3672 | parser chose an object from a potentially ambiguous set: |
| | 3673 | |
| | 3674 | <p><pre> |
| | 3675 | >show bob the rags |
| | 3676 | (the piece of cloth) |
| | 3677 | Bob does not appear interested. |
| | 3678 | </pre> |
| | 3679 | |
| | 3680 | <p>If the parser's decision was wrong, the message will alert the |
| | 3681 | player, so that the player will know to try rephrasing the command |
| | 3682 | rather than being left with the impression that the intended command |
| | 3683 | didn't work. |
| | 3684 | |
| | 3685 | </div> |
| | 3686 | |
| | 3687 | <!-------------------> |
| | 3688 | <div class=entry> |
| | 3689 | |
| | 3690 | The event manager (the part of the library that manages fuses and |
| | 3691 | daemons) now automatically disables a daemon or fuse that throws an |
| | 3692 | exception out of its main execution method. The reason this is |
| | 3693 | important is that an infinite loop would otherwise occur in many |
| | 3694 | cases: if the object remained active, the event manager would |
| | 3695 | re-invoke it after the exception, and in most cases the re-invocation |
| | 3696 | would simply encounter the same exception, at which point the event |
| | 3697 | manager would invoke it once again, and so on ad infinitum. |
| | 3698 | |
| | 3699 | <p>Note that this change only comes into play when a fuse/daemon |
| | 3700 | throws an exception <b>out</b> of its main method. It won't affect a |
| | 3701 | daemon/fuse that merely encounters an exception in the course of its |
| | 3702 | processing, as long as the fuse/daemon catches and handles the |
| | 3703 | exception. |
| | 3704 | |
| | 3705 | </div> |
| | 3706 | |
| | 3707 | <!-------------------> |
| | 3708 | <div class=entry> |
| | 3709 | |
| | 3710 | A new class, OneTimePromptDaemon, makes it easy to set up a prompt |
| | 3711 | daemon that only fires once. It works like an ordinary prompt daemon, |
| | 3712 | but removes itself from the active event list as soon as it fires. |
| | 3713 | This can be handy for cases where you want to defer some non-recurring |
| | 3714 | processing until just before the next command prompt. |
| | 3715 | |
| | 3716 | </div> |
| | 3717 | |
| | 3718 | <!-------------------> |
| | 3719 | <div class=entry> |
| | 3720 | |
| | 3721 | Thanks to Greg Boettcher, the English library's default messages now |
| | 3722 | use typographical ("curly") quote marks and apostrophes. In cases of |
| | 3723 | open/close quote marks, these are generated with |
| | 3724 | <Q>...</Q> markups; in cases of apostrophes, &rsquo; |
| | 3725 | entities are used. |
| | 3726 | |
| | 3727 | <p>This change is purely cosmetic, so it should require no changes to |
| | 3728 | existing game code. It shouldn't even affect test scripts (where you |
| | 3729 | run an input script and "diff" the output against a reference log) - |
| | 3730 | by default, the log file mechanism by default generates transcript |
| | 3731 | output in plain ASCII, and the curly quotes are mapped to ordinary |
| | 3732 | straight quotes when rendered in plain ASCII. |
| | 3733 | |
| | 3734 | </div> |
| | 3735 | |
| | 3736 | <!-------------------> |
| | 3737 | <div class=entry> |
| | 3738 | |
| | 3739 | <a name='getInScopeDistinguisher'></a> |
| | 3740 | The library now attempts to be as precise as possible when announcing |
| | 3741 | objects chosen in vague disambiguations, as defaults for missing noun |
| | 3742 | phrases, and for multiple objects to a verb. In the past, the library |
| | 3743 | simply used the base name of the object being announced, but this |
| | 3744 | didn't take into account the various things that the parser can use to |
| | 3745 | distinguish objects on input, such as lit/unlit state, location, and |
| | 3746 | owner. The library now generates these object announcements using the |
| | 3747 | same Distinguisher mechanism it uses to resolve ambiguous noun phrases |
| | 3748 | in input, ensuring that the generated names are as precise as possible |
| | 3749 | in distinguishing announced objects from others in scope. |
| | 3750 | |
| | 3751 | <p>To accomplish this, the announcements call upon a new Thing method, |
| | 3752 | getInScopeDistinguisher(). This method looks at the Distinguisher |
| | 3753 | objects associated with the object to be announced, and tries to find |
| | 3754 | one that can distinguish the object to be announced from every other |
| | 3755 | object in scope. If it finds one, it returns it. If it fails to find |
| | 3756 | one, it returns the distinguisher that does the best partial job - |
| | 3757 | that is, the one that distinguishes the object from the largest number |
| | 3758 | of other in-scope objects. (The method never returns nil; in the |
| | 3759 | worst case, it simply returns basicDistinguisher, which distinguishes |
| | 3760 | objects based on their disambigName properties.) The announcements |
| | 3761 | then use the returned Distinguisher to generate the announced name. |
| | 3762 | |
| | 3763 | <p>Note that in the simplest case, this change results in the |
| | 3764 | disambigName being used in object announcements; in the past, the base |
| | 3765 | name was used. In most cases, this won't cause any change in game |
| | 3766 | behavior, since the disambigName for most objects is just the base |
| | 3767 | name anyway. |
| | 3768 | |
| | 3769 | </div> |
| | 3770 | |
| | 3771 | <!-------------------> |
| | 3772 | <div class=entry> |
| | 3773 | |
| | 3774 | The library now suppresses vague disambiguation announcements for |
| | 3775 | objects specified with indefinite articles when the announcement |
| | 3776 | would be redundant. That is, if there's no Distinguisher that can |
| | 3777 | tell apart any of the possible matches for an object specified with |
| | 3778 | an indefinite article, the library doesn't bother making the |
| | 3779 | announcement, because it would add no useful information for the |
| | 3780 | player. For example, in the past, you might have seen an exchange |
| | 3781 | like this: |
| | 3782 | |
| | 3783 | <p><pre> |
| | 3784 | >take a silver coin |
| | 3785 | (the silver coin) |
| | 3786 | </pre> |
| | 3787 | |
| | 3788 | <p>The parser was making the announcement because it had chosen |
| | 3789 | arbitrarily from one of several silver coins. But since all of the |
| | 3790 | possible matches were indistinguishable anyway, the announcement |
| | 3791 | doesn't help the player see which one in particular was chosen. The |
| | 3792 | library now suppresses the message in this case. Note, however, that |
| | 3793 | if it's possible to distinguish any of the possible matches from one |
| | 3794 | another, you'll still see a message. For example, if there's a silver |
| | 3795 | coin and a gold coin present, and the player types TAKE A COIN, the |
| | 3796 | library will announce which one (gold or silver). Similarly, if |
| | 3797 | there's a silver coin on the table and another on the floor, and the |
| | 3798 | player types TAKE A SILVER COIN, the library will mention the location |
| | 3799 | of the one chosen: "(the silver coin on the floor)", for example. |
| | 3800 | |
| | 3801 | </div> |
| | 3802 | |
| | 3803 | <!-------------------> |
| | 3804 | <div class=entry> |
| | 3805 | |
| | 3806 | The English library can now correctly generate a plural name for an |
| | 3807 | object whose name includes an "of" phrase; for example, the library |
| | 3808 | now correctly generates the plural for "piece of paper" as "pieces of |
| | 3809 | paper". In the past, the library pluralized the last word of the |
| | 3810 | entire phrase, so the result in this example would have been "piece of |
| | 3811 | papers". The new algorithm when there's an "of" is simply to |
| | 3812 | pluralize the last word before the first "of", using the same rules as |
| | 3813 | for a phrase without "of". |
| | 3814 | |
| | 3815 | </div> |
| | 3816 | |
| | 3817 | <!-------------------> |
| | 3818 | <div class=entry> |
| | 3819 | |
| | 3820 | In the past, the English parser treated a command of the form GIVE |
| | 3821 | <i>adjective noun</i> as though it meant GIVE <i>noun</i> TO |
| | 3822 | <i>adjective</i>. This was almost never what the player actually |
| | 3823 | meant; the player almost always really meant GIVE <i>object</i> TO |
| | 3824 | <i>the current interlocutor</i>, where <i>object</i> is named |
| | 3825 | <i>adjective noun</i>. The parser now applies that more likely |
| | 3826 | interpretation when confronted with this syntax. The same applies to |
| | 3827 | SHOW. |
| | 3828 | |
| | 3829 | <p>(As part of this change, a new parser class was added: |
| | 3830 | ImpliedActorNounPhraseProd. This is a subclass of EmptyNounPhraseProd |
| | 3831 | that works almost the same way, but doesn't apply a grammar ranking |
| | 3832 | penalty for the missing noun phrase if a default interlocutor can be |
| | 3833 | identified. The single-noun-phrase grammars for GIVE and SHOW use |
| | 3834 | this new class, ensuring that they're chosen over the |
| | 3835 | non-prepositional two-noun-phrase phrasings whenever a default |
| | 3836 | interlocutor is present.) |
| | 3837 | |
| | 3838 | </div> |
| | 3839 | |
| | 3840 | <!-------------------> |
| | 3841 | <div class=entry> |
| | 3842 | |
| | 3843 | In the past, the English parser treated the word "of" as a non-weak |
| | 3844 | token when matching noun phrases of the form "x of y". This meant |
| | 3845 | that if a noun phrase consisted only of weak tokens and "of", the |
| | 3846 | parser matched it. This has changed; "of" is now ignored for the |
| | 3847 | purposes of the weak-token test, so a phrase consisting only of weak |
| | 3848 | tokens and "of" is now considered weak overall. |
| | 3849 | |
| | 3850 | </div> |
| | 3851 | |
| | 3852 | <!-------------------> |
| | 3853 | <div class=entry> |
| | 3854 | |
| | 3855 | A bug in the English library caused run-time errors in some cases |
| | 3856 | involving TopicAction verbs. The problem was that some of the |
| | 3857 | TopicAction message generators assumed that they were the current |
| | 3858 | active verb, which isn't always the case. This has been fixed. |
| | 3859 | |
| | 3860 | </div> |
| | 3861 | |
| | 3862 | <!-------------------> |
| | 3863 | <div class=entry> |
| | 3864 | |
| | 3865 | The English library defines the new verb phrasings ASK <i>actor</i> |
| | 3866 | <i>topic</i> and TELL <i>actor</i> <i>topic</i>; these are phrasings |
| | 3867 | for the new actions AskVague and TellVague, respectively. These are |
| | 3868 | defined entirely to provide more helpful error messages in cases where |
| | 3869 | the player enters an ASK or TELL verb without an ABOUT phrase. The |
| | 3870 | default handling for the new actions simply displays an explanation of |
| | 3871 | the proper ASK ABOUT or TELL ABOUT phrasing. Some players have been |
| | 3872 | seen to misinterpret custom phrasings that show up in SpecialTopic |
| | 3873 | prompts, such as "ask bob why", as general-purpose command phrasing, |
| | 3874 | and then attempt to use similar phrasing elsewhere in the game. This |
| | 3875 | results in "invalid command" errors from the parser, of course, but |
| | 3876 | the standard error messages were often unhelpful with this particular |
| | 3877 | kind of phrasing error. The new handlers are meant to improve on the |
| | 3878 | standard error messages for this common case. |
| | 3879 | |
| | 3880 | </div> |
| | 3881 | |
| | 3882 | <!-------------------> |
| | 3883 | <div class=entry> |
| | 3884 | |
| | 3885 | The English library now treats the command phrasing CLIMB IN/INTO/IN |
| | 3886 | TO as a Board action, and CLIMB ON/ONTO/ON TO as a StandOn action. In |
| | 3887 | the past, both forms of CLIMB were defined for both of these actions, |
| | 3888 | which made the choice of which action matched the syntax arbitrary and |
| | 3889 | unpredictable. This change ensures that each of these phrasings is |
| | 3890 | unambiguously assigned to only one action. |
| | 3891 | |
| | 3892 | </div> |
| | 3893 | |
| | 3894 | <!-------------------> |
| | 3895 | <div class=entry> |
| | 3896 | |
| | 3897 | The English library now tries a little harder to figure out whether a |
| | 3898 | command of the form ENTER <i>text</i> means ENTER <i>text</i> ON |
| | 3899 | <i>some implied keypad-type object</i>, or GO IN <i>object</i>. In |
| | 3900 | the past, the library always used the GO IN interpretation. Now, the |
| | 3901 | library assumes the ENTER ON <i>keypad</i> interpretation if there's a |
| | 3902 | suitable default object present; if there isn't, the library reverts |
| | 3903 | to the GO IN interpretation. |
| | 3904 | |
| | 3905 | </div> |
| | 3906 | |
| | 3907 | <!-------------------> |
| | 3908 | <div class=entry> |
| | 3909 | |
| | 3910 | The English library formerly allowed any object to match the pronoun |
| | 3911 | "them"; it now limits "them" matches to (a) objects used in lists in |
| | 3912 | player input, as in TAKE IRON KEY AND BRASS KEY, and (b) objects |
| | 3913 | marked as having plural usage via isPlural. |
| | 3914 | |
| | 3915 | </div> |
| | 3916 | |
| | 3917 | <!-------------------> |
| | 3918 | <div class=entry> |
| | 3919 | |
| | 3920 | The parser now lowers the grammar match ranking for any phrasing |
| | 3921 | involving a plural in a noun slot requiring a single object. This |
| | 3922 | makes the parser a bit smarter about picking the right vocabulary |
| | 3923 | interpretation in cases of nouns that have both singular and plural |
| | 3924 | usage, such as FISH and SHEEP. |
| | 3925 | |
| | 3926 | </div> |
| | 3927 | |
| | 3928 | <!-------------------> |
| | 3929 | <div class=entry> |
| | 3930 | |
| | 3931 | In the English library, the isHim and isHer properties are now taken |
| | 3932 | into account for arbitrary Thing objects in parameter substitutions in |
| | 3933 | messages. In the past, gender was only taken into account for Actor |
| | 3934 | objects; non-Actor objects were always "it" or "them" in messages. |
| | 3935 | |
| | 3936 | </div> |
| | 3937 | |
| | 3938 | <!-------------------> |
| | 3939 | <div class=entry> |
| | 3940 | |
| | 3941 | In the English library, the Actor methods theName, theNameObj, |
| | 3942 | theNamePossAdj, theNamePossNoun, aName, and aNameObj now properly |
| | 3943 | handle the first-person plural case ("we", "us", "our", "ours", etc). |
| | 3944 | In the past, a plural Actor with first-person referralPerson |
| | 3945 | incorrectly used the singular first-person pronouns. |
| | 3946 | |
| | 3947 | </div> |
| | 3948 | |
| | 3949 | <!-------------------> |
| | 3950 | <div class=entry> |
| | 3951 | |
| | 3952 | The PourOnto verb in the English library now correctly uses |
| | 3953 | onSingleNoun as its indirect object response phrase, matching the |
| | 3954 | regular grammar for the verb. (In the past, it incorrectly used |
| | 3955 | withSingleNoun as the response phrase.) |
| | 3956 | |
| | 3957 | </div> |
| | 3958 | |
| | 3959 | <!-------------------> |
| | 3960 | <div class=entry> |
| | 3961 | |
| | 3962 | The English library now tries harder to avoid duplicating vocabulary |
| | 3963 | in the lists it constructs from vocabWords properties during |
| | 3964 | initialization. First, VocabObject.inheritVocab() now avoids |
| | 3965 | redundantly scanning vocabulary inherited from superclasses. Since |
| | 3966 | this routine's whole point is to explicitly scan the class hierarchy |
| | 3967 | for each object and add the vocabulary inherited from each superclass, |
| | 3968 | it needs to bypass the normal automatic inheritance mechanism, which |
| | 3969 | it now does. Second, initializeVocabWith() now explicitly removes |
| | 3970 | duplicates from each word list it updates, to avoid duplication in |
| | 3971 | cases where an object explicitly defines the same vocabulary word at |
| | 3972 | multiple inheritance levels. |
| | 3973 | |
| | 3974 | </div> |
| | 3975 | |
| | 3976 | |
| | 3977 | <!-------------------> |
| | 3978 | <div class=entry> |
| | 3979 | |
| | 3980 | The new function isListSubset() determines if one list is a subset of |
| | 3981 | another list: that is, if every element of the first list also appears |
| | 3982 | somewhere in the second list. (This function was formerly defined as |
| | 3983 | a method in the Lister class, but it's generically useful and wasn't |
| | 3984 | tied in any way to Lister, so it's been broken out as a function to |
| | 3985 | make it more readily accessible to other code.) |
| | 3986 | |
| | 3987 | </div> |
| | 3988 | |
| | 3989 | <!-------------------> |
| | 3990 | <div class=entry> |
| | 3991 | |
| | 3992 | The library functions main() and mainRestore() have been enhanced to |
| | 3993 | catch QuittingException signals. These functions, of course, are the |
| | 3994 | main entrypoints for the entire program - the former is for normal |
| | 3995 | start-up, and the latter is for the special kind of start-up that |
| | 3996 | restores a saved state directly from the operating system shell, such |
| | 3997 | as when the player launches the game by double-clicking a saved-state |
| | 3998 | file on the Windows desktop. Catching QuittingException in these |
| | 3999 | functions allows game code to throw QuittingException just about |
| | 4000 | anywhere, without worrying about the context. In the past, this |
| | 4001 | exception was only usable after the main command loop started; in |
| | 4002 | particular, it wasn't usable from startup or initialization code (such |
| | 4003 | as the code that displays the game's introductory messages), because |
| | 4004 | there was no handler to catch the exception in effect while that code |
| | 4005 | was running. |
| | 4006 | |
| | 4007 | </div> |
| | 4008 | |
| | 4009 | |
| | 4010 | <!------------------------------- 3.0.9 ---------------------------------> |
| | 4011 | <div class="sepbar"><a name='309'></a>3.0.9</div> |
| | 4012 | <p><b><i>Released 8/29/2005</i></b> |
| | 4013 | <p> |
| | 4014 | |
| | 4015 | <div class=firstentry> |
| | 4016 | |
| | 4017 | <b>Minor compatibility-breaking change:</b> In the English library, |
| | 4018 | the ThingState template now uses "+" rather than "@" to introduce the |
| | 4019 | listingOrder property value. The choice of punctuation here is pretty |
| | 4020 | arbitrary; the reason for the change is that a consensus emerged among |
| | 4021 | users that "+" would be easier to remember in this template because |
| | 4022 | the other library templates generally use "+" to mark integer slots. |
| | 4023 | |
| | 4024 | <p>If you have existing game code that defines any ThingState objects |
| | 4025 | using the old template, you'll need to change the definitions to use |
| | 4026 | "+" instead of "@". Alternatively, you could put your own definition |
| | 4027 | of the old ThingState template into a common header file that your |
| | 4028 | game use, in which case you wouldn't have to change any of your |
| | 4029 | existing object definitions; but you're probably better off just |
| | 4030 | changing your code to use the new convention, since defining your own |
| | 4031 | template could cause some slight confusion for other users if you |
| | 4032 | should share your code in the future. |
| | 4033 | |
| | 4034 | </div> |
| | 4035 | |
| | 4036 | <!-------------------> |
| | 4037 | <div class=entry> |
| | 4038 | |
| | 4039 | <b>Slight risk of incompatibility:</b> Thing.getDropDestination() |
| | 4040 | must now accept a nil value for the 'obj' argument. A nil value of |
| | 4041 | 'obj' asks for the drop destination for a "typical" object, rather |
| | 4042 | than for any specific object. In the past, it wasn't specified that |
| | 4043 | 'obj' could be nil, and the library never directly called the method |
| | 4044 | with a nil 'obj' value, so it's possible that some existing game code |
| | 4045 | might assume that 'obj' is non-nil. You should do a quick scan of |
| | 4046 | your game code for getDropDestination() definitions to ensure that |
| | 4047 | they'll work properly when 'obj' is nil. In particular, make sure |
| | 4048 | that you don't evaluate any properties of 'obj' without first checking |
| | 4049 | that 'obj' is non-nil: |
| | 4050 | |
| | 4051 | <p><pre> |
| | 4052 | getDropDestination(obj, path) |
| | 4053 | { |
| | 4054 | if (obj.isReallySmall) ...; <font color=red>// Don't do this!!!</font> |
| | 4055 | if (obj != nil && obj.isReallySmall) ...; <font color=green>// Do this instead</font> |
| | 4056 | } |
| | 4057 | </pre> |
| | 4058 | |
| | 4059 | </div> |
| | 4060 | |
| | 4061 | <!-------------------> |
| | 4062 | <div class=entry> |
| | 4063 | |
| | 4064 | <b>Slight risk of incompatibility:</b> The default value of |
| | 4065 | Event.eventOrder is now 100 (it was formerly 50). This default is |
| | 4066 | essentially arbitrary (since it's only important for relative |
| | 4067 | ordering), but a value of 100 is more consistent with other similar |
| | 4068 | ordering defaults elsewhere in the library. |
| | 4069 | |
| | 4070 | <p>In addition, the eventOrder of the standard sense-change daemon is |
| | 4071 | now 500, to ensure that the sense-change daemon runs after most other |
| | 4072 | events. The library automatically creates the sense-change daemon at |
| | 4073 | game start-up; this is the daemon that displays messages about new, |
| | 4074 | ongoing, or ending sounds and odors. In the past, this daemon had |
| | 4075 | default priority, so its order relative to other fuses and daemons was |
| | 4076 | arbitrary. If another fuse or daemon ran after the sense-change |
| | 4077 | daemon, and made some change that affected the sensory environment, a |
| | 4078 | message about the change wasn't displayed until the following turn, |
| | 4079 | since the chance had already passed to generate the message on the |
| | 4080 | turn during which the change actually occurred. This change ensures |
| | 4081 | that the sense-change daemon runs after most other events, so any |
| | 4082 | changes that occur in daemons and fuses will be reflected in the |
| | 4083 | sense-change update for the same turn. |
| | 4084 | |
| | 4085 | <p>If you've explicitly set eventOrder for any fuses or daemons in |
| | 4086 | your game, you might need to adjust the values you set. In |
| | 4087 | particular, if you set an eventOrder value between 50 and 100 for an |
| | 4088 | event object to ensure that the event is processed after events that |
| | 4089 | inherit the default eventOrder, you'll need to raise that value above |
| | 4090 | 100. You should also consider if it's desirable for those events to |
| | 4091 | run after the sense-change daemon, as they would have in the past |
| | 4092 | (since the sense-change daemon used to have default priority), and if |
| | 4093 | so, raise their eventOrder values to above 500. Finally, if you have |
| | 4094 | an existing eventOrder that's over 500, you might want to consider |
| | 4095 | whether you still want the event to run after the sense-change daemon; |
| | 4096 | if not, you should lower the value to under 500. |
| | 4097 | |
| | 4098 | </div> |
| | 4099 | |
| | 4100 | <!-------------------> |
| | 4101 | <div class=entry> |
| | 4102 | |
| | 4103 | <b>Possibly incompatible change:</b> The parameter lists of some of |
| | 4104 | the internal library routines that handle point-of-view have changed. |
| | 4105 | These aren't likely to affect any existing game code, since these are |
| | 4106 | mostly used only inside the library itself, but you should check your |
| | 4107 | code for any mentions of these names to be sure. You'll need to |
| | 4108 | adjust any code in your game that either calls or overrides any of |
| | 4109 | these methods or functions: |
| | 4110 | |
| | 4111 | <ul> |
| | 4112 | |
| | 4113 | <li>Thing.fromPOV() has a new parameter giving the actor who's doing |
| | 4114 | the looking. |
| | 4115 | |
| | 4116 | <li>Function pushPOV() takes a new parameter giving the actor. |
| | 4117 | |
| | 4118 | <li>Function callFromPOV() takes a new parameter giving the actor. |
| | 4119 | |
| | 4120 | <li>Function setPOV() takes a new parameter giving the actor. |
| | 4121 | |
| | 4122 | <li>Function setRootPOV() takes a new parameter giving the actor. |
| | 4123 | |
| | 4124 | </ul> |
| | 4125 | |
| | 4126 | </div> |
| | 4127 | |
| | 4128 | <!-------------------> |
| | 4129 | <div class=entry> |
| | 4130 | |
| | 4131 | <b>Very slight risk of incompatibility:</b> In the following methods, |
| | 4132 | the parameter now gives the point-of-view <i>actor</i> instead of the |
| | 4133 | point-of-view object. The POV actor and object are usually the same |
| | 4134 | anyway, so the effects on existing code should be minimal. If you |
| | 4135 | actually need the POV object, you can get it with the getPOV() |
| | 4136 | function. |
| | 4137 | |
| | 4138 | <ul> |
| | 4139 | <li>Thing.showRemoteSpecialDesc |
| | 4140 | <li>Thing.remoteInitSpecialDesc |
| | 4141 | <li>Thing.remoteSpecialDesc |
| | 4142 | <li>Thing.showSpecialDescInContents |
| | 4143 | <li>Thing.showObscuredSpecialDescInContents |
| | 4144 | <li>Thing.showDistantSpecialDescInContents |
| | 4145 | <li>Thing.showRemoteSpecialDescInContents |
| | 4146 | <li>Actor.listActorPosture |
| | 4147 | </ul> |
| | 4148 | |
| | 4149 | </div> |
| | 4150 | |
| | 4151 | |
| | 4152 | <!-------------------> |
| | 4153 | <div class=entry> |
| | 4154 | |
| | 4155 | The new function getPOVActor() returns the "point-of-view actor." |
| | 4156 | This is the actor who's doing the looking that is, the actor who's |
| | 4157 | performing the action (LOOK AROUND, EXAMINE, SMELL, etc) that's |
| | 4158 | generating the current description. This is <i>usually</i>, but not |
| | 4159 | always, the same as gActor, and it <i>usually</i>, but not always, |
| | 4160 | returns the same object as getPOV(). |
| | 4161 | |
| | 4162 | <p>The point-of-view actor can differ from gActor in cases where game |
| | 4163 | code explicitly generates a room description from the point of view of |
| | 4164 | one actor in the course of processing a command given to a different |
| | 4165 | actor. In these cases, gActor will be the actor who's performing the |
| | 4166 | command, and getPOVActor() will return the actor who's generating |
| | 4167 | the description. |
| | 4168 | |
| | 4169 | <p>The point-of-view actor can differ from the point-of-view object |
| | 4170 | (the object returned by the getPOV() function) when the actor is |
| | 4171 | observing the location being described through an intermediary object. |
| | 4172 | For example, if we're generating a description of a remote room |
| | 4173 | because an actor is examining a closed-circuit TV monitor showing the |
| | 4174 | remote location, the point-of-view actor will be the actor who's |
| | 4175 | looking at the monitor, while the point-of-view object will be the |
| | 4176 | camera in the remote location. Note that the POV is the camera, not |
| | 4177 | the monitor: the POV is intended to be the object that's physically |
| | 4178 | absorbing the light rays, or other sensory equivalents, from the |
| | 4179 | surroundings being described. |
| | 4180 | |
| | 4181 | </div> |
| | 4182 | |
| | 4183 | <!-------------------> |
| | 4184 | <div class=entry> |
| | 4185 | |
| | 4186 | The library now selects remote descriptions for rooms and other |
| | 4187 | objects a little differently than before. In the past, the remoteness |
| | 4188 | of the point-of-view object was the deciding factor - that is, remote |
| | 4189 | descriptions were used when the POV wasn't in the same room as the |
| | 4190 | object being described. Now, the library bases the decision on the |
| | 4191 | point-of-view actor, not the POV object: if the actor who's doing the |
| | 4192 | looking isn't in the same room, the remote description is used. This |
| | 4193 | means, for example, that the remote description will be generated when |
| | 4194 | observing a room through a closed-circuit TV system: even though the |
| | 4195 | POV (the camera) is in inside the room being described, the actor |
| | 4196 | who's observing the TV monitor is in a different room, so the remote |
| | 4197 | description is used. |
| | 4198 | |
| | 4199 | <p>This change is implemented in Thing.showSpecialDescWithInfo() |
| | 4200 | and Thing.showSpecialDescInContentsWithInfo(). |
| | 4201 | |
| | 4202 | </div> |
| | 4203 | |
| | 4204 | <!-------------------> |
| | 4205 | <div class=entry> |
| | 4206 | |
| | 4207 | The method Thing.lookAroundWithinContents(), which is the part of the |
| | 4208 | room describer that lists the room's contents, had a bug in past |
| | 4209 | versions that caused a single object to be listed twice in some |
| | 4210 | unusual cases. In particular, if the room itself had brightness 1, |
| | 4211 | and it contained an object that also had brightness 1, the object was |
| | 4212 | listed twice: once in a list starting "In the dark you see," then |
| | 4213 | again in a list starting "The <i>room</i> contains." The same problem |
| | 4214 | occurred in a dark room if an object with brightness 1 was inside a |
| | 4215 | container with brightness 1. This has been fixed. |
| | 4216 | |
| | 4217 | </div> |
| | 4218 | |
| | 4219 | <!-------------------> |
| | 4220 | <div class=entry> |
| | 4221 | |
| | 4222 | A new mechanism in Actor allows objects to be explicitly excluded from |
| | 4223 | the "look around" description of a room. To exclude an object, call |
| | 4224 | the method excludeFromLookAround(obj) on the actor, passing in the |
| | 4225 | object 'obj' to be excluded. The object will be suppressed from room |
| | 4226 | descriptions until further notice - it won't show up in any of the |
| | 4227 | visible-object lists, including special descriptions, room contents |
| | 4228 | lists, or nested contents lists. To remove an object from the |
| | 4229 | exclusion list, call unexcludeFromLookAround(obj). |
| | 4230 | |
| | 4231 | <p>The exclusion that this method applies is over and above any other |
| | 4232 | listing-selection mechanisms, such as obj.isListed. It's intended |
| | 4233 | mostly for ephemeral exclusions that are applied other than by the |
| | 4234 | object itself, since the object itself can usually more easily control |
| | 4235 | its own listability via isListed and the like. |
| | 4236 | |
| | 4237 | </div> |
| | 4238 | |
| | 4239 | <!-------------------> |
| | 4240 | <div class=entry> |
| | 4241 | |
| | 4242 | In Thing.adjustLookAroundTable(), the point-of-view actor is no longer |
| | 4243 | removed from the table; instead, just the point-of-view object is |
| | 4244 | removed. In cases where the POV and actor differ and the actor is in |
| | 4245 | sight of the POV, we usually want to include the actor in the |
| | 4246 | generated description. |
| | 4247 | |
| | 4248 | <p>In addition, the method now calls adjustLookAroundTable() on the |
| | 4249 | actor and POV objects, giving them a chance to make further adjustments |
| | 4250 | to the table. |
| | 4251 | |
| | 4252 | </div> |
| | 4253 | |
| | 4254 | <!-------------------> |
| | 4255 | <div class=entry> |
| | 4256 | |
| | 4257 | Suppose we have an NPC who's in scope but out of hearing range, such |
| | 4258 | as when the NPC is on the other side of a transparent, soundproof |
| | 4259 | window from the player character. If the player addresses a command |
| | 4260 | to the NPC, the library now uses the same error message that it uses |
| | 4261 | for ASK ABOUT and other conversation commands in the same situation. |
| | 4262 | |
| | 4263 | <p>(This corrects a bug that used to occur. In the past, the library |
| | 4264 | attempted to let the NPC respond, rather than generating a parser |
| | 4265 | error. The problem with this approach was that the soundproof barrier |
| | 4266 | stopped the PC from hearing the NPC's response, thus the library could |
| | 4267 | only report that "Nothing obvious happens." Now that this is handled |
| | 4268 | as a parsing error instead of a conversational response, the more |
| | 4269 | helpful "Bob does not appear to hear you" is displayed.) |
| | 4270 | |
| | 4271 | </div> |
| | 4272 | |
| | 4273 | <!-------------------> |
| | 4274 | <div class=entry> |
| | 4275 | |
| | 4276 | Thing.isListedInRoomPart has changed slightly. In the past, an object |
| | 4277 | was listed (i.e., shown in a miscellaneous list of portable contents) |
| | 4278 | as part of an EXAMINE FLOOR (or EAST WALL or the like) if the object |
| | 4279 | was nominally part of the room part (that is, nominally on the floor, |
| | 4280 | or on the given wall, etc) <b>and</b> the object was normally listed |
| | 4281 | the same way in a LOOK AROUND command. Now, the object is listed if |
| | 4282 | it's nominally part of the room part <b>and</b> the new RoomPart |
| | 4283 | method isObjListedInRoomPart() returns true. |
| | 4284 | |
| | 4285 | <p>The new method RoomPart.isObjListedInRoomPart returns true by |
| | 4286 | default if the object does <b>not</b> have a special description for |
| | 4287 | the purposes of examining the room part - that is, if the object's |
| | 4288 | useSpecialDescInRoomPart returns nil. We don't want to include the |
| | 4289 | object in the miscellaneous list if it has a special description |
| | 4290 | because the special description will be automatically shown - it would |
| | 4291 | thus be mentioned twice if we included it in the miscellaneous list as |
| | 4292 | well. |
| | 4293 | |
| | 4294 | <p>Floor overrides isObjListedInRoomPart to list an object only if |
| | 4295 | it's listed normally - that is, the object's isListed returns true. |
| | 4296 | This is the old behavior that applied to <b>all</b> room parts, but |
| | 4297 | now it only applies to Floor objects. The reason we treat Floor |
| | 4298 | differently is that everything that's directly in a room is by default |
| | 4299 | nominally on the floor in the room, so if we didn't limit the listings |
| | 4300 | like this in the case of EXAMINE FLOOR, we'd include all of the |
| | 4301 | internal fixtures and components of the room, which is generally |
| | 4302 | undesirable. |
| | 4303 | |
| | 4304 | <p>The main purpose of this change is that it makes it a little easier |
| | 4305 | to set up Fixture-type objects that are described as being situated on |
| | 4306 | walls, ceilings, and the like. Now, all that's necessary is to give |
| | 4307 | the object a specialNominalRoomPartLocation - even if the object isn't |
| | 4308 | normally listed in a room description, as is the case for a Fixture, |
| | 4309 | we'll now list the object when we examine its room part as long as it |
| | 4310 | doesn't have an explicit special description for the room part. |
| | 4311 | |
| | 4312 | </div> |
| | 4313 | |
| | 4314 | <!-------------------> |
| | 4315 | <div class=entry> |
| | 4316 | |
| | 4317 | The new mix-in class RoomPartItem can be used to create an object that |
| | 4318 | shows its special description when an associated room part is |
| | 4319 | described. This is useful for things like doors, windows, ceiling |
| | 4320 | fans, and other objects attached to the room. The main thing this |
| | 4321 | class does is to make the object show its special description when its |
| | 4322 | associated room part is examined (as in LOOK AT EAST WALL), but |
| | 4323 | <i>not</i> in the main room description (as in LOOK AROUND). This is |
| | 4324 | desirable because this kind of object is usually not remarkable enough |
| | 4325 | to call out with a special description in the overall room, but does |
| | 4326 | warrant a mention when its associated room part is explicitly |
| | 4327 | examined. |
| | 4328 | |
| | 4329 | </div> |
| | 4330 | |
| | 4331 | <!-------------------> |
| | 4332 | <div class=entry> |
| | 4333 | |
| | 4334 | SensoryEmanation has a new property, isEmanating, that lets you turn |
| | 4335 | the object on and off. By default, is Emanating is true; if you set |
| | 4336 | this to nil, it shuts off the emanation. This makes it easier to make |
| | 4337 | sounds and odors start and stop, which is often useful when the |
| | 4338 | emanations are associated with dynamic objects such as actors. |
| | 4339 | |
| | 4340 | </div> |
| | 4341 | |
| | 4342 | <!-------------------> |
| | 4343 | <div class=entry> |
| | 4344 | |
| | 4345 | Settable has a new method, canonicalizeSetting(), that converts a |
| | 4346 | proposed new setting to a "canonical" format. Settable now uses this |
| | 4347 | to process the player's input before passing the value to |
| | 4348 | isValidSetting() or makeSetting(), ensuring that these routines don't |
| | 4349 | need to perform any further format conversion of their own. |
| | 4350 | |
| | 4351 | <p>This method makes it much easier to handle superficial formatting |
| | 4352 | variations in the player's input by centralizing the conversions to |
| | 4353 | this single routine. In the past, both isValidSetting() and |
| | 4354 | makeSetting() had to handle formatting variations since they received |
| | 4355 | the raw player input. |
| | 4356 | |
| | 4357 | <p>Settable's default implementation of canonicalizeSetting() doesn't |
| | 4358 | do anything - it just returns the original player input unchanged. |
| | 4359 | NumberedDial overrides the method to convert spelled-out numbers to |
| | 4360 | numeral format and to strip off any leading zeroes from an entered |
| | 4361 | numeral format; LabeledDial overrides it to convert the input to the |
| | 4362 | exact case of the matching entry in the list of valid labels. |
| | 4363 | |
| | 4364 | </div> |
| | 4365 | |
| | 4366 | <!-------------------> |
| | 4367 | <div class=entry> |
| | 4368 | |
| | 4369 | The new library routines parseInt() and parseIntTokens() parse a |
| | 4370 | string or token list (respectively) that contains a spelled-out or |
| | 4371 | digit-string numeric value. These routines parse the input and return |
| | 4372 | the corresponding integer value, or nil if the input can't be parsed |
| | 4373 | as a number. For example, parseInt('one thousand and twenty-four') |
| | 4374 | returns 1024, parseInt('72') returns 72, and parseInt('dusty tome') |
| | 4375 | returns nil. |
| | 4376 | |
| | 4377 | </div> |
| | 4378 | |
| | 4379 | <!-------------------> |
| | 4380 | <div class=entry> |
| | 4381 | |
| | 4382 | The English library now incorporates Michel Nizette's Past Tense |
| | 4383 | extension. This enables the author to select the tense - present or |
| | 4384 | past - used in library messages, and even allows you to change the |
| | 4385 | tense dynamically during the game. |
| | 4386 | |
| | 4387 | <p>The 'master switch" for the active tense is gameMain.usePastTense. |
| | 4388 | Set this to true to activate past tense in library messages. The |
| | 4389 | default is nil, which selects present tense. |
| | 4390 | |
| | 4391 | <p>A number of new message parameters and verbEndingXxx properties |
| | 4392 | help in writing messages that can change tense. The standard library |
| | 4393 | messages defined in en_us/msg_neu.t use these new features to adapt |
| | 4394 | automatically to the current tense. |
| | 4395 | |
| | 4396 | <p>See the comments in en_us/en_us.t for full details. |
| | 4397 | |
| | 4398 | </div> |
| | 4399 | |
| | 4400 | <!-------------------> |
| | 4401 | <div class=entry> |
| | 4402 | |
| | 4403 | The library has a new framework for "global defaults," which lets the |
| | 4404 | user save certain preference settings as default values for future |
| | 4405 | sessions. These saved defaults are global: they apply to <i>any</i> |
| | 4406 | new game subsequently loaded, provided that the new game supports the |
| | 4407 | new global defaults system. Games compiled with library versions |
| | 4408 | prior to 3.0.9 didn't support this new system, but games compiled with |
| | 4409 | 3.0.9 or later will support it by default, as long as an author |
| | 4410 | doesn't explicitly disable it for some reason. The settings are saved |
| | 4411 | to a file whose name and location are determined by the interpreter |
| | 4412 | (and which might vary by system, to conform to local conventions). |
| | 4413 | |
| | 4414 | <p>Two new commands let the user control the global defaults: SAVE |
| | 4415 | DEFAULTS saves the current settings to the configuration file, and |
| | 4416 | RESTORE DEFAULTS explicitly loads the file and applies its settings. |
| | 4417 | These commands both list the full set of saved settings, so that the |
| | 4418 | user can easily tell exactly which settings are affected. |
| | 4419 | |
| | 4420 | <p>By default, the library uses the new global settings framework |
| | 4421 | for the VERBOSE, FOOTNOTES, NOTIFY, and EXITS settings. |
| | 4422 | |
| | 4423 | <p>The new mechanism is implemented mostly in the new file settings.t. |
| | 4424 | The main API is exposed through the new settingsManager object, and |
| | 4425 | the command-line user interface is implemented in the new settingsUI |
| | 4426 | object. The new SettingsItem class is used to encapsulate individual |
| | 4427 | configuration variables. If you want to create your own extensions to |
| | 4428 | the set of global default variables, simply create a SettingsItem |
| | 4429 | object for each new variable you want to add. The settings framework |
| | 4430 | will automatically find your new SettingsItem objects, and save and |
| | 4431 | restore them as needed. |
| | 4432 | |
| | 4433 | </div> |
| | 4434 | |
| | 4435 | <!-------------------> |
| | 4436 | <div class=entry> |
| | 4437 | |
| | 4438 | The new macro gSetSeen(obj) marks an object as having been seen by the |
| | 4439 | player character. |
| | 4440 | |
| | 4441 | </div> |
| | 4442 | |
| | 4443 | <!-------------------> |
| | 4444 | <div class=entry> |
| | 4445 | |
| | 4446 | The new macro gTopicText returns a string containing the literal text |
| | 4447 | of the current topic phrase, when the current action contains a topic |
| | 4448 | phrase. The text returned is as the user typed it, but converted to |
| | 4449 | lower case. |
| | 4450 | |
| | 4451 | </div> |
| | 4452 | |
| | 4453 | <!-------------------> |
| | 4454 | <div class=entry> |
| | 4455 | |
| | 4456 | The LiteralAction and LiteralTAction class are now based on a new |
| | 4457 | common mix-in base class, LiteralActionBase. This is parallel to the |
| | 4458 | structure of TopicAction and TopicTAction, with their common mix-in |
| | 4459 | base class TopicActionBase. This new arrangement shouldn't at all |
| | 4460 | change the behavior of LiteralAction or LiteralTAction, and should be |
| | 4461 | entirely transparent to existing code. |
| | 4462 | |
| | 4463 | <p>The change has two main benefits. First, it eliminates some code |
| | 4464 | duplication, by replacing a few bits of code that were effectively |
| | 4465 | duplicated in LiteralAction and LiteralTAction with common versions |
| | 4466 | that both classes now inherit from LiteralActionBase. Second, game |
| | 4467 | code can now easily determine if an action involves any sort of |
| | 4468 | literal phrase, by testing gAction.ofKind(LiteralActionBase). |
| | 4469 | |
| | 4470 | </div> |
| | 4471 | |
| | 4472 | <!-------------------> |
| | 4473 | <div class=entry> |
| | 4474 | |
| | 4475 | The new Thing method failCheck() makes it a little more convenient to |
| | 4476 | write check() routines. check() routines frequently use this pattern: |
| | 4477 | |
| | 4478 | <p><pre> |
| | 4479 | check() |
| | 4480 | { |
| | 4481 | if (condition) |
| | 4482 | { |
| | 4483 | reportFailure('You can\'t do that for some reason.'); |
| | 4484 | exit; |
| | 4485 | } |
| | 4486 | } |
| | 4487 | </pre> |
| | 4488 | |
| | 4489 | <p>The failCheck() routine encapsulates the display of the failure |
| | 4490 | report and the termination of the action with 'exit'. Using |
| | 4491 | failCheck(), you can rewrite the code above more concisely, |
| | 4492 | like so: |
| | 4493 | |
| | 4494 | <p><pre> |
| | 4495 | check() |
| | 4496 | { |
| | 4497 | if (condition) |
| | 4498 | failCheck('You can\'t do that for some reason.'); |
| | 4499 | } |
| | 4500 | </pre> |
| | 4501 | |
| | 4502 | </div> |
| | 4503 | |
| | 4504 | <!-------------------> |
| | 4505 | <div class=entry> |
| | 4506 | |
| | 4507 | Occluder.occludeObj() has a new default implementation. By default, |
| | 4508 | the method now asks the object being tested for occlusion to make the |
| | 4509 | decision, by calling the object's isOccludedBy() method. |
| | 4510 | |
| | 4511 | <p>Thing provides a default implementation of the new isOccludedBy() |
| | 4512 | method, which simply returns nil to indicate that the object is not |
| | 4513 | occluded by the given Occluder. |
| | 4514 | |
| | 4515 | <p>Existing code won't be affected by this change, since any existing |
| | 4516 | Occluder code already overrides isOccludedBy() to make the per-object |
| | 4517 | occlusion decision. The reason for this change is that it's sometimes |
| | 4518 | easier to decide about occlusion in the individual objects rather than |
| | 4519 | in the Occluder; the new default Occluder.occludeObj() makes it easer |
| | 4520 | to write the code that way by providing a pre-defined framework that |
| | 4521 | already works that way. |
| | 4522 | |
| | 4523 | </div> |
| | 4524 | |
| | 4525 | <!-------------------> |
| | 4526 | <div class=entry> |
| | 4527 | |
| | 4528 | In the past, if a Container was used as the indirect object of PUT IN |
| | 4529 | or POUR INTO, the library applied an objOpen precondition to ensure |
| | 4530 | the container was open. The library now applies the objOpen condition |
| | 4531 | only if the actor performing the action isn't itself inside the |
| | 4532 | container. The reason for the objOpen condition is that putting or |
| | 4533 | pouring things into a container requires access to the container's |
| | 4534 | interior, and a container's interior is only reachable from outside |
| | 4535 | the container when the container is open. However, when an actor is |
| | 4536 | inside a container, the actor can reach the inside of the container |
| | 4537 | whether or not the container is open, so there's no need for the |
| | 4538 | objOpen condition. |
| | 4539 | |
| | 4540 | </div> |
| | 4541 | |
| | 4542 | <!-------------------> |
| | 4543 | <div class=entry> |
| | 4544 | |
| | 4545 | Fixture, Component, and Immovable now define custom handlers for PUT |
| | 4546 | BEHIND that are consistent with their handlers for PUT IN, PUT ON, and |
| | 4547 | PUT UNDER. |
| | 4548 | |
| | 4549 | </div> |
| | 4550 | |
| | 4551 | <!-------------------> |
| | 4552 | <div class=entry> |
| | 4553 | |
| | 4554 | On an actor's attempt to take an item that was inside something the |
| | 4555 | actor was already carrying, Actor.tryMakingRoomToHold() formerly |
| | 4556 | double-counted the item's weight in enforcing the actor's carrying |
| | 4557 | limit - it counted the item first for the weight of carrying the new |
| | 4558 | item itself, then again for its contribution to the weight of its old |
| | 4559 | container (because the old container was in the actor's inventory). |
| | 4560 | The routine now correctly counts the weight only once. (The new |
| | 4561 | algorithm uses the whatIfHeldBy() method, which actually tests the |
| | 4562 | proposed new arrangement to calculate the new weight carried and thus |
| | 4563 | yields reliable results no matter what configuration previously |
| | 4564 | existed.) |
| | 4565 | |
| | 4566 | </div> |
| | 4567 | |
| | 4568 | <!-------------------> |
| | 4569 | <div class=entry> |
| | 4570 | |
| | 4571 | TAKE ALL now tries to take everything that's directly in the actor's |
| | 4572 | current "drop destination", <i>or</i> that's directly in the actor's |
| | 4573 | direct container, <i>or</i> that's in any intermediate container |
| | 4574 | between the two. The former behavior was to take everything in the |
| | 4575 | actor's direct location only. This change improves the behavior when |
| | 4576 | the actor is in something like a chair or bed. In these sorts of |
| | 4577 | nested rooms, items dropped usually land in the enclosing room; the |
| | 4578 | new behavior ensures that a TAKE ALL command attempted while in such a |
| | 4579 | location will include items that were just dropped while in the same |
| | 4580 | location. With the former behavior in this situation, TAKE ALL missed |
| | 4581 | the items in the drop location, which was likely to confuse players. |
| | 4582 | |
| | 4583 | </div> |
| | 4584 | |
| | 4585 | <!-------------------> |
| | 4586 | <div class=entry> |
| | 4587 | |
| | 4588 | NonPortable now defines a default weight and bulk of zero. Since |
| | 4589 | these objects aren't meant to be carried or moved around by actors, |
| | 4590 | their weight and bulk are essentially irrelevant; but the previous |
| | 4591 | non-zero defaults occasionally had undesirable side effects in |
| | 4592 | cases where a non-portable was a component of another object or |
| | 4593 | among another object's contents. |
| | 4594 | |
| | 4595 | </div> |
| | 4596 | |
| | 4597 | <!-------------------> |
| | 4598 | <div class=entry> |
| | 4599 | |
| | 4600 | An attempt to give an object to an NPC when the NPC is already holding |
| | 4601 | the object in question is now ruled out as illogical ("Bob already has |
| | 4602 | that"). |
| | 4603 | |
| | 4604 | </div> |
| | 4605 | |
| | 4606 | <!-------------------> |
| | 4607 | <div class=entry> |
| | 4608 | |
| | 4609 | The library now provides commands that let the player control the |
| | 4610 | display of the exits listing in the status line. EXITS ON now turns |
| | 4611 | on <i>both</i> the status line and room description exit listings, and |
| | 4612 | EXITS OFF turns them both off. The new command EXITS STATUS (which |
| | 4613 | can also be entered as EXITS STATUSLINE or EXITS STATUS LINE) turns on |
| | 4614 | the status line exit listing only, and EXITS LOOK turns on the room |
| | 4615 | description exit listing only. |
| | 4616 | |
| | 4617 | <p>In addition, these new commands are now described in the standard |
| | 4618 | instructions. |
| | 4619 | |
| | 4620 | </div> |
| | 4621 | |
| | 4622 | <!-------------------> |
| | 4623 | <div class=entry> |
| | 4624 | |
| | 4625 | The "probabilistic firing" feature of the RandomEventList class is now |
| | 4626 | available in a separate mix-in class, RandomFiringScript. This new |
| | 4627 | class can be mixed into the superclass list of any Script subclass to |
| | 4628 | add the random firing feature. |
| | 4629 | |
| | 4630 | <p>RandomEventList and ShuffledEventList are now based on the new |
| | 4631 | RandomFiringScript. This doesn't change their behavior; existing |
| | 4632 | code based on these classes should continue to work unchanged. |
| | 4633 | |
| | 4634 | </div> |
| | 4635 | |
| | 4636 | <!-------------------> |
| | 4637 | <div class=entry> |
| | 4638 | |
| | 4639 | The SyncEventList class now delegates calls to its scriptDone() method |
| | 4640 | to its master list object. This ensures that any explicit calls to a |
| | 4641 | SyncEventList's scriptDone() method will be handled via the master |
| | 4642 | list, which is consistent with SyncEventList's handling for most of |
| | 4643 | its other methods. |
| | 4644 | |
| | 4645 | </div> |
| | 4646 | |
| | 4647 | <!-------------------> |
| | 4648 | <div class=entry> |
| | 4649 | |
| | 4650 | The library now has a better response to the FOLLOW command if the |
| | 4651 | target NPC departed the player character's present location while the |
| | 4652 | PC was somewhere else. Suppose the PC sees Bob in the living room, |
| | 4653 | then goes to the dining room; while the PC is in the dining room, Bob |
| | 4654 | departs for a third room (due to some scripted activity). The player |
| | 4655 | then returns to the living room. At this point, it's not possible to |
| | 4656 | FOLLOW BOB, since the PC didn't see where Bob went. This much hasn't |
| | 4657 | changed; what's changed is the library's default response if player |
| | 4658 | types FOLLOW BOB in this situation. In the past, the response was |
| | 4659 | "The last place him was the living room," which is true but not very |
| | 4660 | helpful (and a little non sequiturish). Now, the response is "You're |
| | 4661 | not sure where he went from here." |
| | 4662 | |
| | 4663 | </div> |
| | 4664 | |
| | 4665 | <!-------------------> |
| | 4666 | <div class=entry> |
| | 4667 | |
| | 4668 | NominalPlatform now returns its location's effectiveFollowLocation as |
| | 4669 | its own effectiveFollowLocation. A nominal platform isn't meant to be |
| | 4670 | part of the visible structure of the game world, so, for FOLLOW |
| | 4671 | purposes, a character on a nominal platform is effectively in the |
| | 4672 | enclosing room as far as the other characters in the room are |
| | 4673 | concerned. |
| | 4674 | |
| | 4675 | </div> |
| | 4676 | |
| | 4677 | <!-------------------> |
| | 4678 | <div class=entry> |
| | 4679 | |
| | 4680 | A bug in the parser caused possessive pronouns to be treated |
| | 4681 | differently in a TopicTAction when the direct object phrase was |
| | 4682 | missing than when it was provided. For example, ASK BOB ABOUT HIS KEY |
| | 4683 | was treated differently from the abbreviated equivalent A HIS KEY. |
| | 4684 | This has been corrected. |
| | 4685 | |
| | 4686 | </div> |
| | 4687 | |
| | 4688 | <!-------------------> |
| | 4689 | <div class=entry> |
| | 4690 | |
| | 4691 | The parser now drops its preference for untruncated name matches when |
| | 4692 | resolving an object in "global scope," and instead treats truncated |
| | 4693 | and exact name matches on an equal footing in these cases. This |
| | 4694 | change is analogous to the global scope changes for plurals and |
| | 4695 | adjective-ending phrases introduced in 3.0.6q and 3.0.6p. See the <a |
| | 4696 | href='#global_scope_noun_adj'>adjective-ending notes</a> from 3.0.6p |
| | 4697 | for details on what global scope is and why its rules on matching are |
| | 4698 | more lenient. |
| | 4699 | |
| | 4700 | <p>The practical effect of this change is that topic words will now |
| | 4701 | match properly even when there are longer and shorter versions of the |
| | 4702 | same vocabulary defined for various objects. In the past, if one |
| | 4703 | object was defined with a six-letter noun, and another object had a |
| | 4704 | seven-letter noun with the same first six letters as the other object |
| | 4705 | ("coffee" and "coffees", say), the parser filtered out the |
| | 4706 | seven-letter match in favor of the six-letter match, even though both |
| | 4707 | objects ought to be equally valid in global scope. With the change, |
| | 4708 | both objects are now properly kept as possible resolutions when |
| | 4709 | parsing a topic phrase. |
| | 4710 | |
| | 4711 | </div> |
| | 4712 | |
| | 4713 | <!-------------------> |
| | 4714 | <div class=entry> |
| | 4715 | |
| | 4716 | The parser now selects Collective objects instead of their |
| | 4717 | corresponding individuals when matching "all" and "all except |
| | 4718 | <i>list</i>" noun phrases. |
| | 4719 | |
| | 4720 | <p>Whether it's better to select the Collective or the individuals |
| | 4721 | probably varies according to context, since the "right" one is the one |
| | 4722 | the player intends in a particular command, and that will likely vary |
| | 4723 | from one command to the next (and from one player to the next). But |
| | 4724 | the design of the parser requires that we choose one interpretation or |
| | 4725 | the other across the board; context sensitivity isn't an option. Even |
| | 4726 | if context sensitivity were an option, we might still not have enough |
| | 4727 | information to correctly read the player's mind every time. This |
| | 4728 | change - matching the Collective object instead of the individuals - |
| | 4729 | seems more likely to yield intuitive results more of the time than the |
| | 4730 | old behavior. |
| | 4731 | |
| | 4732 | </div> |
| | 4733 | |
| | 4734 | <!-------------------> |
| | 4735 | <div class=entry> |
| | 4736 | |
| | 4737 | The parser now applies the normal filterResolveList() filtering when |
| | 4738 | resolving a target-actor phrase (such as the "bob" in "bob, go |
| | 4739 | north"), the same as it does when resolving other kinds of noun |
| | 4740 | phrases. In the past, the parser omitted this filtering step for |
| | 4741 | target actors, which didn't give objects like Unthings and Collectives |
| | 4742 | a chance to do their special filtering. |
| | 4743 | |
| | 4744 | </div> |
| | 4745 | |
| | 4746 | <!-------------------> |
| | 4747 | <div class=entry> |
| | 4748 | |
| | 4749 | When the player enters a command of the form TAKE ALL FROM |
| | 4750 | <i>iobj</i>, the TakeFrom action now lets the indirect object |
| | 4751 | determine what ALL means. It does this via a new method, |
| | 4752 | getAllForTakeFrom(scopeList). Thing implements this method using |
| | 4753 | almost the same behavior that TakeFrom used in the past: it returns a |
| | 4754 | list of everything in scope that's directly inside 'self' and isn't a |
| | 4755 | component of 'self'. The old behavior simply returned everything in |
| | 4756 | scope that was directly inside the indirect object. |
| | 4757 | |
| | 4758 | <p>ComplexContainer overrides getAllForTakeFrom() to return everything |
| | 4759 | that's in scope and that's directly in (a) the sub-container or |
| | 4760 | sub-surface, if the object has either, or (b) the sub-rear-surface or |
| | 4761 | sub-underside, if the object doesn't have a sub-container or |
| | 4762 | sub-surface; and as with Thing's version, this list is then limited to |
| | 4763 | objects that aren't components of their direct containers. Note that |
| | 4764 | if there's both a sub-surface <i>and</i> a sub-container, the method |
| | 4765 | will return everything that's in <i>either</i> of these; and likewise |
| | 4766 | with the sub-rear-surface and sub-underside. |
| | 4767 | |
| | 4768 | <p>This change is designed primarily to improve the behavior for |
| | 4769 | ComplexContainers, which wasn't ideal under the old mechanism, as it |
| | 4770 | only returned the complex container's sub-components, which are |
| | 4771 | internal implementation objects that are meant to be invisible to the |
| | 4772 | player. Clearly, in the case a complex container, it's the contents |
| | 4773 | of the inner containers that are of interest in TAKE ALL FROM. This |
| | 4774 | change also makes it easier to customize the TAKE ALL FROM behavior |
| | 4775 | for your own special containers, since it gives the container a chance |
| | 4776 | to determine what ALL means in context. |
| | 4777 | |
| | 4778 | <p>The grammar class VagueContainerNounPhraseProd, which matches |
| | 4779 | locational phrases such as "all in box" and "the one in the box," also |
| | 4780 | uses the new method to determine which objects are involved. This |
| | 4781 | provides the same improvement for commands such as LOOK AT EVERYTHING |
| | 4782 | IN THE BOX when a complex container or other special container is |
| | 4783 | involved. |
| | 4784 | |
| | 4785 | </div> |
| | 4786 | |
| | 4787 | <!-------------------> |
| | 4788 | <div class=entry> |
| | 4789 | |
| | 4790 | The NounPhraseWithVocab method getVocabMatchList() now takes an extra |
| | 4791 | parameter, specifying any extra flags that should be OR'd into the |
| | 4792 | ResolveInfo flags for the items in the match list. In the past, the |
| | 4793 | version of the method in the adjective-phrase subclasses took the |
| | 4794 | extra flags parameter, but the base class method didn't, which made it |
| | 4795 | difficult to create classes for production types that could define |
| | 4796 | grammars with either the adjective or noun subproductions. |
| | 4797 | |
| | 4798 | </div> |
| | 4799 | |
| | 4800 | <!-------------------> |
| | 4801 | <div class=entry> |
| | 4802 | |
| | 4803 | In the past, if the player typed STAND while the PC was sitting or |
| | 4804 | lying on an object derived from BasicPlatform, the library simply made |
| | 4805 | the PC stand up, remaining on the platform. In particular, the |
| | 4806 | library didn't bother checking the allowedPostures property to see if |
| | 4807 | the platform actually allowed the 'standing' posture; it simply |
| | 4808 | assumed that standing was allowed on any platform. This didn't easily |
| | 4809 | allow for things like booths with limited headroom. The |
| | 4810 | makeStandingUp method of BasicPlatform now checks allowedPostures |
| | 4811 | property, to make sure that 'standing' is listed. If 'standing' isn't |
| | 4812 | among the allowed postures, the makeStandingUp method now inherits the |
| | 4813 | base class handling, which removes the actor from the nested room and |
| | 4814 | sets the actor's posture to the default for the enclosing location. |
| | 4815 | This will produce better results in most cases, since the natural |
| | 4816 | implication of STAND UP when in a vertically confined space would be |
| | 4817 | to remove oneself from the space. |
| | 4818 | |
| | 4819 | </div> |
| | 4820 | |
| | 4821 | <!-------------------> |
| | 4822 | <div class=entry> |
| | 4823 | |
| | 4824 | It's now possible to control the order in which preconditions are |
| | 4825 | executed, at the level of the individual preconditions. The new |
| | 4826 | PreCondition property preCondOrder gives the order of execution of a |
| | 4827 | given precondition. The default for most types of preconditions is |
| | 4828 | 100; for TouchObjCondition (and thus for touchObj), it's 200, which |
| | 4829 | means that touchObj conditions will execute after other conditions by |
| | 4830 | default. |
| | 4831 | |
| | 4832 | <p>It's occasionally useful to be able to fine-tune precondition order |
| | 4833 | because preconditions can sometimes interfere with one another. This |
| | 4834 | is particularly a problem with implied actions that require the actor |
| | 4835 | to be in a particular posture or location, because many of the |
| | 4836 | standard preconditions can move the actor around as a side effect. |
| | 4837 | For example, a doorOpen condition could execute an implied STAND as |
| | 4838 | part of its implied OPEN DOOR; if another precondition requires the |
| | 4839 | actor being to be sitting, its effect would be undone if the doorOpen |
| | 4840 | were executed second. We can safely STAND and OPEN DOOR first, then |
| | 4841 | SIT DOWN second, because we'll still satisfy the doorOpen condition |
| | 4842 | even though we're no longer standing when we're done. |
| | 4843 | |
| | 4844 | <p>In addition to the new preCondOrder ordering, the default ordering |
| | 4845 | has changed for two-object verbs (those with direct and indirect |
| | 4846 | objects). By default, the direct object preconditions are now |
| | 4847 | executed first, followed by the indirect preconditions; in the past |
| | 4848 | this order was reversed. This is only the default order - the |
| | 4849 | preCondOrder takes precedence. That is, the action builds a list |
| | 4850 | consisting of the direct object preconditions followed by the indirect |
| | 4851 | object preconditions, then sorts that list in ascending order of |
| | 4852 | preCondOrder, preserving the existing relative order of objects with |
| | 4853 | the same preCondOrder. |
| | 4854 | |
| | 4855 | </div> |
| | 4856 | |
| | 4857 | <!-------------------> |
| | 4858 | <div class=entry> |
| | 4859 | |
| | 4860 | adv3.h now defines a couple of new templates for your convenience: |
| | 4861 | |
| | 4862 | <p><pre> |
| | 4863 | SyncEventList template ->masterObject inherited; |
| | 4864 | Hint template 'hintText' [referencedGoals]? |
| | 4865 | </pre> |
| | 4866 | |
| | 4867 | </div> |
| | 4868 | |
| | 4869 | <!-------------------> |
| | 4870 | <div class=entry> |
| | 4871 | |
| | 4872 | When an Unthing is used as a possessive or locational qualifier ("the |
| | 4873 | key in the unthing" or "the unthing's key," for example), the parser |
| | 4874 | now shows the Unthing's "not here" message. In the past, the parser |
| | 4875 | showed the same default messages for an Unthing as for any other |
| | 4876 | object, using wording like "The unthing doesn't appear to have that" |
| | 4877 | or "You see no key in the unthing." This wording was incongruous for |
| | 4878 | Unthings because an Unthing represents the absence of an object, and |
| | 4879 | hence an Unthing can't "appear" to have or contain - or even not have |
| | 4880 | or not contain - anything. Showing the Unthing's "not here" message |
| | 4881 | yields more sensible results. |
| | 4882 | |
| | 4883 | </div> |
| | 4884 | |
| | 4885 | <!-------------------> |
| | 4886 | <div class=entry> |
| | 4887 | |
| | 4888 | An Unthing now responds to LISTEN and SMELL commands with the same |
| | 4889 | message it uses for EXAMINE (by default, "You don't see that here"). |
| | 4890 | This applies even if the Unthing is distant or obscured. (In the |
| | 4891 | past, the inherited Decoration messages for these verbs were used.) |
| | 4892 | |
| | 4893 | </div> |
| | 4894 | |
| | 4895 | <!-------------------> |
| | 4896 | <div class=entry> |
| | 4897 | |
| | 4898 | The English library provides a new template for Unthing: |
| | 4899 | |
| | 4900 | <p><pre> |
| | 4901 | Unthing template 'vocabWords' 'name' @location? 'notHereMsg'?; |
| | 4902 | </pre> |
| | 4903 | |
| | 4904 | </div> |
| | 4905 | |
| | 4906 | <!-------------------> |
| | 4907 | <div class=entry> |
| | 4908 | |
| | 4909 | The finishGame() function now updates the global turn counter to |
| | 4910 | reflect any turn currently in progress, or, when called from a daemon |
| | 4911 | or fuse, the turn the player has already completed. In the past, the |
| | 4912 | turn counter displayed in finishGame() didn't reflect the turn in |
| | 4913 | progress that triggered the call to finishGame(). Internally, a turn |
| | 4914 | isn't counted in the global turn counter until it's finished; but from |
| | 4915 | the player's perspective, a turn should count as soon as it starts. |
| | 4916 | This change ensures that the count that finishGame() displays is |
| | 4917 | consistent with the player's expectations. |
| | 4918 | |
| | 4919 | </div> |
| | 4920 | |
| | 4921 | <!-------------------> |
| | 4922 | <div class=entry> |
| | 4923 | |
| | 4924 | A Lockable that's also an Openable no longer reports its |
| | 4925 | locked/unlocked status when the object is open. By default, an |
| | 4926 | Openable must be closed in order to be locked, so if it's open, it's |
| | 4927 | always unlocked. This means that the locked/unlocked status is |
| | 4928 | effectively redundant information when the object is open. |
| | 4929 | |
| | 4930 | <p>By way of implementation, the Lockable class has a new method, |
| | 4931 | lockStatusReportable, that indicates whether or not the lock status is |
| | 4932 | worth mentioning in the object's current state. (This doesn't |
| | 4933 | supersede lockStatusObvious, but rather complements it. |
| | 4934 | lockStatusObvious still indicates whether or not the lock status is |
| | 4935 | visually apparent; lockStatusReportable indicates whether it's worth |
| | 4936 | mentioning from an aesthetic point of view.) Lockable defers to any |
| | 4937 | mix-in class that provides the method, and Openable takes advantage of |
| | 4938 | this by providing an implementation of the method that returns true if |
| | 4939 | the object is closed, nil if it's open. |
| | 4940 | |
| | 4941 | </div> |
| | 4942 | |
| | 4943 | <!-------------------> |
| | 4944 | <div class=entry> |
| | 4945 | |
| | 4946 | Door and SecretDoor are now based on a new common base class, |
| | 4947 | BasicDoor. The new BasicDoor class defines the core internal behavior |
| | 4948 | of a door: a travel connector object that can be open or closed, that |
| | 4949 | allows travel only when open, and that can have two objects linked |
| | 4950 | together to represent the two sides of the door. |
| | 4951 | |
| | 4952 | <p>The relationship between BasicDoor and Door is analogous to that |
| | 4953 | between BasicOpenable and Openable. BasicDoor defines the internal |
| | 4954 | behavior, while Door adds handling for user commands to manipulate the |
| | 4955 | door (in particular, OPEN, CLOSE, LOCK, UNLOCK). |
| | 4956 | |
| | 4957 | <p>This change doesn't affect the functionality of Door; it merely |
| | 4958 | rearranges the code for Door internally by moving a few methods to the |
| | 4959 | new BasicDoor base class. SecretDoor isn't much affected, either, but |
| | 4960 | does now add support for remembering a recent traversal for |
| | 4961 | disambiguation purposes, as Door did in the past (and still does). No |
| | 4962 | changes should be needed in existing game code. |
| | 4963 | |
| | 4964 | <p>The main benefits of this change are that it makes SecretDoor |
| | 4965 | behave more consistently with the Door class, and it provides a single |
| | 4966 | base class for all door-like objects. In addition, the new BasicDoor |
| | 4967 | class makes it easier to define custom doors with special controls, |
| | 4968 | since it has all of the necessary functionality but doesn't make any |
| | 4969 | assumptions about handling commands. |
| | 4970 | |
| | 4971 | </div> |
| | 4972 | |
| | 4973 | <!-------------------> |
| | 4974 | <div class=entry> |
| | 4975 | |
| | 4976 | BasicDoor.noteRemoteOpen() now calls a new method, |
| | 4977 | describeRemoteOpen(), to generate the message describing the change. |
| | 4978 | This makes it easier to override the message for a door, since you can |
| | 4979 | simply display the custom message without having to worry about the |
| | 4980 | sense context. |
| | 4981 | |
| | 4982 | </div> |
| | 4983 | |
| | 4984 | <!-------------------> |
| | 4985 | <div class=entry> |
| | 4986 | |
| | 4987 | The Enterable and Exitable classes no longer accept the GO THROUGH |
| | 4988 | command. In the past, these classes did accept GO THROUGH as |
| | 4989 | synonymous with travel, but this became undesirable when the |
| | 4990 | EntryPortal and ExitPortal classes were added. Enterable and Exitable |
| | 4991 | are meant for things like buildings, where ENTER or EXIT make sense |
| | 4992 | but not GO THROUGH; EntryPortal and ExitPortal are for things like |
| | 4993 | doors and passages, where you can equally well ENTER/EXIT them or GO |
| | 4994 | THROUGH them. |
| | 4995 | |
| | 4996 | </div> |
| | 4997 | |
| | 4998 | <!-------------------> |
| | 4999 | <div class=entry> |
| | 5000 | |
| | 5001 | The AutoClosingDoor class has a new method, reportAutoClose(), that |
| | 5002 | generates the message that mentions that the door closed behind |
| | 5003 | whoever just went through it. The TravelVia action() handler calls |
| | 5004 | reportAutoClose() after it automatically closes the door; by default, |
| | 5005 | reportAutoClose() shows the standard library message |
| | 5006 | &doorClosesBehindMsg. In the past, the action() handler simply |
| | 5007 | showed the same library message itself, rather than calling out to a |
| | 5008 | separate method. |
| | 5009 | |
| | 5010 | <p>The purpose of this change is to make it easier to customize how |
| | 5011 | the auto-closing is reported, or whether it's reported at all. If |
| | 5012 | you want the door to close silently, without any mention that it |
| | 5013 | closed, simply override reportAutoClose() to do nothing. |
| | 5014 | |
| | 5015 | </div> |
| | 5016 | |
| | 5017 | <!-------------------> |
| | 5018 | <div class=entry> |
| | 5019 | |
| | 5020 | By default, a FireSource object now removes itself from consideration |
| | 5021 | as a default indirect object for the BurnWith action if it's not |
| | 5022 | already lit. This ensures that the library won't (for example) |
| | 5023 | attempt to use an unlit candle as a default source of fire to light |
| | 5024 | another candle. In the past, under certain circumstances, the library |
| | 5025 | could cause a stack overflow by trying to light one candle with |
| | 5026 | another, which it tried to light with the first, and so on. This |
| | 5027 | change ensures that a fire source will only be chosen as the default |
| | 5028 | indirect object for BurnWith if it's already lit. |
| | 5029 | |
| | 5030 | <p>(Matchstick objects, of course, aren't affected by this change, |
| | 5031 | since they can light themselves on fire independently. Matchsticks |
| | 5032 | thus remain valid as default choices for BurnWith even when they're |
| | 5033 | unlit.) |
| | 5034 | |
| | 5035 | </div> |
| | 5036 | |
| | 5037 | <!-------------------> |
| | 5038 | <div class=entry> |
| | 5039 | |
| | 5040 | The Wearable class now sets an elevated likelihood (via logicalRank()) |
| | 5041 | for a REMOVE (or TAKE OFF or DOFF) command when the object is being |
| | 5042 | worn. This helps avoid disambiguation prompts for these commands. |
| | 5043 | |
| | 5044 | </div> |
| | 5045 | |
| | 5046 | <!-------------------> |
| | 5047 | <div class=entry> |
| | 5048 | |
| | 5049 | When a Hidden object is discovered (via its 'discover()' method), the |
| | 5050 | object now marks itself and its contents as having been seen by the |
| | 5051 | player character, assuming they're within sight at the time the object |
| | 5052 | is discovered. |
| | 5053 | |
| | 5054 | </div> |
| | 5055 | |
| | 5056 | <!-------------------> |
| | 5057 | <div class=entry> |
| | 5058 | |
| | 5059 | The new RoomPart methods moveIntoAdd(room) and moveOutOf(room) make it |
| | 5060 | easier to dynamically change a room's set of RoomPart objects. In the |
| | 5061 | past, there was no straightforward way to change a room's RoomParts |
| | 5062 | dynamically; these new methods make it easy by making the necessary |
| | 5063 | updates to the affected room's properties. |
| | 5064 | |
| | 5065 | </div> |
| | 5066 | |
| | 5067 | <!-------------------> |
| | 5068 | <div class=entry> |
| | 5069 | |
| | 5070 | Room.getExtraScopeItems() now adds the room's floor to scope only if |
| | 5071 | the actor is directly in the room. In the past, this routine added |
| | 5072 | the floor to scope unconditionally. The rationale of adding the floor |
| | 5073 | to scope is that an actor standing in a room is aware that there's a |
| | 5074 | floor there simply by virtue of standing on it - but that rationale |
| | 5075 | only holds when the actor is actually standing on the floor (or |
| | 5076 | sitting on it, or whatever), and that's only the case when the actor |
| | 5077 | is actually directly in the room. If the actor is in a connected |
| | 5078 | room, or inside a nested room within the outer room, then in most |
| | 5079 | cases the actor isn't actually in contact with the floor. |
| | 5080 | |
| | 5081 | <p>Similarly, NestedRoom.getExtraScopeItems() now adds the nested room |
| | 5082 | to scope only when the actor is directly in the nested room. The |
| | 5083 | rationale is the same as for the floor in an outer room. |
| | 5084 | |
| | 5085 | </div> |
| | 5086 | |
| | 5087 | <!-------------------> |
| | 5088 | <div class=entry> |
| | 5089 | |
| | 5090 | The TALK TO command now treats talking to oneself as illogical; in |
| | 5091 | the past, it was merely considered improbable. |
| | 5092 | |
| | 5093 | <p>A side effect of this change is that the intransitive |
| | 5094 | conversational commands (HELLO, GOODBYE, YES, NO) won't try to make |
| | 5095 | the PC talk to itself by default. In version 3.0.8, these commands |
| | 5096 | were enhanced to choose the same default interlocutor as TALK TO would |
| | 5097 | when the most recent interlocutor is no longer present. This had the |
| | 5098 | undesirable effect of choosing the PC as the default target when no |
| | 5099 | other actors were present. Now that TALK TO won't choose the PC as |
| | 5100 | the default actor, HELLO and the rest won't do so, either. |
| | 5101 | |
| | 5102 | </div> |
| | 5103 | |
| | 5104 | <!-------------------> |
| | 5105 | <div class=entry> |
| | 5106 | |
| | 5107 | In past versions, the InConversationState's "boredom counter" was |
| | 5108 | handled inconsistently in certain cases. In particular, when an NPC |
| | 5109 | initiated a conversation, it took one more turn for the NPC to become |
| | 5110 | bored than it took when the PC initiated the conversation. This has |
| | 5111 | been corrected. |
| | 5112 | |
| | 5113 | </div> |
| | 5114 | |
| | 5115 | <!-------------------> |
| | 5116 | <div class=entry> |
| | 5117 | |
| | 5118 | The library now uses the "identity" object when setting a pronoun |
| | 5119 | antecedent in Actor.setPronounObj(). This ensures that when an |
| | 5120 | internal program object is being manipulated, and that object |
| | 5121 | generates a pronoun antecedent, any subsequent command reference to |
| | 5122 | the antecedent will properly refer to the main simulation object |
| | 5123 | associated with the internal implementation object. For example, this |
| | 5124 | ensures that when a ComplexComponent is manipulated, subsequent |
| | 5125 | references to "it" refer back to its ComplexContainer parent. |
| | 5126 | |
| | 5127 | </div> |
| | 5128 | |
| | 5129 | <!-------------------> |
| | 5130 | <div class=entry> |
| | 5131 | |
| | 5132 | A library bug introduced in version 3.0.8 caused a run-time error when |
| | 5133 | the player attempted to address a command to another actor and used a |
| | 5134 | pronoun to identify the target actor (as in HIM, GO NORTH or ASK HIM |
| | 5135 | TO GO NORTH - the first phrasing is awkward enough that most players |
| | 5136 | wouldn't think to use it, but the ASK phrasing is natural enough that |
| | 5137 | players might try it). This has been corrected. |
| | 5138 | |
| | 5139 | </div> |
| | 5140 | |
| | 5141 | <!-------------------> |
| | 5142 | <div class=entry> |
| | 5143 | |
| | 5144 | A bug in ThingOrTopicMatchTopic.isMatchPossible caused a run-time |
| | 5145 | error under certain conditions. This has been fixed. |
| | 5146 | |
| | 5147 | </div> |
| | 5148 | |
| | 5149 | <!-------------------> |
| | 5150 | <div class=entry> |
| | 5151 | |
| | 5152 | The <.roomname> style tag now adds a newline after the room name |
| | 5153 | text; this is in lieu of the <.roomdesc> style tag showing a |
| | 5154 | newline before the room description, as was done in the past. The |
| | 5155 | newline is really part of the room name formatting, to ensure that the |
| | 5156 | room name goes on a line by itself. This change won't affect most |
| | 5157 | existing games, since the usual LOOK AROUND format shows the room name |
| | 5158 | followed by the long description; but the change does ensure that a |
| | 5159 | room description won't have an extra leading newline in cases where |
| | 5160 | the room name isn't displayed. |
| | 5161 | |
| | 5162 | </div> |
| | 5163 | |
| | 5164 | <!-------------------> |
| | 5165 | <div class=entry> |
| | 5166 | |
| | 5167 | In Intangible, Fixture, Decoration, Room, and RoomPart, |
| | 5168 | hideFromDefault() now simply returns nil. (In the past, these classes |
| | 5169 | defined hideFromDefault() as returning the inherited value, which |
| | 5170 | didn't have the desired effect of bypassing the inherited call (from |
| | 5171 | Thing.hideFromDefault()) to self.hideFromAll(). These classes |
| | 5172 | override hideFromAll(), but they want to use separate handling for |
| | 5173 | hideFromDefault(). The old override didn't correctly accomplish this |
| | 5174 | because of the way the base Thing implementation of hideFromDefault() |
| | 5175 | is written.) |
| | 5176 | |
| | 5177 | </div> |
| | 5178 | |
| | 5179 | <!-------------------> |
| | 5180 | <div class=entry> |
| | 5181 | |
| | 5182 | The library now responds to commands like THROW ME, THROW ME AT |
| | 5183 | <i>something</i>, and THROW ME TO <i>something</i> with an appropriate |
| | 5184 | failure message. (In the past, these commands were actually allowed, |
| | 5185 | and used the standard THROW handling, which obviously isn't |
| | 5186 | desirable.) |
| | 5187 | |
| | 5188 | </div> |
| | 5189 | |
| | 5190 | <!-------------------> |
| | 5191 | <div class=entry> |
| | 5192 | |
| | 5193 | The library now accepts SIT and LIE (and, equivalently, SIT DOWN and |
| | 5194 | LIE DOWN) as intransitive verbs. In the past, these were defined as |
| | 5195 | missing-direct-object forms of the transitive commands SIT ON and LIE |
| | 5196 | ON, which meant that the library tried to find a default direct |
| | 5197 | object. This had the undesirable effect of making an actor who was |
| | 5198 | already sitting/lying automatically stand up and sit/lie on some other |
| | 5199 | suitable object in the room, which as a last resort was the default |
| | 5200 | floor. The new intransitive verbs check to see if the actor is |
| | 5201 | already sitting/lying, and if so, simply generate an error message to |
| | 5202 | this effect. If the actor isn't already sitting/lying, the new |
| | 5203 | commands proceed as before: they look for a suitable default object, |
| | 5204 | and sit/lie on that. |
| | 5205 | |
| | 5206 | <p>As part of this change, the intransitive SIT DOWN and LIE DOWN |
| | 5207 | phrasings no longer have [badness], so the parser will match them |
| | 5208 | as full-fledged intransitive phrasings. |
| | 5209 | |
| | 5210 | </div> |
| | 5211 | |
| | 5212 | <!-------------------> |
| | 5213 | <div class=entry> |
| | 5214 | |
| | 5215 | There are two small changes to the action message processor. |
| | 5216 | |
| | 5217 | <p>First, it's now possible to define a message method on a Thing that |
| | 5218 | takes no arguments, even if the message normally does require |
| | 5219 | arguments. This makes it more syntactically convenient to define |
| | 5220 | simple message string or property-redirect methods that require some |
| | 5221 | small chunk of code, but which don't need any of the argument values |
| | 5222 | that are normally sent to the message method. For example, we can now |
| | 5223 | write this: |
| | 5224 | |
| | 5225 | <p><pre> |
| | 5226 | notImportantMsg = (myGenericMsg) |
| | 5227 | </pre> |
| | 5228 | |
| | 5229 | <p>instead of this (which was formerly required): |
| | 5230 | |
| | 5231 | <p><pre> |
| | 5232 | notImportantMsg(obj) { return myGenericMsg; } |
| | 5233 | </pre> |
| | 5234 | |
| | 5235 | <p>Second, these sorts of message methods can now return nil to |
| | 5236 | indicate that they don't want to provide the message after all. This |
| | 5237 | is useful when an object only wants to override a library message when |
| | 5238 | it's in a certain state. It's also useful when an object wants to |
| | 5239 | provide the message only when that object is in a particular role in a |
| | 5240 | two-object command (i.e., a command with both a direct and indirect |
| | 5241 | object). Recall that when a command involves both a direct and an |
| | 5242 | indirect object, the message processor asks both of the objects for an |
| | 5243 | override; this new capability lets the objects be selective about |
| | 5244 | providing an override according to their actual roles in the command. |
| | 5245 | |
| | 5246 | <p>For example, suppose you want your 'vase' object to override the |
| | 5247 | "not a container" message for PUT IN, but only when the vase is the |
| | 5248 | indirect object of the PUT IN, not when it's being put somewhere |
| | 5249 | itself. To do this, you could write vase.notAContainer like so: |
| | 5250 | |
| | 5251 | <p><pre> |
| | 5252 | notAContainerMsg = (gIobj == self |
| | 5253 | ? 'The vase\'s opening is too small.' : nil) |
| | 5254 | </pre> |
| | 5255 | |
| | 5256 | <p>The library provides a pair of new macros that simplifies the |
| | 5257 | syntax for that kind of conditional message override: dobjMsg() |
| | 5258 | and iobjMsg(). These macros simply test to see if gDobj or gIobj |
| | 5259 | (respectively) equal 'self'; if so, they return the argument, and |
| | 5260 | if not they return nil. |
| | 5261 | |
| | 5262 | </div> |
| | 5263 | |
| | 5264 | <!-------------------> |
| | 5265 | <div class=entry> |
| | 5266 | |
| | 5267 | The statusLine object has a new method, setColorScheme(), that sets up |
| | 5268 | the status line's colors. This change won't affect any existing code, |
| | 5269 | since it's just a minor internal reorganization, and the behavior is |
| | 5270 | the same as it used to be. The point of the change is that it's now |
| | 5271 | easier to customize the status line color scheme, since you only have |
| | 5272 | to override this one method, and the only thing the override has to |
| | 5273 | do is to write out a <BODY> tag with the desired color scheme. |
| | 5274 | |
| | 5275 | </div> |
| | 5276 | |
| | 5277 | <!-------------------> |
| | 5278 | <div class=entry> |
| | 5279 | |
| | 5280 | The English tokenizer now recognizes upper-case "'S" (apostrophe-S) |
| | 5281 | suffixes as equivalent to the lower-case version. In the past, the |
| | 5282 | tokenizer only recognized this token in lower-case. |
| | 5283 | |
| | 5284 | </div> |
| | 5285 | |
| | 5286 | <!-------------------> |
| | 5287 | <div class=entry> |
| | 5288 | |
| | 5289 | In the English version, the SpecialTopic matcher now specifically |
| | 5290 | rejects matches for several "weak" topic command inputs: I, L, and |
| | 5291 | LOOK. The matcher only rejects the matches when these are the |
| | 5292 | <i>only</i> thing the player typed. If the player types just "I", for |
| | 5293 | example, they probably intend to enter an INVENTORY command rather |
| | 5294 | than to select a special topic that happens to have "I" among its |
| | 5295 | tokens (as in "tell him I don't know"). |
| | 5296 | |
| | 5297 | </div> |
| | 5298 | |
| | 5299 | <!-------------------> |
| | 5300 | <div class=entry> |
| | 5301 | |
| | 5302 | In the English grammar, plurals are now accepted as possessive |
| | 5303 | qualifier phrases (as in "the women's books"). When a plural |
| | 5304 | possessive is used to qualify a plural phrase ("the women's books"), |
| | 5305 | the parser resolves the overall phrase to all of the in-scope objects |
| | 5306 | matching the base noun phrase that are owned by anyone matching the |
| | 5307 | qualifier phrase. When a plural possessive qualifies a singular noun |
| | 5308 | ("the women's book"), the parser makes the same initial selection, but |
| | 5309 | then prompts for more information if the selection includes more than |
| | 5310 | one object. |
| | 5311 | |
| | 5312 | </div> |
| | 5313 | |
| | 5314 | <!-------------------> |
| | 5315 | <div class=entry> |
| | 5316 | |
| | 5317 | When a possessive phrase is used to qualify a noun phrase, and the |
| | 5318 | result is ambiguous, the parser now filters the list of possible |
| | 5319 | matches using the filterResolveList() mechanism. This ensures that |
| | 5320 | special objects - especially Unthings and Collectives - are treated |
| | 5321 | the same in this case as they are in other situations. In the past, |
| | 5322 | for example, the parser included Unthings in a disambiguation list if |
| | 5323 | the Unthings matched the vocabulary of a possessive qualifier; this |
| | 5324 | was undesirable because Unthings aren't meant to be treated as actual, |
| | 5325 | present objects from the player character's perspective. |
| | 5326 | |
| | 5327 | </div> |
| | 5328 | |
| | 5329 | <!-------------------> |
| | 5330 | <div class=entry> |
| | 5331 | |
| | 5332 | In the past, if the player responded to a disambiguation prompt with a |
| | 5333 | possessive phrase, and the specified possessor didn't own any of the |
| | 5334 | objects in the original disambiguation list, the parser responded with |
| | 5335 | a message like "Bob does not appear to have any such thing." This was |
| | 5336 | inconsistent with the way disambiguation responses are treated for |
| | 5337 | other types of responses. Now, an inappropriate possessive response |
| | 5338 | receives the same message as would a random adjective that doesn't |
| | 5339 | apply to any of the original possibilities: "That was not one of the |
| | 5340 | choices." |
| | 5341 | |
| | 5342 | </div> |
| | 5343 | |
| | 5344 | <!-------------------> |
| | 5345 | <div class=entry> |
| | 5346 | |
| | 5347 | The English version of the library now lets the Action determine which |
| | 5348 | message to use when there's nothing in scope matching a noun phrase in |
| | 5349 | a command. In the past, the parser always used the "noMatch" message, |
| | 5350 | the default wording of which was "You see no <i>noun phrase</i> here." |
| | 5351 | This was sometimes jarring for commands that generally refer to |
| | 5352 | non-visual objects, such as LISTEN TO or SMELL. With this change, the |
| | 5353 | library now calls the Action (via its new method noMatch()) to |
| | 5354 | determine which message to show. Most actions simply invoke the new |
| | 5355 | message method noMatchCannotSee(), which shows the same message as |
| | 5356 | before. The LISTEN and SMELL actions override noMatch() to call the |
| | 5357 | new message method noMatchNowAware(), which shows the message "You are |
| | 5358 | not aware of any <i>noun phrase</i> here." The new wording should be |
| | 5359 | more natural when the noun phrase is something inherently non-visual. |
| | 5360 | |
| | 5361 | <p>(It would be even better if the library could decide based on the |
| | 5362 | noun phrase itself whether the noun phrase refers to something visual |
| | 5363 | or not, since the player could just as well try to EXAMINE THE |
| | 5364 | SULFUROUS ODOR or TAKE THE BEEPING NOISE. Unfortunately, it's |
| | 5365 | effectively impossible to do this, since the true meaning of the error |
| | 5366 | message is that the parser can't determine what the noun phrase |
| | 5367 | actually refers to. We don't want to say that outright, of course, |
| | 5368 | since that would detract from the player's sense of immersion in the |
| | 5369 | game world by calling attention to the parser and its limitations, so |
| | 5370 | the best we can do is to find a heuristic that works most of the time. |
| | 5371 | The addition of the per-action customization improves on the old |
| | 5372 | scheme and should make incongruous cases relatively rare.) |
| | 5373 | |
| | 5374 | </div> |
| | 5375 | |
| | 5376 | <!-------------------> |
| | 5377 | <div class=entry> |
| | 5378 | |
| | 5379 | The parser's algorithm for choosing grammar matches has been |
| | 5380 | fine-tuned to handle cases with truncated words and adjective-ending |
| | 5381 | phrases a little better, particularly in commands involving multiple |
| | 5382 | objects. In some cases, when presented with a two-object command |
| | 5383 | (e.g., PUT X IN Y) in which one of the object phrases failed to match |
| | 5384 | any in-scope objects, for the <i>other</i> phrase, the parser formerly |
| | 5385 | chose a noun-ending phrase over an adjective-ending phrase, even if |
| | 5386 | the adjective-ending version matched an object in scope and the |
| | 5387 | noun-ending version didn't. This sometimes yielded odd "you don't see |
| | 5388 | that" messages that named the object that actually <i>was</i> in |
| | 5389 | scope, from the player's perspective. This change should improve |
| | 5390 | the behavior in situations like this. |
| | 5391 | |
| | 5392 | </div> |
| | 5393 | |
| | 5394 | <!-------------------> |
| | 5395 | <div class=entry> |
| | 5396 | |
| | 5397 | In the English library, the code that tries to figure out whether to |
| | 5398 | use "a" and "an" for an object's aName now ignores any leading HTML |
| | 5399 | tags in the object's base name. This is useful for objects with |
| | 5400 | aName strings such as "<i>Apple County Times</i>". |
| | 5401 | |
| | 5402 | <p>In addition, the code now specially recognizes names that start |
| | 5403 | with one-letter words (such as "X-ray" or "<q>L</q> |
| | 5404 | button"), and assumes they're pronounced by saying the name of the |
| | 5405 | letter. So, for example, "X-ray" turns into "an X-ray," since the "X" |
| | 5406 | is pronounced as "ex." |
| | 5407 | |
| | 5408 | </div> |
| | 5409 | |
| | 5410 | <!-------------------> |
| | 5411 | <div class=entry> |
| | 5412 | |
| | 5413 | The English library now accepts SET as a synonym for PUT in the |
| | 5414 | commands PUT DOWN, PUT ON, PUT IN, PUT UNDER, and PUT BEHIND. |
| | 5415 | |
| | 5416 | <p>SET is also now accepted as a single-object verb. When applied to |
| | 5417 | a Thing, the library assumes the intention is SET <i>thing</i> ON |
| | 5418 | <i>something</i>, and prompts for the other object. When applied to a |
| | 5419 | Settable, the library assumes the intention is SET <i>settable</i> TO |
| | 5420 | <i>setting</i>, and prompts for the setting. |
| | 5421 | |
| | 5422 | <p>Note that the single-object form (simply SET <i>dobj</i>) could be |
| | 5423 | useful all by itself in some cases: SET ALARM, for example. For such |
| | 5424 | cases, you can simply define a custom dobjFor(Set) for the object. |
| | 5425 | |
| | 5426 | </div> |
| | 5427 | |
| | 5428 | <!-------------------> |
| | 5429 | <div class=entry> |
| | 5430 | |
| | 5431 | In the English library, L is now accepted as a synonym for LOOK in the |
| | 5432 | various forms of the LOOK UP and LOOK FOR commands: L UP topic IN |
| | 5433 | object, L topic UP IN object, L FOR topic, etc. |
| | 5434 | |
| | 5435 | </div> |
| | 5436 | |
| | 5437 | <!-------------------> |
| | 5438 | <div class=entry> |
| | 5439 | |
| | 5440 | In the English library, THROW <i>iobj</i> <i>dobj</i> is now accepted |
| | 5441 | as a synonym for THROW <i>dobj</i> TO <i>iobj</i>, allowing phrasing |
| | 5442 | like THROW BOB THE BALL. |
| | 5443 | |
| | 5444 | <p>In addition, THROW <i>obj</i> <i>direction</i> (as in THROW BOOK |
| | 5445 | EAST) is now accepted, via the new action ThrowDir. The default |
| | 5446 | handling for ThrowDir (in Thing) is simply to display a message |
| | 5447 | essentially explaining that the proper command is THROW AT: "You need |
| | 5448 | to be more specific about what you want to throw the book at." If the |
| | 5449 | phrasing is THROW <i>obj</i> DOWN or THROW DOWN <i>obj</i>, though, we |
| | 5450 | use the same response we use for THROW AT FLOOR ("You should just put |
| | 5451 | it down instead"). |
| | 5452 | |
| | 5453 | </div> |
| | 5454 | |
| | 5455 | <!-------------------> |
| | 5456 | <div class=entry> |
| | 5457 | |
| | 5458 | The parser's grammar ranking mechanism has a new ranking criterion: |
| | 5459 | "phrasing weakness." This is an arbitrary numeric value that the |
| | 5460 | language module can use to rank particular phrasings as relatively |
| | 5461 | weak, which means that they're less likely to be valid matches. |
| | 5462 | |
| | 5463 | <p>The English grammar uses this new criterion to mark phrasings as |
| | 5464 | weak when they involve two object phrases with no prepositional marker |
| | 5465 | and no qualifier word - things like GIVE BOB BOOK. These phrasings |
| | 5466 | are weak because they could be interpreted as a single object with a |
| | 5467 | missing phrase instead of two objects - if the wording were GIVE GREEN |
| | 5468 | BOOK, for example, there's probably a GREEN BOOK and a missing object |
| | 5469 | rather than two objects GREEN and BOOK. A phrasing such as GIVE BOOK |
| | 5470 | TO BOB isn't weak because the prespositional marker makes the grammar |
| | 5471 | fairly unambiguous; likewise, GIVE BOB THE BOOK is relatively clear |
| | 5472 | because the article "the" can't normally go in the middle of a noun |
| | 5473 | phrase, so most likely introduces a second noun phrase. |
| | 5474 | |
| | 5475 | </div> |
| | 5476 | |
| | 5477 | <!-------------------> |
| | 5478 | <div class=entry> |
| | 5479 | |
| | 5480 | In the English library, CLIMB UP and CLIMB DOWN without a direct |
| | 5481 | object are now explicitly recognized in the grammar as missing-object |
| | 5482 | versions of CLIMB UP <i>dobj</i> and CLIMB DOWN <i>dobj</i>. This |
| | 5483 | prevents the CLIMB <i>dobj</i> grammar from treating the UP or DOWN as |
| | 5484 | a direct object, which usually yielded an ungainly response along the |
| | 5485 | lines of "you see no up here." (The missing-object CLIMB UP and CLIMB |
| | 5486 | DOWN are marked with "badness" in the grammar, which means that if |
| | 5487 | there actually is an in-scope object with vocabulary words "up" or |
| | 5488 | "down", the CLIMB <i>dobj</i> form will still be matched - so CLIMB UP |
| | 5489 | as short-hand for CLIMB THE UP STAIRWAY will continue to work as it |
| | 5490 | did before.) |
| | 5491 | |
| | 5492 | </div> |
| | 5493 | |
| | 5494 | <!-------------------> |
| | 5495 | <div class=entry> |
| | 5496 | |
| | 5497 | In the English library, the message substitution parameter "{a/he}" |
| | 5498 | was incorrectly not marked as a sentence subject. It's now so marked. |
| | 5499 | |
| | 5500 | </div> |
| | 5501 | |
| | 5502 | <!-------------------> |
| | 5503 | <div class=entry> |
| | 5504 | |
| | 5505 | In the English library, the methods askMissingObject(), |
| | 5506 | missingObject(), askMissingLiteral(), and missingLiteral() have been |
| | 5507 | moved from class messageHelper (in en_us.t) to playerMessages (in |
| | 5508 | msg_neu.t). These methods are just message generators, so they belong |
| | 5509 | in the message object with all of the other message generators. |
| | 5510 | |
| | 5511 | </div> |
| | 5512 | |
| | 5513 | <!-------------------> |
| | 5514 | <div class=entry> |
| | 5515 | |
| | 5516 | In the English library, the messages for noMatchForAll have been |
| | 5517 | changed to variations of "You see nothing suitable." In the past, the |
| | 5518 | message was "You see nothing to use for 'all' here," which was |
| | 5519 | somewhat misleading: it suggested that there's nothing present at all, |
| | 5520 | when the actual point is merely that there's nothing present that can |
| | 5521 | be used in the manner specified. |
| | 5522 | |
| | 5523 | </div> |
| | 5524 | |
| | 5525 | <!-------------------> |
| | 5526 | <div class=entry> |
| | 5527 | |
| | 5528 | In 3.0.8, OOPS X (for any literal X) was changed so that it didn't |
| | 5529 | consume a turn, but OOPS (without a literal) was inadvertantly left |
| | 5530 | unchanged, so it still counted as a turn. This has been corrected: a |
| | 5531 | bare OOPS command no longer consumes a turn. |
| | 5532 | |
| | 5533 | </div> |
| | 5534 | |
| | 5535 | <!-------------------> |
| | 5536 | <div class=entry> |
| | 5537 | |
| | 5538 | In the past, if the player typed NOTE without any text for the note, |
| | 5539 | the parser prompted for the missing text ("What do you want to |
| | 5540 | note?"). It no longer does this. Instead, the first time an empty |
| | 5541 | NOTE is entered, the parser displays a message explaining that NOTE is |
| | 5542 | usually used to enter a message, in case the player wasn't aware of |
| | 5543 | that; and after that, the parser simply accepts an empty NOTE the same |
| | 5544 | as any other. |
| | 5545 | |
| | 5546 | </div> |
| | 5547 | |
| | 5548 | <!-------------------> |
| | 5549 | <div class=entry> |
| | 5550 | |
| | 5551 | In the past, typing the secret command XSPCLTOPIC by itself on a |
| | 5552 | command line caused a run-time error. (XSPCLTOPIC is a verb that the |
| | 5553 | library uses internally to handle SpecialTopic entries. It's not |
| | 5554 | something the player ever needs to type, or indeed is ever allowed to |
| | 5555 | type, but at certain time, the library internally runs XSPCLTOPIC |
| | 5556 | commands through the normal command processing as though the player |
| | 5557 | had typed.) This has been fixed. |
| | 5558 | |
| | 5559 | </div> |
| | 5560 | |
| | 5561 | <!-------------------> |
| | 5562 | <div class=entry> |
| | 5563 | |
| | 5564 | In the past, if the parser asked for a missing literal phrase (such as |
| | 5565 | for TYPE), and the player responded with input that included a |
| | 5566 | character that the game's tokenizer didn't accept, the game displayed |
| | 5567 | an "unknown exception" message. The problem was that the parser |
| | 5568 | didn't properly catch the tokenizer's bad-token exception in this |
| | 5569 | case. The parser now catches this exception and reports it as normal. |
| | 5570 | |
| | 5571 | </div> |
| | 5572 | |
| | 5573 | <!-------------------> |
| | 5574 | <div class=entry> |
| | 5575 | |
| | 5576 | In the English library, when the parser is announcing the name of each |
| | 5577 | object in a multi-object command, paragraph breaks are now suppressed |
| | 5578 | after the object name. This slightly improves formatting in cases |
| | 5579 | where the action response for an object happens to start with a |
| | 5580 | paragraph break. |
| | 5581 | |
| | 5582 | </div> |
| | 5583 | |
| | 5584 | <!-------------------> |
| | 5585 | <div class=entry> |
| | 5586 | |
| | 5587 | In the English library, the verb-phrase builder method (getVerbPhrase()) |
| | 5588 | for TopicAction, TopicTAction, LiteralAction, and LiteralTAction didn't |
| | 5589 | work correctly. This has been corrected. |
| | 5590 | |
| | 5591 | </div> |
| | 5592 | |
| | 5593 | <!-------------------> |
| | 5594 | <div class=entry> |
| | 5595 | |
| | 5596 | The new output control pseudo-tag <./P0> cancels the effect |
| | 5597 | of an immediately preceding <.P0> tag. This is useful in |
| | 5598 | certain cases where you want to ensure that a newline or paragraph |
| | 5599 | break is displayed, even if a <.P0> was just displayed. |
| | 5600 | |
| | 5601 | </div> |
| | 5602 | |
| | 5603 | <!-------------------> |
| | 5604 | <div class=entry> |
| | 5605 | |
| | 5606 | All of the various spellInt-related functions are now implemented in |
| | 5607 | en_us.t. Some of these functions were formerly in numbers.t, but that |
| | 5608 | wasn't the right place for them because some language modules might |
| | 5609 | need to change these functions' interfaces (for example, to specify |
| | 5610 | the grammatical case or gender of the result). This change should |
| | 5611 | have no effect on any existing game code; it's a purely internal |
| | 5612 | change. |
| | 5613 | |
| | 5614 | </div> |
| | 5615 | |
| | 5616 | <!-------------------> |
| | 5617 | <div class=entry> |
| | 5618 | |
| | 5619 | The message property 'flashlightOnButDark' has been renamed to |
| | 5620 | 'flashlightOnButDarkMsg' (that is, the suffix 'Msg' has been added) |
| | 5621 | for consistency with the other message property names. |
| | 5622 | |
| | 5623 | </div> |
| | 5624 | |
| | 5625 | <!-------------------> |
| | 5626 | <div class=entry> |
| | 5627 | |
| | 5628 | The default library message for TASTE has been changed to "It tastes |
| | 5629 | as you expected" (from "You taste nothing out of the ordinary"). This |
| | 5630 | emphasizes that the physical action was completed but that nothing |
| | 5631 | unusual was detected; the old message could have been read as |
| | 5632 | suggesting that the object in question had no flavor at all, which |
| | 5633 | obviously isn't true of most objects. |
| | 5634 | |
| | 5635 | <p>In addition, UntakeableActor and Person now use messages similar to |
| | 5636 | those used for TAKE ("The cat won't let you," "Bob probably wouldn't |
| | 5637 | like that"), since these sorts of actors are meant to exhibit |
| | 5638 | volition, and in the real world would generally not allow themselves |
| | 5639 | to be arbitrarily tasted. |
| | 5640 | |
| | 5641 | </div> |
| | 5642 | |
| | 5643 | <!-------------------> |
| | 5644 | <div class=entry> |
| | 5645 | |
| | 5646 | A couple of the default library messages for POUR incorrectly referred |
| | 5647 | to the direct object where they meant to use the indirect object. |
| | 5648 | These have been fixed. |
| | 5649 | |
| | 5650 | </div> |
| | 5651 | |
| | 5652 | <!------------------------------- 3.0.8 ---------------------------------> |
| | 5653 | <div class="sepbar"><a name='308'></a>3.0.8</div> |
| | 5654 | <p><b><i>Released 9/12/2004</i></b> |
| | 5655 | <p> |
| | 5656 | |
| | 5657 | <div class=firstentry> |
| | 5658 | |
| | 5659 | <b>Compatibility-breaking change:</b> The class formerly named |
| | 5660 | ShipboardRoom has been renamed to simply Shipboard. This name change |
| | 5661 | is for consistency; most of the other similar mix-in classes are named |
| | 5662 | as simple adjectives. You should search your game code for any |
| | 5663 | mentions of ShipboardRoom and change each to Shipboard. |
| | 5664 | |
| | 5665 | <p>Note that the new class ShipboardRoom is provided for convenience |
| | 5666 | as a pre-defined combination of Shipboard and Room. This means that |
| | 5667 | any rooms you previously defined with the superclass list |
| | 5668 | <tt>ShipboardRoom, Room</tt> (and just changed, following the |
| | 5669 | prescription above, to <tt>Shipboard, Room</tt>) can now be written |
| | 5670 | simply as <tt>ShipboardRoom</tt>. This is purely for convenience; you |
| | 5671 | can leave the class list as <tt>Shipboard, Room</tt> and it will |
| | 5672 | behave the same way. |
| | 5673 | |
| | 5674 | </div> |
| | 5675 | |
| | 5676 | <!-------------------> |
| | 5677 | <div class=firstentry> |
| | 5678 | |
| | 5679 | <b>Compatibility-breaking change:</b> The class formerly named |
| | 5680 | OccludingConnector is now called Occluder. This change emphasizes |
| | 5681 | that the class is a mix-in that isn't limited to use with sense |
| | 5682 | connectors. |
| | 5683 | |
| | 5684 | </div> |
| | 5685 | |
| | 5686 | <!-------------------> |
| | 5687 | <div class=entry> |
| | 5688 | |
| | 5689 | <b>Possibly compatibility-breaking change:</b> The parameters to the |
| | 5690 | enterConversation() method of the ConversationReadyState class have |
| | 5691 | changed. The old second parameter, 'explicit', has been deleted and |
| | 5692 | replaced with a new parameter, 'entry', which gives the TopicEntry (if |
| | 5693 | any) that triggered the conversation entry. Any game code that calls |
| | 5694 | or overrides enterConversation() must be changed to accomodate the |
| | 5695 | parameter change. |
| | 5696 | |
| | 5697 | <p>The new parameter gives enterConversation() more information about |
| | 5698 | what triggered the conversation. This extra information is necessary |
| | 5699 | because, without it, the conversation system wasn't able to properly |
| | 5700 | handle topic entries that were marked as conversational but |
| | 5701 | non-greeting (that is, the isConversational property is true, but |
| | 5702 | impliesGreeting is nil). In the past, such entries were incorrectly |
| | 5703 | treated as though they were entirely non-conversational, so they |
| | 5704 | didn't enter an in-conversation state when used in a response. |
| | 5705 | |
| | 5706 | <p>Note that the same information conveyed by the old 'explicit' |
| | 5707 | parameter can be inferred from the new 'entry' parameter. When |
| | 5708 | 'entry' is nil, it means that the conversation entry is explicit, |
| | 5709 | because it was triggered by a direct action (HELLO, etc.) rather than |
| | 5710 | a TopicEntry. When 'entry' is non-nil, it means that the conversation |
| | 5711 | entry is implied by the TopicEntry. |
| | 5712 | |
| | 5713 | </div> |
| | 5714 | |
| | 5715 | <!-------------------> |
| | 5716 | <div class=entry> |
| | 5717 | |
| | 5718 | <b>Possibly compatibility-breaking change:</b> The ConvNode method |
| | 5719 | processSpecialCmd() has an additional parameter, as does the |
| | 5720 | SpecialTopic method matchPreParse(). It's unlikely that any game code |
| | 5721 | will be affected by this, because games don't normally override these |
| | 5722 | methods - usually, games just define SpecialTopic keyword lists. |
| | 5723 | |
| | 5724 | <p>The new parameter in both cases gives the "processed" version of |
| | 5725 | the player's input. The default SpecialTopic implementation now |
| | 5726 | matches the processed version of the input rather than the original |
| | 5727 | text the player entered. |
| | 5728 | |
| | 5729 | <p>In the English library, the processed input is the player's |
| | 5730 | original input with any periods, commas, question marks, exclamation |
| | 5731 | marks, colons, and semicolons removed, and with any leading "A" or "T" |
| | 5732 | keyword removed. |
| | 5733 | |
| | 5734 | <p>The purpose of the change to the parameters of these methods is |
| | 5735 | that it makes it simpler and more efficient to do this filtering. |
| | 5736 | |
| | 5737 | <p>Note that the punctuation filtering is new. We filter out the |
| | 5738 | punctuation because it's not usually meaningful for matching special |
| | 5739 | topics. For example, if the player's input contains the correct |
| | 5740 | keywords to match a special topic, we usually want to match the |
| | 5741 | special topic even if the player (for example) put a period or |
| | 5742 | question mark at the end of the command. |
| | 5743 | |
| | 5744 | </div> |
| | 5745 | |
| | 5746 | <!-------------------> |
| | 5747 | <div class=firstentry> |
| | 5748 | |
| | 5749 | <b>Possibly compatibility-breaking change:</b> The format of the |
| | 5750 | message generated by DropType.getReportPrefix() has been changed so |
| | 5751 | that the message is expected to be a complete sentence. This affects |
| | 5752 | the library messages floorlessDropMsg, droppingObjMsg, throwHitMsg, |
| | 5753 | and throwShortMsg (this last one is new in this update). These |
| | 5754 | methods and messages are mostly for internal use, but if you override |
| | 5755 | or call DropType.getReportPrefix() in your code, or if you've |
| | 5756 | customized any of these messages, you'll need to adjust your own |
| | 5757 | messages for this change. |
| | 5758 | |
| | 5759 | <p>The old sentence fragment format had a couple of problems. First, |
| | 5760 | it was likely to be problematic for some non-English translations. |
| | 5761 | Second, it was less flexible than the new full-sentence format, even |
| | 5762 | in English, for the purposes of adding new "drop type" objects and |
| | 5763 | of adding new messages composed using the prefix. |
| | 5764 | |
| | 5765 | </div> |
| | 5766 | |
| | 5767 | <!-------------------> |
| | 5768 | <div class=entry> |
| | 5769 | |
| | 5770 | The parser's pronoun antecedent rules have changed slightly. In the |
| | 5771 | past, when the player entered a command with multiple noun slots (such |
| | 5772 | as UNLOCK DOOR WITH KEY), the parser always chose the last-resolved |
| | 5773 | object as the antecedent for any future pronoun. This meant that the |
| | 5774 | parser remembered either the direct object or the indirect object, |
| | 5775 | depending on the verb. This rule didn't always produce the results |
| | 5776 | that you'd expect in natural English conversation, and had the further |
| | 5777 | drawback that the remembered object varied from verb to verb. |
| | 5778 | |
| | 5779 | <p>The parser now remembers <i>both</i> objects for two-object verbs, |
| | 5780 | and waits to make a decision until the player actually enters a |
| | 5781 | command with a pronoun. When the player types a singular pronoun (it, |
| | 5782 | he, she), and the most recent command had multiple noun slots, the |
| | 5783 | parser performs the standard "verify" evaluation on each potential |
| | 5784 | antecedent and picks the most logical one. If more than one |
| | 5785 | antecedent is equally logical, the parser simply picks one arbitrarily, |
| | 5786 | and announces the choice in the usual manner. When the choice is |
| | 5787 | completely arbitrary, it will always be the direct object of the |
| | 5788 | two-noun command. |
| | 5789 | |
| | 5790 | <p>Some examples: |
| | 5791 | |
| | 5792 | <p> |
| | 5793 | <pre> |
| | 5794 | >LOCK DOOR WITH KEY |
| | 5795 | Locked. |
| | 5796 | |
| | 5797 | >DROP IT |
| | 5798 | Dropped. <i>(the key, because it's illogical to drop the door)</i> |
| | 5799 | |
| | 5800 | >UNLOCK DOOR WITH KEY |
| | 5801 | (first taking the key) |
| | 5802 | Unlocked. |
| | 5803 | |
| | 5804 | >OPEN IT |
| | 5805 | Opened. <i>(the door, because it's illogical to open the key)</i> |
| | 5806 | |
| | 5807 | >LOCK DOOR WITH KEY |
| | 5808 | (first closing the door) |
| | 5809 | Locked. |
| | 5810 | |
| | 5811 | >EXAMINE IT |
| | 5812 | (the door) |
| | 5813 | It's a heavy wooden door. |
| | 5814 | </pre> |
| | 5815 | |
| | 5816 | <p>In the last command - EXAMINE IT - the choice of the two potential |
| | 5817 | antecedents is arbitrary, because it's equally logical to examine the |
| | 5818 | key or the door. The parser thus chooses the direct object of the |
| | 5819 | prior command, and announces the choice to alert the player (in case |
| | 5820 | she was thinking "it" would refer to the key). |
| | 5821 | |
| | 5822 | </div> |
| | 5823 | |
| | 5824 | <!-------------------> |
| | 5825 | <div class=entry> |
| | 5826 | |
| | 5827 | The new Thing method notifyMoveInto(newContainer) complements the |
| | 5828 | existing moveInto notification routines notifyRemove() and |
| | 5829 | notifyInsert(). The new notifyMoveInto() method is called last in the |
| | 5830 | sequence, after notifyRemove() has been called on the old container |
| | 5831 | tree and notifyInsert() on the new container tree. notifyInsert() |
| | 5832 | gives the object being moved a chance to perform any special |
| | 5833 | additional processing before the move, or to veto the move (which it |
| | 5834 | can do by displaying an explanatory message and calling 'exit', just |
| | 5835 | as notifyRemove() and notifyInsert() are allowed to do). |
| | 5836 | |
| | 5837 | <p>The new routine has several benefits. First, it provides the |
| | 5838 | object being moved with the same sort of notifications that the old |
| | 5839 | and new containers already receive. Since it runs along with these |
| | 5840 | other notifications, it allows the same distinction as those other |
| | 5841 | notifiers between moves that trigger these side effects (via calls to |
| | 5842 | moveInto) and those that don't (via direct calls to baseMoveInto) |
| | 5843 | Second, since the new method runs last, after the notifyRemove() and |
| | 5844 | notifyInsert() notifications, it has the last chance to veto the move; |
| | 5845 | this means that if it doesn't cancel the move, then the move will |
| | 5846 | definitely proceed (at least to the extent that baseMoveInto() will be |
| | 5847 | called). Any side effects that must be carried out only when the move |
| | 5848 | will succeed can thus be safely coded here. |
| | 5849 | |
| | 5850 | </div> |
| | 5851 | |
| | 5852 | <!-------------------> |
| | 5853 | <div class=entry> |
| | 5854 | |
| | 5855 | The parser now provides more helpful error feedback when the player |
| | 5856 | tries to enter a SpecialTopic command that's not active. |
| | 5857 | |
| | 5858 | <p>First, the library automatically enters all of the keywords defined |
| | 5859 | by special topics into the game's dictionary. This ensures that the |
| | 5860 | parser won't claim that special topic keywords are unknown if they're |
| | 5861 | used out of context, as it did in the past. It was confusing when the |
| | 5862 | parser claimed that special topic keywords were unknown, because the |
| | 5863 | parser most certainly did know them some of the time. |
| | 5864 | |
| | 5865 | <p>Second, when the player enters a command that looks syntactically |
| | 5866 | invalid, but which doesn't contain any unknown words, the parser scans |
| | 5867 | recent special topics for a match. If it finds a match, the parser |
| | 5868 | will show a new message: "That command can't be used right now." This |
| | 5869 | old response - "The story doesn't understand that command" - was |
| | 5870 | potentially confusing, since the story <i>can</i> recognize the exact |
| | 5871 | same command at other times. |
| | 5872 | |
| | 5873 | <p>The parser scans the list of special topics most recently listed in |
| | 5874 | topic inventories, using the new specialTopicHistory object. This |
| | 5875 | object keeps track of a configurable number of the most recent |
| | 5876 | SpecialTopic suggestions listed; set its maxEntries property, which |
| | 5877 | defaults to 20, to the maximum number of recent entries to scan. The |
| | 5878 | purpose of the limit is to ensure that a scan won't take too long, by |
| | 5879 | limiting the scan to the specified maximum number of SpecialTopic |
| | 5880 | items. The trade-off is that the parser will forget older |
| | 5881 | suggestions, so they'll be met with the old "story doesn't understand" |
| | 5882 | message if the player tries them. However, it seems safe to assume |
| | 5883 | that the player will also forget about older suggestions, and so won't |
| | 5884 | think to try them. |
| | 5885 | |
| | 5886 | <p>If you set maxEntries to nil, it essentially removes the limit to |
| | 5887 | the number of entries to scan. The library won't maintain the history |
| | 5888 | list at all in this case. Instead, to check an unrecognized command, |
| | 5889 | the parser will simply scan <i>all</i> SpecialTopic objects in the |
| | 5890 | entire game, whether or not they've ever been suggested in topic |
| | 5891 | inventory displays. This option might be preferable for a game where |
| | 5892 | the total number of items is small enough that scanning them all |
| | 5893 | doesn't take an appreciable amount of time. (Or not. Some authors |
| | 5894 | might not want the parser to recognize previously-unseen special |
| | 5895 | topics at all - even to the extent of saying "that command can't be |
| | 5896 | used right now" - because doing so could conceivably give away |
| | 5897 | upcoming plot developments. That is, if the player accidentally types |
| | 5898 | a command that happens to match a special topic that hasn't ever been |
| | 5899 | suggested, the player could infer from the special error message that |
| | 5900 | the command will do something later in the game. The chances of |
| | 5901 | actually giving away anything important this way seem rather remote, |
| | 5902 | but this sort of thing rubs some authors the wrong way. If you don't |
| | 5903 | like the idea of using the different error message for special topics |
| | 5904 | until after they've been suggested at least once, but you also don't |
| | 5905 | want a limit on the number of past topics to remember, just set |
| | 5906 | maxEntries to a very high number.) |
| | 5907 | |
| | 5908 | </div> |
| | 5909 | |
| | 5910 | <!-------------------> |
| | 5911 | <div class=entry> |
| | 5912 | |
| | 5913 | The new property pluralOrder lets you control the order in which a set |
| | 5914 | of objects is processed when the objects match a plural phrase in a |
| | 5915 | command. This property applies to all VocabObjects (which is the base |
| | 5916 | class for any object with vocabulary words); the arbitrary default |
| | 5917 | value is 100. |
| | 5918 | |
| | 5919 | <p>In most cases, the order of processing for the matches for a plural |
| | 5920 | phrase is arbitrary, so you won't need to worry about this new |
| | 5921 | property. Once in a while, though, it's convenient to be able to |
| | 5922 | control the order of matching. This is especially useful when objects |
| | 5923 | have ordinal names (first door, second door, etc), or when objects are |
| | 5924 | named by relative spatial position (top drawer, middle drawer, bottom |
| | 5925 | drawer). |
| | 5926 | |
| | 5927 | <p>Note that the new property only controls the order of processing |
| | 5928 | within an individual plural phrase. For example, in the command TAKE |
| | 5929 | BOOKS AND MAGAZINES, the books will be sorted by their relative |
| | 5930 | pluralOrder values, then the magazines will be sorted by theirs - but |
| | 5931 | when the command is processed, all of the books will be taken before |
| | 5932 | any of the magazines, regardless of the relative pluralOrder values. |
| | 5933 | This is important because it ensures that commands are processed in |
| | 5934 | the order specified by the player. |
| | 5935 | |
| | 5936 | <p>Because pluralOrder and the existing disambigPromptOrder will |
| | 5937 | probably be used in the same way most of the time, disambigPromptOrder |
| | 5938 | now returns the pluralOrder value by default. So, for the common case |
| | 5939 | that the two properties should have the same value, you can simply set |
| | 5940 | pluralOrder. |
| | 5941 | |
| | 5942 | </div> |
| | 5943 | |
| | 5944 | <!-------------------> |
| | 5945 | <div class=entry> |
| | 5946 | |
| | 5947 | The new function cls() clears the screen, and takes care of a couple |
| | 5948 | of chores that should always be done at the same time. First, the |
| | 5949 | function clears any text captured in the transcript manager, ensuring |
| | 5950 | that text that was meant to be displayed before the screen was cleared |
| | 5951 | won't show up on the new, blank screen. Second, the function calls |
| | 5952 | the new gameMain.setAboutBox() method after clearing the screen, |
| | 5953 | ensuring that any <ABOUTBOX> tag is re-displayed; this is |
| | 5954 | necessary because HTML TADS discards any old <ABOUTBOX> |
| | 5955 | information whenever the screen is cleared. |
| | 5956 | |
| | 5957 | </div> |
| | 5958 | |
| | 5959 | <!-------------------> |
| | 5960 | <div class=entry> |
| | 5961 | |
| | 5962 | The new method setAboutBox() has been added to the gameMain() object. |
| | 5963 | This new method is designed as the place to put your game's |
| | 5964 | <ABOUTBOX> tag, if you provide one. The method is invoked |
| | 5965 | during start-up, and is also called from the new cls() function, |
| | 5966 | ensuring that the about-box information will be re-displayed each time |
| | 5967 | the screen is cleared. |
| | 5968 | |
| | 5969 | <p>The default implementation in GameMainDef does nothing. The new |
| | 5970 | method is simply a placeholder for the game's (optional) use. |
| | 5971 | |
| | 5972 | <p>This change is designed to make it easier to manage your about-box |
| | 5973 | information. HTML TADS discards any previous <ABOUTBOX> tag |
| | 5974 | when the screen is cleared, so it's necessary to re-display the tag |
| | 5975 | whenever you clear the screen. If you write your <ABOUTBOX> tag |
| | 5976 | in the new gameMain.setAboutBox() method, and you always use the new |
| | 5977 | cls() function to clear the screen (rather than calling the low-level |
| | 5978 | clearScreen() function directly), the library will automatically keep |
| | 5979 | yout about-box active. |
| | 5980 | |
| | 5981 | </div> |
| | 5982 | |
| | 5983 | <!-------------------> |
| | 5984 | <div class=entry> |
| | 5985 | |
| | 5986 | You can now control whether or not a given verb accepts the word ALL |
| | 5987 | in its noun phrases. By default, every verb accepts ALL. However, if |
| | 5988 | you set the new gameMain property allVerbsAllowAll to nil, only the |
| | 5989 | basic inventory-management verbs (TAKE, TAKE FROM, DROP, PUT IN, PUT |
| | 5990 | ON) will accept ALL, and every other verb will simply show an error |
| | 5991 | message ("'All' isn't allowed with that verb"). |
| | 5992 | |
| | 5993 | <p>Some authors like to limit usage of ALL to the basic inventory |
| | 5994 | verbs, either because of tradition or because they think it's a sort |
| | 5995 | of "cheating" when a player tries commands like OPEN ALL or EXAMINE |
| | 5996 | ALL. This feature is probably of particular interest to writers of |
| | 5997 | puzzle-oriented games. |
| | 5998 | |
| | 5999 | <p>In addition to the all-or-(almost-)nothing option setting in |
| | 6000 | gameMain, you can control ALL acceptance on a verb-by-verb basis. The |
| | 6001 | new Action property actionAllowsAll controls whether a particular |
| | 6002 | Action accepts ALL for its noun phrases. By default, the base |
| | 6003 | definition in Action simply returns the value of |
| | 6004 | gameMain.allVerbsAllowAll. In addition, the basic inventory verbs |
| | 6005 | (Take, TakeFrom, Drop, PutIn, PutOn) override actionAllowsAll to |
| | 6006 | return true. If you want to enable or disable ALL for an individual |
| | 6007 | action, you can use "modify" to set the property for that action |
| | 6008 | class. |
| | 6009 | |
| | 6010 | </div> |
| | 6011 | |
| | 6012 | <!-------------------> |
| | 6013 | <div class=entry> |
| | 6014 | |
| | 6015 | The library uses the new Style Tag <.announceObj> to set the |
| | 6016 | display style for multi-object announcements. (These are the little |
| | 6017 | announcements, of the form "blue book:", that precede the responses |
| | 6018 | when a command is applied to multiple objects.) |
| | 6019 | |
| | 6020 | <p>The default display style is to show object announcements in bold |
| | 6021 | text. When a command operates on several objects, the response can |
| | 6022 | get rather lengthy; the new bold-face style for the announcements is |
| | 6023 | intended to make these responses easier to read by making the |
| | 6024 | boundaries of the sub-parts more visually apparent. |
| | 6025 | |
| | 6026 | <p>The new StyleTag object is called announceObjStyleTag. You can use |
| | 6027 | "modify" with this object to customize the announcement style, if you |
| | 6028 | want. |
| | 6029 | |
| | 6030 | </div> |
| | 6031 | |
| | 6032 | <!-------------------> |
| | 6033 | <div class=entry> |
| | 6034 | |
| | 6035 | Actor.lookAround(), Thing.lookAroundPov(), and Thing.lookAroundWithin() |
| | 6036 | now accept a set of bit flags for the 'verbose' parameter. 'true' and |
| | 6037 | 'nil' can still be passed, and have the same meanings as before, so |
| | 6038 | existing code doesn't need to be changed. However, the new bit flags |
| | 6039 | give you more control over the format of the listing. The flags, which |
| | 6040 | can be combined with the "|" operator, are: |
| | 6041 | |
| | 6042 | <ul> |
| | 6043 | <li>LookRoomName: include the room name, shown on a line by itself at |
| | 6044 | the start of the description. |
| | 6045 | <li>LookRoomDesc: show the full description of the room. |
| | 6046 | <li>LookListSpecials: show the special descriptions (specialDesc) for |
| | 6047 | visible objects that have them. |
| | 6048 | <li>LookListPortables: list the portable items that are visible. |
| | 6049 | </ul> |
| | 6050 | |
| | 6051 | <p>Note that lookAroundWithin() <i>automatically</i> adds LookRoomDesc |
| | 6052 | to the flags if the actor has never seen the room before. |
| | 6053 | |
| | 6054 | <p>If you pass 'nil' for the 'verbose' parameter, the effect is the |
| | 6055 | same as passing (LookRoomName | LookListSpecials | LookListPortables). |
| | 6056 | If you pass 'true', the effect is the same as passing (LookRoomName | |
| | 6057 | LookRoomDesc | LookListSpecials | LookListPortables). |
| | 6058 | |
| | 6059 | <p>The main effect of this change is that it lets you generate a room |
| | 6060 | description without including the room title, which wasn't possible in |
| | 6061 | the past. This can be useful for cases where the standard LOOK AROUND |
| | 6062 | format isn't desirable, such as when describing the view through a |
| | 6063 | sense connector to another room. |
| | 6064 | |
| | 6065 | </div> |
| | 6066 | |
| | 6067 | <!-------------------> |
| | 6068 | <div class=entry> |
| | 6069 | |
| | 6070 | The new Thing method roomRemoteDesc(actor) lets you customize the way |
| | 6071 | a room is described when it's viewed by an actor from another room. |
| | 6072 | The library calls this from Thing.lookAroundWithin() when the actor |
| | 6073 | who's viewing the room is not within the room being viewed. |
| | 6074 | |
| | 6075 | <p>Note that none of the standard library commands ever call this new |
| | 6076 | method, because the basic library doesn't provide any command to view |
| | 6077 | a remote room. However, games might provide their own commands to do |
| | 6078 | so, such as LOOK THROUGH KEYHOLE, and you might want to call |
| | 6079 | lookAroundWithin() to generate the descriptions in these cases. |
| | 6080 | Doing so will invoke roomRemoteDesc instead of roomDesc to generate |
| | 6081 | the room description. |
| | 6082 | |
| | 6083 | <p>The default Thing.roomRemoteDesc implementation simply calls |
| | 6084 | roomDesc. You'll probably want to override this any time you actually |
| | 6085 | use it, to show a suitable description from the remote actor's point |
| | 6086 | of view. |
| | 6087 | |
| | 6088 | </div> |
| | 6089 | |
| | 6090 | <!-------------------> |
| | 6091 | <div class=entry> |
| | 6092 | |
| | 6093 | A new Thing method, adjustLookAroundTable(), lets you customize the |
| | 6094 | set of objects that lookAroundWithin() can mention. By default, this |
| | 6095 | routine removes the POV and actor objects (which are usually the same |
| | 6096 | object) from the table, ensuring that these objects aren't mentioned. |
| | 6097 | |
| | 6098 | <p>In the past, lookAroundWithin() simply removed the actor object |
| | 6099 | directly, so the default behavior is the same as in the past. |
| | 6100 | Separating this out into a new method lets games customize which |
| | 6101 | objects are mentioned and which aren't for the particular room and |
| | 6102 | point of view. |
| | 6103 | |
| | 6104 | </div> |
| | 6105 | |
| | 6106 | <!-------------------> |
| | 6107 | <div class=entry> |
| | 6108 | |
| | 6109 | The new Thing method isLookAroundCeiling() determines whether the LOOK |
| | 6110 | AROUND description for a given object is generated by that object |
| | 6111 | directly, or by its location. By default, this routine returns true |
| | 6112 | if either the object is a top-level room (that is, it has a nil |
| | 6113 | location), <i>or</i> the object's enclosing location isn't visible. |
| | 6114 | In either of these cases, since it's not possible to see out to an |
| | 6115 | enclosing location, the current object has to provide its own interior |
| | 6116 | description. |
| | 6117 | |
| | 6118 | <p>This method is called from lookAroundPov(), which formerly |
| | 6119 | performed the same test directly, so the default behavior hasn't |
| | 6120 | changed. This has been separated into a new method because the |
| | 6121 | default condition isn't always ideal. For example, if the player's |
| | 6122 | inside a closed wooden booth with a small window that looks out to the |
| | 6123 | enclosing location, and the player types LOOK AROUND, we'd want to |
| | 6124 | describe the interior of the booth, not the outside location. For |
| | 6125 | this case, you could override isLookAroundCeiling() for the booth to |
| | 6126 | return true even though the location is visible through the window. |
| | 6127 | |
| | 6128 | </div> |
| | 6129 | |
| | 6130 | <!-------------------> |
| | 6131 | <div class=firstentry> |
| | 6132 | |
| | 6133 | The new TAction method getDobjInfo() returns the full ResolveInfo |
| | 6134 | object associated with the current direct object. Similarly, the |
| | 6135 | new TIAction method getIobjInfo() returns the indirect object's |
| | 6136 | ResolveInfo. |
| | 6137 | |
| | 6138 | </div> |
| | 6139 | |
| | 6140 | <!-------------------> |
| | 6141 | <div class=firstentry> |
| | 6142 | |
| | 6143 | The parser now keeps track of the noun phrase that was parsed for |
| | 6144 | each object involved in the command. This information is kept in |
| | 6145 | the ResolveInfo object, in the 'np_' property. This information can |
| | 6146 | be used, for example, to obtain the original text of the noun phrase |
| | 6147 | that was resolved to a given object. For example, to obtain the |
| | 6148 | original text that resolved to the current direct object being |
| | 6149 | processed in an action() method, you could write this: |
| | 6150 | |
| | 6151 | <p><pre> |
| | 6152 | local txt = gAction.getDobjInfo().np_.getOrigText(); |
| | 6153 | </pre> |
| | 6154 | |
| | 6155 | </div> |
| | 6156 | |
| | 6157 | <!-------------------> |
| | 6158 | <div class=entry> |
| | 6159 | |
| | 6160 | Due to a bug introduced in the previous release, the method |
| | 6161 | PresentLater.makePresentByKeyIf() didn't work correctly if the |
| | 6162 | condition argument was a function pointer. In these cases, the |
| | 6163 | routine called the function on the first object matching the key, and |
| | 6164 | then used that same true/nil result for <i>every</i> matching object. |
| | 6165 | (Thus, if the first matching object was to be revealed, every |
| | 6166 | matching object was revealed; if the first was to be hidden, all were |
| | 6167 | hidden.) This has been corrected; the method once again calls the |
| | 6168 | given function individually for each object matching the key. |
| | 6169 | |
| | 6170 | </div> |
| | 6171 | |
| | 6172 | <!-------------------> |
| | 6173 | <div class=entry> |
| | 6174 | |
| | 6175 | Component objects are now hidden from EXAMINE ALL by default. Since |
| | 6176 | components are simply detail features of larger objects, it's usually |
| | 6177 | enough to examine the larger objects; it usually doesn't make sense to |
| | 6178 | also include the components separately in EXAMINE ALL responses. |
| | 6179 | |
| | 6180 | </div> |
| | 6181 | |
| | 6182 | <!-------------------> |
| | 6183 | <div class=entry> |
| | 6184 | |
| | 6185 | By default, FOLLOW now reports a more helpful message when there's not |
| | 6186 | enough information to carry out the command. In the past, the default |
| | 6187 | message was simply "You don't know where (the actor) went." This was |
| | 6188 | misleading when the real problem was that the actor's departure had |
| | 6189 | been previously observed, but from some other location. The new |
| | 6190 | message is of this form: "The last place you saw (the actor) was (the |
| | 6191 | room where we last saw him)." Note that the library now keeps track |
| | 6192 | of the last place we saw each actor, even when we didn't observe the |
| | 6193 | actor leaving, to ensure that this new message is always accurate. |
| | 6194 | |
| | 6195 | </div> |
| | 6196 | |
| | 6197 | <!-------------------> |
| | 6198 | <div class=entry> |
| | 6199 | |
| | 6200 | The "badness" levels of some of the grammar rules in the English |
| | 6201 | parser have been re-ranked, to put the various error conditions in a |
| | 6202 | different order. In particular, the "miscellaneous noun phrase" rules |
| | 6203 | now have a lower badness than any of the "missing noun phrase" rules. |
| | 6204 | In the past, this relationship was reversed, which caused a subtle |
| | 6205 | problem when a two-noun verb was used with a noun phrase containing a |
| | 6206 | word not in the dictionary. |
| | 6207 | |
| | 6208 | <p>Some background: In the English parser, certain grammar rules are |
| | 6209 | defined specifically to match certain distinct patterns of erroneous |
| | 6210 | user input. The point of matching invalid input is to recognize it |
| | 6211 | and respond intelligently to it, rather than issue a blanket error |
| | 6212 | message. Most of these invalid constructs are marked with "badness" |
| | 6213 | levels, which tells the parser to match them only as a last resort, so |
| | 6214 | that we match a valid grammar rule over one of these special error |
| | 6215 | rules whenever possible. |
| | 6216 | |
| | 6217 | </div> |
| | 6218 | |
| | 6219 | <!-------------------> |
| | 6220 | <div class=entry> |
| | 6221 | |
| | 6222 | In the English grammar, each of the verbs with two noun slots (PUT X |
| | 6223 | ON Y, ASK X ABOUT Y, etc.) has a corresponding special grammar rule |
| | 6224 | that includes only the first noun slot (PUT X, ASK X, etc.), for cases |
| | 6225 | where the player inadvertantly or intentionally types the command with |
| | 6226 | only one noun. In the past, these rules weren't marked with "badness" |
| | 6227 | levels. Now they are: these are treated as having "badness" |
| | 6228 | equivalent to that of an empty noun phrase. This ensures that they'll |
| | 6229 | be matched only as a last resort, when there isn't a more "correct" |
| | 6230 | interpretation of the phrase. |
| | 6231 | |
| | 6232 | </div> |
| | 6233 | |
| | 6234 | <!-------------------> |
| | 6235 | <div class=entry> |
| | 6236 | |
| | 6237 | CollectiveGroup objects are now explicitly marked as unlisted in room |
| | 6238 | or object contents or in inventories (that is, a CollectiveGroup's |
| | 6239 | isListed, isListedInContents, and isListedInInventory properties now |
| | 6240 | return nil). In the past, collective group objects incorrectly showed |
| | 6241 | up in these listings as separate objects under certain circumstances, |
| | 6242 | such as when their individuals were self-illuminating (brightness = 1) |
| | 6243 | and the enclosing room was dark. |
| | 6244 | |
| | 6245 | </div> |
| | 6246 | |
| | 6247 | <!-------------------> |
| | 6248 | <div class=entry> |
| | 6249 | |
| | 6250 | In the past, the description of a dark room listed every visible |
| | 6251 | self-illuminating object, even including those being carried by the |
| | 6252 | actor doing the looking. Now, the description excludes objects in the |
| | 6253 | actor's inventory, since these objects aren't part of the actor's |
| | 6254 | surroundings. |
| | 6255 | |
| | 6256 | </div> |
| | 6257 | |
| | 6258 | <!-------------------> |
| | 6259 | <div class=entry> |
| | 6260 | |
| | 6261 | In the past, the INVENTORY command included in its listing any items |
| | 6262 | that were being directly held, even if they weren't visible, on the |
| | 6263 | assumption that the actor could identify these items by touch alone. |
| | 6264 | This has now been refined slightly: instead of unconditionally |
| | 6265 | including directly-held items in the listing, the library now includes |
| | 6266 | directly-held items that the actor already knows about, as indicated |
| | 6267 | by the actor's knowsAbout() method. The rationale is almost the same |
| | 6268 | as before, but this change means that we no longer assume that the |
| | 6269 | actor can identify an item by touch unless the actor already knows |
| | 6270 | about the item. Of course, this change doesn't affect the listing of |
| | 6271 | visible items - visible items are listed whether previously known or |
| | 6272 | not. |
| | 6273 | |
| | 6274 | </div> |
| | 6275 | |
| | 6276 | <!-------------------> |
| | 6277 | <div class=entry> |
| | 6278 | |
| | 6279 | The "finish option" handler for RESTORE (finishOptionRestore) now |
| | 6280 | terminates any remaining processing on the command line that triggered |
| | 6281 | the finish options, when the RESTORE is successful. This ensures that |
| | 6282 | when the finish options are triggered from somewhere in the middle of |
| | 6283 | a command (such as in a beforeAction method), there will be no strange |
| | 6284 | side effects from carrying out the rest of the triggering command. |
| | 6285 | |
| | 6286 | </div> |
| | 6287 | |
| | 6288 | <!-------------------> |
| | 6289 | <div class=entry> |
| | 6290 | |
| | 6291 | In the English grammar, LOOK OUT is now a synonym for LOOK THROUGH. |
| | 6292 | This allows constructs like LOOK OUT WINDOW, which is more natural |
| | 6293 | for some objects than LOOK THROUGH but has the same meaning in |
| | 6294 | virtually all cases. |
| | 6295 | |
| | 6296 | </div> |
| | 6297 | |
| | 6298 | <!-------------------> |
| | 6299 | <div class=entry> |
| | 6300 | |
| | 6301 | In the English grammar, the acceptable phrasing for the SitOn command |
| | 6302 | no longer includes "sit <i>object</i>" or "sit down <i>object</i>." |
| | 6303 | These phrasings aren't grammatical, but they were included to match |
| | 6304 | intransitive inputs (SIT and SIT DOWN) and then ask for the missing |
| | 6305 | direct object phrase. Now, rather than matching the intransitive |
| | 6306 | forms using the main SitOn rule, they're matched using the SitOnWhat |
| | 6307 | rule. The same change applies to the LieOn rules. |
| | 6308 | |
| | 6309 | </div> |
| | 6310 | |
| | 6311 | <!-------------------> |
| | 6312 | <div class=entry> |
| | 6313 | |
| | 6314 | UnlistedProxyConnector.primaryConn is now initialized to TadsObject by |
| | 6315 | default. In rare cases, game code might invoke a property of an |
| | 6316 | UnlistedProxyConnector before the object is constructed; this new |
| | 6317 | default (rather than nil) provides reasonable behavior in these cases, |
| | 6318 | without requiring an added run-time test for a nil primaryConn. |
| | 6319 | |
| | 6320 | </div> |
| | 6321 | |
| | 6322 | <!-------------------> |
| | 6323 | <div class=entry> |
| | 6324 | |
| | 6325 | In the English messages, the AutoClosingDoor's announcement (of the |
| | 6326 | door having automatically closed) now has a leading paragraph break, |
| | 6327 | to set it off from the room description or other travel report that |
| | 6328 | usually precedes the announcement. |
| | 6329 | |
| | 6330 | </div> |
| | 6331 | |
| | 6332 | <!-------------------> |
| | 6333 | <div class=entry> |
| | 6334 | |
| | 6335 | The English library's rules have changed slightly for substituting |
| | 6336 | reflexive pronouns in message strings. In the past, the library |
| | 6337 | always substituted a reflexive pronoun when an "objective-case" |
| | 6338 | parameter matched the subject of the sentence; for example, in the |
| | 6339 | message string "{You/he} can't eat {the dobj/him}," if the direct |
| | 6340 | object was the same as the actor, the message would be "You can't eat |
| | 6341 | yourself" (rather than simply "You can't eat you"). The new rule is |
| | 6342 | <i>almost</i> the same, but has a new exception: if the <i>parameter |
| | 6343 | name</i> of an objective-case parameter is the same as that of the |
| | 6344 | subject of the sentence, the reflexive substitution is not used. |
| | 6345 | |
| | 6346 | <p>For example, the library now displays "{You/he} close{s} the door |
| | 6347 | behind {you/him}" as "You close the door behind you." The old rule |
| | 6348 | would have used "behind yourself" instead, but the new exception kicks |
| | 6349 | in because both the subject ("{You/he}") and the objective-case item |
| | 6350 | ("{you/him}") refer to the 'actor' parameter object. |
| | 6351 | |
| | 6352 | <p>The reason the automatic reflexive substitution exists in the first |
| | 6353 | place is that it allows you to write a message string that refers to |
| | 6354 | multiple parameters that <i>might</i> end up being the same object |
| | 6355 | some of the time. In the first example ("{You/he} can't eat {the |
| | 6356 | dobj/him}"), the direct object and the actor might sometimes be the |
| | 6357 | same, but usually aren't; since the library automatically provides the |
| | 6358 | reflexive pronoun when the direct object happens to be the same as the |
| | 6359 | actor, the same message string works for any combination of objects |
| | 6360 | ("You can't eat yourself" vs. "You can't eat the deck chair"). |
| | 6361 | However, this rule is too aggressive without the exception. The point |
| | 6362 | of the exception is to give authors exact control in cases where they |
| | 6363 | know <i>in advance</i> that the subject and objective-case object will |
| | 6364 | be the same, by virtue of the fact that the message is referring to |
| | 6365 | the same parameter by name in both cases. In these cases, there's no |
| | 6366 | need for the library to provide reflexive pronouns conditionally, |
| | 6367 | because the author knows in advance that the objects will always be |
| | 6368 | the same - so the author will know whether or not the reflexive |
| | 6369 | pronoun is desired, and will write it that way, or not, as desired. |
| | 6370 | |
| | 6371 | </div> |
| | 6372 | |
| | 6373 | <!-------------------> |
| | 6374 | <div class=entry> |
| | 6375 | |
| | 6376 | If an exception occurs during an NPC's turn (in ActorState.takeTurn, |
| | 6377 | for example), the scheduler will now count the NPC's turn as over, so |
| | 6378 | that other NPC's get a chance to run before the same NPC takes another |
| | 6379 | turn. In the past, an uncaught exception during an NPC's turn |
| | 6380 | bypassed the turn-counting for the NPC, so the same NPC got another |
| | 6381 | turn immediately; in some cases, this caused the NPC to try the same |
| | 6382 | erroneous operation again, which set up an infinite loop as the |
| | 6383 | erroneous NPC code was invoked over and over without giving anyone |
| | 6384 | else a chance to run. The same change applies to fuses, daemons, and |
| | 6385 | any other "schedulable" object. |
| | 6386 | |
| | 6387 | </div> |
| | 6388 | |
| | 6389 | <!-------------------> |
| | 6390 | <div class=entry> |
| | 6391 | |
| | 6392 | In the English library, SCRIPT ON is now accepted as a synonym for |
| | 6393 | SCRIPT (for consistency with SCRIPT OFF), and RECORD ON as a synonym |
| | 6394 | for RECORD. In addition, the RECORD ON/OFF messages have been changed |
| | 6395 | to sound less geeky (they formerly referred to "RECORD mode," but now |
| | 6396 | talk about "command recording" instead). |
| | 6397 | |
| | 6398 | </div> |
| | 6399 | |
| | 6400 | <!-------------------> |
| | 6401 | <div class=entry> |
| | 6402 | |
| | 6403 | In the English library, "inside" and "inside of" are now accepted in |
| | 6404 | locational qualifier phrases (as in "read the coin inside the box"). |
| | 6405 | |
| | 6406 | </div> |
| | 6407 | |
| | 6408 | <!-------------------> |
| | 6409 | <div class=entry> |
| | 6410 | |
| | 6411 | When the player looks behind or through a closed door, the library now |
| | 6412 | assumes that the player's intention is to open the door to see what's |
| | 6413 | on the other side. So, the library now applies an objOpen |
| | 6414 | precondition to these commands, which will implicitly open the door if |
| | 6415 | it's closed. |
| | 6416 | |
| | 6417 | <p>In addition, in the case of LOOK BEHIND, the library uses a special |
| | 6418 | message if the implicit Open was applied: "Opening the door reveals |
| | 6419 | nothing unusual." This message emphasizes that we're looking through |
| | 6420 | the passage, not at the space created between the door and the |
| | 6421 | adjacent wall (if such a thing is applicable). |
| | 6422 | |
| | 6423 | <p>When we look behind a door that was already open, the library |
| | 6424 | assumes that the player's intention is simply to look at the back side |
| | 6425 | of the door, or the space between the door and the adjacent wall. In |
| | 6426 | this case, the inherited Thing message ("you see nothing unusual |
| | 6427 | behind the door") is used. |
| | 6428 | |
| | 6429 | </div> |
| | 6430 | |
| | 6431 | <!-------------------> |
| | 6432 | <div class=entry> |
| | 6433 | |
| | 6434 | LOOK THROUGH PASSAGE now has a custom response when the passage is |
| | 6435 | open: "You can't see much through (the passage) from here." In the |
| | 6436 | real world, we can typically look through a passage into the next |
| | 6437 | room, but the library world model doesn't actually allow us to see |
| | 6438 | anything in the next room; so we don't want to say that we can't see |
| | 6439 | through the passage at all, but at the same time we can't actually say |
| | 6440 | we see anything. The new default suggests that we can in principle |
| | 6441 | see some distance through the passage, but not far enough to see |
| | 6442 | anything in the connected location. |
| | 6443 | |
| | 6444 | <p>When a passage is closed, the inherited Thing message ("you can't |
| | 6445 | see anything through (the passage)") is used instead, since a closed |
| | 6446 | passage is assumed to be something opaque, such as a closed door. |
| | 6447 | |
| | 6448 | </div> |
| | 6449 | |
| | 6450 | <!-------------------> |
| | 6451 | <div class=entry> |
| | 6452 | |
| | 6453 | Looking through, under, or behind a room part now yields a custom |
| | 6454 | response that says that you simply can't do that, rather than using |
| | 6455 | the inherited Thing defaults (which say that you can't see anything |
| | 6456 | there). For room parts, it doesn't generally make sense to perform |
| | 6457 | any of these actions, which the new custom messages try to convey. |
| | 6458 | |
| | 6459 | </div> |
| | 6460 | |
| | 6461 | <!-------------------> |
| | 6462 | <div class=entry> |
| | 6463 | |
| | 6464 | If a player types simply GO or WALK, the library now displays a more |
| | 6465 | helpful message: "You'll have to say which way to go." In the past, |
| | 6466 | the parser didn't recognize that phrasing at all, so responded with |
| | 6467 | the standard unknown-verb message. |
| | 6468 | |
| | 6469 | </div> |
| | 6470 | |
| | 6471 | <!-------------------> |
| | 6472 | <div class=entry> |
| | 6473 | |
| | 6474 | PathPassage now uses a custom message for STAND ON: "If you want to |
| | 6475 | follow the path, just say so." The inherited default ("That isn't |
| | 6476 | something you can stand on") doesn't make a lot of sense for paths, |
| | 6477 | but at the same time, we don't want to treat every path passage as a |
| | 6478 | separate nested room, so this message seeks to convey that the action |
| | 6479 | might be logical in the real-world but isn't required in the game. |
| | 6480 | |
| | 6481 | </div> |
| | 6482 | |
| | 6483 | <!-------------------> |
| | 6484 | <div class=entry> |
| | 6485 | |
| | 6486 | Actor now handles a command of the form PUT ME IN <i>container</i> by |
| | 6487 | replacing it with ENTER <i>container</i>. This is done any time the |
| | 6488 | direct object is the target actor. |
| | 6489 | |
| | 6490 | <p>In addition, the actor is now excluded in all cases from being the |
| | 6491 | default direct object for PUT IN. In the past, the actor was selected |
| | 6492 | as the default if there was nothing better, which occasionally led to |
| | 6493 | odd results. |
| | 6494 | |
| | 6495 | </div> |
| | 6496 | |
| | 6497 | <!-------------------> |
| | 6498 | <div class=entry> |
| | 6499 | |
| | 6500 | Actor now treats the commands PUT ON and PUT UNDER as illogical when |
| | 6501 | applied to oneself (as in PUT ME ON THE TABLE). |
| | 6502 | |
| | 6503 | </div> |
| | 6504 | |
| | 6505 | <!-------------------> |
| | 6506 | <div class=entry> |
| | 6507 | |
| | 6508 | Thing now calls verifyMoveTo() to verify a DROP command <i>only</i> |
| | 6509 | when the object is being held by the actor performing the command. |
| | 6510 | When the object isn't being held, the DROP will be illogical on that |
| | 6511 | basis alone - the object definitely won't be moved, so there's no |
| | 6512 | reason to verify the move. This is important because some subclasses |
| | 6513 | use verifyMoveTo() to report other catch-all conditions ("that's too |
| | 6514 | heavy to move," etc), which in the past sometimes were reported |
| | 6515 | instead of the more basic problem ("you're not holding that"). By |
| | 6516 | avoiding the call to verifyMoveTo() when the object isn't being held, |
| | 6517 | we ensure that the more basic problem is always reported instead of |
| | 6518 | any applicable catch-all condition. |
| | 6519 | |
| | 6520 | </div> |
| | 6521 | |
| | 6522 | <!-------------------> |
| | 6523 | <div class=entry> |
| | 6524 | |
| | 6525 | The Immovable class incorrectly handled certain two-object actions |
| | 6526 | (such as PUT IN, PUT ON, MOVE WITH) by failing in the action() |
| | 6527 | routine. This still allowed the <i>other</i> object involved in the |
| | 6528 | command to handle the action successfully. For these two-object |
| | 6529 | actions, the class needs to block the action in the check() routine |
| | 6530 | instead, which it now does. |
| | 6531 | |
| | 6532 | </div> |
| | 6533 | |
| | 6534 | <!-------------------> |
| | 6535 | <div class=entry> |
| | 6536 | |
| | 6537 | When an AgendaItem throws an exception (including things like 'exit' |
| | 6538 | signals) out of its invokeItem() method, the library now automatically |
| | 6539 | marks the agenda item as finished (by setting its isDone property to |
| | 6540 | true). In most cases, if an agenda item throws an exception, it's |
| | 6541 | because something went wrong; since the same thing would probably go |
| | 6542 | wrong again if the item were tried again, allowing the agenda item to |
| | 6543 | remain in its "ready" state typically resulted in an infinite loop as |
| | 6544 | the actor kept trying the same item over and over. This change avoids |
| | 6545 | infinite loops in these cases by ensuring that an item that throws an |
| | 6546 | error isn't retried automatically. |
| | 6547 | |
| | 6548 | </div> |
| | 6549 | |
| | 6550 | <!-------------------> |
| | 6551 | <div class=entry> |
| | 6552 | |
| | 6553 | When an object provides its own custom definition for a library |
| | 6554 | message (via one of the xxxMsg properties), it can now be defined as a |
| | 6555 | simple single-quoted string, even if the library method for the |
| | 6556 | message normally takes one or more arguments. This makes it more |
| | 6557 | convenient to define these custom messages. Of course, you can still |
| | 6558 | provide a full method definition that takes the same arguments as the |
| | 6559 | corresponding library message method. |
| | 6560 | |
| | 6561 | </div> |
| | 6562 | |
| | 6563 | <!-------------------> |
| | 6564 | <div class=entry> |
| | 6565 | |
| | 6566 | Settable now applies a touchObj precondition to the SetTo action. |
| | 6567 | This ensures, for example, that a dial is reachable before it can be |
| | 6568 | turned to a new setting. |
| | 6569 | |
| | 6570 | </div> |
| | 6571 | |
| | 6572 | <!-------------------> |
| | 6573 | <div class=entry> |
| | 6574 | |
| | 6575 | The Floor class now includes a touchObj precondition for StandOn, |
| | 6576 | SitOn, LieOn, and (as an indirect object for) PutOn. This ensures |
| | 6577 | that a floor in a connected but unreachable room (such as a room |
| | 6578 | connected by distance) will be ruled out as a potential target object |
| | 6579 | for these verbs, avoiding poor defaults and unnecessary disambiguation |
| | 6580 | prompts. |
| | 6581 | |
| | 6582 | </div> |
| | 6583 | |
| | 6584 | <!-------------------> |
| | 6585 | <div class=entry> |
| | 6586 | |
| | 6587 | The touchObj precondition now considers a distant object illogical |
| | 6588 | during its 'verify' phase. |
| | 6589 | |
| | 6590 | <p>In the past, this precondition treated an object that was visible |
| | 6591 | but not reachable as still potentially logical, but at reduced |
| | 6592 | likelihood. The reasoning was that the obstruction might be easily |
| | 6593 | removable via an implied action. For example, an object inside an |
| | 6594 | openable glass case could be made touchable by opening the glass |
| | 6595 | case, which could be performed as an implied action. However, in |
| | 6596 | the case of distance, there's not usually any way to remove the |
| | 6597 | obstruction automatically, so there's no point in considering the |
| | 6598 | object to be logical, even at reduced likelihood. The precondition |
| | 6599 | still does exactly this for objects that aren't at a distance, but |
| | 6600 | now assumes that distance can't be resolved automatically. |
| | 6601 | |
| | 6602 | </div> |
| | 6603 | |
| | 6604 | <!-------------------> |
| | 6605 | <div class=entry> |
| | 6606 | |
| | 6607 | In the past, if the player used a SEARCH command on an Openable, and |
| | 6608 | the object was closed, the implied OPEN action showed the |
| | 6609 | newly-revealed contents of the object. The main SEARCH command that |
| | 6610 | triggered the OPEN also showed the Openable's contents, so the |
| | 6611 | contents were listed twice. Openable now omits the redundant contents |
| | 6612 | listing for the implied OPEN when the main command is SEARCH, just as |
| | 6613 | it's long done when the main command is LOOK IN. |
| | 6614 | |
| | 6615 | </div> |
| | 6616 | |
| | 6617 | <!-------------------> |
| | 6618 | <div class=entry> |
| | 6619 | |
| | 6620 | A "conversational" command (HELLO, GOODBYE, YES, NO) now consistently |
| | 6621 | counts as a turn for the issuing actor, even when a target actor is |
| | 6622 | specified (as in "BOB, HELLO"). This corrects a subtle inconsistency |
| | 6623 | that occurred when a conversational command was directed to an NPC |
| | 6624 | that had a pending agenda item. In the past, explicitly directing a |
| | 6625 | conversational command to such an actor ("BOB, HELLO") prevented the |
| | 6626 | agenda item from executing on the same turn, because specifying the |
| | 6627 | target actor caused the turn to count against the NPC's turn counter |
| | 6628 | rather than the PC's; but leaving out the target actor (as in saying |
| | 6629 | simply "HELLO") counted the action as a PC turn, allowing the NPC to |
| | 6630 | carry out its agenda item. Now, both forms of the command ("HELLO" |
| | 6631 | and "BOB, HELLO") have the same turn-counting treatment, so a pending |
| | 6632 | agenda item will be allowed to proceed in either case. |
| | 6633 | |
| | 6634 | </div> |
| | 6635 | |
| | 6636 | <!-------------------> |
| | 6637 | <div class=entry> |
| | 6638 | |
| | 6639 | The HELLO, GOODBYE, YES, and NO commands now find a suitable default |
| | 6640 | actor to talk to if the target actor isn't specified (that is, if the |
| | 6641 | command entered is simply something like "HELLO" rather than "BOB, |
| | 6642 | HELLO"). If there's a current interlocutor, and it's still within |
| | 6643 | earshot, then it's the default. Otherwise, we look for a suitable |
| | 6644 | default direct object for a TALK TO command. This makes things more |
| | 6645 | convenient for the player, since it allows the player to omit the |
| | 6646 | target actor any time only one suitable actor is present. |
| | 6647 | |
| | 6648 | </div> |
| | 6649 | |
| | 6650 | <!-------------------> |
| | 6651 | <div class=entry> |
| | 6652 | |
| | 6653 | In the past, saying BYE to an actor in a conversation-ready state |
| | 6654 | (that is, an actor ready for a stateful conversation, but not |
| | 6655 | currently in conversation) caused a run-time error. This has been |
| | 6656 | corrected. |
| | 6657 | |
| | 6658 | </div> |
| | 6659 | |
| | 6660 | <!-------------------> |
| | 6661 | <div class=entry> |
| | 6662 | |
| | 6663 | Non-conversational topic entries (those with the isConversational |
| | 6664 | property set to nil) now leave the actor's ConvNode unchanged. |
| | 6665 | Conceptually, a response that doesn't involve any conversation |
| | 6666 | shouldn't affect the thread of an ongoing conversation, so it |
| | 6667 | makes more sense for such topics to leave the ConvNode unchanged. |
| | 6668 | |
| | 6669 | </div> |
| | 6670 | |
| | 6671 | <!-------------------> |
| | 6672 | <div class=entry> |
| | 6673 | |
| | 6674 | In the past, Thing.lookAroundWithin() generated a slightly strange |
| | 6675 | description when the point of view was a remote room, and the room |
| | 6676 | containing the actor doing the looking was visible from the remote |
| | 6677 | room. In these cases, the actors were described as being "here" ( as |
| | 6678 | in "Bob is standing here"), even though the "here" in this kind of |
| | 6679 | description is more properly the remote point-of-view room. The |
| | 6680 | actors are now described as though they're in a remote room ("Bob is |
| | 6681 | standing in the cave"), which is consistent with the perspective of |
| | 6682 | the rest of the description. |
| | 6683 | |
| | 6684 | </div> |
| | 6685 | |
| | 6686 | <!-------------------> |
| | 6687 | <div class=entry> |
| | 6688 | |
| | 6689 | In the past, no turn was counted for giving an actor an order (BOB, GO |
| | 6690 | NORTH) that was refused in the actor's obeyCommand() method. This |
| | 6691 | didn't entirely make sense, since merely attempting to give an order |
| | 6692 | to an actor is an in-game action, from the player's perspective. This |
| | 6693 | has been changed so that giving an order that's refused counts as one |
| | 6694 | turn. |
| | 6695 | |
| | 6696 | </div> |
| | 6697 | |
| | 6698 | <!-------------------> |
| | 6699 | <div class=entry> |
| | 6700 | |
| | 6701 | In the past, if an actor was in an accompanying-travel state, carrying |
| | 6702 | the actor and then traveling to a new room caused a run-time error. |
| | 6703 | The run-time error has been fixed. |
| | 6704 | |
| | 6705 | <p>In addition, the accompanying-travel state is now ignored when the |
| | 6706 | actor is being carried. When an NPC is being carried, it will |
| | 6707 | naturally move along with the actor it's accompanying, just as all of |
| | 6708 | the actor's other inventory items do by virtue of being carried. We |
| | 6709 | therefore don't want the NPC to separately travel to the new location, |
| | 6710 | because doing so makes the actor drop the NPC. |
| | 6711 | |
| | 6712 | </div> |
| | 6713 | |
| | 6714 | <!-------------------> |
| | 6715 | <div class=entry> |
| | 6716 | |
| | 6717 | Thing now defines the methods canSee(obj), canHear(obj), and |
| | 6718 | canSmell(obj). In the past, these were defined only by Actor, not by |
| | 6719 | Thing, since only actors have senses that allow perception of the |
| | 6720 | physical surroundings. In some cases, though, an actor uses an |
| | 6721 | inanimate device as a point of view (a television monitor hooked up to |
| | 6722 | a remote camera, for example), and in these cases it's necessary to |
| | 6723 | check visibility (or other senses) from one inanimate object to |
| | 6724 | another. The new methods provide this capability. They can be |
| | 6725 | overridden as needed; for example, a camera that operates in the |
| | 6726 | infrared might want to override canSee() to calculate visibility in a |
| | 6727 | custom "infraredSight" sense rather than in the basic "sight" sense. |
| | 6728 | |
| | 6729 | </div> |
| | 6730 | |
| | 6731 | <!-------------------> |
| | 6732 | <div class=entry> |
| | 6733 | |
| | 6734 | The NOTE command is now ignored for the purposes of the AGAIN command. |
| | 6735 | For example, if you type INVENTORY, then type NOTE SOMETHING, then |
| | 6736 | type AGAIN, the game will repeat the INVENTORY command. There's no |
| | 6737 | point in repeating a NOTE command, and NOTE is a sort of side |
| | 6738 | conversation between player and author anyway, so it makes sense for |
| | 6739 | AGAIN to act like the NOTE never happened. |
| | 6740 | |
| | 6741 | </div> |
| | 6742 | |
| | 6743 | <!-------------------> |
| | 6744 | <div class=entry> |
| | 6745 | |
| | 6746 | The SAVE command is now ignored for the purposes of AGAIN. There's no |
| | 6747 | point in repeating a SAVE command immediately, as nothing will have |
| | 6748 | changed in the game state between two consecutive SAVE commands, and |
| | 6749 | hence no re-saving is warranted. |
| | 6750 | |
| | 6751 | </div> |
| | 6752 | |
| | 6753 | <!-------------------> |
| | 6754 | <div class=entry> |
| | 6755 | |
| | 6756 | After a game is successfully restored, the memory of the previous |
| | 6757 | command is forgotten, so the AGAIN command cannot be used. This |
| | 6758 | ensures that there's no confusion about whether AGAIN refers back to |
| | 6759 | the RESTORE command (which would be pointless, as it would just |
| | 6760 | re-restore the same state), the previous command in the same session, |
| | 6761 | or the last command before SAVE from the restored game. |
| | 6762 | |
| | 6763 | </div> |
| | 6764 | |
| | 6765 | <!-------------------> |
| | 6766 | <div class=entry> |
| | 6767 | |
| | 6768 | When a "finish options" menu is presented (with finishGame() or |
| | 6769 | finishGameMsg()), and the player selects the UNDO option, the library |
| | 6770 | now treats UNDO as the last command for the purposes of AGAIN. That |
| | 6771 | is, if the player answers a finish-options prompt with UNDO, and then |
| | 6772 | types AGAIN, the library performs another UNDO. (In the past, the |
| | 6773 | game repeated the command that led to the finish-options prompt, since |
| | 6774 | that was the last actual command. However, most players wouldn't |
| | 6775 | think to make this distinction, and wouldn't want to repeat whatever |
| | 6776 | command led to the game-ending prompt anyway, so the most reasonable |
| | 6777 | interpretation of an immediate AGAIN is to perform another UNDO.) |
| | 6778 | |
| | 6779 | </div> |
| | 6780 | |
| | 6781 | <!-------------------> |
| | 6782 | <div class=entry> |
| | 6783 | |
| | 6784 | The RESTORE command is now ignored for the purposes of the UNDO |
| | 6785 | command. When a RESTORE succeeds, there's no way to undo anything: |
| | 6786 | the restore itself can't be undone, and the incoming restored state |
| | 6787 | initially doesn't have any undo history. When the RESTORE fails, it |
| | 6788 | won't make any changes to the game state, so there's nothing about the |
| | 6789 | RESTORE itself to undo. The main effect of this change is that typing |
| | 6790 | UNDO after a failed RESTORE undoes the last undoable command |
| | 6791 | immediately before the RESTORE. |
| | 6792 | |
| | 6793 | </div> |
| | 6794 | |
| | 6795 | <!-------------------> |
| | 6796 | <div class=entry> |
| | 6797 | |
| | 6798 | In the past, if the player typed an OOPS command at the wrong time |
| | 6799 | (when there wasn't any spelling error to correct), it was counted as a |
| | 6800 | turn. This was undesirable because OOPS is a meta command, not an |
| | 6801 | in-game action. The command no longer counts as a turn. |
| | 6802 | |
| | 6803 | </div> |
| | 6804 | |
| | 6805 | <!-------------------> |
| | 6806 | <div class=entry> |
| | 6807 | |
| | 6808 | In the English library, a string pre-parser now wraps the comment text |
| | 6809 | of a NOTE command in quotation marks, <i>if</i> the text contains any |
| | 6810 | punctuation marks or the word THEN. This allows players to enter |
| | 6811 | arbitrary free-form text in NOTE remarks without any danger of |
| | 6812 | confusing the parser. |
| | 6813 | |
| | 6814 | </div> |
| | 6815 | |
| | 6816 | <!-------------------> |
| | 6817 | <div class=entry> |
| | 6818 | |
| | 6819 | The formatting in the English instructions has been tweaked slightly |
| | 6820 | to make it more consistent. In addition, the parsing of the responses |
| | 6821 | to the INSTRUCTIONS prompt had a couple of small problems that have |
| | 6822 | now been corrected. |
| | 6823 | |
| | 6824 | </div> |
| | 6825 | |
| | 6826 | <!-------------------> |
| | 6827 | <div class=entry> |
| | 6828 | |
| | 6829 | A bug in the English library caused message substitution strings of |
| | 6830 | form "{it's dobj/he's}" (that is, with an apostrophe-S on each example |
| | 6831 | word, and the parameter name written in the middle of the two example |
| | 6832 | words) to be expanded incorrectly. This has been corrected. |
| | 6833 | |
| | 6834 | </div> |
| | 6835 | |
| | 6836 | <!-------------------> |
| | 6837 | <div class=entry> |
| | 6838 | |
| | 6839 | In the English library, the methods (theNamePossNoun, theNamePossAdj) |
| | 6840 | that build the default possessive name based on the base name of an |
| | 6841 | object now add an apostrophe-S to a plural name that doesn't end in |
| | 6842 | "s". In the past, a bare apostrophe was always added to a plural |
| | 6843 | name, which produced the wrong results for certain words (the men', |
| | 6844 | the children', the fish'). |
| | 6845 | |
| | 6846 | </div> |
| | 6847 | |
| | 6848 | <!-------------------> |
| | 6849 | <div class=entry> |
| | 6850 | |
| | 6851 | The English library's method that builds the default plural name of |
| | 6852 | an object (pluralNameFrom) now handles abbreviations more in keeping |
| | 6853 | with conventional English usage: |
| | 6854 | |
| | 6855 | <ul> |
| | 6856 | |
| | 6857 | <li>For single letters, the method now adds an apostrophe-S to small |
| | 6858 | letters (a's, b's, c's) and to the capital letters A, E, I, M, U, and |
| | 6859 | V (A's, E's, etc). For other capital letters, and for non-letters, |
| | 6860 | the method simply adds an "s" (Bs, Cs, Ds). (The apostrophe-S |
| | 6861 | capitals are special because they could be confused with words or |
| | 6862 | common abbreviations if we just added an "s".) |
| | 6863 | |
| | 6864 | <li>For words that end in a capital letters or a digit, the method now |
| | 6865 | just adds "s" (CPAs, PCs, MPs, 1970s, 20s). |
| | 6866 | |
| | 6867 | <li>For words that end in a period, the method adds apostrophe-S |
| | 6868 | (Ph.D.'s, M.A.'s). |
| | 6869 | |
| | 6870 | </ul> |
| | 6871 | |
| | 6872 | </div> |
| | 6873 | |
| | 6874 | <!-------------------> |
| | 6875 | <div class=entry> |
| | 6876 | |
| | 6877 | The new Thing property objInPrep can be used to specify the |
| | 6878 | preposition to use when describing another object as being within a |
| | 6879 | given object. In the English library, the default for Thing is 'in'. |
| | 6880 | Note that the existing property actorInPrep is now defined by default |
| | 6881 | as returning the same value as the new objInPrep, since for most |
| | 6882 | purposes they have the same meaning. |
| | 6883 | |
| | 6884 | </div> |
| | 6885 | |
| | 6886 | <!-------------------> |
| | 6887 | <div class=firstentry> |
| | 6888 | |
| | 6889 | A new message is displayed when a Throw command fails because a |
| | 6890 | DistanceConnector is in the way. In the past, the library used the |
| | 6891 | default Thing message, which describes the projectile as bouncing |
| | 6892 | off the object that's in the way. In the case of a distance connector, |
| | 6893 | this doesn't make any sense. The library now uses a custom message |
| | 6894 | that describes the projectile as falling short of the target. |
| | 6895 | |
| | 6896 | </div> |
| | 6897 | |
| | 6898 | <!-------------------> |
| | 6899 | <div class=firstentry> |
| | 6900 | |
| | 6901 | In the past, if an object was thrown through a MultiLoc connector to a |
| | 6902 | separate top-level room, the object sometimes incorrectly landed on |
| | 6903 | the originating side of the connector rather than on the target side. |
| | 6904 | This only happened when the MultiLoc was a peer of the target. The |
| | 6905 | thrown object now correctly lands within the target's top-level |
| | 6906 | location rather than within the origin's top-level room. |
| | 6907 | |
| | 6908 | </div> |
| | 6909 | |
| | 6910 | <!-------------------> |
| | 6911 | <div class=entry> |
| | 6912 | |
| | 6913 | The ComplexContainer class now refers the methods isOpen, isLocked, |
| | 6914 | makeOpen, and makeLocked to the subContainer, if it's non-nil. A |
| | 6915 | complex container appears in the game world as effectively enclosing |
| | 6916 | the contents of its sub-container, because the sub-container doesn't |
| | 6917 | usually appear as a distinct object in the game world, so the apparent |
| | 6918 | open and locked status of the complex container are almost always the |
| | 6919 | same as for its sub-container. These new referrals make it a little |
| | 6920 | easier to write code by removing the need to refer explicitly to the |
| | 6921 | sub-container when checking or changing the open or locked status of a |
| | 6922 | complex container. |
| | 6923 | |
| | 6924 | </div> |
| | 6925 | |
| | 6926 | <!-------------------> |
| | 6927 | <div class=entry> |
| | 6928 | |
| | 6929 | An error in BasicOpenable.makeOpen() caused a run-time error ("wrong |
| | 6930 | number of arguments") in certain cases when a BasicOpenable was used |
| | 6931 | with multiple inheritance. In particular, the error ocurred when an |
| | 6932 | object derived from BasicOpenable also had at least one additional |
| | 6933 | superclass which itself defined makeOpen(), and the additional |
| | 6934 | superclass was placed after the BasicOpenable subclass in the object's |
| | 6935 | superclass list. This has been fixed. |
| | 6936 | |
| | 6937 | </div> |
| | 6938 | |
| | 6939 | <!------------------------------- 3.0.7 ---------------------------------> |
| | 6940 | <div class="sepbar"><a name='307'></a>3.0.7</div> |
| | 6941 | <p><b><i>Released 6/12/2004</i></b> |
| | 6942 | <p> |
| | 6943 | |
| | 6944 | <div class=firstentry> |
| | 6945 | |
| | 6946 | The default rules in Thing and NonPortable for contentsListed and |
| | 6947 | contentsListedInExamine weren't quite right, so they've been changed |
| | 6948 | slightly. The new default rules are that an object's contents are |
| | 6949 | <i>always</i> listed when the object is directly examined, and they're |
| | 6950 | listed in "indirect" examinations if (1) the object is itself |
| | 6951 | mentioned somehow in the indirect description, and (2) its contents |
| | 6952 | would be listed in a direct examination. |
| | 6953 | |
| | 6954 | <p>(A couple of definitions might help. A "direct examination" is |
| | 6955 | what happens when the player explicitly EXAMINEs the object; an |
| | 6956 | "indirect examination" occurs when looking at the room, showing an |
| | 6957 | inventory listing, or directly examining an enclosing object. An |
| | 6958 | object is "mentioned somehow" in an indirect description if either (1) |
| | 6959 | it's included in the basic generated list of portable items within the |
| | 6960 | enclosing object that's being examined, as determined by the isListed |
| | 6961 | property, or (2) it shows as special description, as determined by the |
| | 6962 | useSpecialDesc method.) |
| | 6963 | |
| | 6964 | <p>The reasoning behind the new rules is as follows. First, on |
| | 6965 | directly examining an object, its contents should almost always be |
| | 6966 | mentioned; we'd want to conceal the contents only in unusual cases, so |
| | 6967 | the default for contentsListedInExamine is simply 'true'. Second, |
| | 6968 | when indirectly examining an object, we'd normally want its contents |
| | 6969 | to be included in the description, since they're also, indirectly, the |
| | 6970 | contents of the enclosing object being examined; however, when the |
| | 6971 | object itself isn't mentioned in the indirect examination, then we |
| | 6972 | probably don't want to mention its contents, either. Furthermore, |
| | 6973 | if for some reason we've chosen to conceal the contents even when |
| | 6974 | the object is directly examined, then we almost certainly want to |
| | 6975 | conceal the contents in indirect examinations as well. |
| | 6976 | |
| | 6977 | <p>The rule is slightly different, and simpler, in NonPortable: |
| | 6978 | contentsListed simply returns the value of contentsListedInExamine. |
| | 6979 | The reason for this different default is that a NonPortable is almost |
| | 6980 | always a fixed feature of its enclosing objects, and as such is |
| | 6981 | almost always mentioned, to the extent it merits mentioning, as part |
| | 6982 | of the custom description of the room or containing object. This is |
| | 6983 | sometimes accomplished with a specialDesc, but not always, so the |
| | 6984 | absence of a specialDesc isn't sufficient reason to think that the |
| | 6985 | object isn't mentioned. Since a NonPortable almost always gets some |
| | 6986 | kind of mention in indirect examinations, then, the default is that |
| | 6987 | its contents are listed in these cases, too, as long as they'd be |
| | 6988 | listed in a direct examination. |
| | 6989 | |
| | 6990 | </div> |
| | 6991 | |
| | 6992 | <!-------------------> |
| | 6993 | <div class=entry> |
| | 6994 | |
| | 6995 | The Consultable class now requires that the object be both touchable |
| | 6996 | and visible for the Consult action (in the past, it only had to be |
| | 6997 | touchable). Consultables are typically things like books or maps |
| | 6998 | whose contents are read visually, so in most cases it only makes sense |
| | 6999 | to consult a consultable when it's visible. This change prevents |
| | 7000 | lookup up information in a consultable while in the dark, for example. |
| | 7001 | |
| | 7002 | </div> |
| | 7003 | |
| | 7004 | <!-------------------> |
| | 7005 | <div class=entry> |
| | 7006 | |
| | 7007 | The new property disambigPromptOrder can be given to any VocabObject |
| | 7008 | (any simulation object with vocabulary words) to control its ordering |
| | 7009 | in an interactive disambiguation prompt ("Which book do you mean, the |
| | 7010 | red book, or the blue book?"). When a disambiguation prompt is shown, |
| | 7011 | the objects in the prompt are listed in ascending order of this |
| | 7012 | property value. By default, disambigPromptOrder is 100; since all |
| | 7013 | objects have this same default, if you don't override it for any |
| | 7014 | objects, the ordering of disambiguation lists will be arbitrary. |
| | 7015 | |
| | 7016 | <p>Arbitrary ordering is usually fine. However, it's nice to be able |
| | 7017 | to control the order when objects have ordinals in their names ("first |
| | 7018 | book," "third button," etc), to make the list order match the nominal |
| | 7019 | order. For example, if you have a group of books named "first book," |
| | 7020 | "second book," and "third book," you could give these objects |
| | 7021 | disambigPromptOrder values of 101, 102, and 103, respectively. |
| | 7022 | |
| | 7023 | </div> |
| | 7024 | |
| | 7025 | <!-------------------> |
| | 7026 | <div class=entry> |
| | 7027 | |
| | 7028 | When the parser processes a response to an interactive disambiguation |
| | 7029 | question ("Which book do you mean..."), it now takes a vocabulary |
| | 7030 | match to an ordinal name as superseding the alternative interpretation |
| | 7031 | as a list position. For example: |
| | 7032 | |
| | 7033 | <p><pre> |
| | 7034 | Which book do you mean, the red book, the first black book, or the |
| | 7035 | second black book? |
| | 7036 | <br> |
| | 7037 | <br> >second |
| | 7038 | </pre> |
| | 7039 | |
| | 7040 | <p>The parser will now interpret "second" as referring to "second black |
| | 7041 | book." In the past, it took this to mean the second item in the list, |
| | 7042 | which in this case is "first black book"; this is hardly ever what |
| | 7043 | the player means in these cases, though. |
| | 7044 | |
| | 7045 | <p>(This change is actually a bug fix. The parser already had logic |
| | 7046 | to apply this precedence order, but it didn't work properly. In |
| | 7047 | particular, the "adjective ending" preference - the preference for |
| | 7048 | avoiding a phrase that ends in an adjective - superseded the ordinal |
| | 7049 | preference. Adjective endings are obviously not a problem for |
| | 7050 | disambiguation responses, though, so this has been changed.) |
| | 7051 | |
| | 7052 | </div> |
| | 7053 | |
| | 7054 | <!-------------------> |
| | 7055 | <div class=entry> |
| | 7056 | |
| | 7057 | When the parser asks the player for disambiguation help to choose |
| | 7058 | among several items that can be distinguished only by their location, |
| | 7059 | and some of the items are in different top-level locations from the |
| | 7060 | player character, the parser now describes the remote locations using |
| | 7061 | the remote room names (rather than with the default "floor" or |
| | 7062 | "ground" container, as was formerly the case). This helps ensure |
| | 7063 | that objects are distinguished properly when several top-level |
| | 7064 | rooms are connected by sense connectors. |
| | 7065 | |
| | 7066 | <p><pre> |
| | 7067 | Which coin do you mean, the one on the floor, or the one on the |
| | 7068 | balcony? |
| | 7069 | </pre> |
| | 7070 | |
| | 7071 | <p>In a related change, the parser now chooses a "local" |
| | 7072 | interpretation of a locational qualifier in cases of ambiguity. For |
| | 7073 | example, if the player were to answer the question above with "the one |
| | 7074 | on the floor," the parser would now assume that the player is talking |
| | 7075 | about the coin in the local location (i.e., within the player |
| | 7076 | character's top-level enclosing room). In the past, if the balcony |
| | 7077 | also had a floor, the locational qualifier would have been ambiguous. |
| | 7078 | |
| | 7079 | </div> |
| | 7080 | |
| | 7081 | <!-------------------> |
| | 7082 | <div class=entry> |
| | 7083 | |
| | 7084 | The new function dataTypeXlat(val), defined in the system library file |
| | 7085 | _main.t, returns the "translated" datatype for the given value. This |
| | 7086 | is almost identical to dataType(val), except that when 'val' is an |
| | 7087 | anonymous function, the new dataTypeXlat() returns TypeFuncPtr rather |
| | 7088 | than TypeObject. In most cases, it's convenient to treat an anonymous |
| | 7089 | function pointer value as though it were an ordinary static function |
| | 7090 | pointer, because the two types are almost interchangeable in their |
| | 7091 | usage; this function makes it easier to code such cases, because you |
| | 7092 | don't have to worry about these two different ways that a |
| | 7093 | function-pointer-like value might appear. |
| | 7094 | |
| | 7095 | </div> |
| | 7096 | |
| | 7097 | <!-------------------> |
| | 7098 | <div class=entry> |
| | 7099 | |
| | 7100 | The new class AskTellShowTopic lets you combine responses for an |
| | 7101 | object for ASK ABOUT, TELL ABOUT, and SHOW TO in a single topic |
| | 7102 | response object. Players sometimes find SHOW TO to be more natural |
| | 7103 | than ASK ABOUT when an object is present and visible; this new class |
| | 7104 | makes it convenient when you want to handle either command the same |
| | 7105 | way. |
| | 7106 | |
| | 7107 | </div> |
| | 7108 | |
| | 7109 | <!-------------------> |
| | 7110 | <div class=entry> |
| | 7111 | |
| | 7112 | A bug in Thing.lookAroundWithinContents caused an infinite loop when |
| | 7113 | attempting to describe a location in which three or more top-level |
| | 7114 | rooms were linked by sense connectors. This is now fixed. |
| | 7115 | |
| | 7116 | </div> |
| | 7117 | |
| | 7118 | <!-------------------> |
| | 7119 | <div class=entry> |
| | 7120 | |
| | 7121 | In 3.0.6q, BulkLimiter defined lookInDesc as doing nothing. This was |
| | 7122 | problematic because BulkLimiter is inherited by some special types of |
| | 7123 | containers, such as Underside and RearSurface, that don't have |
| | 7124 | interiors for the purposes of LOOK IN. The problem showed up in |
| | 7125 | Underside and RearSurface objects: attempting to LOOK IN these |
| | 7126 | objects showed no reply at all, hence yielded the library's default |
| | 7127 | "Nothing obvious happens" message. |
| | 7128 | |
| | 7129 | <p>BulkLimiter no longer defines this property at all. Instead, this |
| | 7130 | functionality has been moved to Container and Surface. Furthermore, |
| | 7131 | BulkLimiter.examineInterior no longer shows the lookInDesc; instead |
| | 7132 | Container and Surface now show the lookInDesc as part of their |
| | 7133 | action() handler for the LOOK IN command. |
| | 7134 | |
| | 7135 | </div> |
| | 7136 | |
| | 7137 | <!-------------------> |
| | 7138 | <div class=entry> |
| | 7139 | |
| | 7140 | The new Thing method hideFromDefault() is similar to hideFromAll(), |
| | 7141 | but indicates that the object should be hidden from being used as a |
| | 7142 | default for the given action (that is, it won't be considered as a |
| | 7143 | possible default when the player types a command that omits one or |
| | 7144 | more required noun phrases). By default, this simply returns what |
| | 7145 | hideFromAll() returns for the same action, since in general an object |
| | 7146 | that's hidden from ALL should also be ignored for defaulting. |
| | 7147 | |
| | 7148 | <p>This is a coarser-grained mechanism than using verify() routines |
| | 7149 | for individual actions, but it's more convenient when you want to |
| | 7150 | exclude an object from being used as a default for a large number of |
| | 7151 | actions. |
| | 7152 | |
| | 7153 | </div> |
| | 7154 | |
| | 7155 | <!-------------------> |
| | 7156 | <div class=entry> |
| | 7157 | |
| | 7158 | gActionIs(a) now returns true if 'a' is one of the specific-direction |
| | 7159 | travel subclasses (NorthAction, SouthAction, etc), and the current |
| | 7160 | action is a base Travel action that's going the same direction. This |
| | 7161 | makes it possible to test for a NORTH command simply by testing |
| | 7162 | gActionIs(North), which is what you would have expected even in past |
| | 7163 | versions if you hadn't known better. |
| | 7164 | |
| | 7165 | <p>(In the past, it was necessary to write a test like this instead: |
| | 7166 | (gActionIs(Travel) && gAction.getDirection == |
| | 7167 | northDirection). This two-part test was required because the grammar |
| | 7168 | rules for NORTH, SOUTH, etc. generate the base Travel action instead |
| | 7169 | of the specific-direction subclasses. The grammar rules still do |
| | 7170 | this, but gActionIs() now calls a new Action method, actionOfKind(), |
| | 7171 | which TravelAction overrides to encapsulate the two-part test; since |
| | 7172 | TravelAction does the test for you, there's no longer any need to |
| | 7173 | write it out by hand. You can still write the two-part test if you |
| | 7174 | prefer, and it still works the same as it did before, but it's easier |
| | 7175 | and clearer to just write gActionIs(North) and the like.) |
| | 7176 | |
| | 7177 | </div> |
| | 7178 | |
| | 7179 | <!-------------------> |
| | 7180 | <div class=entry> |
| | 7181 | |
| | 7182 | The algorithm in Actor.tryMakingRoomToHold has been improved slightly. |
| | 7183 | (This is the routine that automatically frees up space in an actor's |
| | 7184 | hands, when the space is needed for the current explicit action, by |
| | 7185 | moving things being held into "bags of holding.") The change is a bit |
| | 7186 | heuristic, but it should work well in most cases. The new rule: when |
| | 7187 | there are at least four items that can be moved into bags of holding, |
| | 7188 | the routine will now find the two that were picked up most recently |
| | 7189 | and move them to the end of the list of possible items. In practice, |
| | 7190 | it's rare to have to put away more than one or two items for a single |
| | 7191 | action, so this change effectively ensures that the items picked up |
| | 7192 | most recently won't be put away automatically. |
| | 7193 | |
| | 7194 | <p>The point of this change is to avoid annoying situations where the |
| | 7195 | game automatically puts away an object that you just picked up in |
| | 7196 | order to do something with it. These situations were especially |
| | 7197 | annoying when they were entirely automatic (for example, the game |
| | 7198 | picked up an object automatically, then put it away automatically in |
| | 7199 | order to make room to pick up another object automatically, then had |
| | 7200 | to go get the first object out again in order to use it). It was |
| | 7201 | rare for this to happen, but it looked pretty silly when it did. |
| | 7202 | |
| | 7203 | <p>In a related change, the library now arranges the order of putting |
| | 7204 | things away to ensure that if object A goes inside bag of holding B, |
| | 7205 | and B goes inside another bag of holding C, then A will be put in B |
| | 7206 | before B is put in C. This was almost always the result anyway due |
| | 7207 | to affinity ordering, but proper nesting order is now explicitly |
| | 7208 | assured. |
| | 7209 | |
| | 7210 | </div> |
| | 7211 | |
| | 7212 | <!-------------------> |
| | 7213 | <div class=entry> |
| | 7214 | |
| | 7215 | There are two new "illogical" status types that "verify" routines can |
| | 7216 | use to indicate the logicalness of an action with greater precision. |
| | 7217 | The library uses these new types when appropriate in its action handlers. |
| | 7218 | The new types are: |
| | 7219 | |
| | 7220 | <ul> |
| | 7221 | |
| | 7222 | <li>illogicalAlready() - this indicates that the action is illogical |
| | 7223 | because the condition the command seeks to create is already in |
| | 7224 | effect. For example, we're trying to TAKE an object that the actor is |
| | 7225 | already holding, or we're trying to OPEN an object that's already |
| | 7226 | open. This new type is almost the same as illogicalNow(), but |
| | 7227 | provides more detail about the condition. |
| | 7228 | |
| | 7229 | <li>illogicalSelf() - this indicates that the action is illogical |
| | 7230 | because it's attempting to use an object on itself in some invalid |
| | 7231 | way. For example, we're trying to PUT something inside itself. This |
| | 7232 | type is almost the same as illogical(), with the added detail that |
| | 7233 | it's the self-application that makes the command impossible to carry |
| | 7234 | out. |
| | 7235 | |
| | 7236 | </ul> |
| | 7237 | |
| | 7238 | </div> |
| | 7239 | |
| | 7240 | <!-------------------> |
| | 7241 | <div class=entry> |
| | 7242 | |
| | 7243 | The Passage class now considers a closed passage to be invisible in a |
| | 7244 | dark room. The reasoning is that, when a passage is open, enough |
| | 7245 | light from the adjoining room (if the adjoining room is lit) comes |
| | 7246 | through the passage to make the passage itself visible, although not |
| | 7247 | enough comes through to light the current room; but when a passage is |
| | 7248 | closed, not even this small amount of light comes through the passage. |
| | 7249 | |
| | 7250 | </div> |
| | 7251 | |
| | 7252 | <!-------------------> |
| | 7253 | <div class=entry> |
| | 7254 | |
| | 7255 | In the past, the parser matched a plural phrase (such as EXAMINE |
| | 7256 | BOXES) to the most likely subset of the matching in-scope objects, as |
| | 7257 | determined by the "verify" logicalness ranking. This was too |
| | 7258 | restrictive; it wasn't at all the common-sense interpretation that |
| | 7259 | most users would expect from a plural usage, which is simply to match |
| | 7260 | everything that matches the vocabulary. |
| | 7261 | |
| | 7262 | <p>This has been changed. There are two possible behaviors, which you |
| | 7263 | can control via a global configuration property, |
| | 7264 | gameMain.filterPluralMatches: |
| | 7265 | |
| | 7266 | <ul> |
| | 7267 | |
| | 7268 | <li>If gameMain.filterPluralMatches is true, the parser excludes |
| | 7269 | objects from matching the plural phrase if their "verify" routines |
| | 7270 | include an "illogical-already" or an "illogical-self" result. This |
| | 7271 | means, for example, that TAKE BOOKS will exclude any books that are |
| | 7272 | already being held, DROP BOOKS will exclude any books that aren't in |
| | 7273 | the player's inventory. This is the default. |
| | 7274 | |
| | 7275 | <li>If gameMain.filterPluralMatches is nil, the parser simply uses |
| | 7276 | <b>all</b> vocabulary matches for a plural. |
| | 7277 | |
| | 7278 | </ul> |
| | 7279 | |
| | 7280 | </div> |
| | 7281 | |
| | 7282 | <!-------------------> |
| | 7283 | <div class=entry> |
| | 7284 | |
| | 7285 | The English parser now handles pronouns better in the recently-added |
| | 7286 | command phrasing TELL <i>actor</i> TO <i>do something</i>. In |
| | 7287 | particular: |
| | 7288 | |
| | 7289 | <ul> |
| | 7290 | |
| | 7291 | <li>A reflexive pronoun that agrees in number and gender with the |
| | 7292 | actor will be treated as referring to the actor, as long as there's |
| | 7293 | not a valid interpretation internal to the predicate. For example, |
| | 7294 | TELL BOB TO HIT HIMSELF will treat HIMSELF as referring to Bob. |
| | 7295 | However, TELL BOB TO ASK BILL ABOUT HIMSELF will treat HIMSELF as |
| | 7296 | referring to Bill, since that interpretation is entirely |
| | 7297 | self-contained within the predicate. |
| | 7298 | |
| | 7299 | <li>A regular pronoun that agrees in number and gender with the |
| | 7300 | actor will be treated as referring to the actor. This is especially |
| | 7301 | important with possessives: TELL BOB TO DROP HIS BOOK will treat |
| | 7302 | HIS as referring to Bob. |
| | 7303 | |
| | 7304 | <li>A second-person pronoun is now considered to refer to the |
| | 7305 | player character, rather than to the target actor. For example, |
| | 7306 | TELL BOB TO HIT YOU is taken to mean that Bob should hit the player |
| | 7307 | character. |
| | 7308 | |
| | 7309 | <li>The target actor is set as a pronoun antecedent for subsequent |
| | 7310 | commands from the issuing actor. For example, after TELL BOB TO GO |
| | 7311 | NORTH, the command FOLLOW HIM will mean to follow Bob. |
| | 7312 | |
| | 7313 | </ul> |
| | 7314 | |
| | 7315 | </div> |
| | 7316 | |
| | 7317 | <!-------------------> |
| | 7318 | <div class=entry> |
| | 7319 | |
| | 7320 | The English parser now rejects the phrasing TELL <i>first actor</i> TO |
| | 7321 | TELL <i>second actor</i> TO <i>do something</i>. (It formerly |
| | 7322 | accepted this, but it didn't handle it as stated: in effect, the first |
| | 7323 | TELL TO was ignored, so the command was treated as simply TELL |
| | 7324 | <i>second actor</i> TO <i>do something</i>.) |
| | 7325 | |
| | 7326 | </div> |
| | 7327 | |
| | 7328 | <!-------------------> |
| | 7329 | <div class=entry> |
| | 7330 | |
| | 7331 | The English parser now accepts the commands SIT DOWN and LIE DOWN. |
| | 7332 | The parser accepts these stated intransitively (i.e., without a |
| | 7333 | direct object), but treats them as synonyms for SIT ON (something |
| | 7334 | unspecified) and LIE ON (something unspecified), respectively. That |
| | 7335 | is, the parser tries to find a suitable default object to sit on, and |
| | 7336 | prompts the player for the missing object it no default can be |
| | 7337 | assumed. |
| | 7338 | |
| | 7339 | </div> |
| | 7340 | |
| | 7341 | <!-------------------> |
| | 7342 | <div class=entry> |
| | 7343 | |
| | 7344 | In the English parser, when the command phrasing involves what looks |
| | 7345 | like an indirect object phrase that doesn't match anything in the |
| | 7346 | grammar, a "miscellaneous preposition phrase" production is matched. |
| | 7347 | This type of production is now more consistent about reporting that |
| | 7348 | "the story doesn't understand that command," to indicate that the |
| | 7349 | structure of the verb phrase was unrecognized. In the past, if the |
| | 7350 | the direct or indirect object phrases were themselves unresolvable, |
| | 7351 | the parser showed that error instead; this was often less useful, |
| | 7352 | because the root problem in these cases is really that the overall |
| | 7353 | verb phrasing can't be parsed. |
| | 7354 | |
| | 7355 | </div> |
| | 7356 | |
| | 7357 | <!-------------------> |
| | 7358 | <div class=entry> |
| | 7359 | |
| | 7360 | The NOTE command now shows a warning if the transcript isn't |
| | 7361 | currently being saved (with the SCRIPT command). This command's main |
| | 7362 | purpose is to let the player embed a comment in the session |
| | 7363 | transcript, as a means of sending feedback to the author. There's |
| | 7364 | not a lot of point in using the command when the transcript isn't |
| | 7365 | being saved, so there's a good chance that a player using the command |
| | 7366 | thinks that a SCRIPT command is already in effect. The warning calls |
| | 7367 | the player's attention to this. The warning is only issued the first |
| | 7368 | time that NOTE is used without logging in effect, but this is reset |
| | 7369 | each time logging is started and then stopped. |
| | 7370 | |
| | 7371 | </div> |
| | 7372 | |
| | 7373 | <!-------------------> |
| | 7374 | <div class=entry> |
| | 7375 | |
| | 7376 | In the past, real-time events created during pre-initialization |
| | 7377 | weren't set up properly, because the real-time manager's internal |
| | 7378 | clock wasn't initialized until run-time start-up. The clock now |
| | 7379 | has a static initializer, ensuring that events created during preinit |
| | 7380 | will have a valid time base. |
| | 7381 | |
| | 7382 | </div> |
| | 7383 | |
| | 7384 | <!------------------------------- 3.0.6q ---------------------------------> |
| | 7385 | <div class="sepbar"><a name='306q'></a>3.0.6q</div> |
| | 7386 | <p><b><i>Released 5/9/2004</i></b> |
| | 7387 | <p> |
| | 7388 | |
| | 7389 | <div class=firstentry> |
| | 7390 | |
| | 7391 | <p><b>Possible compatibility-breaking change:</b> The standard parser |
| | 7392 | dictionary has been renamed from G_dict to cmdDict (for "command |
| | 7393 | dictionary"). The dictionary is simply an object, and the new name is |
| | 7394 | more consistent with other parser object names (in particular, |
| | 7395 | cmdTokenizer, the standard parser tokenizer). |
| | 7396 | |
| | 7397 | <p>It's relatively uncommon for game code to refer to the main |
| | 7398 | dictionary directly, but you should search your code for references |
| | 7399 | to G_dict and change the name to cmdDict. |
| | 7400 | |
| | 7401 | |
| | 7402 | </div> |
| | 7403 | |
| | 7404 | <!-------------------> |
| | 7405 | <div class=entry> |
| | 7406 | |
| | 7407 | <p><b>Possible compatibility-breaking change:</b> The methods that |
| | 7408 | describe an actor's location have been changed, in order to improve |
| | 7409 | consistency and to simplify the code structure. These changes are |
| | 7410 | mostly internal to the library, so they're unlikely to affect |
| | 7411 | existing code unless you've made some rather low-level customizations. |
| | 7412 | |
| | 7413 | <p>The changes involve a lot of renaming and rerouting of internal |
| | 7414 | method calls. The list of changes below is divided into groups of |
| | 7415 | related changes. |
| | 7416 | |
| | 7417 | <p><b>Group 1:</b> The "nominal actor container" methods have been |
| | 7418 | consolidated into a single method. |
| | 7419 | |
| | 7420 | <ul> |
| | 7421 | |
| | 7422 | <li>The methods getNominalStandingContainer, |
| | 7423 | getNominalSittingContainer, and getNominalLyingContainer have been |
| | 7424 | deleted. In their place is a single new method, |
| | 7425 | getNominalActorContainer, which takes the posture as a parameter. |
| | 7426 | Since it's almost never necessary to differentiate the nominal actor |
| | 7427 | container by posture, the single method approach is more convenient, |
| | 7428 | and it's also more readily extensible to new postures. |
| | 7429 | |
| | 7430 | </ul> |
| | 7431 | |
| | 7432 | <p><b>Group 2:</b> The Posture object has been taken out of the loop, |
| | 7433 | as it were, for the methods that describe actors. The Posture |
| | 7434 | object's role in the past was to break out these various methods into |
| | 7435 | a separate version for each posture, and then further dispatch to the |
| | 7436 | actor's nominal location: for example, the okayPostureChange method |
| | 7437 | was split up into okayStand, okaySit, and okayLie. |
| | 7438 | |
| | 7439 | <p>The original idea was that locations might want to customize |
| | 7440 | extensively by posture, but in practice the multiplicity of methods |
| | 7441 | turned out to be more trouble than it was worth. With the present |
| | 7442 | change, each set of Stand/Sit/Lie variations is now consolidated back |
| | 7443 | into a single method, which makes the Posture object's role |
| | 7444 | unnecessary, allowing it to be removed from the dispatch chain. |
| | 7445 | It's still used in generating the final message, but in most cases |
| | 7446 | this is now a simple matter of getting the posture's participle |
| | 7447 | ("sitting", etc) from the Posture object and using it to build the |
| | 7448 | message string. |
| | 7449 | |
| | 7450 | <p>The following list of changes will look daunting, but it's |
| | 7451 | unlikely that existing game code will be much affected, as these |
| | 7452 | methods were always meant mostly for internal use in the library. |
| | 7453 | |
| | 7454 | <ul> |
| | 7455 | |
| | 7456 | <li>Actor.actorHereDesc changes: |
| | 7457 | |
| | 7458 | <ul> |
| | 7459 | |
| | 7460 | <li>Posture.actorHereDesc and libMessages.actorHereDesc have been |
| | 7461 | deleted. Instead, the actor calls directly to roomActorHereDesc on |
| | 7462 | the nominal actor container. |
| | 7463 | |
| | 7464 | <li>The BasicLocation, Floor, and libMessages methods |
| | 7465 | actorStandingHere, actorSittingHere, and actorLyingHere have been |
| | 7466 | deleted, and replaced by the new method roomActorHereDesc. |
| | 7467 | |
| | 7468 | <li>The libMessages methods actorHereStandingOn, actorHereSittingOn, |
| | 7469 | and actorHereLyingOn have been deleted, and replaced by the new method |
| | 7470 | actorInRoom. |
| | 7471 | |
| | 7472 | </ul> |
| | 7473 | |
| | 7474 | <li>Actor.actorThereDesc changes: |
| | 7475 | |
| | 7476 | <ul> |
| | 7477 | |
| | 7478 | <li>BasicLocation, Floor, and libMessages provide definitions of the |
| | 7479 | new method roomActorThereDesc. |
| | 7480 | |
| | 7481 | <li>NestedRoom.roomRemoteActorDesc has been renamed to |
| | 7482 | roomActorThereDesc, and the implementation has been moved from |
| | 7483 | NestedRoom to BasicLocation. |
| | 7484 | |
| | 7485 | <li>libMessages.nestedRoomRemoteActorDesc has been renamed to |
| | 7486 | actorInRemoteNestedRoom, and libMessages.roomRemoteActorDesc has |
| | 7487 | been renamed to actorInRemoteRoom. |
| | 7488 | |
| | 7489 | </ul> |
| | 7490 | |
| | 7491 | <li>Room status name changes - these affect the mechanism that |
| | 7492 | generates room title addenda such as "(sitting in the chair)": |
| | 7493 | |
| | 7494 | <ul> |
| | 7495 | |
| | 7496 | <li>Posture.statusPosture has been deleted. Instead, the (newly |
| | 7497 | renamed) Actor.actorRoomNameStatus now handles this directly. |
| | 7498 | |
| | 7499 | <li>Actor.statusPosture has been renamed to actorRoomNameStatus, to |
| | 7500 | clarify and reflect the broader potential of its purpose. |
| | 7501 | |
| | 7502 | <li>The BasicLocation, Floor, and libMessages methods |
| | 7503 | statusStanding, statusSitting, and statusLying have been deleted, |
| | 7504 | and replaced by the new method roomActorStatus. |
| | 7505 | |
| | 7506 | <li>The libMessages methods statusStandingOn, statusSittingOn, |
| | 7507 | and statusLyingOn have been deleted, and replaced by the new |
| | 7508 | method actorInRoomStatus. |
| | 7509 | |
| | 7510 | </ul> |
| | 7511 | |
| | 7512 | <li>Actor posture description changes: |
| | 7513 | |
| | 7514 | <ul> |
| | 7515 | |
| | 7516 | <li>Posture.actorPostureDesc has been deleted. Actor now handles |
| | 7517 | this directly. |
| | 7518 | |
| | 7519 | <li>The BasicLocation, Floor, and libMessages methods actorStandingDesc, |
| | 7520 | actorSittingDesc, and actorLyingDesc have been deleted, and replaced |
| | 7521 | with the new method roomActorPostureDesc. |
| | 7522 | |
| | 7523 | <li>The libMessages methods actorStandingOnDesc, actorSittingOnDesc, |
| | 7524 | and actorLyingOnDesc have been deleted, and replaced by the new |
| | 7525 | method roomActorPostureDesc. |
| | 7526 | |
| | 7527 | </ul> |
| | 7528 | |
| | 7529 | <li>Posture change acknowledgment changes - these affect the mechanism |
| | 7530 | that generates the default responses to commands like SIT and STAND: |
| | 7531 | |
| | 7532 | <ul> |
| | 7533 | |
| | 7534 | <li>Posture.okayPostureChange has been deleted. Actor now handles |
| | 7535 | this directly. |
| | 7536 | |
| | 7537 | <li>The BasicLocation and Floor methods okayStand, |
| | 7538 | okaySit, and okayLie have been deleted, and replaced by the new |
| | 7539 | method roomOkayPostureChange. |
| | 7540 | |
| | 7541 | <li>The libMessages methods okayStandMsg, okaySitMsg, and okayLieMsg |
| | 7542 | have been replaced by the new method okayPostureChangeMsg. |
| | 7543 | |
| | 7544 | <li>The playerActionMessages and npcActionMessages methods |
| | 7545 | okayStandOnObjMsg, okaySitOnObjMsg, and okayLieOnObjMsg have |
| | 7546 | been deleted, and replaced by the new method roomOkayPostureChange. |
| | 7547 | |
| | 7548 | </ul> |
| | 7549 | |
| | 7550 | <li>Changes to the mechanism that mentions that an actor is |
| | 7551 | sitting/lying/standing in a nested room, as part of the EXAMINE |
| | 7552 | description of the nested room: |
| | 7553 | |
| | 7554 | <ul> |
| | 7555 | |
| | 7556 | <li>Posture.listActorPosture has been deleted. Actor.listActorPosture |
| | 7557 | now calls the nominal actor container directly instead. |
| | 7558 | |
| | 7559 | <li>The BasicLocation and Floor methods listActorStanding, |
| | 7560 | listActorSitting, and listActorLying have been deleted, and replaced |
| | 7561 | by the new method roomListActorPosture. |
| | 7562 | |
| | 7563 | <li>The libMessages methods listActorStandingOn, listActorSittingOn, |
| | 7564 | and listActorLyingOn have been deleted. Their role has been subsumed |
| | 7565 | by actorInRoom. |
| | 7566 | |
| | 7567 | </ul> |
| | 7568 | |
| | 7569 | </ul> |
| | 7570 | |
| | 7571 | <p><b>Group 3:</b> Actor "grouping" is now handled in BasicLocation, |
| | 7572 | rather than only in NestedRoom. |
| | 7573 | |
| | 7574 | <ul> |
| | 7575 | |
| | 7576 | <li>The implementation of listWithActorIn() that was formerly in |
| | 7577 | BasicChair has been moved to NestedRoom. This means that actors |
| | 7578 | without special descriptions are now grouped by default with other |
| | 7579 | actors without special descriptions who are present in the same |
| | 7580 | location and posture. |
| | 7581 | |
| | 7582 | <li>NestedActorGrouper has been renamed to RoomActorGrouper, since |
| | 7583 | it's now used for any room with actors to be grouped, not just nested |
| | 7584 | rooms. |
| | 7585 | |
| | 7586 | <li>In order to accommodate the wider range of cases where actor |
| | 7587 | group lists are now generated by default, RoomActorGrouper now |
| | 7588 | determines two additional bits of information: it gets the nominal |
| | 7589 | actor container for the location containing the actors being listed, |
| | 7590 | and it checks to see if the point-of-view actor is viewing the |
| | 7591 | listing from a "remote" location (a separate top-level room |
| | 7592 | connected by a sense connector). It uses this information to generate |
| | 7593 | the group prefix and suffix messages differently than before: |
| | 7594 | |
| | 7595 | <ul> |
| | 7596 | |
| | 7597 | <li>If the nominal actor container is visible, the grouper calls the |
| | 7598 | new methods actorInGroupPrefix() and actorInGroupSuffix() on the |
| | 7599 | nominal actor container to generate the prefix and suffix messages. |
| | 7600 | BasicLocation and Floor provide suitable default definitions of these |
| | 7601 | new methods. |
| | 7602 | |
| | 7603 | <li>If the nominal actor container isn't visible, but the actors are |
| | 7604 | in a remote location, the new libMessages methods |
| | 7605 | actorThereGroupPrefix() and actorThereGroupSuffix() are used. |
| | 7606 | |
| | 7607 | <li>Otherwise, the new libMessages methods actorHereGroupPrefix() |
| | 7608 | and actorHereGroupSuffix() are used. |
| | 7609 | |
| | 7610 | </ul> |
| | 7611 | |
| | 7612 | <li>Actor.actorListWith now returns an empty list if 'self' overrides |
| | 7613 | specialDesc. This ensures that a specialDesc defined on the actor |
| | 7614 | will take precedence over any list group applied by the location. |
| | 7615 | (This is more important now that BasicLocation applies actor grouping |
| | 7616 | by default.) |
| | 7617 | |
| | 7618 | <li>Actor.actorHereListWith has been renamed to actorListWith. This |
| | 7619 | method is used whether the actor is local, distant, or remote, but |
| | 7620 | the old name incorrectly suggested the existence of a separate |
| | 7621 | actorThereListWith in parallel with the actorHereDesc/actorThereDesc |
| | 7622 | pair. |
| | 7623 | |
| | 7624 | </ul> |
| | 7625 | |
| | 7626 | <p><b>Group 4:</b> Miscellaneous minor changes to the generation |
| | 7627 | of remote room actor descriptions. |
| | 7628 | |
| | 7629 | <ul> |
| | 7630 | |
| | 7631 | <li>NestedRoom.roomRemoteActorDesc now generates a more elaborate |
| | 7632 | message by default, describing not only the actor's immediate |
| | 7633 | location, but its outermost visible location as well. If the actor's |
| | 7634 | outermost visible location isn't the same as 'self', the method now |
| | 7635 | invokes libMessages.nestedRoomRemoteActorDesc, which generates a |
| | 7636 | message of this form: "Bob is in the dining room, sitting in the |
| | 7637 | chair." |
| | 7638 | |
| | 7639 | <li>The method inRoomName that was formerly defined in Room is now |
| | 7640 | defined in Thing instead. This ensures that a suitable default |
| | 7641 | remote room name will be generated for nested rooms as well as |
| | 7642 | top-level rooms. In addition, the method now simply returns |
| | 7643 | actorInName by default, which ensures that the preposition used in |
| | 7644 | the default remote room name will match the one customized via |
| | 7645 | actorInPrep, if necessary. |
| | 7646 | |
| | 7647 | </ul> |
| | 7648 | |
| | 7649 | </div> |
| | 7650 | |
| | 7651 | <!-------------------> |
| | 7652 | <div class=entry> |
| | 7653 | |
| | 7654 | The new TravelConnector method connectorGetConnectorTo() gives a |
| | 7655 | travel connector a chance to scan any "secondary" connectors it knows |
| | 7656 | about for a connection to a given destination. In some cases, a |
| | 7657 | travel connector encapsulates other travel connectors; these are |
| | 7658 | secondary connectors in the sense that they're linked to the room only |
| | 7659 | from the first connector, and thus the room can't find them on its |
| | 7660 | own. This new method provides a way for a room to query a connector |
| | 7661 | for any secondary connectors it knows about, in order to find a |
| | 7662 | connector to a given destination. The base TravelConnector class |
| | 7663 | provides a default implementation suitable for most subclasses, |
| | 7664 | and AskConnector overrides the method to search its list of |
| | 7665 | secondary connectors. Thing.getConnectorTo calls the new method |
| | 7666 | when searching for a connector to a given destination. |
| | 7667 | |
| | 7668 | <p>The immediate practical benefit of the new method is that it makes |
| | 7669 | it possible for scripted NPC travel to traverse AskConnectors. In the |
| | 7670 | past, an NPC encountering an AskConnector was typically unable to |
| | 7671 | proceed, since the AskConnector didn't directly link to the |
| | 7672 | destinations of its underlying connectors, and the underlying |
| | 7673 | connectors typically weren't linked directly as directions to the |
| | 7674 | enclosing room. This made it impossible for the scripted NPC to find |
| | 7675 | a suitable connector, and thus blocked the scripted travel. |
| | 7676 | |
| | 7677 | </div> |
| | 7678 | |
| | 7679 | <!-------------------> |
| | 7680 | <div class=entry> |
| | 7681 | |
| | 7682 | The properties for choosing whether or not to list the contents of an |
| | 7683 | object to list in EXAMINE and LOOK AROUND descriptions have been |
| | 7684 | expanded slightly to provide more control and better consistency. |
| | 7685 | These changes are all in the Thing class. |
| | 7686 | |
| | 7687 | <p>The isListed property now returns, by default, the value of |
| | 7688 | isListedInContents. The meanings of these properties haven't |
| | 7689 | changed: isListedInContents controls whether or not the object is |
| | 7690 | listed when examining the object's <i>direct</i> container, whereas |
| | 7691 | isListedInContents controls listability for examining <i>indirect</i> |
| | 7692 | containers, including the enclosing room. The reason for this change |
| | 7693 | is that it's rare that we'd want an object to be unlisted when its |
| | 7694 | direct container is examined, but still want it to be listed when |
| | 7695 | enclosing containers are examined (whereas the reverse isn't entirely |
| | 7696 | uncommon, since we sometimes want to mention an object only as a |
| | 7697 | detail of its direct parent, but not of the broader room context). |
| | 7698 | |
| | 7699 | <p>The new property contentsListedInExamine lets you control whether |
| | 7700 | or not an object's direct contents are listed when the object is |
| | 7701 | examined directly. In the past, you could do this only by overriding |
| | 7702 | examineListContents, but the new property makes it easier to control |
| | 7703 | this behavior. The new property returns the same thing that |
| | 7704 | contentsListed used to return. |
| | 7705 | |
| | 7706 | <p>The contentsListed property now returns the value of |
| | 7707 | contentsListedInExamine by default. This is parallel to the change |
| | 7708 | to isListed. |
| | 7709 | |
| | 7710 | <p>The new method getListedContentsInExamine() returns the list of |
| | 7711 | direct contents that should be listed when the object is examined. |
| | 7712 | This new method is the direct-examination equivalent of the existing |
| | 7713 | getListedContents() method, and returns the same value that |
| | 7714 | getListedContents() formerly returned: the subset of direct contents |
| | 7715 | that appear in the sense info table passed to the method. |
| | 7716 | |
| | 7717 | <p>The getListedContents() method now simply returns the result |
| | 7718 | of calling getListedContentsInExamine(). |
| | 7719 | |
| | 7720 | <p>The method examineListContentsWith() now calls |
| | 7721 | getListedContentsInExamine() to obtain the list of direct contents to |
| | 7722 | list when examining an object. In the past, this used the 'contents' |
| | 7723 | property. The method also checks the value of |
| | 7724 | contentsListedInExamine, and skips the entire listing if this |
| | 7725 | property is nil. |
| | 7726 | |
| | 7727 | <p>These changes are all designed to be compatible with existing |
| | 7728 | code. They should simply add more flexibility and make certain |
| | 7729 | behaviors easier to customize, but existing code shouldn't be |
| | 7730 | affected. |
| | 7731 | |
| | 7732 | </div> |
| | 7733 | |
| | 7734 | <!-------------------> |
| | 7735 | <div class=entry> |
| | 7736 | |
| | 7737 | In 3.0.6p, the library started listing the visible, portable contents |
| | 7738 | of "remote" rooms as part of each room description. The |
| | 7739 | implementation had a problem when MultiLoc objects were involved, |
| | 7740 | though: if a MultiLoc object appeared in more than one of the |
| | 7741 | connected top-level rooms <i>and</i> had portable contents, those |
| | 7742 | contents were listed several times - once for each connected |
| | 7743 | top-level room in which the MultiLoc appeared. |
| | 7744 | |
| | 7745 | <p>This problem has been corrected: the room description generator |
| | 7746 | now ensures that a MultiLoc's contents appear only once. To do this, |
| | 7747 | the room description code now excludes each object that is also |
| | 7748 | located in the "local" top-level room <i>or</i> in any connected |
| | 7749 | remote room whose contents listing has already been generated. |
| | 7750 | |
| | 7751 | </div> |
| | 7752 | |
| | 7753 | <!-------------------> |
| | 7754 | <div class=entry> |
| | 7755 | |
| | 7756 | NestedRoom now overrides roomRemoteActorDesc() to describe the actor |
| | 7757 | as being in the nested room. In the past, if the nested room's |
| | 7758 | location was visible, the nested room deferred to the location to |
| | 7759 | provide the description. This produced misleading messages, because |
| | 7760 | it described the actor as being in the outermost visible room |
| | 7761 | containing the actor - which was technically true, but left out the |
| | 7762 | important information about the intermediate nested room. |
| | 7763 | |
| | 7764 | </div> |
| | 7765 | |
| | 7766 | <!-------------------> |
| | 7767 | <div class=entry> |
| | 7768 | |
| | 7769 | Noise and Odor objects no longer include themselves in LISTEN TO ALL |
| | 7770 | and SMELL ALL, respectively. These objects formerly did include |
| | 7771 | themselves in ALL for these commands, since the commands are |
| | 7772 | obviously highly applicable. However, because these objects are |
| | 7773 | intangible, it usually doesn't make sense from the player's |
| | 7774 | perspective to consider them in ALL, which a player usually thinks of |
| | 7775 | as applying to the set of discrete, visible objects. In practice, |
| | 7776 | including these in ALL was often problematic because these intangible |
| | 7777 | objects are usually not given names or vocabulary; they usually exist |
| | 7778 | only to model a feature of their source object, and aren't meant to |
| | 7779 | look like separate objects to the player. |
| | 7780 | |
| | 7781 | <p>Along the same lines, Vaporous objects <i>are</i> now included in |
| | 7782 | EXAMINE ALL, SMELL ALL, and LISTEN TO ALL. These objects do have a |
| | 7783 | visible presence, so it makes sense to include them in commands that |
| | 7784 | examine everything in sight with any sense. |
| | 7785 | |
| | 7786 | <p>For particular Noise and Odor objects that you do want to |
| | 7787 | participate in LISTEN TO ALL and SMELL ALL, just override |
| | 7788 | hideFromAll() to return true for the desired action or actions. |
| | 7789 | |
| | 7790 | </div> |
| | 7791 | |
| | 7792 | <!-------------------> |
| | 7793 | <div class=entry> |
| | 7794 | |
| | 7795 | NonPortable now overrides the inherited Thing verify() handling for |
| | 7796 | EXAMINE to make an un-held NonPortable as likely as a held Thing for |
| | 7797 | disambiguation purposes. |
| | 7798 | |
| | 7799 | <p>Recall that, by default, Thing downgrades the disambiguation |
| | 7800 | likelihood that EXAMINE refers to an object not being held. The |
| | 7801 | reasoning is that an object being held is physically closer to the |
| | 7802 | actor, so in a real-world situation, it would be more convenient to |
| | 7803 | closely inspect an object being held than one sitting nearby. Since |
| | 7804 | NonPortable objects can't be held, though, this reasoning breaks down |
| | 7805 | somewhat. The change removes the disambiguation disadvantage for |
| | 7806 | NonPortable objects. |
| | 7807 | |
| | 7808 | </div> |
| | 7809 | |
| | 7810 | <!-------------------> |
| | 7811 | <div class=entry> |
| | 7812 | |
| | 7813 | The objHeld precondition uses a new Thing method, |
| | 7814 | meetsObjHeld(actor), to determine if the object meets the condition. |
| | 7815 | This new method is called instead of isHeldBy(actor) on the given |
| | 7816 | object. This change allows an object to indicate that it's not |
| | 7817 | <i>actually</i> being held by an actor, but that it's as good as held |
| | 7818 | for the purposes of the objHeld condition. It's rare for |
| | 7819 | meetsObjHeld() to return anything other than isHeldBy(), but does |
| | 7820 | happen occasionally. The most obvious case is body parts: these |
| | 7821 | can't be considered to be held in the actor's hands (unless the actor |
| | 7822 | is specifically doing so for some reason), but at the same time, |
| | 7823 | there's no reason the actor should have to hold a body part in order |
| | 7824 | to carry out actions with objHeld conditions. |
| | 7825 | |
| | 7826 | </div> |
| | 7827 | |
| | 7828 | <!-------------------> |
| | 7829 | <div class=entry> |
| | 7830 | |
| | 7831 | The Wearable class now handles SHOW TO specially: if the object is |
| | 7832 | being worn by the actor doing the showing, it doesn't require that it |
| | 7833 | be held. In the past, the objHeld condition was applied, as it is by |
| | 7834 | default to any portable object, which meant that the character had to |
| | 7835 | take off a wearable in order to show it to someone; this doesn't usually |
| | 7836 | make a lot of sense, thus the change. |
| | 7837 | |
| | 7838 | </div> |
| | 7839 | |
| | 7840 | <!-------------------> |
| | 7841 | <div class=entry> |
| | 7842 | |
| | 7843 | In Thing, remoteSpecialDesc(pov) now calls distantSpecialDesc by |
| | 7844 | default; distantSpecialDesc in turn calls specialDesc by default. In |
| | 7845 | the past, remoteSpecialDesc called specialDesc directly by default. |
| | 7846 | This change leaves the default behavior the same as before, but it |
| | 7847 | simplifies the common case where the "distant" and "remote" |
| | 7848 | descriptions are the same by letting a single override - |
| | 7849 | distantSpecialDesc - handle both descriptions. |
| | 7850 | |
| | 7851 | <p>Similarly, remoteInitSpecialDesc(pov) now calls |
| | 7852 | distantInitSpecialDesc by default (rather than initSpecialDesc, as it |
| | 7853 | did in the past). |
| | 7854 | |
| | 7855 | </div> |
| | 7856 | |
| | 7857 | <!-------------------> |
| | 7858 | <div class=entry> |
| | 7859 | |
| | 7860 | Room now treats the GetOutOf action as equivalent to Out. (This |
| | 7861 | means that if the room has vocabulary, the player can now say "get |
| | 7862 | out of (room)" as a synonym for "out".) |
| | 7863 | |
| | 7864 | </div> |
| | 7865 | |
| | 7866 | <!-------------------> |
| | 7867 | <div class=entry> |
| | 7868 | |
| | 7869 | The English verb grammar now accepts LEAVE as a synonym for EXIT. |
| | 7870 | |
| | 7871 | </div> |
| | 7872 | |
| | 7873 | <!-------------------> |
| | 7874 | <div class=entry> |
| | 7875 | |
| | 7876 | The English parser now accepts "A" and "T" as abbreviations for ASK |
| | 7877 | and TELL, respectively, in the full phrasing with ABOUT. That is, |
| | 7878 | you can now say, for example, A BOB ABOUT BOOK. In the past, the A |
| | 7879 | and T abbreviations could only be used in the super-short forms of |
| | 7880 | the commands, where only the topic could be specified (as in T BOOK). |
| | 7881 | |
| | 7882 | </div> |
| | 7883 | |
| | 7884 | <!-------------------> |
| | 7885 | <div class=entry> |
| | 7886 | |
| | 7887 | The English parser now accepts the formats ASK <i>actor</i> TO |
| | 7888 | <i>command</i> and TELL <i>actor</i> TO <i>command</i> as equivalent |
| | 7889 | to the traditional <i>actor</i>, <i>command</i> format for telling an |
| | 7890 | actor to do something. The new ASK TO and TELL TO formats are simply |
| | 7891 | syntactic variations; they're otherwise handled exactly the same way |
| | 7892 | as the traditional <i>actor</i>, <i>command</i> format. |
| | 7893 | |
| | 7894 | </div> |
| | 7895 | |
| | 7896 | <!-------------------> |
| | 7897 | <div class=entry> |
| | 7898 | |
| | 7899 | In the English library, SpecialTopic now allows a variation on the |
| | 7900 | input format to accommodate players who are thinking in terms of |
| | 7901 | ASK/TELL. Now, when a SpecialTopic is active, and the player's input |
| | 7902 | <i>doesn't</i> match the special topic's input pattern, <i>and</i> |
| | 7903 | the user's input starts with "A" or "T" as a separate word, the |
| | 7904 | SpecialTopic checks for a match to the rest of the player's input |
| | 7905 | (i.e., the part following the "A" or "T"). For example, if the |
| | 7906 | special topic is "apologize for forgetting the anniversary," and the |
| | 7907 | player types T ANNIVERSARY, the special topic will try dropping the |
| | 7908 | "T" and matching just the "ANNIVERSARY" part. |
| | 7909 | |
| | 7910 | <p>This change is designed to accommodate players who are accustomed |
| | 7911 | to the standard ASK/TELL format, and who might not realize that the |
| | 7912 | special topic list shows commands meant to be entered literally, or |
| | 7913 | who are just so in the habit of using ASK/TELL commands that it |
| | 7914 | doesn't occur to them to leave out the "A" or "T" part. Since an "A" |
| | 7915 | or "T" command pretty clearly indicates that the player's intent is |
| | 7916 | to communicate with the NPC, it makes sense to check the topic the |
| | 7917 | player is trying against any active special topics. |
| | 7918 | |
| | 7919 | <p>Note that the special topic parser only accepts the |
| | 7920 | super-abbreviated formats - the "A" and "T" commands. This is |
| | 7921 | because it seems much less likely that it would even occur to a |
| | 7922 | player to try a special command with the full ASK ABOUT or TELL ABOUT |
| | 7923 | phrasing. Once the command is expanded to the full phrasing, the |
| | 7924 | detailed syntax of the special command suggestions should make it |
| | 7925 | fairly obvious to the player that the ASK ABOUT or TELL ABOUT part |
| | 7926 | isn't needed. In contrast, since the abbreviated "A" and "T" formats |
| | 7927 | are ungrammatical to start with, it would seem perfectly natural to |
| | 7928 | use them with arbitrary special command suggestions. |
| | 7929 | |
| | 7930 | </div> |
| | 7931 | |
| | 7932 | <!-------------------> |
| | 7933 | <div class=entry> |
| | 7934 | |
| | 7935 | The RoomPart class now downgrades its logicalness for Examine |
| | 7936 | commands, in the same way that Decoration does. Room parts are |
| | 7937 | generally so much background noise, included only in case a player |
| | 7938 | explicitly refers to them. Downgrading the logicalness helps prevent |
| | 7939 | the room parts from causing nuisance disambiguation questions. |
| | 7940 | |
| | 7941 | </div> |
| | 7942 | |
| | 7943 | <!-------------------> |
| | 7944 | <div class=entry> |
| | 7945 | |
| | 7946 | Due to a parser bug, the phrase ALL IN <i>container</i> (which can |
| | 7947 | also be written ALL FROM, ALL THAT'S IN, etc) incorrectly ignored the |
| | 7948 | hideFromAll() status of the objects in the container when determining |
| | 7949 | which objects to match to the phrase. This has been corrected; the |
| | 7950 | phrase now respects the hideFromAll() settings of the objects |
| | 7951 | involved. |
| | 7952 | |
| | 7953 | </div> |
| | 7954 | |
| | 7955 | <!-------------------> |
| | 7956 | <div class=entry> |
| | 7957 | |
| | 7958 | The English parser now matches words it has parsed as "literal |
| | 7959 | adjectives" to ordinary adjectives in the dictionary when resolving a |
| | 7960 | phrase in "global scope." This change is the literal-adjective |
| | 7961 | equivalent of the <a href='#global_scope_noun_adj'>similar changes</a> |
| | 7962 | involving noun phrases in global scope introduced in 3.0.6p. |
| | 7963 | |
| | 7964 | </div> |
| | 7965 | |
| | 7966 | <!-------------------> |
| | 7967 | <div class=entry> |
| | 7968 | |
| | 7969 | Noun phrases that consist entirely of a "literal adjective" word are |
| | 7970 | now marked as "adjective-ending" phrases for the purposes of ranking |
| | 7971 | grammatical pattern matches during parsing. (The omission of this |
| | 7972 | flagging in the past was an oversight.) |
| | 7973 | |
| | 7974 | </div> |
| | 7975 | |
| | 7976 | <!-------------------> |
| | 7977 | <div class=entry> |
| | 7978 | |
| | 7979 | Due to a bug, the removeEvent() method of the RealTimeEvent class |
| | 7980 | (the common base class for real-time fuses and daemons) didn't work |
| | 7981 | properly. This has been corrected. |
| | 7982 | |
| | 7983 | </div> |
| | 7984 | |
| | 7985 | <!-------------------> |
| | 7986 | <div class=entry> |
| | 7987 | |
| | 7988 | A bug in the Lister class caused in-line contents listings to use the |
| | 7989 | "long list" format (i.e., with semicolons as the separator between |
| | 7990 | items) if the enclosing list did. An in-line contents list is set off |
| | 7991 | by parentheses, so it stands as an independent list and thus should a |
| | 7992 | long-list format only if it would need to on its own, irrespective of |
| | 7993 | the needs of the enclosing main list. (At least, the parentheses are |
| | 7994 | used in the English library; other languages might use different |
| | 7995 | notation, but in any case should use a notation that makes the |
| | 7996 | contents list similarly independent of the enclosing list.) |
| | 7997 | |
| | 7998 | </div> |
| | 7999 | |
| | 8000 | <!-------------------> |
| | 8001 | <div class=entry> |
| | 8002 | |
| | 8003 | A couple of minor changes to the default LOOK IN handling make it |
| | 8004 | a little easier to customize the behavior, and reduce the need to do |
| | 8005 | so. |
| | 8006 | |
| | 8007 | <p>First, Thing has a new property, lookInDesc, that gives a message |
| | 8008 | that's displayed by default in response to LOOK IN and SEARCH. This |
| | 8009 | shows the standard default ("there's nothing unusual in it") if you |
| | 8010 | don't provide a custom message. It happens frequently that a game |
| | 8011 | wants to depict an object as having some interior features, but |
| | 8012 | doesn't want to actually model those interior features as separate |
| | 8013 | objects. The new lookInDesc makes this more convenient, since you |
| | 8014 | only need to provide the custom message in this property, rather than |
| | 8015 | overriding the entire dobjFor(LookIn) handling, as was necessary in |
| | 8016 | the past. |
| | 8017 | |
| | 8018 | <p>Second, Decoration now treats LOOK IN as logical by default (in the |
| | 8019 | past, this was handled by the catch-all routine that makes most |
| | 8020 | actions respond that the object is "not important"), and applies the |
| | 8021 | same logical-rank downgrade applied to EXAMINE. Correspondingly, |
| | 8022 | the default lookInDesc for Decoration displays the object's "not |
| | 8023 | important" message. This means that Decoration objects act by |
| | 8024 | default as they did before, displaying "that isn't important" in |
| | 8025 | response to LOOK IN, but can be given a custom LOOK IN response |
| | 8026 | simply by setting lookInDesc, just as with any Thing. |
| | 8027 | |
| | 8028 | <p>Third, the English phrasing for finding nothing in an object |
| | 8029 | specifically searched with LOOK IN or SEARCH has changed slightly, to |
| | 8030 | report that there's nothing "unusual" in the object. In many cases, |
| | 8031 | an object is described as having what would in the real world be |
| | 8032 | interior features, but those interior features aren't modeled as |
| | 8033 | actual game objects and hence don't show up by default in response to |
| | 8034 | LOOK IN or SEARCH. The slight change in phrasing helps make the |
| | 8035 | response at least technically defensible. It's probably still better |
| | 8036 | in most cases to customize the LOOK IN response anyway, but at least |
| | 8037 | the default response is a little less jarring in these cases. |
| | 8038 | |
| | 8039 | </div> |
| | 8040 | |
| | 8041 | <!-------------------> |
| | 8042 | <div class=entry> |
| | 8043 | |
| | 8044 | Decoration now treats READ as logical by default, the same as it |
| | 8045 | does EXAMINE. (As mentioned above, LOOK IN now has the same treatment |
| | 8046 | as well.) |
| | 8047 | |
| | 8048 | </div> |
| | 8049 | |
| | 8050 | <!-------------------> |
| | 8051 | <div class=entry> |
| | 8052 | |
| | 8053 | In the Thing class, PUT X IN X and PUT X ON X now respond with custom |
| | 8054 | messages ("you can't put the X in/on itself"). In the past, the |
| | 8055 | catch-all message indicating that X isn't a container/surface was |
| | 8056 | used, which is a less conspicuous problem than attempting to put |
| | 8057 | something in or on itself. |
| | 8058 | |
| | 8059 | </div> |
| | 8060 | |
| | 8061 | <!-------------------> |
| | 8062 | <div class=entry> |
| | 8063 | |
| | 8064 | In the English library, the |
| | 8065 | <a href='#pluralToNounExpansion'>plural-to-noun match expansion</a> |
| | 8066 | introduced in version 3.0.6p is now limited to "global scope," just as the |
| | 8067 | <a href='#nounEndingToAdjEndingExpansion'>noun-ending-to-adjective-ending |
| | 8068 | match expansion</a> already was. English plurals are usually formed |
| | 8069 | by adding "s" or "es" to the end of a word, so when a noun is six |
| | 8070 | letters or longer, it usually looks like a truncated form of its plural; |
| | 8071 | this interacted with the plural-to-noun match expansion to be overly |
| | 8072 | aggressive in upgrading phrases to a plural interpretation. The |
| | 8073 | match expansion is only really important in global scope anyway (for |
| | 8074 | the reasons why, see the explanation of the |
| | 8075 | <a href='#nounEndingToAdjEndingExpansion'>noun-to-adjective expansion</a>), |
| | 8076 | so this change maintains the primary benefits of the match expansion |
| | 8077 | while avoiding the weird cases that can come up in local scope. |
| | 8078 | |
| | 8079 | </div> |
| | 8080 | |
| | 8081 | <!-------------------> |
| | 8082 | <div class=entry> |
| | 8083 | |
| | 8084 | The parser now considers an indefinite noun phrase to be less |
| | 8085 | desirable, for grammar selection purposes, than a definite |
| | 8086 | interpretation of the same phrase. Object names can occasionally look |
| | 8087 | like indefinite phrases: an elevator button labeled "1" could be |
| | 8088 | called a "one button," for example, and a subway might have an "A |
| | 8089 | train." When there's an interpretation that exactly matches the |
| | 8090 | phrase to the name of an in-scope object, the parser will now prefer |
| | 8091 | that interpretation over one that treats a word like "a" or "one" as |
| | 8092 | signifying that an arbitrary match to the other words should be |
| | 8093 | chosen. |
| | 8094 | |
| | 8095 | </div> |
| | 8096 | |
| | 8097 | <!-------------------> |
| | 8098 | <div class=entry> |
| | 8099 | |
| | 8100 | A library bug that caused a run-time error in |
| | 8101 | Actor.findVisualObstructor() has been corrected. |
| | 8102 | |
| | 8103 | </div> |
| | 8104 | |
| | 8105 | <!-------------------> |
| | 8106 | <div class=entry> |
| | 8107 | |
| | 8108 | The library now executes "prompt daemons" (the special type of daemon |
| | 8109 | that runs before each command prompt, rather than when the turn |
| | 8110 | counter changes) before <i>every</i> prompt, rather than just before |
| | 8111 | a main command prompt. This ensures that various miscellaneous tasks |
| | 8112 | are performed whenever the game pauses for user input, even when |
| | 8113 | input is requested in the course of processing a command. |
| | 8114 | |
| | 8115 | </div> |
| | 8116 | |
| | 8117 | <!------------------------------- 3.0.6p ---------------------------------> |
| | 8118 | <div class="sepbar"><a name='306p'></a>3.0.6p</div> |
| | 8119 | <p><b><i>Released 4/25/2004</i></b> |
| | 8120 | <p> |
| | 8121 | |
| | 8122 | <div class=firstentry> |
| | 8123 | |
| | 8124 | <b>Compatibility-breaking change:</b> The property initDesc, and the |
| | 8125 | related properties, have been <b>renamed</b>. Games that define or |
| | 8126 | use these properties will have to change to use the new names. You |
| | 8127 | should search all of your existing source for the old names, and |
| | 8128 | replace each one with the corresponding new name. |
| | 8129 | |
| | 8130 | <p><b>Important:</b> you <b>must</b> search for "initDesc" and |
| | 8131 | replace it with "initSpecialDesc" <b>first</b>. This is required |
| | 8132 | because the former "initExamineDesc" has been renamed to "initDesc" - |
| | 8133 | so you have to make sure you change all the old "initDesc" instances |
| | 8134 | <b>before</b> you rename "initSpecialDesc" to create new "initDesc" |
| | 8135 | instances. Please do your search-and-replace operations in the order |
| | 8136 | shown below: |
| | 8137 | |
| | 8138 | <ul> |
| | 8139 | <li>change "initDesc" to "initSpecialDesc" |
| | 8140 | <li>change "useInitDesc" to "useInitSpecialDesc" |
| | 8141 | <li>change "obscuredInitDesc" to "obscuredInitSpecialDesc" |
| | 8142 | <li>change "distantInitDesc" to "distantInitSpecialDesc" |
| | 8143 | <li>change "initExamineDesc" to "initDesc" |
| | 8144 | <li>change "useInitExamineDesc" to "useInitDesc" |
| | 8145 | </ul> |
| | 8146 | |
| | 8147 | <p>The purpose of this change is to make the naming more consistent. |
| | 8148 | The old usage - "initDesc" for a special description and |
| | 8149 | "initExamineDesc" for the EXAMINE description - was inconsistent with |
| | 8150 | the respective non-initial properties, "specialDesc" and "desc". The |
| | 8151 | qualification was reversed: "specialDesc" was qualified as special, |
| | 8152 | leaving the EXAMINE description unqualified as simply "desc", while |
| | 8153 | the initial descriptions qualified the EXAMINE desription rather than |
| | 8154 | the special one. |
| | 8155 | |
| | 8156 | </div> |
| | 8157 | |
| | 8158 | <!-------------------> |
| | 8159 | <div class=entry> |
| | 8160 | |
| | 8161 | <b>Minor compatibility-breaking change:</b> The Attachable class's |
| | 8162 | scheme for explaining why the object can't be attached to a given |
| | 8163 | other object has been changed. In the past, the method |
| | 8164 | cannotAttachMsg(obj) returned a message string or |
| | 8165 | actor-action-messages property, but this created a conflict with |
| | 8166 | another message property of the same name, which is used by Thing. To |
| | 8167 | resolve the conflict, the Attachable method has now been renamed to |
| | 8168 | explainCannotAttachTo(obj), and rather than returning a message to |
| | 8169 | display, the new method simply displays the message itself. |
| | 8170 | |
| | 8171 | <p>If you have any Attachable objects that define cannotAttachMsg, |
| | 8172 | you must make two changes to each. First, rename cannotAttachMsg |
| | 8173 | to explainCannotAttachTo. Second, rather than returning a string, |
| | 8174 | display the string directly. |
| | 8175 | |
| | 8176 | </div> |
| | 8177 | |
| | 8178 | <!-------------------> |
| | 8179 | <div class=entry> |
| | 8180 | |
| | 8181 | <b>Possible compatibility-breaking change:</b> The conversation |
| | 8182 | mechanism has some internal changes to support deferral across |
| | 8183 | hierarchy levels (<a href='#topicDeferral'>see below</a>). |
| | 8184 | |
| | 8185 | <ul> |
| | 8186 | |
| | 8187 | <li>In TopicDatabase.<b>findTopicResponse()</b>, the former first |
| | 8188 | parameter, 'topicList', has been dropped, and two new parameters have |
| | 8189 | been added: 'convType', giving the conversation action type; and |
| | 8190 | 'path', giving a list of the inferior topic databases that will be |
| | 8191 | searched for the topic if it's not found in the current database |
| | 8192 | (i.e., 'self'). |
| | 8193 | |
| | 8194 | <li>In TopicDatabase.<b>handleTopic()</b>, the former first parameter, |
| | 8195 | 'topicList', has been dropped; and two new parameters have been added: |
| | 8196 | 'convType' and 'path'. These have the same meanings as above. |
| | 8197 | |
| | 8198 | <li>In ConvNode.<b>handleConversation()</b>, the new parameter 'path' |
| | 8199 | has been added. This <b>only</b> affects the ConvNode instance of |
| | 8200 | this method - the method of the same name in Actor and ActorState is |
| | 8201 | unchanged. |
| | 8202 | |
| | 8203 | </ul> |
| | 8204 | |
| | 8205 | <p>Note that the TopicDatabase methods findTopicResponse() and |
| | 8206 | handleTopic() no longer need the topic list parameter because this |
| | 8207 | information can be obtained from the new convType parameter. |
| | 8208 | |
| | 8209 | <p>These methods are mostly for internal use by the library, so the |
| | 8210 | likelihood that your existing game code will be affected is small. |
| | 8211 | Even so, you should scan through your code for these methods and make |
| | 8212 | the appropriate adjustments. |
| | 8213 | |
| | 8214 | <p><b>Important:</b> note that there are two related but independent |
| | 8215 | methods called handleTopic(). There's the TopicDatabase method, |
| | 8216 | which <b>is</b> affected by this change, and there's the separate |
| | 8217 | TopicEntry method, which is <b>not</b> affected. When you're |
| | 8218 | scanning your code, you only need to change the TopicDatabase |
| | 8219 | version. It's easy to tell which is which at a glance: the |
| | 8220 | TopicDatabase version takes <b>three</b> parameters, while the |
| | 8221 | TopicEntry version only takes <b>two</b>. When you're scanning your |
| | 8222 | code, <b>only change the three-parameter instances</b>. |
| | 8223 | |
| | 8224 | <p><b>Additional technical notes:</b> you'll only need to read this |
| | 8225 | part if you're making some rather advanced overrides to the library. |
| | 8226 | Please skip this part unless you find something that you're not sure |
| | 8227 | how to handle in the search-and-replace step above. |
| | 8228 | |
| | 8229 | <p>If your code contains calls to any of the affected methods, and |
| | 8230 | you're wondering what to pass for the convType parameter, you should |
| | 8231 | first check to see if you're receiving that value as a parameter to |
| | 8232 | the calling code; if so, just pass that parameter down. This is |
| | 8233 | usually easy to spot at a glance. If you have code like this: |
| | 8234 | |
| | 8235 | <p><pre> |
| | 8236 | handleTopic(<b>self.(convType.topicListProp)</b>, actor, topic); |
| | 8237 | </pre> |
| | 8238 | |
| | 8239 | <p>then you can simply change it to this: |
| | 8240 | |
| | 8241 | <p><pre> |
| | 8242 | handleTopic(actor, topic, <b>convType</b>, nil); |
| | 8243 | </pre> |
| | 8244 | |
| | 8245 | <p>The important thing to note here is that you're already using the |
| | 8246 | convType parameter to look up the topic list in the old-style call; |
| | 8247 | you can simply drop the topic list lookup and pass the convType |
| | 8248 | parameter itself instead (but note that it moves to the last |
| | 8249 | position). |
| | 8250 | |
| | 8251 | <p>If you don't have a convType parameter passed in from your caller, |
| | 8252 | you'll need to choose which one to use. Look at which topic list |
| | 8253 | you're passing, and think about what conversational action is |
| | 8254 | triggering your code. Then scan through the list of xxxConvType |
| | 8255 | objects (askAboutConvType, tellAboutConvType, yesConvType, |
| | 8256 | noConvType, etc) defined in actor.t, and choose one that (1) has the |
| | 8257 | same topic list property that you're already using, defined in its |
| | 8258 | topicListProp property, and (2) conceptually matches the action |
| | 8259 | you're performing. If you can't find anything appropriate, you might |
| | 8260 | simply need to define your own ConvType object for whatever extended |
| | 8261 | action you're defining; just create one following the same pattern |
| | 8262 | as the existing ones in actor.t. |
| | 8263 | |
| | 8264 | <p>You can usually just pass nil for the new fourth parameter ('path') |
| | 8265 | to handleTopic(), findTopicResponse(), and |
| | 8266 | ConvNode.handleConversation(). You only have to pass a non-nil value |
| | 8267 | when you're implementing a search through a hierarchy of topic |
| | 8268 | databases, in which case you'll have to pass a list of the inferior |
| | 8269 | databases in the hierarchy. The purpose of the new parameter is to |
| | 8270 | allow a higher-level database to defer to a match in a lower-level |
| | 8271 | database, if one exists, so at each level you must pass the remainder |
| | 8272 | of the "search path" of databases. |
| | 8273 | |
| | 8274 | </div> |
| | 8275 | |
| | 8276 | <!-------------------> |
| | 8277 | <div class=entry> |
| | 8278 | |
| | 8279 | <a name='topicDeferral'></a> |
| | 8280 | The above changes to the conversation methods are designed to |
| | 8281 | facilitate a new mechanism that allows a conversation TopicEntry in |
| | 8282 | one topic database to defer to a TopicEntry from an inferior |
| | 8283 | database. This is done through the new TopicEntry method |
| | 8284 | deferToEntry(entry): this method returns true if 'self' should defer |
| | 8285 | to 'entry', nil if not. 'entry' is always a non-nil TopicEntry |
| | 8286 | object from an inferior topic database. |
| | 8287 | |
| | 8288 | <p>Recall that topic entry databases for conversation are arranged |
| | 8289 | into a three-level hierarchy for each actor: at the top is the |
| | 8290 | ConvNode's list of topics, at the middle level is the ActorState |
| | 8291 | list, and at the bottom level is the Actor list. We find a matching |
| | 8292 | topic entry by scanning each level of this hierarchy in turn, and |
| | 8293 | taking the first match we find. So, if there's a ConvNode match for |
| | 8294 | a topic we're looking for, we use it, even if there's a match for the |
| | 8295 | same topic in the ActorState or Actor. The matchScore is irrelevant: |
| | 8296 | the three-level hierarchy always trumps the matchScore ranking. The |
| | 8297 | matchScore ranking is only used to choose among different matching |
| | 8298 | entries <i>at the same hierarchy level</i>. |
| | 8299 | |
| | 8300 | <p>The new deferToEntry() mechanism allows topic entries to defer |
| | 8301 | handling across hierarchy levels. Here's how the new scheme works: |
| | 8302 | before we start searching the hierarchy, we start by noting the |
| | 8303 | matching entry at each level. Then, we search each level from the |
| | 8304 | top down as before. At each level, though, we look at the winning |
| | 8305 | match, and ask it via deferToEntry() if it wants to defer to the |
| | 8306 | winning match from the next level down the hierarchy. If so, then |
| | 8307 | we ignore the match at that level. This means that we skip the |
| | 8308 | higher-level match and go straight to the lower-level handling. |
| | 8309 | |
| | 8310 | <p>The main purpose of this addition is to allow a DefaultTopic |
| | 8311 | entry to be a catch-all only for topics that aren't handled |
| | 8312 | explicitly at a lower hierarchy level. For example, to create a |
| | 8313 | DefaultTopic that defers to any non-default match at a lower |
| | 8314 | hierarchy level, add this to the DefaultTopic object: |
| | 8315 | |
| | 8316 | <p><pre> |
| | 8317 | deferToEntry(other) { return !other.ofKind(DefaultTopic); } |
| | 8318 | </pre> |
| | 8319 | |
| | 8320 | <p>This tells the topic finder that if there's any match that's |
| | 8321 | not itself a DefaultTopic at a lower hierarchy level, then this |
| | 8322 | default should be ignored. |
| | 8323 | |
| | 8324 | </div> |
| | 8325 | |
| | 8326 | <!-------------------> |
| | 8327 | <div class=entry> |
| | 8328 | |
| | 8329 | The English library template for Room has been extended, and the |
| | 8330 | default relationships that derive one type of Room naming property |
| | 8331 | from another have changed slightly. These changes should be fully |
| | 8332 | compatible with existing game code, and should make it easier |
| | 8333 | to customize the various kinds of room names. |
| | 8334 | |
| | 8335 | <p>The template for Room now takes the first string to be the |
| | 8336 | 'roomName' property, the second to be 'destName', and the third to be |
| | 8337 | the 'name' property. The 'desc' property is still in the last |
| | 8338 | position. |
| | 8339 | |
| | 8340 | <p><pre> |
| | 8341 | Room template 'roomName' 'destName'? 'name'? "desc"?; |
| | 8342 | </pre> |
| | 8343 | |
| | 8344 | <p>In the past, the 'name' was the first entry, and 'destName' was |
| | 8345 | the second. The library took the 'roomName' to be the same as the |
| | 8346 | 'name'. However, it makes more sense to do this the other way |
| | 8347 | around: the 'roomName' is now the one that's explicitly defined by |
| | 8348 | the game, and the 'name' setting is optional. If the 'name' setting |
| | 8349 | is omitted, it's derived by default by converting the 'roomName' to |
| | 8350 | lower case. |
| | 8351 | |
| | 8352 | <p>The 'roomName' is what's shown as the title of the room, in the |
| | 8353 | room description and on the status line. This is usually given in |
| | 8354 | "title case," meaning that each word has an initial capital letter, |
| | 8355 | with the exception of minor function words: "Hall of the Ancient |
| | 8356 | Kings". This is the format that games have defined all along, but |
| | 8357 | in the past, they defined it using the 'name' property. The change |
| | 8358 | improves matters, because it allows the room's ordinary 'name' |
| | 8359 | property to be entered separately, in a format suitable for use |
| | 8360 | when the name is needed in library messages: "You can't have the |
| | 8361 | ice cave." |
| | 8362 | |
| | 8363 | <p>The default 'name' derivation - converting the 'roomName' string |
| | 8364 | to lower case - gives decent results a lot of the time. However, in |
| | 8365 | many cases, you'll want to customize the ordinary name separately. |
| | 8366 | The template makes this easy by adding a slot for the 'name' property |
| | 8367 | separately from the 'roomName'. |
| | 8368 | |
| | 8369 | <p>There's one additional change to the default derivations. In the |
| | 8370 | past, the 'destName' didn't have a default at all. Now, the default |
| | 8371 | is the room's 'theName', which is itself derived, by default, by |
| | 8372 | prepending the ordinary name with 'the'. As before, the template |
| | 8373 | lets you supply a separate, custom 'destName' value. |
| | 8374 | |
| | 8375 | </div> |
| | 8376 | |
| | 8377 | <!-------------------> |
| | 8378 | <div class=entry> |
| | 8379 | |
| | 8380 | The MultiLoc object now transmits sense information to and from |
| | 8381 | its contents in a more consistent fashion. In the past, putting |
| | 8382 | things inside a MultiLoc had somewhat inconsistent results; the |
| | 8383 | behavior should be more predictable now. |
| | 8384 | |
| | 8385 | <p>The primary design principle of a MultiLoc hasn't changed: a |
| | 8386 | MultiLoc is a single object that appears in multiple locations, but |
| | 8387 | which doesn't provide any sense connection among the multiple |
| | 8388 | containers. A MultiLoc is a <i>single</i> object in the sense that |
| | 8389 | the same object appears, in its physical entirety, in each of its |
| | 8390 | containers. |
| | 8391 | |
| | 8392 | <p>In the past, a MultiLoc was essentially a "sense ceiling": sense |
| | 8393 | information propagated from outside the MultiLoc to its interior, but |
| | 8394 | didn't propagate from within the MultiLoc to its containers. This was |
| | 8395 | intended to prevent the MultiLoc from propagating sense information |
| | 8396 | among its containers, but it was too restrictive an implementation. |
| | 8397 | For example, if a MultiLoc contained a flashlight, the flashlight's |
| | 8398 | light didn't shine into the MultiLoc's locations. Similarly, if an |
| | 8399 | NPC was inside a MultiLoc, the NPC couldn't see or hear anything from |
| | 8400 | any of the MultiLoc's locations, and hence couldn't take part in a |
| | 8401 | conversation with the PC while the PC was outside the MultiLoc. |
| | 8402 | |
| | 8403 | <p>The change is that a MultiLoc is no longer a sense ceiling; it's |
| | 8404 | now more like a wall. Now, from a point of view inside the MultiLoc, |
| | 8405 | all of the MultiLoc's locations (and their contents, to the extent |
| | 8406 | that's appropriate) are visible. From the point of view of any of |
| | 8407 | the MultiLoc's containers, the MultiLoc and its contents (as |
| | 8408 | appropriate) are visible, but none of the MultiLoc's other containers |
| | 8409 | are visible. Light is similarly transmitted from inside the MultiLoc |
| | 8410 | to all of its containers, but not from one container to another. So, |
| | 8411 | for example, if a flashlight is inside a MultiLoc, it provides light |
| | 8412 | to every container of the MultiLoc; but if a flashlight is in one of |
| | 8413 | a MultiLoc's containers, the light doesn't make it through the |
| | 8414 | MultiLoc to its other containers. |
| | 8415 | |
| | 8416 | <p>The main effect of this change is that things located inside a |
| | 8417 | MultiLoc now behave the way one would expect them to. In the past, |
| | 8418 | the asymmetrical "sense ceiling" design led to some odd behavior when |
| | 8419 | putting objects inside a MultiLoc: an actor within a MultiLoc |
| | 8420 | couldn't carry on a conversation with someone outside, for example, |
| | 8421 | because the actor inside couldn't hear out beyond the MultiLoc. |
| | 8422 | With the change, MultiLoc should behave much more intuitively. |
| | 8423 | |
| | 8424 | </div> |
| | 8425 | |
| | 8426 | <!-------------------> |
| | 8427 | <div class=entry> |
| | 8428 | |
| | 8429 | The ContainerDoor class now defines the isOpen method to return the |
| | 8430 | same thing as its associated container's isOpen method; and it now |
| | 8431 | defines examineStatus to display its associated container's |
| | 8432 | open/closed status. |
| | 8433 | |
| | 8434 | </div> |
| | 8435 | |
| | 8436 | <!-------------------> |
| | 8437 | <div class=entry> |
| | 8438 | |
| | 8439 | A ComplexContainer can now be used as a bag of holding. Operations |
| | 8440 | involving the bag-of-holding features of a complex container are |
| | 8441 | simply passed redirected to the complex container's subContainer |
| | 8442 | object. |
| | 8443 | |
| | 8444 | </div> |
| | 8445 | |
| | 8446 | <!-------------------> |
| | 8447 | <div class=entry> |
| | 8448 | |
| | 8449 | Certain object contents listings were grammatically incorrect when |
| | 8450 | showing a single item that had a plural name. For example, if an item |
| | 8451 | had the name "some coins," and it was the only item on a table, the |
| | 8452 | table description said "On the table is some coins." |
| | 8453 | |
| | 8454 | <p>The listers now take into account the "cardinality" of each item |
| | 8455 | listed, to ensure grammatical agreement in these cases. For English, |
| | 8456 | there are only two degrees of cardinality that matter: one, and many. |
| | 8457 | The English module therefore assigns a grammatical cardinality of 2 to |
| | 8458 | items whose isPlural property is set to true, 1 for all others; this |
| | 8459 | is done with the new Thing method listCardinality(lister). A lister |
| | 8460 | calls this new method to determine the cardinality of the list, so |
| | 8461 | that it can provide the correct information to the methods that |
| | 8462 | generate the messages. |
| | 8463 | |
| | 8464 | </div> |
| | 8465 | |
| | 8466 | <!-------------------> |
| | 8467 | <div class=entry> |
| | 8468 | |
| | 8469 | The LISTEN TO command now lists not only the sound the object being |
| | 8470 | examined is making, but the audible sounds of its contents as well. |
| | 8471 | This ensures that sounds made by components of an object are properly |
| | 8472 | displayed when the enclosing object is examined, and also ensures that |
| | 8473 | a container that has a sound source inside will have its sound listed. |
| | 8474 | |
| | 8475 | <p>The SMELL command has been similarly enhanced. |
| | 8476 | |
| | 8477 | <p>As part of this change, the thingListenDesc and thingSmellDesc |
| | 8478 | messages have been moved from libMessages to playerActionMessages, and |
| | 8479 | renamed thingListenDescMsg and thingSmellDescMsg, respectively. These |
| | 8480 | messages are now shown as default description messages, necessitating |
| | 8481 | the move to playerActionMessages. |
| | 8482 | |
| | 8483 | </div> |
| | 8484 | |
| | 8485 | <!-------------------> |
| | 8486 | <div class=entry> |
| | 8487 | |
| | 8488 | The Distant class now explicitly allows LISTEN TO, the same way |
| | 8489 | it allows EXAMINE. |
| | 8490 | |
| | 8491 | </div> |
| | 8492 | |
| | 8493 | <!-------------------> |
| | 8494 | <div class=entry> |
| | 8495 | |
| | 8496 | It's now possible to create a SenseConnector that occludes some |
| | 8497 | objects from view, depending on the point of view. This is useful |
| | 8498 | for situations where a sense connector provides only a partial view |
| | 8499 | of another room. For example, consider two rooms with a window |
| | 8500 | between them, providing a view of one room from the other. Now, |
| | 8501 | suppose a bookcase is positioned with its back to the window. When |
| | 8502 | viewing the room with the bookcase from the other side of the window, |
| | 8503 | it's not possible to see the contents of the bookcase. |
| | 8504 | |
| | 8505 | <p>The new class, OccludingConnector, is a mix-in that you can |
| | 8506 | combine with SenseConnector to create a partially occluded sense |
| | 8507 | path. Put OccludingConnector before SenseConnector in the class |
| | 8508 | list. You specify which objects to occlude from view by defining the |
| | 8509 | method occludeObj(obj, sense, pov). 'obj' is an object to test for |
| | 8510 | occlusion; 'sense' is the sense being calculated; and 'pov' is the |
| | 8511 | point of view, which is usually the actor performing the command. |
| | 8512 | Your method must return true if the connector occludes the object, |
| | 8513 | nil if not. |
| | 8514 | |
| | 8515 | <p>To implement the window in our example above, we'd do something |
| | 8516 | like this: |
| | 8517 | |
| | 8518 | <p><pre> |
| | 8519 | OccludingConnector, SenseConnector, Fixture 'window' 'window' |
| | 8520 | "It's a small window. " |
| | 8521 | connectorMaterial = glass |
| | 8522 | locationList = [roomA, roomB] |
| | 8523 | occludeObj(obj, sense, pov) |
| | 8524 | { |
| | 8525 | /* from roomA, we can't see what's in the bookcase in roomB */ |
| | 8526 | return (pov.isIn(roomA) && obj.isIn(bookcase)); |
| | 8527 | } |
| | 8528 | ; |
| | 8529 | </pre> |
| | 8530 | |
| | 8531 | </div> |
| | 8532 | |
| | 8533 | <!-------------------> |
| | 8534 | <div class=entry> |
| | 8535 | |
| | 8536 | <p>OccludingConnector uses a new mechanism that can be used for more |
| | 8537 | extensive customization of the sense path calculation than |
| | 8538 | OccludingConnector itself enables. During each sense path |
| | 8539 | calculation, the library first builds a table of all of the objects |
| | 8540 | connected by containment to the point of view. (This table contains |
| | 8541 | all of the objects that can possibly be sensed, because sense paths |
| | 8542 | are based entirely on containment relationships.) The library then |
| | 8543 | calls clearSenseInfo() on each item to initialize it for the path |
| | 8544 | calculation. |
| | 8545 | |
| | 8546 | <p>In clearSenseInfo(), an object can register itself for an |
| | 8547 | additional notification at the end of the sense calculation. To |
| | 8548 | register for the notification, override clearSenseInfo(), inherit the |
| | 8549 | default code, and append 'self' to the notification vector: |
| | 8550 | |
| | 8551 | <p><pre> |
| | 8552 | clearSenseInfo() |
| | 8553 | { |
| | 8554 | inherited(); |
| | 8555 | senseTmp.notifyList.append(self); |
| | 8556 | } |
| | 8557 | </pre> |
| | 8558 | |
| | 8559 | <p>Now that the object is registered, it will be notified at the |
| | 8560 | end of the calculation, after the sense path to each object is fully |
| | 8561 | calculated, but before the final table of sense paths is constructed. |
| | 8562 | The notification method is called finishSensePath(objs, sense). 'objs' |
| | 8563 | is a LookupTable whose keys are the objects connected by containment |
| | 8564 | to the point of view; 'sense' is the Sense object of the calculation. |
| | 8565 | |
| | 8566 | <p>You can do anything you want to the sense table in |
| | 8567 | finishSensePath(). The sense path information for each object is |
| | 8568 | stored in the object's tmpXxx_ properties - tmpTrans_, tmpAmbient_, |
| | 8569 | tmpObstructor_, etc. To change an object's sense path, simply change |
| | 8570 | those properties. (OccludingConnector simply sets each occluded |
| | 8571 | object's path transparency, in tmpTrans_ and tmpTransWithin_, to nil |
| | 8572 | to indicate that the object cannot be seen.) You can make additional |
| | 8573 | objects visible by adding them to the lookup table and setting their |
| | 8574 | tmpXxx_ properties to the settings you want them to have. |
| | 8575 | |
| | 8576 | <p>Note that the notification step is required for performance |
| | 8577 | reasons. The library <i>could</i> call the notification method on |
| | 8578 | every object, which would simplify things by eliminating the need for |
| | 8579 | the extra line of code to register. However, very few objects are |
| | 8580 | likely to require this extra notification, and since sense path |
| | 8581 | calculations are performed very frequently, the library doesn't want |
| | 8582 | to call the notification method blindly on all objects. So, to avoid |
| | 8583 | adding the notification overhead to every object, the library |
| | 8584 | requires the rare objects that require the notification to register |
| | 8585 | themselves. |
| | 8586 | |
| | 8587 | </div> |
| | 8588 | |
| | 8589 | <!-------------------> |
| | 8590 | <div class=entry> |
| | 8591 | |
| | 8592 | The logic that decides on the descriptions generated for distant and |
| | 8593 | obscured objects has changed slightly. The purpose of these changes |
| | 8594 | is to make it easier to customize the various ways an object is |
| | 8595 | described, and to make the selection of description more intuitive. |
| | 8596 | |
| | 8597 | <p>First, a new type of description has been added: the "remote" |
| | 8598 | description. There are three new remote description methods: |
| | 8599 | remoteDesc, for the EXAMINE description; remoteSpecialDesc, for the |
| | 8600 | special description; and remoteInitSpecialDesc, for the remote |
| | 8601 | initial special description. These new methods are used to provide |
| | 8602 | the examination and special descriptions when the object is viewed |
| | 8603 | from a separate top-level location. For example, if two top-level |
| | 8604 | rooms are connected by a window, so that an actor in one room can see |
| | 8605 | objects in the other room through the window, the remote description |
| | 8606 | is used to describe objects in the other room from the actor's |
| | 8607 | perspective. |
| | 8608 | |
| | 8609 | <p>Second, when choosing a special description (as part of a room or |
| | 8610 | contents listing), the logic is now as follows: |
| | 8611 | |
| | 8612 | <ul> |
| | 8613 | <li>If the object is in a separate top-level location from the actor |
| | 8614 | doing the looking, the remoteSpecialDesc is shown; |
| | 8615 | <li>otherwise, if the object is obscured, the obscuredSpecialDesc is shown; |
| | 8616 | <li>otherwise, if the object is distant, the distantSpecialDesc is shown; |
| | 8617 | <li>otherwise, the specialDesc is shown. |
| | 8618 | </ul> |
| | 8619 | |
| | 8620 | <p>In the past, the sightSize was taken into account in selecting the |
| | 8621 | type of special description to show: the specialDesc was shown if the |
| | 8622 | object had a large visual size, regardless of the transparency of the |
| | 8623 | sense path. Now, the sightSize isn't considered at all. The reason |
| | 8624 | for the change is that the distantDesc and obscuredDesc are almost |
| | 8625 | always custom messages per object, so they will naturally take into |
| | 8626 | account the visual size of the object; considering the visual size |
| | 8627 | added an unnecessary extra dimension. |
| | 8628 | |
| | 8629 | <p>Note how the new remoteSpecialDesc fits into the selection rules: |
| | 8630 | the remote special description takes precedence over the obscured and |
| | 8631 | distant descriptions. That is, if the object being described is in a |
| | 8632 | separate top-level room from the actor doing the looking, the |
| | 8633 | remoteSpecialDesc is used, even if the object is <i>also</i> visually |
| | 8634 | obscured or at a distance. |
| | 8635 | |
| | 8636 | <p>Third, when choosing an examine description (when the object is |
| | 8637 | explicitly examined), the logic is now as follows: |
| | 8638 | |
| | 8639 | <ul> |
| | 8640 | <li>If the object is in a separate top-level room from the actor |
| | 8641 | doing the looking, <b>and</b> a remoteDesc method is defined for |
| | 8642 | the object, the remoteDesc method is used; |
| | 8643 | <li>otherwise, if the object is obscured, <b>and</b> an obscuredDesc |
| | 8644 | method is defined for the object, the obscuredDesc method is used; |
| | 8645 | <li>otherwise, if the object is distant, <b>and</b> a distantDesc method |
| | 8646 | is defined for the object, the distantDesc method is used; |
| | 8647 | <li>otherwise, if the object's details are visible (which will be true |
| | 8648 | even for a distant or obscured object with sightSize set to large), the |
| | 8649 | ordinary desc is used; |
| | 8650 | <li>otherwise, if the object is obscured, the defaultObscuredDesc |
| | 8651 | method will be used; |
| | 8652 | <li>otherwise, if the object is distant, the defaultDistantDesc |
| | 8653 | method will be used. |
| | 8654 | |
| | 8655 | <p>In the past, the 'desc' was used any time the visual details were |
| | 8656 | visible, even if the object was distant or obscured and even if the |
| | 8657 | object had a custom distantDesc or obscuredDesc. The change is that |
| | 8658 | the distantDesc or obscuredDesc will essentially "override" the |
| | 8659 | ordinary 'desc' when custom definitions are provided, regardless of |
| | 8660 | the visual size of the object. The reason for this change is to keep |
| | 8661 | the EXAMINE description selection rules consistent with the special |
| | 8662 | description rules; the rules are essentially parallel in the two |
| | 8663 | cases. The EXAMINE selection rules are slightly more complicated |
| | 8664 | because of the need to generate suitable defaults when a custom |
| | 8665 | obscured/distant description is not defined: by considering first |
| | 8666 | whether or not a custom description is available, we can decide to |
| | 8667 | show the custom distant/obscured description (if one is available), |
| | 8668 | the default ordinary description (if no custom description is |
| | 8669 | available <b>and</b> the details are visible), or a default |
| | 8670 | distant/obscured description (in any other case). |
| | 8671 | |
| | 8672 | <p>Note that the defaultObscuredDesc and defaultDistantDesc methods |
| | 8673 | are new. The default implementations simply display the same default |
| | 8674 | library messages that the default obscuredDesc and distantDesc |
| | 8675 | implementations displayed in past versions. |
| | 8676 | |
| | 8677 | </div> |
| | 8678 | |
| | 8679 | <!-------------------> |
| | 8680 | <div class=entry> |
| | 8681 | |
| | 8682 | <p>The logic for deciding whether or not to use the initial special |
| | 8683 | description and initial examine description for an object has been |
| | 8684 | refactored slightly. The refactoring yields the same default effects |
| | 8685 | as before, so existing game code won't be affected, but the changes |
| | 8686 | provide better control for overriding the default behavior. |
| | 8687 | |
| | 8688 | <p>First, the new Thing method isInInitState determines whether or |
| | 8689 | not to use the initial special and examine descriptions. By default, |
| | 8690 | this method returns true if the object has never been moved, nil if |
| | 8691 | the object has been moved. That is, the object is considered to be |
| | 8692 | in its initial state, for the purposes of descriptions, until the |
| | 8693 | first time the object is moved by an actor in the game. |
| | 8694 | |
| | 8695 | <p>Second, the new Thing method useInitExamineDesc() indicates |
| | 8696 | whether or not the initExamineDesc should be used when examining the |
| | 8697 | object. By default, this returns true if the object is in its |
| | 8698 | initial state, as indicated by isInInitState, <b>and</b> the object |
| | 8699 | defines a non-nil initExamineDesc. Since isInInitState by default |
| | 8700 | returns true if the object has never been moved, and nil otherwise, |
| | 8701 | the default behavior is the same as before, so existing games will |
| | 8702 | not be affected by this change. |
| | 8703 | |
| | 8704 | <p>Third, the existing Thing method useInitDesc() looks at |
| | 8705 | isInInitState to make its determination. Since isInInitState by |
| | 8706 | default returns true if the object has never been moved, this has the |
| | 8707 | same effect as in the past. |
| | 8708 | |
| | 8709 | <p>These changes make it easier to change the "never moved" logic |
| | 8710 | that determines whether or not to use initial descriptions, and also |
| | 8711 | allows you to control the use of the initial special and examine |
| | 8712 | descriptions independently of one another. For example, if you want |
| | 8713 | the initial examine description to be used one time only, rather than |
| | 8714 | to be based on whether the object has been moved, you could override |
| | 8715 | useInitExamineDesc() to base its determination on 'described' rather |
| | 8716 | than on 'moved'. |
| | 8717 | |
| | 8718 | </div> |
| | 8719 | |
| | 8720 | <!-------------------> |
| | 8721 | <div class=entry> |
| | 8722 | |
| | 8723 | In the English library, Room has a new method that provides a |
| | 8724 | prepositional phrase that can be used to describe objects as being in |
| | 8725 | the room. The new method is inRoomName(pov), and it returns a string |
| | 8726 | that can be used to construct a sentence describing objects as being |
| | 8727 | in the room. 'pov' is the point of view; this might not be in the |
| | 8728 | same top-level room, as we could be viewing objects in this room from |
| | 8729 | the point of view of a separate room that's connected to our room by |
| | 8730 | a window or another sense connector. |
| | 8731 | |
| | 8732 | </div> |
| | 8733 | |
| | 8734 | <!-------------------> |
| | 8735 | <div class=entry> |
| | 8736 | |
| | 8737 | Room descriptions now include listings of the portable objects |
| | 8738 | visible in separate top-level locations. In the past, only the |
| | 8739 | contents of the point-of-view actor's own enclosing room were |
| | 8740 | described; now, the contents of each connected top-level room are |
| | 8741 | described as well. |
| | 8742 | |
| | 8743 | <p>To generate the new remote room contents listings, the room |
| | 8744 | describer first determines the set of top-level rooms with items that |
| | 8745 | are visible from the point of view of the actor doing the looking. |
| | 8746 | The room describer shows the contents of the local room (the room |
| | 8747 | containing the point of view) first, using the same procedure it |
| | 8748 | always has. Next, the describer runs through the set of other |
| | 8749 | top-level rooms with visible contents; for each one, it generates a |
| | 8750 | separate remote contents listing. |
| | 8751 | |
| | 8752 | <p>Each remote room's contents listing is displayed using essentially |
| | 8753 | the same procedure used to generate the local room's contents |
| | 8754 | listing. However, instead of using the lister defined by the local |
| | 8755 | room's roomContentsLister property (which is set to the roomLister |
| | 8756 | object by default), each remote listing is generated using a lister |
| | 8757 | returned by the new method remoteRoomContentsLister(other). This |
| | 8758 | method is called on the point-of-view room, and 'other' is the remote |
| | 8759 | room whose contents are to be listed. By default, this returns a |
| | 8760 | lister that uses the remote room's inRoomName to generate the |
| | 8761 | description. |
| | 8762 | |
| | 8763 | <p>You can customize the listing of portable items visible in remote |
| | 8764 | locations by returning a custom lister from remoteRoomContentsLister(). |
| | 8765 | Note that the new class CustomRoomLister makes this easy, if all you |
| | 8766 | want to do is to customize the prefix and suffix messages displayed |
| | 8767 | in the listing: |
| | 8768 | |
| | 8769 | <p><pre> |
| | 8770 | remoteRoomContentsLister(other) |
| | 8771 | { |
| | 8772 | return new CustomRoomLister('Through the window, {you/he} see{s}', '.'); |
| | 8773 | } |
| | 8774 | </pre> |
| | 8775 | |
| | 8776 | <p>Note that remoteRoomContentsLister(other) is called on the |
| | 8777 | <i>local</i> room - the room containing the actor doing the looking - |
| | 8778 | and 'other' is the <i>remote</i> room. This arrangement lets you |
| | 8779 | customize the listing in the point-of-view room, which makes sense in |
| | 8780 | that the overall description is of the point-of-view room. |
| | 8781 | |
| | 8782 | </div> |
| | 8783 | |
| | 8784 | <!-------------------> |
| | 8785 | <div class=entry> |
| | 8786 | |
| | 8787 | When a room is described (as when entering the room, or examining it |
| | 8788 | with a LOOK AROUND command), everything visible from the room is |
| | 8789 | marked as having been seen. In the past, only visible objects that |
| | 8790 | were located within the actor's top-level enclosing location were |
| | 8791 | marked as visible; now, everything that's visible is marked as seen, |
| | 8792 | including objects in other top-level rooms that are visible from the |
| | 8793 | actor's location. |
| | 8794 | |
| | 8795 | </div> |
| | 8796 | |
| | 8797 | <!-------------------> |
| | 8798 | <div class=entry> |
| | 8799 | |
| | 8800 | The library has an enhanced way of listing an actor's presence in a |
| | 8801 | room (as part of the room description) when the actor is visible in a |
| | 8802 | remote location (i.e., a separate top-level room) or at a distance. |
| | 8803 | In the past, there was no distinction between the normal case and the |
| | 8804 | distant and remote cases. Now, when the actor is in a remote room, |
| | 8805 | or at a distance, a different path is used to generate the message. |
| | 8806 | |
| | 8807 | <p>To accomplish this change, Actor now overrides remoteSpecialDesc |
| | 8808 | and distantSpecialDesc. On LOOK AROUND, the room calls the |
| | 8809 | appropriate one of these to describe the actor when the actor is at a |
| | 8810 | distance. (The normal selection procedure is used: the |
| | 8811 | remoteSpecialDesc is used if the NPC is in a separate top-level |
| | 8812 | location from the point-of-view actor, otherwise distantSpecialDesc |
| | 8813 | is used if the NPC is at a distance.) The new Actor implementations |
| | 8814 | of remoteSpecialDesc and distantSpecialDesc invoke the corresponding |
| | 8815 | new ActorState methods of the same names. These new ActorState |
| | 8816 | methods in turn call back to the new Actor method actorThereDesc |
| | 8817 | (both the distant and remote methods call this one new method). The |
| | 8818 | new actorThereDesc calls the new method roomRemoteActorDesc on |
| | 8819 | the actor's location. Thing provides a default |
| | 8820 | implementation of this new methods, which simply calls the same |
| | 8821 | thing on its the location if there's a location that's visible from |
| | 8822 | the point of view, or shows a default library message if not. The |
| | 8823 | default library message method is also called roomRemoteActorDesc. |
| | 8824 | This uses the location's inRoomName to generate the description. |
| | 8825 | |
| | 8826 | <p>This sequence of calls lets you hook in and customize the actor's |
| | 8827 | distant special description at whatever level is most convenient - |
| | 8828 | at the actor itself, at the ActorState, or at the containing room. |
| | 8829 | In most cases, it will probably be most convenient to customize this |
| | 8830 | in the room, to display a message customized to the appearance of |
| | 8831 | the room from a distance. To do this, you'd put a method like this |
| | 8832 | on the room: |
| | 8833 | |
| | 8834 | <p><pre> |
| | 8835 | roomRemoteActorDesc(actor) |
| | 8836 | { |
| | 8837 | "\^<<actor.nameIs>> over at the north end of the courtyard. "; |
| | 8838 | } |
| | 8839 | </pre> |
| | 8840 | |
| | 8841 | <p>Note that the actor to describe is provided as a parameter, and |
| | 8842 | that the method is responsible for displaying the complete message |
| | 8843 | describing the actor's presence. |
| | 8844 | |
| | 8845 | </div> |
| | 8846 | |
| | 8847 | <!-------------------> |
| | 8848 | <div class=entry> |
| | 8849 | |
| | 8850 | In the past, an EXAMINE command applied to a room was always treated |
| | 8851 | as a LOOK AROUND command; this didn't produce good results when the |
| | 8852 | room being examined was a separate room that the actor doing the |
| | 8853 | looking wasn't in (i.e., a room connected to the actor's location via |
| | 8854 | a sense connector of some kind). This no longer happens; when the |
| | 8855 | actor doing the looking isn't inside the room, the standard EXAMINE |
| | 8856 | handling is used, as though the room were any ordinary object. |
| | 8857 | |
| | 8858 | </div> |
| | 8859 | |
| | 8860 | <!-------------------> |
| | 8861 | <div class=entry> |
| | 8862 | |
| | 8863 | Thing.lookAroundPov() now actually sets a global point-of-view object. |
| | 8864 | This ensures that the POV information can be obtained (via the getPOV() |
| | 8865 | function) when room descriptions are being shown. |
| | 8866 | |
| | 8867 | </div> |
| | 8868 | |
| | 8869 | <!-------------------> |
| | 8870 | <div class=entry> |
| | 8871 | |
| | 8872 | Thing.addToSenseInfoTable() no longer includes the 'src' parameter. |
| | 8873 | Instead, the same information can be obtained from |
| | 8874 | senseTmp.pointOfView. (The parameter has been removed for effiency: |
| | 8875 | the information is rarely needed, and is available from this other |
| | 8876 | source when it is needed.) |
| | 8877 | |
| | 8878 | </div> |
| | 8879 | |
| | 8880 | <!-------------------> |
| | 8881 | <div class=entry> |
| | 8882 | |
| | 8883 | The Thing method canDetailsBeSensed() now takes an addition parameter |
| | 8884 | giving the point of view. This is usually the actor performing a |
| | 8885 | LOOK AROUND, EXAMINE, or other command that's causing a description |
| | 8886 | of the object to be generated. |
| | 8887 | |
| | 8888 | </div> |
| | 8889 | |
| | 8890 | <!-------------------> |
| | 8891 | <div class=entry> |
| | 8892 | |
| | 8893 | Thing.lookAroundWithinSense now marks each item with a "presence" in |
| | 8894 | the sense as known to the actor who's doing the looking. This |
| | 8895 | ensures that any noises and odors that are actively listed become |
| | 8896 | known to the actor as soon as they're listed. |
| | 8897 | |
| | 8898 | Objects are marked as known rather than seen, because it might be |
| | 8899 | possible to hear or smell objects that can't be seen. Note that only |
| | 8900 | objects with a "presence" in the sense are marked as known; an object |
| | 8901 | with a presence in a sense is one that is actively calling attention |
| | 8902 | to itself in the sense, via a noise or odor message in the room |
| | 8903 | description. Thus, an object that isn't actually making any noise |
| | 8904 | worth listing doesn't become known just because an actor could hear |
| | 8905 | it if it were making noise; it has to actually be making some noise |
| | 8906 | (and say so by setting its soundPresence to true) to become known in |
| | 8907 | this manner. Note also that a noise and its source are frequently |
| | 8908 | separate objects (likewise with odors), and it's the <i>noise</i> |
| | 8909 | that becomes known in this arrangement, not the source. This is |
| | 8910 | important because it's often possible to hear the sound a thing makes |
| | 8911 | without knowing what's making the noise: we can hear a beeping coming |
| | 8912 | from inside a closed box, so we now know about the beeping, but we |
| | 8913 | can't tell that it's coming from an alarm clock, so the alarm clock |
| | 8914 | remains unknown to us. |
| | 8915 | |
| | 8916 | </div> |
| | 8917 | |
| | 8918 | <!-------------------> |
| | 8919 | <div class=entry> |
| | 8920 | |
| | 8921 | By default, Thing now applies the objHeld precondition to a Show |
| | 8922 | action; this means that SHOW X TO Y requires X to be held if X is an |
| | 8923 | ordinary Thing. In addition, NonPortable only requires that the |
| | 8924 | object be visible. This change assumes that portable objects need to |
| | 8925 | be held up for someone else to look at, as though offering the object |
| | 8926 | to the other person, while non-portable objects can be merely pointed |
| | 8927 | out but left in place. |
| | 8928 | |
| | 8929 | </div> |
| | 8930 | |
| | 8931 | <!-------------------> |
| | 8932 | <div class=entry> |
| | 8933 | |
| | 8934 | The Vehicle class now treats an OUT command while an actor is inside |
| | 8935 | the vehicle as meaning to drive or ride the vehicle out of the |
| | 8936 | vehicle's enclosing location. In the past, OUT in a vehicle meant |
| | 8937 | the same thing as in a nested room: GET OUT of the vehicle. The old |
| | 8938 | behavior didn't seem to match most players' expectations, and it had |
| | 8939 | the drawback that it left no standard way of expressing the intention |
| | 8940 | of driving/riding the vehicle out of its location. |
| | 8941 | |
| | 8942 | <p>For certain vehicles, it might still be desirable for OUT to mean |
| | 8943 | GET OUT. Fortunately, it's easy to override the default behavior on |
| | 8944 | a case-by-case basis - just override a vehicle's 'out' property to |
| | 8945 | return nestedRoomOut: |
| | 8946 | |
| | 8947 | <p><pre> |
| | 8948 | car: Vehicle |
| | 8949 | out = nestedRoomOut |
| | 8950 | |
| | 8951 | // ...other properties... |
| | 8952 | ; |
| | 8953 | </pre> |
| | 8954 | |
| | 8955 | </div> |
| | 8956 | |
| | 8957 | <!-------------------> |
| | 8958 | <div class=entry> |
| | 8959 | |
| | 8960 | In the past, RoomConnector and OneWayRoomConnector didn't apply the |
| | 8961 | proper preconditions to travel; in particular, they didn't properly |
| | 8962 | determine the required initial location for the travel, so they didn't |
| | 8963 | move an actor out of a nested room before attempting the travel. This |
| | 8964 | has been corrected; RoomConnector now uses the travel preconditions |
| | 8965 | formerly defined in RoomAutoConnector, so all RoomConnector subclasses |
| | 8966 | (including OneWayRoomConnector and RoomAutoConnector) now use the |
| | 8967 | correct preconditions. |
| | 8968 | |
| | 8969 | </div> |
| | 8970 | |
| | 8971 | <!-------------------> |
| | 8972 | <div class=entry> |
| | 8973 | |
| | 8974 | Enterable and Exitable objects now add a "touchable" pre-condition to |
| | 8975 | travel through the objects. In the past, only the pre-conditions for |
| | 8976 | the underlying connector were applied; since some types of travel |
| | 8977 | connectors are not themselves physical objects, this occasionally led |
| | 8978 | to odd results. In particular, if an Enterable or Exitable was |
| | 8979 | visible but not touchable (for example, if the object was at a |
| | 8980 | distance, or separated from the actor by a window), it was possible |
| | 8981 | to enter it despite its being unreachable. This type of anomaly should |
| | 8982 | no longer occur. |
| | 8983 | |
| | 8984 | </div> |
| | 8985 | |
| | 8986 | <!-------------------> |
| | 8987 | <div class=entry> |
| | 8988 | |
| | 8989 | The departure and arrival messages for NPC's now yield more pleasing |
| | 8990 | results in cases where an NPC arrives or departs from a visible |
| | 8991 | "remote" location - that is, a location not part of the PC's |
| | 8992 | outermost room, but connected to the PC's location by a sense |
| | 8993 | connector (such as a window between two rooms, or a |
| | 8994 | DistanceConnector). There are two cases where the departure and |
| | 8995 | arrival messages are enhanced. |
| | 8996 | |
| | 8997 | <p>First, when an NPC departs from or arrives at a remote location, |
| | 8998 | and the other end of the NPC's travel is out of sight, the library |
| | 8999 | adds the name of the remote location to the arrival or departure |
| | 9000 | message. For example: "Bob leaves to the east from the alley," or |
| | 9001 | "Bob comes down the stairs to the north end of the courtyard." The |
| | 9002 | name of the location is taken from the destName property of the NPC's |
| | 9003 | location. The location name is only shown when the location is |
| | 9004 | remote; when an NPC enters or leaves the PC's outermost room, the |
| | 9005 | traditional messages ("Bob leaves to the east," etc.) are shown. The |
| | 9006 | addition of the location name to the message helps clarify that the |
| | 9007 | NPC is moving around nearby and within sight, but isn't directly at |
| | 9008 | the PC's location. |
| | 9009 | |
| | 9010 | <p>Second, when an NPC starts and finishes its journey within sight |
| | 9011 | of the PC, the library omits the departure message entirely, and |
| | 9012 | displays a new type of arrival message. When the entire journey is |
| | 9013 | within the PC's field of view, we don't wish to describe the |
| | 9014 | departure and arrival as two separate steps, since the whole journey |
| | 9015 | can be described as a single operation; this is what the new type of |
| | 9016 | arrival message does. The new message is given by the new |
| | 9017 | TravelConnector method describeLocalArrival(), which the traveler |
| | 9018 | calls from its describeNpcArrival method when it determines that the |
| | 9019 | origin is visible to the PC. TravelConnector.describeLocalArrival() |
| | 9020 | in turn calls the new Traveler method sayArrivingLocally(), and the |
| | 9021 | default implementation of this new method simply displays the library |
| | 9022 | message given by libMessages.sayArrivingLocally(). The library |
| | 9023 | message displays a message of the form "Bob enters the alley." Note |
| | 9024 | that it might sometimes be desirable to customize the travel |
| | 9025 | connector's describeLocalArrival() method: you could say things like |
| | 9026 | "Bob climbs the stairs up to the loft," or "Bob squeezes through the |
| | 9027 | window into the kitchen," for example. |
| | 9028 | |
| | 9029 | </div> |
| | 9030 | |
| | 9031 | <!-------------------> |
| | 9032 | <div class=entry> |
| | 9033 | |
| | 9034 | BasicLocation.cannotGoThatWay now obtains the message to display from |
| | 9035 | a new property of 'self', cannotGoThatWayMsg. By default, this |
| | 9036 | returns &cannotGoThatWayMsg, which is the library message property |
| | 9037 | for the default message for this case. You can easily override a |
| | 9038 | room's message when travel is not possible in a given direction by |
| | 9039 | overriding cannotGoThatWayMsg to return a single-quoted string with |
| | 9040 | your custom message. |
| | 9041 | |
| | 9042 | </div> |
| | 9043 | |
| | 9044 | <!-------------------> |
| | 9045 | <div class=entry> |
| | 9046 | |
| | 9047 | The class GuidedInTravelState formerly defined each of the |
| | 9048 | sayDepartingXxx() methods separately to show the departing-with-guide |
| | 9049 | library message. Now, the class instead defines only sayDeparting() |
| | 9050 | to display this message. This creates the identical effect by |
| | 9051 | default, since all of the sayDepartingXxx() methods inherited from |
| | 9052 | GuidedInTravelState's base class (AccompanyingInTravelState) simply |
| | 9053 | call sayDeparting(). The advantage of this change is that it allows |
| | 9054 | GuidedInTravelState's travel message for all of these different |
| | 9055 | variations to be customized by overriding sayDeparting(), rather than |
| | 9056 | overriding each sayDepartingXxx() individually. |
| | 9057 | |
| | 9058 | </div> |
| | 9059 | |
| | 9060 | <!-------------------> |
| | 9061 | <div class=entry> |
| | 9062 | |
| | 9063 | SpaceOverlay now checks the "moved" status of its "identity" object, |
| | 9064 | not its own "moved" status, to determine if it should abandon its |
| | 9065 | contents on being moved for the first time. This makes the operation |
| | 9066 | work properly when the overlay is a component of a ComplexContainer, |
| | 9067 | which will usually be the case; since only the parent complex |
| | 9068 | container is actually marked as moved, checking the status of the |
| | 9069 | child overlay object wasn't enough. Checking the identity object |
| | 9070 | ensures that the status of the larger object of which the overlay is |
| | 9071 | a part is properly taken into account. |
| | 9072 | |
| | 9073 | </div> |
| | 9074 | |
| | 9075 | <!-------------------> |
| | 9076 | <div class=entry> |
| | 9077 | |
| | 9078 | The TravelPushable method beforeMovePushable() now takes a new |
| | 9079 | third parameter, 'dest', giving the destination of the travel. |
| | 9080 | |
| | 9081 | </div> |
| | 9082 | |
| | 9083 | <!-------------------> |
| | 9084 | <div class=entry> |
| | 9085 | |
| | 9086 | SpaceOverlay now overrides beforeMovePushable() to call |
| | 9087 | abandonContents(). This ensures that if the object is a |
| | 9088 | TravelPushable, and it's pushed to an new location, the contents are |
| | 9089 | abandoned <i>before</i> the actor moves to the destination location. |
| | 9090 | In the past, the object waited for the normal moveInto() notification |
| | 9091 | to abandon its contents; but this notification didn't arrive until |
| | 9092 | after the actor had already moved to the destination location, so the |
| | 9093 | actor wasn't able to see the contents being abandoned, thus we weren't |
| | 9094 | able to list the contents properly. |
| | 9095 | |
| | 9096 | <p>ComplexContainer also overrides beforeMovePushable(), passing the |
| | 9097 | notification down to any SpaceOverlay components it has. This |
| | 9098 | corrects the same problem for a ComplexContainer that's also a |
| | 9099 | TravelPushable, and which has SpaceOverlay components. |
| | 9100 | |
| | 9101 | </div> |
| | 9102 | |
| | 9103 | <!-------------------> |
| | 9104 | <div class=entry> |
| | 9105 | |
| | 9106 | SpaceOverlay is now more careful about the way it reveals the |
| | 9107 | contents of the object when it's moved. In the past, it simply did |
| | 9108 | an appropriate kind of nested command (LOOK UNDER for an Underside, |
| | 9109 | for example) to generate the listing. This generally showed up |
| | 9110 | before the main report for the action, so when the main report was a |
| | 9111 | simple default report (such as "Taken"), it created confusion by |
| | 9112 | suggesting that the default report somehow applied to the last object |
| | 9113 | listed in the revelation: |
| | 9114 | |
| | 9115 | <p> |
| | 9116 | <pre> |
| | 9117 | >take box |
| | 9118 | Under the box is a rusty can. Taken. |
| | 9119 | </pre> |
| | 9120 | |
| | 9121 | <p>There are two changes to the way this listing is generated. |
| | 9122 | |
| | 9123 | <p>First, the listing is no longer just a generic LOOK UNDER (or |
| | 9124 | equivalent). Instead, it uses a new lister, given by the |
| | 9125 | abandonContentsLister property of the SpaceOverlay object. Underside |
| | 9126 | uses undersideAbandonContentsLister by default, and RearSurface and |
| | 9127 | RearContainer use rearAbandonContentsLister. These new listers use |
| | 9128 | more specific language to describe the revelation, of the form |
| | 9129 | "Moving the box reveals a rusty can underneath" (or "behind"). |
| | 9130 | |
| | 9131 | <p>Second, the SpaceOverlay takes care to move the listing so that it |
| | 9132 | follows the main report from the command that triggered the listing. |
| | 9133 | This ensures that the main report remains close to the command line, |
| | 9134 | which is required if the terse phrasing of the default reports is |
| | 9135 | to make sense. |
| | 9136 | |
| | 9137 | <p>There's one exception, though: if the actor performing the command |
| | 9138 | ends up in a different location at the end of the command, the |
| | 9139 | listing is <i>not</i> moved to the end of the report. Instead, the |
| | 9140 | listing simply stays at the beginning of the command. This exception |
| | 9141 | is important because travel usually triggers a description of the new |
| | 9142 | location, and once we're in the new location, the revelation of the |
| | 9143 | SpaceOverlay's contents will seem out of place. It's better in these |
| | 9144 | cases to leave the contents listing at the start of the reports. |
| | 9145 | |
| | 9146 | <p>With these two changes, the old listing above is transformed |
| | 9147 | into this: |
| | 9148 | |
| | 9149 | <p> |
| | 9150 | <pre> |
| | 9151 | >take box |
| | 9152 | Taken. Moving the box reveals a rusty can underneath. |
| | 9153 | </pre> |
| | 9154 | |
| | 9155 | </div> |
| | 9156 | |
| | 9157 | <!-------------------> |
| | 9158 | <div class=entry> |
| | 9159 | |
| | 9160 | If all of the changes described above to SpaceOverlay's revelation |
| | 9161 | listing are still not adequate for some special case in your game, |
| | 9162 | you can now easily suppress the default listing and generate your own |
| | 9163 | explicit listing instead, thanks to a couple of new features. |
| | 9164 | |
| | 9165 | <p>First, the new SpaceOverlay property 'neverListOnMove' lets you |
| | 9166 | suppress the default listing; just set this property to true, and no |
| | 9167 | listing will ever be generated when the overlay object is moved. If |
| | 9168 | the contents are to be abandoned, the abanonment will still happen, |
| | 9169 | but no automatic mention will be made of it. Your code is |
| | 9170 | responsible in these cases for generating any desired listing. |
| | 9171 | |
| | 9172 | <p>Second, the new method listContentsForMove() generates the |
| | 9173 | revelation of the contents in the default format. SpaceOverlay calls |
| | 9174 | this method itself to generate the automatic message when |
| | 9175 | appropriate. If you set neverListOnMove to true in order to suppress |
| | 9176 | the default revelation listing, you can call listContentsForMove() at |
| | 9177 | the appropriate juncture in your own code to generate a substitute |
| | 9178 | listing. Of course, you could instead completely customize the |
| | 9179 | listing with your own method; but if you only want to change |
| | 9180 | <i>where</i> the listing appears, without changing its contents, |
| | 9181 | listContentsForMove() makes that easy. |
| | 9182 | |
| | 9183 | <p>Note also that you can customize the standard listing format used |
| | 9184 | by providing your own lister, and setting the SpaceOverlay object's |
| | 9185 | abandonContentsLister to refer to your custom lister. |
| | 9186 | |
| | 9187 | </div> |
| | 9188 | |
| | 9189 | <!-------------------> |
| | 9190 | <div class=entry> |
| | 9191 | |
| | 9192 | In the default Floor class, there were a couple of problems with the |
| | 9193 | commands SIT ON FLOOR, STAND ON FLOOR, and LIE ON FLOOR that have now |
| | 9194 | been corrected. First, when standing in a nested room, STAND ON |
| | 9195 | FLOOR incorrectly failed with the message "You're already standing." |
| | 9196 | Second, when already sitting, lying, or standing on the floor, |
| | 9197 | another command to do the same thing was incorrectly accepted; it's |
| | 9198 | now rejected with an appropriate message (such as "You're already |
| | 9199 | sitting on the floor"). |
| | 9200 | |
| | 9201 | </div> |
| | 9202 | |
| | 9203 | <!-------------------> |
| | 9204 | <div class=entry> |
| | 9205 | |
| | 9206 | If the player character was in a nested room, and typed a command to |
| | 9207 | leave the nested room, and immediately followed with an AGAIN |
| | 9208 | command, the AGAIN incorrectly succeeded, making it look like the |
| | 9209 | character was getting out of the nested room repeatedly without |
| | 9210 | getting back in. This has been corrected; an appropriate message |
| | 9211 | ("you're not in the booth") is now displayed on the errant repetition. |
| | 9212 | |
| | 9213 | </div> |
| | 9214 | |
| | 9215 | <!-------------------> |
| | 9216 | <div class=entry> |
| | 9217 | |
| | 9218 | In ActorTopicDatabase.initiateTopic(), the conversation is "noted" |
| | 9219 | only if an InitiateTopic is found to handle the request. Noting the |
| | 9220 | conversation means that we set the actor's last interlocutor to the |
| | 9221 | player character, so this change means that initiateTopic() won't |
| | 9222 | affect the actor's interlocutor unless a conversation is actually |
| | 9223 | initiated. (In the past, the routine always noted the conversation. |
| | 9224 | This caused odd side effects when initiateTopic() was called |
| | 9225 | speculatively, without knowing for sure that an InitiateTopic was |
| | 9226 | actually available, since the interlocutor changed even though no |
| | 9227 | conversational action was visible to the player. This change ensures |
| | 9228 | that the interlocutor will only change when a conversation actually |
| | 9229 | takes place.) |
| | 9230 | |
| | 9231 | </div> |
| | 9232 | |
| | 9233 | <!-------------------> |
| | 9234 | <div class=entry> |
| | 9235 | |
| | 9236 | When an InConversationState object becomes the active state for an |
| | 9237 | actor, it remembers the previously active state so that it can, by |
| | 9238 | default, transition back to that previous state when the conversation |
| | 9239 | ends. In the past, the InConversationState class remembered |
| | 9240 | <i>any</i> previous state and used it as the new state at the end of |
| | 9241 | the conversation. This has been changed. Now, the class remembers |
| | 9242 | the previous state only if the previous state is a |
| | 9243 | ConversationReadyState, or there's no other previous state already |
| | 9244 | remembered. This change makes it easier for an actor to interrupt a |
| | 9245 | conversation with another activity, and later resume the |
| | 9246 | conversation, because the interrupting state will no longer "take |
| | 9247 | over" at the end of the conversation. You can still explicitly set |
| | 9248 | the end-of-conversation state explicitly to anything you want; this |
| | 9249 | change only affects the default state transitions that occur in the |
| | 9250 | absence of any explicit settings. |
| | 9251 | |
| | 9252 | </div> |
| | 9253 | |
| | 9254 | <!-------------------> |
| | 9255 | <div class=entry> |
| | 9256 | |
| | 9257 | The HELLO and TALK TO commands now defer the implied topic inventory |
| | 9258 | until the end of the turn, if the response to the HELLO or TALK TO |
| | 9259 | contains any non-default reports. This is important because a |
| | 9260 | non-default report could set the ConvNode for the responding actor, |
| | 9261 | but such a change doesn't take effect until the transcript is fully |
| | 9262 | processed at the end of the turn. In the past, HELLO and TALK TO |
| | 9263 | always showed the topic inventory right away, so the inventory didn't |
| | 9264 | necessarily match the new ConvNode's active topics. With this |
| | 9265 | change, a ConvNode change within a HELLO or TALK TO will be properly |
| | 9266 | reflected in the topic inventory. |
| | 9267 | |
| | 9268 | </div> |
| | 9269 | |
| | 9270 | <!-------------------> |
| | 9271 | <div class=entry> |
| | 9272 | |
| | 9273 | The new ConvNode property 'isSticky' lets you create a "sticky" |
| | 9274 | conversation node. By default, nodes are non-stick: this yields the |
| | 9275 | traditional behavior, where the NPC leaves the node if a response |
| | 9276 | doesn't explicitly stay there. (If the node is active, and the NPC |
| | 9277 | shows a response that doesn't set any new node, the actor's current |
| | 9278 | node is set to nil.) |
| | 9279 | |
| | 9280 | <p>If you set 'isSticky' to true for a node, the node will stay |
| | 9281 | active if the NPC shows a response that doesn't set a new node. In |
| | 9282 | other words, the "default next node" for any response while the |
| | 9283 | sticky node is active is the sticky node itself, rather than nil. |
| | 9284 | |
| | 9285 | <p>Sticky nodes are useful in cases where you want an actor to drive |
| | 9286 | a conversation along a particular thread, but you still want to allow |
| | 9287 | the player to digress by talking about other topics. As long as a |
| | 9288 | digression doesn't explicitly set a new node, the sticky node will |
| | 9289 | remain active. |
| | 9290 | |
| | 9291 | </div> |
| | 9292 | |
| | 9293 | <!-------------------> |
| | 9294 | <div class=entry> |
| | 9295 | |
| | 9296 | DefaultCommandTopic now has a matchScore of 3, which makes the |
| | 9297 | library choose it over a DefaultAnyTopic if both kinds of default |
| | 9298 | topics are active for a given response. (In the past, |
| | 9299 | DefaultCommandTopic had the same matchScore as a DefaultAnyTopic, so |
| | 9300 | in cases where both kinds were active the library chose one |
| | 9301 | arbitrarily. The DefaultCommandTopic should always take precedence, |
| | 9302 | as it now does, because it's the more specific kind of response.) |
| | 9303 | |
| | 9304 | </div> |
| | 9305 | |
| | 9306 | <!-------------------> |
| | 9307 | <div class=entry> |
| | 9308 | |
| | 9309 | AltTopic now takes its setting for the 'impliesGreeting' property |
| | 9310 | from its enclosing topic. This ensures that an AltTopic used within |
| | 9311 | a HelloTopic or the like will behave the same as its enclosing main |
| | 9312 | topic by default. |
| | 9313 | |
| | 9314 | </div> |
| | 9315 | |
| | 9316 | <!-------------------> |
| | 9317 | <div class=entry> |
| | 9318 | |
| | 9319 | ByeTopic and ImpByeTopic now work together the same way that |
| | 9320 | HelloTopic and ImpHelloTopic work together. Specifically, ByeTopic is |
| | 9321 | now a catch-all that matches both explicit GOODBYE commands and |
| | 9322 | implied conversation endings. (Implied goodbyes happen when the |
| | 9323 | player character just walks away from a conversation, or the NPC gets |
| | 9324 | "bored" from lack of attention). ImpByeTopic still matches only |
| | 9325 | implied goodbyes; since it's the more specific of the two, it now uses |
| | 9326 | an elevated matchScore. This means that if both a ByeTopic and an |
| | 9327 | ImpByeTopic are active at the same time, the ImpByeTopic will be |
| | 9328 | chosen for an implied goodbye, and the ByeTopic will be chosen for an |
| | 9329 | explicit GOODBYE command. |
| | 9330 | |
| | 9331 | <p>This change makes it easier to program catch-all goodbye messages, |
| | 9332 | while still allowing differentiation when desired. To create a |
| | 9333 | catch-all message that handles both explicit and implicit goodbyes, |
| | 9334 | just create a ByeTopic. If you want to differentiate, create one of |
| | 9335 | each: the ByeTopic will be chosen for the explicit GOODBYE commands, |
| | 9336 | since the ImpByeTopic won't match those; and the ImpByeTopic will be |
| | 9337 | chosen for implied goodbye, because both will match, but the |
| | 9338 | ImpByeTopic's higher matchScore will ensure that it's selected over |
| | 9339 | the ByeTopic. |
| | 9340 | |
| | 9341 | <p>Along the same lines, HelloGoodbyeTopicObj now matches implied |
| | 9342 | as well as explicit goodbyes. (In the past, it handled implied and |
| | 9343 | explicit greetings, but only explicit goodbyes.) |
| | 9344 | |
| | 9345 | </div> |
| | 9346 | |
| | 9347 | <!-------------------> |
| | 9348 | <div class=entry> |
| | 9349 | |
| | 9350 | Some of the behavior of InConversationState.endConversation has been |
| | 9351 | moved to the base ActorState class. This ensures that the active |
| | 9352 | ConvNode will be notified if the player walks away from a |
| | 9353 | conversation. |
| | 9354 | |
| | 9355 | </div> |
| | 9356 | |
| | 9357 | <!-------------------> |
| | 9358 | <div class=entry> |
| | 9359 | |
| | 9360 | The library messages for scoring (showScoreMessage, |
| | 9361 | showScoreNoMaxMessage, showScoreRankMessage, showFullScorePrefix) now |
| | 9362 | refer explicitly to "you", not to the player character. Since the |
| | 9363 | score is a meta-game feature, it should be attributed directly to the |
| | 9364 | player, not to the player character. This is especially important in |
| | 9365 | games that refer to the player character in the first or third |
| | 9366 | person, since the distinction between player and player character is |
| | 9367 | more evident in these cases than it is in second-person games. |
| | 9368 | |
| | 9369 | </div> |
| | 9370 | |
| | 9371 | <!-------------------> |
| | 9372 | <div class=entry> |
| | 9373 | |
| | 9374 | The library message for trying to put an object inside an another |
| | 9375 | object that already contains the first object (i.e., the "circular |
| | 9376 | containment" message) now reports the objects as specified, rather |
| | 9377 | than possibly showing an intermediate container. In the past, an |
| | 9378 | intermediate container was shown in some circumstances, especially |
| | 9379 | when a ComplexContainer was involved; this produced the wrong |
| | 9380 | messages in some cases. |
| | 9381 | |
| | 9382 | </div> |
| | 9383 | |
| | 9384 | <!-------------------> |
| | 9385 | <div class=entry> |
| | 9386 | |
| | 9387 | In the past, the multiple object announcement ("red book: Taken") was |
| | 9388 | missing in in some cases where the action was remapped (via remapTo). |
| | 9389 | This has been corrected. |
| | 9390 | |
| | 9391 | </div> |
| | 9392 | |
| | 9393 | <!-------------------> |
| | 9394 | <div class=entry> |
| | 9395 | |
| | 9396 | The implied action message generator now allows for "silent" implied |
| | 9397 | actions - implied actions that behave as usual but generate no |
| | 9398 | announcement text (the normal announcement is the message of the form |
| | 9399 | "(first opening the door)" shown at the start of the response to the |
| | 9400 | command). |
| | 9401 | |
| | 9402 | <p>First, the new libMessages method silentImplicitAction() can be |
| | 9403 | used in place of the standard announceImplicitAction() to generate |
| | 9404 | the announcement. silentImplicitAction() simply shows no message. |
| | 9405 | To use it, perform the implied action with a call like this: |
| | 9406 | |
| | 9407 | <p><pre> |
| | 9408 | tryImplicitActionMsg(&silentImplicitAction, Open, self); |
| | 9409 | </pre> |
| | 9410 | |
| | 9411 | <p>Second, the lister that aggregates a set of implicit actions into a |
| | 9412 | single announcement message now accepts the empty messages generated |
| | 9413 | by silentImplicitAction(). This ensures that silent implied actions |
| | 9414 | can be mixed with announced implied actions in a single command, and |
| | 9415 | a sensible aggregate announcement will be displayed. |
| | 9416 | |
| | 9417 | </div> |
| | 9418 | |
| | 9419 | <!-------------------> |
| | 9420 | <div class=entry> |
| | 9421 | |
| | 9422 | Thing.setContentsSeenBy() incorrectly marked the object's contents as |
| | 9423 | having been seen by 'gActor' rather than by the actor passed as a |
| | 9424 | parameter to the method. This has been corrected. |
| | 9425 | |
| | 9426 | </div> |
| | 9427 | |
| | 9428 | <!-------------------> |
| | 9429 | <div class=entry> |
| | 9430 | |
| | 9431 | In PresentLater, when the object is made present (via the makePresent |
| | 9432 | method, or any of the related methods), the object and its contents |
| | 9433 | are specifically marked as seen by the player character, to the |
| | 9434 | extent the player character can actually see them at the moment they |
| | 9435 | become present in the location. In most cases, when an object comes |
| | 9436 | into play dynamically via the PresentLater mechanism, the sudden |
| | 9437 | appearance is the result of some specific event that the game will |
| | 9438 | describe through custom handling - that is, the game will |
| | 9439 | specifically mention the new object to the player, so the player |
| | 9440 | character should remember having seen the object. |
| | 9441 | |
| | 9442 | </div> |
| | 9443 | |
| | 9444 | <!-------------------> |
| | 9445 | <div class=entry> |
| | 9446 | |
| | 9447 | In a two-object command (such as PUT VASE ON TABLE), the parser now |
| | 9448 | retains the meaning of a pronoun used in the command, regardless of |
| | 9449 | which object slot the pronoun is used in. For example, after the |
| | 9450 | command PUT VASE ON IT, the pronoun "it" is set to refer to the |
| | 9451 | indirect object, even though "it" would normally refer to the direct |
| | 9452 | object after a PUT X ON Y command. |
| | 9453 | |
| | 9454 | <p>In the past, the parser unconditionally set the pronoun antecedent |
| | 9455 | after a two-object command to the second-resolved object, which in |
| | 9456 | many such verbs is the direct object. So, after PUT VASE ON IT, the |
| | 9457 | pronoun "it" previously referred to the vase. Due to this change, |
| | 9458 | though, the explicit use of the word "it" directly within the command |
| | 9459 | causes meaning of "it" to be left unchanged by the command. This |
| | 9460 | change doesn't affect the behavior when no pronoun is used in the |
| | 9461 | command, so PUT VASE ON TABLE still causes "it" to refer to the vase |
| | 9462 | on the subsequent command. |
| | 9463 | |
| | 9464 | </div> |
| | 9465 | |
| | 9466 | <!-------------------> |
| | 9467 | <div class=entry> |
| | 9468 | |
| | 9469 | ConsultTopic and DefaultConsultTopic now refrain from setting any |
| | 9470 | pronoun antecedents for the topic. This means that after any |
| | 9471 | consultation command (LOOK UP, FIND IN, etc.), the pronoun antecedent |
| | 9472 | will be the consultable object, not the topic last sought. |
| | 9473 | |
| | 9474 | </div> |
| | 9475 | |
| | 9476 | <!-------------------> |
| | 9477 | <div class=entry> |
| | 9478 | |
| | 9479 | TopicTAction (used for commands such as ASK ABOUT and CONSULT ABOUT) |
| | 9480 | didn't work properly if a reflexive pronoun was used as the direct |
| | 9481 | object, referring back to the topic phrase: LOOK UP BOOK IN ITSELF, |
| | 9482 | for example. This showed a couple of symptoms, including "Nothing |
| | 9483 | obvious happens" responses and run-time errors. The problem has been |
| | 9484 | corrected; the action now looks to the topic phrase to resolve the |
| | 9485 | direct object, producing consistent and appropriate results. |
| | 9486 | |
| | 9487 | </div> |
| | 9488 | |
| | 9489 | <!-------------------> |
| | 9490 | <div class=entry> |
| | 9491 | |
| | 9492 | When a command is directed to an NPC (as in BOB, OPEN DOOR), and the |
| | 9493 | parser has to prompt interactively for disambiguation or for a |
| | 9494 | missing noun phrase, the parser now treats gender-matched |
| | 9495 | third-person pronouns in the reponse as referring to the target |
| | 9496 | actor. For example: |
| | 9497 | |
| | 9498 | <p><pre> |
| | 9499 | >look at bob |
| | 9500 | He's wearing a red sweater. |
| | 9501 | |
| | 9502 | >bill, examine |
| | 9503 | What do you want Bill to look at? |
| | 9504 | |
| | 9505 | >his book |
| | 9506 | The book looks old and dusty; the title on the cover is faded |
| | 9507 | to the point of being unreadable. |
| | 9508 | </pre> |
| | 9509 | |
| | 9510 | <p>In the past, the parser would have taken the "his" in the |
| | 9511 | interactive response to refer to Bob, since Bob would have been the |
| | 9512 | pronoun antecedent up until that point (by virtue of having been |
| | 9513 | mentioned in the previous command). With this change, the parser |
| | 9514 | takes "his" to refer to Bill. This fits with the phrasing of the |
| | 9515 | prompt text, and also with the fact that Bill was mentioned more |
| | 9516 | recently in a command (specifically, in the incomplete "examine" |
| | 9517 | command). |
| | 9518 | |
| | 9519 | <p>Similarly, reflexive third-person pronouns (HIMSELF, HERSELF, |
| | 9520 | ITSELF, THEMSELVES) in interactive responses are taken as referring |
| | 9521 | to the target actor, when the gender matches. |
| | 9522 | |
| | 9523 | </div> |
| | 9524 | |
| | 9525 | <!-------------------> |
| | 9526 | <div class=entry> |
| | 9527 | |
| | 9528 | The parser is now more consistent in its treatment of truncated |
| | 9529 | vocabulary matches. (Truncated matches are words in the player's |
| | 9530 | command that match longer object names defined in the game, by |
| | 9531 | truncating the longer object names to the dictionary's minimum length. |
| | 9532 | For example, the default English dictionary truncation length is 6 |
| | 9533 | characters, meaning that the player can shorten the word FLASHLIGHT to |
| | 9534 | FLASHL, FLASHLI, etc., when entering commands.) |
| | 9535 | |
| | 9536 | <p>In the past, the parser treated exact matches as stronger than |
| | 9537 | truncated matches for singular definite noun phrases (the most common |
| | 9538 | kind of noun phrase: TAKE BOOK, OPEN THE BOX). Any time the parser |
| | 9539 | matched some names exactly and other names only after truncation for |
| | 9540 | the same user input, the parser kept only the exact matches, filtering |
| | 9541 | out the truncated matches. This rule hasn't been changed; what's |
| | 9542 | changed is that it has now been extended to every kind of noun phrase, |
| | 9543 | including indefinite phrases (TAKE A BOOK) and plural phrases (TAKE |
| | 9544 | BOOKS). |
| | 9545 | |
| | 9546 | </div> |
| | 9547 | |
| | 9548 | <!-------------------> |
| | 9549 | <div class=entry> |
| | 9550 | |
| | 9551 | <a name='pluralToNounExpansion'></a> |
| | 9552 | In the English parser, when the parser matches a plural phrase (i.e., |
| | 9553 | a phrase with a vocabulary word defined under the 'plural' property), |
| | 9554 | the parser now includes both 'plural' <i>and</i> 'noun' matches for |
| | 9555 | the word. In the past, only the 'plural' matches were included. |
| | 9556 | |
| | 9557 | <p>In some cases, it's convenient to define a word that's |
| | 9558 | grammatically a plural under the 'noun' property, because a single |
| | 9559 | game object encompasses what looks to the user like a set of |
| | 9560 | something: a bookcase might define "shelves" as a noun, for example, |
| | 9561 | since the individual shelves aren't modeled as separate objects. This |
| | 9562 | change ensures that if other objects are in scope that define the same |
| | 9563 | word under the 'plural' property, the bookcase will still match the |
| | 9564 | word "shelves" when the noun phrase is resolved. |
| | 9565 | |
| | 9566 | <p>This change doesn't actually make much difference most of the time, |
| | 9567 | but it is frequently significant in "topic" phrases (as in ASK ABOUT). |
| | 9568 | Topic phrases have very wide scope, so a particular word can match |
| | 9569 | numerous objects from all over the game. In these cases, the old |
| | 9570 | scheme that included only 'plural' matches was overly exclusive, |
| | 9571 | causing the parser to omit objects from the topic resolution that the |
| | 9572 | author would at first glance have expected to be included. The new |
| | 9573 | more inclusive matching should reduce the potential for confusing |
| | 9574 | match exclusions in these cases. |
| | 9575 | |
| | 9576 | </div> |
| | 9577 | |
| | 9578 | <!-------------------> |
| | 9579 | <div class=entry> |
| | 9580 | |
| | 9581 | <a name='#nounEndingToAdjEndingExpansion'></a> |
| | 9582 | The English parser is now more inclusive in matching nouns and |
| | 9583 | adjectives at the ends of "topic" phrases. (Topic phrases are used in |
| | 9584 | commands like ASK ABOUT and TELL ABOUT, where the player can refer to |
| | 9585 | physical objects as well as to abstract Topic objects, and can even |
| | 9586 | use random text that doesn't correspond to any game objects.) |
| | 9587 | |
| | 9588 | <p>Normally, when the last word of a noun phrase can match one or more |
| | 9589 | objects in scope that define the word under the 'noun' property, the |
| | 9590 | parser will ignore any additional in-scope objects that match the same |
| | 9591 | word under the 'adjective' property. For example, if there's a desk |
| | 9592 | in scope that defines 'desk' as a noun, and there's also a desk drawer |
| | 9593 | that defines 'desk' as an adjective, the parser will interpreter LOOK |
| | 9594 | AT DESK as referring to the desk, not to the drawer. However, if |
| | 9595 | there's a red book present, but there's no object in scope that |
| | 9596 | defines 'red' as a noun, the parser takes READ RED as referring to the |
| | 9597 | red book, even though BOOK was left unstated. This combination of |
| | 9598 | rules gives the player the convenience of abbreviating the name of an |
| | 9599 | object to a unique adjective, while avoiding spurious ambiguity in |
| | 9600 | cases like the desk-and-drawer exmaple. |
| | 9601 | |
| | 9602 | <p>In cases of "global" scope, though, this strategy isn't as |
| | 9603 | beneficial. When resolving a topic phrase, objects from all over the |
| | 9604 | game have to be considered "in scope" even though they're not |
| | 9605 | physically present, as it's perfectly reasonable for the player to ASK |
| | 9606 | ABOUT something that was seen earlier in the game but isn't physically |
| | 9607 | present at the time of the question. As a result, the elimination of |
| | 9608 | adjective bindings for a word can cause subtle problems that are very |
| | 9609 | difficult to track down, and which sometimes can't be easily fixed |
| | 9610 | without creating other problems. Two objects could happen to share |
| | 9611 | the same vocabulary words, in one case as an adjective and in the |
| | 9612 | other case as a noun, even though the objects are completely |
| | 9613 | unrelated. Thus, the existence of one object can change the way |
| | 9614 | another object's vocabulary words are treated when matching a topic |
| | 9615 | phrase. |
| | 9616 | |
| | 9617 | <p>The English parser now treats topic resolution differently. When |
| | 9618 | resolving a topic phrase, the parser no longer makes the strict |
| | 9619 | noun/adjective distinction. Instead, the parser considers both kinds |
| | 9620 | of vocabulary to match. So, if the player types ASK BOB ABOUT DESK in |
| | 9621 | our example with the drawer, both the desk and the drawer are now |
| | 9622 | considered possible topic matches. |
| | 9623 | |
| | 9624 | <p>This change has the potential to create a different sort of |
| | 9625 | problem, in that it could include <i>too many</i> possible matches for |
| | 9626 | a topic phrase. However, this is a much easier problem to deal with |
| | 9627 | than the old one, and in most cases won't even be noticeable as a |
| | 9628 | problem. In the first place, topic phrases don't require |
| | 9629 | disambiguation in the normal sense; the parser never asks the player |
| | 9630 | which object was intended, so the more inclusive matching won't |
| | 9631 | degrade the user interface by generating more disambiguation queries. |
| | 9632 | Second, it's much easier to understand why an extra object is matching |
| | 9633 | a given vocabulary word than to understand why a given object is |
| | 9634 | failing to match. A failure to match indicates that some other object |
| | 9635 | is defining the same word under another part of speech, but it doesn't |
| | 9636 | tell you which object or where it's defined; when too many objects |
| | 9637 | match, in contrast, you can easily see (using the debugger, for |
| | 9638 | example) which extra objects are matching, and make any desired |
| | 9639 | vocabulary adjustments. Third, in the vast majority of cases, the |
| | 9640 | extra matches are completely harmless and not even noticeable. Topics |
| | 9641 | are generally handled in conversations, and conversations have to |
| | 9642 | explicitly include responses for all of the topics they want to match. |
| | 9643 | If an extra object or two show up in vocabulary matching for a given |
| | 9644 | conversational command, it won't usually matter, because those |
| | 9645 | unexpected objects won't have topic matches in the conversation anyway |
| | 9646 | and will thus simply be ignored. In cases where you want a |
| | 9647 | conversation to distinguish among objects with similar vocabulary, you |
| | 9648 | can add the necessary distinguishing vocabulary to the objects just as |
| | 9649 | you would in cases of ordinary ambiguity, and you can tweak the topic |
| | 9650 | list (using match scores, for example) to control which response is |
| | 9651 | used for which vocabulary. In the rare cases where it's not |
| | 9652 | straightforward to fine-tune the matching using object vocabulary, you |
| | 9653 | can always resort to using regular expressions as the topic match |
| | 9654 | criteria. |
| | 9655 | |
| | 9656 | </div> |
| | 9657 | |
| | 9658 | <!-------------------> |
| | 9659 | <div class=entry> |
| | 9660 | <a name='global_scope_noun_adj'></a> |
| | 9661 | |
| | 9662 | Consider a situation where a given object is entered in the dictionary |
| | 9663 | with two words for a given part of speech, and one of the words |
| | 9664 | happens to be a leading substring of the other word, and both words |
| | 9665 | are long enough to trigger "truncated" matching (that is, each word is |
| | 9666 | at least six characters long, in the default dictionary truncation |
| | 9667 | configuration). For example, suppose a given object is entered in the |
| | 9668 | dictionary with 'noun' words for WINDOW and WINDOWSILL. Now, if the |
| | 9669 | player enters a command using the shorter word (WINDOW), the raw |
| | 9670 | dictionary match list will contain two matches for this object: one |
| | 9671 | for the exact match to the shorter word, and one for the truncated |
| | 9672 | match to the longer word. |
| | 9673 | |
| | 9674 | <p>In the past, this situation sometimes had undesirable results. In |
| | 9675 | most cases, the two matches to the same object were collapsed into a |
| | 9676 | single match, but the "match flags" from the two matches were combined |
| | 9677 | - so both matches were marked as truncated. Depending on what other |
| | 9678 | objects were in scope at the time, this had the effect of eliminating |
| | 9679 | the object from consideration as a resolution of the noun phrase: even |
| | 9680 | though it had an exact match in the dictionary, the resolver saw it as |
| | 9681 | a truncated match because of the combination of the two sets of match |
| | 9682 | flags. This was especially likely to affect topic phrases (ASK ABOUT, |
| | 9683 | for example), because the global scope made it much more likely that |
| | 9684 | other objects would have exact matches for the same vocabulary. |
| | 9685 | |
| | 9686 | <p>The parser is now smarter about the way it combines these sorts of |
| | 9687 | redundant matches. Instead of simply OR'ing together the match flags, |
| | 9688 | the parser now specifically keeps only the "strongest" match in these |
| | 9689 | cases. In our example, the parser sees that there's a truncated |
| | 9690 | dictionary match (WINDOWSILL) and an exact match (WINDOW) for the same |
| | 9691 | object, so it now decides to consider the match to be exact. |
| | 9692 | |
| | 9693 | </div> |
| | 9694 | |
| | 9695 | <!-------------------> |
| | 9696 | <div class=entry> |
| | 9697 | |
| | 9698 | The English parser now accepts IN <i>object</i>, INTO <i>object</i>, |
| | 9699 | and IN TO <i>object</i> as verb synonyms for ENTER <i>object</i>. |
| | 9700 | These aren't exactly valid English grammar, but they have a certain |
| | 9701 | linguistic consistency with other telegraphic IF-ese constructs, and |
| | 9702 | they seem to naturally occur to some players. These variations all |
| | 9703 | have an obvious meaning to an English speaker, and they're not |
| | 9704 | ambiguous with any other commands, so there should be no harm in |
| | 9705 | adding them as convenient abbreviations. |
| | 9706 | |
| | 9707 | </div> |
| | 9708 | |
| | 9709 | <!-------------------> |
| | 9710 | <div class=entry> |
| | 9711 | |
| | 9712 | After a misspelling, if the player typed OOPS but left off the |
| | 9713 | corrected spelling (i.e., just typed OOPS by itself on the command |
| | 9714 | line), the parser responded with a message saying that OOPS isn't |
| | 9715 | allowed right now. This has been corrected; the parser now responds |
| | 9716 | with a new message explaining the correct syntax, and gives the user |
| | 9717 | another chance to enter the OOPS command. |
| | 9718 | |
| | 9719 | </div> |
| | 9720 | |
| | 9721 | <!-------------------> |
| | 9722 | <div class=entry> |
| | 9723 | |
| | 9724 | When a single player command triggers more than one implied action |
| | 9725 | (for example, GO NORTH might trigger OPEN DOOR, which in turn might |
| | 9726 | trigger UNLOCK DOOR), the reporting mechanism had a couple of problems |
| | 9727 | when the doubly-nested action (UNLOCK DOOR in our example) itself |
| | 9728 | triggered a nested action, such as by remapTo or nestedAction. First, |
| | 9729 | the reported order of the implied actions was reversed ("first opening |
| | 9730 | the door, then unlocking it"); second, the doubly-nested one reported |
| | 9731 | the nested action rather than the original implied action. Both of |
| | 9732 | these have now been corrected. |
| | 9733 | |
| | 9734 | </div> |
| | 9735 | |
| | 9736 | <!-------------------> |
| | 9737 | <div class=entry> |
| | 9738 | |
| | 9739 | When you synthesize an action programmatically (via a function such |
| | 9740 | as replaceAction or nestedAction), the library has to choose a |
| | 9741 | language-specific final subclass of the generic action you specify. |
| | 9742 | It does this by choosing a VerbRule that's subclassed from the base |
| | 9743 | action. In the past, the choice was entirely arbitrary. Now, the |
| | 9744 | library is a little pickier: it now chooses only a final subclass, |
| | 9745 | never an intermediate class. That is, it always chooses a VerbRule |
| | 9746 | which hasn't been further subclassed (or modified with 'modify'). |
| | 9747 | The old, less selective algorithm occasionally caused oddities, such |
| | 9748 | as choosing a base VerbRule that was subclassed with 'modify', thus |
| | 9749 | picking up pre-'modify' values of properties such as the verb's |
| | 9750 | descriptive text. |
| | 9751 | |
| | 9752 | </div> |
| | 9753 | |
| | 9754 | <!-------------------> |
| | 9755 | <div class=entry> |
| | 9756 | |
| | 9757 | The conversationManager object now provides a simple extensibility |
| | 9758 | mechanism that lets you add your own custom conversation tags. To |
| | 9759 | add custom tags, use 'modify' to extend the conversationManager |
| | 9760 | object, then add two things. First, define the customTags property, |
| | 9761 | giving a string with the new tag names you want to add. The tag |
| | 9762 | names must be in lower-case letters; do not include the angle |
| | 9763 | brackets or the leading period in the tag name. Separate multiple |
| | 9764 | tag names with "|" symbols. Second, define a doCustomTag(tag,arg) |
| | 9765 | method that processes your custom tag or tags. The 'tag' argument is |
| | 9766 | a string giving the custom tag that was matched in the output stream; |
| | 9767 | only the tag name will be included, not including the angle brackets |
| | 9768 | or leading period. The 'arg' method is a string giving the argument |
| | 9769 | to the tag, if any; this is simply the part inside the angle brackets |
| | 9770 | following any whitespace after the tag. |
| | 9771 | |
| | 9772 | </div> |
| | 9773 | |
| | 9774 | <!-------------------> |
| | 9775 | <div class=entry> |
| | 9776 | |
| | 9777 | SensoryEmanation and its subclasses Noise and Odor will now let you |
| | 9778 | use Script objects for the hereWithSource and hereWithoutSource |
| | 9779 | properties. This is handy in cases where you want to vary the |
| | 9780 | object's description over time. If you define these properties as |
| | 9781 | Script objects, the SensoryEmanation object will invoke their |
| | 9782 | doScript() methods when an emanation message is to be displayed. |
| | 9783 | |
| | 9784 | </div> |
| | 9785 | |
| | 9786 | <!-------------------> |
| | 9787 | <div class=entry> |
| | 9788 | |
| | 9789 | The Keyring class has a new method, getLooseKeys(actor), that |
| | 9790 | identifies the loose keys in an actor's possession that are eligible |
| | 9791 | for automatic attachment when the keyring is taken. By default, this |
| | 9792 | returns the actor's direct contents (i.e., the objects the actor is |
| | 9793 | directly holding). |
| | 9794 | |
| | 9795 | <p>This can be overridden to consider, for example, loose keys held in |
| | 9796 | the actor's pocket. To prevent the keyring from automatically |
| | 9797 | grabbing any keys when it's taken, simply override this method to |
| | 9798 | return an empty list. Note that you don't need to bother limiting the |
| | 9799 | returned list to include only valid keys, since the caller does this |
| | 9800 | by considering only objects for which isMyKey() returns true. |
| | 9801 | |
| | 9802 | </div> |
| | 9803 | |
| | 9804 | <!-------------------> |
| | 9805 | <div class=entry> |
| | 9806 | |
| | 9807 | The function withParserGlobals() now takes an additional parameter |
| | 9808 | giving the actor who issued the command. (This is an internal |
| | 9809 | function that's probably not used at all by existing game code, so it |
| | 9810 | should have no impact on games. If you are calling this function, |
| | 9811 | though, note that you'll need to supply the extra parameter.) |
| | 9812 | |
| | 9813 | </div> |
| | 9814 | |
| | 9815 | <!-------------------> |
| | 9816 | <div class=entry> |
| | 9817 | |
| | 9818 | The menu system now sets the main content banner window to use |
| | 9819 | scrollbars if possible, and automatically scroll to show new text |
| | 9820 | in any case. This ensures that hint lists that are too long to fit |
| | 9821 | in the window will scroll as needed to keep the last hint in view. |
| | 9822 | |
| | 9823 | </div> |
| | 9824 | |
| | 9825 | <!------------------------------- 3.0.6o ---------------------------------> |
| | 9826 | <div class="sepbar"><a name='306o'></a>3.0.6o</div> |
| | 9827 | <p><b><i>Released 3/14/2004</i></b> |
| | 9828 | <p> |
| | 9829 | |
| | 9830 | <div class=firstentry> |
| | 9831 | |
| | 9832 | <p><b>Possible compatibility-breaking change:</b> The property |
| | 9833 | formerly named 'vocabWords_' has been renamed to 'vocabWords' (the |
| | 9834 | change is that the underscore formerly at the end of the name has been |
| | 9835 | removed). The underscore suffix is conventionally used in the library |
| | 9836 | to indicate an internal library property that isn't normally for use |
| | 9837 | by game code, which obviously isn't appropriate in this case, as this |
| | 9838 | is the property that games usually initialize to set an object's |
| | 9839 | vocabulary words. |
| | 9840 | |
| | 9841 | <p>You should search for instances of 'vocabWords_' in your existing |
| | 9842 | code, and replace them with 'vocabWords'. Most existing game code |
| | 9843 | will probably have few, if any, instances of this property name, since |
| | 9844 | most object definitions in existing game code probably use the |
| | 9845 | standard library templates to set this property's value without giving |
| | 9846 | its name. Even so, you should search through your code and update any |
| | 9847 | mentions to use the new name. |
| | 9848 | |
| | 9849 | </div> |
| | 9850 | |
| | 9851 | <!-------------------> |
| | 9852 | <div class=entry> |
| | 9853 | |
| | 9854 | The method getOutermostRoom(), which was previously defined in |
| | 9855 | BasicLocation and NestedRoom, has been moved instead to Thing. This |
| | 9856 | ensures that the method will work properly even when a nested room is |
| | 9857 | located within a non-room object. The Thing definition simply returns |
| | 9858 | the enclosing location if there is one, or 'self' if not. |
| | 9859 | |
| | 9860 | </div> |
| | 9861 | |
| | 9862 | <!-------------------> |
| | 9863 | <div class=entry> |
| | 9864 | |
| | 9865 | The new TopicEntry subclass AskTellGiveShowTopic makes it easy to |
| | 9866 | define a response that covers ASK, TELL, GIVE, and SHOW for a given |
| | 9867 | object or set of objects. It's sometimes convenient to be able to |
| | 9868 | treat all of these commands as equivalent in handling a response. |
| | 9869 | |
| | 9870 | <p>AskTellGiveShowTopic is based on the new class |
| | 9871 | TopicOrThingMatchTopic, which can be subclassed to create other |
| | 9872 | combinations of other subsets of these four verbs (or to add topic |
| | 9873 | entries for new custom game-defined verbs). This new class combines |
| | 9874 | the features of the "Thing" and "Topic" base classes for topic |
| | 9875 | entries. |
| | 9876 | |
| | 9877 | </div> |
| | 9878 | |
| | 9879 | <!-------------------> |
| | 9880 | <div class=entry> |
| | 9881 | |
| | 9882 | ConvNode has a new method, autoShowTopics(), that returns true if the |
| | 9883 | node is to show a topic inventory automatically on activation. By |
| | 9884 | default, this method returns true if the node contains any active |
| | 9885 | SpecialTopic entries. You can override this if desired to generate a |
| | 9886 | topic inventory automatically under other conditions, or to suppress |
| | 9887 | the automatic inventory when an active special topic is present |
| | 9888 | (although the latter probably isn't a good idea). |
| | 9889 | |
| | 9890 | <p>The main reason you might want to generate a topic inventory |
| | 9891 | automatically on activating a node is that the node contains one or |
| | 9892 | more obscure topics that players will be unlikely to guess on their |
| | 9893 | own. If it's unlikely that the player would think to ask just the |
| | 9894 | right thing at just the right time, a topic inventory can help guide |
| | 9895 | them through the conversation by showing the possibilities. As |
| | 9896 | always, only the topics you specifically mark as suggested (with |
| | 9897 | SuggestedAskTopic, etc) will be listed in the inventory. When possible, |
| | 9898 | it's probably better from a game-design perspective to lead players |
| | 9899 | into asking the right questions more subtly, by putting the right |
| | 9900 | cues in the conversation itself; when this is impractical, the topic |
| | 9901 | inventory is a usable substitute. |
| | 9902 | |
| | 9903 | </div> |
| | 9904 | |
| | 9905 | <!-------------------> |
| | 9906 | <div class=entry> |
| | 9907 | |
| | 9908 | The pronoun expansion for CollectiveGroup objects that was introduced |
| | 9909 | in 3.0.6n has been partially removed. In the past, when an individual |
| | 9910 | object was associated with a CollectiveGroup object, the parser |
| | 9911 | automatically added the group object into consideration for resolving |
| | 9912 | a subsequent pronoun referring to the individual. This was meant to |
| | 9913 | provide better fidelity for resolving pronouns in these cases, but it |
| | 9914 | led to new problems when the original noun phrase could only have |
| | 9915 | referred to the individual. To correct the problems, the parser no |
| | 9916 | longer puts the collective group into consideration when a pronoun |
| | 9917 | refers to one of the group's individuals. |
| | 9918 | |
| | 9919 | <p>The other direction still applies, though: when a pronoun refers to |
| | 9920 | a CollectiveGroup object, the parser puts the group's associated |
| | 9921 | individuals into consideration for resolving the pronoun. |
| | 9922 | |
| | 9923 | </div> |
| | 9924 | |
| | 9925 | <!-------------------> |
| | 9926 | <div class=entry> |
| | 9927 | |
| | 9928 | A bug in the CommandTopic class (introduced in 3.0.6n) prevented it |
| | 9929 | from matching a single Action class as the matchObj correctly. (It |
| | 9930 | did work properly when a list of Action classes was given, but not |
| | 9931 | when a single object was given.) This has been corrected. |
| | 9932 | |
| | 9933 | </div> |
| | 9934 | |
| | 9935 | <!-------------------> |
| | 9936 | <div class=entry> |
| | 9937 | |
| | 9938 | The HelloGoodbyeTopic class now has its impliesGreeting property set |
| | 9939 | to true, ensuring that this topic type won't trigger an implied |
| | 9940 | greeting. Since a HelloGoodbyeTopic is itself a greeting, an implied |
| | 9941 | greeting would be undesirable, not to mention that it caused a |
| | 9942 | run-time error when it occurred. |
| | 9943 | |
| | 9944 | </div> |
| | 9945 | |
| | 9946 | <!-------------------> |
| | 9947 | <div class=entry> |
| | 9948 | |
| | 9949 | A bug in ComplexContainer caused a problem when an object was |
| | 9950 | initially located in one of the the complex container's sub-containers |
| | 9951 | via the 'subLocation' property. In the past, the ComplexContainer |
| | 9952 | didn't properly re-initialize the object's 'location' property to |
| | 9953 | reflect that it was actually in the sub-container. This has been |
| | 9954 | fixed. |
| | 9955 | |
| | 9956 | <p>The problem manifested as strange behavior when the contained |
| | 9957 | object was removed from the sub-container (via TAKE or the like). In |
| | 9958 | particular, because the object's 'location' was still set to the |
| | 9959 | ComplexContainer, the object wasn't properly removed from the |
| | 9960 | sub-container's contents list, so the object appeared to still be in |
| | 9961 | the sub-container as well as in its new location. |
| | 9962 | |
| | 9963 | </div> |
| | 9964 | |
| | 9965 | <!-------------------> |
| | 9966 | <div class=entry> |
| | 9967 | |
| | 9968 | A couple of problems involving formatting and real-time events have |
| | 9969 | been fixed. In 3.0.6i, fuses and daemons - including the real-time |
| | 9970 | versions - started running with a transcript context, which means |
| | 9971 | that their text output is captured. This caused some interactions |
| | 9972 | with the input manager that weren't taken into account properly in |
| | 9973 | the library. |
| | 9974 | |
| | 9975 | <p>First, if a real-time event itself stopped and asked for input from |
| | 9976 | the user (by reading a new command line, for example), the transcript |
| | 9977 | capturing prevented the text displayed by the event from showing up at |
| | 9978 | all until after the user entered something on the new command line. |
| | 9979 | It was possible to work around this by deactivating the transcript |
| | 9980 | prior to showing any output in the real-time event, but this is no |
| | 9981 | longer necessary. |
| | 9982 | |
| | 9983 | <p>Second, even if a real-time event didn't display anything, its mere |
| | 9984 | silent firing caused an extra blank line to show up immediately after |
| | 9985 | the user next pressed the Enter key to finish a command line. |
| | 9986 | |
| | 9987 | <p>Both of these problems are now corrected, so there's no need for |
| | 9988 | real-time events to do anything special with respect to output |
| | 9989 | formatting or command-line input. |
| | 9990 | |
| | 9991 | </div> |
| | 9992 | |
| | 9993 | <!-------------------> |
| | 9994 | <div class=entry> |
| | 9995 | |
| | 9996 | The new pre-defined message object parameter 'pc' can be used to |
| | 9997 | refer directly to the player character. This is similar to the 'actor' |
| | 9998 | parameter, but refers to the player character actor even if an NPC is |
| | 9999 | the current active character. An expression such as "{you pc/he}" |
| | 10000 | thus refers to the current gPlayerChar, not to the current gActor. |
| | 10001 | |
| | 10002 | </div> |
| | 10003 | |
| | 10004 | <!-------------------> |
| | 10005 | <div class=entry> |
| | 10006 | |
| | 10007 | The library messages for scoring (showScoreMessage, |
| | 10008 | showScoreNoMaxMessage, showScoreRankMessage, showFullScorePrefix) |
| | 10009 | incorrectly referred to the current actor rather than the current |
| | 10010 | player character, which resulted in attributing the score to an NPC |
| | 10011 | rather than to the player if a score message was generated on another |
| | 10012 | actor's turn. These messages now explicitly refer to the player |
| | 10013 | character. |
| | 10014 | |
| | 10015 | </div> |
| | 10016 | |
| | 10017 | <!------------------------------- 3.0.6n ---------------------------------> |
| | 10018 | <div class="sepbar"><a name='306n'></a>3.0.6n</div> |
| | 10019 | <p><b><i>Released 3/6/2004</i></b> |
| | 10020 | <p> |
| | 10021 | |
| | 10022 | <div class=firstentry> |
| | 10023 | |
| | 10024 | <b>Major compatibility-breaking change:</b> The library's main |
| | 10025 | entrypoints to the game have changed. Existing games <b>must</b> |
| | 10026 | be modified to accommodate this change. |
| | 10027 | |
| | 10028 | <p>In the past, the game code was responsible for defining two |
| | 10029 | entrypoints: main() and mainRestore(). The template games generated |
| | 10030 | by Workbench's "New Project" command defined these two functions as |
| | 10031 | one-liners that called mainCommon(), where the real action took place. |
| | 10032 | |
| | 10033 | <p>In the new arrangement, the library now invokes methods of a |
| | 10034 | new object, gameMain, which each game <b>must</b> define. For your |
| | 10035 | convenience, the library defines a class, GameMainDef, that you |
| | 10036 | can use as the base class of your gameMain object. This base class |
| | 10037 | defines suitable defaults for the required methods, so you only have |
| | 10038 | to override what you need to customize. Overall, this change should |
| | 10039 | result in much less required startup code for each game. |
| | 10040 | |
| | 10041 | <p>If you use GameMainDef as the base class of your gameMain object, |
| | 10042 | you're only required to define one property in it: |
| | 10043 | |
| | 10044 | <ul> |
| | 10045 | |
| | 10046 | <li>initialPlayerChar - set this property to the Actor object that |
| | 10047 | serves as the initial player character in the game. You <b>must</b> |
| | 10048 | set this; GameMainDef can't provide a default for you here. |
| | 10049 | |
| | 10050 | </ul> |
| | 10051 | |
| | 10052 | <p>In addition, there are a couple of optional optional methods that |
| | 10053 | you can use for customization: |
| | 10054 | |
| | 10055 | <ul> |
| | 10056 | |
| | 10057 | <li>showIntro() - show the game's introduction. Most games will want |
| | 10058 | to override this to show the prologue text for the game. |
| | 10059 | |
| | 10060 | <li>showGoodbye() - show the game's "goodbye" message. Override this |
| | 10061 | if you want to add a parting message as the game terminates. |
| | 10062 | |
| | 10063 | </ul> |
| | 10064 | |
| | 10065 | <p>Most games will find it sufficient to define only initialPlayerChar |
| | 10066 | and showIntro(), and simply inherit the default handling for everything |
| | 10067 | else from GameMainDef. However, there are several additional methods |
| | 10068 | that you can override if you want to do something special. |
| | 10069 | |
| | 10070 | <ul> |
| | 10071 | |
| | 10072 | <li>newGame() - the library invokes this method to start a new game. |
| | 10073 | The default version calls showIntro() to show the introductory text, |
| | 10074 | then runs the main command loop until the player quits, then calls |
| | 10075 | showGoodbye() to show the goodbye message. You can override this |
| | 10076 | if you want to do something extra, such as showing a pre-game |
| | 10077 | options screen. |
| | 10078 | |
| | 10079 | <li>restoreAndRunGame(filename) - the library invokes this method to |
| | 10080 | restore and start running a saved game that the user selected when |
| | 10081 | launching the interpreter. It should rarely be necessary to override |
| | 10082 | this. |
| | 10083 | |
| | 10084 | <li>setGameTitle() - the library invokes this method at start-up to |
| | 10085 | set the interpreter's window title to show the game's title, as |
| | 10086 | defined in versionInfo.name. It should rarely be necessary to |
| | 10087 | override this. |
| | 10088 | |
| | 10089 | </ul> |
| | 10090 | |
| | 10091 | <p>If your existing game code uses the Workbench-generated template, |
| | 10092 | or you follow the same pattern, then rewriting your code to fit the |
| | 10093 | new design is relatively straightforward. Just follow these steps. |
| | 10094 | |
| | 10095 | <ul> |
| | 10096 | |
| | 10097 | <li><b>Save a copy</b> of your existing code before you do anything |
| | 10098 | else. If things don't seem to work properly after you finish |
| | 10099 | applying this update, you can compare the modified version with your |
| | 10100 | backup copy to help track down the problem. |
| | 10101 | |
| | 10102 | <li><b>Delete</b> your main() and mainRestore() functions. Your game |
| | 10103 | code doesn't need to define these routines at all any more, since the |
| | 10104 | library now defines them. |
| | 10105 | |
| | 10106 | <li><b>Create</b> a new object definition for gameMain: |
| | 10107 | |
| | 10108 | <p><pre> gameMain: GameMainDef |
| | 10109 | initialPlayerChar = me |
| | 10110 | showIntro() |
| | 10111 | { |
| | 10112 | // TO DO! |
| | 10113 | } |
| | 10114 | ; |
| | 10115 | </pre> |
| | 10116 | |
| | 10117 | <li><b>Find</b> your introductory text, and anything else you |
| | 10118 | customized in your old mainCommon() routine, and move it into the |
| | 10119 | showIntro() method (replacing the "TO DO!" comment in the |
| | 10120 | example above). |
| | 10121 | |
| | 10122 | <li><b>Delete</b> your mainCommon() function. It has now been |
| | 10123 | subsumed into your new gameMain object. |
| | 10124 | |
| | 10125 | </ul> |
| | 10126 | |
| | 10127 | <p>That's it - if you were using the standard Workbench template |
| | 10128 | for mainCommon(), you're now finished. |
| | 10129 | |
| | 10130 | <p>If you made certain kinds of changes to the template main(), |
| | 10131 | mainRestore(), or mainCommon() that Workbench produced when you |
| | 10132 | originally created your game, you might have to do some additional |
| | 10133 | work. These extra changes are uncommon, but check this list to make |
| | 10134 | sure they don't apply to you: |
| | 10135 | |
| | 10136 | <ul> |
| | 10137 | |
| | 10138 | <li>Do you have anything in main() or mainRestore() beyond a simple |
| | 10139 | call to mainCommon()? If so, you'll probably have to move that code |
| | 10140 | into the showIntro() method, or you might even have to override |
| | 10141 | newGame() (and possibly even restoreAndRunGame()). This is beyond the |
| | 10142 | scope of this simple recipe, so please refer to the definition of |
| | 10143 | GameMainDef in misc.t for full information on the new setup. |
| | 10144 | |
| | 10145 | <li>If you customized the code in mainCommon() that restores the file |
| | 10146 | specified by 'restoreFile', you'll need to override |
| | 10147 | restoreAndRunGame(). You can probably just move your existing code |
| | 10148 | from your old mainCommon() into a new mainGame.restoreAndRunGame() |
| | 10149 | method. Refer to the definition of GameMainDef in misc.t. |
| | 10150 | |
| | 10151 | <li>If you player character isn't named 'me', you'll need to change |
| | 10152 | the initialPlayerChar definition accordingly. |
| | 10153 | |
| | 10154 | </ul> |
| | 10155 | |
| | 10156 | </div> |
| | 10157 | |
| | 10158 | <!-------------------> |
| | 10159 | <div class=entry> |
| | 10160 | |
| | 10161 | <b>Minor Compatibility-breaking change:</b> A few properties that |
| | 10162 | were previously in libGlobal and other library objects have been |
| | 10163 | moved into the new gameMain object instead. The relocated properties |
| | 10164 | all select optional library behavior; they've been moved to gameMain |
| | 10165 | to make it easier for game authors to select non-default option |
| | 10166 | settings. In the past, you had to use 'modify' to change these |
| | 10167 | settings, or explicitly assign them from your startup code; now, you |
| | 10168 | simply have to include any non-default option settings as property |
| | 10169 | values in your gameMain object definition. |
| | 10170 | |
| | 10171 | <p>The properties moved are: |
| | 10172 | |
| | 10173 | <ul> |
| | 10174 | |
| | 10175 | <li>The former libGlobal.verboseMode is now gameMain.verboseMode. |
| | 10176 | |
| | 10177 | <li>The former exitLister.enableStatusline is now |
| | 10178 | gameMain.showExitsInStatusline. |
| | 10179 | |
| | 10180 | <li>The former libGlobal.allowYouMeMixing is now |
| | 10181 | gameMain.allowYouMeMixing. |
| | 10182 | |
| | 10183 | <li>The former libMessages.scoreRankTable is now |
| | 10184 | gameMain.scoreRankTable. |
| | 10185 | |
| | 10186 | <li>The former libScore.maxScore is now gameMain.maxScore. (This value |
| | 10187 | is also now nil by default, since there's no reason for the library to |
| | 10188 | assume a particular maximum score.) |
| | 10189 | |
| | 10190 | </div> |
| | 10191 | |
| | 10192 | <!-------------------> |
| | 10193 | <div class=entry> |
| | 10194 | |
| | 10195 | <b>Compatibility-breaking change:</b> The format of the verbPhrase |
| | 10196 | string has changed slightly for the English version of the library. |
| | 10197 | Game-defined verbs might need to be adjusted to the new format. |
| | 10198 | |
| | 10199 | <p>The change is that prepositions in a verb phrase are now grouped |
| | 10200 | inside the parentheses of the "(what)" placeholders for the objects, |
| | 10201 | if the prepositions go with the noun phrases. For example, the |
| | 10202 | LookIn action's verbPhrase string has changed from 'look/looking in |
| | 10203 | (what)' to 'look/looking (in what)'. The difference is subtle: by |
| | 10204 | moving the preposition 'in' so that it's inside the parentheses with |
| | 10205 | the direct object's "(what)" placeholder, we're telling the library |
| | 10206 | that the 'in' is part of the direct object noun phrase. Contrast |
| | 10207 | this with the verbPhrase for Doff, which is now 'take/taking off |
| | 10208 | (what)': this tells us that the preposition 'off' is part of the verb |
| | 10209 | structure, not part of the direct object. |
| | 10210 | |
| | 10211 | <p>How can you tell which way it goes? There are two rules you |
| | 10212 | should use to determine this. |
| | 10213 | |
| | 10214 | <p>First, if the preposition separates the direct and indirect |
| | 10215 | objects, such as the IN in PUT X IN Y, then it <i>always</i> goes |
| | 10216 | inside the indirect object phrase, hence 'put (what) (in what)'. |
| | 10217 | |
| | 10218 | <p>Second, for any other preposition, use the "it test": try writing |
| | 10219 | the verb using 'it' in place of 'what', and ask whether it sounds |
| | 10220 | right for the preposition to go before or after the 'it'. For |
| | 10221 | example, for the Doff action, TAKE IT OFF sounds right, and TAKE OFF |
| | 10222 | IT is obviously wrong. This means that the preposition 'off' belongs |
| | 10223 | in the verb phrase, hence 'take off (what)'. In contrast, for the |
| | 10224 | LookIn action, LOOK IN IT sounds right, not LOOK IT IN, so the |
| | 10225 | preposition goes with the direct object, hence 'look (in what)'. If |
| | 10226 | the "it test" indicates that the preposition goes <i>before</i> the |
| | 10227 | 'it', then the preposition is part of the direct object and thus goes |
| | 10228 | <i>inside</i> the parentheses of the "(what)"; if the preposition |
| | 10229 | goes <i>after</i> the 'it', then the preposition is part of the verb |
| | 10230 | and goes <i>outside</i> the parentheses. |
| | 10231 | |
| | 10232 | <p>Prepositions that go with the verb are uncommon in two-object |
| | 10233 | verbs, but they do occur. An example from the library is |
| | 10234 | ConsultAbout, one form of which uses the verbPhrase 'look/looking up |
| | 10235 | (what) (in what)'. We'd write LOOK IT UP IN IT, so the preposition |
| | 10236 | 'up' goes after the direct object pronoun and is thus part of the |
| | 10237 | verb, while the preposition 'in' goes before the indirect object |
| | 10238 | pronoun and is thus part of the indirect object. In case there's any |
| | 10239 | ambiguity about whether the 'up' goes with the verb or with the |
| | 10240 | indirect object, try the un-it test: we'd write LOOK UP TOPIC IN |
| | 10241 | BOOK, so clearly the 'up' is not part of the indirect object, but is |
| | 10242 | just part of the verb. |
| | 10243 | |
| | 10244 | </div> |
| | 10245 | |
| | 10246 | <!-------------------> |
| | 10247 | <div class=entry> |
| | 10248 | |
| | 10249 | <b>Compatibility-breaking change:</b> The TextList classes have been |
| | 10250 | removed, leaving only the more general EventList classes. The |
| | 10251 | TextList classes have been gradually converging with the EventList |
| | 10252 | classes anyway, to the point where the TextList classes have become |
| | 10253 | nothing more than renamed versions of the corresponding EventList |
| | 10254 | classes. Retaining the parallel set of names for otherwise equivalent |
| | 10255 | classes is bad because it steepens the learning curve for new users |
| | 10256 | and makes for more to remember for experienced users; so, the |
| | 10257 | redundant names have now been dropped. |
| | 10258 | |
| | 10259 | <p>Existing code will need to be scanned for occurrences of TextList, |
| | 10260 | StopTextList, RandomTextList, ShuffledTextList, and SyncTextList. |
| | 10261 | Replace these names with CyclicEventList, StopEventList, |
| | 10262 | RandomEventList, ShuffledEventList, and SyncEventList, respectively. |
| | 10263 | (Note that you can simply do a global search-and-replace to change to |
| | 10264 | suffix TextList to EventList, except that you must change occurrences |
| | 10265 | the TextList when it occurs as an entire word to CyclicEventList.) |
| | 10266 | |
| | 10267 | <p>In addition, the following property names must be changed: |
| | 10268 | |
| | 10269 | <ul> |
| | 10270 | <li>textStrings to eventList |
| | 10271 | <li>firstStrings to firstEvents |
| | 10272 | <li>messagePercent to eventPercent |
| | 10273 | <li>messageReduceAfter to eventReduceAfter |
| | 10274 | <li>messageReduceTo to eventReduceTo |
| | 10275 | </ul> |
| | 10276 | |
| | 10277 | <p>If you really don't want to change your existing code, you can |
| | 10278 | always use #define to create macros with the substitutions. You |
| | 10279 | really should change your code if possible, though, since using the |
| | 10280 | old names is likely to create confusion as the old names recede from |
| | 10281 | your memory and from the documentation. |
| | 10282 | |
| | 10283 | </div> |
| | 10284 | |
| | 10285 | <!-------------------> |
| | 10286 | <div class=entry> |
| | 10287 | |
| | 10288 | <b>Compatibility-breaking change:</b> In ConversationReadyState, |
| | 10289 | the greeting and goodbye messages have been changed. |
| | 10290 | |
| | 10291 | <p>First, the greetingList property is no longer used; instead, the |
| | 10292 | state now looks for a HelloTopic entry and uses its response. In |
| | 10293 | addition, you can differentiate between explicit HELLO commands and |
| | 10294 | implied greetings generated by other conversational commands (ASK TO, |
| | 10295 | for example) by creating separate HelloTopic and ImpHelloTopic |
| | 10296 | objects. In most cases, it's not necessary to distinguish the two |
| | 10297 | cases, so you can simply use a single HelloTopic to cover both cases. |
| | 10298 | |
| | 10299 | <p>Second, the enterFromByeMsg and enterFromConvMsg methods have been |
| | 10300 | removed, along with the enterFromByeList and enterFromConvList |
| | 10301 | properties. Instead, the state now looks for a ByeTopic or |
| | 10302 | ImpByeTopic entry, depending on whether the conversation is ending |
| | 10303 | due to an explicit GOODBYE command or due to an automatic ending (due |
| | 10304 | to the other actor walking away, or due to an inactivity timeout) and |
| | 10305 | uses its response. |
| | 10306 | |
| | 10307 | <p>You should scan your existing game code for any greetingList, |
| | 10308 | enterFromByeMsg, enterFromByeList, enterFromConvMsg, and |
| | 10309 | enterFromConvList properties, and change them to HelloTopic, |
| | 10310 | ByeTopic, and ImpByeTopic as appropriate. |
| | 10311 | |
| | 10312 | <p>Note that both the HELLO and GOODBYE topic entries go in the |
| | 10313 | ConversationReadyState, not in the InConversationState. This is |
| | 10314 | because these handlers typically describe the transition to and from |
| | 10315 | the "ready" state. A single in-conversation state could work with |
| | 10316 | several "ready" states, so putting the hello/goodbye topic entries in |
| | 10317 | the in-conversation state wouldn't allow any differentiation among |
| | 10318 | the several "ready" state transitions. Keeping the hello/goodbye |
| | 10319 | entries in the "ready" states themselves makes this differentiation |
| | 10320 | easy. For example, this allows a "goodbye" message to say something |
| | 10321 | like "Bob goes back to sweeping the porch." |
| | 10322 | |
| | 10323 | <p> |
| | 10324 | |
| | 10325 | </div> |
| | 10326 | |
| | 10327 | <!-------------------> |
| | 10328 | <div class=entry> |
| | 10329 | |
| | 10330 | <b>Possibly compatibility-breaking change:</b> The internal methods |
| | 10331 | that handle conversational commands in Actor have changed. The changes |
| | 10332 | are isolated to the internal methods that route the commands within |
| | 10333 | and between the Actor and ActorState objects, not to the main public |
| | 10334 | interfaces that game code usually uses. Even so, since it's occasionally |
| | 10335 | useful to override these internal methods, some existing game code |
| | 10336 | might be affected. |
| | 10337 | |
| | 10338 | <p>In general terms, these changes are designed to concentrate the |
| | 10339 | handling of all conversational actions along a single path. In the |
| | 10340 | past, each type of conversational command was handled by its own |
| | 10341 | cluster of methods, so the Actor and ActorState had a set of parallel |
| | 10342 | methods for HELLO, GOODBYE, YES, NO, ASK ABOUT, ASK FOR, TELL ABOUT, |
| | 10343 | SHOW TO, and GIVE TO. This old design was intended to make it easy to |
| | 10344 | override these handlers in isolation, but experience has since shown |
| | 10345 | that it's much more useful to be able to override all of the handlers |
| | 10346 | in concert instead. The new design therefore consolidates all of |
| | 10347 | these different conversational actions into a single method that's |
| | 10348 | parameterized with the type of action. There are still several |
| | 10349 | methods because of the sequence of processing points through the Actor |
| | 10350 | and ActorState, but there are no longer several clusters of methods: |
| | 10351 | each of the old clusters is now a single method. |
| | 10352 | |
| | 10353 | <p>An additional benefit of these changes is that HELLO and GOODBYE |
| | 10354 | are now handled through the topic database like everything else. This |
| | 10355 | has two useful effects. First, it means that a DefaultAnyTopic entry |
| | 10356 | will now respond to a HELLO or GOODBYE along with everything else. |
| | 10357 | This is highly desirable in most cases, because these defaults are |
| | 10358 | usually meant to convey a blanket response to all conversational |
| | 10359 | overtures. Second, it means that it's now a bit easier to customize |
| | 10360 | HELLO and GOODBYE responses: just use HelloTopic, ByeTopic, and |
| | 10361 | HelloByeTopic objects as desired. |
| | 10362 | |
| | 10363 | <p><b>Advice:</b> Because there are a lot of details to these |
| | 10364 | changes, we suggest you scan your code for mentions of the affected |
| | 10365 | methods, to see if your code is affected at all. If your code |
| | 10366 | doesn't define or call any of these methods, you shouldn't be |
| | 10367 | affected. The methods are: |
| | 10368 | |
| | 10369 | <p> |
| | 10370 | <ul> |
| | 10371 | <li>sayToActor |
| | 10372 | <li>handleConversation |
| | 10373 | <li>yesNoFrom |
| | 10374 | <li>answerQuestion |
| | 10375 | <li>hearAbout |
| | 10376 | <li>beShown |
| | 10377 | <li>beGiven |
| | 10378 | <li>answerRequestFor |
| | 10379 | </ul> |
| | 10380 | |
| | 10381 | <p>Now to the specific changes. |
| | 10382 | |
| | 10383 | <p>Actor.sayToActor() has some changes to its parameters. The |
| | 10384 | 'prop', 'propArgs', and 'topicListProp' parameters have been dropped, |
| | 10385 | and the new 'topic' and 'convType' parameters have been added. |
| | 10386 | 'topic' is a special object representing the topic; the library |
| | 10387 | defines the singletons helloTopicObj, byeTopicObj, yesTopicObj, |
| | 10388 | and noTopicObj for the corresponding library actions. 'convType' |
| | 10389 | is an object of type ConvType describing the type of action being |
| | 10390 | performed. |
| | 10391 | |
| | 10392 | <p>The new helloTopicObj and byeTopicObj singletons have |
| | 10393 | been added, as mentioned above. These are used as special topic |
| | 10394 | placeholders for the HELLO and GOODBYE commands, respectively. |
| | 10395 | |
| | 10396 | <p>The new ConvType class has been added, and singleton |
| | 10397 | instances for all of the standard library conversation actions (HELLO, |
| | 10398 | GOODBYE, YES, NO, ASK ABOUT, ASK FOR, etc.) have been defined. |
| | 10399 | |
| | 10400 | <p>The 'topicListProp' and 'handler' parameters of |
| | 10401 | ActorState.handleConversation() has been dropped, and the new |
| | 10402 | 'convType' parameter has been added. 'convType' is a ConvType |
| | 10403 | object representing the conversation type. |
| | 10404 | |
| | 10405 | <p>The 'topicListProp' parameter of |
| | 10406 | ConvNode.handleConversation() has been replaced with a new 'convType' |
| | 10407 | parameter, which is a ConvType object describing the conversation |
| | 10408 | type. |
| | 10409 | |
| | 10410 | <p>Actor now provides a handleConversation() method. The |
| | 10411 | ActorState will invoke this method by default when the ActorState's |
| | 10412 | own handleConversation() method doesn't handle the action. This new |
| | 10413 | Actor method is in lieu of the former cluster of per-command handlers |
| | 10414 | in Actor: yesnoFrom, answerQuestion, hearAbout, beShown, beGiven, |
| | 10415 | answerRequestFor. |
| | 10416 | |
| | 10417 | <p>All of the per-command handlers in Actor and ActorState |
| | 10418 | have been removed: yesNoFrom, answerQuestion, hearAbout, beShown, |
| | 10419 | beGiven, answerRequestFor. These are replaced by the |
| | 10420 | handleConversation() method in Actor and ActorState, as mentioned |
| | 10421 | above. |
| | 10422 | |
| | 10423 | <p>The new Actor method defaultConvResponse() is a general |
| | 10424 | handler for showing the default response when a conversational action |
| | 10425 | isn't otherwise handled (that is, it's not handled by any topic |
| | 10426 | database entry, and the ActorState doesn't want to handle it |
| | 10427 | specially). This new method provides an easy way to show the same |
| | 10428 | response for every conversational action - just override this one |
| | 10429 | method, and you can show a common response for all conversation |
| | 10430 | commands. By default, this method routes looks at the convType |
| | 10431 | parameter to determine the conversation type, and invokes the Actor |
| | 10432 | method that provides the default response for that particular |
| | 10433 | conversation type, using the same default response methods used in the |
| | 10434 | past (defaultGreetingResponse, defaultGoodbyeResponse, etc). |
| | 10435 | |
| | 10436 | <p>The ActorState object can now <i>optionally</i> define any |
| | 10437 | of the default response handlers that Actor can define |
| | 10438 | (defaultGreetingResponse, defaultAskResponse, etc). When these are |
| | 10439 | defined, they'll be called when the state object doesn't provide a |
| | 10440 | suitable TopicEntry in its topic database. Note that these |
| | 10441 | effectively override the Actor's topic database <i>and</i> default |
| | 10442 | response handlers for a given type of action. The order of handling |
| | 10443 | for a conversational action is now ConvNode, ActorState TopicEntry |
| | 10444 | list, ActorState default response method, Actor TopicEntry list, and |
| | 10445 | finally Actor default response method. |
| | 10446 | |
| | 10447 | </div> |
| | 10448 | |
| | 10449 | <!-------------------> |
| | 10450 | <div class=entry> |
| | 10451 | |
| | 10452 | <b>Possibly compatibility-breaking change:</b> A change to the |
| | 10453 | library's message system makes it easier to customize the default |
| | 10454 | response messages for individual objects. In the past, if you wanted |
| | 10455 | to customize the message for OPEN COCONUT, say, you'd have to |
| | 10456 | override the 'verify' method for the 'coconut' object's |
| | 10457 | dobjFor(Open). With this change, you can create a custom per-object |
| | 10458 | message more easily: you simply define coconut.cannotOpenMsg with the |
| | 10459 | custom message string. |
| | 10460 | |
| | 10461 | <p>You can use the new message customization scheme any time the |
| | 10462 | library generates a standard response message using code like this: |
| | 10463 | |
| | 10464 | <p><pre> dobjFor(Open) |
| | 10465 | { |
| | 10466 | verify { illogical(&cannotOpenMsg); } |
| | 10467 | } |
| | 10468 | </pre> |
| | 10469 | |
| | 10470 | <p>Any time you see library code like that, you can override the |
| | 10471 | default response message for that action on an individual object |
| | 10472 | simply by defining the message property in your object: |
| | 10473 | |
| | 10474 | <p><pre> coconut: Thing |
| | 10475 | cannotOpenMsg = '{You/he} would need something sharp to do that. ' |
| | 10476 | ; |
| | 10477 | </pre> |
| | 10478 | |
| | 10479 | <p>In addition to illogical(), this also works with illogicalNow(), |
| | 10480 | inaccessible(), defaultReport(), defaultDescReport(), extraReport(), |
| | 10481 | mainReport() reportBefore(), reportAfter(), reportFailure(), and any |
| | 10482 | other verify or action reporting routines. |
| | 10483 | |
| | 10484 | <p>Here's how this works. In the past, when a verify, check, or |
| | 10485 | action routine generated a message using a message property, the |
| | 10486 | library looked up the message in the current actor's "action message |
| | 10487 | object," which is usually playerActionMessages when the actor is the |
| | 10488 | player character, and npcActionMessages otherwise. Now, the library |
| | 10489 | still looks there, but only <i>after</i> checking the individual |
| | 10490 | objects involved in the command to see if any of them define the |
| | 10491 | message property. |
| | 10492 | |
| | 10493 | <p>The library looks first at the direct object, then at the indirect |
| | 10494 | object. If you were to create your own custom verbs with three or |
| | 10495 | more object slots, such as PUT COIN IN SLOT WITH TWEEZERS, the |
| | 10496 | library would automatically continue on to those extra objects as |
| | 10497 | well. If the library finds the message property in any of these |
| | 10498 | objects, it stops and uses that object as the source of the message; |
| | 10499 | if it can't find the message property among these objects, the |
| | 10500 | library simply falls back on the standard message object |
| | 10501 | (playerActionMessage or whatever). |
| | 10502 | |
| | 10503 | <p><b>Important:</b> As part of this change, all of the library |
| | 10504 | message properties have been renamed to end in "Msg". This affects |
| | 10505 | every message property, so if you've created your own "action message |
| | 10506 | object," or you've used 'modify' to change playerActionMessages |
| | 10507 | and/or npcActionMessages, you'll have to do some extensive searching |
| | 10508 | and replacing to add the "Msg" suffix to every message property name. |
| | 10509 | Sorry about this; the proposed change was put to the TADS 3 mailing |
| | 10510 | list, and no one objected. The naming change isn't gratuitous. The |
| | 10511 | reason for the name change is that it should greatly reduce the |
| | 10512 | chances of collisions between message properties and properties |
| | 10513 | defined for internal use by an object. The library itself formerly |
| | 10514 | had a number of these collisions, so it was necessary to rename at |
| | 10515 | least those properties; using the naming convention consistently for |
| | 10516 | all of the message properties will help ensure that games don't |
| | 10517 | inadvertantly introduce their own name collisions. |
| | 10518 | |
| | 10519 | <p>There's one last detail to mention. An object can override a |
| | 10520 | message property with <i>another</i> message property. For example, |
| | 10521 | the Vaporous object in the library uses this feature: |
| | 10522 | |
| | 10523 | <p><pre> notWithIntangibleMsg = &notWithVaporousMsg |
| | 10524 | </pre> |
| | 10525 | |
| | 10526 | <p>When a message property in an object points directly to another |
| | 10527 | property, the library takes this as an indirection to another library |
| | 10528 | message from the action message object. This feature is mostly for |
| | 10529 | the library's benefit, since library objects are required to get all |
| | 10530 | of their messages from the action message object (to ensure that the |
| | 10531 | library can be translated without rewriting entire object |
| | 10532 | definitions). |
| | 10533 | |
| | 10534 | </div> |
| | 10535 | |
| | 10536 | <!-------------------> |
| | 10537 | <div class=entry> |
| | 10538 | |
| | 10539 | <b>Minor compatibility-breaking change:</b> The Script method |
| | 10540 | getState() has been renamed to getScriptState(), and the Script |
| | 10541 | property curState has been renamed to curScriptState. This change |
| | 10542 | allows Script and its subclasses to be combined (with multiple |
| | 10543 | inheritance) with Thing (which defines its own meaning for getState) |
| | 10544 | and with Actor (which defines its own curState). It's sometimes |
| | 10545 | desirable to combine Thing or Actor with a Script subclass, because |
| | 10546 | that's an easy way to attach simple scripting behavior to these |
| | 10547 | objects. |
| | 10548 | |
| | 10549 | <p>Existing game code that overrides or calls getState or curState |
| | 10550 | for a Script object (including any EventList subclass) will need to |
| | 10551 | be changed to use the new name. You should scan your source code for |
| | 10552 | occurrences of these names, and rename them as needed. Note that |
| | 10553 | you should <b>not</b> rename curState properties that pertain to |
| | 10554 | Actor objects, since Actor.curState has <b>not</b> been renamed. |
| | 10555 | |
| | 10556 | <p>In most cases, game code won't have any reason to override or |
| | 10557 | access these script properties at all, so most game code should be |
| | 10558 | unaffected by this change. Game code usually just defines instances |
| | 10559 | of the library EventList subclasses using templates, and such code |
| | 10560 | won't be affected by this change. |
| | 10561 | |
| | 10562 | </div> |
| | 10563 | |
| | 10564 | <!-------------------> |
| | 10565 | <div class=entry> |
| | 10566 | |
| | 10567 | <b>Minor compatibility-breaking change:</b> The library objects |
| | 10568 | redirectTravelIn, redirectTravelOut, and redirectTravelDown have been |
| | 10569 | renamed to askTravelIn, askTravelOut, and askTravelDown, |
| | 10570 | respectively. The names changes are for consistency with the naming |
| | 10571 | of the new class AskConnector. |
| | 10572 | |
| | 10573 | </div> |
| | 10574 | |
| | 10575 | <!-------------------> |
| | 10576 | <div class=entry> |
| | 10577 | |
| | 10578 | The PresentLater class has a new property, initiallyPresent, that lets |
| | 10579 | you override the standard behavior of the class, which is to make the |
| | 10580 | object initially absent from the game map. This new property is set |
| | 10581 | to nil by default; if you override it to true, the object will be |
| | 10582 | initially present in the game, like any ordinary object. This new |
| | 10583 | property would seem to defeat the purpose of the class, but it |
| | 10584 | actually extends the class to situations where an object comes and |
| | 10585 | goes during the game, but starts out present. Using PresentLater with |
| | 10586 | initiallyPresent set to true, you can still use all of the |
| | 10587 | PresentLater showing and hiding mechanisms, such as the key-based and |
| | 10588 | conditional methods; this is often more convenient than moving objects |
| | 10589 | in and out of the game map individually and manually. |
| | 10590 | |
| | 10591 | </div> |
| | 10592 | |
| | 10593 | <!-------------------> |
| | 10594 | <div class=entry> |
| | 10595 | |
| | 10596 | The Attachable class now automatically notifies itself and each of its |
| | 10597 | attachments whenever the Attachable is carried by a traveler, by |
| | 10598 | calling the new method travelWhileAttached(). The method does nothing |
| | 10599 | by default, but games can override it as needed to enforce conditions |
| | 10600 | or carry out side effects when an attached object is moved indirectly |
| | 10601 | via travel. |
| | 10602 | |
| | 10603 | </div> |
| | 10604 | |
| | 10605 | <!-------------------> |
| | 10606 | <div class=entry> |
| | 10607 | |
| | 10608 | The Attachable class now has a way of specifying the "direction" of |
| | 10609 | an attachment relationship, for the purposes of descriptive messages. |
| | 10610 | Formerly, attachments were always described symmetrically: if A was |
| | 10611 | attached to B, then examining A generated a status message along the |
| | 10612 | lines of "A is attached to B," while examining B generated a message |
| | 10613 | like "B is attached to A." This didn't always work; "the note is |
| | 10614 | attached to wall" is fine, but "the wall is attached to the note" |
| | 10615 | isn't quite right. The new feature lets you specify that the note is |
| | 10616 | always said to be attached to the wall, never vice versa. |
| | 10617 | |
| | 10618 | <p>The direction of a relationship is specified by the new Attachable |
| | 10619 | method isMajorItemFor(obj). By default, this method always simply |
| | 10620 | returns nil, which means that there are no "major" items by default, |
| | 10621 | which makes all attachment relationships symmetrical by default. If |
| | 10622 | you wish, you can override isMajorItemFor() so that it returns true |
| | 10623 | in some cases. When A.isMajorItemFor(B) returns true, the |
| | 10624 | relationship will always be described such that B is said to be |
| | 10625 | attached to A: examining A will yield "a B is attached to the A," |
| | 10626 | while examining B will show "the B is attached to an A." |
| | 10627 | |
| | 10628 | <p>A few new methods have been added to support the new feature; |
| | 10629 | these are mostly for internal use, but could potentially be used by a |
| | 10630 | game to fine-tune the way attachments are listed. The new method |
| | 10631 | isListedAsAttachedTo(obj) lets the object indicate whether or not |
| | 10632 | 'obj' is listed among the things 'self' is attached to; by default, |
| | 10633 | this returns true if 'obj' isn't permanently attached <b>and</b> |
| | 10634 | 'self' isn't the "major" item for 'obj'. The new method |
| | 10635 | isListedAsMajorFor(obj) is essentially the major-list counterpart: it |
| | 10636 | indicates whether or not 'obj' is listed among the things attached to |
| | 10637 | 'self' when 'self' is described. By default, this method returns |
| | 10638 | true if 'self' <b>is</b> the "major" item for 'obj', <b>and</b> |
| | 10639 | obj.isListedAsAttachedTo(self) returns true (that is, 'obj' thinks it |
| | 10640 | should be listed as attached to 'self'). Finally, |
| | 10641 | majorAttachmentLister returns the lister to use for the items |
| | 10642 | attached to 'self' for which 'self' is the "major" item in the |
| | 10643 | relationship; by default, this uses a MajorAttachmentLister instance. |
| | 10644 | |
| | 10645 | </div> |
| | 10646 | |
| | 10647 | <!-------------------> |
| | 10648 | <div class=entry> |
| | 10649 | |
| | 10650 | The new classes Underside, RearContainer, and RearSurface make it |
| | 10651 | easier to model situations where one object is behind or under |
| | 10652 | another. Underside can be used to model the space under an object, or |
| | 10653 | for the bottom surface of an object. RearContainer models the space |
| | 10654 | behind an object, and RearSurface models its back surface. |
| | 10655 | |
| | 10656 | <p>In addition to letting you set up "under" and "behind" |
| | 10657 | relationships among objects initially, these new classes support the |
| | 10658 | PUT UNDER and PUT BEHIND commands to let actors add new contents under |
| | 10659 | and behind the objects. (The PUT BEHIND command is also new in this |
| | 10660 | release.) An Underside can have new objects added under it with PUT |
| | 10661 | UNDER, and a RearContainer or RearSurface can have new contents added |
| | 10662 | with PUT BEHIND. These commands can optionally be disallowed for a |
| | 10663 | given Underside or RearContainer/RearSurface: override the properties |
| | 10664 | allowPutUnder and allowPutBehind, respectively. The new classes |
| | 10665 | derive from BulkLimiter, so you can use the usual BulkLimiter |
| | 10666 | properties to control the individual and total bulk allowed under and |
| | 10667 | behind the objects. |
| | 10668 | |
| | 10669 | <p>ComplexContainer has been extended to support these new classes. |
| | 10670 | The new ComplexContainer property subUnderside can be set to an |
| | 10671 | Underside object representing the space under or bottom surface of the |
| | 10672 | complex container; the new property subRear can be set to a |
| | 10673 | RearContainer or RearSurface representing the space behind or back |
| | 10674 | surface of the complex container. PUT BEHIND and LOOK BEHIND commands |
| | 10675 | on the complex container are routed to the subUnderside; PUT UNDER and |
| | 10676 | LOOK UNDER are routed to the subRear; and both subcomponents are |
| | 10677 | included in the regular LOOK AT display. |
| | 10678 | |
| | 10679 | <p>These additions were adapted from work originally done by Eric Eve. |
| | 10680 | |
| | 10681 | </div> |
| | 10682 | |
| | 10683 | <!-------------------> |
| | 10684 | <div class=entry> |
| | 10685 | |
| | 10686 | It's now easier to set up objects so that they're initially inside the |
| | 10687 | component sub-containers of a ComplexContainer. In the past, if you |
| | 10688 | wanted to create an object in your source code so that it was |
| | 10689 | initially inside a ComplexContainer's internal container, for example, |
| | 10690 | you had to explicitly set the object's 'location' property, rather |
| | 10691 | than using the "+" syntax. Now, you can use the "+" syntax as long as |
| | 10692 | you add a little extra information: give each contained object a new |
| | 10693 | property, 'subLocation', and set it to the property of the component |
| | 10694 | sub-container you want to use as the initial location. For example, |
| | 10695 | here's how you'd create a washing machine as a complex container, |
| | 10696 | with a blanket inside and a laundry basket on top: |
| | 10697 | |
| | 10698 | <p><pre> |
| | 10699 | + washingMachine: ComplexContainer 'washing machine' 'washing machine' |
| | 10700 | subContainer: ComplexComponent, Container { /* etc */ } |
| | 10701 | subSurface: ComplexComponent, Surface { /* etc */ } |
| | 10702 | ; |
| | 10703 | |
| | 10704 | ++ Thing 'blanket' 'blanket' |
| | 10705 | subLocation = &subContainer |
| | 10706 | ; |
| | 10707 | |
| | 10708 | ++ Container 'laundry basket' 'laundry basket' |
| | 10709 | subLocation = &subSurface |
| | 10710 | ; |
| | 10711 | </pre> |
| | 10712 | |
| | 10713 | <p>The blanket and the laundry basket are nominally directly inside |
| | 10714 | the washing machine itself, according to the "+" syntax, but their |
| | 10715 | 'subLocation' settings ensure that they end up in the desired |
| | 10716 | component sub-containers during initialization. |
| | 10717 | |
| | 10718 | <p>Note that 'subLocation' is only intended for initialization, so the |
| | 10719 | library automatically sets subLocation to nil for each object right |
| | 10720 | after the initial setting is used. This helps avoid any unpleasant |
| | 10721 | surprises should the object be moved into a different ComplexContainer |
| | 10722 | later on. When you're moving objects around on the fly in your |
| | 10723 | program code, there's no reason to use subLocation at all; instead, |
| | 10724 | just specify the appropriate component as the explicit destination of |
| | 10725 | the moveInto: <tt>towel.moveInto(washingMachine.subSurface)</tt>, for |
| | 10726 | example. |
| | 10727 | |
| | 10728 | |
| | 10729 | </div> |
| | 10730 | |
| | 10731 | <!-------------------> |
| | 10732 | <div class=entry> |
| | 10733 | |
| | 10734 | The Openable class has a new property, openingLister, that specifies |
| | 10735 | the lister to use to display the list of items revealed when the |
| | 10736 | object is opened. By default, this is set to the |
| | 10737 | openableOpeningLister object. Individual objects can override this |
| | 10738 | if they want to customize the message listing the revealed items. |
| | 10739 | |
| | 10740 | <p>In addition, the object formerly called openingLister has been |
| | 10741 | renamed to openableOpeningLister. |
| | 10742 | |
| | 10743 | </div> |
| | 10744 | |
| | 10745 | <!-------------------> |
| | 10746 | <div class=entry> |
| | 10747 | |
| | 10748 | The new CommandTopic makes it easier to generate a response when an |
| | 10749 | NPC receives a particular command. Just create a CommandTopic, with a |
| | 10750 | list of the Action classes you wish to match. Actions are matched on |
| | 10751 | class alone; if you want to match something more specific, such as |
| | 10752 | matching a particular direct object of a particular action, you'll |
| | 10753 | have to create a custom matchTopic() method for your CommandTopic |
| | 10754 | object. If you want to create a default response that matches any |
| | 10755 | action, use a DefaultCommandTopic. |
| | 10756 | |
| | 10757 | <p>CommandTopic works like any other TopicEntry object, so you can put |
| | 10758 | these in ConvNode, ActorState, and Actor topic databases to provide |
| | 10759 | responses under the specific conditions you need to match. |
| | 10760 | |
| | 10761 | <p>As part of this change, ActorState.obeyCommand() now invokes |
| | 10762 | handleConversation() to look for a response to the command, specifying |
| | 10763 | the Action object as the topic and 'commandConvType' as the |
| | 10764 | conversation type object. This looks as usual in the ConvNode, |
| | 10765 | ActorState, and Actor conversation topic databases for a CommandTopic |
| | 10766 | to handle the response, or for a DefaultAnyTopic if there's no |
| | 10767 | CommandTopic. |
| | 10768 | |
| | 10769 | </div> |
| | 10770 | |
| | 10771 | <!-------------------> |
| | 10772 | <div class=entry> |
| | 10773 | |
| | 10774 | The parser now gives more weight to explicit owners when resolving |
| | 10775 | possessives. If a noun phrase is qualified by a possessive ("my |
| | 10776 | book"), and the noun phrase is ambiguous even with the possessive |
| | 10777 | qualifier (because the possessor is carrying more than one matching |
| | 10778 | object), the parser will now choose an object with an explicit |
| | 10779 | "owner" property over one without an explicit owner. When the parser |
| | 10780 | resolves this kind of ambiguity by choosing an explicitly owned |
| | 10781 | object over one that's merely being carried, it will mark the chosen |
| | 10782 | object with the UnclearDisambig flag to indicate that it's a best |
| | 10783 | guess. |
| | 10784 | |
| | 10785 | </div> |
| | 10786 | |
| | 10787 | <!-------------------> |
| | 10788 | <div class=entry> |
| | 10789 | |
| | 10790 | The library no longer treats "brightness" (the sensory intensity of |
| | 10791 | light, sound, etc.) as diminishing over a "distant" containment |
| | 10792 | boundary. In the past, distance diminished brightness by one level. |
| | 10793 | While this was arguably physically realistic over large distances, in |
| | 10794 | practice it proved to be undesirable for the typical scales in IF |
| | 10795 | settings, where "distant" is usually used to indicate that something's |
| | 10796 | tens or hundreds of feet away, not miles. |
| | 10797 | |
| | 10798 | </div> |
| | 10799 | |
| | 10800 | <!-------------------> |
| | 10801 | <div class=entry> |
| | 10802 | |
| | 10803 | The sense mechanism has a new feature that allows an object to take on |
| | 10804 | its own special sensory status. An object can use this feature to |
| | 10805 | override the normal sense path mechanism and decide for itself how it |
| | 10806 | appears to the senses. The change is comprised of two new methods. |
| | 10807 | |
| | 10808 | <p>First, when building the sense information table, the library now |
| | 10809 | calls a new method, addToSenseInfoTable, on each object connected by |
| | 10810 | containment to the source object. This method by default does what |
| | 10811 | the library has always done: it evaluates the temporary sense |
| | 10812 | properties set up by the containment path traversal, and adds a |
| | 10813 | SenseInfo object to the table based on the sense properties. An |
| | 10814 | objects can now override this method to add a table entry based on a |
| | 10815 | different sensory status. |
| | 10816 | |
| | 10817 | <p>Second, when finding the containment paths from one object to |
| | 10818 | another, the library calls the new method specialPathFrom on the |
| | 10819 | target object if (and <b>only</b> if) no ordinary containment path can |
| | 10820 | be found. This method can supply its own custom containment path. |
| | 10821 | This allows an object to exist outside of the normal containment |
| | 10822 | hierarchy but still get a chance to represent its connection to |
| | 10823 | the normal containment hierarchy as it sees fit. |
| | 10824 | |
| | 10825 | </div> |
| | 10826 | |
| | 10827 | <!-------------------> |
| | 10828 | <div class=entry> |
| | 10829 | |
| | 10830 | When a CollectiveGroup object has no location, it now takes on the |
| | 10831 | sensory status of its individuals. It will take on the "best" sense |
| | 10832 | status of any individual in scope, which is the one that's most |
| | 10833 | transparent and (transparencies being equal) has the highest ambient |
| | 10834 | level. |
| | 10835 | |
| | 10836 | <p>This change makes it much easier to work with CollectiveGroup |
| | 10837 | objects, because it makes a CollectiveGroup as visible, audible, etc. |
| | 10838 | as any of its individuals. |
| | 10839 | |
| | 10840 | <p>Note that this change doesn't affect CollectiveGroup objects that |
| | 10841 | have a normal location. These objects already participated in the |
| | 10842 | sensory model in the normal manner, and will continue to do so. This |
| | 10843 | change only affects group objects with no location. |
| | 10844 | |
| | 10845 | </div> |
| | 10846 | |
| | 10847 | <!-------------------> |
| | 10848 | <div class=entry> |
| | 10849 | |
| | 10850 | The handling of the "catch-all" Default handlers has changed |
| | 10851 | slightly. The sequence of processing is now as follows: |
| | 10852 | |
| | 10853 | <p> |
| | 10854 | <ul> |
| | 10855 | <li>The iobjFor(All) and dobjFor(All) handlers run first, if defined. |
| | 10856 | <li>The iobjFor(Default) and dobjFor(Default) handlers run next, <i>if</i> |
| | 10857 | they "override" the verb-specific handlers. |
| | 10858 | <li>The iobjFor() and dobjFor() handlers for the specific verb run next, |
| | 10859 | <i>unless</i> the corresponding Default handlers override them |
| | 10860 | </ul> |
| | 10861 | |
| | 10862 | <p>In the past, the 'verify', 'check', and 'action' methods for the |
| | 10863 | Default handlers were called <i>in addition to</i> any verb-specific |
| | 10864 | versions of the methods. For example, if an object defined a |
| | 10865 | dobjFor(Default) with an action() method, and the player entered an |
| | 10866 | OPEN command on the object, the Default action handler ran, and then |
| | 10867 | the dobjFor(Open) action() method <i>also</i> ran. In most cases, |
| | 10868 | this made no difference, because the base Thing class doesn't even |
| | 10869 | define action() or check() handlers for most verbs, since it |
| | 10870 | disallows most verbs in the verify() stage. |
| | 10871 | |
| | 10872 | <p>With this change, the Default handlers now run <i>instead of</i> the |
| | 10873 | verb-specific handlers, when the Default handlers run at all. The |
| | 10874 | rules about when Default handlers override verb-specific handlers, |
| | 10875 | and vice versa, haven't changed. A Default handler still overrides |
| | 10876 | any verb-specific handler inherited from a base class, and any |
| | 10877 | verb-specific handler defined in the same class as the Default |
| | 10878 | handler or in any subclass still overrides that Default handler. |
| | 10879 | |
| | 10880 | <p>Note that the relative order of the All and Default handlers has |
| | 10881 | been reversed: the All handler now always runs first. This makes the |
| | 10882 | sequence of methods proceed from most general to most specific. |
| | 10883 | |
| | 10884 | </div> |
| | 10885 | |
| | 10886 | <!-------------------> |
| | 10887 | <div class=entry> |
| | 10888 | |
| | 10889 | If an 'exit' occurs within a PreCondition object's |
| | 10890 | checkPreCondition() method, it's now treated as a failure of the |
| | 10891 | enclosing action that invoked the precondition. The normal pattern |
| | 10892 | that most preconditions use is as follows: first, evaluate if the |
| | 10893 | condition is met; second, if the condition isn't met, try an |
| | 10894 | appropriate implied action to try to bring it into effect; third, |
| | 10895 | re-test the condition to see if the implied action did what it was |
| | 10896 | meant to; and fourth, if the condition still doesn't apply, use |
| | 10897 | 'exit' to terminate the triggering action. It's this use of 'exit' |
| | 10898 | that's now interpreted as a failure of the enclosing action. |
| | 10899 | |
| | 10900 | <p>Note that this doesn't apply if 'exit' is used within a nested |
| | 10901 | implied action; this only applies if 'exit' is used within the |
| | 10902 | precondition's checkPreCondition() method itself. |
| | 10903 | |
| | 10904 | </div> |
| | 10905 | |
| | 10906 | <!-------------------> |
| | 10907 | <div class=entry> |
| | 10908 | |
| | 10909 | The library now defines a template for the Achievement class, taking |
| | 10910 | a double-quoted string for the achievment's description text. |
| | 10911 | |
| | 10912 | </div> |
| | 10913 | |
| | 10914 | <!-------------------> |
| | 10915 | <div class=entry> |
| | 10916 | |
| | 10917 | The new function finishGameMsg() makes it easier to show one of the |
| | 10918 | conventional end-of-game messages, such as "*** YOU HAVE DIED ***" or |
| | 10919 | "*** YOU HAVE WON ***". This function takes two parameters: a |
| | 10920 | message specifier, and a list of extra finishing options. The extra |
| | 10921 | options are the same as for the existing function finishGame(). |
| | 10922 | |
| | 10923 | <p>The message specifier can be one of several standard, pre-defined |
| | 10924 | objects, or it can simply be a string to display. The pre-defined |
| | 10925 | object ftDeath, ftVictory, ftFailure, and ftGameOver display messages |
| | 10926 | for death of the player character ("YOU HAVE DIED"), victory ("YOU |
| | 10927 | HAVE WON"), failure ("YOU HAVE FAILED"), and simply "game over", |
| | 10928 | respectively. Alternatively, you can make up your own messages for |
| | 10929 | unconventional cases ('YOU HAVE SUFFERED A FATE WORSE THAN DEATH', |
| | 10930 | say) simply by specifying a string. Your string will be displayed |
| | 10931 | surrounded by "***" sequences to yield the conventional formatting, |
| | 10932 | or with other sequences that might vary by language. You can also |
| | 10933 | pass nil as the message specifier, in which case no message at all |
| | 10934 | is displayed. |
| | 10935 | |
| | 10936 | </div> |
| | 10937 | |
| | 10938 | <!-------------------> |
| | 10939 | <div class=entry> |
| | 10940 | |
| | 10941 | The value of gameMain.maxScore (formerly libScore.maxScore) is now |
| | 10942 | allowed to be nil. In addition, the default value in GameMainDef is |
| | 10943 | now nil. When this value is nil, the SCORE and FULL SCORE commands |
| | 10944 | simply won't mention a maximum score for the game. |
| | 10945 | |
| | 10946 | <p>If your game has complex scoring that makes it difficult or |
| | 10947 | impossible to state a maximum possible score, or if you simply don't |
| | 10948 | want to give this information to the player, simply set maxScore to |
| | 10949 | nil in your gameMain object. The library uses nil as the default |
| | 10950 | because there's no reason for the library to assume that a game will |
| | 10951 | have a particular maximum score (the library formerly used a default |
| | 10952 | value of 100, but this was overly presumptuous). |
| | 10953 | |
| | 10954 | </div> |
| | 10955 | |
| | 10956 | <!-------------------> |
| | 10957 | <div class=entry> |
| | 10958 | |
| | 10959 | The library's scoring system has a new, optional usage style that |
| | 10960 | provides two benefits. First, it lets you define the number of points |
| | 10961 | an Achievement is worth as part of the Achievement object, better |
| | 10962 | encapsulating the information about the Achievement. Second, the |
| | 10963 | library can use this new information to automatically compute the |
| | 10964 | maximum possible score in the game, saving you the trouble of figuring |
| | 10965 | this out manually (and of keeping the stated maximum in sync with the |
| | 10966 | game as you make changes). |
| | 10967 | |
| | 10968 | <p>If you explicitly set the maxScore property in your gameMain object, |
| | 10969 | the library will <b>not</b> automatically compute the maximum score. |
| | 10970 | Your explicit maxScore setting always overrides the computed value. |
| | 10971 | |
| | 10972 | <p>To take advantage of the new capabilities, simply define the new |
| | 10973 | 'points' property for each Achievement object you create. Then, |
| | 10974 | rather than calling addToScore() or addToScoreOnce(), both of which |
| | 10975 | take a parameter specifying the number of points to award, call the |
| | 10976 | new Achievement methods awardPoints() or awardPointsOnce() instead. |
| | 10977 | For example, suppose you have some existing code that looks like |
| | 10978 | this: |
| | 10979 | |
| | 10980 | <p><pre> |
| | 10981 | vase: Thing |
| | 10982 | handleBreakage() |
| | 10983 | { |
| | 10984 | // ... do the real work here... |
| | 10985 | |
| | 10986 | scoreMarker.addToScoreOnce(10); |
| | 10987 | } |
| | 10988 | |
| | 10989 | scoreMarker: Achievement { "breaking the base" } |
| | 10990 | ; |
| | 10991 | </pre> |
| | 10992 | |
| | 10993 | <p>This code defines a nested object called 'scoreMarker' to describe |
| | 10994 | the scoring item, and the 'handleBreakage' method awards the Achievement |
| | 10995 | object, assigning it 10 points in the score. Using the new style, |
| | 10996 | you'd change the code above to look like this instead: |
| | 10997 | |
| | 10998 | <p><pre> |
| | 10999 | vase: Thing |
| | 11000 | handleBreakage() |
| | 11001 | { |
| | 11002 | // ... do the real work here... |
| | 11003 | |
| | 11004 | scoreMarker.awardPoints(); |
| | 11005 | } |
| | 11006 | |
| | 11007 | scoreMarker: Achievement { +10 "breaking the base" } |
| | 11008 | ; |
| | 11009 | </pre> |
| | 11010 | |
| | 11011 | <p>The "+10" in the nested Achievement definition assigns the object a |
| | 11012 | value of 10 in its 'points' property (using a template defined in |
| | 11013 | adv3.h), indicating that the item is worth 10 points in the score. |
| | 11014 | Rather than specifying this in the code that awards the Achievement, |
| | 11015 | we define it as part of the Achievement object itself. The code that |
| | 11016 | awards the points doesn't need to specify the number of points; it |
| | 11017 | just calls the awardPoints() method of the Achievement object, which |
| | 11018 | awards the points defined in the object. This makes the code easier |
| | 11019 | to read, since you can see the description of the scoring item and the |
| | 11020 | number of points it's worth in one place. |
| | 11021 | |
| | 11022 | <p>To take advantage of the library's automatic computation of the |
| | 11023 | maximum possible score, you have to follow a few rules: |
| | 11024 | |
| | 11025 | <ul> |
| | 11026 | |
| | 11027 | <li>Use <b>only</b> Achievement objects to award points. Never |
| | 11028 | call addToScore() with a string value to award an ad hoc scoring item. |
| | 11029 | |
| | 11030 | <li>Set the 'points' property of each of your Achievement objects |
| | 11031 | to the number of points the item is worth. |
| | 11032 | |
| | 11033 | <li>If an Achievement can be scored more than once, <b>also</b> set |
| | 11034 | the 'maxPoints' property to the maximum number of points the item will |
| | 11035 | contribute to the score. This is usually just 'points' times the number |
| | 11036 | of times the item can be awarded. |
| | 11037 | |
| | 11038 | <li>Only define Achievement objects statically. Never use 'new |
| | 11039 | Achievement' to create an Achievement dynamically. (If you create new |
| | 11040 | Achievements dynamically, the library won't know about them at |
| | 11041 | start-up time, obviously, so it can't count their contributions to the |
| | 11042 | maximum score.) |
| | 11043 | |
| | 11044 | <li>Always award Achievements through their awardPoints() or |
| | 11045 | awardPointsOnce() methods. (This ensures that each Achievement is |
| | 11046 | scored with the number of points specified in its 'points' property.) |
| | 11047 | |
| | 11048 | <li>Achievements can't be mutually exclusive. That is, there must |
| | 11049 | exist at least one solution of the game in which every Achievement |
| | 11050 | object is awarded. (If you have Achievement objects that represent |
| | 11051 | different solutions to the same puzzle, so that only one of these |
| | 11052 | achievements can actually be awarded in any given traversal of the |
| | 11053 | game, the library would incorrectly count the score contributions of |
| | 11054 | all of the alternatives in the maximum score. The correct maximum |
| | 11055 | would count only the single highest score among the alternatives. The |
| | 11056 | library has no way of expressing mutual exclusion among Achievements, |
| | 11057 | so if your game has such a situation, you'll need to set |
| | 11058 | libScore.maxScore manually.) |
| | 11059 | |
| | 11060 | </ul> |
| | 11061 | |
| | 11062 | <p>If you follow these rules, the library will accurately compute the |
| | 11063 | maximum score value, so you don't need to bother figuring out how many |
| | 11064 | points are in the game yourself, and you don't need to worry about |
| | 11065 | initializing libScore.maxScore in your game's start-up code. |
| | 11066 | |
| | 11067 | <p>If your game can't follow the rules above (because you have |
| | 11068 | alternative solutions to puzzles that assign different scores, for |
| | 11069 | example, or because your game has alternative paths with different |
| | 11070 | maximum scores), you'll need to figure the maximum score manually, |
| | 11071 | and set the property 'maxScore' to this value in your 'gameMain' |
| | 11072 | object. Explicitly setting gameMain.maxScore in your code will |
| | 11073 | override the library's automatic computation. |
| | 11074 | |
| | 11075 | </div> |
| | 11076 | |
| | 11077 | <!-------------------> |
| | 11078 | <div class=entry> |
| | 11079 | |
| | 11080 | The finishGame() and finishGameMsg() functions now display the |
| | 11081 | current score (using the same message that the SCORE command normally |
| | 11082 | displays) if the finishOptionFullScore option is in the extra options |
| | 11083 | list. In fact, these functions will announce the score if any extra |
| | 11084 | option has the property showScoreInFinish set to true; |
| | 11085 | finishOptionFullScore has this option set to true, so including it in |
| | 11086 | the extra options list causes the score to be announced. If you want |
| | 11087 | the end-of-game announcement to include the score, but you don't want |
| | 11088 | to offer the FULL SCORE option, you can include finishOptionScore in |
| | 11089 | the extra options list; this is an "unlisted" option, so it doesn't |
| | 11090 | add anything to the list of offered option list, but it does cause |
| | 11091 | the end-of-game announcement to include the score. |
| | 11092 | |
| | 11093 | </div> |
| | 11094 | |
| | 11095 | <!-------------------> |
| | 11096 | <div class=entry> |
| | 11097 | |
| | 11098 | Actor.holdingDesc (which provides the default description of what an |
| | 11099 | actor is holding as part of processing an Examine action on the |
| | 11100 | actor) now uses pretty much the same handling that Thing uses when it |
| | 11101 | lists the contents of an object. The only difference is that |
| | 11102 | Actor.holdingDesc still uses the special holdingDescInventoryLister |
| | 11103 | as the contents lister. One important consequence of this change is |
| | 11104 | that examining an actor marks the actor's contents as having been |
| | 11105 | seen by the player character, just as examining an ordinary object |
| | 11106 | marks the object's contents as seen. Another is that the scope of |
| | 11107 | objects included in the listing is limited to objects the |
| | 11108 | point-of-view actor can actually see. In the past, the examined |
| | 11109 | actor listed everything in "inventory scope," which includes objects |
| | 11110 | that are directly held even if they're not currently visible; this is |
| | 11111 | correct for an inventory listing from the point of the view of the |
| | 11112 | actor taking the inventory (because the actor can presumably identify |
| | 11113 | directly held items by feel, even in the dark), but the new |
| | 11114 | sight-only behavior is more appropriate for examining another actor. |
| | 11115 | |
| | 11116 | <p>This change also adds a new Thing method examineListContentsWith(). |
| | 11117 | This is simply a service method that performs the bulk of what |
| | 11118 | Thing.examineListContents() did before, but is parameterized by |
| | 11119 | a lister to use to generate the listing. |
| | 11120 | |
| | 11121 | </div> |
| | 11122 | |
| | 11123 | <!-------------------> |
| | 11124 | <div class=entry> |
| | 11125 | |
| | 11126 | The new class AskConnector makes it easy to define a directional |
| | 11127 | connection when the direction is ambiguous. For example, suppose |
| | 11128 | that you have two doors leading north, and you don't want to use the |
| | 11129 | traditional trick of distinguishing the doors' respective directions |
| | 11130 | as northeast and northwest. (If you had ten doors leading north |
| | 11131 | instead of two, the traditional northeast/northwest trick wouldn't |
| | 11132 | help anyway.) If the player types NORTH, you would like the parser |
| | 11133 | to ask which door to use. |
| | 11134 | |
| | 11135 | <p>AskConnector makes this easy. Simply define the room's 'north' as |
| | 11136 | an AskConnector object, and set the AskConnector instance's property |
| | 11137 | 'travelAction' to 'GoThroughAction'. The connector, when invoked for |
| | 11138 | travel, will try running the GoThroughAction, but with a missing |
| | 11139 | direct object; this will make the parser ask the player which door to |
| | 11140 | use with the usual prompt for a missing object: "What do you want to |
| | 11141 | go through?" |
| | 11142 | |
| | 11143 | <p>If the direction has a specific set of possible objects, as in |
| | 11144 | our example of two doors leading north, you can further refine the |
| | 11145 | parser's question by specifying the 'travelObjs' property. Set this |
| | 11146 | to a list of the possible direct objects for the action. If you set |
| | 11147 | this property, you should also set 'travelObjsPhrase' to a string |
| | 11148 | giving the noun phrase to use in disambiguous questions: in our |
| | 11149 | example, we might set this to 'door', so that the question becomes |
| | 11150 | "Which door do you mean...?". |
| | 11151 | |
| | 11152 | </div> |
| | 11153 | |
| | 11154 | <!-------------------> |
| | 11155 | <div class=entry> |
| | 11156 | |
| | 11157 | The English library now provides a default verbPhrase for the |
| | 11158 | TravelVia action ('use/using (what)', which is pretty vague, but |
| | 11159 | TravelVia is fairly vague itself). This lets the parser generate |
| | 11160 | usable messages in cases where a TravelVia action elicits a parser |
| | 11161 | prompt, such as when using TravelVia in askForDobj(). |
| | 11162 | |
| | 11163 | </div> |
| | 11164 | |
| | 11165 | <!-------------------> |
| | 11166 | <div class=entry> |
| | 11167 | |
| | 11168 | TravelPushable has several small changes. |
| | 11169 | |
| | 11170 | <p>First, TravelPushable.movePushable() now uses moveIntoForTravel() |
| | 11171 | to move the object, rather than moveInto(). This corrects a problem |
| | 11172 | that occurred when the starting and destination locations were |
| | 11173 | connected by a sense connection (such as a distance connector). |
| | 11174 | |
| | 11175 | <p>Second, movePushable() and describeMovePushable() each now take an |
| | 11176 | additional argument giving the connector being traversed. |
| | 11177 | |
| | 11178 | <p>Third, the new method beforeMovePushable() gives the pushable |
| | 11179 | object a chance to do any necessary work just before the travel takes |
| | 11180 | place. This is especially useful for adding a message describing |
| | 11181 | anything special that happens when pushing the object out of its |
| | 11182 | current location. By default, this routine does nothing. |
| | 11183 | |
| | 11184 | </div> |
| | 11185 | |
| | 11186 | <!-------------------> |
| | 11187 | <div class=entry> |
| | 11188 | |
| | 11189 | The new Traveler methods canTravelVia() and explainNoTravelVia() allow |
| | 11190 | a traveler to disallow travel via a particular connector and/or to a |
| | 11191 | particular destination. These new methods essentially provide a |
| | 11192 | complement of the "travel barrier" mechanism, which allows a connector |
| | 11193 | to disallow travel by a particular traveler. The new methods are |
| | 11194 | useful becuase it's often more convenient to tie a travel condition to |
| | 11195 | the traveler than to the connector. For example, you might want to |
| | 11196 | implement a condition that prohibits a particular actor from going |
| | 11197 | outside; you could do this by defining a canTravelVia() method on the |
| | 11198 | actor that returns nil if the destination is an OutdoorRoom. |
| | 11199 | |
| | 11200 | </div> |
| | 11201 | |
| | 11202 | <!-------------------> |
| | 11203 | <div class=entry> |
| | 11204 | |
| | 11205 | The new BasicLocation methods enteringRoom(traveler) and |
| | 11206 | leavingRoom(traveler) make it more convenient to write code that |
| | 11207 | responds to an actor's arrival into or departure from a room. These |
| | 11208 | methods are called from travelerArriving() and travelerLeaving(), |
| | 11209 | respectively; they differ only in that (1) they have simpler |
| | 11210 | parameter lists, leaving out information that frequently isn't needed |
| | 11211 | to write an arrival/departure event handler, and (2) the base class |
| | 11212 | implementations don't do anything, so there's no need to use |
| | 11213 | 'inherited' to inherit up the base class behavior. These new methods |
| | 11214 | are purely for convenience, to make the very common task of writing |
| | 11215 | arrival/departure event handlers a little less work. |
| | 11216 | |
| | 11217 | </div> |
| | 11218 | |
| | 11219 | <!-------------------> |
| | 11220 | <div class=entry> |
| | 11221 | |
| | 11222 | The new class ContainerDoor makes it easy to create a door for a |
| | 11223 | container, if you want the door to act like a separate object in its |
| | 11224 | own right. This works with the ComplexContainer class: create a |
| | 11225 | parent as a ComplexContainer, and inside it create a ContainerDoor |
| | 11226 | and the normal secret actual Container. The door will redirect |
| | 11227 | commands like open, close, lock, and unlock to the secret inner |
| | 11228 | container, but will still appear as a separate object. |
| | 11229 | |
| | 11230 | </div> |
| | 11231 | |
| | 11232 | <!-------------------> |
| | 11233 | <div class=entry> |
| | 11234 | |
| | 11235 | In the past, the base TravelConnector methods describeArrival() and |
| | 11236 | describeDeparture() simply showed the most generic travel messages |
| | 11237 | ("Bob is leaving the area"). This meant that replacing a simple room |
| | 11238 | connection with a TravelMessage connector meant giving up the |
| | 11239 | directional message that a normal room connection generated ("Bob is |
| | 11240 | leaving to the east"). |
| | 11241 | |
| | 11242 | <p>Now, the directional message is the default in the base |
| | 11243 | TravelConnector class. If there's a direction property linked to the |
| | 11244 | connector from the origin (for a departure) or destination (for an |
| | 11245 | arrival), the base TravelConnector messages will now show the |
| | 11246 | directional version of the message. The generic, non-directional |
| | 11247 | message will only be shown when no directional link can be found. |
| | 11248 | Note that this doesn't affect the more specific types of connectors |
| | 11249 | and their custom messages, so stairs will still say "Bob goes up the |
| | 11250 | stairs," doors will still say "Bob leaves through the wooden door," |
| | 11251 | and so on. |
| | 11252 | |
| | 11253 | </div> |
| | 11254 | |
| | 11255 | <!-------------------> |
| | 11256 | <div class=entry> |
| | 11257 | |
| | 11258 | The new TravelConnector method isConnectorPassable() indicates whether |
| | 11259 | or not a traveler can pass through the connector. This can be used in |
| | 11260 | game code that probes the map to determine if a connector can be |
| | 11261 | traversed in its current state. |
| | 11262 | |
| | 11263 | </div> |
| | 11264 | |
| | 11265 | <!-------------------> |
| | 11266 | <div class=entry> |
| | 11267 | |
| | 11268 | In the past, the noTravel object, and the NoTravelMessage and |
| | 11269 | FakeConnector classes, incorrectly displayed their special messages on |
| | 11270 | attempted travel even when it was dark in the room. In the dark, the |
| | 11271 | "dark travel" message should take precedence. This has been |
| | 11272 | corrected. (The problem was that these classes overrode the |
| | 11273 | dobjFor(TravelVia) check() method to bypass the normal darkness check. |
| | 11274 | The unnecessary override has been removed, so the standard darkness |
| | 11275 | check is now made, so the dark-travel message is now shown instead of |
| | 11276 | any special message.) |
| | 11277 | |
| | 11278 | </div> |
| | 11279 | |
| | 11280 | <!-------------------> |
| | 11281 | <div class=entry> |
| | 11282 | |
| | 11283 | The BasicLocation methods getTraveler() and getPushTraveler() have |
| | 11284 | been renamed and moved into Thing. These methods are now called |
| | 11285 | getLocTraveler() ("get location traveler") and getLocPushTraveler() |
| | 11286 | ("get location push traveler"), respectively. |
| | 11287 | |
| | 11288 | <p>This change is necessary to allow actors to hold other actors, and |
| | 11289 | to allow intermediate containers within rooms (that is, to allow a |
| | 11290 | Room to hold an arbitrary Thing subclass, which in turn holds a |
| | 11291 | NestedRoom). Actor has methods with the names getTraveler() and |
| | 11292 | getPushTraveler(), but these methods have a different purpose than the |
| | 11293 | old BasicLocation methods: the Actor methods get the traveler when the |
| | 11294 | actor is initiating the travel, and the old BasicLocation methods get |
| | 11295 | the actual traveler when a traveler within the location initiates |
| | 11296 | travel. The use of the same name created a conflict between these |
| | 11297 | different purposes, so one or the other set had to be renamed. In |
| | 11298 | addition, limiting these methods to BasicLocation prevented ordinary |
| | 11299 | Things from holding actors who could travel; adding them to Thing |
| | 11300 | corrects this. |
| | 11301 | |
| | 11302 | </div> |
| | 11303 | |
| | 11304 | <!-------------------> |
| | 11305 | <div class=entry> |
| | 11306 | |
| | 11307 | The logic in Vehicle.getTraveler() that determines whether to move |
| | 11308 | the vehicle or the traveler within the vehicle has changed slightly. |
| | 11309 | Rather than basing the decision on travel barriers, the routine now |
| | 11310 | moves the traveler rather than the vehicle only if the connector is |
| | 11311 | contained within the vehicle - that is, the connector leads somewhere |
| | 11312 | from inside the vehicle. The connector is considered to be inside |
| | 11313 | the vehicle if (1) it's a physical object (a Thing) that's inside the |
| | 11314 | vehicle, or (2) one of the direction properties of the vehicle is set |
| | 11315 | to the connector. (The old logic had the undesirable side effect of |
| | 11316 | implicitly removing the traveler from the vehicle if the vehicle |
| | 11317 | couldn't cross a barrier, which was really too automatic.) |
| | 11318 | |
| | 11319 | </div> |
| | 11320 | |
| | 11321 | <!-------------------> |
| | 11322 | <div class=entry> |
| | 11323 | |
| | 11324 | In the past, the way push-travel actions was handled caused a problem |
| | 11325 | in certain cases involving remapping of actions. The problem showed |
| | 11326 | up most readily with StairwayUp and StairwayDown objects; |
| | 11327 | specifically, PUSH x DOWN acted differently than PUSH x DOWN y, where |
| | 11328 | y was a StairwayUp or StairwayDown and the room's 'up' or 'down' |
| | 11329 | pointed to y. These commands obviously should have been equivalent. |
| | 11330 | |
| | 11331 | <p>Stairways were the only library objects that exposed the problem, |
| | 11332 | but it was possible to define your own objects with the same bad |
| | 11333 | behavior. In general, the problem occurred whenever a two-object |
| | 11334 | push-travel action (PUSH x UP y, PUSH x THROUGH y, PUSH x INTO y, |
| | 11335 | etc.) was attempted, <i>and</i> the indirect object's handler for the |
| | 11336 | corresponding travel action (ClimbUp, GoThrough, Enter, etc.) was |
| | 11337 | defined using asDobjFor(), <i>and</i> the handler for the target |
| | 11338 | action of the asDobjFor() was itself defined using a remapTo(). |
| | 11339 | |
| | 11340 | <p>The problem has been fixed, so any two-object push-travel action |
| | 11341 | should now be handled equivalently to the corresponding one-object |
| | 11342 | (directional) push-travel action on the same travel connector. |
| | 11343 | |
| | 11344 | </div> |
| | 11345 | |
| | 11346 | <!-------------------> |
| | 11347 | <div class=entry> |
| | 11348 | |
| | 11349 | The Chair, Bed, and Platform classes can now <i>all</i> allow |
| | 11350 | standing, sitting, and lying on the object. In the past, Chair only |
| | 11351 | allowed sitting, Bed allowed lying and sitting, and Platform allowed |
| | 11352 | all three. The set of postures allowed can now be customized for |
| | 11353 | each individual object. |
| | 11354 | |
| | 11355 | <p>The new property allowedPostures contains a list of the postures |
| | 11356 | that the object allows. By default, Chair allows sitting and |
| | 11357 | standing, and Bed and Platform allow sitting, standing, and lying. |
| | 11358 | You can override allowedPostures for an individual Chair, Bed, or |
| | 11359 | Platform object to add or remove allowed postures. When a posture |
| | 11360 | isn't in the allowed list, it will be ruled as "illogical" in the |
| | 11361 | verification stage. |
| | 11362 | |
| | 11363 | <p>In addition, the new property obviousPostures contains a list of |
| | 11364 | the postures that are "obvious" for the object; these are the |
| | 11365 | postures that are most natural for the object. The obvious postures |
| | 11366 | are enumerated separately from the allowed postures to control |
| | 11367 | defaulting: if a posture is allowed but not obvious for an object, |
| | 11368 | then the corresponding command will be ruled as "nonObvious" in the |
| | 11369 | verify stage, ensuring that the command will only be accepted if |
| | 11370 | stated explicitly (that is, the player will be able to perform the |
| | 11371 | command, but the parser won't automatically guess the command based |
| | 11372 | on incomplete information from the player). By default, it's obvious |
| | 11373 | to sit on a chair, to sit or lie on a bed, and to sit, lie, or stand |
| | 11374 | on a platform. |
| | 11375 | |
| | 11376 | <p>The three separate classes are still three separate classes for a |
| | 11377 | couple of reasons. First, each one has a primary, "natural" posture |
| | 11378 | associated with it: sitting on a chair, lying on a bed, standing on a |
| | 11379 | platform. This primary posture is the one that the library will |
| | 11380 | assume for implied actions and incomplete commands. Second, Platform |
| | 11381 | differs from the other two in that objects dropped while standing on |
| | 11382 | a platform land on the platform, whereas objects dropped while on a |
| | 11383 | chair or bed land in the enclosing room. |
| | 11384 | |
| | 11385 | <p>Note that a posture that isn't allowed by allowedPostures will |
| | 11386 | be treated as illogical. If you want to create an object for which |
| | 11387 | a given posture makes physical sense, but isn't allowed for some |
| | 11388 | other reason (character motivation constraints, for example), you |
| | 11389 | should include the posture in allowedPostures and then disallow the |
| | 11390 | corresponding command using the check() routine. |
| | 11391 | |
| | 11392 | </div> |
| | 11393 | |
| | 11394 | <!-------------------> |
| | 11395 | <div class=entry> |
| | 11396 | |
| | 11397 | NestedRoom now defines 'out' to use the special 'noTravelOut' |
| | 11398 | connector, which will automatically treat an OUT command as a GET OUT |
| | 11399 | OF command while in the nested room. Without this, the 'noTravelOut' |
| | 11400 | would typically be "inherited" from the enclosing room anyway, but |
| | 11401 | not always: if the enclosing room defined its own OUT, the nested |
| | 11402 | room would pick up that one instead, which isn't usually appropriate |
| | 11403 | when within a nested room. This change ensures that nested rooms |
| | 11404 | behave consistently even when nested within rooms with their own |
| | 11405 | explicit 'out' connections. |
| | 11406 | |
| | 11407 | </div> |
| | 11408 | |
| | 11409 | <!-------------------> |
| | 11410 | <div class=entry> |
| | 11411 | |
| | 11412 | The HighNestedRoom class now prohibits exiting the room, by default. |
| | 11413 | It does this by setting the exitDestination property to nil; this |
| | 11414 | indicates that the room has no natural exit location, so it's not |
| | 11415 | possible to leave it. HighNestedRoom generates an appropriate |
| | 11416 | message ("It's too long a drop to do that from here") when an |
| | 11417 | attempt to exit the location fails. |
| | 11418 | |
| | 11419 | <p>The base NestedRoom now checks, in the GetOutOf action's check() |
| | 11420 | handler, that there is a non-nil exitDestination. If there's not a |
| | 11421 | valid exit destination, the check() handler calls the new method |
| | 11422 | cannotMoveActorOutOf() to display an appropriate message, then |
| | 11423 | terminates the command with 'exit'. |
| | 11424 | |
| | 11425 | </div> |
| | 11426 | |
| | 11427 | <!-------------------> |
| | 11428 | <div class=entry> |
| | 11429 | |
| | 11430 | By default, NestedRoom now uses the new travel connector nestedRoomOut |
| | 11431 | for its "out" link, rather than noTravelOut as it did in the past. |
| | 11432 | The nestedRoomOut connector works just like noTravelOut, except that |
| | 11433 | nestedRoomOut is "apparent" to characters, so it shows up in the EXITS |
| | 11434 | list. Since OUT is usually a valid travel command while in a nested |
| | 11435 | room (the command exits the nested room), it makes sense to list OUT |
| | 11436 | explicitly as a possible direction while in a nested room. To |
| | 11437 | override this for a particular nested room, just set 'out' to |
| | 11438 | noTravelOut; to change this behavior for all nested rooms, do the same |
| | 11439 | thing with 'modify NestedRoom'. |
| | 11440 | |
| | 11441 | </div> |
| | 11442 | |
| | 11443 | <!-------------------> |
| | 11444 | <div class=entry> |
| | 11445 | |
| | 11446 | The new Floorless class is a mix-in that can be combined with any |
| | 11447 | other type of Room class to create a floorless version of the room. |
| | 11448 | Mix Floorless in ahead of the Room base class in the superclass list |
| | 11449 | of the room you're creating; Floorless will, among other things, |
| | 11450 | subtract any default floor/ground object from the base room's |
| | 11451 | roomParts list. |
| | 11452 | |
| | 11453 | <p>The existing FloorlessRoom class has been retained, but is now |
| | 11454 | simply a convenience class that combines Floorless and Room. This |
| | 11455 | provides the same behavior as the old FloorlessRoom class, so existing |
| | 11456 | code should not be affected. |
| | 11457 | |
| | 11458 | </div> |
| | 11459 | |
| | 11460 | <!-------------------> |
| | 11461 | <div class=entry> |
| | 11462 | |
| | 11463 | Some fine-tuning has been applied to announcements for cascading |
| | 11464 | implied actions in certain cases. When a series of nested implied |
| | 11465 | actions fails, the parser now announces only the first of the series. |
| | 11466 | For example, in the past, if a travel action initiated an OPEN DOOR |
| | 11467 | which initiated an UNLOCK DOOR which failed, the parser showed |
| | 11468 | something like this: (first trying to unlock the door and then open |
| | 11469 | it). The parser now shows only this: (first trying to unlock the |
| | 11470 | door). |
| | 11471 | |
| | 11472 | <p>The reason for dropping the extra announcements is that they don't |
| | 11473 | really tell the player anything useful, so they're just unnecessary |
| | 11474 | verbosity. Because of the recursive relationship of the implied |
| | 11475 | action in these cases, the first action is nested in the second, |
| | 11476 | which is nested in the third, and so on; so the second and subsequent |
| | 11477 | actions all failed as a direct result of the first one failing (in |
| | 11478 | our example, the OPEN fails because it requires the UNLOCK to |
| | 11479 | succeed, so when the UNLOCK fails the OPEN must also fail). This |
| | 11480 | means that we never actually get around to trying the second and |
| | 11481 | subsequent actions; when the first action fails, we give up on |
| | 11482 | trying any of the others. The only thing they tell the player is |
| | 11483 | why the failed action was attempted at all (in our example, the |
| | 11484 | implied OPEN explains why we're attempting the implied UNLOCK). |
| | 11485 | But the rationale in these cases is almost always obvious to the |
| | 11486 | player, so even this isn't a very good reason to keep the extra |
| | 11487 | announcements. |
| | 11488 | |
| | 11489 | <p>This behavior can be controlled via |
| | 11490 | implicitAnnouncementGrouper.keepAllFailures. The property is nil |
| | 11491 | by default; to list the entire stack of failures for these cases, |
| | 11492 | change it to true. |
| | 11493 | |
| | 11494 | </div> |
| | 11495 | |
| | 11496 | <!-------------------> |
| | 11497 | <div class=entry> |
| | 11498 | |
| | 11499 | The extra "testing" step for opening Lockable objects has been |
| | 11500 | removed. This extra step was introduced in 3.0.6m to make the cascade |
| | 11501 | of implied actions more plausible for these cases, but the extra |
| | 11502 | verbosity was really too much, so it's been removed in the interest |
| | 11503 | of simplicity. |
| | 11504 | |
| | 11505 | <p>Instead, a Lockable now tests a new method, autoUnlockOnOpen(); if |
| | 11506 | this returns true, then OPEN implies UNLOCK, otherwise it does not. |
| | 11507 | This means that, if autoUnlockOnOpen returns nil, and the object is |
| | 11508 | locked, then an OPEN command will simply fail with an error message |
| | 11509 | ("the door seems to be locked"), and the player will have to enter an |
| | 11510 | explicit UNLOCK command. |
| | 11511 | |
| | 11512 | <p>The new autoUnlockOnOpen() method is defined as follows: |
| | 11513 | |
| | 11514 | <ul> |
| | 11515 | |
| | 11516 | <li>For Lockable, the method returns the value of the lockStatusObvious |
| | 11517 | property. This means that OPEN implies UNLOCK if the lock status is |
| | 11518 | readily observable, and requires a separate, explicit UNLOCK if not. |
| | 11519 | |
| | 11520 | <li>For KeyedLockable, the method returns true if the inherited value |
| | 11521 | is true, OR if the actor is carrying a known key for the object. By |
| | 11522 | default, a KeyedLockable automatically remembers keys as known once |
| | 11523 | they're successfully used, so once an object is successfully unlocked |
| | 11524 | with a key, an OPEN command will automatically imply UNLOCK on |
| | 11525 | subsequent attempts, as long as the actor is carrying the same key. |
| | 11526 | This is a concession to playability, in that it eliminates the need |
| | 11527 | to spell out every step of operating a door or other keyed lockable |
| | 11528 | after the first time through, but it's also arguably more realistic: |
| | 11529 | the actor knows from experience how to operate the door, so we can |
| | 11530 | see the automatic UNLOCK as merely leaving some boring details out of |
| | 11531 | the narration. |
| | 11532 | |
| | 11533 | </ul> |
| | 11534 | |
| | 11535 | <p>Some authors might always prefer the automatic UNLOCK to forcing a |
| | 11536 | player to type a separate UNLOCK command for objects with non-obvious |
| | 11537 | locking status. Which way you prefer is a matter of taste. On the |
| | 11538 | one hand, the extra UNLOCK command is a little annoying to players, |
| | 11539 | and is exactly the sort of thing the precondition mechanism was |
| | 11540 | created to avoid. On the other hand, the automatic UNLOCK is weird |
| | 11541 | when the lock status isn't apparent, because until the OPEN fails, we |
| | 11542 | have no way of knowing that the object was locked in the first place |
| | 11543 | and thus no reason to try the implied UNLOCK; it's an instance of the |
| | 11544 | parser revealing game-state information that the player character |
| | 11545 | isn't supposed to know. It also could be seen as actually detracting |
| | 11546 | from playability by making the game do too much automatically, taking |
| | 11547 | away a certain amount of control from the player (the player could |
| | 11548 | think: "I didn't even know that door was locked; if I had, I wouldn't |
| | 11549 | have tried to unlock it right now.") |
| | 11550 | |
| | 11551 | <p>By default, the library implements the more realistic but also |
| | 11552 | more tedious behavior, requiring a separate UNLOCK to OPEN a locked |
| | 11553 | object whose lock status isn't obvious. If you prefer to make UNLOCK |
| | 11554 | automatic on OPEN for a given object, simply override |
| | 11555 | autoOpenOnUnlock() to return true unconditionally for that object; if |
| | 11556 | you prefer to make UNLOCK automatic for all objects, modify Lockable |
| | 11557 | to make autoOpenOnUnlock() return true in all cases. |
| | 11558 | |
| | 11559 | </div> |
| | 11560 | |
| | 11561 | <!-------------------> |
| | 11562 | <div class=entry> |
| | 11563 | |
| | 11564 | The implied command behavior of keyed-lockable objects has been |
| | 11565 | changed slightly. In the past, attempting to OPEN a keyed-lockable |
| | 11566 | triggered an implied UNLOCK, which asked for a key. Thus, a command |
| | 11567 | like OPEN DOOR, or even GO NORTH, could be answered with a question |
| | 11568 | ("What do you want to unlock it with?"). This was a little awkward |
| | 11569 | because the player never actually said in so many words that they |
| | 11570 | wanted to unlock the door. Now, keyed-lockable objects simply |
| | 11571 | point out that a key is required to open the lock: |
| | 11572 | |
| | 11573 | <p><pre> |
| | 11574 | >go north |
| | 11575 | (first trying to unlock the iron door) |
| | 11576 | You need a key to unlock the door. |
| | 11577 | </pre> |
| | 11578 | |
| | 11579 | <p>Note, however, that if the actor knows which key to use, and one |
| | 11580 | of the known keys is in sight, then the command will be allowed to |
| | 11581 | proceed implicitly. In these cases, it won't be necessary to ask for |
| | 11582 | the key, since the actor's knowledge of the key allows it to be |
| | 11583 | supplied automatically as a default. |
| | 11584 | |
| | 11585 | </div> |
| | 11586 | |
| | 11587 | <!-------------------> |
| | 11588 | <div class=entry> |
| | 11589 | |
| | 11590 | The Keyring class now follows the normal Thing conventions for |
| | 11591 | mentioning the contents of the keyring. Formerly, Keyring.desc |
| | 11592 | generated the list of contents, using a lister defined in the property |
| | 11593 | 'examineLister'. Now, Keyring has no separate 'desc' method; |
| | 11594 | instead, the listing is generated by the standard Examine code |
| | 11595 | inherited from Thing, and the 'examineLister' property has been |
| | 11596 | renamed to 'descContentsLister' to accommodate the inherited |
| | 11597 | Thing methods. |
| | 11598 | |
| | 11599 | </div> |
| | 11600 | |
| | 11601 | <!-------------------> |
| | 11602 | <div class=entry> |
| | 11603 | |
| | 11604 | The new class CustomImmovable makes it easy to create an Immovable that |
| | 11605 | uses a single customized message to respond to all attempts to move |
| | 11606 | the object. Just override cannotTakeMsg, and the "move" and "put in" |
| | 11607 | messages will use the same message. The new class CustomFixture does |
| | 11608 | the same thing for Fixture. |
| | 11609 | |
| | 11610 | </div> |
| | 11611 | |
| | 11612 | <!-------------------> |
| | 11613 | <div class=entry> |
| | 11614 | |
| | 11615 | The new class FueledLightSource abstracts some of the functionality |
| | 11616 | that was formerly in Candle, to create a base class for objects that |
| | 11617 | provide light using a limited fuel supply. The new base class |
| | 11618 | doesn't assume that it's something that burns, as Candle does, so you |
| | 11619 | can use the new class to create things like limited-use flashlights. |
| | 11620 | Candle is now based on the new class. This change shouldn't affect |
| | 11621 | any existing game code; the implementation of Candle has merely been |
| | 11622 | rearranged internally to the library, so no changes should be |
| | 11623 | required to existing code. |
| | 11624 | |
| | 11625 | <p>An additional improvement in the new FueledLightSource class is |
| | 11626 | that the fuel source is no longer assumed to be the object itself. |
| | 11627 | This lets you model the fuel source as a separate object; for example, |
| | 11628 | you could use a separate battery object as the fuel source for a |
| | 11629 | flashlight, allowing a character in the game to swap out a dead |
| | 11630 | battery for a new one. Simply override the 'fuelSource' property |
| | 11631 | of your FueledLightSource object to specify the object that provides |
| | 11632 | the fuel. By default, the fuel source is still 'self', so Candle |
| | 11633 | objects in existing source code won't need any changes. |
| | 11634 | |
| | 11635 | </div> |
| | 11636 | |
| | 11637 | <!-------------------> |
| | 11638 | <div class=entry> |
| | 11639 | |
| | 11640 | The tryMakingRoomToHold method in Actor now checks each object it's |
| | 11641 | about to move into a "bag of holding" to make sure the object that's |
| | 11642 | to be held isn't inside the object to be moved. This ensures that the |
| | 11643 | attempt to make more room to hold things doesn't inadvertantly move |
| | 11644 | the object to be held out of reach, defeating the purpose of making |
| | 11645 | room to hold it. This change ensures that the object to be held |
| | 11646 | stays where it is, since all of its containers stay where they are. |
| | 11647 | |
| | 11648 | </div> |
| | 11649 | |
| | 11650 | <!-------------------> |
| | 11651 | <div class=entry> |
| | 11652 | |
| | 11653 | UnlistedProxyConnector.ofKind now returns true if the caller is |
| | 11654 | asking about UnlistedProxyConnector, and <i>also</i> returns true if |
| | 11655 | the caller is asking about the class of the underlying connector. |
| | 11656 | This makes a proxy look like its underlying connector and also like a |
| | 11657 | proxy, which is consistent with the rest of its behavior. |
| | 11658 | |
| | 11659 | </div> |
| | 11660 | |
| | 11661 | <!-------------------> |
| | 11662 | <div class=entry> |
| | 11663 | |
| | 11664 | The new DefaultTopic property 'excludeMatch' can be set to a list of |
| | 11665 | topics (Thing or Topic objects) to exclude from the catch-all match. |
| | 11666 | By default, this is just an empty list, so nothing is excluded. |
| | 11667 | Individual DefaultTopic objects can provide a list of objects to |
| | 11668 | exclude from the catch-all. This is useful when you're creating a |
| | 11669 | DefaultTopic for a ConvNode or ActorState, but you want one or more |
| | 11670 | specific topics to be referred to the enclosing topic database for |
| | 11671 | handling. By including the topics in the excludeMatch list, you |
| | 11672 | ensure that they won't be caught in the catch-all DefaultTopic, which |
| | 11673 | will let them propagate to the enclosing topic database. |
| | 11674 | |
| | 11675 | </div> |
| | 11676 | |
| | 11677 | <!-------------------> |
| | 11678 | <div class=entry> |
| | 11679 | |
| | 11680 | ConvNode.npcContinueConversation() now returns true if anything was |
| | 11681 | displayed in the course of the method, nil if not. This lets a caller |
| | 11682 | determine if the NPC actually had anything to say. |
| | 11683 | |
| | 11684 | <p>ActorState.takeTurn() now uses this information to consider the |
| | 11685 | NPC to have finished its turn if the ConvNode added a conversational |
| | 11686 | message. In the past, merely having a non-nil ConvNode was enough to |
| | 11687 | make takeTurn() consider the turn to be taken entirely by the |
| | 11688 | ConvNode; now, the turn is only considered finished if the ConvNode |
| | 11689 | actually wanted to say something. This allows ordinary actor-state |
| | 11690 | background scripts to continue running even when a ConvNode is |
| | 11691 | active, as long as the ConvNode doesn't generate any NPC conversation |
| | 11692 | messages. |
| | 11693 | |
| | 11694 | </div> |
| | 11695 | |
| | 11696 | <!-------------------> |
| | 11697 | <div class=entry> |
| | 11698 | |
| | 11699 | The nestedActorAction() function now sets a visual sense context for |
| | 11700 | the new actor. (In the past, the nested action incorrectly executed |
| | 11701 | within the same sense context as the enclosing action, which allowed |
| | 11702 | actions that shouldn't have been visible to be reported, and vice |
| | 11703 | versa.) |
| | 11704 | |
| | 11705 | </div> |
| | 11706 | |
| | 11707 | <!-------------------> |
| | 11708 | <div class=entry> |
| | 11709 | |
| | 11710 | If an implied action announcement comes immediately after other |
| | 11711 | report messages for an action in which the implied action is nested, |
| | 11712 | the command transcript now automatically inserts a paragraph start |
| | 11713 | just before the implied action announcement. It's often desirable to |
| | 11714 | invoke a nested action in the course of handling a main action, and |
| | 11715 | in some cases the nested action can trigger implied actions of its |
| | 11716 | own. This new transcript feature makes the spacing look better in |
| | 11717 | these cases when the main action reports its own results before |
| | 11718 | invoking the nested action. |
| | 11719 | |
| | 11720 | Similarly, if an implied action announcement occurs after a result |
| | 11721 | message from a previous implied action, a paragraph break is inserted |
| | 11722 | before the second implied announcement. This improves readability |
| | 11723 | in these cases. |
| | 11724 | |
| | 11725 | </div> |
| | 11726 | |
| | 11727 | <!-------------------> |
| | 11728 | <div class=entry> |
| | 11729 | |
| | 11730 | The CommandTranscript method summarizeAction() now interacts properly |
| | 11731 | with conversational responses. A change in 3.0.6m caused a problem |
| | 11732 | when attempting to summarize a series of conversational messages |
| | 11733 | (generated by TopicEntry activation); specifically, the summarizer |
| | 11734 | didn't recognize the new "in-band" conversational boundary markers |
| | 11735 | that the conversation manager started generating in 3.0.6m. The |
| | 11736 | summarizer now handles the conversation markers properly. |
| | 11737 | |
| | 11738 | </div> |
| | 11739 | |
| | 11740 | <!-------------------> |
| | 11741 | <div class=entry> |
| | 11742 | |
| | 11743 | The AgendaItem class has a new property, initiallyActive, that |
| | 11744 | indicates that an agenda item is active at the start of the game. |
| | 11745 | During initialization, the library will automatically add each |
| | 11746 | initially active agenda item to its actor's agenda (by calling |
| | 11747 | addToAgenda() on the actor). |
| | 11748 | |
| | 11749 | </div> |
| | 11750 | |
| | 11751 | <!-------------------> |
| | 11752 | <div class=entry> |
| | 11753 | |
| | 11754 | The new AgendaItem property agendaOrder makes it easy to control the |
| | 11755 | priority order of agenda items. The agenda list is now sorted in |
| | 11756 | ascending order of the agendaOrder values; this means that the lower |
| | 11757 | the number, the earlier the item will appear in the agenda list. |
| | 11758 | Actors choose the first item in the list that's ready to run, so |
| | 11759 | ready-to-run agenda items will always be executed in order of their |
| | 11760 | agendaOrder values. By default, agendaOrder is set to 100; set a |
| | 11761 | lower value if you want the item to go earlier than other items, a |
| | 11762 | higher number if you want it to go later. If you don't care about the |
| | 11763 | ordering, you can leave the default value unchanged. |
| | 11764 | |
| | 11765 | <p>Note that readiness is more important than agendaOrder. Suppose |
| | 11766 | that AgendaItem A has a lower agendaItem value, and thus goes earlier |
| | 11767 | in the list, than AgendaItem B. Despite this list order, if B is |
| | 11768 | ready to run and A is not, B will be executed. |
| | 11769 | |
| | 11770 | </div> |
| | 11771 | |
| | 11772 | <!-------------------> |
| | 11773 | <div class=entry> |
| | 11774 | |
| | 11775 | The new class SuggestedAskForTopic can be mixed into an AskForTopic |
| | 11776 | object's superclass list to add the "ask for" to the topic inventory. |
| | 11777 | This works in parallel with the other SuggestedTopic subclasses. |
| | 11778 | |
| | 11779 | </div> |
| | 11780 | |
| | 11781 | <!-------------------> |
| | 11782 | <div class=entry> |
| | 11783 | |
| | 11784 | In the past, AltTopic didn't work properly with SpecialTopic. This |
| | 11785 | has been corrected; you can now create AltTopic children of |
| | 11786 | SpecialTopic entries, and they'll work as you'd expect. |
| | 11787 | |
| | 11788 | <p>In a related change, SpecialTopic now inherits from |
| | 11789 | SuggestedTopicTree, rather than SuggestedTopic as it did in the past. |
| | 11790 | This ensures that a special topic will be suggested in the topic |
| | 11791 | inventory when any of its AltTopic children are active. |
| | 11792 | |
| | 11793 | </div> |
| | 11794 | |
| | 11795 | <!-------------------> |
| | 11796 | <div class=entry> |
| | 11797 | |
| | 11798 | The library now defines template variations that allow defining |
| | 11799 | firstEvents lists with various TopicEntry/ShuffledTextList |
| | 11800 | combinations: TopicEntry, MiscTopic, SpecialTopic, DefaultTopic, |
| | 11801 | AltTopic. Now, if you define an instance of one of these classes, |
| | 11802 | your definition can include two lists: the first will be the |
| | 11803 | firstEvents list, and the second will be the eventList list. |
| | 11804 | |
| | 11805 | </div> |
| | 11806 | |
| | 11807 | <!-------------------> |
| | 11808 | <div class=entry> |
| | 11809 | |
| | 11810 | The new DefaultAskForTopic class lets you define a default response |
| | 11811 | to an ASK FOR command. This new class is parallel to the other |
| | 11812 | DefaultTopic subclasses. |
| | 11813 | |
| | 11814 | </div> |
| | 11815 | |
| | 11816 | <!-------------------> |
| | 11817 | <div class=entry> |
| | 11818 | |
| | 11819 | The various DefaultTopic subclasses are now arranged in a hierarchy |
| | 11820 | of low "match score" values. In the past, all DefaultTopics used a |
| | 11821 | match score of 1, which generally made them rank lower than any |
| | 11822 | non-default topic, but didn't differentiate among different default |
| | 11823 | topics that matched the same input topic. Now, the single-type |
| | 11824 | defaults (DefaultAskTopic, DefaultTellTopic, etc.) have a match score |
| | 11825 | of 3, the multi-type defaults (DefaultAskTellTopic, etc.) have a |
| | 11826 | match score of 2, and DefaultAnyTopic has a score of 1. This means |
| | 11827 | that a single-type default will take precedence over a multi-type |
| | 11828 | default, which will in turn take precedence over an ANY default. |
| | 11829 | This lets you define a DefaultAskTopic that will handle any ASK |
| | 11830 | command, for example, and a DefaultAnyTopic to handle everything else. |
| | 11831 | |
| | 11832 | </div> |
| | 11833 | |
| | 11834 | <!-------------------> |
| | 11835 | <div class=entry> |
| | 11836 | |
| | 11837 | The initiateTopic() method (in Actor, ActorState, and ConvNode) now |
| | 11838 | remembers that the player character is talking to the NPC. This |
| | 11839 | ensures that commands that check the current interlocutor, such as |
| | 11840 | TOPICS, properly recognize that the characters are talking to one |
| | 11841 | another. |
| | 11842 | |
| | 11843 | </div> |
| | 11844 | |
| | 11845 | <!-------------------> |
| | 11846 | <div class=entry> |
| | 11847 | |
| | 11848 | A problem in the library generated a spurious "you're not talking to |
| | 11849 | anyone" message under certain obscure circumstances involving an |
| | 11850 | automatic "topic inventory" scheduled at the start of a conversation. |
| | 11851 | This is now fixed. |
| | 11852 | |
| | 11853 | </div> |
| | 11854 | |
| | 11855 | <!-------------------> |
| | 11856 | <div class=entry> |
| | 11857 | |
| | 11858 | In some cases, if an actor was in a ConvNode but didn't say anything |
| | 11859 | on a given turn, the actor was incorrectly set as the most recent |
| | 11860 | pronoun. The library was being overly aggressive about setting the |
| | 11861 | pronoun as though the actor had said something, as a convenience to |
| | 11862 | the player to respond to the actor. The library no longer sets the |
| | 11863 | pronoun unless the actor actually says something (i.e., some text is |
| | 11864 | generated in the course of the actor's turn while in the ConvNode). |
| | 11865 | |
| | 11866 | </div> |
| | 11867 | |
| | 11868 | <!-------------------> |
| | 11869 | <div class=entry> |
| | 11870 | |
| | 11871 | In the English language module, the vocabulary initializer now |
| | 11872 | ignores extra spaces after delimiters (such as '/' or '*'). This |
| | 11873 | makes it easier to break up long vocabulary initializers across |
| | 11874 | multiple lines of code. For example: |
| | 11875 | |
| | 11876 | <p><pre> |
| | 11877 | + Thing 'big large huge gigantic giant book/tome/volume/ |
| | 11878 | text/manuscript' 'huge tome' |
| | 11879 | // etc |
| | 11880 | ; |
| | 11881 | </pre> |
| | 11882 | |
| | 11883 | <p>Note the line break in the middle of the list of nouns. This |
| | 11884 | introduces an extra space into the string, which is now perfectly |
| | 11885 | okay. |
| | 11886 | |
| | 11887 | </div> |
| | 11888 | |
| | 11889 | <!-------------------> |
| | 11890 | <div class=entry> |
| | 11891 | |
| | 11892 | In the English parser, the literal adjective wildcard string has been |
| | 11893 | changed. In the past, "*" (an asterisk within double quotes) was the |
| | 11894 | wildcard character. This made it difficult to match literally an |
| | 11895 | asterisk in the input, so the wildcard is now the character \u0001 |
| | 11896 | (i.e., Unicode code point 1), which is highly unlikely to be used in |
| | 11897 | input. |
| | 11898 | |
| | 11899 | </div> |
| | 11900 | |
| | 11901 | <!-------------------> |
| | 11902 | <div class=entry> |
| | 11903 | |
| | 11904 | In the English parser, 'miscVocab' was used as a token property |
| | 11905 | instead of 'miscWord' in a few places. The correct token type |
| | 11906 | should have been 'miscWord'; this has been corrected. |
| | 11907 | |
| | 11908 | </div> |
| | 11909 | |
| | 11910 | <!-------------------> |
| | 11911 | <div class=entry> |
| | 11912 | |
| | 11913 | The menu system now "wraps" up-arrow and down-arrow keys at the top |
| | 11914 | and bottom of a list of menu items; that is, if the first menu item |
| | 11915 | is selected and user presses the up-arrow, the selection moves to the |
| | 11916 | last menu item, and a down-arrow at the last item selects the first |
| | 11917 | item. |
| | 11918 | |
| | 11919 | </div> |
| | 11920 | |
| | 11921 | <!-------------------> |
| | 11922 | <div class=entry> |
| | 11923 | |
| | 11924 | The library now provides a template for MenuTopicItem, with slots for |
| | 11925 | the title string, an optional heading string, and the menu contents |
| | 11926 | list. |
| | 11927 | |
| | 11928 | </div> |
| | 11929 | |
| | 11930 | <!-------------------> |
| | 11931 | <div class=entry> |
| | 11932 | |
| | 11933 | When a locked door with lockStatusObvious was examined, a message |
| | 11934 | indicating its status (locked or unlocked) was meant to be displayed, |
| | 11935 | but wasn't. This has been corrected. |
| | 11936 | |
| | 11937 | </div> |
| | 11938 | |
| | 11939 | <!-------------------> |
| | 11940 | <div class=entry> |
| | 11941 | |
| | 11942 | A recent change to OOPS processing (in 3.0.6j) introduced a bug: |
| | 11943 | typing OOPS after a misspelling in a response to an interactive |
| | 11944 | parser query didn't work. For example, if your answer to a |
| | 11945 | disambiguation question ("which book do you mean...") contained a |
| | 11946 | typo, you couldn't use OOPS to correct that typo. This now works |
| | 11947 | properly again. |
| | 11948 | |
| | 11949 | </div> |
| | 11950 | |
| | 11951 | <!-------------------> |
| | 11952 | <div class=entry> |
| | 11953 | |
| | 11954 | Typing AGAIN after a SpecialTopic command didn't work in the past. |
| | 11955 | This has been corrected. AGAIN can now be used to repeat a special |
| | 11956 | topic, as long as the same comamnd is still valid as a special topic; |
| | 11957 | if the command isn't a valid special topic any longer, the parser |
| | 11958 | will simply say that the command cannot be repeated. |
| | 11959 | |
| | 11960 | </div> |
| | 11961 | |
| | 11962 | <!-------------------> |
| | 11963 | <div class=entry> |
| | 11964 | |
| | 11965 | The new Thing method expandPronounList() allows an object to |
| | 11966 | effectively reverse the effects of filterResolveList() when a pronoun |
| | 11967 | refers to the object in a subsequent command. The parser calls this |
| | 11968 | new method on each of the objects in the "raw" binding for a pronoun |
| | 11969 | (that is, the set of program objects that were resolved in the |
| | 11970 | previous command that established the antecedent of the pronoun). |
| | 11971 | |
| | 11972 | <p>The Thing and CollectiveGroup objects use this new method to |
| | 11973 | ensure that a collective group's filtering is applied consistently |
| | 11974 | for each command, whether the command uses a full noun phrase or a |
| | 11975 | pronoun to refer to the groupable objects. |
| | 11976 | |
| | 11977 | </div> |
| | 11978 | |
| | 11979 | <!-------------------> |
| | 11980 | <div class=entry> |
| | 11981 | |
| | 11982 | When a noun phrase in a player command refers to an object that has |
| | 11983 | "facets" (as indicated by the object's getFacets() method), and more |
| | 11984 | than one facet of the object is in scope, the parser will now |
| | 11985 | automatically choose only one facet of the object. The parser chooses |
| | 11986 | the facet that has the best transparency in the actor's sight-like |
| | 11987 | senses; if the visibilities are equivalent, then the parser chooses |
| | 11988 | the facet with the best touch transparency; if visibilities and |
| | 11989 | touchabilities are equivalent, the parser chooses one arbitrarily. |
| | 11990 | This change ensures that different facets of the same object will |
| | 11991 | never create ambiguity in the parser, which is important because a set |
| | 11992 | of facets is always meant to implement what the player sees as a |
| | 11993 | single game world object. |
| | 11994 | |
| | 11995 | <p>In a related change, the parser's method of choosing a facet as the |
| | 11996 | antecedent of a pronoun has changed slightly. First, the parser now |
| | 11997 | considers all in-scope facets when an antecedent has facets, even if |
| | 11998 | the base antecedent object is itself in scope. Second, the parser |
| | 11999 | chooses which in-scope facet to use based on the same criteria as |
| | 12000 | above: visibility, then touchability. This ensures that when multiple |
| | 12001 | facets are in scope (because of sense connectors, for example), the |
| | 12002 | most readily visible <i>and</i> reachable one will be selected. |
| | 12003 | |
| | 12004 | </div> |
| | 12005 | |
| | 12006 | <!-------------------> |
| | 12007 | <div class=entry> |
| | 12008 | |
| | 12009 | The parser now selects a default antecedant for a pronoun whenever |
| | 12010 | possible, based on the objects in scope. For example, if you type |
| | 12011 | LOOK AT HIM, and you haven't established a prior meaning for HIM (by |
| | 12012 | referring to a male actor with a previous command), <i>or</i> the |
| | 12013 | prior meaning of HIM is no longer valid (because that actor is no |
| | 12014 | longer present), then the parser will assume that HIM refers to a |
| | 12015 | male actor who is present, assuming there's exactly one. If there |
| | 12016 | are no in-scope objects matching the gender of the pronoun, or |
| | 12017 | multiple matching objects are in scope, the parser has no way of |
| | 12018 | guessing what the pronoun means. When a pronoun could only refer to |
| | 12019 | one object, though, the parser will assume that that's the object you |
| | 12020 | meant. |
| | 12021 | |
| | 12022 | </div> |
| | 12023 | |
| | 12024 | <!-------------------> |
| | 12025 | <div class=entry> |
| | 12026 | |
| | 12027 | In 3.0.6l, the parser started accepting HIM and HER to select a |
| | 12028 | unique gendered object from a disambiguation query ("which one do you |
| | 12029 | mean..."). This handling has been improved slightly: the parser now |
| | 12030 | treats HIM and HER as <i>narrowing</i> the choices, rather than |
| | 12031 | requiring a unique match. If more than one of the choices matches |
| | 12032 | the pronoun, the parser narrows the choices to the ones that match |
| | 12033 | and asks for disambiguation help again, this time offering the |
| | 12034 | reduced list of choices. |
| | 12035 | |
| | 12036 | </div> |
| | 12037 | |
| | 12038 | <!-------------------> |
| | 12039 | <div class=entry> |
| | 12040 | |
| | 12041 | A bug in turn timing showed up when an implied command used |
| | 12042 | replaceAction(); due to the bug, such a command didn't consume a |
| | 12043 | turn. This showed up, for example, when a travel command (GO NORTH) |
| | 12044 | triggered an OPEN DOOR command, which in turn triggered an UNLOCK |
| | 12045 | DOOR command, which replaced itself via askForIobj() with an UNLOCK |
| | 12046 | DOOR WITH WHAT? command. This has now been corrected. |
| | 12047 | |
| | 12048 | </div> |
| | 12049 | |
| | 12050 | <!-------------------> |
| | 12051 | <div class=entry> |
| | 12052 | |
| | 12053 | In the various places where nested actions are created (nestedAction, |
| | 12054 | nestedActorAction, remapTo, etc), it's now easier to specify literal |
| | 12055 | and topic objects. In the past, it was necessary for the caller to |
| | 12056 | wrap these types of objects in the appropriate internal parser |
| | 12057 | structures, such as a ResolvedTopic. This is no longer necessary: |
| | 12058 | actions that use special wrappers internally will now automatically |
| | 12059 | create the appropriate wrappers for you. |
| | 12060 | |
| | 12061 | <p>In practice, this means that you can simply use a string in any |
| | 12062 | nested action context where a literal is required, and you can use |
| | 12063 | a simple Thing or Topic object in any context where a topic is |
| | 12064 | required. Examples that formerly required special coding, but now |
| | 12065 | work in the obvious fashion: |
| | 12066 | |
| | 12067 | <ul> |
| | 12068 | <li>remapTo(TypeLiteralOn, typewriter, 'hello') |
| | 12069 | <li>nestedAction(AskFor, bob, goldKey); |
| | 12070 | </ul> |
| | 12071 | |
| | 12072 | </div> |
| | 12073 | |
| | 12074 | <!-------------------> |
| | 12075 | <div class=entry> |
| | 12076 | |
| | 12077 | A remapTo() object argument can now be a string, when the new verb |
| | 12078 | accepts a literal in that position. For example, you can use |
| | 12079 | remapTo(TypeLiteralOn, typewriter, 'hello') to remap to the command |
| | 12080 | TYPE "HELLO" ON TYPEWRITER. |
| | 12081 | |
| | 12082 | </div> |
| | 12083 | |
| | 12084 | <!-------------------> |
| | 12085 | <div class=entry> |
| | 12086 | |
| | 12087 | The parser failed to announce a defaulted object under certain obscure |
| | 12088 | circumstances. In particular, if a remapTo() on a two-object action |
| | 12089 | remapped a command, and the source of the remapping was itself chosen |
| | 12090 | as a defaulted object, the announcement was missing. The announcement |
| | 12091 | will now be generated. |
| | 12092 | |
| | 12093 | </div> |
| | 12094 | |
| | 12095 | <!-------------------> |
| | 12096 | <div class=entry> |
| | 12097 | |
| | 12098 | In libMessages, obscuredReadDesc() and dimReadDesc() incorrectly |
| | 12099 | returned a string rather than displaying a message, resulting in no |
| | 12100 | message being displayed when reading a Readable under dim or obscured |
| | 12101 | visual conditions. This has been corrected; these libMessages methods |
| | 12102 | now display their messages directly. |
| | 12103 | |
| | 12104 | </div> |
| | 12105 | |
| | 12106 | <!-------------------> |
| | 12107 | <div class=entry> |
| | 12108 | |
| | 12109 | In the default English messages, the various messages indicating that |
| | 12110 | an actor is in the room and situated in or on a nested room (such as |
| | 12111 | sitting in a chair, or standing on a platform) have been changed |
| | 12112 | slightly. In the past, these said something like "Bob is here, |
| | 12113 | sitting on the chair." Now, the essentially pointless "here" part |
| | 12114 | has been dropped, so the messages read more simply: "Bob is sitting |
| | 12115 | on the chair." |
| | 12116 | |
| | 12117 | </div> |
| | 12118 | |
| | 12119 | <!-------------------> |
| | 12120 | <div class=entry> |
| | 12121 | |
| | 12122 | The English library message for attempting to take an UntakeableActor |
| | 12123 | referred to the wrong object (the actor instead of the direct object) |
| | 12124 | in one of its clauses. The message has been corrected. |
| | 12125 | |
| | 12126 | </div> |
| | 12127 | |
| | 12128 | <!-------------------> |
| | 12129 | <div class=entry> |
| | 12130 | |
| | 12131 | The English library message listing the newly revealed objects after |
| | 12132 | opening an Openable now uses specialized phrasing when an NPC performs |
| | 12133 | the action: "Bob opens the box, revealing..." The PC version hasn't |
| | 12134 | changed: "Opening the box reveals..." |
| | 12135 | |
| | 12136 | </div> |
| | 12137 | |
| | 12138 | <!-------------------> |
| | 12139 | <div class=entry> |
| | 12140 | |
| | 12141 | The English library's default message for attempting to ask oneself |
| | 12142 | for something (ASK ME FOR...) incorrectly referred to the |
| | 12143 | substitution parameter "{iobj}" (which isn't available with an ASK |
| | 12144 | FOR command, because the second noun phrase is actually a topic |
| | 12145 | phrase). This has been corrected. |
| | 12146 | |
| | 12147 | </div> |
| | 12148 | |
| | 12149 | <!-------------------> |
| | 12150 | <div class=entry> |
| | 12151 | |
| | 12152 | The English version of the INSTRUCTIONS command now automatically |
| | 12153 | senses the presence of certain optional conversation features and |
| | 12154 | mentions the corresponding commands only if they're used in the |
| | 12155 | game. In particular, the TOPICS command will be mentioned only |
| | 12156 | if there are SuggestedTopic instances in the game; the existence |
| | 12157 | of special topics will be mentioned on if there are SpecialTopic |
| | 12158 | instances; and the TALK TO command will be mentioned only if |
| | 12159 | there are InConversationState instances. This reduces the manual |
| | 12160 | work needed to customize the conversation system instructions; |
| | 12161 | if your game uses these features, they'll be mentioned, otherwise |
| | 12162 | they won't. |
| | 12163 | |
| | 12164 | </div> |
| | 12165 | |
| | 12166 | <!-------------------> |
| | 12167 | <div class=entry> |
| | 12168 | |
| | 12169 | A style tag name can now contain digits, as long it starts with an |
| | 12170 | alphabetic character. (In the past, style tag names were only |
| | 12171 | allowed to contain alphabetic characters. This makes style tag |
| | 12172 | naming more consistent with the HTML tag naming rules.) |
| | 12173 | |
| | 12174 | </div> |
| | 12175 | |
| | 12176 | <!-------------------> |
| | 12177 | <div class=entry> |
| | 12178 | |
| | 12179 | The new function overrides(obj, base, prop) makes it easy to test |
| | 12180 | whether or not the given object 'obj' overrides the property 'prop' |
| | 12181 | that 'obj' inherits from base class 'base'. This function returns |
| | 12182 | true if 'obj' derives from 'base' (that is, obj.ofKind(base) returns |
| | 12183 | true), <b>and</b> 'obj' and 'base' get their definitions of 'prop' |
| | 12184 | from different places. |
| | 12185 | |
| | 12186 | <p>In the past, the library tested in a few places to see if a given |
| | 12187 | property or method was inherited from a given library base class. |
| | 12188 | This was <i>almost</i> the same test that overrides() performs, but |
| | 12189 | didn't work properly in cases where a library base class had been |
| | 12190 | modified by a game or library extension; when 'modify' is used to |
| | 12191 | extend a class, the defining class for methods defined in the original |
| | 12192 | (pre-modification) version of the class is the original version, not |
| | 12193 | the new version created by 'modify', which takes on the original name. |
| | 12194 | To allow for 'modify' usage, all of the tests the library used to make |
| | 12195 | along these lines have now been replaced with calls to overrides() |
| | 12196 | instead. |
| | 12197 | |
| | 12198 | </div> |
| | 12199 | |
| | 12200 | <!-------------------> |
| | 12201 | <div class=entry> |
| | 12202 | |
| | 12203 | The SENSE_CACHE conditional compilation has been removed, so the sense |
| | 12204 | caching code is now permanently enabled. This shouldn't affect any |
| | 12205 | existing code, since I'm not aware of anyone who's wanted to use the |
| | 12206 | option to disable the sense cache. |
| | 12207 | |
| | 12208 | <p>(This is simply an internal change to eliminate some unnecessary |
| | 12209 | extra source code that's been disabled for a long time anyway. When |
| | 12210 | the sense-cache mechanism was first introduced, it was made optional, |
| | 12211 | so that any games that had problems with the caching could turn it |
| | 12212 | off. The code has been active by default for a long time now, and I'm |
| | 12213 | not aware of anyone who has found it necessary or desirable to disable |
| | 12214 | it, so there no longer seems to be any value in the added complexity |
| | 12215 | of having both options. Removing the conditional option simplifies |
| | 12216 | the source code by removing the effectively dead code for the option |
| | 12217 | of disabling the sense cache.) |
| | 12218 | |
| | 12219 | </div> |
| | 12220 | |
| | 12221 | <!-------------------> |
| | 12222 | <div class=entry> |
| | 12223 | |
| | 12224 | Due to a bug in the parser, a run-time error occurred in certain cases |
| | 12225 | when the player entered a two-object command that was missing its |
| | 12226 | indirect object, and then answered the parser's prompt for the missing |
| | 12227 | object. This has been corrected. |
| | 12228 | |
| | 12229 | </div> |
| | 12230 | |
| | 12231 | <!-------------------> |
| | 12232 | <div class=entry> |
| | 12233 | |
| | 12234 | The standard library tokenizer now accepts function pointers and |
| | 12235 | anonymous function pointers in the fourth slot (the converter |
| | 12236 | callback) in a token rule. The function is invoked using the same |
| | 12237 | arguments that are used when calling a method of 'self' to convert |
| | 12238 | the token value. |
| | 12239 | |
| | 12240 | </div> |
| | 12241 | |
| | 12242 | <!------------------------------- 3.0.6m ---------------------------------> |
| | 12243 | <div class="sepbar"><a name='306m'></a>3.0.6m</div> |
| | 12244 | <p><b><i>Released November 15, 2003</i></b> |
| | 12245 | <p> |
| | 12246 | |
| | 12247 | <div class=firstentry> |
| | 12248 | |
| | 12249 | <b>Important compatibility-breaking change #1:</b> The 'explicit' |
| | 12250 | parameter has been removed from Thing.lookAround() and |
| | 12251 | Actor.lookAround(), as well as from the internal Thing service |
| | 12252 | methods lookAroundPov(), lookAroundWithin(), and |
| | 12253 | lookAroundWithinSense(). This extra parameter was an historical |
| | 12254 | relic that's no longer used, so it's being removed to simplify the |
| | 12255 | interfaces to these routines. Game code is likely to call |
| | 12256 | lookAround() in a few places, and might even override it, so authors |
| | 12257 | should check their existing game code and remove this parameter from |
| | 12258 | any calls or overrides. |
| | 12259 | |
| | 12260 | </div> |
| | 12261 | |
| | 12262 | <!-------------------> |
| | 12263 | <div class=entry> |
| | 12264 | |
| | 12265 | <b>Important compatibility-breaking change #2:</b> The AltTopic |
| | 12266 | mechanism has been changed slightly. In the past, AltTopics were |
| | 12267 | nested one within another to form a group of alternatives. Now, |
| | 12268 | AltTopics are still nested within their parent TopicEntry, but |
| | 12269 | they're no longer nested within one another; instead, they're |
| | 12270 | simply siblings. So, for old game code like this: |
| | 12271 | |
| | 12272 | <p><pre> |
| | 12273 | <font color=red><b>// OLD WAY!!!</b></font> |
| | 12274 | + TopicEntry @lighthouse "It's very tall..."; |
| | 12275 | ++ AltTopic "Not really..." isActive=(...); |
| | 12276 | +++ AltTopic "Well, maybe..." isActive=(...); |
| | 12277 | ++++ AltTopic "Okay, it is..." isActive=(...); |
| | 12278 | </pre> |
| | 12279 | |
| | 12280 | <p>...you'd now instead write it like this: |
| | 12281 | |
| | 12282 | <p><pre> |
| | 12283 | // the new way |
| | 12284 | + TopicEntry @lighthouse "It's very tall..."; |
| | 12285 | ++ AltTopic "Not really..." isActive=(...); |
| | 12286 | ++ AltTopic "Well, maybe..." isActive=(...); |
| | 12287 | ++ AltTopic "Okay, it is..." isActive=(...); |
| | 12288 | </pre> |
| | 12289 | |
| | 12290 | <p>The only change you need to make is to remove the additional |
| | 12291 | nesting from the second and subsequent AltTopic in each group - simply |
| | 12292 | put all of the AltTopics in a group at the same '+' nesting level. |
| | 12293 | |
| | 12294 | <p>The old nesting scheme had a tendency to get unwieldy whenever a |
| | 12295 | single topic had more than one or two alternatives. The new scheme |
| | 12296 | makes game code a little cleaner when defining large AltTopic lists. |
| | 12297 | |
| | 12298 | </div> |
| | 12299 | |
| | 12300 | <!-------------------> |
| | 12301 | <div class=entry> |
| | 12302 | |
| | 12303 | <b>Possible compatibility-breaking change #3:</b> The getTraveler() |
| | 12304 | methods, in both Actor and BasicLocation, now have an additional |
| | 12305 | parameter giving the connector being traversed. This allows the |
| | 12306 | routine to take into account both the actor and the connector |
| | 12307 | involved in the travel, which can be useful in some cases. |
| | 12308 | |
| | 12309 | <p>For example, you might want to set up a travel connector that |
| | 12310 | leads out of a vehicle, in which case you'd want the actor within the |
| | 12311 | vehicle rather than the vehicle to be the traveler when the connector |
| | 12312 | is traversed. In these cases, you'd override the vehicle's |
| | 12313 | getTraveler() method to check the connector, returning the actor |
| | 12314 | rather than the vehicle when the outbound connector is the one being |
| | 12315 | traversed. |
| | 12316 | |
| | 12317 | <p>In addition, for greater generality, the "actor" argument to |
| | 12318 | BasicLocation.getTraveler() (and subclass overrides) has been renamed |
| | 12319 | to indicate that it now takes a <i>traveler</i> rather than merely an |
| | 12320 | actor. Vehicle.getTraveler() takes advantage of this: it now |
| | 12321 | recursively asks its container for the traveler, passing itself |
| | 12322 | (rather than the traveler within itself) as the proposed traveler. |
| | 12323 | These changes allows for situations where an actor is inside a |
| | 12324 | vehicle that's inside another vehicle, for example. |
| | 12325 | |
| | 12326 | <p>Finally, Vehicle.getTraveler() now makes an additional check |
| | 12327 | before returning itself as the traveler: if the connector allows the |
| | 12328 | traveler within the vehicle to pass (as indicated by the connector's |
| | 12329 | canTravelerPass() method), but the connector doesn't allow the |
| | 12330 | vehicle itself to pass, then getTraveler() simply returns the |
| | 12331 | original traveler rather than trying to make the vehicle travel. |
| | 12332 | This makes it easy to set up an outbound connector from within a |
| | 12333 | vehicle - simply set up the connector's canTravelerPass() to exclude |
| | 12334 | the vehicle itself, and a traveler within the vehicle will |
| | 12335 | automatically leave the vehicle behind on traversing the connector. |
| | 12336 | |
| | 12337 | </div> |
| | 12338 | |
| | 12339 | <!-------------------> |
| | 12340 | <div class=entry> |
| | 12341 | |
| | 12342 | There are a few minor interface changes in the travel mechanism, all |
| | 12343 | of which should be transparent to existing game code. |
| | 12344 | |
| | 12345 | <p>The TravelConnector method connectorBack() now takes a <i>Traveler</i> |
| | 12346 | object rather than an Actor as its first argument. |
| | 12347 | |
| | 12348 | <p>The TravelConnector method fixedSource() now takes a Traveler instead |
| | 12349 | of an Actor as its second argument. |
| | 12350 | |
| | 12351 | <p>The Thing method getTravelConnector() now accepts a nil 'actor' |
| | 12352 | argument. When the actor is nil, it means that the caller is |
| | 12353 | interested in the structure of the map independently of any actor's |
| | 12354 | present ability to perceive that structure. This is useful in some |
| | 12355 | cases, such as auto-mapping, where we want to know what the map is |
| | 12356 | actually like rather than merely what it looks like to a given actor |
| | 12357 | at a given time. |
| | 12358 | |
| | 12359 | <p>The internal handling of the various PushTravel action subclasses |
| | 12360 | now uses only the 'verify' stage of the action handling for the |
| | 12361 | indirect object, when there's an indirect object at all. For |
| | 12362 | example, PUSH BOX THROUGH DOOR only calls the door's |
| | 12363 | dobjFor(GoThrough) 'verify' handler, not any of its other handlers. |
| | 12364 | This change reflects the fact that the action of a push-travel is |
| | 12365 | always carried out by a nested TravelVia with the special |
| | 12366 | PushTraveler object, hence the only need we have for the indirect |
| | 12367 | object handlers at all during the initial PushTravel handling is for |
| | 12368 | disambiguation via the 'verify' routine. The old implementation was |
| | 12369 | problematic when the indirect object remapped decomposed verb, because |
| | 12370 | it incorrectly remapped the entire action before the proper nested |
| | 12371 | action could be invoked. This change corrects the problem, allowing |
| | 12372 | the PushTravel varieties to work correctly for any combination of |
| | 12373 | objects. |
| | 12374 | |
| | 12375 | <p>In the Traveler class, describeDeparture() and describeArrival() |
| | 12376 | now show their messages in a visual sense context for the traveler, if |
| | 12377 | the player character isn't involved in the travel. This ensures that |
| | 12378 | the travel is properly described (or properly <i>not</i> described) in |
| | 12379 | situations where the traveler is visible to the player character but |
| | 12380 | the motivating NPC isn't, or vice versa, such as when an NPC is inside |
| | 12381 | an opaque vehicle. |
| | 12382 | |
| | 12383 | </div> |
| | 12384 | |
| | 12385 | <!-------------------> |
| | 12386 | <div class=entry> |
| | 12387 | |
| | 12388 | The Fixture and Immovable classes are now based on a new common base |
| | 12389 | class, NonPortable. This change is entirely a matter of the |
| | 12390 | library's internal organization, and is entirely transparent to game |
| | 12391 | code - Fixture and Immovable behave exactly like they did before. |
| | 12392 | |
| | 12393 | <p>The new class was introduced for two reasons. First, it |
| | 12394 | consolidates the behavior common to all non-portable objects, |
| | 12395 | eliminating a small amount of redundancy in the former arrangement. |
| | 12396 | Second, and much more importantly, it roots all of library's |
| | 12397 | non-portable object classes in a single base class. This means that |
| | 12398 | code can reliably test an object for unportability by checking |
| | 12399 | obj.ofKind(NonPortable). In the past, it was necessary to write |
| | 12400 | (obj.ofKind(Immovable) || obj.ofKind(Fixture)); not only is that test |
| | 12401 | more cumbersome, but its very form is suggestive of the potential for |
| | 12402 | additional "||" clauses in the future. The new arrangement |
| | 12403 | formalizes in the library a single root class for all unportable |
| | 12404 | objects, ensuring a clean way for the library and library extensions |
| | 12405 | to add any future specialized unportables without breaking existing |
| | 12406 | game code. |
| | 12407 | |
| | 12408 | <p>Note that this change does <b>not</b> break existing game code |
| | 12409 | that uses the "||" test; other than the new common base class, the |
| | 12410 | inheritance structure for Fixture and Immovable and their subclasses |
| | 12411 | has not changed. Even so, it wouldn't be a bad idea to replace any |
| | 12412 | "||" tests in your existing code with the simpler ofKind(NonPortable) |
| | 12413 | test, because this will ensure that your code takes advantage of the |
| | 12414 | insulation from future changes that the new class affords. |
| | 12415 | |
| | 12416 | </div> |
| | 12417 | |
| | 12418 | <!-------------------> |
| | 12419 | <div class=entry> |
| | 12420 | |
| | 12421 | The Fixture class (and by inheritance, its subclass Component) now |
| | 12422 | considers an instance to be owned by a given object if the object is |
| | 12423 | the Fixture's location, or the location is owned by the object. |
| | 12424 | Since a Fixture/Component is a permanent part of its location, |
| | 12425 | it usually is appropriate to consider the component to be owned |
| | 12426 | by anything that owns the location, as well as to consider the |
| | 12427 | component owned by the location itself. |
| | 12428 | |
| | 12429 | </div> |
| | 12430 | |
| | 12431 | <!-------------------> |
| | 12432 | <div class=entry> |
| | 12433 | |
| | 12434 | The new mix-in class Attachable (in extras.t) makes it easier to |
| | 12435 | define objects that can be attached to one another, such as a hose |
| | 12436 | and a faucet, a plug and an electrical outlet, or a rope and a |
| | 12437 | railing. Attachable is meant to be combined (using multiple |
| | 12438 | inheritance) with Thing or a Thing subclass. The class provides a |
| | 12439 | number of methods that you can override to control which objects can |
| | 12440 | be attached to one another, and the special effect of enacting out |
| | 12441 | those attachments. |
| | 12442 | |
| | 12443 | <p>The Attachable class provides default handlers for AttachTo, |
| | 12444 | Detach, DetachFrom, and TakeFrom, but it's relatively easy to define |
| | 12445 | additional, customized action handlers in terms of these default |
| | 12446 | actions using the standard 'remapTo' mechanism. For example, if |
| | 12447 | you were defining a rope, you could define a TieTo action, and then |
| | 12448 | map TieTo to AttachTo in your rope object. |
| | 12449 | |
| | 12450 | <p>The new classes PermanentAttachment and PermanentAttachmentChild |
| | 12451 | are subclasses of Attachable for cases where you describe objects as |
| | 12452 | attached in the story text, but you don't want to allow the objects |
| | 12453 | to be detached from one another. Describing objects as attached |
| | 12454 | tends to invite a player to try to detach them; these classes lets |
| | 12455 | the objects provide customized responses to the player's attempts, |
| | 12456 | without actually allowing the objects to come apart. (These classes |
| | 12457 | aren't intended for mere components; the Component class is adequate |
| | 12458 | for that. PermanentAttachment is for situations such as a ball |
| | 12459 | attached with a string to a paddle, where essentially separate |
| | 12460 | objects are conspicuously attached to one another.) |
| | 12461 | |
| | 12462 | </div> |
| | 12463 | |
| | 12464 | <!-------------------> |
| | 12465 | <div class=entry> |
| | 12466 | |
| | 12467 | The new mix-in class PresentLater makes it easy to set up objects that |
| | 12468 | aren't in the game world initially, but will appear later in response |
| | 12469 | to some event. For example, you might want to create a hidden door |
| | 12470 | that isn't part of the game world until the player casts the DETECT |
| | 12471 | HIDDEN DOORS spell, or you might want to create a pile-of-leaves |
| | 12472 | object that shows up at the foot of a tree after the player shakes the |
| | 12473 | tree. |
| | 12474 | |
| | 12475 | <p>The traditional way of programming these sorts of objects was to |
| | 12476 | create the object with a 'nil' initial location, then use moveInto() |
| | 12477 | to move the object into the game upon the triggering event. |
| | 12478 | PresentLater provides an alternative. To use PresentLater, you set up |
| | 12479 | the object in its eventual location, as though it were going to be |
| | 12480 | there from the start, but you add PresentLater at the start of the |
| | 12481 | object's superclass list. During pre-initialization, the library will |
| | 12482 | remember the object's starting location, and then move the object to |
| | 12483 | 'nil', effectively removing it from the game world. Later, when you |
| | 12484 | want to the object to appear, simply call makePresent() on the object, |
| | 12485 | and it will automatically move to the eventual location that was noted |
| | 12486 | during start-up. |
| | 12487 | |
| | 12488 | <p>The advantage of using PresentLater is that you define the object's |
| | 12489 | eventual location as part of the object itself, as though it were an |
| | 12490 | ordinary object; this means that you don't have to specify its |
| | 12491 | eventual location as part of some method (in a moveInto call) |
| | 12492 | elsewhere in the source code. Another advantage is that you can use |
| | 12493 | the makePresentByKey() method to bring a whole set of related objects |
| | 12494 | into the game world at once: you can give each PresentLater object a |
| | 12495 | "key" property, which is just an arbitrary value you choose to |
| | 12496 | identify a group of objects, and then bring all objects that have that |
| | 12497 | key into the game world at once. |
| | 12498 | |
| | 12499 | </div> |
| | 12500 | |
| | 12501 | <!-------------------> |
| | 12502 | <div class=entry> |
| | 12503 | |
| | 12504 | The new class Unthing represents the <i>absence</i> of an object. This |
| | 12505 | class is useful for the occasional situation where a player is likely to |
| | 12506 | assume that an object is present even though it's not. For example, |
| | 12507 | sometimes an object becomes hidden, but a player might not notice that; |
| | 12508 | rather than letting the regular parser error handle it, we can create |
| | 12509 | an Unthing that explains that the object can no longer be seen. |
| | 12510 | Unthing is a simple subclass of Decoration, with a customized default |
| | 12511 | handling message. |
| | 12512 | |
| | 12513 | </div> |
| | 12514 | |
| | 12515 | <!-------------------> |
| | 12516 | <div class=entry> |
| | 12517 | |
| | 12518 | The travelerDirectlyInRoom precondition object has been replaced with |
| | 12519 | a new TravelerDirectlyInRoom class. This change allows the caller to |
| | 12520 | create the precondition object with the full set of information it |
| | 12521 | needs via the class's constructor. This change is probably |
| | 12522 | transparent to existing game code, as game could would have little |
| | 12523 | reason to use this precondition. |
| | 12524 | |
| | 12525 | </div> |
| | 12526 | |
| | 12527 | <!-------------------> |
| | 12528 | <div class=entry> |
| | 12529 | |
| | 12530 | The class Thing now defines the method checkTravelerDirectlyInRoom(); |
| | 12531 | the default implementation simply defers to the container. This |
| | 12532 | ensures that connectors that are defined inside ordinary objects (for |
| | 12533 | example, a hole in a bookcase) will properly ensure that a traveler is |
| | 12534 | in the Thing's containing Room or NestedRoom before travel. In the |
| | 12535 | past, the absence of this method meant that there were no conditions |
| | 12536 | at all on a traveler's initial location in such cases. |
| | 12537 | |
| | 12538 | </div> |
| | 12539 | |
| | 12540 | <!-------------------> |
| | 12541 | <div class=entry> |
| | 12542 | |
| | 12543 | The dropDestinationIsOutRoom precondition now moves the actor, |
| | 12544 | rather than the traveler (to the extent that they differ), to the |
| | 12545 | outer room when needed. (Since the actor is attempting to reach the |
| | 12546 | outer room in these cases, it makes more sense to move the actor, |
| | 12547 | rather than any vehicle the actor is inside.) |
| | 12548 | |
| | 12549 | <p>Similarly, the Floor object's SitOn and LieOn handlers now apply a |
| | 12550 | precondition requiring the actor, rather than the traveler, to be in |
| | 12551 | the room directly containing the Floor object. |
| | 12552 | |
| | 12553 | </div> |
| | 12554 | |
| | 12555 | <!-------------------> |
| | 12556 | <div class=entry> |
| | 12557 | |
| | 12558 | The new VocabObject method getFacets() returns a list of "facets" |
| | 12559 | of an object. These are other objects that share the same parsing |
| | 12560 | identity; for example, the two sides of a door are facets of the |
| | 12561 | same physical object, from a character's perspective, so each side |
| | 12562 | would return a list containing the other side from getFacets(). |
| | 12563 | In fact, the Door class overrides getFacets() to do just this. |
| | 12564 | |
| | 12565 | <p>The parser uses getFacets() to resolve an out-of-scope pronoun |
| | 12566 | antecedent, if possible. If the player uses a pronoun, and the |
| | 12567 | antecedent is out of scope, the parser calls the antecedent's |
| | 12568 | getFacets() method, and looks for a facet that's in scope; if it |
| | 12569 | finds an in-scope facet, the parser uses that facet as the |
| | 12570 | replacement antecedent. For example, if you type OPEN DOOR, GO |
| | 12571 | THROUGH IT, THEN CLOSE IT, the parser will now correctly resolve the |
| | 12572 | second "it" to the door. In the past, the second "it" wasn't |
| | 12573 | resolvable, because it referred to the side of the door that's in the |
| | 12574 | other room and thus out of scope after the travel. Using the new |
| | 12575 | facet list capability, the parser can now resolve the second "it" |
| | 12576 | to the side of the door that is in scope. |
| | 12577 | |
| | 12578 | <p>(If more than one new facet of the object is in scope in these |
| | 12579 | cases, the pronoun resolver will take the one that's most readily |
| | 12580 | visible - that is, the one that has the most "transparent" sense path |
| | 12581 | in the actor's visual senses. If all of the in-scope facets are |
| | 12582 | equally visible, the resolver just picks one arbitrarily.) |
| | 12583 | |
| | 12584 | <p>By default, VocabObject.getFacets() simply returns an empty list. |
| | 12585 | The Door and Passage classes override the method to return a list |
| | 12586 | containing the linked object representing the other side of the door |
| | 12587 | or passage, if there is one. The new MultiFaceted object returns the |
| | 12588 | list of facet objects that it synthesizes; each facet instance of |
| | 12589 | a MultiFaceted does the same thing. |
| | 12590 | |
| | 12591 | <p>You can customize getFacets() whenever you use multiple objects |
| | 12592 | with a shared parser identity. One common case where you might want |
| | 12593 | to do this is "object transmutation," where you substitute one object |
| | 12594 | for another in order to effect a radical change in the setting. For |
| | 12595 | example, you might have one object representing a wooden dining |
| | 12596 | table, and another representing the pile of splintered wood that an |
| | 12597 | enraged chef turns it into after the guests insult his cooking. In |
| | 12598 | this case, you could override getFacets() in the table so that it |
| | 12599 | returns the pile-of-splintered-wood object. |
| | 12600 | |
| | 12601 | </div> |
| | 12602 | |
| | 12603 | <!-------------------> |
| | 12604 | <div class=entry> |
| | 12605 | |
| | 12606 | The class AutoMultiLoc has been removed, and its capabilities have |
| | 12607 | been rolled directly into the MultiLoc class itself. All of the |
| | 12608 | initialization properties and methods (initialLocationClass, |
| | 12609 | isInitiallyIn, and buildLocationList) have been moved into MultiLoc, |
| | 12610 | and they work the same as they used to. There really wasn't any need |
| | 12611 | for a separate AutoMultiLoc class, since the two styles of |
| | 12612 | initialization (enumerated and rule-based) can coexist quite easily in |
| | 12613 | the single class. |
| | 12614 | |
| | 12615 | <p>Along the same lines, the DynamicMultiLoc class has been removed, |
| | 12616 | and its functionality has been rolled into MultiLoc. In particular, |
| | 12617 | the reInitializeLocation() method is now part of the base MultiLoc |
| | 12618 | class. |
| | 12619 | |
| | 12620 | <p>If you have any AutoMultiLoc or DynamicMultiLoc objects in your |
| | 12621 | existing game code, you should simply change the AutoMultiLoc or |
| | 12622 | DynamicMultiLoc superclass to MultiLoc. The objects should then |
| | 12623 | behave the same as they did before. |
| | 12624 | |
| | 12625 | </div> |
| | 12626 | |
| | 12627 | <!-------------------> |
| | 12628 | <div class=entry> |
| | 12629 | |
| | 12630 | MultiLoc.moveOutOf() caused a run-time error due to a mismatched |
| | 12631 | call to notifyRemove(). This is now fixed. |
| | 12632 | |
| | 12633 | </div> |
| | 12634 | |
| | 12635 | <!-------------------> |
| | 12636 | <div class=entry> |
| | 12637 | |
| | 12638 | The new classes MultiInstance and MultiFaceted are useful for cases |
| | 12639 | where you want to create an object in multiple locations, but |
| | 12640 | MultiLoc isn't suitable. A MultiLoc is suitable when a single object |
| | 12641 | is contained <i>entirely</i> and <i>simultaneously</i> in more than |
| | 12642 | one location; when a single large object spans several locations, or |
| | 12643 | when you simply want to duplicate a ubiquitous background object in |
| | 12644 | several places, the new classes are better. |
| | 12645 | |
| | 12646 | <p>MultiInstance is good when you want to duplicate a ubiquitous |
| | 12647 | background object in multiple locations: trees in a forest, the sun |
| | 12648 | in outdoor locations, crowds in the street. MultiFaceted is for |
| | 12649 | large objects that span many locations, such as rivers or long ropes. |
| | 12650 | MultiLoc isn't ideal for these sorts of cases because the sense |
| | 12651 | system treats a MultiLoc as a single object that's entirely in all of |
| | 12652 | its locations at once; this means, for example, that if it's lit in |
| | 12653 | one place, it's lit everyplace. |
| | 12654 | |
| | 12655 | <p>MultiInstance and MultiFaceted work mostly like MultiLoc from the |
| | 12656 | programming perspective. Internally, though, rather than appearing |
| | 12657 | itself in each of its locations, a MultiInstance or MultiFaceted |
| | 12658 | creates a separate "instance" object for each of its locations. Each |
| | 12659 | instance is an ordinary singly-located object, so the library creates |
| | 12660 | one per location. The instance objects are instances of a template |
| | 12661 | that you define as part of the MultiInstance or MultiFaceted object. |
| | 12662 | |
| | 12663 | <p>The new classes present the MultiLoc multi-location interface, so |
| | 12664 | you can add and subtract locations as needed, using the usual |
| | 12665 | routines: moveInto(), moveIntoAdd(), moveOutOf(). You can also set |
| | 12666 | the initial set of locations as you would for a MultiLoc: you can set |
| | 12667 | locationList to the list of initial locations, or you can define |
| | 12668 | initialLocationClass, isInitiallyIn, and/or buildLocationList. |
| | 12669 | |
| | 12670 | <p>The instances of a MultiInstance or MultiFaceted are all |
| | 12671 | essentially identical, so these classes are only good for relatively |
| | 12672 | homogeneous objects. These classes aren't appropriate for cases |
| | 12673 | where you want to present distinctive aspects of an object, such as |
| | 12674 | the different sides of a large building, or distinctive individual |
| | 12675 | objects, such as different people in a crowd. When the individual |
| | 12676 | parts are distinct, you're best off just creating separate objects |
| | 12677 | for the different instances. The new classes are mainly for |
| | 12678 | convenience in cases where you'd otherwise have to repeat an |
| | 12679 | identical object definition in several locations. |
| | 12680 | |
| | 12681 | </div> |
| | 12682 | |
| | 12683 | <!-------------------> |
| | 12684 | <div class=entry> |
| | 12685 | |
| | 12686 | The new pre-conditions dobjTouchObj and iobjTouchObj can be applied |
| | 12687 | to the indirect or direct object (respectively) of a two-object |
| | 12688 | action, to require that the one object can touch the other. This is |
| | 12689 | useful for actions where the actor manipulates one of the objects |
| | 12690 | directly, but manipulates the other object only indirectly using |
| | 12691 | the first object. |
| | 12692 | |
| | 12693 | <p>For example, PUSH COIN WITH STICK would be a good |
| | 12694 | place to use iobjTouchObj as a direct object precondition: the |
| | 12695 | actor is manipulating the stick directly, so the actor has to be |
| | 12696 | able to touch the stick, but the coin only needs to be reachable |
| | 12697 | indirectly with the stick. Another example: PLUG CORD INTO OUTLET |
| | 12698 | requires direct manipulation of the cord, but only the cord needs |
| | 12699 | to touch the outlet, so this would be a good case for dobjTouchObj |
| | 12700 | as a precondition on the indirect object. |
| | 12701 | |
| | 12702 | <p>In the class Thing, the default direct object handlers for the |
| | 12703 | actions MoveWith, TurnWith, ScrewWith, and UnscrewWith now use the |
| | 12704 | iobjTouchObj condition rather than touchObj condition. These verbs |
| | 12705 | all generally model interactions where the direct object only needs |
| | 12706 | to be reachable through the indirect object. The new class Attachable |
| | 12707 | uses dobjTouchObj as a precondition on the indirect object. |
| | 12708 | |
| | 12709 | <p>To enable the new iobjTouchObj condition, the TouchObjCondition |
| | 12710 | class can now handle a yet-unresolved source object during the |
| | 12711 | verification stage. When the source object is nil, the pre-condition |
| | 12712 | simply skips its verification stage. This allows a TouchObjCondition |
| | 12713 | to be applied across objects for a two-object action: for example, it |
| | 12714 | allows you to apply a condition to the direct object that the indirect |
| | 12715 | object can touch it. |
| | 12716 | |
| | 12717 | </div> |
| | 12718 | |
| | 12719 | <!-------------------> |
| | 12720 | <div class=entry> |
| | 12721 | |
| | 12722 | The new preconditions sameLocationAsIobj and sameLocationAsDobj let |
| | 12723 | you require that a given object is in the same immediate location as |
| | 12724 | the other object of a two-object command. You use sameLocationAsIobj |
| | 12725 | as a precondition on a direct object, and sameLocationAsDobj as a |
| | 12726 | precondition on an indirect object. Both of these condition objects |
| | 12727 | are based on the class SameLocationCondition, which you can construct |
| | 12728 | dynamically to require the target object to be in the same location as |
| | 12729 | an arbitrary second object, which need not be directly involved in the |
| | 12730 | command. |
| | 12731 | |
| | 12732 | <p>These conditions use the new Thing method tryMovingObjInto(obj), |
| | 12733 | which tries to move the given object 'obj' into 'self'. This method |
| | 12734 | is customized in Room, Container, Surface, and Actor to generate |
| | 12735 | appropriate implied commands for those classes, and you can override |
| | 12736 | it in your own objects as needed. |
| | 12737 | |
| | 12738 | </div> |
| | 12739 | |
| | 12740 | <!-------------------> |
| | 12741 | <div class=entry> |
| | 12742 | |
| | 12743 | The new Actor method endConversation() effectively lets an NPC say |
| | 12744 | GOODBYE of its own volition, ending a conversation without waiting |
| | 12745 | for the player to leave or say GOODBYE. This is the complement of |
| | 12746 | Actor.initiateConversation: it lets an NPC initiate the end of a |
| | 12747 | conversation. |
| | 12748 | |
| | 12749 | <p>The new conversation-ending code endConvActor indicates that we're |
| | 12750 | ending the conversation of the actor's volition. |
| | 12751 | |
| | 12752 | </div> |
| | 12753 | |
| | 12754 | <!-------------------> |
| | 12755 | <div class=entry> |
| | 12756 | |
| | 12757 | The new ConvNode method noteLeaving() is called when the conversation |
| | 12758 | node is about to become inactive. This is the complement of |
| | 12759 | noteActive(). This method doesn't do anything by default, but |
| | 12760 | instances can use it to trigger side effects when leaving the node. |
| | 12761 | |
| | 12762 | </div> |
| | 12763 | |
| | 12764 | <!-------------------> |
| | 12765 | <div class=entry> |
| | 12766 | |
| | 12767 | The conversation manager's mechanism that keeps track of conversation |
| | 12768 | responses has been changed to make it better able to handle multiple |
| | 12769 | conversations on a single turn. In particular, the conversation manager |
| | 12770 | now flags the start and end of each response text in the text stream. |
| | 12771 | Because the "transcript" subsystem captures displayed text |
| | 12772 | and defers its actual output until later, difficult synchronization |
| | 12773 | problems arose if a game tried to trigger multiple responses from |
| | 12774 | different actors on a single turn. This change should be transparent |
| | 12775 | to existing game code. |
| | 12776 | |
| | 12777 | </div> |
| | 12778 | |
| | 12779 | <!-------------------> |
| | 12780 | <div class=entry> |
| | 12781 | |
| | 12782 | TopicEntry has a new method, setTopicPronoun(), that tries to set a |
| | 12783 | pronoun antecedent when the topic is matched. The default |
| | 12784 | handleTopic() method automatically calls the new method. |
| | 12785 | |
| | 12786 | <p>It's not always possible for setTopicPronoun() to guess about an |
| | 12787 | antecedent for a topic phrase match, because TopicEntry instances can |
| | 12788 | match more than one game object, and topic phrases by their nature can |
| | 12789 | refer to more objects than are present visually. The new method will |
| | 12790 | set a pronoun antecedent for the topic if the topic phrase in the |
| | 12791 | player's input yields one object when "intersected" with the |
| | 12792 | TopicEntry's 'matchObj' list. The method first looks only at in-scope |
| | 12793 | objects, then looks to the "likely" list, but only if there are no |
| | 12794 | in-scope matches. If the intersection yields more than one object, |
| | 12795 | the library doesn't set a pronoun antecedent at all, since the match |
| | 12796 | is ambiguous. |
| | 12797 | |
| | 12798 | <p>Since this heuristic procedure can't always decide on an |
| | 12799 | antecedent, you might occasionally want to set the antecedent |
| | 12800 | explicitly in a particular TopicEntry. You can do this by overriding |
| | 12801 | the TopicEntry instance's setTopicPronoun(fromActor,topic), in which |
| | 12802 | you'd call fromActor.setPronounObj(obj), where 'obj' is the game |
| | 12803 | object you want to set as the antecedent. |
| | 12804 | |
| | 12805 | </div> |
| | 12806 | |
| | 12807 | <!-------------------> |
| | 12808 | <div class=entry> |
| | 12809 | |
| | 12810 | In the past, when an "again" command was used to repeat a command |
| | 12811 | directed to a non-player character ("bob, go east"), the turn counter |
| | 12812 | incorrectly advanced by two turns. This was due to an error in the |
| | 12813 | mechanism that allows one actor to wait for another to finish a |
| | 12814 | command. This is now fixed. |
| | 12815 | |
| | 12816 | <p>A separate problem prevented an undo savepoint from being created |
| | 12817 | for an "again" command repeated a command directed to another |
| | 12818 | character. Since no savepoint was created, typing "undo" after such |
| | 12819 | an "again" command took back not only the "again" turn but the turn |
| | 12820 | before it as well. The savepoint is now created properly. |
| | 12821 | |
| | 12822 | </div> |
| | 12823 | |
| | 12824 | <!-------------------> |
| | 12825 | <div class=entry> |
| | 12826 | |
| | 12827 | Due to a bug, the conversation mechanism didn't enter a conversation |
| | 12828 | (i.e., didn't show the "greeting protocol") if a DefaultTopicEntry was |
| | 12829 | used for a response. This has been fixed. |
| | 12830 | |
| | 12831 | <p>As part of this change, the ActorTopicEntry class, which was |
| | 12832 | introduced in the refactoring of the TopicEntry class introduced in |
| | 12833 | 3.0.6l, has been eliminated. On further consideration, the |
| | 12834 | bifurcation of TopicEntry into actor-associated and |
| | 12835 | non-actor-associated subtypes wasn't very clean, since it implied a |
| | 12836 | similar split for some of the other classes that work with TopicEntry, |
| | 12837 | notably AltTopic and DefaultTopic. This was too unwieldy. |
| | 12838 | |
| | 12839 | <p>So, ActorTopicEntry has been removed. In its place, the "topic |
| | 12840 | owner" abstraction, which was introduced in 3.0.6l, has been used |
| | 12841 | throughout the base TopicEntry class to replace the need for an |
| | 12842 | associated actor. This means that the base TopicEntry can do |
| | 12843 | everything that it did before (and everything that ActorTopicEntry did |
| | 12844 | before), but without any assumption that there's an associated actor. |
| | 12845 | The getActor() method is still present, but it's now strictly for the |
| | 12846 | convenience of game code; the library no longer assumes that topic |
| | 12847 | entries to be associated with actors. The TopicEntry.getActor() |
| | 12848 | method simply returns the topic owner if it's of class Actor, |
| | 12849 | otherwise nil. |
| | 12850 | |
| | 12851 | <p>These changes should have no impact on existing game code, since |
| | 12852 | the ActorTopicEntry was intended as an internal class structure only. |
| | 12853 | |
| | 12854 | </div> |
| | 12855 | |
| | 12856 | <!-------------------> |
| | 12857 | <div class=entry> |
| | 12858 | |
| | 12859 | A bug in the TopicResolver class caused a run-time error for |
| | 12860 | a command like ASK <i>someone</i> ABOUT ALL. This is now fixed. |
| | 12861 | |
| | 12862 | </div> |
| | 12863 | |
| | 12864 | <!-------------------> |
| | 12865 | <div class=entry> |
| | 12866 | |
| | 12867 | When the ConsultAbout action picks a default consultable object based |
| | 12868 | on the actor's last ConsultAbout command, the action now marks the |
| | 12869 | defaulted object as such, which triggers the usual announcement of |
| | 12870 | the default object. |
| | 12871 | |
| | 12872 | </div> |
| | 12873 | |
| | 12874 | <!-------------------> |
| | 12875 | <div class=entry> |
| | 12876 | |
| | 12877 | The typographicalOutputFilter object (in en_us.t) is now a little |
| | 12878 | smarter about what it considers sentence-ending punctuation. If a |
| | 12879 | lower-case letter or a hyphen of some kind follows what the filter |
| | 12880 | would otherwise take for sentence-ending punctuation, it doesn't treat |
| | 12881 | it as a sentence ending. This gives better results in the common case |
| | 12882 | of an exclamation point or question mark within a quoted passage: |
| | 12883 | "'Who are you?' he asked." It also helps in some less common |
| | 12884 | cases, such as when an exclamation point is embedded in a sentence, |
| | 12885 | such as in an interjection set off by dashes ("And then -- oh no! -- |
| | 12886 | I dropped it"). |
| | 12887 | |
| | 12888 | </div> |
| | 12889 | |
| | 12890 | <!-------------------> |
| | 12891 | <div class=entry> |
| | 12892 | |
| | 12893 | The PendingCommandInfo class has been refactored into a couple of |
| | 12894 | subclasses for a cleaner class structure. PendingCommandInfo is now |
| | 12895 | an abstract base class; the new concrete subclasses |
| | 12896 | PendingCommandToks, PendingCommandAction, and PendingCommandMarker now |
| | 12897 | implement the specialized behavior that was formerly embedded in the |
| | 12898 | single class and handled conditionally. These classes are mostly for |
| | 12899 | internal use in the library, so this should have no impact on any |
| | 12900 | existing game code. |
| | 12901 | |
| | 12902 | </div> |
| | 12903 | |
| | 12904 | <!-------------------> |
| | 12905 | <div class=entry> |
| | 12906 | |
| | 12907 | Some messages in BasicContainer have been modified slightly to remove |
| | 12908 | the assumption from the base class that it's an object that can be |
| | 12909 | opened. First, the new properties cannotTouchThroughMsg and |
| | 12910 | cannotMoveThroughMsg give property pointers, referring to |
| | 12911 | playerActionMessages properties, that specify the messages to use |
| | 12912 | when an object cannot be reached or moved through the container's |
| | 12913 | containment boundary. By default, these now refer to the new messages |
| | 12914 | cannotTouchThroughContainer and cannotMoveThroughContainer, which don't |
| | 12915 | say anything about the container being closed. Second, BasicOpenable |
| | 12916 | class overrides these two new properties to refer to the original |
| | 12917 | cannotTouchThroughClosed and cannotMoveThroughClosed messages. |
| | 12918 | Third, the tryImplicitRemoveObstructor() method that was formerly |
| | 12919 | in BasicContainer has been moved to BasicOpenable instead, eliminating |
| | 12920 | the assumption in BasicContainer that the obstruction can be removed |
| | 12921 | by opening the container. |
| | 12922 | |
| | 12923 | <p>Note that these changes are designed in such a way that objects |
| | 12924 | based on both Openable and Container (either by mixing the two |
| | 12925 | superclasses, or by using the library class OpenableContainer) should |
| | 12926 | be unaffected. Objects based on Container or BasicContainer, without |
| | 12927 | any Openable mix-in, should now behave more logically, in that they |
| | 12928 | won't assume anything about being openable. |
| | 12929 | |
| | 12930 | </div> |
| | 12931 | |
| | 12932 | <!-------------------> |
| | 12933 | <div class=entry> |
| | 12934 | |
| | 12935 | The touchObj precondition incorrectly reported two failure messages |
| | 12936 | if an implied command failed trying to remove an obstruction to touch. |
| | 12937 | The failure message of the implied command itself was shown, and a |
| | 12938 | separate failure message explaining that the target object isn't |
| | 12939 | reachable was also shown; in such cases, only the implied command |
| | 12940 | failure should have been reported. The precondition now omits the |
| | 12941 | redundant second message. |
| | 12942 | |
| | 12943 | </div> |
| | 12944 | |
| | 12945 | <!-------------------> |
| | 12946 | <div class=entry> |
| | 12947 | |
| | 12948 | KeyedLockable is now more flexible about the "known key list" and who |
| | 12949 | owns it. In the past, the "master object" of a linked lockable (the |
| | 12950 | master object of a two-sided door, for example) always owned the known |
| | 12951 | key list; this made it impossible to have separate keys operate the |
| | 12952 | two sides of a door, and also created a dependency on which side of |
| | 12953 | the door was the master. Now, KeyedLockable instead uses the local |
| | 12954 | side's known key list if it has one, and only uses the master side's |
| | 12955 | list if either the local side has an empty list or the master side has |
| | 12956 | no list; only if the local side has an empty list, and the master side |
| | 12957 | has a list, is the master side used. This makes initialization of |
| | 12958 | two-sided doors much more flexible, because it no longer matters which |
| | 12959 | side is the master for the purposes of the known key list. |
| | 12960 | |
| | 12961 | </div> |
| | 12962 | |
| | 12963 | <!-------------------> |
| | 12964 | <div class=entry> |
| | 12965 | |
| | 12966 | In 3.0.6j, we introduced the notion of whether or not the status of a |
| | 12967 | Lockable is known. The idea was that actors shouldn't just |
| | 12968 | automatically unlock a door on trying to open it unless they have |
| | 12969 | some reason to know the door is locked in the first place. |
| | 12970 | Unfortunately, this mechanism took away the important playability |
| | 12971 | convenience feature that automatically unlocks locked doors when it's |
| | 12972 | obvious how to do so. |
| | 12973 | |
| | 12974 | <p>This mechanism is now replaced with something a little more |
| | 12975 | subtle, which solves the same problem without any loss of convenience |
| | 12976 | for the player. Instead of letting the original OPEN command fail on |
| | 12977 | encountering a door that's locked but not previously known to be |
| | 12978 | locked, the library now inserts a "testing" action into the sequence |
| | 12979 | ahead of the implied UNLOCK. The "testing" action represents the |
| | 12980 | actor's first attempt to open the lockable, as in attempting to turn |
| | 12981 | a locked doorknob. This first phase fails, but instead of letting |
| | 12982 | the rest of the command fail, we consider the actor to have |
| | 12983 | <b>immediately</b> learned from the first phase that the object is |
| | 12984 | locked, so we proceed directly to an implied UNLOCK action. The |
| | 12985 | result looks like this: |
| | 12986 | |
| | 12987 | <p><pre> |
| | 12988 | >go north |
| | 12989 | (first trying the door and finding it locked, unlocking it, then |
| | 12990 | opening it) |
| | 12991 | </pre> |
| | 12992 | |
| | 12993 | <p>Note that the lockStatusObvious property of the former scheme |
| | 12994 | still applies. If lockStatusObvious is true, then the extra |
| | 12995 | "testing" phase is omitted, since we can tell just looking at the |
| | 12996 | object that it's locked. Note also that the "testing" phase is |
| | 12997 | only used when the object is actually locked; when it's not locked, |
| | 12998 | the OPEN command succeeds, so there's no need to split the OPEN |
| | 12999 | action into the two phases. |
| | 13000 | |
| | 13001 | </div> |
| | 13002 | |
| | 13003 | <!-------------------> |
| | 13004 | <div class=entry> |
| | 13005 | |
| | 13006 | The Door class now uses a custom cannotTravel() message, rather than |
| | 13007 | using the default message for the location. The message explains that |
| | 13008 | the travel is not possible because the door is closed; the generic |
| | 13009 | cannot-travel message for a room simply claims that the travel is |
| | 13010 | impossible, which isn't as specific as we can be about it. |
| | 13011 | |
| | 13012 | </div> |
| | 13013 | |
| | 13014 | <!-------------------> |
| | 13015 | <div class=entry> |
| | 13016 | |
| | 13017 | The Openable class has a new method, openStatus, that makes it easier |
| | 13018 | to override the open/closed status addendum that's shown as part of |
| | 13019 | the object's description. The openableContentsLister now calls this |
| | 13020 | method to show the status; the default implementation just says "it's |
| | 13021 | open" (or equivalent, adjusted for gender and number). An Openable |
| | 13022 | can override this to customize the message as needed. |
| | 13023 | |
| | 13024 | </div> |
| | 13025 | |
| | 13026 | <!-------------------> |
| | 13027 | <div class=entry> |
| | 13028 | |
| | 13029 | The Passage class's initialization of a two-sided relationship has |
| | 13030 | been refined slightly. In the past, the non-master side of a |
| | 13031 | two-sided passage explicitly set its master object's otherSide |
| | 13032 | property to point to the non-master side. Now, instead of setting |
| | 13033 | the property directly, the non-master side calls the master object's |
| | 13034 | initMasterObject() method with the non-master side as the parameter; |
| | 13035 | by default, initMasterObject() simply sets 'otherSide' to the other |
| | 13036 | object. This makes it easier to customize the initialization for |
| | 13037 | cases where more than two objects are involved in a passage |
| | 13038 | relationship, or where the passage relationship is dynamic, by |
| | 13039 | allowing the master object to directly control its own initialization. |
| | 13040 | |
| | 13041 | </div> |
| | 13042 | |
| | 13043 | <!-------------------> |
| | 13044 | <div class=entry> |
| | 13045 | |
| | 13046 | In the Candle class, when the object runs out of fuel, it now displays |
| | 13047 | its "burned out" message <i>before</i> actually cutting off its light |
| | 13048 | source (by marking itself as unlit). In the past, the order of these |
| | 13049 | operations was reversed, which caused the library to suppress the |
| | 13050 | "burned out" message when the candle was the only light source. The |
| | 13051 | message was suppressed because these operations are performed in a |
| | 13052 | daemon that runs in the "sight" sense context of the candle itself; |
| | 13053 | once the candle is marked as unlit, it becomes invisible when there's |
| | 13054 | no other light source, and so any message displayed in its sight |
| | 13055 | context is suppressed. By showing the message while the candle is |
| | 13056 | still marked as lit, we ensure that the message will be seen as long |
| | 13057 | as the candle is in view of the player character. |
| | 13058 | |
| | 13059 | </div> |
| | 13060 | |
| | 13061 | <!-------------------> |
| | 13062 | <div class=entry> |
| | 13063 | |
| | 13064 | The Readable class now generates its "obscured" and "dim" default |
| | 13065 | descriptions properly. A bug formerly caused a run-time error when |
| | 13066 | attempting to read a Readable under these sense conditions. |
| | 13067 | |
| | 13068 | </div> |
| | 13069 | |
| | 13070 | <!-------------------> |
| | 13071 | <div class=entry> |
| | 13072 | |
| | 13073 | The menu system now includes an automatic sorting mechanism, |
| | 13074 | which sorts a menu's entries into a game-defined order each time the |
| | 13075 | menu is displayed. The default initializeContents() method in the |
| | 13076 | MenuObject class does the sorting, based on the new 'menuOrder' |
| | 13077 | properties of the items in the menu. The 'menuOrder' property is |
| | 13078 | an integer value giving the relative order of an item among its |
| | 13079 | siblings. By default, 'menuOrder' returns the 'sourceTextOrder' |
| | 13080 | value for the menu item, so the default ordering is simply the |
| | 13081 | original ordering of the items in the source file. |
| | 13082 | |
| | 13083 | </div> |
| | 13084 | |
| | 13085 | <!-------------------> |
| | 13086 | <div class=entry> |
| | 13087 | |
| | 13088 | In the English module, the new property isQualifiedName generalizes |
| | 13089 | the function of the existing isProperName property. isProperName |
| | 13090 | indicates that a 'name' property is "proper," meaning it's the name |
| | 13091 | of a person or place - the kind of noun that's usually capitalized in |
| | 13092 | English. Proper names don't require "qualification" when they appear |
| | 13093 | in sentences, which basically means that they don't need articles |
| | 13094 | like "the" or "a", because they're inherently definite. The new |
| | 13095 | isQualifiedName property can be set to true for an object when the |
| | 13096 | name is fully qualified, but isn't proper. By default, a proper name |
| | 13097 | is considered qualified, but the two properties can be set |
| | 13098 | independently as needed. |
| | 13099 | |
| | 13100 | <p>An example of a non-proper but qualified name is "your book." |
| | 13101 | This isn't the proper name of the book, but the possessive pronoun |
| | 13102 | makes it fully qualified, making it incorrect to add an article when |
| | 13103 | using the name in a sentence. |
| | 13104 | |
| | 13105 | <p>In practice, at the moment, "qualified" and "definite" have the |
| | 13106 | same effect, which is to omit any articles when the name is used in a |
| | 13107 | sentence. The new property is intended to separate the two concepts |
| | 13108 | in case there's a need to distinguish them in the game or in future |
| | 13109 | library changes. |
| | 13110 | |
| | 13111 | </div> |
| | 13112 | |
| | 13113 | <!-------------------> |
| | 13114 | <div class=entry> |
| | 13115 | |
| | 13116 | The English parser has a new bit of fine-tuning in its verb phrase |
| | 13117 | chooser for a particular type of ambiguous phrasing. In certain |
| | 13118 | sentences in English, a preposition can be interpreted either as part |
| | 13119 | of a noun phrase or as a structural part of the verb; for example, |
| | 13120 | DETACH STRING FROM BOX could be interpreted either as a verb with two |
| | 13121 | objects (STRING as the direct object, BOX as the indirect object), or |
| | 13122 | as a verb with a single object (STRING FROM BOX as the direct |
| | 13123 | object). English speakers will almost always assume the two-object |
| | 13124 | interpretation automatically in cases like this; English is such a |
| | 13125 | strongly positional language that the verb phrase structure tends to |
| | 13126 | dominate everything else in a sentence. In the past, the parser |
| | 13127 | didn't care one way or the other, so when both interpretations were |
| | 13128 | valid, the parser sometimes arbitrarily chose the much less probable |
| | 13129 | single-object version. The parser now takes the verb structure |
| | 13130 | dominance into account by preferring the intepretation with more |
| | 13131 | "noun slots" in the verb phrase, whenever there's ambiguity. |
| | 13132 | |
| | 13133 | </div> |
| | 13134 | |
| | 13135 | <!-------------------> |
| | 13136 | <div class=entry> |
| | 13137 | |
| | 13138 | The English parser's tokenizer now treats ampersands essentially as |
| | 13139 | though they were alphabetic characters for the various kinds of |
| | 13140 | "word" tokens. Ampersands have no other meaning to the standard |
| | 13141 | parser, and show up every so often in names of things, so it makes |
| | 13142 | sense for the parser to accept them as parts of words. |
| | 13143 | |
| | 13144 | <p>Note that an ampersand is treated as alphabetic, not as a |
| | 13145 | punctuation mark. This has two implications that might be |
| | 13146 | counterintuitive, at least to the extent that ampersands look to most |
| | 13147 | people like punctuation marks. (In fact, they're not punctuation |
| | 13148 | marks at all; they're actually ligatures of "et," Latin for "and," |
| | 13149 | although the glyph has become so stylized in modern typefaces that |
| | 13150 | it's hard to see that unless you know what to look for.) First, an |
| | 13151 | ampersand is <b>not</b> a token separator, so a sequence like |
| | 13152 | "T&V" will be read as a single token. Second, when an ampersand |
| | 13153 | is surrounded by whitespace (or other token separators), so that it |
| | 13154 | does count as a separate token, it'll be parsed as a "word" token, |
| | 13155 | not as punctuation. For example, "Bob & Sons" is read as three |
| | 13156 | "word" tokens. This means that you can use a lone "&" as an |
| | 13157 | adjective or noun in defining an object's vocabulary. |
| | 13158 | |
| | 13159 | </div> |
| | 13160 | |
| | 13161 | <!-------------------> |
| | 13162 | <div class=entry> |
| | 13163 | |
| | 13164 | In the English module, Thing.conjugateRegularVerb() incorrectly |
| | 13165 | applied an "-ies" ending to verbs ending in a consonant plus a "y", |
| | 13166 | such as "say". This affected routines like itVerb() and nameVerb(). |
| | 13167 | The routine now uses a regular "-s" ending when a vowel precedes |
| | 13168 | a terminal "y". |
| | 13169 | |
| | 13170 | </div> |
| | 13171 | |
| | 13172 | <!-------------------> |
| | 13173 | <div class=entry> |
| | 13174 | |
| | 13175 | The parser now allows possessive pronoun adjectives ("her book") to |
| | 13176 | refer back to the previous noun phrase in the same action. For |
| | 13177 | example, ASK BOB ABOUT HIS HAT will treat "his" as referring to Bob. |
| | 13178 | This is accomplished by first trying to find an earlier noun phrase |
| | 13179 | in the same action that matches the pronoun in number and gender. If |
| | 13180 | we find a match, we use it, otherwise we use the ordinary pronoun |
| | 13181 | antecedent from a previous command. Note that the number/gender |
| | 13182 | match ensures that we don't get overzealous in applying this: if we |
| | 13183 | type ASK BOB ABOUT HER BOOK, we find that BOB doesn't match HER, so |
| | 13184 | we look to the meaning of HER from a previous command. |
| | 13185 | |
| | 13186 | <p>As part of this change, the Action routine that was formerly |
| | 13187 | called getReflexiveBinding has been renamed to getAnaphoricBinding. |
| | 13188 | The new name better reflects the more generalized function, since it |
| | 13189 | can be used for other kinds of anaphoric bindings besides reflexives. |
| | 13190 | This is an internal method that is highly unlikely to be |
| | 13191 | used in any game code, so this change should be transparent. |
| | 13192 | |
| | 13193 | <p>("Anaphor" is the linguistic term for any sort of reference to an |
| | 13194 | earlier noun phrase in a sentence; a reflexive is a particular kind |
| | 13195 | of anaphor that re-uses a noun phrase from an earlier "slot" in a |
| | 13196 | predicate to fill another slot in the same predicate, such as HIMSELF |
| | 13197 | in ASK BOB ABOUT HIMSELF. The reason reflexives exist in English and |
| | 13198 | other languages is that they're unambiguously anaphoric: in ASK BOB |
| | 13199 | ABOUT HIMSELF, HIMSELF can only refer to Bob, whereas the HIM in ASK |
| | 13200 | BOB ABOUT HIM almost certainly refers to someone other than Bob from |
| | 13201 | a previous sentence or clause. The name change in the method |
| | 13202 | reflects the fact that there are other kinds of anaphoric constructs |
| | 13203 | besides reflexives; in ASK BOB ABOUT HIS BOOK, the HIS refers |
| | 13204 | anaphorically to BOB, but it's not reflexive.) |
| | 13205 | |
| | 13206 | |
| | 13207 | </div> |
| | 13208 | |
| | 13209 | <!-------------------> |
| | 13210 | <div class=entry> |
| | 13211 | |
| | 13212 | In Actor.executeActorTurn(), when a pending response is delivered, |
| | 13213 | the actor now clears its memory of the pending response. (In the |
| | 13214 | past, the pending response wasn't cleared, so an NPC with a pending |
| | 13215 | response would keep delivering the pending response over and over.) |
| | 13216 | |
| | 13217 | </div> |
| | 13218 | |
| | 13219 | <!-------------------> |
| | 13220 | <div class=entry> |
| | 13221 | |
| | 13222 | When AskFor changed to a TopicTAction in 3.0.6l, the Actor handler for |
| | 13223 | GiveTo was affected but wasn't updated properly. The GiveTo handler |
| | 13224 | changes a GiveTo command directed to another actor into an AskFor |
| | 13225 | command (BOB, GIVE ME THE CROWBAR becomes ASK BOB FOR CROWBAR), so the |
| | 13226 | AskFor change required this rephrasing to be cast in the new |
| | 13227 | TopicTAction terms. This change wasn't made, so the GiveTo handler |
| | 13228 | didn't work properly. This has now been fixed. |
| | 13229 | |
| | 13230 | </div> |
| | 13231 | |
| | 13232 | <!-------------------> |
| | 13233 | <div class=entry> |
| | 13234 | |
| | 13235 | Actor.desc no longer shows the postureDesc as part of the description |
| | 13236 | of an NPC. Instead, this is shown in examineStatus(). This change |
| | 13237 | shouldn't affect any existing code; it merely moves around where the |
| | 13238 | calls are made, but still makes all the same calls in the same |
| | 13239 | sequence. The change makes it easier to override an Actor's 'desc' |
| | 13240 | without changing the overall display format. |
| | 13241 | |
| | 13242 | </div> |
| | 13243 | |
| | 13244 | <!-------------------> |
| | 13245 | <div class=entry> |
| | 13246 | |
| | 13247 | A bug in the sense system prevented a self-illuminating object (an |
| | 13248 | object with a brightness of 1) from applying its self-illumination to |
| | 13249 | its own interior surface; the illumination was considered external |
| | 13250 | only. This was inconsistent with the normal sense-transmission |
| | 13251 | rules, and it's now been corrected. A self-illuminating object is |
| | 13252 | now considered to have an ambience level of 1 on both its inner and |
| | 13253 | outer surface. |
| | 13254 | |
| | 13255 | </div> |
| | 13256 | |
| | 13257 | <!-------------------> |
| | 13258 | <div class=entry> |
| | 13259 | |
| | 13260 | A subtle bug in the sense system caused ambient sense energy levels |
| | 13261 | to be transmitted incorrectly into the interior of objects with |
| | 13262 | non-transparent fill media. In particular, the sense system |
| | 13263 | incorrectly applied the fill medium to the ambience level at the |
| | 13264 | inner surface of an object as transmitted from the outside of the |
| | 13265 | object. This was incorrect because it meant that a viewer on the |
| | 13266 | inside of an object saw the ambient level to the object adjusted |
| | 13267 | <i>twice</i> for the fill medium: once for the incorrect adjustment |
| | 13268 | at the inner surface, and once more for the path from the viewer, |
| | 13269 | through the fill medium, to the inner surface. This has been |
| | 13270 | corrected: the ambient level arriving at the inner surface of an |
| | 13271 | object from outside the object is now calculated without any |
| | 13272 | adjustment for the fill medium, and any further transmission inward |
| | 13273 | is then adjusted for the fill medium. |
| | 13274 | |
| | 13275 | <p>This problem showed up by making an object invisible from its own |
| | 13276 | interior when the object had a non-transparent fill medium, and the |
| | 13277 | light coming in from outside wasn't bright enough to penetrate the |
| | 13278 | fill medium twice. For example, a transparent booth filled with |
| | 13279 | attenuating fog, with external normal illumination (brightness 3), |
| | 13280 | was not visible from its interior because of the double traversal |
| | 13281 | of the fog. Such a booth is now visible from its interior. |
| | 13282 | |
| | 13283 | </div> |
| | 13284 | |
| | 13285 | <!-------------------> |
| | 13286 | <div class=entry> |
| | 13287 | |
| | 13288 | When looking for an object's default associated Noise or Odor, the |
| | 13289 | Thing methods getNoise() and getOdor() now only consider objects with |
| | 13290 | an active "presence" in their sense. That is, getNoise() will only |
| | 13291 | return a Noise object with a non-nil soundPresence property value, |
| | 13292 | and getOdor() will only return an Odor with a non-nil smellPresence. |
| | 13293 | This makes it easier to turn an object's associated sense data on and |
| | 13294 | off, since you can simply use the presence properties of the Noise |
| | 13295 | and Odor objects. |
| | 13296 | |
| | 13297 | </div> |
| | 13298 | |
| | 13299 | <!-------------------> |
| | 13300 | <div class=entry> |
| | 13301 | |
| | 13302 | In 3.0.6j, CollectiveGroup stopped matching singular phrases and |
| | 13303 | phrases with quantities specified (as in "five coins"). This behavior |
| | 13304 | hasn't changed, but it's now easier to control, with the new method |
| | 13305 | isCollectiveQuant(). This method returns true if the given "required |
| | 13306 | quantity" allows using the collective, nil if not. By default, this |
| | 13307 | returns true if and only if there's no specific quantity needed (in |
| | 13308 | which case the quantity parameter is nil). |
| | 13309 | |
| | 13310 | </div> |
| | 13311 | |
| | 13312 | <!-------------------> |
| | 13313 | <div class=entry> |
| | 13314 | |
| | 13315 | RandomTextList and ShuffledTextList can now handle arbitrary event |
| | 13316 | entries in their lists, using the same rules as the base EventList |
| | 13317 | class. (In the past, only strings and nil values were allowed in |
| | 13318 | these specialized subclasses, but they now use the base class handling |
| | 13319 | to carry out each event, so they can now handle any sort of event the |
| | 13320 | base class can.) |
| | 13321 | |
| | 13322 | </div> |
| | 13323 | |
| | 13324 | <!------------------------------- 3.0.6l ---------------------------------> |
| | 13325 | <div class="sepbar"><a name='306l'></a>3.0.6l</div> |
| | 13326 | <p><b><i>Released October 4, 2003</i></b> |
| | 13327 | <p> |
| | 13328 | |
| | 13329 | <div class=firstentry> |
| | 13330 | |
| | 13331 | The actor knowledge and "sight memory" systems have been revamped to |
| | 13332 | make it easier to keep track of individual knowledge for different |
| | 13333 | actors. <b>A few key interfaces have changed, so existing games will |
| | 13334 | have to make corresponding changes.</b> |
| | 13335 | |
| | 13336 | <p>First, the main interface changes: |
| | 13337 | |
| | 13338 | <ul> |
| | 13339 | <li>obj.seenBy(actor) is now actor.hasSeen(obj) |
| | 13340 | <li>obj.setSeenBy(actor, stat) is now actor.setHasSeen(obj) |
| | 13341 | <li>obj.isKnownBy(actor) is now actor.knowsAbout(obj) |
| | 13342 | <li>obj.setKnownBy(actor, stat) is now actor.setKnowsAbout(obj) |
| | 13343 | </ul> |
| | 13344 | |
| | 13345 | <p>Note that the "stat" parameter has been removed from the two "set" |
| | 13346 | methods. This parameter was essentially superfluous, since it's rare |
| | 13347 | to the point of non-existence for a game to want to mark something as |
| | 13348 | un-seen or unknown after it's been previously seen or known; the new |
| | 13349 | methods elide this parameter and act like the old methods acted with |
| | 13350 | the parameter set to true. |
| | 13351 | |
| | 13352 | <p>You have a choice of how to update your existing game code to the |
| | 13353 | new interfaces. The first option is to do the search-and-replace |
| | 13354 | operations in the list above throughout your game's source code; this |
| | 13355 | is the recommended option, because it'll make your code consistent |
| | 13356 | with future documentation. The second option is to modify the |
| | 13357 | VocabObject class to reinstate the old methods, defining them in |
| | 13358 | terms of the new ones: |
| | 13359 | |
| | 13360 | <p><pre> |
| | 13361 | modify VocabObject |
| | 13362 | seenBy(actor) { return actor.hasSeen(self); } |
| | 13363 | setSeenBy(actor, flag) { actor.setHasSeen(self); } |
| | 13364 | isKnownBy(actor) { return actor.knowsAbout(self); } |
| | 13365 | setKnownBy(actor, flag) { actor.setKnowsAbout(self); } |
| | 13366 | ; |
| | 13367 | </pre> |
| | 13368 | |
| | 13369 | <p>Second, how do the changes facilitate separate NPC knowledge |
| | 13370 | tracking? The change here is that the Thing and Topic 'seen' and |
| | 13371 | 'isKnown' properties that underlay the old system are still used, but |
| | 13372 | are now only <i>defaults</i> for tracking the seen/known information. |
| | 13373 | The actual properties used to track the information are determined on |
| | 13374 | an actor-by-actor basis, using the new Actor.seenProp and |
| | 13375 | Actor.knownProp properties. |
| | 13376 | |
| | 13377 | <p>By default, Actor defines seenProp as &seen, and knownProp as |
| | 13378 | &isKnown. This means that, by default, there's only one |
| | 13379 | "global" set of knowledge. To track an NPC's knowledge individually, |
| | 13380 | simply set seenProp and/or knownProp to new properties unique to that |
| | 13381 | actor. For example: |
| | 13382 | |
| | 13383 | <p><pre> |
| | 13384 | bob: Person |
| | 13385 | // ... other definitions... |
| | 13386 | seenProp = &bobSeen |
| | 13387 | knownProp = &bobKnown |
| | 13388 | ; |
| | 13389 | </pre> |
| | 13390 | |
| | 13391 | <p>This specifies that 'bob' will individually track its knowledge, |
| | 13392 | separately from any other actors. When you call bob.setKnowsAbout(obj), |
| | 13393 | the library will examine obj.bobKnown and obj.bobSeen, because those are |
| | 13394 | the properties that track bob's knowledge. Note that this individual |
| | 13395 | tracking is completely automatic once you define seenProp and knownProp, |
| | 13396 | since the Actor methods hasSeen, setHasSeen, knowsAbout, and setKnowsAbout |
| | 13397 | all use seenProp and/or knownProp to do their work. |
| | 13398 | |
| | 13399 | <p>Note that because the default values in Actor for seenProp and |
| | 13400 | knownProp are (respectively) &seen and &isKnown, everything |
| | 13401 | works roughly the same way it did before if you don't override these |
| | 13402 | properties. In particular, if you don't care about tracking |
| | 13403 | individual NPC knowledge, which typical games probably won't, you |
| | 13404 | only have to worry about 'seen' and 'isKnown' as before. So, if you |
| | 13405 | want to initialize an object as pre-known, before the start of the |
| | 13406 | game, simply set isKnown=true for that object as in the past. |
| | 13407 | |
| | 13408 | <p>Third, a minor enhancement: the GIVE and SHOW iobjFor() handlers |
| | 13409 | in Actor now automatically mark the object being shown, and its |
| | 13410 | visible contents, as having been seen by the actor being shown the |
| | 13411 | object. For games that track NPC knowledge separately, this will |
| | 13412 | ensure that the target of a GIVE or SHOW takes note of having seen |
| | 13413 | the object in question. |
| | 13414 | |
| | 13415 | </div> |
| | 13416 | |
| | 13417 | <!-------------------> |
| | 13418 | <div class=entry> |
| | 13419 | |
| | 13420 | A new class, Consultable, can be used to implement things like books |
| | 13421 | and file cabinets: inanimate objects in which an actor can look up a |
| | 13422 | topic, to find some information. This class works almost exactly |
| | 13423 | like the Actor conversation system. Another new class, ConsultTopic, |
| | 13424 | serves as the TopicEntry subclass for Consultables. Simply create |
| | 13425 | one or more ConsultTopic objects, and locate them within the |
| | 13426 | Consultable, to populate the consultable object's database of |
| | 13427 | responses. |
| | 13428 | |
| | 13429 | <p>In support of the new Consultable class, the TopicDatabase and |
| | 13430 | TopicEntry classes have been refactored a bit. In particular, these |
| | 13431 | two classes no longer assume that they're associated with an actor, |
| | 13432 | and no longer assume that they're involved in conversation. The |
| | 13433 | parts of the former implementations that made assumptions about actor |
| | 13434 | or conversation associations have been moved into a pair of new |
| | 13435 | subclasses, ActorTopicDatabase and ActorTopicEntry. The existing |
| | 13436 | classes that were based directly on TopicDatabase and TopicEntry are |
| | 13437 | now based on the new ActorXxx subclasses instead. For almost all |
| | 13438 | existing game code, this change should be entirely transparent, |
| | 13439 | because the final subclasses that most games use still have the same |
| | 13440 | names and work the same way they did before; the only changes are |
| | 13441 | some internal reshuffling to abstract out most of the functionality |
| | 13442 | into the new base classes. |
| | 13443 | |
| | 13444 | <p>In addition, the TopicResolver class has a new subclass, |
| | 13445 | ConvTopicResolver, that's used for the conversational actions (ASK |
| | 13446 | ABOUT, TELL ABOUT). The base TopicResolver doesn't differentiate |
| | 13447 | at all among topics; it simply considers everything to be an |
| | 13448 | equally good match. The ConvTopicResolver differentiates topics |
| | 13449 | into three sublists, as it did in the past: objects that are in |
| | 13450 | physical scope or are known to the actor performing the command; |
| | 13451 | objects that are "likely" topics, as indicated by the performing |
| | 13452 | actor's isLikelyTopic(); and everything else. |
| | 13453 | |
| | 13454 | </div> |
| | 13455 | |
| | 13456 | <!-------------------> |
| | 13457 | <div class=entry> |
| | 13458 | |
| | 13459 | The ConsultAbout action in the English module now adds grammar for |
| | 13460 | some incomplete forms, such as "look up (topic)". If the player |
| | 13461 | enters one of these incomplete forms, the parser will prompt for |
| | 13462 | the missing object in the usual fashion. |
| | 13463 | |
| | 13464 | <p>Similarly, when the direct object is missing from a CONSULT ABOUT |
| | 13465 | command, the default is the last object consulted by the same actor, |
| | 13466 | as long as that object is still visible. The new Actor property |
| | 13467 | lastConsulted keeps track of the last object consulted; the new Actor |
| | 13468 | method noteConsultation() sets this property. The Consultable class |
| | 13469 | calls gActor.noteConsultation(self) in its ConsultAbout action() |
| | 13470 | handler. This saves the player some typing, since they can leave out |
| | 13471 | the object to be consulted when they're looking up a series of topics |
| | 13472 | in the same consultable (they can type simply LOOK UP BOB, for |
| | 13473 | example). |
| | 13474 | |
| | 13475 | </div> |
| | 13476 | |
| | 13477 | <!-------------------> |
| | 13478 | <div class=entry> |
| | 13479 | |
| | 13480 | The TopicEntry scoring system now uses nil to represent a non-match. |
| | 13481 | This means the valid scoring range now includes zero and negative |
| | 13482 | values, which in turn means that it's no longer a problem if |
| | 13483 | matchScoreAdjustment values reducing scores to zero or below. This |
| | 13484 | makes it easier to use score adjustments, since there's no longer any |
| | 13485 | need to worry about interactions between score values and adjustment |
| | 13486 | values taking a final score out of range. |
| | 13487 | |
| | 13488 | </div> |
| | 13489 | |
| | 13490 | <!-------------------> |
| | 13491 | <div class=entry> |
| | 13492 | |
| | 13493 | The AskFor action is now a TopicTAction instead of a TIAction. That |
| | 13494 | is, the indirect object is now a topic rather than an ordinary |
| | 13495 | resolved object. The TIAction implementation was never really |
| | 13496 | appropriate, since ASK FOR conceptually needs topic-oriented rules |
| | 13497 | for the indirect object: one needs to be able to ask for things that |
| | 13498 | aren't in scope, as well as for abstract topics (ASK FOR HELP, ASK |
| | 13499 | FOR DIRECTIONS). |
| | 13500 | |
| | 13501 | <p>This change should have little or no impact on existing games. |
| | 13502 | |
| | 13503 | </div> |
| | 13504 | |
| | 13505 | <!-------------------> |
| | 13506 | <div class=entry> |
| | 13507 | |
| | 13508 | The new TopicEntry subclass AskAboutForTopic can be used to make a |
| | 13509 | single topic entry respond to either ASK ABOUT or ASK FOR for a given |
| | 13510 | game object or objects (read the name as "ask about/for topic"). |
| | 13511 | Similarly, AskTellAboutForTopic can respond to ASK ABOUT, TELL ABOUT, |
| | 13512 | or ASK FOR (read the name as "ask/tell about/for topic," although the |
| | 13513 | TELL FOR combination implied in that reading doesn't make any sense, |
| | 13514 | obviously). |
| | 13515 | |
| | 13516 | </div> |
| | 13517 | |
| | 13518 | <!-------------------> |
| | 13519 | <div class=entry> |
| | 13520 | |
| | 13521 | The limitSuggestions property now applies to ActorState objects |
| | 13522 | as well as to ConvNode objects. Suggestions are effectively arranged |
| | 13523 | into a hierarchy: the top level of the hierarchy is the ConvNode, the |
| | 13524 | next level is the ActorState, and the bottom level is the Actor. |
| | 13525 | The full list of suggestions consists of the ConvNode's suggestions, |
| | 13526 | plus the ActorState's suggestions, plus the Actor's suggestions. |
| | 13527 | However, if limitSuggestions is true at any level of the hierarchy, |
| | 13528 | then suggestions below that point are not included in the full list. |
| | 13529 | So, if the ConvNode's limitSuggestions property is true, only the |
| | 13530 | ConvNode suggestions are included. If the ConvNode's limitSuggestions |
| | 13531 | property is nil, but the ActorState's limitSuggestions property is |
| | 13532 | true, then the ConvNode and ActorState suggestions are both included. |
| | 13533 | If limitSuggestions is nil for both the ConvNode and ActorState, then |
| | 13534 | the suggestions at all three levels (ConvNode, ActorState, and Actor) |
| | 13535 | are included in the full list. |
| | 13536 | |
| | 13537 | </div> |
| | 13538 | |
| | 13539 | <!-------------------> |
| | 13540 | <div class=entry> |
| | 13541 | |
| | 13542 | The new class SuggestedTopicTree makes it easy to create a tree of |
| | 13543 | AltTopic alternatives that acts as a single suggested topic. |
| | 13544 | |
| | 13545 | <p>Normally, when you create a tree of AltTopic alternatives, |
| | 13546 | you can make each AltTopic a separate suggestion. Each alternative |
| | 13547 | is effectively an independent topic for suggestion purposes, so |
| | 13548 | asking about one doesn't satisfy the PC's curiosity about any of |
| | 13549 | the other alternatives. This means that the game might make the |
| | 13550 | same suggestion several times, as the different alternatives become |
| | 13551 | active. |
| | 13552 | |
| | 13553 | <p>In many cases, it's better to treat the whole group of alternatives |
| | 13554 | as a single suggestion, so that the suggestion is only made once (or |
| | 13555 | only as many times as desired) for the whole set. This is what |
| | 13556 | SuggestedTopicTree is for. To use this class, simply add SuggestedTopicTree |
| | 13557 | to the superclass list for the <b>main</b> TopicEntry (that is, the |
| | 13558 | TopicEntry at the root of the tree: the one containing all of the |
| | 13559 | AltTopic alternatives). |
| | 13560 | |
| | 13561 | <p>Note that the new TopicEntry property altTalkCount keeps track of |
| | 13562 | the number of invocations for an entire alternative group. This |
| | 13563 | property is kept in the outermost TopicEntry for an AltTopic group, |
| | 13564 | and is incremented each time the outermost TopicEntry or any of its |
| | 13565 | AltTopic objects is invoked (via ASK ABOUT, TELL ABOUT, etc). |
| | 13566 | SuggestedTopicTree uses this new counter to determine if the PC's |
| | 13567 | curiosity has been satisfied for the set of alternatives as a group. |
| | 13568 | |
| | 13569 | </div> |
| | 13570 | |
| | 13571 | <!-------------------> |
| | 13572 | <div class=entry> |
| | 13573 | |
| | 13574 | The former ConversationManager method setRespondingActor() has been |
| | 13575 | renamed to beginResponse(), and a new method finishResponse() has been |
| | 13576 | added. Each call to beginResponse() should have a corresponding call |
| | 13577 | to finishResponse(). |
| | 13578 | |
| | 13579 | <p>This change allows the conversation manager to defer setting the |
| | 13580 | new default ConvNode in the responding actor until after the response |
| | 13581 | has been finished. This ensures that a ConvNode's noteActive() |
| | 13582 | method will not be invoked in response to a <.convstay> tag. |
| | 13583 | In the past, the conversation manager immediately transitioned the |
| | 13584 | actor to the default next ConvNode at the start of showing the |
| | 13585 | response, so if the response contained a <.convstay> tag, this |
| | 13586 | caused a transition back to the starting ConvNode, and thus a call to |
| | 13587 | noteActive() on the ConvNode object. The new scheme ensures that the |
| | 13588 | actor's ConvNode won't change at all when processing a |
| | 13589 | <.convstay> tag. |
| | 13590 | |
| | 13591 | </div> |
| | 13592 | |
| | 13593 | <!-------------------> |
| | 13594 | <div class=entry> |
| | 13595 | |
| | 13596 | The AgendaItem class has a new method, resetItem(), that is invoked |
| | 13597 | each time the item is added to an actor's agenda (via |
| | 13598 | Actor.addToAgenda()). By default, this method sets the item's isDone |
| | 13599 | property to nil, as long as the property isn't a method. This makes |
| | 13600 | it easier to re-use agenda items, since you don't have to worry about |
| | 13601 | resetting isDone explicitly. |
| | 13602 | |
| | 13603 | </div> |
| | 13604 | |
| | 13605 | <!-------------------> |
| | 13606 | <div class=entry> |
| | 13607 | |
| | 13608 | The Surface class now uses a custom Lister, |
| | 13609 | surfaceInlineContentsLister, to show its in-line contents listing. |
| | 13610 | The new lister shows the in-line contents using the format "(on which |
| | 13611 | is...)". In the past, Surface simply inherited Thing's in-line |
| | 13612 | contents lister, which phrases things in terms of containment |
| | 13613 | ("(which contains...)"), which isn't quite right for surfaces. |
| | 13614 | |
| | 13615 | <p>For naming consistency, the Lister formerly named |
| | 13616 | keyringListingContentsLister has been renamed to |
| | 13617 | keyringInlineContentsLister. The old name was a bit odd and didn't |
| | 13618 | properly call attention to the "in-line" aspect. |
| | 13619 | |
| | 13620 | </div> |
| | 13621 | |
| | 13622 | <!-------------------> |
| | 13623 | <div class=entry> |
| | 13624 | |
| | 13625 | Whenever an object's contents are listed via EXAMINE, LOOK IN, or |
| | 13626 | OPEN, the library now automatically marks all of the object's visible |
| | 13627 | contents as having been seen. Only contents that are actually |
| | 13628 | visible to the character performing the command will be marked as |
| | 13629 | seen, but it doesn't matter whether or not the contents are mentioned |
| | 13630 | at all in the description of the object. |
| | 13631 | |
| | 13632 | </div> |
| | 13633 | |
| | 13634 | <!-------------------> |
| | 13635 | <div class=entry> |
| | 13636 | |
| | 13637 | The new Thing method useSpecialDescInRoom(room) lets an object specify |
| | 13638 | whether or not its special description should be shown in a LOOK AROUND |
| | 13639 | description. By default, this simply returns useSpecialDesc(). In |
| | 13640 | some cases, it might be desirable for an object to show its special |
| | 13641 | description only when a container is examined, but not in a room |
| | 13642 | description; this methods lets the object control this. |
| | 13643 | |
| | 13644 | </div> |
| | 13645 | |
| | 13646 | <!-------------------> |
| | 13647 | <div class=entry> |
| | 13648 | |
| | 13649 | <p>The new Thing property suppressAutoSeen can be used to suppress |
| | 13650 | the library's automatic "seen" marking. By default, the library |
| | 13651 | automatically marks every visible object as having been seen whenever |
| | 13652 | a LOOK AROUND command is performed. The library also automatically |
| | 13653 | marks as seen every visible object within a container when the |
| | 13654 | container is explicitly examined (with EXAMINE, LOOK IN, or OPEN, for |
| | 13655 | example). |
| | 13656 | |
| | 13657 | <p>suppressAutoSeen is nil by default. If you set it to true for an |
| | 13658 | object, then the library will not mark the object as having been seen |
| | 13659 | in any of the standard cases, even when the object is visible. The |
| | 13660 | game must mark the object as having been seen by explicitly calling |
| | 13661 | setSeenBy(), if and when desired. |
| | 13662 | |
| | 13663 | </div> |
| | 13664 | |
| | 13665 | <!-------------------> |
| | 13666 | <div class=entry> |
| | 13667 | |
| | 13668 | DistanceConnector now derives from Intangible as well as |
| | 13669 | SenseConnector. This makes it easier to use DistanceConnector, since |
| | 13670 | it's no longer necessary to mix it with a Thing subclass. Each |
| | 13671 | distance-connector object needs to derive from Thing so that it fits |
| | 13672 | into the normal sense model, but these objects will almost never have |
| | 13673 | any physical presence in the game; Intangible fills both of these |
| | 13674 | needs. |
| | 13675 | |
| | 13676 | </div> |
| | 13677 | |
| | 13678 | <!-------------------> |
| | 13679 | <div class=entry> |
| | 13680 | |
| | 13681 | The DistanceConnector template in adv3.h, which sets the locationList |
| | 13682 | property, has been changed into a generic MultiLoc template. This |
| | 13683 | lets you initialize any MultiLoc object's location list by specifying |
| | 13684 | the list of locations after the class name when defining the object. |
| | 13685 | |
| | 13686 | </div> |
| | 13687 | |
| | 13688 | <!-------------------> |
| | 13689 | <div class=entry> |
| | 13690 | |
| | 13691 | The Room template in en_us/en_us.h now accepts a room that defines |
| | 13692 | only a 'name' property; the 'desc' property is now optional. This |
| | 13693 | lets you use the template to define the room name even if you want |
| | 13694 | to define a complex method for the 'desc'. |
| | 13695 | |
| | 13696 | </div> |
| | 13697 | |
| | 13698 | <!-------------------> |
| | 13699 | <div class=entry> |
| | 13700 | |
| | 13701 | A bug in the Sense class incorrectly considered objects to be out of |
| | 13702 | range of the 'smell' and 'sound' senses when the objects had distant, |
| | 13703 | obscured, or attenuated sense paths. This has been corrected. |
| | 13704 | |
| | 13705 | </div> |
| | 13706 | |
| | 13707 | <!-------------------> |
| | 13708 | <div class=entry> |
| | 13709 | |
| | 13710 | A Door object's getDoorOpenPreCond() can now return nil, if it's |
| | 13711 | not desirable to use a precondition for opening the door. |
| | 13712 | |
| | 13713 | </div> |
| | 13714 | |
| | 13715 | <!-------------------> |
| | 13716 | <div class=entry> |
| | 13717 | |
| | 13718 | The BasicChair, BasicBed, and BasicPlatform classes now include |
| | 13719 | a touchObj precondition for the SIT ON, LIE ON, and STAND ON commands. |
| | 13720 | |
| | 13721 | </div> |
| | 13722 | |
| | 13723 | <!-------------------> |
| | 13724 | <div class=entry> |
| | 13725 | |
| | 13726 | Where it makes sense, the preconditions that report failures with |
| | 13727 | messages along the lines of "You must open (something) first" now set |
| | 13728 | the pronoun antecedent to the object mentioned. This makes exchanges |
| | 13729 | like this work as one would expect: |
| | 13730 | |
| | 13731 | <p><pre> |
| | 13732 | >north |
| | 13733 | You must open the door first. |
| | 13734 | |
| | 13735 | >open it |
| | 13736 | </pre> |
| | 13737 | |
| | 13738 | </div> |
| | 13739 | |
| | 13740 | <!-------------------> |
| | 13741 | <div class=entry> |
| | 13742 | |
| | 13743 | In the hint system's Goal class, the new properties openWhenKnown and |
| | 13744 | closeWhenKnown let you tie a hint topic to the player character's |
| | 13745 | knowledge of a Topic or Thing. If you set a Goal object's |
| | 13746 | openWhenKnown to refer a Topic or Thing, then the Goal will become |
| | 13747 | "open" as soon as the Topic or Thing becomes known to the PC. |
| | 13748 | Likewise, if you set closeWhenKnown to a Topic or Thing, the goal |
| | 13749 | will become "closed" when the Topic or Thing becomes known. |
| | 13750 | |
| | 13751 | <p>The new Goal properites openWhenRevealed and closeWhenRevealed |
| | 13752 | let you tie a hint to a <.reveal> tag. You can set these |
| | 13753 | properties to (single-quoted) strings giving <.reveal> tags |
| | 13754 | to test. |
| | 13755 | |
| | 13756 | </div> |
| | 13757 | |
| | 13758 | <!-------------------> |
| | 13759 | <div class=entry> |
| | 13760 | |
| | 13761 | The Goal class has two new methods, openWhen and closeWhen, that |
| | 13762 | compute the conditions for opening and closing the hint topic, |
| | 13763 | respectively. These methods isolate the conditions that were |
| | 13764 | formerly included in-line in the updateContents() method. |
| | 13765 | |
| | 13766 | <p>Isolating the conditions in separate methods makes it easier to |
| | 13767 | use 'modify Goal' to add new custom open/close sub-conditions. For |
| | 13768 | example, suppose you wanted to add a pair of new custom Goal |
| | 13769 | properties that open and close hint topics based on a Thing being |
| | 13770 | moved for the first time. You could do this like so: |
| | 13771 | |
| | 13772 | <p><pre> |
| | 13773 | modify Goal |
| | 13774 | openWhenMoved = nil |
| | 13775 | closeWhenMoved = nil |
| | 13776 | openWhen = (inherited || (openWhenMoved != nil && openWhenMoved.moved)) |
| | 13777 | closeWhen = (inherited || (closeWhenMoved != nil && closeWhenMoved.moved)) |
| | 13778 | ; |
| | 13779 | </pre> |
| | 13780 | |
| | 13781 | </div> |
| | 13782 | |
| | 13783 | <!-------------------> |
| | 13784 | <div class=entry> |
| | 13785 | |
| | 13786 | The new library function intOrdinal(n) returns a "numeric ordinal" |
| | 13787 | representation of the number: '1st', '2nd', '3rd', and so on. |
| | 13788 | (Thanks to Søren J. Løvborg for suggesting this and providing a |
| | 13789 | sample implementation.) |
| | 13790 | |
| | 13791 | <p>Along the same lines, the new library functions spellIntOrdinal(n) |
| | 13792 | and spellIntOrdinalExt(n, flags) return fully spelled-out ordinals |
| | 13793 | ('first', 'second', 'third', etc). The 'Ext' version takes the same |
| | 13794 | bit-flag values as spellIntExt(). |
| | 13795 | |
| | 13796 | </div> |
| | 13797 | |
| | 13798 | <!-------------------> |
| | 13799 | <div class=entry> |
| | 13800 | |
| | 13801 | The library no longer considers the player character to be an |
| | 13802 | antecedent to a third-person pronoun when the game itself refers to |
| | 13803 | the PC in the first or second person (as determined by the PC Actor's |
| | 13804 | referralPerson property). In the past, typing X ME and then X IT |
| | 13805 | examine the player character twice. This will no longer happen, |
| | 13806 | except in third-person games, since the first X ME won't set ME as an |
| | 13807 | antecedent for HIM, HER, IT, or THEM. This isn't especially important |
| | 13808 | for IT and THEM, but it can be for HIM and HER if the PC has a specified |
| | 13809 | gender. |
| | 13810 | |
| | 13811 | </div> |
| | 13812 | |
| | 13813 | <!-------------------> |
| | 13814 | <div class=entry> |
| | 13815 | |
| | 13816 | The library now treats HIM and HER a little differently in disambiguation |
| | 13817 | responses. If HIM or HER is given as the answer to a disambiguation |
| | 13818 | question ("which one do you mean..."), the parser first looks to see |
| | 13819 | if there's a prior meaning of the pronoun that applies; it always did |
| | 13820 | this much. This is the new part: if there is no prior meaning for |
| | 13821 | the pronoun, or the prior meaning isn't one of the choices in the |
| | 13822 | query, then the parser looks to see if any of the objects in the query |
| | 13823 | match the pronoun. If there's exactly one match, the parser takes that |
| | 13824 | as the result. |
| | 13825 | |
| | 13826 | </div> |
| | 13827 | |
| | 13828 | <!-------------------> |
| | 13829 | <div class=entry> |
| | 13830 | |
| | 13831 | The English library module defines a few new methods related to |
| | 13832 | pronouns and gender. The new Thing methods canMatchHim, canMatchHer, |
| | 13833 | canMatchIt, and canMatchThem determine if an object can match these |
| | 13834 | individual pronouns. By default, these simply return true if the |
| | 13835 | corresponding isHim/isHer/isIt flags are true. Actor overrides these |
| | 13836 | so that they return true if the inherited version returns true |
| | 13837 | <i>and</i> the actor can be referred to in the third person, which is |
| | 13838 | determined by testing the additional new Actor method |
| | 13839 | canMatch3rdPerson. The new canMatch3rdPerson method returns true if |
| | 13840 | the actor isn't the player character, <i>or</i> the game refers to |
| | 13841 | the PC in the third person. |
| | 13842 | |
| | 13843 | </div> |
| | 13844 | |
| | 13845 | <!-------------------> |
| | 13846 | <div class=entry> |
| | 13847 | |
| | 13848 | The former Actor methods canTouch(obj) and findTouchObstructor(obj) |
| | 13849 | have been moved to Thing. There wasn't any need for these methods to |
| | 13850 | be special to Actor, and it's sometimes useful to establish |
| | 13851 | reachability between arbitrary non-Actor objects, so these are more |
| | 13852 | appropriate for Thing than Actor. |
| | 13853 | |
| | 13854 | </div> |
| | 13855 | |
| | 13856 | <!-------------------> |
| | 13857 | <div class=entry> |
| | 13858 | |
| | 13859 | The new class TouchObjCondition implements a generic object-to-object |
| | 13860 | reachability condition. This is similar to the existing touchObj |
| | 13861 | pre-condition, but allows for arbitrary source objects, whereas |
| | 13862 | touchObj can only test to see if the current gActor can touch an |
| | 13863 | object. touchObj is now a subclass of TouchObjCondition. |
| | 13864 | |
| | 13865 | </div> |
| | 13866 | |
| | 13867 | <!-------------------> |
| | 13868 | <div class=entry> |
| | 13869 | |
| | 13870 | In the past, throwing an object at a MultiLoc object, or at a component |
| | 13871 | within a MultiLoc object, didn't work properly. This has been corrected. |
| | 13872 | |
| | 13873 | <p>In order to allow throwing at MultiLoc objects, the interface to a |
| | 13874 | Thing method, getDropDestination, has been altered slightly. This |
| | 13875 | method now takes an additional parameter giving the "sense path" that |
| | 13876 | was used in the operation that's seeking the drop destination. The |
| | 13877 | new sense path parameter is a list in the same format returned by |
| | 13878 | Thing.selectPathTo. This path information allows getDropDestination |
| | 13879 | to determine whence the MultiLoc object was approached - that is, it |
| | 13880 | allows a MutliLoc object to find out which of its containers or |
| | 13881 | containment peers was last traversed to reach the object. This path |
| | 13882 | can be nil, but when it's supplied, it tells us how we're approaching |
| | 13883 | the drop destination. |
| | 13884 | |
| | 13885 | <p>Note that this change slightly affects the interfaces to several |
| | 13886 | Thing methods: getHitFallDestination, throwTargetHitWith, |
| | 13887 | stopThrowViaPath, throwViaPath, and throwTargetCatch. In all of these |
| | 13888 | routines, the former 'prvCont' parameter is now replaced with the |
| | 13889 | 'path' parameter. Similarly, the processThrow method passes the path |
| | 13890 | rather than the previous container. |
| | 13891 | |
| | 13892 | </div> |
| | 13893 | |
| | 13894 | <!-------------------> |
| | 13895 | <div class=entry> |
| | 13896 | |
| | 13897 | In the English grammar, abbreviated words that include periods in the |
| | 13898 | abbreviation (as in "Main St." or "J. Pretensions") are now treated a |
| | 13899 | little differently, to ensure that abbreviated words don't have any |
| | 13900 | bad interactions with unabbreviated equivalents. This change should |
| | 13901 | be completely transparent to existing game code. |
| | 13902 | |
| | 13903 | <p>First, the tokenizer no longer treats an abbreviation as a single |
| | 13904 | token that includes the period, but rather as two separate tokens: |
| | 13905 | one for the word itself, and a separate token for the period. The |
| | 13906 | period is entered not with the ordinary punctuation token class, but |
| | 13907 | with the new 'tokAbbrPeriod' class. Second, wherever ordinary noun |
| | 13908 | tokens were allowed in the grammar, the grammar now instead accepts |
| | 13909 | the new subproduction 'nounWord'. This new production matches an |
| | 13910 | ordinary noun token, <i>or</i> a noun token followed by a |
| | 13911 | tokAbbrPeriod token. Third, and similarly, the existing 'adjWord' |
| | 13912 | production now accepts an adjective token followed by a tokAbbrPeriod |
| | 13913 | token. Fourth, the vocabulary initialization |
| | 13914 | (VocabObject.initializeVocabWith, which parses the vocabWords_ |
| | 13915 | string) now enters each token that ends in a period with the period, |
| | 13916 | as it did, but also <i>without</i> the period. So, for example, the |
| | 13917 | vocabWords_ string 'main st.' will create an adjective 'main', a noun |
| | 13918 | 'st.', and a second noun 'st' (in other words, 'st' is entered in the |
| | 13919 | dictionary both with and without a trailing period). |
| | 13920 | |
| | 13921 | <p>This corrects a problem that could have occurred with the old |
| | 13922 | scheme if the same word was used abbreviated and unabbreviated. For |
| | 13923 | example, if 's.' was used as an abbreviated word (for a string like |
| | 13924 | 's. main st.', for example), and 's' was also entered in the |
| | 13925 | dictionary as a verb (which it is by default, for the South action) |
| | 13926 | the command "s." was not properly handled. The problem was that the |
| | 13927 | tokenizer would see that "s." was entered in the dictionary with the |
| | 13928 | period, so it tokenized it with the period. This precluded |
| | 13929 | interpreting it as two tokens, 's' and '.', so the 's' was not |
| | 13930 | matched to the verb, hence the command was rejected as not understood. |
| | 13931 | |
| | 13932 | <p>A useful side effect of this change is that each abbreviation is |
| | 13933 | now automatically entered in the dictionary without its period. This |
| | 13934 | should be helpful to players who choose to avoid the extra typing of |
| | 13935 | entering the periods in abbreviations. |
| | 13936 | |
| | 13937 | </div> |
| | 13938 | |
| | 13939 | <!-------------------> |
| | 13940 | <div class=entry> |
| | 13941 | |
| | 13942 | The new Hidden class can be used to implement objects that are present |
| | 13943 | but not seen. This is useful for objects that are too inconspicuous |
| | 13944 | to be noticed, or are positioned in such a way that they can't be |
| | 13945 | readily seen (but in such a way that the ordinary sense mechanism |
| | 13946 | would think the object was visible). |
| | 13947 | |
| | 13948 | </div> |
| | 13949 | |
| | 13950 | <!-------------------> |
| | 13951 | <div class=entry> |
| | 13952 | |
| | 13953 | The BulkLimiter class now parameterizes all of the messages that |
| | 13954 | were previously coded directly as failure reports. The new BulkLimiter |
| | 13955 | properties tooLargeMsg, becomingTooLargeMsg, and becomingTooFullMsg |
| | 13956 | join the existing tooFullMsg in specifying the various failure reports; |
| | 13957 | these properties in turn contain property pointers that refer to |
| | 13958 | messages defined in the playerActionMessages object. This makes it |
| | 13959 | easier to create "cosmetic" subclasses of BulkLimiter that define |
| | 13960 | customized types of containment relationships. |
| | 13961 | |
| | 13962 | </div> |
| | 13963 | |
| | 13964 | <!-------------------> |
| | 13965 | <div class=entry> |
| | 13966 | |
| | 13967 | The new macro askForTopic(action) allows a single-object TAction to |
| | 13968 | ask for a topic phrase and retry the command as a TopicTAction. This |
| | 13969 | allows, for example, a CONSULT action with no topic specified to ask |
| | 13970 | for a topic and turn itself into a CONSULT ABOUT action. |
| | 13971 | |
| | 13972 | <p>To enable this change, the parser includes a new grammar |
| | 13973 | production, EmptyTopicPhrase. This new production represents a topic |
| | 13974 | phrase that requires an interactive response from the player. |
| | 13975 | |
| | 13976 | </div> |
| | 13977 | |
| | 13978 | <!-------------------> |
| | 13979 | <div class=entry> |
| | 13980 | |
| | 13981 | In the past, it wasn't possible to use askForDobj() to convert a |
| | 13982 | LiteralAction into a LiteralTAction, or a TopicAction into a |
| | 13983 | TopicTAction, by requesting a missing direct object from the player. |
| | 13984 | This was due to an oversight in the library, which has now been |
| | 13985 | corrected. |
| | 13986 | |
| | 13987 | <p>Another similar, though more subtle, oversight made it impossible |
| | 13988 | to use askForDobj() to convert a TAction into a TIAction. This is an |
| | 13989 | unusual scenario, because the usual way to perform this conversion |
| | 13990 | would be through askForIobj(): it's almost always the indirect object |
| | 13991 | that's missing in these cases. However, there are cases where a |
| | 13992 | missing direct object is possible; for example, we might want a |
| | 13993 | full-fledged SPRAY verb that takes only one object, as in SPRAY AIR |
| | 13994 | FRESHENER, but also have a two-object form for things like SPRAY SINK |
| | 13995 | WITH DISINFECTANT, in which it's the direct object that's missing |
| | 13996 | from the two-object form when we type SPRAY DISINFECTANT. (This |
| | 13997 | particular example is a bit contrived, since we could just as well |
| | 13998 | have defined the verb as SPRAY DISINFECTANT ON SINK, but even so, we |
| | 13999 | don't want to be forced to find such a rephrasing.) In these cases, |
| | 14000 | askForDobj() can now be used. When a TAction is retried as a |
| | 14001 | TIAction with askForDobj(), the direct object of the TAction now |
| | 14002 | becomes the <i>indirect</i> object of the TIAction; this is plainly |
| | 14003 | the only way it can be, since we know the direct object is missing by |
| | 14004 | virtue of the fact that we're asking for it. |
| | 14005 | |
| | 14006 | </div> |
| | 14007 | |
| | 14008 | <!-------------------> |
| | 14009 | <div class=entry> |
| | 14010 | |
| | 14011 | The interface of the method Actor.trackFollowInfo() has been changed |
| | 14012 | slightly to improve its flexibility. In the past, this method assumed |
| | 14013 | that the current action was actually performing the travel; now, the |
| | 14014 | method instead takes an additional argument to eliminate this |
| | 14015 | dependency. The new third argument gives the starting location of the |
| | 14016 | travel; this is normally simply the location of the actor traveling, |
| | 14017 | but could be something else; for example, when the actor is inside |
| | 14018 | a vehicle, then the starting location is the vehicle's location. |
| | 14019 | |
| | 14020 | </div> |
| | 14021 | |
| | 14022 | <!-------------------> |
| | 14023 | <div class=entry> |
| | 14024 | |
| | 14025 | The new class NestedRoomFloor can be used for convenience in creating |
| | 14026 | an object that serves as the floor of a nested room. |
| | 14027 | |
| | 14028 | </div> |
| | 14029 | |
| | 14030 | <!-------------------> |
| | 14031 | <div class=entry> |
| | 14032 | |
| | 14033 | The Floor class now accepts STAND ON commands. STAND ON FLOOR is |
| | 14034 | simply remapped to STAND UP. |
| | 14035 | |
| | 14036 | </div> |
| | 14037 | |
| | 14038 | <!-------------------> |
| | 14039 | <div class=entry> |
| | 14040 | |
| | 14041 | The BurnWith action now resolves its direct object first. This is |
| | 14042 | the better resolution order for this action, since it allows the |
| | 14043 | direct object to set the scope for choosing the indirect object, |
| | 14044 | which is likely to be omitted and thus require a suitable default |
| | 14045 | to be chosen. |
| | 14046 | |
| | 14047 | <p>In addition, the FireSource class now declares it illogical to |
| | 14048 | burn an object using itself as the fire source. It's common for a |
| | 14049 | Candle to also be a FireSource; this change prevents such an object |
| | 14050 | from being chosen as its own default fire source in a command like |
| | 14051 | LIGHT CANDLE, which would cause an infinite loop as we tried to light |
| | 14052 | the candle with itself, which would require first lighting the |
| | 14053 | candle, which would default to lighting it with itself again, and so |
| | 14054 | on. |
| | 14055 | |
| | 14056 | <p>The FireSource and Matchstick classes have also been fine-tuned to |
| | 14057 | work together a little better. The FireSource class now specifies a |
| | 14058 | logicalRank of 150 when used as the indirect object of BurnWith. The |
| | 14059 | Matchstick class uses a logical rank of 160 when lit and 140 when not |
| | 14060 | lit. This makes a matchstick an especially logical choice for |
| | 14061 | starting a fire under all conditions, but makes a non-matchstick an |
| | 14062 | even better choice when it's already burning. A lit match trumps |
| | 14063 | everything (160), next best is an already-lit non-matchstick |
| | 14064 | FireSource (150), and when there's nothing else around that's |
| | 14065 | burning, a matchstick will still be a good choice (140). This |
| | 14066 | ensures that we don't light a new match when there's another fire |
| | 14067 | source readily at hand, but at the same time ensures that we'll |
| | 14068 | default to using a match when no better choice is available. |
| | 14069 | |
| | 14070 | </div> |
| | 14071 | |
| | 14072 | <!-------------------> |
| | 14073 | <div class=entry> |
| | 14074 | |
| | 14075 | When an implicit action is interrupted with an interactive prompt, |
| | 14076 | the announcement of the implicit action is now phrased as "trying" |
| | 14077 | the action. This is along the same lines as the change in 3.0.6k |
| | 14078 | that phrased failed implicit actions as "trying"; since an interactive |
| | 14079 | prompt interrupts an implied action, it makes more sense to refer to |
| | 14080 | the implied action as being merely attempted at this stage. |
| | 14081 | |
| | 14082 | <p>Internally, the announcement generator distinguishes between |
| | 14083 | failed actions and actions interrupted for interactive input, so it's |
| | 14084 | a fairly easy matter to customize the types of messages separately. |
| | 14085 | To customize the "asking" case separately from the "trying" case, |
| | 14086 | customize the askingImpCtx object; in particular, override its |
| | 14087 | buildImplicitAnnouncement() method and its useInfPhrase property as |
| | 14088 | needed. The default in the library is to use the same message |
| | 14089 | style for both cases. |
| | 14090 | |
| | 14091 | </div> |
| | 14092 | |
| | 14093 | <!-------------------> |
| | 14094 | <div class=entry> |
| | 14095 | |
| | 14096 | Due to a bug in the library, using "exit" to abort an action from |
| | 14097 | within a check() handler did not properly mark the action as failed |
| | 14098 | within the transcript, which meant that the "trying" form of an |
| | 14099 | implicit action announcement was not generated. This has been |
| | 14100 | corrected. |
| | 14101 | |
| | 14102 | </div> |
| | 14103 | |
| | 14104 | <!-------------------> |
| | 14105 | <div class=entry> |
| | 14106 | |
| | 14107 | In the past, when an implied action was remapped to another action |
| | 14108 | (via remapTo), the normal announcement of the implied action wasn't |
| | 14109 | generated. This has been corrected: the announcement will now be |
| | 14110 | shown as usual. |
| | 14111 | |
| | 14112 | </div> |
| | 14113 | |
| | 14114 | <!-------------------> |
| | 14115 | <div class=entry> |
| | 14116 | |
| | 14117 | The parser is now a little smarter about excluding items with ALL |
| | 14118 | EXCEPT in cases of simple remappings. In many cases, remapTo is used |
| | 14119 | to create simple object-to-object synonyms for certain verbs; for |
| | 14120 | example, OPEN DESK might be remapped to OPEN DRAWER when it's obvious |
| | 14121 | that the two commands mean the same thing. In these cases, when an |
| | 14122 | object is excluded from the ALL list with EXCEPT, the parser will now |
| | 14123 | look for these simple synonym remappings, and it will treat them as |
| | 14124 | equivalent. So, if OPEN DESK is remapped to OPEN DRAWER, and the |
| | 14125 | player types OPEN ALL BUT DESK or OPEN ALL BUT DRAWER, then the desk |
| | 14126 | and drawer will be excluded from the ALL list. |
| | 14127 | |
| | 14128 | <p>Note that the parser can only exclude synonym remappings when |
| | 14129 | they're remapped using the remapTo (or maybeRemapTo) mechanism. |
| | 14130 | Remappings that are done using replaceAction() or the like can't |
| | 14131 | be detected as synonyms, so they won't be excluded. Remappings |
| | 14132 | that aren't simple synonyms won't be excluded, since remapping |
| | 14133 | to different verbs or word orders changes the meaning of the |
| | 14134 | command enough that the EXCEPT list shouldn't exclude the new |
| | 14135 | objects. For example, if OPEN DOOR remaps to PUSH BUTTON, because |
| | 14136 | a button is used to operate a mechanical door, OPEN ALL BUT BUTTON |
| | 14137 | would <b>not</b> exclude the remapping to PUSH BUTTON, since we |
| | 14138 | didn't say not to PUSH the button, only not to OPEN the button. |
| | 14139 | |
| | 14140 | </div> |
| | 14141 | |
| | 14142 | <!-------------------> |
| | 14143 | <div class=entry> |
| | 14144 | |
| | 14145 | The standard "weak vocabulary" checking in Thing now takes into account |
| | 14146 | truncatable vocabulary words, as well as any other special dictionary |
| | 14147 | comparison rules, by using the main dictionary's string comparator |
| | 14148 | to check for weak tokens. Note that this routine uses the global |
| | 14149 | property languageGlobals.dictComparator, so if the game ever changes |
| | 14150 | the main dictionary's string comparator object, it should also change |
| | 14151 | this global property at the same time. |
| | 14152 | |
| | 14153 | </div> |
| | 14154 | |
| | 14155 | <!-------------------> |
| | 14156 | <div class=entry> |
| | 14157 | |
| | 14158 | The Topic class now specifically disallows sensing a topic object |
| | 14159 | with any physical senses. This ensures that a topic object will |
| | 14160 | never be in any physical scope, even if the object is part of a |
| | 14161 | containment hierarchy. (It's sometimes convenient to include a topic |
| | 14162 | as part of a containment hierarchy in order to associate the topic |
| | 14163 | with a physical game world object.) |
| | 14164 | |
| | 14165 | </div> |
| | 14166 | |
| | 14167 | <!-------------------> |
| | 14168 | <div class=entry> |
| | 14169 | |
| | 14170 | The possessive qualifier resolver (PossessiveResolver) now considers |
| | 14171 | an object to be in scope in a possessive phrase only if the object |
| | 14172 | has the property canResolvePossessive set to true. This property is |
| | 14173 | true by default for all Things and nil by default for all Topics. In |
| | 14174 | other words, by default, possessive phrase qualifiers can only be |
| | 14175 | resolved to physical game world objects, never to abstract topics. |
| | 14176 | |
| | 14177 | </div> |
| | 14178 | |
| | 14179 | <!------------------------------- 3.0.6k ---------------------------------> |
| | 14180 | <div class="sepbar"><a name='306k'></a>3.0.6k</div> |
| | 14181 | <p><b><i>Released August 17, 2003</i></b> |
| | 14182 | <p> |
| | 14183 | |
| | 14184 | <div class=firstentry> |
| | 14185 | |
| | 14186 | The new TopicEntry method isMatchPossible() tries to guess whether or |
| | 14187 | not the TopicEntry can be matched by any input currently. This |
| | 14188 | question is unanswerable in general, because it's asking if there |
| | 14189 | exists any input, out of the infinite set of possible inputs, that |
| | 14190 | will match the topic entry. However, the TopicEntry subclasses use |
| | 14191 | heuristics to provide an answer that's right in most cases. In |
| | 14192 | particular, the ASK and TELL entries consider themselves matchable if |
| | 14193 | any of their matchObj objects are either known to the player character |
| | 14194 | or are simply in scope; the GIVE and SHOW entries are considered |
| | 14195 | matchable if any of their matchObj objects are in scope; and YES, NO, |
| | 14196 | and special topic entries are always considered matchable. If a game |
| | 14197 | creates a custom matchTopic() method, it might want to customize |
| | 14198 | isMatchPossible() to match the custom match condition. |
| | 14199 | |
| | 14200 | <p>The SuggestedTopic method isSuggestionActive() uses this new |
| | 14201 | method to hide suggestions that aren't currently matchable. This |
| | 14202 | provides an important benefit for the most common cases: topics won't |
| | 14203 | be suggested until the player character knows about them. This |
| | 14204 | avoids showing suggestions for things the player shouldn't even |
| | 14205 | have heard of yet. |
| | 14206 | |
| | 14207 | <p>To facilitate this change, isSuggestionActive() now takes an |
| | 14208 | additional argument, giving the list of in-scope objects. This |
| | 14209 | avoids the need to repeatedly compute the scope list when scanning |
| | 14210 | a large list of suggested topic objects, which is important because |
| | 14211 | the scope calculation is complex and can be time-consuming. |
| | 14212 | |
| | 14213 | </div> |
| | 14214 | |
| | 14215 | <!-------------------> |
| | 14216 | <div class=entry> |
| | 14217 | |
| | 14218 | Some important terminology for TopicEntry objects has been changed: |
| | 14219 | where we formerly referred to a TopicEntry as "known," we now refer to |
| | 14220 | it as "active" instead. The old terminology implied that TopicEntry |
| | 14221 | objects model NPC knowledge; this was misleading, though, because the |
| | 14222 | availability of a TopicEntry often depends on PC knowledge as well as |
| | 14223 | NPC knowledge, or what the NPC <i>wishes</i> to reveal rather than |
| | 14224 | what the NPC actually knows, or various other things. The new |
| | 14225 | terminology removes the implication that NPC knowledge in particular |
| | 14226 | is being modeled. |
| | 14227 | |
| | 14228 | <p>This change requires new names for several TopicEntry properties: |
| | 14229 | isKnown is now isActive; checkIsKnown is now checkIsActive; and |
| | 14230 | topicGroupKnown is now topicGroupActive. |
| | 14231 | |
| | 14232 | <p>Game code that uses TopicEntry objects will have to rename isKnown |
| | 14233 | to isActive in the object definitions. The other renamed properties |
| | 14234 | might have to be changed as well, of course, but these are less likely |
| | 14235 | to appear in game code. |
| | 14236 | |
| | 14237 | </div> |
| | 14238 | |
| | 14239 | <!-------------------> |
| | 14240 | <div class=entry> |
| | 14241 | |
| | 14242 | The travel precondition mechanism has been tweaked a little to make it |
| | 14243 | more flexible for handling nested-room situations. In the past, each |
| | 14244 | travel connector was responsible for providing a precondition applied |
| | 14245 | whenever an actor traversed the connector, via the travel connector's |
| | 14246 | actorTravelPreCond(actor) method. This formerly returned the |
| | 14247 | actorStanding precondition. While this was appropriate in most cases, |
| | 14248 | since it ensured that the actor wasn't sitting in a chair or anything |
| | 14249 | like that, it didn't make for easy customization for specialized nested |
| | 14250 | rooms or other unusual situations. |
| | 14251 | |
| | 14252 | <p>The change is that TravelConnector.actorTravelPreCond(actor) now |
| | 14253 | returns a new precondition, actorTravelReady, instead of |
| | 14254 | actorStanding. The actorTravelReady precondition abstracts the travel |
| | 14255 | condition by letting the actor's immediate location handle it. In |
| | 14256 | particular, it calls three new BasicLocation methods to carry out the |
| | 14257 | precondition: isActorTravelReady(conn), tryMakingTravelReady(conn), |
| | 14258 | and notTravelReadyMsg. By default, these methods do exactly what |
| | 14259 | actorStanding does: they require the actor to be standing up before |
| | 14260 | travel. However, a location can override any or all of these. For |
| | 14261 | example, a particular nested room might want to use a command other |
| | 14262 | than "stand up" to get the actor out of the nested room in preparation |
| | 14263 | for travel; the nested room could override tryMakingActorTravelReady() |
| | 14264 | in this case to carry out the desired implied command. |
| | 14265 | |
| | 14266 | <p>Note that the travel connector to be traversed is an argument to |
| | 14267 | the first two of the new methods. This allows the actor's current |
| | 14268 | location to impose different requirements on travel via different |
| | 14269 | connectors. For example, it might be necessary to climb down from a |
| | 14270 | ladder before leaving via any connector except for a window high up on |
| | 14271 | the wall, which can only be reached when on the ladder. |
| | 14272 | |
| | 14273 | </div> |
| | 14274 | |
| | 14275 | <!-------------------> |
| | 14276 | <div class=entry> |
| | 14277 | |
| | 14278 | The new Action method cancelIteration() lets you tell cancel further |
| | 14279 | iteration of the current action, if multiple objects are involved in |
| | 14280 | the action. You can call this method on the current gAction object |
| | 14281 | during the 'check' or 'action' phases of execution. Once the method |
| | 14282 | is called, the action will complete the execution cycle for the |
| | 14283 | current object as normal, but it will then act as though the current |
| | 14284 | object were the last object of the command. |
| | 14285 | |
| | 14286 | <p>Note that this new method does <b>not</b> have any effect on the |
| | 14287 | execution of the command for the current object; in particular, it |
| | 14288 | doesn't interrupt the execution flow the way 'exit' and the like do. |
| | 14289 | Instead, this method simply sets a flag in the current Action object |
| | 14290 | telling it to ignore any additional objects it would otherwise |
| | 14291 | iterate over. If you want to jump out of the execution cycle in |
| | 14292 | addition to canceling further iteration, simply use 'exit' (or one of |
| | 14293 | the similar signals) after calling this method. Note also that this |
| | 14294 | method obviously can't cancel the iteration for any prior objects in |
| | 14295 | the iteration. |
| | 14296 | |
| | 14297 | </div> |
| | 14298 | |
| | 14299 | <!-------------------> |
| | 14300 | <div class=entry> |
| | 14301 | |
| | 14302 | In the status-line and menu modules, there were some unnecessary |
| | 14303 | "flush" operations (on banners and on the main window). Most of these |
| | 14304 | were placed before "sizeToContents" calls on banners, which is |
| | 14305 | unnecessary because that operation automatically flushes the |
| | 14306 | underlying output stream anyway. These extra calls were not only |
| | 14307 | unnecessary but were also undesirable, because the explicit flush |
| | 14308 | operations always update the display immediately in addition to |
| | 14309 | flushing internal text buffers. This made the display flicker |
| | 14310 | annoyingly at times. The extra flushes have been removed, which |
| | 14311 | makes the display updating faster and eliminates the flicker in |
| | 14312 | the common cases covered by the changes. |
| | 14313 | |
| | 14314 | </div> |
| | 14315 | |
| | 14316 | <!-------------------> |
| | 14317 | <div class=entry> |
| | 14318 | |
| | 14319 | When a MenuLongTopicItem is part of a series of "chapters" (as |
| | 14320 | indicated by the isChapterMenu property), and the user navigates |
| | 14321 | directly from one chapter to the next, the menu system keeps the |
| | 14322 | banner configuration for the chapter display throughout the change |
| | 14323 | to the new chapter. In the past, the menu system removed the banner |
| | 14324 | and then immediately restored it, which caused some visual flicker. |
| | 14325 | This change eliminates the flicker during the chapter change. |
| | 14326 | |
| | 14327 | </div> |
| | 14328 | |
| | 14329 | <!-------------------> |
| | 14330 | <div class=entry> |
| | 14331 | |
| | 14332 | The English implicitAnnouncementGrouper implementation now uses |
| | 14333 | pronouns, where appropriate, to refer to repeated objects when it |
| | 14334 | groups a series of announcements. It frequently happens that the same |
| | 14335 | object appears more than once when a series of implied actions is |
| | 14336 | performed; this new phrasing makes the announcement text shorter and |
| | 14337 | makes it read more naturally. For example, rather than saying "first |
| | 14338 | unlocking the door, then opening the door", we'll now say "first |
| | 14339 | unlocking the door, then opening it". |
| | 14340 | |
| | 14341 | </div> |
| | 14342 | |
| | 14343 | <!-------------------> |
| | 14344 | <div class=entry> |
| | 14345 | |
| | 14346 | The implicit action announcement mechanism now phrases the |
| | 14347 | announcement for a failed action a little differently than for a |
| | 14348 | successful action. When an action fails, the message now reads |
| | 14349 | "(first trying to ...)". The old phrasing was a little awkward at |
| | 14350 | times, because the announcement describes the action as being |
| | 14351 | performed, and then the (usually) very next message says just the |
| | 14352 | opposite, that the action wasn't performed at all because it failed. |
| | 14353 | Depending on the wording of the failure message, the combination could |
| | 14354 | even be misleading on occasion, since the suggestion in the |
| | 14355 | announcement that the action was performed could lead to a player |
| | 14356 | assuming that the failure message must refer to something else. |
| | 14357 | |
| | 14358 | <p>To enable this change, the interface to the libMessages method |
| | 14359 | announceImplicitAction() has changed slightly. The method now takes a |
| | 14360 | "context" parameter, which is an object of class |
| | 14361 | ImplicitAnnouncementContext The context contains information on the |
| | 14362 | format of the message to be generated. |
| | 14363 | |
| | 14364 | <p>Also, the implicitGroupTransform internally scans for failure |
| | 14365 | messages that apply to implied action announcements, and rewrites the |
| | 14366 | implied action announcements into the new format when failures are |
| | 14367 | noted. |
| | 14368 | |
| | 14369 | <p>Finally, the implicitAnnouncementGrouper object implementation in |
| | 14370 | the English module does some additional grouping, to render a series |
| | 14371 | of "trying" messages as readably as possible. When a series of |
| | 14372 | consecutive "trying" messages appears, the grouper combines them under |
| | 14373 | a single "trying" phrase, as in "first trying to unlock the door and |
| | 14374 | then open it." |
| | 14375 | |
| | 14376 | </div> |
| | 14377 | |
| | 14378 | <!-------------------> |
| | 14379 | <div class=entry> |
| | 14380 | |
| | 14381 | Several small internal changes have been made in the English library |
| | 14382 | module. |
| | 14383 | |
| | 14384 | <p>First, the new method getInfPhrase() returns a string giving the |
| | 14385 | full action description in infinitive form. This returns a phrase |
| | 14386 | such as "open the box" or "unlock the door with the key". The verb is |
| | 14387 | always in the infinitive form, but note that the English infinitive |
| | 14388 | complementizer, "to", is not part of the returned phrase; this is |
| | 14389 | because an infinitive is used without a complementizer in certain |
| | 14390 | contexts in English, such as with auxiliary verbs (such as "might" or |
| | 14391 | "should"). |
| | 14392 | |
| | 14393 | <p>Second, the new method getVerbPhrase(inf, ctx) returns the full |
| | 14394 | verb phrase in either the infinitive form ("open the box") or the |
| | 14395 | present participle form ("opening the box"). In English, the two |
| | 14396 | forms are equivalent except for the verb ending, so the code to |
| | 14397 | generate both forms can be easily consolidated into a single routine. |
| | 14398 | The subclasses of Action override getVerbPhrase() as needed to provide |
| | 14399 | appropriate phrasings. The context object 'ctx' is optional; if it's |
| | 14400 | not nil, it should be an instance of the new class |
| | 14401 | GetVerbPhraseContext. If the context object is provided, the routine |
| | 14402 | uses it to keep track of pronoun antecedents for the verb phrase; the |
| | 14403 | returned verb phrase will use a pronoun if one of its objects matches |
| | 14404 | the current antecedent, and the routine will set the antecedent in the |
| | 14405 | context for the next verb phrase that uses the same context. The |
| | 14406 | context is useful if you're generating a series of verb phrases that |
| | 14407 | you're going to string together into a single sentence; by using |
| | 14408 | pronouns to refer to repeated objects, the sentence will be shorter |
| | 14409 | and will read more naturally. |
| | 14410 | |
| | 14411 | <p>Third, the implementation of getParticiplePhrase() now simply |
| | 14412 | calls getVerbPhrase() in all cases. |
| | 14413 | |
| | 14414 | <p>Fourth, the routine formerly called verbInf() has been renamed to |
| | 14415 | getQuestionInf(), to better describe its purpose. This routine |
| | 14416 | doesn't return the full infinitive form of the verb, but rather |
| | 14417 | returns an infinitive form specifically for an interrogative in which |
| | 14418 | one of the verb's objects is the interrogative's unknown. The old |
| | 14419 | name was always misleading, but the addition of getInfPhrase() would |
| | 14420 | have made the name even more confusing because of the similarity of |
| | 14421 | the names. |
| | 14422 | |
| | 14423 | </div> |
| | 14424 | |
| | 14425 | <!-------------------> |
| | 14426 | <div class=entry> |
| | 14427 | |
| | 14428 | In the routine that tries to free up space in an actor's hands by |
| | 14429 | moving objects into a "bag of holding," objects with no encumbering |
| | 14430 | bulk are now never moved. In the past, objects were moved in |
| | 14431 | descending order of encumbering bulk, so objects with zero bulk were |
| | 14432 | typically ignored; however, if there weren't enough bulky objects |
| | 14433 | present, it was possible for the routine to try moving bulkless items. |
| | 14434 | Since worn items have no encumbering bulk by default, this meant the |
| | 14435 | routine sometimes removed worn items and moved them to the bag, which |
| | 14436 | was pointless. |
| | 14437 | |
| | 14438 | </div> |
| | 14439 | |
| | 14440 | <!-------------------> |
| | 14441 | <div class=entry> |
| | 14442 | |
| | 14443 | The new class FloorlessRoom, a subclass of Room, makes it easier to |
| | 14444 | build rooms that represent locations without conventional floors. |
| | 14445 | Anything dropped in the room is described as falling and vanishing |
| | 14446 | below, since there's no floor for it to land on. You can control |
| | 14447 | where dropped objects land using the bottomRoom property; by default, |
| | 14448 | this is nil, which means that dropped objects simply disappear |
| | 14449 | from the game. |
| | 14450 | |
| | 14451 | </div> |
| | 14452 | |
| | 14453 | <!-------------------> |
| | 14454 | <div class=entry> |
| | 14455 | |
| | 14456 | The Room class no longer requires the room's floor to be represented |
| | 14457 | by the first element of the roomParts list for the room. Instead, the |
| | 14458 | new method roomFloor returns the room's floor object; this method |
| | 14459 | finds an object of class Floor in the roomParts list and returns it, |
| | 14460 | or nil if there no object of class Floor in the list. This change |
| | 14461 | eliminates the fragility caused by the former convention. |
| | 14462 | |
| | 14463 | </div> |
| | 14464 | |
| | 14465 | <!-------------------> |
| | 14466 | <div class=entry> |
| | 14467 | |
| | 14468 | A new mechanism provides more consistent handling when objects |
| | 14469 | are dropped into a room. The new mechanism is used in the library |
| | 14470 | to handle the DROP and THROW commands, both of which can result in |
| | 14471 | an object being dropped into the enclosing room. The mechanism is |
| | 14472 | extensible, so library extensions and games can add their own actions |
| | 14473 | that drop objects into the room. |
| | 14474 | |
| | 14475 | <p>Whenever an object is to be dropped into the enclosing room, the |
| | 14476 | DROP and THROW commands first find the drop destination using the |
| | 14477 | existing getDropDestination() method. Then, they invoke the new |
| | 14478 | receiveDrop(obj, desc) method on the drop destination object. In most |
| | 14479 | cases, the drop location is the enclosing room, so the enclosing |
| | 14480 | room's receiveDrop() method is usually the one that will be invoked. |
| | 14481 | |
| | 14482 | <p>The receiveDrop() method is responsible for carrying out the |
| | 14483 | effects of dropping the object, including any game-state changes (such |
| | 14484 | as moving the dropped to its new location) <i>and</i> reporting the |
| | 14485 | results of the action. |
| | 14486 | |
| | 14487 | <p>In most cases, the effects won't vary according to which command |
| | 14488 | was used to discard the object. This is the reason that there's only |
| | 14489 | one receiveDrop() method, rather than separate methods for DROP, |
| | 14490 | THROW, and any library extension or game-specific verbs. By using a |
| | 14491 | common routine to handle all means of discarding an object, the game |
| | 14492 | only has to implement any special handling once. |
| | 14493 | |
| | 14494 | <p>However, the <i>message</i> will almost always vary according to |
| | 14495 | the command, for the simple reason that the message needs to |
| | 14496 | acknowledge what the actor did to discard the item in addition to the |
| | 14497 | effects of dropping it. This is the main reason the 'desc' argument |
| | 14498 | is provided: it's a special "drop descriptor" object that lets you |
| | 14499 | find out what command was used. You could also look at gAction to |
| | 14500 | find the Action being performed, but the descriptor object makes your |
| | 14501 | job a lot easier by providing some convenience methods for building |
| | 14502 | report messages. |
| | 14503 | |
| | 14504 | <p>The descriptor object is of class DropType. This class has two |
| | 14505 | important methods. First, standardReport() displays the "normal" |
| | 14506 | report for the action. For DROP, this is simply "Dropped." For |
| | 14507 | THROW, this is a message of the form "The ball hits the desk, and |
| | 14508 | falls to the floor." You can use the standard report when your |
| | 14509 | receiveDrop() method doesn't do anything out of the ordinary and thus |
| | 14510 | doesn't require a special report. Second, getReportPrefix() returns a |
| | 14511 | string that gives the <i>start</i> of a sentence describing the |
| | 14512 | action. The returned string is a complete main clause for a sentence |
| | 14513 | -- but it has no ending punctuation, so you can add more to the |
| | 14514 | sentence if you like. The main clause will always be written so that |
| | 14515 | the object being dropped will be the logical antecedent for any |
| | 14516 | pronouns in subsequent text, which lets you tack on a string like |
| | 14517 | this: ", and it falls to the floor." |
| | 14518 | |
| | 14519 | <p>Rather than building a message from the report prefix provided by |
| | 14520 | the descriptor, you are free to build a completely custom message, if |
| | 14521 | you prefer. To do this, you could use 'modify' to add your own method |
| | 14522 | to each DropType subclass in the library, and then call this method |
| | 14523 | from your receiveDrop(). Alternatively, you could use ofKind() to |
| | 14524 | check what kind of DropType descriptor you got, and show custom |
| | 14525 | messages for the ones you recognize. |
| | 14526 | |
| | 14527 | </div> |
| | 14528 | |
| | 14529 | <!-------------------> |
| | 14530 | <div class=entry> |
| | 14531 | |
| | 14532 | Thing.stopThrowViaPath() now simply calls throwTargetHitWith() by default. |
| | 14533 | When an object interrupts a projectile's course, the result is exactly as |
| | 14534 | though the projectile had been successfully thrown at the interrupting |
| | 14535 | object, so the separate implementations were redundant. |
| | 14536 | |
| | 14537 | </div> |
| | 14538 | |
| | 14539 | <!-------------------> |
| | 14540 | <div class=entry> |
| | 14541 | |
| | 14542 | finishGame() now resets the sense context. This ensures that if the |
| | 14543 | event that triggered the end of the game happened while a blocking |
| | 14544 | sense context was in effect, the finish options are still listed. |
| | 14545 | (Since the finish options involve direct interaction with the player, |
| | 14546 | they obviously shouldn't be displayed in any NPC sense context.) |
| | 14547 | |
| | 14548 | </div> |
| | 14549 | |
| | 14550 | <!-------------------> |
| | 14551 | <div class=entry> |
| | 14552 | |
| | 14553 | Thing now has a constructor, which calls initializeThing(). This ensures |
| | 14554 | that any Thing objects that are created dynamically (with 'new') are |
| | 14555 | initialized in the same manner as objects defined statically. |
| | 14556 | |
| | 14557 | </div> |
| | 14558 | |
| | 14559 | <!-------------------> |
| | 14560 | <div class=entry> |
| | 14561 | |
| | 14562 | The library's handling of RESTART has been changed slightly to correct |
| | 14563 | a problem that cropped up under certain unusual circumstances. The |
| | 14564 | old handling reset the VM within the Restart action execution method, |
| | 14565 | and then threw a RestartSignal to tell the main loop to re-enter the |
| | 14566 | game from the beginning. This approach had a subtle flaw: if any |
| | 14567 | dynamically-created objects were referenced from an intermediate stack |
| | 14568 | frame in the code that initiated the restart, those objects were |
| | 14569 | retained through the VM reset because they were still accessible via |
| | 14570 | the stack. These objects then had a chance to remain visible to an |
| | 14571 | object loop, such as those that run during the library |
| | 14572 | pre-initialization. The Restart action handler now simply throws the |
| | 14573 | RestartSignal to the main loop, and the main loop now performs the VM |
| | 14574 | reset. This ensures that the stack is reset to initial conditions |
| | 14575 | before the VM reset occurs, which in turn ensures that only those |
| | 14576 | dynamic objects that should survive the reset do survive the reset. |
| | 14577 | |
| | 14578 | </div> |
| | 14579 | |
| | 14580 | <!------------------------------- 3.0.6j ---------------------------------> |
| | 14581 | <div class="sepbar"><a name='306j'></a>3.0.6j</div> |
| | 14582 | <p><b><i>Released August 2, 2003</i></b> |
| | 14583 | <p> |
| | 14584 | |
| | 14585 | <div class=firstentry> |
| | 14586 | |
| | 14587 | The new class DistanceConnector is a specialized subclass of |
| | 14588 | SenseConnector that allows two (or more) locations to be connected, |
| | 14589 | but at a distance. This is handy for situations such as divided rooms |
| | 14590 | (where we use two or more Room objects to model a single large |
| | 14591 | physical location), and for cases where two rooms are open to one |
| | 14592 | another (such as a balcony overlooking a courtyard). |
| | 14593 | |
| | 14594 | </div> |
| | 14595 | |
| | 14596 | <!-------------------> |
| | 14597 | <div class=entry> |
| | 14598 | |
| | 14599 | The new class Vaporous is a subclass of Intangible designed for |
| | 14600 | insubstantial but visible objects, such as fire, smoke, and fog. |
| | 14601 | This class works a lot like Intangible, but it has a visual presence, |
| | 14602 | and it specifically allows the commands Examine, Smell, and Listen To; |
| | 14603 | in addition, it allows the commands Look In, Look Under, Look Behind, Look |
| | 14604 | Through, and Search, and responds to these with "You just see (the |
| | 14605 | object)." |
| | 14606 | |
| | 14607 | </div> |
| | 14608 | |
| | 14609 | <!-------------------> |
| | 14610 | <div class=entry> |
| | 14611 | |
| | 14612 | The Lister class no longer sets the 'seen' attribute of objects it |
| | 14613 | lists, because this attribute is now more generally handled in the |
| | 14614 | main room description routines (per the change in meaning of 'seen' |
| | 14615 | in 3.0.6i). As a result, the Lister.markAsSeen method has been |
| | 14616 | removed. |
| | 14617 | |
| | 14618 | </div> |
| | 14619 | |
| | 14620 | <!-------------------> |
| | 14621 | <div class=entry> |
| | 14622 | |
| | 14623 | A new macro, gSetKnown(obj), marks an object (usually a Thing or a |
| | 14624 | Topic) as known by the player character. This is simply short-hand |
| | 14625 | for obj.setKnownBy(gPlayerChar, true), for convenience. |
| | 14626 | |
| | 14627 | </div> |
| | 14628 | |
| | 14629 | <!-------------------> |
| | 14630 | <div class=entry> |
| | 14631 | |
| | 14632 | The EventList object has been enhanced slightly to accept property |
| | 14633 | pointer entries. A property pointer entry is interpreted as a |
| | 14634 | property to invoke on the EventList itself, with no argument. This |
| | 14635 | allows writing complex steps as separate properties of the EventList |
| | 14636 | object, and then referring to them from the script by property |
| | 14637 | pointer. |
| | 14638 | |
| | 14639 | <p>In addition, the ScriptEvent class has been eliminated. Instead, |
| | 14640 | simply use Script objects in an event list. So, when an object |
| | 14641 | appears in an event list, the EventList class now invokes the |
| | 14642 | object's doScript() method. This makes it easy to build event lists |
| | 14643 | recursively. |
| | 14644 | |
| | 14645 | <p>The new EventList subclasses CyclicEventList and StopEventList |
| | 14646 | provide new pre-defined options for the behavior of an event list |
| | 14647 | after visiting all elements. The new subclass SyncEventList provides |
| | 14648 | a list that synchronizes its state with another list. |
| | 14649 | |
| | 14650 | <p>The TextList, StopTextList, and SyncTextList classes are now |
| | 14651 | simple subclasses of CyclicEventList, StopEventList, and |
| | 14652 | SyncEventList, respectively. |
| | 14653 | |
| | 14654 | <p>A new EventList method, scriptDone(), is invoked by doScript() |
| | 14655 | after it processes the script's current step. By default, this |
| | 14656 | method simply invokes advanceState() to advance the event list to |
| | 14657 | its next state. Subclasses can override scriptDone() so that it |
| | 14658 | does not advance the script's state, or does something else in |
| | 14659 | addition. |
| | 14660 | |
| | 14661 | <p>The new EventList subclass ExternalEventList overrides scriptDone() |
| | 14662 | so that the method does nothing. This makes it easy to create an |
| | 14663 | event list that is driven externally; that is, the event list doesn't |
| | 14664 | advance its state when doScript() is invoked, but only advances its |
| | 14665 | state in response to some external processing that calls |
| | 14666 | advanceState() directly on the event list object. |
| | 14667 | |
| | 14668 | </div> |
| | 14669 | |
| | 14670 | <!-------------------> |
| | 14671 | <div class=entry> |
| | 14672 | |
| | 14673 | The Room class now provides a dobjFor(Examine) that replaces the |
| | 14674 | Examine action with a Look action. This means that if a Room object |
| | 14675 | has ordinary vocabulary words defined, and the player types EXAMINE |
| | 14676 | (room), the command will automatically be treated as though the |
| | 14677 | player had typed LOOK AROUND. |
| | 14678 | |
| | 14679 | </div> |
| | 14680 | |
| | 14681 | <!-------------------> |
| | 14682 | <div class=entry> |
| | 14683 | |
| | 14684 | The new class IndirectLockable is a subclass of Lockable that |
| | 14685 | can be used for situations where a lockable object cannot have |
| | 14686 | its locked status directly manipulated by LOCK and UNLOCK commands. |
| | 14687 | The reply to LOCK and UNLOCK can be customized via the object's |
| | 14688 | cannotLockMsg and cannotUnlockMsg properties. |
| | 14689 | |
| | 14690 | </div> |
| | 14691 | |
| | 14692 | <!-------------------> |
| | 14693 | <div class=entry> |
| | 14694 | |
| | 14695 | The Lockable class now handles the 'objUnlocked' precondition a little |
| | 14696 | more subtly. The class now keeps track of whether or not the player |
| | 14697 | knows the object to be locked; the status is assumed to be unknown |
| | 14698 | initially. When the player doesn't know the status, the Open action |
| | 14699 | does <b>not</b> apply an objUnlocked precondition, but instead disallows |
| | 14700 | the action in the check() routine. When the status is known, the |
| | 14701 | objUnlocked precondition is applied as before. Whenever the Open |
| | 14702 | action fails in the check() due to the object being locked, the |
| | 14703 | status is taken to be known for subsequent attempts. |
| | 14704 | |
| | 14705 | <p>This change makes the precondition handling a little more |
| | 14706 | intelligent. When the player doesn't know the status beforehand, an |
| | 14707 | Open command will simply fail with the discovery that the object is |
| | 14708 | locked. This usually makes more sense than attempting to unlock the |
| | 14709 | object automatically with an implied Unlock command, because if the |
| | 14710 | object isn't already known to be locked, there's no reason to try to |
| | 14711 | unlock it. When the status is known, however, it makes sense to |
| | 14712 | perform the implied Unlock. |
| | 14713 | |
| | 14714 | <p>Objects whose lock status is visibly apparent can be marked as such |
| | 14715 | with the lockStatusObvious property. This property is nil by default; |
| | 14716 | an object whose lock status can be visibly observed should set this to |
| | 14717 | true. When this property is set, the lock status is <i>always</i> |
| | 14718 | known, since we'll assume that actors will simply look at the lock and |
| | 14719 | observe the status. In addition, when this property is set, we'll add |
| | 14720 | the locked/unlocked status at the end of the object's 'Examine' |
| | 14721 | description (we'll add "It's currently locked" or "It's currently |
| | 14722 | unlocked"). |
| | 14723 | |
| | 14724 | </div> |
| | 14725 | |
| | 14726 | <!-------------------> |
| | 14727 | <div class=entry> |
| | 14728 | |
| | 14729 | A new class, TravelWithMessage, can be mixed (using multiple inheritance) |
| | 14730 | with TravelConnector or a subclass of TravelConnector to create a connector |
| | 14731 | that shows a message as it's traversed. This is slightly more flexible |
| | 14732 | than using TravelMessage, since TravelMessage can't usually be mixed with |
| | 14733 | other TravelConnector-derived classes. |
| | 14734 | |
| | 14735 | </div> |
| | 14736 | |
| | 14737 | <!-------------------> |
| | 14738 | <div class=entry> |
| | 14739 | |
| | 14740 | A new TravelConnector property, stagingLocation, gives the location |
| | 14741 | in which a traveler must be located prior to traversing the connector. |
| | 14742 | In the past, the connector simply assumed the traveler needed |
| | 14743 | to be in the connector's direct location; this new property allows |
| | 14744 | this condition to be customized. At times, the connector might be |
| | 14745 | inside an intermediate container, for example, in which case the |
| | 14746 | staging location might be a container of the container. By default, |
| | 14747 | the staging location is the connector's location, so connectors that |
| | 14748 | don't override stagingLocation will have the same behavior as before. |
| | 14749 | |
| | 14750 | </div> |
| | 14751 | |
| | 14752 | <!-------------------> |
| | 14753 | <div class=entry> |
| | 14754 | |
| | 14755 | A new Thing method, roomLocation, returns the 'self' if the object |
| | 14756 | is capable of serving as a location for actors, or the nearest |
| | 14757 | container that is a roomLocation otherwise. |
| | 14758 | |
| | 14759 | <p>The Passage travel connector class now uses the other side's |
| | 14760 | container's roomLocation as the default destination of the passage, |
| | 14761 | rather than the other side's immediate container, as it did in the |
| | 14762 | past. This makes it much easier to create passages that model |
| | 14763 | non-trivial containment relationships, such as holes in walls, since |
| | 14764 | an intermediate container (between the Passage and the enclosing Room |
| | 14765 | or NestedRoom) will no longer create any confusion in performing the |
| | 14766 | travel. |
| | 14767 | |
| | 14768 | </div> |
| | 14769 | |
| | 14770 | <!-------------------> |
| | 14771 | <div class=entry> |
| | 14772 | |
| | 14773 | The NoTravelMessage class can now multiply inherit from Script, for |
| | 14774 | convenience in defining message lists. If you want to provide several |
| | 14775 | different messages to choose from when the connector is traversed, you |
| | 14776 | can make your connector object inherit from TextList as well as |
| | 14777 | NoTravelMessage, and the travelDesc() will automatically invoke the |
| | 14778 | script to show a message. |
| | 14779 | |
| | 14780 | </div> |
| | 14781 | |
| | 14782 | <!-------------------> |
| | 14783 | <div class=entry> |
| | 14784 | |
| | 14785 | <p>If the travel connector has a non-nil location, the TravelConnector |
| | 14786 | class's connectorTravelPreCond method adds a precondition that the |
| | 14787 | connector must be touchable. This ensures that characters won't be |
| | 14788 | allowed to traverse connectors that are visible but on the other side |
| | 14789 | of a window, for example, or connectors that are out of reach. |
| | 14790 | |
| | 14791 | </div> |
| | 14792 | |
| | 14793 | <!-------------------> |
| | 14794 | <div class=entry> |
| | 14795 | |
| | 14796 | The travel notification protocol has been changed very slightly. The |
| | 14797 | travel connector's noteTraversal() method is now invoked from within |
| | 14798 | the Traveler.travelerTravelTo() method rather than the TravelVia |
| | 14799 | handler in the connector. This change means that noteTraversal() |
| | 14800 | is called just before the traveler is actually moved, and in particular |
| | 14801 | that it occurs <i>after</i> all of the other travel notifications |
| | 14802 | (beforeTravel, actorTravel, and travelerLeaving). This is generally |
| | 14803 | the more desirable ordering for the notifications, because it puts |
| | 14804 | the connector's reaction closest to the actual traveler movement. |
| | 14805 | If you want the connector to do something special before any of the |
| | 14806 | other notifications, you can override the action() handler |
| | 14807 | in the connector's dobjFor(TravelVia) so that it performs the special |
| | 14808 | code and then inherits the base class handling. |
| | 14809 | |
| | 14810 | </div> |
| | 14811 | |
| | 14812 | <!-------------------> |
| | 14813 | <div class=entry> |
| | 14814 | |
| | 14815 | When an actor travels through a connector that leads to a location |
| | 14816 | with a posture other than the actor's original posture, the new |
| | 14817 | location now sets the actor's posture directly, rather than via a |
| | 14818 | nested action. For example, if a travel connector leads to a chair, |
| | 14819 | then traversing the connector will move the actor into the chair and |
| | 14820 | set the actor's posture to 'sitting', without activating a nested Sit |
| | 14821 | action. In the past, the nested Sit action would have been used |
| | 14822 | instead. This change is in BasicLocation.travelerArriving(), which |
| | 14823 | sets the new actor's posture via a call to Actor.makePosture(). |
| | 14824 | |
| | 14825 | <p>This change is generally desirable because we usually want arrival |
| | 14826 | by travel connector to be self-contained; we don't want it to appear |
| | 14827 | as though the character walked to the new location and only then |
| | 14828 | performed a SIT ON THE CHAIR command (say). It's worth noting, |
| | 14829 | however, that any side effects of the usual way of getting into the |
| | 14830 | new location's posture will be skipped. Therefore, when linking a |
| | 14831 | travel connector into a nested room with a non-standing posture, you'll |
| | 14832 | need to consider any side effects you'd want to trigger, and trigger |
| | 14833 | them explicitly on the travel connector itself. |
| | 14834 | |
| | 14835 | </div> |
| | 14836 | |
| | 14837 | <!-------------------> |
| | 14838 | <div class=entry> |
| | 14839 | |
| | 14840 | The new Actor method scriptedTravelTo() simplifies coding of scripted |
| | 14841 | travel for an actor. This routine is suitable for cases where an NPC |
| | 14842 | is to perform a series of scripted travel actions, where each room |
| | 14843 | along the way is scripted in advance. This routine is <i>not</i> |
| | 14844 | suitable for goal-seeking NPC's, because it can only perform travel to |
| | 14845 | a location adjacent to the actor's current location, and because it's |
| | 14846 | "omniscient" (it doesn't take into account the actor's knowledge of |
| | 14847 | the the map, but simply considers the actual map). For cases where |
| | 14848 | an NPC is to visit a scripted series of locations, this is a convenient |
| | 14849 | way to accomplish the travel, since it requires specifying only the |
| | 14850 | destination of each step of the travel. |
| | 14851 | |
| | 14852 | </div> |
| | 14853 | |
| | 14854 | <!-------------------> |
| | 14855 | <div class=entry> |
| | 14856 | |
| | 14857 | The class SecretDoor is now based on BasicOpenable as well as |
| | 14858 | ThroughPassage. The class previously didn't have BasicOpenable |
| | 14859 | anywhere among its superclasses, which prevented its open/closed |
| | 14860 | mechanisms (initiallyOpen, isOpen, makeOpen) from working |
| | 14861 | consistently with other types of doors, which are all based |
| | 14862 | (indirectly) on BasicOpenable. |
| | 14863 | |
| | 14864 | </div> |
| | 14865 | |
| | 14866 | <!-------------------> |
| | 14867 | <div class=entry> |
| | 14868 | |
| | 14869 | The new ThroughPassage subclass PathPassage is a specialization for |
| | 14870 | cases such as outdoor walkways, paths, and streets. The key |
| | 14871 | difference between the standard ThroughPassage and the more |
| | 14872 | specialized PathPassage is that path passages are not considered |
| | 14873 | enclosed, so the descriptions for arrival and departure via a path |
| | 14874 | take this into account. In the English messages, we describe travel |
| | 14875 | on a path as being "via" the path rather than "through" it. In |
| | 14876 | addition, the English parser accepts "take" as a synonym for "enter" |
| | 14877 | or "go through." |
| | 14878 | |
| | 14879 | <p>To handle this new class, TravelMessageHandler and its subclasses |
| | 14880 | have a new pair of methods, sayArrivingViaPath() and |
| | 14881 | sayDepartingViaPath(), for generating travel messages related to |
| | 14882 | paths. |
| | 14883 | |
| | 14884 | |
| | 14885 | </div> |
| | 14886 | |
| | 14887 | <!-------------------> |
| | 14888 | <div class=entry> |
| | 14889 | |
| | 14890 | The new method Actor.actorTravel(traveler, connector) complements |
| | 14891 | beforeTravel() and afterTravel(). This new method is called on the |
| | 14892 | actor who <b>initiated</b> the travel (that is, the actor performing |
| | 14893 | the command, if any); it's called after the beforeTravel() |
| | 14894 | notifications are sent to nearby objects. This method is provided for |
| | 14895 | symmetry with the beforeAction/actorAction/afterAction set. |
| | 14896 | |
| | 14897 | </div> |
| | 14898 | |
| | 14899 | <!-------------------> |
| | 14900 | <div class=entry> |
| | 14901 | |
| | 14902 | The AccompanyingState.accompanyTravel() method has been changed slightly. |
| | 14903 | The first parameter is now a Traveler object, which might be an Actor but |
| | 14904 | could also be another kind of Traveler, such as a Vehicle. This allows |
| | 14905 | the game to determine whether the NPC is to accompany actors when they |
| | 14906 | travel on vehicles or in other indirect ways. |
| | 14907 | |
| | 14908 | <p>In addition, the class's beforeAction() method, which responded to |
| | 14909 | the initiating actor's travel, has been changed to a beforeTravel() |
| | 14910 | method. This takes advantage of the more precise kind of notification |
| | 14911 | offered by beforeTravel(). In particular, using this method avoids |
| | 14912 | unnecessary attempts to accompany an actor who attempts a travel command |
| | 14913 | that doesn't actually result in travel (because the connector doesn't |
| | 14914 | go anywhere, for example). |
| | 14915 | |
| | 14916 | </div> |
| | 14917 | |
| | 14918 | <!-------------------> |
| | 14919 | <div class=entry> |
| | 14920 | |
| | 14921 | If a travel connector is located inside a nested room, the |
| | 14922 | preconditions for traversing the connector now correctly move the |
| | 14923 | character to the nested room prior to the travel. In the previous |
| | 14924 | library version, the enclosing room tried to add its own precondition |
| | 14925 | requiring the traveler to be in the outer room, which was incorrect. |
| | 14926 | |
| | 14927 | </div> |
| | 14928 | |
| | 14929 | <!-------------------> |
| | 14930 | <div class=entry> |
| | 14931 | |
| | 14932 | The Follow command now provides better feedback to the player in |
| | 14933 | certain cases. When the player has previously observed the target |
| | 14934 | actor departing, but from a different location than the player's |
| | 14935 | current location, the Follow command will now respond with the message |
| | 14936 | "You didn't see which we he went" (rather than "You can't do that from |
| | 14937 | here" as it did in the past). |
| | 14938 | |
| | 14939 | </div> |
| | 14940 | |
| | 14941 | <!-------------------> |
| | 14942 | <div class=entry> |
| | 14943 | |
| | 14944 | An Actor's executeTurn() method, and all of the methods it invokes |
| | 14945 | (the Actor's idleTurn() and the ActorState's takeTurn(), for |
| | 14946 | example), now run within a valid "action environment," just like |
| | 14947 | fuses and daemons started doing in 3.0.6i. In addition, the |
| | 14948 | executeTurn() method sets up a visual sense context for the actor, |
| | 14949 | ensuring that any output displayed in the course of the actor's turn |
| | 14950 | is displayed only when the actor is visible to the player character. |
| | 14951 | (It is presumed that the effects of any action that an actor performs |
| | 14952 | are visible if and only if the actor is visible. This is just the |
| | 14953 | default case, though: the game is always free to set up a separate |
| | 14954 | sense context, using callWithSenseContext(), whenever necessary.) |
| | 14955 | |
| | 14956 | <p>To facilitate this change and make it easier to override an actor's |
| | 14957 | per-turn processing, the main handling for an actor's turn is now in |
| | 14958 | a new method, executeActorTurn(). The executeTurn() method simply sets |
| | 14959 | up the action environment and then invokes executeActorTurn(). In most |
| | 14960 | cases, subclasses that need to specialize the per-turn processing should |
| | 14961 | override executeActorTurn() rather than executeTurn(), since this will |
| | 14962 | let the override run in the action environment. |
| | 14963 | |
| | 14964 | </div> |
| | 14965 | |
| | 14966 | <!-------------------> |
| | 14967 | <div class=entry> |
| | 14968 | |
| | 14969 | The optional initial "look around" that the runGame() function |
| | 14970 | performs is now executed within an "action environment," just like |
| | 14971 | fuses and daemons started doing in 3.0.6i. This allows the initial |
| | 14972 | room description to refer to gActor and gAction, which some library |
| | 14973 | methods do implicitly. |
| | 14974 | |
| | 14975 | </div> |
| | 14976 | |
| | 14977 | <!-------------------> |
| | 14978 | <div class=entry> |
| | 14979 | |
| | 14980 | callWithSenseContext() now uses "lazy evaluation": rather than |
| | 14981 | immediately calculating the effect of the new sense context, the |
| | 14982 | routine now simply notes that it has a new context, and defers |
| | 14983 | calculating the effects of the new context until the effects actually |
| | 14984 | need to be known. This makes it very inexpensive to set up a new |
| | 14985 | sense context in cases where the context won't actually be needed for |
| | 14986 | anything, which is frequently the case in daemons, fuses, and the |
| | 14987 | standard per-turn processing for NPC's. This can save a substantial |
| | 14988 | amount of time when a game has numerous background events if, as is |
| | 14989 | typical, most of the background events don't generate any output on a |
| | 14990 | given turn. |
| | 14991 | |
| | 14992 | </div> |
| | 14993 | |
| | 14994 | <!-------------------> |
| | 14995 | <div class=entry> |
| | 14996 | |
| | 14997 | The new macros actorStateDobjFor(action) and actorStateIobjFor(action) |
| | 14998 | make it convenient to delegate an actor's processing for an action to |
| | 14999 | the actor's current ActorState object. These are defined in adv3.h, |
| | 15000 | and work analogously to asDobjFor(action) and asIobjFor(action). Using |
| | 15001 | these macros involves two steps. First, in the Actor, write a short |
| | 15002 | handler for the action that uses the macro to delegate to the state |
| | 15003 | object: |
| | 15004 | |
| | 15005 | <p><pre> |
| | 15006 | bob: Person |
| | 15007 | // ... other definitions ... |
| | 15008 | dobjFor(AttackWith) actorStateDobjFor(AttackWith) |
| | 15009 | ; |
| | 15010 | </pre> |
| | 15011 | |
| | 15012 | <p>This sets up the "bob" Actor object so that the handling for |
| | 15013 | AttackWith, with bob as the direct object, will be delegated to bob's |
| | 15014 | current ActorState object. Second, just write a normal dobjFor() handler |
| | 15015 | in each of the ActorState objects associated with bob: |
| | 15016 | |
| | 15017 | <p><pre> |
| | 15018 | + bobFighting: ActorState |
| | 15019 | dobjFor(AttackWith) |
| | 15020 | { |
| | 15021 | action() { "Bob puts up a fight..."; } |
| | 15022 | } |
| | 15023 | ; |
| | 15024 | + bobCowering: ActorState |
| | 15025 | dobjFor(AttackWith) |
| | 15026 | { |
| | 15027 | action() { "Bob just hides in the corner..."; } |
| | 15028 | } |
| | 15029 | ; |
| | 15030 | </pre> |
| | 15031 | |
| | 15032 | </div> |
| | 15033 | |
| | 15034 | <!-------------------> |
| | 15035 | <div class=entry> |
| | 15036 | |
| | 15037 | The withActionEnv() function now takes an addition parameter giving |
| | 15038 | the Actor object to use as the gActor value while running the |
| | 15039 | callback. In the past, this function always used the player character |
| | 15040 | Actor (given by gPlayerChar); the new parameter allows other actors to |
| | 15041 | be used instead. |
| | 15042 | |
| | 15043 | </div> |
| | 15044 | |
| | 15045 | <!-------------------> |
| | 15046 | <div class=entry> |
| | 15047 | |
| | 15048 | The withCommandTranscript() function now returns the result of the |
| | 15049 | callback function, rather than the transcript object created to run |
| | 15050 | the callback. Callers who still need the transcript object as the |
| | 15051 | result can simply return gTranscript from the callback function |
| | 15052 | itself, as this value will then be passed up as the return value from |
| | 15053 | withCommandTranscript(). |
| | 15054 | |
| | 15055 | </div> |
| | 15056 | |
| | 15057 | <!-------------------> |
| | 15058 | <div class=entry> |
| | 15059 | |
| | 15060 | The attentionSpan property of an InConversationState object can now be |
| | 15061 | set to nil to indicate that there is no attention span limit for the |
| | 15062 | NPC. Setting attentionSpan to nil will prevent the NPC from ever |
| | 15063 | ending the conversation by virtue of being ignored for too long. |
| | 15064 | |
| | 15065 | </div> |
| | 15066 | |
| | 15067 | <!-------------------> |
| | 15068 | <div class=entry> |
| | 15069 | |
| | 15070 | The standard SpecialTopic template (in adv3.h) now allows defining a |
| | 15071 | list of strings (for the textStrings property) in place of a single |
| | 15072 | response. The standard TopicEntry, SpecialTopic, and YesNoTopic |
| | 15073 | templates now make the response/response list entry optional, allowing |
| | 15074 | the rest of the templates to be used even if a custom method is |
| | 15075 | needed to handle the response. |
| | 15076 | |
| | 15077 | </div> |
| | 15078 | |
| | 15079 | <!-------------------> |
| | 15080 | <div class=entry> |
| | 15081 | |
| | 15082 | A new DefaultTopic subclass, DefaultAnyTopic, matches all of the |
| | 15083 | different sorts of topic interactions: ASK, TELL, GIVE, and SHOW. |
| | 15084 | This is especially useful for default handling in conversation nodes |
| | 15085 | (ConvNodes) where you want catch all topics not otherwise handled. |
| | 15086 | |
| | 15087 | </div> |
| | 15088 | |
| | 15089 | <!-------------------> |
| | 15090 | <div class=entry> |
| | 15091 | |
| | 15092 | The new TopicEntry property isConversational lets a TopicEntry |
| | 15093 | specify whether or not the response is "conversational." A |
| | 15094 | conversational response is one that involves some kind of interaction |
| | 15095 | with the NPC. This property is true by default, but some response |
| | 15096 | objects will want to set it to nil to indicate that the response |
| | 15097 | doesn't involve any conversation with the NPC. For example, a |
| | 15098 | response like "You don't think he wants to discuss that right now" is |
| | 15099 | non-conversational, because it doesn't involve any exchange with the |
| | 15100 | NPC. |
| | 15101 | |
| | 15102 | <p>When isConversational is nil for the response object that's found |
| | 15103 | for a conversation command, a ConversationReadyState will <b>not</b> |
| | 15104 | enter its in-conversation, but will simply show the response and |
| | 15105 | remain in the conversation-ready state. This means that there will |
| | 15106 | be no "greeting" exchange for these responses. |
| | 15107 | |
| | 15108 | </div> |
| | 15109 | |
| | 15110 | <!-------------------> |
| | 15111 | <div class=entry> |
| | 15112 | |
| | 15113 | The new ConvNode method canEndConversation(actor, reason) lets a node |
| | 15114 | prevent a conversation from ending. 'reason' is an enum indicating |
| | 15115 | what is triggering the attempted termination: endConvBye if the player |
| | 15116 | typed BYE; endConvTravel if the other actor is leaving (i.e., the player |
| | 15117 | typed a travel command); or endConvBoredom if we're terminating the |
| | 15118 | conversation on our own because our attentionSpan has been exceeded. |
| | 15119 | This method can cancel the operation that attempted the termination |
| | 15120 | simply by returning nil; the method should display an explanation |
| | 15121 | when returning nil, to let the player know why the command is being |
| | 15122 | canceled. |
| | 15123 | |
| | 15124 | <p>In related changes, ConvNode.endConversation() and |
| | 15125 | ActorState.endConversation() now take 'reason' codes rather than |
| | 15126 | 'explicit' flags. This gives the methods full details on why the |
| | 15127 | termination is occurring. |
| | 15128 | |
| | 15129 | </div> |
| | 15130 | |
| | 15131 | <!-------------------> |
| | 15132 | <div class=entry> |
| | 15133 | |
| | 15134 | The new AgendaItem class provides a simple new mechanism for handling |
| | 15135 | cases where you want to model an NPC in terms of motivation. Each |
| | 15136 | actor has an "agenda," which is a list of AgendaItem objects. On each |
| | 15137 | turn, the actor's ActorState object (in the takeTurn method) will look |
| | 15138 | at the agenda list, to see if any items are ready to execute. If |
| | 15139 | there's an item that's ready to execute, the ActorState will execute |
| | 15140 | the first one that's ready. |
| | 15141 | |
| | 15142 | <p>Each AgendaItem object has a method called isReady, which indicates |
| | 15143 | whether or not the item is ready to execute. An actor will only execute |
| | 15144 | an agenda item once it's ready. The invokeItem method contains the code |
| | 15145 | that actually carries out the agenda item's action. |
| | 15146 | |
| | 15147 | <p>By default, an agenda item is removed from the actor's agenda list |
| | 15148 | when it's executed. However, if the item's stayInList property is true, |
| | 15149 | then the item will not be removed on execution. This property lets you |
| | 15150 | handle agenda items which the actor will try repeatedly, until some |
| | 15151 | other code determines that the goal has been achieved and removes the |
| | 15152 | item from the actor's agenda. |
| | 15153 | |
| | 15154 | <p>You must nest AgendaItem objects within their actor, using the "+" |
| | 15155 | notation. This associates the AgendaItem objects with the actor, but |
| | 15156 | it doesn't add them to the actor's agenda list. You must explicitly |
| | 15157 | add agenda items to the actor's agenda list by calling the actor's |
| | 15158 | addToAgenda() method. Agenda items must be explicitly added because |
| | 15159 | an actor's motivation typically will change dynamically as the game's |
| | 15160 | events unfold. |
| | 15161 | |
| | 15162 | </div> |
| | 15163 | |
| | 15164 | <!-------------------> |
| | 15165 | <div class=entry> |
| | 15166 | |
| | 15167 | Autonomous NPC conversation continuation processing has been moved |
| | 15168 | from InConversationState to the base ActorState. This allows actors |
| | 15169 | that don't use greeting protocols to nonetheless use stateful |
| | 15170 | conversations. |
| | 15171 | |
| | 15172 | <p>To accommodate this change, the default takeTurn() method in |
| | 15173 | ActorState now preforms more processing. If the actor has an active |
| | 15174 | ConvNode, then this takes precedence over any other default processing |
| | 15175 | for the actor's takeTurn() method. If the actor hasn't engaged in |
| | 15176 | conversation on the same turn, we invoke the ConvNode to continue the |
| | 15177 | conversation under NPC control; otherwise, we do nothing more. If |
| | 15178 | there's no ConvNode, we process the actor's "agenda." If there's no |
| | 15179 | ConvNode, and the actor has no agenda items that are ready to execute, |
| | 15180 | and the ActorState inherits from Script, then we invoke the script. |
| | 15181 | This structure means that a stateful conversation takes precedence |
| | 15182 | over everything, and an agenda item takes precedence over state-level |
| | 15183 | background activity. |
| | 15184 | |
| | 15185 | </div> |
| | 15186 | |
| | 15187 | <!-------------------> |
| | 15188 | <div class=entry> |
| | 15189 | |
| | 15190 | In the Actor class, the TellAbout and AskAbout handlers now include |
| | 15191 | the "canTalkToObj" precondition by default. This ensures that the NPC |
| | 15192 | being addressed can actually hear the other actor, to disallow |
| | 15193 | conversations in cases such as when the two actors are too far apart |
| | 15194 | to hear one another. The HELLO, GOODBYE, YES, and NO commands now all |
| | 15195 | make the same check as well, in the sayToActor() method. |
| | 15196 | |
| | 15197 | <p>Similarly, ConversationReadyState now makes the same check before |
| | 15198 | going through a greeting. If the initating actor can't talk to the |
| | 15199 | target actor, the enterConversation() method says so and uses 'exit' |
| | 15200 | to terminate the command. This prevents strange situations from |
| | 15201 | arising commands that don't require the canTalkToObj precondition. |
| | 15202 | (SHOW TO works this way, because the actors don't necessarily have to |
| | 15203 | be able to talk to each other to use SHOW TO; we could show a note to |
| | 15204 | an NPC on the other side of a sound-proof window, for example.) |
| | 15205 | |
| | 15206 | </div> |
| | 15207 | |
| | 15208 | <!-------------------> |
| | 15209 | <div class=entry> |
| | 15210 | |
| | 15211 | The new TopicEntry subclass InitiateTopic provides an easy way of |
| | 15212 | making an NPC initiate conversation based on simulation objects in the |
| | 15213 | environment. To make an NPC trigger a conversation, call the actor's |
| | 15214 | initiateTopic(obj) method, where 'obj' is the simulation object you |
| | 15215 | want to use to key the conversation. This will find an InitiateTopic |
| | 15216 | object in the actor's topic database matching the given object |
| | 15217 | ('obj'), and show its response text. One easy way to use this is to |
| | 15218 | initiate conversation based on the NPC's current location: just create |
| | 15219 | InitiateTopic objects keyed to those locations where you want the NPC |
| | 15220 | to say something special, and add a line like this to the ActorState's |
| | 15221 | takeTurn() method: |
| | 15222 | |
| | 15223 | <p><pre> |
| | 15224 | getActor().initiateTopic(getActor().location); |
| | 15225 | </pre> |
| | 15226 | |
| | 15227 | </div> |
| | 15228 | |
| | 15229 | <!-------------------> |
| | 15230 | <div class=entry> |
| | 15231 | |
| | 15232 | The "topic inventory" list shown by the TOPICS command is no longer |
| | 15233 | enclosed in parentheses by default. The parentheses are still included |
| | 15234 | when the topic inventory is shown implicitly (by a TALK TO command or |
| | 15235 | a <.topics> tag, for example). |
| | 15236 | |
| | 15237 | </div> |
| | 15238 | |
| | 15239 | <!-------------------> |
| | 15240 | <div class=entry> |
| | 15241 | |
| | 15242 | The new ConvNode property limitSuggestions allows a ConvNode to |
| | 15243 | indicate that suggested topics from the broader conversation context |
| | 15244 | should not be included in a topic inventory listing. This is useful |
| | 15245 | for times when the ConvNode won't allow the player to stray from the |
| | 15246 | subject, such a a ConvNode that only allows a YES or NO answer to a |
| | 15247 | question. In these cases, set limitSuggestions to true. The property |
| | 15248 | is nil by default, which causes topic inventory listings to include |
| | 15249 | not only any suggestions defined within the ConvNode, but also any |
| | 15250 | defined in the active ActorState or in the Actor itself. |
| | 15251 | |
| | 15252 | </div> |
| | 15253 | |
| | 15254 | <!-------------------> |
| | 15255 | <div class=entry> |
| | 15256 | |
| | 15257 | The new Actor.scheduleInitiateConversation(state, node, turns) method |
| | 15258 | lets the game set up an NPC to start a converation at the next opportunity |
| | 15259 | after the given number of turns has elapsed. If 'turns' is zero, then |
| | 15260 | the conversation can start on the next turn on which the NPC hasn't |
| | 15261 | been targeted for conversation by the player; if 'turns' is one, the |
| | 15262 | player will get at least one more turn before the conversation can start, |
| | 15263 | and so on for higher 'turns' values. The important thing is that the |
| | 15264 | conversation can only start on a turn on which the NPC isn't targeted |
| | 15265 | with a conversational command (ASK, TELL, etc). The Actor checks its |
| | 15266 | list of pending conversations on each turn in its takeTurn() method, |
| | 15267 | before invoking the current state's takeTurn() method. |
| | 15268 | |
| | 15269 | </div> |
| | 15270 | |
| | 15271 | <!-------------------> |
| | 15272 | <div class=entry> |
| | 15273 | |
| | 15274 | In the previous version, if Actor.initiateConversation() was called |
| | 15275 | from within the player character's turn (in an NPC's beforeAction() |
| | 15276 | handler responding to a player character action, for example), and |
| | 15277 | the ConvNode had a "continuation" message (defined in |
| | 15278 | npcContinuationMsg or npcContinuationList), the first continuation |
| | 15279 | message was incorrectly shown on the same turn. This no longer |
| | 15280 | occurs; the continuation message won't be shown until the next turn |
| | 15281 | at the earliest. ("At the earliest," because a continuation message |
| | 15282 | won't be shown on a given turn if the player character addresses a |
| | 15283 | conversational command to the NPC on that turn.) |
| | 15284 | |
| | 15285 | </div> |
| | 15286 | |
| | 15287 | <!-------------------> |
| | 15288 | <div class=entry> |
| | 15289 | |
| | 15290 | When an actor continues a conversation of its own volition (using |
| | 15291 | npcContinueMsg or npcContinueList) in a ConvNode, if the continuation |
| | 15292 | routine actually displays any text, then the ConvNode will |
| | 15293 | automatically set the player character and the initiating NPC to be in |
| | 15294 | conversation with one another. This ensures that any subsequent |
| | 15295 | conversational command from the player will have the initiating NPC as |
| | 15296 | the default interlocutor. |
| | 15297 | |
| | 15298 | </div> |
| | 15299 | |
| | 15300 | <!-------------------> |
| | 15301 | <div class=entry> |
| | 15302 | |
| | 15303 | In the past, the REPLAY QUIET command didn't display any acknowledgment, |
| | 15304 | and improperly left all subsequent text in bold-face. This has been |
| | 15305 | corrected. |
| | 15306 | |
| | 15307 | </div> |
| | 15308 | |
| | 15309 | <!-------------------> |
| | 15310 | <div class=entry> |
| | 15311 | |
| | 15312 | ActorState.greetingsFrom now delegates to a method of the same name |
| | 15313 | in Actor; this makes it easier to change the default greeting for a |
| | 15314 | simple actor without a state object. |
| | 15315 | |
| | 15316 | <p>Along the same lines, ActorState.showGreetingMsg has been removed, |
| | 15317 | and replaced with Actor.defaultGreetingResponse. The method has been |
| | 15318 | moved to Actor because of the change to greetingsFrom, and the method |
| | 15319 | has been renamed for consistency with the similar pattern for the |
| | 15320 | other conversation command default message methods (for ASK, TELL, |
| | 15321 | etc) in Actor. |
| | 15322 | |
| | 15323 | <p>Along the same lines, ActorState.goodbyeFrom now delegates to a |
| | 15324 | method of the same name in Actor by default. A new Actor method, |
| | 15325 | defaultGoodbyeResponse, displays the default message, for consistency |
| | 15326 | with the naming of the similar methods for other conversation |
| | 15327 | commands. |
| | 15328 | |
| | 15329 | </div> |
| | 15330 | |
| | 15331 | <!-------------------> |
| | 15332 | <div class=entry> |
| | 15333 | |
| | 15334 | Two new ConversationReadyState methods have been added: |
| | 15335 | enterFromByeMsg and enterFromConvMsg. These are provided for |
| | 15336 | convenience as single-message complements for enterFromByeList and |
| | 15337 | enterFromConvList, respectively. By default, these simply invoke |
| | 15338 | their respective list scripts. |
| | 15339 | |
| | 15340 | </div> |
| | 15341 | |
| | 15342 | <!-------------------> |
| | 15343 | <div class=entry> |
| | 15344 | |
| | 15345 | VocabObject has a new feature that allows an object's vocabulary to |
| | 15346 | be divided into "strong" and "weak" tokens. Weak and strong tokens are |
| | 15347 | the same as far as the parser is concerned, and are entered into the |
| | 15348 | dictionary as usual. The difference is that a weak token can only |
| | 15349 | be used to refer to an object in combination with one or more strong |
| | 15350 | tokens. That is, if the player enters a noun phrase, and the noun |
| | 15351 | phrase matches all of the vocabulary for a given in-scope object, |
| | 15352 | the object will match the noun phrase only if one or more of the |
| | 15353 | words in the noun phrase is a strong token for the object. |
| | 15354 | |
| | 15355 | <p>The purpose of this new feature is to make it easy to define extra |
| | 15356 | vocabulary for an object that the parser accepts for an object |
| | 15357 | without creating any new ambiguity. This comes up in situations |
| | 15358 | where you simply want to create additional synonyms for an object, as |
| | 15359 | well as in cases where an object is most strongly identified in terms |
| | 15360 | of its relationship to something else. For example, you might have a |
| | 15361 | location that contains a couple of doors, one to a house and the |
| | 15362 | other to a shed. You could use adjectives ("house door" and "shed |
| | 15363 | door") to differentiate the doors, but it might be more natural to |
| | 15364 | use a prepositional phrasing, such as "the door of the house" and |
| | 15365 | "the door of the shed." If you also have a house and a shed object, |
| | 15366 | though, this phrasing would create unwanted ambiguity with those |
| | 15367 | objects. This is where weak tokens come in. If you define "house" |
| | 15368 | and "shed" as weak tokens for the respective door objects, the parser |
| | 15369 | will never take those words alone to refer to the doors, so there |
| | 15370 | will be no ambiguity with the house and shed objects themselves; but |
| | 15371 | the parser will still allow "house" and "shed" to refer to the doors, |
| | 15372 | as long as they're used in combination with the strong token "door". |
| | 15373 | |
| | 15374 | <p>Weak tokens are defined per-object (they're not global). Each |
| | 15375 | object that has weak tokens keeps a list of its weak tokens in its |
| | 15376 | 'weakTokens' property. In the basic VocabObject.matchName() |
| | 15377 | implementation, the object checks the noun phrase to see if it |
| | 15378 | consists entirely of weak tokens, and rejects the match if so. |
| | 15379 | |
| | 15380 | <p>When you define an object, you can define weak tokens in one |
| | 15381 | of two ways. If you define 'noun' and 'adjective' (etc.) properties |
| | 15382 | directly, simply define a 'weakTokens' property containing a list of |
| | 15383 | strings giving the object's weak tokens. If you use the |
| | 15384 | vocabulary initialization string, simply enclose each weak token |
| | 15385 | in parentheses. For example: |
| | 15386 | |
| | 15387 | <p><pre>+ Door 'front door/(house)' 'front door of house' |
| | 15388 | "The door is badly weathered. " |
| | 15389 | ; |
| | 15390 | </pre> |
| | 15391 | |
| | 15392 | </div> |
| | 15393 | |
| | 15394 | <!-------------------> |
| | 15395 | <div class=entry> |
| | 15396 | |
| | 15397 | VocabObject.matchName() and matchNameDisambig() now invoke a new |
| | 15398 | method, matchNameCommon(), to carry out their common handling. |
| | 15399 | This change facilitates the weak-token feature mentioned above. |
| | 15400 | In most cases, when a game needs to override an object's name |
| | 15401 | matching test, it should override matchNameCommon(), since this |
| | 15402 | method provides the common handling for normal matching and |
| | 15403 | disambiguation matching. Games can still override matchName() |
| | 15404 | and/or matchNameDisambig() individually, but it's only necessary |
| | 15405 | to do so when you want to use different rules for normal matching |
| | 15406 | and disambiguation matching. |
| | 15407 | |
| | 15408 | </div> |
| | 15409 | |
| | 15410 | <!-------------------> |
| | 15411 | <div class=entry> |
| | 15412 | |
| | 15413 | The English parser's handling of quoted string literals as adjectives |
| | 15414 | has been improved slightly, but the changes will require some small |
| | 15415 | adjustments to any games currently using literal adjectives. |
| | 15416 | |
| | 15417 | <p>Instead of allowing any adjective to be quoted, the parser now |
| | 15418 | only matches quoted strings that are specifically designated as |
| | 15419 | "literal adjectives" in an object's vocabulary. To designate an |
| | 15420 | adjective as a literal adjective, you can either enclose the |
| | 15421 | adjective in double-quotes in the vocabulary initializer string, or |
| | 15422 | you can explicitly define the word using the 'literalAdjective' |
| | 15423 | part-of-speech property instead of the normal 'adjective' |
| | 15424 | part-of-speech. For example, you could define an elevator button |
| | 15425 | for the lobby level like so: |
| | 15426 | |
| | 15427 | <p><pre>+ Button '"L" button' 'L button' "It's a button labeled <q>L.</q> "; |
| | 15428 | </pre> |
| | 15429 | |
| | 15430 | <p>This change makes the parser stricter about which words it accepts |
| | 15431 | as quoted adjectives, but it also allows the parser to be more |
| | 15432 | flexible about requiring the quotes. In particular, the parser now |
| | 15433 | accepts all of the following forms for the button defined above: "L" |
| | 15434 | button, button "L", L button, and button L. In the past, the parser |
| | 15435 | was unable to accept the last of these, because without the quotes, |
| | 15436 | it wasn't able to tell that the unquoted "L" was meant as a literal |
| | 15437 | adjective. Now that the "L" is defined in the dictionary as a |
| | 15438 | literal adjective, it's no longer necessary for the player to quote |
| | 15439 | the word for the parser to recognize it as a literal adjective, so |
| | 15440 | the parser is able to accept the form with the literal adjective |
| | 15441 | following the noun. |
| | 15442 | |
| | 15443 | <p>Note that this change also involves a subtle change to the special "*" |
| | 15444 | vocabulary wildcard token. In the past, if the string '"*"' (that is, |
| | 15445 | an asterisk enclosed in double-quotes) appeared as an 'adjective' |
| | 15446 | dictionary entry for an object, then that object matched any quoted |
| | 15447 | string used as an adjective in player input. Now, this effect is |
| | 15448 | obtained by using the string '*' as a 'literalAdjective' dictionary |
| | 15449 | entry for an object. This change has no effect at all on the way you |
| | 15450 | write vocabulary initializer strings, since you still enclose the |
| | 15451 | asterisk in quotes in that string; however, if you're defining a |
| | 15452 | 'literalAdjective' list directly for an object, you now must drop |
| | 15453 | the quotes and add a word entry consisting of simply the asterisk. |
| | 15454 | |
| | 15455 | </div> |
| | 15456 | |
| | 15457 | <!-------------------> |
| | 15458 | <div class=entry> |
| | 15459 | |
| | 15460 | The English parser now accepts pronouns as responses to |
| | 15461 | disambiguation questions. (The disambigListItem(noun) rule now |
| | 15462 | matches completeNounPhraseWithoutAll rather than qualifiedNounPhrase, |
| | 15463 | as it did in the past; the new sub-production matches pronouns, which |
| | 15464 | qualifiedNounPhrase does not.) |
| | 15465 | |
| | 15466 | </div> |
| | 15467 | |
| | 15468 | <!-------------------> |
| | 15469 | <div class=entry> |
| | 15470 | |
| | 15471 | In the English parser rules, the command "T <i>topic</i>" is now |
| | 15472 | accepted as a short-cut for "TELL ABOUT <i>topic</i>." Together with |
| | 15473 | the "A <i>topic</i>" shortcut for ASK ABOUT, this can greatly reduce |
| | 15474 | the amount of typing a player has to do in a game that has a lot of |
| | 15475 | ASK/TELL character interaction. |
| | 15476 | |
| | 15477 | </div> |
| | 15478 | |
| | 15479 | <!-------------------> |
| | 15480 | <div class=entry> |
| | 15481 | |
| | 15482 | In the English parser rules, the Hello action now accepts "hallo" |
| | 15483 | as equivalent to "hello" or "hi", and also accepts "say" with any |
| | 15484 | of these variations. |
| | 15485 | |
| | 15486 | </div> |
| | 15487 | |
| | 15488 | <!-------------------> |
| | 15489 | <div class=entry> |
| | 15490 | |
| | 15491 | A new Action method, callAfterActionMain(obj), allows a game to register |
| | 15492 | an object for invocation at the end of the current action. This is |
| | 15493 | only meanginful when used on the current gAction object, since it |
| | 15494 | registers for notification of completion of the current action. |
| | 15495 | When the current action is finished - including the iteration over |
| | 15496 | all of the objects involved in the action - the action invokes |
| | 15497 | the afterActionMain() method of each registered object. |
| | 15498 | |
| | 15499 | <p>This new method is especially useful for adding a "summary" of an |
| | 15500 | action that involves multiple objects. Each individual object's |
| | 15501 | action handler (an action() method in a dobjFor() block, for example) |
| | 15502 | can register a handler object to receive notification when the |
| | 15503 | overall command is finished. A given object can be registered only |
| | 15504 | once - redundant registrations are simply ignored - so each |
| | 15505 | individual iterated object doesn't have to worry about whether or not |
| | 15506 | other iterated objects will register the same handler. Then, at the |
| | 15507 | end of the action, the handler will be invoked; it can determine what |
| | 15508 | happened in the action, and do something based on the end result. |
| | 15509 | For example, the handler could scan the transcript (gTranscript) for |
| | 15510 | certain types of reports, and add a summary message based on the |
| | 15511 | reports, or could even replace some of the individual reports with a |
| | 15512 | summary. The handler could also take addition action based on the |
| | 15513 | overall end results; for example, in a GIVE TO command, a handler |
| | 15514 | could look at the full set of objects successfully given, and decide |
| | 15515 | that the combination is sufficient to allow the recipient to give the |
| | 15516 | donor something in return. |
| | 15517 | |
| | 15518 | </div> |
| | 15519 | |
| | 15520 | <!-------------------> |
| | 15521 | <div class=entry> |
| | 15522 | |
| | 15523 | A new CommandTranscript method, summarizeAction(), can be used with |
| | 15524 | the new callAfterActionMain() system to generate a summary of an |
| | 15525 | action that involves multiple objects. summarizeAction() scans |
| | 15526 | through the transcript, looking for runs of two or more reports for |
| | 15527 | the current action that match criteria specified by the caller (via a |
| | 15528 | callback function). For each run of two or more consecutive |
| | 15529 | qualifying reports, the method removes those reports, along with their |
| | 15530 | corresponding multi-object announcements, and replaces the last of the |
| | 15531 | reports with a single "summary" report generated by the caller (via |
| | 15532 | another callback function). This method lets you turn a transcript |
| | 15533 | like this: |
| | 15534 | |
| | 15535 | <p><pre> gold coin: Bob accepts the gold coin. |
| | 15536 | gold coin: Bob accepts the gold coin. |
| | 15537 | gold coin: Bob accepts the gold coin. |
| | 15538 | </pre> |
| | 15539 | |
| | 15540 | <p>into something like this: |
| | 15541 | |
| | 15542 | <p><pre> Bob accepts the three gold coins. |
| | 15543 | </pre> |
| | 15544 | |
| | 15545 | <p>This sort of summary isn't straightforward to generate in general, |
| | 15546 | and the library makes no attempt to apply it generically. In specific |
| | 15547 | cases where you can control the range of possible results, though, |
| | 15548 | this can be a powerful way to improve the game's output by describing |
| | 15549 | an iterated action as though it were a single logical unit. |
| | 15550 | |
| | 15551 | </div> |
| | 15552 | |
| | 15553 | <!-------------------> |
| | 15554 | <div class=entry> |
| | 15555 | |
| | 15556 | Phrases involving quantities ("five coins") and "all" with a plural |
| | 15557 | ("all coins") are now resolved a little more consistently and |
| | 15558 | intuitively, from a player's perspective. First, phrases involving |
| | 15559 | quantities are now always disambiguated in the same manner as |
| | 15560 | singular phrases, and then the required number of objects is chosen; |
| | 15561 | in the past, disambiguation filtering was not as consistent. This |
| | 15562 | change ensures in particular that "collectives" are properly filtered |
| | 15563 | in or out; the old mechanism sometimes missed collectives because it |
| | 15564 | sometimes skipped the normal disambiguation filtering. Second, |
| | 15565 | "all"-plus-plural phrases are now resolved to all matching objects, |
| | 15566 | rather than to only the most logical subset of matching objects, as |
| | 15567 | was the case in the past. This means that a command applied to "all |
| | 15568 | coins" really is applied to all coins that are present, even those |
| | 15569 | for which the action isn't currently valid. |
| | 15570 | |
| | 15571 | <p>To implement these changes, NounPhraseProd has a new method, |
| | 15572 | getVerifyKeepers(), that the disambiguation filtering methods call to |
| | 15573 | reduce the list. The default NounPhraseProd definition of the method |
| | 15574 | does the traditional filtering that the disambiguation filter did, |
| | 15575 | which keeps just the most logical subset of the results. |
| | 15576 | AllPluralProd overrides this method to keep everything in the list, |
| | 15577 | and QuantifiedPluralProd overrides the method to select a subset with |
| | 15578 | the desired number of entries. |
| | 15579 | |
| | 15580 | </div> |
| | 15581 | |
| | 15582 | <!-------------------> |
| | 15583 | <div class=entry> |
| | 15584 | |
| | 15585 | <p>The CollectiveGroup object by default no longer matches a noun |
| | 15586 | phrase that specifies a quantity ("take five coins" or "take both |
| | 15587 | coins"; or any singular phrase, since a singular phrase specifies a |
| | 15588 | quantity of one). Collective groups are designed to stand in for |
| | 15589 | a completely collection of in-scope individuals, not for arbitrary |
| | 15590 | subsets of the individuals, so when a quantity is specified we must |
| | 15591 | fall back on iterating over a selected subset of the individuals. |
| | 15592 | |
| | 15593 | <p>To implement this change, the filterResolveList() method now takes |
| | 15594 | two additional parameters: one giving the quantity specified in the |
| | 15595 | noun phrase, if any, and another giving the role played by the object |
| | 15596 | (DirectObject, IndirectObject, etc). When the noun phrase specifies |
| | 15597 | a quantity, the new parameter will be set to an integer giving the |
| | 15598 | quantity specified. If the noun phrase is unspecific about the |
| | 15599 | quantity (as in "take coins" or "get all coins"), then the quantity |
| | 15600 | parameter will be nil. |
| | 15601 | |
| | 15602 | <p>Note that the isCollectiveAction() method now takes an additional |
| | 15603 | parameter as well, giving the role in the action played by the object |
| | 15604 | being resolved (DirectObject, IndirectObject, etc). This allows |
| | 15605 | differentiating the handling based on both the action and the role |
| | 15606 | played in the action. |
| | 15607 | |
| | 15608 | <p>Custom CollectiveGroup objects <i>can</i> represent specific |
| | 15609 | quantities of objects, from the player's perspective, if desired. For |
| | 15610 | example, a game might want to create a CollectiveGroup that represents |
| | 15611 | a quantity of money, rather than dealing with the individual coins |
| | 15612 | making up the quantity. To do this, the CollectiveGroup object must |
| | 15613 | override the filterResolveList() method, and must set the "quant_" |
| | 15614 | element of its own ResolveInfo entry to an integer giving the number |
| | 15615 | of <i>grammatical</i> objects it represents. The CollectiveGroup must |
| | 15616 | keep track of what it's representing somehow; the best way to do this |
| | 15617 | is to create a new instance of the CollectiveGroup itself, and store a |
| | 15618 | property in the new instance giving the quantity represented by the |
| | 15619 | collective. Note that using CollectiveGroup objects in this manner |
| | 15620 | is tricky; you'll need to code action handlers for the custom |
| | 15621 | CollectiveGroup object so that they correctly take into the account |
| | 15622 | the quantity represented by the group object. |
| | 15623 | |
| | 15624 | </div> |
| | 15625 | |
| | 15626 | <!-------------------> |
| | 15627 | <div class=entry> |
| | 15628 | |
| | 15629 | The ownershipAndLocationDistinguisher has been refactored into two |
| | 15630 | separate distinguishers: ownershipDistinguisher and locationDistinguisher. |
| | 15631 | Each of these new distinguishers is very similar to the old combined |
| | 15632 | distinguisher, but the ownershipDistinguisher gives priority to |
| | 15633 | ownership, regardless of the containment relationship. The library |
| | 15634 | classes that define distinguishers now use both of these, with |
| | 15635 | the ownership distinguisher applied first. |
| | 15636 | |
| | 15637 | <p>The purpose of this change is to ensure that ownership will be |
| | 15638 | used as a distinguishing feature whenever possible, before the parser |
| | 15639 | falls back on location. The old combined distinguisher could only |
| | 15640 | use ownership in the limited case where the owner and immediate |
| | 15641 | location were the same, because it couldn't otherwise be sure that it |
| | 15642 | would be able to distinguish multiple objects with the same owner but |
| | 15643 | different locations. By separating the ownership and location |
| | 15644 | distinguishers, we first try to identify objects purely by ownership; |
| | 15645 | when this fails, we fall back on the old approach of identifying by |
| | 15646 | immediate location in preference to owner. |
| | 15647 | |
| | 15648 | <p>To support this change, the English methods for owner-or-location |
| | 15649 | names (aNameOwnerLoc, theNameOwnerLoc, countNameOwnerLoc) now take |
| | 15650 | a parameter indicating whether to use ownership or location as the |
| | 15651 | first priority in generating the name. When ownership takes priority, |
| | 15652 | these methods will show the name with a possessive form of the owner |
| | 15653 | regardless of the containment relationship between the object and its |
| | 15654 | owner. |
| | 15655 | |
| | 15656 | </div> |
| | 15657 | |
| | 15658 | <!-------------------> |
| | 15659 | <div class=entry> |
| | 15660 | |
| | 15661 | Possessive qualifiers (such as "bob's" in "bob's chair") are now |
| | 15662 | resolved in a special resolution context that allows referring to |
| | 15663 | owners that aren't in scope for the purposes of the phrase being |
| | 15664 | qualified (such as the "chair" in "bob's chair"). A possessive |
| | 15665 | phrase is now considered in scope if it's in scope for the phrase |
| | 15666 | being qualified <b>or</b> it's known to the actor performing the |
| | 15667 | command. This allows possessive phrases to be used to refer to |
| | 15668 | objects that are present, and which are known to belong to an |
| | 15669 | actor, even if the actor itself isn't present. |
| | 15670 | |
| | 15671 | </div> |
| | 15672 | |
| | 15673 | <!-------------------> |
| | 15674 | <div class=entry> |
| | 15675 | |
| | 15676 | When the parser generates a disambiguation prompt, and the prompt |
| | 15677 | distinguishes objects by possessives ("which match: bob's match or |
| | 15678 | your match?"), the parser automatically sets the pronoun antecedents |
| | 15679 | for "him" and/or "her" to the people mentioned in the prompt. This |
| | 15680 | allows the player to answer with "his" or "hers" (or "his match"), |
| | 15681 | referring back to the person or people mentioned in the message. |
| | 15682 | |
| | 15683 | </div> |
| | 15684 | |
| | 15685 | <!-------------------> |
| | 15686 | <div class=entry> |
| | 15687 | |
| | 15688 | The parser error messages that display literal text entered by the |
| | 15689 | player (such as the message for unrecognized punctuation marks, and |
| | 15690 | the message for unknown words) now HTML-ify the user's text. This |
| | 15691 | ensures that any markup-significant characters (such as "<" and |
| | 15692 | "&") are converted into HTML sequences that display the |
| | 15693 | corresponding characters. |
| | 15694 | |
| | 15695 | </div> |
| | 15696 | |
| | 15697 | <!-------------------> |
| | 15698 | <div class=entry> |
| | 15699 | |
| | 15700 | A bug in the English parser's rule for phrases like "anything in the box" |
| | 15701 | caused run-time errors when the word "anything" alone was used as a noun |
| | 15702 | phrase. This has been fixed. |
| | 15703 | |
| | 15704 | </div> |
| | 15705 | |
| | 15706 | <!-------------------> |
| | 15707 | <div class=entry> |
| | 15708 | |
| | 15709 | In the hint system, the new Goal methods openWhenTrue and closeWhenTrue |
| | 15710 | can be used to define arbitrary conditions that open and close the goal. |
| | 15711 | These new general-purpose conditions supplement the more specific |
| | 15712 | conditions (openWhenSeen, openWhenAchieved, etc.); the goal will be |
| | 15713 | opened if <i>any</i> of the openWhenXxx conditions are met, and will |
| | 15714 | be closed when any of the closeWhenXxx conditions are met. |
| | 15715 | |
| | 15716 | <p>The new Goal property openWhenDescribed lets you specify that the goal |
| | 15717 | should be opened when the referenced object is described (usually with |
| | 15718 | EXAMINE). This is good for goals where the existence of a puzzle isn't |
| | 15719 | made apparent until the full description of an object is viewed. The |
| | 15720 | new property closeWhenDescribed correspondingly closes the goal when |
| | 15721 | the referenced object is described. |
| | 15722 | |
| | 15723 | </div> |
| | 15724 | |
| | 15725 | <!-------------------> |
| | 15726 | <div class=entry> |
| | 15727 | |
| | 15728 | The RESTART command no longer resets the commandSequencer to the |
| | 15729 | "no-command" state, as it did in the past. This change corresponds to |
| | 15730 | the change in commandSequencer start-up state effected in 3.0.6i. |
| | 15731 | |
| | 15732 | </div> |
| | 15733 | |
| | 15734 | <!-------------------> |
| | 15735 | <div class=entry> |
| | 15736 | |
| | 15737 | The English grammar now accepts '1' as a synonym for 'one' or 'any' in |
| | 15738 | singular indefinite noun phrases, such as "take 1 coin." (In the |
| | 15739 | past, the grammar omitted this alternative.) |
| | 15740 | |
| | 15741 | </div> |
| | 15742 | |
| | 15743 | <!-------------------> |
| | 15744 | <div class=entry> |
| | 15745 | |
| | 15746 | The new class SecretFixture is designed for objects that are needed in |
| | 15747 | the internal implementation but are not meant to be manipulated |
| | 15748 | directly by characters. This is a simple subclass of Fixture; the |
| | 15749 | main difference is that a SecretFixture is hidden from "all," to help |
| | 15750 | prevent direct references to it in commands. |
| | 15751 | |
| | 15752 | </div> |
| | 15753 | |
| | 15754 | <!-------------------> |
| | 15755 | <div class=entry> |
| | 15756 | |
| | 15757 | In the English grammar, a new production named singleNounOnly can be used |
| | 15758 | where a single noun (rather than a list of nouns) is <i>structurally</i> |
| | 15759 | required. The singleNoun production itself will structurally match a |
| | 15760 | list of nouns, but considers such matches semantically invalid. In |
| | 15761 | contrast, singleNounOnly won't even structurally match a noun list. |
| | 15762 | |
| | 15763 | <p>The firstCommandPhrase(withActor) rule now uses the new singleNounOnly |
| | 15764 | production to match the actor phrase. This eliminates the structural |
| | 15765 | ambiguity of certain types of invalid input that were able to cause |
| | 15766 | unbounded memory consumption with the old rule. |
| | 15767 | |
| | 15768 | </div> |
| | 15769 | |
| | 15770 | <!-------------------> |
| | 15771 | <div class=entry> |
| | 15772 | |
| | 15773 | The menu system no longer shows a border in full-screen menu windows. |
| | 15774 | (When a menu takes up the whole game window, a border is superfluous, |
| | 15775 | since there's no other window requiring separation. Removing the |
| | 15776 | border slightly but noticeably improves the appearance of a full-screen |
| | 15777 | menu.) |
| | 15778 | |
| | 15779 | </div> |
| | 15780 | |
| | 15781 | <!-------------------> |
| | 15782 | <div class=entry> |
| | 15783 | |
| | 15784 | The Decoration class now gives Examine commands a reduced "logical |
| | 15785 | rank" (of 70) for disambiguation purposes. This means that if the |
| | 15786 | player enters an Examine command, and the vocabulary for the direct |
| | 15787 | object matches a Decoration object and a non-Decoration object, the |
| | 15788 | non-Decoration object will be chosen ahead of the Decoration. It's |
| | 15789 | usually desirable to treat Decoration objects as second-class citizens |
| | 15790 | for disambiguation purposes, because they're usually meant to stay in |
| | 15791 | the background as much as possible. |
| | 15792 | |
| | 15793 | </div> |
| | 15794 | |
| | 15795 | <!-------------------> |
| | 15796 | <div class=entry> |
| | 15797 | |
| | 15798 | The standard Actor handlers for the Give and Show actions now produce |
| | 15799 | more sensible messages for giving or showing something to oneself. |
| | 15800 | (The old message was the generic "you do not respond"; the new message |
| | 15801 | is "Giving [or showing] that to yourself won't accomplish anything.") |
| | 15802 | |
| | 15803 | </div> |
| | 15804 | |
| | 15805 | <!-------------------> |
| | 15806 | <div class=entry> |
| | 15807 | |
| | 15808 | The base definition of the method filterResolveList() has been moved |
| | 15809 | from Thing to VocabObject. The parser calls this method on objects |
| | 15810 | that match vocabulary in player input, so it more properly pertains to |
| | 15811 | VocabObject than to Thing. (In practice, this is important in some |
| | 15812 | cases when Topic objects match player input, because Topic objects |
| | 15813 | descend from VocabObject but not from Thing.) |
| | 15814 | |
| | 15815 | </div> |
| | 15816 | |
| | 15817 | <!-------------------> |
| | 15818 | <div class=entry> |
| | 15819 | |
| | 15820 | The cached scope list in Resolver and its subclasses is now better |
| | 15821 | encapsulated, to make it easier to subclass Resolver. In particular, |
| | 15822 | the "scope_" member is referenced only in the method cacheScopeList(), |
| | 15823 | objInScope(), and the new method getScopeList(). This means that a |
| | 15824 | subclass can dispense entirely with the cached scope list (and the |
| | 15825 | "scope_" member), as long as the subclass implements objInScope() and |
| | 15826 | getScopeList() to return mutually consistent results. A subclass |
| | 15827 | can alternatively override cacheScopeList() to use a different set |
| | 15828 | of rules to obtain and cache the scope list. |
| | 15829 | |
| | 15830 | <p>Along similar lines, TAction.initResolver() now calls |
| | 15831 | cacheScopeList() to initialize its cached scope list, rather than |
| | 15832 | doing so directly. This allows TAction subclasses to customize the |
| | 15833 | scope rules in exactly the same way that subclasses of Resolver can |
| | 15834 | customize scope. Likewise, TopicResolver.filterAmbiguousNounPhrase() |
| | 15835 | now calls objInScope() rather than accessing the "scope_" list |
| | 15836 | directly. |
| | 15837 | |
| | 15838 | </div> |
| | 15839 | |
| | 15840 | <!-------------------> |
| | 15841 | <div class=entry> |
| | 15842 | |
| | 15843 | The new Achievement method addToScoreOnce() makes it a little easier |
| | 15844 | to do score book-keeping in the common case of achievements that are |
| | 15845 | scorable only once. This method adds the achievement to the score, |
| | 15846 | with a given number of points, but only if the achievement has never |
| | 15847 | been scored before; if the achievement has been scored before, the |
| | 15848 | method does nothing at all. This makes it unnecessary to keep track |
| | 15849 | of any separate status to avoid scoring the same action more than |
| | 15850 | once. (Some achievements are meant to be repeatable; this method |
| | 15851 | wouldn't be useful in such cases, obviously.) |
| | 15852 | |
| | 15853 | </div> |
| | 15854 | |
| | 15855 | <!-------------------> |
| | 15856 | <div class=entry> |
| | 15857 | |
| | 15858 | The complexMultiTransform report transformer is now a little more |
| | 15859 | liberal in determining when to add visual separation between reports |
| | 15860 | when an action is iterated over multiple objects. In the past, visual |
| | 15861 | separation (i.e., a paragraph break) was added only when implicit |
| | 15862 | command announcements were present. Now, visual separation will be |
| | 15863 | added any time the report group for an individual object in the |
| | 15864 | iteration consists of more than one report, or a report has a single |
| | 15865 | message with text over 60 characters in length. This new, more |
| | 15866 | liberal policy is designed to add visual separation essentially any |
| | 15867 | time an individual object's result message is non-trivial, since |
| | 15868 | multi-object messages become hard to read when they're all jammed |
| | 15869 | together, unless each individual message is very short. The new |
| | 15870 | policy errs on the side of adding too much visual separation, which on |
| | 15871 | balance seems to do considerably less harm to readability than too |
| | 15872 | little separation. |
| | 15873 | |
| | 15874 | </div> |
| | 15875 | |
| | 15876 | <!-------------------> |
| | 15877 | <div class=entry> |
| | 15878 | |
| | 15879 | The handling of OOPS responses has been improved slightly. In |
| | 15880 | particular, when the player uses an OOPS command to correct an error, |
| | 15881 | the new text that results from applying the OOPS substitution is now |
| | 15882 | run through the normal pre-parsing sequence. |
| | 15883 | |
| | 15884 | <p>In the past, an OOPS command itself was run through the normal |
| | 15885 | pre-parsing steps, but the new command resulting from applying the |
| | 15886 | OOPS replacement text was <i>not</i> pre-parsed. This resulted in |
| | 15887 | incorrect behavior in certain certain rare cases. One noticeable |
| | 15888 | example was when a SpecialTopic was active. Because SpecialTopics |
| | 15889 | rely on pre-parsing to match their special command templates, and |
| | 15890 | because the corrected text after the OOPS wasn't pre-parsed, it was |
| | 15891 | effectively impossible to use OOPS to correct a typo in a command |
| | 15892 | intended to match a SpecialTopic. The new OOPS handling ensures that |
| | 15893 | pre-parsing is run as normal on the new command resulting from |
| | 15894 | applying an OOPS correction. |
| | 15895 | |
| | 15896 | </div> |
| | 15897 | |
| | 15898 | <!-------------------> |
| | 15899 | <div class=entry> |
| | 15900 | |
| | 15901 | When the player enters a command that matches an active SpecialTopic, |
| | 15902 | the library now treats this as a conversational action directed to the |
| | 15903 | interlocutor, as though the player had typed an ASK or TELL command. |
| | 15904 | This is important in cases where the actor has background actions that |
| | 15905 | it performs based on the absence of an explicit conversational |
| | 15906 | interaction from the player on any given turn, such as showing |
| | 15907 | ConvNode continuation messages. |
| | 15908 | |
| | 15909 | </div> |
| | 15910 | |
| | 15911 | <!-------------------> |
| | 15912 | <div class=entry> |
| | 15913 | |
| | 15914 | ASK FOR commands are now handled uniformly with other conversational |
| | 15915 | commands (ASK ABOUT, TELL ABOUT, GIVE TO, etc). In particular, these |
| | 15916 | commands are now routed to the ActorState for handling, and can be |
| | 15917 | handled using the new AskForTopic class, which works along the same |
| | 15918 | lines as GiveToTopic and ShowToTopic. |
| | 15919 | |
| | 15920 | </div> |
| | 15921 | |
| | 15922 | <!-------------------> |
| | 15923 | <div class=entry> |
| | 15924 | |
| | 15925 | The library now automatically sets the antecedent for the appropriate |
| | 15926 | pronouns to refer to a responding actor, any time a TopicEntry is used |
| | 15927 | to generate response text. This ensures that the player can use a |
| | 15928 | pronoun on the next command to refer to the last actor who generated a |
| | 15929 | conversational message. |
| | 15930 | |
| | 15931 | </div> |
| | 15932 | |
| | 15933 | <!-------------------> |
| | 15934 | <div class=entry> |
| | 15935 | |
| | 15936 | The new method Actor.setPronounObj(obj) makes it easier to set a |
| | 15937 | simulation object as the pronoun antecedent for commands targeting the |
| | 15938 | given actor. (In the past, only the setPronoun() method was |
| | 15939 | available, which took a list of ResolveInfo objects. When the game or |
| | 15940 | the library needs to set the pronoun directly, it's often easier to |
| | 15941 | set it directly in terms of simulation objects, without creating a |
| | 15942 | ResolveInfo list.) |
| | 15943 | |
| | 15944 | </div> |
| | 15945 | |
| | 15946 | <!-------------------> |
| | 15947 | <div class=entry> |
| | 15948 | |
| | 15949 | The new classes SimpleNoise and SimpleOdor make it easier to define |
| | 15950 | Noise and Odor objects for the common case that a noise/odor is just |
| | 15951 | a background part of the room description that (1) doesn't require |
| | 15952 | ongoing "daemon" announcements, and (2) doesn't need any |
| | 15953 | differentiation among the different types of descriptive messages. |
| | 15954 | These classes simply use the "desc" property as the default for all |
| | 15955 | of the descriptive messages, and are marked as "ambient," to avoid |
| | 15956 | automatic inclusion in the room description. |
| | 15957 | |
| | 15958 | </div> |
| | 15959 | |
| | 15960 | <!-------------------> |
| | 15961 | <div class=entry> |
| | 15962 | |
| | 15963 | The Throw command now works properly when throwing something at |
| | 15964 | oneself. (In the past, throwing something at oneself incorrectly |
| | 15965 | tried to treat the actor as the drop location of the throw; it now |
| | 15966 | correctly treats the actor's location as the drop location.) |
| | 15967 | |
| | 15968 | </div> |
| | 15969 | |
| | 15970 | <!-------------------> |
| | 15971 | <div class=entry> |
| | 15972 | |
| | 15973 | The new NOTE verb accepts an arbitrary literal as its object; the |
| | 15974 | command doesn't do anything except acknowledge the input. The purpose |
| | 15975 | of the command is to allow the player to enter arbitrary notes into |
| | 15976 | the session transcript as she plays the game. Players might want to |
| | 15977 | make such notes for their own later reference, but this command is |
| | 15978 | especially useful for play-testing, because it gives play-testers |
| | 15979 | a very easy way of pointing out bugs or making comments directly in |
| | 15980 | the session transcript where they apply, and at the moment they occur |
| | 15981 | to the player. |
| | 15982 | |
| | 15983 | </div> |
| | 15984 | |
| | 15985 | <!-------------------> |
| | 15986 | <div class=entry> |
| | 15987 | |
| | 15988 | A library bug caused a run-time error if an attempt was made to remap |
| | 15989 | from a direct object handler (a dobjFor) to an intransitive action |
| | 15990 | (an action with no objects). Remapping to intransitive actions will |
| | 15991 | now work properly. |
| | 15992 | |
| | 15993 | </div> |
| | 15994 | |
| | 15995 | <!-------------------> |
| | 15996 | <div class=entry> |
| | 15997 | |
| | 15998 | The RealTimeDaemon class had a couple of problems that prevented it |
| | 15999 | from working properly. For one thing, it wasn't based on RealTimeEvent |
| | 16000 | as it should have been; for another, it didn't reset its next firing |
| | 16001 | time when fired. These problems have been corrected. |
| | 16002 | |
| | 16003 | </div> |
| | 16004 | |
| | 16005 | <!------------------------------- 3.0.6i ---------------------------------> |
| | 16006 | <div class="sepbar"><a name='306i'></a>3.0.6i</div> |
| | 16007 | <p><b><i>Released June 15, 2003</i></b> |
| | 16008 | <p> |
| | 16009 | |
| | 16010 | <div class=firstentry> |
| | 16011 | |
| | 16012 | The commandSequencer now starts in "before-command" mode, rather than |
| | 16013 | in "no-command" mode. This allows any introductory text displayed |
| | 16014 | before the first command to use the normal command sequencing tags. |
| | 16015 | |
| | 16016 | </div> |
| | 16017 | |
| | 16018 | <!-------------------> |
| | 16019 | <div class=entry> |
| | 16020 | |
| | 16021 | The "seen" property of Thing has been changed slightly in meaning. In |
| | 16022 | the past, this property was set to true only when an object was |
| | 16023 | specifically listed as a portable item in a room description. Now, |
| | 16024 | the property is set to true whenever a room description is displayed |
| | 16025 | from the player character's perspective, and the object is visible to |
| | 16026 | the player character. The important difference is that |
| | 16027 | <b>unlisted</b> items, such as 'Fixture' and 'Heavy' items, or items |
| | 16028 | with special descriptions, will be marked as seen as soon as their |
| | 16029 | containing rooms are described. |
| | 16030 | |
| | 16031 | </div> |
| | 16032 | |
| | 16033 | <!-------------------> |
| | 16034 | <div class=entry> |
| | 16035 | |
| | 16036 | Due to a bug in the previous version, the REPLAY command only worked |
| | 16037 | when one of its qualifiers (REPLAY QUIET or REPLAY NONSTOP) was used; |
| | 16038 | just plain REPLAY didn't work. The plain REPLAY command now works |
| | 16039 | correctly. |
| | 16040 | |
| | 16041 | </div> |
| | 16042 | |
| | 16043 | <!-------------------> |
| | 16044 | <div class=entry> |
| | 16045 | |
| | 16046 | The gameinfo.t module has been removed from the base system library. |
| | 16047 | In its place, the GameID class has been extended to write the GameInfo |
| | 16048 | data file automatically during pre-initialization. If the game defines |
| | 16049 | a GameID object, then the library automatically writes a gameinfo.txt |
| | 16050 | file, using values from the GameID object. Refer to the comments |
| | 16051 | in modid.t for the GameID class. |
| | 16052 | |
| | 16053 | </div> |
| | 16054 | |
| | 16055 | <!-------------------> |
| | 16056 | <div class=entry> |
| | 16057 | |
| | 16058 | Actor.setConvNode() now accepts a string giving the name of a |
| | 16059 | ConvNode, as an alternative to a reference to a ConvNode object. In |
| | 16060 | the past, only the object reference was accepted. Passing in a |
| | 16061 | string naming a ConvNode now has the same effect as passing a |
| | 16062 | reference to the ConvNode itself. |
| | 16063 | |
| | 16064 | </div> |
| | 16065 | |
| | 16066 | <!-------------------> |
| | 16067 | <div class=entry> |
| | 16068 | |
| | 16069 | The new Actor method initiateConversation() makes it easier to code |
| | 16070 | an NPC initiating a conversation. This method takes an ActorState |
| | 16071 | object to use as the NPC's new state, and a ConvNode (which can be |
| | 16072 | specified by the string name of the ConvNode) to use as the initial |
| | 16073 | conversation node. |
| | 16074 | |
| | 16075 | <p>In addition, the new ConvNode method npcGreetingMsg is defined to |
| | 16076 | display the initial conversational exchange in an NPC-initiated |
| | 16077 | conversation. Any ConvNode used in an initiateConversation() call |
| | 16078 | must either override npcGreetingMsg to define a greeting message, or |
| | 16079 | define an npcGreetingList property as a TextList containing a list |
| | 16080 | of greeting messages. |
| | 16081 | |
| | 16082 | </div> |
| | 16083 | |
| | 16084 | <!-------------------> |
| | 16085 | <div class=entry> |
| | 16086 | |
| | 16087 | The new ConvNode method npcContinueMsg is defined to display a |
| | 16088 | conversational "continuation" message from the actor. This method |
| | 16089 | lets the NPC continue a conversation of its own volition if the player |
| | 16090 | character doesn't do so. This method is invoked on each turn when the |
| | 16091 | ConvNode is active, <i>and</i> the player didn't enter a |
| | 16092 | conversational command on that turn. The method is invoked during the |
| | 16093 | actor's takeTurn() daemon processing. To define a continuation |
| | 16094 | message, you can either define npcContinueMsg as a double-quoted |
| | 16095 | string with the message, or you can define npcContinueList to a |
| | 16096 | TextList subclass containing a list of continuation messages. |
| | 16097 | |
| | 16098 | <p>If you don't override npcContinueMsg or npcContinueList, there will |
| | 16099 | be no NPC-initiated continuation message. If you do provide a |
| | 16100 | continuation message, then the ConvNode stays active by default. You |
| | 16101 | can use the <.convnode> tag within the continuation message's |
| | 16102 | text to switch to a new ConvNode, just as in a topic response message. |
| | 16103 | |
| | 16104 | </div> |
| | 16105 | |
| | 16106 | <!-------------------> |
| | 16107 | <div class=entry> |
| | 16108 | |
| | 16109 | The commandSequencer now starts in "before-command" mode, rather than |
| | 16110 | in "no-command" mode. This allows any introductory text displayed |
| | 16111 | before the first command to use the normal command sequencing tags. |
| | 16112 | |
| | 16113 | </div> |
| | 16114 | |
| | 16115 | <!-------------------> |
| | 16116 | <div class=entry> |
| | 16117 | |
| | 16118 | The Yes and No topic classes (YesTopic, NoTopic, YesNoTopic) had a |
| | 16119 | number of bugs that prevented them from working properly. These |
| | 16120 | classes should now work correctly. |
| | 16121 | |
| | 16122 | </div> |
| | 16123 | |
| | 16124 | <!-------------------> |
| | 16125 | <div class=entry> |
| | 16126 | |
| | 16127 | A new template for DefaultTopic makes it easier to define these |
| | 16128 | objects. The DefaultTopic template accepts simply a response string |
| | 16129 | (double-quoted), or a list of response strings (single-quoted). |
| | 16130 | |
| | 16131 | </div> |
| | 16132 | |
| | 16133 | <!-------------------> |
| | 16134 | <div class=entry> |
| | 16135 | |
| | 16136 | A bug in the AltTopic mechanism prevented intermediate AltTopics in |
| | 16137 | nestings more than one level deep from being properly selected. This |
| | 16138 | is now fixed. |
| | 16139 | |
| | 16140 | </div> |
| | 16141 | |
| | 16142 | <!-------------------> |
| | 16143 | <div class=entry> |
| | 16144 | |
| | 16145 | In the English-language module, the miscWord production now accepts |
| | 16146 | '#'-prefaced numbers and quoted strings. This provides more |
| | 16147 | flexibility for inputs in things like topic phrases. |
| | 16148 | |
| | 16149 | </div> |
| | 16150 | |
| | 16151 | <!-------------------> |
| | 16152 | <div class=entry> |
| | 16153 | |
| | 16154 | The AccompanyingState class didn't use the correct test for a travel |
| | 16155 | action in its beforeAction() method, which prevented the class from |
| | 16156 | carrying out its accompanying travel role at all. This has been |
| | 16157 | corrected. |
| | 16158 | |
| | 16159 | </div> |
| | 16160 | |
| | 16161 | <!-------------------> |
| | 16162 | <div class=entry> |
| | 16163 | |
| | 16164 | ActorState.obeyCommand() generated the wrong default message. This |
| | 16165 | is now fixed. |
| | 16166 | |
| | 16167 | </div> |
| | 16168 | |
| | 16169 | <!-------------------> |
| | 16170 | <div class=entry> |
| | 16171 | |
| | 16172 | ConvNode had a couple of problems that caused run-time errors or other |
| | 16173 | strange behavior when activating a ConvNode that had no associated |
| | 16174 | SpecialTopics. These have been fixed. |
| | 16175 | |
| | 16176 | </div> |
| | 16177 | |
| | 16178 | <!-------------------> |
| | 16179 | <div class=entry> |
| | 16180 | |
| | 16181 | Fuses and daemons (including real-time events and prompt daemons) now |
| | 16182 | run automatically in a standard Action environment. This means that |
| | 16183 | you can call essentially any library code without having to worry |
| | 16184 | about whether or not it will need to access gAction or gTranscript. |
| | 16185 | In the past, fuse and daemon code was called with no Action |
| | 16186 | environment in effect, which made it necessary to either limit the |
| | 16187 | library calls made within the fuse or daemon, or to explicitly set up |
| | 16188 | an action environment (using withActionEnv(), for example) before |
| | 16189 | invoking library code. This added a lot of unnecessary complexity |
| | 16190 | to fuse/daemon code. Now that these routines are always invoked with |
| | 16191 | a valid Action environment, these restrictions have been lifted. |
| | 16192 | |
| | 16193 | </div> |
| | 16194 | |
| | 16195 | <!-------------------> |
| | 16196 | <div class=entry> |
| | 16197 | |
| | 16198 | The withActionEnv() method now takes an additional argument, giving the |
| | 16199 | specific Action class to use for the dummy action object in effect during |
| | 16200 | the callback. |
| | 16201 | |
| | 16202 | </div> |
| | 16203 | |
| | 16204 | <!-------------------> |
| | 16205 | <div class=entry> |
| | 16206 | |
| | 16207 | The senseContext object's pushSenseContext() and popSenseContext() have |
| | 16208 | been removed; they've been replaced with a new withSenseContext() method. |
| | 16209 | |
| | 16210 | <p>In addition, the callWithSenseContext() function has been changed |
| | 16211 | to eliminate the argument list parameter; instead, callers should use |
| | 16212 | anonymous functions when the code to be invoked requires arguments. |
| | 16213 | (This is the way the rest of the library already used the function in |
| | 16214 | most cases anyway, so this change simply cleans up some old code |
| | 16215 | that's no longer needed. Most games won't need to call this function |
| | 16216 | directly, so this is unlikely to affect any existing game code.) |
| | 16217 | |
| | 16218 | </div> |
| | 16219 | |
| | 16220 | <!-------------------> |
| | 16221 | <div class=entry> |
| | 16222 | |
| | 16223 | The INSTRUCTIONS command now operates either in menu or in-line mode, |
| | 16224 | not both. In the past, the menu format supplemented the in-line format, |
| | 16225 | but this was redundant and complicated the user interface. |
| | 16226 | |
| | 16227 | </div> |
| | 16228 | |
| | 16229 | <!------------------------------- 3.0.6h ---------------------------------> |
| | 16230 | <div class="sepbar"><a name='306h'></a>3.0.6h</div> |
| | 16231 | <p><b><i>Released June 7, 2003</i></b> |
| | 16232 | <p> |
| | 16233 | |
| | 16234 | <div class=firstentry> |
| | 16235 | |
| | 16236 | Several major enhancements to the Actor class have been added. |
| | 16237 | These changes are described in more detail in the comments in the |
| | 16238 | library sources files, and in a new series of technical articles on |
| | 16239 | the <a href='http://www.tads.org'>tads.org</a> web site, <a |
| | 16240 | href='http://www.tads.org/howto/t3actor.htm'>Creating Dynamic |
| | 16241 | Characters in TADS 3</a>. We'll summarize the changes here, but you |
| | 16242 | should refer to the articles for full details. |
| | 16243 | |
| | 16244 | <p><b>WARNING! Due to the extensive scope of these new features, |
| | 16245 | there's a good chance that they'll undergo some changes as we gain |
| | 16246 | experience with them. Be aware that game code that uses these features |
| | 16247 | might have to be changed to accommodate library changes in future updates. |
| | 16248 | </b> |
| | 16249 | |
| | 16250 | <p>A new class, ActorState, makes it easier to create characters that |
| | 16251 | exhibit multiple behaviors. The Actor class has been changed to work |
| | 16252 | with ActorState; most of the methods involved in describing an actor's |
| | 16253 | physical state and in interacting with an actor are now delegated from |
| | 16254 | the Actor class to the ActorState object. The idea is that most of |
| | 16255 | the parts of an actor that need to vary according to the actor's |
| | 16256 | behavior have been moved to the new ActorState object; this means that |
| | 16257 | adding a new behavior to an actor is a matter of defining a new |
| | 16258 | ActorState object for the actor. |
| | 16259 | |
| | 16260 | <p>Several subclasses of ActorState have also been created. These |
| | 16261 | include ConversationReadyState and InConversationState, which are used |
| | 16262 | to make an actor explicitly enter, maintain, and exit a conversation; |
| | 16263 | HermitActorState, for times when an actor is unresponsive; and |
| | 16264 | AccompanyingState and AccompanyingInTravelState, which allow an NPC to |
| | 16265 | travel with another character as part of the character's own turns. |
| | 16266 | |
| | 16267 | <p>A new "topic database" system makes it easier to manage |
| | 16268 | conversational interactions, by creating individual objects that |
| | 16269 | represent responses to ASK, TELL, GIVE, SHOW, and other interactions. |
| | 16270 | The TopicDatabase class is used to store an actor's responses; Actor |
| | 16271 | and ActorState inherit from TopicDatabase, so you don't normally |
| | 16272 | create instances of this class directly. The TopicEntry class |
| | 16273 | represents a response; several subclasses, including AltTopic, |
| | 16274 | AskTopic, TellTopic, AskTellTopic, GiveTopic, ShowTopic, |
| | 16275 | GiveShowTopic, YesTopic, NoTopic, DefaultTopic, and SpecialTopic are |
| | 16276 | used to create the individual responses. |
| | 16277 | |
| | 16278 | <p>The conversationManager object and the ConvNode class are used |
| | 16279 | to manage "threaded" conversations. A threaded conversation is one |
| | 16280 | where an actor keeps track of what has been said before, and responds |
| | 16281 | according to the context of the conversation. |
| | 16282 | |
| | 16283 | <p>The SuggestedTopic class and its subclasses let you maintain a |
| | 16284 | "topic inventory," which is a mechanism that automatically suggests |
| | 16285 | topics to the player. This is an optional mechanism that you can |
| | 16286 | use in various ways; you can use it as a sort of hint system, and |
| | 16287 | you can use it to guide threaded conversations. |
| | 16288 | |
| | 16289 | </div> |
| | 16290 | |
| | 16291 | <!-------------------> |
| | 16292 | <div class=entry> |
| | 16293 | |
| | 16294 | Two library modules have been renamed: 'hints.t' is now 'hintsys.t', |
| | 16295 | and 'menus.t' is now 'menusys.t'. Since these modules are included in |
| | 16296 | most projects using the library file (adv3.tl), this shouldn't require |
| | 16297 | any changes to any game code or project makefiles. The new names |
| | 16298 | better reflect that these modules define the hint and menu systems, |
| | 16299 | respectively, rather than actual hints or menus. |
| | 16300 | |
| | 16301 | </div> |
| | 16302 | |
| | 16303 | <!-------------------> |
| | 16304 | <div class=entry> |
| | 16305 | |
| | 16306 | A new function, withActionEnv(func), makes it possible for daemon |
| | 16307 | code to create a simulated Action environment. Some code relies upon |
| | 16308 | there being a current Action object and an active command transcript |
| | 16309 | object; these objects are normally only available while executing a |
| | 16310 | command, which made it difficult to call code that depends on this |
| | 16311 | command environment from within a daemon. This new function makes it |
| | 16312 | easy to call such code from within daemons and other non-command |
| | 16313 | contexts. The function sets up a dummy Action object and a default |
| | 16314 | command transcript, then invokes the given function; the function can |
| | 16315 | do anything that can be done during normal Action processing. |
| | 16316 | |
| | 16317 | </div> |
| | 16318 | |
| | 16319 | <!-------------------> |
| | 16320 | <div class=entry> |
| | 16321 | |
| | 16322 | Openable now shows any special descriptions of the contents of an |
| | 16323 | object that are revealed when the object is opened (via an OPEN |
| | 16324 | command). |
| | 16325 | |
| | 16326 | </div> |
| | 16327 | |
| | 16328 | <!-------------------> |
| | 16329 | <div class=entry> |
| | 16330 | |
| | 16331 | The English module now includes some needed customizations to the |
| | 16332 | TopicAction class. These were missing in the past, which caused |
| | 16333 | incorrect messages to be generated in some cases involving this |
| | 16334 | type of action. |
| | 16335 | |
| | 16336 | </div> |
| | 16337 | |
| | 16338 | <!-------------------> |
| | 16339 | <div class=entry> |
| | 16340 | |
| | 16341 | The new class RoomAutoConnector is a subclass of RoomConnector that |
| | 16342 | can be mixed in to any BasicLocation subclass to make the room usable |
| | 16343 | directly as a connector to itself. Room inherits from this class (it |
| | 16344 | formerly inherited from RoomConnector and overrode part of the |
| | 16345 | interface; the overrides are no longer necessary because they're |
| | 16346 | contained in RoomAutoConnector itself now). In particular, |
| | 16347 | RoomAutoConnector can be mixed in to any NestedRoom object's |
| | 16348 | superclasses to make the nested room usable as a connector to itself. |
| | 16349 | |
| | 16350 | </div> |
| | 16351 | |
| | 16352 | <!-------------------> |
| | 16353 | <div class=entry> |
| | 16354 | |
| | 16355 | The new notification methods beforeTravel(traveler, connector) and |
| | 16356 | afterTravel(traveler, connector) are invoked just before and after a |
| | 16357 | traveler travels via travelerTravelTo(). These notifications are sent |
| | 16358 | to each object connected by containment to the traveler; |
| | 16359 | beforeTravel() is called on each object connected by containment to |
| | 16360 | the traveler in its old location, and afterTravel() is called on each |
| | 16361 | object connected by containment in the new location. |
| | 16362 | |
| | 16363 | <p>These notifications are more precise than using beforeAction() and |
| | 16364 | afterAction() with the TravelVia pseudo-action, because these actions |
| | 16365 | are only called when travel is actually occurring. TravelVia will |
| | 16366 | fire notifications even when travel isn't actually possible. |
| | 16367 | |
| | 16368 | <p>A beforeTravel() method can veto the travel action using "exit". |
| | 16369 | The notification is invoked before the travel is actually performed, |
| | 16370 | and even before a description of the departure is produced. |
| | 16371 | |
| | 16372 | </div> |
| | 16373 | |
| | 16374 | <!-------------------> |
| | 16375 | <div class=entry> |
| | 16376 | |
| | 16377 | <p>The method Actor.trackFollowInfo() is now invoked from |
| | 16378 | Actor.beforeTravel() rather than directly from |
| | 16379 | traveler.travelerTravelTo(), as it was in the past. This change |
| | 16380 | makes the follow-tracking a lot less "special," in that it uses the |
| | 16381 | general before/after travel notification system rather than a |
| | 16382 | separate, purpose-built notification system. Note that this change |
| | 16383 | means that any actor object that overrides beforeTravel() must |
| | 16384 | inherit the base class implementation if the actor wants to be able |
| | 16385 | to follow other actors. |
| | 16386 | |
| | 16387 | </div> |
| | 16388 | |
| | 16389 | <!-------------------> |
| | 16390 | <div class=entry> |
| | 16391 | |
| | 16392 | The default travel precondition calculations have been changed |
| | 16393 | slightly to allow connections between top-level rooms to be placed |
| | 16394 | inside nested rooms. This allows, for example, a window that can |
| | 16395 | only be reached when standing on a desk, or a secret passage from |
| | 16396 | inside a wardrobe. The main changes are that TravelVia doesn't |
| | 16397 | automatically require the traveler to be in the outermost room, but |
| | 16398 | in the room containing the outbound connector; and travel between |
| | 16399 | top-level rooms that leaves the traveler inside a nested room (as |
| | 16400 | would happen when climbing through the window from outside and ending |
| | 16401 | up on the shelf) now provides a normal arrival message. |
| | 16402 | |
| | 16403 | <p>First, BasicLocation.roomTravelPreCond() no longer does anything; |
| | 16404 | the method is still present so that rooms can override it as desired, |
| | 16405 | but it doesn't do anything by default. In the past, this method |
| | 16406 | unconditionally added a precondition requiring that the traveler be |
| | 16407 | in the outermost room; we don't want to apply that condition, since |
| | 16408 | the required starting location of the traveler depends on the |
| | 16409 | outbound connector, not the room. |
| | 16410 | |
| | 16411 | <p>Second, TravelConnector.connectorTravelPreCond() now adds a |
| | 16412 | requirement that the traveler be in the connector's location, if the |
| | 16413 | connector has a location. This ends up having the same effect as |
| | 16414 | BasicLocation.roomTravelPreCond() in cases where explicit connectors, |
| | 16415 | such as doors and passages, are situated in the top-level room. |
| | 16416 | |
| | 16417 | <p>Third, RoomAutoConnector.connectorTravelPreCond() overrides the |
| | 16418 | inherited version, and instead requires that the traveler be in the |
| | 16419 | "appropriate" starting location. This provides the same effect as |
| | 16420 | the old BasicLocation.roomTravelPreCond(), but with an enhancement. |
| | 16421 | The "appropriate" location is defined as the nearest enclosing |
| | 16422 | location (enclosing the traveler) that has a directional connection |
| | 16423 | ("north = xxx", etc) leading to the room. In most cases, rooms are |
| | 16424 | connected directly to one another only at the top level; in such |
| | 16425 | cases, the directional connection will be found in the traveler's |
| | 16426 | outermost room, so the effect will be exactly as it was with the old |
| | 16427 | system. But here's the enhancement: in cases where the directional |
| | 16428 | connector is defined leading out of a nested room, this will |
| | 16429 | correctly find the nested room as the starting location. |
| | 16430 | |
| | 16431 | <p>Note that NestedRoom objects <b>cannot</b> by default be used as |
| | 16432 | direct targets of directional connectors, because they're not based |
| | 16433 | on RoomConnector. It seems highly unlikely that it would ever be |
| | 16434 | useful to connect a nested room directly to a directional connector |
| | 16435 | (i.e., "east = wardrobe") - some kind of explicit connector (a door, |
| | 16436 | or a passage, or something) seems desirable in almost every case, |
| | 16437 | just from the perspective of game geography. In the event that a |
| | 16438 | direct directional connector is required, though, simply include |
| | 16439 | RoomAutoConnector in the superclass list for your specific nested |
| | 16440 | room. |
| | 16441 | |
| | 16442 | <p>Fourth, the methods travelerArriving() and travelerLeaving() have |
| | 16443 | been moved from Room to BasicLocation. This produces the proper |
| | 16444 | travel messages for any travel between top-level locations, even when |
| | 16445 | the travel starts or ends in a nested location. |
| | 16446 | |
| | 16447 | </div> |
| | 16448 | |
| | 16449 | <!-------------------> |
| | 16450 | <div class=entry> |
| | 16451 | |
| | 16452 | BasicLocation.travelerArriving() now enforces the defaultPosture |
| | 16453 | setting for the location. The default posture is enforced via a |
| | 16454 | nested command before the arrival message is displayed. This makes |
| | 16455 | it easier to create locations with restrictions on posture, such as a |
| | 16456 | low crawl where you can only sit or lie down. |
| | 16457 | |
| | 16458 | <p>Note that if all goes well, there won't be any mention of the |
| | 16459 | action for the player character (because the successful nested action |
| | 16460 | will result in a default report, which will be suppressed due to the |
| | 16461 | non-default message for the room description); so the new posture |
| | 16462 | will simply be reflected in the description of the new location. |
| | 16463 | Generally, all should always go well in these cases, since the actor |
| | 16464 | will already be located within the location and merely has to change |
| | 16465 | posture. If you want to explain why the posture change is necessary, |
| | 16466 | you can override travelerArriving() for the location, display an |
| | 16467 | explanation, then inherit the default. An appropriate message would |
| | 16468 | be something like "The ceiling is so low you have to lie down." |
| | 16469 | |
| | 16470 | </div> |
| | 16471 | |
| | 16472 | <!-------------------> |
| | 16473 | <div class=entry> |
| | 16474 | |
| | 16475 | The semantics of TravelConnector.getDestination() have been changed |
| | 16476 | slightly. First, the method now takes a traveler rather than an |
| | 16477 | actor, since connectors are always traversed by travelers. (A |
| | 16478 | traveler might in fact turn out to be an actor, of course, but it |
| | 16479 | could also be something else, such as a vehicle.) Second, the method |
| | 16480 | is now required to return the destination, and the destination must be |
| | 16481 | stable for the duration of the turn up to the point where the travel |
| | 16482 | actually occurs. |
| | 16483 | |
| | 16484 | <p>To allow for connectors that are affected by traversal (for |
| | 16485 | example, a connector that randomizes its destination each time it's |
| | 16486 | used), the new method noteTraversal() must be called whenever the |
| | 16487 | connector is actually traversed. This method can change the connector |
| | 16488 | state as needed for the traversal. Note that game code should |
| | 16489 | generally never need to call noteTraversal(), as the library |
| | 16490 | dobjFor(TravelVia) action implementations do this automatically as |
| | 16491 | needed. This method is provided for games to override as needed. |
| | 16492 | |
| | 16493 | </div> |
| | 16494 | |
| | 16495 | <!-------------------> |
| | 16496 | <div class=entry> |
| | 16497 | |
| | 16498 | The base TAction and TIAction classes no longer require that any of |
| | 16499 | the target objects of the command define an action() method for the |
| | 16500 | verb. Instead, the classes now merely require that at least one of |
| | 16501 | the target objects defines any of action(), check(), or verify(). If |
| | 16502 | none of the target objects defines any of these methods for the verb, |
| | 16503 | then the verb will automatically add an "illogical" status during the |
| | 16504 | verify phase. |
| | 16505 | |
| | 16506 | <p>The purpose of this check is to ensure that the command has |
| | 16507 | <i>some</i> sort of handling. If the game adds a new verb, but never |
| | 16508 | defines any handling at all for the new verb for some object, then |
| | 16509 | without this check, there would be no handling at all if the player |
| | 16510 | attempted to apply the verb to that object. The old check tested for |
| | 16511 | the existence of an action() handler, but this was overly |
| | 16512 | conservative, since an object could have fully handled the verb in its |
| | 16513 | verify() or check() handler. The new test allows for this by allowing |
| | 16514 | the action to proceed if any sort of handler (check, verify, or |
| | 16515 | action) is defined for an object involved in the command. |
| | 16516 | |
| | 16517 | </div> |
| | 16518 | |
| | 16519 | <!-------------------> |
| | 16520 | <div class=entry> |
| | 16521 | |
| | 16522 | A new property, globalParamName, has been added to Thing. This lets |
| | 16523 | you define a substitution parameter string (for "{xxx}" sequences) |
| | 16524 | that can be used at any time to refer to the object in message text. |
| | 16525 | Once you define an object as having a global parameter name, you can |
| | 16526 | use that name to refer to the object in {xxx} sequences, even when no |
| | 16527 | command is active, and even when the object isn't involved in any |
| | 16528 | command. This can be especially useful for writing messages that |
| | 16529 | refer to objects whose names change in the course of the game, such as |
| | 16530 | actors who are known by one name until introduced, then are known by |
| | 16531 | another name ("the white-haired man" might become "Bob" after he tells |
| | 16532 | us his name, for example). |
| | 16533 | |
| | 16534 | </div> |
| | 16535 | |
| | 16536 | <!-------------------> |
| | 16537 | <div class=entry> |
| | 16538 | |
| | 16539 | A new Script subclass, EventList, provides a convenient way of |
| | 16540 | defining scripts using procedural code in steps without writing a big |
| | 16541 | 'switch' statement in the doScript() method. The eventList property |
| | 16542 | contains a list of script step elements. Each element gives one step |
| | 16543 | of the script. An element can be a single-quoted string, in which |
| | 16544 | case the string is simply displayed; a function pointer, in which case |
| | 16545 | the function is invoked with no arguments; a ScriptEvent object, in |
| | 16546 | which case the object's doEvent() method is invoked; or nil, in which |
| | 16547 | case nothing happens on the step. |
| | 16548 | |
| | 16549 | </div> |
| | 16550 | |
| | 16551 | <!-------------------> |
| | 16552 | <div class=entry> |
| | 16553 | |
| | 16554 | The Actor method getDefaultInterlocutor() has been renamed to |
| | 16555 | getCurrentInterlocutor(), to better reflect its purpose. The |
| | 16556 | conversation model keeps track of the actor we're currently talking |
| | 16557 | to; conversational commands that aren't directed to a specific actor |
| | 16558 | (such as ASK ABOUT BOOK) are assumed to be directed to the current |
| | 16559 | conversational partner. |
| | 16560 | |
| | 16561 | </div> |
| | 16562 | |
| | 16563 | <!-------------------> |
| | 16564 | <div class=entry> |
| | 16565 | |
| | 16566 | A couple of the abstract base classes in the area of Container have |
| | 16567 | been renamed to better reflect their purposes. The class formerly |
| | 16568 | known as BasicContainer is now called BulkLimiter, and the class |
| | 16569 | formerly known as Encloser is now called BasicContainer. So, Container |
| | 16570 | is a BasicContainer, which is a BulkLimiter; Surface is also a |
| | 16571 | BulkLimiter. The new name BulkLimiter is more consistent with its |
| | 16572 | main purpose, which is to constrain the aggregate bulk of its |
| | 16573 | contents. The old name "Encloser" was confusingly similar to the |
| | 16574 | real word "Enclosure," and was vague in conveying how the class |
| | 16575 | differs from Container; the new name BasicContainer makes it clearer |
| | 16576 | that this class contains some of the basic abstract functionality |
| | 16577 | of Container but |
| | 16578 | |
| | 16579 | </div> |
| | 16580 | |
| | 16581 | <!-------------------> |
| | 16582 | <div class=entry> |
| | 16583 | |
| | 16584 | The actor inventory listing mechanism has been reworked to make it a |
| | 16585 | smarter about the listing format. When the inventory list is short, |
| | 16586 | the listing will appear in a single sentence showing both the items |
| | 16587 | being carried and the items being worn. When the listing is long, |
| | 16588 | it's broken up into two sentences, as in the past. The threshhold for |
| | 16589 | "long" is set with a property of the new DividedInventoryLister class, |
| | 16590 | singleSentenceMaxNouns; the default is 7, which means that the listing |
| | 16591 | will be shown in one sentence if it involves seven items of fewer, two |
| | 16592 | sentences otherwise. For example: |
| | 16593 | |
| | 16594 | <p> |
| | 16595 | <pre> |
| | 16596 | >inventory |
| | 16597 | You are carrying a music box, a gold coin, and thirty silver coins, |
| | 16598 | and you're wearing a watch and a helmet. |
| | 16599 | |
| | 16600 | >inventory |
| | 16601 | You are carrying a cardboard box (which contains several LP's, a |
| | 16602 | bunch of photographs, and some letters), a rubber chicken, two |
| | 16603 | pieces of the Magic Goblet of Forblotsk, and a bowl of chowder. |
| | 16604 | You're wearing a pair of flippers, a wool jacket, and a red wig. |
| | 16605 | </pre> |
| | 16606 | |
| | 16607 | <p>The list length is determined by capturing the output and counting |
| | 16608 | the phrase separators. The English library counts commas, semicolons, |
| | 16609 | the word "and", and right parentheses to determine the phrase count. |
| | 16610 | |
| | 16611 | <p>This change slightly affects the Actor class (showInventoryWith now |
| | 16612 | takes only one lister object), and extensively affects the |
| | 16613 | InventoryLister class and the WearingLister class and their subclasses |
| | 16614 | (the English-specific implementations in msg_neu.t). Games shouldn't |
| | 16615 | be affected unless they modified these classes. |
| | 16616 | |
| | 16617 | <p>If you want the old behavior, where the items being worn and the |
| | 16618 | items being carried were always shown as separate sentences, simply |
| | 16619 | set DividedInventoryLister.singleSentenceMaxNouns to zero. If you |
| | 16620 | want to always use a single sentence no matter what, set the property |
| | 16621 | to some absurdly high number - 30000, say. |
| | 16622 | |
| | 16623 | <p>If you'd prefer the more traditional behavior that shows the items |
| | 16624 | being worn marked "(being worn)" and mixed in with the rest of the |
| | 16625 | inventory in a single listing, simply change Actor.inventoryLister |
| | 16626 | to refer to actorSingleInventoryLister. |
| | 16627 | |
| | 16628 | </div> |
| | 16629 | |
| | 16630 | <!-------------------> |
| | 16631 | <div class=entry> |
| | 16632 | |
| | 16633 | The match list for an ALL phrase in player input is now filtered |
| | 16634 | through the filterResolveList() method of each object in the list, |
| | 16635 | just as ambiguous noun phrases are. This allows objects that |
| | 16636 | substitute for others in resolution lists (such as Collective and |
| | 16637 | CollectiveGroup objects) to perform the same substitutions in ALL |
| | 16638 | lists that they would in normal matches. |
| | 16639 | |
| | 16640 | </div> |
| | 16641 | |
| | 16642 | <!-------------------> |
| | 16643 | <div class=entry> |
| | 16644 | |
| | 16645 | The miscWord grammar rules are now defined in en_us.t, rather than |
| | 16646 | in the language-independent parser.t as they were previously. This |
| | 16647 | change is necessary because different languages might have different |
| | 16648 | token types that are valid in miscellaneous word lists. (In point of |
| | 16649 | fact, the English parser defines a special language-specific token, |
| | 16650 | tokApostropheS, that is now allowed in miscellaenous word lists.) |
| | 16651 | |
| | 16652 | </div> |
| | 16653 | |
| | 16654 | <!-------------------> |
| | 16655 | <div class=entry> |
| | 16656 | |
| | 16657 | The menu system now uses the regular game color scheme as the |
| | 16658 | defaults; the top "instructions" bar is shown using the status line |
| | 16659 | color scheme, and the main menu area uses the normal game window color |
| | 16660 | scheme. This scheme is the safest default, since it uses only colors |
| | 16661 | the user has selected (on interpreters that allow the user to select |
| | 16662 | the color scheme); this ensures in particular that things like |
| | 16663 | hyperlink colors work well with the menu colors, since presumably the |
| | 16664 | user will have chosen settings that work well together. (If not, at |
| | 16665 | least it's not the game's fault.) This change means that menus won't |
| | 16666 | stand out as well from the main game window, since they use the same |
| | 16667 | color scheme, so the default mode for menus has been changed to the |
| | 16668 | "full screen" mode. This new default appearance - full screen, using |
| | 16669 | normal game and status-line colors - makes menus very unobtrusive, |
| | 16670 | since they just look like an ordinary game screen. |
| | 16671 | |
| | 16672 | </div> |
| | 16673 | |
| | 16674 | <!-------------------> |
| | 16675 | <div class=entry> |
| | 16676 | |
| | 16677 | The menu system takes advantage of the new MORE-mode banner style |
| | 16678 | option, by using a separate banner to show "long topic" items. Since |
| | 16679 | long text can now safely be displayed in a banner, with the interpreter |
| | 16680 | providing pagination via MORE prompts as needed, long topics can avoid |
| | 16681 | taking over the main game window. This is nice because it leaves the |
| | 16682 | original game window intact (without any need to clear the screen) after |
| | 16683 | the user exits from the menu system. |
| | 16684 | |
| | 16685 | </div> |
| | 16686 | |
| | 16687 | <!-------------------> |
| | 16688 | <div class=entry> |
| | 16689 | |
| | 16690 | The MenuItem class has a new property, heading, that specifies the |
| | 16691 | text to display as the heading of the menu while the menu is active. |
| | 16692 | By default, the heading is the same as the title, which is the string |
| | 16693 | displayed in the parent menu's list of items. The separate property |
| | 16694 | allows the caption shown while the menu is active to differ from its |
| | 16695 | title, if this is desired. |
| | 16696 | |
| | 16697 | </div> |
| | 16698 | |
| | 16699 | <!-------------------> |
| | 16700 | <div class=entry> |
| | 16701 | |
| | 16702 | A couple of the English messages for the npcMessagesDirect group have |
| | 16703 | been recast as quoted statements from the NPC, for consistency with |
| | 16704 | other messages in the group. The affected messages are |
| | 16705 | noMatchDisambig and disambigOrdinalOutOfRange. In addition, |
| | 16706 | askDisambig (in the same group) has been tweaked slightly to |
| | 16707 | accommodate this change. |
| | 16708 | |
| | 16709 | </div> |
| | 16710 | |
| | 16711 | <!-------------------> |
| | 16712 | <div class=entry> |
| | 16713 | |
| | 16714 | The CollectiveGroup class has been split into two classes. The full |
| | 16715 | behavior of the old class is now contained in the class |
| | 16716 | ItemizingCollectiveGroup, which is a subclass of CollectiveGroup. On |
| | 16717 | Examine, the CollectiveGroup class no longer shows the itemized list |
| | 16718 | of collected items, but instead simply shows its own description using |
| | 16719 | the normal Examine handling. The itemizing behavior is desirable in |
| | 16720 | some cases of collective groups, but certainly not all; this change |
| | 16721 | makes it easy for the game to select whether or not the itemizing |
| | 16722 | behavior is used. |
| | 16723 | |
| | 16724 | </div> |
| | 16725 | |
| | 16726 | <!-------------------> |
| | 16727 | <div class=entry> |
| | 16728 | |
| | 16729 | If a check() routine (in a dobjFor() or iobjFor() group) terminates |
| | 16730 | the command with 'exit', the parser now automatically marks the action |
| | 16731 | in the transcript as having failed. This is the same thing that the |
| | 16732 | reportFailure() macro does, so this means that it's never necessary |
| | 16733 | to use reportFailure() from within a check() handler. Since the purpose |
| | 16734 | of check() is to enforce conditions on the action, exiting from the |
| | 16735 | check() routine necessarily means that the command has failed; this |
| | 16736 | change takes advantage of that to save games a bit of work. |
| | 16737 | |
| | 16738 | </div> |
| | 16739 | |
| | 16740 | <!-------------------> |
| | 16741 | <div class=entry> |
| | 16742 | |
| | 16743 | A new set of grammar productions provide for third-person reflexive |
| | 16744 | pronouns in verbs with two noun-phrase slots: "put klein bottle in |
| | 16745 | itself," for example. These are mostly intended for conversation, |
| | 16746 | specifically things like "ask bob about himself," but will work in |
| | 16747 | general for the rare cases where they might be useful. |
| | 16748 | |
| | 16749 | <p>The parser resolves a third-person reflexive pronoun by referring |
| | 16750 | back to the resolved object list for the other noun phrase in the |
| | 16751 | action. Verbs taking only one noun phrase don't accept these, as they |
| | 16752 | make no sense: "open itself" isn't meaningful. In the basic TIAction, |
| | 16753 | the order of noun phrase resolution can vary by verb, and the order |
| | 16754 | of resolution isn't required to match the order of the nouns in the |
| | 16755 | phrase; in English, at least, a reflexive pronoun in this type of |
| | 16756 | construction is always anaphoric (i.e., it always refers to a phrase |
| | 16757 | earlier in the sentence). This means that the TIAction resolver could |
| | 16758 | find itself trying to resolve the reflexive phrase first, before it |
| | 16759 | knows the resolution of the phrase to which the reflexive refers. |
| | 16760 | To cope with this situation, the resolver notes when this occurs, |
| | 16761 | provides an empty list for the initial resolution of the reflexive, |
| | 16762 | and then goes back and re-resolves the reflexive after resolving |
| | 16763 | the other noun phrase. |
| | 16764 | |
| | 16765 | </div> |
| | 16766 | |
| | 16767 | <!-------------------> |
| | 16768 | <div class=entry> |
| | 16769 | |
| | 16770 | The new Thing property isKnown lets you specify that an object is |
| | 16771 | known in advance to the actors in the game. The method isKnownBy(actor) |
| | 16772 | can be used to test actor knowledge of a Thing: isKnownBy(actor) returns |
| | 16773 | true if seenBy(actor) returns true, or the isKnown property is set to |
| | 16774 | true for the object. The Actor methods knowsTopic() and isLikelyTopic() |
| | 16775 | now use isKnownBy() rather than seenBy() to determine actor knowledge. |
| | 16776 | |
| | 16777 | </div> |
| | 16778 | |
| | 16779 | <!-------------------> |
| | 16780 | <div class=entry> |
| | 16781 | |
| | 16782 | A few new conversation-related verbs have been added: Goodbye, |
| | 16783 | Yes, and No. These are handled similarly to Hello. |
| | 16784 | |
| | 16785 | </div> |
| | 16786 | |
| | 16787 | <!-------------------> |
| | 16788 | <div class=entry> |
| | 16789 | |
| | 16790 | A new Action method, isConversational(issuingActor), determines if an |
| | 16791 | action is "conversational." A conversational action is one that |
| | 16792 | involves the issuing actor saying something, within the game context, |
| | 16793 | to the target actor, as opposed to an order to the target actor to do |
| | 16794 | something. Of the system-defined verbs, Hello, Goodbye, Yes, No, and |
| | 16795 | TellAbout (with the issuing actor as the direct object) are defined |
| | 16796 | as conversational. |
| | 16797 | |
| | 16798 | </div> |
| | 16799 | |
| | 16800 | <!-------------------> |
| | 16801 | <div class=entry> |
| | 16802 | |
| | 16803 | The interface of the Actor.obeyCommand() has changed, as has its meaning. |
| | 16804 | The method now takes two parameters: the actor who issued the command, and |
| | 16805 | the Action object. In the past, this method was called with only the |
| | 16806 | issuing actor as a parameter, because the action was unresolved when the |
| | 16807 | method was called. Now, the parser calls this method <i>after</i> |
| | 16808 | resolving the action and its objects. This change gives the method |
| | 16809 | full access to the details of the action, so it can decide to accept |
| | 16810 | or reject commands based on the actual action being performed. |
| | 16811 | |
| | 16812 | <p>The parser <i>does not</i> call this method when the action is |
| | 16813 | "conversational," as indicated by the isConversational() method no the |
| | 16814 | action. Conversational methods are not considered to involve an order |
| | 16815 | to the target actor. The actual physical action of a conversational |
| | 16816 | action simply consists of the issuing actor saying something to the |
| | 16817 | target actor, so even though these actions are phrased as though |
| | 16818 | they're orders to the target actor, they're really carried out by the |
| | 16819 | issuing actor, and thus don't require acceptance by the target actor. |
| | 16820 | |
| | 16821 | <p>The default implementation of this method on Actor calls the |
| | 16822 | corresponding method on the atcor's current state object. The |
| | 16823 | basic state object implementation simply refuses the command, so the |
| | 16824 | default behavior is the same as it was in the past. |
| | 16825 | |
| | 16826 | </div> |
| | 16827 | |
| | 16828 | <!-------------------> |
| | 16829 | <div class=entry> |
| | 16830 | |
| | 16831 | The TextList subclass formerly known as SlaveTextList has been |
| | 16832 | renamed to SyncTextList, to better reflect that this list is always |
| | 16833 | kept synchronized with its associated master list. The old name |
| | 16834 | suggested that the connection was one-way, that state changes flowed |
| | 16835 | only from the master to the slave, when in fact the master and slave |
| | 16836 | are fully synchronized. The new name is more suggestive of this |
| | 16837 | two-way connection. |
| | 16838 | |
| | 16839 | </div> |
| | 16840 | |
| | 16841 | <!-------------------> |
| | 16842 | <div class=entry> |
| | 16843 | |
| | 16844 | A new TextList subclass, StopTextList, provides a minor variation on |
| | 16845 | the standard text list script. Once StopTextList reaches its last |
| | 16846 | message, it will simply stay at the last message forever, repeating |
| | 16847 | the last message each time the script is invoked. This is useful for |
| | 16848 | cases such as a conversation topic where an actor has several things |
| | 16849 | to say, but once the actor has said each bit, the actor will from |
| | 16850 | that point on just repeat the last message; the last message would |
| | 16851 | usually be something like "I've already told you all I know about |
| | 16852 | it," or could be a summary of what the actor revealed. |
| | 16853 | |
| | 16854 | </div> |
| | 16855 | |
| | 16856 | <!-------------------> |
| | 16857 | <div class=entry> |
| | 16858 | |
| | 16859 | ShuffledTextList features a few enhancements. |
| | 16860 | |
| | 16861 | <p>First, a new property, firstStrings, can be set to a list of |
| | 16862 | strings to show sequentially before starting the shuffled strings. |
| | 16863 | This can be useful in cases where you have some meaningful |
| | 16864 | information to convey initially, but once those messages have been |
| | 16865 | displayed, you want to fall back on randomized messages for |
| | 16866 | atmosphere and variety. The firstStrings list is shown only once, in |
| | 16867 | sequential order. Once the firstStrings list is exhausted, these |
| | 16868 | strings are never shown again. |
| | 16869 | |
| | 16870 | <p>Second, the main shuffled list in textStrings can now be shown |
| | 16871 | sequentially the first time through, if desired. Set the property |
| | 16872 | shuffleFirst to nil (it's true by default) if you don't want the list |
| | 16873 | shuffled the first time through. Since the strings in the textStrings |
| | 16874 | list are intended to be shown in random order, in most cases it won't |
| | 16875 | matter to the author what order is used, and in this sense the order |
| | 16876 | in which the strings are actually defined is as random as any other |
| | 16877 | order. In some cases, it might actually be desirable to have the |
| | 16878 | strings come out in a certain order the first time through; this lets |
| | 16879 | you refer back to an earlier message in a later message, for example, |
| | 16880 | with assurance that the player will have always seen the earlier |
| | 16881 | message first. After the first time through the list, the list is |
| | 16882 | always shuffled and shown again in random order. |
| | 16883 | |
| | 16884 | <p>Third, the class now takes care to ensure that a message is never |
| | 16885 | repeated consecutively. Repeats are normally avoided naturally by |
| | 16886 | the shuffling: every item is shown once before anything is repeated. |
| | 16887 | But a consecutive repeat was still possible in one special case, |
| | 16888 | which is immediately after a shuffle. Because the order of one |
| | 16889 | shuffle is independent of the order of the next shuffle, it was |
| | 16890 | possible for the last element of the previous shuffle to be the same |
| | 16891 | as the first element of the next shuffle. The class now suppresses |
| | 16892 | this case by checking each new shuffle to make sure its first element |
| | 16893 | doesn't match the last element of the previous shuffle, and choosing |
| | 16894 | again when necessary. This change is intended to increase the |
| | 16895 | apparent randomness by ensuring that the same string is never shown |
| | 16896 | twice in a row. |
| | 16897 | |
| | 16898 | </div> |
| | 16899 | |
| | 16900 | <!-------------------> |
| | 16901 | <div class=entry> |
| | 16902 | |
| | 16903 | The special description list order has been modified slightly. If two |
| | 16904 | objects have the same specialDescOrder value, but one of the two |
| | 16905 | objects is inside the other, we'll list the outer object first. So, |
| | 16906 | specialDescOrder still dominates, but when there's no specialDescOrder |
| | 16907 | preference, we'll list containers before their children. In almost |
| | 16908 | all cases, this produces a more pleasing list order; objects within |
| | 16909 | other objects will frequently mention their placement in their special |
| | 16910 | description text, so it's usually better to have seen the containing |
| | 16911 | item's own special description before we see the containing item |
| | 16912 | mentioned in a child item's special description. |
| | 16913 | |
| | 16914 | </div> |
| | 16915 | |
| | 16916 | <!-------------------> |
| | 16917 | <div class=entry> |
| | 16918 | |
| | 16919 | A set of new commands makes it easier to record and play back command |
| | 16920 | scripts, which can be especially useful while writing and testing a |
| | 16921 | game. The command RECORD (RecordAction) starts recording a command |
| | 16922 | script, which saves command input text to a file. RECORD OFF |
| | 16923 | (RecordOffAction) turns off the recording starting with RECORD (it has |
| | 16924 | no effect if no recording is in progress). REPLAY (ReplayAction) |
| | 16925 | plays back a command script previously recorded. RECORD and REPLAY |
| | 16926 | both accept a filename in quotes on the command line, but this is |
| | 16927 | optional; if you just type RECORD or REPLAY, the commands will ask you |
| | 16928 | to select a file using a standard file dialog. |
| | 16929 | |
| | 16930 | <p>REPLAY has two mutually exclusive options. REPLAY QUIET plays |
| | 16931 | back the script without showing any output while the script is running. |
| | 16932 | REPLAY NONSTOP plays back the script without pausing for MORE prompts. |
| | 16933 | |
| | 16934 | <p>Because REPLAY is fully redundant with the old "@" syntax, but much |
| | 16935 | friendlier, the "@" syntax has been removed. |
| | 16936 | |
| | 16937 | </div> |
| | 16938 | |
| | 16939 | <!-------------------> |
| | 16940 | <div class=entry> |
| | 16941 | |
| | 16942 | The new class LocateInParent makes it easy to define a nested object |
| | 16943 | that's to be located within the enclosing object. This is a mix-in |
| | 16944 | superclass, so simply add it to the object's superclass list; |
| | 16945 | LocateInParent should go ahead of Thing or any Thing subclass in the |
| | 16946 | superclass list. |
| | 16947 | |
| | 16948 | </div> |
| | 16949 | |
| | 16950 | <!------------------------------- 3.0.6g ---------------------------------> |
| | 16951 | <div class="sepbar"><a name='306g'></a>3.0.6g</div> |
| | 16952 | <p><b><i>Released April 12, 2003</i></b> |
| | 16953 | <p> |
| | 16954 | |
| | 16955 | <div class=firstentry> |
| | 16956 | |
| | 16957 | The default object picker has been improved to better handle cases |
| | 16958 | where commands are remapped. Remapping from one object to another is |
| | 16959 | often used as a convenience to the player, so that the same command |
| | 16960 | can be applied to any of several related objects with the same |
| | 16961 | effect. For example, you might want to set up a jar with a lid so |
| | 16962 | that OPEN JAR and OPEN LID have the same effect; this could be done |
| | 16963 | by remapping OPEN LID to OPEN JAR. Similarly, a house with a door |
| | 16964 | might remap ENTER HOUSE so that it's handled as ENTER DOOR. In the |
| | 16965 | past, cases like these prevented the parser from choosing a default |
| | 16966 | object, because the parser can only apply a default when there's only a |
| | 16967 | single object that could make sense - the remappings made several |
| | 16968 | different objects look equally good superficially, even though the |
| | 16969 | apparent different possibilities were all going to turn into the same |
| | 16970 | thing in the end thanks to the remapping. |
| | 16971 | |
| | 16972 | <p>The parser now keeps track, during the verification process, of |
| | 16973 | any remapped objects. The default picker looks at this remapping |
| | 16974 | information before deciding on a default. If there are any objects |
| | 16975 | among the possible defaults that are to be remapped, the default |
| | 16976 | picker will discard any that are redundant due to the remappings. |
| | 16977 | For the OPEN JAR/OPEN LID example, the parser would see that OPEN LID |
| | 16978 | turns into OPEN JAR, and it would thus discard the lid from the list |
| | 16979 | of possible defaults, since the jar is already in the list. This |
| | 16980 | would leave us with just one possibility, so the parser would be able |
| | 16981 | to apply use it as the default. |
| | 16982 | |
| | 16983 | <p>The parser will only eliminate a remapped object as redundant |
| | 16984 | when the remapping matches the object, action, and role of another |
| | 16985 | object in the list of possible defaults. If a remapping changes the |
| | 16986 | verb, the remapped object will only match another object if it's also |
| | 16987 | remapped to that same new verb. The verb has to match because the |
| | 16988 | command could otherwise have a different effect, and thus the two |
| | 16989 | actions on the same object wouldn't be redundant with one another. |
| | 16990 | |
| | 16991 | </div> |
| | 16992 | <!-------------------> |
| | 16993 | <div class=entry> |
| | 16994 | |
| | 16995 | The asExit() macro has been changed slightly. You should no longer |
| | 16996 | uses the ":" syntax to define the direction; instead, simply put |
| | 16997 | the asExit macro directly after the direction name: |
| | 16998 | |
| | 16999 | <p><pre> north asExit(down) |
| | 17000 | </pre> |
| | 17001 | |
| | 17002 | <p>This change is intended to make asExit more consistent with |
| | 17003 | the similarly-named asDobjFor() and related macros. |
| | 17004 | |
| | 17005 | </div> |
| | 17006 | |
| | 17007 | <!-------------------> |
| | 17008 | <div class=entry> |
| | 17009 | |
| | 17010 | The menu system has a few minor changes to make the user interface |
| | 17011 | more easily customizable. |
| | 17012 | |
| | 17013 | <ul> |
| | 17014 | <li>In HTML interpreters, the top title/instructions bar now shows |
| | 17015 | a hyperlink that returns to the parent menu. The text in this |
| | 17016 | hyperlink is controlled by the 'prevMenuLink' property, which |
| | 17017 | by default uses the text 'Previous'. |
| | 17018 | |
| | 17019 | <li>In HTML interpreters, a hyperlink is shown in topic lists to |
| | 17020 | advance to the next topic item. The text of the hyperlink is given |
| | 17021 | by the 'nextMenuTopicLink' property. |
| | 17022 | |
| | 17023 | <li>The 'fgcolor' and 'bgcolor' properties now look to the parent |
| | 17024 | menu, if there is a parent menu, for their default values. For |
| | 17025 | the top-level menu, the defaults are still the status line colors. |
| | 17026 | In most cases, you'll want all of the menus in an entire menu tree |
| | 17027 | to have the same appearance, and this change makes it easy to |
| | 17028 | accomplish this: simply specify the appearance in the top-level |
| | 17029 | menu, and all of the child menus will use the parent menu settings. |
| | 17030 | Of course, individual menus can sever this parental dependence simply |
| | 17031 | by overriding these properties. |
| | 17032 | |
| | 17033 | <li>Two new properties, 'topbarfg' and 'topbarbg', allow each menu to |
| | 17034 | specify the foreground (text) and background colors of the top |
| | 17035 | title and instructions bar. By default, these look to the parent |
| | 17036 | menu, if there is one; the top-level menu defaults to using the |
| | 17037 | inverse of the color scheme of the menu itself. |
| | 17038 | |
| | 17039 | <li>The 'indent' property uses the parent's value by default. |
| | 17040 | |
| | 17041 | <li>A new property, 'fullScreenMode', lets you indicate that you want |
| | 17042 | the menu to take over the entire interpreter window. By default, |
| | 17043 | menus are given just enough space at the top of the interpreter |
| | 17044 | window to display their contents. If 'fullScreenMode' is true, |
| | 17045 | though, menus will cover the entire interpreter window. Full-screen |
| | 17046 | mode has the advantage that it's less jumpy than the default |
| | 17047 | partial-screen mode, since the partial mode resizes the menu windows |
| | 17048 | on each navigation operation to accommodate the new contents. |
| | 17049 | </ul> |
| | 17050 | |
| | 17051 | </div> |
| | 17052 | |
| | 17053 | <!-------------------> |
| | 17054 | <div class=entry> |
| | 17055 | |
| | 17056 | A new hint menu type has been added: HintLongTopicItem. This is |
| | 17057 | simply a MenuLongTopicItem subclass designed for use in hint menus. |
| | 17058 | (Regular HintLongTopicItem objects don't have the necessary logic for |
| | 17059 | calculating visibility in a hint menu, so the specialized subclass |
| | 17060 | should be used for long-topic menus within hint menu trees rather |
| | 17061 | than the base MenuLongTopicItem type.) |
| | 17062 | |
| | 17063 | </div> |
| | 17064 | |
| | 17065 | <!-------------------> |
| | 17066 | <div class=entry> |
| | 17067 | |
| | 17068 | The library's turn-counter incorrectly counted a command as two turns |
| | 17069 | if the command's action() handler invoked a nested action which was |
| | 17070 | then remapped (via remapTo). Nested actions aren't supposed to count |
| | 17071 | as separate turns; it was erroneous for the remapping to affect this |
| | 17072 | one way or the other. This has been corrected. |
| | 17073 | |
| | 17074 | </div> |
| | 17075 | |
| | 17076 | <!-------------------> |
| | 17077 | <div class=entry> |
| | 17078 | |
| | 17079 | moveInto(nil) now works properly for a MultiLoc object. (In the past, |
| | 17080 | this incorrectly caused a run-time error.) |
| | 17081 | |
| | 17082 | </div> |
| | 17083 | |
| | 17084 | <!-------------------> |
| | 17085 | <div class=entry> |
| | 17086 | |
| | 17087 | SensoryEmanation has a new property, isAmbient. This is nil by default; |
| | 17088 | if set to true, it indicates that the noise/odor/etc is purely in |
| | 17089 | the background, so it's not especially noticeable. Ambient emanations |
| | 17090 | won't be mentioned when they first become sensed; normally, an emanation |
| | 17091 | is automatically mentioned whenever conditions change so that it was |
| | 17092 | not sensed previously but is now. Ambient emanations will still be |
| | 17093 | mentioned in explicit intransitive LISTEN/SMELL commands; they simply |
| | 17094 | won't be mentioned on their own. |
| | 17095 | |
| | 17096 | </div> |
| | 17097 | <!-------------------> |
| | 17098 | <div class=entry> |
| | 17099 | |
| | 17100 | Part of the Container class has been separated into a new lower-level |
| | 17101 | base class, Encloser. An Encloser is an object that can enclose its |
| | 17102 | contents, so that all senses must pass through the encloser's |
| | 17103 | material when passing in and out of the object. Encloser has all |
| | 17104 | of the basic handling for enclosing contents, but not the action |
| | 17105 | handling. Encloser is meant for cases where the object's contents |
| | 17106 | are not to be directly manipulable by the player, via "put in" |
| | 17107 | commands and the like. Container is now a subclass of Encloser; |
| | 17108 | Container defines the suitable action handlers to allow a player |
| | 17109 | to manipulate the container's contents. |
| | 17110 | |
| | 17111 | </div> |
| | 17112 | <!-------------------> |
| | 17113 | <div class=entry> |
| | 17114 | |
| | 17115 | <p> |
| | 17116 | A new mechanism in the Actor class makes it relatively easy to set it |
| | 17117 | up so one or more non-player characters accompany the player character |
| | 17118 | on travel. This kind of group travel is especially good for things |
| | 17119 | like a sidekick character who goes everywhere the player does, and for |
| | 17120 | tour guides or other escorts who are showing the player character |
| | 17121 | where to go. |
| | 17122 | |
| | 17123 | <p>This mechanism is similar to the "follow" mechanism, which makes |
| | 17124 | one actor attempt to follow another on each turn, but it improves |
| | 17125 | considerably on regular following by customizing the messages. Normal |
| | 17126 | following is a little awkward for explicit group travel of the sort |
| | 17127 | that one wants with sidekicks and escorts, because the messages are so |
| | 17128 | generic; the NPC almost seems to be wandering around on its own and |
| | 17129 | just coincidentally showing up where the PC is. This new |
| | 17130 | "accompanying" mechanism accomplishes much the same thing, but smooths |
| | 17131 | out the messages a bit. First, rather than having the NPC trailing |
| | 17132 | along after the fact, the new system sends accompanying NPC's on |
| | 17133 | ahead; this means that the NPC's don't just wander in later as they do |
| | 17134 | with normal following. Second, the message for the NPC's |
| | 17135 | pre-departure is customized to make it clear that the NPC isn't |
| | 17136 | departing, but is coming along with you. Third, on arriving in the |
| | 17137 | new location, there's a customization hook for describing the NPC's |
| | 17138 | presence in the new location specially for the group travel; this is |
| | 17139 | important because it gives us a place to mention that the actor starts |
| | 17140 | doing whatever it is the actor normally does in the new location. The |
| | 17141 | overall effect is that each group travel action is made to look like a |
| | 17142 | single, integrated action, rather than two generic and unrelated actor |
| | 17143 | travel actions. |
| | 17144 | |
| | 17145 | <p>NPC's can also be set to accompany NPC's with the same mechanism, |
| | 17146 | but it's much less interesting for that, since the main value of the |
| | 17147 | new mechanism is that it improves the messages for PC-plus-NPC group |
| | 17148 | travel. For NPC-plus-NPC group travel, this new mechanism has no |
| | 17149 | particular advantage over the the simpler "follow" mechanism. |
| | 17150 | |
| | 17151 | <p>Setting up accompanying travel is relatively straightforward. |
| | 17152 | You have to specify the conditions under which the group travel occurs, |
| | 17153 | and you should customize two messages related to the travel. You |
| | 17154 | set this all up by overriding methods on the NPC who's going to follow |
| | 17155 | the lead actor (usually the PC). The methods to override are as |
| | 17156 | follows. |
| | 17157 | |
| | 17158 | <p>First, override the accompanyTravel() method so that it returns |
| | 17159 | true under the conditions where you want the accompanying travel to |
| | 17160 | occur. This method is called each time your NPC is present and sees |
| | 17161 | another actor attempt a travel action (it's called during your NPC's |
| | 17162 | beforeAction when the action is a TravelVia). If you want your actor |
| | 17163 | to accompany the PC everywhere, simply return true when the action |
| | 17164 | actor is the PC. The method also has access to the TravelConnector |
| | 17165 | involved in the travel, so you selectively accompany an actor for |
| | 17166 | some destinations but not others, if you wish. |
| | 17167 | |
| | 17168 | <blockquote> |
| | 17169 | <b>Warning: the next two parts are likely to be modified soon.</b> |
| | 17170 | I'd recommend against writing any code that makes customizations using |
| | 17171 | these features right now. |
| | 17172 | </blockquote> |
| | 17173 | |
| | 17174 | <p>Second, define an accompanyDesc method for your actor. This method |
| | 17175 | is used instead of the usual actorHereDesc method to describe your |
| | 17176 | actor in the new location immediately after the group travel is |
| | 17177 | finished. It's usually desirable to use a special message to describe |
| | 17178 | the actor right after the accompanying travel, because you usually |
| | 17179 | want to convey that the actor is just arriving - not that the actor is |
| | 17180 | walking in separately from the lead actor, but that the actor is |
| | 17181 | arriving at the same time as the lead actor. If you do override |
| | 17182 | accompanyingDesc, you should override accompanyingListWith to return |
| | 17183 | an empty list ([]). |
| | 17184 | |
| | 17185 | <p>Third, you can optionally provide a special TravelMessageHandler |
| | 17186 | for your actor by overriding getAccompanyingTravelMessageHandler. By |
| | 17187 | default, this routine provides a message handler that uses messages |
| | 17188 | like "Bob goes with you" instead of the usual "Bob leaves to the east" |
| | 17189 | to describe the departure of your actor. The normal departure message |
| | 17190 | isn't appropriate, because the actor isn't just leaving, it's leaving |
| | 17191 | *with* the lead actor. The default "Bob goes with you" is better, but |
| | 17192 | you might still want to override this handler to provide even more |
| | 17193 | customized messages: "Bob escorts you to the east," or "You drag Bob |
| | 17194 | with you," or whatever makes sense for the specific situation. |
| | 17195 | |
| | 17196 | <p>Finally, note that you can use accompanying travel and the regular |
| | 17197 | following mechanism together. Regular following can be a useful |
| | 17198 | fallback for cases you don't want to customize. Regular following |
| | 17199 | occurs after the fact, because it occurs on an NPC's turn when the |
| | 17200 | NPC sees that the actor it's tasked to follow is no longer present. |
| | 17201 | Accompanying travel, in contrast, happens on the same turn as the |
| | 17202 | lead actor's travel. This means that regular following is essentially |
| | 17203 | overridden by accompanying travel, since it happens first. |
| | 17204 | |
| | 17205 | </div> |
| | 17206 | |
| | 17207 | <!-------------------> |
| | 17208 | <div class=entry> |
| | 17209 | |
| | 17210 | The English parser now accepts quoted strings as adjectives. Quoted |
| | 17211 | strings can be used as adjectives in exactly the same way that numbers |
| | 17212 | can be used, so phrases such as "QU" TILE and BUTTON "G" are accepted. |
| | 17213 | |
| | 17214 | <p>For the purposes of matching vocabulary in the dictionary, quoted |
| | 17215 | adjectives are simply treated as though the quotes weren't present. |
| | 17216 | So, "QU" TILE is treated exactly the same as QU TILE. This means you |
| | 17217 | don't have to worry about the quotes when defining your vocabulary |
| | 17218 | words. |
| | 17219 | |
| | 17220 | <p>There is an additional bit of special treatment for quoted strings. |
| | 17221 | The special vocabulary word '"*"' (that is, an asterisk within |
| | 17222 | double-quote characters) serves as a wildcard for any quoted string. |
| | 17223 | If an object defines this special wildcard as an adjective among its |
| | 17224 | vocabulary words, then that object will match <i>any</i> quoted string |
| | 17225 | as an adjective. This is the equivalent of the '#' wildcard string |
| | 17226 | for numeric adjectives. |
| | 17227 | |
| | 17228 | <p>String-as-adjective phrasing is implemented using the new |
| | 17229 | production literalAdjPhrase. This new production is now used |
| | 17230 | wherever numberPhrase was formerly used in the role of an adjective |
| | 17231 | in noun phrase rules. literalAdjPhrase matches numbers, '#' number |
| | 17232 | phrases, and quoted strings. |
| | 17233 | |
| | 17234 | </div> |
| | 17235 | |
| | 17236 | <!-------------------> |
| | 17237 | <div class=entry> |
| | 17238 | |
| | 17239 | In travel.t, there were formerly a couple of TravelConnector |
| | 17240 | subclasses that handled action synonyms for TravelVia using |
| | 17241 | asDobjFor(TravelVia). These have been changed to use |
| | 17242 | remapTo(TravelVia) instead. |
| | 17243 | |
| | 17244 | <p>The asDobjFor() approach had the drawback that the action |
| | 17245 | synonyms didn't ever generate TravelVia actions proper, but |
| | 17246 | simply called the TravelVia handlers internally; so, for example, |
| | 17247 | beforeAction() routines wouldn't ever see a TravelVia action |
| | 17248 | being performed. The new remapping approach is better because |
| | 17249 | it means that every possible action on these objects that |
| | 17250 | involves travel will go through an actual TravelVia action. |
| | 17251 | This allows beforeAction() and similar routines to be assured |
| | 17252 | that they can catch all travel actions by looking for TravelVia |
| | 17253 | alone, eliminating the need to worry about synonym actions that |
| | 17254 | could cause travel. |
| | 17255 | |
| | 17256 | </div> |
| | 17257 | |
| | 17258 | <!-------------------> |
| | 17259 | <div class=entry> |
| | 17260 | |
| | 17261 | A couple of new classes simplify a few tasks involving entry |
| | 17262 | and exit portals. Exitable is a new class that's similar to |
| | 17263 | Enterable, but provides Exit instead of Enter as its main |
| | 17264 | action. EntryPortal and ExitPortal are just like Enterable and |
| | 17265 | Exitable, respectively, but add support for GoThrough actions. |
| | 17266 | |
| | 17267 | </div> |
| | 17268 | |
| | 17269 | <!-------------------> |
| | 17270 | <div class=entry> |
| | 17271 | |
| | 17272 | Added finishOptionFullScore, to make it easy for the game to |
| | 17273 | offer the player the option of seeing the full score at completion. |
| | 17274 | |
| | 17275 | </div> |
| | 17276 | |
| | 17277 | <!------------------------------- 3.0.6f ---------------------------------> |
| | 17278 | <div class="sepbar"><a name='306f'></a>3.0.6f</div> |
| | 17279 | <p><b><i>Released March 23, 2003</i></b> |
| | 17280 | <p> |
| | 17281 | |
| | 17282 | <div class=firstentry> |
| | 17283 | |
| | 17284 | It's now less dire for gPlayer.location to be set to nil. In the |
| | 17285 | past, setting gPlayer.location to nil caused an infinite error loop, |
| | 17286 | because the status line code dereferenced gPlayer.location without |
| | 17287 | checking for nil, which caused an error, which aborted the current |
| | 17288 | turn, which started a new turn, which tried to update the status |
| | 17289 | line, and around we went. It's still not completely valid for |
| | 17290 | gPlayer.location to be nil; this change just removes the infinite |
| | 17291 | error loop, which makes it a little easier to deal with this problem |
| | 17292 | arising during programming and testing. |
| | 17293 | |
| | 17294 | </div> |
| | 17295 | |
| | 17296 | <!-------------------> |
| | 17297 | <div class=entry> |
| | 17298 | |
| | 17299 | Changed Thing.dobjFor(Remove) to remap to RemoveFrom (asking for an |
| | 17300 | iobj). Wearable now overrides Remove to map it to Doff. It makes |
| | 17301 | more sense in general for "remove foo" to mean "remove foo (from |
| | 17302 | something)" rather than "doff foo"; only when "foo" is an article of |
| | 17303 | clothing does the "doff" interpretation usually apply. |
| | 17304 | |
| | 17305 | </div> |
| | 17306 | |
| | 17307 | <!-------------------> |
| | 17308 | <div class=entry> |
| | 17309 | |
| | 17310 | Added the new TravelConnector property isConnectorListed. If this |
| | 17311 | property is nil, the connector is suppressed from generated exit |
| | 17312 | lists (such as the status line exit list, and "you can't go that way" |
| | 17313 | messages). |
| | 17314 | |
| | 17315 | </div> |
| | 17316 | |
| | 17317 | <!-------------------> |
| | 17318 | <div class=entry> |
| | 17319 | |
| | 17320 | Added a new class, UnlistedProxyConnector, that acts as a proxy for |
| | 17321 | an underlying connector, but is unlisted. The idea is to make it |
| | 17322 | easy to add an exit that acts exactly like another connector, but is |
| | 17323 | suppressed from exit lists. |
| | 17324 | |
| | 17325 | </div> |
| | 17326 | |
| | 17327 | <!-------------------> |
| | 17328 | <div class=entry> |
| | 17329 | |
| | 17330 | Added a macro, asExit(), that can be used to define an |
| | 17331 | UnlistedProxyConnector that links to another direction exit. |
| | 17332 | |
| | 17333 | </div> |
| | 17334 | |
| | 17335 | <!-------------------> |
| | 17336 | <div class=entry> |
| | 17337 | |
| | 17338 | Integrated Stephen Granade's menu system (menus.t) with the main |
| | 17339 | library. |
| | 17340 | |
| | 17341 | </div> |
| | 17342 | |
| | 17343 | <!-------------------> |
| | 17344 | <div class=entry> |
| | 17345 | |
| | 17346 | Added an on-line adaptive hint system (hints.t). |
| | 17347 | |
| | 17348 | </div> |
| | 17349 | |
| | 17350 | <!-------------------> |
| | 17351 | <div class=entry> |
| | 17352 | |
| | 17353 | Added the new class RestrictedContainer. This is a Container |
| | 17354 | specialization that makes it easy to define containers that only |
| | 17355 | accept certain objects as contents. In the basic implementation, the |
| | 17356 | allowable objects are simply enumerated as a list of objects; but |
| | 17357 | this can be easily overridden for other methods of determining which |
| | 17358 | objects are allowed. |
| | 17359 | |
| | 17360 | </div> |
| | 17361 | <!-------------------> |
| | 17362 | <div class=entry> |
| | 17363 | |
| | 17364 | Added the new class SingleContainer, and the associated new |
| | 17365 | precondition objEmpty. SingleContainer is a specialization of |
| | 17366 | Container that only allows a single object to be in the container at |
| | 17367 | a time; this is suitable for things like sockets and receptacles. |
| | 17368 | SingleContainer places the objEmpty precondition on the PutIn action; |
| | 17369 | the objEmpty precondition simply requires that the subject object is |
| | 17370 | empty, and tries implicit TakeFrom actions on the contents to |
| | 17371 | accomplish this. |
| | 17372 | |
| | 17373 | </div> |
| | 17374 | <!-------------------> |
| | 17375 | <div class=entry> |
| | 17376 | |
| | 17377 | In en_us.t, changed typographicalOutputFilter.eosPattern to ignore |
| | 17378 | any run of HTML tags between sentence-ending punctuation and a |
| | 17379 | following space. |
| | 17380 | |
| | 17381 | </div> |
| | 17382 | <!-------------------> |
| | 17383 | <div class=entry> |
| | 17384 | |
| | 17385 | The main implicit action processor now uses the more abstract |
| | 17386 | "allowed in implicit" test on the verify results, rather than merely |
| | 17387 | checking for "dangerous" results. This will allow results flagged as |
| | 17388 | "non-obvious" to cancel implied actions, as they should. (A |
| | 17389 | non-obvious command should never be done implicitly, because implicit |
| | 17390 | commands are specifically for actions that are obvious intermediate |
| | 17391 | steps toward the explicitly stated command.) |
| | 17392 | |
| | 17393 | </div> |
| | 17394 | <!-------------------> |
| | 17395 | <div class=entry> |
| | 17396 | |
| | 17397 | Openable and Lockable have been cleaned up slightly. A new class, |
| | 17398 | Linkable, has been added for objects that can be paired in |
| | 17399 | master/slave relationships; Openable and Lockable are now based on |
| | 17400 | Linkable. This removes some duplicated code for managing the |
| | 17401 | masterObject relationship. In initialization, Linkable checks for a |
| | 17402 | master object loop (where each object points to the other as the |
| | 17403 | master) and break such loops by arbitrarily selecting one as the |
| | 17404 | master. Also, we have reduced the number of times we have to refer |
| | 17405 | to masterObject by relying on isOpen/isLocked/makeOpen/makeLocked to |
| | 17406 | defer to the master. Also, the initiallyOpen/initiallyLocked |
| | 17407 | initializations are now handled in initializeThing() rather than in |
| | 17408 | isOpen/isLocked. |
| | 17409 | |
| | 17410 | <p>Another new class, BasicOpenable, provides the basic state |
| | 17411 | management for openable objects (which can optionally be linked |
| | 17412 | in pairs to maintain the same status across the pair) but doesn't |
| | 17413 | provide any of the verb handling of Openable. This can be used |
| | 17414 | for objects that want to maintain open/closed state using the |
| | 17415 | usual method names, but which don't respond to direct player |
| | 17416 | open/close commands. |
| | 17417 | |
| | 17418 | <p><b>IMPORTANT:</b> Objects based on Openable and Lockable must |
| | 17419 | <b>not</b> initialize their open status with isOpen or their locked |
| | 17420 | status with isLocked. Instead, initialize the status with |
| | 17421 | initiallyOpen and initiallyLocked, respectively. Also, be sure |
| | 17422 | you never set isOpen or isLocked directly; instead, call makeOpen() |
| | 17423 | and makeLocked() to effect these status changes. |
| | 17424 | |
| | 17425 | </div> |
| | 17426 | <!-------------------> |
| | 17427 | <div class=entry> |
| | 17428 | |
| | 17429 | Changed Passage slightly to rely on isOpen/etc more to manage the |
| | 17430 | masterObject relationship. |
| | 17431 | |
| | 17432 | </div> |
| | 17433 | <!-------------------> |
| | 17434 | <div class=entry> |
| | 17435 | |
| | 17436 | Added a parameter to Direction.defaultConnector() giving the location |
| | 17437 | from which travel is being attempted. This allows the direction to |
| | 17438 | customize the default connector according to the type of location. |
| | 17439 | |
| | 17440 | </div> |
| | 17441 | <!-------------------> |
| | 17442 | <div class=entry> |
| | 17443 | |
| | 17444 | Added a new property, isShipboard, to Thing. By default, if we have |
| | 17445 | a location, we use the location's isShipboard setting, otherwise we |
| | 17446 | return nil. Rooms aboard ships can set this to true to indicate that |
| | 17447 | shipboard directions make sense here. |
| | 17448 | |
| | 17449 | <p>In ShipboardDirection.defaultConnector, if the source location or |
| | 17450 | any container has 'isShipboard' set to true, then we now use noTravel |
| | 17451 | as the default connector rather than noShipTravel, as the latter is |
| | 17452 | meant to convey that shipboard directions make no sense in |
| | 17453 | non-shipboard locations. |
| | 17454 | |
| | 17455 | <p>Added a ShipboardRoom mix-in class that defines isShipboard to true. |
| | 17456 | |
| | 17457 | </div> |
| | 17458 | <!-------------------> |
| | 17459 | <div class=entry> |
| | 17460 | |
| | 17461 | Changed the way that VerifyResultList determines if an action is |
| | 17462 | allowed at all or allowed as an implicit command. In the past, this |
| | 17463 | calculation did what the "most disapproving" result in the list said |
| | 17464 | to do; this wasn't quite right, because approval is essentially a |
| | 17465 | separate axis from the "disapproval" order, despite the name. In |
| | 17466 | reality, the "disapproval" order is the message priority order, and |
| | 17467 | the actual determination of approval depends on there being |
| | 17468 | no disapprovers. So, to determine approval, we now scan the full |
| | 17469 | result list and require that every result approves; a single |
| | 17470 | disapproval, no matter where it appears in message priority order, |
| | 17471 | constitutes disapproval. |
| | 17472 | |
| | 17473 | </div> |
| | 17474 | <!-------------------> |
| | 17475 | <div class=entry> |
| | 17476 | |
| | 17477 | In the English module, added a new token type for numbers specified |
| | 17478 | with a leading pound sign (as in "#2 pencil" or "room #101"). These |
| | 17479 | are treated essentially the same as numeric adjectives. These match |
| | 17480 | vocabulary for just the underlying numbers, not including the pound |
| | 17481 | signs, so vocabulary should be specified simply as '2 pencil' and |
| | 17482 | '101 room'. (In other words, do <b>not</b> include a pound sign in |
| | 17483 | vocabulary words; just use the number as with ordinary numeric |
| | 17484 | adjectives, and the parser will match the number with or without the |
| | 17485 | pound sign). |
| | 17486 | |
| | 17487 | </div> |
| | 17488 | <!-------------------> |
| | 17489 | <div class=entry> |
| | 17490 | |
| | 17491 | The TravelVia check() condition in Passage no longer uses isOpen as |
| | 17492 | its test. Instead, it calls the new abstract condition method, |
| | 17493 | canActorTravel(), passing the current actor as a parameter. This |
| | 17494 | makes it easy to allow some actors to pass and not others, and to |
| | 17495 | test for conditions other than isOpen. By default, canActorTravel() |
| | 17496 | simply returns isOpen, so this doesn't change the default behavior. |
| | 17497 | |
| | 17498 | <p>Along the same lines, Door.connectorTravelPreCond() now calls |
| | 17499 | a separate method, getDoorOpenPreCond(), to obtain the door-is-open |
| | 17500 | precondition object. By default, this returns a doorOpen precondition |
| | 17501 | (wrapped with an ObjectPreCondition for 'self'), so the default behavior |
| | 17502 | hasn't changed. |
| | 17503 | |
| | 17504 | </div> |
| | 17505 | <!-------------------> |
| | 17506 | <div class=entry> |
| | 17507 | |
| | 17508 | In the past, when an NPC was following another actor, and the actor |
| | 17509 | being followed moved into a nested room within the current room, we |
| | 17510 | generated a redundant message: |
| | 17511 | |
| | 17512 | <p><pre>>stand on platform |
| | 17513 | Okay, you are now standing on the platform. |
| | 17514 | Bill stands on the platform. |
| | 17515 | Bill follows you onto the platform. |
| | 17516 | </pre> |
| | 17517 | |
| | 17518 | <p> |
| | 17519 | The redundant "Bill follows you" has been eliminated. |
| | 17520 | |
| | 17521 | </div> |
| | 17522 | <!-------------------> |
| | 17523 | <div class=entry> |
| | 17524 | |
| | 17525 | The reporting mechanism now processes sets of implicit action announcements |
| | 17526 | to make them more readable and more easily understood. In the past, |
| | 17527 | each implicit action was shown separately; when one implicit action |
| | 17528 | triggered another, this could make for somewhat confusing displays. |
| | 17529 | For example, in the Platform Room in sample.t, if the PC is sitting on |
| | 17530 | the blue chair and wants to get up and sit on the red chair, we formerly |
| | 17531 | generated a transcript like this: |
| | 17532 | |
| | 17533 | <p><pre>>sit on red chair |
| | 17534 | (first standing on the red platform) |
| | 17535 | (first getting off of the blue platform) |
| | 17536 | (first standing) |
| | 17537 | Okay, you're now sitting on the red chair. |
| | 17538 | </pre> |
| | 17539 | |
| | 17540 | <p>To the uninitiated, this looks backwards: shouldn't we stand up, |
| | 17541 | then get off the blue platform, then get on the red platform, and then |
| | 17542 | sit on the red chair? Of course, that's what's actually happening, |
| | 17543 | and in its own way the transcript above reflects this: the second |
| | 17544 | "first" applies to the first "first": it's saying "before you can |
| | 17545 | stand on the red platform, you first have to get off the blue |
| | 17546 | platform." Likewise, the third "first" applies to the second "first," |
| | 17547 | to say "before you can stand on the red platform, you have to stand up |
| | 17548 | first." In other words, the implied reports are nested recursively. |
| | 17549 | The recursive structure isn't represented visually, though, so it's |
| | 17550 | not evident whether one of the later "firsts" refers to the preceding |
| | 17551 | "first" or back to the original command line. It would have been |
| | 17552 | possible to represent the recursive structure visually, using |
| | 17553 | indentation or something like that, but this probably wouldn't have |
| | 17554 | made most people very happy; most non-programmers aren't accustomed to |
| | 17555 | thinking in terms of recursion and stacks and tree views, and even |
| | 17556 | programmers might well have found this kind of presentation to be too |
| | 17557 | obviously mechanistic. |
| | 17558 | |
| | 17559 | <p>To improve the situation, the transcript processor now features a |
| | 17560 | new transform, called implicitGroupTransform, that rearranges these |
| | 17561 | recursive listings into an order that should be entirely |
| | 17562 | straightforward to anyone, programmer or not. The new transform also |
| | 17563 | consolidates these lists into a much more concise and readable format. |
| | 17564 | The transformer does two things. First, it "unstacks" recursive lists |
| | 17565 | of implied action announcements to put them into the chronological |
| | 17566 | order in which the commands were actually performed; the transcript |
| | 17567 | has always kept track internally of which announcement is tied to |
| | 17568 | which action, so the new transformer can merely inspect these records |
| | 17569 | to determine the action relationships and use this information to |
| | 17570 | unwind the stack. Second, the transformer combines each run of |
| | 17571 | adjacent implied action announcements into a single announcement, |
| | 17572 | showing a list of the actions performed. The result is that the |
| | 17573 | example above now looks like this: |
| | 17574 | |
| | 17575 | <p><pre>>sit on red chair |
| | 17576 | (first standing, getting off of the blue platform, then standing on |
| | 17577 | the red platform) |
| | 17578 | Okay, you're now sitting on the red chair. |
| | 17579 | </pre> |
| | 17580 | |
| | 17581 | <p>This new format should be easier for players to understand, |
| | 17582 | since it shows implied actions in the order in which they're actually |
| | 17583 | carried out, eliminating any need to be aware of the recursive |
| | 17584 | goal-seeking work that the system is doing internally. Hopefully, |
| | 17585 | players will also find it more readable and less obviously mechanistic |
| | 17586 | than the old format. |
| | 17587 | |
| | 17588 | </div> |
| | 17589 | |
| | 17590 | |
| | 17591 | <!------------------------------- 3.0.6a-e ---------------------------------> |
| | 17592 | <div class="sepbar"><a name='306ae'></a>3.0.6a-e</div> |
| | 17593 | |
| | 17594 | <p><b><i>3.0.6e was released March 16, 2003</i></b> |
| | 17595 | <p> |
| | 17596 | |
| | 17597 | <div class=firstentry> |
| | 17598 | |
| | 17599 | For a restore-on-startup operation, if the restore fails, don't simply |
| | 17600 | start the game from the beginning. Instead, offer options to START |
| | 17601 | from the beginning, RESTORE another game, or QUIT, using the same type |
| | 17602 | of prompt that we use for presenting "finishing" options. |
| | 17603 | |
| | 17604 | </div> |
| | 17605 | |
| | 17606 | <!-------------------> |
| | 17607 | <div class=entry> |
| | 17608 | |
| | 17609 | Add a verb for OOPS typed at arbitrary times, which simply explains |
| | 17610 | that OOPS can only be used after the parser has pointed out an unknown |
| | 17611 | word. |
| | 17612 | |
| | 17613 | </div> |
| | 17614 | |
| | 17615 | <!-------------------> |
| | 17616 | <div class=entry> |
| | 17617 | |
| | 17618 | Fix problem using possessive qualifiers in topic phrases. (The |
| | 17619 | problem is that we're using the topic resolver to resolve qualifiers |
| | 17620 | in the topic phrase; we should be using an ordinary object resolver. |
| | 17621 | Change the topic resolver's qualifier resolver to use the topic |
| | 17622 | action's direct object resolver by default.) |
| | 17623 | |
| | 17624 | </div> |
| | 17625 | |
| | 17626 | <!-------------------> |
| | 17627 | <div class=entry> |
| | 17628 | |
| | 17629 | Move the pronoun-setting routines (setPronoun, setIt, setHim, setHer, |
| | 17630 | setThem) into Actor - these shouldn't be global functions since they |
| | 17631 | need to operate on the current actor. |
| | 17632 | |
| | 17633 | </div> |
| | 17634 | |
| | 17635 | <!-------------------> |
| | 17636 | <div class=entry> |
| | 17637 | |
| | 17638 | In TopicAction, set the pronoun antecedent based on the direct object |
| | 17639 | phrase immediately during resolution, to allow things like "ask bob |
| | 17640 | about his book." |
| | 17641 | |
| | 17642 | </div> |
| | 17643 | |
| | 17644 | <!-------------------> |
| | 17645 | <div class=entry> |
| | 17646 | |
| | 17647 | Add a DefineIAction macro, for defining IAction classes. |
| | 17648 | |
| | 17649 | </div> |
| | 17650 | |
| | 17651 | <!-------------------> |
| | 17652 | <div class=entry> |
| | 17653 | |
| | 17654 | Base LiteralAction on IAction, not directly on Action. |
| | 17655 | |
| | 17656 | Because of this change, rewrite OopsAction to implement its processing |
| | 17657 | in execAction() rather than doActionMain(). |
| | 17658 | |
| | 17659 | </div> |
| | 17660 | |
| | 17661 | <!-------------------> |
| | 17662 | <div class=entry> |
| | 17663 | |
| | 17664 | Refactor the Instructions action into an InstructionsAction base class |
| | 17665 | and a separate grammar rule, to allow the base class to be referenced |
| | 17666 | by name from other code. |
| | 17667 | |
| | 17668 | </div> |
| | 17669 | |
| | 17670 | <!-------------------> |
| | 17671 | <div class=entry> |
| | 17672 | |
| | 17673 | Add a banner manager, along the lines of the input and output |
| | 17674 | managers. A new BannerWindow class would represent a banner; this |
| | 17675 | would encapsulate the system banner handle and provide methods that |
| | 17676 | operate on the banner. The game should use the BannerWindow methods |
| | 17677 | to perform all operations on banners, rather than calling the |
| | 17678 | system-level banner API directly. |
| | 17679 | |
| | 17680 | The banner manager should provide persistence support, so that the |
| | 17681 | on-screen banner layout is restored on RESTORE, UNDO, or RESTART. To |
| | 17682 | this end, BannerWindow should be an ordinary persistent object, and a |
| | 17683 | separate set of transient objects should track the current UI state. |
| | 17684 | On RESTORE, UNDO, or RESTART, the transient tracking list and the |
| | 17685 | persistent BannerWindow states should be compared, and the actual |
| | 17686 | on-screen UI state, as represented in the transient objects, should be |
| | 17687 | brought into line with the saved state. |
| | 17688 | |
| | 17689 | </div> |
| | 17690 | |
| | 17691 | <!-------------------> |
| | 17692 | <div class=entry> |
| | 17693 | |
| | 17694 | Wait to mark an object as 'seen' in Thing.lookAroundWithin() until |
| | 17695 | just before the method returns, so that any routines called from the |
| | 17696 | method can check the old 'seen' status. |
| | 17697 | |
| | 17698 | </div> |
| | 17699 | |
| | 17700 | <!-------------------> |
| | 17701 | <div class=entry> |
| | 17702 | |
| | 17703 | Fix gAction reference in Actor.travelWithin() so that it's conditional |
| | 17704 | on gAction being non-nil. |
| | 17705 | |
| | 17706 | </div> |
| | 17707 | |
| | 17708 | <!-------------------> |
| | 17709 | <div class=entry> |
| | 17710 | |
| | 17711 | Fix takeFromNotInActor message (iobj/dobj are reversed). |
| | 17712 | |
| | 17713 | </div> |
| | 17714 | |
| | 17715 | <!-------------------> |
| | 17716 | <div class=entry> |
| | 17717 | |
| | 17718 | Fix TAction.retryWithMissingDobj() and |
| | 17719 | TIAction.retryWithMissingIobj() so that they cancel the game time |
| | 17720 | contribution of their enclosing (replaced) actions. |
| | 17721 | |
| | 17722 | </div> |
| | 17723 | |
| | 17724 | <!-------------------> |
| | 17725 | <div class=entry> |
| | 17726 | |
| | 17727 | Fix touchObj precondition logic so that it realizes when an attempt |
| | 17728 | to remove an obstruction with a precondition fails. To do this, keep |
| | 17729 | track of which obstructions we've tried to remove with implicit |
| | 17730 | commands, and give up if we encounter the same obstruction more than |
| | 17731 | once. |
| | 17732 | |
| | 17733 | </div> |
| | 17734 | |
| | 17735 | <!-------------------> |
| | 17736 | <div class=entry> |
| | 17737 | |
| | 17738 | Add <.parser> to msg_neu.t responses for some system verbs (NOTIFY |
| | 17739 | ON/OFF, EXITS ON/OFF, a few others). |
| | 17740 | |
| | 17741 | </div> |
| | 17742 | |
| | 17743 | <!-------------------> |
| | 17744 | <div class=entry> |
| | 17745 | |
| | 17746 | Assign the IndirectObject role to the literal in a LiteralTAction by |
| | 17747 | overriding getRoleFromIndex, getObjectForRole, and getMatchForRole. |
| | 17748 | These are needed to allow remapTo to be used with a LiteralTAction. |
| | 17749 | |
| | 17750 | <p> |
| | 17751 | Note that the literal is <b>always</b> in the IndirectObject role, |
| | 17752 | regardless of whichLiteral, which only specifies the grammatical role |
| | 17753 | for message generation purposes. |
| | 17754 | |
| | 17755 | <p> |
| | 17756 | Likewise, assign the IndirectObject role to the topic in TopicAction. |
| | 17757 | This will allow remapTo to be used with a TopicAction. |
| | 17758 | |
| | 17759 | </div> |
| | 17760 | |
| | 17761 | <!-------------------> |
| | 17762 | <div class=entry> |
| | 17763 | |
| | 17764 | Rename TopicAction to TopicTAction, parallel to LiteralTAction. |
| | 17765 | |
| | 17766 | </div> |
| | 17767 | |
| | 17768 | <!-------------------> |
| | 17769 | <div class=entry> |
| | 17770 | |
| | 17771 | Add a new TopicAction that takes only a topic as its object, parallel |
| | 17772 | to LiteralAction. |
| | 17773 | |
| | 17774 | </div> |
| | 17775 | |
| | 17776 | <!-------------------> |
| | 17777 | <div class=entry> |
| | 17778 | |
| | 17779 | Rename whichObject, whichLiteral, and whichTopic to |
| | 17780 | whichMessageObject, whichMessageLiteral, and whichMessageTopic, |
| | 17781 | respectively, to make it clearer that these apply only to the roles |
| | 17782 | played in generated messages, and not to any other roles. |
| | 17783 | |
| | 17784 | <p> |
| | 17785 | In particular, the message role only affects the way the object is |
| | 17786 | used in generating messages based on the verb, such as "what do you |
| | 17787 | want to open it with?". |
| | 17788 | |
| | 17789 | </div> |
| | 17790 | |
| | 17791 | <!-------------------> |
| | 17792 | <div class=entry> |
| | 17793 | |
| | 17794 | It would be better to interpret "type on typewriter" as having a |
| | 17795 | missing literal than as having a missing ON phrase (in other words, |
| | 17796 | we want to interpreter this as TYPE <empty literal> ON TYPEWRITER |
| | 17797 | rather than as TYPE "ON TYPEWRITER" <on missing object>). |
| | 17798 | |
| | 17799 | <p> |
| | 17800 | To do this, add a verb rule for TYPE ON <object>, without any literal |
| | 17801 | phrase. For most objects, fail in verification; but when |
| | 17802 | verification passes, in the action, ask for a missing literal phrase. |
| | 17803 | (This has the additional benefit that it makes it easy to create |
| | 17804 | objects that allow generic typing on them, as in TYPE ON COMPUTER, |
| | 17805 | for situations where the game doesn't want to make the player type |
| | 17806 | anything specific but still wants to allow the generic act of typing |
| | 17807 | on the object.) |
| | 17808 | |
| | 17809 | </div> |
| | 17810 | |
| | 17811 | <!-------------------> |
| | 17812 | <div class=entry> |
| | 17813 | |
| | 17814 | <pre> |
| | 17815 | >ASK BOB ABOUT |
| | 17816 | what do you want to ask him about? |
| | 17817 | |
| | 17818 | >BILL |
| | 17819 | "Ah, yes, , very interesting..." |
| | 17820 | </pre> |
| | 17821 | |
| | 17822 | <p> |
| | 17823 | (The problem is that we're not propagating getOrigText() from the |
| | 17824 | empty topic phrase match down to the underlying replacement match.) |
| | 17825 | |
| | 17826 | </div> |
| | 17827 | |
| | 17828 | <!-------------------> |
| | 17829 | <div class=entry> |
| | 17830 | |
| | 17831 | <pre> |
| | 17832 | >ASK BOB |
| | 17833 | what do you want to ask him about? |
| | 17834 | |
| | 17835 | >ABOUT BILL |
| | 17836 | "Ah, yes, about bill, very interesting..." |
| | 17837 | </pre> |
| | 17838 | |
| | 17839 | <p> |
| | 17840 | (The problem is that we need an aboutTopicPhrase production to parse |
| | 17841 | responses to ABOUT WHAT questions.) |
| | 17842 | |
| | 17843 | </div> |
| | 17844 | |
| | 17845 | <!-------------------> |
| | 17846 | <div class=entry> |
| | 17847 | |
| | 17848 | Add a generic Settable class for things (such as dials) that can be |
| | 17849 | set to various settings. Base Dial on Settable. |
| | 17850 | |
| | 17851 | </div> |
| | 17852 | |
| | 17853 | <!-------------------> |
| | 17854 | <div class=entry> |
| | 17855 | |
| | 17856 | Do not override lookAroundWithinDesc() in BasicLocation; instead, |
| | 17857 | provide an implementation of BasicLocation.roomDesc that simply uses |
| | 17858 | the 'desc' property to display the room's interior description. |
| | 17859 | (This allows nested rooms to differentiate more easily between |
| | 17860 | interior and exterior descriptions, if they want to.) |
| | 17861 | |
| | 17862 | </div> |
| | 17863 | |
| | 17864 | <!-------------------> |
| | 17865 | <div class=entry> |
| | 17866 | |
| | 17867 | Add a new method to Thing, filterResolveList(), to allow "global" |
| | 17868 | filtering of a noun phrase resolution list. Call this method from |
| | 17869 | the parser where we use 'verify' to filter a resolution list. Unlike |
| | 17870 | 'verify', this new method has access to the entire resolution list; |
| | 17871 | this allows the method to take action based on which other objects |
| | 17872 | are in the resolve list. |
| | 17873 | |
| | 17874 | </div> |
| | 17875 | |
| | 17876 | <!-------------------> |
| | 17877 | <div class=entry> |
| | 17878 | |
| | 17879 | Add a new mix-in class, Collective, to serve the purpose of the |
| | 17880 | former isCollectiveFor(obj) method in Thing. To create an object |
| | 17881 | like the matchbook in the sample game, use Collective as an |
| | 17882 | additional base class. |
| | 17883 | |
| | 17884 | <p> |
| | 17885 | Remove the special-cased plural filtering in AllPluralProd and |
| | 17886 | DefinitePluralProd. Move this logic instead into Collective's |
| | 17887 | filterResolveList() implementation. |
| | 17888 | |
| | 17889 | </div> |
| | 17890 | |
| | 17891 | <!-------------------> |
| | 17892 | <div class=entry> |
| | 17893 | |
| | 17894 | Add a new class, CollectiveGroup, to allow creating "abstract" |
| | 17895 | collective objects. These differ from regular Collective objects in |
| | 17896 | that a Collective is actually a simulation object (such as a |
| | 17897 | matchbook that can hold several matches), whereas a CollectiveGroup |
| | 17898 | is not a separate object from the player's perspective (so it's never |
| | 17899 | listed as a separate object in a room's contents listing, for |
| | 17900 | example). |
| | 17901 | |
| | 17902 | <p> |
| | 17903 | Add a new Thing property, collectiveGroup, that allows an ordinary |
| | 17904 | object to be associated with a CollectiveGroup object. In |
| | 17905 | CollectiveGroup's filterResolveList() method, choose to keep either |
| | 17906 | the individuals (the ordinary Thing objects associated via their |
| | 17907 | collectiveGroup properties with a CollectiveGroup object) or the |
| | 17908 | CollectiveGroup in the resolution list, but not both. By default, |
| | 17909 | make the selection based on action; subclasses can override as |
| | 17910 | desired to use other criteria. |
| | 17911 | |
| | 17912 | <p> |
| | 17913 | CollectiveGroup can be used to create things like a "money" object |
| | 17914 | to represent a set of coins and bills, so that a command like "look |
| | 17915 | at money" can respond with a single description of all of the money |
| | 17916 | present, rather than iterating over all of the coins and bills |
| | 17917 | individually. |
| | 17918 | |
| | 17919 | </div> |
| | 17920 | |
| | 17921 | <!-------------------> |
| | 17922 | <div class=entry> |
| | 17923 | |
| | 17924 | Eliminate the actorHereLister. Instead, handle actor descriptions |
| | 17925 | using the special description mechanism. By default, give actors |
| | 17926 | a higher specialDescOrder, to keep actor special descriptions listed |
| | 17927 | after other special descriptions. |
| | 17928 | |
| | 17929 | </div> |
| | 17930 | |
| | 17931 | <!-------------------> |
| | 17932 | <div class=entry> |
| | 17933 | |
| | 17934 | Add a new special description control property to Thing, |
| | 17935 | specialDescBeforeContents; set it to true by default in Thing, but |
| | 17936 | override it to nil in Actor. In verbose room descriptions, show |
| | 17937 | special descriptions in two phases: where we currently show special |
| | 17938 | descriptions, just before the room's list of portable contents, show |
| | 17939 | special descriptions only for items with specialDescBeforeContents |
| | 17940 | set to true. Then, after we've shown the portable contents list |
| | 17941 | and any other sensory messages (listen/smell), show the special |
| | 17942 | descriptions for objects with specialDescBeforeContents set to nil. |
| | 17943 | |
| | 17944 | <p> |
| | 17945 | This will allow the traditional ordering, with actor "I am here" |
| | 17946 | messages placed after the rest of the room description, while keeping |
| | 17947 | the rest of the special descriptions grouped with the room's main |
| | 17948 | description. Most special descriptions belong with the main room |
| | 17949 | description because they're meant to be extensions of the room |
| | 17950 | description. Some special descriptions are not; they're meant to |
| | 17951 | describe more ephemeral status information, so work better when |
| | 17952 | grouped with the other status-like messages. Actors in particular |
| | 17953 | fall into the latter category, since actors are meant to seem |
| | 17954 | autonomous, not parts of the rooms they occupy. |
| | 17955 | |
| | 17956 | </div> |
| | 17957 | |
| | 17958 | <!-------------------> |
| | 17959 | <div class=entry> |
| | 17960 | |
| | 17961 | When showing special descriptions of the contents of an object as part |
| | 17962 | of the object's description, use a new form of the special description |
| | 17963 | method, showSpecialDescInContentsWithInfo(), and corresponding |
| | 17964 | specific methods for viewing conditions (showSpecialDescInContents, |
| | 17965 | showObscuredSpecialDescInContents, showDistantSpecialDescInContents). |
| | 17966 | |
| | 17967 | <p> |
| | 17968 | Override showSpecialDescInContents in Actor, so that we can show |
| | 17969 | the type of description we previously showed using nestedActorLister. |
| | 17970 | |
| | 17971 | <p> |
| | 17972 | Remove nestedActorLister and NestedRoom.examineNestedRoomActors(). |
| | 17973 | |
| | 17974 | </div> |
| | 17975 | |
| | 17976 | <!-------------------> |
| | 17977 | <div class=entry> |
| | 17978 | |
| | 17979 | Add a default output filter, typographicalOutputFilter, to the main |
| | 17980 | output stream. In this filter, convert '--' and '---' sequences to |
| | 17981 | typographical dashes, and insert an en space at the end of each |
| | 17982 | sentence. |
| | 17983 | |
| | 17984 | <p> |
| | 17985 | The conversion of sentence-ending punctuation compensates for the |
| | 17986 | elimination of the double-space insertion in the VM-level formatter. |
| | 17987 | It also improves matters over the old way by making the treatment of |
| | 17988 | sentence-ending punctuation customizable: the game can replace the |
| | 17989 | filter method with its own custom conversions. This allows |
| | 17990 | customization not only for stylistic variation but for |
| | 17991 | language-specific conventions as well. |
| | 17992 | |
| | 17993 | </div> |
| | 17994 | |
| | 17995 | <!-------------------> |
| | 17996 | <div class=entry> |
| | 17997 | |
| | 17998 | Add the special {subj} messageBuilder token. This token simply notes |
| | 17999 | its target object as the subject of the sentence, for internal |
| | 18000 | book-keeping purposes, but doesn't actually display anything. |
| | 18001 | |
| | 18002 | </div> |
| | 18003 | |
| | 18004 | <!-------------------> |
| | 18005 | <div class=entry> |
| | 18006 | |
| | 18007 | Add a "log file console" type. This would act like the main console |
| | 18008 | or a banner console, in that it would apply the full set of VM-level |
| | 18009 | output formatting (including text-only HTML interpretation) to the |
| | 18010 | text sent through the stream, but it would write the output only to a |
| | 18011 | file, rather than displaying it anywhere. This would be useful for |
| | 18012 | capturing output to a file without showing the output at all on the |
| | 18013 | display; for example, this would make it easy to generate an About.txt |
| | 18014 | file by capturing the output of the ABOUT command to a file during |
| | 18015 | preinit, without having the ABOUT output also show up on the screen. |
| | 18016 | |
| | 18017 | <p> |
| | 18018 | This would require a new set of VM-level functions in the tads-io set: |
| | 18019 | |
| | 18020 | <p> |
| | 18021 | <ul> |
| | 18022 | <li>logConsoleCreate(filename, charmap, width): |
| | 18023 | returns a handle to the new console |
| | 18024 | |
| | 18025 | <li>logConsoleSay(handle, ...): writes the arguments to the |
| | 18026 | log console; works like say() and bannerSay() |
| | 18027 | |
| | 18028 | <li>logConsoleClose(handle): closes the console |
| | 18029 | </ul> |
| | 18030 | |
| | 18031 | <p> |
| | 18032 | In addition, add a LogConsole library class to simplify operations |
| | 18033 | with the log console. This class can be quite simple; it's just an |
| | 18034 | OutputStream subclass that implements the writeFromStream method to |
| | 18035 | call logConsoleSay(). |
| | 18036 | |
| | 18037 | </div> |
| | 18038 | |
| | 18039 | <!-------------------> |
| | 18040 | <div class=entry> |
| | 18041 | |
| | 18042 | Add a TopicQualifierResolver subclass of Resolver, specifically for |
| | 18043 | resolving qualifier phrases in topics. Use a new instance of this |
| | 18044 | class instead of the direct object resolver in TopicActionBase. (The |
| | 18045 | direct object resolver isn't really appropriate, and doesn't work at |
| | 18046 | all with plain TopicActions, because they don't have direct object |
| | 18047 | resolvers at all.) |
| | 18048 | |
| | 18049 | </div> |
| | 18050 | |
| | 18051 | <!-------------------> |
| | 18052 | <div class=entry> |
| | 18053 | |
| | 18054 | Add a new mapping macro, iobjAsDobjFor(), that makes it safe to map |
| | 18055 | an indirect object handler to a direct object handler in the same |
| | 18056 | object. Use this for the mapPushTravelHandlers() macro. |
| | 18057 | |
| | 18058 | <p> |
| | 18059 | (The mapPushTravelHandlers() macro essentially wants to decompose the |
| | 18060 | two-object action into two single-object actions, which isn't safe |
| | 18061 | with the regular asDobjFor() mapping. The difference with |
| | 18062 | iobjAsDobjFor() is that this new routine temporarily makes the |
| | 18063 | indirect object take on the direct object role, so that the target |
| | 18064 | dobj handler sees the proper object in the direct object slot.) |
| | 18065 | |
| | 18066 | </div> |
| | 18067 | |
| | 18068 | <!-------------------> |
| | 18069 | <div class=entry> |
| | 18070 | |
| | 18071 | Add a LabeledDial subclass of Dial. This class accepts arbitrary text |
| | 18072 | labels as dial stops; the property validSettings contains a list of |
| | 18073 | strings giving the valid dial stop labels. |
| | 18074 | |
| | 18075 | </div> |
| | 18076 | |
| | 18077 | <!-------------------> |
| | 18078 | <div class=entry> |
| | 18079 | |
| | 18080 | Remove any .t and .tl extensions from adv3.tl and en_us.tl. (The |
| | 18081 | extensions are implied by the file types; it makes the library file |
| | 18082 | more portable to omit the extensions, since the compiler will |
| | 18083 | automatically apply the default extensions using the appropriate local |
| | 18084 | conventions when the extensions aren't explicitly included in the |
| | 18085 | names as they appear in the library files.) |
| | 18086 | |
| | 18087 | </div> |
| | 18088 | |
| | 18089 | <!-------------------> |
| | 18090 | <div class=entry> |
| | 18091 | |
| | 18092 | Get rid of Thing.articleIndef; games should simply override aName |
| | 18093 | instead when they want to override the default indefinite article |
| | 18094 | determination. |
| | 18095 | |
| | 18096 | </div> |
| | 18097 | |
| | 18098 | <!-------------------> |
| | 18099 | <div class=entry> |
| | 18100 | |
| | 18101 | Change the way theDisambigName, aDisambigName, and countDisambigName |
| | 18102 | work. If name == disambigName, then return the corresponding xxxName |
| | 18103 | from xxxDisambigName; otherwise, apply the same algorithm to |
| | 18104 | disambigName that the corresponding xxxName applies to name. For |
| | 18105 | example, in aDisambigName, if name == disambigName, simply return |
| | 18106 | aName; otherwise, apply the indefinite article algorithm to |
| | 18107 | disambigName and return the result. |
| | 18108 | |
| | 18109 | <p> |
| | 18110 | This change will allow disambigName to be overridden without |
| | 18111 | requiring all of the xxxDisambigName's to be overridden at the same |
| | 18112 | time, because the xxxDisambigName's will by default apply the |
| | 18113 | standard algorithms to the modified disambigName. At the same time, |
| | 18114 | though, this has the virtue of the original implementation that, in |
| | 18115 | the common case where disambigName is not overridden, any overrides |
| | 18116 | to theName, aName, and countName will be used for the corresponding |
| | 18117 | xxxDisambigName's. Furthermore, since these are all still separate |
| | 18118 | methods, objects can still separately override each xxxDisambigName |
| | 18119 | as needed for cases where the disambigName is customized <i>and</i> the |
| | 18120 | customized name requires overriding the normal article algorithms. |
| | 18121 | |
| | 18122 | <p> |
| | 18123 | While we're at it, add pluralDisambigName, using the same logic. |
| | 18124 | |
| | 18125 | </div> |
| | 18126 | |
| | 18127 | <!-------------------> |
| | 18128 | <div class=entry> |
| | 18129 | |
| | 18130 | Remove the dictionary properties possessiveAdj, possessiveNoun, and |
| | 18131 | their corresponding grammar. (These are no longer needed, since we |
| | 18132 | now have explicit grammar for all of the possessive pronouns in |
| | 18133 | adjective and noun usages. At one time, these were used for adding |
| | 18134 | vocabulary for the player character, but it worked better to use the |
| | 18135 | grammar and resolver mechanism more explicitly.) |
| | 18136 | |
| | 18137 | </div> |
| | 18138 | |
| | 18139 | <!-------------------> |
| | 18140 | <div class=entry> |
| | 18141 | |
| | 18142 | Rework "'s" handling for literal vocabulary: |
| | 18143 | |
| | 18144 | <p> |
| | 18145 | First, remove the special-case tokenizer handling for "'s" words that |
| | 18146 | appear in the dictionary, so that we handle <b>all</b> "'s" words |
| | 18147 | uniformly in the tokenizer: all "'s" suffixes are treated as separate |
| | 18148 | tokens. |
| | 18149 | |
| | 18150 | <p> |
| | 18151 | Second, never add "'s" words to the dictionary in initializeVocab(). |
| | 18152 | Instead, define a new dictionary property, adjApostS; when we see a |
| | 18153 | "'s" word in a vocabulary list, remove the "'s" suffix and add only |
| | 18154 | the prefix to the dictionary, but add it as an adjApostS instead of |
| | 18155 | as an adjective. (For simplicity, don't bother with nounApostS at |
| | 18156 | all; allow only adjectives as apostrophe-s words.) |
| | 18157 | |
| | 18158 | <p> |
| | 18159 | Third, add a new grammar production, adjWord, that accepts either a |
| | 18160 | single adjective or an adjApostS followed by an apostrophe-s token. |
| | 18161 | |
| | 18162 | <p> |
| | 18163 | Fourth, where appropriate, change 'adjective->' grammar rules to use |
| | 18164 | 'adjWord->' instead. |
| | 18165 | |
| | 18166 | <p> |
| | 18167 | These changes correct the problem that adding a literal "'s" word to |
| | 18168 | an object's vocabulary prevented that word from being used as a true |
| | 18169 | possessive phrase in the grammar. The old tokenizer rule was that a |
| | 18170 | word that appeared with an explicit "'s" suffix in the dictionary was |
| | 18171 | kept intact, rather than split into separate tokens for the root word |
| | 18172 | and the "'s" suffix. Since the word was kept intact as a single |
| | 18173 | token, it couldn't match the grammar rules for possessive phrases, |
| | 18174 | which only match the separated form. These changes allow the same |
| | 18175 | word to be used in either context, since everything is treated the |
| | 18176 | same way in the tokenizer; even if a word is used as a literal |
| | 18177 | vocabulary word with a "'s", it'll still be split up during |
| | 18178 | tokenization. Even with this change, we can still match explicit |
| | 18179 | "'s" vocabulary words, thanks to the adjWord grammar. |
| | 18180 | |
| | 18181 | <p> |
| | 18182 | Note this has one small potential impact on existing games: if an |
| | 18183 | object explicitly defines its own 'adjective' property (rather than |
| | 18184 | using the automatic library initialization), and a word defined in the |
| | 18185 | adjective list ends in apostrophe-s, then that word must be stripped |
| | 18186 | of the apostrophe-s suffix, removed from the 'adjective' list, and |
| | 18187 | added to a new 'adjApostS' list instead. Similarly, if any vocabulary |
| | 18188 | words that end in apostrophe-s are dynamically added with |
| | 18189 | G_dict.addWord(), the apostrophe-s words should be stripped of the |
| | 18190 | suffix and added under the '&adjApostS' property instead of the |
| | 18191 | '&adjective' property. |
| | 18192 | |
| | 18193 | </div> |
| | 18194 | |
| | 18195 | <!-------------------> |
| | 18196 | <div class=entry> |
| | 18197 | |
| | 18198 | Add noteLiteral(lst_.getOrigText()) to getVocabMatchList() in |
| | 18199 | simpleNounPhrase(misc)? This would make the length of text in a |
| | 18200 | miscellaneous word list a match selection criterion (less important |
| | 18201 | than the presence of a misc word list). This won't change anything in |
| | 18202 | cases where we want to choose between a match with a misc word list |
| | 18203 | and one without, as the presence or absence of a misc word list is |
| | 18204 | more important than literal length, but it will help distinguish |
| | 18205 | between two matches that both have misc word lists. Since we prefer a |
| | 18206 | shorter literal match, this will have the effect of preferring to |
| | 18207 | match the more structured interpretation, since a shorter misc word |
| | 18208 | match means a longer grammar match. |
| | 18209 | |
| | 18210 | </div> |
| | 18211 | |
| | 18212 | <!-------------------> |
| | 18213 | <div class=entry> |
| | 18214 | |
| | 18215 | Fix run-time error with "a <phrase>" (the 'inherited' argument list |
| | 18216 | is wrong in AskAboutAction.getDefaultDobj; the same problem is in |
| | 18217 | TellAboutAction). |
| | 18218 | |
| | 18219 | </div> |
| | 18220 | |
| | 18221 | <!-------------------> |
| | 18222 | <div class=entry> |
| | 18223 | |
| | 18224 | Rename class Fixed to Fixture. |
| | 18225 | |
| | 18226 | </div> |
| | 18227 | |
| | 18228 | <!-------------------> |
| | 18229 | <div class=entry> |
| | 18230 | |
| | 18231 | Add new class Immovable: this is for objects that aren't fixed in |
| | 18232 | place obviously or by their very nature (as are Fixtures), but rather |
| | 18233 | are fixed for some other reason: great weight, hidden fasteners, etc. |
| | 18234 | This class differs from Fixture in that it disallows actions like |
| | 18235 | take, move, push, and pull not in the verify() but in the action(). |
| | 18236 | |
| | 18237 | <p> |
| | 18238 | Add a subclass, Heavy, for objects that are immovable because they're |
| | 18239 | very heavy. This is suitable for things like large furniture and big |
| | 18240 | boulders. |
| | 18241 | |
| | 18242 | </div> |
| | 18243 | |
| | 18244 | <!-------------------> |
| | 18245 | <div class=entry> |
| | 18246 | |
| | 18247 | Remove moveInto() override on Immovable. (This attempted to be a last |
| | 18248 | resort to disallow actions that involved trying to move the object, |
| | 18249 | but it prevented programmatic relocation as well, creating more |
| | 18250 | problems than it solved.) |
| | 18251 | |
| | 18252 | </div> |
| | 18253 | |
| | 18254 | <!-------------------> |
| | 18255 | <div class=entry> |
| | 18256 | |
| | 18257 | Fix problem with applying AGAIN to a command issued to another actor: |
| | 18258 | the target actor becomes "busy" and won't accept another command until |
| | 18259 | a turn passes. The problem is that we're not accounting for |
| | 18260 | synchronous actors in the AGAIN processing: we need to tell the issuer |
| | 18261 | to waitForIssuedCommand on the target actor. |
| | 18262 | |
| | 18263 | </div> |
| | 18264 | |
| | 18265 | <!-------------------> |
| | 18266 | <div class=entry> |
| | 18267 | |
| | 18268 | Fix problem in GiveTo and ShowTo actions: getDefaultIobj calls |
| | 18269 | inherited() with wrong argument list. |
| | 18270 | |
| | 18271 | </div> |
| | 18272 | |
| | 18273 | <!-------------------> |
| | 18274 | <div class=entry> |
| | 18275 | |
| | 18276 | Fix the parameter list for npcActionMessages.okayTurnTo. |
| | 18277 | |
| | 18278 | </div> |
| | 18279 | |
| | 18280 | <!-------------------> |
| | 18281 | <div class=entry> |
| | 18282 | |
| | 18283 | Make RandomTextList customizable with the percentage of the time a |
| | 18284 | message is generated at all. Random message lists are often used for |
| | 18285 | atmospheric messages, and it's usually better if these messages don't |
| | 18286 | appear on every single turn. Add a 'messagePercent' property that |
| | 18287 | determines the percentage of turns where a message is generated; the |
| | 18288 | default is 100, which leaves the default behavior as it was (i.e., a |
| | 18289 | message is generated on every turn). |
| | 18290 | |
| | 18291 | <p> |
| | 18292 | In addition, especially with random atmospheric messages, it can get |
| | 18293 | tedious to see the same messages over and over if you spend a lot of |
| | 18294 | time in the same area. It's therefore often the case that we want |
| | 18295 | frequent atmospheric messages when the player first gets to a |
| | 18296 | location, but then we want the frequency to drop dramatically after |
| | 18297 | the player has spent more than a few turns there. To make this easy |
| | 18298 | to handle, add a couple of new properties: 'messageReduceAfter' is the |
| | 18299 | number of times that we want to see messages at the initial frequency, |
| | 18300 | and 'messageReduceTo' is a new value for 'messagePercent' that we'll |
| | 18301 | apply after we've generated the messages 'messageReduceAfter' times. |
| | 18302 | Make these nil by default, which means that there is never a reduction |
| | 18303 | in the frequency. Authors can use these properties to generate random |
| | 18304 | atmosphere messages at high frequency at first, but then drop the |
| | 18305 | frequency to just an occasional message after the player has been in |
| | 18306 | the location long enough to get the idea. |
| | 18307 | |
| | 18308 | </div> |
| | 18309 | |
| | 18310 | <!-------------------> |
| | 18311 | <div class=entry> |
| | 18312 | |
| | 18313 | Add a new class, NominalPlatform. This is a "secret" object: it's not |
| | 18314 | visible to the player as a separate simulation object, and won't |
| | 18315 | normally have any vocabulary or appear in any room listings. The |
| | 18316 | purpose of this object is to make it easier to describe NPC's as |
| | 18317 | standing somewhere specific within a room; the author locates an NPC |
| | 18318 | within the NominalPlatform, and the library will automatically |
| | 18319 | describe the NPC as standing on the platform: "Bob is here, standing |
| | 18320 | in the corner." The author can also customize the display methods for |
| | 18321 | the nominal platform so that the description is something like |
| | 18322 | "leaning against the lamppost." |
| | 18323 | |
| | 18324 | </div> |
| | 18325 | |
| | 18326 | <!-------------------> |
| | 18327 | <div class=entry> |
| | 18328 | |
| | 18329 | Add a new property to Thing, specialContentsLister, that lets |
| | 18330 | individual objects and rooms customize the lister they use to generate |
| | 18331 | special descriptions. Set the property by default to |
| | 18332 | specialDescLister. |
| | 18333 | |
| | 18334 | </div> |
| | 18335 | |
| | 18336 | <!-------------------> |
| | 18337 | <div class=entry> |
| | 18338 | |
| | 18339 | Add a new topicPhrase grammar rule that matches a miscWordList without |
| | 18340 | badness. (The normal topicPhrase grammar matches a singleNoun, which |
| | 18341 | matches a miscWordList, but it does so with badness; we want to add an |
| | 18342 | explicit rule that matches a miscWordList without badness.) It's in |
| | 18343 | the nature of topic phrases to go outside of what's implemented in the |
| | 18344 | simulation model; we don't want to treat resolvable and irresolvable |
| | 18345 | topic phrases any differently at the grammatical level, because doing |
| | 18346 | so can lead to inconsistencies when parsing a verb containing both a |
| | 18347 | topic and another kind of noun phrase. |
| | 18348 | |
| | 18349 | </div> |
| | 18350 | |
| | 18351 | <!-------------------> |
| | 18352 | <div class=entry> |
| | 18353 | |
| | 18354 | Add gLiteral to adv3.h, analogous to gTopic. |
| | 18355 | |
| | 18356 | </div> |
| | 18357 | |
| | 18358 | <!-------------------> |
| | 18359 | <div class=entry> |
| | 18360 | |
| | 18361 | Change Thing.dobjFor(Attack) so that the default Attack handling is |
| | 18362 | simply to display the message "it's useless to attack that." Remove |
| | 18363 | the askIobjFor(AttackWith). Specifying a weapon shouldn't be |
| | 18364 | required; especially for attacks like "hit" and "kick," asking for an |
| | 18365 | indirect object will seem wrong to a player. This makes a tiny bit of |
| | 18366 | extra work for authors when AttackWith is overridden, since Attack |
| | 18367 | will have to be overridden as well in such cases, but this is probably |
| | 18368 | worthwhile anyway because it'll encourage authors to make the same |
| | 18369 | distinction between weapon and weaponless attacks that players are |
| | 18370 | likely to make in their own minds. |
| | 18371 | |
| | 18372 | </div> |
| | 18373 | |
| | 18374 | <!-------------------> |
| | 18375 | <div class=entry> |
| | 18376 | |
| | 18377 | Move the code from Contents.examineContainerContents into |
| | 18378 | Thing.examineStatus (actually, into a new method called from |
| | 18379 | Thing.examineStatus, call it examineListContents). Get rid of |
| | 18380 | Surface.examineSurfaceContents. Ordinary Thing objects should |
| | 18381 | traverse into their contents during Examine; this shouldn't be limited |
| | 18382 | to Container and Surface objects. We need to do this listing in |
| | 18383 | Thing, because a Thing could contain a component that's a container, |
| | 18384 | and we want to list its contents when examining the Thing. |
| | 18385 | |
| | 18386 | </div> |
| | 18387 | |
| | 18388 | <!-------------------> |
| | 18389 | <div class=entry> |
| | 18390 | |
| | 18391 | Fix bug in Action.getObjPreconditions: if pre is nil before appending |
| | 18392 | the catch-all list, we'll get an error. Check that pre is nil before |
| | 18393 | appending, and just use the catch-all list by itself if so. |
| | 18394 | |
| | 18395 | </div> |
| | 18396 | |
| | 18397 | <!-------------------> |
| | 18398 | <div class=entry> |
| | 18399 | |
| | 18400 | Change the TravelConnector.describeDeparture() and describeArrival() |
| | 18401 | interfaces to add a new parameter for the traveler. Use the traveler |
| | 18402 | parameter instead of the global gActor. This makes the travel |
| | 18403 | routines more flexible, and in particular allows them to be called |
| | 18404 | from outside of commands (in daemons, for example). It also will |
| | 18405 | improve the handling for non-actor travelers (vehicles in particular). |
| | 18406 | |
| | 18407 | </div> |
| | 18408 | |
| | 18409 | <!-------------------> |
| | 18410 | <div class=entry> |
| | 18411 | |
| | 18412 | In RoomConnector.describeDeparture/Arrival, use gPlayerChar rather |
| | 18413 | than gActor as the point-of-view object in directionForConnector(). |
| | 18414 | The description is being generated for the benefit of the player, so |
| | 18415 | it should be from the PC's perspective. |
| | 18416 | |
| | 18417 | <p> |
| | 18418 | Split off a new method from each of Traveler.describeDeparture and |
| | 18419 | describeArrival: describeNpcDeparture/Arrival, which is called when |
| | 18420 | an NPC (or a traveler not involving the PC) is doing the travel. |
| | 18421 | This will simplify overriding the messages for vehicles and other |
| | 18422 | special travelers when desired, since the overriding method won't |
| | 18423 | have to make all of the checks to see if it's the PC doing the travel. |
| | 18424 | |
| | 18425 | </div> |
| | 18426 | |
| | 18427 | <!-------------------> |
| | 18428 | <div class=entry> |
| | 18429 | |
| | 18430 | Run all of the libMessages.sayDeparting/Arriving connector-specific |
| | 18431 | messages through an intermediate method call in the Traveler; these |
| | 18432 | new Traveler methods by default are simply be covers for calls to the |
| | 18433 | libMessages methods. The purpose of the extra layer of calls through |
| | 18434 | Traveler is to make it easier for individual Traveler subclasses to |
| | 18435 | customize the messages on a per-connector-subclass basis. |
| | 18436 | |
| | 18437 | </div> |
| | 18438 | |
| | 18439 | <!-------------------> |
| | 18440 | <div class=entry> |
| | 18441 | |
| | 18442 | '@script.txt' at the command prompt should start reading from the |
| | 18443 | named script file. (This should work essentially the same way it did |
| | 18444 | in tads 2, except that we want to handle this in the library instead |
| | 18445 | of in the interpreter.) Also, '@@script.txt' should run the script in |
| | 18446 | "quiet mode," which is to say that input and output generated while |
| | 18447 | reading the script are to be suppressed. |
| | 18448 | |
| | 18449 | </div> |
| | 18450 | |
| | 18451 | <!-------------------> |
| | 18452 | <div class=entry> |
| | 18453 | |
| | 18454 | Add some new classes to misc.t for "shuffled" random selections. A |
| | 18455 | shuffled selection is a random selection taken from a set of values |
| | 18456 | that doesn't repeat a selection until we've gone through all of the |
| | 18457 | values once, like dealing from a shuffled deck of cards. |
| | 18458 | |
| | 18459 | <p> |
| | 18460 | ShuffledList: the basic shuffled selection class. Keeps a list of |
| | 18461 | values, and returns a randomly selected element on demand. |
| | 18462 | |
| | 18463 | <p> |
| | 18464 | ShuffledIntegerList: a specialization of ShuffledList that returns |
| | 18465 | a randomly selected integer from a given range. |
| | 18466 | |
| | 18467 | <p> |
| | 18468 | ShuffledTextList: a subclass of RandomTextList that makes its |
| | 18469 | selection using shuffling rather than independent random selection. |
| | 18470 | |
| | 18471 | </div> |
| | 18472 | |
| | 18473 | <!-------------------> |
| | 18474 | <div class=entry> |
| | 18475 | |
| | 18476 | Add a point-of-view parameter to Thing.showSpecialDescWithInfo(). |
| | 18477 | |
| | 18478 | </div> |
| | 18479 | |
| | 18480 | <!-------------------> |
| | 18481 | <div class=entry> |
| | 18482 | |
| | 18483 | Add a parameter to the following library messages to indicate which |
| | 18484 | object is being described (the object is needed for things like gender |
| | 18485 | and number agreement in some languages): |
| | 18486 | |
| | 18487 | <p> |
| | 18488 | openMsg, closedMsg, lockedMsg, unlockedMsg, onMsg, offMsg |
| | 18489 | |
| | 18490 | </div> |
| | 18491 | |
| | 18492 | <!-------------------> |
| | 18493 | <div class=entry> |
| | 18494 | |
| | 18495 | Add a parameter to the following library messages to indicate which |
| | 18496 | actor is being described (the actor is needed for things like gender |
| | 18497 | and number agreement in some languages): |
| | 18498 | |
| | 18499 | <p> |
| | 18500 | statusStanding, statusSitting, statusLying, |
| | 18501 | statusStandingOn, statusSittingOn, statusLyingOn |
| | 18502 | |
| | 18503 | </div> |
| | 18504 | |
| | 18505 | <!-------------------> |
| | 18506 | <div class=entry> |
| | 18507 | |
| | 18508 | Add a parameter to the various name methods in ThingState (listName, |
| | 18509 | inventoryName, wornName) providing a list of the objects being shown |
| | 18510 | in this state. This is needed for some languages so that the state |
| | 18511 | description can agree (in gender and number, for example) with the |
| | 18512 | objects being desribed as being in the state. |
| | 18513 | |
| | 18514 | </div> |
| | 18515 | |
| | 18516 | <!-------------------> |
| | 18517 | <div class=entry> |
| | 18518 | |
| | 18519 | Change the count parameter to the full list in |
| | 18520 | actorStandingGroupPrefix and the related methods in libMessages. |
| | 18521 | This will allow the prefix/suffix messages to check any attributes of |
| | 18522 | the individual objects in the list, such as gender mix, that might |
| | 18523 | affect the message. |
| | 18524 | |
| | 18525 | </div> |
| | 18526 | |
| | 18527 | <!-------------------> |
| | 18528 | <div class=entry> |
| | 18529 | |
| | 18530 | The INSTRUCTIONS command should not take any turns (make it a |
| | 18531 | "system" command). Also, it should not consume any game time on the |
| | 18532 | real-time clock (which, given the size of the instructions, could be |
| | 18533 | noticeable). |
| | 18534 | |
| | 18535 | </div> |
| | 18536 | |
| | 18537 | <!-------------------> |
| | 18538 | <div class=entry> |
| | 18539 | |
| | 18540 | Add an extended form of inputManager.getInputLine(), which takes a |
| | 18541 | new InputDef object to define the input parameters. Use this new |
| | 18542 | parameter definitions object to determine what to display to set and |
| | 18543 | remove the input text style; do this instead of unconditionally using |
| | 18544 | the <.inputline> style tag. The InputDef class should use |
| | 18545 | <.inputline> as the default, of course. Keep the existing |
| | 18546 | getInputLine() method, but make it a cover for a call to the new |
| | 18547 | extended version, setting up an InputDef object representing the |
| | 18548 | parameters. |
| | 18549 | |
| | 18550 | </div> |
| | 18551 | |
| | 18552 | <!-------------------> |
| | 18553 | <div class=entry> |
| | 18554 | |
| | 18555 | Make "remove" (with a direct object but no indirect object) a fully |
| | 18556 | separate verb from "doff". In English, "remove foo" usually means |
| | 18557 | "doff foo", but it can also have the substantially separate sense of |
| | 18558 | removing a component of an object. In the English library module, |
| | 18559 | provide a default mapping of "remove" to "doff" in Thing, to keep the |
| | 18560 | default meaning the same. Making a separate Remove action will allow |
| | 18561 | this action to be independently overridden per object when it's |
| | 18562 | desirable to do so. |
| | 18563 | |
| | 18564 | </div> |
| | 18565 | |
| | 18566 | <!-------------------> |
| | 18567 | <div class=entry> |
| | 18568 | |
| | 18569 | By default, don't list anything in the credits for a library module. |
| | 18570 | We should leave the formatting of the credits fully up to the author. |
| | 18571 | |
| | 18572 | </div> |
| | 18573 | |
| | 18574 | <!------------------------------- 3.0.5 ---------------------------------> |
| | 18575 | <div class="sepbar"><a name='305'></a>3.0.5</div> |
| | 18576 | |
| | 18577 | <div class=firstentry> |
| | 18578 | |
| | 18579 | Add an optional mainRestore() function, to be provided by the game |
| | 18580 | and called from the run-time startup code when a saved game is |
| | 18581 | explicitly selected for restoration at startup (such as by |
| | 18582 | double-clicking on a saved position file from a GUI desktop, or using |
| | 18583 | the "-r" option with the command-line interpreter). |
| | 18584 | |
| | 18585 | </div> |
| | 18586 | |
| | 18587 | <!-------------------> |
| | 18588 | <div class=entry> |
| | 18589 | |
| | 18590 | Change runGame() so that it no longer takes the initial player |
| | 18591 | character parameter. Instead, callers should always set gPlayerChar |
| | 18592 | explicitly prior to calling runGame(). (This change makes runGame() |
| | 18593 | more sensible for cases where a game is restored: since the restore |
| | 18594 | operation will restore gPlayerChar as part of restoring the rest of |
| | 18595 | the game's state, it would be redundant to pass gPlayerChar as a |
| | 18596 | parameter to runGame() only to have runGame() set gPlayerChar to that |
| | 18597 | value.) |
| | 18598 | |
| | 18599 | </div> |
| | 18600 | |
| | 18601 | <!-------------------> |
| | 18602 | <div class=entry> |
| | 18603 | |
| | 18604 | Fix the bug in EventManager.removeMatchingEvents ('eventMatches' should |
| | 18605 | be 'cur.eventMatches') |
| | 18606 | |
| | 18607 | </div> |
| | 18608 | |
| | 18609 | <!-------------------> |
| | 18610 | <div class=entry> |
| | 18611 | |
| | 18612 | Add a new output stream method, addOutputFilterBelow(), which adds an |
| | 18613 | output filter at a given point in the filter stack. |
| | 18614 | |
| | 18615 | </div> |
| | 18616 | |
| | 18617 | <!-------------------> |
| | 18618 | <div class=entry> |
| | 18619 | |
| | 18620 | Remove the "\( \)" escape sequences (for highlighted text). Authors |
| | 18621 | should use HTML markups <B> and </B> instead. |
| | 18622 | |
| | 18623 | </div> |
| | 18624 | |
| | 18625 | <!-------------------> |
| | 18626 | <div class=entry> |
| | 18627 | |
| | 18628 | Combine open/closed and contents status listings into a single |
| | 18629 | message, to make the openable container default description less |
| | 18630 | choppy. |
| | 18631 | |
| | 18632 | </div> |
| | 18633 | |
| | 18634 | <!-------------------> |
| | 18635 | <div class=entry> |
| | 18636 | |
| | 18637 | Rename maxBulk to bulkCapacity, to make the meaning clearer. |
| | 18638 | Similarly, rename maxWeight to weightCapacity. |
| | 18639 | |
| | 18640 | </div> |
| | 18641 | |
| | 18642 | <!-------------------> |
| | 18643 | <div class=entry> |
| | 18644 | |
| | 18645 | >put trike in bag. drop bag. ride trike. |
| | 18646 | (produces a run-time error) |
| | 18647 | |
| | 18648 | The problem is that we're failing to treat the bag as an invalid |
| | 18649 | "staging location" on the way to boarding the trike. Add a routine, |
| | 18650 | checkStagingLocation, to Thing, and call when moving an actor into a |
| | 18651 | chosen staging location; this routine should generate an error |
| | 18652 | explaining why the travel is impossible and terminate the command |
| | 18653 | with 'exit'. BasicLocation should override this to allow being used |
| | 18654 | as a staging location. |
| | 18655 | |
| | 18656 | </div> |
| | 18657 | |
| | 18658 | <!-------------------> |
| | 18659 | <div class=entry> |
| | 18660 | |
| | 18661 | add default Thing handling for 'feel' and 'taste' commands |
| | 18662 | |
| | 18663 | </div> |
| | 18664 | |
| | 18665 | <!-------------------> |
| | 18666 | <div class=entry> |
| | 18667 | |
| | 18668 | <pre> |
| | 18669 | >close bag; x all in bag |
| | 18670 | red ball: You cannot see that. [etc] |
| | 18671 | </pre> |
| | 18672 | <p> |
| | 18673 | We're incorrectly resolving the contents of an object for an "all in |
| | 18674 | x" phrase, even when the contents can't be seen. We must filter the |
| | 18675 | resolved objects to include only the visible contents. |
| | 18676 | |
| | 18677 | </div> |
| | 18678 | |
| | 18679 | <!-------------------> |
| | 18680 | <div class=entry> |
| | 18681 | |
| | 18682 | "all in x" doesn't filter for objects hidden from "all" phrases; it |
| | 18683 | should. |
| | 18684 | |
| | 18685 | </div> |
| | 18686 | |
| | 18687 | <!-------------------> |
| | 18688 | <div class=entry> |
| | 18689 | |
| | 18690 | Standing should be a precondition of "jump". |
| | 18691 | |
| | 18692 | </div> |
| | 18693 | |
| | 18694 | <!-------------------> |
| | 18695 | <div class=entry> |
| | 18696 | |
| | 18697 | The noMatchDisambig and disambigOrdinalOutOfRange messages should use |
| | 18698 | <.parser> open tags, but not close tags: instead, the <.parser> mode |
| | 18699 | should be left open, to be closed by the disambiguation re-prompt that |
| | 18700 | always follows. |
| | 18701 | |
| | 18702 | <p> |
| | 18703 | askDisambig should provide an open <.parser> tag if and only if askAgain |
| | 18704 | is false: this will let the mode flow in from the preceding re-prompt |
| | 18705 | message from noMatchDisambig or disambigOrdinalOutOfRange. askDisambig |
| | 18706 | should always close the <.parser> tag. |
| | 18707 | |
| | 18708 | </div> |
| | 18709 | |
| | 18710 | <!-------------------> |
| | 18711 | <div class=entry> |
| | 18712 | |
| | 18713 | Get rid of parserMessage(), and just use <.parser> tags instead. |
| | 18714 | |
| | 18715 | </div> |
| | 18716 | |
| | 18717 | <!-------------------> |
| | 18718 | <div class=entry> |
| | 18719 | |
| | 18720 | We shouldn't be able to read at brightness 2. For Readable, |
| | 18721 | differentiate readability according to brightness and transparency, |
| | 18722 | as long as a readDesc is defined. (When no readDesc is defined for |
| | 18723 | the object, use the default "examine" behavior as usual.) |
| | 18724 | |
| | 18725 | </div> |
| | 18726 | |
| | 18727 | <!-------------------> |
| | 18728 | <div class=entry> |
| | 18729 | |
| | 18730 | Disambiguation: when indistinguishables are involved, answering with |
| | 18731 | an ordinal applies the ordinal to the full list, rather than the |
| | 18732 | reduced list offered: |
| | 18733 | |
| | 18734 | <p><pre> |
| | 18735 | >take coin |
| | 18736 | Which coin do you mean, a gold coin, a silver coin, or a copper coin? |
| | 18737 | |
| | 18738 | >second |
| | 18739 | Taken. [actually takes a gold coin, since more than one was present] |
| | 18740 | </pre> |
| | 18741 | </div> |
| | 18742 | |
| | 18743 | <!-------------------> |
| | 18744 | <div class=entry> |
| | 18745 | |
| | 18746 | Add a new option flag, libGlobal.allowYouMeMixing, that controls |
| | 18747 | whether or not the parser accepts "you" and "me" in commands as |
| | 18748 | equivalent. Set this to true by default, since most games will not |
| | 18749 | have both first- and second-person narrative characters at the same |
| | 18750 | time, and hence it seems unlikely that it will ever create confusion |
| | 18751 | if the player can use "you" and "me" interchangeably. (Having the |
| | 18752 | option to make the parser strict about this will take care of any |
| | 18753 | cases where a game actually does have separate first- and |
| | 18754 | second-person characters present simultaneously.) |
| | 18755 | |
| | 18756 | </div> |
| | 18757 | |
| | 18758 | <!-------------------> |
| | 18759 | <div class=entry> |
| | 18760 | |
| | 18761 | The forwarding scheme isn't quite right. Replace it. |
| | 18762 | |
| | 18763 | <p> |
| | 18764 | First, get rid of dobjForwardTo, iobjForwardTo, remapTIAction, |
| | 18765 | dobjRemapTI, iobjRemapTI, dobjRemapTIReverse, and iobjRemapTIReverse. |
| | 18766 | |
| | 18767 | <p> |
| | 18768 | Second, add a new mechanism that combines the old forwarding and |
| | 18769 | remapping schemes into a single new system. Use syntax like so: |
| | 18770 | |
| | 18771 | <p><pre> |
| | 18772 | desk: Fixed |
| | 18773 | dobjFor(Open) remapTo(Open, drawer) |
| | 18774 | dobjFor(Close) remapTo(Close, drawer) |
| | 18775 | ; |
| | 18776 | </pre> |
| | 18777 | <p> |
| | 18778 | The first definition above maps the Open action, when applied to the |
| | 18779 | desk, to a replacement action of Open applied to the drawer instead. |
| | 18780 | The second does the same thing for Close. This replaces the old |
| | 18781 | dobjForwardTo/iobjForwardTo scheme, so we no longer need forwarding at |
| | 18782 | all. The difference with the new remapTo scheme is that we use a |
| | 18783 | replacement action for the remapping - the remap for Open above is |
| | 18784 | essentially like using replaceAction(Open, drawer) for the action |
| | 18785 | definition of Open on the desk. |
| | 18786 | |
| | 18787 | <p> |
| | 18788 | Further, consider this syntax: |
| | 18789 | |
| | 18790 | <p><pre> |
| | 18791 | lid: Fixed |
| | 18792 | dobjFor(Push) remapTo(Open, jar) |
| | 18793 | dobjFor(Pull) remapTo(Close, jar) |
| | 18794 | ; |
| | 18795 | </pre><p> |
| | 18796 | Here we've remapped not only the object (as we formerly did with |
| | 18797 | forwarding), but also the action. The first definition above says |
| | 18798 | to replace "push lid" with the new action "open jar." |
| | 18799 | |
| | 18800 | <p> |
| | 18801 | Next, consider this: |
| | 18802 | |
| | 18803 | <p><pre> |
| | 18804 | ninjaThrowingStar: Weapon |
| | 18805 | iobjFor(AttackWith) remapTo(ThrowAt, self, DirectObject) |
| | 18806 | ; |
| | 18807 | </pre> |
| | 18808 | <p> |
| | 18809 | In this case, we're doing what the old dobjRemapTIReverse did, but |
| | 18810 | with considerably clearer syntax. We're saying that when we resolve |
| | 18811 | the indirect object of "attack with" and find that it's the throwing |
| | 18812 | star, we should remap the action to "throw <ninjaThrowingStar> at |
| | 18813 | <direct object>", where <direct object> is the original direct object |
| | 18814 | of the AttackWith action. The important thing about using the |
| | 18815 | "DirectObject" argument is that it tells us to use the pre-resolved |
| | 18816 | match tree for the direct object if we haven't yet resolved the direct |
| | 18817 | object noun phrase - this means that we'll be able to resolve that |
| | 18818 | noun phrase in the context of the new action (ThrowAt) rather than in |
| | 18819 | the original action (AttackWith) context. |
| | 18820 | |
| | 18821 | </div> |
| | 18822 | |
| | 18823 | <!-------------------> |
| | 18824 | <div class=entry> |
| | 18825 | |
| | 18826 | Compiler: for each nested object definition, set a property of the |
| | 18827 | nested object, 'lexicalParent', to point to the lexically enclosing |
| | 18828 | object. |
| | 18829 | |
| | 18830 | </div> |
| | 18831 | |
| | 18832 | <!-------------------> |
| | 18833 | <div class=entry> |
| | 18834 | |
| | 18835 | Change the default message for talking/asking/etc a random object to |
| | 18836 | indicate more specifically that it's illogical to talk to the object. |
| | 18837 | |
| | 18838 | </div> |
| | 18839 | |
| | 18840 | <!-------------------> |
| | 18841 | <div class=entry> |
| | 18842 | |
| | 18843 | Add a class for a complex container, for objects that contain objects |
| | 18844 | in multiple ways. Examples: a crate that can contain things within |
| | 18845 | and also have objects placed on top of it; a container with |
| | 18846 | components. |
| | 18847 | |
| | 18848 | <p> |
| | 18849 | The class should treat all of its immediate contents as components, |
| | 18850 | so it should be based on Thing rather than Container or Surface. It |
| | 18851 | should have two additional properties: one for a secret object that |
| | 18852 | serves as the internal container, and another for a secret object |
| | 18853 | that serves as the internal surface. Commands like "put in" and |
| | 18854 | "look in" should be redirected to the internal container, if one is |
| | 18855 | defined; "put on" and the like to the internal surface, if present. |
| | 18856 | The contents lister must specifically show the contents of the secret |
| | 18857 | internal container and surface as though they were contained directly |
| | 18858 | by the outer object. |
| | 18859 | |
| | 18860 | </div> |
| | 18861 | |
| | 18862 | <!-------------------> |
| | 18863 | <div class=entry> |
| | 18864 | |
| | 18865 | Change default Thing handling for Push, Pull, Move, MoveWith (dobj), |
| | 18866 | and MoveTo (dobj), so that verification succeeds with a logicalRank |
| | 18867 | of 50, and report that there is no effect in the action. (These |
| | 18868 | actions all involve physical manipulations that a player might want |
| | 18869 | to try with any object, so it's better to allow these to pass |
| | 18870 | verification, so that preconditions can be allowed to proceed rather |
| | 18871 | than halting before even getting to preconditions.) |
| | 18872 | |
| | 18873 | </div> |
| | 18874 | |
| | 18875 | <!-------------------> |
| | 18876 | <div class=entry> |
| | 18877 | |
| | 18878 | OutOfReach seems to put the object itself (not just its contents) out |
| | 18879 | of reach. Add a separate test for reaching 'self'. |
| | 18880 | |
| | 18881 | </div> |
| | 18882 | |
| | 18883 | <!-------------------> |
| | 18884 | <div class=entry> |
| | 18885 | |
| | 18886 | In Actor.canReach, don't make touching our immediate location a special |
| | 18887 | case - just traverse the sense path to the container as normal. |
| | 18888 | |
| | 18889 | </div> |
| | 18890 | |
| | 18891 | <!-------------------> |
| | 18892 | <div class=entry> |
| | 18893 | |
| | 18894 | <pre> |
| | 18895 | >look in stove |
| | 18896 | (First opening the stove) |
| | 18897 | Opening the stove reveals a loaf of bread. The stove contains a loaf of bread. |
| | 18898 | </pre> |
| | 18899 | <p> |
| | 18900 | It would be good to remove this redundancy: if we're opening |
| | 18901 | something implicitly for a look-in command, we shouldn't bother |
| | 18902 | showing what the opening reveals. (We can handle this in Openable's |
| | 18903 | Open action handler: if the action is implied, and the parent action |
| | 18904 | is LookIn with the same direct object, we can suppress the revelation |
| | 18905 | message.) |
| | 18906 | |
| | 18907 | </div> |
| | 18908 | |
| | 18909 | <!-------------------> |
| | 18910 | <div class=entry> |
| | 18911 | |
| | 18912 | Suppress default "you see nothing special about it" or "it's an |
| | 18913 | ordinary x" descriptions when there's a special status message, |
| | 18914 | such as contents to be listed. |
| | 18915 | |
| | 18916 | </div> |
| | 18917 | |
| | 18918 | <!-------------------> |
| | 18919 | <div class=entry> |
| | 18920 | |
| | 18921 | <pre> |
| | 18922 | >look in small alcove |
| | 18923 | You see nothing in it. A trophy is visible... |
| | 18924 | </pre> |
| | 18925 | <p> |
| | 18926 | (Perhaps if we special description items, and nothing listed, we should |
| | 18927 | display no message at all.) |
| | 18928 | |
| | 18929 | </div> |
| | 18930 | |
| | 18931 | <!-------------------> |
| | 18932 | <div class=entry> |
| | 18933 | |
| | 18934 | Use tags for line-input modes in commandSequencer, eliminating method |
| | 18935 | calls. This should remove the fragile order-of-call issues that we |
| | 18936 | currently have. |
| | 18937 | |
| | 18938 | </div> |
| | 18939 | |
| | 18940 | <!-------------------> |
| | 18941 | <div class=entry> |
| | 18942 | |
| | 18943 | Should we reformat some messages involving implied commands? For example: |
| | 18944 | |
| | 18945 | <p><pre> |
| | 18946 | >put coin in bag |
| | 18947 | (first opening the bag) |
| | 18948 | Opening the bag reveals a keyring. Done. |
| | 18949 | </pre> |
| | 18950 | <p> |
| | 18951 | Perhaps we should put that "done" on a new line - no paragraph separator, |
| | 18952 | just a new line. (In general, perhaps when there's a non-default response |
| | 18953 | from an implied command, we should add an "implied command terminator |
| | 18954 | separator," which by default would simply be a newline.) |
| | 18955 | |
| | 18956 | </div> |
| | 18957 | |
| | 18958 | <!-------------------> |
| | 18959 | <div class=entry> |
| | 18960 | |
| | 18961 | Rename the English-specific part of the library to make it easier to add |
| | 18962 | new languages in the future. In particular: |
| | 18963 | |
| | 18964 | <ul> |
| | 18965 | <li>Create a new US English subdirectory of the |
| | 18966 | adv3 library directory; use ISO 639/3166 codes for the naming |
| | 18967 | convention, so the US English directory is called en_us. |
| | 18968 | |
| | 18969 | <li>Move us_eng.t to en_us/en_us.t |
| | 18970 | |
| | 18971 | <li>Move us_eng.h to en_us/en_us.h |
| | 18972 | |
| | 18973 | <li>Move msg_neu.t to en_us/msg_neu.t |
| | 18974 | |
| | 18975 | <li>Add a new library, en_us/en_us.tl. Move the |
| | 18976 | English-specific source file inclusions out of adv3.tl and into |
| | 18977 | en_us.tl. |
| | 18978 | |
| | 18979 | <li>Include the new en_us.tl library in the |
| | 18980 | auto-generated makefile for the new-project wizard in Workbench. |
| | 18981 | (We'll have to add a user preference at some point that lets the user |
| | 18982 | select the language library to use, rather than using en_us.tl |
| | 18983 | unconditionally.) |
| | 18984 | </ul> |
| | 18985 | |
| | 18986 | </div> |
| | 18987 | |
| | 18988 | <!-------------------> |
| | 18989 | <div class=entry> |
| | 18990 | |
| | 18991 | Add a general IF instructions module (like instruct.t from tads 2) |
| | 18992 | |
| | 18993 | </div> |
| | 18994 | |
| | 18995 | <!-------------------> |
| | 18996 | <div class=entry> |
| | 18997 | |
| | 18998 | Fix nil dereference in transcript processing for ambiguous noun |
| | 18999 | phrase errors. |
| | 19000 | |
| | 19001 | </div> |
| | 19002 | |
| | 19003 | <!-------------------> |
| | 19004 | <div class=entry> |
| | 19005 | |
| | 19006 | Fix command state management for suffixes so that suffixes are always |
| | 19007 | generated before the prompt. (We simply need to display <.commandbegin> |
| | 19008 | in intput.t before displaying the prompt.) |
| | 19009 | |
| | 19010 | </div> |
| | 19011 | |
| | 19012 | <!-------------------> |
| | 19013 | <div class=entry> |
| | 19014 | |
| | 19015 | Add a new command state, stateNoCommand, for interactive input. In |
| | 19016 | this state, don't add any prefixes/separators/suffixes when reading |
| | 19017 | input. This should be used for yes/no answers, answers to |
| | 19018 | end-of-game prompts, and so forth - for anything where we need to |
| | 19019 | read input interactively in the course of a command. |
| | 19020 | |
| | 19021 | </div> |
| | 19022 | |
| | 19023 | <!-------------------> |
| | 19024 | <div class=entry> |
| | 19025 | |
| | 19026 | Move en_us.t Thing vocabulary initialization code to VocabObject. |
| | 19027 | |
| | 19028 | </div> |
| | 19029 | |
| | 19030 | <!-------------------> |
| | 19031 | <div class=entry> |
| | 19032 | |
| | 19033 | For commands like "put coin with jar," we're asking "what do you want |
| | 19034 | to put," which is a weird question. (This happens because we |
| | 19035 | interpret this as "put coin with jar in missing-np" and then resolve |
| | 19036 | the iobj first; this asks the usual question, which comes out the way |
| | 19037 | it does because the dobj tentatively resolves to an empty list since |
| | 19038 | it is a non-matching phrase. To solve this, we could use a dummy |
| | 19039 | entry in the tentative resolution list, to signal that we actually |
| | 19040 | have a dobj phrase, even if it's not resolvable to anything.) |
| | 19041 | |
| | 19042 | </div> |
| | 19043 | |
| | 19044 | <!-------------------> |
| | 19045 | <div class=entry> |
| | 19046 | |
| | 19047 | It might be nice to catch constructs like this: |
| | 19048 | |
| | 19049 | <p><pre> |
| | 19050 | >open door with key |
| | 19051 | You see no door with key here. |
| | 19052 | </pre> |
| | 19053 | <p> |
| | 19054 | In particular, it might be nice to recognize "<nounPhrase> <prep> |
| | 19055 | <nounPhrase>" constructs specifically, and flag them as "command not |
| | 19056 | understood" errors instead of "object not seen" errors. This could be |
| | 19057 | handled by adding a "badness" production for np-prep-np structures for |
| | 19058 | the prepositions commonly used in command phrases; by making this a |
| | 19059 | badness match, we'll match it as a last resort when we can't find a |
| | 19060 | valid verb phrase structure. |
| | 19061 | |
| | 19062 | </div> |
| | 19063 | |
| | 19064 | <!-------------------> |
| | 19065 | <div class=entry> |
| | 19066 | |
| | 19067 | Add an extra category of reports, "extraReport", that's used to add |
| | 19068 | extra information that doesn't replace any default report. Use this |
| | 19069 | for the key-found-on-keyring report, since this report is supplemental |
| | 19070 | to any default Locked/Unlocked report and shouldn't suppress it. |
| | 19071 | |
| | 19072 | </div> |
| | 19073 | |
| | 19074 | <!-------------------> |
| | 19075 | <div class=entry> |
| | 19076 | |
| | 19077 | Move the call to initializeVocab out of Thing.initializeThing, and |
| | 19078 | instead call initializeVocab directly from adv3LibPreinit.execute() |
| | 19079 | for each VocabObject. (This will initialize vocabulary for non-Thing |
| | 19080 | VocabObjects, such as Topic objects.) |
| | 19081 | |
| | 19082 | </div> |
| | 19083 | |
| | 19084 | <!-------------------> |
| | 19085 | <div class=entry> |
| | 19086 | |
| | 19087 | Add a new inputManager method, promptForMore(), that shows the MORE |
| | 19088 | prompt, taking care of flushing the transcript and dealing with the |
| | 19089 | real-time clock. The method should take an argument specifying |
| | 19090 | whether or not to freeze the real-time clock; but even if the clock |
| | 19091 | keeps running, real-time events shouldn't be allowed to occur until |
| | 19092 | after the user acknowledges the MORE prompt, because otherwise we'd |
| | 19093 | defeat the purpose of the MORE pause, which is to wait for user |
| | 19094 | acknowledgment before showing any new output. |
| | 19095 | |
| | 19096 | </div> |
| | 19097 | |
| | 19098 | <!-------------------> |
| | 19099 | <div class=entry> |
| | 19100 | |
| | 19101 | Change the Decoration class so that its generic not-important message |
| | 19102 | can be overridden simply by changing a property, rather than having |
| | 19103 | to override all of the Default handlers individually. |
| | 19104 | |
| | 19105 | <p> |
| | 19106 | Likewise for Distant and Intangible. |
| | 19107 | |
| | 19108 | </div> |
| | 19109 | |
| | 19110 | <!-------------------> |
| | 19111 | <div class=entry> |
| | 19112 | |
| | 19113 | Add a new 'isTopLevel' property, which determines if an object is a |
| | 19114 | top-level container within the game world. Set this to nil by |
| | 19115 | default for everything except Room objects, where we set it to true. |
| | 19116 | Use this property in evaluating isIn(nil): for an object with a nil |
| | 19117 | location, isIn(nil) returns true if and only if the object is NOT |
| | 19118 | top-level. This allows isIn(nil) to be used to sense whether or |
| | 19119 | not the object is part of the game world, recursively considering |
| | 19120 | the status of the object's containers. |
| | 19121 | |
| | 19122 | </div> |
| | 19123 | |
| | 19124 | <!-------------------> |
| | 19125 | <div class=entry> |
| | 19126 | |
| | 19127 | Remove selfInReach from OutOfReach. |
| | 19128 | |
| | 19129 | </div> |
| | 19130 | |
| | 19131 | <!-------------------> |
| | 19132 | <div class=entry> |
| | 19133 | |
| | 19134 | Fix problem with TravelConnector.verifyTravel(): when this routine is |
| | 19135 | called, gVerifyResults is not reliably set to a valid list. In |
| | 19136 | particular, gVerifyResults must be set to a valid result list from |
| | 19137 | TravelAction.verifyAction(). |
| | 19138 | |
| | 19139 | </div> |
| | 19140 | |
| | 19141 | <!-------------------> |
| | 19142 | <div class=entry> |
| | 19143 | |
| | 19144 | Turn on the sense cache while generating the status line. Displaying |
| | 19145 | the status line can involve some substantial sense calculations, so |
| | 19146 | enabling caching while generating it can improve overall response |
| | 19147 | time noticeably. |
| | 19148 | |
| | 19149 | </div> |
| | 19150 | |
| | 19151 | <!-------------------> |
| | 19152 | <div class=entry> |
| | 19153 | |
| | 19154 | Fix 'follow wall' (generates nil pointer error) |
| | 19155 | |
| | 19156 | </div> |
| | 19157 | |
| | 19158 | <!-------------------> |
| | 19159 | <div class=entry> |
| | 19160 | |
| | 19161 | Fix 'throw x at wall' (or floor or other room parts - nil pointer error) |
| | 19162 | |
| | 19163 | </div> |
| | 19164 | |
| | 19165 | <!-------------------> |
| | 19166 | <div class=entry> |
| | 19167 | |
| | 19168 | Fix nil pointer error when addressing an ambiguous target actor. |
| | 19169 | |
| | 19170 | </div> |
| | 19171 | |
| | 19172 | <!-------------------> |
| | 19173 | <div class=entry> |
| | 19174 | |
| | 19175 | <pre> |
| | 19176 | >sit on darker chair |
| | 19177 | >sit on chair |
| | 19178 | Which one? |
| | 19179 | >darker |
| | 19180 | </pre> |
| | 19181 | <p> |
| | 19182 | This is allowed, but shouldn't be - the reply should be "you're |
| | 19183 | already sitting on the darker chair." (The problem is that we verify |
| | 19184 | the lighter chair as okay, and we remember that we verified something |
| | 19185 | as okay but don't bother remembering what; we need to track which |
| | 19186 | objects we verify as okay individually.) |
| | 19187 | |
| | 19188 | </div> |
| | 19189 | |
| | 19190 | <!-------------------> |
| | 19191 | <div class=entry> |
| | 19192 | |
| | 19193 | Make searching a surface (or looking in a surface) show the surface's |
| | 19194 | contents. |
| | 19195 | |
| | 19196 | </div> |
| | 19197 | |
| | 19198 | <!-------------------> |
| | 19199 | <div class=entry> |
| | 19200 | |
| | 19201 | Check bulk when adding a new item to a surface. (This will fix the |
| | 19202 | weird inconsistency with chairs that allows you to put an object |
| | 19203 | on a chair you're sitting on, even if there's not room for you to |
| | 19204 | sit on the chair when the object is already on it.) |
| | 19205 | |
| | 19206 | </div> |
| | 19207 | |
| | 19208 | <!-------------------> |
| | 19209 | <div class=entry> |
| | 19210 | |
| | 19211 | Reduce the verification logical rank of non-Food objects for >TASTE. |
| | 19212 | |
| | 19213 | </div> |
| | 19214 | |
| | 19215 | <!-------------------> |
| | 19216 | <div class=entry> |
| | 19217 | |
| | 19218 | <pre> |
| | 19219 | >sit on chair |
| | 19220 | >look |
| | 19221 | ... You contain a keyring ... |
| | 19222 | </pre> |
| | 19223 | <p> |
| | 19224 | (We shouldn't mention your contents in that manner. The problem is |
| | 19225 | that Actor inherits contentsListed from Fixed; Actor should override |
| | 19226 | contentsListed and set it to nil, since an actor's contents shouldn't |
| | 19227 | be listed in the ordinary fashion in a room description.) |
| | 19228 | |
| | 19229 | </div> |
| | 19230 | |
| | 19231 | <!-------------------> |
| | 19232 | <div class=entry> |
| | 19233 | |
| | 19234 | Show object contents for EXAMINE and LOOK IN to full depth. |
| | 19235 | |
| | 19236 | </div> |
| | 19237 | |
| | 19238 | <!-------------------> |
| | 19239 | <div class=entry> |
| | 19240 | |
| | 19241 | Searching (or looking in) a room part shows contents as being "in" |
| | 19242 | it, which isn't appropriate for walls, ceilings, or floors. |
| | 19243 | |
| | 19244 | </div> |
| | 19245 | |
| | 19246 | <!-------------------> |
| | 19247 | <div class=entry> |
| | 19248 | |
| | 19249 | For THROW AT FLOOR, perhaps we should have a message other than |
| | 19250 | "Dropped" - something indicating the action is more violent than |
| | 19251 | just setting the object down. |
| | 19252 | |
| | 19253 | </div> |
| | 19254 | |
| | 19255 | <!-------------------> |
| | 19256 | <div class=entry> |
| | 19257 | |
| | 19258 | Make contents listings go to arbitrary depth. Rather than showing a |
| | 19259 | separate list for the contents of top-level list items, show the |
| | 19260 | contents of each item parenthetically, and then recursively add these |
| | 19261 | parenthetical lists to show all contents. (Only do this when the |
| | 19262 | ListRecurse flag is set.) |
| | 19263 | |
| | 19264 | <p> |
| | 19265 | Add a new Thing property, contentsListedSeparately, that allows an |
| | 19266 | object to control whether its contents are listed in the new in-line |
| | 19267 | style, or as the traditional separate list. Make this nil by default. |
| | 19268 | |
| | 19269 | </div> |
| | 19270 | |
| | 19271 | <!-------------------> |
| | 19272 | <div class=entry> |
| | 19273 | |
| | 19274 | For "tall" listings, show contents of unlisted top-level items in |
| | 19275 | separate lists after the main list, just as we do for "wide" listings. |
| | 19276 | |
| | 19277 | </div> |
| | 19278 | |
| | 19279 | <!-------------------> |
| | 19280 | <div class=entry> |
| | 19281 | |
| | 19282 | Remove the need to call showContentsList() separately after showList(); |
| | 19283 | instead, call this automatically from showList() if the ListRecurse |
| | 19284 | flag is set. |
| | 19285 | |
| | 19286 | </div> |
| | 19287 | |
| | 19288 | <!-------------------> |
| | 19289 | <div class=entry> |
| | 19290 | |
| | 19291 | Throwing destinations aren't working quite right. Refactor things a |
| | 19292 | bit: rename getFallDestination() to getHitFallDestination(), and give |
| | 19293 | it the previous container in the path as a parameter, so that it can |
| | 19294 | decide whether the object is being thrown from inside or outside (or, |
| | 19295 | in the case of a multi-location item, the source location). Make |
| | 19296 | things drop to the floor in most cases; games can override to make |
| | 19297 | things fall into intermediate containers when desired. |
| | 19298 | |
| | 19299 | </div> |
| | 19300 | |
| | 19301 | <!-------------------> |
| | 19302 | <div class=entry> |
| | 19303 | |
| | 19304 | Change Actor.standUp to use reportFailure() when already standing. |
| | 19305 | |
| | 19306 | </div> |
| | 19307 | |
| | 19308 | <!-------------------> |
| | 19309 | <div class=entry> |
| | 19310 | <p><pre> |
| | 19311 | >out |
| | 19312 | Out of what? |
| | 19313 | >e |
| | 19314 | You can't get out of that (the east wall). |
| | 19315 | </pre> |
| | 19316 | <p> |
| | 19317 | It would be nice to treat such responses as new commands. We could |
| | 19318 | probably adopt the heuristic that we give the new command |
| | 19319 | interpretation priority over the noun phrase interpretation of a reply |
| | 19320 | to this prompt. Anything that looks like both a syntactically valid |
| | 19321 | noun phrase and a syntactically valid command probably matches the |
| | 19322 | noun phrase syntax only because it's extremely abbreviated; the |
| | 19323 | chances of the verb phrase match being an accident are somewhat less. |
| | 19324 | In addition, it should be less confusing to the user to treat the |
| | 19325 | response as a new command when a noun phrase was intended than vice |
| | 19326 | versa, and it should be fairly obvious how to force a noun phrase |
| | 19327 | interpretation (adding "the" would do the trick, for example). |
| | 19328 | |
| | 19329 | </div> |
| | 19330 | |
| | 19331 | <!-------------------> |
| | 19332 | <div class=entry> |
| | 19333 | |
| | 19334 | Can we go to arbitrary depth for contentsListedSeparately? In particular: |
| | 19335 | |
| | 19336 | <p><pre> |
| | 19337 | >i |
| | 19338 | You are carrying a duffel bag (which contains a pen cup). The |
| | 19339 | pen cup contains four pens. |
| | 19340 | </pre> |
| | 19341 | <p> |
| | 19342 | Right now, we're not adding that bit about the pens, because we think |
| | 19343 | we're done with the top-level list, as we've already listed |
| | 19344 | everything: we scan the duffel, and decide that we don't need to |
| | 19345 | recurse into it, since it's listed and has in-line listed contents. |
| | 19346 | What we'd need to do is add another recursive descent to look for |
| | 19347 | everything that we listed at the second (or deeper) level that has |
| | 19348 | contentsListedSeparately. |
| | 19349 | |
| | 19350 | </div> |
| | 19351 | |
| | 19352 | <!-------------------> |
| | 19353 | <div class=entry> |
| | 19354 | |
| | 19355 | Tweak the parser's command match-tree ranking mechanism a little, so |
| | 19356 | that differences in the number of occurrences of a problem are counted |
| | 19357 | in a second pass, after we've exhausted the possibility of any |
| | 19358 | differences in the presence or absence of problems. This will make |
| | 19359 | slightly better choices in certain cases, such as when we have two |
| | 19360 | separate noun phrases in the action, and one interpretation treats |
| | 19361 | only one as ending in an adjective while the other has an adjective |
| | 19362 | ending in both phrases. |
| | 19363 | |
| | 19364 | </div> |
| | 19365 | |
| | 19366 | <!-------------------> |
| | 19367 | <div class=entry> |
| | 19368 | |
| | 19369 | Add a profiling facility, to gather statistics for performance |
| | 19370 | optimizations in the library. |
| | 19371 | |
| | 19372 | </div> |
| | 19373 | |
| | 19374 | <!-------------------> |
| | 19375 | <div class=entry> |
| | 19376 | |
| | 19377 | Rename senseInfoList to senseInfoTable, and make it return a |
| | 19378 | LookupTable rather than a list. Sense information lists are almost |
| | 19379 | always used as random-access tables, so we can speed up some |
| | 19380 | operations by representing these as lookup tables keyed on object. |
| | 19381 | |
| | 19382 | </div> |
| | 19383 | |
| | 19384 | <!-------------------> |
| | 19385 | <div class=entry> |
| | 19386 | |
| | 19387 | Rename connectionList to connectionTable, and make it return a |
| | 19388 | LookupTable rather than a list. Since we want only one copy of each |
| | 19389 | object in the result, it's faster to build this as a lookup table, |
| | 19390 | where we can determine whether or not an object is already present |
| | 19391 | much more quickly than we can with a vector. |
| | 19392 | |
| | 19393 | </div> |
| | 19394 | |
| | 19395 | <!-------------------> |
| | 19396 | <div class=entry> |
| | 19397 | |
| | 19398 | <pre> |
| | 19399 | >e |
| | 19400 | >put cup in desk |
| | 19401 | >undo |
| | 19402 | </pre> |
| | 19403 | <p> |
| | 19404 | (Takes back turns through "e". The problem is that we're marking a |
| | 19405 | remapped action as a nested action; it's not really nested, because |
| | 19406 | the original action is completely replaced and will never reach the |
| | 19407 | execution phase. Do not mark remapped actions as nested.) |
| | 19408 | |
| | 19409 | </div> |
| | 19410 | |
| | 19411 | <!-------------------> |
| | 19412 | <div class=entry> |
| | 19413 | |
| | 19414 | Add Thing.specialDescOrder to control specialDesc the relative order |
| | 19415 | of specialDesc listings. |
| | 19416 | |
| | 19417 | </div> |
| | 19418 | |
| | 19419 | <!-------------------> |
| | 19420 | <div class=entry> |
| | 19421 | |
| | 19422 | Change the format of the first-score-notification supplemental |
| | 19423 | message, which explains how to turn off score notifications: rather |
| | 19424 | than showing it as part of the same paragraph with the score, start a |
| | 19425 | new line and show it as a separate notification message. |
| | 19426 | |
| | 19427 | </div> |
| | 19428 | |
| | 19429 | <!-------------------> |
| | 19430 | <div class=entry> |
| | 19431 | |
| | 19432 | Rename UnqualifiedPluralProd to DefinitePluralProd. In the English |
| | 19433 | parser, base implicitDetPluralOnlyNounPhrase(main) and |
| | 19434 | explicitDetPluralNounPhrase(definite) on DefinitePluralProd, since |
| | 19435 | "books" and "the books" should act the same way in English. |
| | 19436 | |
| | 19437 | </div> |
| | 19438 | |
| | 19439 | <!-------------------> |
| | 19440 | <div class=entry> |
| | 19441 | |
| | 19442 | Simplify the Key and Keyring Attach and Detach handling by using |
| | 19443 | remapTo() in the keyring: remap "attach x to keyring" to "put x on |
| | 19444 | keyring" in Keyring.iobjFor(AttachTo), and remap "detach x from |
| | 19445 | keyring" to "take x from keyring" in Keyring.iobjFor(DetachFrom). |
| | 19446 | This removes a bunch of code from Key to handle the remapping at its |
| | 19447 | end - that code all predated the remap mechanism, and can now be |
| | 19448 | greatly simplified by using the new mechanism. |
| | 19449 | |
| | 19450 | </div> |
| | 19451 | |
| | 19452 | <!-------------------> |
| | 19453 | <div class=entry> |
| | 19454 | |
| | 19455 | Fix a problem in vocabulary initialization: if a hyphen is used as a |
| | 19456 | placeholder in a vocabWords_ setting, the hyphen is added to the |
| | 19457 | object's part-of-speech property (it's not added to the dictionary, |
| | 19458 | but it does show up in the list for the part-of-speech property). It |
| | 19459 | should be omitted from the list, since it's not really a vocabulary |
| | 19460 | word. |
| | 19461 | |
| | 19462 | </div> |
| | 19463 | |
| | 19464 | <!-------------------> |
| | 19465 | <div class=entry> |
| | 19466 | |
| | 19467 | Fix finishOptionUndo so that it can be used in daemons. This requires |
| | 19468 | a couple of changes. First, remove the transcript flush - this is a |
| | 19469 | relic of the pre-'transient' transcript mechanism and is no longer |
| | 19470 | needed. Second, daemons and fuses need to be able to use |
| | 19471 | TerminateCommandException and the like to exit, so we should catch |
| | 19472 | command-ending exceptions in the event manager. |
| | 19473 | |
| | 19474 | </div> |
| | 19475 | |
| | 19476 | <!-------------------> |
| | 19477 | <div class=entry> |
| | 19478 | |
| | 19479 | Fix examining sightSize=large objects at a distance. (The problem is |
| | 19480 | that Thing.canDetailsBeSensed() is attenuating the ambient light level |
| | 19481 | for the sense path, which is unnecessary as the SenseInfo already does |
| | 19482 | this. canDetailsBeSensed doesn't need to go to so much trouble - any |
| | 19483 | SenseInfo with trans != opaque indicates the object can be sensed, |
| | 19484 | since trans will always be set to opaque for objects that cannot be |
| | 19485 | sensed.) |
| | 19486 | |
| | 19487 | </div> |
| | 19488 | |
| | 19489 | <!-------------------> |
| | 19490 | <div class=entry> |
| | 19491 | |
| | 19492 | Add tok.t to system.tl. (This file isn't actually necessary to |
| | 19493 | compile a simple program, which is why it hasn't been in system.tl all |
| | 19494 | along; but it is necessary for any game based on the library, so on |
| | 19495 | balance it's probably better to include it in the default library. |
| | 19496 | |
| | 19497 | </div> |
| | 19498 | |
| | 19499 | <!-------------------> |
| | 19500 | <div class=entry> |
| | 19501 | |
| | 19502 | Separate some action-time checks into check() routines: |
| | 19503 | Container.dobjFor(LookIn); Dial.dobjFor(TurnTo) (this could perhaps |
| | 19504 | benefit from some 'verify' checking of the literal value as well). |
| | 19505 | |
| | 19506 | </div> |
| | 19507 | |
| | 19508 | <!-------------------> |
| | 19509 | <div class=entry> |
| | 19510 | |
| | 19511 | Add a specialDescLister, and use it for listing special descriptions. |
| | 19512 | Add a new property of Thing, specialDescListWith, which returns a list |
| | 19513 | group to use when showing special descriptions; use this new list |
| | 19514 | group generator in specialDescLister. This will allow special |
| | 19515 | descriptions to be grouped when desired, simply by using the standard |
| | 19516 | list grouping mechanism. |
| | 19517 | |
| | 19518 | </div> |
| | 19519 | |
| | 19520 | <!-------------------> |
| | 19521 | <div class=entry> |
| | 19522 | |
| | 19523 | Add an "isCircularPassage" property to TravelConnector: when this |
| | 19524 | property of the connector is true, fully describe travel that winds |
| | 19525 | up in the origin. (We normally don't bother describing such circular |
| | 19526 | trips, but sometimes it's desirable to be able to do so.) |
| | 19527 | |
| | 19528 | </div> |
| | 19529 | |
| | 19530 | <!-------------------> |
| | 19531 | <div class=entry> |
| | 19532 | |
| | 19533 | In en_us.t, add askDobjResponseProd=singleNoun for each action that |
| | 19534 | takes a singleDobj as its direct object. |
| | 19535 | |
| | 19536 | </div> |
| | 19537 | |
| | 19538 | <!-------------------> |
| | 19539 | <div class=entry> |
| | 19540 | |
| | 19541 | In en_us.t, remove the redundant syntax for "walk in/into" and "go |
| | 19542 | in/into" from VerbRule(GoThrough), as these are already handled by |
| | 19543 | VerbRule(Enter). |
| | 19544 | |
| | 19545 | </div> |
| | 19546 | |
| | 19547 | <!-------------------> |
| | 19548 | <div class=entry> |
| | 19549 | |
| | 19550 | In en_us.t, use <Q> tags wherever literal quotes are used, rather than |
| | 19551 | ASCII-34 quotes. |
| | 19552 | |
| | 19553 | </div> |
| | 19554 | |
| | 19555 | <!-------------------> |
| | 19556 | <div class=entry> |
| | 19557 | |
| | 19558 | Convert the parser to use the new Dictionary API. In the English |
| | 19559 | parser, install a StringComparator to perform case folding and |
| | 19560 | truncation matching. Remove case conversions from the English |
| | 19561 | tokenizer, as they're not needed with the StringComparator. |
| | 19562 | |
| | 19563 | </div> |
| | 19564 | |
| | 19565 | <!-------------------> |
| | 19566 | <div class=entry> |
| | 19567 | |
| | 19568 | Refactor the travel connector operations so that everything turns into |
| | 19569 | a TravelVia on its connector. Handle direction commands ("go north") |
| | 19570 | by using replaceAction(TravelVia, connector). This simplifies the |
| | 19571 | travel verbs, and makes the task of defining travel connectors more |
| | 19572 | consistent with defining other action handlers. |
| | 19573 | |
| | 19574 | </div> |
| | 19575 | |
| | 19576 | <!-------------------> |
| | 19577 | <div class=entry> |
| | 19578 | |
| | 19579 | Move the travel connector checks for dark-to-dark travel and for |
| | 19580 | travel barriers into the TravelVia check() handler. |
| | 19581 | |
| | 19582 | </div> |
| | 19583 | |
| | 19584 | <!-------------------> |
| | 19585 | <div class=entry> |
| | 19586 | |
| | 19587 | Rearrange the room description code (lookAroundPov, etc) so that |
| | 19588 | lookAround can be called on any object. To do this, move all of the |
| | 19589 | room description mechanism from BasicLocation into Thing, and work the |
| | 19590 | NestedRoom code into the Thing code for descriptions. |
| | 19591 | |
| | 19592 | </div> |
| | 19593 | |
| | 19594 | <!-------------------> |
| | 19595 | <div class=entry> |
| | 19596 | |
| | 19597 | Add a return value to basicEventManager.removeMatchingEvents, |
| | 19598 | indicating whether or not a matching event was actually found. |
| | 19599 | |
| | 19600 | </div> |
| | 19601 | |
| | 19602 | <!-------------------> |
| | 19603 | <div class=entry> |
| | 19604 | |
| | 19605 | Fix getTenativeLiteralText argument mismatches in parser.t when |
| | 19606 | calling getLiteralText. |
| | 19607 | |
| | 19608 | </div> |
| | 19609 | |
| | 19610 | <!-------------------> |
| | 19611 | <div class=entry> |
| | 19612 | |
| | 19613 | In MessageBuilder.generateMessage(), for the case where we're |
| | 19614 | substituting '{actor}' but there's no current action, use the current |
| | 19615 | gActor value if it's not nil, or gPlayerChar if gActor is nil (rather |
| | 19616 | than always using gPlayerChar - using gActor instead allows a daemon |
| | 19617 | or other non-action message producer to set gActor to indicate the |
| | 19618 | actor doing whatever it is that's generating the message). |
| | 19619 | |
| | 19620 | </div> |
| | 19621 | |
| | 19622 | <!-------------------> |
| | 19623 | <div class=entry> |
| | 19624 | |
| | 19625 | In Actor.addPendingAction() and addFirstPendingAction(), take |
| | 19626 | a resolved object list as the last varargs-list argument, and pass |
| | 19627 | it to the PendingCommandInfo constructor. |
| | 19628 | |
| | 19629 | </div> |
| | 19630 | |
| | 19631 | <!-------------------> |
| | 19632 | <div class=entry> |
| | 19633 | |
| | 19634 | Hide Fixed objects from "drop all". |
| | 19635 | |
| | 19636 | </div> |
| | 19637 | |
| | 19638 | <!-------------------> |
| | 19639 | <div class=entry> |
| | 19640 | |
| | 19641 | Add some more default verbs: CutWith, Kiss. |
| | 19642 | |
| | 19643 | </div> |
| | 19644 | |
| | 19645 | <!-------------------> |
| | 19646 | <div class=entry> |
| | 19647 | |
| | 19648 | Add RoomPart.isIn(). Consider a RoomPart to be within a given location |
| | 19649 | if its room part location is equal to or within the given location, or |
| | 19650 | the inherited isIn returns true. |
| | 19651 | |
| | 19652 | </div> |
| | 19653 | |
| | 19654 | <!-------------------> |
| | 19655 | <div class=entry> |
| | 19656 | |
| | 19657 | Add some more string-quoting styles to the English tokenizer: `like |
| | 19658 | this', and with typographical ("curly") single and double quotes |
| | 19659 | (\u2018 and \u2019 for single quotes, \u201c and \u201d for double). |
| | 19660 | |
| | 19661 | </div> |
| | 19662 | |
| | 19663 | <!-------------------> |
| | 19664 | <div class=entry> |
| | 19665 | |
| | 19666 | Add a quotedStringPhrase production type, for rules that explicitly |
| | 19667 | call for quoted strings (but not unquoted literal text). Use this |
| | 19668 | production to build the quoted string rule for literalPhrase. |
| | 19669 | |
| | 19670 | </div> |
| | 19671 | |
| | 19672 | <!-------------------> |
| | 19673 | <div class=entry> |
| | 19674 | |
| | 19675 | Add SAVE, RESTORE, and SCRIPT command variations that take quoted |
| | 19676 | strings giving the filenames to use. |
| | 19677 | |
| | 19678 | </div> |
| | 19679 | |
| | 19680 | <!-------------------> |
| | 19681 | <div class=entry> |
| | 19682 | |
| | 19683 | Traveler.travelTo in a daemon dereferences gAction - check to see if |
| | 19684 | gAction is nil, and skip that step if so. |
| | 19685 | |
| | 19686 | </div> |
| | 19687 | |
| | 19688 | <!-------------------> |
| | 19689 | <div class=entry> |
| | 19690 | |
| | 19691 | Change all uses of 'seen' to use the seenBy() and setSeenBy() methods. |
| | 19692 | Move these from BasicLocation into Thing so that all objects uses them |
| | 19693 | uniformly. |
| | 19694 | |
| | 19695 | </div> |
| | 19696 | |
| | 19697 | <!-------------------> |
| | 19698 | <div class=entry> |
| | 19699 | |
| | 19700 | Bug: TERSE mode doesn't show full descriptions on first entry. |
| | 19701 | |
| | 19702 | </div> |
| | 19703 | |
| | 19704 | <!-------------------> |
| | 19705 | <div class=entry> |
| | 19706 | |
| | 19707 | Some of the objects shown in the introductory room description aren't |
| | 19708 | getting marked as seen. (The problem is that Thing.lookAroundWithin |
| | 19709 | is using gActor in a few places where it should be using the 'actor' |
| | 19710 | parameter.) |
| | 19711 | |
| | 19712 | </div> |
| | 19713 | |
| | 19714 | <!-------------------> |
| | 19715 | <div class=entry> |
| | 19716 | |
| | 19717 | Bug: NoTravelMessage is commented as being an apparent connector, but |
| | 19718 | is implemented as a non-apparent connector. Leave the implementation |
| | 19719 | the way it is, but fix the comments, and add a new class that acts the |
| | 19720 | same as NoTravelMessage but has an apparent connector (call it |
| | 19721 | FakeConnector, perhaps). |
| | 19722 | |
| | 19723 | </div> |
| | 19724 | |
| | 19725 | <!-------------------> |
| | 19726 | <div class=entry> |
| | 19727 | |
| | 19728 | Rename LiteralAction to LiteralTAction. Add a new LiteralAction |
| | 19729 | class that takes only a literal phrase as its object (i.e., no other |
| | 19730 | direct object), for commands like "say random stuff". |
| | 19731 | |
| | 19732 | Note that DefineLiteralAction is likewise renamed to |
| | 19733 | DefineLiteralTAction, and we add a new DefineLiteralAction for |
| | 19734 | defining an action with only a literal phrase for its object. |
| | 19735 | |
| | 19736 | </div> |
| | 19737 | |
| | 19738 | <!-------------------> |
| | 19739 | <div class=entry> |
| | 19740 | |
| | 19741 | Add a PostUndoObject class, analogous to PostRestoreObject. |
| | 19742 | |
| | 19743 | </div> |
| | 19744 | |
| | 19745 | <!-------------------> |
| | 19746 | <div class=entry> |
| | 19747 | |
| | 19748 | Reduce parse rankings for pronoun phrases vs noun phrases: if a word |
| | 19749 | is explicitly defined as noun, it probably should be a stronger match |
| | 19750 | than a pronoun interpretation of the same word. |
| | 19751 | |
| | 19752 | </div> |
| | 19753 | |
| | 19754 | <!----------------------------------- 3.0.4 ---------------------------------> |
| | 19755 | <div class=sepbar><a name='304'></a>3.0.4 and earlier</div> |
| | 19756 | |
| | 19757 | <div class=firstentry> |
| | 19758 | |
| | 19759 | Consider this command: |
| | 19760 | |
| | 19761 | <p><pre> |
| | 19762 | >put ball in asdf |
| | 19763 | Which ball do you mean, the red ball, or the green ball? |
| | 19764 | |
| | 19765 | >red |
| | 19766 | The story doesn't know the word 'asdf'. |
| | 19767 | |
| | 19768 | >oops box |
| | 19769 | Which ball do you mean, the red ball, or the green ball? |
| | 19770 | </pre> |
| | 19771 | |
| | 19772 | <p> |
| | 19773 | The issue is that OOPS retries the entire command with an updated |
| | 19774 | token list, and as a result, the disambiguation work from the first |
| | 19775 | attempt at resolving the objects is lost for the second iteration. |
| | 19776 | The reparsing is necessary, since the corrected typo could change |
| | 19777 | the entire meaning of the command. |
| | 19778 | |
| | 19779 | <p> |
| | 19780 | One possible solution: add a resolution pass specifically to catch |
| | 19781 | unknown words. Don't do any other resolution on this pass - just |
| | 19782 | deal with unknown words. This would ensure that we process OOPS |
| | 19783 | before we ask any disambiguation questions. |
| | 19784 | |
| | 19785 | <p> |
| | 19786 | Another possibility: keep a set of answers to questions, and the |
| | 19787 | conditions under which the questions were asked. Clear the list |
| | 19788 | each time we start a new parsing from scratch, but let the list |
| | 19789 | survive if we reparse a token list. Whenever we're about to ask |
| | 19790 | a question, look to see if the same question has been asked with |
| | 19791 | the same conditions, and if so, reuse the same response. |
| | 19792 | |
| | 19793 | </div> |
| | 19794 | |
| | 19795 | <!-------------------> |
| | 19796 | <div class=entry> |
| | 19797 | |
| | 19798 | All |
| | 19799 | |
| | 19800 | </div> |
| | 19801 | |
| | 19802 | <!-------------------> |
| | 19803 | <div class=entry> |
| | 19804 | |
| | 19805 | Missing noun phrases: prompt for input when PC gave command |
| | 19806 | |
| | 19807 | </div> |
| | 19808 | |
| | 19809 | <!-------------------> |
| | 19810 | <div class=entry> |
| | 19811 | |
| | 19812 | Missing noun phrases: use a default when possible |
| | 19813 | |
| | 19814 | </div> |
| | 19815 | |
| | 19816 | <!-------------------> |
| | 19817 | <div class=entry> |
| | 19818 | |
| | 19819 | Object announcements: include a preposition when appropriate (announcing |
| | 19820 | indirect object, announcing direct object with verb taking a preposition: |
| | 19821 | ">dig \n (in the dirt)") |
| | 19822 | |
| | 19823 | </div> |
| | 19824 | |
| | 19825 | <!-------------------> |
| | 19826 | <div class=entry> |
| | 19827 | |
| | 19828 | Pronouns |
| | 19829 | |
| | 19830 | </div> |
| | 19831 | |
| | 19832 | <!-------------------> |
| | 19833 | <div class=entry> |
| | 19834 | |
| | 19835 | Again |
| | 19836 | |
| | 19837 | </div> |
| | 19838 | |
| | 19839 | <!-------------------> |
| | 19840 | <div class=entry> |
| | 19841 | |
| | 19842 | Again: should we use disambiguation information from past commands? |
| | 19843 | For example: |
| | 19844 | |
| | 19845 | <p><pr> |
| | 19846 | >take book |
| | 19847 | Which book do you mean, the red one, the blue one, or the green one? |
| | 19848 | |
| | 19849 | >blue |
| | 19850 | Taken. |
| | 19851 | |
| | 19852 | >g |
| | 19853 | </pre> |
| | 19854 | |
| | 19855 | <p> |
| | 19856 | Should this 'take blue book' or should it ask... |
| | 19857 | Which book do you mean, the blue one, or the green one? |
| | 19858 | |
| | 19859 | <p> |
| | 19860 | Right now we use the literal tokens from the original command, so we |
| | 19861 | ask the disambiguation question again. This is exactly what we want |
| | 19862 | in cases with indistinguishables: |
| | 19863 | |
| | 19864 | <p> |
| | 19865 | <pre> |
| | 19866 | You see five silver coins here. |
| | 19867 | >take coin |
| | 19868 | Taken. |
| | 19869 | >g |
| | 19870 | Taken. |
| | 19871 | </pre> |
| | 19872 | |
| | 19873 | <p> |
| | 19874 | But in cases where we have distinguishable objects, we probably want |
| | 19875 | the resolved objects, not the words. |
| | 19876 | |
| | 19877 | <p> |
| | 19878 | We probably want to distinguish this way: if we had indefinites or |
| | 19879 | indistinguishables, resolve again from the original text. Otherwise, |
| | 19880 | use the original resolution. |
| | 19881 | |
| | 19882 | </div> |
| | 19883 | |
| | 19884 | <!-------------------> |
| | 19885 | <div class=entry> |
| | 19886 | |
| | 19887 | disambiguation: we're not keeping the full list properly in cases of |
| | 19888 | indistinguishables: |
| | 19889 | |
| | 19890 | <p> |
| | 19891 | <pre> |
| | 19892 | >take coin |
| | 19893 | Which coin, a gold coin, or a silver coin? |
| | 19894 | |
| | 19895 | >coin |
| | 19896 | Which coin, the silver coin, or the gold coin? |
| | 19897 | </pre> |
| | 19898 | |
| | 19899 | <p> |
| | 19900 | The second time around, the cardinality of the full list should not change, |
| | 19901 | so we should be asking the same question as the first time. |
| | 19902 | |
| | 19903 | </div> |
| | 19904 | |
| | 19905 | <!-------------------> |
| | 19906 | <div class=entry> |
| | 19907 | |
| | 19908 | Preconditions |
| | 19909 | |
| | 19910 | </div> |
| | 19911 | |
| | 19912 | <!-------------------> |
| | 19913 | <div class=entry> |
| | 19914 | |
| | 19915 | We need 'touchDobj' and 'touchIobj' preconditions - use these for all |
| | 19916 | objects that require that the object be physically manipulated by the |
| | 19917 | actor but not necessarily held. These are required to deal with things |
| | 19918 | like the contents of a closed transparent container, where an object |
| | 19919 | can be in scope but cannot be manipulated. |
| | 19920 | |
| | 19921 | <p> |
| | 19922 | As part of this, we need to find a way to say what object blocks a |
| | 19923 | sense path opaquely, so that we can say why we can't touch something |
| | 19924 | that we can see. There are two main cases: containers are in the way, |
| | 19925 | and connectors are in the way. |
| | 19926 | |
| | 19927 | </div> |
| | 19928 | |
| | 19929 | <!-------------------> |
| | 19930 | <div class=entry> |
| | 19931 | |
| | 19932 | Bag of holding: when an actor's hands are full and the actor is trying |
| | 19933 | to take something, pick a held object and try to find a bag of holding |
| | 19934 | for it. First, check the object's preferredHolder property - this |
| | 19935 | gives an object or class that the object prefers as its bag of holding. |
| | 19936 | If the actor is holding such a holder, move the object to the holder. |
| | 19937 | If we can't find any affinity, look for any object the actor is holding |
| | 19938 | of the generic BagOfHolding class. |
| | 19939 | |
| | 19940 | <p> |
| | 19941 | Examples of specialized bags of holding: wallet, key ring, purse, duffel |
| | 19942 | bag. |
| | 19943 | |
| | 19944 | </div> |
| | 19945 | |
| | 19946 | <!-------------------> |
| | 19947 | <div class=entry> |
| | 19948 | |
| | 19949 | Formatting: where does the blank line come from before an implicit |
| | 19950 | message for a single command? |
| | 19951 | |
| | 19952 | </div> |
| | 19953 | |
| | 19954 | <!-------------------> |
| | 19955 | <div class=entry> |
| | 19956 | |
| | 19957 | use disambiguation filter even for indefinites, so we pick the best |
| | 19958 | possibility if there are objects of different likelihoods |
| | 19959 | |
| | 19960 | </div> |
| | 19961 | |
| | 19962 | <!-------------------> |
| | 19963 | <div class=entry> |
| | 19964 | |
| | 19965 | "The red one" should work for exclusion lists. It should probably also |
| | 19966 | work in general - although 'one' should bind more tightly to an actual |
| | 19967 | name, in the absence of a name it should serve as a generic noun. |
| | 19968 | |
| | 19969 | </div> |
| | 19970 | |
| | 19971 | <!-------------------> |
| | 19972 | <div class=entry> |
| | 19973 | |
| | 19974 | "drop coins" - should we consider only the ones we're carrying? In other |
| | 19975 | words, should we run verification and include only the logical ones? |
| | 19976 | Probably - if there are some logical and some not logical, apply the |
| | 19977 | command only to the logical ones; otherwise, apply the command to all |
| | 19978 | of them. |
| | 19979 | |
| | 19980 | </div> |
| | 19981 | |
| | 19982 | <!-------------------> |
| | 19983 | <div class=entry> |
| | 19984 | |
| | 19985 | "take both coins" - really wacky |
| | 19986 | |
| | 19987 | </div> |
| | 19988 | |
| | 19989 | <!-------------------> |
| | 19990 | <div class=entry> |
| | 19991 | |
| | 19992 | "take two gold" should work (i.e., quantified ending in adjective) |
| | 19993 | |
| | 19994 | </div> |
| | 19995 | |
| | 19996 | <!-------------------> |
| | 19997 | <div class=entry> |
| | 19998 | |
| | 19999 | consider: |
| | 20000 | |
| | 20001 | <p> |
| | 20002 | <pre> |
| | 20003 | >take both coins |
| | 20004 | Which two (of five gold coins or three silver coins) do you mean? |
| | 20005 | |
| | 20006 | >two gold |
| | 20007 | You don't see that many coins here. |
| | 20008 | </pre> |
| | 20009 | |
| | 20010 | <p> |
| | 20011 | The problem is that we disambiguate with the reduced match list. |
| | 20012 | |
| | 20013 | </div> |
| | 20014 | |
| | 20015 | <!-------------------> |
| | 20016 | <div class=entry> |
| | 20017 | |
| | 20018 | <pre> |
| | 20019 | >take coin |
| | 20020 | Which coin, gold, silver, or copper? |
| | 20021 | |
| | 20022 | >all but copper |
| | 20023 | </pre> |
| | 20024 | |
| | 20025 | <p> |
| | 20026 | no worky - might even be a gram prod bug, since we seem to have a weird |
| | 20027 | firstToken/lastToken value in these cases |
| | 20028 | |
| | 20029 | </div> |
| | 20030 | |
| | 20031 | <!-------------------> |
| | 20032 | <div class=entry> |
| | 20033 | |
| | 20034 | "take books except red" - disambiguation of the exclusion list should be |
| | 20035 | limited in scope to the resolved plural list. |
| | 20036 | |
| | 20037 | </div> |
| | 20038 | |
| | 20039 | <!-------------------> |
| | 20040 | <div class=entry> |
| | 20041 | |
| | 20042 | "take books except silver" - "You see no silver here" - this should |
| | 20043 | ignore the missing object. |
| | 20044 | |
| | 20045 | </div> |
| | 20046 | |
| | 20047 | <!-------------------> |
| | 20048 | <div class=entry> |
| | 20049 | |
| | 20050 | "take coins except copper" - the 'copper' should implicitly be plural |
| | 20051 | rather than indefinite so that we skip all of the copper coins if there |
| | 20052 | are several |
| | 20053 | |
| | 20054 | </div> |
| | 20055 | |
| | 20056 | <!-------------------> |
| | 20057 | <div class=entry> |
| | 20058 | |
| | 20059 | <pre> |
| | 20060 | >take gold coin, gold coin |
| | 20061 | gold coin: Taken. |
| | 20062 | gold coin: You're already carrying the gold coin. |
| | 20063 | </pre> |
| | 20064 | |
| | 20065 | <p> |
| | 20066 | When we have multiple equivalent items in scope, and we mention several |
| | 20067 | items in a list, we should pick separate equivalent instances for each |
| | 20068 | mention. |
| | 20069 | |
| | 20070 | <p> |
| | 20071 | This should apply to disambiguation responses, too: |
| | 20072 | |
| | 20073 | <p> |
| | 20074 | <pre> |
| | 20075 | >take coin |
| | 20076 | Which coin do you mean, a gold coin or a silver coin? |
| | 20077 | |
| | 20078 | >gold, gold |
| | 20079 | </pre> |
| | 20080 | |
| | 20081 | </div> |
| | 20082 | |
| | 20083 | <!-------------------> |
| | 20084 | <div class=entry> |
| | 20085 | |
| | 20086 | "take any ball except green" - takes the green if there's nothing else |
| | 20087 | left |
| | 20088 | |
| | 20089 | </div> |
| | 20090 | |
| | 20091 | <!-------------------> |
| | 20092 | <div class=entry> |
| | 20093 | |
| | 20094 | add verification for pre-conditions - objHeld, for example, would boost |
| | 20095 | the likelihood for a held object |
| | 20096 | |
| | 20097 | </div> |
| | 20098 | |
| | 20099 | <!-------------------> |
| | 20100 | <div class=entry> |
| | 20101 | |
| | 20102 | add the new pre-execution check as a separate phase (checkXxx?) |
| | 20103 | |
| | 20104 | </div> |
| | 20105 | |
| | 20106 | <!-------------------> |
| | 20107 | <div class=entry> |
| | 20108 | |
| | 20109 | output capturers - one at a time |
| | 20110 | |
| | 20111 | </div> |
| | 20112 | |
| | 20113 | <!-------------------> |
| | 20114 | <div class=entry> |
| | 20115 | |
| | 20116 | add object affinities for bag of holding |
| | 20117 | |
| | 20118 | </div> |
| | 20119 | |
| | 20120 | <!-------------------> |
| | 20121 | <div class=entry> |
| | 20122 | |
| | 20123 | key ring - not just a bag of holding, but automatically adds items |
| | 20124 | as they're picked up when the key ring is in inventory |
| | 20125 | |
| | 20126 | </div> |
| | 20127 | |
| | 20128 | <!-------------------> |
| | 20129 | <div class=entry> |
| | 20130 | |
| | 20131 | Key ring messages: we should check for a non-default report, and if there |
| | 20132 | is no non-default report we should include more details: "You take the |
| | 20133 | key and put it on the keyring." |
| | 20134 | |
| | 20135 | </div> |
| | 20136 | |
| | 20137 | <!-------------------> |
| | 20138 | <div class=entry> |
| | 20139 | |
| | 20140 | Probably should have an objDirectlyHeld precondition. This one would |
| | 20141 | be used for commands that physically move an object; objHeld would |
| | 20142 | continue to be used for commands that merely need to do something |
| | 20143 | with an object. So, "put x in y" would require that x is directly |
| | 20144 | held, while "unlock x with y" would only require that y be nominally |
| | 20145 | held. For objDirectlyHeld, we'll make the implicit command silent |
| | 20146 | if the object is being indirectly carried, so that we don't get weird |
| | 20147 | things like this: |
| | 20148 | |
| | 20149 | <p> |
| | 20150 | <pre> |
| | 20151 | >i |
| | 20152 | You are carrying a paper bag. The paper bag contains a key. |
| | 20153 | |
| | 20154 | >drop key |
| | 20155 | (First taking the key) |
| | 20156 | Dropped. |
| | 20157 | </pre> |
| | 20158 | |
| | 20159 | </div> |
| | 20160 | |
| | 20161 | <!-------------------> |
| | 20162 | <div class=entry> |
| | 20163 | |
| | 20164 | If there's no doXxx, fail verification with a generic Illogical('you |
| | 20165 | can\'t do that'). |
| | 20166 | |
| | 20167 | </div> |
| | 20168 | |
| | 20169 | <!-------------------> |
| | 20170 | <div class=entry> |
| | 20171 | |
| | 20172 | For travel: shouldn't we have a verify phase for moving the actor? |
| | 20173 | |
| | 20174 | </div> |
| | 20175 | |
| | 20176 | <!-------------------> |
| | 20177 | <div class=entry> |
| | 20178 | |
| | 20179 | need to export propNotDefined in a system file |
| | 20180 | |
| | 20181 | </div> |
| | 20182 | |
| | 20183 | <!-------------------> |
| | 20184 | <div class=entry> |
| | 20185 | |
| | 20186 | take key: if it started on the keyring, we should take it off the |
| | 20187 | keyring |
| | 20188 | |
| | 20189 | </div> |
| | 20190 | |
| | 20191 | <!-------------------> |
| | 20192 | <div class=entry> |
| | 20193 | |
| | 20194 | Travel connectors |
| | 20195 | |
| | 20196 | </div> |
| | 20197 | |
| | 20198 | <!-------------------> |
| | 20199 | <div class=entry> |
| | 20200 | |
| | 20201 | Fix 'i tall' listings to show contents with a better format |
| | 20202 | |
| | 20203 | </div> |
| | 20204 | |
| | 20205 | <!-------------------> |
| | 20206 | <div class=entry> |
| | 20207 | |
| | 20208 | Move senses to a separate module. |
| | 20209 | |
| | 20210 | </div> |
| | 20211 | |
| | 20212 | <!-------------------> |
| | 20213 | <div class=entry> |
| | 20214 | |
| | 20215 | <pre> |
| | 20216 | >get coin |
| | 20217 | Which coin, a gold coin, a copper coin, or a silver coin? |
| | 20218 | |
| | 20219 | >coin |
| | 20220 | Which coin, a copper coin, a silver coin, or a gold coin? |
| | 20221 | </pre> |
| | 20222 | |
| | 20223 | <p> |
| | 20224 | The re-ordering on the second round is weird - we should keep the order |
| | 20225 | stable if we can. |
| | 20226 | |
| | 20227 | </div> |
| | 20228 | |
| | 20229 | <!-------------------> |
| | 20230 | <div class=entry> |
| | 20231 | |
| | 20232 | <pre> |
| | 20233 | >get ball |
| | 20234 | Which ball, red or green? |
| | 20235 | |
| | 20236 | >blue |
| | 20237 | You don't see that here. |
| | 20238 | </pre> |
| | 20239 | |
| | 20240 | <p> |
| | 20241 | The error shouldn't be "you don't see that here" - it should be more |
| | 20242 | like "that's not one of the choices you were offered." However, it |
| | 20243 | would be better to widen the scope again to the real scope, rather |
| | 20244 | than failing. |
| | 20245 | |
| | 20246 | </div> |
| | 20247 | |
| | 20248 | <!-------------------> |
| | 20249 | <div class=entry> |
| | 20250 | |
| | 20251 | Add maxWeight and weight enforcement |
| | 20252 | |
| | 20253 | </div> |
| | 20254 | |
| | 20255 | <!-------------------> |
| | 20256 | <div class=entry> |
| | 20257 | |
| | 20258 | Move pre-conditions to the objects. Keep the verb preconditions as |
| | 20259 | well, but verb-specific pre-conditions should never mention the |
| | 20260 | objects. |
| | 20261 | |
| | 20262 | </div> |
| | 20263 | |
| | 20264 | <!-------------------> |
| | 20265 | <div class=entry> |
| | 20266 | |
| | 20267 | Mark objects for which we've displayed descriptions, for topic scoping |
| | 20268 | |
| | 20269 | </div> |
| | 20270 | |
| | 20271 | <!-------------------> |
| | 20272 | <div class=entry> |
| | 20273 | |
| | 20274 | Add "module ID" objects, for library extensions. The "credits" command |
| | 20275 | should run through the module ID's and show a credit for each one. |
| | 20276 | |
| | 20277 | </div> |
| | 20278 | |
| | 20279 | <!-------------------> |
| | 20280 | <div class=entry> |
| | 20281 | |
| | 20282 | Make styles into objects |
| | 20283 | |
| | 20284 | </div> |
| | 20285 | |
| | 20286 | <!-------------------> |
| | 20287 | <div class=entry> |
| | 20288 | |
| | 20289 | Fuses and daemons |
| | 20290 | |
| | 20291 | </div> |
| | 20292 | |
| | 20293 | <!-------------------> |
| | 20294 | <div class=entry> |
| | 20295 | |
| | 20296 | Need to apply logical tests again after running preconditions. (Try |
| | 20297 | this: "put rusty key on keyring" - it'll pick up the key for the |
| | 20298 | 'held' precondition, which will put the key on the keyring, but then |
| | 20299 | the explicit put-on-keyring command will succeed, which it shouldn't.) |
| | 20300 | |
| | 20301 | </div> |
| | 20302 | |
| | 20303 | <!-------------------> |
| | 20304 | <div class=entry> |
| | 20305 | |
| | 20306 | Generalize the showList mechanism to allow for other types of |
| | 20307 | hierarchies besides contents to be shown. Use the lister interface |
| | 20308 | to virtualize the hierarchy traversal. |
| | 20309 | |
| | 20310 | </div> |
| | 20311 | |
| | 20312 | <!-------------------> |
| | 20313 | <div class=entry> |
| | 20314 | |
| | 20315 | Use the generic showList mechanism for the full score lister, rather |
| | 20316 | than using a specialized lister that does essentially the same thing. |
| | 20317 | |
| | 20318 | </div> |
| | 20319 | |
| | 20320 | <!-------------------> |
| | 20321 | <div class=entry> |
| | 20322 | |
| | 20323 | Score change notifications: add daemon that senses score changes and |
| | 20324 | notifies between turns. |
| | 20325 | |
| | 20326 | </div> |
| | 20327 | |
| | 20328 | <!-------------------> |
| | 20329 | <div class=entry> |
| | 20330 | |
| | 20331 | Do not count the time taken for implicit commands. |
| | 20332 | |
| | 20333 | </div> |
| | 20334 | |
| | 20335 | <!-------------------> |
| | 20336 | <div class=entry> |
| | 20337 | |
| | 20338 | Add a "message generation context" that determines what is generating |
| | 20339 | messages. This object must be sensible to the player character for |
| | 20340 | messages to be generated. For convenience, define a callWithMessageContext |
| | 20341 | function that establishes the context, invokes a callback, then restores |
| | 20342 | the enclosing context. |
| | 20343 | |
| | 20344 | <p> |
| | 20345 | When establishing a new context, we check to see if the generator is in |
| | 20346 | scope in the given sense. If not, we hide messages; if so, we show |
| | 20347 | messages. |
| | 20348 | |
| | 20349 | <p> |
| | 20350 | A nested context should actually be considered a context switch, |
| | 20351 | because we don't want an enclosing hiding context to hide an enclosed |
| | 20352 | showing context. For example, if we are generating messages with |
| | 20353 | sight scope for Lloyd, and we have a nested context where Lloyd is |
| | 20354 | saying something and so we now are in hearing scope for Lloyd, we |
| | 20355 | want the nested context to show its messages if in fact Lloyd is in |
| | 20356 | hearing scope even if Lloyd is not in sight scope (maybe the player |
| | 20357 | character and Lloyd are in contact over a walkie-talkie). |
| | 20358 | |
| | 20359 | </div> |
| | 20360 | |
| | 20361 | <!-------------------> |
| | 20362 | <div class=entry> |
| | 20363 | |
| | 20364 | NPC messages: only show if NPC is in sight of PC (using message generation |
| | 20365 | context) |
| | 20366 | |
| | 20367 | </div> |
| | 20368 | |
| | 20369 | <!-------------------> |
| | 20370 | <div class=entry> |
| | 20371 | |
| | 20372 | Use message generation context for fuses and daemons. Allow events to |
| | 20373 | be created with a context object and sense object; whenever an event |
| | 20374 | is executed, establish the context for the duration of the event's |
| | 20375 | execution. |
| | 20376 | |
| | 20377 | </div> |
| | 20378 | |
| | 20379 | <!-------------------> |
| | 20380 | <div class=entry> |
| | 20381 | |
| | 20382 | try this: bob, n. z. s. / n. z |
| | 20383 | |
| | 20384 | <p> |
| | 20385 | We should see bob leaving on his third queued move, but we don't for |
| | 20386 | some reason. |
| | 20387 | |
| | 20388 | </div> |
| | 20389 | |
| | 20390 | <!-------------------> |
| | 20391 | <div class=entry> |
| | 20392 | |
| | 20393 | Do we really want to remove the objects directly involved in a command |
| | 20394 | from the beforeAction and afterAction processing? It seems like it's |
| | 20395 | an unnecessary inconsistency. |
| | 20396 | |
| | 20397 | </div> |
| | 20398 | |
| | 20399 | <!-------------------> |
| | 20400 | <div class=entry> |
| | 20401 | |
| | 20402 | Should consider directing report messages to the pc/npc message |
| | 20403 | objects. This would more readily allow separate messages for |
| | 20404 | reporting the results of pc and npc commands (for example, "Taken" vs |
| | 20405 | "Bob takes the book"). This is probably trivial, since we already |
| | 20406 | have the pc/npc message generator division anyway; we probably just |
| | 20407 | need to use it rather than verbMessages for generating report |
| | 20408 | messages. (If there's really a good reason to have a separate |
| | 20409 | verbMessage object, maybe we should have a per-actor verbMessages |
| | 20410 | object, the way we do with the default library messages generator.) |
| | 20411 | |
| | 20412 | </div> |
| | 20413 | |
| | 20414 | <!-------------------> |
| | 20415 | <div class=entry> |
| | 20416 | |
| | 20417 | Missing blank line between commands on parser failures: |
| | 20418 | |
| | 20419 | <p> |
| | 20420 | <pre> |
| | 20421 | >bob, n. get silver coin. |
| | 20422 | >n |
| | 20423 | </pre> |
| | 20424 | |
| | 20425 | </div> |
| | 20426 | |
| | 20427 | <!-------------------> |
| | 20428 | <div class=entry> |
| | 20429 | |
| | 20430 | In room descriptions, list actors separately. |
| | 20431 | |
| | 20432 | </div> |
| | 20433 | |
| | 20434 | <!-------------------> |
| | 20435 | <div class=entry> |
| | 20436 | |
| | 20437 | Don't let the room lister include actor inventory listings with the |
| | 20438 | main room contents listing. |
| | 20439 | |
| | 20440 | </div> |
| | 20441 | |
| | 20442 | <!-------------------> |
| | 20443 | <div class=entry> |
| | 20444 | |
| | 20445 | Footnote system |
| | 20446 | |
| | 20447 | </div> |
| | 20448 | |
| | 20449 | <!-------------------> |
| | 20450 | <div class=entry> |
| | 20451 | |
| | 20452 | Add an initExamineDesc, to parallel initDesc when an object is |
| | 20453 | in its initial position and is explicitly examined. |
| | 20454 | |
| | 20455 | </div> |
| | 20456 | |
| | 20457 | <!-------------------> |
| | 20458 | <div class=entry> |
| | 20459 | |
| | 20460 | Check changes in object bulks for effects on containers. If a |
| | 20461 | container doesn't allow a change in child bulk, fail the command |
| | 20462 | that attempted the change. (For example, in a stretchy bag, |
| | 20463 | putting a new object into the bag should be disallowed if doing |
| | 20464 | so would make expand the bag so much that the bag would be too |
| | 20465 | large for its own container.) |
| | 20466 | |
| | 20467 | </div> |
| | 20468 | |
| | 20469 | <!-------------------> |
| | 20470 | <div class=entry> |
| | 20471 | |
| | 20472 | Stretchy bags, that conform to their contents (in the sense that |
| | 20473 | the bulk changes according to its contents) |
| | 20474 | |
| | 20475 | </div> |
| | 20476 | |
| | 20477 | <!-------------------> |
| | 20478 | <div class=entry> |
| | 20479 | |
| | 20480 | Use normal command result reports (especially ReportFailure) in |
| | 20481 | precondition checks. |
| | 20482 | |
| | 20483 | </div> |
| | 20484 | |
| | 20485 | <!-------------------> |
| | 20486 | <div class=entry> |
| | 20487 | |
| | 20488 | For target of "put in", elevate likelihood for an item being held. |
| | 20489 | |
| | 20490 | </div> |
| | 20491 | |
| | 20492 | <!-------------------> |
| | 20493 | <div class=entry> |
| | 20494 | |
| | 20495 | implement save/restore |
| | 20496 | |
| | 20497 | </div> |
| | 20498 | |
| | 20499 | <!-------------------> |
| | 20500 | <div class=entry> |
| | 20501 | |
| | 20502 | implement restart |
| | 20503 | |
| | 20504 | </div> |
| | 20505 | |
| | 20506 | <!-------------------> |
| | 20507 | <div class=entry> |
| | 20508 | |
| | 20509 | implement undo |
| | 20510 | |
| | 20511 | </div> |
| | 20512 | |
| | 20513 | <!-------------------> |
| | 20514 | <div class=entry> |
| | 20515 | |
| | 20516 | For undoing commands to NPC's, show the NPC as part of the command |
| | 20517 | being undone: "undoing one command: bob, go north". |
| | 20518 | |
| | 20519 | </div> |
| | 20520 | |
| | 20521 | <!-------------------> |
| | 20522 | <div class=entry> |
| | 20523 | |
| | 20524 | Add '\{' and '\}' (push/pop formatter state) output sequences. |
| | 20525 | |
| | 20526 | </div> |
| | 20527 | |
| | 20528 | <!-------------------> |
| | 20529 | <div class=entry> |
| | 20530 | |
| | 20531 | Implicit commands should not set antecedents. |
| | 20532 | |
| | 20533 | </div> |
| | 20534 | |
| | 20535 | <!-------------------> |
| | 20536 | <div class=entry> |
| | 20537 | |
| | 20538 | "Take All" should include the non-fixed contents of fixed containers |
| | 20539 | and surfaces within the room. |
| | 20540 | |
| | 20541 | </div> |
| | 20542 | |
| | 20543 | <!-------------------> |
| | 20544 | <div class=entry> |
| | 20545 | |
| | 20546 | Status line |
| | 20547 | |
| | 20548 | </div> |
| | 20549 | |
| | 20550 | <!-------------------> |
| | 20551 | <div class=entry> |
| | 20552 | |
| | 20553 | Footnotes: add FOOTNOTE MEDIUM mode, which shows new footnote |
| | 20554 | references but hides references to footnotes that have already |
| | 20555 | been read. This helps cut down on unnecessary clutter, since |
| | 20556 | a footnote reference is unlikely to be of much interest once |
| | 20557 | it's been read, assuming that footnotes are always extra |
| | 20558 | information that isn't required to finish the game. |
| | 20559 | |
| | 20560 | </div> |
| | 20561 | |
| | 20562 | <!-------------------> |
| | 20563 | <div class=entry> |
| | 20564 | |
| | 20565 | Weird: |
| | 20566 | |
| | 20567 | <p> |
| | 20568 | <pre> |
| | 20569 | >get large red ball, small red ball and drop them |
| | 20570 | [works] |
| | 20571 | |
| | 20572 | >get asdf red ball, small red ball and drop them |
| | 20573 | Don't know the word 'asdf' |
| | 20574 | |
| | 20575 | >oops large |
| | 20576 | ...you see no drop them here |
| | 20577 | </pre> |
| | 20578 | |
| | 20579 | <p> |
| | 20580 | Why does it pick out the right interpretation normally but can't |
| | 20581 | on a token reparse? |
| | 20582 | |
| | 20583 | </div> |
| | 20584 | |
| | 20585 | <!-------------------> |
| | 20586 | <div class=entry> |
| | 20587 | |
| | 20588 | Add an "unobvious" verification mode that allows the command but will |
| | 20589 | not be accepted as a default. |
| | 20590 | |
| | 20591 | </div> |
| | 20592 | |
| | 20593 | <!-------------------> |
| | 20594 | <div class=entry> |
| | 20595 | |
| | 20596 | Decorations |
| | 20597 | |
| | 20598 | </div> |
| | 20599 | |
| | 20600 | <!-------------------> |
| | 20601 | <div class=entry> |
| | 20602 | |
| | 20603 | Add dobjCheck, iobjCheck, dobjGen, iobjGen equivalents |
| | 20604 | |
| | 20605 | </div> |
| | 20606 | |
| | 20607 | <!-------------------> |
| | 20608 | <div class=entry> |
| | 20609 | |
| | 20610 | Add a default mechanism for listing the inventory of an actor as |
| | 20611 | part of the actor's description. ("Bob is carrying...wearing..."). |
| | 20612 | |
| | 20613 | </div> |
| | 20614 | |
| | 20615 | <!-------------------> |
| | 20616 | <div class=entry> |
| | 20617 | |
| | 20618 | Add a sorter method to the list group object, for simple control over |
| | 20619 | the sorting order |
| | 20620 | |
| | 20621 | </div> |
| | 20622 | |
| | 20623 | <!-------------------> |
| | 20624 | <div class=entry> |
| | 20625 | |
| | 20626 | Add input font switch when reading a command |
| | 20627 | |
| | 20628 | </div> |
| | 20629 | |
| | 20630 | <!-------------------> |
| | 20631 | <div class=entry> |
| | 20632 | |
| | 20633 | When defaulting a direct object of a two-object command, include the |
| | 20634 | verb's participle form in the default message: |
| | 20635 | |
| | 20636 | <p> |
| | 20637 | <pre> |
| | 20638 | >ask about watch |
| | 20639 | (asking Bob) |
| | 20640 | </pre> |
| | 20641 | |
| | 20642 | <p> |
| | 20643 | Most default messages are meant to be tagged onto the end of the |
| | 20644 | command line, but when we're adding a direct object to a two-object |
| | 20645 | verb, the added object goes in the middle of the command and hence |
| | 20646 | the default phrase doesn't sound right when tagged onto the end of |
| | 20647 | the command line. By adding the participle form of the verb, we |
| | 20648 | make it clear that the default message stands alone as a new sentence |
| | 20649 | (or sentence fragment, anyway) and is not meant as a missing |
| | 20650 | continuation of the original command text. |
| | 20651 | |
| | 20652 | </div> |
| | 20653 | |
| | 20654 | <!-------------------> |
| | 20655 | <div class=entry> |
| | 20656 | |
| | 20657 | "show iron key" - since the missing phrase form of this command has |
| | 20658 | badness, this ends up being interpreted as "show key to iron", which |
| | 20659 | is silly. For command forms like this with two objects and no |
| | 20660 | preposition, we should probably add a non-badness single-object |
| | 20661 | grammar that asks for the missing prepositional phrase. How we |
| | 20662 | select the misisng-object phrasing over the two-object interpretation |
| | 20663 | is unclear, though. |
| | 20664 | |
| | 20665 | </div> |
| | 20666 | |
| | 20667 | <!-------------------> |
| | 20668 | <div class=entry> |
| | 20669 | |
| | 20670 | Parameterize the amount of time it takes for an actor to give an |
| | 20671 | order to another actor. |
| | 20672 | |
| | 20673 | </div> |
| | 20674 | |
| | 20675 | <!-------------------> |
| | 20676 | <div class=entry> |
| | 20677 | |
| | 20678 | try 'inflate raft and put it in bottle' - we don't get a blank line |
| | 20679 | before the 'put it in bottle' response, presumably because it has |
| | 20680 | an implicit command first |
| | 20681 | |
| | 20682 | </div> |
| | 20683 | |
| | 20684 | <!-------------------> |
| | 20685 | <div class=entry> |
| | 20686 | |
| | 20687 | Floor/ceiling/walls for indoor rooms, ground/sky for outdoor rooms |
| | 20688 | |
| | 20689 | </div> |
| | 20690 | |
| | 20691 | <!-------------------> |
| | 20692 | <div class=entry> |
| | 20693 | |
| | 20694 | Traverse the sense path for throwing an object at another object, and |
| | 20695 | make the projectile land in the appropriate place when an intervening |
| | 20696 | object prevents the throw from finishing. |
| | 20697 | |
| | 20698 | </div> |
| | 20699 | |
| | 20700 | <!-------------------> |
| | 20701 | <div class=entry> |
| | 20702 | |
| | 20703 | Keep track of multiple logical results, and make comparisons based on |
| | 20704 | the whole list. Distinguish different reasons (using 'key' values) |
| | 20705 | for different logical results with the same ranking. |
| | 20706 | |
| | 20707 | <p> |
| | 20708 | The idea is that if we have two objects that are both ranked the same |
| | 20709 | way on one axis but are distinguishable on another axis, we want to |
| | 20710 | consider the axis on which they're distinguishable. For example, if |
| | 20711 | we type "put silver coin in jar," and one jar is open and the other |
| | 20712 | is closed, we want to pick the one that's open. At the same time, |
| | 20713 | they'll both be ranked as equivalently logical on the basis that |
| | 20714 | neither is held by the actor. We don't want the being-held status to |
| | 20715 | override the open status, but we likewise don't want the open status |
| | 20716 | to override the being-held status if both are open but only one is |
| | 20717 | being held. The solution is to ignore the equivalent being-held |
| | 20718 | status when both objects have this same value, and to ignore the |
| | 20719 | equivalent open status when both have the same value, but still |
| | 20720 | consider these attributes when they differ. |
| | 20721 | |
| | 20722 | </div> |
| | 20723 | |
| | 20724 | <!-------------------> |
| | 20725 | <div class=entry> |
| | 20726 | |
| | 20727 | Provide suitable default implementations for about 1.0e+6 verbs |
| | 20728 | |
| | 20729 | </div> |
| | 20730 | |
| | 20731 | <!-------------------> |
| | 20732 | <div class=entry> |
| | 20733 | |
| | 20734 | "re-route" syntax - see, for example, keyring.iobjFor(AttachTo). |
| | 20735 | Use asDobjFor and asIobjFor: |
| | 20736 | |
| | 20737 | <p> |
| | 20738 | <pre> |
| | 20739 | iobjFor(AttachTo) asIobjFor(PutOn) |
| | 20740 | </pre> |
| | 20741 | |
| | 20742 | </div> |
| | 20743 | |
| | 20744 | <!-------------------> |
| | 20745 | <div class=entry> |
| | 20746 | |
| | 20747 | For travel: actorStanding pre-condition that automatically extricates |
| | 20748 | the actor from chairs and the like. We must catch dangerous conditions |
| | 20749 | in the verifier. |
| | 20750 | |
| | 20751 | </div> |
| | 20752 | |
| | 20753 | <!-------------------> |
| | 20754 | <div class=entry> |
| | 20755 | |
| | 20756 | For missing iobj's, allow preposition in response: |
| | 20757 | |
| | 20758 | <p> |
| | 20759 | <pre> |
| | 20760 | >dig in dirt |
| | 20761 | What do you want to dig in it with? |
| | 20762 | |
| | 20763 | >with shovel |
| | 20764 | </pre> |
| | 20765 | |
| | 20766 | </div> |
| | 20767 | |
| | 20768 | <!-------------------> |
| | 20769 | <div class=entry> |
| | 20770 | |
| | 20771 | Type/enter string/number on object |
| | 20772 | |
| | 20773 | </div> |
| | 20774 | |
| | 20775 | <!-------------------> |
| | 20776 | <div class=entry> |
| | 20777 | |
| | 20778 | Type/turn to unquoted string? |
| | 20779 | |
| | 20780 | </div> |
| | 20781 | |
| | 20782 | <!-------------------> |
| | 20783 | <div class=entry> |
| | 20784 | |
| | 20785 | In a two-object action, when assuming one object or the other, and |
| | 20786 | then asking for the other, we should show the defaulted one before |
| | 20787 | prompting: |
| | 20788 | |
| | 20789 | <p> |
| | 20790 | <pre> |
| | 20791 | >ask |
| | 20792 | (Bob) |
| | 20793 | What do you want to ask him about? |
| | 20794 | </pre> |
| | 20795 | |
| | 20796 | </div> |
| | 20797 | |
| | 20798 | <!-------------------> |
| | 20799 | <div class=entry> |
| | 20800 | |
| | 20801 | For disambiguation, never pick a 'not obvious' over an illogical, because |
| | 20802 | a 'not obvious' essentially counts as an illogical for the purposes of |
| | 20803 | picking objects. |
| | 20804 | |
| | 20805 | </div> |
| | 20806 | |
| | 20807 | <!-------------------> |
| | 20808 | <div class=entry> |
| | 20809 | |
| | 20810 | It might be good to eliminate the redundant default announcement in |
| | 20811 | cases like this: |
| | 20812 | |
| | 20813 | <p> |
| | 20814 | <pre> |
| | 20815 | >ask |
| | 20816 | (asking Bob) |
| | 20817 | What do you want to ask him about? |
| | 20818 | |
| | 20819 | >watch |
| | 20820 | (asking Bob) |
| | 20821 | </pre> |
| | 20822 | |
| | 20823 | </div> |
| | 20824 | |
| | 20825 | <!-------------------> |
| | 20826 | <div class=entry> |
| | 20827 | |
| | 20828 | It might be good to eliminate the participle when asking for a direct |
| | 20829 | object of a two-object verb and the indirect object is not yet known: |
| | 20830 | |
| | 20831 | <p> |
| | 20832 | <pre> |
| | 20833 | >ask |
| | 20834 | (asking Bob) |
| | 20835 | </pre> |
| | 20836 | |
| | 20837 | <p> |
| | 20838 | It would be better as simply |
| | 20839 | |
| | 20840 | <p> |
| | 20841 | <pre> |
| | 20842 | >ask |
| | 20843 | (Bob) |
| | 20844 | </pre> |
| | 20845 | |
| | 20846 | </div> |
| | 20847 | |
| | 20848 | <!-------------------> |
| | 20849 | <div class=entry> |
| | 20850 | |
| | 20851 | Turn x to string/number |
| | 20852 | |
| | 20853 | </div> |
| | 20854 | |
| | 20855 | <!-------------------> |
| | 20856 | <div class=entry> |
| | 20857 | |
| | 20858 | Dials (turn, turn to) |
| | 20859 | |
| | 20860 | </div> |
| | 20861 | |
| | 20862 | <!-------------------> |
| | 20863 | <div class=entry> |
| | 20864 | |
| | 20865 | Buttons (push) |
| | 20866 | |
| | 20867 | </div> |
| | 20868 | |
| | 20869 | <!-------------------> |
| | 20870 | <div class=entry> |
| | 20871 | |
| | 20872 | Switches (turn on, turn off) |
| | 20873 | |
| | 20874 | </div> |
| | 20875 | |
| | 20876 | <!-------------------> |
| | 20877 | <div class=entry> |
| | 20878 | |
| | 20879 | Levers (pull, push, move) |
| | 20880 | |
| | 20881 | </div> |
| | 20882 | |
| | 20883 | <!-------------------> |
| | 20884 | <div class=entry> |
| | 20885 | |
| | 20886 | Doors |
| | 20887 | |
| | 20888 | </div> |
| | 20889 | |
| | 20890 | <!-------------------> |
| | 20891 | <div class=entry> |
| | 20892 | |
| | 20893 | In the dark: should be able to list items you're holding by touch. |
| | 20894 | |
| | 20895 | </div> |
| | 20896 | |
| | 20897 | <!-------------------> |
| | 20898 | <div class=entry> |
| | 20899 | |
| | 20900 | In the dark, 'look at' should indicate that it's the darkness that |
| | 20901 | prevents an in-scope item from being inspected. |
| | 20902 | |
| | 20903 | </div> |
| | 20904 | |
| | 20905 | <!-------------------> |
| | 20906 | <div class=entry> |
| | 20907 | |
| | 20908 | In the dark, inventory should do something better than say "you're |
| | 20909 | empty-handed". |
| | 20910 | |
| | 20911 | </div> |
| | 20912 | |
| | 20913 | <!-------------------> |
| | 20914 | <div class=entry> |
| | 20915 | |
| | 20916 | Climbables (such as stairs). These should probably just be travel |
| | 20917 | connectors that go up and down. |
| | 20918 | |
| | 20919 | </div> |
| | 20920 | |
| | 20921 | <!-------------------> |
| | 20922 | <div class=entry> |
| | 20923 | |
| | 20924 | Check scope for preconditions - make sure we don't apply a command |
| | 20925 | to an object not in scope by way of a precondition implicit command. |
| | 20926 | For example, if you type "go north" in the dark, and there's a closed |
| | 20927 | door that you can't see, you shouldn't be able to open the door by |
| | 20928 | way of the travel precondition. |
| | 20929 | |
| | 20930 | </div> |
| | 20931 | |
| | 20932 | <!-------------------> |
| | 20933 | <div class=entry> |
| | 20934 | |
| | 20935 | <pre> |
| | 20936 | >go through passage |
| | 20937 | >again |
| | 20938 | </pre> |
| | 20939 | |
| | 20940 | <p> |
| | 20941 | This somehow keeps the old passage in scope. Must need to check |
| | 20942 | scope again for 'again'. |
| | 20943 | |
| | 20944 | <p> |
| | 20945 | (The problem is that the last action is hanging on to its cached |
| | 20946 | resolver scope lists. We simply need to drop the old resolvers |
| | 20947 | so that we start the new command with new resolvers.) |
| | 20948 | |
| | 20949 | </div> |
| | 20950 | |
| | 20951 | <!-------------------> |
| | 20952 | <div class=entry> |
| | 20953 | |
| | 20954 | climb up/climb down verbs |
| | 20955 | |
| | 20956 | </div> |
| | 20957 | |
| | 20958 | <!-------------------> |
| | 20959 | <div class=entry> |
| | 20960 | |
| | 20961 | make sure we have makeOpen, makeClosed, makeLocked, makeUnlocked, etc. - |
| | 20962 | in other words, encapsulate these types of state changes the same way |
| | 20963 | moveInto encapsulates containment changes |
| | 20964 | |
| | 20965 | </div> |
| | 20966 | |
| | 20967 | <!-------------------> |
| | 20968 | <div class=entry> |
| | 20969 | |
| | 20970 | Add an "inaccessible" verification failure - this would be more |
| | 20971 | disapproving than any "illogical" level and would be used for |
| | 20972 | "it's too dark" and "you can't reach that" types of failures. |
| | 20973 | |
| | 20974 | </div> |
| | 20975 | |
| | 20976 | <!-------------------> |
| | 20977 | <div class=entry> |
| | 20978 | |
| | 20979 | The pre-condition execution sequence should probably be like this: |
| | 20980 | |
| | 20981 | <p> |
| | 20982 | <pre> |
| | 20983 | for (pass = 1 ; pass <= 2 ; ++pass) |
| | 20984 | run all verifiers |
| | 20985 | for each precondition |
| | 20986 | run this precondition, allowing implicit commands on pass 1 ONLY |
| | 20987 | if no implicit commands were executed |
| | 20988 | break |
| | 20989 | </pre> |
| | 20990 | |
| | 20991 | <p> |
| | 20992 | This would ensure that side effects of an implicit command are re-tested |
| | 20993 | through previous preconditions. Each precondition would only be allowed |
| | 20994 | to run its implicit command on pass 1 because this would prevent |
| | 20995 | infinite loops from conflicting preconditions - on pass 2, if the |
| | 20996 | condition isn't met by now, we'll assume it's not going to be, so |
| | 20997 | we'll simply fail the command. |
| | 20998 | |
| | 20999 | </div> |
| | 21000 | |
| | 21001 | <!-------------------> |
| | 21002 | <div class=entry> |
| | 21003 | |
| | 21004 | "actor, give x to me" should be handled as though it were "ask actor |
| | 21005 | for x", via a replacement command. |
| | 21006 | |
| | 21007 | </div> |
| | 21008 | |
| | 21009 | <!-------------------> |
| | 21010 | <div class=entry> |
| | 21011 | |
| | 21012 | actors: shouldn't allow taking possessions in general |
| | 21013 | |
| | 21014 | </div> |
| | 21015 | |
| | 21016 | <!-------------------> |
| | 21017 | <div class=entry> |
| | 21018 | |
| | 21019 | Dark rooms: limit travel to adjacent lit locations? |
| | 21020 | |
| | 21021 | </div> |
| | 21022 | |
| | 21023 | <!-------------------> |
| | 21024 | <div class=entry> |
| | 21025 | |
| | 21026 | Explicitly inherit base class vocabWords_ in initializeVocab() in |
| | 21027 | us_eng.t. |
| | 21028 | |
| | 21029 | </div> |
| | 21030 | |
| | 21031 | <!-------------------> |
| | 21032 | <div class=entry> |
| | 21033 | |
| | 21034 | touch/feel verbs |
| | 21035 | |
| | 21036 | </div> |
| | 21037 | |
| | 21038 | <!-------------------> |
| | 21039 | <div class=entry> |
| | 21040 | |
| | 21041 | Add verb "listen" (both transitive and intransitive) |
| | 21042 | |
| | 21043 | </div> |
| | 21044 | |
| | 21045 | <!-------------------> |
| | 21046 | <div class=entry> |
| | 21047 | |
| | 21048 | Add verb "smell" (transitive and intransitive) |
| | 21049 | |
| | 21050 | </div> |
| | 21051 | |
| | 21052 | <!-------------------> |
| | 21053 | <div class=entry> |
| | 21054 | |
| | 21055 | Enterables |
| | 21056 | |
| | 21057 | </div> |
| | 21058 | |
| | 21059 | <!-------------------> |
| | 21060 | <div class=entry> |
| | 21061 | |
| | 21062 | keys and doors: add options for boosting likelihood for keys: |
| | 21063 | |
| | 21064 | <ul> |
| | 21065 | <li> |
| | 21066 | on the first successful use of a key, automatically boost the |
| | 21067 | likelihood for future disambiguation using the key if an option is |
| | 21068 | set (this might be the default option) |
| | 21069 | |
| | 21070 | <li> |
| | 21071 | if the author wants the player character to know from the outset |
| | 21072 | which key goes with a door, the author can add the key to the |
| | 21073 | lockable's knownKeyList - this can be useful for games with obvious |
| | 21074 | key associations or key associations known from the outset to the |
| | 21075 | player character (for example, if the PC has a key to their own |
| | 21076 | house, the ought to know what the key opens) |
| | 21077 | </ul> |
| | 21078 | |
| | 21079 | </div> |
| | 21080 | |
| | 21081 | <!-------------------> |
| | 21082 | <div class=entry> |
| | 21083 | |
| | 21084 | locks and keys |
| | 21085 | |
| | 21086 | </div> |
| | 21087 | |
| | 21088 | <!-------------------> |
| | 21089 | <div class=entry> |
| | 21090 | |
| | 21091 | lockable doors |
| | 21092 | |
| | 21093 | </div> |
| | 21094 | |
| | 21095 | <!-------------------> |
| | 21096 | <div class=entry> |
| | 21097 | |
| | 21098 | Automatic key rings for unlocking doors - an "unlock" command with no |
| | 21099 | indirect object automatically searches for a keyring in the actor's |
| | 21100 | inventory, and automatically searches for a key on the keyring. |
| | 21101 | |
| | 21102 | </div> |
| | 21103 | |
| | 21104 | <!-------------------> |
| | 21105 | <div class=entry> |
| | 21106 | |
| | 21107 | keyring: need to implicitly take keyring if not held when trying it |
| | 21108 | |
| | 21109 | </div> |
| | 21110 | |
| | 21111 | <!-------------------> |
| | 21112 | <div class=entry> |
| | 21113 | |
| | 21114 | keyrings: message on success should be something like: |
| | 21115 | |
| | 21116 | <p> |
| | 21117 | (trying each key on the keyring, you find that the iron key unlocks the door) |
| | 21118 | |
| | 21119 | </div> |
| | 21120 | |
| | 21121 | <!-------------------> |
| | 21122 | <div class=entry> |
| | 21123 | |
| | 21124 | keyring search: when we already know the correct key, we should just |
| | 21125 | default it rather than search the keyring for it |
| | 21126 | |
| | 21127 | </div> |
| | 21128 | |
| | 21129 | <!-------------------> |
| | 21130 | <div class=entry> |
| | 21131 | |
| | 21132 | implicit commands that use 'replace' should inherit original implicit |
| | 21133 | status (try 's' from the stair bottom - we get an "unlocked" report |
| | 21134 | for the replaced 'unlock door' command) |
| | 21135 | |
| | 21136 | </div> |
| | 21137 | |
| | 21138 | <!-------------------> |
| | 21139 | <div class=entry> |
| | 21140 | |
| | 21141 | For Fixed, indirect the illogical messages through properties, to |
| | 21142 | allow easier customization. |
| | 21143 | |
| | 21144 | </div> |
| | 21145 | |
| | 21146 | <!-------------------> |
| | 21147 | <div class=entry> |
| | 21148 | |
| | 21149 | Whenever any message appears before a room description in a command |
| | 21150 | sequence, show a blank line before the room description. This applies |
| | 21151 | especially to travel, but is generally desirable for any command that |
| | 21152 | shows a room description. |
| | 21153 | |
| | 21154 | </div> |
| | 21155 | |
| | 21156 | <!-------------------> |
| | 21157 | <div class=entry> |
| | 21158 | |
| | 21159 | Put iron key in duffel; unlock iron door - won't default the iron |
| | 21160 | key, because the keyring takes precedence by virtue of being held. |
| | 21161 | |
| | 21162 | <p> |
| | 21163 | The problem is that the objHeld precondition is applying a likelihood |
| | 21164 | of 80 because the iron key isn't held, and the held keys are getting |
| | 21165 | 100's. Maybe we need to reduce the likelihood of any other keys or |
| | 21166 | keyrings when the known key is present, but this seems like a poor |
| | 21167 | special-case hack for a problem that is likely to arise in other |
| | 21168 | contexts. |
| | 21169 | |
| | 21170 | <p> |
| | 21171 | To solve this, add a 'priority' to logical results. Use low priority |
| | 21172 | for precondition rankings, because these are inherently of lower |
| | 21173 | importance than unique attributes of the objects themselves. |
| | 21174 | |
| | 21175 | </div> |
| | 21176 | |
| | 21177 | <!-------------------> |
| | 21178 | <div class=entry> |
| | 21179 | |
| | 21180 | Add an 'exit only passage' to be used as the receiving end of things |
| | 21181 | like trap doors, chutes, and so on. |
| | 21182 | |
| | 21183 | </div> |
| | 21184 | |
| | 21185 | <!-------------------> |
| | 21186 | <div class=entry> |
| | 21187 | |
| | 21188 | Message travel connectors: simple connector that shows a message as the |
| | 21189 | connector is traversed. |
| | 21190 | |
| | 21191 | </div> |
| | 21192 | |
| | 21193 | <!-------------------> |
| | 21194 | <div class=entry> |
| | 21195 | |
| | 21196 | preserve the case of tokens in literal phrases |
| | 21197 | |
| | 21198 | </div> |
| | 21199 | |
| | 21200 | <!-------------------> |
| | 21201 | <div class=entry> |
| | 21202 | |
| | 21203 | Light/dark changes should be noted at the end of each turn. |
| | 21204 | |
| | 21205 | </div> |
| | 21206 | |
| | 21207 | <!-------------------> |
| | 21208 | <div class=entry> |
| | 21209 | |
| | 21210 | Light/dark changes should be noted before/after each daemon is |
| | 21211 | dispatched. |
| | 21212 | |
| | 21213 | </div> |
| | 21214 | |
| | 21215 | <!-------------------> |
| | 21216 | <div class=entry> |
| | 21217 | |
| | 21218 | |
| | 21219 | <pre> |
| | 21220 | >move me to |
| | 21221 | What do you want to move it to? |
| | 21222 | </pre> |
| | 21223 | |
| | 21224 | <p> |
| | 21225 | Could we substitute "yourself" for "it" somehow? |
| | 21226 | |
| | 21227 | </div> |
| | 21228 | |
| | 21229 | <!-------------------> |
| | 21230 | <div class=entry> |
| | 21231 | |
| | 21232 | Trap doors - in particular, the arrival message should indicate that the |
| | 21233 | trap door automatically slams shut after the actor arrives. |
| | 21234 | |
| | 21235 | </div> |
| | 21236 | |
| | 21237 | <!-------------------> |
| | 21238 | <div class=entry> |
| | 21239 | |
| | 21240 | Possessives - "take his box", "take bob's box" |
| | 21241 | |
| | 21242 | </div> |
| | 21243 | |
| | 21244 | <!-------------------> |
| | 21245 | <div class=entry> |
| | 21246 | |
| | 21247 | possessives - problem with disambig: |
| | 21248 | |
| | 21249 | <p> |
| | 21250 | <pre> |
| | 21251 | >get key's jar |
| | 21252 | Which key's do you mean... |
| | 21253 | </pre> |
| | 21254 | |
| | 21255 | <p> |
| | 21256 | That should just be 'which key do you mean', not 'which KEY'S' |
| | 21257 | |
| | 21258 | </div> |
| | 21259 | |
| | 21260 | <!-------------------> |
| | 21261 | <div class=entry> |
| | 21262 | |
| | 21263 | possessives - plurals |
| | 21264 | |
| | 21265 | </div> |
| | 21266 | |
| | 21267 | <!-------------------> |
| | 21268 | <div class=entry> |
| | 21269 | |
| | 21270 | possessives - five of bob's keys |
| | 21271 | |
| | 21272 | </div> |
| | 21273 | |
| | 21274 | <!-------------------> |
| | 21275 | <div class=entry> |
| | 21276 | |
| | 21277 | possessives - bob's keys except the green one |
| | 21278 | |
| | 21279 | </div> |
| | 21280 | |
| | 21281 | <!-------------------> |
| | 21282 | <div class=entry> |
| | 21283 | |
| | 21284 | get all of bob's keys except the rusty and iron ones - even when this |
| | 21285 | is just one key, we should announce it as though it were a multiple |
| | 21286 | object (so we need to set some flag) |
| | 21287 | |
| | 21288 | </div> |
| | 21289 | |
| | 21290 | <!-------------------> |
| | 21291 | <div class=entry> |
| | 21292 | |
| | 21293 | possessives: |
| | 21294 | |
| | 21295 | <p> |
| | 21296 | <pre> |
| | 21297 | >bob's |
| | 21298 | unknown word ''s' |
| | 21299 | </pre> |
| | 21300 | |
| | 21301 | </div> |
| | 21302 | |
| | 21303 | <!-------------------> |
| | 21304 | <div class=entry> |
| | 21305 | |
| | 21306 | possessives - problem with disambig: |
| | 21307 | |
| | 21308 | <p> |
| | 21309 | <pre> |
| | 21310 | >get key |
| | 21311 | Which key do you mean... |
| | 21312 | |
| | 21313 | >get bob's key |
| | 21314 | The word ''s' is not necessary... |
| | 21315 | </pre> |
| | 21316 | |
| | 21317 | <p> |
| | 21318 | The problem would seem to be that we don't handle 's in disambig |
| | 21319 | responses and treat it as an unknown word. |
| | 21320 | |
| | 21321 | </div> |
| | 21322 | |
| | 21323 | <!-------------------> |
| | 21324 | <div class=entry> |
| | 21325 | |
| | 21326 | <pre> |
| | 21327 | >look under me |
| | 21328 | You see nothing unusual under you. |
| | 21329 | </pre> |
| | 21330 | |
| | 21331 | <p> |
| | 21332 | We should make that second 'you' into 'yourself' instead. In general, |
| | 21333 | can we change an objective case use of an object already used in the |
| | 21334 | nominative should to a reflexive instead? |
| | 21335 | |
| | 21336 | </div> |
| | 21337 | |
| | 21338 | <!-------------------> |
| | 21339 | <div class=entry> |
| | 21340 | |
| | 21341 | possessives - disambig response should allow 'bob's' as a choice, |
| | 21342 | even if it's not offered |
| | 21343 | |
| | 21344 | </div> |
| | 21345 | |
| | 21346 | <!-------------------> |
| | 21347 | <div class=entry> |
| | 21348 | |
| | 21349 | possessives - "get keys except bob's" - need special grammar for |
| | 21350 | just a possessive in this context |
| | 21351 | |
| | 21352 | </div> |
| | 21353 | |
| | 21354 | <!-------------------> |
| | 21355 | <div class=entry> |
| | 21356 | |
| | 21357 | <pre> |
| | 21358 | >bob, x key |
| | 21359 | Which key? |
| | 21360 | |
| | 21361 | >quit |
| | 21362 | This command cannot be directed to another character... |
| | 21363 | </pre> |
| | 21364 | |
| | 21365 | </div> |
| | 21366 | |
| | 21367 | <!-------------------> |
| | 21368 | <div class=entry> |
| | 21369 | |
| | 21370 | Distant items |
| | 21371 | |
| | 21372 | </div> |
| | 21373 | |
| | 21374 | <!-------------------> |
| | 21375 | <div class=entry> |
| | 21376 | |
| | 21377 | Finish topic-verb implementation |
| | 21378 | |
| | 21379 | </div> |
| | 21380 | |
| | 21381 | <!-------------------> |
| | 21382 | <div class=entry> |
| | 21383 | |
| | 21384 | Consider: |
| | 21385 | |
| | 21386 | <p> |
| | 21387 | <pre> |
| | 21388 | >lock door |
| | 21389 | (first closing the iron door) |
| | 21390 | (with the iron key) |
| | 21391 | Locked. |
| | 21392 | </pre> |
| | 21393 | |
| | 21394 | <p> |
| | 21395 | The defaulted indirect object is misleading. This should instead be: |
| | 21396 | |
| | 21397 | <p> |
| | 21398 | <pre> |
| | 21399 | >lock door |
| | 21400 | (with the iron key) |
| | 21401 | (first closing the iron door) |
| | 21402 | Locked. |
| | 21403 | </pre> |
| | 21404 | |
| | 21405 | <p> |
| | 21406 | The problem comes from the fact that "Lock" has an objClosed |
| | 21407 | precondition for keyed lockable; "Lock" doesn't need this |
| | 21408 | precondition, because "LockWith" has it. Removing the precondition |
| | 21409 | will get the ordering right. |
| | 21410 | |
| | 21411 | </div> |
| | 21412 | |
| | 21413 | <!-------------------> |
| | 21414 | <div class=entry> |
| | 21415 | |
| | 21416 | truncated adjectives seem worse than unknowns in ranking: |
| | 21417 | |
| | 21418 | <p> |
| | 21419 | <pre> |
| | 21420 | >type hello on typewri |
| | 21421 | </pre> |
| | 21422 | |
| | 21423 | </div> |
| | 21424 | |
| | 21425 | <!-------------------> |
| | 21426 | <div class=entry> |
| | 21427 | |
| | 21428 | do not filter the 'all' list with hideFromAll when looking for default |
| | 21429 | objects |
| | 21430 | |
| | 21431 | </div> |
| | 21432 | |
| | 21433 | <!-------------------> |
| | 21434 | <div class=entry> |
| | 21435 | |
| | 21436 | <pre> |
| | 21437 | >get iron key |
| | 21438 | You take the key and attach it to the keyring |
| | 21439 | |
| | 21440 | >get keys |
| | 21441 | brass key: You take and attach... |
| | 21442 | rusty key: You take and attach... |
| | 21443 | iron key: Taken. |
| | 21444 | </pre> |
| | 21445 | |
| | 21446 | <p> |
| | 21447 | It's irritating that the last one is taken off the keyring. Should |
| | 21448 | we leave items out of plurals when we have multiple logical items of |
| | 21449 | different logicalness? (This isn't a completely academic problem, |
| | 21450 | since you could in practice have a couple of new keys in a room that |
| | 21451 | you want to pick up, without detaching keys you already have on the |
| | 21452 | keyring. One easy way to solve this would be to use a different |
| | 21453 | command for detaching from the keyring - require 'take key off |
| | 21454 | keyring', and say Illogical('if you want to take the key off the |
| | 21455 | keyring, say so'); but this could be irritating when you just want to |
| | 21456 | take the key off the keyring. |
| | 21457 | |
| | 21458 | </div> |
| | 21459 | |
| | 21460 | <!-------------------> |
| | 21461 | <div class=entry> |
| | 21462 | |
| | 21463 | follow: should replace command with actual command used for last |
| | 21464 | observed travel; alternatively, reproduce the preconditions and |
| | 21465 | verification for the travel via the connector |
| | 21466 | |
| | 21467 | </div> |
| | 21468 | |
| | 21469 | <!-------------------> |
| | 21470 | <div class=entry> |
| | 21471 | |
| | 21472 | Player character vocabulary - either add switchPlayer to fiddle with |
| | 21473 | the dictionary, or have some other way to route 'me' and 'my' to the |
| | 21474 | current player character (using matchName, for example). |
| | 21475 | |
| | 21476 | </div> |
| | 21477 | |
| | 21478 | <!-------------------> |
| | 21479 | <div class=entry> |
| | 21480 | |
| | 21481 | Move travel preconditions into the connectors after all. Just create |
| | 21482 | an openDoor precondition type that is instantiated with a specific |
| | 21483 | door to open, rather than attaching it to a command object. |
| | 21484 | |
| | 21485 | </div> |
| | 21486 | |
| | 21487 | <!-------------------> |
| | 21488 | <div class=entry> |
| | 21489 | |
| | 21490 | send bob into dark. follow bob into dark, then: |
| | 21491 | |
| | 21492 | <p> |
| | 21493 | <pre> |
| | 21494 | >follow bob |
| | 21495 | Bob is right here. |
| | 21496 | |
| | 21497 | >bob, u |
| | 21498 | You see no bob here. |
| | 21499 | </pre> |
| | 21500 | |
| | 21501 | </div> |
| | 21502 | |
| | 21503 | <!-------------------> |
| | 21504 | <div class=entry> |
| | 21505 | |
| | 21506 | <pre> |
| | 21507 | >bob, n |
| | 21508 | >g |
| | 21509 | </pre> |
| | 21510 | |
| | 21511 | <p> |
| | 21512 | We're not checking to see if the actor is still in scope. |
| | 21513 | |
| | 21514 | </div> |
| | 21515 | |
| | 21516 | <!-------------------> |
| | 21517 | <div class=entry> |
| | 21518 | |
| | 21519 | <pre> |
| | 21520 | >n. open door. |
| | 21521 | >close door and sit down |
| | 21522 | </pre> |
| | 21523 | --> endless loop - weird problem with token indices for 'sit down' part |
| | 21524 | of grammar tree. The token indices for the second predicate are for |
| | 21525 | the entire command, strangely, so we think we need to parse the entire |
| | 21526 | phrase again and again. |
| | 21527 | |
| | 21528 | <p> |
| | 21529 | This has something to do with the empty dobj noun phrase. Same thing |
| | 21530 | happens with 'close door and open' (which also has an empty dobj), |
| | 21531 | but not with 'close door and look' (which takes no dobj) or 'close |
| | 21532 | door and sit down on floor' (which has a non-empty dobj). |
| | 21533 | |
| | 21534 | </div> |
| | 21535 | |
| | 21536 | <!-------------------> |
| | 21537 | <div class=entry> |
| | 21538 | |
| | 21539 | when changing sensory contexts, don't flush output; instead, consider |
| | 21540 | sensory context when queueing reports, so that we simply don't queue |
| | 21541 | a report unless it's visible in the sense context |
| | 21542 | |
| | 21543 | </div> |
| | 21544 | |
| | 21545 | <!-------------------> |
| | 21546 | <div class=entry> |
| | 21547 | |
| | 21548 | when a door closes from the other side, show a message about it |
| | 21549 | |
| | 21550 | </div> |
| | 21551 | |
| | 21552 | <!-------------------> |
| | 21553 | <div class=entry> |
| | 21554 | |
| | 21555 | Status line messages for nested rooms, sitting, lying |
| | 21556 | |
| | 21557 | </div> |
| | 21558 | |
| | 21559 | <!-------------------> |
| | 21560 | <div class=entry> |
| | 21561 | |
| | 21562 | Standing needs to be able to specify what you're standing on in some |
| | 21563 | cases, such as platforms. Is it only the floor that won't? |
| | 21564 | |
| | 21565 | </div> |
| | 21566 | |
| | 21567 | <!-------------------> |
| | 21568 | <div class=entry> |
| | 21569 | |
| | 21570 | when standing, make sure we move actor to room |
| | 21571 | |
| | 21572 | </div> |
| | 21573 | |
| | 21574 | <!-------------------> |
| | 21575 | <div class=entry> |
| | 21576 | |
| | 21577 | when sitting/standing, make sure we do all the necessary work of |
| | 21578 | travelTo |
| | 21579 | |
| | 21580 | </div> |
| | 21581 | |
| | 21582 | <!-------------------> |
| | 21583 | <div class=entry> |
| | 21584 | |
| | 21585 | Chairs, beds (make Room not Fixed? or make a deeper base class for |
| | 21586 | BaseRoom, with Room: Fixed, Room?) |
| | 21587 | |
| | 21588 | </div> |
| | 21589 | |
| | 21590 | <!-------------------> |
| | 21591 | <div class=entry> |
| | 21592 | |
| | 21593 | sit/lie on floor: actor doesn't actually need to stand first, if the |
| | 21594 | actor is already sitting/lying in the room. In other words, if we're |
| | 21595 | just changing from sitting to lying or vice versa, and not changing |
| | 21596 | containers, we don't need an intermediate standing state. We need |
| | 21597 | something like standing-or-in-obj instead. |
| | 21598 | |
| | 21599 | </div> |
| | 21600 | |
| | 21601 | <!-------------------> |
| | 21602 | <div class=entry> |
| | 21603 | |
| | 21604 | sit/lie/stand on - when checking that we can enter a nested room, make |
| | 21605 | sure we're in the immediate container of the nested room |
| | 21606 | |
| | 21607 | </div> |
| | 21608 | |
| | 21609 | <!-------------------> |
| | 21610 | <div class=entry> |
| | 21611 | |
| | 21612 | sit/lie: need to configure prep for 'on' vs 'in' (since we 'sit on' |
| | 21613 | some things but 'sit in' other things, and likewise for 'lie on' |
| | 21614 | vs 'lie in') |
| | 21615 | |
| | 21616 | </div> |
| | 21617 | |
| | 21618 | <!-------------------> |
| | 21619 | <div class=entry> |
| | 21620 | |
| | 21621 | sit on floor, then sit on chair -> no intermediate 'stand'. This might |
| | 21622 | not be important, since it won't involve actual movement, but it's a |
| | 21623 | little weird, and it would be nice to make it consistent with the real |
| | 21624 | nested rooms. |
| | 21625 | |
| | 21626 | </div> |
| | 21627 | |
| | 21628 | <!-------------------> |
| | 21629 | <div class=entry> |
| | 21630 | |
| | 21631 | 'sit on floor' doesn't work if run from a doubly-nested room (or deeper) |
| | 21632 | |
| | 21633 | </div> |
| | 21634 | |
| | 21635 | <!-------------------> |
| | 21636 | <div class=entry> |
| | 21637 | |
| | 21638 | sit on armchair, then stand on dais: "already standing on the dais". |
| | 21639 | Need to deal with an implied command that effects the change required |
| | 21640 | of the main command. |
| | 21641 | |
| | 21642 | </div> |
| | 21643 | |
| | 21644 | <!-------------------> |
| | 21645 | <div class=entry> |
| | 21646 | |
| | 21647 | Might want a precondition for travel more general than 'standing', |
| | 21648 | to allow for standing in vehicles and on platforms |
| | 21649 | |
| | 21650 | </div> |
| | 21651 | |
| | 21652 | <!-------------------> |
| | 21653 | <div class=entry> |
| | 21654 | |
| | 21655 | list actors in a nested room when describing the room |
| | 21656 | |
| | 21657 | </div> |
| | 21658 | |
| | 21659 | <!-------------------> |
| | 21660 | <div class=entry> |
| | 21661 | |
| | 21662 | maximum seating capacity for a chair |
| | 21663 | |
| | 21664 | </div> |
| | 21665 | |
| | 21666 | <!-------------------> |
| | 21667 | <div class=entry> |
| | 21668 | |
| | 21669 | in box: try 'e': "you can't do that from the main platform". |
| | 21670 | |
| | 21671 | </div> |
| | 21672 | |
| | 21673 | <!-------------------> |
| | 21674 | <div class=entry> |
| | 21675 | |
| | 21676 | in box: in the dark, should probably have the enclosing room in scope |
| | 21677 | |
| | 21678 | </div> |
| | 21679 | |
| | 21680 | <!-------------------> |
| | 21681 | <div class=entry> |
| | 21682 | |
| | 21683 | in box: when closed and we have light, definitely should have the |
| | 21684 | enclosing room in scope |
| | 21685 | |
| | 21686 | </div> |
| | 21687 | |
| | 21688 | <!-------------------> |
| | 21689 | <div class=entry> |
| | 21690 | |
| | 21691 | in box: should not be able to try to get out of box when we can't |
| | 21692 | sense beyond the box - it should serve as top-level location for |
| | 21693 | the purposes of the implied actions in this case |
| | 21694 | |
| | 21695 | </div> |
| | 21696 | |
| | 21697 | <!-------------------> |
| | 21698 | <div class=entry> |
| | 21699 | |
| | 21700 | When in box, and box is closed, list contents of box as top-level |
| | 21701 | contents of room. |
| | 21702 | |
| | 21703 | </div> |
| | 21704 | |
| | 21705 | <!-------------------> |
| | 21706 | <div class=entry> |
| | 21707 | |
| | 21708 | Listing room contents should show contents of fixed items to any |
| | 21709 | depth. The first-level contents of anything not listed should by |
| | 21710 | default be listed. |
| | 21711 | |
| | 21712 | </div> |
| | 21713 | |
| | 21714 | <!-------------------> |
| | 21715 | <div class=entry> |
| | 21716 | |
| | 21717 | Vehicles |
| | 21718 | |
| | 21719 | </div> |
| | 21720 | |
| | 21721 | <!-------------------> |
| | 21722 | <div class=entry> |
| | 21723 | |
| | 21724 | traveling - don't use actorStanding, but use travelerReady instead. |
| | 21725 | If the traveler is an actor this turns into actorStanding (or whatever |
| | 21726 | is appropriate for the actor); for a vehicle it's probably nothing, but |
| | 21727 | could be used to check for things like the doors being closed on a car |
| | 21728 | or seatbelts being fastened. |
| | 21729 | |
| | 21730 | </div> |
| | 21731 | |
| | 21732 | <!-------------------> |
| | 21733 | <div class=entry> |
| | 21734 | |
| | 21735 | Vehicles: when PC is riding, we get no description of the new room |
| | 21736 | |
| | 21737 | </div> |
| | 21738 | |
| | 21739 | <!-------------------> |
| | 21740 | <div class=entry> |
| | 21741 | |
| | 21742 | Vehicles: put tricycle on platform; get on tricycle; ride tricycle: |
| | 21743 | we don't seem to move the tricycle off the platform first. |
| | 21744 | |
| | 21745 | </div> |
| | 21746 | |
| | 21747 | <!-------------------> |
| | 21748 | <div class=entry> |
| | 21749 | |
| | 21750 | Vehicles: departing should use definite article |
| | 21751 | |
| | 21752 | </div> |
| | 21753 | |
| | 21754 | <!-------------------> |
| | 21755 | <div class=entry> |
| | 21756 | |
| | 21757 | Vehicles: departing doesn't list riders (presumably they're out of |
| | 21758 | scope by the time the departure message is generated; need to save |
| | 21759 | sense info or something) |
| | 21760 | |
| | 21761 | </div> |
| | 21762 | |
| | 21763 | <!-------------------> |
| | 21764 | <div class=entry> |
| | 21765 | |
| | 21766 | sample game: implement 'ride tricycle' |
| | 21767 | |
| | 21768 | </div> |
| | 21769 | |
| | 21770 | <!-------------------> |
| | 21771 | <div class=entry> |
| | 21772 | |
| | 21773 | sample game: when getting on tricycle, mention how to ride it |
| | 21774 | |
| | 21775 | </div> |
| | 21776 | |
| | 21777 | <!-------------------> |
| | 21778 | <div class=entry> |
| | 21779 | |
| | 21780 | Put x on floor: if we're in a nested room with a drop location that |
| | 21781 | isn't the main room, we'll perform a "drop" in the nested room. Should |
| | 21782 | actually move to outermost room if possible. (Maybe we need to leave |
| | 21783 | the nested room as a precondition.) |
| | 21784 | |
| | 21785 | </div> |
| | 21786 | |
| | 21787 | <!-------------------> |
| | 21788 | <div class=entry> |
| | 21789 | |
| | 21790 | Vehicles: need a convenient way to put up vehicle barriers, so that |
| | 21791 | you can walk through a door but not ride through, and vice versa |
| | 21792 | |
| | 21793 | </div> |
| | 21794 | |
| | 21795 | <!-------------------> |
| | 21796 | <div class=entry> |
| | 21797 | |
| | 21798 | 'follow me' mode for an actor |
| | 21799 | |
| | 21800 | </div> |
| | 21801 | |
| | 21802 | <!-------------------> |
| | 21803 | <div class=entry> |
| | 21804 | |
| | 21805 | recognize (in input) reflexive pronouns referring to target actor |
| | 21806 | (bob, examine yourself) |
| | 21807 | |
| | 21808 | </div> |
| | 21809 | |
| | 21810 | <!-------------------> |
| | 21811 | <div class=entry> |
| | 21812 | |
| | 21813 | Allow things to be placed out of reach from within nested rooms |
| | 21814 | (canReachFromRoom). |
| | 21815 | |
| | 21816 | </div> |
| | 21817 | |
| | 21818 | <!-------------------> |
| | 21819 | <div class=entry> |
| | 21820 | |
| | 21821 | change from LangThing to 'modify Thing', etc. |
| | 21822 | |
| | 21823 | </div> |
| | 21824 | |
| | 21825 | <!-------------------> |
| | 21826 | <div class=entry> |
| | 21827 | |
| | 21828 | change "bob, tell me about x" into "me, ask bob about x" |
| | 21829 | |
| | 21830 | </div> |
| | 21831 | |
| | 21832 | <!-------------------> |
| | 21833 | <div class=entry> |
| | 21834 | |
| | 21835 | 'push/move dobj to iobj' - for things like building staircases ('push |
| | 21836 | crate to window'). Synonyms might include 'push/move/put dobj under iobj'. |
| | 21837 | |
| | 21838 | </div> |
| | 21839 | |
| | 21840 | <!-------------------> |
| | 21841 | <div class=entry> |
| | 21842 | |
| | 21843 | Fix follow problem: "bill cannot stand in closed box" is reported |
| | 21844 | even though we're out of range of the sense. |
| | 21845 | |
| | 21846 | </div> |
| | 21847 | |
| | 21848 | <!-------------------> |
| | 21849 | <div class=entry> |
| | 21850 | |
| | 21851 | Allow some types of nested rooms (platforms, booths) to be their own |
| | 21852 | follow locations, so we can follow an actor into such a room |
| | 21853 | |
| | 21854 | </div> |
| | 21855 | |
| | 21856 | <!-------------------> |
| | 21857 | <div class=entry> |
| | 21858 | |
| | 21859 | Might want to keep pronoun antecedents per actor. When an issuer |
| | 21860 | gives a command to a target, the target should copy all of the |
| | 21861 | antecedents from the issuer. |
| | 21862 | |
| | 21863 | </div> |
| | 21864 | |
| | 21865 | <!-------------------> |
| | 21866 | <div class=entry> |
| | 21867 | |
| | 21868 | for 'in' and 'out', by default ask for a direct object if there's |
| | 21869 | no evident travel connection for the direction |
| | 21870 | |
| | 21871 | </div> |
| | 21872 | |
| | 21873 | <!-------------------> |
| | 21874 | <div class=entry> |
| | 21875 | |
| | 21876 | remove all preconditions from noTravel, as we know travel will not occur |
| | 21877 | and hence don't need to meet any conditions |
| | 21878 | |
| | 21879 | </div> |
| | 21880 | |
| | 21881 | <!-------------------> |
| | 21882 | <div class=entry> |
| | 21883 | |
| | 21884 | 'push obj north' (and other directions) |
| | 21885 | |
| | 21886 | </div> |
| | 21887 | |
| | 21888 | <!-------------------> |
| | 21889 | <div class=entry> |
| | 21890 | |
| | 21891 | for "follow", track actors in vehicles as well as the vehicles |
| | 21892 | themselves |
| | 21893 | |
| | 21894 | </div> |
| | 21895 | |
| | 21896 | <!-------------------> |
| | 21897 | <div class=entry> |
| | 21898 | |
| | 21899 | 'draggable' class, implementing a general framework for pushing |
| | 21900 | objects from one room to another |
| | 21901 | |
| | 21902 | </div> |
| | 21903 | |
| | 21904 | <!-------------------> |
| | 21905 | <div class=entry> |
| | 21906 | |
| | 21907 | add a push-travel barrier that works like the vehicle barrier, but |
| | 21908 | for traveling while pushing objects |
| | 21909 | |
| | 21910 | </div> |
| | 21911 | |
| | 21912 | <!-------------------> |
| | 21913 | <div class=entry> |
| | 21914 | |
| | 21915 | Change the barrier mechanism so that barriers are listed on the connector, |
| | 21916 | rather than being part of the connector. This is needed because the |
| | 21917 | connector is in many cases directly addressable - putting the barrier |
| | 21918 | in front of the connector as a proxy connector doesn't work when you |
| | 21919 | can reach the connector directly, making an end run around the barrier. |
| | 21920 | |
| | 21921 | </div> |
| | 21922 | |
| | 21923 | <!-------------------> |
| | 21924 | <div class=entry> |
| | 21925 | |
| | 21926 | Change the listing mechanism so that showList is a method of the |
| | 21927 | ShowListInterface class, to simplify argument lists. |
| | 21928 | |
| | 21929 | </div> |
| | 21930 | |
| | 21931 | <!-------------------> |
| | 21932 | <div class=entry> |
| | 21933 | |
| | 21934 | Handle nested grouping. Use this for equivalents in groups. |
| | 21935 | |
| | 21936 | </div> |
| | 21937 | |
| | 21938 | <!-------------------> |
| | 21939 | <div class=entry> |
| | 21940 | |
| | 21941 | For group listings, don't add a group when there's only one group due |
| | 21942 | to equivalence. We currently say this, which is awkward: "the jar |
| | 21943 | contains two coins (two copper coins)." |
| | 21944 | |
| | 21945 | </div> |
| | 21946 | |
| | 21947 | <!-------------------> |
| | 21948 | <div class=entry> |
| | 21949 | |
| | 21950 | Equivalent listings - eliminate as a separate special case and simply |
| | 21951 | list equivalents using a listing group. Add an Equivalent Group |
| | 21952 | which implements a simple listing group for equivalents; by default, |
| | 21953 | the group simply shows the count. |
| | 21954 | |
| | 21955 | </div> |
| | 21956 | |
| | 21957 | <!-------------------> |
| | 21958 | <div class=entry> |
| | 21959 | |
| | 21960 | For our silver/gold/copper coins in the sample game, make sure the |
| | 21961 | grouping mechanism can list like this: "eight coins (three silver and |
| | 21962 | five gold)". Note that the names in the parens leave off "coins" and |
| | 21963 | just list the number and adjective. |
| | 21964 | |
| | 21965 | </div> |
| | 21966 | |
| | 21967 | <!-------------------> |
| | 21968 | <div class=entry> |
| | 21969 | |
| | 21970 | Move all of the lister objects into the messages module, and eliminate |
| | 21971 | the secondary indirection through the libMessages object. Simply make |
| | 21972 | the lister itself part of the messages module, and put the messages |
| | 21973 | directly in the lister. |
| | 21974 | |
| | 21975 | </div> |
| | 21976 | |
| | 21977 | <!-------------------> |
| | 21978 | <div class=entry> |
| | 21979 | |
| | 21980 | Get rid of the unnecessary list flags LIST_WORN and LIST_INVENTORY, |
| | 21981 | replacing them with parameterization at the listing method level |
| | 21982 | instead. |
| | 21983 | |
| | 21984 | </div> |
| | 21985 | |
| | 21986 | <!-------------------> |
| | 21987 | <div class=entry> |
| | 21988 | |
| | 21989 | Use the generic list mechanism to list actors in a room. By default, |
| | 21990 | each actor simply lists separately, but it should be possible to |
| | 21991 | group actors using the normal listing group mechanism ("Bob and Bill |
| | 21992 | are at their desks", for example). |
| | 21993 | |
| | 21994 | </div> |
| | 21995 | |
| | 21996 | <!-------------------> |
| | 21997 | <div class=entry> |
| | 21998 | |
| | 21999 | Can we make the disambig list use the normal listing mechanism? |
| | 22000 | <no, probably not worth it> |
| | 22001 | |
| | 22002 | </div> |
| | 22003 | |
| | 22004 | <!-------------------> |
| | 22005 | <div class=entry> |
| | 22006 | |
| | 22007 | Add a "specialDesc", similar to initDesc but for more general purposes. |
| | 22008 | specialDesc should turn into initDesc when initDesc is applicable. |
| | 22009 | |
| | 22010 | </div> |
| | 22011 | |
| | 22012 | <!-------------------> |
| | 22013 | <div class=entry> |
| | 22014 | |
| | 22015 | add "the former" and "the latter" as disambiguation responses |
| | 22016 | |
| | 22017 | </div> |
| | 22018 | |
| | 22019 | <!-------------------> |
| | 22020 | <div class=entry> |
| | 22021 | |
| | 22022 | For nested rooms, break out the "staging location" test from |
| | 22023 | checkActorReadyToEnterNestedRoom into a separate routine. Use a |
| | 22024 | list of possible staging areas given by a separate property for |
| | 22025 | easier overriding. |
| | 22026 | |
| | 22027 | </div> |
| | 22028 | |
| | 22029 | <!-------------------> |
| | 22030 | <div class=entry> |
| | 22031 | |
| | 22032 | For nested rooms, use a separate "exit destination" property for the |
| | 22033 | destination of a GetOutOf action, rather than assuming that we always |
| | 22034 | move to the enclosing location. |
| | 22035 | |
| | 22036 | </div> |
| | 22037 | |
| | 22038 | <!-------------------> |
| | 22039 | <div class=entry> |
| | 22040 | |
| | 22041 | Add a "high nested room" that can't be entered except from particular |
| | 22042 | staging areas due to height. These is a fairly trivial |
| | 22043 | specialization: first, don't solve the problem using implicit |
| | 22044 | commands unless the actor has already solved it before; second, the |
| | 22045 | default failure message is something like "you can't enter that from |
| | 22046 | here; it's too high up." |
| | 22047 | |
| | 22048 | </div> |
| | 22049 | |
| | 22050 | <!-------------------> |
| | 22051 | <div class=entry> |
| | 22052 | |
| | 22053 | Rename the '*predicate*' production classes to '*command*' |
| | 22054 | |
| | 22055 | </div> |
| | 22056 | |
| | 22057 | <!-------------------> |
| | 22058 | <div class=entry> |
| | 22059 | |
| | 22060 | Base all command (formerly predicate) classes on a common CommandProd |
| | 22061 | base class |
| | 22062 | |
| | 22063 | </div> |
| | 22064 | |
| | 22065 | <!-------------------> |
| | 22066 | <div class=entry> |
| | 22067 | |
| | 22068 | Add a resolveAction method to the command classes. This method |
| | 22069 | retrieves the action from the command. In English, this simply |
| | 22070 | retrieves the 'predicate' match tree object, which is always based on |
| | 22071 | action; other languages, especially those that use case markers |
| | 22072 | rather than word order to encode phrase-role information, can |
| | 22073 | customize this behavior appropriately for their grammatical systems. |
| | 22074 | |
| | 22075 | </div> |
| | 22076 | |
| | 22077 | <!-------------------> |
| | 22078 | <div class=entry> |
| | 22079 | |
| | 22080 | When scanning command parse matches, we can immediately eliminate |
| | 22081 | any match for which resolveAction fails to find a valid action. |
| | 22082 | |
| | 22083 | </div> |
| | 22084 | |
| | 22085 | <!-------------------> |
| | 22086 | <div class=entry> |
| | 22087 | |
| | 22088 | Use separate listers for room/object contents lists and inventory lists. |
| | 22089 | Use separate show-list-item methods for inventory items. |
| | 22090 | |
| | 22091 | </div> |
| | 22092 | |
| | 22093 | <!-------------------> |
| | 22094 | <div class=entry> |
| | 22095 | |
| | 22096 | For keyrings, show contents of keyring in room/object/inventory contents |
| | 22097 | as a sublist: a keyring (attached to which are an iron key and a bronze |
| | 22098 | key)... |
| | 22099 | |
| | 22100 | </div> |
| | 22101 | |
| | 22102 | <!-------------------> |
| | 22103 | <div class=entry> |
| | 22104 | |
| | 22105 | Allow queuing pending actions for an actor, not just token lists. |
| | 22106 | Make it possible to insert a pending action at the beginning of the |
| | 22107 | queue (for continuation actions). |
| | 22108 | |
| | 22109 | </div> |
| | 22110 | |
| | 22111 | <!-------------------> |
| | 22112 | <div class=entry> |
| | 22113 | |
| | 22114 | Use a separate listing flag (isListedInInventory) for inventory |
| | 22115 | list inclusion. For actors, make this true by default, even though |
| | 22116 | actors are not listed in room descriptions. |
| | 22117 | |
| | 22118 | </div> |
| | 22119 | |
| | 22120 | <!-------------------> |
| | 22121 | <div class=entry> |
| | 22122 | |
| | 22123 | Dispenser and Dispensable, for matchbooks and the like |
| | 22124 | |
| | 22125 | </div> |
| | 22126 | |
| | 22127 | <!-------------------> |
| | 22128 | <div class=entry> |
| | 22129 | |
| | 22130 | Collective objects for cases like "book of matches" and "matches" - |
| | 22131 | when we type "take matches," we should interpret this as the book of |
| | 22132 | matches (i.e., "matches" == singular) rather than as the individual |
| | 22133 | matches ("matches" == plural). |
| | 22134 | |
| | 22135 | </div> |
| | 22136 | |
| | 22137 | <!-------------------> |
| | 22138 | <div class=entry> |
| | 22139 | |
| | 22140 | Matches - flammable objects that are self-igniting |
| | 22141 | |
| | 22142 | </div> |
| | 22143 | |
| | 22144 | <!-------------------> |
| | 22145 | <div class=entry> |
| | 22146 | |
| | 22147 | Matchbooks |
| | 22148 | |
| | 22149 | </div> |
| | 22150 | |
| | 22151 | <!-------------------> |
| | 22152 | <div class=entry> |
| | 22153 | |
| | 22154 | Include a checksum in saved state files, and check at start of load. |
| | 22155 | This will help avoid attempting to restore a file that was corrupted. |
| | 22156 | |
| | 22157 | </div> |
| | 22158 | |
| | 22159 | <!-------------------> |
| | 22160 | <div class=entry> |
| | 22161 | |
| | 22162 | Add a tentative pre-resolution pass, for the later-resolved object of |
| | 22163 | a two-object action, that runs before the resolution of the |
| | 22164 | earlier-resolved object. Don't perform full resolution on this pass; |
| | 22165 | specifically, don't count any problems against the ranking results, |
| | 22166 | and don't ask for help interactively. |
| | 22167 | |
| | 22168 | <p> |
| | 22169 | Make use of this information in 'verify' routines for the |
| | 22170 | earlier-resolved objects when applicable. For example, for "take |
| | 22171 | <dobj> from <iobj>", we resolve the indirect object first, so we |
| | 22172 | don't know the final dobj resolution when resolving the iobj; so, use |
| | 22173 | the tentative information so that we can rule an iobj illogical if |
| | 22174 | there's no tentative dobj inside the proposed iobj. |
| | 22175 | |
| | 22176 | </div> |
| | 22177 | |
| | 22178 | <!-------------------> |
| | 22179 | <div class=entry> |
| | 22180 | |
| | 22181 | Might want to clean up the other-object business in askMissingObject |
| | 22182 | and related routines. This scheme doesn't feel properly generalized. |
| | 22183 | For that matter, we might want to rethink the whole scheme so that |
| | 22184 | it's subclassed by and handled in the action classes, rather than |
| | 22185 | parameterized, since the parameterization scheme seems hokey and |
| | 22186 | brittle. |
| | 22187 | |
| | 22188 | </div> |
| | 22189 | |
| | 22190 | <!-------------------> |
| | 22191 | <div class=entry> |
| | 22192 | |
| | 22193 | Remove the otherObjectList and otherObjectWhich stuff when we've |
| | 22194 | cleaned up the corresponding code. This information should now be |
| | 22195 | available via the tentative resolution lists instead. |
| | 22196 | |
| | 22197 | </div> |
| | 22198 | |
| | 22199 | <!-------------------> |
| | 22200 | <div class=entry> |
| | 22201 | |
| | 22202 | When lighting a match as part of an implied command, reduce the burn |
| | 22203 | time by one turn - this ensures that lighting the match as part of |
| | 22204 | another action won't artificially extend the match's burn time. |
| | 22205 | |
| | 22206 | </div> |
| | 22207 | |
| | 22208 | <!-------------------> |
| | 22209 | <div class=entry> |
| | 22210 | |
| | 22211 | candles, torches, oil lanterns - flammable objects that must be lit with |
| | 22212 | another item, such as a match |
| | 22213 | |
| | 22214 | </div> |
| | 22215 | |
| | 22216 | <!-------------------> |
| | 22217 | <div class=entry> |
| | 22218 | |
| | 22219 | defaults: when there are two or more equivalent items that could be |
| | 22220 | used as defaults, pick one arbitrarily |
| | 22221 | |
| | 22222 | </div> |
| | 22223 | |
| | 22224 | <!-------------------> |
| | 22225 | <div class=entry> |
| | 22226 | |
| | 22227 | for implied transfers into a bag of holding, put the indirect object |
| | 22228 | of "take from" last in the affinity list |
| | 22229 | |
| | 22230 | </div> |
| | 22231 | |
| | 22232 | <!-------------------> |
| | 22233 | <div class=entry> |
| | 22234 | |
| | 22235 | for implied transfers into a bag of holding, other things being equal, |
| | 22236 | transfer the least recently acquired object first |
| | 22237 | |
| | 22238 | </div> |
| | 22239 | |
| | 22240 | <!-------------------> |
| | 22241 | <div class=entry> |
| | 22242 | |
| | 22243 | food items |
| | 22244 | |
| | 22245 | </div> |
| | 22246 | |
| | 22247 | <!-------------------> |
| | 22248 | <div class=entry> |
| | 22249 | |
| | 22250 | Change the logic of checkActorInStagingLocation so that it doesn't |
| | 22251 | assume that we can reach a staging location just because we're |
| | 22252 | indirectly in the location. Instead, add a "choose staging location" |
| | 22253 | method so that rooms can override the staging location chooser with |
| | 22254 | appropriate special-case code when needed. |
| | 22255 | |
| | 22256 | </div> |
| | 22257 | |
| | 22258 | <!-------------------> |
| | 22259 | <div class=entry> |
| | 22260 | |
| | 22261 | Add issuing actor and target actor parameters to resolveAction(), so |
| | 22262 | that the resolver can tell what reflexive pronoun phrases mean. (In |
| | 22263 | many languages, reflexive constructions are structurally part of some |
| | 22264 | predicates, and affect the meaning of the predicate, so the identity |
| | 22265 | of the speaker and of the subject must sometimes be known to |
| | 22266 | correctly determine the interpretation of the predicate structure.) |
| | 22267 | |
| | 22268 | </div> |
| | 22269 | |
| | 22270 | <!-------------------> |
| | 22271 | <div class=entry> |
| | 22272 | |
| | 22273 | sample game: reject just plain "match" in the matchbook's matchName |
| | 22274 | |
| | 22275 | </div> |
| | 22276 | |
| | 22277 | <!-------------------> |
| | 22278 | <div class=entry> |
| | 22279 | |
| | 22280 | touch scope: include contents of matchbooks and keyrings, so that |
| | 22281 | these can be used even in the dark |
| | 22282 | |
| | 22283 | </div> |
| | 22284 | |
| | 22285 | <!-------------------> |
| | 22286 | <div class=entry> |
| | 22287 | |
| | 22288 | Add an associated odor and sound property to each Thing. This points |
| | 22289 | to an object that encapsulates the object's sensory emanations. Always |
| | 22290 | add these objects to scope when the associated objects are in scope, |
| | 22291 | with the same properties. |
| | 22292 | |
| | 22293 | <p> |
| | 22294 | Make "listen to x" and "smell x" defer to the associated objects. |
| | 22295 | |
| | 22296 | <p> |
| | 22297 | For scoping, a sound or smell doesn't have to place the main object |
| | 22298 | in scope, but rather can just put the intangible sensory emanation in |
| | 22299 | scope. For example, if an alarm clock is buzzing, the 'buzzing |
| | 22300 | sound' object would be in scope but not the alarm clock itself. (On |
| | 22301 | the other hand, some sounds, like a ringing phone, might be |
| | 22302 | sufficiently distinctive as to place the main object in scope. But |
| | 22303 | for those cases we can simply associate the sound/smell with the main |
| | 22304 | object.) |
| | 22305 | |
| | 22306 | </div> |
| | 22307 | |
| | 22308 | <!-------------------> |
| | 22309 | <div class=entry> |
| | 22310 | |
| | 22311 | We need different odor/sound descriptions for different situations: |
| | 22312 | |
| | 22313 | <p> |
| | 22314 | <pre> |
| | 22315 | >listen to phone |
| | 22316 | It's ringing. |
| | 22317 | <i>==> phone.soundDesc</i> |
| | 22318 | |
| | 22319 | >listen to ring [phone visible] |
| | 22320 | It's coming from the phone. |
| | 22321 | <i>==> sound.soundWithSource</i> |
| | 22322 | |
| | 22323 | >listen to ring [phone not visible] |
| | 22324 | It sounds like a phone. |
| | 22325 | <i>==> sound.soundWithoutSource</i> |
| | 22326 | |
| | 22327 | >look [phone visible] |
| | 22328 | ... |
| | 22329 | The phone is ringing. |
| | 22330 | <i>==> sound.soundHereWithSource</i> |
| | 22331 | |
| | 22332 | >look [phone not visible] |
| | 22333 | ... |
| | 22334 | You can hear what sounds like a phone ringing. |
| | 22335 | <i>==> sound.soundHereWithoutSource</i> |
| | 22336 | </pre> |
| | 22337 | |
| | 22338 | </div> |
| | 22339 | |
| | 22340 | <!-------------------> |
| | 22341 | <div class=entry> |
| | 22342 | |
| | 22343 | Don't open a footnote when the PC isn't seeing the text with the |
| | 22344 | footnote reference. |
| | 22345 | |
| | 22346 | </div> |
| | 22347 | |
| | 22348 | <!-------------------> |
| | 22349 | <div class=entry> |
| | 22350 | |
| | 22351 | Add sense emanations to inventory displays. |
| | 22352 | |
| | 22353 | </div> |
| | 22354 | |
| | 22355 | <!-------------------> |
| | 22356 | <div class=entry> |
| | 22357 | |
| | 22358 | For sound/smell objects, add options to control ongoing announcements |
| | 22359 | of sensory emanations: |
| | 22360 | |
| | 22361 | <ul> |
| | 22362 | <li>always show on room description, or only show on |
| | 22363 | explicit "look" descriptions (and corresponding sense commands - |
| | 22364 | "smell", "listen") |
| | 22365 | |
| | 22366 | <li>show every n clock ticks |
| | 22367 | |
| | 22368 | <li>show every n clock ticks for m iterations, then go |
| | 22369 | to a secondary message every p clock ticks (for something like "the |
| | 22370 | phone is still ringing"). |
| | 22371 | </ul> |
| | 22372 | |
| | 22373 | </div> |
| | 22374 | |
| | 22375 | <!-------------------> |
| | 22376 | <div class=entry> |
| | 22377 | |
| | 22378 | Room descriptions should be differentiated according to whether we're |
| | 22379 | explicitly looking or merely entering a new room. |
| | 22380 | |
| | 22381 | </div> |
| | 22382 | |
| | 22383 | <!-------------------> |
| | 22384 | <div class=entry> |
| | 22385 | |
| | 22386 | When a noise's or odor's source is not visible, and the object is |
| | 22387 | examined (via "examine", or via "listen to" or "smell" or whatever), |
| | 22388 | it might be desirable in many cases to show the <i>apparent</i> source, |
| | 22389 | which is to say the visually opaque obstructor, and describe the |
| | 22390 | sound/odor as coming from inside/outside/behind/whatever the |
| | 22391 | obstructor. |
| | 22392 | |
| | 22393 | <p> |
| | 22394 | The obstructor can be easily found with |
| | 22395 | gActor.findOpaqueObstructor(sight, obj) (where 'obj' is the noise or |
| | 22396 | odor object). Once the obstructor is found, we'll have to generate |
| | 22397 | an appropriate message, which will require a new method parallel to |
| | 22398 | obs.cannotReachObject(obj) - perhaps we could call it |
| | 22399 | obs.describeSoundObstructor(obj) etc - which would display "The |
| | 22400 | ringing seems to be coming from inside the box" and the like. |
| | 22401 | |
| | 22402 | <p> |
| | 22403 | This entire mechanism would not be used when the obstructor itself |
| | 22404 | cannot be seen, such as in the dark. |
| | 22405 | |
| | 22406 | </div> |
| | 22407 | |
| | 22408 | <!-------------------> |
| | 22409 | <div class=entry> |
| | 22410 | |
| | 22411 | Consider: |
| | 22412 | |
| | 22413 | <p> |
| | 22414 | <pre> |
| | 22415 | >look |
| | 22416 | ... |
| | 22417 | You can hear what sounds like a phone ringing. |
| | 22418 | |
| | 22419 | >listen to ring |
| | 22420 | It sounds like a phone. |
| | 22421 | |
| | 22422 | >x phone |
| | 22423 | You don't see any phone. |
| | 22424 | </pre> |
| | 22425 | |
| | 22426 | <p> |
| | 22427 | It would be better if that last line were: |
| | 22428 | |
| | 22429 | <p> |
| | 22430 | <pre> |
| | 22431 | >x phone |
| | 22432 | You can hear a phone ringing, but you can't see it. |
| | 22433 | </pre> |
| | 22434 | |
| | 22435 | <p> |
| | 22436 | To deal with this, adjust the touchObj and objVisible preconditions |
| | 22437 | so that it provides better feedback for an object that can be heard |
| | 22438 | but not seen. |
| | 22439 | |
| | 22440 | </div> |
| | 22441 | |
| | 22442 | <!-------------------> |
| | 22443 | <div class=entry> |
| | 22444 | |
| | 22445 | Write a common main() that most games will use, with appropriate |
| | 22446 | hooks for showing the introductory text and so on. Or, perhaps |
| | 22447 | better, write a standard initialization routine that the game's |
| | 22448 | main() can call. |
| | 22449 | |
| | 22450 | </div> |
| | 22451 | |
| | 22452 | <!-------------------> |
| | 22453 | <div class=entry> |
| | 22454 | |
| | 22455 | Provide an author-configurable option to process multiple orders to |
| | 22456 | NPC's synchronously - so, if you say "bob, go north, get all, go |
| | 22457 | south", the PC doesn't get a command line prompt again until Bob |
| | 22458 | finishes the whole set of commands. |
| | 22459 | |
| | 22460 | </div> |
| | 22461 | |
| | 22462 | <!-------------------> |
| | 22463 | <div class=entry> |
| | 22464 | |
| | 22465 | It might be worth considering making the disambiguation responses for |
| | 22466 | &noMatchDisambig and &disambigOrdinalOutOfRange more interactive. |
| | 22467 | Currently, if you give an invalid response to a disambig question, |
| | 22468 | you get an error and no chance to retry. Something like this might |
| | 22469 | be more intuitive: |
| | 22470 | |
| | 22471 | <p> |
| | 22472 | <pre> |
| | 22473 | >take ball |
| | 22474 | Which ball, the red ball, or the green ball? |
| | 22475 | |
| | 22476 | >third |
| | 22477 | There weren't that many choices - did you mean the red ball, or the |
| | 22478 | green ball? |
| | 22479 | |
| | 22480 | >orange |
| | 22481 | That wasn't one of the choices - did you mean the red ball, or the |
| | 22482 | green ball? |
| | 22483 | </pre> |
| | 22484 | |
| | 22485 | <p> |
| | 22486 | However, if the response looks like a valid response but doesn't give |
| | 22487 | us a match, and it also looks syntactically like a valid new command, |
| | 22488 | treat it as a new command. |
| | 22489 | |
| | 22490 | </div> |
| | 22491 | |
| | 22492 | <!-------------------> |
| | 22493 | <div class=entry> |
| | 22494 | |
| | 22495 | Generic script objects: an object for which we call a method automatically |
| | 22496 | each turn it's active. We'd keep a counter that we'd automatically advance |
| | 22497 | on each call. We should probably use this generic object to implement |
| | 22498 | text lists. |
| | 22499 | |
| | 22500 | </div> |
| | 22501 | |
| | 22502 | <!-------------------> |
| | 22503 | <div class=entry> |
| | 22504 | |
| | 22505 | Generic text lists: an object that encapsulates a list of messages |
| | 22506 | to display, one per turn. |
| | 22507 | |
| | 22508 | <p> |
| | 22509 | Text lists should be linkable to a common counter object, so that the |
| | 22510 | lists are synchronized on the same counter. This lets you have separate |
| | 22511 | lists for each room, but keep the timeline in each list the same. |
| | 22512 | |
| | 22513 | <p> |
| | 22514 | It should be possible to associate a text list object with a room instead |
| | 22515 | of coding the room's text list in-line in the room. |
| | 22516 | |
| | 22517 | </div> |
| | 22518 | |
| | 22519 | <!-------------------> |
| | 22520 | <div class=entry> |
| | 22521 | |
| | 22522 | Room text lists: a list of atmosphere messages we cycle through while |
| | 22523 | the player is in the room. This should be totally automatic, so you |
| | 22524 | just program the list and the library automatically sets up a daemon |
| | 22525 | to run through the messages. |
| | 22526 | |
| | 22527 | </div> |
| | 22528 | |
| | 22529 | <!-------------------> |
| | 22530 | <div class=entry> |
| | 22531 | |
| | 22532 | When describing an object, show the special descriptions for any contents |
| | 22533 | of the object, just as we would list them in room descriptions. This |
| | 22534 | lets us see the special descriptions for contents, without having to |
| | 22535 | write any additional descriptive code in the container. |
| | 22536 | |
| | 22537 | </div> |
| | 22538 | |
| | 22539 | <!-------------------> |
| | 22540 | <div class=entry> |
| | 22541 | |
| | 22542 | consider: |
| | 22543 | |
| | 22544 | <p> |
| | 22545 | <pre> |
| | 22546 | >take coin |
| | 22547 | Which coin, silver or gold? |
| | 22548 | </pre> |
| | 22549 | |
| | 22550 | <p> |
| | 22551 | We should probably keep the copper one in the list. In particular, |
| | 22552 | we probably shouldn't remove an item from consideration for |
| | 22553 | disambiguation just because it's less likely - once we've determined |
| | 22554 | that the noun phrase is ambiguous, we should offer all logical |
| | 22555 | matches, even when they're less likely. |
| | 22556 | |
| | 22557 | </div> |
| | 22558 | |
| | 22559 | <!-------------------> |
| | 22560 | <div class=entry> |
| | 22561 | |
| | 22562 | consider: |
| | 22563 | |
| | 22564 | <p> |
| | 22565 | <pre> |
| | 22566 | >take coinc |
| | 22567 | Which coin...? |
| | 22568 | |
| | 22569 | >take tricyc |
| | 22570 | The word 'tricyc' is not necessary in this story. |
| | 22571 | |
| | 22572 | >take tricyc |
| | 22573 | Taken. |
| | 22574 | </pre> |
| | 22575 | |
| | 22576 | <p> |
| | 22577 | For some reason, truncated words are treated as misspellings when they |
| | 22578 | appear in disambiguation responses. |
| | 22579 | |
| | 22580 | </div> |
| | 22581 | |
| | 22582 | <!-------------------> |
| | 22583 | <div class=entry> |
| | 22584 | |
| | 22585 | Can we cache sense information to speed up resolution a bit? In |
| | 22586 | particular, we should be able to cache sense information during the |
| | 22587 | noun phrase resolution and verification steps, since these do not |
| | 22588 | normally involve any game state changes; once execution begins, |
| | 22589 | though, caching should be turned off. (This is probably the optimal |
| | 22590 | set of trade-offs: on the one hand, the game and library should |
| | 22591 | never have to worry about cache invalidation - the library only needs |
| | 22592 | to turn caching on before starting the parsing phase and then turn |
| | 22593 | caching off before beginning the execution phase of a command; on |
| | 22594 | the other hand, we should derive substantial efficiency from caching |
| | 22595 | during the parsing phase, because this phase in particular tends to |
| | 22596 | evaluate a lot of sense information. |
| | 22597 | |
| | 22598 | <p> |
| | 22599 | (Experimental code has been added, conditionally compiled based on |
| | 22600 | the SENSE_CACHE macro. We'll leave it on for the time being to get |
| | 22601 | some experience with it to see how well it works.) |
| | 22602 | |
| | 22603 | </div> |
| | 22604 | |
| | 22605 | <!-------------------> |
| | 22606 | <div class=entry> |
| | 22607 | |
| | 22608 | Preparsing |
| | 22609 | |
| | 22610 | </div> |
| | 22611 | |
| | 22612 | <!-------------------> |
| | 22613 | <div class=entry> |
| | 22614 | |
| | 22615 | Just-out-of-reach containers. Create a container type that puts its |
| | 22616 | contents in the distance for 'touch' purposes. This can be used for |
| | 22617 | things like items on the ceiling. We'll need a way to make this vary |
| | 22618 | depending on the source object, so that, for example, something could |
| | 22619 | be out of reach for an actor standing in the room but in reach if the |
| | 22620 | actor stands on a desk. |
| | 22621 | |
| | 22622 | </div> |
| | 22623 | |
| | 22624 | <!-------------------> |
| | 22625 | <div class=entry> |
| | 22626 | |
| | 22627 | When using 'again' with a command that had an interactive |
| | 22628 | disambiguation response, the response 'that wasn't one of the |
| | 22629 | choices' is not appropriate since the player doesn't get to respond. |
| | 22630 | |
| | 22631 | </div> |
| | 22632 | |
| | 22633 | <!-------------------> |
| | 22634 | <div class=entry> |
| | 22635 | |
| | 22636 | cache touch paths (and canTouch information) the same way we cache |
| | 22637 | sense paths |
| | 22638 | |
| | 22639 | </div> |
| | 22640 | |
| | 22641 | <!-------------------> |
| | 22642 | <div class=entry> |
| | 22643 | |
| | 22644 | For OutOfReach containers, we shouldn't be able to touch the |
| | 22645 | container itself, since not only the contents but the container |
| | 22646 | itself is meant to be out of reach. To do this, add a PathTo |
| | 22647 | traversal for the last item in a path (and while we're at it, add the |
| | 22648 | symmetrical PathFrom for the first item in the path), and in |
| | 22649 | OutOfReach's checkTouchViaPath, treat PathTo the same as PathIn. |
| | 22650 | |
| | 22651 | </div> |
| | 22652 | |
| | 22653 | <!-------------------> |
| | 22654 | <div class=entry> |
| | 22655 | |
| | 22656 | 'down' from a platform should be 'get off platform' by default |
| | 22657 | |
| | 22658 | </div> |
| | 22659 | |
| | 22660 | <!-------------------> |
| | 22661 | <div class=entry> |
| | 22662 | |
| | 22663 | add 'debug' verb (to break into the debugger) |
| | 22664 | |
| | 22665 | </div> |
| | 22666 | |
| | 22667 | <!-------------------> |
| | 22668 | <div class=entry> |
| | 22669 | |
| | 22670 | Real-time events: on save/restore, adjust system clock basis to keep |
| | 22671 | everything in sync |
| | 22672 | |
| | 22673 | </div> |
| | 22674 | |
| | 22675 | <!-------------------> |
| | 22676 | <div class=entry> |
| | 22677 | |
| | 22678 | Real-time events: design a class for the events |
| | 22679 | |
| | 22680 | </div> |
| | 22681 | |
| | 22682 | <!-------------------> |
| | 22683 | <div class=entry> |
| | 22684 | |
| | 22685 | Real-time events: integrate with the scheduler and command reader |
| | 22686 | |
| | 22687 | </div> |
| | 22688 | |
| | 22689 | <!-------------------> |
| | 22690 | <div class=entry> |
| | 22691 | |
| | 22692 | Real-time events: when an interruption occurs, catch any output and |
| | 22693 | automatically cancel the interrupted input |
| | 22694 | |
| | 22695 | </div> |
| | 22696 | |
| | 22697 | <!-------------------> |
| | 22698 | <div class=entry> |
| | 22699 | |
| | 22700 | Fix problem with quoted strings in literal phrases (as in 'type |
| | 22701 | "hello" on typewriter') |
| | 22702 | |
| | 22703 | </div> |
| | 22704 | |
| | 22705 | <!-------------------> |
| | 22706 | <div class=entry> |
| | 22707 | |
| | 22708 | Fix problem with 'throw': it's illogical to throw something at an |
| | 22709 | object within the object being thrown |
| | 22710 | |
| | 22711 | </div> |
| | 22712 | |
| | 22713 | <!-------------------> |
| | 22714 | <div class=entry> |
| | 22715 | |
| | 22716 | Change all of the exclusion list phrases to terminalNounPhrase rules - |
| | 22717 | otherwise, when they exclude everything, they get misinterpreted as |
| | 22718 | ((all but x and y) and z) which turns into (z and z). Everything with |
| | 22719 | a 'but' should turn into a terminalNounPhrase, just like the plain |
| | 22720 | 'all but <list>' rule. |
| | 22721 | |
| | 22722 | </div> |
| | 22723 | |
| | 22724 | <!-------------------> |
| | 22725 | <div class=entry> |
| | 22726 | |
| | 22727 | Make 'me' symmetric with 'yourself' in the grammar. In particular, |
| | 22728 | 'me' should refer to the issuing actor, which is not necessarily the |
| | 22729 | player character. |
| | 22730 | |
| | 22731 | </div> |
| | 22732 | |
| | 22733 | <!-------------------> |
| | 22734 | <div class=entry> |
| | 22735 | |
| | 22736 | fix problem with "yourself, jump" |
| | 22737 | |
| | 22738 | </div> |
| | 22739 | |
| | 22740 | <!-------------------> |
| | 22741 | <div class=entry> |
| | 22742 | |
| | 22743 | For chairs and the like, we might want to consider an object owned |
| | 22744 | by an actor if the actor is occupying the object (so, "bob's chair" |
| | 22745 | is the chair bob is sitting on). |
| | 22746 | |
| | 22747 | </div> |
| | 22748 | |
| | 22749 | <!-------------------> |
| | 22750 | <div class=entry> |
| | 22751 | |
| | 22752 | When taking an item, reduce the likelihood that an item being carried |
| | 22753 | by another actor is the one being taken. |
| | 22754 | |
| | 22755 | </div> |
| | 22756 | |
| | 22757 | <!-------------------> |
| | 22758 | <div class=entry> |
| | 22759 | |
| | 22760 | Provide a way of distinguishing lit and unlit equivalents in a list. |
| | 22761 | Likewise for worn and unworn objects. Should probably add another |
| | 22762 | list group object after the equivalent grouper, and in this object |
| | 22763 | we should provide one group for lit objects and another for unlit. |
| | 22764 | The desired output is something like this: |
| | 22765 | |
| | 22766 | <p> |
| | 22767 | <pre> |
| | 22768 | You are carrying three matches (one lit), two flashlights (one |
| | 22769 | providing light). |
| | 22770 | </pre> |
| | 22771 | |
| | 22772 | </div> |
| | 22773 | |
| | 22774 | <!-------------------> |
| | 22775 | <div class=entry> |
| | 22776 | |
| | 22777 | Move the inheritNext into the behavior as the default native 'inherit' |
| | 22778 | instruction. Remove inheritNext from library source files. |
| | 22779 | |
| | 22780 | </div> |
| | 22781 | |
| | 22782 | <!-------------------> |
| | 22783 | <div class=entry> |
| | 22784 | |
| | 22785 | the dagger shouldn't show up in the 'x desk' description when the |
| | 22786 | dagger's initial message is still being shown |
| | 22787 | |
| | 22788 | </div> |
| | 22789 | |
| | 22790 | <!-------------------> |
| | 22791 | <div class=entry> |
| | 22792 | |
| | 22793 | Add macros to make grammar rules for predicates easier to read. |
| | 22794 | |
| | 22795 | </div> |
| | 22796 | |
| | 22797 | <!-------------------> |
| | 22798 | <div class=entry> |
| | 22799 | |
| | 22800 | Improve the module names (adv3g -> parser.t, adv3v -> verbs.t, etc) |
| | 22801 | |
| | 22802 | </div> |
| | 22803 | |
| | 22804 | <!-------------------> |
| | 22805 | <div class=entry> |
| | 22806 | |
| | 22807 | provide .t3m, .tdc for sample game with proper directory set-up |
| | 22808 | |
| | 22809 | </div> |
| | 22810 | |
| | 22811 | <!-------------------> |
| | 22812 | <div class=entry> |
| | 22813 | |
| | 22814 | accept 'all <adj>' and the like |
| | 22815 | |
| | 22816 | </div> |
| | 22817 | |
| | 22818 | <!-------------------> |
| | 22819 | <div class=entry> |
| | 22820 | |
| | 22821 | build the #include file list in Workbench automatically when creating |
| | 22822 | a project, and when explicitly asked via a new command "scan source |
| | 22823 | files for #include" |
| | 22824 | |
| | 22825 | </div> |
| | 22826 | |
| | 22827 | <!-------------------> |
| | 22828 | <div class=entry> |
| | 22829 | |
| | 22830 | compiler: warn on finding a backslash outside quoted text in front of |
| | 22831 | anything but a newline |
| | 22832 | |
| | 22833 | </div> |
| | 22834 | |
| | 22835 | <!-------------------> |
| | 22836 | <div class=entry> |
| | 22837 | |
| | 22838 | Add a simpler, more structured way to add a single paragraph break. |
| | 22839 | Use a new pseudo-tag, "<.p>", to indicate a paragraph break; process |
| | 22840 | this tag just before writing output to the console. |
| | 22841 | |
| | 22842 | </div> |
| | 22843 | |
| | 22844 | <!-------------------> |
| | 22845 | <div class=entry> |
| | 22846 | |
| | 22847 | All library input functions should coordinate with command reports to |
| | 22848 | turn off output capturing. |
| | 22849 | |
| | 22850 | </div> |
| | 22851 | |
| | 22852 | <!-------------------> |
| | 22853 | <div class=entry> |
| | 22854 | |
| | 22855 | Add a finishGame() function offering restart/restore/undo/quit options |
| | 22856 | |
| | 22857 | </div> |
| | 22858 | |
| | 22859 | <!-------------------> |
| | 22860 | <div class=entry> |
| | 22861 | |
| | 22862 | Build a proper set of Workbench sample games |
| | 22863 | |
| | 22864 | </div> |
| | 22865 | |
| | 22866 | <!-------------------> |
| | 22867 | <div class=entry> |
| | 22868 | |
| | 22869 | Freeze the real-time clock while we're waiting for inputFile results, |
| | 22870 | while we're saving/restoring a file, and while we're waiting for an |
| | 22871 | inputLine when real-time events are not allowed. All of these should |
| | 22872 | be considered to be outside the normal real-time flow of the game, |
| | 22873 | so none of them should consume any game real-time. |
| | 22874 | |
| | 22875 | </div> |
| | 22876 | |
| | 22877 | <!-------------------> |
| | 22878 | <div class=entry> |
| | 22879 | |
| | 22880 | In showList: mix groups and singles in the original order of lst, |
| | 22881 | rather than displaying groups and then singles separately. This is |
| | 22882 | important because we're not preserving the original ordering when |
| | 22883 | the list is sorted and it has subgroups. We can't guarantee |
| | 22884 | that we'll preserve the sorting order, of course, since grouping |
| | 22885 | could put together items that weren't consecutive in the sorting |
| | 22886 | order, so let grouping prevail when there's a conflict; but when |
| | 22887 | possible, keep the order the same. To do this, we should have |
| | 22888 | a single loop that traverses the original lst; for each item, if |
| | 22889 | it's a single, show the single, otherwise show its group. Only |
| | 22890 | show the group for the first item in the group; once we match a |
| | 22891 | group, mark the group as used so we don't show it again. |
| | 22892 | |
| | 22893 | </div> |
| | 22894 | |
| | 22895 | <!-------------------> |
| | 22896 | <div class=entry> |
| | 22897 | |
| | 22898 | '+' should consistently concatenate individual items from a |
| | 22899 | collection on the right-hand side, whether the right-hand side is a |
| | 22900 | list, vector, or array |
| | 22901 | |
| | 22902 | </div> |
| | 22903 | |
| | 22904 | <!-------------------> |
| | 22905 | <div class=entry> |
| | 22906 | |
| | 22907 | '+' and '-' should work with an Array as the left-hand side |
| | 22908 | |
| | 22909 | </div> |
| | 22910 | |
| | 22911 | <!-------------------> |
| | 22912 | <div class=entry> |
| | 22913 | |
| | 22914 | Delete class Array. We'll have to change the function object stuff |
| | 22915 | to use Vector instead of Array. |
| | 22916 | |
| | 22917 | </div> |
| | 22918 | |
| | 22919 | <!-------------------> |
| | 22920 | <div class=entry> |
| | 22921 | |
| | 22922 | Make Vector+val and Vector-val return new objects - do not modify the |
| | 22923 | original vector in place |
| | 22924 | |
| | 22925 | </div> |
| | 22926 | |
| | 22927 | <!-------------------> |
| | 22928 | <div class=entry> |
| | 22929 | |
| | 22930 | add Vector.appendAll() - appends list elements in-place; maybe |
| | 22931 | Vector.removeValue() and Vector.removeAllValues() to do '-' in-place |
| | 22932 | |
| | 22933 | </div> |
| | 22934 | |
| | 22935 | <!-------------------> |
| | 22936 | <div class=entry> |
| | 22937 | |
| | 22938 | LookupTable.forEach: remove the 'key' argument to make its interface |
| | 22939 | the same as everything else's. |
| | 22940 | |
| | 22941 | </div> |
| | 22942 | |
| | 22943 | <!-------------------> |
| | 22944 | <div class=entry> |
| | 22945 | |
| | 22946 | Everything with a forEach: add a forEachAssoc(key, val) method alongside |
| | 22947 | forEach. |
| | 22948 | |
| | 22949 | </div> |
| | 22950 | |
| | 22951 | <!-------------------> |
| | 22952 | <div class=entry> |
| | 22953 | |
| | 22954 | for Openable, if the object isn't transparent looking in, implicitly |
| | 22955 | open the object for "look in" |
| | 22956 | |
| | 22957 | </div> |
| | 22958 | |
| | 22959 | <!-------------------> |
| | 22960 | <div class=entry> |
| | 22961 | |
| | 22962 | Iterators: add getCurVal and getCurKey methods. |
| | 22963 | |
| | 22964 | </div> |
| | 22965 | |
| | 22966 | <!-------------------> |
| | 22967 | <div class=entry> |
| | 22968 | |
| | 22969 | Fix bug: 'listen' or 'smell' shows no response when there are things |
| | 22970 | that nominally have Noise/Odor associations, but none of the Noise/Odor |
| | 22971 | objects actually has anything to say at the moment. |
| | 22972 | |
| | 22973 | </div> |
| | 22974 | |
| | 22975 | <!-------------------> |
| | 22976 | <div class=entry> |
| | 22977 | |
| | 22978 | Dictionary: add a way to iterate over the entries in the dictionary. |
| | 22979 | |
| | 22980 | </div> |
| | 22981 | |
| | 22982 | <!-------------------> |
| | 22983 | <div class=entry> |
| | 22984 | |
| | 22985 | For inputManager.inputLineBegin and inputLineEnd, use a new style tag |
| | 22986 | "<.inputline>" rather than coding "<font face=tads-input>" directly. |
| | 22987 | This makes it easier for a game to customize the input font setting. |
| | 22988 | |
| | 22989 | </div> |
| | 22990 | |
| | 22991 | <!-------------------> |
| | 22992 | <div class=entry> |
| | 22993 | |
| | 22994 | Add access to the "restore code" (the second argument passed to |
| | 22995 | restoreGame()) for PostRestoreObject instances by adding the value as |
| | 22996 | a class property of PostRestoreObject. |
| | 22997 | |
| | 22998 | </div> |
| | 22999 | |
| | 23000 | <!-------------------> |
| | 23001 | <div class=entry> |
| | 23002 | |
| | 23003 | Change the Thing template that ends with "desc" @location to end |
| | 23004 | instead with @location "desc" (i.e., reverse the desc and location |
| | 23005 | property order). Since "desc" can be lengthy, putting the location |
| | 23006 | first will make the template more readable. |
| | 23007 | |
| | 23008 | </div> |
| | 23009 | |
| | 23010 | <!-------------------> |
| | 23011 | <div class=entry> |
| | 23012 | |
| | 23013 | Add before/after command separation messages in libMessages, to allow |
| | 23014 | for finer-grained control over the formatting of command responses. |
| | 23015 | |
| | 23016 | </div> |
| | 23017 | |
| | 23018 | <!-------------------> |
| | 23019 | <div class=entry> |
| | 23020 | |
| | 23021 | Check dark travel before checking any barriers - move the call to |
| | 23022 | gActor.checkDarkTravel into the TravelConnector methods that call |
| | 23023 | gActor.travelTo, since this must be called as a separate phase before |
| | 23024 | the travel connectors do any of their other work. |
| | 23025 | |
| | 23026 | </div> |
| | 23027 | |
| | 23028 | <!-------------------> |
| | 23029 | <div class=entry> |
| | 23030 | |
| | 23031 | Make Illogical() the most illogical ranking, and make IllogicalNow() |
| | 23032 | slightly less illogical (i.e., invert the old ordering of Illogical |
| | 23033 | and IllogicalNow). |
| | 23034 | |
| | 23035 | </div> |
| | 23036 | |
| | 23037 | <!-------------------> |
| | 23038 | <div class=entry> |
| | 23039 | |
| | 23040 | Add Action.setMessageParam(), to allow message processors to set |
| | 23041 | their own special message parameters that they can use in expansion |
| | 23042 | text. This would be better than constructing messages partially with |
| | 23043 | the "{it obj/him}" mechanism and brute-force string concatenation, |
| | 23044 | because it would allow the concatenated bits to participate in the |
| | 23045 | same processing steps, such as reflexive pronoun conversions. |
| | 23046 | |
| | 23047 | <p> |
| | 23048 | Add a macro (gMessageParams) to simplify the syntax for adding new |
| | 23049 | message parameters. |
| | 23050 | |
| | 23051 | </div> |
| | 23052 | |
| | 23053 | <!-------------------> |
| | 23054 | <div class=entry> |
| | 23055 | |
| | 23056 | "x me" doesn't work in dark (target actor of a command should always |
| | 23057 | be in scope) |
| | 23058 | |
| | 23059 | </div> |
| | 23060 | |
| | 23061 | <!-------------------> |
| | 23062 | <div class=entry> |
| | 23063 | |
| | 23064 | Remove 'actorResolved' check from execCommandTokens - this check is |
| | 23065 | vestigial (it stopped being necessary when we started pulling out the |
| | 23066 | actor phrase after resolution and re-parsing the rest of the command), |
| | 23067 | and makes it impossible to have multiple levels of indirection, as in |
| | 23068 | "tell bob to tell bill to go north". |
| | 23069 | |
| | 23070 | </div> |
| | 23071 | |
| | 23072 | <!-------------------> |
| | 23073 | <div class=entry> |
| | 23074 | |
| | 23075 | Refactor FirstCommandProdWithActor (parser.t) to move the actor resolution |
| | 23076 | stuff into a separate CommandProdWithActor that FCPWA inherits from. |
| | 23077 | |
| | 23078 | </div> |
| | 23079 | |
| | 23080 | <!-------------------> |
| | 23081 | <div class=entry> |
| | 23082 | |
| | 23083 | <pre> |
| | 23084 | >bob, get ball |
| | 23085 | Which ball? |
| | 23086 | |
| | 23087 | >z |
| | 23088 | Bob waits... |
| | 23089 | </pre> |
| | 23090 | |
| | 23091 | <p> |
| | 23092 | The "z" should have a default target of the player character, not Bob. |
| | 23093 | |
| | 23094 | </div> |
| | 23095 | |
| | 23096 | <!-------------------> |
| | 23097 | <div class=entry> |
| | 23098 | |
| | 23099 | Allow things like "tell bill to tell bob to go north". In particular, |
| | 23100 | fix execCommandTokens so that it doesn't assume that only one actor can |
| | 23101 | be resolved per command. |
| | 23102 | |
| | 23103 | </div> |
| | 23104 | |
| | 23105 | <!-------------------> |
| | 23106 | <div class=entry> |
| | 23107 | |
| | 23108 | Keep first-on-line information in the PendingCommandInfo. (This requires |
| | 23109 | changing the interfaces to all of the Actor routines that create pending |
| | 23110 | command info objects: addPendingCommand, addFirstPendingCommand, |
| | 23111 | addPendingAction, addFirstPendingAction.) |
| | 23112 | |
| | 23113 | </div> |
| | 23114 | |
| | 23115 | <!-------------------> |
| | 23116 | <div class=entry> |
| | 23117 | |
| | 23118 | Add a noun-list grammar rule for singleNoun, so that if we match a |
| | 23119 | noun list in a place where a single noun is grammatically required, |
| | 23120 | we can generate an appropriate message rather than failing to match |
| | 23121 | grammar. |
| | 23122 | |
| | 23123 | <p> |
| | 23124 | Symptoms fixed: "ask bob and bill about box" -> "you see no bob and |
| | 23125 | bill here"; "give coins to bob and bill" -> "you see no coins to here". |
| | 23126 | |
| | 23127 | </div> |
| | 23128 | |
| | 23129 | <!-------------------> |
| | 23130 | <div class=entry> |
| | 23131 | |
| | 23132 | Add a point-of-view argument to BasicLocation.lookAround, so that a |
| | 23133 | room can be described from a point of view other than the actor doing |
| | 23134 | the looking. |
| | 23135 | |
| | 23136 | </div> |
| | 23137 | |
| | 23138 | <!-------------------> |
| | 23139 | <div class=entry> |
| | 23140 | |
| | 23141 | Fix: paragraph break in response to getting out of white box while |
| | 23142 | the box is closed (in the platform room). (The last report - |
| | 23143 | "Okay..." - is displayed on the same line as the beeper noise.) |
| | 23144 | |
| | 23145 | </div> |
| | 23146 | |
| | 23147 | <!-------------------> |
| | 23148 | <div class=entry> |
| | 23149 | |
| | 23150 | Can we make every kind of noun phrase production derive from a common |
| | 23151 | NounPhraseProd base class? |
| | 23152 | |
| | 23153 | </div> |
| | 23154 | |
| | 23155 | <!-------------------> |
| | 23156 | <div class=entry> |
| | 23157 | |
| | 23158 | Allow multiple actors per command line, tads2-style, as in "bob, go |
| | 23159 | north. look. bill, go south." (In tads 2, a new actor can be |
| | 23160 | specified after a period.) However, only allow this in "synchronous" |
| | 23161 | mode, where the issuing actor waits for all commands to NPC's to |
| | 23162 | complete before taking another turn; in asynchronous mode, do not |
| | 23163 | allow mid-command target actor changes, because it's too confusing. |
| | 23164 | |
| | 23165 | </div> |
| | 23166 | |
| | 23167 | <!-------------------> |
| | 23168 | <div class=entry> |
| | 23169 | |
| | 23170 | Fix problem in touchObj precondition: we assume that we can find a |
| | 23171 | valid touch path, so we traverse the path without checking to see if |
| | 23172 | we got a nil path. In some cases (such as when the target object is |
| | 23173 | in a location not sharing any common container with the actor), there |
| | 23174 | is no touch path at all, so we need to deal properly with this |
| | 23175 | possibility. |
| | 23176 | |
| | 23177 | </div> |
| | 23178 | |
| | 23179 | <!-------------------> |
| | 23180 | <div class=entry> |
| | 23181 | |
| | 23182 | Fix visual command separation for 'undo' after a multi-command line, |
| | 23183 | and for a multi-undo command line. |
| | 23184 | |
| | 23185 | </div> |
| | 23186 | |
| | 23187 | <!-------------------> |
| | 23188 | <div class=entry> |
| | 23189 | |
| | 23190 | Modify/replace/delete grammar rules. Add new syntax: |
| | 23191 | |
| | 23192 | <p> |
| | 23193 | <pre> |
| | 23194 | modify grammar production(tag): <new-grammar-rule>: |
| | 23195 | <property-list> |
| | 23196 | ; |
| | 23197 | replace grammar production(tag): <new-grammar-rule>: <class> |
| | 23198 | <property-list> |
| | 23199 | ; |
| | 23200 | </pre> |
| | 23201 | |
| | 23202 | <p> |
| | 23203 | To make this workable, the "production(tag)" names of grammar match |
| | 23204 | objects must be unique; change the compiler to enforce uniqueness of |
| | 23205 | these names. |
| | 23206 | |
| | 23207 | <p> |
| | 23208 | Also, change VerbRule to include a tag: VerbRule(tag). This will |
| | 23209 | allow modify/replace to be used with VerbRule(tag) definitions to |
| | 23210 | replace library verb grammar rules. |
| | 23211 | |
| | 23212 | </div> |
| | 23213 | |
| | 23214 | <!-------------------> |
| | 23215 | <div class=entry> |
| | 23216 | |
| | 23217 | Add a mechanism for remapping a two-noun-phrase action to a different |
| | 23218 | action after resolving first object. For example, allow mapping |
| | 23219 | ATTACK x WITH THROWING STAR to THROW THROWING STAR AT x. |
| | 23220 | |
| | 23221 | <p> |
| | 23222 | To do this, add a new pair of properties to TIAction: remapDobjProp |
| | 23223 | and remapIobjProp; define these properties using the same template |
| | 23224 | style as the rest of the properties in DefineTIAction. Add a new |
| | 23225 | remapTIAction() macro that can be used from within a remap() method |
| | 23226 | to remap a command. |
| | 23227 | |
| | 23228 | <p> |
| | 23229 | Note that only the first-resolved object can be remapped, because the |
| | 23230 | whole point is to effect the remapping before resolving the |
| | 23231 | second-resolved object, so that the second-resolved object can be |
| | 23232 | resolved using the rules of the new action rather than of the |
| | 23233 | original action. |
| | 23234 | |
| | 23235 | </div> |
| | 23236 | |
| | 23237 | <!-------------------> |
| | 23238 | <div class=entry> |
| | 23239 | |
| | 23240 | In BasicLocation.lookAround, remove the point-of-view object from |
| | 23241 | the list of objects to be described, rather than removing the actor. |
| | 23242 | |
| | 23243 | </div> |
| | 23244 | |
| | 23245 | <!-------------------> |
| | 23246 | <div class=entry> |
| | 23247 | |
| | 23248 | Move the grammar convenience macros (VerbRule, SingleDobj, etc) out |
| | 23249 | of adv3.h and into us_eng.h - these are all specific to the English |
| | 23250 | verb grammar, so they should be in the English-specific definitions |
| | 23251 | rather than the language-independent definitions. |
| | 23252 | |
| | 23253 | </div> |
| | 23254 | |
| | 23255 | <!-------------------> |
| | 23256 | <div class=entry> |
| | 23257 | |
| | 23258 | If a Daemon is created with an interval of zero or less, it'll put |
| | 23259 | the scheduler into an infinite loop invoking the daemon, because the |
| | 23260 | daemon will be permanently schedulable. Force the interval to at |
| | 23261 | least 1 on creation. |
| | 23262 | |
| | 23263 | </div> |
| | 23264 | |
| | 23265 | <!-------------------> |
| | 23266 | <div class=entry> |
| | 23267 | |
| | 23268 | Add a lookAround() method to Thing, to generate a description from |
| | 23269 | the point of view of the Thing. This is necessary to allow things |
| | 23270 | like remote cameras. This method should call the container's |
| | 23271 | lookAroundPov() method (which must also be added to Thing) with the |
| | 23272 | point of view set self; this algorithm will eventually reach the |
| | 23273 | innermost room-like object, which will display the appropriate |
| | 23274 | room-like description. |
| | 23275 | |
| | 23276 | </div> |
| | 23277 | |
| | 23278 | <!-------------------> |
| | 23279 | <div class=entry> |
| | 23280 | |
| | 23281 | Add a PAUSE command, to stop the real-time clock for games that |
| | 23282 | use real-time events. |
| | 23283 | |
| | 23284 | </div> |
| | 23285 | |
| | 23286 | <!-------------------> |
| | 23287 | <div class=entry> |
| | 23288 | |
| | 23289 | Add a grammar notation that specifies a match for one of several |
| | 23290 | vocabulary properties. With the '<prod>' grammar that was being |
| | 23291 | kicked around for a while, the notation '<noun | adjective>' was |
| | 23292 | appealing, but without the angle brackets, it's not obvious what the |
| | 23293 | equivalent syntax would be. |
| | 23294 | |
| | 23295 | <p> |
| | 23296 | Use angle-bracket notation, even though we don't use it for |
| | 23297 | individual tokens: <nounM nounN nounF> |
| | 23298 | |
| | 23299 | </div> |
| | 23300 | |
| | 23301 | <!-------------------> |
| | 23302 | <div class=entry> |
| | 23303 | |
| | 23304 | Add an explicit 'grammar' declaration with no matchable rules, so that |
| | 23305 | production names can be declared without actually creating rules for |
| | 23306 | them. |
| | 23307 | |
| | 23308 | </div> |
| | 23309 | |
| | 23310 | <!-------------------> |
| | 23311 | <div class=entry> |
| | 23312 | |
| | 23313 | make 'inherited' after 'delegated' more consistent with the regular |
| | 23314 | inheritance behavior (in particular, the relatively new dynamic |
| | 23315 | inheritance search algorithm will fail to find a class related to |
| | 23316 | 'self' in the delegatee's superclass tree, so there will be nothing |
| | 23317 | to inherit; ideally, we'd have an 'inheritance target' in the stack |
| | 23318 | frame in addition to 'self') |
| | 23319 | |
| | 23320 | </div> |
| | 23321 | |
| | 23322 | <!-------------------> |
| | 23323 | <div class=entry> |
| | 23324 | |
| | 23325 | NestedRoom.getTravelConnector refers to gActor. The reason the method |
| | 23326 | looks at gActor is that it wants to check if the actor can see the |
| | 23327 | containing room, so that it can get the connector from the containing |
| | 23328 | room. Add an 'actor' parameter to getTravelConnector(), so that we |
| | 23329 | can specify an actor explicitly and thus ask for travel connectors |
| | 23330 | outside of turn execution contexts. |
| | 23331 | |
| | 23332 | </div> |
| | 23333 | |
| | 23334 | <!-------------------> |
| | 23335 | <div class=entry> |
| | 23336 | |
| | 23337 | SouthwestAction is missing from action.t |
| | 23338 | |
| | 23339 | </div> |
| | 23340 | |
| | 23341 | <!-------------------> |
| | 23342 | <div class=entry> |
| | 23343 | |
| | 23344 | noTravelIn, noTravelOut, noTravelDown - these need to override |
| | 23345 | isConnectorApparent to return nil. |
| | 23346 | |
| | 23347 | <p> |
| | 23348 | Add redirectTravelIn, etc, which do show isConnectorApparent = true. |
| | 23349 | |
| | 23350 | </div> |
| | 23351 | |
| | 23352 | <!-------------------> |
| | 23353 | <div class=entry> |
| | 23354 | |
| | 23355 | Add newActionObj alongside _newAction: the new function takes a |
| | 23356 | pre-created action instance, rather than creating a new instance |
| | 23357 | itself. |
| | 23358 | |
| | 23359 | </div> |
| | 23360 | |
| | 23361 | <!-------------------> |
| | 23362 | <div class=entry> |
| | 23363 | |
| | 23364 | Add a getBestMatch() method to ResolvedTopic to retrieve the |
| | 23365 | top-ranking object. By default, provide an implementation that simply |
| | 23366 | returns an arbitrary object from the strongest match list. Games and |
| | 23367 | library extensions could customize this to use a different topic |
| | 23368 | picker mechanism as desired, but providing a decent default |
| | 23369 | implementation would help authors get started without having to worry |
| | 23370 | about coding their own topic framework if they didn't want anything |
| | 23371 | specific here. |
| | 23372 | |
| | 23373 | </div> |
| | 23374 | |
| | 23375 | <!-------------------> |
| | 23376 | <div class=entry> |
| | 23377 | |
| | 23378 | Add a PreRestartObject, analogous to PreSaveObject, to allow any special |
| | 23379 | actions to be performed before a restart. |
| | 23380 | |
| | 23381 | </div> |
| | 23382 | |
| | 23383 | <!-------------------> |
| | 23384 | <div class=entry> |
| | 23385 | |
| | 23386 | execCommandTokens should probably switch the sense context upon |
| | 23387 | discovering a target actor different from the issuing actor, before |
| | 23388 | actually starting to execute the command. |
| | 23389 | |
| | 23390 | </div> |
| | 23391 | |
| | 23392 | <!-------------------> |
| | 23393 | <div class=entry> |
| | 23394 | |
| | 23395 | Move all of the output management into discrete OutputStream objects. |
| | 23396 | Associate filters, notifiers, capturers with individual streams. By |
| | 23397 | default, create one stream for the main text and another for the |
| | 23398 | status line. |
| | 23399 | |
| | 23400 | <p> |
| | 23401 | <b>NOTE:</b> This change affects all of the notifier, filter, monitor, and |
| | 23402 | capturer function interfaces. All of these formerly global functions |
| | 23403 | are now methods of the OutputStream class. |
| | 23404 | |
| | 23405 | </div> |
| | 23406 | |
| | 23407 | <!-------------------> |
| | 23408 | <div class=entry> |
| | 23409 | |
| | 23410 | Regarding touch path calculation (see e.g. touchObj precondition): |
| | 23411 | should we be finding a touch path to an object in a separate location |
| | 23412 | not connected by containment, but connected by a SenseConnector? |
| | 23413 | |
| | 23414 | </div> |
| | 23415 | |
| | 23416 | <!-------------------> |
| | 23417 | <div class=entry> |
| | 23418 | |
| | 23419 | Fix basicScoreChange reporting for changes of 1 (or -1) points: use |
| | 23420 | singular "point". |
| | 23421 | |
| | 23422 | </div> |
| | 23423 | |
| | 23424 | <!-------------------> |
| | 23425 | <div class=entry> |
| | 23426 | |
| | 23427 | change the T3 Workbench .tdc format to use .t3m files |
| | 23428 | |
| | 23429 | </div> |
| | 23430 | |
| | 23431 | <!-------------------> |
| | 23432 | <div class=entry> |
| | 23433 | |
| | 23434 | vmrun: respond to Ctrl+Break to break into debugger |
| | 23435 | |
| | 23436 | </div> |
| | 23437 | |
| | 23438 | <!-------------------> |
| | 23439 | <div class=entry> |
| | 23440 | |
| | 23441 | "parse-debug" command: accept the command without the "on" or "off" |
| | 23442 | specifier, and simply invert the current mode. |
| | 23443 | |
| | 23444 | </div> |
| | 23445 | |
| | 23446 | <!-------------------> |
| | 23447 | <div class=entry> |
| | 23448 | |
| | 23449 | Add a nounMultiList production alongside nounList. Use this |
| | 23450 | production in matching singleNoun, rather than using the regular |
| | 23451 | nounList, so that we don't create spurious additional matches for the |
| | 23452 | degenerate single noun phrase form of nounList. |
| | 23453 | |
| | 23454 | </div> |
| | 23455 | |
| | 23456 | <!-------------------> |
| | 23457 | <div class=entry> |
| | 23458 | |
| | 23459 | For bags of holding, check (in Container.tryPuttingObjInBag) to make |
| | 23460 | sure that the object being moved into the bag actually fits, and |
| | 23461 | don't even try if it won't. This will avoid spurious attempts and |
| | 23462 | failures to move things in to a bag of holding implicitly after the |
| | 23463 | bag becomes full. |
| | 23464 | |
| | 23465 | </div> |
| | 23466 | |
| | 23467 | <!-------------------> |
| | 23468 | <div class=entry> |
| | 23469 | |
| | 23470 | Refactor the CommandProd-based productions in parser.t to move the |
| | 23471 | methods into new classes, and base the defined grammars on the |
| | 23472 | classes. This will facilitate adding new commandPhrase grammar rules |
| | 23473 | by allowing the existing behavior to be re-used via inheritance. |
| | 23474 | |
| | 23475 | </div> |
| | 23476 | |
| | 23477 | <!-------------------> |
| | 23478 | <div class=entry> |
| | 23479 | |
| | 23480 | Add a new Actor property (revertTargetActorAtEndOfSentence) that, when |
| | 23481 | set, tells the parser to consider target actor designations ("bob, go |
| | 23482 | north...") in effect only until the end of a sentence. When the |
| | 23483 | property is set to true, switch the target actor back to the original |
| | 23484 | issuing actor at the end of each sentence. |
| | 23485 | |
| | 23486 | </div> |
| | 23487 | |
| | 23488 | <!-------------------> |
| | 23489 | <div class=entry> |
| | 23490 | |
| | 23491 | As a convenience, add a new StyleTag subclass, HtmlStyleTag, for tags |
| | 23492 | with different renderings in HTML and plain text modes. |
| | 23493 | |
| | 23494 | </div> |
| | 23495 | |
| | 23496 | <!-------------------> |
| | 23497 | <div class=entry> |
| | 23498 | |
| | 23499 | Add some new style tags: |
| | 23500 | |
| | 23501 | <ul> |
| | 23502 | <li><.a> - for <a> text (and use it for |
| | 23503 | all links we generate) |
| | 23504 | |
| | 23505 | <li><.statusroom> - for the room name portion of |
| | 23506 | the status line |
| | 23507 | |
| | 23508 | <li><.statusscore> - for the score/turn count |
| | 23509 | portion of the status line |
| | 23510 | </ul> |
| | 23511 | |
| | 23512 | </div> |
| | 23513 | |
| | 23514 | <!-------------------> |
| | 23515 | <div class=entry> |
| | 23516 | |
| | 23517 | Add inputManager methods getKey() and getEvent() that provide covers |
| | 23518 | for inputKey() and inputEvent(), respectively, the integrate with the |
| | 23519 | real-time manager and the reports gatherer in the same manner as |
| | 23520 | inputLine. |
| | 23521 | |
| | 23522 | </div> |
| | 23523 | |
| | 23524 | <!-------------------> |
| | 23525 | <div class=entry> |
| | 23526 | |
| | 23527 | Don't use [badness] to reduce the priority of ordinal lists in |
| | 23528 | disambiguation responses; instead, use the ranking mechanism to give |
| | 23529 | ordinals a lower ranking than noun/adjective interpretations. |
| | 23530 | |
| | 23531 | </div> |
| | 23532 | |
| | 23533 | <!-------------------> |
| | 23534 | <div class=entry> |
| | 23535 | |
| | 23536 | Fix looping problem with answering 'g' to disambiguation queries. |
| | 23537 | (Don't store the response to a disambiguation query until after we |
| | 23538 | actually know that the input is an answer to the query, as opposed to |
| | 23539 | a new command.) |
| | 23540 | |
| | 23541 | </div> |
| | 23542 | |
| | 23543 | <!-------------------> |
| | 23544 | <div class=entry> |
| | 23545 | |
| | 23546 | Do not notify sense path in moveInto() when traveling. (Travel uses |
| | 23547 | the separate TravelConnector mechanism, which doesn't necessarily map |
| | 23548 | directly onto sense connections; we don't want to attempt to notify |
| | 23549 | sense connections of travel because we don't actually use them for |
| | 23550 | travel.) |
| | 23551 | |
| | 23552 | </div> |
| | 23553 | |
| | 23554 | <!-------------------> |
| | 23555 | <div class=entry> |
| | 23556 | |
| | 23557 | When disambiguating interactively, if the response isn't in the full |
| | 23558 | list, check to see if it's in the full scope list. This allows for |
| | 23559 | cases where the player really wants to try a command on something |
| | 23560 | that we decide isn't logical - it's better to let the player try than |
| | 23561 | to deny that the object is among the possible choices. |
| | 23562 | |
| | 23563 | <p> |
| | 23564 | We should test the scope list as a second pass rather than allowing |
| | 23565 | the full scope on the first pass. So, we should try first as we do |
| | 23566 | now, limiting scope to the narrowed ("logical") list; then, if that |
| | 23567 | fails, we should try again with the full scope list. |
| | 23568 | |
| | 23569 | </div> |
| | 23570 | |
| | 23571 | <!-------------------> |
| | 23572 | <div class=entry> |
| | 23573 | |
| | 23574 | Add an equivalent of the tads 2 "->" syntax: this syntax allowed |
| | 23575 | routing messages for one object to another object. For example, if |
| | 23576 | we wanted to route "open desk" to "open drawer", we would put "doOpen |
| | 23577 | -> drawer" in the desk. Define a new macro: |
| | 23578 | |
| | 23579 | <p> |
| | 23580 | <pre> |
| | 23581 | dobjForwardTo(Open, drawer) |
| | 23582 | </pre> |
| | 23583 | |
| | 23584 | <p> |
| | 23585 | This is used <i>in place of</i> a dobjFor(). |
| | 23586 | |
| | 23587 | <p> |
| | 23588 | (This was from Phil Lewis, who suggested "reroute" as the name and |
| | 23589 | also suggested a slightly more general format: dobjReroute(drawer, |
| | 23590 | Open). It might also be useful to be able to specify the verb to |
| | 23591 | forward separately, so that you could handle a verb with both a |
| | 23592 | different verb and different target object, but the action is |
| | 23593 | probably the same in most cases, so it seems more convenient to be |
| | 23594 | able to omit it.) |
| | 23595 | |
| | 23596 | </div> |
| | 23597 | |
| | 23598 | <!-------------------> |
| | 23599 | <div class=entry> |
| | 23600 | |
| | 23601 | In roomSmellLister (and roomListenLister), add a custom isListed |
| | 23602 | method that checks a new property of the target object, |
| | 23603 | isSmellListedInRoom (isSoundListedInRoom in the case of Noise |
| | 23604 | objects). Set these properties to true by default. Add an isListed |
| | 23605 | override to smellActionLister (and listenActionLister) that simply |
| | 23606 | returns true. This change allows an Odor/Noise to list in response |
| | 23607 | to a >SMELL or >LISTEN without also showing in the normal room |
| | 23608 | description, as it would by default. |
| | 23609 | |
| | 23610 | </div> |
| | 23611 | |
| | 23612 | <!-------------------> |
| | 23613 | <div class=entry> |
| | 23614 | |
| | 23615 | Propagate the results of an action up to callers by returning the |
| | 23616 | CommandReportList. Actually, we'll have to return a list of |
| | 23617 | CommandReportList objects, since one CommandReportList is generated |
| | 23618 | per iteration for an iterated action. The aggregate list could be |
| | 23619 | stored in a CommandResults object, which could provide high-level |
| | 23620 | analysis methods (e.g., isFailure()) to interpret the action results. |
| | 23621 | |
| | 23622 | <p> |
| | 23623 | To do this, return a CommandResults object describing the command |
| | 23624 | reports list from newAction(), nestedAction(), and so on. |
| | 23625 | |
| | 23626 | </div> |
| | 23627 | |
| | 23628 | <!-------------------> |
| | 23629 | <div class=entry> |
| | 23630 | |
| | 23631 | Provide a way of specifying a subclass of CommandReportList to use |
| | 23632 | when executing a new or nested command. To do this, callers use |
| | 23633 | a new function that takes a particular CommandReportList subclass |
| | 23634 | to use while calling a callback: |
| | 23635 | |
| | 23636 | <p> |
| | 23637 | <pre> |
| | 23638 | result = withCommandReportsClass( |
| | 23639 | MyCommandReportList, {: nestedActorAction(bob, SitOn, chair) }); |
| | 23640 | </pre> |
| | 23641 | |
| | 23642 | </div> |
| | 23643 | |
| | 23644 | <!-------------------> |
| | 23645 | <div class=entry> |
| | 23646 | |
| | 23647 | In the tokenizer, if a word with a "'s" suffix explicitly appears in |
| | 23648 | the dictionary with the "'s", do NOT make the "'s" into a separate |
| | 23649 | token - keep the whole string with the "'s" as a single token. This |
| | 23650 | allows for cases where the grammar has a literal token with a "'s" |
| | 23651 | suffix, and where vocabulary words (such as adjectives) are |
| | 23652 | explicitly defined with "'s" suffixes. |
| | 23653 | |
| | 23654 | </div> |
| | 23655 | |
| | 23656 | <!-------------------> |
| | 23657 | <div class=entry> |
| | 23658 | |
| | 23659 | In TravelConnector, allow for a single barrier rather than a list |
| | 23660 | of barriers. If the travelBarrier property is not a Collection of |
| | 23661 | some kind, treat it as a single TravelBarrier. |
| | 23662 | |
| | 23663 | </div> |
| | 23664 | |
| | 23665 | <!-------------------> |
| | 23666 | <div class=entry> |
| | 23667 | |
| | 23668 | Add a OneWayRoomConnector to make it easier to define a connector |
| | 23669 | that connects one room to another but not vice versa.f |
| | 23670 | |
| | 23671 | </div> |
| | 23672 | |
| | 23673 | <!-------------------> |
| | 23674 | <div class=entry> |
| | 23675 | |
| | 23676 | Add checkTravelConditions() to TravelConnector. Call this from |
| | 23677 | checkTravelBarriers(). By default, this does nothing; instances |
| | 23678 | can override it to apply special conditions to the travel in lieu |
| | 23679 | of creating a separate TravelBarrier object when the conditions |
| | 23680 | don't need to be re-used in other connectors. |
| | 23681 | |
| | 23682 | </div> |
| | 23683 | |
| | 23684 | <!-------------------> |
| | 23685 | <div class=entry> |
| | 23686 | |
| | 23687 | Fix indentation problem for grouped items in INVENTORY TALL lists. |
| | 23688 | |
| | 23689 | </div> |
| | 23690 | |
| | 23691 | <!-------------------> |
| | 23692 | <div class=entry> |
| | 23693 | |
| | 23694 | Hide intangibles from 'all' by default. Noises and odors should |
| | 23695 | probably be included in 'all' for LISTEN/SMELL. |
| | 23696 | |
| | 23697 | </div> |
| | 23698 | |
| | 23699 | <!-------------------> |
| | 23700 | <div class=entry> |
| | 23701 | |
| | 23702 | When trying to put objects into a bag of holding to make room to take |
| | 23703 | a new object, don't even try moving an object that contains the bag |
| | 23704 | of holding (because doing so will just fail with a message "the <bag |
| | 23705 | of holding> is already in that"). |
| | 23706 | |
| | 23707 | </div> |
| | 23708 | |
| | 23709 | <!-------------------> |
| | 23710 | <div class=entry> |
| | 23711 | |
| | 23712 | Need a better way to say "the one in the room" than showing the room |
| | 23713 | name, because that's not useful in input. Should say something |
| | 23714 | like "the match on the floor". |
| | 23715 | |
| | 23716 | </div> |
| | 23717 | |
| | 23718 | <!-------------------> |
| | 23719 | <div class=entry> |
| | 23720 | |
| | 23721 | Once everything in a disambiguation list is a basic equivalent, we |
| | 23722 | could use the 'name' of the objects to display the prompt, rather |
| | 23723 | than using the input text. |
| | 23724 | |
| | 23725 | </div> |
| | 23726 | |
| | 23727 | <!-------------------> |
| | 23728 | <div class=entry> |
| | 23729 | |
| | 23730 | In Thing.initializeEquivalent, deal with the possibility that we have |
| | 23731 | a base class with a separate equivalent grouper. Create a separate |
| | 23732 | grouper for the subclass by testing to see if equivalentGrouper is |
| | 23733 | defined <i>directly</i> by the class object. If there is an inherited |
| | 23734 | grouper, we must create our own separate grouper for the subclass, |
| | 23735 | AND we must take the superclass grouper out of the listWith for the |
| | 23736 | subclass (since it will inherit the base class listWith by default). |
| | 23737 | |
| | 23738 | </div> |
| | 23739 | |
| | 23740 | <!-------------------> |
| | 23741 | <div class=entry> |
| | 23742 | |
| | 23743 | In action.t around line 1532, when we're adding the UnclearDisambig |
| | 23744 | flag, we might want to suppress the flag if the object we selected |
| | 23745 | and the objects we rejected are basic equivalents of one another. |
| | 23746 | This avoids weird situations such as |
| | 23747 | |
| | 23748 | <p> |
| | 23749 | <pre> |
| | 23750 | >light match |
| | 23751 | (the match) |
| | 23752 | </pre> |
| | 23753 | |
| | 23754 | <p> |
| | 23755 | when we have one match we're holding and another in the matchbook: |
| | 23756 | we choose the one we're holding over the one in the matchbook because |
| | 23757 | of the must-be-holding precondition to lighting a match, but mentioning |
| | 23758 | which one we're choosing is weird because it doesn't tell us anything. |
| | 23759 | |
| | 23760 | </div> |
| | 23761 | |
| | 23762 | <!-------------------> |
| | 23763 | <div class=entry> |
| | 23764 | |
| | 23765 | <pre> |
| | 23766 | >drop match |
| | 23767 | Which match, one of your matches, or the match in the matchbook? |
| | 23768 | |
| | 23769 | >my match |
| | 23770 | Which match, one of your matches, or the match in the matchbook? |
| | 23771 | </pre> |
| | 23772 | |
| | 23773 | <p> |
| | 23774 | ...etc. The problem is that we're taking "my match" to mean any |
| | 23775 | match in my possession for parsing purposes, whereas we differentiate |
| | 23776 | holding from indirectly owned. Ideally, we'd prefer to treat "my |
| | 23777 | match" as "the match I'm holding directly" when it's ambiguous. |
| | 23778 | |
| | 23779 | </div> |
| | 23780 | |
| | 23781 | <!-------------------> |
| | 23782 | <div class=entry> |
| | 23783 | |
| | 23784 | Add a disambigName property, and use it instead of the ordinary name |
| | 23785 | when generating disambiguation prompts. (We'll need aDisambigName, |
| | 23786 | theDisambigName, and countDisambigName as well to round out the set.) |
| | 23787 | |
| | 23788 | </div> |
| | 23789 | |
| | 23790 | <!-------------------> |
| | 23791 | <div class=entry> |
| | 23792 | |
| | 23793 | Add "x in y" grammar. |
| | 23794 | |
| | 23795 | </div> |
| | 23796 | |
| | 23797 | <!-------------------> |
| | 23798 | <div class=entry> |
| | 23799 | |
| | 23800 | Add a mechanism for distinguishing equivalents with different states: |
| | 23801 | |
| | 23802 | <p> |
| | 23803 | <pre> |
| | 23804 | Which candle to you mean, the lit candle or the unlit candle? |
| | 23805 | |
| | 23806 | -but not- |
| | 23807 | Which wax do you mean, the unlit candle or the seal? |
| | 23808 | -which should just be |
| | 23809 | Which wax do you mean, the candle or the seal? |
| | 23810 | </pre> |
| | 23811 | |
| | 23812 | <p> |
| | 23813 | Use this mechanism to create a base class for light sources. We |
| | 23814 | can use this for things like matches and candles. The disambig |
| | 23815 | name for an object is "lit x" or "unlit x", so we add the adjective |
| | 23816 | "lit" or "unlit" according to state. Check the adjective in parseName. |
| | 23817 | |
| | 23818 | <p> |
| | 23819 | Use this same mechanism to specify by owner when owner is a |
| | 23820 | distinguishing factor - "which gas mask do you mean, yours, or |
| | 23821 | teeterwaller's?" |
| | 23822 | |
| | 23823 | <p> |
| | 23824 | To do this, associate with each object a list of "distinguisher" |
| | 23825 | objects. A candle might include the "lit" distinguisher object, and |
| | 23826 | probably all objects would include the "owner" distinguisher. We'd |
| | 23827 | make a list of all of the distinguishables in common to the set of |
| | 23828 | equivalents, then run through the common set. For each one, we'd ask |
| | 23829 | the distinguisher if the list of equivalents we have is |
| | 23830 | distinguishable via this distinguisher. The "lit" distinguisher |
| | 23831 | would return true if the objects were all in different "lit" states, |
| | 23832 | and the "owner" distinguisher would return true if all had different |
| | 23833 | owners. We'd stop at the first distinguisher that can tell all of |
| | 23834 | the objects apart. The distinguisher would give us the method to |
| | 23835 | call in each of the objects to list its distinguishing name - the |
| | 23836 | "lit" distinguisher would call the litName property, for example, |
| | 23837 | which would display "the lit candle" or "the unlit candle"; the |
| | 23838 | "owner" distinguisher would display "yours" or "teeterwaller's". |
| | 23839 | |
| | 23840 | <p> |
| | 23841 | The response would have to be handled by the normal disambiguation |
| | 23842 | response mechanism, so the objects would have to conspire with the |
| | 23843 | distinguisher to have the proper adjectives. This is easy, though, |
| | 23844 | because the objects are the ones displaying the adjectives in the |
| | 23845 | first place when they show the disambiguation list. |
| | 23846 | |
| | 23847 | <p> |
| | 23848 | If we find no distinguisher that can tell all of the items apart, |
| | 23849 | we'd look for one that can tell at least some of the items apart, and |
| | 23850 | phrase it like this: "the lit candle, or one of the unlit candles". |
| | 23851 | If they select one of the ones indistinguishable with this |
| | 23852 | distinguisher, we'd iterate, and maybe pick it up with a separate |
| | 23853 | distinguisher next time. |
| | 23854 | |
| | 23855 | <p> |
| | 23856 | If none of the distinguishers can tell any of the objects apart, we'd |
| | 23857 | simply choose one arbitrarily like we do now. |
| | 23858 | |
| | 23859 | <p> |
| | 23860 | <pre> |
| | 23861 | >take candle |
| | 23862 | Which candle do you mean, the lit candle, or one of the unlit candles? |
| | 23863 | |
| | 23864 | >unlit |
| | 23865 | Which do you mean, your candle, or one of Bob's? |
| | 23866 | |
| | 23867 | >bob's |
| | 23868 | (arbitrarily picking one of bob's several unlit candles) |
| | 23869 | Taken. |
| | 23870 | </pre> |
| | 23871 | |
| | 23872 | <p> |
| | 23873 | Note that for ownership distinctions, need to offer a way to refer to |
| | 23874 | unowned objects: |
| | 23875 | |
| | 23876 | <p> |
| | 23877 | <pre> |
| | 23878 | >get candle |
| | 23879 | Which candle do you mean, Bob's, or the other one? |
| | 23880 | <i>-or-</i> Which candle do you mean, Bob's, or another one? |
| | 23881 | |
| | 23882 | <i>[responses would include...]</i> |
| | 23883 | >another / another one / another gold coin / one of the others |
| | 23884 | / one of the other gold coins / other / the other / the other one |
| | 23885 | / the other gold coin / other gold coin |
| | 23886 | </pre> |
| | 23887 | |
| | 23888 | </div> |
| | 23889 | |
| | 23890 | <!-------------------> |
| | 23891 | <div class=entry> |
| | 23892 | |
| | 23893 | Hide actors from 'all' for all verbs by default. |
| | 23894 | |
| | 23895 | </div> |
| | 23896 | |
| | 23897 | <!-------------------> |
| | 23898 | <div class=entry> |
| | 23899 | |
| | 23900 | For "put in" and "put on", use roughly the same strategy as "take" |
| | 23901 | for generating the "all" list: include only objects that are directly |
| | 23902 | in the actor's location, or in fixed objects in the actor's location, |
| | 23903 | as "take" does, but also include objects that the actor is directly |
| | 23904 | holding. Keep the same iobj/in-iobj exclusions. |
| | 23905 | |
| | 23906 | </div> |
| | 23907 | |
| | 23908 | <!-------------------> |
| | 23909 | <div class=entry> |
| | 23910 | |
| | 23911 | Break up TravelConnector.checkTravelConditions() into two separate |
| | 23912 | methods (canTravelerPass(traveler) and explainTravelBarrier(traveler)), |
| | 23913 | just like TravelBarrier. |
| | 23914 | |
| | 23915 | </div> |
| | 23916 | |
| | 23917 | <!-------------------> |
| | 23918 | <div class=entry> |
| | 23919 | |
| | 23920 | Fix Thing.normalizePath() so that it makes two separate passes over |
| | 23921 | the list. It should apply the PathThrough tranformation first, then |
| | 23922 | the PathPeer transformation as a second pass. (Performing both |
| | 23923 | transformations both on a single pass can cause PathThrough |
| | 23924 | transformations to be missed, because the PathPeer changes the list in |
| | 23925 | such a way that the PathThrough transformation doesn't recognize a |
| | 23926 | needed change. The PathThrough condition could alternatively be |
| | 23927 | modified to recognize PathPeer operations, but it's easier to do |
| | 23928 | things in two passes. Note that doing PathThrough first is safe, |
| | 23929 | because it only adds to the list - it never drops any operations that |
| | 23930 | the PathPeer transformation looks at.) |
| | 23931 | |
| | 23932 | </div> |
| | 23933 | |
| | 23934 | <!-------------------> |
| | 23935 | <div class=entry> |
| | 23936 | |
| | 23937 | Add distance differentiation for 'examine' descriptions (and for |
| | 23938 | 'listen') and 'smell' descriptions as well). Specifically, add |
| | 23939 | distantDesc and obscuredDesc, and call them from basicExamine |
| | 23940 | according to the current point of view. Add corresponding methods for |
| | 23941 | 'listen' and 'smell' descriptions. |
| | 23942 | |
| | 23943 | </div> |
| | 23944 | |
| | 23945 | <!-------------------> |
| | 23946 | <div class=entry> |
| | 23947 | |
| | 23948 | Add automatic state listing to the equivalent grouper. Use a new |
| | 23949 | Thing method, getState, that returns a ThingState object. Use this |
| | 23950 | object to group equivalents by state and to show the state of each |
| | 23951 | item. |
| | 23952 | |
| | 23953 | </div> |
| | 23954 | |
| | 23955 | <!-------------------> |
| | 23956 | <div class=entry> |
| | 23957 | |
| | 23958 | Use the ThingState object to provide the ordinary status description |
| | 23959 | of an object. |
| | 23960 | |
| | 23961 | </div> |
| | 23962 | |
| | 23963 | <!-------------------> |
| | 23964 | <div class=entry> |
| | 23965 | |
| | 23966 | Use ThingState to provide automatic matchName() filtering by state. |
| | 23967 | Add a property to ThingState, stateTokens, that lists tokens that |
| | 23968 | can only be used in noun phrases referring to an object in the state. |
| | 23969 | |
| | 23970 | </div> |
| | 23971 | |
| | 23972 | <!-------------------> |
| | 23973 | <div class=entry> |
| | 23974 | |
| | 23975 | Integrate Steve's exit lister package into the library. |
| | 23976 | |
| | 23977 | </div> |
| | 23978 | |
| | 23979 | <!-------------------> |
| | 23980 | <div class=entry> |
| | 23981 | |
| | 23982 | It would be nice to have a sorting order for the directions, so we |
| | 23983 | list in a more canonical order: north, south, east, west, northeast, |
| | 23984 | northwest, southeast, southwest, up, down, in, out. |
| | 23985 | |
| | 23986 | </div> |
| | 23987 | |
| | 23988 | <!-------------------> |
| | 23989 | <div class=entry> |
| | 23990 | |
| | 23991 | When two exits have the same destination, list them together: "south |
| | 23992 | (or out) to the front yard". |
| | 23993 | |
| | 23994 | </div> |
| | 23995 | |
| | 23996 | <!-------------------> |
| | 23997 | <div class=entry> |
| | 23998 | |
| | 23999 | Don't show exits to dark rooms in the dark. |
| | 24000 | |
| | 24001 | </div> |
| | 24002 | |
| | 24003 | <!-------------------> |
| | 24004 | <div class=entry> |
| | 24005 | |
| | 24006 | In listing exits from a dark room, maybe we should show exits leading |
| | 24007 | to rooms with light, since travel would be allowed to those locations. |
| | 24008 | |
| | 24009 | </div> |
| | 24010 | |
| | 24011 | <!-------------------> |
| | 24012 | <div class=entry> |
| | 24013 | |
| | 24014 | Change the way we figure out if travel from a dark room to an |
| | 24015 | adjoining lit room is possible. Add a separate TravelConnector |
| | 24016 | method that specifically determines if the connector itself is |
| | 24017 | visible to a given actor in a given origin location when the origin |
| | 24018 | location is dark. By default, make a connector visible from a dark |
| | 24019 | location when the destination room is lit. This will provide the |
| | 24020 | customary behavior (i.e., dark-to-dark travel is prohibited, but |
| | 24021 | dark-to-light is allowed on the theory that some of the light from |
| | 24022 | the destination leaks through to the origin, making the connection |
| | 24023 | itself self-illuminating and thus visible even in the dark origin |
| | 24024 | room), while more clearly articulating the rule by making the |
| | 24025 | visibility of the connector the explicit factor in determining |
| | 24026 | whether or not the travel is allowed, and also providing a clean way |
| | 24027 | to override the default heuristic for visibility of the connector for |
| | 24028 | particular connections that should use a different rule. |
| | 24029 | |
| | 24030 | </div> |
| | 24031 | |
| | 24032 | <!-------------------> |
| | 24033 | <div class=entry> |
| | 24034 | |
| | 24035 | Add an option to show available exits in the status line (using |
| | 24036 | a terse display that just lists the direction names). |
| | 24037 | |
| | 24038 | </div> |
| | 24039 | |
| | 24040 | <!-------------------> |
| | 24041 | <div class=entry> |
| | 24042 | |
| | 24043 | Make Surface.PutOn behave like Container.PutIn with respect resolving |
| | 24044 | the indirect object using the tentative direct object list: if |
| | 24045 | everything in the tentative direct object match list is already on |
| | 24046 | the indirect object, flag the indirect object as illogical. |
| | 24047 | |
| | 24048 | </div> |
| | 24049 | |
| | 24050 | <!-------------------> |
| | 24051 | <div class=entry> |
| | 24052 | |
| | 24053 | Sense Event Model: Create a new class, SensoryEvent, that can be used |
| | 24054 | to trigger transient sensory events that actively notify interested |
| | 24055 | observers of their occurrence. |
| | 24056 | |
| | 24057 | </div> |
| | 24058 | |
| | 24059 | <!-------------------> |
| | 24060 | <div class=entry> |
| | 24061 | |
| | 24062 | Add convenience macros for remapTIAction that define the full remapping |
| | 24063 | for a dobj or iobj to another action, with the same or reversed noun |
| | 24064 | phrase order: |
| | 24065 | |
| | 24066 | <p> |
| | 24067 | <pre> |
| | 24068 | dobjRemapTI(OpenWith, UnlockWith) |
| | 24069 | dobjRemapTIReverse(FillWith, PutIn) |
| | 24070 | dobjRemapTIReverse(ThrowAt, AttackWith) |
| | 24071 | </pre> |
| | 24072 | |
| | 24073 | </div> |
| | 24074 | |
| | 24075 | <!-------------------> |
| | 24076 | <div class=entry> |
| | 24077 | |
| | 24078 | examineSpecialContents should probably differentiate according to POV |
| | 24079 | and sight viewing conditions. |
| | 24080 | |
| | 24081 | </div> |
| | 24082 | |
| | 24083 | <!-------------------> |
| | 24084 | <div class=entry> |
| | 24085 | |
| | 24086 | Change CommandReportList to a SimpleOutputCapturer. We don't actually |
| | 24087 | want to process any notifiers or monitors when capturing report results, |
| | 24088 | because we turn them into a report list that can be reordered. We want |
| | 24089 | to wait until we actually display the reports to notify anything of the |
| | 24090 | output. |
| | 24091 | |
| | 24092 | </div> |
| | 24093 | |
| | 24094 | <!-------------------> |
| | 24095 | <div class=entry> |
| | 24096 | |
| | 24097 | <pre> |
| | 24098 | >i |
| | 24099 | You are carrying three matches (one lit), and a matchbook (which |
| | 24100 | contains two matches). |
| | 24101 | |
| | 24102 | >x match |
| | 24103 | Which match do you mean, an unlit match, or the lit match? |
| | 24104 | |
| | 24105 | >an unlit match |
| | 24106 | (the match) |
| | 24107 | The match is an ordinary match. |
| | 24108 | </pre> |
| | 24109 | |
| | 24110 | <p> |
| | 24111 | It would be better not to make an arbitrary choice here, unless they |
| | 24112 | explicitly said "any unlit match". We should have another go at |
| | 24113 | asking for detail in this case. |
| | 24114 | |
| | 24115 | </div> |
| | 24116 | |
| | 24117 | <!-------------------> |
| | 24118 | <div class=entry> |
| | 24119 | |
| | 24120 | Add TITLEs to <A HREF>'s in system messages. |
| | 24121 | |
| | 24122 | </div> |
| | 24123 | |
| | 24124 | <!-------------------> |
| | 24125 | <div class=entry> |
| | 24126 | |
| | 24127 | Exit lister: if we have multiple exits from a location with nil |
| | 24128 | destination names, we are incorrectly grouping them as though they |
| | 24129 | had the same destination name. The result is that we only see one |
| | 24130 | such exit in an EXITS list. Destinations with nil destination names |
| | 24131 | should be treated as unknown destinations. |
| | 24132 | |
| | 24133 | </div> |
| | 24134 | |
| | 24135 | <!-------------------> |
| | 24136 | <div class=entry> |
| | 24137 | |
| | 24138 | Sort adv3.tl alphabetically (except for 'modify' order dependencies). |
| | 24139 | |
| | 24140 | </div> |
| | 24141 | |
| | 24142 | <!-------------------> |
| | 24143 | <div class=entry> |
| | 24144 | |
| | 24145 | Add Dan Schmidt's hyphen-converting output filter to output.c |
| | 24146 | |
| | 24147 | </div> |
| | 24148 | |
| | 24149 | <!-------------------> |
| | 24150 | <div class=entry> |
| | 24151 | |
| | 24152 | Add Dan's Thing.canBeSeenBy, Thing.canBeSeen, etc. (These are |
| | 24153 | convenience methods, especially for canBeSeen and its like, which |
| | 24154 | operate on the player character, saving a little typing by making |
| | 24155 | 'gPlayerChar' implicit.) |
| | 24156 | |
| | 24157 | </div> |
| | 24158 | |
| | 24159 | <!-------------------> |
| | 24160 | <div class=entry> |
| | 24161 | |
| | 24162 | Add Dan's Event.delayEvent, removeEvent methods |
| | 24163 | |
| | 24164 | </div> |
| | 24165 | |
| | 24166 | <!-------------------> |
| | 24167 | <div class=entry> |
| | 24168 | |
| | 24169 | Add an event manager method that cancels an event based on the |
| | 24170 | obj/prop combination, to save work for cases where this uniquely |
| | 24171 | identifies the event (this way, the author doesn't have to go to the |
| | 24172 | extra trouble of saving the Event object reference if the event can |
| | 24173 | be uniquely identified without it). |
| | 24174 | |
| | 24175 | </div> |
| | 24176 | |
| | 24177 | <!-------------------> |
| | 24178 | <div class=entry> |
| | 24179 | |
| | 24180 | Add a "mass" or "collective" noun property, for objects that refer to |
| | 24181 | collections of large numbers of smaller parts, or continuously-measured |
| | 24182 | quantities: "some popcorn", "some water". (Is there anything that this |
| | 24183 | changes besides changing aName to "some <name>"? Should think about it.) |
| | 24184 | |
| | 24185 | </div> |
| | 24186 | |
| | 24187 | <!-------------------> |
| | 24188 | <div class=entry> |
| | 24189 | |
| | 24190 | Add a lower-level base class for Switch, OnOffControl, that keeps |
| | 24191 | track of the on/off state and accepts "turn on" and "turn off". |
| | 24192 | Define the additional switch-specific verbs ("switch" and "flip") |
| | 24193 | only in the Switch subclass - this allows for adding on/off behavior |
| | 24194 | without making something look exactly like a light switch. |
| | 24195 | |
| | 24196 | </div> |
| | 24197 | |
| | 24198 | <!-------------------> |
| | 24199 | <div class=entry> |
| | 24200 | |
| | 24201 | Add a GO BACK command to return to the most recent location (if the |
| | 24202 | connector in was reversible). |
| | 24203 | |
| | 24204 | </div> |
| | 24205 | |
| | 24206 | <!-------------------> |
| | 24207 | <div class=entry> |
| | 24208 | |
| | 24209 | Keep track of the last "interlocutor" for each actor; this is actor |
| | 24210 | last addressed in a targeted command ("bob, go north"), or the last |
| | 24211 | actor in a conversational command - ASK ABOUT, TELL ABOUT, SHOW TO, |
| | 24212 | GIVE TO. For the conversational commands, if the actor is left out |
| | 24213 | (ASK ABOUT GOLD, TELL ABOUT STORM), use the performing actor's most |
| | 24214 | recent interlocutor as the default, if the interlocutor is still |
| | 24215 | within talking range. |
| | 24216 | |
| | 24217 | </div> |
| | 24218 | |
| | 24219 | <!-------------------> |
| | 24220 | <div class=entry> |
| | 24221 | |
| | 24222 | Create a subclass of Actor, UntakeableActor, for an actor that can't |
| | 24223 | be taken or moved. Define an additional subclass, Person, to |
| | 24224 | represent human characters, and provide some custom "fixed" messages |
| | 24225 | for it. |
| | 24226 | |
| | 24227 | </div> |
| | 24228 | |
| | 24229 | <!-------------------> |
| | 24230 | <div class=entry> |
| | 24231 | |
| | 24232 | Ensure that the SCORE and FOOTNOTE modules are completely modular, |
| | 24233 | so that they can simply be omitted from the build if not required. |
| | 24234 | |
| | 24235 | </div> |
| | 24236 | |
| | 24237 | <!-------------------> |
| | 24238 | <div class=entry> |
| | 24239 | |
| | 24240 | Get rid of libMessages.openBracket and closeBracket; instead, add |
| | 24241 | a style tag, <.parser>...<./parser>. |
| | 24242 | |
| | 24243 | Also, add <.notification>...<./notification> for notifications |
| | 24244 | (score changes, FOOTNOTE instructions, etc.). |
| | 24245 | |
| | 24246 | </div> |
| | 24247 | |
| | 24248 | <!-------------------> |
| | 24249 | <div class=entry> |
| | 24250 | |
| | 24251 | Change withBrackets() to parserMessage(), for better documentary |
| | 24252 | effect. |
| | 24253 | |
| | 24254 | </div> |
| | 24255 | |
| | 24256 | <!-------------------> |
| | 24257 | <div class=entry> |
| | 24258 | |
| | 24259 | Simplify the menagerie of output filters, notifiers, monitors, |
| | 24260 | and capturers, reducing everything to a single type (filter). |
| | 24261 | Enforce stacking of filters. |
| | 24262 | |
| | 24263 | </div> |
| | 24264 | |
| | 24265 | <!-------------------> |
| | 24266 | <div class=entry> |
| | 24267 | |
| | 24268 | Get rid of the paragraph suppression immediately following input. |
| | 24269 | Instead, use the command sequencer to display the appropriate kind |
| | 24270 | of separation. |
| | 24271 | |
| | 24272 | </div> |
| | 24273 | |
| | 24274 | <!-------------------> |
| | 24275 | <div class=entry> |
| | 24276 | |
| | 24277 | Rename CommandReportList to CommandTranscript, and rename |
| | 24278 | gCommandReports to gTranscript. |
| | 24279 | |
| | 24280 | </div> |
| | 24281 | |
| | 24282 | <!-------------------> |
| | 24283 | <div class=entry> |
| | 24284 | |
| | 24285 | Add resolved object arguments to Actor.addPendingAction, |
| | 24286 | Actor.addFirstPendingAction. |
| | 24287 | |
| | 24288 | </div> |
| | 24289 | |
| | 24290 | <!-------------------> |
| | 24291 | <div class=entry> |
| | 24292 | |
| | 24293 | Rearrange arguments to Actor methods addPendingCommand, |
| | 24294 | addPendingAction, addFirstPendingCommand, addFirstPendingAction to |
| | 24295 | move the firstInSentence flag first. This will keep everything |
| | 24296 | consistent with the rearrangement necessitated by adding the varargs |
| | 24297 | resolved object list to addPendingAction and addFirstPendingAction. |
| | 24298 | |
| | 24299 | </div> |
| | 24300 | |
| | 24301 | <!-------------------> |
| | 24302 | <div class=entry> |
| | 24303 | |
| | 24304 | When a command is applied to several objects, and processing the |
| | 24305 | command for some of the objects involves implied subcommands, set |
| | 24306 | off the results for the objects with implied subcommands visually, |
| | 24307 | by putting an extra paragraph break before and after each result |
| | 24308 | for an object with implied subcommands: |
| | 24309 | |
| | 24310 | <p> |
| | 24311 | <pre> |
| | 24312 | PO Box: Taken. |
| | 24313 | red ball: Taken. |
| | 24314 | |
| | 24315 | iron key: |
| | 24316 | (First putting the red ball in the duffel bag to make room) |
| | 24317 | Taken. |
| | 24318 | |
| | 24319 | blue test booklet: Taken. |
| | 24320 | |
| | 24321 | brass key: |
| | 24322 | (First putting the red book in the duffel bag to make room) |
| | 24323 | Taken. |
| | 24324 | |
| | 24325 | gold coin: Taken. |
| | 24326 | gold coin: Taken. |
| | 24327 | </pre> |
| | 24328 | |
| | 24329 | </div> |
| | 24330 | |
| | 24331 | <!-------------------> |
| | 24332 | <div class=entry> |
| | 24333 | |
| | 24334 | Use a new style tag, <.commandsep>, for command separation, |
| | 24335 | eliminating the method call commandSequencer.startNewCommand(). |
| | 24336 | Using a tag instead of a method call will work better with text that |
| | 24337 | doesn't reach the output stream immediately (for example, text that |
| | 24338 | is queued into a command transcript during command results display). |
| | 24339 | |
| | 24340 | </div> |
| | 24341 | |
| | 24342 | <!-------------------> |
| | 24343 | <div class=entry> |
| | 24344 | |
| | 24345 | In Thing.construct(), initialize the new object's vocabulary words and |
| | 24346 | add them to the global dictionary. |
| | 24347 | |
| | 24348 | </div> |
| | 24349 | |
| | 24350 | <!-------------------> |
| | 24351 | <div class=entry> |
| | 24352 | |
| | 24353 | Add information on the connector back, if known, to the EXITS display: |
| | 24354 | |
| | 24355 | <p> |
| | 24356 | <pre> |
| | 24357 | Obvious exits lead north, back to the east, and south to the den. |
| | 24358 | ...north; east, back to the living room; and south, to the den. |
| | 24359 | </pre> |
| | 24360 | |
| | 24361 | </div> |
| | 24362 | |
| | 24363 | <!-------------------> |
| | 24364 | <div class=entry> |
| | 24365 | |
| | 24366 | For NPC's, the announcement/result format for implied commands should |
| | 24367 | probably be changed. In particular, we should probably just treat NPC |
| | 24368 | implied actions as full separate commands: |
| | 24369 | |
| | 24370 | <p> |
| | 24371 | <pre> |
| | 24372 | >bob, north |
| | 24373 | Bob opens the door. |
| | 24374 | |
| | 24375 | Bob departs through the door. |
| | 24376 | </pre> |
| | 24377 | |
| | 24378 | </div> |
| | 24379 | |
| | 24380 | <!-------------------> |
| | 24381 | <div class=entry> |
| | 24382 | |
| | 24383 | For NPC's, don't allow interactive defaulting for an implied command. |
| | 24384 | |
| | 24385 | </div> |
| | 24386 | |
| | 24387 | <!-------------------> |
| | 24388 | <div class=entry> |
| | 24389 | |
| | 24390 | For NPC's, if an implied command fails, we should fail with an indication |
| | 24391 | that the NPC needs to perform the implied command: |
| | 24392 | |
| | 24393 | <p> |
| | 24394 | <pre> |
| | 24395 | >bob s |
| | 24396 | Bob must open the door before he can do that. |
| | 24397 | |
| | 24398 | >bob, open door |
| | 24399 | Bob must unlock the door before he can do that. |
| | 24400 | </pre> |
| | 24401 | |
| | 24402 | </div> |
| | 24403 | |
| | 24404 | <!-------------------> |
| | 24405 | <div class=entry> |
| | 24406 | |
| | 24407 | Get rid of gCommandReportClass and withCommandReportsClass. Instead, |
| | 24408 | add a parameter to _newAction() to specify the transcript class to |
| | 24409 | use. |
| | 24410 | |
| | 24411 | </div> |
| | 24412 | |
| | 24413 | <!-------------------> |
| | 24414 | <div class=entry> |
| | 24415 | |
| | 24416 | Add a new BasicLocation method, getRoomPartLocation(part), which |
| | 24417 | returns the immediate container of the given room part, as perceived |
| | 24418 | in that location. Top-level rooms would generally just return 'self' |
| | 24419 | if they have the room part, nil if not. Nested rooms would generally |
| | 24420 | pass this up to their containers, because they don't have room parts |
| | 24421 | themselves in most cases. Nested rooms with their own room parts |
| | 24422 | would handle it themselves. |
| | 24423 | |
| | 24424 | </div> |
| | 24425 | |
| | 24426 | <!-------------------> |
| | 24427 | <div class=entry> |
| | 24428 | |
| | 24429 | "x floor" - should list objects that are on the floor; likewise for |
| | 24430 | other room parts (walls, ceiling). Use a separate listing test |
| | 24431 | (isListedInRoomPart(part)) to allow objects to opt out of being |
| | 24432 | listed specifically in such cases. |
| | 24433 | |
| | 24434 | <p> |
| | 24435 | For special descriptions, add a "room part location" property - this |
| | 24436 | is a purely advisory property used only for finding contents of the |
| | 24437 | floor and so on. When we "x floor", show special descriptions only |
| | 24438 | for objects whose roomPartLocation is the floor of interest. |
| | 24439 | |
| | 24440 | </div> |
| | 24441 | |
| | 24442 | <!-------------------> |
| | 24443 | <div class=entry> |
| | 24444 | |
| | 24445 | Re-enable the transcript after prompting for interactive resolution |
| | 24446 | (reading an OOPS response, a disambiguation response, etc). |
| | 24447 | |
| | 24448 | </div> |
| | 24449 | |
| | 24450 | <!-------------------> |
| | 24451 | <div class=entry> |
| | 24452 | |
| | 24453 | Add a method to Action to swap the roles of the tentative objects, |
| | 24454 | for use with the 'verify' forwarding for TIAction remapping. Add a |
| | 24455 | call to this method to the dobjRemapTIReverse/iobjRemapTIReverse |
| | 24456 | macros before they forward their 'verify' calls. |
| | 24457 | |
| | 24458 | </div> |
| | 24459 | |
| | 24460 | <!-------------------> |
| | 24461 | <div class=entry> |
| | 24462 | |
| | 24463 | When an action is remapped, and we need to announce an object (such |
| | 24464 | as a defaulted object), announce the <i>entire</i> action, not just the |
| | 24465 | object. For example: |
| | 24466 | |
| | 24467 | <p> |
| | 24468 | <pre> |
| | 24469 | >fill bucket |
| | 24470 | (dipping the bucket into the river) |
| | 24471 | |
| | 24472 | >fill bucket |
| | 24473 | (pouring the coffee into the bucket) |
| | 24474 | </pre> |
| | 24475 | |
| | 24476 | <p> |
| | 24477 | This is important because the normal announcements are worded with the |
| | 24478 | intention of being tacked onto the end of what the player typed; when |
| | 24479 | the action is remapped, the action we're actually executing is different |
| | 24480 | from what the player typed, so phrase fragments that are intended to be |
| | 24481 | added to what the player typed are no long applicable. |
| | 24482 | |
| | 24483 | </div> |
| | 24484 | |
| | 24485 | </body> |
| | 24486 | </html> |