An Introduction

Table of Contents

Syntax used in this document

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 an asterisk will be converted to a footnote on the resulting page.

[ [*] («text» | «comment»)* ]

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:

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

There are 3 categories of literals: quoted literals, arithmetic literals, and list literals.

Arithmetic Literals

Basic arithmetic literals for numbers are quite straightforward - minus sign, digits, and decimal point as expected. The one thing that may be unexpected for people used to programming language is that exponents are given in standard mathematical style, using either the letter X or a multiplication sign.

There are also literals for time values, as well as custom literals that can have almost any syntax you can imagine. The definition of the custom literal specifies the exact form of each preamble, whether a component can be omitted, whether the preamble of an omitted component can be omitted, and whether spaces are required or forbidden between components.

digits [-] digits [. digits] [(x | × | * ) 10 ^ [-] digits]
digitsst/nd/rd/th
HH:MM AM/PM
integer hour/hours [integer minute/minutes]
integer minute/minutes
[«preamble»] «number» («preamble» «number»)* [«preamble of omitted component»]
unicode «digits»

Apart from the obvious literal forms, numbers from zero to twelve may be written out as words. Furthermore, the ordinal forms first through twelfth can also be written out as words. Note that ordinals seem to be allowed only in conditions, not assertions. Also note that the four possible ordinal suffixes are all treated as equivalent – Inform doesn't care if you use the wrong one for a particular number. A space before the suffix is an error.

For real numbers, the constants e, pi, plus infinity, and minus infinity are understood.

Also, though it's not quite an arithmetic type, any integer can be turned into a unicode character constant just by prefixing the word unicode to it.

Quoted Literals

A quoted literal begins and ends with a double quote. There is no way to directly embed a double quote inside a quoted literal. Within a quoted literal, square brackets are significant and must be paired up.

" (text | [ text ])* "

Text Literals

In text literals, almost everything is taken literally exactly as written, with three exceptions:

  1. A literal apostrophe is treated specially. Unless it's both preceded and followed by a letter, it will be replaced by a double quote.
  2. Any text ending with a literal period, exclamation mark, or question mark automatically has a line break appended. Literal here means that the line break is only appended if said final punctuation is present before substitutions have been applied. If a substitution at the end of the string happens to end in a period, no line break is appended.
  3. Anything enclosed in square brackets is treated as a substitution. Sometimes, multiple substitutions work in concert to determine the final text – this is called a segmented substitution.

