Disambiguation (on the ground) Adv3Lite

Hi all,

I’m curious how this is supposed to work. When you get a disambiguation reply for identical objects (coins for example), on option offered for objects directly in the room is the one on the ground. However, I can’t figure out any way in the response to refer to it. Here is my example code:

#charset "us-ascii"

#include <tads.h>
#include "advlite.h"

versionInfo: GameID
;

gameMain: GameMainDef
    /* Define the initial player character; this is compulsory */
    initialPlayerChar = me
;

startroom: Room  'The Starting Location'
    "The starter room"
;
/* The starting location; this can be called anything you like */

+ table : Thing 'table'
;

++ coin : Thing 'gold coin'
;

+ coin2 : Thing 'gold coin'
;

+ fisherman : Actor 'Fisherman'
;

++ coin3 : Thing 'gold coin';

+ me: Thing 'you'   
    isFixed = true       
    person = 2  // change to 1 for a first-person game
    contType = Carrier    
; 

And some sample output:

The Starting Location

The starter room


You can see a gold coin and a table here.


On the table you see a gold coin.

Fisherman is here. 

>take coin

Which do you mean, Fisherman’s gold coin, the gold coin on the table, or the gold coin on the ground ?

>table

Taken. 

>take coin

Which do you mean, Fisherman’s gold coin or gold coin on the ground ?

>ground

Which do you mean, Fisherman’s gold coin or gold coin on the ground ?

>ground

1 Like

I don’t know about adv3lite, but in adv3 it is expecting you to disambiguate with the full noun phrase, e.g.:

Void
This is a featureless void with a table.

You see a pebble here.  On the table is a pebble.

>take pebble
Which pebble do you mean, the pebble on the table, or the pebble on the floor?

>floor
That was not one of the choices.  Which did you mean, the pebble on the table,
or the pebble on the floor?

>pebble on the floor
Taken.
3 Likes

A3Lite has a DisambigName property for unique disambiguation terms, avoiding the issue of circular disambiguation (as in your case)

I, for example, actually have a NPC and a portrait of her, so, in the definition of her portrait I used:

disambigName = 'depicted [NPC]' //4 when the actual [NPC] is with the PC...

whose indeed work as designed & expected.

HTH and
Best regards from Italy,
dott. Piergiorgio.

2 Likes

Has anyone figured an elegant way to streamline this, to make the first attempt above work (or at least advise the player better)? I have a routine that adds location-noun as adjective which is very handy for nonportable items. For portable items though, the upkeep to remove old location vocab and add new every time it moves feels kludgy. I am just really unhappy with the default behavior.

1 Like

I don’t know about adv3lite, but in adv3 the behavior you’re interested in lives in BasicResolveResults.ambiguousNounPhrase().

I’ve got some code that builds a literal from the parsed tokens from the disambiguation prompt (in this case “floor” from the player-supplied >FLOOR) and checks it against the object labels spit out by the distinguisher provided by the match list (in this example “the pebble on the table” and “the pebble on the floor”, and if exactly one matches, it generates a new set of tokens from the distinguisher output (“the pebble on the floor” in this case) and punts it back to the parse loop via a goto retryParse.

This is not what I would call “elegant” but it works as far as I can tell.

I think a “clean” fix would require modifying or providing a replacement mainDisambigPhrase, which is the top-level grammatical production that handles the parsing of the disambiguation input.

2 Likes

The function that provides the disambiguation message is askAmbiguous(cmd, role, names), so you could modify or replace it to advise the player better.

Also, the player can respond to such a prompt with FIRST or SECOND to choose the first or second option.

So one way of addressing this might be to include the following:

disambigPreParser: StringPreParser
    doParsing(str, which)
    {
        if(which == rmcDisambig)
        {
            local num = tryInt(str);
            if(num && num <= ordinals.length)
                return ordinals[num];                      
        }  
           
    
           
        /* return the original string unchanged */
        return str;
    }
    
    ordinals = ['first', 'second', 'third', 'fourth' ,'fifth', 'sixth', 'seventh',
        'eighth', 'ninth', 'tenth', 'eleventh', 'tweltfh' ];
;

modify askAmbiguous(cmd, role, names)
{
    local numbered_names = [];
    local item;
    
    for(local i in 1 .. names.length)
    {
        item = '<b>(' + toString(i) + ')</b> ' + names[i];
        
        numbered_names += item;
    }
    
    replaced (cmd, role, numbered_names);
}

This would then produce a prompt like:

Which pebble do you mean, (1) the pebble on the table, or (2) the pebble on the floor?

To which the player can simply reply 1 or 2 (as well as FIRST or SECOND or ON THE TABLE or OR THE FLOOR).

I’m addting something along these lines to the adv3Lite library.

5 Likes