How to capture player command in value holding a direction?

I am trying to write some rules to handle players in dark rooms. I have managed to get room descriptions working with the following source (sorry, not sure how to do tabs but I am not getting any indentation errors):

Rule for printing the description of a dark room: if an adjacent room is lit: repeat with that way running through directions: if the room that way from the location is lit: say "It is pitch dark, and you can't see a thing... except for a faint light coming from the [that way]."; otherwise: say "It is pitch dark, and you can't see a thing." instead.

…which quite nicely prints out a prompt that directs a player to move towards a lighted area is they have walked into a dark one without a light source. This wouldn’t work quite right if there were multiple adjacent lit rooms but I’ll avoid that with map design.

I want to apply similar rules to movement, that warn a player to move toward a lighted area if there is an adjacent lit area, or if there is no lit area adjacent, allow the player to move about. So I have this code:

Before going when the location is a dark room: if an adjacent room is lit: repeat with that way running through directions: if the room that way from the location is lit: if that way matches the player's command: say "Match." instead; otherwise: say "It is not wise to continue on in darkness. You can make out a faint light coming from the [that way]." instead; otherwise: say "It is not wise to continue on in darkness.".

But I am getting a type mismatch error. The temporarily created [that way] value holds a direction, but the player command holds a snippet which prevents a comparison.

So my question is, how can I store the contents of the players command in a value holding a direction so I can compare the two?

For the going action, the direction is stored in the noun. That is, the action is “going west,” where “west” is the noun. So where you want to test it, you could say “If the noun is that way.”

However, in this case, where you want to test the room the player is going to, you might want to use the action variable for going “the room gone to,” which stores the room that you’re trying to go to. For going, you can abbreviate “Before going when the room gone to is dark” with “Before going to a dark room.” And there’s “the room gone from,” which similarly abbreviates to “going from.” So like this:

Before going from a dark room to a dark room: [and then check for lit rooms]

One caveat is that, if you want to have this work whenever the player tries an invalid direction–if there’s no room at all to the south, rather than a dark room–you’d have to say:

Before going from a dark room when the room gone to is not a lit room:

In this case, “the room gone to” is nothing, which is not a lit room but not a dark room either.

Also, if you have more than one adjacent lit room your code will print a message for each adjacent lit room. You might want to have your code gather a list of directions and then print them all at once at the end.

Thank you! I’ve have been going mad trying to figure this out and knew it would be something simple like that.

And thanks for the tips how how to phrase it in other ways.

Do note that “a dark room” even includes rooms containing light sources! It just checks whether the room is lit of its own accord.

I believe “lighted room” means there is a light source or the room is lit.

Sadly no, there’s no built-in way. You can do a workaround with I7 (as explained in the Manual) or use a little I6 trick. Just include these two lines:

Definition: a room is light-filled rather than darkness-filled if I6 routine "OffersLight" says so (it contains a light source). Definition: a thing is light-filled rather than darkness-filled if I6 routine "OffersLight" says so (it contains a light source).

And now you can check if the room is “light-filled”, which takes into account lamps, candles, and other sources of light. (Note that this calculation is more expensive than the “lit” calculation, and doesn’t take into account lighted doors or backdrops.)

This is included in my collection of miscellaneous Helpful Functions.

Would “if the location of [something] is lit” work?

Anything referring to the property “lit” or “lighted” (they’re generally synonymous) is asking whether that room or thing provides light of its own accord. “Light-filled” is different; something is “light-filled” if it contains a light source, or is a light source. The player can see if and only if the holder of the player is light-filled, for example.

Thanks for the tips and sorry for late reply, I found out the hard way that my routines were not going to work right when I realised Inform was not dynamicly updating the Dark/Lit property of the room in response to lit objects within.

I was going to write some rules to update that property myself (based on an every turn rule) but your code snippet seems very eloquent. I haven’t had time to work on my code for a day, but I wondered, how does it handle lit objects being enclosed by a closed container? Would rooms still be light-filled or would it know to turn them dark again?

That would get stuck, right? Once you mark a room “lighted”, it’s a light source, so your every-turn rule will find that it’s illuminated forever after.

The point here is that there is no property of a room which tracks whether it’s light-filled. Inform computes that on the fly, every turn, but only for the current room. Draconis’s snippet taps into that computation, although it’s imperfect for other rooms – that’s why the warning about backdrops.

