I7: Question on lists as variables

I have a question about using lists as variables. I’m much more interested in learning the particular reason why something I tried didn’t work than I am in learning some other way to accomplish my goal, since that’s already done.

Some time ago I made door-kind that simulates various doors with electronic locks openable using various keycards, and as I was recently going through my code I noticed these somewhat forgotten keycard/door toys and thought it would be interesting to add a second kind of electronic door that simulates a biometric locking system. My initial thought about how to implement such was that I’d assign each (simulated) lock a list of names of characters authorized to access the lock, and that the (simulated) unlocking action for these doors would simply consist of determining if the current actor’s name was listed therein.

I started by writing the following:

[code]A biodoor is a kind of door. A biodoor is usually closed and openable. A biodoor is usually locked and lockable. The description of a biodoor is usually “A sturdy door with a computerized biometric locking mechanism. A fingerprint-scanning device is set in the middle of the door.”. Understand “electronic door” or “door” or “computerized door” as a biodoor.

A biometric scanner is a kind of thing. Understand “biometric scanner” or “scanner” or “scanning device” or “scanner pad” or “scan pad” or “pad” or “glass” as a biometric scanner. The description of a biometric scanner is usually “A hand-sized piece of dark glass, inset at an angle on top a small metal box, is firmly attached to the middle of the door. To unlock the door, one touches one’s hand to the glass; the device then scans the user’s fingerprints and (assuming the user is authorized to access the door) automatically unlocks the door.”. A biometric scanner has a list of text called the authorizedusers. The authorizedusers of a biometric scanner is usually {“nobody”}.

One biometric scanner is part of every biodoor.

The testarea is a room.

A man called George is in the testarea. The player is George.

The southernarea is a room.

A biodoor called the Security Door is south of the testarea and north of the southernarea. The authorizedusers of the Security Door’s biometric scanner is {“George”}.[/code]
That was all fine, and compiled with no problem. I then added a series of checks to redirect all the various ways a character could interact with such a door or scanner to the the action of the actor trying to touch a biometric scanner when the door incorporating it is closed and locked. That was all fine as well. However, when I tried to write the actual rule that would unlock and open such a door, I couldn’t find any relevant phrasing that would compile. For example, my first try was:

[code]Procedural rule for an actor touching a biometric scanner:
ignore the report touching things rule.

Carry out an actor touching a biometric scanner that is part of a biodoor (called hbdr):
if the actor is listed in the authorizedusers of the noun:
change hbdr to unlocked;
silently try the actor opening hbdr;
if hbdr is open:
if the actor is the player:
say “You touch your hand to the scanner and hear a metallic ‘click’ as [the hbdr] unlocks and opens.”;
otherwise if the player can see the actor:
say “[The actor] touches the scanner, and you hear a metallic ‘click’ as [the hbdr] unlocks and opens.”;
otherwise:
if the actor is the player:
say “You touch your hand to the scanner, but nothing happens. Something must be wrong with either the scanner or [the hbdr].”;
otherwise if the player can see the actor:
say “[The actor] touches the scanner, but nothing happens. Something must be wrong with either the scanner or [the hbdr].”;
otherwise:
if the actor is the player:
say “You touch your hand to the scanner, but nothing happens. You are not authorized to access [the hbdr].”;
otherwise if the player can see the actor:
say “[The actor] touches the scanner, but nothing happens. Apparently [the actor] is not authorized to access [the hbdr].”;
otherwise:
stop the action.[/code]
Which failed to compile with the message:

I tried other various combinations of the first few lines, variations on a theme such as:

Carry out an actor touching a biometric scanner that is part of a biodoor (called hbdr): let curbdl be the authorizedusers of the noun; if the actor is listed in curbdl: change hbdr to unlocked;
that all resulted in similar failed compiler messages. I also tried changing the code for the biometric scanner object by defining the list as:

A biometric scanner has a list of people called the authorizedusers.  The authorizedusers of a biometric scanner is usually {"nobody"}.

resulting in the compiler errors:

which make little sense to me in this context since both “nobody” and “George” are valid terms for referring to people in this particular code.

What I’m wondering is: why exactly didn’t any of these attempts work?

Although the following probably has little to do with my question, for the sake of anyone interested in the outcome of the experiment I eventually did find a very obtuse way to use the list idea. The following code compiles fine and works fine when substituted for the first lines of the Carry Out rule:

Carry out an actor touching a biometric scanner that is part of a biodoor (called hbdr): let curbdl be the authorizedusers of the noun; let checkone be the printed name of the actor; repeat with checktwo running through curbdl: if checktwo matches the text checkone: change hbdr to unlocked;
Since it seems pointless to compose and test against a list if one is going to go to the trouble of changing it to indexed text later, I threw the whole thing out and just set up the doors to work in a somewhat similar way to the keycard doors I already had (which also use indexed text). So in the end I went with the following basic code for the biometric doors:

[code]A biodoor is a kind of door. A biodoor is usually closed and openable. A biodoor is usually locked and lockable. The description of a biodoor is usually “A sturdy door with a computerized biometric locking mechanism. A fingerprint-scanning device is set in the middle of the door.”. Understand “electronic door” or “door” or “computerized door” as a biodoor.

A biometric scanner is a kind of thing. Understand “biometric scanner” or “scanner” or “scanning device” or “scanner pad” or “scan pad” or “pad” or “glass” as a biometric scanner. The description of a biometric scanner is usually “A hand-sized piece of dark glass, inset at an angle on top a small metal box, is firmly attached to the middle of the door. To unlock the door, one touches one’s hand to the glass; the device then scans the user’s fingerprints and (assuming the user is authorized to access the door) automatically unlocks the door.”. A biometric scanner has some indexed text called the authorizedusers. The authorizedusers of a biometric scanner is usually “nobody”.

One biometric scanner is part of every biodoor.

Procedural rule for an actor touching a biometric scanner:
ignore the report touching things rule.

Carry out an actor touching a biometric scanner that is part of a biodoor (called hbdr):
let curper be indexed text;
let curper be the printed name of the actor;
if the authorizedusers of the noun matches the text curper, case insensitively:
change hbdr to unlocked;
silently try the actor opening hbdr;
if hbdr is open:
if the actor is the player:
say “You touch your hand to the scanner and hear a metallic ‘click’ as [the hbdr] unlocks and opens.”;
otherwise if the player can see the actor:
say “[The actor] touches the scanner, and you hear a metallic ‘click’ as [the hbdr] unlocks and opens.”;
otherwise:
if the actor is the player:
say “You touch your hand to the scanner, but nothing happens. Something must be wrong with either the scanner or [the hbdr].”;
otherwise if the player can see the actor:
say “[The actor] touches the scanner, but nothing happens. Something must be wrong with either the scanner or [the hbdr].”;
otherwise:
if the actor is the player:
say “You touch your hand to the scanner, but nothing happens. You are not authorized to access [the hbdr].”;
otherwise if the player can see the actor:
say “[The actor] touches the scanner, but nothing happens. Apparently [the actor] is not authorized to access [the hbdr].”;
otherwise:
stop the action.

The testarea is a room.

The southernarea is a room.

A man called George is in the testarea. The player is George.

A biodoor called the Security Door is south of the testarea and north of the southernarea. The authorizedusers of the Security Door’s biometric scanner is “george”.[/code]

Which works just fine.

In any case, I’m hoping anyone familiar with list functions can comment on why my attempted usage of a list failed in the original cases, and if there is a way to use a list to achieve the sort of functionality I originally envisioned. Thanks in advance for any responses.

I don’t have I7 at hand now to test, but “nobody” and “George” are actually not valid terms for referring to people; they are strings of text. (For example ‘Instead of examining “George”: …’ would not work for the same reason.)

If you remove the quotation marks around George it should work. Also, unless you have a person called nobody in the game, I’m not sure referring to it will work. You can just have an empty list if the object doesn’t have any authorized users. (The authorizedusers of a biometric scanner is usually {}.)

Thanks. You’re right about the quotation marks; they were a significant part of the problem.

Although “nobody” (no quotes) can refer to a lack of actors, for example:

The testarea is a room. A bed is an enterable supporter in the testarea. Every turn: if nobody is on the bed: say "The bed is empty.".
in this case as you said “nobody” (with quotes) was text in the same way that “George” (with quotes) was text rather than a reference to an actor. I think by the time I got to that last bit that actually did give a useful error message (“this ought to be a list of people, not some text”) I was too frustrated to pause and consider the error message carefully. This is also why the whole thing worked when I converted the contents of the lists to indexed text and tried to match them.

