Wearing things in layers (new to I7)

Hello, newbie here :slight_smile:

As a first exercise I decided to try and “fix” the layered clothing model presented in “What Not To Wear” (http://inform7.com/learn/man/Rex426.html#e426).

The issues I want to fix:

  1. It only works on the player (should be easy to fix, not my focus at the moment)

  2. It relates every piece of clothing in existence, which seems wasteful. My idea here is to create a set of garment archetypes and establish relations between those. Then each real garment holds a reference to the appropriate archetype.

A garment-element is a kind of thing. It has a garment-element called archetype.
The hat-archetype is a garment-element.
A hat is a kind of garment-element. The archetype of a hat is usually the hat-archetype.
The beanie, the fedora and the baseball cap are hats.

And so forth. It’s a bit of a mess; I’m having trouble working with object models in Inform. My current implementation (see below) appears to work, but it’s slow. The original code also feels more sluggish that I’d expected, but mine is even worse.

I’d appreciate any suggestions for improvements :slight_smile:

[spoiler][code]
“Test” by blah

[Original “What Not To Wear”]

[Include Plurality by Emily Short.]

[ Not used yet, maybe useful at some point:
To decide whether (X - a value) is sibling to (Y - a value): no.
To decide whether (X - a value of kind K) is sibling to (Y - a value of kind M): if K is M, yes; no.
]

Section 1 - Overlying and Underlying

[We start by borrowing some of the same ideas from the Bogart example, but we’re also going to make a kind called “garment-element”. This kind will include both garments (objects of clothing) and body parts (things that can be covered by clothing); using it allows us to restrict the way our underlying and overlying relations apply, which will make them a bit faster at run-time.]

A garment-element is a kind of thing. A garment-element has a garment-element called archetype.

Underlying relates various garment-elements to various garment-elements with fast route-finding.
The verb to underlie (it underlies, they underlie, it is underlying, it is underlaid) implies the underlying relation.
The verb to be under implies the underlying relation.

Overlying relates various garment-elements to various garment-elements.
The verb to overlie (it overlies, they overlie, it is overlying) implies the overlying relation.

Covering relates a garment-element (called A) to a garment-element (called B) when the number of steps via the overlying relation from A to B is greater than 0.
The verb to cover (it covers, they cover, it is covering, it is covered) implies the covering relation.

Definition: a garment-element is uppermost if it is not under something opaque.

Check taking off:
if the noun underlies something (called the impediment) which is worn by the actor, say “[The impediment] is in the way.” instead.

Carry out taking off:
now the noun is not underlaid by anything.

Report taking off something:
say “You are now wearing [a list of garments worn by the player].” instead. [uppermost removed]

Before taking off something which underlies something which is worn by the player:
while the noun underlies something (called the impediment) which is worn by the player:
say “(first removing [the impediment])[command clarification break]”;
silently try taking off the impediment;
if the noun underlies the impediment, stop the action.

[ ORIGINAL:
Before wearing something when a garment which covers the noun is worn by the player:
while the player wears a garment (called the impediment) which covers the noun:
say “(first removing [the impediment])[command clarification break]”;
silently try taking off the impediment;
if the player is wearing the impediment, stop the action.

Before wearing something:
let N be the layering depth of the noun;
repeat with item running through things worn by the player:
if the layering depth of the item is N and the item covers a garment-region which is covered by the noun:
say “(first taking off [the item])[command clarification break]”;
silently try taking off the item;
if the player wears the item, stop the action.
]

Before wearing something:
repeat with worn-garment running through garments worn by the actor:
if the archetype of the worn-garment covers the archetype of the noun:
say “(first removing [the worn-garment])[command clarification break]”;
silently try taking off the worn-garment;
if the actor is wearing the worn-garment, stop the action;
let regions-covered-by-noun be the list of garment-regions covered by the archetype of the noun;
say “regions-covered-by-noun = [regions-covered-by-noun].”;
repeat with worn-garment running through garments worn by the actor:
let I be regions-covered-by-noun;
repeat with region-covered-by-worn-garment running through garment-regions covered by the archetype of the worn-garment:
if region-covered-by-worn-garment is not listed in regions-covered-by-noun, remove region-covered-by-worn-garment from I, if present;
repeat with shared-region running through I:
let A be the layering depth of the worn-garment for shared-region;
let B be the layering depth of the noun for shared-region;
if A is B:
say “shared-region = [shared-region], depth of worn-garment = [A], depth of the noun = [B]”;
say “(first taking off [the worn-garment])[command clarification break]”;
silently try taking off the worn-garment;
if the actor is wearing the worn-garment, stop the action;
break.

Carry out wearing:
repeat with worn-garment running through things worn by the actor:
if the archetype of the noun covers the archetype of the worn-garment, now the worn-garment underlies the noun.

[This may seem like overkill, but it allows us to create garments that cover different subsets of the body – pants and shirt vs. a dress, for instance.]

To decide what number is the layering depth of (chosen garment - a garment) for (target-region - garment-region):
let N be 0;
if the archetype of the chosen garment covers the archetype of the target-region:
let N be the number of steps via the overlying relation from the archetype of the chosen garment to the archetype of the target-region;
decide on N.

[
To decide what number is the layering depth of (chosen garment - a thing):
let N be 0;
if the chosen garment covers a garment-region (called base):
let N be the number of steps via the overlying relation from the chosen garment to the base;
decide on N.
]

[To help with modeling, we’ll give everyone body parts (garment regions), broken down according to their relevance to clothing:]

A garment-region is a kind of garment-element.
A torso, a hip, a head, a pair of legs, and a pair of feet are kinds of garment-region.

One head, one torso, one pair of legs, one pair of feet and one hip are part of every person. [One pair of legs is part of every person. …]

The torso-archetype is a torso.
The hip-archetype is a hip.
The head-archetype is a head.
The legs-archetype is a pair of legs.
The feet-archetype is a pair of feet.

The archetype of a torso is usually torso-archetype.
The archetype of a hip is usually hip-archetype.
The archetype of a head is usually head-archetype.
The archetype of a pair of legs is usually legs-archetype.
The archetype of a pair of feet is usually feet-archetype.

[And now we make some categories of clothing:]

A garment is a kind of garment-element. A garment can be transparent. A garment is usually wearable. [A garment has a garment called archetype.]
A pair of pants, a pair of underpants, a foundation garment, a pair of socks, a pair of shoes, a jacket, a hat, a dress, and a shirt are kinds of garment.

The plural of pair of pants is pairs of pants. The plural of pair of underpants is pairs of underpants. The plural of pair of socks is pairs of socks. The plural of pair of shoes is pairs of shoes.

The pants-archetype is a pair of pants.
The underpants-archetype is a pair of underpants.
The foundation-archetype is a foundation garment.
The socks-archetype is a pair of socks.
The shoes-archetype is a pair of shoes.
The jacket-archetype is a jacket.
The hat-archetype is a hat.
The dress-archetype is a dress.
The shirt-archetype is a shirt.

The archetype of a pair of pants is usually pants-archetype.
The archetype of a pair of underpants is usually underpants-archetype.
The archetype of a foundation garment is usually foundation-archetype.
The archetype of a pair of socks is usually socks-archetype.
The archetype of a pair of shoes is usually shoes-archetype.
The archetype of a jacket is usually jacket-archetype.
The archetype of a hat is usually hat-archetype.
The archetype of a dress is usually dress-archetype.
The archetype of a shirt is usually shirt-archetype.

Instead of taking inventory: [uppermost removed]
say “You’re carrying [a list of things carried by the player][if the player wears something]. You are wearing [a list of garments worn by the player][end if].”

When play begins:
now socks-archetype overlies feet-archetype;
now shoes-archetype overlies socks-archetype;
now underpants-archetype overlies hip-archetype;
now pants-archetype overlies legs-archetype;
now pants-archetype overlies underpants-archetype;
now foundation-archetype overlies torso-archetype;
now jacket-archetype overlies shirt-archetype;
now jacket-archetype overlies dress-archetype;
now hat-archetype overlies head-archetype;
now dress-archetype overlies underpants-archetype;
now dress-archetype overlies foundation-archetype.

Section 2 - The Scenario

The Dressing Room is a room.

The player carries some capris, some jeans, a corset, a plunge bra, a thong, boy-shorts, black satin D’Orsay pumps, brown leather boots, a camisole, a cocktail dress, a bolero, a cashmere shrug, a sheer wrap, woolly socks, and a linen tunic.

The thong has the description “a red barely-there crime against good taste”.

The woolly socks are a pair of socks.
The D’Orsay pumps and the brown leather boots are pairs of shoes.
The thong and the boy-shorts are pairs of underpants.
The capris and the jeans are pairs of pants.
The tunic is a shirt.
The camisole, the corset, and the plunge bra are foundation garments.
The cocktail dress is a dress.
The bolero, the cashmere shrug, and the sheer wrap are jackets. The shrug and the wrap are transparent.

[Aaron, Ben, Carl, David, Earl, Fargo, Gabriel, Harry, Ian, Jack, Kyle, Larry, Michael, Nate, Ozzy and Patrick are men in the Dressing Room.]

[The player is wearing the thong and the jeans.]

Test legs with “wear thong / wear jeans”.
Test me with “wear capris / wear jeans / i / wear thong / i / wear dress / wear corset / wear dress / i / wear wrap / i / wear boots / wear pumps / i”.

[/code][/spoiler]

How does this compare to a “update the layers of worn clothing” during the carry out wearing rules? Such a function would just relate the items the player is wearing (ie “now the noun overlies every shirt worn by the actor” (not tested)). The advantage with the initial code is that there’s only the initial setup, which is a little boggy in IDE but more or less unnnoticeable on most machines I’ve tried, which simplifies code. How is the speed when you actually compile your WIP?

I’ve had fairly good success with the “when play begins” method combined with updates as clothing status changes, but if you come up with something faster, please let me know, since I’m using similar gutted code for my WIP.

Nice. A while ago I managed to do largely what you refer to using a combination of values, kinds, ‘to decide’-phrases, and custom relations. The project unfortunately foundered; the more appropriate the autogenerated prose became, the less I wanted it to be as generic as it had to be. I still have a lot to learn in terms of making prose flow smoothly.

Anyway, the end benefit of doing it that way is a great deal of flexibility and an impressive speed boost (or at least, the speed in the I7 environment was (very) noticeably improved compared to What Not To Wear, despite my test using far more body parts and possible areas and overall greater complexity). The drawbacks are the aforementioned complexity; it simply requires more moving parts, and the conceptual complexity is increased by a large factor.

This is actually what’s happening now – or is supposed to happen at any rate. Permanent relations are only established for the archetypes, and during play the worn items are related as appropriate.

The current “when play begins” bit is misleading; that stuff should happen before play begins, replaced with code that establishes relations for garments worn by the player and NPCs when play begins.

If I can’t get this working with acceptable performance, might as well give up on enforcing the layering and let the player wear whatever s/he pleases. Then again, this system would be good for deciding what NPCs wear.

Maybe. I don’t know. I’m really no good at math or algorithms :stuck_out_tongue:

Are you willing to share your code? I don’t plan to use this in any finished work, it’s just something to play with while learning Inform. If something usable were to come out of it, I could make it available as an extension if there’s any interest.

I should probably fix the code in the first post somehow, it’s very difficult to read without tabs.

If you use the code tag to wrap your source, it’ll preserve the tabs. (The web browser will then convert them to spaces anyway, because all browser designers hate programming languages with significant whitespace, but if you quote the post you’ll see the tabs are still tabs behind the scenes!)

Gladly. It’s a WIP anyway, and it wasn’t going anywhere. Bit big for the forum though, and it’s probably inelegant, so in order to spare the eyes of purists and aesthetes alike, I’ll spoilerize it.

"Lightweight" by Björn Paulsen

Include Epistemology by Eric Eve.



Part 1 - Garments and Body-parts
Chapter 1 - Kinds
Section 1 - Garment-element

A garment-element is a kind of thing.



Section 2 - Garment

A garment is a kind of garment-element. A garment can be worn. A garment can be transparent. A garment can be underwear. A garment can be openable. A garment can be open or closed. 


Section 3 - Body-part

A body-part is a kind of garment-element. A body-part can be unexpected. [This allows for tattoos as well as more bizarre occurences that you wouldn't expect until you see it... horns, maybe?]



Section 4 - Wrapping it up

Every garment-element has a number called level. The level of a garment is usually 2. The level of a body-part is usually 0.

A body-area is a kind of value.




Chapter 2 - Coverage and visibility

Section 1 - Relating body-areas to things on the body


Placement relates various garment-elements to various body-areas.
The verb to occupy (he occupies, they occupied, it is occupying) implies the placement relation.

To decide whether (x - a garment-element) covers (y - a body-area):
	if x is transparent, no;
	if x occupies y, yes;
	no.

	


Section 2 - Rules for checking visibility

Definition: a thing is being worn if someone is wearing it.


The warderobe rules are an object based rulebook.

A warderobe rule for a garment (called cloth) (this is the don't hide what's not worn rule):
	if the cloth is not being worn, rule succeeds;
	make no decision.

A warderobe rule for a body-part (called flesh) (this is the don't hide naked bodies rule):
	if the holder of the flesh does not wear an opaque garment, rule succeeds;
	make no decision.
	
A warderobe rule for a garment-element (called element) (this is the don't hide outermost attire rule):
	let subject be holder of the element;
	repeat with item running through opaque garments worn by subject:
		if the level of the item is greater than the level of the element, make no decision;
	rule succeeds.

A warderobe rule for a garment-element (called element) (this is the standard hidden attire rule):
	let subject be holder of the element;
	let overlying garment-cover be a list of body-areas;
	repeat with item running through opaque garments worn by subject:
		if the level of the item is greater than the level of the element:
			repeat with gar running through body-areas:
				if the item covers gar, add gar to overlying garment-cover, if absent;
	repeat with area running through body-areas:
		if the element occupies the area and the area is not listed in overlying garment-cover, rule succeeds;
	rule fails.

To decide whether (element - a garment-element) is in sight:
	consider the warderobe rules for the element;
	if rule succeeded, yes;
	no.


	
Section 3 - Finding the clothes that cover
	
To decide which list of garments is garments hiding (area in question - a body-area) on (subject - a person):
	let clothesline be a list of garments;
	repeat with cloth running through opaque garments worn by subject:
		if the cloth covers the area in question, add the cloth to the clothesline;
	sort the clothesline in level order;
	decide on the clothesline.
	
To decide which list of garments is visible garments hiding (area in question - a body-area) on (subject - a person):
	let clothesline be garments hiding area in question on subject;
	if the number of entries in clothesline is at least 2:
		let extra clothesline be a list of garments;
		repeat with cloth running through clothesline:
			consider the warderobe rules for the cloth;
			if rule succeeded, add the cloth to extra clothesline;
		decide on extra clothesline;
	decide on clothesline.
	



Chapter 3 - Accessibility

Section 1 - Relations

General access-permission relates various garments to various body-areas. 

The verb to generally permit access to (he generally permits access to, they generally permit access to, it is generally permitting access to) implies the general access-permission relation.


To decide whether (x - a garment-element) makes (y - a body-area) inaccessible:
	if x generally permits access to y, no;
	if x covers y, yes;
	no.	



Section 2 - Access permission

The access permission rules are an object based rulebook. 

An access permission rule for a garment (called cloth) (this is the don't anchor what's not worn rule): 
	if the cloth is not being worn, rule fails;
	make no decision.

An access permission rule for a garment-element (called element) (this is the don't anchor topmost element rule):
	let subject be the holder of the element;
	repeat with item running through garments worn by subject:
		if the level of the item is greater than the level of the element:
			make no decision;
	rule fails.

An access permission rule for a garment-element (called element) (this is the standard access permission for elements rule):
	let subject be the holder of the element;
	repeat with item running through garments worn by subject:
		if the level of the item is greater than the level of the element:
			repeat with bar running through body-areas:
				if the element occupies the bar: 
					if the item makes the bar inaccessible:
						rule succeeds;
	rule fails.


To decide whether (element - a garment-element) can be affected:
	consider the access permission rules for the element;
	if rule succeeded, decide no;
	yes.



	
Section 2 - Locking down

To decide whether (upper - a garment) locks down (lower - a garment-element):
	repeat with bar running through body-areas:
		if upper makes the bar inaccessible and lower occupies the bar, yes;
	no.

To decide which list of garments is clothes that lock (specific element - garment-element):
	let locklist be a list of garments;
	consider the access permission rules for the specific element;
	if rule succeeded:
		let the subject be the holder of the specific element;
		repeat with item running through garments worn by the subject:
			if the item is not the specific element:
				if the item locks down the specific element, add the item to locklist;
	decide on locklist.

To decide which list of garments is nearest clothes that lock (specific element - garment-element):
	let locklist be a list of garments;
	let locklist be clothes that lock the specific element;
	if the number of entries in the locklist is at least 2:
		let result be a list of garments;
		sort the locklist in level order;
		let desired level be the level of entry 1 of locklist;
		repeat with item running through locklist:
			if the level of the item is the desired level, add item to result;
		decide on result;
	decide on locklist.





	
Chapter 4 - Knowledge (For use with Epistemology by Eric Eve)

A body-part is usually familiar. An unexpected body-part is usually unfamiliar.

The mark items as seen when looking rule is not listed in any rulebook.

Carry out looking (this is the fancy mark items as seen when looking rule): 
	unless in darkness:
		repeat with item running through things that are enclosed by the location:
			if the item is a garment-element:
				consider the warderobe rules for the item;
				if rule succeeded:
					now the item is familiar;
					now the item is seen;
			otherwise:
				if the item is not enclosed by an opaque closed container, now the item is seen.

After actor taking off garment:
	repeat with item running through things that are enclosed by actor:
		if the item is a garment-element:
			consider the warderobe rules for the item;
			if rule succeeded:
				now the item is familiar;
				now the item is seen;
	continue the action.

After disrobing garment (this is the fancy mark items as seen when removing rule):
	unless in darkness:
		repeat with item running through things that are enclosed by the holder of the noun:
			if the item is a garment-element:
				consider the warderobe rules for the item;
				if rule succeeded:
					now the item is familiar;
					now the item is seen;
	continue the action.


Carry out examining visible garment (this is the fancy mark items as seen on examining rule):
	consider the warderobe rules for the noun;
	if rule succeeded:
		now the noun is familiar;
		now the noun is seen;
	otherwise:
		stop the action.



Part 2 - Default action behaviour

Chapter 1 - Concealed

Rule for deciding the concealed possessions of a person:
	if the particular possession is unknown, yes;
	otherwise no.



Chapter 2 - Removing clothes

Section 1 - Disrobing and permissions

Disrobing is an action applying to one touchable thing.


The disrobing permission rules are an object based rulebook.
A disrobing permission rule: rule succeeds.


Rule for implicitly taking something (called cloth) when the cloth is not worn by the person asked and the cloth is worn by a person and the current action is taking off the cloth:
	try disrobing the cloth. 

Check disrobing: 
	let subject be holder of the noun;
	consider the disrobing permission rules for the noun;
	if rule failed, say "[The subject] doesn't concur." instead.

Carry out disrobing: now the noun is in the location of the noun.
Report disrobing: say "You take off [the noun]."












Part 3 - Defining the particulars

Chapter 1 - Body-areas

Head-area, chest-area, belly-area, back-area, arm-area, hand-area, pelvis-area, thigh-area, ankle-area, and foot-area are body-areas.



Chapter 2 - Body-parts

A chest, arms, legs, a butt, and a head are kinds of body-part.
Arms, legs, a butt, a chest, and a head are parts of every person.

Arms and legs are usually plural-named.

Every chest occupies chest-area.
Every breasts occupies chest-area.
Every arms occupies arm-area.
Every legs occupies thigh-area, ankle-area, and foot-area.
Every butt occupies pelvis-area.
Every head occupies head-area.


Chapter 3 - Clothing

A kilt is a kind of garment. Every kilt occupies the pelvis-area and the thighs-area. The level of a kilt is 2.
A bra is a kind of garment. Every bra occupies chest-area. The level of a bra is 1. A bra is underwear.
A pair of panties is a kind of garment. Every pair of panties occupies the pelvis-area. The level of a pair of panties is 1. A pair of panties is underwear.
A suit is a kind of garment. Every suit occupies the pelvis-area, the thighs-area, the chest-area, the arm-area, and the ankle-area. The level of a suit is 3.


Part 3 - Showtime

A persuasion rule for asking someone to try doing something: persuasion succeeds.


Chapter 1 - Room

The Arena is a room. 


Chapter 2 - Player

The chainmail bikini is a pair of panties. The chainmail bra is a bra. The leather armor is a suit.

Sonja is a woman in the Arena. Sonja is wearing the leather armor, the chainmail panties and the chainmail bra. The player is Sonja.


Chapter 3 - NPC

The scale armor is a suit. The loincloth is a kilt.

Conan is a man in the Arena.  Conan is wearing the loincloth and the scale armor.

Before posting I had to perform some surgery to excise the things that weren’t germane to the example. Other things I had no time to get into - for instance, there’s no report examining known garment rule, but it should be trivial to add.

Thanks Emerald, fixed the code in the first post.

Thanks a lot, I’ll take a look at it soon.

A moment ago I tried adding a bunch of people to my test scenario and it slowed down even more, which is interesting because they aren’t wearing anything. Something is definitely not right with it, I’ll have to check how the original WNTW behaves.

Apparently a lot of time is spent executing this in “Before wearing something”:

let regions-covered-by-noun be the list of garment-regions covered by the archetype of the noun;
[the variable’s name is a bit misleading]

I can’t see why. Any ideas?

I haven’t done any profiling to verify where the slowness is. But eyeballing the code, I see that the covering relation requires doing a graph search through the overlying relation, which is many-to-many. You’re calling that a lot.

I suspect (again, haven’t verified) that that list-making command iterates through every garment-region in the game, and does a “covers” test on it. That would probably be slow.

Yeah, I figured it out earlier: every person in the game has multiple garment-regions (head, torso, etc), and the code goes through all of them and the clothes, even though it’s only necessary to check the “archetypes”.

I changed it now and it’s much faster, though I’m not sure whether it actually works. I’ll update the first post as soon as I have tested it further.