When that calculation is made, wn == 5
. Consult_Grammar_1434()
forcibly sets wn
to 5
as its first operation, and the invoking routine SnippetIncludes()
makes no effort to save it and restore a previous value.
As far as I can tell, the contents of parse
and buffer
are as desired (i.e. reflecting >ASK WHAT IS WORTH SEEING) when the action moves to ParseTokenStopped()
. ParseTokenStopped()
does not halt early because it sees the request as in-bounds for the current contents.
The particular logical fault seems to be within TryGivenObject()
, which has the block:
! If input has run out then always match, with only quality 0 (this saves
! time).
if (wn > num_words) { ! stale value of num_words for some reason
if (nomatch) return 0;
if (indef_mode ~= 0)
dict_flags_of_noun = $$01110000; ! Reject "plural" bit
MakeMatch(obj,0);
#Ifdef DEBUG;
if (parser_trace >= 5) print " Matched (0)^";
#Endif; ! DEBUG
return 1;
}
If the comparison condition is changed to
if (wn > WordCount()) { ! check current parse array value
then the RTP does not occur.
Here’s the inclusion for 6M62:
TryGiveObject (modified)
Include (-
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Parser.i6t: TryGivenObject
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
[ TryGivenObject obj nomatch threshold k w j;
#Ifdef DEBUG;
if (parser_trace >= 5) print " Trying ", (the) obj, " (", obj, ") at word ", wn, "^";
#Endif; ! DEBUG
if (nomatch && obj == 0) return 0;
! if (nomatch) print "*** TryGivenObject *** on ", (the) obj, " at wn = ", wn, "^";
dict_flags_of_noun = 0;
! If input has run out then always match, with only quality 0 (this saves
! time).
if (wn > WordCount()) { ! MODIFIED
if (nomatch) return 0;
if (indef_mode ~= 0)
dict_flags_of_noun = $$01110000; ! Reject "plural" bit
MakeMatch(obj,0);
#Ifdef DEBUG;
if (parser_trace >= 5) print " Matched (zero)^";
#Endif; ! DEBUG
return 1;
}
! Ask the object to parse itself if necessary, sitting up and taking notice
! if it says the plural was used:
if (obj.parse_name~=0) {
parser_action = NULL; j=wn;
k = RunRoutines(obj,parse_name);
if (k > 0) {
wn=j+k;
.MMbyPN;
if (parser_action == ##PluralFound)
dict_flags_of_noun = dict_flags_of_noun | 4;
if (dict_flags_of_noun & 4) {
if (~~allow_plurals) k = 0;
else {
if (indef_mode == 0) {
indef_mode = 1; indef_type = 0; indef_wanted = 0;
}
indef_type = indef_type | PLURAL_BIT;
if (indef_wanted == 0) indef_wanted = INDEF_ALL_WANTED;
}
}
#Ifdef DEBUG;
if (parser_trace >= 5) print " Matched (", k, ")^";
#Endif; ! DEBUG
if (nomatch == false) MakeMatch(obj,k);
return k;
}
if (k == 0) jump NoWordsMatch;
}
! The default algorithm is simply to count up how many words pass the
! Refers test:
parser_action = NULL;
w = NounWord();
if (w == 1 && player == obj) { k=1; jump MMbyPN; }
if (w >= 2 && w < 128 && (LanguagePronouns-->w == obj)) { k = 1; jump MMbyPN; }
if (Refers(obj, wn-1) == 0) {
.NoWordsMatch;
if (indef_mode ~= 0) { k = 0; parser_action = NULL; jump MMbyPN; }
rfalse;
}
threshold = 1;
dict_flags_of_noun = (w->#dict_par1) & $$01110100;
w = NextWord();
while (Refers(obj, wn-1)) {
threshold++;
if (w)
dict_flags_of_noun = dict_flags_of_noun | ((w->#dict_par1) & $$01110100);
w = NextWord();
}
k = threshold;
jump MMbyPN;
];
-) instead of "TryGivenObject" in "Parser.i6t".
None of the other code from previous posts matters for resolving the issue.
I think this does qualify as an actual bug… you could argue that it’s a consequence of the particular path to TryGivenObject()
, but really the routine is relying on a cached value that it doesn’t cost much to refresh or read directly.