Need help on creating random, but matching (!) clothes

Hi,

in order to make the virtual world a bit more realistic, I often put clothes on the characters in my stories. Now - one downside of static clothing is that you stop looking at them after a while (as developer) and after a playthrough (as player).

In order to make things a bit more interesting I am using a table with pre-defined clothes from which I randomly pick one row (one row contains a full set) when play begins. That’s working out ok but - for the developer - there’s still little variation as you know your tables.

I have been thinking of making it completely random - but then I’d have to ensure that colours would not clash and that the garment made sense. A business blouse with sweatpants would be a tad off. Unfortunately I’m stuck with this in such a way that I never even found a start to code from. But maybe someone out there has done the same or a similar thing or is just so much better at coding in Inform that he or she could help me with a few tips?

Here’s my “how it should work” so far:

We divide the clothes into “classes” first
over-tops: Like a jacket, a coat …
tops: dresses (yes, I think we must see them as tops), sweaters, t-shirts, blouses …
bottoms: shorts, jeans, pants, leggings, skirts …
socks: stockings, socks, pantyhose …
shoes: flats, heels, boots …

For style-matchig we would need some “style compatibility” and some styles …
styles: casual, sportive, formal, …
jeans are casual-style compatible
leggings are casual-style compatible
leggings are sportive-style compatible

Next we would need to define which clothing is compatible to what clothing
jeans are compatible to sweaters
jeans are compatible to t-shirts
jeans are compatible to blouses

Next we would have to define colours and define colour compatibility:
colours: red, blue, black, white, brown

Then we’d be in need of some compatibility that is not a sore to the eye:
blue jeans are colour-compatible to white t-shirts
blue jeans are colour-compatible to black t-shirts
blue jeans are colour-compatible to brown t-shirts
black jeans are colour-compatible to white t-shirts
black jeans are colour-compatible to black t-shirts
black jeans are colour-compatible to red t-shirts

A more compact form (like a list as jeans are compatible to {t-shirts, sweaters, blouses}) would be GREAT as this would get loooong … well, that’s what extensions are for in case there is no compact way to write this.

As for picking a set of clothes once everything is in place:

(1) Pick a style-compatible top at random (the people have a preferred style)
(2) select a colour for the top at random
(3) select a random style-compatible bottom part
(4) assign the bottom part a compatible colour
(5) continue with socks
(6) continue with shoes
(7) continue with over-top if needed (if it is an outdoor scene)

Things get a bit more complicated as dresses are something special (except for leggings, which should be optional, no other bottom garment is actually compatible) but let’s ignore the special cases for now - exceptions or special handling is easy once the framework is in place - which it is in no way, unfortunately.

Has anyone ever done something like that or has a few hints on how to get started or an idea how to achieve this in a completely different way?

I recognize the frustration of having an abstraction not quite suited for the problem at hand. I’d probably do it this way:

  1. Determine a number of generic ensembles. [Jeans + t-shirt] could be one, [gown + slippers] another. Implementation is undefined, but the idea is that the algorithm would first select an ensemble. An ensemble would, perhaps, be a kind of value. That, in turn, would allow us to define from the get-go whether an ensemble is casual, smart, etc.
  2. Each ensemble links to one or more tables. These tables hold specific garments, one table per slot. Once you pick an ensemble, have the code randomize the exact elements of the ensemble from these tables: you simply pull one garment at random from each table linked.
  3. Color can be added last, and should be no real trouble. In fact, it’s probably best to select either one color, or a main and accent color. Items could be tagged as “commonly accented” to let the algorithm prefer them for accent colors, so that a scarf or a tie would stand out. I would actually not use color so much as a more nebulous quality, one that would include some colors but also patterning or texture.

It’s not trivial, but I suspect that’s the easiest way to get descriptions on the form of “John is wearing something hastily thrown together: a black t-shirt with a faded Nirvana print, a pair of baggy jeans, and a big nickel keychain.” or “Alice is dressed to kill: a long black gown, velvet opera gloves, black high heels, and a scarlet scarf around her neck.”

Hm - interesting approach with the pre-defined ensembles. Unfortunately this seems to be a bit hampered in terms of legibility by Inform being unable to handle something like this:

Table 1 - Casual Ensembles
Tops	Bottoms	Shoes
t-shirt	jeans	flats
sweater	jeans	flats
blouse	skirt	heels
t-shirt	shorts	flats

