Determining If Disambiguation Would Be Necessary

Okay! Just had an absolute party with @johnnywz00, and we found a solution to a problem, and then I realized we solved the wrong problem, but I hope that thread proves useful to future explorers.

Now! The actual problem I was having!

Let’s say we have a set of objects (with the following vocabs):

  • left box
  • right box
  • front box
  • back box

All four of these have identical descriptions.

If I say EXAMINE BOX, a disambiguation comes up:

Which do you mean? The left box, right box, front box, or back box?

and the player then clarifies:


and the right box’s description is shown.

But we have a problem. If the player uses EXAMINE BOXES, then the game says “Yeah, sure, comin’ right up, cap’n!” and prints four identical descriptions for all four boxes.

We can filter out matches using the following:

class Box: Thing {
    filterResolveList(np, cmd, mode) {
        if (doNotFilter()) return;
        if (np.matches.length > 1) {
            np.matches = np.matches.subset({m: m.obj != self});

    doNotFilter() {
        // Code that solves the upcoming logic problem...

So, here’s the logic problem:
At the filtering stage, how can we determine if the player is referring to multiple nouns as a plural versus one noun among many, which could require disambiguation? What can I put into doNotFilter() that would return nil if the player referred to a plural form of a noun, which matches multiple nouns?

Thank you for your time!

Well, in adv3 vocab, the words after the asterisk are listed in the cmdDict as plurals: ‘big box/carton*boxes’
Lite inits vocab differently so I’m not sure how it marks things as plural tokens…

1 Like

Joey, I’m not sure I totally got what you’re going for this time. But I wonder if perusing gCommand.dobjNPs for {x:x.isMultiple} is anywhere in the ballpark…

1 Like

I just now figured it out!

class PrefabObject: object { 
     // Filter matches 
     filterResolveList(np, cmd, mode) { 
         local matchProp; 
         switch (np.role) { 
                 matchProp = &dobjMatch; 
             case IndirectObject: 
                 matchProp = &iobjMatch; 
             case AccessoryObject: 
                 matchProp = &accMatch; 
         local fellowMatches = getMatchCountForFellowClass(np.matches); 
         if (actionIsSpecific(cmd) || (np.role != DirectObject)) { 
             if (cmd.verbProd.(matchProp).grammarTag == 'single') return; 
             if (fellowMatches <= 1) return; 
             if (mode == Definite) return; 
         if (fellowMatches > 1) { 
             np.matches = np.matches.subset({m: m.obj != self}); 
     // We primarily want to skip redundant responses, 
     // and these actions are the usual suspects: 
     actionIsSpecific(cmd) { 
         if (cmd.action.ofKind(Examine)) return nil; 
         if (cmd.action.ofKind(Feel)) return nil; 
         if (cmd.action.ofKind(SmellSomething)) return nil; 
         if (cmd.action.ofKind(Taste)) return nil; 
         if (cmd.action.ofKind(ListenTo)) return nil; 
         return true; 
     // How many matches of our fellow class were there? 
     getMatchCountForFellowClass(matches) { 
         local count = 0; 
         for (local i = 1; i <= matches.length; i++) { 
             if (hasPrefabMatchWith(matches[i].obj)) { 
         return count; 
     // What determines a fellow prefab? 
     hasPrefabMatchWith(obj) { 
         return true; 

// Example implementation:
class Box: PrefabObject, Thing {
    hasPrefabMatchWith(obj) { 
         return obj.ofKind(Box); 

EDIT: I need to tweak this a bit to allow for other iobj and aobj, not just dobj…

EDIT 2: Okay! It now works for other roles, as well!

So, basically, @johnnywz00, this was my goal:
Let’s assume a situation where you have multiple similar objects (functionally used for different things, but all look the same, sound the same, feel the same, smell the same, taste the same, etc). You’d have a reason to use all of them for different reasons, but there are certain actions where it just doesn’t matter, and you don’t want the player to have to choose or get redundant responses.

This mitigates that problem.

EDIT 3: Don’t mind the weird spacing. GitHub on mobile does weird things. Updated the code to use hasPrefabMatchWith(obj). I feel like this makes implementations way more flexible.

1 Like

Gotcha. I’ve gotten pretty far by just arbitrarily bumping the vocabLikelihood of one of the equivalents, but then I also use almost no plural vocabulary whatsoever, and when I do there’s basically always a CollectiveGroup to field what would be redundant answers…

Also note, I fed you a bad debugPrint… Lite doesn’t use a Transcript. So you can cut that conditional out…

1 Like

Lol, yeah, I discovered that. Not a problem. :smile:

1 Like

Thanks, joey! I think that also my problem with the furniture in the mezzanine and ballroom is SOLVED.

OTOH, elsewhere (wardrobe/s and parchment/s) the plural is used as a collective description, so I must see how I should use your interesting code…

Thanks, and
Best regards from Italy,
dott. Piergiorgio.


Yay!!! I helped!