Some of you probably already noticed from my previous test that I’m replacing the lighting system with rulebooks.
For reference, this is the core of what I did:
Lighting Rulebooks
Light emission rules are an object based rulebook.
Light emission rules have outcomes it is emitting light (success) and it is unlit (failure).
Light absorption rules are an object based rulebook.
Light absorption rules have outcomes it admits light (success) and it blocks light (failure).
Lighting level rules is an object based rulebook.
Lighting level rules have outcomes it is bright (success) and it is dark (failure).
Include (-
[ HasLightSource obj;
return FollowRulebook((+ light emission rulebook +), obj, true) && RulebookSucceeded();
];
-) replacing "HasLightSource".
To decide whether (it - a thing) is emitting light: (-
HasLightSource({it});
-).
To decide whether (it - a thing) is not emitting light: (-
~~HasLightSource({it});
-).
Include (-
[ HidesLightSource obj;
return FollowRulebook((+ light absorption rulebook +), obj, true) && RulebookFailed();
];
-) replacing "HidesLightSource".
To decide whether (it - a thing) admits light: (-
~~HidesLightSource({it});
-).
To decide whether (it - a thing) blocks light: (-
HidesLightSource({it});
-).
Include (-
[ OffersLight obj;
FollowRulebook((+ lighting level rulebook +), obj, true);
return RulebookSucceeded();
];
-) replacing "OffersLight".
Definition: a room is bright rather than dim if I6 routine "OffersLight" says so (it is offering light).
Definition: a container is bright rather than dim if I6 routine "OffersLight" says so (it is offering light).
But showing it off isn’t the purpose of my post. I want to make sure I covered all the cases that the core lighting routines cover. I have a simple test case:
The Chapel is a room.
"It's a high vaulted chapel. Very pretty!"
The chapel switch is a light switch in the Chapel.
It illuminates the Chapel.
It is switched on.
The confessional is a closed openable enterable opaque container.
It is in the Chapel.
The kiosk is a closed openable enterable transparent container.
It is in the Chapel.
Some pews are an enterable supporter in the Chapel.
The flashlight is a light source carried by the player.
There is a candy in the confessional.
There is some cash in the kiosk.
There is a hymnal on the pews.
There are a couple of custom kinds in there, but they’re fairly self-explanatory – the light switch
effectively toggles the room between lighted and dark, and the light source
toggles itself between lighted and dark (both are kinds of devices).
What follows are rules that I think are equivalent to the built-in checks.
OffersLight
[Note: I'm not sure if Inform would order these correctly by default, but assume that they're explicitly listed in the order shown here.]
Lighting level rule for a lighted room:
[should cover "if (obj has light) rtrue"]
it is bright.
Lighting level rule for a room (called there):
[should cover "objectloop (j in obj) if (HasLightSource(j)) rtrue"]
repeat with the article running through everything in there:
[just checking: "in" is only directly contained things, right?]
if the article is emitting light, it is bright.
Lighting level rule for a closed opaque container:
[should cover "if ((obj has container) && (obj hasnt open) && (obj hasnt transparent)) rfalse]
it is dark.
Lighting level rule for something incorporated by something (called the parent):
[should cover "if ((obj provides component_parent) && (obj.component_parent))"]
abide by the lighting level rules for the parent.
Lighting level rule for something held by something (called the parent):
[should cover the "else" case; not quite sure if "held by something" is allowed, will check soon]
abide by the lighting level rules for the parent.
Last lighting level rule:
it is dark.
HasLightSource
Light emission rule for a lit thing:
[should cover "if (i has light) rtrue"]
it is emitting light.
Light emission rule for a lighted room:
[also covers "if (i has light) rtrue" for the case of a room]
[not sure if these rules need to cover rooms though]
it is emitting light.
Definition: a thing is see-through if I6 routine "IsSeeThrough" says so.
Light emission rule for a see-through thing (called it):
[should cover "if ((IsSeeThrough(i) && (~~(HidesLightSource(i)))) objectloop (j in i) if (HasLightSource(j)) rtrue"]
if it admits light:
repeat with the article running through everything held by it:
if the article is emitting light, it is emitting light.
[I have no idea what "ad = i.&add_to_scope" does, so by extension I have no idea what the following block does either.]
Light emission rule for something (called the parent) that incorporates something (this is the propagate lights from components rule):
[should cover "if (ComponentHasLight(i)) rtrue"]
repeat with the part running through things incorporated by the parent:
if the part is lit or the part is emitting light, it is emitting light;
if the part incorporates something:
follow the propagate lights from components rule with the part;
if the rule succeeded, it is emitting light.
HidesLightSource
Light absorption rule for the player:
[should cover "if (obj == player) rfalse"]
it admits light.
Light absorption rule for a something transparent
[should cover "if (obj has transparent) rfalse"]
it admits light.
Light absorption rule for a supporter:
[should cover "if (obj has supporter) rfalse"]
[note: this probably misses rideable animals though, while the default implementation handles them]
it admits light.
Light absorption rule for a person:
[should cover "if (obj has animate) rfalse"]
[note: technically non-persons could be made animate, but that's not normally done]
it admits light.
Light absorption rule for a container (called the box):
if the box is open, it admits light;
otherwise it blocks light.
Last light absorption rule for something (called it):
if it is enterable, it admits light;
otherwise it blocks light.
My first goal here is to verify that the rules I’ve written reflect the same logic as the original I6 code, and in particular to fill in that one big gap related to scope in HasLightSource
. If the best way to fill it in is to put that code back in the I6 routine, that is an option, but I would like to know what it’s doing first.
My second goal here is to extend the test case to cover more possibilities. For example, probably the test case should have some cases involving things that are part of something. Is there anything else that’s missing?