two keys for one door

Hi! Is there a way to create a door that can only be opened using two different keys?

What I’d like to do is have an orange door, but it can only be opened with a red key and a yellow key (or a green door that can only be opened with a blue key and a yellow key, etc). If possible, I’d also like to have it so that if the player tries to use only one of the keys, the door only opens halfway, but is still too small an opening to fit through.

Also, now that I think about it, can one key open more than one door (then I could have an orange key that unlocks both a yellow door and a red door)? This one seems like it would be simpler to program, but I’d still like to know how to do both.

The second case (one key opening multiple doors) should be easy (see WWI section “Locks and Keys” or search for “matching key”), but I’m having a little trouble understanding exactly what you’re looking for in the first case. Will you provide an example fake transcript of the kind of interaction you want? Specifically, what kind of command would open the door completely?

For example, after:

X ORANGE DOOR
It has two keyholes. One is red and one is yellow.

… which of the following commands would you want the player to type?

UNLOCK ORANGE DOOR
UNLOCK ORANGE DOOR WITH RED KEY
UNLOCK ORANGE DOOR WITH YELLOW KEY
UNLOCK ORANGE DOOR WITH RED KEY AND YELLOW KEY

Okay, I’ll do my best, haha.

X ORANGE DOOR
It has two keyholes, one red and one yellow

(although this is intended to be an educational game, so the keyholes wouldn’t necessarily be defined by color, as I want the player/student to learn that red and yellow make orange)

UNLOCK ORANGE DOOR WITH RED KEY
You put the red key into one of the keyholes. As you turn it, the door slides up halfway. Unfortunately, it’s still too small for you to fit through.

UNLOCK ORANGE DOOR WITH YELLOW KEY
(Response if the red key is already in the door) You put the yellow key into one of the keyholes and turn it. With the red key already in place, the door proceeds to open fully.
(Response if the red key is not yet in the door) You put the yellow key into one of the keyholes. As you turn it, the door slides up halfway. Unfortunately, it’s still too small for you to fit through.

Or, another scenario:

X ORANGE DOOR
It has two keyholes, one red and one yellow

UNLOCK ORANGE DOOR WITH RED KEY AND YELLOW KEY
You place both the red key and the yellow key into the two keyholes. As you turn them, the door proceeds to open fully.

I hope that makes sense!

OK, you provided two different modes as examples – each has its own set of hassles. The “using two keys at once” approach seemed more interesting and perhaps slightly friendlier to new players, so here’s an example using that.

"Two Keys"

A key is a kind of thing.

The player carries a key called a red key. The player carries a key called a yellow key. The player carries a key called a blue key.

The player carries an edible thing called a watermelon.

Foyer is a room.

A two-lock door is a kind of door. A two-lock door has a list of keys called matching key set.

A closed locked two-lock door called an orange door is east of Foyer. The description of the orange door is "This sliding door has not one but two keyholes." The matching key set of the orange door is {red key, yellow key}.

Prize Room is east of the orange door.

Unlocking it dually with is an action applying to two things. Understand "unlock [something] with [things preferably held]" as unlocking it dually with.

The announce items from multiple object lists rule does nothing when current action is unlocking something dually with.

To slide is a verb.

Suppress further keys is a truth state that varies. Multi-key spacing adjustment made is a truth state that varies.

Before reading a command:
	now suppress further keys is false;
	now multi-key spacing adjustment made is false.

Check unlocking it dually with:
	if the number of entries in the multiple object list is less than two:
		now suppress further keys is true;
		say "It looks like you need to use two keys at once on this door." instead;
	if the number of entries in the multiple object list is greater than two:
		now suppress further keys is true;
		say "That's more keys than there are keyholes." instead.

Check unlocking it dually with:
	repeat with checked item running through multiple object list:
		if checked item is not a key:
			now suppress further keys is true;
			say "[The checked item] can't be used as a key!" instead.

Check unlocking it dually with:
	repeat with alleged key running through multiple object list:
		if alleged key is not listed in the matching key set of the noun:
			now suppress further keys is true;
			say "[The alleged key] doesn't seem to fit into either keyhole." instead.

Check unlocking it dually with when suppress further keys is true:
	unless multi-key spacing adjustment made is true:
		now multi-key spacing adjustment made is true;
		say "[conditional paragraph break]";
	stop the action.

Carry out unlocking it dually with:
	now the noun is unlocked;
	now the noun is open;
	now suppress further keys is true.

Report unlocking it dually with:
	say "The [multiple object list] [slide] smoothly into the keyholes, and a double twist unlocks [the noun]. It swings open."

Check unlocking a two-lock door (called stubborn door) with a key (called attempted key):
	if the attempted key is listed in the matching key set of the stubborn door:
		say "[The attempted key] fits into one of the keyholes and turns easily, but the door only opens halfway, leaving a gap too small for you to wriggle through. As you remove the key, [the stubborn door] closes again." instead;
	otherwise:
		say "You try [the attempted key] on both keyholes, but it doesn't seem to fit either." instead.