There are ways to work around each of these cases if you need to:

  1. The substitution ['] or [apostrophe] can force an apostrophe where it would normally be converted to a double quote. Similarly, if you need a double quote in a place where putting an apostrophe wouldn't normally convert it, you can use the substitution [quote].
  2. The easiest way to avoid an automatic line break is to just add a space at the end of the text. If that doesn't work for some reason, you can use the substitution [no line break]. Similarly, you can force a line break anywhere with [line break].
  3. The substitutions [bracket] and [closed bracket] expand to literal bracket characters.

Substitutions can take on one of two forms – they are either an expression evaluating to a sayable value or a say phrase. All the examples shown above are the latter.

Allowing for arbitrary expressions is already extremely versatile. Nearly all kinds of value are sayable in Inform7, including names of objects, values of enumerated kinds, and literal values. Since it's an expression, any phrase that returns a value can be used. A conditional phrase can also be used by converting it to a truth state value with the special phrase whether or not. The name of a property can be used even without referencing the owning object – there is a variable called item described that is searched for the property in such cases.

One particularly powerful instance of sayable values that deserves special mention is verbs. A verb in Inform is treated as just another kind of value. When you substitute a verb into a sentence, Inform automatically does its best to adapt it to fit the context – the current story tense and story viewpoint, and the current object or objects under discussion. The current object is determined by a variable called prior named object that is set whenever the name of an object is printed. It can also be set explicitly via the say phrase regarding something.

But say phrases are even more powerful, even allowing game state to be changed in response to printing text to the screen. There are built-in phrases to substitute the correct article or pronoun for an object, with first-person pronouns automatically updating the prior named object to refer to the player.

Topics

Most quoted literals are text intended to be output to the screen. However, in a few contexts, they are instead topics used to match the player's input. Square brackets in a topic don't mean substitution. Instead, they enclose either a description of values or the name of a special token. There are only a small number of built-on tokens, though new ones can be defined if needed using an Understand assertion.

Within a topic, the forward slash has special significance when separating words – when a sequence of words is separated by forward slashes, it means the input should match exactly one of those words. If the sequence is ended with /--, the meaning changes to at most one, meaning the absence of any word in that position can also match.

Topics can also be joined together with the word or. This doesn't go inside the quotes but is rather placed between two quoted topics. In some contexts, a sequence of topics joined by or is treated like a topic literal. This only works in table columns or Understand assertions.

List Literals

Ironically, list literals are simpler than either arithmetic or quoted literals. A list literal can only contain constant values – you can't use the literal syntax to construct a list out of variables.

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

Generic Sentence Grammar

A lot of places in Inform use the concept of a sentence. This isn't the same as a sentence in English. Rather, it's a restricted subset of what constitutes an English sentence. There are quite a few exceptional cases that don't quite fit the general concept of a sentence, but probably about 90% of assertions can be boiled down to this syntax, and a great many conditions as well.

noun phrase verb [adverb] noun phrase

In the above grammer, the verb phrase is any sequence of words understood as a verb. Inform's concept of a verb is looser than English, and includes prepositional phrases. So for example, "to be in" and "to be on top of" and "to be understood by" would all be considered verbs and thus can be conjugated as a valid verb phrase. Inform similarly has a loose concept of what constitutes a preposition – any sequence of words that can appear after "to be" is considered a preposition, so in the preceding examples you have prepositions "in", "on top of", and "understood by". In fact, a preposition by Inform's definition very often begins with a participle.

The noun phrase is similar to a description of values (defined later on) and looks like this:

(adjective* noun | «adjective»+ | «correlative pronoun» «adjective»*) [«relative phrase»] [ and noun phrase ]

As that shows, it's not legal to omit both noun and adjective – you must have at least a noun or an adjective. A correlative pronoun here is a word such as "someone" or "nothing". Though Inform permits noun phrases to be chained together with "and", it's easy to get in trouble doing this – all the phrases would need to be compatible, and if done on both sides of the verb, it gets even more error-prone. It's best to only do this on one side of the verb.

The relative phrase looks like this:

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

Inform considers prepositional phrases to be a special case of relative clauses where the verb is implied as "to be". And, remember, participles are treated as just another type of preposition. So, "the man carrying the basket" parses the same as "the man who is carrying the basket", and "the fruit bowl on the table" parses the same as "the fruit bowl which is on the table".

Formally, Inform expects all sentences to end in a period .. This includes sentences that are structured very different from English, such as phrasebooks and asides. However, there are two places where Inform will infer a missing period.

Inform allows commas , between adjectives in sentences, which may help disambiguation in some cases for multi-word adjectives. It also allows commas to precede or substitute for and or or in many contexts. However, both of these usages are forbidden in conditional sentences, and in many places, commas have special meanings which will be mentioned as they come up.

Inform mostly ignores articles altogether, treating them the same as whitespace. There are some exceptions to this rule where the choice of article can be significant. Most of the exceptions only apply to phrases however, which are not sentences. But there is at least one case where articles can be significant in sentences, which will be explained where it becomes relevant.

Similarly, Inform doesn't care about plurality. It understands singular and plural forms of most nouns, as well as singular and plural present forms of verbs, but it treats the singular and plural forms purely as synonyms and doesn't care if you use the one that actually happens to agree in a certain context. You can write ungrammatical sentences like “The cat are on the table’ or “Some apples is in the box” and Inform will happily accept them without complaint. Because of this, I'll usually use only singular forms when describing the syntax, unless there are cases where this rule is broken.

Inform allows parentheses to be used for grouping in many cases. This is not allowed in static assertions, but it can be useful in descriptions or conditions.

Inform gives a special meaning to the colon and semicolon in phrasebooks. That will be discussed in more detail later on.

For example, suppose you have a room called "Road to Paradise" and want to disable exiting it on foot in a specific direction. The obvious way won't work:

Instead of going west from Road to Paradise by nothing: do nothing.

The parser unfortunately sees the “to” in the name and thinks you're trying to match the room gone to. Coupled with the way that multiword objects can be referred to by only part of the name, assuming you have no other objects with clashing names, this rule would only match if west of the Road to Paradise was the Road to Paradise. You can work around this issue by enclosing the name of the room in parentheses:

Instead of going west from (Road to Paradise) by nothing: do nothing.

Assertions

Assertions are sentences that declare the state of the game. Technically, almost everything in Inform 7 is part of an assertion. Section headers and comments could be said to be the only exceptions. But not all assertions provide the exact same purpose, and in this section I'll stick to assertions that don't have any exotic punctuation in them, like colons or semicolons. Even then, it's worth breaking down assertions into subcategories – structural assertions, definitions, and imperative assertions.

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 – if you attempt to use him, her, or them, it’ll be taken as the name of an object, so the only valid pronoun is it. This refers to the subject of the most recent sentence that had one (if the left side of the verb is a prepositional phrase, then there is no subject and the referent of it is not changed). 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 [adjectives] [kind].
There is [number] kind [called name].

Note: If you omit the kind, it is implied to be thing. This means that only adjectives that can be applied to thing (or object, as every thing is also an object) can be used to define an object without specifying the kind. For example, “The puddle is scenery” works because scenery is a property on things, but “The puddle is open” does not work, because open is a property on containers, not things. But if you wrote “A thing can be open or closed.”, it would work and infer the puddle to be a thing (not a container).

Assertions of this form don't just define objects – nearly everything that can be defined in Inform uses a sentence of this form to define it. Enumerated values (including scenes), kinds, actions, verbs, rulebooks, and activities are all defined with this same basic structure.

Those assertions aren’t particularly interesting. Most assertions specify a relation. Such assertions can take on the form of any generic sentence, as defined above, plus an optional called clause in some cases that mirrors the one in the basic definitions. But this 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. This list also covers directions, which are something of a special case, as well as a unique case for backdrops. The ones with name are explicitly defining the object at the same time as they specify a relationship.

room or door is direction of room or door .
direction of room or door is room or door .
direction of room or door is direction of room or door .
direction of room or door is nowhere .
Nowhere is direction of room or door .
name is kind preposition noun .
noun verb noun .
noun is preposition noun .
preposition noun is noun.
preposition noun is kind [called name] .
preposition noun is number kind .
kind [called name] verb noun .
number kind verb noun .
backdrop is 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. Similarly, anywhere you see “verb”, it’s implied that a preposition can be used, as Inform treats the preposition as part of the verb.

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”.

One thing to keep in mind when defining things with assertions is that Inform 7 tries to intelligently guess a few properties of the thing based on how you write the description. This is one of the few places where an article has significance. There are at least two distinct rules here.

The first rule is that the presence of an article matters. If you define a thing without using an article, it receives the proper-named property. If it's defined with the article some, it receives the plural-named property.

The second rule is that every object has an indefinite article property that is automatically populated based on its name. Normally it's blank, which means Inform automatically selects “a” or “an” as appropriate, but if you define the object using called the, it will be set to "the".

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

noun is adjective .
property of noun is value .
noun has 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 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.

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 values .
values is 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»] )]
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 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 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, plus a number if needed to make the name unique) 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 adverb adjective .
(adjective kind | correlative pronoun adjective) is adverb adjective .
property name of kind or value is 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 a kind of (base kind | value) that/which is adjective (and adjective)* .
name is 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 if Z doesn't already exist:

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 kind (that/which varies | variable) .
name is initially value .

