Chapter 27, Cont.
Now we get to the Inform 6 stuff!
Section 27.14, Using Inform 6 within Inform 7
We learn that Inform 6 code used within Inform 7 never goes through an Inform 6 compiler; instead it becomes ‘inter’, which then becomes something else.
The rest of the book is dedicated to using Inform 6, without actually explaining Inform 6.
It is clear that Graham Nelson does not want people using Inform 6 in Inform 7:
Ideally, all I6 content would be confined to extensions (and this may be mandated in future releases of Inform), and even writers of extensions are asked to pare down their usage of I6 to the minimum necessary.
I am happy to fulfill this dream of his by never using Inform 6 myself.
It also mentions that while it seems like you might be able to edit the Standard Rules a lot, the compiler expects certain behavior from it, so without rewriting the compiler the whole thing will likely crash.
It also says that is you see stuff in Basic Inform or Standard Rules that isn’t documented, it’s because you weren’t supposed to see it in the first place, and it may disappear at will. (Somehow I think this message is for people like Zed who look at everything).
Section 27.15 is Defining Phrases in Inform 6.
It gives an example of an I6 phrase in the Standard Rules:
To end the story: (- deadflag=3; story_complete=false; -).
The parentheses and hyphens are used to demarcate between Inform 6 and Inform 7. The use of the minus sign is intentional as you’re ‘going down a version’.
A phrase with a single I6 command is compiled inline (so instead of calling a function that copies the given code, it’s just copied directly during compiling).
Here are some other examples with inputs:
To say (something - number): (- print {something}; -).
To sort (T - table name) in (TC - table column) order:
(- TableSort({T}, {TC}, 1); -).
In this case, during compilation, both the phrase and the variable name are replaced with I6 equivalents.
So
say the capacity of the basket
becomes
print O17_basket.capacity;
Braces are special characters in I6, so to print an actual brace you put a space after it.
Similarly if you have a minus sign followed by a parentheses for some reason in I6, it will exit out of the I6 paradigm, so you can put a space between the minus and the parenthesis to avoid leaving.
Example 450 is Pink or Blue:
When play begins:
say "Should your character be male or female? >";
if men win, now the player is male;
otherwise now the player is female;
say paragraph break.
To decide whether men win:
(- Question('male','M//','man','female','F//','woman') -)
Include (-
[ Question pos1 pos2 pos3 neg1 neg2 neg3 first_word_typed;
while (true) {
VM_ReadKeyboard(buffer, parse);
wn = 1; first_word_typed = NextWordStopped();
if (first_word_typed == pos1 or pos2 or pos3) rtrue;
if (first_word_typed == neg1 or neg2 or neg3) rfalse;
print "Please choose ", (address) pos1, " or ", (address) neg1, ". > ";
}
];
-)
Section 27.16 is Phrases to decide in Inform 6
Phrases that just do something in Inform 6 end in semicolons. Phrases that return something have parentheses:
To decide whether in darkness: (- (location==thedark) -).
To decide which number is the hours part of (t - time): (- ({t}/60) -).
I’ll be honest, I6 disgusts me. I strongly prefer high level programming languages like Python and Java. Weird stuff like C and Malloc just creeps me out. I named a spell in a horror part of my game Mallox.
Section 25.17 is Handling Phrase options
This is best shown with an example:
To list the contents of (O - an object),
with newlines,
indented,
giving inventory information,
as a sentence,
including contents,
including all contents,
tersely,
giving brief inventory information,
using the definite article,
listing marked items only,
prefacing with is/are,
not listing concealed items,
suppressing all articles
and/or with extra indentation:
(- I7WriteListFrom(child({O}), {phrase options}); -).
The phrase options thing at the end is a special substitution that is a bitmap, assigning one bit to each option mentioned above.
Section 27.18 is Making and Using test options.
Use options are translated into I6. So for instance,
use American dialect
defines the constant DIALECT_US
.
You can make new options like follows (this reminds me of hacking Quixe to allow music and images and putting global constants in the JS):
Use American dialect translates as (- Constant DIALECT_US; -).
Use full-length room descriptions translates as (- Constant I7_LOOKMODE = 2; -).
The recommendation for testing for the status of these things is to use I7:
if the American dialect option is active, ...
The phrase list of active use options
will tell you what the options are, for instance:
We're currently using: dynamic memory allocation option [8192], maximum text length option [1024], maximum things understood at once option [100], American dialect option and fast route-finding option.
Some options let you raise different values. If an extension uses an I6 array with a max number of values, it would be useful to let that number be raised. So you can do this:
Use maximum presented footnotes of at least 100 translates as (- Constant MAX_PRESENTED_FOOTNOTES = {N}; -).
Then the user can mess around with it.
Multiple extensions can define the same Use options as long as they define them exactly the same way.
Section 27.19 is Longer Extracts of code. You can define bigger chunks of code like so, which causes them to be compiled at the end of the file:
Include (-
[ ExtraFunction a b; return a*b; ];
-).
Sometimes you’ll need to pass stuff into I6 from I7. You use a plus and parentheses to do this:
Include (-
Global my_global = (+ the tartan rucksack +);
-).
Which the compiler interprets into:
Global my_global = O18_tartan_rucksack;
or something similar.
There are three things to beware of with inclusions:
Accidentally typing (+ and exiting out of Inform 6.
2. Placing an @ at the beginning of a new line (which marks paragraph divisions). Putting a space fixes this.
3. Creating an I6 variable holding initialized I7 text.
For this 3rd one, an example:
Include (-
Global saved_optional_prompt = (+ "!!>" +);
-).
this is bad. Why? We are not told. This is how to fix it:
Include (-
Array sop_storage --> PACKED_TEXT_STORAGE "!!>";
Global saved_optional_prompt = sop_storage;
-).
Example 451 is Status Line with Centered Text, the hard way
It says that major display changes require a lot of Inform 6.
Rule for constructing the status line:
print the location in the center of the status line;
rule succeeds.
To print the location in the center of the status line:
(- PrintCenteredStatus(); -).
Include (-
Array printed_text --> 64;
[ PrintCenteredStatus i j;
@set_cursor 1 0;
i = 0->33;
spaces(i);
@output_stream 3 printed_text;
print (name) location;
@output_stream -3;
j = (i - (printed_text-->0))/2;
@set_cursor 1 j;
print (name) location;
spaces j-1;
];
-)
This example doesn’t compile for me, with the following errors:

Section 27.20 is Primitive Inform 6 Declarations of rules
You can make a rule definition in Inform 7 that basically says ‘I’ll define this later in Inform 6’:
The underground rule translates into I6 as "UNDERGROUND_R".
Include (-
[ UNDERGROUND_R;
if (real_location hasnt light) { RulebookSucceeds(); rtrue; }
rfalse;
];
-).
You can put this into rulebooks like any other named rule.
This compiles just fine.
Section 27.21 is Inform 6 objects and classes
I7 turns each kind into an I6 class and each object into an I6 object.
You can finetune this process like so:
A thing has a number called marmalade jar size. The marmalade jar size of a thing is usually 6. The marmalade jar size property translates into I6 as "marmalade_jar_size".
Or even more:
Include (- with before [; Go: return 1; ], -) when defining a vehicle.
This is provided the following bewildering explanation (but this whole half chapter was professed to be only for I6 afficionados):
This glues in a new property to the class compiled to represent the I7 kind “vehicle”. (See the DM4 for why. However, since the entire actions machinery is different in the I7 world, note that “after”, “react_before” and “react_after” no longer have any effect, and nor does “before” for rooms.)
You can include other attributes like this:
Include (- has my_funny_attribute, -) when defining the hot air balloon.
and you can force translation of things:
The whatsit object translates into I6 as "whatsit".
The thingummy kind translates into I6 as "thingummy_class".
We are then told that the ‘include’ when defining is deprecated and will disappear in future versions of Inform!
Section 27.22 is Inform 6 variables, properties, actions, and attributes
This says that I7 variables are usually array entries and not I6 variables, but you can tell I7 to use I6 variables. Like this:
Room description style is a kind of value. The room description styles are Brief, Verbose and Superbrief.
The current room description style is a room description style that varies.
The current room description style variable translates into I6 as "lookmode".
You can also create new I6 variables to do this with, which is not encouraged:
Include (- Global my_variable = 0; -).
Hmm, I wonder if this is why this is the last chapter and all the Inform 6 stuff was crammed in and hidden by extensions. Maybe Graham Nelson was doing everything he could to keep people from using I6?
I’m doing my part!
You can tell I7 to translate some property to a pre-existing I6 property:
The switched on property translates into I6 as "on".
The initial appearance property translates into I6 as "initial".
and actions:
The unlocking it with action translates into I6 as "Unlock".
Section 27.23 is Inform 6 Understand Tokens.
You can make I7 understand things the I6 way as follows:
The Understand token squiggle translates into I6 as "SQUIGGLE_TOKEN".
This creates a token called [squiggle].
then Inform would parse the command COPY FIGURE EIGHT by calling the SQUIGGLE_TOKEN routine as a GPR with the word marker at 2, that is, at the word FIGURE.
Section 27.24 is Inform 6 adjectives
You can define adjectives at I6 level like this:
Definition: a number is prime rather than composite if I6 routine "PRIMALITY_TEST" says so (it is greater than 1 and is divisible only by itself and 1).
The parentheses stuff is just used for Index listing.
Another way to use I6 adjectives is like this:
Definition: a scene is crucial if I6 routine "SceneCrucial" makes it so
(it is essential to winning).
(note the difference between ‘says so’ in the first example and ‘makes it so’ in the second.)
SceneCrucial" is called with two arguments: SceneCrucial(S, -1) tests whether the scene is crucial or not and returns true or false; SceneCrucial(S, true) must make it true; and SceneCrucial(S, false) must make it false. Another useful difference is that if the kind of value is one which is stored in block form (e.g. for an adjective applying to text), the routine is given a pointer to the block, not a fresh copy.
A third way is to do this (fast code, essentially a macro):
Definition: a rulebook is exciting if I6 condition
"excitement_array-->(*1)==1" says so (it is really wild).
Section 27.25 is Naming unicode characters
This seems to be no longer relatd to I6. Maybe we’re just in a random assortment appendix?
You can name them with stuff like this: anticlockwise open circle arrow translates into Unicode as 8634.
. A few built-in extensions already do this.
Section 27.26 is Overriding definitions in kits:
I7 is turned into a code called ‘Inter’ by the compiler. This is sustained by additional Inter code called ‘kits’. There are three standard kits:
BasicInformKit, WorldModelKit and CommandParserKit.
To learn more about this, look up documentation on ‘inter’.
To add extra Inter code, use the same notation as for I6 (have we just been doing Inter all along?)
For instance:
Include (-
[ ExtraFunction a b; return a*b; ];
-).
But to replace something in a standard kit:
Include (-
[ SquareRoot num;
"Nobody cares about square roots, son.";
];
-) replacing "SquareRoot".
Kits did not exist between 2010 and 2021, instead having template files serve that purpose.
So you used to be able to type stuff like this:
Include (- ... -) before "Relations.i6t".
Include (- ... -) instead of "Relations.i6t".
Include (- ... -) after "Symmetric One To One Relations" in "Relations.i6t".
But we can’t use 'instead of ’ at all now, and just use ‘replacing’.
This has also been deleted:
Include (- {-segment:MyStuff.i6t} -).
Instead, you have to make a new kit, using rules in the documentation for ‘inter’.
Section 27.27 is Translating the language of play
The language of play is usually English, but hardworking users in other communities have helped create translations. In I6, this is done with header files, but in I7 it is done with extensions.
‘English Language’ by Graham Nelson comes built-in to Inform and is a template.
Section 27.28 is Segmented substitutions
These are substitutions like ‘[first time]’ or ‘[one of]…[or]…’
To define these, you have to not only translate into I6, but use special notation.
Each substitution has to be defined as a ‘beginning’ one, a ‘middle’ one, or an ‘ending’ one.
Then the syntax rules are as follows:
(a) Any usage must lie entirely within a single say or piece of text.
(b) It must begin with exactly one of the substitutions marked as "beginning".
(c) It can contain any number, including none, of the substitutions marked as "continuing" (if there are any).
(d) It must end with exactly one of the substitutions marked as "ending".
Here is an example:
To say emphasis on -- beginning say_emphasis_on: (- style underline; -).
To say emphasis off -- ending say_emphasis_on: (- style roman; -).
Now, these substitutions can only be used as a pair.
Example 452 is Chanel Version 1:
To say i -- beginning say_i -- running on: (- style underline; -).
To say /i -- ending say_i -- running on: (- style roman; -).
To say b -- beginning say_b -- running on: (- style bold; -).
To say /b -- ending say_b -- running on: (- style roman; -).
Place Vendôme is a room. "[i]Fashion fades, only style remains the same[/i] ([b]Coco Chanel[/b]). And this elegant drawing-room, once a milliner's shop, is a case in point."
Instead of going nowhere, say "[i]Don't spend time beating on a wall, hoping to transform it into a door.[/i] ([b]Coco Chanel[/b]) This one is a wall.".
Test me with "look / e".
This just mimics html format.
Section 27.29 is Invocation labels, counters and storage.
An invocation is the process of expanding I6 code.
Invocation is very complex and may change at any time.
There is then a list of special invocations, such as {-open-brace}, {-delete}, etc.
You can manipulate variables and counters with different invocations, and let a counter be preserved between invocations. An instanc:
To say once only -- beginning say_once_only:
(- {-counter-makes-array:say_once_only}if (I7_ST_say_once_only-->{-counter:say_once_only} == false) {-open-brace} I7_ST_say_once_only-->{-counter-up:say_once_only} = true; -).
To say end once only -- ending say_once_only:
(- {-close-brace} -).
Then if there is a variety of ways to end an I6-defined text substitution, you can define them like this:
To say emphasise -- beginning say_emphasise:
(- style {-final-segment-marker}; -).
To say with italics -- ending say_emphasise with marker underline:
(- style roman; -).
To say with fixed space type -- ending say_emphasise with marker fixed:
(- style roman; -).
And finally…To say one of! Section 27.30
This contains a vast chunk of horrifying code showing how ‘one of’ is coded:
To say one of -- beginning say_one_of (documented at phs_oneof): (-
{-counter-makes-array:say_one_of}
{-counter-makes-array:say_one_flag}
if (I7_ST_say_one_flag-->{-counter:say_one_flag} == false) {
I7_ST_say_one_of-->{-counter:say_one_of} = {-final-segment-marker}(I7_ST_say_one_of-->{-counter:say_one_of},
{-segment-count});
I7_ST_say_one_flag-->{-counter:say_one_flag} = true;
}
if (say__comp == false) I7_ST_say_one_flag-->{-counter:say_one_flag}{-counter-up:say_one_flag} =
false;
switch ((I7_ST_say_one_of-->{-counter:say_one_of}{-counter-up:say_one_of})%({-segment-count}+1)-1)
{-open-brace}
0: -).
To say or -- continuing say_one_of (documented at phs_or):
(- @nop; {-segment-count}: -).
To say purely at random -- ending say_one_of with marker I7_SOO_PAR (documented at phs_purelyrandom):
(- {-close-brace} -).
We can alter this as shown in the examples.
Example 453 is Blink:
> Atmosphere is a kind of value. The atmospheres are normal, melancholy, and creepy.
> The current atmosphere is an atmosphere that varies.
> The current atmosphere variable translates into I6 as "current_atmosphere".
> To say by atmosphere -- ending say_one_of with marker I7_SOO_ATM:
> (- {-close-brace} -).
Include (-
Global current_atmosphere = 1;
[ I7_SOO_ATM oldval count;
if (count < current_atmosphere) return count;
return current_atmosphere; ];
-)
The Flat is a room. "A small [one of]but cozy[or]depressing[or]imprisoning[by atmosphere] flat. Outside the window, the sun is [one of][or][or]apparently [by atmosphere]shining and there is a brisk breeze through the leaves of the birch trees. [one of]It would be quite nice weather for a walk[or]The rest of the world apparently has no appreciation of what you suffer[or]It all looks deceptively normal[by atmosphere]."
Example 454 is Uncommon Ground, adding some new text substitutions:
switch(player)
{
yourself: print "quaint";
Lolita: print "thrilling";
default: print "squalid";
}
Instead of waiting:
if the player is Lolita, now the player is Leforge;
if the player is yourself, now the player is Lolita;
say "You jump bodies. Whoops!"
To say show to (N - a person) -- beginning say_seen_by:
(-
switch(player)
{-open-brace}
{N}:
-).
To say to (N - a person) -- continuing say_seen_by:
(-
{N}:
-).
To say to everyone else -- continuing say_seen_by:
(-
default:
-)
To say end show -- ending say_seen_by:
(-
{-close-brace}
-)
The Mud Village is a room. "You stand at the center of a [show to yourself]quaint[to Lolita]thrilling[to everyone else]squalid[end show] mud village."
And we’re done! The great project to read through and comment on all of the Writing with Inform manual ends not with a bang, but with a whimper, as we peek past the wholesome facade of Inform 7 and peek into the eldritch horrors of Inter, Inform 6, and Invocations that lie behind it.
Overall, I found this fun. I gained a much greater appreciation of the Index, which is so much more powerful than I imagined.
I learned the most from Chapter 6: Descriptions, Chapter 11: Phrases, Chapter 18: Activities, and Chapter 12: Advanced Actions. Visibility, reaching, persuasion, and phrases that return objects and values were very helpful to me.
Things I’m excited to try in the future include website templates and some of the fancier releasing options, and I’ve dedicated a whole area of my game to use persuasion rules in, since they form such a large portion of this text.
Overall, it was great. There were times when the examples were more complex than needed or the text was obscure, but I’ve read many iterations of design documentation over the year and I prefer this manual to most others (I like this better than WW3schools for python and java).
Thanks to those who read along!
I do plan on reading The Inform Recipe Book at some point, but I’m going to take a break. There are exactly 50 games right now with 100+ ratings on IFDB and I think I’ll replay them all for fun before I read the next book.