Thanks for the response. It would have taken me a while to realize what I was doing wrong there.

You wrote 'if the actor is listed in the authorizedusers of the noun begin' : but the ingredients in this phrase do not fit it, but I am confused enough by this that I can't give a very helpful problem message. Sorry about that.

Is it the colons in your nested ifs? I always have trouble with nested ifs, but maybe I don’t know what I’m talking about. Also, the error message you posted has the word “begin” in it, but the code you posted does not, so I don’t think we’re seeing the exact code that generated that error?

Nope, it’s that the contents of the list don’t match what they’re compared to.

Inform converts internally the “colon-and-indent” syntax into the “begin-end” syntax when it processes the source code, so it’s merely the error message that’s misquoting the code.

As Nitku rightly said, the “begin” thing is a left-over from the time when the only writing style Inform allowed was the “begin if/end if” system; a lot of compiler messages are worded as if this was still the case.

What sorts of trouble? There are a few different ways of writing things supported by Inform 7, so if you’re having trouble with one style you may have other options.

Eh, I always work it out eventually. I can only ever get the “begin” style to work actually, and it seems like overkill for certain small if statements. I guess it would be good if I understood the other style better. I guess I could examine the sample given here actually.

On larger nested if statements, no matter which style I attempt, I always seem to manage to get the punctuation wrong. There are no examples that I know of in the documentation of heavily nested if statements, so I feel like I’m doing a lot of guessing.

@ShaeSays:

I’ve never been able to make any sense of the “begin if/end if” system myself, so I can imagine your frustration if you’re trying to use it at the same time as generally figuring out how to do various semi-complex things in your code. If you want to try the indentation system but find first looking at examples helpful, here is the code for the doors with electronic key locks (briefly mentioned in my original post); it contains a few more statements that consider multiple if-then checks.

The original purpose of this code was to a) generally have some sort of high-tech security doors, and b) have some doors that escape the limitations of the “one matching key per lock” philosophy of Inform’s Standard Rules:

[code]Color is a kind of value. The colors are red, blue, and green.

Sliding it into is an action applying to one carried thing and one visible thing. Understand “slide [something] in [something]” as sliding it into. Understand “slide [something] into [something]” as sliding it into. Understand “swipe [something] in [something]” as sliding it into.

Check an actor sliding something into something:
unless the noun is a card-key:
try the actor inserting the noun into the second noun instead;
unless the second noun is an eldoor or the second noun is a key-card reader:
try the actor inserting the noun into the second noun instead.

Report examining a door (called lathl):
if lathl is open:
say “[The lathl] is currently open.”;
otherwise:
say “[The lathl] is currently closed.”.

An eldoor is a kind of door. An eldoor is usually closed and openable. An eldoor is usually locked and lockable. The description of an eldoor is usually “A sturdy door with an electronic locking mechanism. A key-card reader is set in the middle of the door.”. Understand “electronic door” or “door” as an eldoor.

A key-card reader is a kind of thing. Understand “keycard reader” or “key card reader” or “key-card reader” or “card reader” or “lock” or “card-reader” or “slot” or “card slot” or “keycard slot” or “key-card slot” or “key card slot” or “key slot” or “vertical slot” as a key-card reader. The description of a key-card reader is usually “An electronic locking mechanism is firmly attached to the door. The most prominent feature of the device is a small vertical slot along the edge of one side. To unlock the door, one must slide a valid card-key in the slot.” A key-card reader has some indexed text called the doorcode. The doorcode of a key-card reader is usually “1”.

One key-card reader is part of every eldoor.

A card-key is a kind of thing. Understand “card-key” or “cardkey” or “card key” or “keycard” or “key card” or “card” or “key” as a card-key. The description of a card-key is usually “A credit card-sized key with a magnetic strip along one side, for use in electronic security mechanisms.”. A card-key has some indexed text called the lockcode. The lockcode of a card-key is usually “0”. A card-key has a color. Understand the color property as referring to the card-key.

Check an actor inserting something into a key-card reader:
unless the noun is a card-key:
say “The slot is designed to read card-keys, not [noun]s.” instead;
otherwise:
try the actor sliding the noun into the second noun instead.

Check an actor inserting something into an eldoor:
unless the noun is a card-key:
say “The slot is designed to read card-keys, not [noun]s.” instead;
otherwise:
try the actor sliding the noun into a random key-card reader that is incorporated by the second noun instead.