The internal light computation takes account of containers properly. Light escapes from a container if it is open, transparent, or both.

I was going to do something along the lines of:

Every turn: If the location encloses a lit thing: now the location is not dark; otherwise: now the location is dark.

Sorry for lack of indentation, on a phone ATM.

“The location” only means the room that the player is in. If you want it to go through all rooms, you’d have to loop over rooms.

However, if you wanted that effect it would be simpler just to define an adjective:

Definition: A room is light-enclosing if it encloses a lit thing. Definition: A room is light-filled if it is lit or it is light-enclosing. Definition: A room is truly dark if it is not light-filled.

(I haven’t tested these so they might not be quite right.)

And then you could just use “Before going from a truly dark room when the room gone to is not light-filled” or something like that.

However, as the other folks have pointed out, this won’t catch every case–if you have a lighted thing in a closed opaque container, it’ll count as light-filled by this definition. So it’s probably better to use the I6 trick Draconis mentioned, which does all the lighting calculations.

(The reason it doesn’t work for lighted doors and backdrops is that those are floating objects–they aren’t really in more than one room at once, so the game moves them around to be in the player’s location as needed, which means that when the player isn’t in a room the game won’t count a lighted door as being there, even if it really should. But you can avoid that by not having lighted doors or backdrops.)

Those definitions wouldn’t make changes to the dark property of the room though, would they? They would just create another property to check?

Indeed. You don’t want to mess with the dark/unlit/lit/lighted property, usually. That’s designed to indicate whether something is, in and of itself, a source of light. Using it for anything else is inviting trouble.

OK - So you basically have to ignore that system, create your own properties for handling light and then write new rules for actions based on those properties?

OK - Here’s all the code I have relating to light and darkness which appears to be working so far:

[code]A room can be naturallylit. A room is usually naturallylit.

Every turn:
if the location is not naturallylit:
if the location does not enclose a lit thing:
now the location is dark;
otherwise:
now the location is not dark.

Rule for printing the description of a dark room:
if an adjacent room is lit:
repeat with that way running through directions:
if the room that way from the location is lit:
say “It is pitch dark, and you can’t see a thing… except for a faint light coming from the [that way].”;
otherwise:
say “It is pitch dark, and you can’t see a thing.” instead.

Before going when the location is a dark room:
if an adjacent room is lit:
repeat with that way running through directions:
if the room that way from the location is lit:
if that way is the noun:
continue the action;
otherwise:
say “It is not wise to continue on in darkness. You can make out a faint light coming from the [that way].” instead;
otherwise:
if the blindturns of the player is less than 15:
now the blindturns of the player is the blindturns of the player plus 1;
say “It’s not a good idea to go blundering about in the dark, you could trip over something and have a nasty fall.”;
otherwise:
say “Whilst blundering about in the darkness (an activity which can only be described as [’]not a good idea[’]), you trip over something and crash to the floor, smashing your head on something very hard on the way. So hard in fact, you are knocked unconscious and fall into a coma… from which, you do not awaken.”;
end the story saying “You have died. Bad Ending(Nasty Fall)” instead.

After going when the room gone from is not naturallylit:
if the room gone from does not enclose a lit thing:
now the room gone from is dark;
otherwise:
now the room gone from is not dark;
continue the action.[/code]

It appears to be working nicely but I’d love to hear further thoughts if anyone can spot problems that might occur with this logic.

Thanks again to everyone who commented so far, it’s been really helpful.

The blindturns counter will only rise when the player is in a dark place with no adjacent lights. Is that intentional? Furthermore, the blind turns will not reset, so if the player returns to a lighted space after 14 turns of stumbling in utter darkness, they’re fine until the next time they get into a similar situation.

Yes. It’s intentional. I thought bumping up the chance of death when you can clearly see a way back to a lighted area would be unfair, and, as it only increases if you actively attempt to move around in a dark area, I thought 15 warnings that it was a bad idea throughout the course of the game would be a fair amount.

The movement rules prevent a person from going into a dark area if there is an adjacent lighted area so in order to get into this situation, the player would need to intentionally extinguish a light source whilst in a location that is not naturallylit. So my idea is that this is fair warning not to engage in such behaviour.

