Inform7/10 Reference Manual

Welcome to my world.

Not sure what you’re saying here. Could you give an example, please?

when <specific-scene> begins and when <specific-scene> ends are conventional rulebooks, but they’re created by the compiler. And, counter-intuitively, they’re not scene-based: they’re the default, action-based. Their associated scene is baked into the rulebook’s identity itself so it doesn’t need it as a parameter.

A bit of syntactic sugare I like for scenes:

During is a scene based rulebook.

This is the during stage rule:
  repeat with sc running through scenes begin;
    if sc is not happening, next;
    follow the during rules for sc;
  end repeat.

The during stage rule is listed before the every turn stage rule in the turn sequence rules.

During entire game: say "this rule is going to get annoying fast."

Here’s my organizing scheme for talking about these things:

An inform program is a series of assertions, optionally organized by sections (i.e., one of volume, book, part, chapter, section); these section headers aren’t assertions, per se.

Assertions are terminated by a . or by whitespace that includes two newlines (and, optionally, any number of .s or ;s so long as you don’t have both a . and ; on the same line, because that would be silly).

Specifying the title and/or author in the first line is syntactic sugar for one or both of these assertions:

The story title is "Work of Genius".
The story author is "Brilliant Writer".

There are three kinds of things that can take imperative code blocks: to-phrases, rules, definitions. The specification of each of these things is, itself, an assertion, but the code blocks themselves cannot include assertions. Code blocks are made of phrases, cannot have blank lines, and each phrase other than the last must end ;. The last phrase ends both itself and the assertion that is the definition of the imperative code block itself, thus may end ..

To-phrases, here, includes to say phrases, to decide if phrases, to decide what/which <kind> phrases.

at <time> or at the time when ... specify rules; they’re just a special-case of rules that don’t exist within a rulebook.

actions are a kind of value, the same kind of value named by stored action.

You can, though, say

The X rule does nothing when Y.

which is logically equivalent to adding when Y is not true preamble on the rule. (Yes, I know you’re concerned with syntax here.)

1 Like

The Standard Rules have the following definitions:

When scene begins is a scene based rulebook.
When scene ends is a scene based rulebook.

So that made me wonder what’s the difference between that and the “when «scene» begins” syntax. Thus, I tried doing both:

When entire game begins: do nothing.
When a recurring scene begins: do nothing.
When scene begins for entire game: do nothing.
When scene begins for a recurring scene: do nothing.

The first two use the special syntax. The second two are normal syntax for a scene based rulebook. After compiling, the Scenes Index shows four rules in the “when scene begins” rulebook.

The When entire game begins rule is missing however… that’s weird. I didn’t notice that last time. (One of the four “when scene begins” rules listed in the Scenes Index is defined in the Standard Rules, so only three of my four rules are there.)

Ah, looking closer, I found it listed further up under the description of the “Entire Game” scene. So maybe “When «scene name» begins” is somehow special, but “When «description of scenes» begins” seems to be the same as “When scene begins for «description of scenes»”. I don’t think scene ending options can be specified in the latter format though.

Yeah, I too was thinking along these lines. I don’t know of any assertions that can contain semicolons though? (I’m not counting what I call “phrasebooks” here.) But I’m thinking of pretty much everything else as an assertion, which means that everything in the source text is either an assertion, a phrasebook, or a section header. (Plus comments.)

Hmm, maybe that’s a good point, I could move those two into the rules section… it does feel a little silly having a separate section just for them.

I practically copy-pasted that list from the syntax document, but you have a good point. I’m not sure why that would be included under the non-kind parameter types.

1 Like

They (other than the assertions creating a definition, rule, or to-phrase) can’t contain them, but if an assertion is being terminated by whitespace-that-includes-two-newlines… well, this compiles.

The story author is "aoeuaoeu";;;;
;
;;;;

lab is a room.

Hunh, and this is a better way to have vertical whitespace within a code block than []:

This is the during stage rule:
  repeat with sc running through scenes begin;
;
    if sc is not happening, next;
;
    follow the during rules for sc;
  end repeat.

Can’t immediately follow the colon, though.

This isn’t true… it’s something closer to: anywhere you can have one semi-colon, you can have any number of them, and any place where you can have one period, you can have any number of them.

1 Like

one must be careful that [] being i7/10’s comment delimiter, one can surmise wrongly that ; is the comment-to-EOL… but OTOH, inform 7/10 is designed as NL for people with little or no programming experience, so the risk of confusing ; with the comment-to-EOL, typical of assembly coding, should be near-nil.

Best regards from Italy,
dott. Piergiorgio.

Hmmm… here’s another weird discovery. The compiler accepts “action”, “description of actions”, and “described action” as parameter types, but it’s not clear what it thinks a “description of actions” actually is. Meanwhile, “described action” doesn’t work, with an error message that seems to imply it fully understood it yet gave up anyway.

To attempt (A - action): try A.
To randomly attempt (A - description of actions): try a random A. [This compiles, but I don't know a way to actually call this phrase.]
To contemplate (A - described action): do nothing. [Not sure what can even be done with A here]

The kitten is an animal. The courtyard is a room. The kitten is in the courtyard.

When play begins:
	attempt taking the kitten;
	[both these lines give an error]
	randomly attempt doing something to the kitten;
	contemplate doing something to the kitten;
The full error messages:

Problem. You wrote ‘randomly attempt doing something to the kitten’, but ‘doing something to the kitten’ seems to be a described action, whereas I was expecting to find a description of actions there.

I was trying to match this phrase:

randomly attempt (doing something to the kitten - description of actions) :x:

I recognised:

doing something to the kitten = a described action


Problem. You wrote ‘contemplate doing something to the kitten’, but ‘doing something to the kitten’ seems to be a described action, whereas I was expecting to find a described action there.

I was trying to match this phrase:

contemplate (doing something to the kitten - described action) :x:

I recognised:

doing something to the kitten = a described action


Okay. I think I’ll post a few more snippets now.

Descriptions are used throughout the source text (in rule preambles and phrases) to refer to things based on their properties and relations. Ron Newcomb compares them to regular expressions, and indeed they are a form of pattern matching.

Descriptions of Values

A description of values takes on one of the following two general forms:

«indefinite pronoun» [«adjectives»] [( called «name» )] [that/which/who «verb» «description»]
[«determiner»] [«adjectives»] [«noun»] [( called «name» )] [that/which/who «verb» «description»]

The noun can be the name of a kind, or the name of a specific object. It’s more commonly the name of a kind. The verb for relative clauses can be any verb that means a relation or property, and is of course followed by a description of values pertaining to the type of the property or the other side of the relation. Since many relations relate objects to objects, this recursive definition allows the creation of very complex patterns.

The indefinite pronouns are as follows:

something/someone/somebody/somewhere
anything/anyone/anybody/anywhere
everything/everyone/everybody/everywhere
nothing/no-one/no one/nobody/nowhere

In rule preambles, only the first two rows are allowed, with any- forms being equivalent to the corresponding some- form. Each of the indefinite pronouns is equivalent to a determiner plus a noun. However, “any” as a determiner (eg “any container”) is not allowed in rule preambles, even though “any” as a determiner seems to essentially be a noise word that does nothing.

Indefinite pronoun meanings
Pronoun Meaning
something a thing
someone/somebody a person
somewhere a room
anything any thing
anyone/anybody any person
anywhere any room
everything every thing
everyone/everybody every person
everywhere every room
nothing no thing
no-one/no one/nobody no person
nowhere no room

Determiners are only allowed in a conditional context, not in rule preambles. The determiners are as follows:

any
each/every/all of
some of
most of
almost all of
no/none of
exactly «number»
[at least] «number»
at most «number»
fewer/less than «number»
more than «number»
all but/except «number»

Most of these have obvious meanings, but “some of”, “most of”, and “almost all of” aren’t so clear. They mean “at least one”, “more than half”, and “at least 80%”, respectively.

Although descriptions of values are most commonly seen with subkinds of objects, with descriptions of enumerated values being the next most common, they can be used on other kinds as well. For example, “an even number” is a description of numbers, and “a one-to-one relation” is a description of relations.

Unlike in assertions, a string of adjectives in a description may not be separated by commas. You can write “a fixed in place open container” but not “a fixed in place, open container”.

Descriptions of Actions

Action descriptions (or “described actions” as the compiler calls them) can get quite complex. The general form is as follows – since it’s quite long, it has been split across several lines:

[«actor»] «action list» [«description of objects»]
[«action preposition» «description of objects»]
[«action variable preposition» «description of values»]+
[in «description of rooms»]
[in the presence of «description of objects»]
[when/while «condition»]
[«recurrence condition» | «duration condition»]

The optional initial «actor» specifies who is doing the action (the actor) and whether it is requested. If omitted entirely, it means the player is doing the action. It can take one of the following possible forms:

«description of objects» [trying]
asking «description of objects» to try
an actor [trying]

The first form matches if the actor fits the description, but never matches when the actor is the player. The optional word “trying” is used for disambiguation, in case the last word of the description looks like an action participle. The second form matches if the player is requesting the action and the person asked fits the description. The third form matches any actor at all, but I believe it does not match requested actions. It must be the exact words “an actor” – if you write “actor” or “the actor” it will not work. I’m pretty sure there’s no reason to ever use “an actor trying”, but it does compile.

The «action list» can take the following possible forms, where «action» is either an action name preamble (the part before “it”, if the name contains “it”; otherwise the full name) or a named behaviour (also called a kind of action).

«action» [ (, | or | , or) «action»]+
doing something/anything [to/with]
doing it
doing something/anything (except | other than) «action» [, «action»]+ [ [,] or «action»] [to/with]

The special form “doing it” would more naturally be written as “doing so”, but unfortunately the compiler doesn’t understand the latter. In a rule preamble, it means the action described in the previously-declared rule, including its noun specifications (so adding noun specifications is not allowed in this form). I haven’t tested if this works similarly within a phrasebook.

The second form is a wildcard, matching anything at all. The last form is also essentially a wildcard, but a restricted one.

Specifying the noun and the second noun is done with a normal description of values. The “action preposition” used to introduce the second noun is part of the action name, the part that comes after “it”. When there are multiple actions, it must be the action preposition of the final action in the list. For example, “putting or inserting something into something” is correct, and “inserting or putting something on something” is correct, but “putting or inserting something on something” and “inserting or putting something into something” won’t work.

In both of the “doing something” forms, you can only specify the first noun as part of the description (the only way to constrain the second noun is with a when/while condition). Use of the preposition “to” or “with” when “doing something except” has a different effect than using no preposition. (This is mentioned in the documentation… I need to come up with a good example to illustrate it, because it’s a bit hard to describe.)

When using behaviours (kinds of action), you can’t specify the noun or second noun, because the behaviour could potentially contain various actions applying to various different nouns. You can mix behaviours and regular actions in a single description; I haven’t tested whether there’s any way to specify a noun or second noun just on the actions that aren’t behaviours.

Action variable clauses are introduced by the preposition defined for the specific action variable. Action variables without a “matched as” clause in their definition cannot be matched in action descriptions. After the preposition is a description of values matching the kind of the action variable, so it can be almost anything.

The location and presence clauses are pretty straightforward. The one thing you need to be careful about is that “in the presence of a person” will always match, because the player is a person and you are always in the presence of yourself. Thus you instead need “in the presence of a person who is not the player” or similar.

The conditional clause is just a regular condition. The one downside is that there’s no way to negate the entire condition, like “unless”.

The “recurrence clause” at the end is things like “for the first time”. The same clause can be used on a relation condition, so see the description of conditions for details of its format.

A description of actions is usually written in the present tense, but it can also be used in the past tense. In this case, just substitute the present participle with the corresponding past participle. Past tense descriptions are also more restricted – there can only be one action (“done something” is not supported), actions taking a second noun are not allowed, the first noun must be a specific object, and none of the optional clauses are permitted.

Composite Kinds

Kinds defined directly in the source text are simple kinds – they have a name, and that’s it. But Inform also understands a small number of composite kinds that can be built out of simple kinds.

Composite kinds have a concept of covariance and contravariance. Put simply, suppose you have a variable of a composite kind built out of a simple kind K. If the composite is covariant, that means that a composite built from a more specific type can be assigned to the variable. If the composite is contravariant, that means a composite built from a less specific type can be assigned to the variable.

For example, lists are covariant, which means you can assign a list of doors to a list of things variable, but you can’t assign a list of objects. On the other hand, activities are contravariant, so if you have an activity on things variable, you can’t assign it an activity on doors… but you can assign it an activity on objects, because an object is less specific than a thing.

The following is a full list of composite kinds that can be created:

list of «kind»
activity on «kind»
description of «kind»
«kind» valued property
«kind» valued table column
relation of «kind»
relation of «kind» to kind
nothing based rule/rulebook
nothing based rule/rulebook producing «kind»
«kind» based rule/rulebook
«kind» based rule/rulebook producing «kind»
phrase nothing -> nothing
phrase «kind» -> nothing
phrase nothing -> «kind»
phrase «kind» -> «kind»
phrase ( «kind» (, «kind»)+ ) -> nothing
phrase ( «kind» (, «kind»)+ ) -> «kind»

Lists, descriptions, properties, table columns, and relations are covariant, while activities are contravariant. Rules and phrases are a bit more complicated. A rule or rulebook is contravariant in its basis, but covariant in its production. Similarly, a phrase is contravariant in its parameters, but covariant in its return value.

I have not yet investigated how “nothing” fits into the co(ntra)variance system. As far as I’m aware, phrases need to at least have the same number of parameters, but I have not investigated that in detail, either.

Conditions

A condition (the text you write after “if”, “unless”, “when”, or “while”) can come in several different forms:

«conditional phrase»
[we are] [not] «description of action»
we have [not] «description of action in past tense»
«description of value» «relation verb» «description of values» [ «recurrence condition» | «duration condition» ]
«condition» and «condition»
«condition» or «condition»
( «condition» )

A conditional phrase refers to any phrase defined by “To decide if/whether”. There is no general way to negate a condition. Conditional phrases often (but not always) define a negated form of the phrase, however; and action and relation conditions have a built-in way to negate them.

Action conditions in the present can optionally take a “we are” prefix only when the action description doesn’t specify the actor. It is allowed for “asking to try” however. Action conditions that do specify the actor will usually need to add “trying” to disambiguate.

The most common relation verb used is “to be”, but any relation verb works in a condition as far as I know. The verb can be conjugated into simple/perfect, present/past, and positive/negative. The possible forms are as follows (using “to unlock” as an example):

Form Normal verb to be to be able to
Positive simple present unlock/unlocks is/are can
Negative simple present do/does not unlock is/are not cannot
Positive simple past unlocked was could
Negative simple past did not unlock was not could not
Positive perfect present has unlocked has been has been able to
Negative perfect present has not unlocked has not been has not been able to
Positive perfect past had unlocked had been had been able to
Negative perfect past had not unlocked had not been had not been able to

A recurrence condition can take the following forms:

once/twice/thrice
[for] «number» time/times
for at least/most «number» time/times
for «number» to «number» time/times

Keep in mind that «number» can be either a cardinal or ordinal number, so for example line 2 above covers both “for five times” and “for the fifth time”, which are equivalent.

These all match non-consecutive actions, simply counting how many times the action has been attempted . It counts unsuccessful attempts as well, so it’s best to use such clauses only in Before rules or occasionally in Persuasion or Instead rules. Every turn rules should also be safe.

A duration condition can take the following forms:

for «number» turn/turns
for at least/most «number» turn/turns
for «number» to «number» turn/turns

These all match consecutive actions, as if an implicit “in a row” were appended. (However, it’s not valid to explicitly add “in a row” on the end.) Though ordinals are technically supported here, I think it makes it sound misleading and would recommend cardinals only. (Would you guess without being told that “Before jumping for the fourth turn” triggers when you jump four times in a row?)

1 Like

You have passed through the third gate, and there is nothing left but for you to read the literate source: Action Patterns.

And may Knuth have mercy on your soul.

No, wait, there’s one thing left… be sure to read this reply regarding Action Patterns too.

2 Likes

To be perfectly honest, I don’t find that to be very useful. It’s good to see it, and it’s not like it’s too technical for me or anything, but it’s mostly just showing code with some brief, terse comments, and the code itself is fairly cryptic.

I actually saw that post already. It was pretty helpful and probably influenced my explanation of action patterns.


I’m planning to post an attempt at “every possible assertion that can be made” next, though I still haven’t finished compiling the list so I’m not sure when that’ll be. I might post something else in the meantime if it takes awhile.

I also just discovered (maybe rediscovered?) the haphazard attempt at a “sentence grammar” in example 223 (§13.9). I’m not sure to what extent that’ll influence my overview of assertions though; it’s perhaps a little too general to be broadly useful (as it rolls assertions, conditions, and now-conditions into a single category). It also seems like it might be incomplete – I’m not sure how “west of X is south of Y” would fit into that grammar, assuming that “west of” and “south of” count as prepositions. Plus it only covers simple sentences, and most assertions outside of basic structural sentences have special syntaxes that don’t fit well into that grammar.

It is a little frustrating how many cases there are that seem like they should work but don’t. Things like “when we have taken or dropped X” and “if we have taken the noun” seem like they should be relatively simple to resolve, but the compiler just gives up. In the former case, it seems obvious to me that it should expand to “when we have taken X or we have dropped X”, and in the latter case, well… why on earth would you want to ask “if we have taken the global variable called noun”? That’s how the compiler interprets it, yet it has a much more sensible and logical interpretation of “if we have taken whatever object is currently stored in the noun” that seems like it should be easy to check.

Graham needs a lesson on responsive web design.

1 Like

It is sensible to consider sentences in assertions, conditions, and imperatives as a single category. These are excerpts from the rules:

To if (c - condition) begin -- end conditional
        (documented at ph_if):
        (- {c}  -).
[...]
To now (cn - condition)
        (documented at ph_now):
        (- {cn} -).

Now there are verbs that mean different things in different contexts (to be, to have, to hold) and there are things that are semantically valid as one but not another (one of the most obvious being that only conditionals can have tenses other than present).

And it wouldn’t be Inform if there weren’t special cases. West of X is south of Y is an assertion but it isn’t really a sentence in the Example 223 sense because west of X and south of Y aren’t really description phrases.

To the extent there’s any documentation on this, it’s Mapping Hint Requests.

2 Likes

Hmm. Or it might be more accurate to say that they are sentences but that Example 223’s explanation of Description Phrases is lacking. I’m not sure.

1 Like

Okay, so now let’s talk about the syntax of assertions. First, before we get started, assertions and conditions both have something in common in their structure.

Generic Sentence Grammar As noted in §13.2, 90% of assertions can be boiled down to the following syntax:

«noun phrase» «verb» [«adverb»] «noun phrase»

Where the noun phrase looks something like this:

«adjective»* «noun»? «relative phrase»?

And the relative phrase looks something like this:

(«preposition» | «participle» | which/that «verb») «noun phrase»

Conditions also follow the same basic syntax. Note that all the components of the noun phrase are marked as optional, but that’s not quite accurate – you must have at least one component. Furthermore, some constructs are allowed only in certain contexts (only in assertions, or only in conditions). For example, “«relative phrase» «verb» «noun»” is not allowed as a condition, but is allowed as an assertion.

The verb is perhaps the most interesting part of this, because it can be put into several forms:

  • active or passive voice
  • positive or negative
  • past or present tense
  • simple or perfect
  • simple or progressive

Assertions however only allow the first two. They also allow simple or progressive tenses. Also, progressive seems to be unsupported in the passive voice and for the verbs to be and to be able to. Those two verbs also don’t support the passive voice. This kind of makes sense though, since most people wouldn’t use those forms anyway even if they are technically valid grammar.

I already posted a table of verb forms in the Conditions section, but that omitted progressive and passive forms, so here’s a more complete table. Or rather, three tables. I’m using the verb to carry as an example of a standard verb here.

Voice Tense Aspect Positive Form Negative Form
active present simple carries/carry do/does not carry
active present progressive is/are carrying is/are not carrying
active present perfect has/have carried has/have not carried
active present progressive perfect has/have been carrying has/have not been carrying
active past simple carried did not carry
active past progressive was carrying was not carrying
active past perfect had carried had not carried
active past progressive perfect had been carrying had not been carrying
passive present simple is/are carried by is/are not carried by
passive present perfect has/have been carried by has/have not been carried by
passive past simple was carried by was not carried by
passive past perfect had been carried by had not been carried by

Here’s the same table for to be, simplified to omit the unsupported forms:

Tense Aspect Positive Form Negative Form
present simple is/are is/are not
present perfect has/have been has/have not been
past simple was was not
past perfect had been had not been

And for to be able:

Tense Aspect Positive Form Negative Form
present simple can cannot
present perfect has been able to has not been able to
past simple could could not
past perfect had been able to had not been able to

Anyway, knowing the grammar at this generic level isn’t the most useful, so let’s go ahead and make a list of everything that you can assert. This means specifying which verb to use in most cases.

Structural Assertions

I’m defining “structural assertions” as ones that directly make a statement about the model world. They define the things that exist, and how they relate to each other.

Assertion sentences support the use of pronouns. They don’t have any concept of gender however – you can use him, her, or them if you want, but it’s no different from using it. All of these refer to the subject of the most recent sentence that had one. The pronoun here is also supported, and refers to the most recently defined room. That means you can write something like “the size of it is 21”. In fact, this is so common that you can omit “of it” entirely and just write “the size is 21”.

Anyway, let’s start with basic declarative assertions – those that explicitly define something in the world. These usually take forms like the following:

«name» is/are [«adjectives»] «kind».
There is/are [«number»] «kind» [called «name»].

Note: You can also write something like “The puddle is scenery” even though scenery is defined as an adjective and not a kind. I think this might be a special exception for scenery, but I haven’t investigated.

Those assertions aren’t particularly interesting. Most assertions specify a relation. Such assertions can take on a form like the following:

[«preposition»] «name» «verb» [«preposition»] «name» [called «name»]

That definition is perhaps a bit too abstract to be useful, so here are a bunch of examples:

Examples

The Harbour is south of the Shopping Mall.
The wood-slatted crate is in the Gazebo.
Mr Jones wears a top hat.
The crate contains a croquet mallet.
West of the Hadean Pits is the Elysian Fields.
On the table is a scrumptious meal.
Miss Felix is interested in Mr Jones.
Interested in videogames is Felix.
On the table is a thing.
Three things are in the box.
Miss Trombone hides the pencil.
On the table is a box called a bowl.
A supporter called a comfy armchair is in the lounge.
East of the Debris Room is nowhere.
West of Thames Street End is north of Fisher’s Row.
The attic is a dark room above the Parlour.
The sky is everywhere.

So the abstract definition could be broken down into the following (possibly incomplete) list of possibilities, most of them using the verb to be:

«room or door» is/are «direction» of «room or door».
«direction» of «room or door» is/are «room or door».
«direction» of «room or door» is/are «direction» of «room or door».
«direction» of «room or door» is/are nowhere.
Nowhere is «direction» of «room or door».
«noun» is/are «kind» «preposition» «noun».
«noun» «verb» «noun».
«noun» is/are «preposition» «noun».
«preposition» «noun» is/are «noun».
«preposition» «noun» is/are «kind» called «name».
«kind» called «name» «verb» «noun».
«backdrop» is/are everywhere.

That’s still pretty abstract, but in my opinion it does give a better idea of the kinds of things that are possible. Note in particular the case where it’s safe to put more than just a name after “called” – this will only work if there’s no other verb before “called” in the sentence. Also, consider a “preposition” here to be any sequence of words that could be placed after to be, so in particular, it could be a participle rather than an actual preposition, or it could be the passive voice.

For some further explanation, suppose you define the following verbs:

The verb to quark means the X relation.
The verb to be in front of means the Y relation.
The verb to be able to carp means the Z relation.

Now all the following sentence forms become viable as assertions:

thing A quarks thing B.
thing C is quarking thing D.
thing E is quarked by thing F.
quarked by thing G is thing H.
thing I is in front of thing J.
in front of thing K is thing L.
thing M can carp thing N.

Notice the apparent inconsistency that the passive voice is invertible but the progressive tense is not. Notice also that progressive is not supported for the verb to be, and to be able doesn’t appear to support even the passive.

The result of those statements, as shown by the relations command, is:

X relates various things to various things:
  Thing A  >=>  thing B
  Thing C  >=>  thing D
  Thing F  >=>  thing E
  Thing G  >=>  thing H
Y relates various things to various things:
  Thing I  >=>  thing J
  Thing L  >=>  thing K
Z relates various things to various things:
  Thing M  >=>  thing 

Relation assertions don’t just define a relation between two things. They can also implicitly define the things involved in the relation. For example, suppose “hides” is defined as meaning a relation applying to one person and one trinket. Then the statement “Miss Trombone hides the pencil” will also implicitly define Miss Trombone as a person and the pencil as a trinket. This also works for enumerated values instead of things; and if you use the name of a kind of object, it ends up creating an object that doesn’t have a name.

Note that a statement like “Three apples are in the box” won’t necessarily create three apples. If “apple” isn’t already defined as a kind, it will instead create a single thing called “Three apples”.

Next is property assertions – specifying that something has a particular property. These can take the following forms:

«noun» is/are «adjective».
«property» of «noun» is/are «value».
«noun» has/have «property» «value».

As a special case, you can write a quoted string as a sentence of its own, without any preamble. Usually, this is equivalent to setting the description property of the value or object currently referred to by the pronoun it. However, if the object in question is a non-scenery thing, it sets the initial appearance property instead. Note that this functionality is not limited to built-in objects (rooms, things, and scenes) – any value or object that can have a description will support this.

You can link multiple sentences together with and, as long as they have the same verb and either the same subject or the same object. That is, if you have sentences “X is Y” and “X is Z”, you can write them as one sentence, “X is Y and Z”. Similarly, if you have sentences “X is Z” and “Y is Z”, you can write them as one sentence, “X and Y are Z”. This may not work in every conceivable case though, and in particular should be avoided on sentences using called, as the compiler may interpret the and as part of the first object’s name instead.

Finally, it’s possible to mass-define things using a table. The syntax for that looks like this:

«kind» [«preposition» «noun»] is/are defined by «table name».

The optional preposition can specify a relation applied to every defined thing. It must be a various-to-one or various-to-various relation. This syntax works for kinds of objects and also for enumerated values.

I think there’s maybe something lacking in the above explanation. It really isn’t easy to just give a list of every possible format that an assertion can be expressed in, after all. The fact that you can invent arbitrary verbs to be used in sentences complicates things too.

Defining Kinds

Assertions can be used to define new kinds. The basic format for this is:

«name» is a kind of («base kind» | value).

The base kind can be either a previously-known kind of object (including object itself), or the special word value. You must define the base kind before you can define any subkinds. Note that kinds of value don’t have a tree, so this isn’t a consideration.

Usually Inform automatically guesses the correct plural form of a kind. However, you can override its guess as follows, or even define multiple plurals:

plural of «kind» is «plural kind».

By default, a custom kind of value is neither an enumerable nor an arithmetic value. However, such a kind cannot be used for anything, so to finish defining it you need to actually give it some values. There are two ways to do this. The first makes it a kind of enumerated value.

«name of kind of value» is/are «values».
«values» is/are «name of kind of value».

In fact, notice that declaring the values for an enumerated value is exactly identical to declaring the existence of an object. This means that any enumerated kind of value can be extended with additional values at the author’s convenience – there doesn’t appear to be any way to prevent this. (It is however disallowed for some built-in enumerated types, such as truth states.)

The second way is to make it an arithmetic kind. You can declare any number of formats for an arithmetic kind, but the first such declaration for any arithmetic kind cannot use the scaled up/down or equivalent to clauses (but scaled at is allowed, though mutually exclusive with with parts). This syntax is quite long, so I’ve split it across multiple lines.

«format specification»
[( [singular/plural] , [in «name»] )]
specify/specifies «kind of value»
[with parts «part specification» (, «part specification»)* |
scaled (at | up/down by) «number» | equivalent to «value of same kind»].

Format specifications are kind of really complicated, in that they can be almost anything imaginable – other than double quotes, there doesn’t seem to be any kind of restriction on the characters you can use in a format specification. Generally speaking, the specification will be broken down into sequences of digits and non-digits. Even a decimal point is treated as a non-digit, unless it’s followed by a zero, in which case it declares the type to be real-valued rather than integer-valued. (I_think_ that’s the rule, at least.) Similarly, if the first run of digits is preceded by a minus sign, it means you’re allowed to write negative values of the kind, but otherwise a minus sign is just treated as another character. The format specification can contain spaces but does not have to, so you can declare kinds with a compact specification like $99.99, or kinds that are written out in words like 99 feet 11 inches.

When breaking down the format specification, each run of non-digits is associated with the following run of digits as its preamble. Runs of digits after the first are also treated as limits on that component, so in the feet and inches example above it won’t let you set the inches to 12 or higher.

A format specification can be given a name with in (which enables you to convert values of this kind into this format for output) and can be declared to be either plural or singular. The plurality affects which form is chosen for saying values of this kind – it’ll choose a singular form if the value is 1 and a plural form otherwise (in English at least, I don’t know how that carries over to other languages).

The part specification can give a name to each of the components, and also set options for them. It’s a comma-separated list, each element of which looks like this:

«name» [( [[preamble] optional] , [without leading zeros] )]

If the segment is optional, it can be omitted entirely when writing values of that type. If the preamble is optional, both the segment and its preamble may be omitted. Without leading zeroes controls how the value is printed when the segment has fewer digits than the specification.

Lastly, by default it’s an error to multiply an arithmetic kind by anything other than a plain number, but you can specify how arithmetic kinds are multiplied together. At least one format specification must be defined before you can do this.

«kind» times «kind» specify/specifies «kind».

Note also that you can’t write “X divided by Y specifies Z”. Instead you have to rearrange it to write “Y times Z specifies X”.

You can define new properties for specific objects, kinds of object, or kinds of enumerated values. (Arithmetic values are not allowed to have properties.) This can be done using statements like the following:

«kind or value» can be [either] «adjective» [or «adjective»].
«kind or value» can be [either] «adjective» (([,] or | ,) «adjective»)+ [( this is its/her/his/their «name» property )].
«kind or value» has/have «kind» [called «name»].

The first form creates an either/or property. If the opposite is not specified, it defaults to prefixing not to the adjective. This form doesn’t necessarily need to define a new adjective – it can also be used to specify that an existing either/or adjective can be applied to the new kind. If the property already exists, you can use either the adjective or its opposite here, or you can use both; but specifying a different opposite from the already-existing one is not allowed.

The second form creates a new enumerated kind of value with the specified name (defaulting to suffixing condition to the name of the object or kind) and adds a property with the same name as the new kind. Though the syntax definition above doesn’t make this clear, it must have at least three alternatives. Also, the new kind can still be extended with additional possible values using separate assertions later on.

The third form creates a property of the specified kind with the specified name (defaulting to the same name as the property). Note that when a property has the same name as its kind, and the kind is an enumerated value, you can use the values of that kind as adjectives describing the object or value that has the property. However, if the property has a different name, you can’t use the values as adjectives.

You can control default values for properties or specify implications between either/or adjectives using statements like the following:

«kind or value» is/are «adverb» «adjective».
(«adjective» «kind» | «correlative pronoun» «adjective») is/are «adverb» «adjective».
«property name» of «kind or value» is/are «adverb» «value».
«kind or value» «adverb» «verb meaning a property» «value».

Correlative pronoun here refers to any of the pronouns beginning with “some” or “any”. The possible adverbs are:

usually/normally
seldom/rarely
always
never

But not all these adverbs are supported in every type of sentence, and in fact, only the first form (X is «adv» Y) supports all four. The second form (something X is «adv» Y) doesn’t support always or never, and the last two that work with arbitrary-valued properties only support usually/normally.

It’s possible to define a kind and give it properties in a single statement like this:

«name» is/are a kind of («base kind» | value) that/which is «adjective» (and «adjective»)*.
«name» is/are a kind of («base kind» | value) with «property name» «value» (and «property name» «value»)*.

Each of these rolls up three statements into a single sentence. If you write “X is a kind of Y that is Z”, it’s equivalent to the following three statements:

X is a kind of Y.
X can be Z.
X is usually Z.

Similarly, if you write “X is a kind of Y with Z W”, it’s equivalent to the following three statements, automatically inferring the kind of W:

X is a kind of Y.
X has a (kind of W) called Z.
The Z of X is usually W.

Defining a global variable looks a lot like a declaring an object, but with a few extra words:

«name» is/are «kind» (that varies | variable).
«name» is/are initially «value».

A variable previously defined using the first form can also be given an initial value without using the word initially.

You can also declare constants with a similar assertion:

«name» is always «value».

The word every can be added to a normal relation assertion (merging with correlative pronouns, if present, to become everything etc) to make a broad assertion about kinds. If both sides of the relation are a kind, this even implicitly defines instances of the kind on the opposite side as every so as to make the statement true – this is called “assembly”. The general form is like this:

(every «kind» | «universal pronoun») «verb» [«number»] «kind» [( called «name» )].
[«number»] «kind» [( called «name» )] «verb» (every «kind» | «universal pronoun»).
(every «kind» | «universal pronoun») «verb» «value».
«value» «verb» (every «kind» | «universal pronoun»).

The called clause, if present, generates names for the implicitly-defined objects, substituting any pronouns or possessive pronouns in the specified name with the name of the owning object, in the possessive if applicable. The supported pronouns are it, he, she, and they, together with their possessive forms. The called statement doesn’t work if you specify a number.

If you want, you can give names to Unicode characters. Usually this would be done by an extension though.

«name» translates into Unicode as «number».

This is pretty similar to the syntax to specify the I6 name of something.

«name» translates into I6 as «quoted I6 identifier».

I’m starting to wonder if this gets too wordy, but… I do think a lot of these quirks are better documented in-place rather than linking to the official documentation or something. Anyway, there’s still one more bundle of assertions to cover…

Defining Other Things

You can define new actions with the following syntax:

«name» is an action «action specification»

The action specification is a sequence of one or more of the following:

applying to nothing
applying to one [visible/touchable/carried] thing.
applying to two [visible/touchable/carried] things.
applying to one ([visible/touchable/carried] thing | «kind») and one ([visible/touchable/carried] thing | «kind»).
out of world
requiring light
with past participle «participle»

For obvious reasons, you can’t have more than one applying clause. Also, actions applying to two things must include the pronoun it somewhere in the middle of their name, which divides the name into two parts – the part after it is considered the preposition of the new action. Be careful – the compiler will accept a name ending in it, but it won’t be able to recognize the action in action descriptions, so this should be avoided.

Defining action variables looks almost exactly the same as defining properties:

«action name» action has «kind» called «name» [( matched as «quoted word» )].

The main differences are the matched as clause (which defines a preposition for matching this variable in action descriptions) and the fact that called is required.

You can group actions together as “behaviours” or “kinds of action”. The general pattern for this is as follows:

«description of action» is «behaviour name».

Such assertions for the same name are cumulative. The descriptions permitted for behaviours are a little limited – requested actions and actions with a specified actor (including an actor) can’t be added to behaviours.

A scene is just a regular enumerated value, so new scenes can be declared in the same way as other things. Specifying when they begin and end however use some special statements:

«scene» begins when «condition».
«scene» begins when play begins.
«scene begins when «scene» begins/ends.
«scene» ends [«ending name»] when «condition».
«scene» ends [«ending name»] when «scene» begins/ends.

A scene can have multiple begin conditions, but each ending can only be given a single condition. Fortunately, the when «condition» form is a full-fledged condition, so it can use and. It is possible to define a general (nameless) ending in addition to named endings; I’m not sure if this is useful however.

Relations can be defined as follows:

«name» relates various «kind» to various «kind» [with fast route-finding].
«name» relates one «kind» [( called «name» )] to various «kind» [with fast route-finding].
«name» relates various «kind» to one «kind» [( called «name» )] [with fast route-finding].
«name» relates one «kind» [( called «name» )] to one «kind».
«name» relates various «kind» to each other [with fast route-finding].
«name» relates one «kind» [( called «name» )] to another.
«name» relates one «kind» to another [( called «name» )].
«name» relates «kind» [( called «name» )] to kind.
«name» relates «kind» [( called «name» )] to «kind» [( called «name» )] when «condition».

The second-to-last form is particularly interesting in terms of whether Inform defaults to various or one. In fact, that relation will be one-to-various if a called clause is used and various-to-one otherwise. So it’s probably better to always specify whether each side is various or one. (I assume it’s also possible to omit one/various on one side but specify it on the other, but again, I wouldn’t recommend it.)

The form creating an equivalence relation (in groups) also accepts the with fast route-finding clause, but I think this is a mistake, as it doesn’t make sense to route-find through an equivalence relation (for any two things, there’s either no route at all, or a single-step route). Relations that don’t have various on at least one side will raise an error if you try to specify it.

It’s worth noting that a called clause in the definition of a non-calculated relation actually defines properties on the related kinds, which are automatically kept in sync with the relation. So, changing the relation updates the property and vice versa.

Verbs can be defined as follows:

To «verb» is a verb [( «conjugation» )].
The verb to «verb» [( «conjugation» )] means/implies ([reversed] «relation» | «property»).

Note that the name of a relation always ends in relation and the name of a property always ends in property. So, the second form will always end in one of those words. The first form defines a verb that is sayable but has no other meaning.

It’s also worth noting that defining a verb to mean a property also defines an implicit, nameless relation that automatically relates the holder of the property to its value, as if you had written something like the following:

My-property-relation relates a thing (called A) to a value (called B) when the «property-name» of A is B.

Despite not automatically defining them as verbs, Inform7 knows the conjugations of most English irregular verbs, so you usually don’t need to specify the conjugation manually. However, if you want to do so, it’s a comma-separated list of one or more of the following (I think they must also be in the specified order):

he/she/it «present singular»
they «present plural»
he/she/it «past»
he/she/it is «past participle»

I don’t think there’s any way to specify the present participle, probably because it’s always regular in English.

There are two special cases of verbs: to be, and to be able to. Inform7 has special handling for defining a verb that begins with either of those. It’s not permitted to specify the conjugation in this case.

If you define a verb beginning with to be (but not beginning with to be able to), then the sentence defines a preposition rather than a verb. Everything after to be in the definition becomes the preposition.

Similarly, if you define a verb beginning with to be able to, it’s defined not as a regular verb but as something that can follow can or could in a sentence.

You can create new rulebooks or activities with an assertion:

«name» rules/rulebook is/are «kind of rulebook».
«name» is/are «kind of activity».

This is pretty much a normal declaration, the only quirk being that the word something is treated specially in the name of an activity. Here a «kind of rulebook» or «kind of activity» uses the syntax explained in the Composite Kinds section.

Activities and rulebooks can both have semi-local variables. This looks exactly like adding a property to an object, except that the called part is required rather than optional:

«rulebook or activity» has/have «kind» called «name».

For rulebooks, you can specify the default outcome, or define a set of named outcomes. Both of these only work for rulebooks that don’t produce a value, with one exception – you can specify that a rulebook producing a value has default failure (or no outcome, which is the default anyway and thus redundant). (Though I say it’s not allowed, there’s a bug that the compiler allows you to do it anyway and then just does weird stuff at runtime, potentially even crashing.)

«rulebook» has/have default failure/success.
«rulebook» has/have default no outcome.
«rulebook» has/have outcomes «list of outcomes».

The list of outcomes is one or more of the following, joined by commas and/or and:

«name»
«name» ( success [- the default] )
«name» ( failure [- the default] )
«name» ( no outcome [- the default] )

Note that a named outcome corresponding to no outcome will never be treated as the outcome of a rulebook. Thus, it only serves to give a nicer name to the make no decision phrase when used in the rulebook in question.

I haven’t tested whether it works correctly to have multiple outcomes defined as failure.

Lastly, you can adjust the contents of an existing rulebook or conditionally control when rules trigger with statements like the following:

«rule» is listed [before/after «rule» | instead of «rule» | first/last] in «rulebook».
«rule» is not listed in («rulebook» | any rulebook).
«rule» (does nothing | substitutes for «rule») [when «condition»].

I think that pretty much covers every possible form of non-imperative assertion, and it really is a lot… but please let me know if you can think of something that I’ve forgotten. I’ll add imperative assertions (including Understand) in a later post.

1 Like

This looks good so far.

The general caveats, as I’m sure you’ve noticed, are:

  • Exactly what syntax are allowed and disallowed is pretty tightly tied to the underlying implementation. E.g. “Arithmetic values are not allowed to have properties” – because the implementation would require an extensible hash table or something like that, and Inform isn’t set up to do that. But it could. Similarly, the question of what kinds of relations are allowed grows directly from what mechanisms Inform has to store the data.

  • Because of that, any detailed syntax list is likely to change quite a bit from Inform version to version. This may not be obvious because we’re in an unusually extended period of stability. The transition from 9.3 to 10.1 was a low-level rewrite, so the user-facing syntax didn’t change much. (Aside from I6 inclusions.) But I would expect a fair number of changes when 10.2 hits.

  • (That’s a gut feeling. I haven’t gone over the Jira repository looking for what’s changed.)

Small comments:

You can also write something like “The puddle is scenery” even though scenery is defined as an adjective and not a kind. I think this might be a special exception for scenery, but I haven’t investigated.

Parallel to “The chest is open,” “The brass lamp is lit,” etc.

If you write “X is a kind of Y that is Z”, it’s equivalent to the following three statements:

I suspect there are lots of ways to combine assertions into a single sentence. But I prefer my Inform code to use the simplest sentences possible, so I haven’t explored this.

1 Like

Maybe I wasn’t quite clear. There is in fact a difference between “The puddle is scenery” and “The chest is open” – the latter will only work if Inform already knows what the chest is, while the former can be the line that defines the puddle – Inform infers it to be a thing.

You’re correct that they’re syntactically identical, though.

I find it a bit hard to imagine what the use-case would be for giving properties to an arithmetic value…

Hmm? Was there some kind of relation that’s not allowed? The options there seemed pretty comprehensive to me. Other than not being able to define new spatial relations, I guess.

Oh, whoops! I see what you mean.

The difference is that scenery is defined on things, and Inform is willing to assume that an unmentioned object is a thing. open is only defined on containers and supporters.

So you can say “The puddle is lit” or “The puddle is handled”, but not “The puddle is male” or “The puddle is openable.”

1 Like

Same as the use-case for defining relations on an arithmetic value. (Which you can do.) A property more or less is a various-to-one relation, although Inform doesn’t treat it that way.

Was there some kind of relation that’s not allowed?

Gah, I don’t know, I have never exhaustively dug unto relations. I may have been thinking of properties there.

“The puddle is fixed in place” in particular is relatively common and parallel to “the puddle is scenery”.

1 Like

Okay, so “puddle is lit” and “puddle is fixed in place” both compile. And so does this:

A thing can be current.
The puddle is current.

And this:

A thing can be current or obsolete.
The puddle is obsolete.

And even this:

A thing can be current, fading away, or obsolete.
The puddle is fading away.

And wow, even this!

A thing has a number called age.
The age of the puddle is 3.

So it’s not even limited to either/or properties – seems like any property on things will infer that something is a thing.

However, this doesn’t work, so it’s not a question of “is it the only kind the property can possible apply to”:

A container has a number called bulk capacity.
The bulk capacity of the trolley is 42.

I suspect it’s more that Inform automatically assumes that an unknown name is a thing, so if the property is one that applies to things, everything’s fine and it just sets it.

I assume you meant an enumerated value here?

Ah, that’s true, and Inform does in fact treat it that way if you use “called” in your relation definition or define a verb to mean a property (as mentioned in my assertions post).

Loving relates one number to various texts.
Hating relates various numbers to one text.

The verb to love means the loving relation.
The verb to hate means the hating relation.

2 loves "two".
2 loves "duo".
4 hates "four".

Why? I mean, why not? Values can have properties and relations. Numbers are values.

Oh, I missed that you said “relation” instead of “property” there.

I already covered the two biggest giants in Inform7 syntax, so in this post and the next big post I’ll go through all the bits and pieces I missed:

  • Headers
  • Literals
  • Comments
  • Asides
  • Punctuation and articles
  • Imperative assertions
  • Basic phrases

I think that should cover everything.

Headers

A header takes the following general form:

«level» «number» - «title» [( «special instruction» )]

The level is one of the following, ordered from highest to lowest:

  • Volume
  • Book
  • Part
  • Chapter
  • Section

The number doesn’t need to be an actual number, but I think it has to be a single word. A heading must be preceded and followed by a blank line. The title can be any text. I think it can even be omitted entirely along with the separating hyphen (and the number can similarly be omitted). Most special instructions are specified in parentheses, but there are some that can also be set off with an additional hyphen instead. I won’t note which ones those are. Though all three parts of the heading other than the level itself are optional, you must have at least one of them in order for it to count as a heading.

The special instruction can be any of the following:

unindexed
not for release
for release only
for use with «extension»
for use without «extension»
for «interpreter» only
not for «interpreter»
in place of «section» in «extension»

The «interpreter» can be either Z-machine or Glulx.

When using in place of, the section being replaced must be of the same level as the section replacing it, and the section name specified must be the full, exact name of the substituted section (probably including any special instructions). The section name can be enclosed in quotes to resolve ambiguity (needed if it contains the word in). When naming an extension, you must use the full, exact name of the extension and its author.

Other than headings, there are a few heading-like special syntax cases. The first is the story header:

«quoted title» by «optionally-quoted author»

This is syntax sugar for setting the variables story title and story author.

An extension must be bracketed by the following paired sentences:

[version «number» of] «extension name» by «author» begin/begins here.

«extension name» end/ends here.

Immediately following the extension opening sentence, there may be one or two paragraphs consisting of nothing but a single quoted string. The first is a short description of the extension’s content, known as the “rubric”, and should be formatted as a proper paragraph. The second text is intended as a way to provide credit to additional authors, and should be written in a way that makes sense when placed in parentheses after the extension’s name.

After the extension closing sentence, you may add an optional documentation section, introduced by a line exactly like this surrounded by blank lines:

---- DOCUMENTATION ----

Everything after the documentation header is treated as a comment. (However, actual comments are still parsed and thrown out, meaning they won’t appear in the generated documentation at all.) There are some special syntaxes used to control the format of the generated documentation.

First of all, any series of paragraphs indented by a single tab is treated as sample code, and will be formatted as such in the generated output.

Next, the documentation section has its own set of headings, which work sort of like the main source text headings in that they must be preceded and followed by a blank line. There are three types:

Chapter : «title»
Section : «title»
Example : (* | ** | *** | ****) «name» - «summary»

The asterisk(s) specify the example’s level. An example section should contain a complete code sample that can compile if copy-pasted into a fresh project, culminating with one or more test assertions that demonstrate the scenario. If there are multiple examples, they should be ordered by increasing level (number of asterisks).

An indented code sample can begin with the special syntax *: to request that a paste button be inserted. The paste button will paste the sample code from the point where *: is placed up until the end of the indented passage. Examples don’t automatically get a paste button, so one of these should generally be included at the top of each example.

Everything in the code sample must be indented in order for the paste button to work – unlike the examples in Writing with Inform, extension document doesn’t support any way to add commentary interspersed with the example code. You can add unindented commentary, but it will interrupt the operation of the paste button, so it’s best not to in most cases.

Literals

Inform7 supports three categories of literal values – quoted values (text and topics), arithmetic values (numbers, time, units, etc), and lists. Most other kinds, such as objects or enumerations have named values, which I’m not counting as literals. This includes the truth state type with its values true and false.

Arithmetic Literals

The number kind in Inform7 is what most other programming languages (and mathematicians for that matter) would refer to as integers. There isn’t really anything special about how they’re represented – just a sequence of digits, potentially preceded by a minus sign. The only unusual details are that numbers from zero to twelve can be written out in words, and that ordinal forms of the numbers can be used in some contexts (and again, first through twelfth can be written out in words). An ordinal is formed by adding the th suffix to the number, but it is purely sugar and has no actual effect on how the line is interpreted. However, it doesn’t seem to be allowed in static assertions.

Real numbers are represented very differently from most programming languages, but in a form that would be more familiar to a mathematician:

1.2345 x 10^26

The x can be either the letter X or an actual multiplication sign. Of course, the exponent can be omitted if not required for the range of number being represented. Inform predefines e and pi as constants, and also understands plus infinity and minus infinity.

Note: One thing to be wary of when working with numbers in Inform7 is that it does not honour standard rules of mathematical precedence and associativity when using mathematical operators in a phrase. If you have any math more complicated than basic addition or multiplication, it’s recommended to use an equation instead.

Any integer constant can be turned into a unicode character constant by simply prefixing the word unicode to it. This is still considered to be a constant and thus can be used in static assertions.

Custom arithmetic types can define arbitrary syntax around the core of what makes a number, using almost any combination of symbols or words imaginable. One such type is built-in – the time type, which can be expressed in the following ways:

«HH»:«MM» AM
«HH»:«MM» PM
«number» hours [«number» minutes]
«number» minutes

Quoted Literals

Most of the time, something enclosed in double quotes is text. The contents of text is usually literal, but there are three exceptions to this:

  • A literal apostrophe character is treated specially. Unless it’s both preceded and followed by a letter, it will be replaced by a double quote. You can explicitly specify an apostrophe where it would otherwise be replaced using ['] or [apostrophe]. Similarly, you can explicitly specify a double quote where it wouldn’t normally be inferred with [quote].
  • Any string ending with a literal period, exclamation mark, or question mark (., !, or ?) automatically has a line break appended. (Literal here means that it won’t occur if the period is present as a result of another substitution.) Take note that this doesn’t occur with other punctuation, such as an ellipsis (), though three successive dots of course does produce this behaviour (since that’s ending in a period). You can disable this behaviour by simply adding a space after the punctuation. If you want this behaviour when it wouldn’t be implicit (for example, after an ellipsis character), just add [line break].
  • Anything enclosed within square brackets is treated as a substitution. The syntax shown above used to work around the preceding two rules are just some basic examples of substitutions.

There are a few contexts where text is not allowed to have substitutions (with a special exception for [']). The story title is the primary one. Possibly it applies to all bibliographic information.

Substitutions can either be expressions that evaluate to a sayable value, or specially-defined say phrases.

The first type is already extremely versatile. Nearly all kinds of value are sayable in Inform7, including names of objects, values of enumerated kinds, and literal values. Any phrase that returns a value (ie, phrases defined with to decide which/what) can be used as a substitution. Conditional phrases can similarly be used, by converting the condition to a truth state value with the whether or not phrase. You can also use the names of properties without specifying the object you want to take the property from – in this case it infers you’re referring to a property of the item described.

And perhaps the most powerful type of value substitution in Inform7 is verbs. Verbs are treated as values in Inform7, and substituting a verb into text will automatically adapt the verb to the current story tense, story viewpoint, and current object being discussed[1]. Pronoun phrases and the special phrase regarding «something» updates said object in the middle of the text, and substituting the name of an object also automatically updates it.

Say phrases are extremely powerful, allowing you to do anything you want, even altering game state in response to text being printed. However, you must be careful if doing this, as text may be expanded for purposes other than printing. There is a conditional phrase to help with this. There are built-in say phrases for automatically substituting the right pronoun or article for a given context, and many other things as well.

There are several advanced types of substitutions where several square-bracketed sections work together in concert to produce the final result. These are called segmented substitutions. The simplest of these is the if/else substitution.


Usually, quoted passages are treated as text meant to be output to the screen and read by the player. However, in some contexts, quoted passages are instead treated as topics used to match the player’s input. In a topic, square brackets don’t mean substitution, but instead enclose either descriptions of values or specific matching tokens. There are only a small number of tokens available, though new ones can be defined as needed.

In addition to square bracket matching patterns, topics support two other syntaxes. The first is word alternations, which is a sequence of words separated by forward slashes, potentially ending in /--. This syntax within quoted topics has the exact same semantics as the same syntax used in defining phrases – it’ll match exactly one of the specified words, or possibly none if -- is included.

The second syntax is that two or more topics can be joined together with or to represent something that must match exactly one of the topics in question. This is sort of halfway between an expression and a value. It can be used in understand assertions and also in a table column called topic or explicitly declared as being of kind topic. It’s not allowed in general assertions or rulebook preambles. I’m not sure if it can be used anywhere else.

List Literals

List literals are, strangely enough, simpler to define than the other two types. They take the following form:

{ [«value» (, «value»)] }

A list literal can only contain constants, not variables.

Comments

Comments in Inform7 are probably one of the simplest parts of the language. Any text enclosed in square brackets ([]) outside of a quoted string is treated as a comment. Furthermore, comments can be nested – all open brackets encountered during the comment must be matched before the comment ends.

There is just one special syntax within comments, used when generating an HTML page displaying the source text. A comment beginning with * will be converted to a footnote on the resulting page.

Asides

I’m using the term “asides” for chunks of text set apart from the source text. There are either two or five types of asides, depending on how technical you want to get on the topic of what exactly constitutes an aside.

Tables

A table is a chunk of text set apart from the source text (with a blank line before and after it) which has the following overall line structure:

Table «table title» [( continued/amended )]
«optional blank line»
«table header row»
«table content row»*
[with «number» blank rows.]

The table title can take on one of the following forms:

«number»
of «name»
«number» - «name»

As with headers, the number need not be an actual number, but should be a single word. The third form is interesting in that it actually defines two separate names for the table – the table may henceforth be referred to either as “table «number»” or as “table of «name»”. Note that it may not be referred to as “table «number» - «name»”.

The optional parenthetical after the table title allows adjusting a previously declared table, either adding extra rows at the end or modifying previously-defined rows. When amending tables, Inform searches for a match based on the leftmost columns, one at a time, until the possible matches are narrowed down to a single row. It’s an error if no rows are matched, or if more than one row is matched. Columns used for matching are limited in the kinds they can contain. Enumerated values are allowed, as are most arithmetic values. The documentation doesn’t mention real numbers in the list of permitted values, which may mean that real-valued units are not allowed (I have not tested it). Activities, objects, and action names are also permitted.

The header and content rows both consist of tab-separated cells. The cells are separated by exactly one tab. The header and each content row must have the same number of cells, with the exception that content rows can omit trailing blank cells entirely (ie, not even adding the tabs as placeholders).

If using an IDE other than the official IDE, the fact that tables require exactly one tab between columns can be problematic, as few IDEs allow for elastic tabs as the official one does (though the official IDE’s elastic tabs are very buggy and only properly align the table about one-third of the time). Fortunately, spaces between table columns have no effect whatsoever on how the table is parsed, so it’s not hard to manually align a table by inserting an appropriate number of spaces before each of the column-separating tabs.

Each table header cell has the following form:

«name» [( «kind» )]

Each table content cell can take one of the following forms:

«value»
«kind»
--

The special syntax -- specifies a blank cell. Such a cell doesn’t even have the default value for the column’s kind – there’s nothing there at all. For those familiar with databases, you can think of it as a “null”. In some programming languages, this kind of situation is also called an “optional”.

Placing the name of a kind in a table cell is an alternative to specifying the kind after the name of the column. It’s only allowed in a column that’s blank (there are no values in any row) and even then only in the first row.

As long as a column contains at least one value, it’s generally not necessary to specify the kind of the column – it will be inferred from the value. Each cell in a given column must contain the same kind. Usually, quoted text is inferred as the text type, but an exception is made if the column is named topic – such a column is inferred as the topic type. You can also explicitly declare a differently-named column as a topic column, of course.

Defining a table also defines each of its columns as value of type “table column of kind K”. The practical outcome of this is that you can’t have two tables that have a column with the same name but a different type. If you do happen to declare a second table which reuses a column name, the type will be assumed to match that of the first table (and any attempt to override that is an error).

Equations

Like a table, an equation is a chunk of text set apart from the source text. It has the following overall line structure:

Equation «title»
«equation content»
where «variable declarations».

Similar to tables, the equation title can take on one of three forms:

«number»
- «name»
«number» - «name»

And similarly to tables, the third version defines two different names for the same equation. The only difference between table names and equation names is that equation names don’t use the word of when referring to an equation by name – it’s simply “equation «name»”.

The equation content consists of the mathematical equation written according to conventional mathematical style. It must contain exactly one equals sign (=. It’s common to indent the equation, but this is not required. Conventional mathematical style means that implicit multiplication is supported, so for example if m and a are defined as variables, then ma is read the same as m*a. The supported operators are just + - * / ^. Other than that, parentheses are understood for grouping.

Several common mathematical functions are understood. Parentheses are not required for function application, in keeping with conventional mathematical style for well-known functions; however, you do need a space after the function name (but a space before is optional). The full list of understood functions is:

abs (absolute value)
root (square root)
ceiling, floor
int (I’m not sure what this does; I thought it would be truncation but got very weird results when trying it)
log, exp (log is specifically the natural logarithm)
sin, cos, tan, arcsin, arccos, arctan
sinh, cosh, tanh, arcsinh, arccosh, arctanh

The variable declarations at the end of the equation specify the meaning of each of the variables. It’s essentially one or more simple assertions stating the kind or value of each variable, separated by commas. Variable names in equations don’t have to be a single letter, but they do need to be short. Also, unlike normal mathematical convention (but like everything else in Inform), variable names should be considered to be case-insensitive. Examples:

a, b, and c are numbers
m is a mass and a is an acceleration
m is a mass and g is 9.8 m/s/s and h is a length

An equation is more than just a function that can calculate one value from several inputs. In fact, Inform7 understands algebra enough to solve the equation for any variable it uses (as long as there is an unambigious solution). Additionally, unlike in phrases containing arithmetic operators, equations correctly respect mathematical precedence and associativity.

When solving an equation, Inform looks for the variables needed by the equation amonst those variables visible to the local scope. Thus, it’s typical to locally define all but one of the required variables prior to solving the equation.

It’s possible to define an anonymous equation inline in a phrase. The syntax is essentially the same, but without the title – that is, it looks like the following:

«equation content» where «variable definitions»

Assuming the input variables all exist already, you don’t need to specify their types again, but you do need to specify at least the type of the variable being solved for (generally the sole variable to the left of the equals sign in this case).

Other Asides

The other three types covered here are figures, sounds, and external files. It’s debatable whether these actually qualify as asides, but from a literary standpoint, they serve a similar purpose, so I’ve included them here. As far as I can tell, they don’t share the binary naming convention of tables and equations, though they’re often named as though they did. They can be declared with the following assertions:

figure/sound «name» is the file «quoted filename» [( «quoted alt text» ).
[binary] file «name» [( owned by (another project | project «quoted UUID») )] is called «quoted name without extension».


  1. I’m not completely clear on how this is determined. I know there’s a prior named object, but I don’t think that can cover all the ways in which verbs adapt, such as the regarding «description/number» forms. ↩︎

1 Like