Every turn when the player is in Prize Room:
	end the story saying "Well, that was educational."

test me with "open door / unlock door with blue key / unlock door with red key / open door / unlock door with yellow key / open door / unlock orange door with blue key and watermelon / open door / unlock orange door with red key and blue key / open door / unlock orange door with red key and yellow key / open door / e"

There’s probably more work to do handling situations that were not thought out for the example above, but this should get you started. Also, there are some niceties (like names for rules) that are left out, and that you should probably add.

Some of the rules are a little odd-looking because of some fighting that needs to be done with the parser about how to handle a multiple object list. This approach is a bit crude, but it looks OK to the player. Someone smarter than me might be able to show how to rewire handling of actions repeated across a multiple-object list more elegantly. Matt W’s extension “Action on Groups” might also be useful, but I’m not familiar with how it works.

Allowing use of individual keys sequentially would require a totally different approach, potentially involving modeling individual locks. Getting both methods to work in the same game would involve gutting the example above to ensure that the same lock logic is used regardless of the player’s chosen approach.

I would probably have done this a different way. I would make an open unopenable container (the lockplate) as part of every multiple-key door (a new kind). Then, redirect unlocking a multiple-key door with something to inserting something into the lockplate. At this point, check inserting can prevent anything other than the appropriate keys from being inserted, and carry out inserting can unlock the door programmatically when all the appropriate keys are inserted. This approach has the advantage of handing any number of keys (although I think otistdog’s approach could be modified to handle this pretty easily) but the disadvantage of messing with parts of objects, which is always a little weird.

In order to make UNLOCK ORANGE DOOR WITH RED KEY AND YELLOW KEY work I think it would be sufficient just to add a new grammar line ‘Understand “unlock [something] with [things preferably held]” as unlocking it with.’ With that both grammar approaches do the same thing in basically the same way.

Here’s a simple implementation of the sequential keys scenario. It isn’t exactly elegant, but never mind. A door can have any number of keys.

A colour-door is a kind of door. A colour-door is scenery and lockable. A colour-door is usually locked. 
A colour-door has a list of things called the key set. A colour-door has a list of things called the unlocked set. 

[The key set lists all of the keys matching the door. The unlocked set lists the ones which are currently unlocked. So the door should be unlocked when the two sets are the same. ] 

The description of a colour-door is "It stands [if open]open[otherwise if the number of entries in the unlocked set is greater than 0]partly open, but you can't get through yet[otherwise]firmly shut[end if]."

The can't unlock without the correct key rule does nothing when unlocking a colour-door with something.

Check unlocking a colour-door (called the current door) with something (called the current key):
	if the current key is not listed in the key set:
		say "That doesn't seem to help with [the current door]." instead;
	if the current key is listed in the unlocked set:
		say "You've already tried that. It only got you so far." instead.
. 
Carry out unlocking a colour-door (called the current door) with something (called the current key):
	add the current key to the unlocked set;
	if the number of entries in the unlocked set is the number of entries in the key set:
		now the current door is open;	
	rule succeeds.

Report unlocking a colour-door (called the current door) with something (called the current key):
	say "You turn [the current key] in the lock. [run paragraph on]";
	if the noun is open: 
		say "The [current door] slides all the way open.";
	otherwise if the number of entries in the unlocked set is greater than 1:
		say "The door slides open a little further, but you still can't get through.";
	otherwise:
		say "The door slides part of the way open, but not enough for you to go through.";
	stop the action.

