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

Regarding chapter 22, I haven’t really had an occasion to use the more abstract constructs in an actual IF project, but just recently I used the method from 22.8. Matching the names of kinds in a small example:

[...]

A car is a kind of vehicle.

A sedan is a kind of car.
A convertible is a kind of car. 

[...]

To paint (name of kind of value K):
	let palette be the list of colours;
	sort palette in random order;
	repeat with paint-target running through Ks in the carpool:
		now the colour of paint-target is entry 1 of palette;
		remove entry 1 from palette;
        
When play begins:
	paint sedans;
	paint convertibles;

There are doubtlessly other ways to do this, but I felt it made for relatively compact, yet readable code, and it’s very easy to add further kinds of car, like SUVs, hatchbacks, etc., without having to change or duplicate much code.

(In the particular example, I wanted each sedan (etc.) to have a unique colour, but didn’t want to simply paint all cars in one go, because I wanted to re-use colours for different types, so we can have a red sedan and a red convertible, for example.)


These threads have some further examples of how the techniques from chapter 22 might be used:

4 Likes

This appears in the next example (and you discuss it a bit later down), but just to make it explicit:

To foo the bar (this is fooing):

The “this is ___” note is how you give a name to a phrase. To pass that phrase around as a value, you use that name.

Never. But it’s one of those things that’s straightforward-but-tedious to implement given the tools provided, so the standard library might as well do it for us.

The important isn’t the word “original” (you could also call it “V” or “foo” if you wanted)—the important part is that, instead of its type being “value”, its type is now “value of kind K”. This binds “K” to the type of the argument, so you can specify that the phrase returns a “K” and everything is good.

Or in C++ terms:

template<typename K>
K triple(K orig){ return 3*orig; }

This time, the parameter is of type “phrase K → value of kind L”, which binds the types K and L. For the purpose of this one phrase, “K” and “L” are valid names of kinds. Which means “list of L” is also a valid kind, and we can return it.

For a practical example, here’s the only time I’ve ever used descriptions as arguments, or parameterized kinds:

To print a/the/-- list of (T - text) for (D - description of values of kind K), prefacing with is/are and/or disjunctive:
	let N be the number of D;
	if prefacing with is/are:
		say "[if N <= one]is[else]are[end if] ";
	if N is zero:
		say "nothing";
		stop;
	let J be 1;
	push the listing parameter;
	repeat with V running through D:
		set the K being listed to V;
		say T;
		if J is N: [Final one]
			next;
		else if J is N minus 1: [Second-to-last]
			if N > 2 and the serial comma option is active: [Only print a serial comma if there are three or more items]
				say ",";
			say " [if disjunctive]or[else]and[end if] ";
		else: [Any other]
			say ", ";
		increment J;
	pull the listing parameter.

In other words, this is a way to write a nice list of any kind, not just things! I need the argument to be specifically a “description of values of kind K” to bind K, so that I can do things with K variables in the code.

What do I do with those K variables? Well:

To decide which K is the (name of kind of value K) being listed: (- listing_parameter -).
To set the (name of kind of value K) being listed to (V - K): (- listing_parameter = {V}; -).

Type-safety? What’s that? Here we’ve got some horribly unsafe casting: we can stick a value of any kind into a global variable (with “set the [name of K] being listed to [value of kind K]”) and read any kind out of it (with “the [name of K] being listed → K”). Use it responsibly.

3 Likes

Chapter 23 Figures, Sounds and Files

I’ve added sound and music to Quixe before, but only by manually editing the javascript files, never by using Inform’s default stuff. So I’m going to experiment along with this stuff.

Section 23.1 is Beyond text. It just says that if we use Glulx we can add files to things.

Section 23. 2 is How IF views pictures. This is just talking about cultural expectations around IF games and graphics.

In the cultural history of IF, graphics in text adventures have sometimes been looked at with suspicion. Mostly this is because attempts in the 1980s were not very successful, because computer graphics were so poor then (by modern standards). It may be that some people also felt that the takeover of computer games by graphical interfaces was the death knell of IF. But pictures are now rendered in superb quality by computers, and the death of IF turned out to be an exaggeration, so it is time to move on

I’ll admit, I’m not at all a fan of graphical adventure games more than others. I think adventure games can be fun (I really loved the Indiana Jones Atlantis game as a kid) but I have no desire to play Monkey Island or stuff like this. I like the text part of text games, not the world model and puzzles.

The section goes on to suggest hiring artists if you suck at art and that some devices can’t display images or have varying resolutions or color ranges.

Section 23.3 (No examples, this is all talk so far) says that IF story files are complex documents, not like pdfs or photographs. It says that a story file is itself a program for a virtual machine, which runs in the interpreter. (I always thought of the interpreter as the VM, but that’s because I don’t know the nitty gritty).

The last note is that some formats can incorporate images, while others can’t.

Section 23.4 is Gathering the figures.

First, we must use Glulx.

Inform calls pictures ‘figures’.

You have to put them in the Materials folder for your project in the Figures folder (creating one if there isn’t one yet).

For educational purposes, I will use the following public domain image for when the player attacks:

Section 23.5 is Declaring and previewing the figures.

With the images in the right folder, we name them like so:

Figure of Woodlands is the file "Woodlands.png".
Figure 2 is the file "Red Admiral Butterfly.png".

So I’m going to make

Figure of attack is the file "bam.png".

It should show up in the ‘Figures’ tab in the index (another tab I didn’t know existed until today! I should look at all of them some time):

image

Section 23.6 is Displaying the figures.

We can display images. It treats it just like text in that you can scroll away. To divide up the screen and use permanent images, you need fancy Glulx stuff.

To just print the image, we need to say:

display the Figure of Woodlands;

Or, in other words for my example:

display the figure of attack;

Let’s try it out:

The sandbox is a room. The mannequin is in the sandbox.

Figure of attack is the file "bam.png".

Instead of attacking something:
	display the figure of attack;

Man, that’s way too big! I’d need to edit that file size. Let’s resize it (not using inform) and recompile and try again:

image

Okay, that’s better.

Section 23.7 is Recorded sounds.

It warns us:

Sound support is very newly added to the system and work is still in progress. In particular, sounds are not played by Inform for OS X (although it does produce valid blorbed Glulx story files), though they should be audible from within the Inform application for Windows.

We have to use Glulx and not all interpreters support it.

Speaking of which…let’s try our ‘bam’ program in other interpreters first!

Works in gargoyle:

image

If I ‘release along with an interpreter’ and click ‘play.html’ and attack, it doesn’t show up:

image

Hmm, that must be why I ended up hacking my own stuff for the Inform version of Swigian. I know Brain Guzzlers from Beyond put images into Glulx that worked; how did Steph Cherrywell do that?

Anyway back to music, we hae to use AIFF (uncompressed, huge) or Ogg Vorbis. That was to avoid copyright issues for MP3, but I think MP3 is legal to use now after a copyright dispute (but I wouldn’t rely on that info, I just remember really worrying about it 5 years ago).

It then says not to pirate copyrighted music and that music won’t even play on Macs when using Inform 7’s built-in interpreter.

Section 23.8 is Declaring and playing back sounds.

We make a ‘Sounds’ folder in materials and download the sound. I’m using a dial up ogg vorbis sound from Wikimedia, so I also declare this in my code:

Sound of internet is the file "Dial_up_connection.ogg".

This is my figures Index:

image

That’s not promising!

Then we play it:
play the sound of rustling leaves;

I’ll try:

Instead of thinking:
   play the sound of internet;

It works! Both in my Inform 7 interpreter and in Gargoyle.

What about Quixe?

Nope, just says Sound effect number 4 here.

But I have a way to hack music into Quixe. You can check it out by loading my game Absence of Law here and typing ‘sou’:

https://media.textadventures.co.uk/games/wBrLVx-dkUa3_ER_VEQQBg/AbsenceOfLaw/index.html

Section 23.9 is Providing Accessibility text. This is just alt text, and it’s like so:

Figure 2 is the file "butterfly.jpg" ("A red admiral butterfly.").
Release along with cover art ("A cathedral at sunset.").
Fugue is the file "Bach.ogg" ("A church organ playing a Bach fugue.").

Alas, despite adding alt text to my sound, Quixe still just says ’
image

when it plays, even though I specified:
Sound of internet is the file "Dial_up_connection.ogg" ("An old moden dialing up").

Of course Vorple does all these things very well! (but my version does run in an offline local version of the html interpreter).

Section 23.10 is Some technicalities about figures and sounds

