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

Chapter 21: Lists

We’re getting near the end! Only one more chapter of ‘real’ stuff after this and then all the finicky details like images, testing, etc.

Section 21.1 is Lists and entries.

We’re basically just doing arrays/linked lists/sets. I think it’s more like linked lists since lists are variable in length and ordered.

We can declare a list at any time:

let L be a list of numbers;

but we must include the type (can’t just say ‘a list’).

A list has a length, which can be accessed like so:
say "L has [the number of entries in L] entries.";

If we have a list of numbers, we can add numbers to the list all we want. Starting with an empty list L, we can do the following:

add 2 to L; add 3 to L; add 5 to L;

You print out a list by just using its name in a substitution, so that:
say "L is now [L].";

prints out:

L is now 2, 3 and 5.

Once a list has a type and stuff in it, that doesn’t get changed, so you can’t mix various data types in one list.

Apparently you can make lists of lists of numbers…that with the math means we could implement matrices and tensors in Inform, maybe even the Einstein equations for general relativity! Good for my Schwarzschild black hole simulator.

Section 21.2 is Constant lists.

I guess this is useful reading (although I’ve read this whole chapter more than any other part of the manual), since I always got confused with the fact that we are only shown temporary lists in this section with the ‘let’ notation.

You need spaces after each comma when defining a list, like so:

let L be {1, 2, 3, 4};

or for texts:

let L be {"apple", "pear", "loganberry"};

Making a global list is snuck into the following paragraph example:

The marshmallow, the firework and the stink bomb are in the Scout Hut. The list of prohibited items is a list of objects that varies. The list of prohibited items is {the firework, the stink bomb}.

(so the standard way to make a global list is to declare a list that varies and give it a value).

To make a list of lists:

let L be {{1, 2}, {6, 7, 8}};

You can also declare lists in a table:

The duck, the orange, the cider, the cinnamon and the orange are in the Kitchen.

Table of Requirements

recipe ingredients
“duck à l’orange” {the duck, the orange}
“spiced cider” {the cider, the cinnamon, the orange}

The empty list is ambiguous so can’t be defined without saying what type it is, so you can’t just say:
let M be { };

but if M already has a type you can make it an empty list of that type:
now M is { };

You can’t put variables into this brace notation:
let L be {100, the turn count}; is not allowed.

Section 21.3 is Saying lists of values

You just say them like any other variable:

let L1 be {2, 3, 5, 7, 11};
say L1;

produces the text "2,

You can also construct lists with descriptions and print them in various formats.

For debugging, you might use this:

"[list of people in brace notation]"

while for more general use you can use this:

let L be {the piano, the music stand};
say "[L with definite articles]";

(this prints out “the piano and the music stand”)

or this:

let L be {the piano, the music stand};
say "[L with definite articles]";

which prints this: a piano and a music stand

I’m pretty sure you can just type [the L] or [a L] and get the same result. I know you can do that with lists built from descriptions but I don’t remember if it works with named lists.

Example 424 is Oyster Wide Shut:

This is the first example with lists and is pretty wildly complex for someone jumping directly to this chapter; I’d honestly recommend a softer introduction. This includes a rulebook with a basis and multiple rules that replace a standard inform rule. The list part is at the beginning:

Carry out taking inventory (this is the new print inventory rule):
    say "You are carrying: [line break]";
    list the contents of the player, with newlines, indented, including contents, with extra indentation.

Although the phrase ‘list the contents’ isn’t something we’ve seen yet. So I feel like this example really is out of place here.

Section 21.4 is Testing and iterating over lists.

To check if something is or isn’t in a list:

if ... is listed in ....
if ... is not listed in ...

You can also repeat through a list:

let L be {2, 3, 5, 7, 11, 13, 17, 19};
repeat with prime running through L:

It then warns us not to change the size of a list while repeating through it.

We build lists in multiple ways like:

adding single value:

let L be {60, 168};
add 360 to L;

producing:
{60, 168, 360}

concatenating lists:

let L be {2, 3, 5, 7};
add {11, 13, 17, 19} to L;

resulting in
{2, 3, 5, 7, 11, 13, 17, 19}.

adding values in certain spots:

let L be {1, 2, 3, 4, 8, 24};
add 12 at entry 6 in L;

resulting in
{1, 2, 3, 4, 8, 12, 24}

adding a list in the middle of another list:

let L be {1, 2, 3, 4};
add {4, 8, 12} at entry 3 in L;

