Problem with object possession and identical names

so this is the basic scenario i’m stuck with:

#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
#include <extensions/TCommand/TCommand.t>

versionInfo: GameID
    name = 'the lab'
;

gameMain: GameMainDef
  initialPlayerChar = me
;

Room 'lab' 'lab';

+ me: Actor ;

+ tim: Person 'tim' 'tim'
  isProperName = true
  isHim = true
;

++ TCommandTopic @PutOnAction
  obeyCommand = true
;

+ Surface, Immovable 'finger scanner' 'finger scanner';

Thing 'finger' 'his finger' @tim
  isQualifiedName = true
  owner = tim
;

Thing 'finger' 'your finger' @me
  isQualifiedName = true
  owner = me
;

what i’m trying to achieve is that when i refer to ‘finger’ alone, it always translates to my finger, and not tim’s.
here’s how the current code is behaving right now:

>x finger
(your finger)
You see nothing unusual about it.

>put finger on scanner
(your finger)
Done.

>put finger on scanner
(first taking his finger)
Tim won't let you have that.

>x finger
Which finger do you mean, your finger, or his finger?

>

so i want to be able to have either my finger, or tim’s on the scanner (and yes, it’s important that the finger is then actually on the scanner), but as you can see, as soon as my finger is no longer in my inventory, i can only solve the disambiguation by typing “my / your finger” or “his / tim’s finger”. that would be a solution, but it’s not one i’m happy with for reasons that aren’t obvious from this short example. and ideally, the solution would also get rid of the disambiguation report.
i’ve been messing around with this for quite some time now, and haven’t really gotten anywhere.
any ideas?

cheers

Hi again… how did you code the finger objects? Does the game actually move the finger object out of your player character’s “contents” and moveInto(scanner)?
You could override finger.dobjFor(PutOn) to simply set a property flag instead… if you’re familiar with the TADS verify routines at all, you’ll find that if an object is already “put on” something, by default the parser will look for a different object to “put on”. Apparently it chooses Tim’s finger the second time because it is more “logical” to put a finger on the scanner that isn’t already there yet.
You should be able to override this behavior in the finger object code, and its dobjFor. You might also try the vocabLikelihood property, which, if you assign your own finger a number higher than zero, should always prefer your finger to Tim’s, other things being equal.
Disambiguation is something I haven’t completely solved the mysteries for, but if you haven’t already, I’d suggest reading chapter 19 in Learning TADS 3, and being acquainted with matchNameCommon, filterResolveList, etc.
This might be a total hack and not solve your problem, but in some cases of similarly-named objects in the same room, I listed the name of the one of lesser importance as an adjective instead of a noun, since the parser should always choose a noun over an adjective.
Thus:

myFinger: Component 'my finger*fingers' @ me
timsFinger: Component 'tim\'s finger -' @ tim

(the hyphen indicates a placeholder for no nouns in the vocab, if you didn’t already discover that… but I don’t know if this hack would even be a solution for you…)

haha, did you scroll down for the fingers code? :slight_smile:

yeah, i thought of flags too, but that would be a really messy workaround, since i’m actually doing something way more complicated than in this example, i.e. there will also be other objects on the thing that is the scanner in this example, and i would really like to have the same behavior for all objects.
i didn’t get anywhere with machNameCommon since i just don’t have the information i need in that method (or i don’t know where to look for it).
i also tried vocabLikelihood, but in doing so i found out that it’s somehow ignored in this specific case.
what i haven’t tried yet is messing around with object scope, but i haven’t really found much info on that.
i’m afraid your last proposal won’t cut it in my actual ingame situation :frowning:

That’s hilarious, I didn’t scroll down in your code either…
This is lifted from Learning TADS 3… could you adjust this for Tim’s finger, so that the parser will only choose that object if “tim’s finger” is entered?

+ carKey: Key 'car key*keys' 'car key'
    matchNameCommon(origTokens, adjustedTokens)
{
/*
         *   We're looking for the exact phrase 'car key' which the player
         *   will only have typed if adjustedTokens is ['car', &adjective,
         *   'key', &noun] with possible variations in the case of 'car' and
         *   'key' and whether 'key' is singular or plural.
*/
        if(adjustedTokens.length == 4
            && adjustedTokens[1].toLower == 'car'
           && adjustedTokens[3].toLower is in ('key', 'keys'))
            return self;
return nil; }
;

…presuming that you only want tim’s finger to be referenced if the player explicitly types “tim’s finger” (or “his finger”)?

Have you also tried giving Tim’s finger a lower logicalRank in its verify routines?

1 Like

thanks for making me play around with logicalRank some more! my first attempts were fruitless, but i think i’ve got it working now.

with these changes:

+ Surface, Immovable 'finger scanner' 'finger scanner'
  iobjFor(PutOn) {
    action {
      for(obj in self.contents) {
        obj.moveInto(obj.owner);
      }
      inherited;
    }
  }
;

Thing 'finger' 'his finger' @tim
  isQualifiedName = true
  owner = tim
  verifyDobjPutOn {
    logicalRank((gActor == tim ? 100 : 0), 'fingers');
  }
;

Thing 'finger' 'your finger' @me
  isQualifiedName = true
  owner = me
  verifyDobjPutOn {
    logicalRank((gActor == me ? 100 : 0), 'fingers');
  }
;

i get this behavior:

>put finger on scanner
(your finger)
Done.

>put finger on scanner
(your finger)
Your finger is already on the finger scanner.

>tim, put finger on scanner
Tim puts his finger on the finger scanner.

>tim, put finger on scanner
His finger is already on the finger scanner.

which is exactly what i wanted (now i just have to get rid of the disambiguation message).
thanks again!

This is just a stab… you might try to override announceAmbigActionObject(obj,whichObj,action) of libMessages to return nil if the object is a finger…
I feel like a short while ago I knew where that parenthesized announcement was called, but I don’t have it filed in my memory…

That might not be the right method… let me know if you can’t find it after a little library reference hunting…

Perhaps libMessages.announceDefaultObject(obj, whichObj, action, resolvedAllObjects)…
I feel really silly that I used TADS 3 for almost a year before realizing that if you include the reflect files, the run-time errors automatically list the call stack for you… I was looking up line numbers in source files to trace call chains :-p

announceAmbigActionObject

that was the one that needed ovrerriding. thanks!

not knowing about the reflect library was probably a good learning experience though :slight_smile: