It looks like consult_from
and consult_words
are being set correctly by the parser, but then the command buffer is being wiped of the first command and then retokenised prior to action processing, so the original dictionary word being pointed to by consult_from
is no longer in either the parse array or the command buffer when you try to use it in your code. Because the two commands have the same structure, your code picks up the topic word in the second command.
The confusion of entries isn’t a given, but the confusion of words is. Entering commands >LOOK UP ME IN BOOK. JUMP. LOOK UP PETER IN BOOK.
leaves the word 'look'
in position 3 after retokenisation.
I’m not sure that it’s possible to get access to the topic word(s) of the first ##Consult
action in this scenario without modification of the parser.
To expand on some details:
The initial setting of consult_from
and consult_words
occurs during Parser section G, which calls ParseToken__()
as part of its work. In ParseToken__()
section A:
TOPIC_TOKEN:
consult_from = wn; ! *** sets consult_from ***
if ((line_ttype-->(token_n+1) ~= PREPOSITION_TT) &&
(line_token-->(token_n+1) ~= ENDIT_TOKEN))
RunTimeError(13); ! "A 'topic' token can only be followed by a preposition"
do o = NextWordStopped(); ! advance past potentially meaningful words
until (o == -1 || PrepositionChain(o, token_n+1) ~= -1);
wn--;
consult_words = wn-consult_from; ! *** sets consult_words ***
if (consult_words == 0) return GPR_FAIL;
if (action_to_be == ##Ask or ##Answer or ##Tell) { ! for some verbs: set noun as dictionary word, stripping one leading 'the'
o = wn; wn = consult_from; parsed_number = NextWord();
#Ifdef EnglishNaturalLanguage;
if (parsed_number == 'the' && consult_words > 1) parsed_number=NextWord();
#Endif; ! EnglishNaturalLanguage
wn = o; return 1;
}
if (o==-1 && (line_ttype-->(token_n+1) == PREPOSITION_TT))
return GPR_FAIL; ! don't infer if required preposition is absent
return GPR_PREPOSITION; ! signal successful parsing of topic
Parsing continues as normal until the command has been fully parsed. Then Parser section G takes notice that the player’s command includes multiple commands:
! However, if the superfluous text begins with a comma or "then" then
! take that to be the start of another instruction
if (wn <= num_words) {
l = NextWord();
if (l == THEN1__WD or THEN2__WD or THEN3__WD or comma_word) {
held_back_mode = 1; hb_wn = wn-1; ! *** sets held_back_mode flag ***
}
else {
for (m=0 : m<32 : m++) pattern2-->m = pattern-->m;
pcount2 = pcount;
etype = UPTO_PE;
break;
}
}
Near the end of Parser section G, after the first command has been fully parsed, the code checks to see whether held_back_mode
has been set, and, if so, do more work:
! ...and return from the parser altogether, having successfully matched
! a line.
if (held_back_mode == 1) { ! *** flag still set ***
wn=hb_wn;
jump LookForMore;
}
rtrue;
This moves to Parser section K, which does not account for the case in your example code:
.LookForMore;
if (wn > num_words) rtrue;
i = NextWord();
if (i == THEN1__WD or THEN2__WD or THEN3__WD or comma_word) {
if (wn > num_words) {
held_back_mode = false;
return;
}
i = WordAddress(verb_wordnum);
j = WordAddress(wn);
for (: i<j : i++) i->0 = ' '; ! *** wipes first command from command text buffer ***
i = NextWord();
if (i == AGAIN1__WD or AGAIN2__WD or AGAIN3__WD) {
! Delete the words "then again" from the again buffer,
! in which we have just realised that it must occur:
! prevents an infinite loop on "i. again"
i = WordAddress(wn-2)-buffer;
if (wn > num_words) j = INPUT_BUFFER_LEN-1;
else j = WordAddress(wn)-buffer;
for (: i<j : i++) buffer3->i = ' ';
}
Tokenise__(buffer,parse);
held_back_mode = true;
return;
}
best_etype = UPTO_PE;
jump GiveError;
and that’s where the root problem lies.
The only way to permanently solve this that I can see is to defer wiping the text buffer until after action processing, which would probably mean making this functionality part of Parser section A and adding some globals to preserve information between calls to the parser.
It appears that there is a related issue when the topic is placed at the end of the command grammar. In such a case, it seems that the parser doesn’t notice that a THEN*__WD
is in the topic, so it just includes later commands in the parsed topic, e.g. >CONSULT BOOK ABOUT ME. CONSULT BOOK ABOUT PETER.
is treated as a single command with consult_from == 4
and consult_words == 7
.
Here is an almost totally untested proof of concept demonstrating that in theory these can be solved. WARNING: In all likelihood the quick and rough surgery performed here has created new problems.
helpboard.inf (52.4 KB)
However, it seems to work for your scenario:
>CONSULT BOOK ABOUT ME. CONSULT BOOK ABOUT PETER.
111-1234567
222-7654321
>LOOK UP ME IN BOOK. LOOK UP PETER IN BOOK.
111-1234567
222-7654321
>LOOK UP ME IN BOOK. JUMP. CONSULT BOOK ABOUT PETER.
111-1234567
You jump on the spot, fruitlessly.
222-7654321