adv3Lite: PourInto and PourOnto

Here’s a little puzzler (solved – see below). It’s also a bit of a spoiler, but since I’ll probably never finish this game, I’m not going to worry too much about that.

The problem is this: I have a bottle of poison that needs to be poured into (or onto) some gunk that’s in a transparent container (it’s down underneath a metal grate). The PourOnto action works exactly as I expect it to, whether I choose the gunk or the grate as the object of the pouring action. PourInto works if I choose the grate (the container) as the object of the action, but NOT if I choose the gunk that’s underneath the grate.

The reason this makes no sense to me is because the two actions are coded in exactly equivalent ways. For starters, both the grate and the gunk have

allowPourIntoMe = true allowPourOntoMe = true
And the bottle where the pouring action is coded has

dobjFor(PourInto) asDobjFor(PourOnto)

In addition, the grate object has this:

canReachIn { if (isOpen) return true; if ((gAction == PourOnto) || (gAction == PourInto)) return true; return nil; }
As far as I can see, then, there’s no difference between ‘pour liquid onto gunk’ and ‘pour liquid into gunk’ – but nonetheless, the former command works, while the latter command gives me a “You can’t pour the liquid into that” message.

Edit: As it turns out, this is down to the fact that the grate is a container, while the gunk isn’t. In addition to allowPourIntoMe, a separate property called canPourIntoMe also has to be set. I guess I’m not exactly clear about the difference between the two…

The difference between canPourIntoMe and allowPourIntoMe is quite subtle. The first controls whether it is physically possible to pour something into object in question. The second controls whether you want the game to allow it. It would normally be possible to pour something into just about any open container, but you may not want to allow that to happen in your game, since otherwise you’d have to provide handling for pouring stuff into every container in your game.

Suppose, for example, you have a metal can, a red coffee mug, and a red ball.

POUR OIL INTO RED should prefer the mug to the ball, since it’s more meaningful to pour something into a mug than into a ball. canPourIntoMe is therefore true on the mug (and the metal can, but not the ball) because it’s physically possible to pour oil into the mug.

But suppose you don’t actually want stuff to be poured into the mug in your game, but only into the metal can. Then you set allowPourIntoMe as nil on the mug but true on the can (while canPourIntoMe would be true on both).

Ah – so these properties are being used somewhat as the equivalent of the verify/check distinction. I get it. I’m still getting used to this business of properties being used for making subtle distinctions. The other thing that takes some getting used to, I think, is that so many of the properties are defined on Thing, even though they may be conceptually related to the behavior of a subclass.

Any library is complex. I’m not complaining, just noticing.