Check an actor sliding a card-key into an eldoor:
try the actor sliding the noun into a random key-card reader that is part of the second noun instead.

Carry out an actor sliding a card-key into a key-card reader that is part of an eldoor (called hedr):
if hedr is unlocked:
if the actor is the player or the player can see the actor:
say “The door will automatically lock itself the next time it closes.”;
otherwise:
stop the action;
otherwise:
if the actor is the player:
if the lockcode of the noun matches the text doorcode of the second noun:
change hedr to unlocked;
silently try the actor opening hedr;
if hedr is open:
say “You slide the card in the slot, and hear a metallic ‘click’ as the [hedr] unlocks and opens.”;
otherwise:
say “The [hedr] should have opened, but didn’t. Something else must be preventing the door from opening.”;
otherwise:
say “You slide the card in the slot, but nothing happens. Apparently the [noun] doesn’t work with the [hedr].”;
otherwise:
if the player can see the actor:
if the lockcode of the noun matches the text doorcode of the second noun:
change hedr to unlocked;
silently try the actor opening hedr;
if hedr is open:
say “[The actor] slides [if the actor is male]his[otherwise if the actor is female]her[otherwise]its[end if] [noun] into the slot, and you hear a metallic ‘click’ as the [hedr] unlocks and opens.”;
otherwise:
say “[The actor] slides [if the actor is male]his[otherwise if the actor is female]her[otherwise]its[end if] [noun] into the slot, but nothing happens. Apparently something else is preventing the [hedr] from opening.”;
otherwise:
say “[The actor] slides [if the actor is male]his[otherwise if the actor is female]her[otherwise]its[end if] [noun] into the slot, but nothing happens. Apparently [actor]'s [noun] doesn’t work with the [hedr].”;
otherwise:
if the lockcode of the noun matches the text doorcode of the second noun:
change hedr to unlocked;
try the actor opening hedr;
otherwise:
stop the action.

Instead of switching on a key-card reader, say “It doesn’t work that way.”.

Instead of switching off a key-card reader, say “It doesn’t work that way.”.

Instead of an actor closing an eldoor:
change the noun to locked;
continue the action.

Instead of an actor closing a key-card reader that is part of an eldoor (called hedr):
say “(closing [the hedr])”;
try the actor closing hedr.

Instead of an actor locking a locked eldoor with something:
if the actor is the player or the player can see the actor:
say “[The noun] is already locked.”;
otherwise:
stop the action.

Instead of an actor locking an unlocked eldoor with something:
try the actor sliding the second noun into a random key-card reader that is part of the noun.

Instead of an actor unlocking a locked eldoor with something:
try the actor sliding the second noun into a random key-card reader that is part of the noun.

Instead of an actor unlocking an unlocked eldoor with something:
if the actor is the player or the player can see the actor:
say “[The noun] is already unlocked.”;
otherwise:
try the actor opening the noun;
continue the action.

Persuasion rule: persuasion succeeds.

The testarea is a room.

An eldoor called a wooden door is north of the testarea and south of the northern testarea. The doorcode of the wooden door’s key-card reader is “a”.

An eldoor called a steel door is east of the testarea and west of the eastern testarea. The doorcode of the steel door’s key-card reader is “c”.

An eldoor called a glowing door is south of the testarea and north of the southern testarea. The doorcode of the glowing door’s key-card reader is “e”.

An eldoor called the sliding door is west of the testarea and east of the western testarea. The doorcode of the sliding door’s key-card reader is “g”.

Every turn when the sliding door was open:
now the sliding door is closed;
now the sliding door is locked;
if the player can see the sliding door:
say “The sliding doors slam shut with a harsh metallic ‘clang.’”.

Joan is a woman in the testarea.

A security pass is a kind of card-key.

The player carries a pass1. The pass1 is a card-key. The pass1 is green. The printed name of the pass1 is “green security pass”. Understand “security pass” or “pass” or “security card” as the pass1. The lockcode of pass1 is “abcd”.

The player carries a marble. The description of the marble is “A shiny marble with a rainbow swirl of colors.”.

Joan carries a pass2. The pass2 is a card-key. The pass2 is blue. The printed name of the pass2 is “blue security pass”. Understand “security pass” or “pass” or “security card” as the pass2. The lockcode of the pass2 is “abcdefg”.