A variable previously defined using the first form can also be given an initial value without using the word initially. Using initially without also using the first form will cause Inform 7 to infer the type of the variable.

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 .

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 | play) begins/ends .
scene ends [ending name] when condition .
scene ends [ending name] when (scene | play) 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. Note that when play ends is not a valid condition, since nothing happens after the game ends anyway.

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 | in groups] .
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 | verb) .

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. You can also define phrasal verbs that do not begin with either of those – they are not handled specially, and you can specify the conjugation normally.

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 kind of rulebook .
name [something] is 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. This is the case even if it's not the final word, but if it is the final word, then it's also omitted from the actual name of the 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 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 default failure/success .
rulebook has default no outcome .
rulebook has 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/while condition] .

Imperative Assertions

Understand

Understand topic as action name [( with nouns reversed)] [when/while condition] .
Understand the command command list as command .
Understand the command command as something new .
Understand nothing as action name .

These forms all work with verbs – defining a verb to mean an action, giving word-level synonyms, or clearing out previously-defined grammar.

For the first one, there’s a special restriction on the topic – there may not be any alternations on the first word.

Understand topic as value or kind [when/while condition] .
Understand topic as the plural of value or kind [when/while condition] .

These forms work on nouns. I don’t really have anything more to say here.

Understand topic as token .
Understand token name translates into I6 as quoted I6 identifier .