[For simplicity a door opens as soon as it is unlocked, and can't be closed/locked again. (But locking is no harder than unlocking to implement if we want it.)]

Check unlocking an open colour-door with something:
        say "It's already open." instead;
Check locking a colour-door with something:
	say "The door won't close." instead.
Check closing an open colour-door:
	say "It won't close." instead.
Check closing a colour-door when the number of entries in the  unlocked set is greater than 0:
	say "It seems to be stuck, part open and part closed." instead.
Check opening a colour-door: 
	say "You need to find a way of unlocking it." instead.
	

The White Room is a room. "There is a green door in the north wall." 
The green door is a colour-door. It is north from the White Room. Through it is the Green Room.

The red key, the yellow key and the blue key are things in the White Room.
The key set of the green door is {yellow key, blue key}.

Even simpler:

Please ignore my goof with the door description.

[code]N-Room is a room.

S-Room is a room.

a white door is a door. “There is a white door to the [best route from the location to white door].” It is south of N-Room and north of S-Room. It is closed. It is locked.

A rusty white key is in N-Room. A gleaming white key is in N-Room.

Check unlocking white door with rusty white key:
now rusty white key unlocks white door.

Check unlocking white door with gleaming white key:
now gleaming white key unlocks white door.

Check locking white door with rusty white key:
now rusty white key unlocks white door.

Check locking white door with gleaming white key:
now gleaming white key unlocks white door.

Last carry out unlocking white door with something:
now nothing unlocks white door.

Last carry out locking white door with something:
now nothing unlocks white door.[/code]

first of all, thanks everyone who is helping me out. there’s apparently a lot more to process (mentally, non computer-ally) than I realized.

hanono, in your last example, I’m a little confused, which is not to say that I’m not thoroughly confused by all the examples everyone has provided and obviously i have a lot more learning to do, haha. At any rate, the reason I’m confused is because in your example, both the rusty key and the gleaming key unlock the door, but the player only needs one or the other and not both at the same time, am I correct?

Is there a way to modify that example (because it’s the one I understood the most of up to this point) so that the door won’t unlock unless both the gleaming and the rusty are used on the door at the same time?

My apologies for not reading closely this morning and completely misinterpreting what you wanted (lack of coffee).

This should do what you want. Only caution - locking the door with either key requires both keys to unlock it again, so you may want to prevent the player from closing the door after it’s open, or from discarding the keys if they need to unlock the door multiple times.

[code]
N-Room is a room.

S-Room is a room.

a white door is a door. “There is a white door here. It appears to have a gleaming keyhole and a rusty keyhole.” It is south of N-Room and north of S-Room. It is closed. It is locked. Understand “keyhole/keyholes” and “gleaming keyhole” and “rusty keyhole” as white door.

A rusty white key is in N-Room. A gleaming white key is in N-Room.

white door can be rwk. white door can be gwk

Check unlocking white door with rusty white key:
now white door is rwk;
if white door is gwk:
now rusty white key unlocks white door;
otherwise:
say “You’ve unlocked the rusty lock. You’ll need another key to unlock the gleaming lock.”;
rule succeeds.

Check unlocking white door with gleaming white key:
now white door is gwk;
if white door is rwk:
now gleaming white key unlocks white door;
otherwise:
say “You’ve unlocked the gleaming lock. You’ll need another key to unlock the rusty lock.”;
rule succeeds.

Check locking white door with rusty white key:
now rusty white key unlocks white door.

Check locking white door with gleaming white key:
now gleaming white key unlocks white door.

Last carry out unlocking white door with something:
now nothing unlocks white door;
now white door is not rwk;
now white door is not gwk.

Last carry out locking white door with something:
now nothing unlocks white door;
now white door is not rwk;
now white door is not gwk.[/code]

I know I’m being a bad coder and shortcutting as some of this should technically be in CARRY OUT rules, but if your game is not complicated it’ll do.

thanks, HanonO. I think I can interpret most of what you’ve shown me here. The others, while I’m sure are just as effective, I had some trouble wrapping my head around.

Your last comment just raises a whole new set of questions for me though, as I’ve always wondered myself how I’m supposed to know whether something belongs in the CHECK, CARRY OUT, or REPORT rules, but I suppose that’s something for a different thread. thanks again.

Here are the relevant parts of the documentation:

http://inform7.com/learn/man/WI_12_2.html
http://inform7.com/learn/man/WI_12_9.html

Also all of chapter 7 goes over actions, here’s the start of it.

http://inform7.com/learn/man/WI_7_1.html

Thanks for everyone for the interesting debate ! It’s, in a more generalized form, a classical puzzle trope. (two or more keys/items for opening a chest/door/safe) whose, IMVHO, it’s a coding case whose deserve to be included in the WI/RB.

Best regards from Italy,
dott. Piergiorgio.

Just a couple of observations about rule books.
It can help using debug commands “actions/actions off” to understand what happens:
if any “instead of” rule applied, action will be “failed” (however in fact it’s a popular way to redefine standard “blocking” rules);
if check or before rule stopped the action, it’s also “failed”;
whatever happens in carry out and report rules, action is “succeeded”.

Carry out is supposed to manipulate the world model but be silent (in case you want to “try it silently” from other actions). Carry out is supposed to always succeed, it’s too late to fail.
Report is supposed just to say things.

(In practice, of course, it’s not possible to follow those practices too strictly).
You can also use “rules/rules all/rules off” to see what rules are executed and in what sequence.

A few examples: examining action prints descriptions in it’s carry out, so you may add more phrases after description in “report examining X for the first time” rule.
If existing action already has check/carry out/report in Standard Rules or extensions, you can quickly (without having to care about rule ordering) add behaviours with “Before” and “After”.
E.g. if you want to increment score when something is done which always succeeds:

Before asking Guru about something for the first time: if Attic is unvisited, increment the score.
But if you want to make sure that action succeeded first, do:

After opening Chest when player does not know the noun: increment the score; now player knows the noun; continue the action. Note “continue the action” as by default, After rule will prevent Report rules and chest opening will not be reported.