Hi all – I’m looking for someone wise in the ways of Inform’s parser! Aaron Reed’s Numbered Disambiguation Choices extension misbehaves, and neither Aaron nor I understand why. Here is a sample game:
[code]Include Numbered Disambiguation Choices by Aaron Reed.
Paradise is a room.
An apple of Eden is a kind of thing.
An apple of Hell is a kind of thing.
The table is a supporter in Paradise.
The player carries an apple of Eden and an apple of Hell.
Test me with “put apple on table / 2”.[/code]
The test command leads to an “I didn’t understand that sentence” error. The problem only occurs when (a) you use a command that includes a second noun (or at least is more complicated than “drop apple”, which works fine), and (b) you choose a number that is not “1”.
Aaron’s reaction:
Although a rewrite of the extension would of course be appreciated, I’m also happy with just a hint that would enable me to fix the weird behaviour of the current extension. (It’s rather relevant to Kerkerkruip’s “put scroll in analyser” command, I’m afraid.)
(There is also a ‘bug’ in the extension where the numbers come out weird if the list of disambiguables contains rooms and other non-things, but that only happens in not-for-release mode when using commands like “showme” and “gonear”.)
TRACE 4 shows that the parser somehow loses track of the number of words it has read. At the end of the following quote it skips word 4 and obviously believes that word 5 is “on” (whereas it should be a noun).
Actually, I don’t understand what this means in terms of functionality. I can just see that womething goes wrong there.
I think this came up before. But IIRC, the bug appears in code written by ni, so there’s no easy way to make a direct fix—you would have to workaround it in the template layer like Felix suggested in that thread.
The problem there was that the I6 function “TryNumber” (which deals with the number in “take 2 apples”) was interfering with the numerical choices in Numbered Disambiguation Choices. You can easily fix this like so.
[spoiler][code]Include (-
[ Descriptors o x flag cto type n;
ResetDescriptors();
if (wn > num_words) return 0;
for (flag=true : flag :) {
o = NextWordStopped(); flag = false;
for (x=1 : x<=LanguageDescriptors-->0 : x=x+4)
if (o == LanguageDescriptors-->x) {
flag = true;
type = LanguageDescriptors-->(x+2);
if (type ~= DEFART_PK) indef_mode = true;
indef_possambig = true;
indef_cases = indef_cases & (LanguageDescriptors-->(x+1));
if (type == POSSESS_PK) {
cto = LanguageDescriptors-->(x+3);
switch (cto) {
0: indef_type = indef_type | MY_BIT;
1: indef_type = indef_type | THAT_BIT;
default:
indef_owner = PronounValue(cto);
if (indef_owner == NULL) indef_owner = InformParser;
}
}
if (type == light) indef_type = indef_type | LIT_BIT;
if (type == -light) indef_type = indef_type | UNLIT_BIT;
}
if (o == OTHER1__WD or OTHER2__WD or OTHER3__WD) {
indef_mode = 1; flag = 1;
indef_type = indef_type | OTHER_BIT;
}
if (o == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD) {
indef_mode = 1; flag = 1; indef_wanted = INDEF_ALL_WANTED;
if (take_all_rule == 1) take_all_rule = 2;
indef_type = indef_type | PLURAL_BIT;
}
if (allow_plurals) {
wn--;
if (NextWordStopped() ~= -1 && signal == 0) {
!print signal, " TEST 1^";
n = TryNumber(wn-1);
}
else {
!print signal, " TEST 2^";
n=0;
signal = 0;
}
if (n == 1) { indef_mode = 1; flag = 1; }
if (n > 1) {
indef_guess_p = 1;
indef_mode = 1; flag = 1; indef_wanted = n;
indef_nspec_at = wn-1;
indef_type = indef_type | PLURAL_BIT;
}
}
if (flag == 1 && NextWordStopped() ~= OF1__WD or OF2__WD or OF3__WD or OF4__WD)
wn--; ! Skip 'of' after these
}
wn--;
return 0;
-) instead of “Parsing Descriptors” in “Parser.i6t”.
Include (-
Global signal;
-) after “Definitions.i6t”.
The disambiguation flag is a truth state that varies. The disambiguation flag variable translates into I6 as “signal”.[/code][/spoiler]
Now all you have to do is set the disambiguation flag to true when disambiguating and false otherwise.
However, this fix doesn’t solve the “weirdness” above. I’ll take a look into it, since I’m familiar with diving head first into the world that is the I6 template layer.
This seems like a minimal case, demonstrating that the problem isn’t anything particular to Numbered Disambiguation Choices; you can get it simply by understanding a number (greater than one) as a thing:
Lab is a room. The player carries a flask. Understand "2" as the flask. The table is a supporter in lab.
Test me with "put flask 2 on table/put 2 flask on table".
I managed to figure out what the problem was. It seems that the word number is incremented one too many times and it tries to see if “table” is a valid preposition rather than “on”, which fails giving the error message “I didn’t understand that sentence.”. You can fix this by adding this.
[spoiler][code]Include (-
[ Descriptors o x flag cto type n;
hold = 0;
ResetDescriptors();
if (wn > num_words) return 0;
for (flag=true : flag :) {
o = NextWordStopped(); flag = false;
for (x=1 : x<=LanguageDescriptors-->0 : x=x+4)
if (o == LanguageDescriptors-->x) {
flag = true;
type = LanguageDescriptors-->(x+2);
if (type ~= DEFART_PK) indef_mode = true;
indef_possambig = true;
indef_cases = indef_cases & (LanguageDescriptors-->(x+1));
if (type == POSSESS_PK) {
cto = LanguageDescriptors-->(x+3);
switch (cto) {
0: indef_type = indef_type | MY_BIT;
1: indef_type = indef_type | THAT_BIT;
default:
indef_owner = PronounValue(cto);
if (indef_owner == NULL) indef_owner = InformParser;
}
}
if (type == light) indef_type = indef_type | LIT_BIT;
if (type == -light) indef_type = indef_type | UNLIT_BIT;
}
if (o == OTHER1__WD or OTHER2__WD or OTHER3__WD) {
indef_mode = 1; flag = 1;
indef_type = indef_type | OTHER_BIT;
}
if (o == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD) {
indef_mode = 1; flag = 1; indef_wanted = INDEF_ALL_WANTED;
if (take_all_rule == 1) take_all_rule = 2;
indef_type = indef_type | PLURAL_BIT;
}
if (allow_plurals) {
if (NextWordStopped() ~= -1) { wn--; n = TryNumber(wn-1); } else { n=0; wn--; }
if (n == 1) { indef_mode = 1; flag = 1; }
if (n > 1) {
indef_guess_p = 1;
indef_mode = 1; flag = 1; indef_wanted = n;
indef_nspec_at = wn-1;
indef_type = indef_type | PLURAL_BIT;
}
}
if (flag == 1 && NextWordStopped() ~= OF1__WD or OF2__WD or OF3__WD or OF4__WD) {
hold=1;
wn--; ! Skip 'of' after these
}
}
wn--;
if (hold == 1) {
hold=0;
wn--;
}
return 0;