Kinds are important in Inform, and names for figures have the kind ‘figure name’. You can use this for variables:

The turn card image is a figure name that varies.

An Old Master is a kind of thing. An Old Master has a figure name called appearance. Figure 1 is the file "Giaconda.jpg". The Mona Lisa is an Old Master. The appearance of the Mona Lisa is Figure 1.

To place (F - a figure name) in the gallery: ...

Sound names have the value ‘sound name’.

In the blorb, things have internally given resource IDs. You can find them with the phrase ‘Glulx resource ID of (figure name)…number’.

And the following mysterious text:

(iv) Glulx hackers may also like to know that whenever Inform 7 builds a project for Glulx, the Inform 6 code it generates always contains a full copy of John Cater’s definitive header file “infglk.h”.

Section 23.11 is Files. It says that Inform files are run in a sandbox, which means it can’t infect the computer through malware. A Z-code game can’t affect any other files at all. But Glulx allows reading and writing to data files, basically like browser cookies.

Section 23.12 is Declaring files.

You declare a file like this:

The File of Glaciers is called "ice".

You can do this even before the file exists.

Filenames should follow these rules:

Quoted filenames should contain only letters and digits, should be 23 characters or fewer, and should begin with a letter. (In particular they can contain no slashes or dots - no subfolders or extensions can be indicated.) The actual filename this translates to will vary from platform to platform, but “ice.glkdata” is typical, stored in some sensible folder.

Each file has an ‘owner’, but you can declare that the file is owned by a different project:

The file of Boundaries (owned by another project) is called "milnor".
The file of Spectral Sequences (owned by project "4122DDA8-A153-46BC-8F57-42220F9D8795") is called "adams".

(We use the IFID to specify the owner, with the IFID given by typing VERSION during play or looking in Contents index, under the Card.)

I’m declaring the following:

The file of Amusing Deaths is called "lolfile".

And I get this in my figures index:
image

My ‘File of Amusing Deaths’ has a kind of value called ‘external file’. We can use text files or binary files. Binary files are declared as so:

The binary File of Glaciation Data is called "icedata".

I’m going to copy this into my project:

image

Section 23.13 is Writing and reading tables to external files.

Tables are focused on as everything else (mostly) can be contained in files. Here’s how we do it:

write File of Glaciation Data from the Table of Antarctic Reserves

All blank rows are ignored.

To load it back:

read File of Glaciation Data into the Table of Antarctic Reserves

you can check it with this:
if the File of Glaciation Data exists, ...

So I’ll try this out.

I’ll add commands for reading and writing to a file.

I’ll have a table of amusing deaths and a table of emptiness. One command will write the table of amusing deaths to an external file, and one command will load it into the table of emptiness and then print everything in that table.

If I try to load before writing, I get this reasonable error:

image

(I could have avoided this by checking if the file was empty)

Trying to write, though, gives me this error:

image

This was my code:

The File of Amusing Deaths is called "lolfile".

The binary File of Glaciation Data is called "icedata".

Table of Stuff
object	name
mannequin	"The mannequin punches you back!"


Table of Emptiness
object	name
--	--

Instead of jumping:
	write File of Amusing Deaths from the Table of Stuff;
	
Instead of going nowhere:
	read File of Amusing Deaths into the Table of Emptiness;
	repeat through the Table of Emptiness:
		say name entry;

So I think maybe having an object is bad? I’ll try to make it just text.

That works with no error for writing. Now to try loading:

image

(sorry the examples are nonsensical, I just wrote whatever popped in my brain).

Hmm, pretty neat! I wonder if this is the technique @Afterward uses for saves for his Fly Fishing game.

Now we have 3 examples!

Example 439 is Alien Invasion Part 23

Carry out selecting difficulty:
    choose row 1 in the Table of Preference Settings;
    now challenge level entry is difficulty understood;
    say "Puzzles will be [challenge level entry] from now on."

The File of Preferences is called "prefs".

When play begins:
    if File of Preferences exists:
        read File of Preferences into the Table of Preference Settings;
        choose row 1 in the Table of Preference Settings;
        say "(The current puzzle difficulty is set to [challenge level entry].)"

Check quitting the game:
    write File of Preferences from the Table of Preference Settings.

Table of Preference Settings
challenge level
easy

Example 440 is Labyrinth of Ghosts

Table of Ghostly Presences

haunted position score at death turns at death manner of death sequence
a grid location a number a number a demise a number
with 19 blank rows.
To have the player (sticky end - a demise):
    let the new sequence number be 0;
    repeat through the Table of Ghostly Presences:
        let S be the sequence entry;
        if S is greater than the new sequence number, let the new sequence number be S;
    increment the new sequence number;
    if the number of blank rows in the Table of Ghostly Presences is 0:
        choose row 1 in the Table of Ghostly Presences;
        blank out the whole row;
    choose a blank row in the Table of Ghostly Presences;
    now the sequence entry is the new sequence number;
    now the manner of death entry is the sticky end;
    now the turns at death entry is the turn count;
    now the score at death entry is the score;
    now the haunted position entry is the coordinates of the location;
    write the File of Ghosts from the Table of Ghostly Presences;
    now the latest demise is the sticky end;
    end the story saying "You have been [latest demise]".

The File of Ghosts is called "ghosts".

When play begins:
    if the File of Ghosts exists, read File of Ghosts into the Table of Ghostly Presences;
    sort the Table of Ghostly Presences in sequence order.

After looking:
    repeat through the Table of Ghostly Presences in reverse sequence order:
        if the haunted position entry is the coordinates of the location, say "You sense the ghostly presence of an adventurer, [manner of death entry] with a score of [score at death entry] in [turns at death entry] turns."

So all your previous deaths stick around permanently. Reminds me of Undertale, remembering what you do unless you delete the game (or DDLC, which I haven’t played).

Example 441 is Rubies, with a scoreboard:

When play ends:
    choose row 10 in the Table of Leaders; [we've sorted the table, so the lowest score will be the one at the bottom]
    if the score is greater than scored amount entry:
        now name entry is the player's forename;
        now the scored amount entry is the score;
    show leaderboard;
    write the File of Leaderboard from the Table of Leaders.

To show leaderboard:
    sort the Table of Leaders in reverse scored amount order;
    say "Current leading scores: [paragraph break]";
    say fixed letter spacing;
    repeat through Table of Leaders:
        if scored amount entry is greater than 0:
            say " [name entry]";
            let N be 25 minus the number of characters in name entry; [here we want to space out the scores so they make a neat column]
            if N is less than 1, now N is 1;
            say N spaces;
            say "[scored amount entry][line break]";
    say variable letter spacing.

To say (N - a number) spaces:
    repeat with index running from 1 to N:
        say " ".

There is a table of leaders too that isn’t copying to here nicely.

Section 23.14 is Writing, reading, and appending text to files.

This just erases a declared file and puts text in it:

write "Jackdaws love my big sphinx of quartz." to the file of Abecedary Wisdom;

If we don’t want to erase, we can just add more to a file (or create it if it doesn’t exist):

append "Jinxed wizards pluck ivy from the big quilt." to the file of Abecedary Wisdom;

This text can contain substitutions and be long.

To read it back, just put the following:

"[text of the File of Abecedary Wisdom]"

You can even copy one file to another:
write "[text of the file of Abecedary Wisdom]" to the file of Secondary Wisdom;

Example 442 is The Fourth Body:

A jotter is a kind of thing. A jotter has an external file called the text file. A jotter can be fresh or used. A jotter is usually fresh. A jotter has a text called the heading.

The currently erased jotter is an object that varies.
To erase (pad - a jotter):
    now the currently erased jotter is the pad;
    write "[heading of the currently erased jotter][paragraph break]" to the text file of the pad;
    now the pad is fresh.

To write in (pad - a jotter):
    append "[the time of day]: [topic understood][line break]" to the text file of the pad;
    now the pad is used.

To read (pad - a jotter):
    say "You read: [paragraph break][text of the text file of the pad]".

Example 443 is similar but with slight variations in how writing down things is handled. Since I didn’t copy that part of the code for the first example, I won’t here either.

Section 23.15 is Exchanging Files with other programs.

To avoid writing into an in-use file, we have a condition called ‘ready’.

if ready to read the file of Invariants, ...

How do we know something is ready? If we used the following phrase:

mark the file of Invariants as ready to read;

(by the way, I tried out the file writing in Quixe and it actually worked! I couldn’t find where it was storing it; cookies? Local storage?)

We can also mark things as not ready to read:

mark the file of Invariants as not ready to read;

These commands let us use non-Inform programs to communicate with Inform! Pretty wild. To do that we need to know some details which are in this section but which I will not copy, basically adding a cool header to the file encoded in ASCII Latin-1.

Example 444 is The Flathead News Network, which uses a background Perl script to fetch real time RSS headlines that update whenever the player looks at the news! Pretty wild stuff, I recommend checking it out.

1 Like

For my project, I included three different resolutions options for each image and let the player pick one. There are some surprising differences in the way images appear in different interpreters. :frowning:

2 Likes

Remember that files can be exchanged between games! (Or between different versions of the same game.) So the rule of thumb is, you can only read and write values that will make sense to a different Inform game. Numbers are fine, text is fine, objects are not—what if the other game doesn’t have the same object, or even any object at all, at that memory address?

This also applies to rules and phrases, though I have no idea why you’d try to save those to files.

If you don’t need the file to be compatible with other versions of your game (which might change memory addresses around), you can circumvent Inform’s type-checker and save objects anyway:

To decide what number is (O - object) serialized: (- {O} -).
To decide what object is (N - number) unserialized: (- {N} -).

But the easier way is just to give objects some property that’s guaranteed to be unique (and stable between versions) and store the value of that property instead. That’s what the ghosts example does with the room coordinates.

3 Likes

Chapter 24: Testing and Debugging

Section 24.1 Checking against the Index

This section says the index is a convenient way to check if you defined things correctly, like forgetting to make something scenery or accidentally creating two of an item.

I traditionally relied on custom things to do this (like printing out the description of every item), but working through this book has shown me how useful the Index is.)