The token to be defined in the first form must be a quoted string containing nothing but a single square-bracketed token. The topic here is also restricted – it may contain at most one token in it, and if you use alternatives with or, every alternative must be compatible. Either they all contain no tokens, or they all contain a token of the same kind.

Understand property as describing value or kind [when/while condition] .
Understand property as referring to value or kind [when/while condition] .
Understand topic as adjective .

The describing form allows the adjective to be used alone to refer to the object, whereas referring to means it can only refer to the object if it appears alongside the object’s name.

And lastly:

Understand topic as a mistake [( text )] [when/while condition].

Test

Test name with script [holding thing [ ( [ , ] and | , ) thing ] ] [in room] .

The script is a quoted list of commands to be run, separated by forward slashes (/). Unlike everywhere else in the language, the forward slash here doesn’t separate words only – it functions more like a semicolon or period. I believe you can use [/] if you need a literal forward slash to be included in a command.

Include

Include [version version of] extension by author .
Include (- Inform 6 code -) [when defining kind or object | replacing quoted I6 identifier] .
Include (- Preform code -) in the Preform grammar.

Include segments can do a great many things, and I'm not certain that this is every possible way they can be written. The most common use-case should be the first one, which includes an extension.

Within Inform 6 code embedded in Inform 7, you can use two types of special substitutions that are not part of Inform 6:

(+ Inform 7 value +)
{ substitution }

The first case translates a snippet of Inform 7 representing a value into the Inform 6 representation of that value. It can also convert a property name or a defined adjective into the Inform 6 representation. The second case is used to substitute the value of a phrase argument into the code, as well as some other special cases.

The following special substitutions are mentioned in the documentation:

{phrase options}
{-delete}
{-erase}
{-open-brace}
{-close-brace}
{-counter: name }
{-counter-up: name }
{-zero-counter: name }
{-counter-makes-array: name }
{-segment-count}
{-final-segment-marker}

There are many others, but the documentation explicitly states that you should not use them because there is no guarantee that they won't be removed in a new version, so I won’t attempt to list them here.

Use

Use option [of at least/most value] (and option [of at least/most value])* .
Use option [of at least/most value] translates as (- Inform 6 code -) .

The first line is how to apply a use option. The second describes how to define use options. The value can be interpolated into the I6 code with the special substitution {N}. This is due to be overhauled in the next release, so I don't know how long it’ll remain current, but it’s been like that for at least a year now, so I think it’s fair to document it.

