Is there a way to make properties depend on other parts of the world state?

I’ve got the following simple little example:

Brightroom is a room. "Brightly lit by a spotlight above."
Darkroom is a room. It is dark. "Lit by light coming in through the door."

The lightproof door is a door. It is east of Brightroom and west of Darkroom.
After opening the lightproof door:
    now Darkroom is lit;
    continue the action.
After closing the lightproof door:
    now Darkroom is not lit;
    continue the action.

This obviously works, but I was wondering if it was possible to get the same behaviour in a slightly more declarative way, like

Brightroom is a room. "Brightly lit by a spotlight above."
Darkroom is a room. "Lit by light coming in through the door."
The lightproof door is a door. It is east of Brightroom and west of Darkroom.

To decide whether Darkroom is lit:
    decide on whether or not the lightproof door is open.

But this doesn’t actually connect to the Darkroom’s lit property, it just makes a new phrase “if Darkroom is lit”. Is there a way of doing what I’m looking for here?

1 Like

Inform 7 doesn’t offer methods that would make it transparent whether you were accessing stored data or the result was being calculated dynamically. Action rules, in particular either Carry Out or After rules, are the natural I7-ish way to accomplish what you’re after here. The other approaches I can think of would both add complication and invite problems.

2 Likes

I believe the format is:

To decide whether Darkroom is lit:
    if the lightproof door is open, decide yes;
    decide no.

This might run into the issue that the “lit” property has its own rulebook that might overrule decide rules.

Usually decide is for a more unusual property like

To decide whether danger lurks: 
    if in darkness, decide yes; 
    if the Control Room has been visited, decide no; 
    decide yes.

2 Likes

Lighting is handled at a pretty deep and primitive level, below the Standard Rules (i.e. in the template layer), so it’s not exactly easy to modify. But not impossible, either.

Here’s a quick (and only cursorily tested) extension that might be of use to you (EDIT: compressed and updated, see reply below).

Dynamic Lighting.i7x.zip (4.9 KB)

I would be interested in fixing any bugs that are found.

2 Likes

Unless I misunderstood something, I think such an extension already exists.

But it’s quite old, and I don’t know if it still works with the last version of Inform 7.

1 Like

This extension looks really cool. I tried it just now in 6G60 and it appears to work fine. Compiles fine, and I tested one of its rules, and it worked. The demo below shows it using a rule to determine the lit status of a lantern, and going into a dark cave.

Include Alternate Lighting System by Daniel Stelzer.

Lab is a room. "There is a dark cave to the east.".

Cave is east of lab. "The lab is west.".

cave is dark.

a lantern is a device in lab.

Special light calculation for the lantern:
	if the lantern is switched on:
		rule succeeds;
	rule fails;

Test me with "get lantern/e/w/turn on lantern/e".

-Wade

That extension is quite similar. The main difference is that mine covers other uses of the light attribute in the template layer (e.g. for list-writer routines).

On closer inspection, however, I saw that I missed the handling of the built-in “lit” and “unlit” adjectives in ScoreMatchL(), and that the variable lighting rulebook was being run even when it wasn’t necessary.

It also looks like there is a minor issue with the 6M62 list-writer code: Things that are otherwise indistinguishable instances of the same kind aren’t listed as “ (providing light)” when in a location providing light. Instead, you get output like “You can also see two magical pebbles and three magical pebbles here.” The same situation in an unlighted room would output “You can also see two magical pebbles (providing light) and three magical pebbles here.

The root of this issue seems to be in the interaction between routines ListEqual() and WriteAfterEntry(). ListEqual() drives creation of different listing groups for things based on differing light attribute values irrespective of location lighting conditions, so two groups are created. WriteAfterEntry() decides not to mention the lit status of the lit group. I assume that the intent of WriteAfterEntry() as currently constructed is to de-emphasize the lit nature of, say, a brass lamp in a room that has its own light.

The extension now aims to harmonize the template code’s logic for this type of thing and allows the author to choose whether or not to suppress the “ (providing light)” notice. (The default is to not suppress it, however, because it seems odd to deny this information to the player in cases like the magical pebbles example.)

Huh, this has been interesting. I hadn’t quite made the obvious connection that new phrases are basically the same as “declarative” properties, as long as it’s a new property. Or that light is kinda a special case already. I’ll check out the extensions, thanks!