resulting in
{1, 2, 4, 8, 12, 3, 4}.

Lists can have duplicates and order matters (so these aren’t ‘sets’).

We can also remove entries or sublists:

let L be {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
remove entry 3 from L;

resulting in {3, 1, 1, 5, 9, 2, 6, 5, 3}.

or

let L be {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
remove entries 3 to 6 from L;

resulting in {3, 1, 2, 6, 5, 3}.

Example 425 is Robo 1, a great example about a robot copying you, which I adapted to my current game about a clone copying you.

This does use ‘stored actions’ which I believe are now deprecated in favor of just ‘actions’, but I might be wrong.

The current instruction set is a list of stored actions that varies.

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.

Every turn when Robo is not watching:
    if the number of entries in the current instruction set is 0:
        say "Robo has run out of behavior and grinds to an (expectant) halt.";
        now the red button is switched off;
    otherwise:
        let the next task be entry 1 of the current instruction set;
        try the next task;
        remove entry 1 from the current instruction set.

You then have to write some report rules so the robot’s actions are printed.

Section 21.6 is Lists of objects.

You can make constant ones like the notation used earlier:

let L be {the pot plant, the foxglove};

but it’s usually better to write a ‘description’ (in the sense of Chapter 6 and not in the sense of object descriptions):

let L be the list of open containers;
let L be the list of things;

etc.

And you can add and remove things like normal:

add the list of open doors to L;
remove the list of backdrops from L;

You can then ‘say’ them with definite or indefinite articles:

"[L with definite articles]"
"[L with indefinite articles]"

and sort them:

sort L in P order;
sort L in reverse P order;

(which sorts them in value order, which is alphabetical for strings, I think, although upper case and lower case can cause weird issues if I remember an earlier chapter right).

Section 426 is What Makes You Tick:

Understand "combine [something] with [something]" as combining it with. Combining it with is an action applying to two carried things. Understand the command "connect" as "combine".

Understand the command "attach" as something new. Understand "attach [something] to [something]" as combining it with.

The combining it with action has an object called the item built.

Setting action variables for combining something with something:
    let X be a list of objects;
    add the noun to X;
    add the second noun to X;
    sort X;
    repeat through the Table of Outcome Objects:
        let Y be the component list entry;
        sort Y;
        if X is Y:
            now the item built is the result entry.

Check combining it with:
    if the item built is nothing or the item built is not in limbo,
        say "You can't combine [the noun] and [the second noun] into anything useful." instead.

Carry out combining it with:
    move the item built to the holder of the noun;
    now the noun is nowhere;
    now the second noun is nowhere.

Report combining it with:
    say "You now have [an item built]."

Table of Outcome Objects

component list result
{stick, string} hookless fishing pole
{wire hook, string} hooked line
{hooked line, stick} complete fishing pole
{hookless fishing pole, wire hook} complete fishing pole

Example 427 is Formicidae

This is a way to reorde the results of ‘take all’:

The magic rule is listed before the generate action rule in the turn sequence rules.

A thing has a number called dramatic potential.

This is the magic rule:
    let L be the multiple object list;
    if the number of entries in L is greater than 1:
        sort L in dramatic potential order;
        alter the multiple object list to L.

The rock is a thing in Foothills. Before printing the name of the rock when the rock is not handled: say "innocent-looking ". The dramatic potential of the rock is 10.

Section 21.7 is Lists of values matching a description

This is just like the last section, except we use values instead of objects:

let L be the list of non-recurring scenes;
let C be the list of colours;

We just can’t do ‘infinite’ lists:

let N be the list of even numbers;

Section 21.8 is Sorting, reversing and rotating lists:

You can reverse a list:

let L be {11, 12, 14, 15, 16, 17};
reverse L;

Sort it (in ascending order):

let L be {6 PM, 11:13 AM, 4:21 PM, 9:01 AM};
sort L;

Sort it (in reverse order):

let L be {6 PM, 11:13 AM, 4:21 PM, 9:01 AM};
sort L in reverse order;

and sort in random order:

let L be {1, 2, 3, 4, 5, 6};
sort L in random order;

If you have a list of things with properties, you can sort them by those properties:

let L be the list of people;
sort L in carrying capacity order;

or in reverse:

let L be the list of people;
sort L in reverse carrying capacity order;

You can also ‘rotate’ a list:

let L be { "cow", "heifer", "bullock" };
rotate L;

resulting in { "bullock", "cow", "heifer" }.

or rotate it backwards:

let L be { "cow", "heifer", "bullock" };
rotate L backwards;

I use rotating for ‘carousels’, like an evidence computer with forward and backwards buttons to cycle through displayed objects:

EvidenceList is a list of objects which varies. EvidenceList is {the gilded-dagger, the medical-report, weird-chip, package-receipt, background-report, signed-book};

Instead of pushing the next-button:
	if evidenceon is false:
		say "Nothing happens. The machine doesn't seem to be running.";
	otherwise:
		let current be a random thing enclosed by transparent-dome;
		rotate evidencelist;
		now current is nowhere;
		now entry 1 of evidencelist is in transparent-dome;
		say "You hear a clunking noise. [The current] disappears from inside the dome. After a few seconds, it is replaced by [a entry 1 of evidencelist].";

Example 21.9 is Accessing entries in a list

You do this with number of entries in ...

To access a specific element, just say
entry 2 of L

You have to be careful, though, because an out of bounds number gives you an error.

Example 428 is Robo 2, a more advanced version of the copying robot.

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.

Rule for printing the name of a program (called the target) which is not blank:
    say "[starter command of the target in upper case]".

Definition: a program is blank if the number of entries in its script is 0.

The current instruction name is some text that varies. The current instruction set is a list of stored actions that varies.

This and previous sections have inspired me; in my current game one of the sketched-out dimensions is a combat dimension. I’m thinking of including robots as NPCs in your ‘squadron’ that you program to carry out specific tactics.

Section 21.10 is lengthening or shortening a list

change L to have 21 entries; will either add default values (like 0s) to fill out the list or remove the last few entries.

truncate L to 8 entries will only shorten, never lengthen.

We can also say truncate L to the first 4 entries (which is the same as just truncating) or
truncate L to the last 4 entries

We can also say
`extend L to 80 entries1

Section 429 is Leopard-skin

I never saw this example before, but it would have helped a lot! This is for when you have to solve something by an exact sequence of actions (not the famous ‘exact sequence’ from homological algebra), and you have to check if the last few actions match with the ‘combination’, so to speak.

The maze-sequence is a list of stored actions that varies.

When play begins:
    add jumping to the maze-sequence;
    add clapping to the maze-sequence;
    add kweepaing to the maze-sequence.

The attempted-sequence is a list of stored actions that varies.

Every turn when the player is in the Fur-Lined Maze:
    truncate the attempted-sequence to the last two entries;
    add the current action to the attempted-sequence;
    if the attempted-sequence is the maze-sequence:
        say "That does it! You are instantly transported from the maze!";
        end the story finally.

I did something similar in Grooverland, where a player has to traverse a maze in exactly the right order:

Every turn when the player is in creakyregion (this is the stalkertext rule):
	if the player is in creaky house:
		now The playercreaks is {"howl", "howl", "howl", "howl", "howl", "howl", "howl", "howl"};
	if stalkerroom is not the location of the player:
		say stalkertext of stalkerroom;
		say "[paragraph break]";
		if the player is not in creaky house:
			add creaktext of stalkerroom to playercreaks;
			remove entry 1 from playercreaks;
		let tempcreaks be playercreaks;
		if playercreaks is {"creak", "creak", "rattle", "rattle", "shake", "shake", "turn", "turn"}:
			destroy the house;
			now winddie is false;

Example 430 is The Facts Were These

This is a way of making actions involving multiple objects consider them as a group instead of individually.

Check multiply-giving it to:
    let L be the multiple object list;
    let bribe-price be $0;
    repeat with item running through L:
        if the player does not carry the item:
            abide by the ungivability rules for the item;
            carry out the implicitly taking activity with the item;
            if the player does not carry the item:
                now already gave at the office is true;
                say "You can't include [the item] in your bribe, since you're not holding [them]![paragraph break]" instead;
        increase bribe-price by the price of item;
    if the number of entries in the recently-collected list is greater than 0:
        repeat with item running through the recently-collected list:
            now item is marked for listing;
        say "You pick up [the list of marked for listing things] and make your offer. [run paragraph on]";
        now everything is unmarked for listing;
    if the bribe-price is less than the price of the second noun:
        now already gave at the office is true;
        say "[The second noun] angrily rejects your piffling bribe.[paragraph break]" instead.

Carry out multiply-giving it to:
    let L be the multiple object list;
    repeat with item running through L:
        now the second noun carries the item;
        now the item is given;
    now already gave at the office is true;

Report multiply-giving it to:
    say "[The second noun] rather shamefacedly tucks [the list of given things] away into a pocket.[paragraph break]".

Finally, we have 21.11: Variations: arrays, logs, queues, stacks, sets, sieves and rings

These aren’t necessarily things that you can declare already in Inform, but you can mimic them.

Arrays are basically lists that don’t vary in length.

A log records the most recent items but deletes the oldest:

The most-recently-taken list is a list of objects that varies.
Carry out taking something (called the item):
    truncate the most-recently-taken list to the last 6 entries;
    add the item to the most-recently-taken list.
After taking:
    say "Taken. (So, your recent acquisitions: [most-recently-taken list].)"

(I use this concept for a video monitor in my game that shows clips of the player in the past. The benefit of a log, as the text says, is it uses less memory than a list of evergrowing size).

A queue has elements get added to the back while stuff in the front gets paid attention to.

add the new customer to the queue;

Every turn when the number of entries in the queue is not 0:
    let the next customer be entry 1 of the queue;
    say "[The next customer] is served and leaves.";
    remove entry 1 from the queue.

You can also simulate a Stack:

add V to S;
let N be the number of entries in S;
let V be entry N of S;
remove entry N from S;

To simulate a set, we keep it sorted at all times (to make comparing two sets be easier) and use the phrase ‘if absent’:

add 8 to T, if absent; sort T;

You could do set intersections like this:

let I be T;
repeat with the element running through T:
    if the element is not listed in S, remove the element from I.

A sieve (like sieve of eratosthenes) is exactly like a set but you start with something big and remove it.

A ring is a list where the first and last entry are next to each other. The main thing is rotating it:

rotate the ring;
rotate the ring backwards;

Unlike other programming languages, Inform passes lists as values and not as pointers. So if you pass it in as a parameter and change it, it doesn’t change the original list, just a new list created for this function.

You can mess with a list then put it back:

To decide which list of numbers is the extended (L - a list of numbers):
    add 7 to L, if absent;
    decide on L.

Now we get 7 examples, all one-star.

Example 431 is Circle of Misery:

The circle of misery is a list of objects that varies.

When play begins:
    now all the luggage items are in the carousel;
    add the list of luggage items to the circle of misery.

Every turn when the number of entries in the circle of misery is not 0:
    rotate the circle of misery;
    let the bag be entry 1 of the circle of misery;
    say "The carousel trundles on, bringing [a bag] to within reach."

After taking a luggage item (called the bag):
    remove the bag from the circle of misery, if present;
    say "Taken."

Before doing something with a luggage item (called the bag) which is in the carousel:
    if the bag is not entry 1 of the circle of misery, say "[The bag] is maddeningly out of range. You'll have to wait for it to come round." instead.

(That one’s honestly pretty funny)

Next is 432, Eyes, Fingers, Toes, an example I’ve probably copied more than any other inform example.

The Addams Wine Cellar is a room. It contains a closed lockable locked container called a safe.

The safe has a list of numbers called the current combination.

The safe has a list of numbers called the true combination. The true combination of the safe is {2, 10, 11}.

Understand "set [something] to [a number]" as setting it numerically to. Setting it numerically to is an action applying to one thing and one number.

Instead of examining the safe:
    if the number of entries in the current combination of the safe is 0,
        say "You haven't dialed the safe to any combination yet.";
    otherwise say "You have dialed the safe to [the current combination of the safe].".

Check setting something numerically to (this is the block setting numerically rule):
    say "[The noun] cannot be set."

Instead of setting the safe numerically to the number understood:
    truncate the current combination of the safe to the last 2 entries;
    add the number understood to the current combination of the safe;
    if the safe is locked and the current combination of the safe is the true combination of the safe:
        say "You dial [the number understood], and [the safe] gives a joyous CLICK.";
        now the safe is unlocked;
    otherwise if safe is unlocked and the safe is closed and the current combination of the safe is not the true combination of the safe:
        say "You spin the dial, and [the safe] snicks locked.";
        now the safe is locked;
    otherwise:
        say "You dial [the number understood] on the safe."

Example 433 is the fibonacci sequence

To decide what list of numbers is the first (F - a number) terms of the Fibonacci sequence:
    let the Fibonacci sequence be {1, 1};
    let N be 3;
    while N < F:
        let the last term be entry (N - 1) of the Fibonacci sequence;
        let the penultimate term be entry (N - 2) of the Fibonacci sequence;
        let the next term be the last term plus the penultimate term;
        add the next term to the Fibonacci sequence;
        increment N;
    decide on the Fibonacci sequence.

This is some real Project Euler stuff.
Exampes 434 is I didn’t come all the way from great portland street:

The Round is a scene. The Round begins when play begins. The Round ends when the turn count is 10.

The tally is a list of stored actions that varies.

To challenge for (infraction - text):
    say "Bzzzzt! 'And [one of]Clement Freud[or]Derek Nimmo[or]Kenneth Williams[or]Peter Jones[at random] has challenged.'[paragraph break]'[infraction]'[paragraph break]'Well, as it's your first time playing the game, and the audience was enjoying your contribution so much, I will disallow the challenge, you have [10 minus the turn count] turn[s] left on musical instruments, starting... now!"

Before doing something:
    if the current action is listed in the tally, challenge for "Repetition of [the current action]!" instead;
    otherwise add the current action to the tally;
    if waiting, challenge for "Hesitation!" instead;
    if not looking and not waiting and the noun is not an instrument and the second noun is not an instrument, challenge for "Deviation!" instead.

Example 435 is Lugubrious Pete’s Delicatessen

This is a depressing example where a lewd man Pete serves women in order of their modesty (with most revealing served first):

Modesty is a kind of value. The modesties are positively prim, buttoned up, modest, flirty, revealing and downright immodest. Every woman has a modesty. Alice is positively prim. Beth is downright immodest. Gemma is modest. Delia is flirty. Eliza is revealing.

Every turn when the number of entries in the deli queue is not 0 and a random chance of 1 in 3 succeeds (this is the customer being served rule):
    let Pete's preference be the deli queue;
    sort Pete's preference in reverse modesty order;
    let the customer be entry 1 of Pete's preference;
    let the first in line be entry 1 of the deli queue;
    if the player is in the Delicatessen, say "[if the customer is the first in line]Pete gives a droopy expression as he serves [the customer], who nevertheless brightens and leaves.[otherwise]Outrageously, Pete scans the queue, notices [the customer] in her [modesty of the customer] clothes, and serves her next, while [the first in line] glares at him.";
    if the player is in the Supermarket, say "[The customer] emerges cheerfully from the Delicatessen Counter, and goes about her regular shopping.";
    now the customer is in the Supermarket;
    remove the customer from the deli queue.

Example 436 is the Sieve of eratosthenes:

Sieving is an action applying to one number. Understand "sieve [number]" as sieving.

Instead of sieving, say "You make a feeble attempt, sketching in the sand, but it goes nowhere. Eratosthenes smirks. 'I expect your friends call you gamma, then?'"

Persuasion rule for asking Eratosthenes to try sieving: persuasion succeeds.

Report Eratosthenes sieving:
    let N be the number understood;
    let the composites be a list of numbers;
    let I be 2;
    while I times I is at most N:
        if I is not listed in the composites:
            let J be I times 2;
            while J is at most N:
                add J to the composites, if absent;
                increase J by I;
        increment I;
    sort the composites;
    let the primes be a list of numbers;
    repeat with P running from 2 to N:
        add P to the primes;
    remove the composites from the primes;
    say "Eratosthenes sketches lines in the sand with the air of much practice. 'The primes up to [N] are [the primes]. The composites are [the composites].'"

Big Mike Spivey energy.

Example 437 is Your mother doesn’t work here:

A person has a list of stored actions called the current plan.

Every turn:
    repeat with culprit running through people who are not the player:
        if the number of entries in current plan of the culprit is greater than 0:
            let N be the number of entries in the current plan of the culprit;
            try entry N of the current plan of the culprit;
            remove entry N from the current plan of the culprit.

Report your mother taking something:
    say "Your mother picks up [the noun][one of], sighing deeply[or], jaw tight[or], with assorted comments on your manners[or]; to judge from her comments, she is also indulging in a pleasant fantasy about Swiss boarding schools[stopping]." instead.

When play begins:
    add mother going west to the current plan of mother;
    add mother rubbing the rug to the current plan of mother.

Every turn:
    if mother is not in the Living Room, end the story finally.

Carry out dropping something:
    add mother taking the noun to the current plan of mother.

And that’s it for lists! A fairly straightforward but powerful Chapter. And the next chapter is the end of the middle, the last section to deal with the text itself!

2 Likes