| 21.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 File of Glaciation Data from the Table of Antarctic Reserves
naming the file (which should be one already declared) and specifying which table it should come from. To load a file back into a table,
read File of Glaciation Data into the Table of Antarctic Reserves
We can check if a file already exists using:
if File of Glaciation Data exists, ...
On writing a table, any blank rows are automatically moved to the bottom, and only the non-blank rows are written; on reading a file back in, 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.
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, weareas 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" |
The trick here is that we need a table with indexed text in order to keep track of the players' names.
Part 1 largely replicates the source from "Identity Theft"; new material starts at Part 2.
"Rubies"
Part 1 - Collecting Names
The player's forename is an indexed text that varies. The player's full name is an indexed text that varies.
When play begins:
change the command prompt to "What is your name? > "
To decide whether collecting names:
if the command prompt is "What is your name? > ", yes;
no.
After reading a command when collecting names:
if the number of words in the player's command is greater than 5
begin;
say "[paragraph break]Who are you, a member of the British royal family? No one has that many names. Let's try this again.";
reject the player's command;
end if;
change the player's full name to the player's command;
change the player's forename to word number 1 in the player's command;
change the command prompt to ">";
say "Hi, [player's forename]!";
say "[banner text]";
move the player to the location;
reject the player's command.
Instead of looking when collecting names: do nothing.
Rule for printing the banner text when collecting names: do nothing.
Rule for constructing the status line when collecting names: do nothing.
Procedural rule: if collecting names, ignore the turn sequence rules.
Part 2 - Adding the Leaderboard
File of Leaderboard is called "leaderboard".
When play begins:
if the File of Leaderboard exists
begin;
read File of Leaderboard into the Table of Leaders;
sort the Table of Leaders in reverse scored amount order;
end if;
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
begin;
change name entry to the player's forename;
change the scored amount entry to the score;
end if;
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
begin;
if scored amount entry is greater than 0
begin;
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, change N to 1;
say N spaces;
say "[scored amount entry][line break]";
end if;
end repeat;
say variable letter spacing.
To say (N - a number) spaces:
repeat with index running from 1 to N
begin;
say " ";
end repeat.
Table of Leaders
scored amount | name (indexed text) |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
0 | "Smithee" |
And now we introduce a scenario that allows different players to come up with different scores -- admittedly not a very interesting scenario, but it will do for now:
Part 3 - Scenario
Carry out taking something which is not handled:
increase score by 1.
The Big Treasure Chamber is a room. It contains a ruby, an emerald, a gold tooth, an antique katana, and a silver coin.
Instead of waiting, end the game in victory.
Test me with "get ruby / z".
|