apostrophe in vocab words interferes with take command

I have a character who has a wallet that contains a driver’s license.

If I enter take driver’s license, the game responds that there is no driver’s license, yet when I look in the wallet, it is listed correctly.

If I enter take driver, the license is taken as expected.

Is there a way to trap the apostrophe and allow the command to succeed?

The apostrophe is really the only way to correctly name the thing; none of the most obvious alternatives sound correct…

driver license
driving license
license

Here’s my code…

#charset "us-ascii"

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

versionInfo: GameID
    IFID = '47ca87f1-2d0e-4b54-a776-2bc128e30927'
    name = 'TADS 3 Lite Test Bed'
    byline = 'by Jerry Ford'
    htmlByline = 'by <a href="mailto:jerry.o.ford@gmail.com">
                  Jerry Ford</a>'
    version = '1'
    authorEmail = 'Jerry Ford <jerry.o.ford@gmail.com>'
    desc = 'Test bed for experimenting with TADS 3 Lite.'
    htmlDesc = 'Test bed for experimenting with TADS 3 Lite.'
;

gameMain: GameMainDef
    initialPlayerChar = harry
    usePastTense = true
;

// harry, main character
harry: Actor 'Harry;;man self' @harrysBedroom
    ""
    contType = Carrier
    globalParamName = 'harry'
    isFixed = true   
    isHim = true
    isInitState = true
    ownsContents = true
    person = 3   
    proper = true
    
;
+ wallet: Thing 'wallet;;wallet'
    "Harry's wallet"
    
    listContents = nil
;
++ driversLicense: Thing 'driver\'s license;;license'
    "Harry's driver's license"
;

harrysBedroom: Room
    'Bedroom' 'bedroom'
    "The bedroom."
    
    listContents = nil
;

…and here’s the game play…

(And yes, I know, I still have to fix the “on which was” for the wallet contents, but one thing at a time.)

(Btw, it’s a good idea to mention that you’re using Adv3Lite.)

Shouldn’t it be:

'driver\'s license;;driver\'s license'

Unfortunately this seems to be a ‘feature’ of the Mercury parser I can’t immediately find a way round (though obviously I’ll keep investigating). While I’m not trying to dodge responsibility here, this is code that Mike Roberts wrote, and this is one part I haven’t entirely figured out.

The problem is that the English language tokenizer splits “driver’s license” into three tokens (“driver”, “'s” and “license”) but only stores “driver” and “license” as vocabWords belonging to the driversLicense object, while retaining all three tokens from the player’s input when trying to match it against a game object. You can attempt to defeat this by entering the vocab as:

++ driversLicense: Thing 'driver\'s license; \'s; driver'
    "Harry's driver's license"
;

But, as you’ll see when you try it, that just gives you another problem.

So it looks to me as if Mike wrote the parser so that an apostrophe-S ending would always be parsed as an attempt to match a game object that’s explicitly owned by another game object (which doesn’t work here). I’ll try figuring something out, but I may have to go back to Mike for a solution!

Thanks. I can see the difficulty in parsing the apostrophe-s.

I guess listing the thing as a driver license is not so onerous after all; I took a look at my California license, and that’s what it’s called, on the card itself: CALIFORNIA DRIVER LICENSE.

I guess you can’t fight the DMV.

(And yes, RealNC, you are correct, it’s adv3Lite, and it does matter—vocab words are declared differently in the lite library. Sorry for the omission.)

In the meantime, here’s one workaround I’ve come up with. Define the driver’s license thus:

++ driversLicense: Thing 'driver\'s license; driver^s;'
    "Harry's driver's license"        
;

Then add the following at the end of your code:

StringPreParser
    doParsing(str, which)
    {
        return str.toLower.findReplace('driver\'s', 'driver^s');
    }
;

Excellent! Thanks, works great.

Great! I’m glad it works for you!

I’ll probably put something in the next release that effectively does this for you, unless I can come up with a better solution.

In the meantime I should perhaps points out that it makes no sense to define listContents = nil on the wallet and the bedroom. listContents is a method, not a property, and overriding it to nil could have potentially catastrophic consequences. Perhaps you meant to set the contentsListed property to nil, which is fine on the wallet, but wouldn’t work on a Room.

Okay, thanks. When you put it in the library, will it be something more generic, or just special-case for driver’s?

Thanks also for the tip re: listContents vs. contentsListed. Yes, I was getting them confused, and the latter appears to be what I want. I’ll have to be more careful.

FYI, mentionedh is another property I thought I could use for my own purposes, but it turns out your advisory in the Reference library that, as it’s set by the system, it’s best left untouched turns out to be true.

I want to control when items in a room become visible in look or examine, (can’t see the pocket until you’ve seen the pants, can’t see the wallet until you’ve seen the pocket) so I was overriding mention until conditions suited me. Not such a good idea. The system was setting it back to nil at unexpected times. I ended up creating my own xxxHasBeenMentioned property for each thing I wanted to control. This lets me set it to true anytime I want and I can have confidence it will remain that way unless and until I decide otherwise.

Jerry

I had in mind something generic. The idea is that when you have a possessive in a vocab property, say ‘foo’s bar’, the routine that stores the vocab words for the object will store it as ‘foo^s bar’ and at the same time make a note that “foo’s” needs to be replaced by “foo^s” in the player input (by storing this in a LookupTable). A StringPreParser will then check every word in the player’s input against a table of replacements and so replace “foo’s” with “foo^s”. This should work whatever “foo” happens to be, or however many such possessive forms you use in your game.

One potential problem with this scheme is if you have an NPC called ‘Harry’ say, and specifically name something as ‘Harry’s wallet’ or ‘Harry’s nose’, since this will sever the normal possessive matching between an owned object and its owner. I have a solution to that, but game authors will need to remember to use it. (Basically it’s to employ a new ownerNamed property).

But this is all a bit provisional at the moment, and may change once I’ve experimented with it a bit more and polished it up a bit.

That’s right; mentioned is property intended for the internal use of the library; it’s best not for game code to mess with it.

You may be able to do this by manipulating the isListed properties of the objects concerned. Or for the wallet, you might use hiddenIn:


+ pants: Wearable 'some pants;;them'
    "They have a pocket. "
    wornBy = harry
;

++ pocket: Fixture, Container 'pocket'
    hiddenIn = [wallet]
;
    
wallet: Thing 'wallet' // NB You don't need to repeat 'wallet' here!
    "Harry's wallet. " 
;

With this scheme, the player explicitly has to LOOK IN POCKET to find the wallet. If you want the wallet to be found with EXAMINE PANTS as well you could try something like this:

++ pocket: Fixture, Container 'pocket'
    hiddenIn = [wallet]
    
    examineStatus()
    {
        if(!wallet.moved)
            doNested(LookIn, self);
        else
            inherited;
    }
;