Chapter 22: Figures, Sounds and Files
22.12. Writing and reading tables to external files

The main use for files is to store and retrieve data, and the most flexible form of data used by Inform is the Table, so facilities are provided which make it as easy as possible to write and read the contents of a table to files.

To save the contents of a table to a file, we use the phrase:

write (external file) from (table name)

This phrase causes the entire contents of the given table to be written out to the given file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:

write File of Glaciation Data from the Table of Antarctic Reserves

Any blank rows in the table are automatically moved to the bottom, and only the non-blank rows are written.

To load a file back into a table,

read (external file) into (table name)

This phrase causes the entire contents of the given table to be read in from the given file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:

read File of Glaciation Data into the Table of Antarctic Reserves

Any rows left spare at the foot of the table are automatically blanked. On the other hand if the file is too large to fit into the table - with too many columns or too many rows - a run-time problem is produced.

We can check if a file already exists using:

if (external file) exists:

This condition is true if the file-system used by the player appears to contain a file with the right name. For example, if we declared:

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

and then tested

if the File of Glaciation Data exists, ...

then Inform would search for a file called "icedata". (The arrangements for where this might be stored, and its filename extension, vary from platform to platform.)

One unfortunate restriction must be kept in mind. Some of what is stored in tables is solid information whose meaning never changes: the number 342, for instance, means the same to everyone. But other information depends entirely on the current location of certain structures in memory - for instance, a rule is internally referred to by its memory location. This potentially changes each time Go or Replay is clicked, and so it is not safe to pass it from one copy to another, or from one project to another. The only tables which Inform allows us to write into files are those containing "safe" data: numbers, units, times of day and kinds of value with named alternatives. Scenes, rules or rulebooks, in particular, are not allowed.

And nor is text - but we can easily get around that, because indexed text (see the previous chapter) is. For instance, the following table can legally be written out to a file, whereas it would have thrown up a run-time problem if we tried it with the surface column defined simply as text:

Table of Neptune's Moons
moon   surface (indexed text)   
1   "utterly unknown"   
2   "cryovolcanic ridges"   
3   "highly irregular and sooty"   


429
* Example  Alien Invasion Part 23
Keeping a preference file that could be loaded by any game in a series.

RB

Suppose that we have a series of games each of which allows the player to select a puzzle difficulty level. When the player plays a new game in the series, we want him to start out by default with the same difficulty level he faced earlier on, so we store this information in a small preferences file, as follows:

"Alien Invasion Part 23"

A difficulty is a kind of value. The difficulties are easy, moderate, hard, and fiendish.

Understand "use [difficulty] puzzles" as selecting difficulty. Selecting difficulty is an action out of world, applying to one difficulty.

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

The Sewer Junction is a room.

Our preference file is restricted to a single option here for simplicity's sake, but we could keep track of more information -- whether the player preferred verbose or brief room descriptions, screen configurations, and so on.

If we were disposed to be somewhat crueler, we could use a similar method to make the player finish each episode of the series in order to "unlock" the next. All we would need to do is store a numerical password in our preferences file when the player finished a given level; the next level would check, say, the Table of Completed Levels for that password, and refuse to play unless the right number were present.

430
** Example  Labyrinth of Ghosts
Remembering the fates of all previous explorers of the labyrinth.

RB
431
*** Example  Rubies
A scoreboard that keeps track of the ten highest-scoring players from one playthrough to the next, adding the player's name if he has done well enough.

RB


PreviousContentsNext