I7: Creating kinds with optional parts

I am currently having some difficulties with creating kinds in Inform 7 with optional parts. Specifically, consider the following situation:

A chair is a kind of enterable supporter.
A desk is a kind of supporter. A chair (called its seat) is usually a part of every desk.

TESTROOM is a room.
In TESTROOM is a desk called SEATDESK.
In TESTROOM is a desk which has no seat.

----------------------------------------

[when running]
>showme
TESTROOM - room
    yourself - person
    SEATDESK - desk
        SEATDESK's seat (part of SEATDESK) - chair
    desk which has no seat

Inform considers “desk which has no seat” as the name of a thing, rather than describing the composition of a desk.

I also tried this:

A chair is a kind of enterable supporter.
A desk is a kind of supporter. A chair (called its seat) is usually a part of every desk.

TESTROOM is a room.
In TESTROOM is a desk called SEATDESK.
In TESTROOM is a desk called STANDINGDESK. No seat is a part of STANDINGDESK.

----------------------------------------

[when running]
>showme
TESTROOM - room
    yourself - person
    SEATDESK - desk
        SEATDESK's seat (part of SEATDESK) - chair
    STANDINGDESK - desk
        STANDINGDESK's seat (part of STANDINGDESK) - chair
        No seat (part of STANDINGDESK)

This creates a desk with a seat anyway, and then also interprets “No seat” as the name of an additional thing.

I also tried defining an adjective to create them:

A chair is a kind of enterable supporter.
A desk is a kind of supporter.
Definition: a desk is seatful rather than seatless:
	if a chair is a part of the desk, decide yes;
	decide no.
A desk is usually seatful.

TESTROOM is a room.
In TESTROOM is a desk called SEATDESK.
In TESTROOM is a seatless desk called STANDINGDESK.

----------------------------------------

[compilation error]
  >--> In the sentence 'a desk is seatful rather than seatless', you ask me to
arrange for something to be 'seatful' at the start of play. There are some
adjectives ('open' or 'dark', for instance) which I can fix, but others are just
too vague. For example, saying 'Peter is visible.' isn't allowed, because it
doesn't tell me where Peter is. Like 'visible', being 'seatful' is something I can
test during play at any time, but not something I can arrange at the start.

Can anyone guide me on how I can create a kind with an optional part, and then create an instance of that kind without the part? Thank you so much :slight_smile:


EDIT: I also just tried this, unsuccessfully:

A chair is a kind of enterable supporter.
A desk is a kind of supporter. A chair (called its seat) is usually a part of every desk.

TESTROOM is a room.
In TESTROOM is a desk called SEATDESK.
In TESTROOM is a desk called STANDINGDESK. STANDINGDESK's seat is nothing.

----------------------------------------

[compilation error]
  >--> The sentence 'STANDINGDESK's seat is nothing' appears to say two
things are the same - I am reading 'STANDINGDESK's seat' and 'nothing
as two different things, and therefore it makes no sense to say that one
is the other: it would be like saying that 'Adams is Jefferson'. It would
be all right if the second thing were the name of a kind, perhaps with
properties: for instance 'Virginia is a lighted room' says that something
called Virginia exists and that it is a 'room', which is a kind I know
about, combined with a property called 'lighted' which I also know about.
1 Like

I’m surprised this compiled; it doesn’t work as expected. Basically, Inform is ignoring the “usually” in that declaration and makes a chair part of every desk. The best way to deal with this is to either make two different kinds of supporter or make two subkinds of desk.

lab is a room.
A chair is a kind of enterable supporter.
A desk is a kind of supporter. 

A standing-desk is a kind of desk.
A seated-desk is a kind of desk. A chair (called its seat) is a part of every seated-desk.

A seated-desk called the writing desk is in the Lab.
A standing-desk called the workbench is in the Lab.

A chair called the wooden stool is in the Lab.

The easiest way to check if your kinds are being declared properly is to check the index after compilation. After compiling the above, you get:

4 Likes

Oh haha I was just about to post pretty much the same code, labels and all.

For the record, you can use more than one word per name (e.g. seated desk).

You’ve already seen some of the ways Inform creates unwanted additional things. As far as I know, which is not used in Inform.

Your seatful example never sets seatfulness, and the condition (has a chair) is actually meant to be the result, but with some tweaking it would work.

The reason why your “move the chair away” example doesn’t work is because parts of things have to be…part of the thing, so they need the same location.

2 Likes

Thank you! I’m gonna experiment with this a bit later and see if it matches my use case for how I want to implement actions for desks. My guess is that it should probably work, but I will have to try it out first to make sure. If it does, I will mark your comment as the solution.

One other question: is it at all possible to make it such that creates an object as a desk automatically creates it as a seated-desk? I would ideally like for no desks to be able to exist that aren’t standing-desks or seated-desks, and I would like desks to have seats by default. If this isn’t possible, then I will just write the rest of my story being more specific, but I’d certainly rather declare the kind such that the default behavior avoids future problems over forgetfulness.

A desk can be seated or standing. A desk is usually seated.

Different setup (properties instead of kinds) but it does more or less the same thing.

@Hidnook But in this case, would it be possible to only give a seat to a seated desk?

Sorry, I should’ve been more specific. Something like this:

