Disambiguation Control by Jon Ingold


Chapter: Problems This Extension Tackles

Inform has a clever parser, capable of making intelligent deductions based on the incomplete and sometimes plain lazy input of its human players. However, its algorithm is not perfect and Inform 6 and 7 authors have frequently struggled with namespace clashes and the problem, not obviously associated, of over-eager parser guesswork. A frequent question on the programming newsgroup is "how do I make the parser ask which object the player means instead of choosing itself?" This extension aims to extend more control to authors over how Inform makes these decisions, and to promote a philosophy of "ask more questions and make fewer guesses".

There are four major areas tackled by "Disambiguation Control". Each section is headed by a piece of real parser interaction from an I7 sample game.

Section: Namespace clashes

Consider the following:

There is a tree here. In the tree is a tree house.

>EXAMINE TREE
Which do you mean, the tree or the tree house?

>TREE
Which do you mean, the tree or the tree house?

This is an example of a namespace clash - one object, whose accepted synonyms are a subset of another's, making it impossible to refer to the first object. Inform 7 authors will be as familiar with their players, the language itself faces the same difficulties! This extension provides a rulebook which details to the parser how to disambiguate in these situations and ensure the player always gets the object intended.

Traditionally, these cases have been tackled by using a "does the player mean" rule to promote the under-named noun: in the above example, we would write

Does the player mean doing something with the tree: it is likely.

Unfortunately, these rules cause an unfortunate side-effect, namely:

Section: Over-eager Guesswork

>TAKE
(the tree)
That's fixed in place.

The problem arises because the parser uses the same "does the player mean" rules to distinguish cases when the player has given unclear input (such as "TREE" above, or more commonly something like "TAKE KEY" when there are several keys nearby); and cases when the player has given no input - either through laziness or a misunderstanding of the commands recognised by the game. At its least serious, over-eager guesswork can make a game look stupid: at its worst - in time-critical scenes, say, or in perilous locations - a parser guessing can lead to the player's demise and the need for an UNDO.

Clearly preferable would be the following:

>TAKE
What do you want to take: the apple, the tree, the ladder or the tree house?

or, perhaps, even better:

>TAKE
What do you want to take: the apple or the ladder?

"Disambiguation Control" aims to produce questions of this type under all circumstances when there is not a single, obvious possibility. It will list all the sensible options for a particular verb, if it can find any, and if it can't, it will ask simply "What do you want to take?". It provides a rulebook to decide what kind of objects are sensible in a given context which the author can alter and add to. It also provides functionality to limit the length of the list of options produced, to stop unwieldy output and, if preferred, to turn it off completely and produce a more tidy

>TAKE
What do you want to take?

every time.

Inform 7 does have a system of automatic defaulting built in, based on the location of the object and the type of verb being used. However, it is unpredictable and non-transparent for the player, and tends to lead to more guesswork and fewer questions. On the occasions that it guesses correctly, it's magic. On those when it fails, however, it can be frustrating and, for unseasoned players, confusing. This extension removes this mechanism entirely (although I6 and template users may be interested to know that it maintains the score bonuses for being non-scenery, non-actor and non-compass objects.)

