Dynamic relations: what's the idiom?

Imagine a game with a stealth system that involves hiding on top of things, behind things, underneath things, and so on. We’d want a way to specify which positions work for which things.

(#wall allows concealment #behind)
(#wall allows concealment #ontop)

Sometimes, which positions work for which things depends on other factors.

(#crate allows concealment #in)
    ~(#motorcycle is #in #crate)

Then we can determine which things are valid hiding places.

(valid hiding place $item)
    ($item allows concealment $)

And so on.

Now suppose I want to do this in Inform 7.

A relation between things and hiding-positions seems like the obvious solution. But that doesn’t allow us to make the relationship depend on other factors, like the crate allowing concealment iff the motorcycle isn’t in it.

We could make the relation depend on a phrase:

Concealment-potential relates a thing (called X) to a hiding-position (called Y)
when X can accept Y for concealment.

To decide whether (X - the crate) can accept (Y - a hiding-position) for concealment:
    if Y is not inside-position, no;
    if the motorcycle is in the crate, no;

But this means we have to explicitly write one of these phrase definitions for every thing, and can’t use a nice relation assertion sentence (“the wall allows concealment in above-position and behind-position”).

What’s the idiomatic way to do this?

Strikes me as a job for rulebooks.

A hiding-position is a kind of value.
Some hiding-positions are underneath, on-top-of, behind, inside-of.
a hiding-position has a thing based rulebook called the guide.

hiding-inside is a thing based rulebook.
hiding-inside the crate when the crate contains the motorcycle: rule fails.
hiding-inside a container: rule succeeds.
last hiding-inside: rule fails.
The guide of inside-of is the hiding-inside rules.

To decide if (t - a thing) can accept (Y - a hiding-position) for concealment:
  follow the guide of Y for t;
  decide on whether or not rule succeeded.
1 Like

Zed beat me to it (with maybe a better idea that I had), but yeah, I would use rulebooks too.

The idea of having a rulebook per position is clever! Too bad Inform can’t have rulebooks taking multiple arguments.

(I was going to suggest a single rulebook where the position would be stored inside a global or a rulebook variable, but Zed’s idea might be better.)

1 Like

This works, but it means each position is an independent rulebook, which gets rid of a lot of the flexibility of Inform rules. One of the big benefits of rules is that you don’t have to think about whether a “before cutting the apple with the knife in the presence of Bob” behavior goes in the cutting action, the apple object, the knife object, or the Bob object. With this, if I decide that I want a general behavior to apply to a bunch of different positions for the same object, I have to duplicate the code.

I had started out with a scheme where there’s a hiding-node object that has a thing and a hiding-position, and it can be in-use, and the can accept for concealment phrase gets a random not in-use hiding-node, marks it in-use, and follows a single comprehensive hiding-node based rulebook. That rulebook would have a rulebook variable for each of the thing and the position and a first rule that unpacks the hiding-node parameter into its component parts. (can accept for concealment recycles the hiding-node object by marking it not in-use again.)

The following is more English-y, but at the cost of dependence on a global in a way I’m not thrilled about.

A thing has a hiding-position called position under consideration.
The verb to consider means the position under consideration property.
Hiding-potential is a thing based rulebook.

To decide if considering (y - a hiding-position):
  decide on whether or not the position under consideration of the container in question is y.

Hiding-potential for the crate when considering inside-of and the motorcycle is in the crate: rule fails.
Hiding-potential for a container: rule succeeds.
Last hiding-potential: rule fails.

To decide if (t - a thing) can accept (Y - a hiding-position) for concealment:
  now t considers Y;
  follow the hiding-potential rules for t;
  decide on whether or not rule succeeded.
1 Like

I’ve used globals as rulebook “parameters” with no shame. In fact the Ritual-Processing rulebook in Hadean Lands, which has most of the rules for doing magic, has about ten globals parametrizing all the stuff that goes on in various ritual actions.

It’s only a problem if you plan to run the rulebook recursively. And even if you are, you can manage the situation with a strategic wrapper function and some local variables to stash the state in.