Issue removing NPC's clothing when more than one NPC is present in a room

Hi everyone! I’m brand new to Inform 7 and have had some great success getting started with my game. However, I’ve encountered my first major stumbling block and the documentation has not gifted me an answer, so I have to turn to you guys.

My game involves several people that wear identical nondescript clothing items. That is: Joe wears a shirt, Chris wears a shirt, and Bob wears a shirt. Their shirts share the same properties and names. Joe does not wear “Joe’s shirt”; he just wears “shirt”. I want the player to be able to collect and stack the nondescript items for the player’s own use.

I am encountering an issue when trying to remove pieces of clothing from these NPCs. Without fail, using undress <clothing> from <NPC> will only work on the first NPC brought into the scene. Otherwise, it will act as if the clothing isn’t there. I suspect this has to do with the clothing being nondescript and not unique.

Here is a test script demonstrating the problem:

"Garment Test" by Ukai

The Barracks is a room.
The player is in the Barracks.

[Garments]

A garment is a kind of thing. A garment is wearable.
A garment can be head-worn, face-worn, torso-worn, legs-worn, groin-worn, hand-worn, or feet-worn.
A flak jacket is a kind of garment. A flak jacket is torso-worn. Understand "flak jacket", "jacket", and "flak vest" as flak jacket.
The flak pants are a kind of garment. The flak pants are legs-worn. Understand "flak pants", "pants", and "trousers" as flak pants.
A flak helmet is a kind of garment. A flak helmet is head-worn. Understand "flak helmet", "helmet", and "flak hat" as flak helmet.

[People]

Solid Snake is a man in the barracks. "Solid Snake is ready for battle." The description of Solid Snake is "He is really good at hiding in boxes."
Solid Snake is wearing a flak jacket, flak pants, and a flak helmet.

Master Chief is a man in the barracks. "Master Chief is ready for battle." The description of Master Chief is "This guy is tough."
Master Chief is wearing a flak jacket, flak pants, and a flak helmet.

[Undressing]

Undressing is an action applying to two touchable things. Understand "undress [something] from [someone]" as undressing.

Check undressing:
	if the noun is not wearable:
		say "It's not clothing. You can't undress it." instead;
	else if the second noun is not wearing the noun:
		say "[the second noun] isn't wearing that." instead.

Carry out undressing:
	if the noun is wearable:
		say "You undress his [noun].";
		now the noun is nowhere.

And here is the issue in action:

Garment Test
An Interactive Fiction by Ukai
Release 1 / Serial number 230430 / Inform 7 v10.1.2 / D

Barracks
Solid Snake is ready for battle.

Master Chief is ready for battle.

>showme
Barracks - room
    yourself - person
    Solid Snake - man
        flak jacket (worn) - flak jacket
        flak pants (worn) - flak pants
        flak helmet (worn) - flak helmet
    Master Chief - man
        flak jacket (worn) - flak jacket
        flak pants (worn) - flak pants
        flak helmet (worn) - flak helmet

>actions
Actions listing on.

>undress flak pants from chief
[undressing the flak pants]
Master Chief isn't wearing that.
[undressing the flak pants - failed the Check undressing]

>undress flak pants from snake
[undressing the flak pants]
You undress his flak pants.
[undressing the flak pants - succeeded]

>

As you can see, we cannot remove the flak pants from Master Chief because he is not the first actor in the scene. Solid Snake is, and thus we have no issues removing his pants.

Any suggestions are appreciated!

My belief is that inform doesn’t know which flak jacket you want to remove, so it picks the one worn by the first player. It then processes the second part of the line, i.e. the person, and says, ‘Wait a second, he’s not wearing that!’

You could get around it by making specific instance of clothing instead of generic kinds. Like ‘flak pants are a kind of thing. The stained paints are flak pants worn by master chief’.

Alternatively, you can use ‘does the player mean’. I got it to work with these modifications:

Undressing it from is an action applying to two touchable things. Understand "undress [something] from [someone]" as undressing it from.