(The original system is left intact, and the extension provides a hook for turning it back on, although at present this is not fully coded up because I've not yet found it useful!)

Section: Creating Specific Defaults

>DRINK BEER
Which beer do you mean, your beer or his beer?

In situations like this, it would often be nice to provide the correct default rather than bore the player with an "unnecessary" question. However, using a "does the player mean rule" has the usual over-eager guesswork consequence mentioned above. "Disambiguation Control" provides a new rulebook for providing these kind of defaults, that does not interfere with the process of "guesswork" mentioned above.

Finally, "Disambiguation Control" leverages the "which do you mean" method for the case of:

Section: Rejecting Multiple Actions

>EXAMINE FRUIT
You can't use multiple objects with that verb.

This is a little brusque, at least - and made worse by the fact that some "multiple objects" are in fact single objects with plural names...

"Disambiguation Control" replaces this message entirely with a system of offering a choice, using the same rulebooks and code as the rest of the disambiguation process, producing:

>EXAMINE FRUIT
Please be more specific - what do you want to examine: a cherry or the apple?

Should the multiple object actually be a set of identical objects (of the same kind), the game will pick one to act as a representative, giving the following:

>EXAMINE CHERRIES
(a cherry)
The cherry is a rich red colour and has a beautiful smooth skin.

Chapter: How to Update an Existing Project

You can include this extension without making any changes to your code. It will automatically improve points (2) and (4) above, namely, producing less parser guesswork and more "which do you mean" questions, and replacing the multiple action error with a prompt for more detail.

You will, however, need to update any "does the player mean" rules in your code - this extension renders this rulebook redundant (although it borrows its output values of "it is likely", and so forth).

How you should update each rule depends on its function. There are two types:

Section: Should the game choose rules (Does the player mean doing something specific...)

Consider:

In the Living Room is a leather armchair and a hard wicker chair. Marcus is a man on the wicker chair.
Does the player mean entering the leather armchair: it is likely.

Here the "does the player mean" rulebook is being used to guide the player into the correct chair automatically: the game is being "smart" and ensuring that a player who merely types "SIT ON CHAIR" will not be offered a choice (the leather armchair or the wicker chair?) when there is no choice available.

"Disambiguation Control" maintains this idea, using the "should the game choose" rulebook. This has the following set of (positive!) outcomes:

it is an excellent choice
it is a good choice
it is a passable choice

and one way of removing an option entirely, so that disambiguation will never allow it (although directly typing it will still work, of course):

never

These rules take precedence over everything else so should be used with caution - but with one substantial improvement from the normal I7 "does the player mean rules": they will never fire unless the player has typed at least one noun signifier. This avoids behaviour like:

>SIT
(on the wicker chair)

>EXAMINE
(the wicker chair)

>KISS
(the wicker chair)

... and so forth.

A second improvement over I7 is a bug-fix: when writing rules for actions such as "put <x> in <x>", there's no need to remember to write the rule without the first noun: "Disambiguation Control" searches comprehensively across all possible nouns, so will fire rules written as either "put into something" or "put something into something". (If all that means nothing to you, don't worry, it's only one less thing to worry about.)

Because these rules are so powerful, they often need quite careful context: not just where the player is and what's happening around him, but also what other options the player might be referring to in the particular input. Several phrases are provided to help with this:

Firstly, phrases to check whether match list contains certain objects (amongst others)

... when also considering (a particular object)
... when considering some (things matching a description)

A phrase to test if the match list consists of one specific other thing:

... when also only considering (a particular object)... (or only also, or only just)

(This condition is good for separating namespace clashes, with rules such as:

Should the game choose doing something with the lemon when also only considering the lemon grass: it is a good suggestion.)

We can also check if the match list is entirely contained by some specified set of objects, using the "comparing phrases":

One, two or three objects separated by and/or/against...

Should the game choose when comparing the lemon against the lemon grass:
     it is a good choice.

Should the game choose when comparing the cat against the cat flap + the cat nip:
     it is a good choice.

A description...

Should the game choose doing something with the plain door when comparing doors:
     it is a good choice.

Note, we either include the action description "doing something with"... or we have no action description, and use "comparing <the thing in question> against <other things>".

The "+" separating terms in the comparing phrases is clunky, but using "and" or "or" confuses Inform!

Section: Should the game suggest rules (Does the player mean doing something, in general...)

Consider:

Does the player mean taking something heavy: it is unlikely.
Does the player mean drinking something liquid: it is likely.

These are rules that reflect elements of the simulation: the player will want to enter enterable things, open closed things, eat edible things, and so forth. "Disambiguation Control" uses this kind of rule to help provide sensible options for the player when guessing, and also to provide the opportunity for some defaulting when the player's ambiguous input has only one sensible meaning.

The rulebook used for teaching the parser the rules of the world is called the "Should the game suggest" rulebook. It has six outcomes: it is an excellent suggestion, it is a good suggestion, it is a passable suggestion, no opinion, it is a bad suggestion and never. The "excellent" outcome is provided as "slack": the library does not use them and the author is advised to leave them be. (The more different levels of score there are, the more likely the parser is to find a unique best guess and default without the player understanding what's happened!)

The following are the rules above, rewritten for use with this extension:

Should the game suggest taking something heavy: it is a bad suggestion.
Should the game suggest drinking something liquid: it is a good suggestion.

The extension comes preloaded with a set of basic rules covering the usual I7 world model. Here are four rules from within it:

Should the game suggest closing an open thing: it is a good suggestion.
Should the game suggesting taking a portable thing: it is a passable suggestion.
Should the game suggest taking a scenery thing: it is a bad suggestion.
Should the game suggest wearing a scenery thing: never.

The parser will either default to a single choice, or offer a list of outcomes, or offer a blank request for more information ("What would do you want to take?") The rules for how it decides are slightly fiddly, and in this version, not user-configurable. In order to choose which outcomes to provide for any given rules, some rules of thumb are provided below.

Excellent: Not necessary, probably, but provided as a stepping-stone between actions that should always happen, but that don't take precedence over namespace clashes

Good: These are the outcomes which will be favoured under normal conditions.

Passable: This sits just above the default value - this is for action the library wants to leave as a last resort, such as taking things you already have or wearing a hat you've got on your head.

(Passable is a somewhat odd category - the parser will never offer them to the player when the player has only typed a verb (it would seem strange to suggest the hat on your head is a suitable thing to try and WEAR); but if the player has been more specific then the parser will both offer this as an option, and accept it as a default value.)

Bad: - the default This covers actions which would look stupid if offered by the game at any time. Taking this as the default prevents the game from offering long lists to open commands (TAKE) but doesn't prevent the player being offered objects he's referenced if there's nothing better (TAKE OAK). The extension includes several of these despite this outcome being the default - a bit of precision was never a bad thing!

Never: Never actions should be those which have a high cost (damage, death or irrevocable change); actions which away puzzle solutions that the player could solve by accident; and actions involving fake objects which are only there to provide particular responses and don't really exist in the game-world.

The "Should the game suggest" rules must be extended if the parser is to suggest things which are have meaningful actions outside of the standard model-world rules, typically those handled by Instead and Check rules rather than Carry Out rules; as well as new aspects of simulation added by the author. For example, we might include:

Should the game suggest climbing the roses: it is a good suggestion.
Should the game suggest opening the newspaper: it is a good suggestion.
Should the game suggest pulling a rope: it is a good suggestion.

Note that "excellent" suggestions will beat all those in the library (with the caveat that it has to reach the rule you want it to...)

Section: What are we checking for?

Note that the same rules apply when checking the noun part or the second noun part of the action. Sometimes this doesn't matter - for example, the rule that prevents us trying to put something inside itself applies to both the noun and the second noun part of the phrase. But sometimes, we want a rule only to apply when we're testing a particular part of the phrase.

We can do this use the conditions "if testing the noun" and "if testing the second noun". For example, in a game featuring a key kind, the following rules might be added:

Should the game suggest unlocking with a key when testing the second noun: it is a good suggestion.
Should the game suggest locking with a key when testing the second noun: it is a good suggestion.

Here we need the "if testing the second noun" because if we left it out, the game would assign "good" status to bad action patterns like "lock yourself with brass key" or "unlock apple with brass key", which ought to be considered poor because of their noun part.

Section: Use Options to alter the lists produced

In games with lots of objects, "Disambiguation Control" can lead to very large lists of options, especially in response to blank input lines. We have some mechanisms for controlling this:

Use disambiguation list length of at least 4;

Limits the length of the option list produced: if it contains more than 4 items, the game will ask for clarification without offering a list. The default list length is 6. (Note the "at least" is meaningless here - the number is definitely "at most". Unfortunately, I7's variable use options take this format only.)

Use no parser suggestions.

This will prevent blank "guesswork" lines from offering suggestions, so typing a blank "TAKE" will always reply "What do you want to take?" (unless there is one best-guess object, in which case this will be chosen).

Use no multiple suggestions.

This prevent "EXAMINE ALL" printing a list of possible things to examine: instead it will always reply "Please be specific - what do you want to examine?"

Section: To alter the text of the messages

Messages used to be stored in a table, but now use the standard Response system. You will probably want to replace one of the responses of the Disambiguation Printing Rule.

Chapter: Summary of the Disambiguation Process

Section: Guesswork Situations

For input like

>TAKE
>DROP
>PUT HAT IN

the order of flow is:

1) Is there only one object in scope? If so, pick this. 2) Consult the "Should the game suggest" rules. Is there only one object at the best level of suggestion? If so, default? (We never default to "passable" or worse suggestions, however.) 3) Are there several possibilities at a good or better level of suggestion? If so, list them and ask the player for more information. 4) If the best objects are passable or worse, ask generically for more information, but don't print a list. 5) If all the objects are identical and good or better, pick one