Section 24.2 is Debugging features to use in source

The TEST command is great. I use this all the time to ensure that my game is still completable after changes.

You make new test commands like this:

Test me with "up / kill captain eo".
Test eo with "zap eo" holding the ray gun.
Test dinner with "eat bread / eat soup / eat butter" in the Ship Cafeteria.

Then you can start the game and type TEST ME or TEST EO, etc.

You can also merge tests:
Test megatest with "test me / test eo".

We can also use ‘showme’ in the middle of phrases to see what’s going on:

To say key score:
    let count be the number of keys which are not carried by the player;
    showme count;
    if count is greater than 2 and the player is timid:
        say "You're still missing a lot of keys, bucko!"

I’ve only recently started using SHOWME in this way; I previously would print out stuff like 'The current action is [current action]", or pretty often (I know this is stupide and childish) ‘say “poop”;’, since I knew I’d have to delete that (sorry if that stuck around in any of my games!)

Section 24.3 is High-level debugging commands

This includes SHOWME as an in-game command, which lists tons of stuff like this:

>SHOWME BAT
bat - thing
location: on the table in Locker Room
singular-named, improper-named; unlit, inedible, portable, patterned
printed name: "bat"
printed plural name: none
indefinite article: none
description: none
initial appearance: none

Another useful command I only learned about recently is ACTIONS, which gives output like this:

>ACTIONS
Actions listing on.

>JUMP
[jumping]
You jump on the spot.
[jumping - succeeded]

Something I’ve used for a very long time is RULES, which announces all rules which are running:

>RULES
Rules tracing now switched on. Type "rules off" to switch it off again, or "rules all" to include even rules which do not apply.

>JUMP
[Rule "announce items from multiple object lists rule" applies.]
[Rule "set pronouns from items from multiple object lists rule" applies.]
[Rule "before stage rule" applies.]
[Rule "instead stage rule" applies.]
[Rule "investigate player's awareness before action rule" applies.]
[Rule "player aware of his own actions rule" applies.]
[Rule "check stage rule" applies.]
[Rule "carry out stage rule" applies.]
[Rule "after stage rule" applies.]
[Rule "investigate player's awareness after action rule" applies.]
[Rule "report stage rule" applies.]
[Rule "report jumping rule" applies.]
You jump on the spot.
[Rule "last specific action-processing rule" applies.]

[Rule "A first turn sequence rule" applies.]
[Rule "every turn stage rule" applies.]
[Rule "A last turn sequence rule" applies.]
[Rule "notify score changes rule" applies.]
>

This is very useful in helping to track down problems. For some stuff though it doesn’t print anything, which always frustrated me until I learned (recently) that they are activities, which sadly don’t have an ACTIVITIES command.

Similarly, we have SCENES, which keeps a running list of scenes that are starting, running, or stopping.

RELATIONS and RESPONSES respectively print out all relations (I’ve never used this) and all responses (I use this a ton to figure out what responses to change!)

Finally, RANDOM sets the random generator to a specific seed, which lets the player avoid randomness in testing.

Section 24.4 is Low-level debugging commands

This is stuff like PURLOIN, ABSTRACT, and GONEAR, which respectively move something to the player (purloin sandwich), move something as direction (abstract sandwich to table), and move the player to the location of the object (gonear sandwich).

You can get runtime errors if you type dumb stuff into this.

You can also build-in some of this stuff into testing commands:

Test me with "eat grain" in the Fertile Plain.
(This puts the player in Fertile Plain immediately, like using GONEAR but with less computational power)

Similarly, Test me with "drop table" holding the table. puts the table in the player’s inventory.

VERIFY checks if the storyfile is intact, but it’s pretty rare to use.

TREE lists all object containment. I’ve used it occasionally to check for stray objects that were defined wrong (especially if I mistyped the name and made two of the object).

SCOPE lists objects in scope, which I’m just learning about now.

SHOWHEAP shows how many bytes are free.

TRACE, TRACE 2,…,TRACE 5 give increasingly more detailed info on what the parser is doing when it parses a line (and yet there’s no activity command; why not?)

Section 24.5 is Adding new testing verbs and release for testing

This is just like a brainstorming session for things to add, like jumping to different chapters, status information, and checking which puzzles are satisfied.

If you want testers to have access to testing commands that are pre-made or that you put in ‘not for release’ sections, you can compile Inform with ‘release for testing’, an option in the IDE.

Section 24.6 is Testing for thoroughness, which contains code like I described earlier (I must have borrowed it from here or someone else’s project years ago):

When play begins (this is the run property checks at the start of play rule):
    repeat with item running through things:
        if description of the item is "":
            say "[item] has no description."

It also suggests the Object Response Tests by Juhana Leinonen. I tried downloading it from th public library in the IDE but it doesn’t compile, failing on the phrase ‘try the test-actor taking [the noun]’ and all other similar phrases.

Section 24.7 is Commands for beta-testers:

This just describes the TRANSCRIPT and TRANSCRIPT OFF commands., which allows beta testers to print out their adventures in the game. I know a lot of comp judges like to send in transcripts too, and IFComp automatically records people’s transcripts when people use the default interpreter.

Section 24.8 is Help from the user community, suggesting that people go to th exotic website intfiction.org to get programming advice and find testers. Sounds weird to me.

3 Likes

The version in the Public Library seems to be version 6. Version 7 from the Friends of I7 Github repository should work, I think: extensions/Juhana Leinonen/Object Response Tests-v7.i7x at 10.1 · i7/extensions · GitHub

3 Likes

Thank you, I downloaded that it worked very well!

1 Like

Chapter 25: Releasing

This is a pretty hefty chapter, all about release options. I’ve used ‘with an interpreter’, ‘with a website’, ‘with source’, and that’s about it.

Section 25.1 is just saying that to actually play your game people need a file, to which we can attach things.

Section 25.2 Bibliographic data

Here is some stuff you can add to the general info of an Inform game:

The story title is "Mansfield Perk".
The story author is "Janet Austen".
The story headline is "An Interactive Romance".
The story genre is "Romance".
The release number is 7.
The story description is "In Miss Austen's new interactive novella, Miss Henrietta Pollifax is adopted by the tempestuous landowner Sir Tankerley Mordant, and must make a new life for herself on the rugged moors."
The story creation year is 2005.

We don’t have to explicity declare the story title and author. You can type

"Mansfield Park" by Janet Austen as the first line and that will set the title and author. We wrap the author’s name in quotations if it has punctuation in it.