Does the player mean undressing a garment from someone:
	if the noun is worn by the second noun:
		it is likely;
	otherwise:
		it is unlikely;

(I renamed it to ‘undressing it from’ to make it easier to write rules about)

3 Likes

Thank you Brian! This certainly makes it function as intended. I can remove the same item from both of them in any order and have it show up in my inventory. Very neat.

Still, there is one minor issue:

Barracks
Solid Snake is ready for battle.

Master Chief is ready for battle.

>undress flak pants from chief
You undress his flak pants.

>undress flak pants from snake
You undress his flak pants.

>i
You are carrying:
  two pairs of flak pants

>undress helmet
(from Solid Snake)
You undress his flak helmet.

>undress helmet
Whom do you want to undress the flak helmet from?

>chief
[undressing the flak helmet from Master Chief]
Master Chief isn't wearing flak helmet.
[undressing the flak helmet from Master Chief - failed the Check undressing]

>showme
Barracks - room
    yourself - person
        flak helmet - flak helmet
        flak pants - flak pants
        flak pants - flak pants
    Solid Snake - man
        flak jacket (worn) - flak jacket
    Master Chief - man
        flak jacket (worn) - flak jacket
        flak helmet (worn) - flak helmet

>

When undressing in two commands it seems to not quite understand which garment it is referring to, falsely suggesting that Master Chief isn’t wearing a flak helmet. This is fine, since I can figure out a way to forbid the player from using undress in two commands (requiring the full undress x from y syntax instead). More precisely, I will find a way to forbid the player from using undress in two commands when there are two or more NPCs in a room.

In any event, works well enough for me. Thanks!

1 Like

I think what’s happening…

undress helmet
(from Solid Snake)
You undress his flak helmet.

The parser has interacted with Snake and his particular similarly-named helmet.

undress helmet
Whom do you want to undress the flak helmet from?

The parser infers you mean Snake’s similarly named helmet that the player last interacted with and is currently holding.

chief
[undressing the flak helmet from Master Chief]
Master Chief isn’t wearing flak helmet.
[undressing the flak helmet from Master Chief - failed the Check undressing]

The parser here I believe is i trying to undress the helmet (that the player is holding that was just taken from Snake) from Master Chief. This of course fails because the helmet the parser infers isn’t being worn. This is difficult to figure out since you have multiple un-specified instances of a kind.

I think you can fix this by naming specific kinds.

Snake's flak helmet is a flak helmet. It is worn by Snake.

Or…you can actually take advantage of an AIF trick: if you make a kind, and then say that one of the kind is “part of” every person (basically attaching it to them) Inform automatically will name the kind as belonging to the person. Then you can remove it from the person and it remains named.

One flak helmet is part of every man. 
When play begins:
	repeat with hat running through flak helmets:
		if hat is part of a person (called wearer):
			now wearer wears hat.

showme chief
Master Chief - man
Master Chief’s flak helmet (worn) - flak helmet

showme snake
Solid Snake - man
Solid Snake’s flak helmet (worn) - flak helmet

Now the parser can infer a bit better, or it’s at least clear:

undress helmet
Which do you mean, Solid Snake’s flak helmet or Master Chief’s flak helmet?

master
Whom do you want to undress Master Chief’s flak helmet from?

master
(Master Chief)
You undress his Master Chief’s flak helmet.

undress
What do you want to undress?

helmet
Whom do you want to undress Solid Snake’s flak helmet from?

This is very handy because it also allows the player to refer to kinds by their automatic name.

undress snake’s flak helmet
You undress his Solid Snake’s flak helmet.

Quick fix:

Carry out undressing:
	if the noun is worn by a person (called wearer):
		say "You undress [noun] from [wearer].";
		now the noun is nowhere.

undress snake’s helmet
You undress Solid Snake’s flak helmet from Solid Snake.

3 Likes

Assemblies can be about other relations than incorporation.

A helmet is a kind of thing.
Every person wears a helmet (called its helmet).

Bob is a person in the lab.
Alice is a person in the lab.

