Doer scope limiter not working (adv3Lite)

I have three doors, each with a doorbell attached, but only one of them can be answered.

For the two that can’t, and for ringing any other thing, the ring action is handled in a Doer

Doer 'ring Thing' when = gDobj != doorbell300b execAction(curCmd) { local item = curCmd.dobj.name; switch(item) { case 'doorbell': "As you press the button for the "; say(item); ", you hear a faint <i>ding dong</i> from behind the door. </p>"; break; default: "Your attempt to ring the "; say(item); " falls flat. There is no ringing sound, only a dull <i>thwp</i>.<.p>"; } } ;

For the doorbell that can be answered, I handle the ring action in a dobjFor(Ring) on the doorbell object…

dobjFor(Ring) { check() { if(!jobSeeker.canChangeClothes) { "As you press the button for the for the doorbell to 300b, you hear a faint <i>ding dong</i> from behind the door. </p>"; } } action() { coleridge300b.makeOpen(true); lucy.moveInto(coleridgeLanding); "You ring the bell and wait for what seems like an eternity. Finally, you hear a click as the latch turns, and a voice booms loud from behind the opening door. <.p>"; lucy.setState(lucyAnsweringFrontDoorState); jobSeeker.setState(jobSeekerWithLucyAferMuggingState); lucy.initiateTopic(coleridgeLanding); } } ;

But the Doer is intercepting the ring action on all objects, including the doorbell300b object that should be excluded by the when property. This blocks the local dobjFor() action, even though I can see in the debugger the when = gdobj != doorbellb condition is true.

The Ring command is implemented as…

[code]// ring
VerbRule(Ring)
(‘ring’) singleDobj
: VerbProduction
action = Ring
verbPhrase = ‘ring/ringing’
missingQ = ‘ring what’
;
DefineTAction(Ring)
;

[/code]

How can I limit the scope of the Doer so that it will intercept ring actions on anything except the doorbell to 300b?

Jerry

Actually, you don’t need a Doer. You can get what you’re looking for just as easily by coding dobjFor(Ring) on the Thing class to create a default, a second response on the Doorbell class (assuming you’ve created such a class), and then a specific response on the object that you want to produce a specific response. That would be the normal TADSy way of doing it.

Not saying there isn’t a library bug here. Could be. On the other hand, at the point when the Doer is activated, gDobj may not have a value. It may acquire a value by the time you see it in Watch Expressions in Workbench, but without setting a breakpoint you won’t know for sure when that value was established.

Hmmm, okay, thanks. I hadn’t thought of modifying the Thing class. I’ll give it a try.

Meanwhile, I have just a few minutes ago got the Doer to work.

Turns out, the Doer implementation in the library does not appear to recognize != as an inequality operator.

When I redefined the when condition as !(x == y) instead of x != y, it works.

Jerry

It might also work if you put parentheses around the condition, or made it a method:

when = (gDobj != doorbell300b)

or possibly (untested, and my T3 is rusty):

when { return gDobj != doorbell300b; }

The only solution I’ve found that works is !(x == y)

Doer 'ring Thing' when = !gDobj == doorbell300b // yes, works, with or without parens // when = (gDobj != doorbell300b) // no, does not work, with or without parens // when { return gDobj != doorbell300b; } // no, function does not work

Jerry

I’m pretty sure this is the case. At the point the library is checking whether a Doer matches its conditions, gDobj hasn’t yet been assigned.

You could possibly comfirm this by testing for gCommand.dobj instead. A quick test shows that this works as you expected:

Doer 'ring Thing'
    when = gCommand.dobj != doorbell300b // NOTE CHANGE HERE
    execAction(curCmd)
    {
        local item = curCmd.dobj.name; 
        switch(item)
        {
        case 'doorbell':
            "As you press the button for the ";
            say(item);
            ", you hear a faint <i>ding dong</i> from behind the door. </p>";
            break;
        default:
            "Your attempt to ring the ";
            say(item);
            " falls flat. There is no ringing sound, only a dull
            <i>thwp</i>.<.p>";
        }
    }
;

But it would be neater to code it like this:

Doer 'ring Thing'    
    execAction(curCmd)
    {
        local item = curCmd.dobj.name;
        switch(item)
        {
        case 'doorbell':
            "As you press the button for the ";
            say(item);
            ", you hear a faint <i>ding dong</i> from behind the door. </p>";
            break;
        default:
            "Your attempt to ring the ";
            say(item);
            " falls flat. There is no ringing sound, only a dull
            <i>thwp</i>.<.p>";
        }
    }
;

Doer 'ring doorbell300b'
;

Then the more specific Doer will take precedence over the less specific one, so that Doer ‘ring Thing’ won’t be matched if the direct object is doorbell300b; but Jim’s suggestion for handling it is better still.

However, since this looks like an accident waiting to happen for the unwary game author, I’ll try adding some code to set the values of gDobj and the like earlier in the cycle so that Doer conditions can use them.

Then why does when = !( gDobj == y ) work?

Jerry

It doesn’t; at least, not when I try it. But it’s not what you wrote in your sample code, which was:

Doer 'ring Thing'
    when = !gDobj == doorbell300b               // yes, works, with or without parens
//    when = (gDobj != doorbell300b)            // no, does not work, with or without parens
//    when { return gDobj != doorbell300b; }    // no, function does not work

when = !gDobj == doorbell300b is not the same as when = !(gDobj == doorbell300b).

If you test further, you’ll find that when = !gDobj == y always fails the test (i.e. the Doer is never matched), no matter what the value of y, so it isn’t really working as a test.

If you set a breakpoint in Doer.findDoers() you’ll see for yourself that gDobj is nil at the point at which this method is looking for Doers that match the command (and so is testing their when conditions). You’ll also see that the following expressions have the following values:

gDobj nil
!gDobj true
!gDobj == doorbell300b nil
!(gDobj == doorbell300b) true

The third of these is testing whether true == doorbell300b, which it doesn’t, so the Doer will never be matched.