Instead, try...something ambiguous

Hi there! Infrequent poster, frequent “oh god I don’t understand this, maybe the intfiction.org forum has something” searcher. Currently struggling through writing basically my second parser game, and it’s, well, a learning experience.

So. Suppose I have the following Very Boring Game.

"In the Garden" by Tahnan

The garden is a room.

The yellow apple is in the garden. The red apple is nowhere.  The green apple is nowhere.

The tree is scenery in the garden.  Instead of attacking the tree:
	if the yellow apple is in the garden:
		now the yellow apple is nowhere;
		move the red apple to the garden;
		move the green apple to the garden;
	else:
		now the red apple is nowhere;
		now the green apple is nowhere;
		move the yellow apple to the garden;
	say "Switched."

Instead of eating the tree, try eating the apple.

My intent is that, if only one apple is present, “eat tree” will redirect to eating that apple; but if more than one apple is present, “eat tree” will redirect to “which do you mean…?”. Unfortunately, what I get is this:

garden
You can see a yellow apple here.

>ACTIONS
Actions listing on.

>eat tree
[eating the tree]
[(1) eating the yellow apple]
That's plainly inedible.
[(1) eating the yellow apple - failed the can't eat unless edible rule]

[eating the tree - failed the can't eat unless edible rule]

>attack tree
[attacking the tree]
Switched.
[attacking the tree - failed]

>l
[looking]
garden
You can see a green apple and a red apple here.

[looking - succeeded]

>eat tree
[eating the tree]
[(1) eating the yellow apple]
That isn't available.
[(1) eating the yellow apple - failed the basic accessibility rule]

[eating the tree - failed the basic accessibility rule]

With the yellow apple gone, and two apples present, why did try eating the apple instead direct the action to the yellow apple, rather than an apple that’s visible? (I’ve tried all kinds of “Does the player mean X when X is not visible: it is very unlikely” additions, to no avail.) Is it possible to get the parser to redirect the action to something ambiguous, or is that a lost cause, and I need something like Instead of eating the tree when more than one apple is visible, say "Obviously you mean the apple, but which apple did you mean?"?

2 Likes

The problem at the moment is that line “Instead of eating the tree, try eating the apple.”.

Inform can’t guess which apple you mean. And in the source, it’s made an assumption that you meant the yellow one, just because it’s called ‘apple’ and it was the first one you defined.

So what you need is a way of making it try to eat, say, a random apple that’s in the location, which requires slightly more code. First I make apples a kind of thing. Then I try to pick a random apple that’s present if the player tries ‘eat tree’. This will work:

The garden is a room.

An apple is a kind of thing.

The yellow apple is an apple in the garden. The red apple is an apple. The green apple is an apple.

The tree is scenery in the garden.  Instead of attacking the tree:
	if the yellow apple is in the garden:
		now the yellow apple is nowhere;
		move the red apple to the garden;
		move the green apple to the garden;
	else:
		now the red apple is nowhere;
		now the green apple is nowhere;
		move the yellow apple to the garden;
	say "Switched.";

Instead of eating the tree:
	if there is an apple in the location:
		let TARGET be a random apple in the location;
		say "You decide to try [the TARGET].";
		try eating TARGET;

Note how when defining the additional apples, I don’t need to say they are ‘nowhere’. If I create an instance of a kind (an apple), and don’t say that it’s somewhere in particular, Inform places it nowhere / off-stage.

-Wade

1 Like

Here’s the line that’s confusing Inform:

Instead of eating the tree, try eating the apple.

You wrote “the apple” presumably meaning like a generic apple. But you’d need to create “apple” as a kind of thing (by writing, straightforwardly enough, An apple is a kind of thing.) for that to make sense; instead, it tries to match “the apple” to a specific object. You’ve got three objects with “apple” in the name, and when in doubt, Inform typically defaults to whichever is mentioned first, which in this case is the yellow one.

As for getting your desired behavior, forcing ambiguity into the player’s command is I think pretty hard so I leave it to wiser heads than mind. You could do something like this, though:

The garden is a room.

An apple is a kind of thing.  An apple is edible.

The yellow apple is an apple.  It is in the garden. The red apple is an apple.  It is nowhere.  The green apple is an apple.  It is nowhere.

The tree is scenery in the garden.

Instead of eating the tree:
	Let foo be the number of apples in the garden;
	If foo is 0, say "None of the fruit on the tree looks edible."; 
	Otherwise if foo is 1:
		let bar be a random apple in the garden;
		try eating the bar;
	Otherwise:
		Say "There are several apples here, including [the list of apples in the garden] -- you should probably take them one at a time."

Great minds think alike. Apparently they even think at the same time.

-Wade

3 Likes

Thanks for the quick response, y’all!

I should have known–I probably kind of suspected–that while the player can talk about 'the apple" and get a disambiguation, the parser is not the player (Hm. What if the parser were the player? Hold on a sec, let me jot that down.)

In this case, I don’t want the player eating a random apple; they need to choose one or the other. And fortunately in my actual, non-boring half-finished game, the analogues of the apples are sufficiently tied to something else that I don’t even need the foo-counter; I can just condition the “there are several apples here” response on that thing being present or absent. The upshot is, I now know what I’m doing and it’s blessedly uncomplicated, even if it’s not as simple as falling back on the parser’s disambiguation tool.

Thanks again, great minds!

You want to trigger parser disambiguation. This means that the parser has to be fooled into thinking that the word(s) typed by the player can correspond to multiple things in the game world. This can be achieved through use of conditional Understand... lines for the objects in question.

You may be happier with whatever alternative you’ve already worked out, but for the sake of answering your original question:

"In the Garden"

To hang is a verb.

The Garden is a room. "A large apple tree is here[if an apple is part of the tree]. On its branches [regarding apples part of the tree][hang] [a list of apples part of the tree][end if]."

An apple is a kind of edible thing. [so that apples can be handled as a group in rules]

The action to be is an action name that varies. The action to be variable translates into I6 as "action_to_be". [expose a bit of parser machinery for your purposes]

To decide whether fooling the parser: [defines your special case]
    if the action to be is the eating action and the player can see the tree, decide yes;
    decide no.

The red apple, the yellow apple and the green apple are apples. Understand "tree" as an apple when fooling the parser. [Q: when is a tree not a tree?]

The tree is privately-named scenery in the garden. Understand "tree" as the tree when not fooling the parser. [A: whenever not fooling the parser]

The red apple and green apple are part of the tree. [for world model's sake]

The can't take component parts rule does nothing when the noun is an apple part of the tree. [to counter the world model nicety]

Instead of jumping: [testing command]
    now the yellow apple is part of the tree;
    say "Yellow apple now on tree."

Test me with "x tree / eat apple / eat tree / green / eat apple / jump / look / eat tree / x tree / climb tree / eat tree".

In theory there could be some alternative to “try” that, instead of invoking the action machinery directly, goes all the way through the parser. So you could say “try parsing ‘eat the apple’ instead” and get the disambiguation you want.

No such thing exists by default, because the parser is not very well encapsulated, so invoking it involves setting and resetting a whole lot of global variables in precise ways. But you can achieve a similar effect with Command Modification by Daniel Stelzer, which circumvents the keyboard-reading step on the next turn and feeds the parser a pre-made command instead.

Instead of eating the tree, silently execute the command "eat apple".

This will trigger disambiguation just like it would if the player typed it. The “silently” here means it doesn’t print the command before executing it; the player will still see any responses from that command. (You’d want not-“silently” for implementing something like the Skein.)

The one downside to this is that “every turn” rules will run twice, once for eating the tree, then once for eating the apple. If this becomes a problem, I can come up with a workaround for it too.

2 Likes