Possessive noun phrase failure messages only referring to the possessor in TADS3/adv3

Another adv3 possessive noun phrase problem.

If you have a noun phrase with an adjective in a command and it doesn’t resolve to anything in scope, the failure message usually includes the entire noun phrase, including the adjective (unless the adjective is an unknown word).

So for example if we have an object somewhere with “blue” in its vocabulary and a pebble that doesn’t, we get:

Void
This is a featureless void.

You see a pebble here.

>x blue pebble
You see no blue pebble here.

But if the adjective is a possessive (or at least an apostrophe-S posessive), instead we get:

>x alice's pebble
You see no alice here.

I assume this is because adv3 defaults to a positional system of implied ownership (a pebble is Alice’s if Alice is currently carrying it).

Is there a standard/existing workaround for handling this more naturally/conversationally?

1 Like

Well, I don’t know if it’s optimal, but I added an approach to this situation to the personScope module I put up previously.

The place where the magic happens is Action.noMatch(), which is where we end up when all else fails in the situation(s) described above (in the OP).

In stock adv3 Action.noMatch() is a one-liner, just punting off to noMatchCannotSee() on a message object. The message object is passed to notMatch() as the first arg, the second arg being the Actor taking the action, and the third being the text literal of the noun phrase the parser couldn’t resolve into an in-scope object.

The approach I’m using is to add additional logic to this method, more or less just expanding what I had previously already done with the personScope module. It checked if noun phrase corresponds to an actor not currently in scope, so it can fail with something like “You see nobody named Alice here” instead of “You see no alice here”.

The complication is that if the typed noun phrase that caused the problem contains a possessive, what we’ll end up as the third arg to Action.noMatch() isn’t the whole noun phrase, but just the noun form of the possessive adjective from it. So if the command was >X ALICE'S PEBBLE, ExamineAction.noMatch() will get “alice” as the noun phrase.

This is a side-effect of how possessives are parsed…basically instead of getting a single noun (“alice’s pebble”, which is what it would resolve to if there was a matching object in scope) it ends up with two nouns, “alice” and “pebble”, and the noun resolution failure ends up being handled by the first one.

As near as I can tell there’s no straightforward way to fix this by jiggling the knobs on the grammar. So what I did instead was just do something kinda like what Action.getEnteredVerbPhrase() does to recover the originally-typed verb text. Only we keep track of both the verb and the noun phrase bits.

Having done that we check to see if the bit we got in Action.noMatch() corresponds to a) a noun phrase in the originally-typed command, and if it is b) if it’s part of a possessive adjective. If so, we re-assemble the full noun phrase.

Separately, we do what the personScope module already did at this point, which is to take the noun phrase that failed to resolve and see if it corresponds to a Person not currently in scope. If it is, we get the Person instance.

Having done both of the above, we check to see if we got both a full noun phrase from the first part and an object from the second part. If so, then we know that the phrase is something like “Alice’s pebble”—it contains the possessive form of an in-game character’s name as part of a noun phrase. If that’s true, we handle it as a special case, reporting the failure appropriately.

If we didn’t get a full noun phrase (containing a possessive adjective) but we did get an out-of-scope Person object, then we handle that as a different special case. This is what the personScope module was already doing.

And if neither of the above applies, we fall through and use the default behavior.

In action, with a pebble that is neither blue nor Alice’s, in a game with blue objects and a character named Alice out of scope:

Middle Room
This is the middle room.  There are rooms north, south, and east of here.

You see a pebble here.

>x alice's pebble
You don't see Alice's pebble here.

>x alice
There isn't anyone named Alice here.

>x blue pebble
You see no blue pebble here.

>x blue's pebble
You see no blue here.

>x pebble
A small, round pebble.

No idea if this is going to need a bunch of further tweaking. My WIP has a bunch of cases where the player is going to be worried about what objects are (dirt-covered lump turning out to be an ancient pottery shard, or that kind of thing), who owns them (is the bloody knife Alice’s or Bob’s), and so on. Which involves a bunch of stuff that just on the ragged edge of easy to implement in T3…and whenever anything is just outside the ragged edge of easy, it turns into an all-day source dive kind of thing.

1 Like

Ooof. Just found another bit of weirdness in possessives. At first I assumed this must be the result of me messing around with scope, but this happens in stock adv3:

Void
This is a featureless void.

You see a pebble here.

>x alice's pebble
You see no alice here.

>n
Other Room
This is the other room.

You see a rock here.

Alice is standing here.

>s
Void
This is a featureless void.

You see a pebble here.

>x alice's pebble
Alice does not appear to have any such thing.

>

This is &noMatchForPossessive, getting called in a thrown exception via VocabObject.throwNoMatchForPossessive(), in turn from BasicResolveResults.noMatchForPossessive().

Back at it I guess.

1 Like

Okay, I think that’s sorted.

The change is on playerMessages.noMatchForPossessive(). It gets three args: the actor, the owner for the possessive, and the noun phrase the parser is complaing about. So in the case of >X ALICE'S PEBBLE, the actor is gActor, the owner is Alice’s Person instance, and the noun phrase is “pebble”.

I just added a check to see if owner is in actor’s scope list, and if not, re-constructs the possessive noun phrase from owner and the noun phrase argument and pass the result to the same message method already used for out-of-scope possessives.

Middle Room
This is the middle room.  There are rooms north, south, and east of here.

You see a pebble here.

>x alice's pebble
You don't see Alice's pebble here.

>n
North Room
This is the north room.  There's another room to the south.

Alice is standing here.

>s
Middle Room
This is the middle room.  There are rooms north, south, and east of here.

You see a pebble here.

>x alice's pebble
You don't see Alice's pebble here.

>
1 Like

Sounds like fun times…