-
Notifications
You must be signed in to change notification settings - Fork 1
/
changes.htm
25302 lines (19429 loc) · 923 KB
/
changes.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<html>
<title>Recent Changes to the TADS 3 Library</title>
<style type="text/css">
<!--
body {
font: 10pt/14pt Verdana, Arial, Helvetica, Sans-Serif;
}
h1 {
font: 18pt/24pt Georgia, Times New Roman, New York, Times, Serif;
color: #400060;
}
h2 {
font: 14pt/18pt Georgia, Times New Roman, New York, Times, Serif;
color: #600060;
}
h3 {
background: #f0f0f0;
border-top: 1px solid #d8d8d8;
margin-top: 2.5em;
padding: 1ex 1ex 1ex 1ex;
font: 12pt/14pt Georgia, Times New Roman, New York, Times, Serif;
color: #600060;
}
li {
margin-top: 0.75em;
margin-bottom: 0.75em;
}
li ul {
margin-top: 0.75em;
}
li li {
margin-top: 0.25em;
margin-bottom: 0.25em;
}
li p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul.toc li {
margin: 0;
}
div.sepbar {
width: 100%;
background: #f0f0f0;
border-top: 1px solid #d8d8d8;
margin-top: 2.5em;
padding: 1ex 1ex 1ex 1ex;
font: 12pt/14pt Georgia, Times New Roman, New York, Times, Serif;
color: #600060;
}
div.firstentry {
padding: 0em .5ex 1em .5ex;
margin: 0px .5ex 0px .5ex;
border-top: none;
}
div.entry {
padding: 1em .5ex 1em .5ex;
margin: 0px .5ex 0px .5ex;
border-top: 1px solid #c0c0c0;
}
#versionIndex {
height: 0px;
overflow: hidden;
transition: height .5s;
-webkit-transition: height .5s;
}
#versionIndexBtn {
margin-top: 1em;
}
//-->
</style>
<body>
<h1>Recent Changes to the TADS 3 Library</h1>
<p>This is a history of changes to Adv3, the TADS 3 adventure game
library. Changes are listed in reverse chronological order (the most
recent changes are first).
<div id="versionIndexBtn">
<a href="#" onclick="javascript:return toggleVersionIndex(this);">Show version index</a>
</div>
<script type="text/javascript">
function toggleVersionIndex(a)
{
var i = document.getElementById("versionIndex");
if (i.clientHeight > 0) {
i.style.height = "0px";
a.innerHTML = "Show version index";
} else {
i.style.height = i.querySelector("ul").clientHeight + "px";
a.innerHTML = "Hide version index";
}
}
</script>
<div id="versionIndex">
<ul class=toc>
<li><a href='#313'>3.1.3</a>
<li><a href='#312'>3.1.2</a>
<li><a href='#311'>3.1.1</a>
<li><a href='#310'>3.1.0</a>
<li><a href='#3018a'>3.0.18.1</a>
<li><a href='#3018'>3.0.18</a>
<li><a href='#3017a'>3.0.17.1</a>
<li><a href='#3017'>3.0.17</a>
<li><a href='#3016'>3.0.16</a>
<li><a href='#3015c'>3.0.15.3</a>
<li><a href='#3015b'>3.0.15.2</a>
<li><a href='#3015a'>3.0.15.1</a>
<li><a href='#3015'>3.0.15</a>
<li><a href='#3014'>3.0.14</a>
<li><a href='#3013'>3.0.13</a>
<li><a href='#3012'>3.0.12</a>
<li><a href='#3011'>3.0.11</a>
<li><a href='#3010'>3.0.10</a>
<li><a href='#309'>3.0.9</a>
<li><a href='#308'>3.0.8</a>
<li><a href='#307'>3.0.7</a>
<li><a href='#306q'>3.0.6q</a>
<li><a href='#306p'>3.0.6p</a>
<li><a href='#306o'>3.0.6o</a>
<li><a href='#306n'>3.0.6n</a>
<li><a href='#306m'>3.0.6m</a>
<li><a href='#306l'>3.0.6l</a>
<li><a href='#306k'>3.0.6k</a>
<li><a href='#306j'>3.0.6j</a>
<li><a href='#306i'>3.0.6i</a>
<li><a href='#306h'>3.0.6h</a>
<li><a href='#306g'>3.0.6g</a>
<li><a href='#306f'>3.0.6f</a>
<li><a href='#306ae'>3.0.6a-e</a>
<li><a href='#305'>3.0.5</a>
<li><a href='#304'>3.0.4 and earlier</a>
</ul>
</div>
<!------------------------------- 3.1.3 --------------------------------->
<div class="sepbar"><a name='313'></a>3.1.3</div>
<p><b><i>Released May 16, 2013</i></b>
<p>
<!------------------->
<div class=firstentry>
A bug in the parser caused a run-time error when a player attempted to
traverse an AskConnector. This is now fixed.
(<a href="http://bugdb.tads.org/view.php?id=0000169">bugdb.tads.org #0000169</a>)
</div>
<!------------------->
<div class=entry>
For conversational commands such as HELLO, GOODBYE, YES, and NO, the
parser now sets the sense context to the issuing actor (that is, the
actor who issued a command, which is usually the player character)
rather than the target actor (the target in BOB, GOODBYE is Bob). For
most commands, the target actor is the one who's meant to carry out
the command - BOB, GO NORTH asks Bob to go north - so it's appropriate
to execute most actions in the sense context of the target actor. In
the past, the parser did just this, unconditionally for all types of
actions. However, this isn't appropriate for conversational commands,
because the meaning of the target actor is different in these
commands; the target specifies the person being addressed in the
conversation rather than the actor carrying out the command. BOB,
HELLO doesn't tell Bob to say hello, but rather tells the player
character to say hello to Bob. In these types of commands, then, the
actor actually carrying out the command is the issuer, not the target,
so the sense context should remain with the issuer. The parser now
makes this distinction when setting the sense context.
(<a href="http://bugdb.tads.org/view.php?id=0000190">bugdb.tads.org #0000190</a>)
</div>
<!------------------->
<div class=entry>
A parser bug caused the same object to be matched multiple times in a
disambiguation query under certain circumstances. If an object
defined multiple 'noun' words that all had a common prefix up to the
truncation limit, and there were two or more objects with the same
list of similar nouns, and the player entered a noun phrase that
matched the common leading substring, a normal disambiguation question
would be triggered. If the player then answered this question with
ALL, the parser matched each object multiple times, equal to the
number of matching (truncated) nouns per object.
<p>The key element to triggering the bug is multiple noun synonyms
that share a common prefix that's longer than the truncation limit.
It's rare to find examples of this in English games, but it's common
in inflected languages where nouns have multiple forms with different
endings (the bug was discovered in a Czech translation). Here's a
somewhat contrived English example. The kind of compass you use to
inscribe circles can be called a COMPASS or COMPASSES - it's one of
those odd English words like "scissors" or "pants" where the plural
noun form can be used for the singular object, but (unlike scissors or pants)
the singular form can be used interchangeably. If you set the TADS
truncation limit to 6 characters, and then create a red compass and a
blue compass with COMPASS and COMPASSES as noun synonyms, the bug
would have caused the following odd interaction:
<pre>
>x compas
Which compas do you mean, the red compass or the blue compass?
>all
red compass: It's an ordinary red compass.
blue compass: It's an ordinary blue compass.
blue compass: It's an ordinary blue compass.
red compass: It's an ordinary red compass.
</pre>
<p>This is now fixed.
(<a href="http://bugdb.tads.org/view.php?id=0000188">bugdb.tads.org #0000188</a>)
</div>
<!------------------->
<div class=entry>
The library showed the wrong default message for the THROW DOWN
command (that is, the ThrowDir action, when the direction is Down).
The message used to be the rather non sequitur "You're not carrying
that"; the message now says "You should just put it down instead."
</div>
<!------------------------------- 3.1.2 --------------------------------->
<div class="sepbar"><a name='312'></a>3.1.2</div>
<p><b><i>Released August 20, 2012</i></b>
<p>
<!------------------->
<div class=firstentry>
In the past, atmosphere messages (via the Room atmosphereList
property) didn't display a paragraph separator before the message, so
if whatever item happened to be displayed just before an atmosphere
message didn't add a paragraph separator at the end, the atmosphere
message was shown as a continuation of the preceding paragraph.
Room.roomDaemon() now explicitly adds a <.commandsep> before
each atmosphere message to ensure that a paragraph break is displayed.
(<a href="http://bugdb.tads.org/view.php?id=0000161">bugdb.tads.org #0000161</a>)
</div>
<!------------------------------- 3.1.1 --------------------------------->
<div class="sepbar"><a name='311'></a>3.1.1</div>
<p><b><i>Released July 14, 2012</i></b>
<p>
<!------------------->
<div class=firstentry>
The "inventory tall" lister incorrectly listed the contents of
contentsListedSeparately containers both in-line and separately.
This has been fixed, so that only the separate contents list is shown.
(<a href="http://bugdb.tads.org/view.php?id=0000116">bugdb.tads.org #0000116</a>)
</div>
<!------------------->
<div class=entry>
The Thing methods for LOOK and EXAMINE that generate listings of contents
now pass an additional named parameter, "examinee:", to the list methods.
This is occasionally useful when one of the listing-related methods on
one of the contents objects needs to know exactly what the context of
the listing is.
<p>The specific situation that motivated this change was a problem
involving MultiLoc items with special descriptions, as described in
the next item.
</div>
<!------------------->
<div class=entry>
In the past, a MultiLoc with a special description was incorrectly
included in the miscellaneous object list portion of a LOOK
description for its room, or an EXAMINE description of its container.
A special description is supposed to supersede inclusion in the
ordinary list, since it provides the same information. This
now works correctly.
<p>The reason for the double listing was that the method that decides
whether or not to include an object in the ordinary list,
isListedInContents, didn't deal properly with MultiLoc objects. In
fact, it couldn't deal with them properly, because it didn't have
enough information, namely the identity of the object being
examined.
<p>For an ordinary Thing, the examinee is implicit in the call to
isListedInContents, because this method is called only on direct
children of the examinee; a Thing has only one direct container, so
the examinee is implicitly the Thing's location. This logic doesn't
work for a MultiLoc, though, because a MultiLoc can have multiple
direct containers. So, to work properly, this method needed to know
the examinee. This information is now available to the method via
the new "examinee:" named parameter that the various Thing methods
for LOOK and EXAMINE now supply. A new BaseMultiLoc.isListedInContents
method uses the "examinee:" parameter to get the correct listing
information.
(<a href="http://bugdb.tads.org/view.php?id=0000119">bugdb.tads.org #0000119</a>)
</div>
<!------------------->
<div class=entry>
openableContentsLister has been renamed to openableDescContentsLister,
because the original name was inconsistent with the corresponding
listers for other classes. xxxContentsLister is supposed to be the
lister assigned to the 'contentsLister' property for class xxx, and
xxxDescContentsLister is the one for 'descContentsLister'.
('contentsLister' is the lister used for descriptions of objects
<i>containing</i> the xxx, such as the enclosing room description;
'descContentsLister' is for EXAMINE descriptions of the xxx itself.)
There isn't (and never was) a separate 'contentsLister' for Openable;
the former openableContentsLister was always its 'descContentsLister',
but unfortunately wasn't named accordingly.
<p>To minimize the impact on existing code, adv3.h provides a #define
that maps the old name to the new name. In the case of Openable,
there's no need for a specialized 'contentsLister' at all, so there's
no practical need to distinguish the two names, allowing us to create
the mapping for the sake of compatibility. Existing code shouldn't
notice the difference unless it defined an openableDescContentsLister
object of its own, which seems unlikely given that
openableContentsLister already filled the role implied by that name.
</div>
<!------------------->
<div class=entry>
The dobjFor() and iobjFor() macros in adv3.h now have some special
code that catches handler definitions for non-existent Actions. If
the Action named in the dobjFor() or iobjFor() doesn't exist, the
compiler will report an "undefined symbol" error naming the Action
object. This only happens in debug builds (e.g., using the "-d"
option for the command-line compiler), since it generates some extra
code to create a reference to the action object. The warning can be
helpful for catching typos (misspelled action names) or references to
actions you intended to define but never got around to.
(<a href="http://bugdb.tads.org/view.php?id=0000135">bugdb.tads.org #0000135</a>)
</div>
<!------------------->
<div class=entry>
The English parser is a little more nuanced about the way it handles
queries for missing direct objects for verbs with prepositional phrasing
for the direct object. For example:
<p>
<pre>>DIG
What do you want to dig in?
>IN THE DIRT
</pre>
<p>In the past, the parser treated the reply "IN THE DIRT" as a new
command meaning ENTER DIRT. The assumption was that if the reply
matched the phrasing of a new command, it must in fact be a new
command rather than a reply to the missing object query. In many
cases where there's this kind of ambiguity, the parser would have to
be able to read the user's mind to know what was intended, but in this
particular case the parallel phrasing of the query ("...dig in?") and
the reply ("in <i>noun</i>") suggests pretty strongly that the user
did indeed intend the input as a reply to the query rather than as a
new command.
<p>To address this, the parser has a new method for production
matches, isSpecialResponseMatch. This new method returns true if the
production matches special phrasing that makes it more likely to be a
query response than a new command, otherwise nil. The English parser
uses this for the various prepositional response phrasings, such as
inSingleNoun and forSingleNoun; these are all subclasses of
PrepSingleNounProd. When one of these productions matches input that
starts with its preposition, it will return true from
isSpecialResponseMatch, causing the missing object query processor to
treat the match as a reply to the query rather than as a new command,
even when the phrasing could also be interpreted as a new command.
(<a href="http://bugdb.tads.org/view.php?id=0000147">bugdb.tads.org #0000147</a>)
</div>
<!------------------->
<div class=entry>
A bug in the parser caused the wrong message to be displayed when a
command was directed to an actor, and the predicate portion of the
command contained an unknown word, and the noun phrase wording for the
actor portion matched at least one grammatical structure phrasing that
could only refer to an out-of-scope object. In such a case, the
parser reported "You see no <i>actor</i> here" rather than "The word
<i>word</i> is not necessary in this story". This was obviously the
wrong message when an actor matching the noun phrase actually was in
scope, but was also inconsistent with the "unknown word" message shown
in other similar cases that didn't meet all of the bug conditions.
This has now been fixed so that the "unknown word" message is used.
(<a href="http://bugdb.tads.org/view.php?id=0000149">bugdb.tads.org #0000149</a>)
</div>
<!------------------->
<div class=entry>
In the past, the library incorrectly called breakTopicTie() on each
matching topic with the topic object as the first argument, instead of
passing the whole list of matching topics as advertised. This has
been corrected.
(<a href="http://bugdb.tads.org/view.php?id=0000138">bugdb.tads.org #0000138</a>)
</div>
<!------------------------------- 3.1.0 --------------------------------->
<div class="sepbar"><a name='310'></a>3.1.0</div>
<p><b><i>Released 12/21/2011</i></b>
<p>
<!------------------->
<div class=firstentry>
The on-again, off-again <a
href='#getInScopeDistinguisher'>detailed-naming scheme</a> is now on
again, this time with enhancements that will (hopefully) make it here
to stay. This feature was first introduced in version 3.0.10, then
disabled by default in 3.0.11 due to rough edges in that first
attempt. It's reinstated in this release, with improvements. This
improved version has been separately available for some time in an
extension called newNames.t, so it's seen some testing and we think
it'll provide good results.
<p>The problem with the 3.0.10 implementation was that it made the
object-name announcements unnaturally verbose - it added an excess of
qualifiers to object names compared to what a human speaker would use.
The new version tries to be smarter about adding only useful detail,
by using more contextual information. For a multi-object
announcement, for example, the new version only adds enough detail to
distinguish the objects being announced from one another (rather than
from everything else in scope), and also considers the context at a
fixed point in time. The new version also uses the ordinary name for
an object whenever that's enough to distinguish it; it only uses the
(usually more verbose) disambig name when it's needed.
<p>If you find that the new version still produces awkward
announcements, or if you just prefer the original style, you can
disable this feature: just set
gameMain.useDistinguishersInAnnouncements = nil. This makes the
parser revert to the basic object names in announcements.
<p>Note that this change makes the newNames.t extension superfluous,
since the library now incorporates it in its entirety.
</div>
<!------------------->
<div class=entry>
It's now possible for a game to provide custom code to break ties in
topic matches, when more than one topic matches the player's input
with the same score. In the past, the parser just chose a matching
topic entry arbitrarily. In some cases, it's possible for the game to
make a smarter choice based on the exact input text. In addition, the
parser now automatically filters tie lists by selecting exact text
matches over truncated text matches.
<p>To add a custom tie-breaker, you add the method breakTopicTie to
one or more of your TopicEntry objects. This method receives as
arguments the list of tied TopicEntry objects, the original
ResolvedTopic object from the parser, the atcor, and the original
input token list. When a topic tie occurs, the parser calls this
method on each tied TopicEntry object in turn, in in arbitrary order.
This method can either select the tie-breaker or do nothing. If it
selects the tie-breaker, the selection process ends immediately with
the selected winner; otherwise, the parser continues calling
breakTopicTie on the remaining TopicEntry objects in the list of ties.
<p>This method was added to address a situation where two topics
happened to match the same input due to vocabulary truncation.
Suppose we have a game object that matches the vocabulary "elephant",
and another that matches "elephants". If the player enters ASK ABOUT
ELEPHANT, the word ELEPHANT in the input will match both game objects,
since the parser allows the user to abbreviate words by truncating to
the first six characters only. Now suppose we have separate topic
entries for these two objects, and that both topics are active at the
same time and have the same match score. This results in a topic tie,
triggering the new tie-breaking code.
<p>For the sake of this example, let's suppose that you want to
distinguish between ASK ABOUT ELEPHANT and ASK ABOUT ELEPHANTS (which
stands to reason, as you probably wouldn't have created both topic
entries otherwise). In the past, since we have a tie between the two
topic entries, the parser simply chose one arbitrarily. You can now
specifically select one or the other for a given entry, by writing a
breakTopicTie method. Since we want ASK ABOUT ELEPHANT to match the
singular version of the topic, here's how the method would look:
<p>
<pre>
breakTopicTie(matches, topic, actor, toks)
{
if (toks[1].toLower() == 'elephant')
return self;
return nil;
}
</pre>
<p>You can add this method to either TopicEntry object, but it really
belongs conceptually with the singular version of the topic.
<p>The default handling for breakTopicTie() is simply to return nil,
which defers to other objects in the list to make the selection.
<p>For the specific case of truncation matching, you actually don't
have to write a breakTopicTie() method after all, since the parser now
<b>also</b> uses vocabulary truncation to break ties on its own. It
does this <b>after</b> applying any custom breakTopicTie() results.
That is, if breakTopicTie() fails to break the tie, because none of
the TopicEntry objects return a non-nil result for the method, the
parser tries to break the tie on its own by comparing vocabulary
truncation flags. If one topic entry matched with truncation, and
another didn't, the parser will select the one that matched without
truncation.
<p>The parser selects by truncation because this is probably the most
common basis for selection. But it's certainly not the only basis.
Other selection criteria could include word order, and the presence or
absence of certain words. Those sorts of criteria would be very
difficult to encode into a general framework, thus breakTopicTie()
leaves it to the game to make the selection.
<p>This feature addresses <a
href="http://bugdb.tads.org/view.php?id=78">bugdb.tads.org #0000078</a>.
</div>
<!------------------->
<div class=entry>
The scheme that selects which message to display for a reportFailure()
or similar message call had a problem when a verb had both a direct
and an indirect object, <i>and</i> both of those objects had overrides
for the same message. The message generator always gave priority to
the direct object when both objects had overrides, which was wrong if
the message was due to a condition relating to the indirect object.
For example, given an Underside and a Container, both with limited
bulk, "PUT Underside IN Container" showed the Underside's bulk error
message ("The Container won't fit under the Underside"), since the
Underside is the direct object.
<p>The message generator now gives priority to the <i>calling</i>
object. The generator looks in the stack trace for a "self" object in
the source list, and gives priority to the first source object it
finds. This is the source object whose method is actually generating
the message; this will usually be a verify(), check(), or action()
method to process a verb, so presumably it's the object to which the
error condition applies.
<p>(It's certainly valid to generate messages from other places than
the verify(), check(), and action() methods, or indeed from an object
that's not one of the message sources. But the source priority
shouldn't matter in those cases, because the message presumably has no
particular object affiliation anyway if it's not being generated by
code attached to one of the source objects.)
<p>(<a href="http://bugdb.tads.org/view.php?id=61">bugdb.tads.org #0000061</a>)
</div>
<!------------------->
<div class=entry>
The new TAction methods getDobjTokens() and getDobjWords() make it easier
to retrieve the original text entered by the player to refer to the current
direct object. These work only when there's an active direct object
(a non-nil object in gDobj).
<p>The corresponding new TIAction methods getIobjTokens() and getIobjWords()
retrieve the original text of the current indirect object.
<p>The token lists returned generally contain the full phrase that the
player entered, including qualifiers like articles ("the") and possessives.
When the player enters a list ("take book, bell, and candle"), the
token list will only include the phrase for the current object, not
the whole list.
<p>Original text isn't always available even when there's a valid
direct/indirect object in play. For example, text isn't generally
available when the action is a nested or implied action, since these
actions are synthesized internally within the game rather than being
parsed from user input. The new methods return nil when there's no
original text available for the corresponding objects.
</div>
<!------------------->
<div class=entry>
In the past, the getOrigTokenList() method on a noun phrase that had
been manually disambiguated ("which book do you mean...") returned
only the tokens of the user's last answer. For example, if the player
typed "take book", and answered the "which book" question with "blue",
then getOrigTokenList() on the resulting noun phrase returned just the
"blue" token.
<p>The parser now builds a token list that has the complete original
noun phrase plus the disambiguation answer (or answers, if multiple
questions were needed to narrow the list sufficiently). The naive way
to do this (at least in English) might be to simply prepend the
disambiguation answer to the original noun phrase, on the assumption
that the answer is simply an adjective modifying the original phrase;
this would work for the "blue book" example above. One problem with
this is that some names include prepositional phrases, such as "stack
of bills"; we'd want a "which one?" answer of "$20" to turn this into
"stack of $20 bills" instead of "$20 stack of bills", since that would
mean something rather different. The bigger problem is that the
parser accepts a number of answer formats that aren't mere adjectives,
such as "the blue one", "both", "any of them", and "2" or "second" or
"the second one" to pick the second item listed in the parser's "which
book" question. These obviously would produce nonsense using the
naive algorithm.
<p>The parser's solution is to append each new answer parenthetically
to the end of the original phrase. This produces a result that's at
least comprehensible (and usually pretty good) for any answer format,
because it parallels the way the phrase was actually built, as a
series of post hoc clarifications: "book (the blue one)" or "tea (Earl
Gray) (hot)". Further, if there's a need to display the phrase to the
player, it should make sense to the player because it parrots back
what they just typed, retaining the same word order and grouping.
</div>
<!------------------->
<div class=entry>
SenseConnector now overrides checkThrowViaPath(), to handle throwing
objects across the connector independently of "move" and "reach"
operations. In the past, throwing was handled as equivalent to
moving, but this caused an unintended change of behavior when
DistanceConnector was recently changed (in 3.0.16) to allow moving
objects across a distance.
<p>SenseConnector also defines a new method, checkThrowThrough().
This method is the "throw" equivalent of the existing methods
checkMoveThrough() and checkTouchThrough(). The default definition of
the new method returns a failure indication, parallel to the
corresponding existing methods for "move" and "reach".
<p>Finally, DistanceConnector overrides checkThrowThrough() in
parallel to its corresponding overrides for "move" and "reach".
<p>This change (a) restores the pre-3.0.16 behavior for throwing
across a distance, by disallowing it, and (b) makes it possible to
define independent move, reach, and throw handling for sense
connectors.
</div>
<!------------------->
<div class=entry>
The English parser now accepts "LOOK <i>thing</i>" and "L
<i>think</i>" as synonyms for "LOOK AT <i>thing</i>", since it's been
observed that many novice players use this syntax.
<p>(<a href="http://bugdb.tads.org/view.php?id=91">bugdb.tads.org #0000091</a>)
</div>
<!------------------->
<div class=entry>
Thing.addToContents() now skips adding the child object to the
'contents' list if it's already there. In the past, it was possible
to cause an item to added to its parent's contents list twice, by
explicitly using moveInto() in an initializeThing() override; this
caused strange behavior, such as listing the child item twice in
contents list messages. The extra check avoids this unintended
duplication.
<p>(<a href="http://bugdb.tads.org/view.php?id=67">bugdb.tads.org #0000067</a>)
</div>
<!------------------->
<div class=entry>
Using a RoomPart as a regular contents item in a room (rather than as
an element of a roomParts list) caused a run-time error on LOOK AROUND
in some cases. This has been corrected.
<p>(<a href="http://bugdb.tads.org/view.php?id=76">bugdb.tads.org #0000076</a>)
</div>
<!------------------->
<div class=entry>
In the past, if you put one StretchyContainer inside another, the library
didn't properly enforce the bulkCapacity of the outer container when adding
new contents to the inner container. (Since the inner container is itself
a StretchyContainer, its bulk can increase when a new item is added, which
can make it too large for the outer container.) This has been corrected.
<p>(<a href="http://bugdb.tads.org/view.php?id=68">bugdb.tads.org #0000068</a>)
</div>
<!------------------->
<div class=entry>
ASK ABOUT and other topic verbs sometimes didn't work properly when
plural words were used in the topic phrase. This has been corrected.
<p>(<a href="http://bugdb.tads.org/view.php?id=69">bugdb.tads.org #0000069</a>)
</div>
<!------------------->
<div class=entry>
The English command grammar now allows "the" as an article in
possessive phrases, as in "the orc's axe". In the past, possessive
phrases didn't allow any article qualifier (the library took the
overly narrow view that possessives are usually proper names, as in
"Bob's book").
<p>In addition, plural possessives, signified by an apostrophe at the
end of a plural word, are now accepted. For example, "the Smiths'
house" would be accepted if "Smiths" is defined as a plural word.
(<a href="http://bugdb.tads.org/view.php?id=77">bugdb.tads.org #0000077</a>)
</div>
<!------------------->
<div class=entry>
The Lister had a bug involving list groups with minimum group sizes.
If there weren't enough candidate items to list with a group,
according to the group's minGroupSize property, but there were more
than one item, the list builder incorrectly included only one of the
items in the final list, omitting the others. This has been corrected
- the list builder now includes moves all of the candidate items to
the "singles" list, so they all show up in the final list.
(<a href="http://bugdb.tads.org/view.php?id=83">bugdb.tads.org #0000083</a>)
</div>
<!------------------->
<div class=entry>
In the past, if a command contained a noun phrase of the form THE ONE
IN <i>CONTAINER</i>, and the phrase required interactive
disambiguation, the parser incorrectly acted as though the player
answered the "which one do you mean?" prompt with ALL. This was due
to a parser bug; it's now fixed.
(<a href="http://bugdb.tads.org/view.php?id=95">bugdb.tads.org #0000095</a>)
</div>
<!------------------->
<div class=entry>
The parser now gives priority to a possessive-phrase interpretation of
a noun phrase that doesn't match anything in scope, in cases where the
same words could be interpreted as a plain noun phrase without any
possessive qualifiers. For example, in the library sample game, we
have an object defined with vocabulary words including "Bob's fish
cleaner", which means that "Bob's" is defined as an adjective in the
dictionary. "Bob" also is the name of an actor in the game, so the
word "Bob's" in player input can be interpreted in two ways: as an
adjective, or as a possessive qualifier. If the player enters a noun
phrase such as "Bob's desk", the same phrase can be interpreted with
two very different grammatical structures: the possessive qualifier
"Bob's" modifying an underlying noun phrase "desk", or the noun phrase
"Bob's desk", where the first word is a simple adjective from the
dictionary. In the past, the parser considered the two phrasings be
equally strong at the structural level. If one phrasing has a valid
resolution (i.e., it could be mapped to in-scope objects) and the
other doesn't, the structural equivalence doesn't matter, because the
parser always picks the phrase that has the best resolution to game
objects. However, in cases where neither phrasing has a resolution -
because there's no desk in scope at all, say - the parser picks the
interpretation based on structural strength. Since the two phrasings
were equally strong, the parser picked one arbitrarily. If the winner
happened to be the adjective interpretation, this produced the odd
error message "You see no bob's desk here." Now, with this change,
the parser gives priority to the possessive interpretation in cases
where other things are equal, so the error will be "You see no desk
here." This is a better message because the unmatched object really
is simply "desk", regardless of whose desk it is; reporting that
"bob's desk" is the missing object seems overly literal.
(<a href="http://bugdb.tads.org/view.php?id=96">bugdb.tads.org #0000096</a>)
</div>
<!------------------->
<div class=entry>
Room now provides a suitable message for cases where objects are
thrown within the room, but there's no floor object among the room
part list for the room. In the past, this caused a run-time error,
because there was no message defined for this situation.
<p>When an object is thrown, the library's default handling is simply
to drop the object into the room, as though the player had typed DROP
<i>PROJECTILE</i>. The default message, though, describes the object
as "falling <i>to the floor</i>", where <i>to the floor</i> is
replaced by a message that depends on the "nominal drop destination"
for the location - i.e., the object where things are <i>described</i>
as landing when dropped in the room. The standard nominal drop is the
room's floor, which is to say the Floor object in the room's roomParts
list. If there's no floor object, though, the fallback is the Room
itself. The run-time error occurred because Room didn't have the
associated message property for this situation. The <i>to the
floor</i> phrase in the message is obtained via the putDestMessage
property, which Room didn't define. Room now defines this property as
the message property pointer &putDestRoom. libMessages in the
English library in turn defines putDestRoom to display "into <i>the
room</i>". The result is that THROW PROJECTILE AT WALL in a room
without a floor now properly replies "...and falls into <i>the
room</i>", instead of causing a run-time error.
<p>(<a href="http://bugdb.tads.org/view.php?id=78">bugdb.tads.org #0000078</a>)
</div>
<!------------------->
<div class=entry>
Using replaceAction with GiveTo sometimes caused a run-time error.
(This was due a complex interaction with the giveMeToAskFor global
remapping. AskFor is a "topic" action, but GiveTo isn't; the remapping
tried to resolve the GiveTo direct object as a topic for AskFor, but
within the context of the GiveTo verb, which didn't provide one of
the required resolver methods, createTopicQualifierResolver. This
method is now defined for the base Action class, since this situation
creates a dependency on it even for ordinary non-topic action types.)
<p>(<a href="http://bugdb.tads.org/view.php?id=103">bugdb.tads.org #0000103</a>)
</div>
<!------------------->
<div class=entry>
The English library message for an empty topic inventory has been reworded
slightly for the past-tense version, replacing "right now" with "just then".
</div>
<!------------------------------- 3.0.18.1 --------------------------------->
<div class="sepbar"><a name='3018a'></a>3.0.18.1</div>
<p><b><i>Released 5/5/2009</i></b>
<p>
<!------------------->
<div class=firstentry>
A typo in the English message for refuseCommand has been fixed.
</div>
<!------------------------------- 3.0.18 --------------------------------->
<div class="sepbar"><a name='3018'></a>3.0.18</div>
<p><b><i>Released 4/28/2009</i></b>
<p>
<!------------------->
<div class=firstentry>
More of the lister classes have been reorganized along the same lines
as the BaseContentsLister refactoring in version 3.0.17. In particular:
<ul>
<li>surfaceLookInLister, undersideLookUnderLister, and rearLookBehindLister
are now trivial classes based on the new class LookWhereContentsLister.
For consistency, thingLookInLister is based on the new class as well,
but is non-trivial due to its different wording.
<li>surfaceInlineContentsLister, undersideInlineContentsLister, and
rearInlineContentsLister are now trivial classes based on the new class
BaseInlineContentsLister. For consistency, inlineContentsLister
is also based on the new base class, but is non-trivial due to
its different wording.
</ul>
</div>
<!------------------->
<div class=entry>
When an action remapping is inherited from a base class, a subclass or
instance can now define a verify() method for the original action. In
the past, only the <b>new</b> action's verify() was called - the
remapping bypassed any dobjFor() or iobjFor() definitions for the
old action. This made it impossible to tweak the subclass handling
for verbs that were remapped in base classes.
<p>With this change, the verify() for the <b>new and old</b> actions
are <b>both</b> called, <b>if</b> there's a verify() for the old
action defined on a subclass of the class where the remap() itself is
defined. In other words, if the verify() "overrides" the remap(), the
subclassed verify() is invoked.
<p>Because the verify() methods for both the old and new actions are
called, you can't actually override the new action's verify() call.
But verify() results are cumulative, so you <i>can</i> use it to
adjust the logicalness of the action, or to make the action illogical.
</div>
<!------------------->
<div class=entry>
The parser can now has an option to generate more descriptive messages
when noun phrases are disambiguated using the logicalness rules.
<p>Disambiguation occurs when the player uses a noun phrase that
matches more than one in-scope object. For example, if the current
room contains a red door and a blue door, and the player types OPEN
DOOR, the noun phrase DOOR could refer to either of the two door
objects. The parser must decide which of the two objects the player
is referring to; this process is called disambiguation. The parser
does this by applying the various logical, logicalRank, illogicalNow,
illogicalAlready, and related rules defined on the matching objects in
the library and in your game code.
<p>There are two kinds of disambiguation results: "clear" and
"unclear". When exactly one of the objects involved is logical, it's
a clear disambiguation result: we consider it safe to assume that the
player was referring to that exact object, since the other choices
simply don't make sense. When more than one object is logical,
though, the parser can sometimes still pick one automatically (i.e.,
without generating an extra question asking the player to specify
which one she intended) based on the "likelihood" rankings given by
logicalRank rules. A pick based on likelihood rankings is an unclear
result, because the player could plausibly have been referring to one
of the other logical matches.
<p>For unclear results, the parser has always generated a
parenthetical announcement saying which object it chose. This is to
alert the player to the parser's choice, so that any misunderstanding
is immediately apparent.
<p>However, in past versions, the parser didn't say anything to
explicate clear disambiguation results. In practice, even clear
results can sometimes disagree with the player's intentions, for the
simple reason that the player sometimes misunderstands the current
state of the objects. So some authors have found that it's better to
make some kind of object announcement in every case, regardless of how
clear the parser thinks the resolution is.
<p>The parser now provides two new modes, in addition to the
traditional mode, for announcing clear disambiguation results. These
new modes are selected via the new gameMain property ambigAnnounceMode.
You can set this in your gameMain object to select the behavior you