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.