After examining or searching Joan:
if Joan carries anything:
say “Joan is holding [a list of things carried by Joan].”.

Does the player mean doing something with a security pass that is carried by the player: it is likely.

A container called a locker #1 is in the testarea. The locker #1 is locked and lockable. The locker #1 is closed and openable. The description of the locker #1 is “A steel foot-locker with a large white ‘1’ painted on the top. This is your locker.”. The matching key of the locker #1 is the pass1. Understand “locker 1” or “my locker” as the locker #1.

A container called a locker #2 is in the testarea. The locker #2 is locked and lockable. The locker #2 is closed and openable. The description of the locker #2 is “A steel foot-locker with a large white ‘2’ painted on the top. This is Joan’s locker.”. The matching key of the locker #2 is the pass2. Understand “locker 2” or “joan’s locker” as the locker #2.[/code]
The basic way the code works, then, is that we can create some things called card-keys. These card-keys can function as normal keys if we like, but they can also function in a more complex way by using some indexed text called “lockcode” that may be assigned individually. Furthermore, each “eldoor” has some indexed text called “doorcode”. The way I have things set up above is that each door has one letter (a, b, c, etc) for its doorcode, while each card-key has several letters assigned for its lockcode (abcd, abcdef, etc). Therefore each card-key will open any door whose doorcode letter matches a letter found in the card-key’s lockcode. In the above example, Joan’s key will open all the doors and the locker #2, while the player’s key will only open the wooden door, the steel door, and the locker #1.

The basic things to remember when using the indentation system are to end a condition check with a colon and a statement with a semicolon; also Inform won’t allow you to indent by more than 9 tab-indents on any individual line.

Endosphere,

Awesome, thanks. I’m going to bookmark this page to help me get through those nested if statements next time.

OK Endosphere, here I am having my recurring nested if problem.

Check riding: Instead of riding something that is not the black horse: If the noun is a person: say "That would violate the categorical imperative."; Otherwise: say "Nothing is to be achieved by this.".

To me, this example looks quite a bit like the one you posted above, but it will not compile.

I realize that I have two lines at the beginning that are already using colons, which maybe prohibits me from using those other colons, or something. But this is exactly what I always run into – my problem never exactly matches any documentation I can find, so I end up using the “begin;” style because I can make that work.

This time I decided to try to go ahead and try to learn rather than fall back on the other style. Advice appreciated.

Here’s the error, if that helps.

I already tried removing and re-tabbing the tabs.

The problem is that “Check riding:” specifies a rule in the check riding rulebook, but “Instead of riding…” specifies a rule in the instead rulebook. To fix the problem, just decide on one or the other:

Check riding: If the noun is not the black horse: If the noun is a person: say "That would violate the categorical imperative."; Otherwise: say "Nothing is to be achieved by this.".

Instead of riding something that is not the black horse: If the noun is a person: say "That would violate the categorical imperative."; Otherwise: say "Nothing is to be achieved by this.".

chinkeeyong gave a very good answer.

@ShaeSays
You can have Before, Check, Instead, Carry Out, After, or Report rules, but you can’t mix these phrases inside of a rule. Perhaps some confusion could be caused by by the fact that the word “instead” can be used inside these rules, but not in the way you tried to use it; it’s used to redirect the rule to something else or end the rule after checking against a condition, but “instead” can’t be used as a condition itself inside the other kinds of rules.

Once you decide the rule will be a Check rule or an After rule (for example), you can only have conditions inside it; other types of rules aren’t allowed. So it’s not the “ifs” that you were trying to nest, it was the rule types themselves.

One small thing to note on the example “Check” rule chinkeeyong posted is that since there’s no instead at the end of the conditions to redirect the action, the rule doesn’t effectively check anything, so if you want to try it as an example you’d want to change it to:

Check riding: if the noun is not the black horse: if the noun is a person: say "That would violate the categorical imperative." instead; otherwise: say "Nothing is to be achieved by this." instead; [otherwise: continue the action.]
You don’t need to write the “otherwise: continue the action” part in a check rule, but maybe it would be helpful to imagine it there to see how the check rule works.

Whoops. Sorry about the code error, ShaeSays, and thanks for pointing it out, Endosphere.

OK, makes sense. thanks guys.