Forcing the parser to choose a specific noun

I created the following code:

Stated item is an object that varies.
Stating is an action out of world applying to one visible thing. Understand "[any  thing]" as stating.
Check stating:
	If the noun is enclosed by the location:
		now the stated item is the noun;
		say "What do you want to do with [the noun]?";
	otherwise:
		say "I see no [noun] here."
Does the player mean doing something to the stated item: it is very likely.
Rule for supplying a missing noun when the stated item is not nothing: now the noun is the stated item.
Every turn when doing something other than stating (this is the reset stated item rule), now the stated item is nothing.

The problem is that even though the parser will often choose the stated item to go with the subsequent verb, sometimes it will not. For example, if the stated item is not being held by the player and the player were to type “drop”, the parser will choose the item that is in inventory. Is there any way to avoid that? Can I force the parser to choose what I want? (barring creating understand tokens without nouns for every single verb)

One issue you’re hitting is that the Inform parser has a preference to act on items carried by the player.

The other issue is the bigger one for your approach as a whole – actions can be grammatically defined in different ways. Some can/will exploit a rule for supplying a missing noun, some will not. However, you can redefine any action so that it will try to grab a noun (automatically).

Here are a two examples from The Standard Rules.

Let’s look at ENTER. The definition says ‘Entering is an action applying to one thing.’ So it always wants an object.

The first two lines of grammar for it say:

Understand "enter" as entering.
Understand "enter [something]" as entering.

The one with token ‘something’ will make the entering action expect a noun. However the preceding line that allows the player to just type ‘enter’ without a noun also prevents Inform from asking for a missing noun. If you just type ENTER, the game will say ‘You must supply a noun’. This action cannot and will not use any ‘rule for supplying a missing noun’ rules as is.

Let’s look at the definition of another verb, PULL.

Pulling is an action applying to one thing.

Again, it wants an object. The grammar says:

Understand "pull [something]" as pulling.

Note that there is no additional line saying

'Understand "pull" as pulling.' (without reference to ‘something’)

The effect of this grammar is that this command must have a noun to function, and if the player doesn’t give it one, it will grab one automatically, preferably from the inventory, or by using ‘rule for suppling a missing noun rules’, and then by various preferences within Inform.

So actions whose definitions include a non-token-including version of the action, like ENTER, will not go looking for missing nouns. With this knowledge, you can look through the action definitions in Standard Rules and know roughly how the action will behave.

We could redefine ENTER so it will try to use a missing noun. First we can eliminate its existing grammar like this:

Understand the command "enter" as something new.

Now we can re-create it without the tokenless version:

Understand "enter [something]" as entering.

Now if the player types ENTER on its own, the game will grab a noun automatically and also heed rules for supplying missing nouns. In the case of this verb, that’s probably not a great idea, which is why it’s not set up that way in the first place? But that’s how you can change an action to work that way.

-Wade

3 Likes

I think the thing you’re probably unaware of is that “rule for supplying a missing noun” is misleadingly named and has nothing to do with disambiguation. It only does anything in the situation where you have an action applying to a noun and a grammar line with no corresponding token:

Transmogrifying is an action applying to one thing. Understand "transmogrify" as transmogrifying.

In this instance, when the player types TRANSMOGRIFY, the “rule for supplying a missing noun” will be used to … well, supply the missing noun.

1 Like

Addendum: I just tested it out, and I think your code does what you want … if you add a nounless grammar line for every verb:

Understand "take" as taking when the stated item is not nothing.
Understand "drop" as dropping when the stated item is not nothing.
Understand "open" as opening when the stated item is not nothing.

… and so on ad infinitum. Note that:

  • You’ll need to do it for every verb, not just every action (synonyms aren’t automatically included)
  • I’m not sure exactly how you want this to work for actions with a second noun
  • This probably has a million hairy edge cases, so test everything extensively
1 Like

In short: yeah, that’s what you need. :)

I assume you’re trying to support noun-first disambiguation questions as a general strategy:

> LAMP
What do you want to do with the cheese?
> TAKE

This is interesting – I don’t recall an IF system trying this. However, I think to make it work consistently you’d have to dig down into the parser and do some serious adjustment. In the above plan, you’re bypassing a lot of “what can the player see” logic which the world model normally relies on. Plus there’s the whole question of handling PUT COIN IN BAG, etc.

@2lindell: Can you clarify (by a transcript of interaction) what you mean by “For example, if the stated item is not being held by the player and the player were to type ‘drop’, the parser will choose the item that is in inventory.”? I can’t seem to replicate that using your code.

I get the following with @2lindell 's original example, which I assume is the undesirable behaviour in question:

You can see a microphone and a priceless vase here.

>VASE
What do you want to do with the priceless vase?

>TAKE
(the priceless vase)
Taken.

>MICROPHONE
What do you want to do with the microphone?

>DROP
(the priceless vase)
Dropped.
1 Like

The original adventure had this feature (although it also allowed swapping the noun and verb).
I think the issue here is the token “[things preferably held]”. It always bothers me that the parser is so hard to manipulate. I wish there were more ways to customize.

1 Like

Yes, that’s exactly it

Yeah, I think that’s it. If I’m reading the trace output right, the parser doesn’t match things that aren’t held for “drop”

trace