Well, the point of Draconis’s comment was that you should leave the dark/lighted/unlit/lit properties as the things the game uses to handle whether the player can see in a particular room. (Which determines whether you get messages like “It is pitch dark…”) You should leave those alone–don’t try to turn the “dark” property off and on by hand based on a calculation as to whether you think it’s lit up by something, let it stay “dark” (that is, not naturally lit) and let Inform figure out whether it’s got light in it by itself.

The reason you need the other properties is to calculate whether a room is lit up–naturally lighted or containing a light source. So those should just go in your check rules.

So I’d rewrite this like this, using the definitions I gave:

[code]Definition: A room is light-enclosing if it encloses a lit thing.
Definition: A room is light-filled if it is lit or it is light-enclosing.
Definition: A room is truly dark if it is not light-filled.

Rule for printing the description of a dark room: [OK, this one is confusing. The name of the activity is “printing the description of a dark room,” but it’s not actually for any room that has the property “dark”; it’s really a rule for looking in darkness. There isn’t any corresponding activity “printing the description of a lighted room” or anything like that. See Writing with Inform §18.22]
if an adjacent room is light-filled:
repeat with that way running through directions:
if the room that way from the location is light-filled:
say “It is pitch dark, and you can’t see a thing… except for a faint light coming from the [that way].”;
otherwise:
say “It is pitch dark, and you can’t see a thing.” instead. [you don’t actually need the “instead” here, since it’s an activity–running one “for” rule for an activity automatically preempts all other “for” rules for the activity]

Before going from a truly dark room when the room gone to is truly dark:
if an adjacent room is lit:
repeat with that way running through directions:
if the room that way from the location is lit: [we don’t need the “if that way is the noun” check, because we already checked whether the room gone to is truly dark.]
say “It is not wise to continue on in darkness. You can make out a faint light coming from the [that way].” instead;
otherwise:
if the blindturns of the player is less than 15:
now the blindturns of the player is the blindturns of the player plus 1; [there’s also a shorthand phrase for this, “increment the blindturns of the player”]
say “It’s not a good idea to go blundering about in the dark, you could trip over something and have a nasty fall.”;
otherwise:
say “Whilst blundering about in the darkness (an activity which can only be described as [’]not a good idea[’]), you trip over something and crash to the floor, smashing your head on something very hard on the way. So hard in fact, you are knocked unconscious and fall into a coma… from which, you do not awaken.”;
end the story saying “You have died. Bad Ending(Nasty Fall)” instead.

[and note that you don’t need the “After going” rule at all, because you’re not trying to adjust the darkness rules by hand][/code]

This saves you a lot of logic, means you don’t have to adjust darkness by hand, and prevents you from having weird effects elsewhere.

Here it is in a scenario. (By the way, if you paste code directly from the IDE into the forum, it’ll preserve your tab stops–you should be able to paste this directly in and have the tab stops work.)

[code]A room is usually dark.

Cave Mouth is a lighted room. Outer Cave is west of Cave Mouth. Central Cave is west of Outer Cave. Alcove is north of Central Cave. Inner Cave is west of Central Cave.

A lamp is a kind of device. A lamp is usually fixed in place. A lamp is usually switched on. A lamp is usually lit. [these just ensure that the lamps are all switched on and lit at the beginning of the game.] One lamp is in every room.

The flashlight is a lamp. The flashlight is portable. The flashlight is switched off. The flashlight is not lit. The player carries the flashlight. [Otherwise we’d never be able to switch a lamp back on, because we couldn’t see it.]

Carry out switching off a lamp (called lantern): now the lantern is not lit.
Carry out switching on a lamp (called lantern): now the lantern is lit.

The player has a number called blindturns.

Definition: A room is light-enclosing if it encloses a lit thing.
Definition: A room is light-filled if it is lit or it is light-enclosing.
Definition: A room is truly dark if it is not light-filled.

Rule for printing the description of a dark room: [OK, this one is confusing. The name of the activity is “printing the description of a dark room,” but it’s not actually for any room that has the property “dark”; it’s really a rule for looking in darkness. There isn’t any corresponding activity “printing the description of a lighted room” or anything like that. See Writing with Inform §18.22]
if an adjacent room is light-filled:
repeat with that way running through directions:
if the room that way from the location is light-filled:
say “It is pitch dark, and you can’t see a thing… except for a faint light coming from the [that way].”;
otherwise:
say “It is pitch dark, and you can’t see a thing.” instead. [you don’t actually need the “instead” here, since it’s an activity–running one “for” rule for an activity automatically preempts all other “for” rules for the activity]

