adv3Lite disambigName suggestion

It appears disambigName is only printed if the name properties of two objects are actually identical. This is usually sensible enough. But I happen to have a cooler in which are some six-packs of beer, from which the player can remove a single six-pack. This leads to the following output:

And because adv3Lite is cheerfully willing to understand implied plurals, that type of message may be difficult for the player to deal with. At the very least, it looks like a guess-the-noun problem, even though it’s not.

Would it be practical for the parser to use disambigName if it is defined on the object, rather than only when it’s specifically needed? Or would that cause other problems?

As I understand it your cooler contains an object representing several six packs of beer, and when the player tries to take a six pack of beer, a separate six pack of beer object is moved into scope. Both objects now respond to ‘six-packs of beer’ because the parser automatically implies the plural of ‘six-pack of beer’.

I confess the first time I read your post I didn’t understand how your proposal would meet the problem, but on re-reading I think what you mean is that you could get round your problem if the parser used the disambigNames in this situation (since you could make them more meaningful), but it’s not doing so because the name properties aren’t identical. This is certainly something I can take a look at. The current behaviour wasn’t of my design; it’s something advLite has inherited from Mike Roberts’s Mercury parser code (and in a part of it I haven’t really looked at that closely, since up until now it seemed to be working fine). I would have thought the more useful behaviour would be to have the disambigName default to the name, and for the parser always to use the disambigName when disambiguating (which would more or less have the effect you were suggesting), but there may be some reason for not doing it this way, and a quick look at Mike’s code suggests to me that it may not be trivial to achieve.

So, I think there may be an issue for me to look at here, but until I’ve had a chance to look into it further (and it’s clearly not going to be a five-minute job), I’m not sure what the right answer is.

In the meantime, there are a number of other possible ways round your particular problem that you may want to consider:

(1) Since your cooler can presumably contain only a finite number of six-packs, you could define a SixPack class and put, say, a dozen instances of it in your cooler. This would represent the actual situation I assume you’re trying to model in the simplest and most direct way, and dispenses with the need for a separate six-packs (plural) object. It’s a possible solution here since the total number of six-packs that are realistically likely to exist is quite low (it would not work so well for a bunch of grapes and individual grapes, but that’s not what you’re trying to model).

(2) Alternatively, you could stop the six-pack (singular) object matching the plural (six-packs) by giving it some other plural the player would never type, e.g. ‘six-pack[-zz]’. This is essentially the solution employed in an analogous solution in the Airport game example in the adv3Lite Tutorial.

(3) Another possibility would be to give one or other object a vocabLikelihood of 10, say, so that the parser would always prefer it to the other when both were in scope (thus avoiding the disambiguation question altogether).

(4) It may be that making the six-packs (plural) a CollectiveGroup would help, since this would enable you do define which actions were handled by the CollectiveGroup object and which by its members (in this case the single six-pack).

This raises more general questions about collective/individual dispenser/dispensed type disambiguation that I’ll need to put some more thought into, alongside your disambigName suggestion.

Thanks – using vocabLikelihood and a dummy plural (I think using curly braces, not square brackets as you indicated above) solves the immediate problem.

I intend the player to be able to extract only one six-pack from the cooler, so creating a class and a CollectiveGroup would be extra overhead.

I’ve now taken a look at your original disambigName suggestion and realized it’s a special case of a wider potential problem. Suppose you had a game that included the following object definitions:

+ redBall: Thing 'red ball'
;

+ bigBall: Thing 'ball'
    disambigName = 'big ball'
;

As things stand, because these objects have different names, a command like X BALL will result in the question “Which do you mean, the red ball or the ball?” even though the bigBall has a disambigName. The solution I’ve adopted is to change the parser’s notion of what counts as different names in this situation. In particular I’ve changed the nameDistinguisher to this:

/*
 *   The basic name distinguisher distinguishes objects by their base names.
 *   This is the first distinguisher we apply, since the name is always the
 *   easiest way to tell objects apart in parsing. However since one name could
 *   be entirely contained within another (e.g. 'ball' and 'red ball') we
 *   consider the names as equal for this purpose if one of them is part of the
 *   other.
 */
nameDistinguisher: Distinguisher
    sortOrder = 100
    equal(a, b) { return a.name.find(b.name) || b.name.find(a.name); }
;

It’s possiblt to construct situations where this will result in the use of disambigName where they are not strictly necessary, but I suspect they will be few and far between, e.g. the response to X RED when we have:

+ Thing 'red ant; scary'
   disambigName = 'scary red ant'
;

+ Thing 'red antelope; fast'
    disambigName = 'fast red antelope'    
;

The other (Dispsenser/Dispensed) problem will require furhter thought.

Returning to this topic, only 8 years later. Eric’s change in the library, described above, is now in the version I’m running … but it doesn’t quite solve a new problem I’ve run into. I have a keyhole (in a door) and also a small hole (in a wind-up object) which is in fact a keyhole but the author is being perhaps a tiny bit coy by referring to it in the output as a small hole, even though ‘keyhole’ is acceptable as an input to refer to it. So…

>put pin in keyhole
Which do you want to put it in, the keyhole or the small hole?

>keyhole
Sorry; multiple objects aren’t allowed with that command.

Eric’s code patch works if one of the objects’ names is found in the other object’s name, but in this case that doesn’t happen, because ‘keyhole’ is not found in ‘small hole’ nor vice versa.

I’ve fixed the problem (rather inelegantly) by changing ‘small hole’ to ‘small round opening’, but if anybody would care to speculate about how the library code might be changed using a different sort of string search, that could be very useful.

Me, I’m just going to soldier onward with the game. (And yes, it’s the same game I was asking about 8 years ago. Gonna finish it now…)

Dear Jim,

There are a couple of ways you could deal with this without changing the library code.

One way would be to add:

vocabLikelihood =10

To the definition of the keyhole object.

Another way would be to add the adjective ‘large’ to the definition of the keyhole object along with disambigName = ‘large keyhole’

Best wishes,

Eric

~WRD0000.jpg

2 Likes

Dear Jim,

I’ve taken a further look at this, and perhaps the neatest way to deal with this is to add the following to the definition of whichever object you don’t want the parser to match when the player types PUT PIN IN KEYHOLE (I assume this would be the small hole):

filterResolveList(np, cmd, mode)

{

if(np.matches.length > 1)

np.matches = np.matches.subset({m: m.obj != self});

}

This will then cause the small hole to rule itself out of contention if the player’s input can match anything else, and it does so before the parser gets to complain about multiple objects, so hopefully, it should solve your problem more elegantly.

Best wishes,

Eric

~WRD0000.jpg

1 Like