Hiding compound clarification message produced by Does The Player Mean

Using 6M62:

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".

Try

Rule for clarifying the parser's choice of something when the current action involves the apple: do nothing.

EDIT: no, sorry, that doesn’t work.

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.

2 Likes

[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.

6 Likes

Actually I recommend doing this instead. This is a lot more elegant and extensible than my I6 solution.

1 Like

Thanks everyone. And an extra thanks to otis whose neat method I have incorporated.

-Wade

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!

It works for me in 10.1 if the Include parts are changed to:

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 +));
	}
];

-) replacing "PrintInferredCommand".

Include (-

[ 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;
	}
];

-) replacing "PrintCommand".
1 Like

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)

It’s a pretty specific intervention, so there shouldn’t be. If there is, post back.

Sorry about the extra space issue – a copy/paste error. I’ve edited it above.

1 Like

@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.

See his discussion at Recognize and summarily block informal names - #7 by drpeterbatesuk for more. If this turns out to be a practical issue for you, definitely bring it up on the forum.

1 Like