Inform 7 Home Page / Documentation
§21.9. Accessing entries in a list
The length of a list can change as values are added or removed, and can in principle be any number from 0 upwards. A list with 0 entries is empty. We can find the length with:
number of entries in/of/from (list of values) ... number
This phrase produces the number of positions in the list. Example:
is 5, even though there are only two genuinely different items in the list.
If the length is N then the entries are numbered from 1 (the front) to N (the back). These entries can be accessed directly by their numbers. For instance,
entry 2 of L
refers to the second entry of L: it can be used as a value, or changed, just as if it were a named variable. For instance, we could write:
now entry 7 of L is "Spain";
say "The rain in [entry 7 of L] stays mainly in the plain.";
which would (untruthfully) print "The rain in Spain stays mainly in the plain", but only if L had an entry 7 to make use of: if L were a list of 5 entries, say, then a run-time problem results. (And if L cannot hold text, a problem message means that we never get as far as run-time.) Because entries number from 1, this is always incorrect:
entry 0 of L
and if L is currently empty, then there is no entry which can be accessed, so that any use of "entry ... of L" would produce a run-time problem. There are programming languages in the world where accessing entry 100 in a 7-entry list automatically extends it to be 100 entries long: Inform is not one of them. But see the next section for how to change list lengths explicitly.
|Start of Chapter 21: Lists|
|Back to §21.8. Sorting, reversing and rotating lists|
|Onward to §21.10. Lengthening or shortening a list|
We have seen how we can make a robot that watches the player, then plays back the same actions again. A slightly more adventurous implementation would be to let the player create a whole series of named scripts which the robot will run on command.
To do this, we'll need each program to have a command that sets it off (stored as text, since this is the best way to capture and preserve arbitrary text entered by the player) and then the script of actions that must result:
The hard drive is a container. A program is a kind of thing. 15 programs are in hard drive. A program has some text called the starter command. A program has a list of stored actions called the script. Understand the starter command property as describing a program.
Now, we want to let Robo learn new programs; for this purpose, we'll emulate the code from our previous implementation, so that Robo watches what the player does and stores those actions in his script:
After doing something when Robo is watching and Robo can see the player:
now the actor is Robo;
add the current action to the current instruction set;
now the actor is the player;
say "Robo watches you [the current action][one of], his yellow eyes lamp-like and observant[or]. In his metal head, gears whirr[or], his brushed-copper handlebar moustaches twitching[or] impassively[at random].";
continue the action.
Of course, we also need to be able to switch learning mode off, and store any script learned this way. We'll also use the same STOP command to make Robo terminate a program he's in the middle of running.
Carry out Robo stopping when Robo is watching:
let N be a random blank program;
if N is a program:
now the starter command of N is the current instruction name;
now the script of N is the current instruction set;
say "'Stored [current instruction name in upper case].'";
say "FAILURE: no program slots remaining."
Next, we need to be able to play these programs back again. We'll give Robo a "current program" to store which program he's currently working on, and a number called "stage" which will record where he is in the script. Our previous implementation simply had Robo erase entries from his script list as he performed them, but this time we would like Robo to be able to remember and rerun the same scripts over and over, so we need something a little more subtle.
Every turn when Robo is replaying:
let the chosen script be the script of the current program of Robo;
let maximum be the number of entries in the chosen script;
let N be the stage of Robo;
let the next step be entry N of the chosen script;
try the next step;
increment the stage of Robo;
if the stage of Robo is greater than the maximum:
say "Robo's program ends, and he reverts to stand-by mode.";
now Robo is standing by;
now the stage of Robo is 1.
For the player's sanity, we should also provide a way to find out which programs Robo has stored in memory and what they do, so we design two listing commands:
And to complete the suite, in case the player runs into Robo's fifteen-program limit:
Now we use pretty much the same set-up as before to test Robo's abilities:
Robo is a man in the Experimentation Chamber. "Robo, your prototype tin companion, stands awkwardly beside you[if watching], watching[end if]." Robo can be watching, replaying, or standing by. Robo is standing by. Robo has a program called the current program. Robo has a number called the stage.
Report Robo examining the player:
say "Robo stares at you, unblinkingly, for several seconds together[if a random chance of 1 in 7 succeeds]. His left moustache-bar twitches infinitesimally upward[end if]." instead.
Report Robo taking the cylinder:
say "[one of][Robo] needs several attempts to get his metal fingers around [the cylinder] -- they are not designed for grasping small objects elegantly. But at last he succeeds[or]Once again, Robo struggles a bit before picking up [the cylinder][stopping]." instead.
Test chocolate with "learn chocolate / stop / list programs / Robo, learn chocolate / take red / put all on counter / Robo, stop / Robo, list programs / Robo, run chocolate / z / Robo, run chocolate / Robo, stop / z".
Test vanilla with "Robo, learn vanilla / take all / i / drop all / x robo / x me / Robo, stop / Robo, list programs / Robo, list vanilla / Robo, run vanilla / z / z / robo, delete vanilla / robo, stop / robo, list vanilla / robo, delete vanilla / robo, list programs".
We could also have written this so that Robo learns new scripts by accepting the player's instructions, so that
...would store the script 'library theft' with the actions taking the book and going east. The implementation there would have been mostly identical, except that instead of an "after doing something..." rule, we would have captured commands as we asked Robo to perform them, and added those to the command list in progress. The alternative code might look something like this: