Sitting on a Cushion (adv3Lite)

Here’s a pretty little problem. I have a dangerous throne, on the seat of which rests a cushion. The player may try to sit on the throne, which works as expected – the player will get zapped, and will leap up again. But instead, the player may try SIT ON CUSHION. When this happens, there seems to be an implicit action running in the background. Even though the dobjFor(SitOn) code in the cushion object does not permit the action to go forward, the player object ends up sitting on the throne anyhow.

Note that I’ve included postures.t, which is where the Chair class is defined.

EDIT: Found the solution (but I’ll keep the rest of the message, describing the problem, in case someone is wondering what the fuss is about). Here’s the solution:

dobjFor(SitOn) {
    remap () { if (isIn(throne)) return throne; else return nil; }
    verify() { if (!isIn(throne)) illogicalNow ('The cushion is not arrayed
        in a manner that would be conducive to sitting. ');
    }
}

Here’s the output that demonstrates the problem:

> sit on cushion

(first getting on the throne)
You step up to the throne, turn, and sit. ZAP!!! A powerful shooting pain stabs you from near the base of your spine straight up to the top of your head! You leap off the throne, breathing rapidly and trembling.

> l

Throne Room (sitting on the throne)

Remarkable for its grand splendor (a cynic might call it ostentation), the Throne Room is dominated by an enormous throne encrusted with gold and jewels. On the walls, gently billowing tapestries depict a variety of legendary events.

A broad stairway leads down to the east. Mounted in the south wall is a square hatch.

You are on the throne.

That shouldn’t happen. The player should not be on the throne.

Note also that if the player tries SIT ON THRONE first, it operates normally, but if the second command is then SIT ON CUSHION, the player object is automatically sent to the throne, even though the cushion object should not be allowing that.

Here’s the code:

  • + throne: Chair, Fixture ‘throne; imposing splendid huge massive; chair’
    "The throne from which your father once ruled Oz is huge and decorated with
    a stunning array of gold and jewels. Its back is high and its armrests are
    thick. A plump purple cushion provides comfort for the royal fundament.
    Your father’s royal sceptre is attached to the throne’s right-hand armrest. "
    isDangerous = true
    hasZapped = nil
    canStandInMe = nil
    canStandOnMe = nil
    canLieInMe = nil
    canLieOnMe = nil
    dobjFor(SitOn) {
    verify() {}
    check() {
    if (isDangerous && hasZapped) "Nothing would induce you to try that experiment again. ";
    }
    action() {
    if (isDangerous) {
    hasZapped = true;
    "You step up to the throne, turn, and sit. ZAP!!! A
    powerful shooting pain stabs you from your nether region up your spine to
    the top of your head! You leap off the throne, breathing rapidly and trembling. ";
    }
    else inherited;
    }
    }
    ;
    
    ++ purpleCushion: Thing ‘plump purple cushion’
    "The cushion is decorated with gold tassels. "
    dobjFor(SitOn) {
    verify() { if (!(location == throne)) illogicalNow ('The cushion is not arrayed
    in a manner that would be conducive to sitting. ');
    }
    check() {
    if (throne.isDangerous && throne.hasZapped) "Nothing would induce you to try that experiment
    again. ";
    }
    action() {
    if (throne.isDangerous) {
    throne.hasZapped = true;
    "You step up to the throne, turn, and sit. ZAP!!! A
    powerful shooting pain stabs you from near the base of your spine straight up to
    the top of your head! You leap off the throne, breathing rapidly and trembling. ";
    exit;
    }
    else { "Testing. "; doInstead(SitOn, throne); }
    }
    }
    isListed = (!isIn(throne))
    ;
    

I had originally tried simply redirecting SIT ON CUSHION to SIT ON THRONE using a doInstead(SitOn, throne) in the cushion’s action() block, but that didn’t work. That was why I tried just copying the code for the throne into the cushion object. That didn’t work either.

Running in the debugger to check the value of me.location suggests strongly that an implicit action is causing SIT ON CUSHION to be redirected somehow to SIT ON THRONE (silently, with no output) after the cushion’s SitOn verify() runs but before SitOn check() is evaluated. But neither the throne nor the cushion has a defined beforeAction, so I don’t see how this could happen.

I’m sure there’s probably a simple way to do what I have in mind, but I’m a bit baffled.

2 Likes

It looks like you’ve solved this, but for future reference I suspect the behaviour you were seeing was triggered by the actorInStagingLocation precondition. If one nested room type object (A) is located in another (B) then if the actor attempts to enter A this precondition first moves the actor to A’s staging location, which is normally A’s location. To change this, you can override A’s stagingLocation property.

So, for example, you might define the cushion’s stagingLocation as:

  stagingLocation = isIn(throne) ? throne.location : location

Then if the cushion is on the throne, SIT ON CUSHION should move the actor to the cushion without first moving the actor to the throne.

1 Like

That makes sense, yes. In this case the cushion isn’t a nested room type object, it’s just a Thing, but since most classes are derived from Thing, I can see how there might be overlap in what the library does, especially since the SitOn action might have code that would reflect the idea that if the player can sit on things, they must be of the nested room type. I could be wrong; I’m just guessing. Anyway, it’s a fairly cute puzzle, in my humble opinion.

Summary

The magical item causing the problem for the player is under the cushion.

1 Like