Swapping clothes

Hi guys, I have a bit of a problem. I want to make my clothing system really simple, but I have a hitch. I can get Inform7 to tell if the player is wearing a suit, but I can’t stop them from wearing fifty suits! :stuck_out_tongue:

What I want to do is basically have root types of wearable objects, like hats, and then test if the player is already wearing an object of the same type. If they are, I want the game to just swap the objects over, dropping the discarded object in the inventory. Can I do this? Here’s a rough example of what I’m trying to do:

Instead of wearing a (object of the same type): if the player is wearing a (object of the same type): move the (object of the same type) to the player; Try wearing the noun; otherwise: Try wearing the noun.

Your example code is going to trigger an infinite loop, since “try wearing the noun” will trigger the rule itself. That can be fixed, though!

Here’s what I came up with:

[code]“Two Shirts”

Example Location is a room.

A clothing is a kind of thing. A clothing is usually wearable.

A shirt is a kind of clothing.

The aloha shirt is a shirt. The player carries the aloha shirt.

The Pink Floyd shirt is a shirt. The player carries the Pink Floyd shirt.

Before wearing a shirt:
if the player is wearing a shirt:
let N be a random shirt worn by the player;
say “First you take off [N].”;
move N to the player.

The description of the player is “Currently wearing: [a list of things worn by the player].”[/code]

Using a “Before” rule lets us get all pre-wearing business out of the way and then allow the normal wearing mechanics to happen.

The problem with this version is that you need a “Before wearing a [clothing type]” rule for every single clothing type. Not very elegant! I think that to make a single rule work, you’d need to treat an article of clothing’s type as a property of the object instead of its kind. Or maybe not. It’d be a little more difficult, whatever the solution is.

I think this will be much easier if, instead of making different types of wearable objects, you make body parts a kind of value and give every piece of clothing a body part that it covers. Then you can check very easily whether the player is already wearing something that covers that body part.

So something like this (untested):