Release

Release along with release instruction (and release instruction)* .

Possible release instructions include:

file text called quoted file or directory name
cover art [( quoted alt text )]
introductory booklet/postcard
quoted template name website
quoted interpreter name interpreter
existing story file [called quoted filename]
[public/private] solution
[public/private] source text
[public/private] library card
style sheet quoted filename

Index map

Index map with mapping instruction (and mapping instruction)* .

Possible mapping instructions are:

room mapped cardinal direction of room
direction mapped as cardinal direction
EPS file
rubric text [size number] [font text] [color text] at offset [from room]
setting [of part] set to value

When adjusting settings, the optional part can be one of the following:

description of rooms
description of regions
first room
level number

The level number can be negative.

Setting values can be any of the following (depending on the setting in question):

quoted text
number
on/off
number&number

That last type is called an offset, and is also used for the rubric instruction.

The possible settings are:

font
minimum-map-width
title
title-size
title-font
title-colour
map-outline
border-size
vertical-spacing
monochrome
annotation-size
annotation-length
annotation-font
subtitle
subtitle-size
subtitle-font
subtitle-colour
grid-size
route-stiffness
route-thickness
route-colour
room-offset
room-size
room-colour
room-name
room-name-size
room-name-font
room-name-colour
room-name-length
room-name-offset
room-outline
room-outline-colour
room-outline-thickness
room-shape

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. A space can be added if needed to disambiguate names longer than a single character. 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 with extension [( quoted alt text ) .
[binary] file name [( owned by (another project | project quoted UUID) )] is called quoted name without extension .

Phrasebooks

In contrast to an assertion, which is resolved statically at compile time, a phrasebook contains imperative code to be executed at runtime.

With one exception, all phrasebooks have one of the following general forms:

preamble : phrase ( phrase ; )* .
preamble : (- inform 6 code -) .

That’s not quite accurate, as the final period can be omitted or (for inform 7 phrasebooks at least) replaced by a semicolon as long as the phrasebook is followed by a blank line. In fact, any number of redundant semicolons will just be ignored, and a semicolon will be inferred at the end of every line. Though the preamble depends on the type of phrasebook, the contents of all phrasebooks is the same – a sequence of phrases that are run one after another.

The type of phrasebook you're looking at can always be determined by the first word – To for a phrase, At for an event, Definition for a definition. Anything else is a rule – if the first word is This, it's initially unlisted in any rulebook. (Arguably events are rules too, but they're a special type of rule.)

The remainder of this section focuses only on the preamble of each type of phrasebook.

Phrases

I believe the following list covers every possible way of defining a phrase:

To say phrase pattern [( this is phrase name )] :
To decide what/which kind or kind variable is phrase pattern [phrase option list] [( this is phrase name )] :
To decide if/whether phrase pattern [phrase option list] [( this is phrase name )] :
To phrase pattern [phrase option list] [( this is phrase name )] :

The following form is not allowed, except for phrases defined in I6 – you need to use the if/whether form instead:

To decide what/which truth state is

Phrase patterns are a sequence of one or more of the following:

any literal word [ / any literal word ] [ / -- ]
( name of kind of generic value kind kind variable )
( name - generic value kind of kind kind variable )
( name - description of values )
( name - special non-kind )

That first one is slightly inaccurate – -- is not required to come at the end. The second and third ones define a kind variable which can then be referenced from other parameters or in the phrase body. There is also a restriction that a close parenthesis cannot be followed by an open parenthesis – at least one literal word must be interposed.

When matching the name of a phrase, Inform 7 prefers to match a phrase that uses more words over one that uses fewer. For this purpose, even articles are significant – so, this is a place where articles are not simply noise words. Of course, that only applies if the phrase pattern explicitly used articles.

This is a list of the special non-kinds. It's not necessarily comprehensive. These are only allowed on I6 phrases.

storage
[ existing/nonexisting/global ] [ kind ] variable
property-value
table-reference
list-entry
condition
now-condition
phrase
action
Phrase options are defined with the following syntax (these are the full specification, not alternatives):
, phrase option
[ ( , phrase option )* [ , ] ( or | and/or ) phrase option ]
[ special phrase option ]

Special phrase options always contain -- and are only recognized as such if they are an exact known option that applies to that phrase type. Otherwise, they (along with the double hyphen introducing them) are treated as part of the preceding pattern or phrase option. The only special phrase option that I know of that's useful for phrases not written in I6 is running on, which is valid for say phrases. This is a list of all special phrase options used in Basic Inform:

-- running on (for say phrases)
-- beginning name (for say phrases)
-- continuing name (for say phrases)
-- ending name [ with marker name ] (for say phrases)
begin -- end conditional/loop (this seems to be the way to define block phrases)
-- in loop (a phrase that can only be used in a loop; works on imperative phrases, haven't tested on other types)

Rules

There are two primary ways of declaring rules, and a few special cases. The first is a named rule with no circumstances and not placed in a rulebook:

This is the rule name :

The second way is a rule with circumstances, placed in a rulebook, with an optional name (this is the full syntax, not a list of alternatives):

[ First/Last ] rulebook name [ for | of | rule about/for/on ]
[ description of target ]
[ when/while condition ]
[ during description of scenes ]
[ ( this is the rule name ) ] :

The form of description of target depends on the basis of the rulebook. For a nothing based rulebook, it's not allowed at all. For an action based rulebook, it will be a description of an action. For an object based rulebook, it will be a description of an object.

There is a bit of ambiguity here for action based rulebooks, as a description of an action also supports a when/while clause. However, it's not valid to have two when/while clauses on a rule, so if there's an action description in the preamble, the when/while clause belongs to that description and the second one noted above may not be included.

The third way of declaring rules is the special exception noted earlier, where a phrasebook definition does not include a colon:

(Before/After/When | Instead of | Every turn) rest of preamble , phrase .

Note that there can only be a single phrase in this form. Furthermore, the initial word or words don't need to be the full name of the rulebook – this form can be used for any rulebook whose name happens to begin with one of those words. Though it's rarely done, this form can be given a name.

The fourth way of declaring rules applies only to rules for when a scene begins or ends:

When scene (begins | ends [ ending ] ) :
When description of scens begins/ends :

The first case places the rule in a special rulebook that exists only for that scene, and allows you to match a specific ending. On the other hand, the second case places the rule in a global rulebook for when any scene begins or ends, and doesn't allow detecting how the scene ended (for scenes with multiple endings).

The fifth and final way of declaring a rule is events, which are very simple. They are a special type of rule that has no circumstances but will be triggered by a separate mechanism that fires every turn. There are two ways to define them:

At time :
At the time when event name :

The second case will be an error if there is no code that schedules it. Also, the name it defines is not actually a full-fledged rule name. You can’t use it in assertions, such as listing it in a rulebook. However, it can be used in any phrase that expects a rule, including storing it in a local variable, or directly following it. On the other hand, even if you store it in a variable, you can’t call it with that variable – the phrase to call a timed event can only take the literal name of the event.

Definitions

A definition phrasebook is defined with the following preamble:

Definition : kind or value [ ( called name ) ] is/are adjective [ rather than opposite adjective ] :

There are also two forms of definition that are not technically phrasebooks (as they don’t contain phrasebooks), but are included here because they have the same initial word:

Definition : kind or value [ ( called name ) ] is/are adjective if condition .
Definition : kind or value is/are adjective if its/his/her/their property name is/are value [ or more/less ] .

Descriptions

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.

The exact meanings of the indefinite pronouns are as follows:

PronounMeaning
somethinga thing
someone/somebodya person
somewherea room
anythingany thing
anyone/anybodyany person
anywhereany room
everythingevery thing
everyone/everybodyevery person
everywhereevery room
nothingno thing
no-one/no one/nobodyno person
nowhereno 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.

If necessary, parentheses (()) can be used to disambiguate grouping in descriptions of values.

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 condition is just a regular condition. The one downside is that there’s no way to negate the entire condition, like unless.

The recurrence condition 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.

If necessary, parentheses (()) can be used to disambiguate grouping in descriptions of actions.

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.

Other than the obvious case of the object kind hierarchy, real numbers are treated as less specific than numbers, but “nothing” is treated as unrelated to any other kind. All other kinds are also treated as unrelated.

Note that there are some restrictions on how composite kinds can be combined. If you get an error after adding a complicated composite kind (for example, a list of descriptions of lists of number valued properties that varies.), it probably means Inform just can't represent that combination.

Conditions

A condition (the text you write after if, unless, when, while, or now) is a type of sentence which 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 values 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):

FormNormal verbto beto be able to
Positive simple presentunlock/unlocksis/arecan
Negative simple presentdo/does not unlockis/are notcannot
Positive simple pastunlockedwascould
Negative simple pastdid not unlockwas notcould not
Positive perfect presenthas unlockedhas beenhas been able to
Negative perfect presenthas not unlockedhas not beenhas not been able to
Positive perfect pasthad unlockedhad beenhad been able to
Negative perfect pasthad not unlockedhad 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?)

If necessary, parentheses (()) can be used to disambiguate grouping in descriptions of actions.

References

By references I mean things that reference a mutable value. The simplest type of reference is a variable, either declared with the let phrase or by an assertion, but there are at least three other types of references: table entries, list entries, and property references. The documentation collectively refers to these in some places as “stored values”, and the compiler refers to them as “storage” in internal phrase definitions. Another type is responses, which are implicitly created by certain say phrases in named rules.

List entries and property references are pretty simple. They look like this:

property name of object or value
entry number of list
name of the rule response ( response letter )

There are several ways to reference a table entry. Some of them require a row to have been previously chosen with one of the choose phrases or the table repeat phrase.

column name entry
column name in row number of table name
column name listed in table name
column name corresponding to column name of value in table name
column name of value in table name

The first case requires a row to be selected. The third case is normally seen in comparisons or in descriptions of actions to test if a value exists in a particular column, and I suspect it cannot be used in most other places. It also appears to constitute selecting the matching row.

Basic Phrases

The best quick reference for phrases is the index, but this section will cover the most basic phrases that you’ll need to know.

General Flow Control

rule succeeds – the containing rule succeeds with no outcome
rule fails – the containing rule fails with no outcome
make no decision – the containing rule makes no decision and produces no outcome
rule succeeds with value value – the containing rule succeeds with no outcome and the specified value
rulebook outcome – the containing rule succeeds, fails, or makes no decision, and produces the specified outcome
continue the action/activity – equivalent to “make no decision”
stop [the action] – generic “stop and return nothing” statement for phrases, also works in rules
[decide] yes/no – return true or false from a phrase
decide on value – return specified value from a phrase
next – go to next loop iteration
break – exit loop
do nothing – the placeholder for when you have a block that needs a phrase but no phrase to put there; this phrase just does nothing.

The various result phrases for rules could use some further explanation. There are 4 different types of outcomes that a rule can produce:

  • Should the rulebook continue processing? Defaults to true; stop changes it to false, as do any phrases that make the rule succeed or fail.
  • Did the rule succeed? This has three possible answers: yes, no, or unknown. Default is specified by the rulebook; rule fails, rule succeeds, and make no decision override this, as to named outcomes.
  • What value did the rule produce? This is set by rule succeeds with result, and can't be set on rules that failed.
  • What named outcome did the rule end in? This is set by using the named outcome, which also causes the rule to succeed or fail depending on how the outcome was defined.
  • All of the above also immediately exit the current rule, so there's no way to, for example, state that the rule succeeds but processing should continue.

The result phrases for phrases are more straightforward:

  • The decide on phrase can only be used in To decide… phrases. It can be used in To decide whether… phrases – in this case the value must be a truth state.
  • The stop phrase cannot be used in To decide… phrases. It's fine in any other phrase, including To say… phrases.
  • The decide yes and decide no phrases can only be used in To decide whether… phrases. They’re also allowed in adjective definitions.

Blocks

A few core, built-in phrases introduce a block, which is a sequence of statements under the control of the introductory phrase. There are two ways to write a block, but you can't mix the two ways in the same phrasebook.

The first way is to put a colon (:) instead of a semicolon after the block header phrase, and then indent each subsidiary phrase one level deeper than the level of the controlling phrase. This is similar to how the Python programming language handles scoping.

The other form looks like this:

first word of phrase rest of phrase begin ;
sequence of subsidiary phrases
end first word of phrase repeated ;

It gets a little more complicated than that in if statements, but at least that's the basic idea.

Conditionals

if/unless condition , single phrase ;
[otherwise/else single phrase ;]

I’m pretty sure one-liners can only use the above form – there’s no "else if" equivalent.

if/unless condition : sequence of phrases
otherwise/else if/unless condition : sequence of phrases
otherwise/else : sequence of phrases

Note that otherwise and else are completely synonymous. On the other hand, if and unless are opposites – the latter negates the entire condition.

A switch statement has the following structure:

if value is* : block of phrases
( -- value : block of phrases)*
[ -- otherwise : block of phrases]

Note that, unlike in regular conditional statements, we don't have else as a synonym for otherwise here (which is weird), nor do we have the option of using unless to negate the entire condition (which wouldn't make sense in any case). Also note that a switch statement cannot be used in the begin/end style of blocks – if you want to use a switch statement you need to use indentation.