Section: Ambiguous Input

For input like

>EXAMINE RED
>TAKE KEY

where there are multiple objects to which the player may be referring. The order of flow is:

1) Is there only one object in scope? If so, pick this. 2) Consult the "should the game choose" rules. Is there an object which is the best choice? If so, default to this. 3) Consult the "Should the game suggest" rules. Remove any "never" objects. If there is now only one object, default to this. 4) If the best objects are bad or worse, ask generically for more information, but don't print a list. 5) If all the objects are identical and passable or better, pick one

Section: Unusable Plural Input

For input like

>EXAMINE ALL
>PUSH STATUES

the order of flow is:

1) If no nouns/adjective have been provided, treat the input as just a verb (guesswork, above) 2) If nouns/adjectives are supplied, treat this as ambiguous input

Chapter: Summary of New Rulebooks

Section: should the game choose?

Used to default the parser smoothly, given specific circumstances. Most useful for scripting situations in which a particular ambiguity has a "correct" choice (such as taking the model Eiffel tower, drinking your own beer or climbing the step-ladder rather the ladder in your tights.)

The "never" outcome will remove the object from all disambiguation lists (under the context of the action).

Only affects input with some content.

Take precedence over all other rulebooks which means this rulebook can take precedence over a namespace clash, which make it impossible for the player to try some actions! Use with caution!

