Let's Play/Read: Inform 7 manuals (Done for now)

I’ve seen different names for these object properties. I think these are called attributes in Inform 6. I think of them as flags or boolean properties. Inform 7 programmer’s Manual refers to them as boolean adjectives.

Inform 7 adds a feature where you can name both the set and unset versions of these either/or properties, for example locked and unlocked. If you can’t think of a good “opposite name”, you can just prepend a not in front of it, for example: the opposite of portable is both not portable and fixed in place.

Side note: in other programming languages, programmers typically slap an “is” on the front and give them names like isOpen and, in Lisp languages, programmers typically put a question mark on the end and name them like this: open?. The value,true or false, is answering the question posed by the name.

1 Like

Agreed. There is a real art to creating room descriptions and the subsequent scenery descriptions they beget. It can also be tricky naming things and understand-ing everything so they don’t conflict with portable objects, and each other.

As a completist, I sometimes find myself going down some deep examine rabbit holes as I keep introducing new nouns into each level of the descriptions I write. I have to watch myself.

I also try to make my portable object have completely different names from the scenery to avoid ambiguity problems but if I have a room with a river, for example, and the player grabs some water in a bucket, “water” is going to create some ambiguity trouble.

I also try to keep track of all of the nouns I introduce as I am writing description so my understand assertions cover them, but I have found it easier just to cut the fat and get rid of as many nouns as I can if they don’t add anything to the story.

Update: Okay, apparently, posters are limited to five replies in a row in a given post unless someone replies to a reply? I’m getting an error message about something like that, had no idea there was a limit. Anyway, I don’t feel like figuring it all out and I don’t really want to consolidate all of my postings, so I will stop here. Thanks for the posting, though, very useful stuff!

People had the manual in their heads as a whole when the topic was new (well, I did) and now they don’t (well, I don’t!), making it more work to interact. Nevertheless, I’m going to use my awesome forum power of not being you, to reply to you, to allow you to post more if you should so desire. Probably with continued expectation of a low reply rate.

-Wade

2 Likes

Yes, in general it’s better to make one reply than many in a row. You can quote multiple posts/people in one post, so you don’t need to reply once per post you’re responding to.

2 Likes

I still have confusion around degrees of certainty. I use usually as a good way to initialize a value that varies (i.e. variable):

txt is some text that varies.
txt is usually "foo".

However, I naïvely believed that always could set up a text (i.e. string) constant and learned otherwise after attempting to compile:

txt is some text that varies.
txt is always "foo".

Problem. You wrote 'txt is always "foo"' : but a variable can only be given its value straightforwardly or qualified by 'usually', not with 'always', 'seldom' or 'never'.

Which, of course, makes perfect sense because the text either varies or is always constant. Can’t be both. The compiler error also saved me the trouble of testing this with never – a strange concept, a string that will never contain a unique sequence of characters – and I have no idea what seldom would even mean in this context.

Eventually, I did find the way to declare and implement a constant, which does utilize always:

txt is always "foo".

And, yes, the purpose of using always in this way is both to prevent the programmer, via a compiler error, from overwriting a value they shouldn’t overwrite, and also to have a single place to change the constant values littered throughout your code. The same reasons that programmers use constants in other languages.

Except…that’s not how always always works. If a value is owned by another thing (I think?) it doesn’t act the same way. I found out about this difference after I was experimenting with degrees of certainty and I filed this bug: Log in with Atlassian account.

always refers to what the value is across owners, not across time. This code will not throw a compiler error and will happily change the always value:

The lab is a room.

The lab has a number called the bar. The bar of the lab is always 42.

Fooing is an action applying to nothing.
Understand "foo" as fooing.
Instead of fooing:
	showme the bar of the lab;
	now the bar of the lab is 1;
	showme the bar of the lab.

Test me with "foo".

So, I guess you could say that my degree of certainty about degrees of certainty is somewhat uncertain. But, hopefully, my mistakes will help others and I did find two ways (stated above) in which degrees of certainty can be very useful.

3 Likes

You have diagnosed this correctly. “Always” for properties has a different meaning than “always” for global variables. (See chapter 4.3 vs chapter 4.13.)

This is confusing, but I can’t remember anybody noticing it before, so maybe it’s not that confusing? Worth a note in 4.3, although I guess changing properties isn’t introduced until chapter 8 so it might be confusing either way.

My recollection is that the idea of global constants wasn’t invented until well after the properties meaning of “always” was settled. We failed to go back and think about the implications for the earlier concept.

3 Likes

Also it’s worth saying that the property usage (4.3) is meant for kinds, not individual objects. It says that you can’t define an instance of that kind with a different starting value.

So writing “The bar of the lab is always 42,” where the lab is an individual object (room), has no effect at all.

3 Likes

Yeah, it all comes down to combining a number and a unit into a single type. I think I am hyper-aware of this distinction because of my background in healthcare software development, where we do unit conversion acrobatics all of the time. It is a very common data type in that context.

But have I ever come up with a scenario where I would use this in IF? Not yet. I also haven’t ever used the Metric Units or Approximate Metric Units extensions. Would be a great piece of functionality for educating kids on unit conversion though, which is, by far, the most useful skill I picked up in my high school chemistry class :slight_smile:

What is the proper term for the result of instantiating a Kind in Inform 7? An object? An instance? I completely understand why you used the phrase “Single things” and I know you didn’t mean an instance of the Thing Kind and it all made me realize I don’t know what these “single things” are actually called.

Regardless, this is a really nice way of specializing a single instance instead of assigning a property to every single instance of a given Kind.

Inform’s not big on formalizing terminology, to our detriment, I think. Certainly, one could correctly call the umbrella a thing or an object. I’d say that, sure, instance works, too; we do see instance in WI 12.3:

In fact, an action can be carried out by anybody - by any instance of the “person” kind, that is, which includes all the men, women and animals in the story, and not only the player.

…but it’s not especially standard in the Inform world.

4 Likes

It is at this point of the manual that I usually gloss over because I am confused by this concept. But this is all about really reading and understanding everything in the manual, so I am going to dig deeper this time. Fair warning, it’s pretty detailed and probably of absolutely no use to anyone but I did make myself a promise that I would really understand this stuff this time around.

I understand kinds of values or named values or enumerated values, because it is a common programming idea. But when we start talking about assigning properties to enumerated values, the lines between “object” and “value” start to blur for me. As Inform 7 for Programmers puts it:

Named values can be used almost anywhere an object can. Plus there’s a few phrases with named values can used but objects can’t, since multiple object instances don’t have any sort of ordering to them.

Side Note: Yes, enumerated values have order, if you need it, but I like them even more because they allow me to assign human-readable names to much less human-readable numbers that the computer understands. In fact, without actually understanding how they work under the hood, I think of them as arrays with nice constant names, so I can write something similar to rainbow_colors[ORANGE] instead of rainbow_colors[2], where I don’t have to remember if I started my ROY G BIV ordering at zero or at one. I just know the relative ordering.

The phrase that really interests me here, though, is “Named values can be used almost anywhere an object can.”. So, if values can have properties and can be used in many places that objects can be used, besides the ordering, how are they different from objects? And where do they “live” in the game?

Objects live in the object tree. I know because I can see them when I compile the follow code:

Lab is a room.

Brightness is a kind of value.
The brightnesses are guttering, weak, radiant and blazing.

A lantern is in the lab.
The lantern has a brightness.
The lantern is blazing.

And then I type tree:

>tree
(Compass object) (546490) 
  the north
  the northeast
  the northwest
  the south
  the southeast
  the southwest
  the east
  the west
  the up
  the down
  the inside
  the outside
(thedark object) (546522) 
(VPH_25) (546554) 
(VPH_2) (546586) 
Lab (547034) 
  yourself
  a lantern

There’s my compass object (it’s a pretty long print out so I won’t include it in subsequent examples), the dark room object, a couple of internal objects I’m not going to worry about right now (although if someone knows what they are I would appreciate a reply just for my own info), the Lab, my PC and the lantern.

Some of these objects have names that the player can refer to in the command parser, like yourself (i.e. x me) and the lantern (i.e. x lantern) and even the compass directions (i.e. x north). But not the (Compass Object) or (thedark object) or the VPH objects. Those are internal objects the player never directly interacts with.

I don’t see my brightness enumerated value there, nor would I expect to. It hasn’t been instantiated, it’s not an object in the game world and I don’t expect the player to be able to refer to brightness from the command line. But I can see it in the Kinds index:

Screenshot 2024-03-02 at 6.21.29 AM

Now let’s add a few lines of code:

Lab is a room.

Brightness is a kind of value.
The brightnesses are guttering, weak, radiant and blazing.

the-light is a brightness that varies.
the-light is initially weak.

A lantern is in the lab.
The lantern has a brightness.
The lantern is blazing.

Fooing is an action applying to nothing.
Understand "foo" as fooing.
Instead of fooing:
	showme the lantern;
	showme the-light.

I introduced a testing command foo and a new instance of the brightness kind, called the-light, but it still isn’t an object in the world, as you can see by typing tree:

(...)
(thedark object) (546846) 
(VPH_25) (546878) 
(VPH_2) (546910) 
Lab (547358) 
  yourself
  a lantern

So, again, everything is acting the way I would expect. But where is the-light “living” in the game when I run this? Let’s see what my testing command has to say about it:

>foo
thing: lantern
"the-light" = brightness: weak

Not much, other than it does exist and is of the brightness Kind. I imagine it is in some sort of global variable space, separate from the object tree, based on the little I read about how Inform 6 works. Can someone clarify this for me?

Okay, I am going to finally get back to my original point of confusion. I am going to assign an either/or property to my value:

Lab is a room.

Brightness is a kind of value.
The brightnesses are guttering, weak, radiant and blazing.

A brightness can be adequate or inadequate.
A brightness is usually adequate.
Guttering is inadequate.

the-light is a brightness that varies.
the-light is initially weak.

A lantern is in the lab.
The lantern has a brightness.
The lantern is blazing.

Fooing is an action applying to nothing.
Understand "foo" as fooing.
Instead of fooing:
	showme the lantern;
	showme the-light.

I saw something different in the tree this time:

(...)
(thedark object) (547421) 
(VPH_25) (547453) 
(VPH_2) (547485) 
(VPH_23) (547517) 
Lab (547965) 
  yourself
  a lantern

A new VPH_23 object? Did adding the property to the enumerated value just turn the-light into an object in the object tree? Maybe the line between values and objects is even blurrier than I initially imagined? Does anyone know why this happened? Or what this VPH_23 object is?

1 Like

Sounds good to me. I’m going to continue to use “instance” then, to avoid ambiguities in my future posts.

1 Like

You can think of it as syntactic sugar around something like…

Exactly this. Giving properties to colors is effectively making an array indexed by the color—this is exactly why you can give properties to enumerated kinds of value but not numerical kinds of value (i.e. you can’t attach properties to ints or floats), because that would require an impractically large array.

In other words, “a color has a number called hue” and “the hue of red” is the equivalent of int hue[N_COLORS]; and hue[RED].

(This is, in fact, pretty close to how properties of objects work too. In a language like C, there’s a big difference between a struct and a global array: you can make new structs on the stack or the heap and pass them around. In Inform, by default, you can’t do that. The number of objects is known at compile-time. So some properties are actually part of the memory block that the “object” points to, and some of them are stored in big arrays indexed by the “object”, and the I7 user never has to know or care which is which. Relations and route-finding things especially use the “big array” approach.)

2 Likes

From an I7 vantage point, enumerated kinds of value are kinda like objects, but each kind of EKoV is its own class, with no possible sub-classing.

Named values can be used almost anywhere an object can.

The differences are chiefly described in WI 11.18.

Then there are a bunch of grotty differences in the details…

  • pathfinding only works for relations of objects
  • only objects can be in scope… but EKoVs can be used as tokens. So in terms of how the parser deals with stuff, the granularity of objects is on a per-object basis, but for EKoVs it’s per-class – the parser will either accept any value of that EKoV in a given place or none of them
  • an action can act on multiple objects, but not multiple values of some EKoV
  • to act on an EKoV, an action specification can and must specify that EKoV; in 10.1 and earlier, to act on an object, you must say thing which means… object. In the forthcoming v11, you’ll be able to name a particular subkind of object… except that thing will continue to mean any object for backwards compatibility
  • a bunch of obvious things like that the spatial relations are relations of objects, so only objects can be in the game world
  • some less obvious things like the indefinite article machinery only works with objects

I’m sure the above is incomplete.

Edited to add: Thought of another. Actions can apply to nothing, or to one thing, or to one thing and one non-thing (whether EKov, number, topic, whatever), or to two things, but they cannot apply to two non-things, thus, an action cannot apply to two EKoVs.

4 Likes

More specifically this is about a type of value called a sayable value. These are values that have some sort of text representation such that if you use a say phrase on them, something will print out:

say "[(sayable value)]"

Another type of value, enumerated value, was introduced in the previous chapter.

According to Inform 7 for Programmers, there are six different values, also known as generic types:

arithmetic value
pointer value
word value
sayable value
enumerated value
value

We haven’t yet encountered arithmetic or pointer or word values in this documentation, but I will be keeping my eye out for when they appear.

Arithmetic values do get documented (they’re sort of the opposite of enumerated values) but I don’t believe word values and pointer values are ever mentioned in the documentation. They don’t really matter in I7, only in I6—I7 works hard to avoid exposing them to the user directly.

3 Likes

I don’t think they exist in the current language at all.

POINTER_VALUE exists at the I6 level (it’s sort of the base type of “stored action”, etc). But you can’t refer to it in I7 as far as I know.

4 Likes

As valuable as Inform 7 for Programmers remains, it was last updated when 8.5/6G60 was current, and the subsequent version, 9.1/6L02 was significantly difference. See the 9.1 release notes and Updating Code Written for 6G60 in the I7 docs and resources post’s Miscellany section.

1 Like

Yeah, “description” is a bit of an overloaded word in Inform 7 because it can refer to both the description property of objects – which is really important for the content of your game world – as well as describing a list of data entities – also, an extremely important and powerful feature of Inform 7. Two very different, important pieces of Inform 7 with the same name.

I now think of this second type of description as a “set-description”, yet another name used in Inform 7 for Programmers. You provide one of these set-descriptions and it finds a list of zero or one or more data entities that fulfill those set-description requirements. I assume it is always an actual set that is returned – a list with no duplicates in it – but I don’t know if this is true or not.

If the game world is the database, then the set-description is the query language that allows you to pull together a precise of list of data (usually objects) for you to use. It’s like Inform 7 has its own little SQL relational database built right in.

1 Like

Yeah, I figured parts of Inform 7 for Programmers are outdated and I appreciate everyone helping me out, identifying those parts.

For me, Inform 7 for Programmers was the document that helped me finally start to really understand Inform 7, outdated or not. So, I am glad to continue referring to it and to also getting everyone’s valuable feedback on those references as well. Sort of like getting two manual reviews in one :slight_smile: .