Implementing a keyring

In my games I have a keyring of four keys–there are four things that these keys unlock, however it’s actually the keyring that’s ‘the matching key’, because at the time I started working with Inform(May last year), I was not yet versed in some of the intricacies of the language. So instead of having four separate keys on a keyring, I made them all one ‘matching key’–the keyring itself, and used Understand statements equating “house/mailbox/car/utility key” to the keyring. It works, but the player may be a little cockeyed when he finds out he can unlock the mailbox with the ‘house key’, etc. or the keyring itself. So although I describe the keyring as having four different keys on it, you can type in the name of any key to unlock one of the items, but you cannot remove any of the keys from the ring, or add any. Now that I am doing a super-overhaul edit of my games, I need a ‘real’ keyring.
I toyed with the idea of making each key a ‘part of’ the keyring, but issues over having to ‘take’ a key first obviously arise. So my choice was to make the keyring a portable supporter, and putting the keys on the ring. I would then have the player ‘try silently’ taking each key(and I have put the keys into a kind, such as mykeys) before use. I would put this all under a Before rule, which stops the action in the case that the wrong key is typed. An After rule is then invoked in case of success, where I say ‘You unlock the door(etc)’, and then have the player ‘try silently’ putting the key back onto the ring. This all works perfectly. Except when I try to write some rules about taking a key from the ring. Now, if the player has the key off of the ring, and uses it, it works fine, he only puts the key back on the ring(silently) if the key was previously on the ring(if the mykey was on the keyring:…). However, when I write a rule about taking the key off of the ring, such as–

After taking a mykey: if the noun was on the keyring: say "You slide the key through the metal spiral, until it pops off into your hand."; otherwise: say "Taken."
—this rule will be invoked if I use a key on the ring to unlock something, even if it was not my intention for the player to take the key off of the ring. It will say –

UNLOCK SHOEBOX HOUSE WITH HOUSE KEY
You select the house key on the keyring.

You slide the key through the metal spiral, until it pops off into your hand.

You unlock the shoebox house.

Now because I have the player ‘try silently’ putting the key back on the ring, if it was previously on the ring, the key goes back onto the ring, so I don’t want the middle statement to print.
Any ideas?

Here is more of my code(not from the actual game, but from my incubator game)–

A keyring is here. It is a portable supporter. "Laying on the ground, in its usual place, is your keyring." The description is "These are your keys--your house key, your car key and your whatsit key. All fatefully attached on the same ring, because I cannot seem to describe it any other way." A mykey is a kind of thing. The house key, the car key and the whatsit key are mykeys. Before unlocking something with a mykey:[just the unlocking--the locking is similar] if the second noun is on the keyring: if the keyring is carried by the player: say "You select [the second noun] from the keyring."; if the noun is: -- the shoebox house: if the second noun is not the house key: say "But I'm afraid that that's the wrong key."; stop the action; otherwise: try silently taking the house key; -- the matchbox car: if the second noun is not the car key: say "But I'm afraid that that's not the right key."; stop the action; otherwise: try silently taking the car key; -- the whatisit: if the second noun is not the whatsit key: say "But I'm afraid that that's the wrong key."; stop the action; otherwise: try silently taking the whatsit key; -- otherwise: say "That cannot be unlocked with that key."; stop the action; otherwise: say "Where are your keys...??"; stop the action. After unlocking something with a mykey: say "You unlock [the noun] with [the second noun]."; if the mykey was on the keyring: try silently putting the second noun on the keyring.

The keys and what they unlock–

A house key is on the keyring. The description is "This is the key to your house." A car key is on the keyring. The description is "This is the key to your car." A whatsit key is on the keyring. The description is "This is the key to your whatisit." A shoebox house is here. It is scenery and a container. It is closed and locked. It is enterable. It has matching key the house key. The description is "It's your pathetic little house, about the size of a shoebox." A matchbox car is here. It is scenery and a container. It is closed and locked. It has matching key the car key. The description is "Your car. Smaller than the house. You can't even get into it." A whatisit is here. It is scenery and a container. It is closed and locked. It has matching key the whatsit key. The description is "Your whatisit. What is it?"

I know of the Locksmith extension, and that it features a keyring, but I prefer to be able to write code on my own, albeit with a little assistance.

Okay–I think I just solved my problem–
Instead of having the player ‘try silently’ taking the key, I could just simply say ‘now the house key(etc) is carried by the player;’
Duh.