and Alice will be wearing Alice’s helmet and Bob will be wearing Bob’s helmet. But the parser won’t automatically recognize “Alice’s”, so…

Understand "[something related by reversed wearing]'s helmet" as a helmet.

After reading a command:
let x be "[the player's command]";
replace the text "'s" in x with " [']s";
change the text of the player’s command to x.
5 Likes

Zed of course is doing it the smart way… But I like incorporation to get everything named as the person it belongs to and then just rip everything off the bodies when play begins! That way you’ve already got everything named and it works for the player.

undress snake’s helmet
You undress Solid Snake’s flak helmet from Solid Snake.

3 Likes

Actually, this works to make things named, e.g., Alice’s helmet, Bob’s helmet, in a way that’s automatically recognized by the parser with no extra work!

one helmet (called its helmet) is worn by every person.
1 Like

Zed of course is a genius with I7 and I’m just a dude to makes games about body parts and sticks in the rut of what I know works ! :joy: But it’s very cool to know these tricks.

3 Likes

If you don’t want to differentiate between garments at all you can try this (slightly modified form of mathbrush’s code) I think:

Undressing it from is an action applying to two touchable things. Understand "undress [something worn by someone] from [someone]" as undressing it from.

Does the player mean undressing a garment from someone:
	if the noun is worn by the second noun:
		it is likely;
	otherwise:
		it is unlikely;
1 Like

You just taught me something, too: WI 4.16 says Inform always defaults to (called its <name of kind of value>) in the absence of an explicit (called [...]), but apparently that doesn’t work for containment, supporting, carrying, wearing.

1 Like

I got it working exactly as I wanted using part of Zed’s solution, mathbrush/Timur’s, and a little bit of duct tape.

Understand "[something related by reversed wearing]'s flak helmet" as a flak helmet.
Understand "[something related by reversed wearing]'s flak jacket" as a flak jacket.
Understand "[something related by reversed wearing]'s flak pants" as a flak pants.


After reading a command:
     let x be "[the player's command]";
     replace the text "'s" in x with " [']s";
     change the text of the player’s command to x.

Undressing it from is an action applying to two touchable things. Understand "undress [something worn by someone] from [someone]" as undressing it from.

Does the player mean undressing a garment from someone:
	if the noun is worn by the second noun:
		it is likely;
	otherwise:
		it is unlikely;

This works almost perfectly but produces a quirk. If you type undress without any further parameters, you will be stuck in a loop of “What do you want to undress?” Therefore, I’ve done something very sloppy:

UndressNull is an action applying to nothing. Understand "undressnull" as UndressNull.
After reading a command:
	if the player's command matches "undress":
		replace the player's command with "undressnull".
		
Carry out UndressNull:
	say "You need to specify something to undress. Try [italic type]undress <clothing> from <person>[roman type]."

Seems watertight in my testing. Thank you everyone

2 Likes

Happy that you have what you want. But really, credit should go to mathbrush, I have just added a small modification to his code.

It was a good instinct to reach for another action, but you can reuse the same command verb with a different number of parameters or different kinds of parameters or different prepositions to mean different actions.

There’s a lot of this is in the Standard Rules, e.g.,

Understand "get in/on" as entering.
Understand "get out/off/down/up" as exiting.
Understand "get [things]" as taking.
Understand "get in/into/on/onto [something]" as entering.
Understand "get off/down [something]" as getting off.
Understand "get [things inside] from [something]" as removing it from.

So your UndressNull could be just:

null-undressing is an action applying to nothing.
Understand "undress" as null-undressing.
Before null-undressing, instead say "You need to specify something to undress. Try [italic type]undress <clothing> from <person>[roman type]."
1 Like

I can never remember (and don’t have the IDE in front of me) - can you just use understand as a mistake in this situation, or would that mess with the real action? Like:

Understand “undress” as a mistake (“ You need to specify something to undress. Try [italic type]undress from [roman type].")

2 Likes

yes, that works fine! Even better!

1 Like