Loops

while condition :
repeat with name running from arithmetic or enumerated value to value of same kind :
repeat with name running through iterable value :
repeat through table name [in [reverse] [table column] order] :

The iterable value for the third form can be either a list or a description of values.

That last one is slightly imprecise – you need at least one of reverse and a table column. It's not allowed to say in order.

Saying

The say phrase might be the most complicated phrase in the game. This is its most general form:

say sayable thing (, sayable thing)*

where a sayable thing is one of the following:

text [( response letter )]
expression evaluating to sayable value
say phrase

Saying a comma-separated list of things seems to be exactly equivalent to saying each of them in turn in separate say statements.

The first form of a sayable thing is by far the most common – any quoted text, with an optional response letter following it. However, it's interesting to note that if the entire contents of your text is a bracket substitution, you can get the same effect by removing both the quotes and the brackets.

A response letter is only valid in named rules. In particular, it is not valid in named phrases (which seems a little strange to me, honestly). It must be a single uppercase letter, which means you're limited to at most 26 responses in any given rule. (If you find yourself exceeding this, it's probably a sign you should split the rule up anyway.) Using this form creates a value of kind response, formatted as noted in the references section. Thus a response can be assigned to in assertions as though it’s a variable.

Other

I'm not going to cover every imaginable phrase, as the Phrasebook section in the index is pretty extensive, but I'll list a few more of the most basic ones here.

let name be value or kind

When specifying the kind, the name must not already exist. However, when specifying a value, the name can already exist, and must be a local variable. (You can't use let to assign to global variables.) If you only declare the kind, the initial value is the default value of that kind.

now condition

As crazy as it seems, this statement takes almost any condition and immediately arranges things so that it’s true. To be more precise, it will only accept the same kinds of conditions that you can use as static assertions. For example, no past tense or calculated adjectives or relations. I'm not sure if there are any types of conditions that work statically but not in now or vice versa.

whether or not condition

This value phrase effectively casts a condition to a truth state value. Since conditions and values are two different things in Inform, this allows converting between them. Note that true and false are not valid conditions on their own, unlike in many programming languages, and if you have a truth state variable, you need to test it with is like anything else.

Index