Is there a way to suppress compound clarification messages produced by Does The Player Mean rules? I have a particular object for which I always want the message suppressed if the object is involved – even when another object is involved at the same time.
In the attached demo, pretend the apple is the thing I hate and whose name I don’t want to see.
I favour the apple over the other fruit. So GET FRUIT picks the apple. The “Rule for clarifying the parser’s choice of apple” is able to stop a bracketed (the apple) from appearing at this moment. Hooray.
However, if we now PUT FRUIT ON TABLE, Inform prints the clarification message:
“(the apple on the table)”
Because this also mentions the apple, I don’t want to see it, or anything at all, there.
Is this doable?
-Wade
Summary
Lab is a room.
a fruit is a kind of thing. Understand "fruit" as a fruit.
an apple is a fruit in lab.
a banana is a fruit in lab.
an orange is a fruit in lab.
Does the player mean doing anything to apple:
it is likely;
Rule for clarifying the parser's choice of apple:
do nothing;
a table is a supporter in lab.
Test me with "put fruit on table".
This message is printed by the I6 routine PrintInferredCommand, which examines the current parsing registers, then:
If the thing being inferred is a single noun, invokes the “clarifying the parser’s choice” activity with that noun
Otherwise, prints the inferred command without calling any I7 code
So what you need to do is hack PrintInferredCommand to detect your specific circumstances, and not print anything under those circumstances. I can’t see any elegant way to do this, but here’s one option. This code is for 10.1 but it shouldn’t take much adjustment to work for 9.3 instead.
Include (-
[ PrintInferredCommand from singleton_noun;
singleton_noun = false;
if ((from ~= 0) && (from == pcount-1) &&
(pattern-->from > 1) && (pattern-->from < REPARSE_CODE))
singleton_noun = true;
if (singleton_noun) {
BeginActivity(CLARIFYING_PARSERS_CHOICE_ACT, pattern-->from);
if (ForActivity(CLARIFYING_PARSERS_CHOICE_ACT, pattern-->from) == 0) {
print "("; PrintCommand(from); print ")^";
}
EndActivity(CLARIFYING_PARSERS_CHOICE_ACT, pattern-->from);
} else {
if(CommandUnprintable(from)) rtrue; ! this line is new
print "("; PrintCommand(from); print ")^";
}
];
-) replacing "PrintInferredCommand".
Include (-
[ CommandUnprintable from ;
for( : from<pcount : from++ ){
if(from == (+ the apple +)) rtrue;
}
rfalse;
];
-).
This adds a new routine, CommandUnprintable, that decides if the current pattern includes the apple (by just running through that pattern and seeing if the apple appears anywhere in it). If it does, PrintInferredCommand does nothing.
[Only read this if the solution from Draconis isn’t working for you.]
The clarifying the parser's choice activity is only applied when a single noun is being inferred. This is by design, as can be seen in the default definition of the underlying PrintInferredCommand() routine. That routine has a separate branch for when multiple objects are inferred, but no opportunity for intervention is provided.
It’s possible to add a custom activity and insert it there in order to allow you to write I7 rules to intervene. The compliction is that this routine runs while the parser is determining the action. This means that the noun, second noun and current action will all be undefined.
The following example creates a new activity that is wedged into the multiple inference branch of PrintInferredCommand(). Several new psuedo-globals are added to allow you to define the conditions for intervention with specificity, but the normal way of defining an action in the rule preamble won’t work. In particular, it is necessary to specify action names (i.e. the eating action) instead of actions (i.e. eating). It might be possible to force the setup of the current action to allow the default rule preamble syntax here.
Printing an inferred command
"Don't Repeat Apple"
Lab is a room.
a fruit is a kind of thing. Understand "fruit" as a fruit.
A fruit is usually edible. [added]
an apple is a fruit in lab.
a banana is a fruit in lab.
an orange is a fruit in lab.
Does the player mean doing anything to apple:
it is very likely; [changed]
Does the player mean doing anything to banana: [added]
it is likely;
a table is a supporter in lab.
Printing an inferred command is an activity. [added]
To decide which action name is the action to be: [added]
(- action_to_be -).
To decide which object is the presumptive noun: [added]
(- parser_results-->INP1_PRES -).
To decide which object is the presumptive second noun: [added]
(- parser_results-->INP2_PRES -).
[can't use "involves" condition because the current action won't be set at this point]
Rule for printing an inferred command when the action to be is the putting it on action and the presumptive noun is the apple and the presumptive second noun is the table: [added]
do nothing;
Test me with "put fruit on table / eat / put fruit on table". [changed]
Include (-
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Parser.i6t: Print Command (MODIFIED)
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
[ PrintInferredCommand from singleton_noun;
singleton_noun = FALSE;
if ((from ~= 0) && (from == pcount-1) &&
(pattern-->from > 1) && (pattern-->from < REPARSE_CODE))
singleton_noun = TRUE;
if (singleton_noun) {
BeginActivity(CLARIFYING_PARSERS_CHOICE_ACT, pattern-->from);
if (ForActivity(CLARIFYING_PARSERS_CHOICE_ACT, pattern-->from) == 0) {
print "("; PrintCommand(from); print ")^";
}
EndActivity(CLARIFYING_PARSERS_CHOICE_ACT, pattern-->from);
} else {
BeginActivity((+ printing an inferred command +));
if (ForActivity((+ printing an inferred command +)) == 0) {
print "("; PrintCommand(from); print ")^";
}
EndActivity((+ printing an inferred command +));
}
];
[ PrintCommand from i k spacing_flag;
if (from == 0) {
i = verb_word;
if (LanguageVerb(i) == 0)
if (PrintVerb(i) == 0) print (address) i;
from++; spacing_flag = true;
}
for (k=from : k<pcount : k++) {
i = pattern-->k;
if (i == PATTERN_NULL) continue;
if (spacing_flag) print (char) ' ';
if (i == 0) { PARSER_CLARIF_INTERNAL_RM('F'); jump TokenPrinted; }
if (i == 1) { PARSER_CLARIF_INTERNAL_RM('G'); jump TokenPrinted; }
if (i >= REPARSE_CODE)
print (address) VM_NumberToDictionaryAddress(i-REPARSE_CODE);
else
if (i ofclass K3_direction)
print (LanguageDirection) i; ! the direction name as adverb
else
print (the) i;
.TokenPrinted;
spacing_flag = true;
}
];
-) instead of "Print Command" in "Parser.i6t".
I’ve modified your scenario and test me a bit in order to demonstrate that default behavior would still apply to the banana. I’ve also removed the clarifying the parser's choice of the apple rule because it is a bit mystifying in other contexts like >EAT.
I had a similar need myself and the solution by otistdog seems to be exactly what I am looking for, but it seems to not work anymore (in Inform for Windows 10.1.2.20220830). It raises errors about the Include syntax having changed, but apparently more knowledge and effort is needed to adapt the code, since my attempts of just blindly changing the complained about bits of the syntax result in a bunch of code generation pipeline errors.
Hopefully it’s not too much trouble. Having this working would be very helpful!
Thank you so much!
Just so I understand what I’m working with, I take that as long as nothing else attempts to interfere with the same parts as this does, there’s no side effects or anything to worry about?
(also, looks like the space still needed removing from “Print Command” in the final replacing statement, but I managed to figure it out myself)
@rathydra: FYI, the good @drpeterbatesuk points out that there is a possible issue with the shortcut taken, because in certain situations (e.g. multiple object processing, commands with topics) the values read for presumptive noun and/or presumptive second noun might not be typesafe.