Layering Clothing

I’m interested in clothes that layer: you can’t take off your socks without first taking off your shoes, and you can’t put shoes on over other shoes, that sort of thing. I limited myself to handling footwear so far to keep things simple. I decided not to include body part objects for this exercise, though if desired I think the same general system would work for covering body parts with clothes.

(prevent [wear $new-footwear])
 {
  (terminal footwear $new-footwear)
 (or)
  (layerable footwear $new-footwear)
 }
 (current player $actor)
 ($old-footwear is #wornby $actor)
 (terminal footwear $old-footwear)
 You would have to remove (the $old-footwear) first.
(perform [wear $new-footwear])
 {
  (terminal footwear $new-footwear)
 (or)
  (layerable footwear $new-footwear)
 }
 (current player $actor)
 ($old-footwear is #wornby $actor)
 (layerable footwear $old-footwear)
 ~($old-footwear is covered by $)
 (narrate wearing $new-footwear)
 (now) ($new-footwear is #wornby $actor)
 (now) ($new-footwear is handled)
 (now) ($old-footwear is covered by $new-footwear)
(prevent [remove $covered])
 ($covered is covered by $covering)
 You can't take off (the $covered) without first taking off (the $covering).
(perform [remove $covering])
 ($covered is covered by $covering)
 (narrate removing $covering)
 (current player $actor)
 (now) ($covering is #heldby $actor)
 (now) ($covering is handled)
 (now) ~($covered is covered by $)

Here is playing around with the code.

> wear red socks
(first attempting to take your red socks)
You take your red socks.
You put on your red socks.

> wear blue socks
(first attempting to take your blue socks)
You take your blue socks.
You put on your blue socks.

> remove red socks
You can't take off your red socks without first taking off your blue socks.

> wear red shoes
(first attempting to take your red shoes)
You take your red shoes.
You put on your red shoes.

> wear blue shoes
(first attempting to take your blue shoes)
You take your blue shoes.
You would have to remove your red shoes first.

I want to extend this to more types of clothes, handle taking inventory so that layering is expressed to the player in an understandable fashion, handle concealment of underlying layers (underwear), and so on; I’ll post progress reports here.

2 Likes

I managed to make it so that socks, shoes, underwear and pants all coexist and layer in their own little stacks without resorting to a “foot slot, lower body slot”, etc system. There are two predicates needed, ($ can go underneath $) that defines how layering works and ($ can coexist with $) that defines what can exist in a separate stack.

%% Coder responsible for all other (their $) predicate definitions

(their (current player $))
 your

This is the base class for any type of thing that can belong to someone.

%% Possession class

(name (possession $possession))
 (if)
  ($possession belongs to $owner)
 (then)
  (their $owner)
 (endif)
 (possession prefix $possession)
 (possession name $possession)
 (possession suffix $possession)

(possession prefix $)
(possession suffix $)

(dict ($ belongs to $owner))
 *(dict $owner)

(proper (possession $possession))
 (if)
  ($possession belongs to $owner)
 (then)
  (proper $owner)
 (else)
  (possession proper $possession)
 (endif)

(possession proper $)
 (fail)

(singleton (possession $possession))
 (if)
  ($possession belongs to $owner)
 (then)
  (singleton $owner)
 (else)
  (possession singleton $possession)
 (endif)

(possession singleton $)
 (fail)

All clothes derive from this subclass.

%% Clothing subclass

(possession *(clothing $))

(dict (clothing $))
 clothing garment

(plural dict (clothing $))
 clothing clothes garments

(wearable (clothing $))

Socks can go under socks and shoes, and coexist with underwear and pants.

%% Socks subclass

(clothing *(socks $))

(possession name (socks $))
 socks

(dict (socks $))
 sock

(plural (socks $))

((socks $) can go underneath (socks $))
((socks $) can go underneath (shoes $))

((socks $) can coexist with (underwear $))
((socks $) can coexist with (pants $))
((shoes $) can coexist with (necklace $))

Nothing goes over shoes; they coexist with underwear and pants.

%% Shoes subclass

(clothing *(shoes $))

(possession name (shoes $))
 shoes

(dict (shoes $))
 shoe

(plural (shoes $))

((shoes $) can coexist with (underwear $))
((shoes $) can coexist with (pants $))
((shoes $) can coexist with (necklace $))

Underwear can go under underwear and pants, and coexist with socks and shoes.

%% Underwear

(clothing *(underwear $))

(possession name (underwear $))
 underwear

(plural dict (underwear $))
 underwears

((underwear $) can go underneath (underwear $))
((underwear $) can go underneath (pants $))

((underwear $) can coexist with (socks $))
((underwear $) can coexist with (shoes $))
((underwear $) can coexist with (necklace $))

Pants can go under other pants as well as underwear, even though doing so is a bit silly. They coexist with socks and shoes.

%% Pants

(clothing *(pants $))

(possession name (pants $))
 pants

(dict (pants $))
 pant

(plural (pants $))

((pants $) can go underneath (underwear $))
((pants $) can go underneath (pants $))

((pants $) can coexist with (socks $))
((pants $) can coexist with (shoes $))
((pants $) can coexist with (necklace $))

The prevent rule is complicated, it collects all the exposed clothing and if none of them can go under the clothing being put on nor coexist with them, wearing is prevented. EDIT - Informative error message.

%% Wearing rules

(prevent [wear $new-clothing])
 (current player $actor)
 (collect $worn-clothing)
  *($worn-clothing is #wornby $actor)
  ~($worn-clothing is underneath $)
 (into $exposed-clothing)
 ~(empty $exposed-clothing)
 *($choice is one of $exposed-clothing)
 ~($choice can go underneath $new-clothing)
 ~($choice can coexist with $new-clothing)
 You can't wear (the $new-clothing)
 without first removing (the $choice).

(perform [wear $new-clothing])
 (current player $actor)
 *($old-clothing is #wornby $actor)
 ~($old-clothing is underneath $)
 ($old-clothing can go underneath $new-clothing)
 (narrate wearing $new-clothing over $old-clothing)
 (now) ($new-clothing is #wornby $actor)
 (now) ($new-clothing is handled)
 (now) ($old-clothing is underneath $new-clothing)

(narrate wearing $new-clothing over $old-clothing)
 You put on (the $new-clothing)
 over (the $old-clothing).

Removing layered clothes is simpler.

%% Removing rules

(prevent [remove $covered])
 ($covered is underneath $covering)
 You can't remove (the $covered)
 without first removing (the $covering).

(perform [remove $covering])
 (current player $actor)
 *($covered is #wornby $actor)
 ($covered is underneath $covering)
 (narrate removing $covering exposing $covered)
 (now) ($covering is #heldby $actor)
 (now) ($covering is handled)
 (now) ~($covered is underneath $)

(narrate removing $covering exposing $covered)
 You take off (the $covering),
 exposing (the $covered).

One issue is initialization at the start of the game, if you want the player to start clothed in layers you have to manually set up the ($ is underneath $) relationships, which isn’t hard but tedious.


EDIT: Tried something new, a necklace subclass that can coexist with itself, allowing you to put on and remove them in any order without them layering. This seems to work fine, but it’s becoming clear that having to write coexist rules for every pair of subclass is going to get unwieldy. I’m trying to think of a way to infer coexist rules without having to write them all out.

%% Necklace

(clothing *(necklace $))

(possession name (necklace $))
 necklace

(plural dict (necklace $))
 necklaces

((necklace $) can coexist with (socks $))
((necklace $) can coexist with (shoes $))
((necklace $) can coexist with (underwear $))
((necklace $) can coexist with (pants $))
((necklace $) can coexist with (necklace $))
2 Likes

I found a solution to require significantly less written out ($ can coexist with $) rules.

($clothing1 can coexist with $clothing2)
 ~($clothing1 can go underneath $clothing2)
 ~($clothing2 can go underneath $clothing1)

There is one problem with this: it doesn’t handle preventing shoes being put on in a separate stack when you have shoes (which can’t layer under anything) on already. This is the case where you do have to explicitly state that shoes can’t coexist with shoes; do this for any clothes you can’t put anything over.

~((shoes $) can coexist with (shoes $))

Edit, here’s a simple inventory printout predicate:

(perform [inventory])
 (current player $player)
 (collect $x)
  *($x is #heldby $player)
 (into $held)
 (collect $x)
  *($x is #wornby $player)
  ~($x is underneath $)
 (into $exposed)
 (collect $x)
  *($x is #wornby $player)
  ($x is underneath $)
 (into $covered)
 (if)
  (empty $held)
 (then)
  You are empty handed.
 (else)
  You hold (a $held).
 (endif)
 (if)
  (empty $exposed)
 (then)
  You are naked.
 (else)
  You wear (a $exposed).
  (if)
   ~(empty $covered)
  (then)
   Underneath you wear (a $covered).
  (endif)
 (endif)
 (line)

> inv
You hold your red pants and your blue shoes. You wear your blue necklace, your red necklace, your blue pants, and your red shoes. Underneath you wear your blue underwear, your red underwear, your blue socks, and your red socks.

I would prefer something of the form “You wear your blue necklace, your red necklace, your blue pants over your blue underwear over your red underwear, and your red shoes over your blue socks over your red socks.”, but haven’t thought how to do that just yet.

2 Likes