Examples:

should the game choose drinking my beer: it is a good choice.
should the game choose wearing my hat when also considering Lucy's hat: it is a passable choice.
should the game choose wearing Lucy's hat when the player cannot see Lucy: it is an excellent choice.
should the game choose attacking the vial of poison: never.

When conditions:

also considering <an item>
also considering <some thing matching a description>
also only considering <an item, and nothing else>

Outcomes:

it is an excellent choice
it is a good choice
it is a passable choice
never

(this is probably far more outcomes than anyone would reasonably need, but the slack is there.)

Section: Should the game suggest?

Used to give the parser an idea of what's appropriate in the model world. It's used to streamline the responses given by the parser in response to a verb with no noun qualifiers at all, such as "EXAMINE", "TAKE" or "PUT CAT IN" (but also "EXAMINE ALL", "CLIMB ALL"). The rules will be consulted on all objects in scope and objects at the best level of outcome will be collected up.

Good suggestions will be printed together, and if there's only one it'll be defaulted to. Passable suggestions will never be printed, but if there's only one it'll be defaulted to. Bad and Never suggestions will not be printed or defaulted to.

The suggest rules are also used when the player has given the game some information: they take a lower priority than the "choose" rules, and act as a sanity check. The only difference is that passage and bad suggestions will be listed on-screen, however, bad choices will never be defaulted to.

Note that objects not matching any rules will be given a default value that sits between "passable" and "bad", but will share list/default properties with the category *below* them.

Examples:

Should the game suggest playing a musical instrument: it is a good suggestion.
Should the game suggest taking the castle: it is a good suggestion.
Should the game suggest entering the crossword competition: it is a good suggestion.

For actions which should be offered because, although they're not great, they make more sense than the alternative:

Should the game try wearing something wearable when the player is wearing the noun: it is a passable suggestion.
Should the game try tying a knotted knot: it is a passable suggestion.

For actions which could be offered to the player if he asked for them, but should not be defaulted to because they're dangerous

Should the game suggest taking something flaming: it is a bad suggestion.

For actions that should never be offered to the player under any circumstances:

Should the game suggest taking your nose: never.
Should the game suggest unlocking the door with the hairpin: never.

Outcomes:

it is an excellent suggestion
it is a good suggestion
it is a passable suggestion
it is a bad suggestion
never

Chapter: Thanks, Notes and Limitations

Section: Thanks

Disambiguation is built in, on and out of Graham Nelson's I6 parser, an intricately complicated machine. This extension begs, borrows and cuts-and-pastes extensively. The code may work, but in no way does it detract from the major achievement that the original library represents.

Thanks for Eric Eve and Ron Newcomb for feedback and suggestions.

Matt Weiner and Daniel Stelzer updated this extension for version 6L02.

Matt Weiner updated this extension for version 6M62 (I believe this should be backward compatible to 6L02).

Section: Notes and Limitations

The various rules in this extension will get called repeatedly on a turn. Needless to say, they should not attempt to say anything, and cannot be used reliably to track or reference variables.

The phrase "when comparing <a thing> against <something else>" isn't much good when talking about classes of objects, because everything thing must be a thing, not a description! You should be able to create any tests with classes using the "considering" rules, but you might have to be careful to catch the situation you want. (See the "Scrumping" example for a demonstration of disambiguating between a kind and a specific thing.)

The multiple action support only works for "all", not for specific numbers: so "EXAMINE ALL APPLES" (or just "EXAMINE APPLES") will be handled, but "EXAMINE TWO APPLES" won't be. (This is because Inform wants to treat "two" as an adjective rather than a quantifier in non-multiple actions: I may look into this at some point, but for now, consider it a drawback.)

Section: Feedback

If you have comments, suggestions, questions or bugs please contact Matt Weiner at matt@mattweiner.net.

Section: Changelog

Version 6 - Updated to compile with 6E59.

Version 7 - Small fix for an error with rebuilding the input line after querying the second noun when the first noun was an object picked from a set of identical objects.