as it expects actual values in a table. But it sounds promising. So maybe use a numeric “outfit code” and have the same value as property on the actual clothing kind. Then do a list of all clothes with that code and select oen at random …

Getting there … this actually works:

"Clothing - Test" by HtF

Dressing Room is a room. 

Colors is a kind of value. The Colors are red, white, black, brown.

clothes are a kind of wearable thing.
clothes can be formal, casual or sportive. clothes usually are casual.
clothes have a Colors called Color.
clothes have number called outfit-code.

tops are kind of clothes.
bottoms are a kind of clothes.
shoes are a kind of clothes.

a t-shirt is a kind of tops. The outfit-code of t-shirts is 1.
a sweater is a kind of tops. The outfit-code of sweaters is 2.
a blouse is a kind of tops. The outfit-code of blouses is 3.

a shorts is a kind of bottoms. The outfit-code of shorts is 10.
a pants is a kind of bottoms. The outfit-code of pants is 11.
a skirt is a kind of bottoms. The outfit-code of skirts is 12.

a flats is a kind of shoes. The outfit-code of flats is 20.
a boots is a kind of shoes. The outfit-code of boots is 21.
a heels is a kind of shoes. The outfit-code of heels is 22.

the printed t-shirt is a t-shirt.
the mono-coloured t-shirt is a t-shirt.
the Led Zeppelin t-shirt is a t-shirt.

The scratchy sweater is a sweater.
The soft sweater is a sweater.

the formal-blouse is a blouse.
the casual-blouse is a blouse.

The Bermudas is a shorts.
The Hot-Pants is a shorts

The proper skirt is a skirt.
The mini-skirt is a skirt.

The Mary-Janes are flats.
The Ballerinas are flats.
The Sneakers are flats.

The Pumps are a heels.
The Ankle-Breakers are heels.

The army boots are boots.
The rain boots are boots.

The Faded-Jeans are pants.
The Torn-Jeans are pants.
The Tight-Jeans are pants.

Table 1.0 - Casual Ensembles
Tops	Bottoms	Shoes
1	11	20
2	11	20
3	12	22
1	10	20

when play begins:
	Say "Initializing clothes.";
	Sort the table of Casual Ensembles in random order;
	Choose row 1 in the Table of Casual Ensembles;
	Let AllClothes be the list of clothes;
	Let TheCode be 0;
	Let L be a list of clothes;
	Now L is {};
	Now TheCode is the Tops entry;
	Repeat with OnePiece running through AllClothes:
		if the outfit-code of OnePiece is TheCode:
			add OnePiece to L;
	Sort L in random order;
	Move entry 1 in L to the Dressing room;
	Now L is {};
	Now TheCode is the Bottoms entry;
	Repeat with OnePiece running through AllClothes:
		if the outfit-code of OnePiece is TheCode:
			add OnePiece to L;
	Sort L in random order;
	Move entry 1 in L to the Dressing room;
	Now L is {};
	Now TheCode is the Shoes entry;
	Repeat with OnePiece running through AllClothes:
		if the outfit-code of OnePiece is TheCode:
			add OnePiece to L;
	Sort L in random order;
	Move entry 1 in L to the Dressing room;
	Say "Done!"

It produces a random (yet colourless) outfit that (more or less) matches!

Is there a better way than to iterate over the whole list each and every time? I tried multiple variations in the form of:

let L be the list of clothes where color-code is TheCode

but this does not compile … Looking though other things I have I came to notice that I never managed to filter a list creation by other means than cycling through it and pushing the elements I wanted to a new list. Is it just me or is there really no other way?

You can do it but you need a global variable to hold a temporary color value.

Global-color is a colors that varies.
Definition: a clothes is global-color-matching if the color of it is global-color.

Instead of jumping:
	now global-color is red;
	let L be the list of global-color-matching clothes;
	say "L is [L]."

And I think that, for your code, once you’ve got zarf’s solution in place you can skip the list-building and go straight to picking a random one:

Now a random global-color-matching clothes is in the Dressing Room

Another potential thing to do, instead of codes, might be to define outfits as a kind of object (or maybe value, if that works), define a relationship such as “belongs to” between clothes and outfits, and then I think you might be able to do “a random top that belongs to the chosen outfit” where “the chosen outfit” is a variable name for an outfit.