Body part is a kind of value. The body parts are head, torso, legs, feet, and hands. A vestment is a kind of thing. A vestment is always wearable. [didn't use "clothing" because "a clothing" sounds funny.] A vestment has a body part called its covering. Collision relates a vestment (called X) to a vestment (called Y) when the covering of X is the covering of Y. The verb to collide with means the collision relation. Check wearing something when the player is wearing something that collides with the noun: say "You're already wearing something on your [covering of the noun]." instead. A hat is a kind of vestment. The covering of a hat is always head. A shirt is a kind of vestment. The covering of a shirt is always torso.

…and so on. If you want some more complicated stuff (e.g., pants over underpants, dresses covering torso and legs) you can look at the example “What Not To Wear” in the documentation, and more discussion here and here. And if you really want to get the type of an object we were coincidentally just discussing that and you could use loxlie’s brief I6 solution.

(Whoops, this doesn’t have the auto-remove functionality you want. Well, you can just get the vestment that’s colliding with the noun, print “(first taking off the doohickey),” try taking it off, and stop the action if the player still wears it–this is a bit more robust than just moving it to the player in case there’s something the player isn’t supposed to be able to take off like the cursed headband, or a message you want to print when they take something off, or something like that.)

To make it entirely modular, you could use Brady Garvin’s Object Kinds extension. That would let you compare the kinds to each other directly, like so:

[code]Include Object Kinds by Brady Garvin.

To decide whether (actor - a person) is already wearing something similar to (duds - a garment):
if the stuff worn by the actor that’s similar to the duds is nothing, decide no;
yes.

To decide which object is stuff worn by (actor - a person) that’s similar to (duds - a garment):
repeat with item running through things worn by the actor:
if the object kind of the duds is the object kind of the item and the duds is not the item, decide on the item;
decide on nothing.

Instead of wearing a garment (called duds) when the player is already wearing something similar to the duds:
say “You’re already wearing [the stuff worn by the player that’s similar to the duds].”

A garment is a kind of thing. A garment is wearable.

A shirt is a kind of a garment.
Some shoes is a kind of garment.

The red blouse is a shirt.
The purple t-shirt is a shirt.
The black shoes are shoes.
All garments are in Home.

Home is a room.

Test me with “wear red/wear purple/wear shoes/wear red”.[/code]

Wow, thanks guys, I’ll try those and see which I like best! :smiley:

[code]A hat is a kind of thing. A hat is wearable. A fedora is a hat. A cap is a hat. A bonnet is a hat.

The Locker is a room. The cap and the bonnet are in the Locker.

The player wears a fedora.

Instead of wearing a hat (called the desired) when the player is wearing a hat (called the oldwig):
try taking off the oldwig;
try wearing the desired.

Before taking off the fedora, say “You perform the fedora tip.”[/code]

Be careful with this: if the action of taking off the old hat fails for some reason, it will go into an infinite loop.

Hey guys, thanks for that, it’s really working well. By the way, at the moment I have a bunch of clothes with randomly assigned descriptions based on variables (e.g. hat style) and I have come up against a bit of an in game problem. If my character picks up a hat with the ‘red’ and ‘bowler’ variables it will be described in game as a red bowler hat, but if they type ‘take red hat’ or ‘take bowler’ or anything like that, the game gets confused, even though the script says “Understand the hat style property as describing a hat.” So even though the printed name of the hat is “red bowler hat” it only picks it up if you say “hat”.

Can anyone tell me what might be going wrong? I really don’t understand this as I have found that line of script several times in the manual.

Can you post some code–preferably the smallest possible excerpt of code that demonstrates the problem? From what you’ve said it sounds like it should work.

Ok, thanks, here you go.

[code]Testroom is a room.

hat is a kind of thing. They are wearable.

A hat style is a kind of value. The hat styles are red bowler, blue bowler, green bowler. A hat has a hat style. Before printing the name of a hat, say "[hat style] ". Understand the hat style property as describing a hat.

there is a hat in the Testroom.[/code]

You should see it if you say “take red”, “take red hat” or any other combination that includes “red” or “bowler”. Unfortunately I can’t even correct it by hard scripting it with “understand bowler as hat” because I have about five kinds of hat in a dozen colours. :stuck_out_tongue:

Change “describing” to “referring to” if you want the player to be able to use the property as a noun as well as an adjective.

EDIT: Sorry, this is incorrect; see below.

When you have a multi-word property name, the player has to use the entire name in order to be understood. So your game will understand “take red bowler” but not “take red hat” or “take bowler hat,” because in those latter cases the player hasn’t used the entire name of the hat’s hat style property. This is in contrast with multi-word object names, where by default Inform will understand every individual word (so if the object were called “red bowler hat” you’d be OK).

If your hat styles all consist of a color and a kind of hat, then your easiest solution might just be to make color a separate property from hat style–then if you have a separate “Understand the color property as describing a hat” and “Understand the style property as describing a hat” it should work. Alternatively this:

Understand "red" or "bowler" as red bowler.

would work, except that you’d need a similar line for every multi-word name for a hat style.

(Draconis, I’m pretty sure that it’s the other way around–if you use “describing” you can use the property as either a noun or an adjective, if you use “referring” you can only use it as an adjective. I think. Definitely “referring” is the more restrictive one and the one I never use, but Inform crashed when I went to double-check it so I’m not positive.)

Unfortunately neither of those work! :confused: I guess it makes sense that if it doesn’t understand the style of hat as the hat in game it wouldn’t in the script either. I think I’m just going to have to create all the possible variables as items in separate rooms, which I don’t really want to do as the whole game is already set up using the variable method. I think I may submit a bug report as “Understand the hat style property as describing a hat.” should have worked.

It really should work. What problem are you encountering exactly, with what code?

This works for implementing the color and style separately:

Testroom is a room. A hat is a kind of thing. A hat is wearable. Color is a kind of value. The colors are red, green, and blue. A hat has a color. Understand the color property as describing a hat. Style is a kind of value. The styles are bowler, derby, and fedora. A hat has a style. Understand the style property as describing a hat. Before printing the name of a hat: say "[color of the item described] [style of the item described] ". The description of a hat is usually "It's a [style of the item described] that is [color of the item described]." One blue bowler hat is in Testroom. One red derby hat is in Testroom.

And this one works by explicitly giving an understand statement for each word in the the multi-word value names:

[code]Testroom is a room.

hat is a kind of thing. They are wearable.

A hat style is a kind of value. The hat styles are ten gallon, dixie cup, and Anthony Eden. A hat has a hat style. Before printing the name of a hat, say "[hat style] ". Understand the hat style property as describing a hat.

Understand “ten” and “gallon” and “ten-gallon” as ten gallon. Understand “dixie” and “cup” as dixie cup.

One ten gallon hat, one dixie cup hat, and one Anthony Eden hat are in the Testroom.

test me with “x gallon hat/x ten hat/x dixie hat/x cup hat/x anthony eden hat/x eden hat”.[/code]

Note in the last one that “Eden hat” doesn’t work because I didn’t include a like to have “Eden” understood as “Anthony Eden,” so the player has to type “Anthony Eden” out in full.

What problem are you having?

…one problem you might be encountering is that you have to say “One red bowler hat is in Testroom” instead of “A red bowler hat is in Testroom.” If you start a sentence with “A red bowler hat” and “hat” is the name of a kind, then Inform sometimes thinks you’re trying to generalize about all hats (as we do when we say “A hat has a color”). So it doesn’t like it if you’re saying “A hat is in Testroom” or something.

Oh, 0k. Thanks, that works now!

By the way, I have been trying for ages to find a way to abbreviate descriptions of variables that are the same across all of a set. So, for example, if the player wears a red hat, pants, and tailcoat, I want the description to read: “You are wearing a red suit and hat.” But, if the player is wearing green tie I want the description to read: “You are wearing a red suit and hat with a green tie.” Instead of “You are wearing a red hat, red pants, a red tailcoat and a green tie.” which is what it does now.

Is there any way to do this? This is the main reason I wanted to use values instead of separate objects, but I’m stuck.

There’s no automatic way to do it, I’m afraid. You’ll have to write a description routine with a lot of if statements.

Here’s something I put together. I haven’t totally stress-tested it but the cases I’ve tried have worked. (Note that I didn’t try to prevent the player from wearing more than one hat.)

[code]Use American dialect and the serial comma.

Testroom is a room.
Clothing is a kind of thing. Clothing is wearable.
Color is a kind of value. The colors are red, green, and blue. Clothing has a color. Understand the color property as describing clothing.
A hat is a kind of clothing.
Hat style is a kind of value. The hat styles are bowler, derby, and fedora. A hat has a hat style. Understand the hat style property as describing a hat.
Colors already printed is initially false. [A truth state flag. If I don’t put this in, it’ll say things like “You’re wearing a green green homurg hat and green tie” and that’s no good.]
Before printing the name of a hat when colors already printed is false: say "[color of the item described] [hat style of the item described] ".
The description of a hat is usually “It’s a [hat style of the item described] that is [color of the item described].”
Before printing the name of clothing when the item described is not a hat and colors already printed is false: say "[color of the item described] ".

A coat is a kind of clothing.
A tie is a kind of clothing.
A cravat is a kind of clothing.
A skirt is a kind of clothing.
pants are a kind of clothing. Pants are plural-named. The indefinite article of pants is usually “some”.
socks are a kind of clothing. Socks are plural-named. The indefinite article of socks is usually “some”.
A shirt is a kind of clothing.

Coloration relates a thing (called X) to a color (called Y) when the color of X is Y. The verb to be colored means the coloration relation.
Cocoloration relates a clothing (called X) to a clothing (called Y) when the color of X is the color of Y and X is not Y. The verb to be the same color as means the cocoloration relation.

The description of the player is “You’re wearing [color-sorted list of clothes of the player].”

To say color-sorted list of clothes of (subject - a person):
[let’s make a list of lists of cocolored clothing worn by the player]
let master clothes list be a list of lists of clothing;
let miscellaneous clothes list be a list of clothing;
repeat with hue running through colors:
let shade list be the list of (clothing worn by the player) that is colored hue;
if the number of entries in shade list is 1:
add shade list to miscellaneous clothes list;
otherwise if shade list is not empty:
add shade list to master clothes list; [this is tricky–adding shade list to misc. clothes list adds its entry to it, while adding it to master clothes list adds the list itself as a new entry–because adding a list to a list is different from adding it to a list of lists]
if master clothes list is empty:
if miscellaneous clothes list is empty:
say “nothing”;
otherwise:
say “[miscellaneous clothes list with indefinite articles]”;
otherwise:
now colors already printed is true;
let N be the number of entries in master clothes list;
repeat with counter running from 1 to N:
let shade list be entry counter of master clothes list;
sort shade list in indefinite article order; [this should put “a” and things that don’t have indefinite articles–which are also “a”–to the front, I hope]
say "[if the indefinite article of entry 1 of shade list is not empty][indefinite article of entry 1 of shade list][otherwise]a[end if] [color of entry 1 of shade list] ";
say shade list;
if counter is 1 and (N is greater than 1 or miscellaneous clothes list is not empty):
say ", with "; [this is why we keep track of counter instead of just repeating through master clothes list]
otherwise if counter is less than N or miscellaneous clothes list is not empty:
say " and ";
now colors already printed is false;
say “[miscellaneous clothes list with indefinite articles]”.

One red coat, one blue tie, one red cravat, one blue skirt, one green pants, one green socks, one green shirt, and one blue bowler hat are in testroom.[/code]

Some things to note:
The handling of pants is not super elegant. I figured that it was OK to say “a green shirt, socks, and pants” and “some green socks and pants” but not so much “some green socks, shirt, and pants.” So I sort the shade list in order of the indefinite article to force the stuff whose indefinite article is “a” to the front–except somehow those things have an indefinite article of “” instead of “a,” so I had to include a special check for that. This may not be super robust if you have indefinite articles other than “some” and “”.
If any of your color names start with vowels then the indefinite articling will get hairy (since you’ll need “an orange shirt”). My advice: just don’t implement anything orange.
You will notice that I ditched the printing of the hat style in the description of yourself. You might be able to recover this with a more complicated “Before printing the name of” rule that suppresses the color but not hat style when the flag that tells it not to print colors is active, or you could just fold the hat style into the printed name of the hat.

Anyway, I realize this is a pretty complicated code example, but I hope it’s helpful!

…oh, and abbreviating “red pants and tailcoat” to “red suit” gives me the heebie-jeebies just thinking about it. Maybe you could write a routine for turning a list of individual clothing items into a list of more complicated descriptions, so it takes the shade list, sees if there’s a coat and pants in it, and turns that into “suit”? That seems like it’d have a lot of complicated ifs in it for sure.