- FIx for failing to parse the word "her": the system was interpreting this as a possessive, missing extra information. It now changes its mind if the "indef_possambig" flag is true, mimicking what the standard parser does.

Version 8 - Attempt by Matt Weiner and Daniel Stelzer to adapt extension for 6L02.

- Changed deprecated phrase "End the game in victory" in example "Scrumping". - Replaced table of messages with standard responses.

Version 9/171416 - Attempt by Matt Weiner to adapt extension for 6M62.

- Changed every instance of "yes" and "no" in a To decide if phrase to "decide yes" and "decide no." - Changed the feedback address from Jon's to Matt's.

Version 10/171416

- Eliminated the bypass disambiguation rulebook, which has never worked, and which inteferes with legal use of "yes" and "no" in other phrases.

Example: * Keys and Locks - A quick example showing how to make keys and locks that the parser prefers to choose

"Keys and Locks"

Include Disambiguation Control by Jon Ingold.

A lock is a kind of thing. A lock can be lockable. A lock can be locked. A lock is always lockable. A lock is usually unlocked.

A key is a kind of thing.

Section - the rules

Should the game suggest locking a lock with when testing the noun:
     it is a good suggestion.
Should the game suggest unlocking a lock with when testing the noun:
     it is a good suggestion.

The first should the game suggest unlocking something with something when the second noun unlocks the noun:
     it is an excellent suggestion.
The first should the game suggest locking something with something when the second noun unlocks the noun:
     it is an excellent suggestion.

Should the game suggest locking something with a key when testing the second noun:
     it is a good suggestion.
Should the game suggest unlocking something with a key when testing the second noun:
     it is a good suggestion.

Section - The scene

The Lock Shop is a room.

There is a brass lock, an iron lock and a lock of hair in the Lock Shop.
There is a brass key, an iron key, a key chain in the Lock Shop.

The brass key and iron key are keys.
The brass lock and iron lock are locks.

The brass key unlocks the brass lock.
The iron key unlocks the iron lock.

There is a metal mincer in the Lock Shop.

Instead of inserting something into the metal mincer:
     remove the noun from play;
     say "The metal mincer minces [the noun].";

Test me with "lock lock with key / iron / put brass lock in mincer / unlock lock with brass"

Example: * Scrumping - An example demonstrating multiple actions, suggestions and defaults

"Scrumping"

Include Disambiguation Control by Jon Ingold.

The Orchard is a room.

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

Understand "fruit" as the plural of apple.
Understand "fruit" as the plural of cherry.

A tree is a kind of supporter. Understand "trees" as the plural of tree. A tree is scenery.

In the Orchard is a tree called the apple tree.
In the Orchard is a tree called the cherry tree.
In the Orchard are some bushes.

Five apples are on the apple tree.
Seven cherries are on the cherry tree.

Instead of climbing the cherry tree: say "The branches are too flimsy."

Instead of climbing the apple tree:
     say "You leap up the apple tree and tuck in!";
     end the story finally saying "You have won".

Should the game choose climbing the apple tree (this is the climb apple not cherry rule):
     it is a good choice.

Should the game choose doing something with an apple when also considering the apple tree (this is the namespace default to apple not apple tree rule):
     it is a good choice.

Should the game suggest climbing a tree (this is the trees are good for climbing rule):
     it is a good suggestion.

Test multiples with "examine trees / examine fruit / examine all / climb all".

Test suggestions with "examine / eat / take / climb".

Test choosing with "eat apple / climb cherry / climb tree"

Test me with "test multiples / test suggestions / test choosing"

Example: * Pile of Bricks - an example showing a pile of objects from which an individual object can be taken (which is a common cause of namespace clashes).

"Pile of Bricks"

Include Disambiguation Control by Jon Ingold.

The Building Site is a room. In the building site is a pile of bricks.

The brick is a thing.

Instead of climbing or entering the pile of bricks:
     say "You'd break your neck if you climbed up the bricks."

Instead of taking the pile of bricks when the brick is on-stage:
     say "You've already got a brick."

Instead of taking the pile of bricks:
     move the brick to the player;
     say "You take a brick from the pile."

Understand "brick" as the pile of bricks.

Should the game suggest when comparing the pile of bricks against the brick (this is the pick the brick over the pile of bricks under all straight face-offs rule): never.

Should the game suggest entering or climbing the pile of bricks when also only considering the brick (this is the we can climb up the pile of bricks rule): it is a good suggestion.

Test me with "take brick / take brick / drop brick / take brick / enter brick / take pile of bricks".