The only text substitutions allowed are ['] and unicode.

Here are the defaults:

Story title: Untitled
Story author: Anonymous
Story headline: An Interactive Fiction
Story genre: Fiction
Release number: 1

Section 25.3 is Genres

These are the 'standard categories`:

Comedy, Erotica, Fairy Tale, Fantasy, Fiction, Historical, Horror, Mystery, Non-Fiction, Other, Romance, Science Fiction, Surreal

‘Comedy’ is suggested instead of humor do to British/American differences. ‘Other’ is intended for things that aren’t really narrative, like Tetris.

Section 25.4 is The Library Card

This is a metadata file that can be processed by some interpreters and other info. It’s placed in the blorb of a blorbed file (blorb is like a zip for a story file that contains the story file, library card, cover art, etc.)

Section 25.5 is The Treaty of Babel and the IFID.

The treaty of Babel was an agreement in 2006 to create a standardized system for identifying games with a number system. Twine, Inform, and TADS and Dialogue have ways of doing this (I think Dialogue just tells you to go to a website and pick an IFID).

The goal is for it to be unique, like an ISBN.

Section 25.6 is The Release Button and the Materials folder.

Pushing the Release button makes a folder at the same level as the .inform folder and calls the new folder .materials. The author is intended to put images, sounds, etc. in that materials directory.

Releasing creates a Release folder in the Materials folder that gathers everything together. For me at least, any project that’s more than a simple blorb file is uploaded to websites as the whole release folder zipped up.

Section 25.7 is The Joy of Feelies. Feelies refers to early Infocom physical materials that came in the boxed set, like little toys, maps, manuals, etc.

Nowadays ‘feelies’ are often pdfs or images, things like maps or poems or other things.

If you want a feely included in your release folder, you place it in materials first and then includes a line like this:

Release along with a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3".

This gives a description and a filename for each file.

If the feelie is an html page, the convention is to create a folder with the name of the page you want and then put index.html in it.

Like this:

Release along with a file of "Baltrazar's Guide to Magic" called "Guide".

it is expected to sit inside a folder called “Guide”, with its home page being “Guide/index.html”.

Section 25.8 is Cover Art.

From my personal experience, Cover Art really helps with a game getting traction. One of my more popular games in terms of online plays in the last few years is The Magpie Takes the Train, which has excellent cover art that JJ Guest paid for.

Cover art will look best if created at 960 by 960 pixels, but should not be less than 120 pixels in either direction.

For Cover art, put a file called Cover.jpg or Cover.png in the materials folder, and add this kind of line:

Release along with cover art ("A cathedral at sunset.").

Section 25.9 is An introductory booklet and postcard

These two things are guides to how IF works. The introductory booklet is 8 pages long, written by Emily Short, that basically explains how to play a parser game.

The postcard is the same thing but smaller and written by Zarf and Lea Albaugh.

You can say stuff like:
Release along with cover art, the introductory booklet, a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3".

or
Release along with an introductory postcard.

Section 25.10 is A Website.

This makes the standard website you may have seen if you’ve played parser games online, including in this comp. It looks like this:
image
And is created by adding Release along with a website.

(Note that the website alone doesn’t play the game; that’s next section).

Section 25.11 is A Playable web page.

You say Release along with an interpreter, which automatically adds the website too.

The two standard interpreters are Parchment for Z-code and Quixe for Glulx, although parchment also works for Glulx. If you want to use parchment with glulx (which I’ve never tried!) you say:

Release along with the "Parchment" interpreter.

(This brings back fond memories of when I started playing IF and played a lot of games using parchment on iplayif.com on an ipad).

If you have some super fancy interpreter, just put it into the templates subfolder of materials and say:

Release along with the "Urbzig" interpreter.

Section 25.12 Using Inform with Vorple

This section basically says Vorple is cool but has its own website:

Section 25.13 is Website templates

You can name templates for websites and use them. The standard one is called “Standard”, and the only other default one is “Classic”.

If you had a template called ‘platinum’, you could put it in the materials folder in Templates. Here’s where the compiler will look for it (in order):

(a) the "Templates" subfolder of the project's own .materials folder, if this subfolder should exist;
(b) the "Templates" folder in the user's own library - on Mac OS X, this is:
    ~/Library/Inform/Templates
or on Windows:
    My Documents\Inform\Templates
or on Linux:
    /Inform/Templates
(c) the built-in stock of templates, currently only "Standard" and "Classic".

The template should be a folder with the name you’re going to give in quotations, and should have one or more of these things:

Platinum
    index.html
    source.html
    style.css
    (extras).txt

I’d like to see new templates made! We need a library of these things! Man that would be cool!

The easiest template is like so:

Platinum
    style.css

Parser players should crowdfund some money to get people like @lizadaly or @Grim to use their CSS wizardry to make some cool templates.

Section 25.14 is Advanced website templates

The way to make templates is first, take any ‘extras’ like special pages or images and put them in the template folder, and make a file called (extras).txt that does nothing but list the extras like this:

easter.html
egg.png

(By the way, here’s what a game released with the ‘classic’ format looks like:)

Anyway, to make the template, you include index.html and source.html with placeholder text.

I only recently learned about this because Aaron Reed left behind a vast machinery for Spring Thing that includes website templates that get automatically filled by data from excel files using python scripts.

To make a template, you put a reference to the css at the top:

<link rel="stylesheet" href="style.css" type="text/css" media="all" />

And you can use what are essentially text substitutions in HTML to get stuff replaced, like this:

[TITLE] becomes the story title
[AUTHOR] becomes the author's name
[YEAR] becomes the story creation year
[BLURB] becomes the story description
[RELEASE] becomes the release number
[COVER] becomes an image of the cover art (the small 120x120 cover image)
[DOWNLOAD] becomes the download link
[AUXILIARY] becomes the list of feelie-like files, if any
[IFID] becomes the IFID
[STORYFILE] becomes the "leafname" of the story file, e.g., "Bronze.gblorb"
[TEMPLATE] becomes the name of the template used to make the page
[SMALLCOVER] becomes the filename of the cover when used at a smaller size
[BIGCOVER] becomes the filename of the cover when used at full size
[TIMESTAMP] and [DATESTAMP] become the time and date of releasing

In source text, you can also put the following:

[SOURCE] becomes the portion of the source text on this page
[SOURCELINKS] becomes the navigational links
[SOURCENOTES] becomes the footnote matter at the bottom of the source
[PAGENUMBER] and [PAGEEXTENT] are such that the text "page [PAGENUMBER] of [PAGEEXTENT]" produces, e.g., "page 2 of 7"

Both [SOURCE] and [SOURCENOTES] must exist on the page, and [SOURCENOTES] must appear after [SOURCE] does in the file. (Of course the CSS in “style.css” might move the copy around on screen, but that’s another matter.)

You guys will be proud of me…I made my own template!

In my templates folder in my top-level Inform folder, I added a folder called ‘Ugly’. Inside it, I made an index.html file whose entire contents were this:

<link rel="stylesheet" href="style.css" type="text/css" media="all" />

<body>
[TITLE]

[COVER]

</body>

I added release along with an "Ugly" interpreter to the code.

And…are you ready for the results?

image

I plan on copyrighting this ‘Ugly’ template and licensing it to other authors, so please don’t steal :triumph:

I think I’ll stop there for the day so casual browsers can easily see my gorgeous website, and also because the rest of this chapter has super complex stuff about making a map in Inform.

4 Likes

Okay!

Chapter 25, cont.

Section 25.15 is Republishing xisting works of IF. This is actually pretty cool! It’s a way to take old Inform games (including Inform 6) and release them with a website, feelies, etc. even without access to the source code. You just type:

Release along with an existing story file called "Zork1_sg.z5".

which works as long as a story file of that name is in the .materials folder. If you don’t provide a storyname, it looks for Story.z8.

You have to have the settings panel set to Z-machine to do this.

So here’s how you could use the Inform 7 IDE to rerelease Curses (example in the text):

"Curses" by Graham Nelson

The story genre is "Fantasy".

The story headline is "An Interactive Diversion".

The story creation year is 1993.

The release number is 16.

The story description is "It's become a matter of pride now not to give up. That tourist map of Paris must be up here somewhere in all this clutter, even if it has been five years since your last trip. And it's your own fault. It looks as if your great-grandfather was the last person to tidy up these lofts..."

Release along with cover art and an existing story file.

Section 25.16 is pretty cool, I tried it out last night: Walkthrough solutions.

So if you type Release along with a solution, it makes a walkthrough for you!

Sort of.

What it does is it makes a walkthrough as long as your Skein in the Index makes it to some pre-determined point.

The way you choose that point is by annotating a ‘knot’ (or more than one knot) with three asterisks: ***

Then Inform will provide a walkthrough with the skein commands that go there. If you have more than one annotated ending knot or it it branches for any other reason, the walkthrough will branch:

Solution to "Memoirs of India" by Graham Nelson

Choice:
INVENTORY -> go to branch (1)
EAST -> go to branch (2)

Branch (1)
DROP MANUSCRIPT
SOUTH

Branch (2)
INVENTORY ... Always a good idea
GIVE MANUSCRIPT TO THOMAS

And this is all in a text file.

I found this very convenient, and used it to create the walkthrough I sent out to my most recent tester last night. I always hated the skein because my nonlinear games have so many different starts that it gets really tangled, but knowing I can mark a single best point is nice.

Section 25.17 is Releasing the source text

You just type:
Release along with the source text.

If not making a website, this just makes a plain text file.

If making a website, it make a cool tree of webpages based on your heading structure.

Comments in the source that start with an asterisk will be printed as footnoted.

Thus comments thus:

Hercules is a demigod.[* We're using Greek spellings so he ought to be Heracles, but players are so much more familiar with Hercules.]

will be printed more like so:

Hercules is a demigod.[1]
...
Note
[1]. We're using Greek spellings so he ought to be Heracles, but players are so much more familiar with Hercules.

Source text is automatically linked from the webpage if both are corrected. This can be made hidden with:

Release along with the private source text.

You can also Release along with the library card which takes the metadata from the gblorb and puts it into a separate xml file.

Section 25.18 is Improving the index Map.

I like using the index map, because it shows me if I forget to put some room in a region or if I didn’t connect it to other rooms or made a duplicate.

Apparently that map can be output into a cool printed map! I didn’t know it!

It says,

The map-maker is one of the most complex parts of Inform, even though it actually contributes nothing to the final story file: the problem of how to draw up a "correct" map from the source text is by no means easy to solve.

I’ve never tried using it for this purpose before; has anyone else used an Inform-generated map before?

So you can alter the way the Index map is drawn by commands that only alter the physical position of rooms on the map and not the actual in-game connection between the two.

So you can say stuff like:
Index map with Didcot mapped southeast of Abingdon.

or

Index map with Beach Hut Interior mapped west of Sweeping Sands.

So I’ll try this with a copy of my game Swigian that I had on my computer. This is what the map looks like without intervention on one of the levels:

image

I then added this line of code:
Index map with Darkness mapped west of Mead Room and Rocky Summit mapped north of Mother.

and got this result back:

image

Pretty nice! The two stray rooms are now closer together.

Section 25.19 is Producing an EPS Format map.

So the ‘index map with’ stuff actually has 4 possible inputs, not just what we saw!

You can index a map with the following things:

[room A] mapped [direction] of [room B]
EPS file
rubric [text] ... and some optional details ...
[setting] of [whatever] set to [value]

The second one is invoked by typing Index map with EPS file.

This creates a barebones file in .materials called Inform Map.eps that is supposed to be ugly and hard to display because the intent is that it will be modified.

I just tried using this feature. Unfortunately, the resulting .eps could not be imported into GIMP or Libre Office Draw, both giving errors like ‘Image filter not found’, ‘input/output errors’, etc.

I finally got it to work using a web-based EPS viewer which converted it to PDF for me. Here’s a screenshot of part of it:

Section 25.20 is Settings in the map maker. Apparently there are 35 named settings! Each level has their own independent 24 settings.

You can select room size like so, with the numbers referring to 1/72nd of an inch:

Index map with room-size set to 36 and room-size of level 2 set to 28 and room-size of the Hall of Kings set to 52.

I tried those exact same setting in my game (except making my room Mother larger since I don’t have a Hall of Kings). It didn’t change the in-Index map, but it did change the EPS map:

But I didn’t notice any changes to level 2 and stuff, even when I went back and made them only ‘4’, so I wonder if I just misunderstood what a level is. I even tried setting level 2 to 100 and nothing happened. Sad!

Out other options include room-outline-thickness. And we can mess with regions and kinds of rooms.

Index map with room-outline-thickness of the first room set to 2.

A rivery room is a kind of room. Index map with room-colour of rivery rooms set to "Navy" and room-name-colour of rivery rooms set to "White".

Northern Oxfordshire is a region. Hampton Poyle and Steeple Barton are in Northern Oxfordshire. Index map with room-name-font of Northern Oxfordshire set to "Helvetica-Oblique".

I was able to get a few of these to work in my game:
image
(Here you see the navy rooms, one of which is not navy because I forget to include it.)

I’m not really seeing the different font (it’s in the EPS file, just doesn’t show up here in the blue regions in the top). The navy coloring and the thicker line around the first room of the game (not shown here) also do show up in the in-interpreter Index map.

Section 25.21 is Table of map-maker settings, which is just a list, including things like subtitle and title size, font, colour, etc., and the thickness of routes (and route-stiffness, an integer for a Bezier spline curve scale factor.):

Section 25.22 is Kinds of value accepted by the map maker.

This just explains the previous section. It has this useful info about fonts which might explain the result I had with font changes:

Font names are in double-quotes: "Helvetica", etc. Note that Inform makes no effort to look for such fonts: if we give the name of a font we haven't got, the result will probably be that the map's EPS file will be displayed in various applications with Courier (which looks like bad typewriting) substituted. All fonts are by default equal to the global "font" setting (by default equal to "Helvetica"), so changing "font" for the whole map affects everything not explicitly specified as having a different font.

The shape of the box can be changed, with the only options being ‘circle’, ‘square’, and ‘rectangle’.

It mentions that the only real use of the Bezier curve is going around a corner, with stiffness values starting a 100 and going between limits of around 1 and 250.

This is the list of possible colors:

Summary

“Alice Blue”
“Antique White”
“Aqua”
“Aquamarine”
“Azure”
“Beige”
“Bisque”
“Black”
“Blanched Almond”
“Blue”
“Blue Violet”
“Brown”
“Burly Wood”
“Cadet Blue”
“Chartreuse”
“Chocolate”
“Coral”
“Cornflower Blue”
“Cornsilk”
“Crimson”
“Cyan”
“Dark Blue”
“Dark Cyan”
“Dark Golden Rod”
“Dark Gray”
“Dark Green”
“Dark Khaki”
“Dark Magenta”
“Dark Olive Green”
“Dark Orange”
“Dark Orchid”
“Dark Red”
“Dark Salmon”
“Dark Sea Green”
“Dark Slate Blue”
“Dark Slate Gray”
“Dark Turquoise”
“Dark Violet”
“Deep Pink”
“Deep Sky Blue”
“Dim Gray”
“Dodger Blue”
“Feldspar”
“Fire Brick”
“Floral White”
“Forest Green”
“Fuchsia”
“Gainsboro”
“Ghost White”
“Gold”
“Golden Rod”
“Gray”
“Green”
“Green Yellow”
“Honey Dew”
“Hot Pink”
“Indian Red”
“Indigo”
“Ivory”
“Khaki”
“Lavender”
“Lavender Blush”
“Lawn Green”
“Lemon Chiffon”
“Light Blue”
“Light Coral”
“Light Cyan”
“Light Golden Rod Yellow”
“Light Grey”
“Light Green”
“Light Pink”
“Light Salmon”
“Light Sea Green”
“Light Sky Blue”
“Light Slate Blue”
“Light Slate Gray”
“Light Steel Blue”
“Light Yellow”
“Lime”
“Lime Green”
“Linen”
“Magenta”
“Maroon”
“Medium Aquamarine”
“Medium Blue”
“Medium Orchid”
“Medium Purple”
“Medium Sea Green”
“Medium Slate Blue”
“Medium Spring Green”
“Medium Turquoise”
“Medium Violet Red”
“Midnight Blue”
“Mint Cream”
“Misty Rose”
“Moccasin”
“Navajo White”
“Navy”
“Old Lace”
“Olive”
“Olive Drab”
“Orange”
“Orange Red”
“Orchid”
“Pale Golden Rod”
“Pale Green”
“Pale Turquoise”
“Pale Violet Red”
“Papaya Whip”
“Peach Puff”
“Peru”
“Pink”
“Plum”
“Powder Blue”
“Purple”
“Red”
“Rosy Brown”
“Royal Blue”
“Saddle Brown”
“Salmon”
“Sandy Brown”
“Sea Green”
“Sea Shell”
“Sienna”
“Silver”
“Sky Blue”
“Slate Blue”
“Slate Gray”
“Snow”
“Spring Green”
“Steel Blue”
“Tan”
“Teal”
“Thistle”
“Tomato”
“Turquoise”
“Violet”
“Violet Red”
“Wheat”
“White”
“White Smoke”
“Yellow”
“Yellow Green”

It mentions that when doing ‘offsets’ (one of the options), you need to give two numbers like
"Index map with room-offset of Botley set to 10&-30."

I tried this:


Index map with title set to "Awesome map" and subtitle set to "This is complex."

But it didn’t change the Index map or the output. In fact, the .eps file doesn’t even contain the words ‘awesome’ or ‘complex’.

An even bigger issue to me is that the output truncates room names to make them fit, so even the .eps file only has abbreviations.

So so far this whole complex system just isn’t producing useful output for me, being incompatible with most problems and not transmitting vital information. I may be deeply misunderstanding it, though, so feel free to suggest fixes.

Section 25.23 is Titling and abbreviation.

This section deals with my two complaints! It says ‘subtitle’ should be used like this:

Index map with subtitle of level -1 set to "Tunnels and Sewers".

Hmm, so I changed my commands to:


Index map with title set to "Awesome map".

Index map with subtitle of Level 1 set to "This is complex."

But still nothing, not in the Index or the EPS file.

(I’m using 6M62 btw).

It also says room name abbreviations are necessary so they don’t spill over. You can adjust this with the setting ‘room-name-length’.

It has a few examples:

Example 445 is Baedeker:

Dome is a room. North of Dome is North Chapel. South of the Dome is South Chapel. West of the Dome is Western End. Quiet Corner is northwest of the Dome, north of Western End, and west of North Chapel. Loud Corner is east of North Chapel, northeast of Dome, and north of Eastern End. Eastern End is north of Dim Corner and east of Dome. Dim Corner is southeast of Dome and east of South Chapel. Ruined Corner is southwest of Dome, west of South Chapel, and south of Western End.

The church door is east of Eastern End and west of the Courtyard. The church door is a door.

Index map with
    room-shape set to "square" and
    room-size set to 60 and
    room-name-size set to 9 and
    room-name-length set to 13 and
    route-thickness set to 20 and
    room-outline set to off and
    map-outline set to off and
    route-colour set to "White" and
    room-colour set to "White" and
    room-shape of Dome set to "circle" and
    room-size of Dome set to 80 and
    EPS file.

When I run this code and display it, I get this:

The image shown in the manual says that with some manipulation by Adobe we can get this:

image

Example 445 is Port Royal 5. I’ll again show the output I get and the one shown in the textbook.

Mine:
image

There’s (after editing):
image

The example 447 is Bay Leaves and Honey Wine.

Mine:

Theirs:

(The room names are white, which is why they aren’t showing up in my version).

Section 25.24 is Rubrics

You can add any text you want anywhere with stuff like this!

Index map with rubric "Here Be Wyverns" size 16 font "Helvetica-Oblique" colour "Thistle" at 150&0 from Cloud-Cuckoo-Land.

I’ve been a bit frustrated by this chapter, so I will not attempt this.

Does this stuff work better on other computers or with 10.1? The title and subtitle and room sizes per level just aren’t working for me.

2 Likes

I’ll be honest, I’ve never even tried the examples from this chapter. I don’t have a good vector graphics program so I use Trizbort to make maps instead (which tends to be pretty serviceable, though nowhere near as pretty as the ones here).

3 Likes

Chapter 26: Publishing

This is probably the lightest chapter at all, but has some good stuff in it.

Section 26.1: Finding a readership

This is the eternal struggle, right?

This section mentions that interactive fiction means a lot of things to a lot of people, and that choice-based mobile games are really popular right now.

Although it is not a typical tool for choice-based mobile games, Inform has been used to produce commercial works, both parser-based and not. Users are very welcome to sell works created by Inform with no royalty or requirement for rights clearance. It’s also widely used in education, and as a prototyping tool for other kinds of stories, such as interactive narratives that will ultimately take another (not text-based) form.

Section 26.2 is Editing and Quality Assurance

It says that if you think of IF as story, editing is important, and if you think of it as a game, beta testing is good, and gives this sound counsel:

Whatever the background, it’s good practice to have your work checked by other people before you release it. Other players can identify issues from typos to missing hints to thematic incongruities.

Play-testers can often be recruited by placing an ad on intfiction.org.

Section 26.3 is A Page of its Own

One option for publishing an Inform game is to just host your own website.

One option for sharing your work with the world is to set up a web page and a copy of the story file on a private web host. That host should ideally be as stable as possible, so that the URL is likely to remain fixed for what might be a long period. Freeware stories have a long period of viability relative to commercial games, which means that players may still be hearing about and checking out a story years after its initial release. A stable address helps everyone with links, and makes it easier for search engines to direct people.

For distribution platforms, it recommends itch.io over Steam or app stores.

Section 26.4 is The IF Archive

Because of the portable underlying format, however, games written in Inform are unusually stable and maintainable. Inform projects written in the early 90s can still be played – indeed, can be played on platforms that did not exist when the games were written.

This is true, and one reason I care a lot about archiving games: because we can! Flash may die, and console stores may obsolesce, but Inform games really last well, since you generally have to just port the interpreter once to put almost all games onto a new platform (excluding those using highly technical features like quote overlays or multiple windows).

It describes the IFArchive has a mirrored collection of if games, maps, walkthroughs, etc., and that its main focus is long-term archiving, not advertisement.

Uploading a work to the IF Archive is not too difficult, and can be done in two ways. One way is to use the archive’s web form at:

https://upload.ifarchive.org/cgi-bin/upload.py

The other is to create a new page at the Interactive Fiction Database, at:

https://ifdb.org/

It’s then possible to upload the story file to the IF Archive from IFDB. This is easiest all round, since it allows both IFDB and IF Archive to be updated at once.

I believe this is an error; I’m not aware of any way to use the IFDB interface to upload to IF Archive. If it’s there then I sure feel silly for not using it!

Given the recent flurry of several mini-controversies regarding archiving (of which I’ve instigated at least one), this is interesting:

Committing a story to the Archive is meant to be permanent. While the maintainers will happily replace older versions of stories with new improved releases, they are less eager to remove stories entirely. If that doesn’t seem appealing, or if we do not want our story to be treated as freeware with essentially unlimited distribution, the Archive may not be a good choice. But it is deeply valued by the IF community, and has saved many works which could otherwise easily have been lost forever. Many contributions important in the history of IF were made by people who are now not easy to trace, and whose websites are long gone. But their work lives on.

I heartily endorse these words. Write for the ages!

SEction 26.5 is IFDB: The interactive fiction database. It says this website is similar to IMDB or the iTunes music store. It allows people to read reviews or also play directly in the browser.

IFDB is community-editable, like Wikipedia, though editors are required to create an account and log in first – this is free, of course. A standard form is provided for creating a new record (accessible by selecting the option to add a story listing). More or less the same information that appears on Inform’s library card in the Contents index needs to be copied over: there’s space for the author name, story title, genre, and so on. IFDB will also ask for an IFID, a code identifying the story uniquely. Inform generates one of these automatically for each project, and it, too, is on the Library Card. It can always be found by typing VERSION into the compiled story and looking at the line that says

The download link should give the most stable URL available. If you have not yet uploaded your story to the IF Archive, you may do so by selecting the “Upload it to the IF Archive” link instead of pressing the “Add a Link” button. The benefits of submitting your story to the IF Archive in this manner are two-fold. One, IFDB will fill in much of the information required by the IF Archive for you. Two, the link to your story will not appear until the IF Archive maintainers move it to its permanent home in the archive, at which point the download link will be automatically updated and presented on the story page

This again. Is this true? I’ve got to see this.



I have never noticed this button in my life. I am IFDB’s most prolific user and an admin. I have added dozens of games to IFDB. Ever single time, I have skipped over this form.

I feel very dumb right now.

Wow.

A final quote from this text while I am recovering mentally:

Some awards for interactive fiction, such as the annual XYZZY Awards, require a game to have an IFDB entry as an eligibility requirement.

Section 26.6 is Competitions, Exhibitions, and Jams.

Wow, this includes a reference to ParserComp! Neat!

One very common way to get players for IF is to enter the story into an IF competition. The annual IF Competition, often just called IFComp, is the most prestigious and has the widest field, but the Spring Thing, ParserComp, EctoComp, and other events also catch people’s attention. Entering a competition is a path of least effort for authors promoting their new work, because the competition organizer usually takes care of hosting and archiving submitted stories, promoting the competition as a whole, collecting votes, and encouraging players to post reviews.

It references IFWiki for a list of events on the front page.

It mentions that longer games may not be a good fit for competitions (one reason I’m not going to release my 10+ hour game in a competition).

It mentions the XYZZY Awards as an annual event for games listed on IFDB, and suggests itch.io jams.

It finally references procjam for heavily procedurally generated projects.

Section 26.7 is Meetups and conferences. It suggests checking this url:

and Emily Short’s blog.

Section 26.8 is A Short Concluding Homily

I will just reproduce this in full, since I feel these are the true last words of the manual. We have another (fairly hefty) chapter coming up, but it’s not about writing your own game. So here are some ‘final’ words:

It’s natural to want to make a huge splash with a story, but in the IF community, instant widespread adulation for any work is pretty uncommon.

For one thing, players tend to play when they get around to it… which may be weeks, months, or even years after the initial release. Reviews trickle rather than flooding in. Appreciation builds slowly. And sometimes works that placed unspectacularly in a competition, or seemed to be overlooked in the annual XYZZY Awards, gradually come to be regarded as classics because of some pioneering technique.

So it’s wise (if difficult) not to judge a story’s success entirely by its immediate feedback. Even after its debut, a story can often use a little care and attention if it’s to reach all its potential fans – whether that means building further releases, posting hint files or walkthroughs, developing new websites, or approaching outside reviewers.

I think this was even true for Curses, Graham Nelson’s game that is my favorite out of the 2.5K+ games I’ve tried.

3 Likes

Steam discourages free games; Itch encourages them. If you’re not charging money, your clear choices are Itch, ifarchive.org, your own web site, or (why not) multiple of the above.

(Mobile app stores encourage “free-to-play” games but are also drowned in them, mostly the kind that try to suck money out of you anyway. Your free-as-in-ifarchive game will be lost in the noise.)

If you are charging money and expect to sell a meaningful number of copies – hundreds, long-term – it is worth considering Steam. Creating a Steam storefront page is a giant hassle but then money trickles in without further effort. (Mind you, if you do that, you should also make an Itch storefront page and charge the same amount.)

Of course, that money trickling in is reported to the government. So then you’re looking at Schedule C (for US taxpayers) or the equivalent. Research this before diving in.

4 Likes

By the way, as this let’s play is coming to a close, I’ve peaked through the Recipe Book, and it looks like it’s essentially just all the examples from Writing with Inform grouped by various classifications (e.g. complex NPC behavior).

Since I already touched on every example, should I just skip the recipe book and finish with Writing with Inform? Or go through the recipe book with an emphasis on trying out each of the examples as games?

While most RB sections do little more than list the examples with brief (perhaps even superbrief) descriptions, sometimes they’re pretty substantial, like Chapter 6: Commands. I’d be interested in what you had to say about them, and whether your view of any of the examples has changed.

1 Like

Last chapter of Writing with Inform!

Chapter 27: Using Inform 6 in Inform 7

Just kidding. The real title is:

Chapter 27: Extensions.

It just happens to have all the Inform 6 stuff in it.

Section 27.1 is The Status of Extensions, which has this interesting tidbit:

Between 1993 and 2006, quite a range of “library extensions” for Inform’s predecessor language (Inform 6) was written. Most of these extensions aimed to fill out the model by simulating other aspects of life, too: money, clothing, pourable liquids. None of these extensions was official and all of them were: it was a free-for-all, and in several cases different authors wrote rival extensions to model the same basic ideas.

Strange to thing that Inform 7 has been around longer than all previous versions of Inform were before it, all added up.

The section goes on to say that no extensions are ‘official solutions’, and that they can be private, but that some public extensions exists, namely, those archived on the Inform website. (Although these days there are like 5 places to find extensions).

ns as “public”. Public extensions are the ones archived on the Inform website for the free use of all Inform writers. Those who wish to contribute an extension as a public one are obliged to follow a number of guidelines, which are mostly stylistic points intended to make the range of extensions easier to work with.

When I made a conversation extension, several people in this forum really helped a lot to make it much more usable (my credits list Michael Lauenstein, Gavin Lambert and Matt Weiner, although I swear someone else helped a lot).

These public extensions all have the broadest creative commons license, even allowing people to do commercial work with them.

To publish a public extension is a public-spirited act, done for only the reward of a modest acknowledgement.

Section 27.2 is The Standard Rules

The standard rules are actually an extension! They have statements like

A container is a kind of thing.

When compiling starts it’s automatically included as an extension.

What happens when an “Include” sentence is reached is that the sentence is replaced with the whole text of the file in question, often many paragraphs long.

Each extension is only copied once, to prevent infinite recursion if two extensions include each other.

Section 27.3 is Built-in, installed and project-specific extensions

About 20 extensions are always built-in to inform, like Graham Nelson’s metric extension.

You can install other ones from the Public Library feature in Inform itself (which I swear has been deprecated) or using the ‘install extension menu’ in the application (I didn’t eve know that existed; I always just created an appropriate folder and copied the file inside it).

You can also make an extension only be for one project by putting it in an Extensions folder in a Materials folder. This can be used to override other extensions, even The Standard Rules!

Section 27.4 is Authorship.

Extensions are named, so two authors can name extensions the same thing.

The name of an extension, and of an author, should be written in Sentence Capitalisation: that is, upper case for the first letter in each word.

It suggests avoiding accents or ‘unusual’ letters in names.

The authors name can’t start with The or have by, and, or version in it.

Authors are encouraged to use real or real-sounding names:

Authors are asked to use real names rather than cryptic handles like “ifguy”, and to use genteel, plausible pseudonyms like “Emily Short” rather than, say, “Drooling Zombie” or “Team Inform”. Authors are also asked to use the same author’s name for all their own extensions, and (it should go without saying) not to masquerade as anybody else.

Extensions are name for the most recent updater, so if you take over someone’s extension (with permission!) your name goes on it instead of theirs.

Section 27.5 is A simple sample extension.

The last section ended with a note that it would show us how to credit other authors in this section, but that’s not here at all.

Instead, it just says that Extensions are plain text files that anything can edit, using Unicode UTF-8 encoding.

Here is a complete extension:

The Ducking Action by Beatrix Potter begins here.

"An action for ducking one's head."

Ducking is an action applying to nothing. Report ducking: say "You duck!" Understand "duck" as ducking.

The Ducking Action ends here.

It’s important that the only content of line 1 be the title with the author’s name and ‘begins here’, as shown. It needs to end with ‘ends here’ too, as shown. And any double-quoted sentence underneath the first line becomes the description of the extension (called the ‘rubric’).

If you add yet another double quoted line, you can add credits to earlier versions (oh, so I was wrong to say that the last section was wrong. Sorry!):

The Ducking Action by Beatrix Potter begins here.

"An action for ducking one's head."

"based on original Inform 6 code by Marc Canard"

Example 448 is an extension for modern conveniences in kitchens, making every kitchen have a fridge, a freezer, etc. Although it’s written as a game, not an extension; this isn’t too strange, as extensions just get copied into games.

The only extension-specific thing here is that lots of rules are named so they can be manually overwritten by games using the extensions:

Setting action variables for opening a stove (this is the stove-opening rule):
    let relevant oven be a random oven which is part of the noun;
    now the noun is the relevant oven.

Setting action variables for switching on something which includes a switch (this is the redirecting switches for switching on rule):
    let relevant switch be a random switch which is part of the noun;
    now the noun is the relevant switch.

Setting action variables for switching off something which includes a switch (this is the redirecting switches for switching off rule):
    let relevant switch be a random switch which is part of the noun;
    now the noun is the relevant switch.

Before printing the name of a switch (called target) (this is the switch identification rule):
    say "[random thing which includes the target] ".

A sink is a kind of container. A sink is usually fixed in place and scenery. A tap is a kind of switch. A tap is part of every sink. Understand "faucet" or "taps" as a tap. Understand "[something related by reversed incorporation] tap/faucet/taps" as a tap.

Section 27.6 is Version numbering.

You can do version numbers like this:

Include version 2 of the Ducking Action by Beatrix Potter.

Version 1.2.4 of the Ducking Action by Beatrix Potter begins here.

The rules for extensions are that you can only use whole numbers with dots between them.

There used to be a complicated version of numbering where it was the version number, followed by a slash, followed by the date in YYMMDD:

Version 6/040426 of the Ducking Action by Beatrix Potter begins here.

Now that’s not really used. An extension that uses that will just internally turn the backslash character into .0.

Inform tries to use the semantic version numbering (and suggested going to semver.org)

In this versioning style, there are three numbers, X.Y.Z. You change X if your changes break compatibility. You change Y if you add new stuff that’s backwards compatible. And you change Z when you make minor bug fixes.

You can be general or specific in which version you need:
Include the Ducking Action by Beatrix Potter.
Include version 2.4 of the Ducking Action by Beatrix Potter.

However many of X,Y, and Z you specify, Inform looks for, so if you just say Version 2, it will accept 2.4, 2.4.1, etc.

The VERSION command will tell you what versions of things are beings used (I use VERSION a lot when I play games, especially if they look non-standard or if I can’t tell if they’re inform, as was the case when I first tried @nilsf’s games.)

You can print this list at any time with the following:

say "[the list of extension credits]"

To make your extension uncredited, say
“Use authorial modesty”. It makes extensions by the author of the current game not get mentioned.

You can bypass this by saying [the complete list of extension credits]

Section 27.7 is Extensions and story file formats

Inform has Glulx and Z-machine, and extensions might not work in one of those!

You can restrict an extension you make like so:

Version 2 of Basic Screen Effects (for Z-Machine version 8 only) by Emily Short begins here.

or (for Glulx only), etc.

Extensions can also have some sections only used for certain formats:

Section 2.3G (for Glulx only)

To reveal the explosion:
[...the Glulx way...]

Section 2.3Z (for Z-machine only)

To reveal the explosion:
[...the Z-machine way...]

Example 449 is Tilt 3, which is about playing cards (we’ve seen Tilt 1 and Tilt 2 before)

It has this innovation:

Section 0Z (for Z-machine only)

Include Basic Screen Effects by Emily Short.

Section 0G (for Glulx only)

Include Basic Screen Effects by Emily Short.

Section 0G (for Glulx only)

Section 27.8 is Extensions can include other extensions, like so:

Version 1 of Basic Help Menu by Emily Short begins here.

Include Menus by Emily Short.

This is fine, but if multiple different version are requested that are incompatible, this is bad.

If making your own extension that relies on other extensions, the requested format is to mention the other extension early on.

Section 27.9 is Extensions can interact with other extensions.

You can make your extension do stuff only if other extensions are present, like this:

Chapter 2a (for use with Locksmith by Emily Short)

Chapter 2b (for use without Locksmith by Emily Short)

You can also replace other sections of code wholesale (this would be fun for demolishing standard rules):

Section 6 - Hacked locking (in place of Section 1 - Regular locking in Locksmith by Emily Short)

If the section being replaced has ‘in’ in its name, put the whole section in quotation marks:

Section - Hacked questions (in place of "Section 4 - Phrase used to ask questions in closed mode" in Questions by Michael Callaghan)

Section 27.10 is Extensions in the Index

The contents lists each index, and the Kinds index lists kinds created by an extension. You can give people gentle help by a ‘specification’:

The specification of player's holdall is "Represents a container which the player can carry around as a sort of rucksack, into which spare items are automatically stowed away."

This actually appears in the Kinds index:

image

Unfortunately, I didn’t put specifications in the extension I made. Sad.

Extensions have their own content headings and numbering.

Finally, any phrase or variable defined immediately under a heading whose name ends in the word “unindexed” will be omitted from the Phrasebook or Contents index respectively. (That won’t apply to definitions under subheadings of the heading.) This is intended so that technical apparatus used only inside the extensions can be concealed from the outside user’s immediate view. Inform as it is presently constituted does not allow extensions to make fully private definitions, but this feature at least allows them to make unadvertised ones.

Section 27.11 is Extension Documentation.

When making an extension, you add a documentation section at the very end (after the … ends statement):

...
The Ducking Action ends here.

---- DOCUMENTATION ----

This is a modest extension, with much to be modest about. It allows us to use a new action for ducking, as in ducking the player's head (not as in ducking a witch). Ducking will do nothing unless rules are added:

    Instead of ducking in the Shooting Gallery, say "Too late!"

...

Saying ‘we’ is preferred over ‘you’ in the ‘house style’ of writing extensions.

It says something weird about how to indent code examples and tables, but doesn’t say why. Looking at my extension, all the code examples are indented, so that makes sense.

Here are some of the code examples in my extension:

Example: * The Raven - Having a single topic with a single target.

	*: "The Raven"
	
	Include Clues and Conversation by Brian Rushton.

	The Study is a room.

	Poe is a man in the Study. The description of Poe is "A man who seems to awaiting a pronouncement of eternal doom."

	When play begins:
		deliver Doom;
		
	Doom is a quip. The preview of Doom is "Nevermore".

	The target of Doom is Poe. The TargetResponse of Doom is "'Nevermore', quoth you.

	'No!' screams Poe."

	Report uttering Doom to Poe:
		end the story finally;

	Test me with "I / talk to poe / T / say Doom"

Example: * The Detective - Having a single clue with no specific target.

	*: "The Detective"
	
	Include Clues and Conversation by Brian Rushton.

	The Study is a room. Parlor is north of the Study.

	Watson is a man in the Parlor. The description of Watson is "Watson is interested in everything you have to say."

	When play begins:
		deliver Ash;
		
	Ash is a clue. The preview of Ash is "The ash was from a cigar manufactured in Greenland.".

	The TargetResponse of Ash is "'This is a Greenland cigar', you shout.

	'Hurrah!' says Watson."

	Test me with "T / say Ash / N / say ash / T"
	

Section 27.12 is Examples and headings in extension documentation

You can divide up your documentation like so:

Chapter: Avoiding Events

Section: Ducking examinations and tests

It says this will automatically make them stand out and make a table of contents, but I must have messed that up in my own extension, because mine looks like this in the IDE:

image

Even though each section is bolded when editing the actual extension.

You can make up to 26 examples, and you make them like this (with asterisks representing number of stars of complexity):

Example: ** We Must Perform a Quirkafleeg - Ducking to avoid arrows as one proceeds east across battlements.

Each example should (normally) contain one single, complete, story, long enough to demonstrate the use of the extension and to have a little flavour to it, but not so long that the reader gets lost. It should have a title, which should match the name of the example (in the case above, “We Must Perform a Quirkafleeg”). It should conclude with a paragraph defining a test:

Test me with "east / duck / east / jump / east / duck / east / rescue esmerelda".

There is a bit about adding a ‘paste’ button; apparently adding *: before an example gives a paste button.

Section 27.13 is Implications

This is about ‘usually’ stuff when applied to objects with properties. I haven’t really seen these before. It’s when you have conditions both before and after the implications:

Something locked is usually lockable.

This is different from ‘usually’ statements applied to kinds of things, because ‘something locked’ isn’t a kind.

I’ll stop there for today. Tomorrow will be the finale, as well as all the Inform 6 stuff!

4 Likes

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:
image

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.

11 Likes

It becomes Inform 6 again later. (Assuming you’re compiling for Glulx. Compiling Inform to C code is a different kettle of shoggoths.)

[ PrintCenteredStatus i j;
    @set_cursor 1 0;
...

This example doesn’t compile for me…

This is Z-code assembly. The example should really mention that.

Include (- with before [; Go: return 1; ], -) when defining a vehicle.

This glues in a new property [the before 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.)

The DM4 documents the Inform 6 language and also the I6 library. before/after/react_before/react_after are I6 library properties. This footnote explains that the Inform 7 library is structured completely differently, which is true; therefore there’s no point in mentioning the before property in the first place. You can ignore it.

Maybe Graham Nelson was doing everything he could to keep people from using I6?

Well, yes. The reason for that is that this chapter doesn’t document enough about I6 to let you write a game. It’s way beyond the scope of this manual. This chapter is an overview of how to interface with the I6 internals in a few key ways. Making use of that is entirely your problem.

Also, even if you figured out how it worked, it would be substantially rearranged in the next I7 release and you’d have to figure it out all over again.

1 Like

Well, I have silently followed the debate (indeed, I have a pair of comment to do…) but what matters is that thanks to Brian and all whose have partecipated to the debate, I guess we have enough material for…

a critical edition of the WI

and, I must note that the copyright holder is an oxonian academic, so he should, noblesse oblige, gracefully allow the publication of a critcal edition of his work…

(OTOH, he admitted that in developing Inform 1 to 6 during the 90s, he has taken many notes from r.a.i.f. so I think that the reciprocal should be similarly mutually beneficial… )

Best regards from Italy,
dott. Piergiorgio.

2 Likes

Thanks, Brian. This was great and I look forward to closely rereading the whole thing.

4 Likes