A desk is a kind of supporter. 
A desk can be seatful or seatless. A desk is usually seatful.

A chair is a kind of enterable supporter. 
A chair is part of every desk.

TESTROOM is a room.

SEATDESK is a seatful desk in TESTROOM.
STANDINGDESK is a seatless desk in TESTROOM.

When play begins:
	repeat with D running through seatless desks:
		let C be a random chair which is part of D;
		now C is nowhere;
		say "[D]'s chair has been removed."

---

> showme
TESTROOM - room
    yourself - person
    SEATDESK - desk
        SEATDESK's chair (part of SEATDESK) - chair
    STANDINGDESK - desk

(I went back to seatless/seatful because it doesn’t sound like a verb.)

2 Likes

I’m not sure I understand; the names are just arbitrary – you can call them anything you like. If you want desks to default to having chairs, just change around the names in my example. The point is, if you want a kind that almost always has a part, the easiest way to do it is create a kind that always has that part and create a different kind that doesn’t. Yes, (as @Hidnook was showing as I was typing) you could just create all desks with chairs and then create a “when play begins” rule to remove certain chairs. However, I would argue that this method is wasteful in terms of memory (not really a big deal) and prone to programming errors (bigger deal).

It sounds to me like you’re getting hung up on the whole kinds thing and their overall usefulness in Inform programming. My strategy here would be to figure out what kind I’m using the most of in my game. (In yours, it sounds like “desk with an included chair.”) I would call that kind “desk” since it’s short. Then I would create another kind of enterable supporter called something else. Whether or not you make both of those as subkinds of supporter or subkinds of some sort of “master desk” kind will depend upon the number of properties all the “desks” in your world share. For example, if every desk has properties like “material,” “height,” “age,” or whatever, you might want to create a “master desk” (call it whatever you want) that has all those properties and then the two desk subkinds (w/ and w/out chairs) as subkind of that kind. This will save some typing.

2 Likes

I think the correct answer here is to for the seatless desk to be a different kind. Like, a seatful desk is a kind of desk. a chair is part of every seatful desk.

1 Like

Thank you @BadParser @Hidnook @Celtic_Minstrel ! Just as an update, I ended up figuring out the following:

A chair is a kind of enterable supporter.

An idesk is a kind of supporter.
Seatfulness is a kind of value. The seatfulnesses are seatful and seatless.
Every idesk has a seatfulness. An idesk is usually seatless.
After printing the name of an idesk:
	say " ([seatfulness])".

A desk is a kind of idesk. A chair (called its seat) is usually a part of every desk.
A desk is always seatful.

A standdesk is a kind of idesk.

TESTROOM is a room.
In TESTROOM is a desk called SEATDESK.
In TESTROOM is a standdesk called STANDINGDESK.
In TESTROOM is an idesk called INTERFACEDESK.

-----------------------------------------------

>showme
TESTROOM - room
    yourself - person
    SEATDESK (seatful) - desk
        SEATDESK's seat (part of SEATDESK (seatful)) - chair
    STANDINGDESK (seatless) - standdesk
    INTERFACEDESK (seatless) - idesk

This gives me a few different advantages:

  1. Because (as BadParser suggested) I have named the seatful desk as “desk”, this will automatically be the default behavior
  2. I also have the standdesk kind available for me for situations where I want that
  3. By defining the seatful/seatless property, instead of writing logic based on whether or not something is a desk/standdesk, I can just use the property. Any idesk declared directly is automatically counted as seatless, so it isn’t excluded in the logic.
  4. By defining the property as a kind of value, I can use it in a text substitution, rather than creating a more elaborate if/otherwise setup. To be honest, this part I will probably not actually use in the situation I am actually trying to write, but it was still good to test it out for practice.

Thank you all so much! I appreciate your prompt replies.

It’s funny, but I was going to warn you above not to do that. Creating a property for something which is derived from some other determined condition almost always leads to problems later. A calculated value (like a definition) should be used instead. Now in your case, this will probably won’t matter. If your are only declaring the seatfulness when you create the object and never plan on changing it, you should be fine (other than adding a redundant property to all of your idesks).

But, if six months from now, you decide it would be a cool puzzle to have a desk with a chair that can be broken off by the player, and forget that you need to change the seatfulness when that happens, your game might misbehave. This is a common mistake in Inform (7): an author creates a property to track some condition and then writes code that – instead of checking that condition – checks the property, which has in the meantime fallen “out-of-sync” with the condition it’s supposed to be tracking, leading to weirdness.

Sorry if that’s confusing, but I’ve seen this happen so many times here, I just couldn’t let it go. I would recommend getting rid of the kind of value/property for seatfulness and instead do this:

Definition: An idesk is seatful rather than seatless if a seat is part of it.

Don’t get me wrong, I love using new KOVs, just not here. If you need to say the seatfulness for some reason:

To say seatfulness of (T - a thing):
	if T is seatful, say "seatful";
	otherwise say "seatless".

After printing the name of an idesk:
	say " ([seatfulness of the item described])".
3 Likes

This is incredibly helpful advice thank you! I literally just finished implementing actions for redirecting entering or sitting on/at a desk towards its seat, and I was about to take a look at how I might remove a seat from a desk. I will definitely keep in mind this “out-of-sync” issue as I continue to move forward with I7.

1 Like