In Inform 7 I’m able to take a look at all or part of user input with ‘the topic understood’, but Inform 6 seems to be much more rigid with the action, noun, second table detailed in the DM under conversation – is there a way, ideally within a life rule, to intercept all of a user’s input? I’m specifically wondering about a situation like:
Object Priest...
life [;
Answer: ... ! todo: parse entire input between 'say' command and 'to' qualifier to find keywords/phrases like 'sacred text' and 'learning'
];
...and then user inputs:
>say I am interested in learning about the sacred text to priest
where more than just the noun ‘I’ and second ‘priest’ is needed to formulate a coherent response.
It sounds like you want to look at consult_from and consult_words, described on that DM page. They describe a subset of the user’s input as measured in words (start and count). This is the same information encoded in I7’s topic understood, except that I7 has facilities to auto-convert that information into a text, whereas in I6 you have to use NextWord() to dig through the word list.
I discovered that the internal ‘buffer’ variable of the library will hold the raw user input see Roger Firth deep dive here, but it’s a pain to step through manually. consult_from/to and NextWord() are much more (relatively) elegant!
I’m having some trouble with NextWord() – I keep seeing something like
Ask:
for(index = 0: index < consult_words: index++) {
currentWord = NextWord();
print "^the ", index, "th word in the any clause is [", currentWord,"].";
if(currentWord == 'test') {
print "^Found the test token!";
}
}
with input string “ask MyCharacter about something test stuff” gives output:
the 0th word in the any clause is [0]
the 1th word in the any clause is [0]
the 2th word in the any clause is [0]
and currentWord never matches ‘test’. Do I need to convert the return value from NextWord() in some way?
[ PrintWord wordn at len;
at = parse->(wordn * 4 + 1);
len = parse->(wordn * 4) + at;
for ( : at < len: at++)
print (char) buffer->at;
];
Object Bob "Bob" room
with
name 'bob',
Life [ w cw flag;
Ask:
wn = consult_from;
cw = consult_words;
while (cw) {
w = NextWord();
switch (w) {
'worda', 'wordb', 'wordc':
flag = 1;
print "~I know everything about ", (PrintWord) (wn-1), ".~^";
'wordd', 'worde':
flag = 1;
print "~I know everything about ", (PrintWord) (wn-1), ".~^";
}
cw--;
}
if (~~flag) "~I don't know anything about ", (PrintWord) (wn-1), ".~";
rtrue;
],
has animate proper;
Nextword()'s starting word is in wn. So you have to load wn with the right value: here, it is consult_from (the position of the first word in the topic tag).
consult_words contains the number of words that the player has entered in topic tag.
It’s better style to copy consult_words to a local and decrement that. Just in case some other rule wants to look at consult_from/consult_words in the same turn.
…the difference between what I posted and aureas’s sample code is that (address) prints the canonical form of the dict word, which will be lowercase and perhaps truncated to nine characters. The PrintWord function quoted above will print the subset of the player’s input which matched that dict word.
I also did it this way for “~I don’t know anything about … ~”; the word may not be in the dictionary. It’s a topic tag, the input is free.
But in this case, it might be better to display the whole topic than just one word.