Here is my entire code for the keyring–any comments??

[code]A keyring is here. It is a portable supporter. “Laying on the ground, in its usual place, is your keyring.” The description is “This is the ring for your keys–your house key, your car key and your whatsit key. All fatefully attached by the same ring, even if not actually present on it.”
A mykey is a kind of thing. The house key, the car key and the whatsit key are mykeys. A mykey can be ringed or unringed.
Unlocking something with a mykey is being handy. Locking something with a mykey is being handy.
Before being handy:
if the second noun is on the keyring:
if the keyring is carried by the player:
say “You select [the second noun] from the keyring.”;
if the noun is:
– the shoebox house:
if the second noun is not the house key:
say “But I’m afraid that that’s the wrong key.”;
stop the action;
otherwise:
now the house key is carried by the player;
– the matchbox car:
if the second noun is not the car key:
say “But I’m afraid that that’s not the right key.”;
stop the action;
otherwise:
now the car key is carried by the player;
– the whatisit:
if the second noun is not the whatsit key:
say “But I’m afraid that that’s the wrong key.”;
stop the action;
otherwise:
now the whatsit key is carried by the player;
– otherwise:
say “That key does not fit [the noun].”;
stop the action;
otherwise:
say “Where are your keys…??”;
stop the action.
After being handy:
say “You [if the action name part of the current action is unlocking it with action]unlock [otherwise]lock [end if][the noun] with [the second noun].”;
if the second noun is ringed:
now the second noun is on the keyring.

Instead of taking a mykey:
if the noun is on the keyring:
if the keyring is carried by the player:
say “You slide the [noun] through the metal spiral until it pops off into your hand.”;
now the noun is carried by the player;
now the noun is unringed;
otherwise:
try taking the keyring;
otherwise:
say “Taken.”;
now the noun is carried by the player.
After taking the keyring:
if there is something on the keyring:
say “The keyring jingles as you snatch it up.”;
otherwise:
say “You take the keyring in the palm of your hand.”
After putting a mykey on the keyring:
say “You slide the key back through the metal spiral until it snaps on.”;
now the noun is ringed.[/code]

Okay a problem arises if I have already locked something and try to lock it again–the key comes off the ring and stays off–so I added more clauses under the Before rule(before the clauses about nouns to be locked/unlocked)–
if the action name part of the current action is unlocking it with action:
if the noun is unlocked:
say “[The noun] is already unlocked.”;
stop the action;
otherwise:
if the noun is locked:
say “[The noun] is thoroughly locked.”;
stop the action;

One problem that I see may arise with this code is that the player may try to do something other than locking or unlocking with the keys. If I use something like ‘Before doing anything other than locking or unlocking with a mykey…’ does it matter that the key would actually be an indirect object to the verb??

For that, I think “Before doing anything other than locking or unlocking when the second noun is a mykey” should work. (I checked a little to make sure that “when the second noun is a mykey” doesn’t get subsumed under the “other than,” but it doesn’t.)

However–I will say that this is a place when it is a good idea to look at Locksmith and see if you can adapt its code, which is a good source of assistance for writing your own! The problems with taking the keys arise from the carrying requirements–since unlocking is defined as applying to a thing and a carried thing, Inform wants to take the second noun before doing anything. In order to do an end run around this, we can modify the carrying requirements rule. Here’s what Locksmith does:

[code]The keychain-aware carrying requirements rule is listed instead
of the carrying requirements rule in the action-processing rules.

This is the keychain-aware carrying requirements rule:
if locking or unlocking something with something which is on a keychain which is carried by the actor:
continue the action;
abide by the carrying requirements rule.[/code]

Effectively it puts in a new rule which firsts check whether we’re unlocking or locking with a key on a keychain we’re carrying–if so, it just lets us act; if not, it goes through the normal rules. This might give you a good source for adapting to the case where the keys are part of the keyring, without having to write a lot of code for sliding the keys on and off it.

How can I get in to see the full code of Locksmith?
Thanks for the tips!

At least on the Mac, File -> Open Installed Extension -> Emily Short -> Locksmith. (That is, pull down the File menu and hover over “Open Installed Extension”; the other two menus will pop up on the right.) Should work pretty similar on other operating systems. Locksmith is built in, so you should be able to do this without having to install the extension.

Thanks.