Well, I was thinking that relationships might be useful but I’mnot that experienced with Inform and it’s quite hard to find suitable examples from which one can learn. Another issue is, of course,that as a rather experienced programmer in various languages I have this tendency to try to solve Inform problems as I would do with a “normal” language. And I admit that graph/relation based databases have not yet crossed my path since their concept would, most likely, be helpful to me.

Is this purely description/textual or do the clothes also need to exist as objects in the game?

Hm … actually a good question. :slight_smile:

I’d say for most Prop-NPCs there is no need for actual clothes. Which is the bulk of them. There’s only a small number (inlcuding the player) where actual clothes are needed.

Incidentally, you can put kinds of values in a table, so you could do something like this:

Clothing-type is a kind of value. The clothing-types are t-shirt-type, blouse-type, skirt-type, shorts-type, flats, heels.

A clothing has a clothing-type.

A t-shirt is a kind of clothing. A t-shirt usually has clothing-type t-shirt-type.

and then your table might look like

Table of Casual Ensembles
Tops	Bottoms	Shoes
t-shirt-type	skirt-type	flats-type

And that lets you write things like:

choose a random row in the Table of Casual Ensembles;
move a random clothing that is tops entry to the location;

Yep, I know I can do it at that level but the job is to collect all kinds of tops, not just one-of-a-kinds. If you look at my first (non-working) example:

Table 1 - Casual Ensembles
Tops   Bottoms   Shoes
t-shirt   jeans   flats
sweater   jeans   flats
blouse   skirt   heels
t-shirt   shorts   flats

t-shirt, sweater and blouse are all of the top-kind. But when Inform encounters the fist “type” it memorizes it and expects all entries to be t-shirts as well and coughs as soon as the sweater is reached.

The difference is that your example made a table of kinds, but if you instead use table of properties you can use them as adjectives which is easier to read than numbers.

So your working example could have a much simpler “when play begins” rule:

[code]“Clothing - Test” by HtF

Dressing Room is a room.

Clothing-type is a kind of value. The clothing-types are t-shirt-type, sweaters-type, blouses-type, shorts-type, pants-type, skirts-type, flats-type, boots-type, heels-type.

Colors is a kind of value. The Colors are red, white, black, brown.

clothes are a kind of wearable thing.
clothes have clothing-type.

tops are kind of clothes.
bottoms are a kind of clothes.
shoes are a kind of clothes.

a t-shirt is a kind of tops. The clothing-type of t-shirts is t-shirt-type.
a sweater is a kind of tops. The clothing-type of sweaters is sweaters-type.
a blouse is a kind of tops. The clothing-type of blouses is blouses-type.

a shorts is a kind of bottoms. The clothing-type of shorts is shorts-type.
a pants is a kind of bottoms. The clothing-type of pants is pants-type.
a skirt is a kind of bottoms. The clothing-type of skirts is skirts-type.

a flats is a kind of shoes. The clothing-type of flats is flats-type.
a boots is a kind of shoes. The clothing-type of boots is boots-type.
a heels is a kind of shoes. The clothing-type of heels is heels-type.

the printed t-shirt is a t-shirt.
the mono-coloured t-shirt is a t-shirt.
the Led Zeppelin t-shirt is a t-shirt.

The scratchy sweater is a sweater.
The soft sweater is a sweater.

the formal-blouse is a blouse.
the casual-blouse is a blouse.

The Bermudas is a shorts.
The Hot-Pants is a shorts

The proper skirt is a skirt.
The mini-skirt is a skirt.

The Mary-Janes are flats.
The Ballerinas are flats.
The Sneakers are flats.

The Pumps are a heels.
The Ankle-Breakers are heels.

The army boots are boots.
The rain boots are boots.

The Faded-Jeans are pants.
The Torn-Jeans are pants.
The Tight-Jeans are pants.

Table 1.0 - Casual Ensembles
Tops Bottoms Shoes
t-shirt-type pants-type flats-type
sweaters-type pants-type flats-type
blouses-type skirts-type heels-type
t-shirt-type shorts-type flats-type

when play begins:
Say “Initializing clothes.”;
choose a random row in the Table of Casual Ensembles;
move a random clothes that is tops entry to the location;
move a random clothes that is bottoms entry to the location;
move a random clothes that is shoes entry to the location;
Say “Done!”
[/code]