What do you want to do with ball?

drop
[ “drop” drop ]
[Parsing for the verb ‘drop’ (4 lines)]

[line 0 * multiheld → Drop]
[line 0 token 1 word 2 : multiheld]
[Object list from word 2]
[Calling NounDomain on location and actor]
[NounDomain called at word 2 (domain1 lab, domain2 yourself)
seeking definite object
Trying the north at word 2
Matched (0)
Trying the northeast at word 2
Matched (0)
Trying the northwest at word 2
Matched (0)
Trying the south at word 2
Matched (0)
Trying the southeast at word 2
Matched (0)
Trying the southwest at word 2
Matched (0)
Trying the east at word 2
Matched (0)
Trying the west at word 2
Matched (0)
Trying the up at word 2
Matched (0)
Trying the down at word 2
Matched (0)
Trying the inside at word 2
Matched (0)
Trying the outside at word 2
Matched (0)
Trying yourself at word 2
Matched (0)
Trying ball at word 2
Matched (0)
Trying key at word 2
Matched (0)
[ND made 15 matches]
[Adjudicating match list of size 15 in context 3
definite object
[ND returned key]
[token resulted in success]
[line 0 token 2 word 2 : END]
[Line successfully parsed]
(key)
Dropped.

there’s probably some smoothing out needed, but you can replace the noun rather than DtPM it.

before doing something when the stated item is not nothing:
	now the noun is the stated item;
	now the stated item is nothing;
	try the current action instead;
	
rule for clarifying the parser's choice of something while the stated item is not nothing:
	do nothing.

This is a good idea, but the parser asks for a noun before inform even gets to the before stage rule, and knocking out the clarifying the parser’s choice activity only effects the printing of command clarification, it doesn’t stop the parser’s asking when it can’t decide. So if the parser chose something this rule will replace it, but in our example the parser will still ask for clarification on what to drop if the player isn’t holding anything.

However, does the player mean seems to help for that case. There’s still the issue if the player typed a new noun you don’t want this rule applying so we’ll have to work that out.

Is there an easy way to check if the noun was matched from the player’s command or was picked by the parser?

A lot of Dialog games sort of do this, but the way it works under the hood is that the default “[something]” action pops up a list of hyperlinks, where TAKE is linked to the command TAKE THINGUMMY and so on. If you actually just type TAKE as a command after typing a noun, it’ll ask what you want to take.

I haven’t tested, but I think you could use @Draconis’ Subcommands extension to check which part of the player’s command was understood as referring to the noun. If it was wholly inferred by the parser, it should have an empty subcommand.

1 Like

@jwalrus: Thanks! I was assuming that it was a problem limited to objects with name clashes.

@severedhand: Like jwalrus says, the only actions that can trigger the supplying a missing noun rules are those with grammar lines that omit noun tokens (like the entering action) but which also have an action definition that requires a noun (as in the example of pulling that you provided). The entering action does require a noun, actually, but the Standard Rules include this:

Rule for supplying a missing noun while entering (this is the find what to enter rule):
	if something enterable (called the box) is in the location,
		now the noun is the box;
	otherwise continue the activity.

@2lindell: As you and kamineko point out, the [something preferably held] token (and the related [things preferaby held] token) impose a world state requirement on parsing itself. If the stated item does not meet that requirement, the parser will look for something that does. (Although your response to stating takes the form of a question, the parser is fully reset and expecting a brand new command at that point.) Since the world state requirement added by the token is imposed during inference, the most straightforward way around this is to modify the Adjudicate() routine to allow an exception for the stated item, specifically the block:

   if (context==HELD_TOKEN && (n == (+ stated item +) || parent(n)==actor))	! MODIFIED
    {   good_ones++; last=n; }
    if (context==MULTI_TOKEN && ultimate==ScopeCeiling(actor)
        && n~=actor && n hasnt concealed && n hasnt scenery) 
    {   good_ones++; last=n; }
    if (context==MULTIHELD_TOKEN && (n == (+ stated item +) || parent(n)==actor))	! MODIFIED
    {   good_ones++; last=n; }

However, this is just the first of many problems that you’ll have to solve to get the kind of interaction that you seem to want. For example, with that in place and your existing DTPM rule (using default Standard Rules grammar), you will get interaction like:

>ROCK
What do you want to do with the rock?

>INSERT
(the rock in the rock)
You can't put something inside itself.

when the player character is holding only the rock. This is for two reasons:

  1. Your DTPM score is – probably unexpectedly – causing the parser to rate every possible second noun as very likely.
  2. As severedhand mentions obliquely, inference uses a hidden default scoring system that prioritizes held objects (most of the time).

There are pieces of the parser (especially the inference subsystem) that are relevant to what you’re trying to do. You might want to look into Jon Ingold’s Disambiguation Control extension, which allows finer control over inference.

1 Like

Try:

Include (-

[ FindInferredObject      idx ;
	if (idx = inferfrom) {
		while (pattern-->idx ~= ENDIT_TOKEN) {
			if (pattern-->idx ofclass Object) return pattern-->idx;
			idx++;
		}
	}
	return nothing;
];

-). [not used here but might be handy somewhere else]

To decide which object is inferred object:
	(- (FindInferredObject()) -).

if the noun is the inferred object...