Before going from a truly dark room when the room gone to is truly dark:
if an adjacent room is light-filled:
repeat with that way running through directions:
if the room that way from the location is lit: [we don’t need the “if that way is the noun” check, because we already checked whether the room gone to is truly dark.]
say “It is not wise to continue on in darkness. You can make out a faint light coming from the [that way].” instead;
otherwise:
if the blindturns of the player is less than 15:
now the blindturns of the player is the blindturns of the player plus 1; [there’s also a shorthand phrase for this, “increment the blindturns of the player”]
say “It’s not a good idea to go blundering about in the dark, you could trip over something and have a nasty fall. (You’ve been doing this for [blindturns of the player] turns.)”;
otherwise:
say “Whilst blundering about in the darkness (an activity which can only be described as [’]not a good idea[’]), you trip over something and crash to the floor, smashing your head on something very hard on the way. So hard in fact, you are knocked unconscious and fall into a coma… from which, you do not awaken.”;
end the story saying “You have died. Bad Ending(Nasty Fall)” instead.[/code]

There are also a few problems in the code. One is that a room is getting set to dark/lit only when the player has visited it, so if there are some rooms that start out dark with a light source they will register as dark when you check them… which will mean that the player won’t be able to go to them when they should, and that they won’t show up as adjacent rooms from which light is coming.
Another is that you have some loops over directions that stop (with “instead”) as soon as they encounter a non-lit room, when they really should be going and gathering all the adjacent non-lit rooms.
Another is that in the “Before going” rule, if the loop hits a direction with an adjacent room, it’ll stop and print a message about that even when the room the player is trying to go to is lit. (The loop over directions starts with north, so when you’re in the central cave you always get messages about the alcove even though you should be able to go to the inner cave if its lamp is on.)
And finally, you have an “After going” rule with a missing “continue the action” in one place, which cuts off the report going rule that prints the description of the new room. You could solve this by adding a “continue the action,” but it’d be better to just make it a Carry out going.

[code]A room is usually dark.

Cave Mouth is a lighted room. Outer Cave is west of Cave Mouth. Central Cave is west of Outer Cave. Alcove is north of Central Cave. Inner Cave is west of Central Cave.

A lamp is a kind of device. A lamp is usually fixed in place. A lamp is usually switched on. A lamp is usually lit. [these just ensure that the lamps are all switched on and lit at the beginning of the game.] One lamp is in every room.

The flashlight is a lamp. The flashlight is portable. The flashlight is switched off. The flashlight is not lit. The player carries the flashlight. [Otherwise we’d never be able to switch a lamp back on, because we couldn’t see it.]

Carry out switching off a lamp (called lantern): now the lantern is not lit.
Carry out switching on a lamp (called lantern): now the lantern is lit.

The player has a number called blindturns.

A room can be naturallylit. A room is usually not naturallylit. Cave Mouth is naturallylit.

Every turn:
if the location is not naturallylit:
if the location does not enclose a lit thing:
now the location is dark;
otherwise:
now the location is not dark.

Rule for printing the description of a dark room:
if an adjacent room is lit:
repeat with that way running through directions:
if the room that way from the location is lit:
say “It is pitch dark, and you can’t see a thing… except for a faint light coming from the [that way].”;
otherwise:
say “It is pitch dark, and you can’t see a thing.” instead. [if room in the first direction you check is not lit, this interrupts the loop before you get to anything else]

Before going when the location is a dark room:
if an adjacent room is lit:
repeat with that way running through directions:
if the room that way from the location is lit:
if that way is the noun:
continue the action;
otherwise:
say “It is not wise to continue on in darkness. You can make out a faint light coming from the [that way].” instead;
otherwise:
if the blindturns of the player is less than 15:
now the blindturns of the player is the blindturns of the player plus 1;
say “It’s not a good idea to go blundering about in the dark, you could trip over something and have a nasty fall.”;
otherwise:
say “Whilst blundering about in the darkness (an activity which can only be described as [’]not a good idea[’]), you trip over something and crash to the floor, smashing your head on something very hard on the way. So hard in fact, you are knocked unconscious and fall into a coma… from which, you do not awaken.”;
end the story saying “You have died. Bad Ending(Nasty Fall)” instead.

After going when the room gone from is not naturallylit: [honestly this should be an “after going”]
if the room gone from does not enclose a lit thing:
now the room gone from is dark;
continue the action; [otherwise this blocks the “report going” rule]
otherwise:
now the room gone from is not dark;
continue the action.

test first with “w/w/switch off lamp/l/showme Alcove”. [since we haven’t been to the alcove, it never got set to being lighted and it doesn’t show up when we look, and interrupts the loop too]
test tour with “w/w/n/s/w/e/switch off lamp/l/showme Alcove/n/switch off lamp/s/n/n/n/n”. [looking messages not great]
test uh-oh with “w/w/n/s/w/e/switch off lamp/l/w”. [the loop in the before going rule hits north and interrupts the going action before you can go west, which is bad][/code]

OK, one more thing. We have some annoying logic involving looping over directions to check if the room that way is light-filled (or lit, depending on the version); which winds up printing a bunch of different messages about where the light is coming from. We can avoid that completely by defining an adjective on directions that checks whether the room that way is light-filled:

Definition: A direction (called that way) is light-going if the room that way from the location is light-filled.

and then wrap that up with a list, like so:

[code]A room is usually dark.

Cave Mouth is a lighted room. Outer Cave is west of Cave Mouth. Central Cave is west of Outer Cave. Alcove is north of Central Cave. Inner Cave is west of Central Cave.

A lamp is a kind of device. A lamp is usually fixed in place. A lamp is usually switched on. A lamp is usually lit. [these just ensure that the lamps are all switched on and lit at the beginning of the game.] One lamp is in every room.

Use the serial comma [dammit].

The flashlight is a lamp. The flashlight is portable. The flashlight is switched off. The flashlight is not lit. The player carries the flashlight. [Otherwise we’d never be able to switch a lamp back on, because we couldn’t see it.]

Carry out switching off a lamp (called lantern): now the lantern is not lit.
Carry out switching on a lamp (called lantern): now the lantern is lit.

The player has a number called blindturns.

Definition: A room is light-enclosing if it encloses a lit thing.
Definition: A room is light-filled if it is lit or it is light-enclosing.
Definition: A room is truly dark if it is not light-filled.
Definition: A direction (called that way) is light-going if the room that way from the location is light-filled.

Rule for printing the description of a dark room: [OK, this one is confusing. The name of the activity is “printing the description of a dark room,” but it’s not actually for any room that has the property “dark”; it’s really a rule for looking in darkness. There isn’t any corresponding activity “printing the description of a lighted room” or anything like that. See Writing with Inform §18.22]
if an adjacent room is light-filled:
say “It is pitch dark, and you can’t see a thing… except for a faint light coming from the [list of light-going directions].”; [this prints “the west, east, and north”; if you want “the west, the east, and the north” you could write [the list of light-filled directions] but I like that less]
otherwise:
say “It is pitch dark, and you can’t see a thing.” instead. [you don’t actually need the “instead” here, since it’s an activity–running one “for” rule for an activity automatically preempts all other “for” rules for the activity]

Before going from a truly dark room when the room gone to is truly dark:
if an adjacent room is light-filled:
say “It is not wise to continue on in darkness. You can make out a faint light coming from the [list of light-going directions].” instead;
otherwise:
if the blindturns of the player is less than 15:
now the blindturns of the player is the blindturns of the player plus 1; [there’s also a shorthand phrase for this, “increment the blindturns of the player”]
say “It’s not a good idea to go blundering about in the dark, you could trip over something and have a nasty fall. (You’ve been doing this for [blindturns of the player] turns.)”;
otherwise:
say “Whilst blundering about in the darkness (an activity which can only be described as [’]not a good idea[’]), you trip over something and crash to the floor, smashing your head on something very hard on the way. So hard in fact, you are knocked unconscious and fall into a coma… from which, you do not awaken.”;
end the story saying “You have died. Bad Ending(Nasty Fall)” instead.[/code]

I hope this is, er, illuminating.

And finally, note that instead of the definitions of light-filled and truly dark, we could use Draconis’s definitions using the I6 routines:

Definition: a room is light-filled rather than darkness-filled if I6 routine "OffersLight" says so (it contains a light source). Definition: a thing is light-filled rather than darkness-filled if I6 routine "OffersLight" says so (it contains a light source).
which would take into account light sources in closed containers and the like.