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

(With “first thing held by / next thing held after”: )

You stop when you see nothing. If there are no contents at all, “first thing held by” will be nothing. Otherwise, “next thing held after” will be nothing when the chain runs out.

These phrases expose the underlying I6 object tree to I7 code. You will almost never have a use for them.

2 Likes

Thanks, both these responses help clarify a lot.

I think this is what you’re after:

Move player to The Secret House, without printing a room description;

Oh, never mind, you found it :slight_smile:

3 Likes

Oh my gosh I missed this too! I usually just do a convoluted hack saying various room description rules do nothing in specific circumstances!

Oh that’s clever!

Similarly, I couldn’t get this to work in my first game so made a custom netherworld – I think I hadn’t fully internalized the hyphens in on- and off-stage so was confused when “now OBJECT is offstage” didn’t work.

Bees!

Looking forward to seeing your analysis when this comes up for full treatment – I feel like for some reason this way of doing loops really throws a lot of experienced programmers and I’m not sure why.

Wait is there not an “enclosed by” example? That’s the one most in need of an example, I think, since it’s very very useful but not as intuitive as most of the rest.

Wow this really conjures up a scenario! (I like that the examples, and even the little code snippets like this, are quite evocative, for the most part)

Yeah I’m really wracking my brain to figure out when you would need these – I think in some of the Infocom games when you exceeded the carrying limit, you’d drop the first thing in your inventory, so this would help with that?

1 Like

Yes, Mike. Bees!

(Now what does that remind me of…)

2 Likes

Chapter 9 - Time

This is one of a few smaller chapters in a row.

Section 9.1 is 'When play begins"

This just does things that only happen once, when the game starts:

When play begins: say "Welcome to Old Marston Grange, a country house cut off by fog."

The “when play begins” rules are checked only at the start of a story, not when a saved session is restored from disc. What happens is that these rules are followed, then the story’s banner is printed, then the initial room description is printed up, and then the player is asked for a first command.

Example 135 is Clueless, and shows how you can use ‘when play begins’ for stuff besides talking:

The murderer is a person that varies.

When play begins:
now the murderer is a random person who is not the player.

The Billiards Room is a room. Colonel Mustard and Professor Plum are men in the Billiards Room. Miss Scarlet and Mrs White are women in the Billiards Room.

Section 9.2 is Awarding points (which isn’t really a time thing?)

Having a score used to be a default, but now must be turned on manually:

Use scoring.

This enables in-game commands SCORE, NOTIFY ON and NOTIFY OFF and allows the author to award points at any time by this:
increase the score by 5;

I have mixed feelings on scoring. I used to squarely be in the ‘it’s outdated’ camp, but the nice thing about having a score is it really helps with pacing in a game; it makes it clear how long the overall game and how fast you’re progressing.

They warn not to let scoring actions happen over and over again (my current game doesn’t use the built-in score, but has a custom scoring thing for one section, and one beta tester found a way to get an unlimited score).

They give an example of scoring that can be abused by repeating the action:

After taking the trophy:
    increase the score by 5;
    say "Well done!"

and a similar one that can not be abused:

After taking the trophy when the trophy was not handled:
    increase the score by 5;
    say "Well done!"

(It is very important to note that this rule uses the past tense in its verb ‘was handled’; this is the first time we’ve seen this, where using the past tense refers to the game state at the beginning of the turn).

You can establish a maximum score as so:

The maximum score is 10.

And you can change the maximum score and current score at any time.

Example 136 is Mutt’s Adventure:

A room can be scored or unscored.

Carry out going to a unvisited scored room:
increment the score.

The Treasure Room is scored.

Example 137 uses tables for advanced scoring:

Table of Point Values

item score
cow 10
incantations 4
chessman 1
Report taking an item listed in the Table of Point Values:
    increase the score by the score entry;
    blank out the whole row.

‘Blank out the whole row’ is something we’ll see a lot more later on.

Section 9.2 is Introducing tables: rankings, which again has nothing to do with time. It just gives a way to make a table of rankings. ‘Rankings’ is a special name in Inform, and if made with a column called score with numbers and a column called rank made with text:

Score Rank
0 “Beginner”
25 “Amateur Adventurer”
50 “Novice Adventurer”
100 “Junior Adventurer”
200 “Adventurer”
300 “Master”
330 “Wizard”
350 “Master Adventurer”

Customarily, the score in the final row should be the maximum possible achieved in the story - so that only a player with maximum possible score can be awarded the final ranking - and the value of “maximum score” is automatically set to this bottom-row value if it has not been explicitly set anywhere else in the source text.

Section 9.4 is When play ends, which introduces some phrases for ending everything.

These includes:
end the story, which ends the game and prints ‘The End’, but it isn’t final (the game won’t print this like author’s notes, etc.)
end the story finally, which does the same as above but is considered final and prints final menu options

You can also change the printed message from ‘the end’ to anything else you want:
end the story saying (text)
or `end the story finally saying (text)'.

The book gives this example:

end the story finally saying "You have defeated Sauron"

The closing message is printed between three asterisks on left and right, and looks weird if it’s too long. I usually use a say " " command first to give most of the ending or death message, then end the story finally with one last sentence.

I always get errors because I tend to time ‘end the game’ instead of ‘end the story’.

We can check if the story is over as follows:

if story has ended
if story has not ended
if story has ended finally
if story has not ended finally

Any commands in ‘when play ends’ happen before the final message, like

When play ends, say "Oh dear."

Surprisingly, you can also just take back the ending with the command resume the story:

When play ends:
    if the story has not ended finally:
        say "Oh dear. Still, here's another chance.";
        resume the story.

Example 138 is Big Sky Country:

When play ends when the story has not ended finally:
    say "Oh dear, that ought to be fatal! However, if you like I can get you out of it...

    Shall I? >";
    if the player consents:
        repeat with item running through things had by the player:
            move the item to a random visited room;
        say "A strong wind picks you up and sets you back at [the location], though perhaps minus a few of your things.";
        resume the story;
        try looking.

This introduces if the player consents, which gives a special yes/no prompt.

Section 9.5 is ‘Every turn’.

Inform is a turn-based system, with one command giving one action taking one turn, in general.

There is a variable called turn count that is a number equal to the number of turns in play. It is turn 0 when the banner is printed and turn 1 whn the first command is typed.

At the end of the turn, you can make commands run with ‘Every turn’:
Every turn, say "The summer breeze shakes the apple-blossom."

Apparently this is equivalent to:
An every turn rule: say "The summer breeze shakes the apple-blossom."

but I don’t understand rulebooks so I’ll learn about that later.

I should say that Inform lets you see all rules running with RULES, but rules without names just print their conditions, and so if you use ‘every turn’ a lot (like I do) it’ll just say ‘every turn rule’ ‘every turn rule’ etc. with no further clarification. It helps to either name rules (which we’ll get to later) or just add conditions like:
every turn when the player is in spell-region, because that’s easier to pick out when debugging.

Example 139 is Witnessed:

A battery is a kind of thing. A battery has a number called charge. The charge of a battery is usually 15.

Every turn:
    repeat with hollow running through battery compartments:
        if the hollow is part of a switched on device (called the machine):
            if a battery (called cell) is in the hollow:
                decrement the charge of the cell;
                carry out the warning about failure activity with the machine;
                if the cell is discharged, carry out the putting out activity with the machine;
            otherwise:
                carry out the putting out activity with the machine.

Example 140 is a rare four-star example: Text Foosball.

I actually made a foosball table in my current game, and I wondered if Inform had a sample foosball table in its documentation, and it did!

I ended up not using this code because it heavily involves an NPC and mine doesn’t, but it’s really cool.

It has stuff like this:

Every turn when the ball is still and Joey is active:
    let total be Joey's score + score;
    if total > 9, make no decision;
    if the ball is unreachable, make no decision;
    now Joey is inactive;
    if a random chance of 1 in 2 succeeds:
        now the ball is approaching;
        say "Joey hits the ball solidly down towards your goal. Now it is [small white ball condition].";
    otherwise:
        say "Joey fails to hit the ball in your direction. It remains [small white ball condition]."

Section 9.6 is The time of day

This weirded me out when I first saw it but I like it.

Inform keeps an internal time tracker for games. Each game starts at 9 AM and every turn takes one minute.

This is great for timed games where the exact sequence of events happens every time you play it.

You can change the time of day any time you want:
The time of day is 3:13 PM.

You can say stuff like:

At the time when the player loses consciousness:
    now the time of day is 10:12 AM;
    say "A mist comes over your vision, and when you come to, it is morning and you are in bed."

This is the first time we’ve seen ‘at the time when’ that I can remember so far.

Example 141 is IPA:

When play begins: now the right hand status line is "[time of day]".

The time of day is 9:50 AM.

A shop is a kind of room. A shop has a time called the opening hour. The opening hour of the shop is usually 8 AM. A shop has a time called the closing hour. A shop usually has closing hour 6 PM.

Check going to a shop (called the target):
    if the time of day is before the opening hour of the target,
        say "[The target] is locked up until [the opening hour of the target]." instead.

Check going to a shop (called the target):
    if the time of day is after the closing hour of the target,
        say "[The target] has been closed since [the closing hour of the target]." instead.

Every turn when the location is a shop:
    let deadline be the closing hour of the location;
    if the deadline is before the time of day:
        let target be a random adjacent room which is not a shop;
        say "You are gently but firmly ushered out, since [the location] is closing.";
        move the player to the target.

Section 9.7 is Tell the time:

The Clock Chamber is a room. "The dark chamber behind the clock face, a mill-room of gears which grind down the seconds. Through the glass you can see the reversed hands reading [the time of day]."

This prints numerals. To print words:
"Through the glass you can see the reversed hands reading [the time of day in words]."

You can also make the command prompt the time of day (not with any special syntax, just combining regular syntax):
When play begins: now the command prompt is "[time of day] >".

Example 142 is Situation Room.

To say (relevant time - a time) as 24h time:
    let H be the hours part of relevant time;
    let M be the minutes part of relevant time;
    say "[if H is less than 10]0[end if][H][if M is less than 10]0[end if][M]".

When play begins:
    now the time of day is 6:09 PM;
    now the right hand status line is "[time of day as 24h time]".

Section 9.8 is Approximate times, lengths of time

You can specify how rounded off to make the time:
The Clock Chamber is a room. "The dark chamber behind the clock face, a mill-room of gears which grind down the seconds. Through the glass you can see the reversed hands reading [the time of day to the nearest five minutes in words]."

Next we do a little type casting:

let X be 5;
if the player is in the Slow Room, now X is 10;
let deadline be the time of day plus X minutes

so X is a number but we turn it into a time. 1440 is the maximum time.

If we type ‘hours’ instead of ‘minutes’ it makes hours instead of minutes, which makes sense. 24 is the max of hours.

Section 9.9 is Comparing and shifting times:

The chronometer is in the Clock Chamber. “On one wall is a terribly self-important chronometer showing the time in major world cities. London: [time of day]. Paris: [one hour after the time of day]. Tokyo: [9 hours after the time of day]. Cupertino, California: [7 hours before the time of day].”

This shows how you can shift the time of day when printing.

You can also do it in conditions:
if time of day is before 11AM, etc.

Obviously since time is periodic, every time is both before and after every other time, but Inform restricts it to one day, and assumes days start at 4:00 AM.

Section 9.10 is Calculating times

You can split time up into the minutes part and hours part:

minutes part of 12:41 PM
hours part of 8:21 AM

And like early you can ‘cast’ any integer to a time by putting hours or minutes after it:

The clock error is a number that varies. To thump the mechanism: now the clock error is a random number from -10 to 10.

The broken grandfather clock is in the Chamber. "An erratic grandfather clock seems to say it is [clock error minutes after the time of day]."

When play begins, thump the mechanism. Instead of attacking the broken clock: thump the mechanism; say "You thump the clock, which now reads [clock error minutes after the time of day].".

This is just like python where you have a number n but you want to concatenate it onto a string so you ‘cast’ it with print("The number is" + str(n).)

Section 9.11 is ‘Future events’, which I’ve used before but always feels like a weird pseud-way of making scenes, like a parallel development that was discarded.

 Instead of pushing the egg-timer:
    say "It begins to mark time.";
    the egg-timer clucks in four turns from now.

At the time when the egg-timer clucks:
    say "Cluck! Cluck! Cluck! says the egg-timer."

So this construction just lets you schedule things a certain amount of times in the advance.

This construction is great for making funny jokes in code (like ‘the goblin breakdances in five turns from now’), since you can just type anything.

I used it a ton in The Magpie Takes the Train, which was a one-room game with a lot of schedule events:

To say ParrotSing:
	now the parrot is musical;
	the musicing ceases in three turns from now;
	
At the time when the musicing ceases:
	say "Horus stops singing and preens his feathers. He seems eager to sing again.";
	now Music is not TargetGiven;
	now the parrot is not musical;
	say "[line break][bracket]Renewed topic for the parrot - [bold type]Music[roman type][close bracket][line break]";

Every turn:
	if the parrot is musical:
		say "Horus is currently singing at the top of his lungs[if the parrot is offended], but he's glaring at you while he does it[end if].";

You can phrase it in minutes or in turns (which are minutes by default) or for specific times of day:

the egg-timer clucks in 18 minutes from now;
the egg-timer clucks in four turns from now;
the egg-timer clucks at 11:35 AM;

These are all used inside of other rules. If you know a specific time you can just declare it as its own rule (don’t know if this is a technical ‘rule’ but it’s like them):

At 4 PM: say "The great bells of the clock tower chime four."

It says that the scenes index lists these. Let’s try this with a sample game:

Adding:
At 9:03 AM: say "The rooster crows".
to a sandbox game makes the following appear in the index:

image

Note that I got an error the first time I tried this because I didn’t type ‘AM’.

Lots of examples!

Example 143 is MRE, with a hunger timer:

Food is a kind of thing. Food is usually edible. Food has a time called the satisfaction period. The satisfaction period of a food is usually 5 minutes.

A person can be hungry or replete. The player is hungry.

The Larder contains an apple, a candy bar, and a large plate of pasta. The apple, the candy bar, and the pasta are food. The satisfaction period of the apple is 2 minutes. The satisfaction period of the pasta is 125 minutes.

Carry out eating something:
    now the player is replete;
    hunger resumes in the satisfaction period of the noun from now.

At the time when hunger resumes:
    starvation occurs in three minutes from now;
    now the player is hungry.

At the time when starvation occurs:
    if the player is hungry, end the story saying "You have starved".

I noticed they changed ‘carry out’ here. Wouldn’t that get rid of regular eating rules, and not delete the object? Let’s try it out.

Huh, compiling this example, the apple does go away. Does adding our own ‘carry out’ rules just stack with older carry out rules instead of replacing them completely?

Example 144 is Totality:

At the time when the penumbra appears:
    say "The sunlight dies away to an eerie, brownish penumbra."

At the time when the eclipse begins:
    say "The moon passes across the disc of the sun, plunging the world into darkness.";
    now the Chamber is dark.

At the time when the eclipse ends:
    say "The moon passes away from the sun, and a gloomy penumbral light returns.";
    now the Chamber is lighted.

At the time when normal sunlight returns:
    say "The sun shines once more bright in the sky, not to be eclipsed again on this spot for another thirty-seven years."

To schedule an eclipse for (totality - a time):
    the penumbra appears at two minutes before totality;
    the eclipse begins at totality;
    the eclipse ends at three minutes after totality;
    normal sunlight returns at five minutes after totality.

‘To schedule an eclipse’ is an example of a Phrase.

Example 145 is Empire:

At 4:45 PM:
    if the player is in the train or the player is in the station of the train, say "The train pulls out of [the station of the Train]!";
    now the station of the Train is the Train.

At 5:10 PM:
    now the station of the Train is Edmonds;
    if the player is in the train or the player is in the station of the train, say "The train pulls into Edmonds and comes to a stop."

At 5:17 PM:
    if the player is in the train or the player is in the station of the train, say "The train pulls out of [the station of the Train], running north along the shore towards Everett.";
    now the station of the Train is the Train.

I’ve only reproduced a small part of this.

Example 146 is Hour of the Wren:

The player carries a card. The description of the card is "Typed: 'Active astrology - dislike your fortunes? change your stars! - make an appointment now - hour of the wren STILL AVAILABLE.'".

The time of day is 1:55 PM.

Understand "pick [time]" or "choose [time]" or "make appointment for [time]" or "make an appointment for [time]" as making an appointment for. Making an appointment for is an action applying to one time.

Carry out making an appointment for:
say "Fate cannot be commanded more than once."

Instead of making an appointment for the time understood for the first time:
say "You settle on [the time understood] for your appointment. The woman makes a note of it in an appointment book, which she carries in a brown paper bag. 'Excellent choice, ma'am,' she says in a low, urgent voice. 'You'll be very satisfied.'";
stars shift at the time understood.

Understand "hour of the wren" as 2:00 PM.

At the time when stars shift:
end the story saying "insert cataclysm here".

Section 9.12 is Actions as conditions:

We can use actions as conditions, like this:
if we are taking a container, ...
or the abbreviated form:
if taking a container, ...

I didn’t know this! I always did ‘if the current action is the player looking’ or ‘if the current action is looking’. This is similar but slightly more natural, which is nice.

You can also use the past tense:
Instead of waiting when we have taken the lantern, say "No, your acquisitive nature is roused now, and simply waiting will no longer do."

This only works if someone has ever successfully taken the lantern.

This past tense stuff is really heavy; I feel like it could be a massive game changer but I’m just learning it now.

Example 147 is Night Sky:
The Planetarium is a room. "[if we have examined the sinister message]A dark room where it seems something is about to jump out at you![otherwise]A tranquil dark room with a ceilingful of stars.[end if]"

There is also an example that doesn’t work since it uses ‘instead’ so the action that matters isn’t successful:
The sinister message is a thing in the Planetarium. "A message plays very softly, so that you would have to listen to hear it." Instead of doing anything other than listening to the message: say "It's only a sound, after all.". Instead of listening to the sinister message: say "A voice whispers, 'BEWARE'."

Example 148 is Zero:

Weight is a kind of value. The weights are light, manageable, and horribly heavy. Everything has a weight.

A thing is usually manageable.

Before printing the name of a horribly heavy thing (called weighty object):
    if we have taken the weighty object, say "[weight] ".

This includes ‘before printing the name of’, which to me is in the category of ‘mystical phrases I only see in random examples’.

Section 9.13 is past and perfect tenses.

There are three ways to do conditions in inform:
if X is Y...., which is what we’ve used the most.
if X has been Y' (which checks if X is Y has ever been true), and if X was Y` which only checks if X was Y at the start of the current turn

This is fantastic! I’ve rolled my own rules for this kind of thing many times, setting a flag at the beginning of every turn and then checking if the flag was still true at the end. This is great:

if the lantern was switched on, now the lantern is switched off;
if the lantern was switched off, now the lantern is switched on;

can be used for ‘push button’, for instance.

There is also the past perfect text which checks if ‘X has been Y’ was true at the beginning of the current action.

Do not say things like ‘if the noun has been open’, the manual warns, as ‘the noun’ is a variable phrase and when using ‘has been’ it checks past values of the noun.

Example 149 is Tense Boxing:

The mysterious box is in the Temporal Prism. It is an openable closed container.

To assess the box:
    if the box was not open, say "The box was not open.";
    if the box was open, say "The box was open.";
    if the box had not been open, say "The box had not been open.";
    if the box had been open, say "The box had been open.";
    if the box is not open, say "The box is not open.";
    if the box is open, say "The box is open.";
    if the box has not been open, say "The box has not been open.";
    if the box has been open, say "The box has been open."

Before opening the mysterious box:
    say "You are about to open the box.";
    assess the box.

Before closing the mysterious box:
    say "You are about to close the box.";
    assess the box.

After taking the mysterious box:
    if the box had not been carried by the player, say "You lift the mysterious box for the first time.";
    if the box had been carried by the player, say "You again pick up the mysterious box."

Example 150 is Brunesau’s Journey

Carry out burning the candle:
    now the candle is lit.

Report burning:
    if the candle had been lit, say "You relight the candle.";
    otherwise say "You light the candle for the first time.".

Carry out blowing out the candle:
    now the candle is unlit.

Report blowing out:
    if the noun is the candle and the candle was lit, say "You blow out [the noun].";
    otherwise say "You blow on [the noun], to little effect."

Example 151 is Elsie:

Every turn when the sliding door was open:
    now the sliding door is closed;
    if the player can see the sliding door:
        say "The sliding door slips back into place, sealing the wall as though there had never been a breach."

I wondered what would happen if you typed ‘close door’ when the door was open; would this rule fire anyway?

Yes, it does, but it fits in. It prints the following:

You close the sliding door.

The sliding door slips back into place, sealing the wall as though there had never been a breach.

In my current game I have the following:

Every turn when wax-doors are open:
	now wax-doors are closed;
	say "The double doors swing closed."

This has the negative effect of never letting the player open the doors without immediately closing. So I might switch to this new way.

Section 9.14 is How many times? This is some phrasing I’ve tried using but usually fail and just make some counter variable I increment myself:

if the player is in the Ballroom for the third time ...

This only works if the condition is true then false then true then false then true. So staying in the ballroom three turns doesn’t trigger it, but leaving and returning does.

You can also say:

if the player is in the Ballroom for more than the third time ...
if the player has been in the Ballroom three times ...

‘only’ and ‘exactly’ mean the same thing, so:
‘if the player has been in the Ballroom only three times …’

can be written. How is this different from not adding ‘exactly’? I don’t know. I think when using ‘has been’ that it defaults to ‘at least __ times’, so exactly avoids that. IDK though.

Examples 152 is Infiltration:
The Secure Zone has the description "[if the player is in the Zone for the second time]Re-entering the Zone has not made you any more comfortable inside. [end if]Despite your carefully-chosen outfit and the walk you have been practicing, you are sure those inside can tell you don't belong. Not that very many people are visible here[if the player is in the Zone for more than the second time] -- the place seems more desolate than ever[end if]."

Trying this example out, the first part of the message only prints the second time, and never again. The second part is ‘sticky’ and keeps printing.

If we change the first condition to if the player has been in the Zone two times, it plays the second time and every time after that.

Finally, 9.15 is How many turns?

This is for conditions that are holding now and the previous turn and so on:

if the floppy hat has been worn for three turns ...

This is an ‘at least’ kind of thing so will fire if it has been worn every turn for at least 3 turns.

You can instead say any of these three things to mean ‘exactly three turns’:

if the floppy hat is worn for the third turn ...
if the floppy hat has been worn for only 3 turns ...
if the floppy hat has been worn for exactly three turns ...

Again, we shouldn’t use variable nouns like ‘if the noun has been open’, since ‘the noun’ might have meant something in the past.

Every turn:
    if the player has been in the Minivan for 5 turns, say "'Are we there [if saying no]now?'[otherwise]yet?' asks Pete.[end if]"

Whew! Not the biggest chapter, but some pretty intense stuff.

3 Likes

Yeah, there are all sorts of tricks here I wish I knew. This new chapter I just did has ‘was’ and ‘has been’ and ‘had been’, which is wild.

1 Like

if the first thing held by X is nothing is noticeably faster than the alternatives for testing whether a supporter or container is empty, or whether a person neither carries nor wears anything. Some of the obvious alternatives for testing emptiness compile to something that iterates through all the things in the game to make its determination. The difference won’t be noticeable for most games, but with a large number of things and such a test happening repeatedly in some loop, it could become conspicuous. (Zarf publicized this speed issue when he found it made a real difference while testing Hadean Lands.)

Along the same lines, this is a highly efficient way to iterate through things supported by something, things contained by a container, or things either carried or worn by a person:

let h be the first thing held by the player;
while h is not nothing begin;
  [ do something with h ]
  now h is the next thing held after h;
end while;

I do habitually use the former to test emptiness, but rarely use the latter to iterate.

3 Likes

These exist mostly for library purposes. They’re a lot more efficient than “a random thing that…”, because they query the object tree directly instead of going through the description system (which, in the general case, checks every object in the game to see if it matches the description). So library authors will want to use these when defining adjectives that need to be checked hundreds or thousands of times a turn.

Most games will never need to use them directly. But they’re documented so that extensions can depend on them.

I would say it’s more like a function minutes(n) which takes an int and returns a time.

Yep! Only “instead” and “after” rules cut off further processing, by default.

I find this extremely useful for tutorials. You can prompt the player about taking inventory only if they’ve never taken inventory yet.

2 Likes

Remember that not only is HL a very large game, it’s a very large game that I promised would run on the iPhone 4! I was really worried about efficiency.

So in that game, if I knew a container had exactly one item I would write “the first thing held by C” rather than “a random thing in C”. But in smaller games, I don’t bother worrying about that stuff.

That said, feel free to steal these lines:

Definition: a container is empty rather than non-empty if the first thing held by it is nothing.
Definition: a supporter is empty rather than non-empty if the first thing held by it is nothing.

(The Standard Rules define empty/nonempty for lists, rulebooks, texts, and other coding constructs, but not for game world objects. This is probably sensible for reasons of generality. It’s pretty common to define game containers which aren’t implemented as Inform containers, so a standard definition of “empty” would go wrong in a confusing way. But as long as you are aware of that, you can make use of these.)

5 Likes

Just wanted to document me trying to apply what I learned.

I have tears in space that lead to dimensions. I wanted to be able to type ‘in’ to go into any of them and ‘out’ to go out of any of them, regardless of what their standard direction was.

So I tried this:

Instead of going nowhere when the noun is inside in the front side of a space-tear (called currenttear):
	try entering currenttear;

but it failed.

Then I changed it to:

Before going nowhere in the front side of a space-tear (called currenttear):
	if the noun is inside:
		try entering currenttear instead;

and got the error:

You wrote ‘Before going nowhere in the front side of a space-tear (called currenttear)’ , but ‘a space-tear (called currenttear)’ is used in a context where I’d expect to see a (single) specific example of an object, not a description.

I ended up going with this:

Before going nowhere when the noun is inside:
	repeat with current running through space-tears:
		if the location is the front side of current:
			try entering current instead;

and that ended up working.(with something similar for the other side)

2 Likes

I think this’d work…

Before going nowhere in the presence of a space-tear (called the tear)
when the location is the front side of the tear:
   instead try entering the tear.
2 Likes

Chapter 10: Scenes

This is one of the shortest chapters so far, but a very useful one. I am in a bit of a rush today so also have less to add.

Section 10.1 just introduces the concept of a scene.

Scenes are to plot and time the way that rooms are to layout and direction.

Inform also allows us to create scenes, with cues for them to start and end, and some stage machinery (so to speak) making it easy to move the action on.

So organising the story-line into scenes is not simply a matter of making a list (Scene 1, then Scene 2, then Scene 3, finis). It is more like a chart in which one scene can lead in several possible ways to others - a sort of map of time, which as we shall see Inform displays in its “Scenes” index.

Section 10.2 is Creating a scene

We just do this by naming it:
Train Stop is a scene.

This has no effect on the player’s experience of the game…yet.

Scenes need a starting point:
Train Stop begins when the player is in the Station for the third turn.

Conditions like this only get checked at the start and end of turns, so if a condition becomes true for part of a turn and then false, the scene won’t trigger.

One of the most common ways I’ve seen people make scenes is with global flags. Here’s a scene I handle that way in my current game:
PlayerAflame is a truth state that varies. PlayerAflame is false.

Player-burning is a recurring scene. Player-burning begins when playeraflame is true.

Every turn during player-burning:
	if the time since player-burning began is 1 minutes:
		say "The flames that wreathe you grow taller and significantly more painful.";
	if the time since player-burning began is 2 minutes:
		say "Your skin is beginning to crispen in the flames.";
	if the time since player-burning began is 3 minutes:
		say "It is difficult to breathe as the fire burns away all the oxygen. The pain makes it difficult to walk.";
	if the time since player-burning began is 4 minutes:
		say "The flames are consuming you. With one last gasp, you fall to the ground.

[Sand-Dying]";
		now the player is in end-room;

Player-burning ends normally when the player is in end-room.
Player-burning ends abruptly when the player is not in spell-region.
Player-burning ends mercifully when playerAflame is false.

The multiple ending conditions is something we’ll get to later in this chapter. The advantage of using a global flag is that you can simply turn it off or on as needed. The disadvantage is that it doesn’t use all of Inform’s neat features for tracking state.

Every scene has two ‘rulebooks’, one at the beginning and one at the end:

When Train Stop begins:
    now the Flying Scotsman is in the Station;
    say "The Flying Scotsman pulls up at the platform, to a billow of steam and hammering."

When Train Stop ends:
    now the Flying Scotsman is nowhere;
    if the player is in the Station, say "The Flying Scotsman inches away, with a squeal of released brakes, gathering speed invincibly until it disappears around the hill. All is abruptly still once more."

Scenes have a ‘description’ tag (which is optional to fill out), which is just printed when the scene begins, making the following two lines equivalent:

Arrival is a scene. "There's a flourish of trumpets."
When Arrival begins: say "There's a flourish of trumpets."

You can give scenes properties and then write endings for all scenes with a given property (which I should try, since I have copy-and-pasted code for all the spell scenes in the spell portion of my game):

A scene can be bright or dim. A scene is usually dim. Dawn is a bright scene.

When a scene which is bright ends: say "So passes the bright [scene being changed]."

Example 154 is Pine 1:

Discovery is a scene. Discovery begins when play begins. Discovery ends when Sleeping Beauty is awake. Marriage Proposal is a scene. Marriage Proposal begins when Discovery ends.

When Discovery ends: say "Throughout the palace you can hear the other sounds of stirring and movement as the spell of centuries is broken."

This example then goes on to provide several ways to wake someone.

Example 155 is Entrapment:

A person can be confident, nervous, or embarrassed. The player is confident.

Touching the paneling is embarrassing behavior. Looking under the carpet is embarrassing behavior. Entering the table is embarrassing behavior. Looking under the table is embarrassing behavior.

Instead of embarrassing behavior:
    if the player is nervous, now the player is embarrassed;
    if the player is confident:
        say "Before you can act, you hear movement from the inner office. You freeze, not quite ready to be discovered in this situation. But no one comes out, and you begin to breathe more easily.";
        now the player is nervous;
    otherwise:
        continue the action.

Causing trouble is a scene. Causing trouble begins when play begins. Causing trouble ends when the player is embarrassed. When Causing trouble ends: say "Just at this inopportune moment, you hear a throat being cleared behind you. 'We can see you now within,' says a dry voice."; end the story saying "To be continued..."

Section 10.3 is Using the Scene Index.

Here’s an example scene index from my game:


This is a nice way to check if you remembered to add a start and an ending to all your scenes and to check if things are recurring.

I didn’t really know it existed until this week!

You can use some timing things here. The wording has to be very precise; I’ve typed many paraphrased version of this but they’ve never worked:

Train Stop ends when the time since Train Stop began is 3 minutes.

You can also measure the time since a scene ended:
time since Formal Dinner ended

You can also get a specific time of day (remembering that games start at 9:00 AM) by typing time when (scene) began or time when (scene) ended

Example 156 is Age of Steam, which is kind of the main example of this chapter:

Train Stop is a scene. Train Stop begins when the player is in the Station for the third turn. Train Stop ends when the time since Train Stop began is 3 minutes.

When Train Stop begins:
    now the Flying Scotsman is in the Station;
    say "The Flying Scotsman pulls up at the platform, to a billow of steam and hammering."

When Train Stop ends:
    now the Flying Scotsman is nowhere;
    say "The Flying Scotsman inches away, with a squeal of released brakes, gathering speed invincibly until it disappears around the hill. All is abruptly still once more."

Section 10.4 is During Scenes

You can just add ‘during such and such scene’ to check that the scene is happening.

Before going north during the Train Stop, say "The train blocks your way." instead.

Or you can just check directly:

if Train Stop is happening, ...

You can also check:
if Train Stop has happened:
if Train Stop has not happened:
if Train Stop has ended:
if Train Stop has not ended:

For recurring scenes (which we haven’t covered yet), a scene can simultaneously have ended and be happening.

A scene is a kind of thing and can have properties:
A scene has a text called cue speech. The cue speech of Train Stop is "All aboard!".

And you can make up properties and test them:
Before going north during a dull non-recurring scene, ...

Example 157 is Full Moon:

Wolf Pursuit is a scene. Wolf Pursuit begins when play begins.

Every turn during Wolf Pursuit, say "[one of]A twig snaps behind you![or]The wind howls in your ears.[or]You feel chilly.[at random]".

Example 158 is Space Patrol - Stranded on Jupiter!

Last score is a number that varies. Every turn: now the last score is the score.

Ralstons Ad is a scene. Ralstons Ad begins when score is not the last score. Ralstons Ad ends when the Ricechex is consumed.

Include Basic Screen Effects by Emily Short.

When Ralstons Ad begins:
    center "*** We'll be back in just a moment! ***";
    pause the game;
    strip the player;
    move the player to the Kitchen.

When Ralstons Ad ends:
    center "*** And now, back to today's exciting adventure ***";
    pause the game;
    restore the player.

Example 159 is Bowler Hats and Baby Geese

This is a complex example but interesting, so I’ve included a lot of it.

A scene can be restricted or free.

Instead of going somewhere during a restricted scene:
say "Better to stay here for the moment and find out what is going to happen next."
The Clown Performance is a restricted scene. Clown Performance begins when the turn count is 3.

When Clown Performance begins:
    move the clown to the location.

Every turn during Clown Performance:
    repeat through the Table of Clowning:
        say "[event description entry][paragraph break]";
        blank out the whole row;
        stop.

When Clown Performance ends:
    now the eggs are nowhere;
    now the clown carries the omelet.

Clown Performance ends when the number of filled rows in the Table of Clowning is 0.

Table of Clowning
event description
"A clown with a purple polka-dot bowler hat strides into the vicinity and begins to juggle baby geese."
"While the clown juggles, the baby geese visibly grow older and larger. The clown becomes unnerved."
"In an attempt to resolve the problem, the clown reverses the direction of his juggling. The geese revert to goslings."
"The goslings become smaller and smaller until the clown is juggling goose eggs[replace eggs]."
"The clown throws all the eggs into the air at once and catches them in the bowler hat. He takes a bow; the audience applauds. As a final gesture, he upends his hat to release a perfectly cooked omelet."

To say replace eggs:
    now the supply of baby geese is nowhere;
    now the clown carries the eggs.

Free Time is a scene. Free Time begins when Clown Performance Ends.

Example 160 is Day One:

Lecture is a scene. Lecture begins when play begins.

Every turn during Lecture:
    repeat through Table of Lecture Events:
        say "[event entry][paragraph break]";
        blank out the whole row;
        rule succeeds.

Lecture ends when the number of filled rows in the Table of Lecture Events is 0.

Instead of doing something other than waiting, looking, listening or examining during Lecture:
    say "Dr Freitag glares at you so fiercely that you are frozen into inaction."

There then follows a table of lecture events which is quite long.

Section 10.5 is Linking Scenes together:

This just points out that you can start one scene when another ends:

Brief Encounter is a scene. Brief Encounter begins when Train Stop ends.

Village Exploration is a scene. Village Exploration begins when Brief Encounter ends.

Example 161 is Pine 2, which adds some extra scenes:
Marriage Proposal is a scene. Marriage Proposal begins when Discovery ends.

Instead of asking an awake beauty about a topic listed in the Table of Conversation:
    now Beauty is passive;
    say "[reply entry][paragraph break]";
    blank out the whole row.

Marriage Proposal ends when the number of filled rows in the Table of Conversation is 0.

Every turn during Marriage Proposal:
    if Beauty is active:
        repeat through Table of Conversation:
            say "[quip entry][paragraph break]";
            blank out the whole row;
            make no decision.

This example is really odd, with a set of things you can say and responses, but if you don’t talk the responses happen automaticallly.

This game is in the genre of Emily Short’s other ‘fractured fairy tales’ (I think that’s the phrase).

Section 10.6 is More general linkages

It’s just pointing out that you don’t have to start one scene when another ends; you can do random stuff like:
Luggage Trouble is a scene. Luggage Trouble begins when Brief Encounter begins.
or
Luggage Trouble ends when Brief Encounter ends.
or
Railway Meeting is a scene. Railway Meeting begins when play begins.

And it points out that:

When play ends, of course, all scenes end, so there is no need to say that.

Example 162 is The Prague Job:

Reviewing Possessions is a scene. Reviewing Possessions begins when play begins.

Escalating Danger is a scene. Reviewing Possessions ends when Escalating Danger begins. Escalating Danger begins when preparations near completion.

To decide whether preparations near completion:
if at least two of the things which are carried by the player are seen, yes;
no.

When Escalating Danger begins: say “Someone pounds on the door of your hideout and yells at you in Czech.”

Instead of going from the Toilet during Reviewing Possessions: say “You need to go over your equipment first, and make sure you’re ready here.”

Instead of going from the Toilet during Escalating Danger: say “You’re not done checking over your materials.”

Instead of waiting during Escalating Danger: say “There’s no time to waste.”

Every turn during Escalating Danger: if the time since Escalating Danger began is greater than 1 minute, say “Impatient footsteps pass your door again.”

Escalating Danger ends when every thing which is carried by the player is seen. When Escalating Danger ends, say “There – nothing damaged or torn. You’re ready to go.”

Mission is a scene. Mission begins when the player is in the Long Hallway. When Mission begins: end the story saying “The game is afoot”

This kind of thing can make a game really fun, honestly.

This uses the ‘to decide whether’ construction, which I’ve found useful for scenes:

The picture-arrival is scene. Picture-arrival begins when the pictures are ready.

To decide whether the pictures are ready:
	if the number of hidden-spears in weapons-rack < 6, decide no;
	if the number of hidden-silks on chan-line < 6, decide no;
	decide yes;

Example 163 is Entrevaux:
This is another great example (this whole chapter has examples whose quality is above the other chapters). Here we give scenes a room and a list of objects that need to be put in the room and things the player needs to hold:

A scene has a room called the starting location.

A scene has a list of objects called the scenery props.

A scene has a list of objects called the inventory props.

We then use some rules that have the ‘first’ or ‘last’ keywords:

A scene can be location-silent or location-loud.

First when a scene (called the current scene) which is not the Entire Game begins:
    if chapter counter is greater than 0:
        pause the game;
    increment chapter counter;
    say "[bold type]Chapter [chapter counter]: [current scene][roman type]";

Last when a scene (called the current scene) which is not the Entire Game begins:
    repeat with item running through the scenery props of the current scene:
        move the item to the starting location of the current scene;
    repeat with item running through the inventory props of the current scene:
        move the item to the player;
    if the location is not the starting location of the current scene:
        if the current scene is location-loud:
            move the player to the starting location of the current scene;
        otherwise:
            move the player to the starting location of the current scene, without printing a room description.

When a scene (called the current scene) ends:
    repeat with item running through things which are not fixed in place:
        if the item is not the player:
            now the item is nowhere.

Then we have some actual scenes:

Arrival is a location-silent scene. "After many days['] journey, you have arrived at last in Entrevaux, a walled medieval town now chiefly of interest to tourists and crusade re-enactors."
    The starting location of Arrival is the Entrevaux Station.
    The scenery props of Arrival are { re-enactors, trolley }.
    The inventory props of Arrival are { the used ticket, one-euro coin }.

Arrival begins when play begins. Arrival ends when the time since Arrival began is 2 minutes.

Abduction is a location-loud scene. "You check into the Hotel Vauban and sleep deeply enough; it was a long and sticky trip to get here.

Then in the middle of the night something confusing happens. You have the impression of strangers in your room, and then a searing pain, and you don't come back to yourself until midmorning of the following day..."
    The starting location of Abduction is the Hillside Tower.
    The scenery props of Abduction are { kidnapper }.

Abduction begins when Arrival ends.

Section 10.7 is multiple beginnings and repeats. You can have multiple triggering conditions for a scene:

Bittersweet Ending begins when Stranger's Rejection ends.
Bittersweet Ending begins when Stranger's Acceptance ends.

You can also have scenes that repeat called ‘recurring scenes’. I use this for the spells in the spell region of my game, since they last for about 3 turns before they can be cast again.

This is the text’s example of a recurring scene:

Train Stop is a recurring scene. Train Wait is a recurring scene.
Train Wait begins when play begins.
Train Stop begins when Train Wait ends.
Train Wait begins when Train Stop ends.

Example 164 is Night and Day:

The sun is a backdrop. It is everywhere. The description is "Currently out of sight."

Night is a recurring scene. Night begins when play begins. Night begins when Dusk ends. Night ends when the time since Night began is 3 minutes.

Dawn is a recurring scene. Dawn begins when Night ends. Dawn ends when the time since Dawn began is 1 minute.

Day is a recurring scene. Day begins when Dawn ends. Day ends when the time since Day began is 3 minutes.

Dusk is a recurring scene. Dusk begins when Day ends. Dusk ends when the time since Dusk began is 1 minute.

It also has special things to print when those scenes begin.

The scenes index lists it like so:

Night (recurring)
Dawn (recurring)
Day (recurring)
Dusk (recurring)
Night

Example 165 is Pine 3, which is quite complex by now.

It adds a flashback:

Instead of asking an awake beauty about a topic listed in the Table of Flashback Material:
    now Beauty is passive;
    say "[reply entry][paragraph break]".

A fact is a kind of thing. The family circumstances is a fact. A fact can be known or unknown. A fact can be current or past.

Table of Flashback Material

topic reply
“poor/poverty/family/money/mother/circumstances” or “family circumstances” or “my family/mother” “[if family circumstances is unknown]‘I wish you’d give some thought to marrying me. You see,’ you say, your jaw tensing. ‘I wouldn’t ask if it weren’t for my [family circumstances]…’[otherwise]‘I don’t think you fully understand the [family circumstances],’ you say.[end if]”

After printing the name of a fact (called target): now the target is current; now the target is known.

Poverty flashback is a recurring scene. Poverty flashback begins when family circumstances is current. When poverty flashback begins: strip the player; move the player to the Woodcutter's Shack.

And so on. ‘Strip the player’ sounds like a standard phrase, but it has to be defined:

Saved location is a room that varies. Locker is a container. Wardrobe is a container.

To strip the player:
     now every thing carried by the player is in the locker;
    now every thing worn by the player is in the wardrobe;
    now saved location is location.

I do something very similar in my current game, moving all of my worn and held things to a fake player in another room. Later I actually have you visit the room and see the person in the horror section…

Section 10.8 is Multiple endings, which I’ve used a lot recently and enjoy quite a bit. You can have up to 31 endings per scene (or 15 in z-machine). You just add adverbs (or whatever) after the word ‘ends’:

Brief Encounter ends happily when ...
Brief Encounter ends wisely but sadly when ...

So no matter how you end the scene, the ‘when scene ends’ rules all trigger. You can also make special rules that only trigger with certain endings, like:
when Brief encounter ends sadly but wisely:

You can also make new scenes only start if a certain kind of ending happened:

Stranger's Acceptance begins when Brief Encounter ends happily.
Stranger's Rejection begins when Brief Encounter ends wisely but sadly.

And you can also check how something happened:

if Brief Encounter ended happily ...
if Brief Encounter did not end happily ...
if Brief Encounter ended wisely but sadly ...
if Brief Encounter did not end wisely but sadly ...

This is a pretty important section and I wish it had a bit more examples in the main text.

Example 166 is Panache:
This example creates a Table of Events instead of a score.

To record (occurrence - text) in (target table - a table name):
choose a blank row in the target table;
now the event entry is the occurrence.

Table of Events
event
"A Duel of Insults"
with 30 blank rows.

The plot summary rule is listed instead of the announce the score rule in the carry out requesting the score rules.

This is the plot summary rule:
    say "The Plot So Far: [paragraph break]";
    let act number be 0;
    repeat through the table of Events:
        increment act number;
        say " Act [act number]: [event entry][line break]".

Sulky Ramble is a scene. Sulky Ramble begins when Courting Roxane ends in success. Sulky Ramble ends when the time since Sulky Ramble began is 2 minutes. When Sulky Ramble ends: record "Wandering the Streets, Sulking" in the Table of Events.

Every turn during Sulky Ramble:
    say "You find yourself kicking fenceposts quite without thinking about it."

Smug Ramble is a scene. Smug Ramble begins when Courting Roxane ends in failure. Smug Ramble ends when the time since Smug Ramble began is 2 minutes. When Smug Ramble ends: record "Wandering the Streets, Exultant" in the Table of Events; say "Of course, you will regret this soon enough."

Every turn during Smug Ramble:
    say "You find yourself smiling fiercely at the moon."

Example 167 is Pine 4, which has another flashback that repeats only until a condition is met:

Beauty has a number called clue count.

Dramatic revelation is a recurring scene. Dramatic revelation begins when attempting confidence.

To decide whether attempting confidence:
    if dramatic revelation ended in success, no;
    if secret identity is current, yes;
    no.

When dramatic revelation begins:
    strip the player;
    say "You reminisce about one of the many stops on the way here: you had a long journey from your homeland, and it wasn't made any easier by your poverty, the inability to afford decent inns or plentiful food or any kind of ride along the way.";
    move the player to the Forest Clearing;
    move the pack to the player; now the player wears the trousers; now the player wears the shirt.

Instead of swimming in the presence of the pool:
    increment clue count of Beauty;
    say "You consider going for a swim, but don't dare be caught unclad and unarmed, not here. There are too many men around, and any of them discovering you here would surely take advantage."

Instead of searching or drinking the pool:
    increment clue count of Beauty;
    say "You lean over the pool and look carefully at your reflection, your hair loose and unbound, falling around your face in waves. (That should surely give it away!)"

Instead of waiting during dramatic revelation: say "You wait for the penny to drop, for her to understand."

Dramatic revelation ends in failure when waiting or the time since dramatic revelation began is five minutes. When dramatic revelation ends in failure:
    now secret identity is past;
    restore the player;
    now Beauty is passive;
    say "She wrinkles her nose. 'I don't understand!' she says. 'What are you trying to tell me?'

    You could weep for womankind. But you don't quite dare spell it out in so many words, not when someone might come up the stair and overhear a chance revelation."

Dramatic revelation ends in success when Beauty is clever. When dramatic revelation ends in success:
    restore the player;
    now Beauty is passive;
    say "'You're -- a girl? Like me?'

'Not much like you,' you say, glancing over her petite frame and pert nose. 'But female, at any rate.'"

Definition: Beauty is clever if the clue count of Beauty is greater than 2.

This is a very complex example, of which I’ve only added a bit. There are other scenes added as well. Yet this is just listed as a 3 star example!

Section 10.9 is Why are scenes designed this way.

It points out that we specifically do not have a way to say ‘start the scene now’. Here is the reasoning:

  • it guarantees that each action falls entirely inside, or entirely outside, of any given scene (and therefore that “during…” clauses in the conditions for a rule are not affected by rule ordering);
  • it ensures that scene changes occur outside actions, like every turn rules;
  • it promotes a style of writing which makes it clearer to the reader of the source text when a scene begins and ends, and what conditions are guaranteed to be true during it;
  • it makes it possible for the Scenes index page to show this information in a communicative way.

I actually agree with this design decision. It does make you think of things in a well-regulated and organized way. And as he points out:

Since scenes are, in the end, only a convenient way to organise rules, and do nothing that cannot be done by other means, this simplified system of scene changing does not really restrict us.

In fact, I did this a lot early on. I made my own ‘scene structure’ by just having a numerical variable I incremented every turn until it reached a certain number. That’s the nice thing about Inform; it doesn’t matter too much that a lot of it is obscure, because the main core of things is robust enough that every problem has multiple solutions.

Overall, this is a sensible, well laid out chapter that explains scenes well, and has great examples that show the power of scenes. This was a pleasant highlight for me to read.

Example 168 is Cheese-makers. It just has different ways of handling conversation during scenes:

Prologue is a scene. Prologue begins when play begins.
Instead of talking to the player when the Prologue is happening:
    say "There will be plenty of occasion for muttered asides later in the play, but for now you must prepare the audience for things to come."

Instead of talking to the audience when the Prologue is happening:
    say "Drawing breath, you turn to the audience, and offer them a genial, witty, colorful, and of course crude synopsis of what they are about to see; describing all the characters in unmistakable terms and not omitting the most important of them all, your august self.";
    now the audience is prepared.

Instead of talking to the audience when the Prologue has happened:
    say "You may only direct monologues to the audience when the other actors are off-stage. Otherwise, their characters might have to notice."

Prologue ends when the audience is prepared.

Parodos is a scene. Parodos begins when Prologue ends.
When Parodos begins:
move the chorus to the theater.

Instead of talking to someone during Parodos:
say "Sssh: this moment belongs to the chorus. They've worked so hard on it, after all."

Parodos ends when the time since Parodos began is 4 minutes.
2 Likes

I would use “going inside” as the criterion here, rather than “going nowhere”. It’s simpler, since it doesn’t get into the question of whether there’s an “in” exit already.

(There shouldn’t be, of course; that would be confusing to the player.)

Before going inside when a tear (called T) is in the location:
	instead try entering T;

I’m also using “… is in the location” rather than “in the presence of…” because, again, it’s simpler. “Presence of” does a scope check, but we don’t have to worry about tears being inside containers or supporters, so just checking the object’s location is fine.

(If spacetime-tear is a kind that could be in a container, well, then you have to get less simple.)

The earlier examples distinguished the front side of a tear from the back side, which we can easily add. Or maybe you’d distinguish the kind of room? Like you might start “A dimension is a kind of room” and handle “going outside” in those rooms instead. Various options.

4 Likes

Yeah, all of these are helpful!

And the front sides of all the tears are all in a region called ‘ship-region’, so I could also use that region to refer to things. Thanks to both of you for the tips

This is the example that illustrates issue I7-2074. The scene will never end if Train Stop began three minutes or less to midnight. A similar piece of code caused Counterfeit Monkey to soft lock for some players.

1 Like

Chapter 11 - Phrases

This is an important chapter, and one I didn’t figure out for a long time.

My biggest grip with Inform 7 at the beginning was that it didn’t have functions, so I couldn’t repeat behavior without copying and pasting.

But I’ve since found it it does! They’re just called phrases and they’re so general that at first it just looks like nonsense. You can type anything you want, like

To become awesome:
    now the player is in throne-room;
    now the crown is worn by the player;

and then you can just type that whenever you want:

After touching the wish-stone:
  become awesome;

However, this chapter doesn’t teach us how to make our own phrases, that will be much later. Instead, it teaches us about inform’s own phrases.

Section 11.1 What are phrases?

Inform has around 350 phrases built-in, and the chapters so far have already defined about 100 of those.

There are 4 kinds of phrases:
a) Phrases that do things (like void functions in other languages)
b) Phrases to decide conditions (these are like functions returning boolean values, and we’ll talk more about them later)
c) Phrases to decide a value (like functions returning a number)
d) Text substitutions (like functions returning a string)

Inform provides about 60 built-in text substitutions.

Section 11.2 is The Phrasebook.

The phrasebook is the collection of phrases Inform recognizes in the Index. I have never looked at this panel. Let’s do so!

Here’s a sample from the first tab of my phrasebook index:

Oh, so this section does show how to make a new phrase (that seems more important than the phrasebook, maybe make this section called Making new phrases instead of Phrasebook?)

Here is a simple definition of a new phrase:

To spring the trap:
    say "'Sproing!' go the hinges and, with a flash of silver, the enormous blades whisk together!";
    end the story.

And then you can use that phrasing whatever, but you have to type it word for word without the ‘to’:

Instead of entering the cage:
    spring the trap.

Section 11.3 is pattern matching. This is where the weird ( - ) phraseology I asked about upthread comes from:

To admire (item - an object):
    say "You take a long look at [item].".

This does very little, of course, but it does allow the wording to be different each time the phrase is used:

admire the diamonds;
admire Mr Cogito;
admire the honey sandwich;

Ohhhh, now I get why phrases use this weird parentheses hyphen thing instead of (called a ____) like everything else; it’s because:

The bracketed part of the definition, “(item - an object)”, tells Inform to expect an object in that position, and Inform enforces this carefully. So this definition might tell Inform what “admire the barricade” means, but not what

admire "blue cheese";
admire 63;

mean.

Technically they could have allowed something like
“To admire an object (called item)” but I wonder if the way phrases are worded is so general that the parser would get a lot of hiccups trying to figure out where the static part stopped and the variable part began.

So this is just a way to input parameters into phrases, which are Inform 7’s functions.

Another example:

To slam shut (box - an open container):
    say "With great panache, you slam shut [the box].";
    now the box is closed.

If you type that, then later you can type:
slam shut the Dutch armoire;

and inform will compile and print that as:
With great panache, you slam shut the Dutch armoire.

Bizarrely, you can make a phrase that only applies to one thing. If we ‘overload’ a phrase with multiple possible inputs and if something falls into more than one of the possible input categories, it only picks the more specific one.

So the example in the text is making a phrase that applies to all numbers and the the same phrase but it only applies to the number 7 (which honestly seems pretty dumb to do but kind of works like an ‘instead’ in this specific situation):

To grant (bonus - a number) points:
    increase the score by the bonus.

To grant (bonus - 7) points:
    say "You shiver uncontrollably."

[B]oth apply to the case of “grant 7 points”, Inform uses the second, because it’s the more specific of the two possibilities.

You can use slashes to vary the wording used in phrases (something I’ve never done):

To grant (bonus - a number) point/points: ...
or allow a word to be omitted using ‘–’:

To grant (bonus - a number) point/points/--: ...

Example 169 is Ahem:

To do/follow (chosen rule - a rule) exactly/precisely/just (N - a number) time/times:
    repeat with index running from 1 to N:
        follow chosen rule.

This is the throat-clearing rule:
    say "'Ahem,' says [a random visible person who is not the player]."

After waiting:
    do the throat-clearing rule just one time.

Instead of listening:
    follow the throat-clearing rule precisely three times.

Example 170 is Ferragamo Again:
This example shows some basic ‘to say’ phrases, which are the ones I use the most often:

To say (annoyed-person - a person) gestures in irritation:
    say "[The annoyed-person] sighs heavily. [run paragraph on]"

To say (annoyed-person - Vanessa) gestures in irritation:
    say "[The annoyed-person] takes off her glasses and polishes them on her sleeve. [run paragraph on]".

To say (annoyed-person - Holman) gestures in irritation:
    say "Holman bobs his head. [run paragraph on]"

The previous subject is a subject that varies.

Instead of talking about something for more than one turn:
    if the noun is the previous subject, say "[a random visible person who is not the player gestures in irritation]Maybe you should let this one go.[line break][paragraph break]";
    otherwise continue the action.

Anything defined with ‘to say’ can be thrown into any printed text, so I like to use them to trigger actions. In my game, conversational topics are physical objects called ‘quips’, so I often have stuff like this:

The description of the flight-tear is "...It issues a series of beeps, and the space in front of you to the north rips open violently, space itself tearing. The creature dives through the tear. Officer Mefe doesn't seem to notice anything at all[deliverchipless]...."

To say deliverchipless:
	deliver chipless-quip;

‘Deliver’ itself is a phrase from my extensions Clues and Conversation:

To deliver (CurrentQuip - a quip):
	if CurrentQuip is carried by the player:
		do nothing;
	otherwise:
		now CurrentQuip is deliveryflagged;

And ‘deliveryflagged’ is an either/or property that gets fed into another phrase (in spoilers for length):

Summary
To clear the flags:
	let somethingDelivered be 0;
	repeat with currentquip running through once-delivered deliveryflagged quips:
		now currentquip is not deliveryflagged;
	repeat with currentquip running through deliveryflagged quips:
		say "[bracket]New [if currentquip is a squip]Clue [otherwise]Topic [end if]- [currentquip][close bracket][roman type]";
		say "[line break]";
		now history of currentquip is "[currentquip] - [preview of currentquip][line break]";
		now currentquip is carried by the emrys-weaver;
		now currentquip is not deliveryflagged;
		now currentquip is once-delivered;
		now somethingDelivered is 1;
		if the target of currentquip is nothing:
			repeat with currentperson running through talkative people:
				now currentperson heeds currentquip;
	if somethingDelivered is 1:
		If FirstClear is 0:
			say "[line break][bracket]You can see your list of [HasCluesOrTopics]s by typing [CapCluesOrTopics], or just [if the number of clues carried by the player > 0]C[otherwise]T[end if].[close bracket]";
			say "[line break]";
			now FirstClear is 1;
		if the player is not emrys-weaver:
			if cluesclear is false:
				say "[line break][bracket]Clues discovered during statements can be used or discussed once the statement is over.[close bracket]";
				say "[line break]";
				now cluesclear is true;

and finally this gets fed into an Every turn rule:

Every turn:
	clear the flags

(this rigmarole is to ensure that new conversational topics are printed at the end of a given turn instead of in the middle).

Example 11.4 is The SHOWME phrase, which is similar to the SHOWME command used for testing only.

“showme” is a convenient way to see what’s going on inside a phrase which isn’t behaving as expected, or to find out the kind of a value. Here are some trickier examples. Suppose our design includes:

The matching key of the blue door is the brass Yale key.

If we then try this:

When play begins:
showme matching key of the blue door.

we get, when the story starts up,

"matching key of the blue door" = object: brass Yale key

I never do this, because you can simply add something like:

Every turn:
    say "The matching key of the blue door is [the matching key of the blue door]";

I do stuff like that constantly for debugging. The main benefit of showme that I can see is that it never does anything in the final, released version of the game.

Section 11.5 is Conditions and questions.

A condition is anything which might be true or false:

Mr Kite is in Bishopsgate
the score is greater than 10
Sherlock Holmes suspects a woman

There are a few special conditions:

if in darkness tests if the player has no light, and is different than being in a dark room (since the player might have light or be in a container).

if player consents:

This condition is unusual in doing something and not simply making a silent check: it waits for the player to type YES (or Y) or NO (or N) at the keyboard, and then is true if the answer was yes.

You can turn any condition into a boolean with the following phrase:
whether or not (a condition) … truth state

For instance, you can say:

let victory be whether or not all the treasures are in the cabinet;

and then subsequently:

if victory is true, ...

I find this personally a bit disturbing, to be honest. It feels like Inform I’ve seen and used before but slightly off, like a cat you think is your own and you go to pet it before you realize it’s someone else’s cat that’s wandered by your house.

You can also make truth states that vary:
Salvation earned is a truth state that varies.

I used to use 0/1 variables because I didn’t know truth states existed, so I’d be like FlyingFlag is a number that varies. FlyingFlag is 0.

Now I just say
FlyingFlag is a truth state that varies. FlyingFlag is false.
It’s logically the same, but helps me remember what the numbers stand for.

Example 171 is Proposal:
This has two different ways to handle yes/no questions: the ‘player consents’, and regular conversation.

Mr Spruce is a man in the Conservatory. Mr Spruce can be apprehensive or calm. Mr Spruce is calm. Mr Spruce can be handsome or ugly.

When play begins:
    say "Do you like Mr Spruce? ";
    if player consents, now Spruce is handsome;
    otherwise now Spruce is ugly;
    say paragraph break.

Instead of saying yes in the presence of an ugly apprehensive Mr Spruce:
    now Mr Spruce is calm;
    say "Remembering what your mother said to you about the stock exchange and Dear Papa, you close your eyes and accept Mr Spruce.";
    end the story saying "Alas for your maiden hopes."

Instead of saying yes in the presence of a handsome apprehensive Mr Spruce:
    now Mr Spruce is calm;
    say "You are silent with delight for a moment before you say yes, yes!";
    end the story saying "How Genevieve Stubbs will cry!"

Instead of saying no in the presence of an ugly apprehensive Mr Spruce:
    now Mr Spruce is calm;
    say "Gently you inform Mr Spruce that it is impossible. He seems less deflated than you had expected.";
    end the story saying "Odd, that..."

Instead of saying no in the presence of a handsome apprehensive Mr Spruce:
    now Mr Spruce is calm;
    say "You lower your eyes and refuse petulantly, hoping to stir him to a more ardent repetition of these same requests. But then -- alack! -- he says 'I see how it is!' in a strangled voice, and strides from the room!";
    end the story saying "A fatal error!"

Section 11.6 is If, which is a Rudyard Kipling…wait, never mind, it’s just the regular if statement from programming.

You can use ‘if’ in two different ways:

if (a condition) , (a phrase)

or:

if (a condition):

So, all in one line with a phrase following or in a block format. If you want to type ‘if not…’, just use Unless:

unless (a condition) , (a phrase)

or:

unless (a condition):

Section 11.7 is Begin and End. It talks about two ways to group complex if statements in blocks.

The first is as so, using indentation:

To comment upon (whatever - a thing):
    if whatever is transparent, say "I see right through this!";
    if whatever is an open door:
        say "Oh look, an open door!";
        if whatever is openable, say "But you could always shut it."

The second is to use ‘begin’ and ‘end if’:

To comment upon (whatever - a thing):
    if whatever is transparent, say "I see right through this!";
    if whatever is an open door
    begin;
        say "Oh look, an open door!";
        if whatever is openable, say "But you could always shut it.";
    end if.

I don’t use this, but I’ve seen some people do and it confused me.

It also claims that Python is named after Monty Python’s Flying Circus, which I am deliberately not going to look up for confirmation.

Example 172 is Matreshka:
This example has nothing to do with the material in the section. Instead of using Begin and If in an if statement, it introduces a ‘while’ statement with no explanation in the commentary:

Carry out ransacking:
    while the player can see a closed openable unlocked container (called target):
        say "[target]: [run paragraph on]";
        try opening the target.

Although it does have an if statement earlier (still not using Begin or If):

Check ransacking:
    if the noun is not the location, say "You can hardly search [the noun] from here." instead.

Example 173 is the princess and the pea, which also uses a while statement. Was this section originally a section on while statements that got rewritten, but the examples just never got changed?

Check ransacking:
    if the noun is not the location, say "You can hardly search [the noun] from here." instead.

Section 11.8 is called ‘otherwise’, which is exactly equivalent to ‘else’ in most programming languages. You can use it in many ways (including just typing ‘else’):
otherwise if (a condition)

or:

otherwise unless (a condition)

or:

otherwise (a phrase)

or:

else if (a condition)

or:

else unless (a condition)

or:

else (a phrase)

So, for example:

if N is 2, say "Hooray, N is 2!";
otherwise say "Boo, N is not 2...";

So this is pretty bog standard programming. If you’ve programmed with any language every, you’ve probably done If/Else statements. If inform is your first language, then this section does a pretty good job of explaining it.

You can also use ‘switches’ in Inform like this:

if the dangerous item is:
    -- the electric hairbrush:
        say "Mind your head.";
    -- the silver spoon:
        say "Steer clear of the cutlery drawer."

and you can use ‘otherwise’ for exactly one of these options:

if N is:
    -- 1: say "1.";
    -- 2: say "2.";
    -- otherwise: say "Neither 1 nor 2.";

I don’t use this, but I’ve seen people using it recently on this forum, and I think it looks neat!

Example 174 is Numberless:

When play begins:
    let N be a random number between 1 and 5;
    if N is 1:
        say "N is one.";
    otherwise if N is 2:
        say "N is two.";
    otherwise if N is 3:
        say "N is three.";
    otherwise:
        say "N is more than the number of your toes."

When play begins:
    let Y be a random number between 6 and 10;
    if Y is:
        -- 6: say "Six is the magic number!";
        -- 7: say "The number of the day is seven!";
        -- otherwise: say "Today's magic number is boring."

When play begins:
    let X be a random number between 11 and 14;
    if X is a number listed in the Table of Switching, say "[output entry][paragraph break]";
    otherwise say "X is greater than the number of your noses!"

Table of Switching
number

output

11

"X is eleven!"

12

"X is twelve!"

13

"X is thirteen!"

So three different ways of handling if statements with text responses.

Section 11.9 is ‘While’, which has no examples. So it looks like the examples for 11.9 accidentally got moved to section 11.7, and that should probably be reported as a bug.

So a while loop just gets repeated forever until it’s no longer true:

while someone (called the victim) is in the Crypt:
    say "A bolt of lightning strikes [the victim]!";
    now the victim is in the Afterlife;

These are dangerous and should be tested thoroughly to avoid infinite loops. The example in the text is amusing:

while eggs is eggs:
say "again and ";

which, as sure as eggs is eggs (which is very sure indeed), writes out

again and again and again and again and again and ..

You can use the indentation method or the begin/end method:

while ...
begin;
    ...
end while.

Section 11.10 is Repeat, which is a for loop, and something I find very useful indeed. Repeat loops always have a definite ending, unlike while loops.

This section does the most basic kind of Repeat loop, which just goes through consecutive values in any kind of enumerated value:

repeat with (a name not so far used) running from (arithmetic value) to (arithmetic value)

or:

repeat with (a name not so far used) running from (enumerated value) to (enumerated value):

Examples include:

repeat with counter running from 1 to 10:
repeat with moment running from 4 PM to 4:07 PM:
Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet.

I don’t think I ever used this version of repeat.

There is a more complicated example:

To plot a grid with size (S - a number):
    repeat with x running from 1 to S:
        say "Row [x]:";
        repeat with y running from 1 to S:
            say " [y]";
        say "."

This section is another of the ‘basic programming language 101’ sections. So maybe this chapter 11 would be a good introduction for ‘Inform for programmers’, since this chapter has functions, if statements, else statements, while and for loops, which are most of the main things you want to do in almost any programming language. This is as opposed to the ‘Basic Actions’ , ‘Change’ and ‘Scene’ sections, which I think are good for non-technical introductions and/or actual game making.

Example 175 is Wonka’s Revenge:

A lottery drum is in the Lodge. "Before you is the lottery drum[if we have spun the drum], ready to disgorge a ticket[otherwise], waiting to be spun[end if]." In the drum are a red ticket, an orange ticket, a yellow ticket, a green ticket, a blue ticket, a purple ticket, and a ticket of pure gold.

Spinning is an action applying to one thing.

Check spinning: if the noun is an open container which contains something, say "[The list of things in the noun] would fly out." instead.

Carry out spinning a container:
shuffle the contents of the noun.

To shuffle the contents of (basket - a container):
    let moves be the number of things in the basket;
    repeat with counter running from 1 to moves:
        move a random thing in the basket to the basket.

11.11 is Repeat running through

This section has my preferred form of repeat loops. I have 53 loops in my game of the form ‘repeat with ___ running through’.

You use it like this:
repeat with item running through open containers:
and then you write code including whatever name you gave your variable (here, ‘item’).

repeat with suspect running through the men who are in a lighted room:
    say "[The suspect] is in [the location of the suspect].";

You can’t repeat through all numbers but can repeat through all 1440 times in the day.

Example 176 is Strictly Ballroom:


A person can be alert or occupied. A person is usually alert.

When play begins:
now the player is occupied.

Dance is a kind of value. The dances are waltzes, polkas, cha-chas, charlestons, fox-trots, tangos, lambadas, and two-steps.

The current round is a dance that varies.

Manner is a kind of value. The manners are swiftly, primly, energetically, suavely, seductively, elegantly, and badly.

Every turn: now the current round is a random dance.

Every turn:
    repeat with dancer running through people who are not the player:
        if dancer is alert:
            now dancer is occupied;
            let partner be a random alert person who is not the dancer;
            if partner is a person:
                now partner is occupied;
                say "[The dancer] [the current round][if a random chance of 1 in 5 succeeds] [a random manner][end if] with [partner]. ";
            otherwise:
                say "[paragraph break][The dancer] is forced to be a wallflower. Poor [dancer]. ";
    say paragraph break.

I use it for a device that has a lockpick mode:

Report tuning it to: 
	say "You set [the noun] to [tool-mode understood].";
	if the curious-tool is lockpick:
		repeat with current running through lockable doors:
			now curious-tool unlocks current;
		now curious-tool unlocks treasure-case;
		now curious-tool unlocks arthur-briefcase;
		say "[bracket]To use the lockpick, simple UNLOCK a locked door WITH the tool.[close bracket][line break]";
	otherwise:
		repeat with current running through lockable doors:
			now curious-tool does not unlock current;
		now curious-tool does not unlock treasure-case;
	if the curious-tool is flashlight:
		now curious-tool is lit;
		say "The tool brightens up the surrounding area considerably.";
	otherwise:
		now curious-tool is not lit;

Section 11.12 is Next and Break. These are ways to skip things in a loop or to stop a loop.

For instance:

repeat with X running from 1 to 10:
    if X is 4, next;
    say "[X] ".

produces the text "1 2 3 5 6 7 8 9 10 ", with no “4” because the “say” phrase was never reached on the fourth repetition.

Break is used similarly:

repeat with X running from 1 to 10:
    if X is 7, break;
    say "[X] ".

produces the text "1 2 3 4 5 6 ", with nothing after “6” because the loop was broken at that point. The “say” wasn’t reached on the 7th repetition, and the 8th, 9th and 10th never happened.

I’ve never used either one, although I can see the use. These are also pretty standard in most programming languages.

Section 11.13 is ‘Stop’. This is similar to break, but used in any phrase:

To judge the score:
    if the score is 0, stop;
    say "The score is [score in words] more than it was a half-hour ago."

In the case when the score is 0, the “stop” ends the phrase immediately, so that the subsequent text is printed only if the score is not 0.

“Stop” can also be used in action rules, though this is not very good style - it’s clearer to use “stop the action”, which is exactly equivalent.

Section 11.14 is Phrase options. These are just functions with extra parameters:

To go hiking, into the woods or up the mountain:
    if into the woods, say "Watch out for badgers.";
    if up the mountain, say "Better take your compass.";
    say "You go hiking."

and then you can type any of these three:

go hiking;
go hiking, into the woods;
go hiking, up the mountain;

I’ve never used this, but I’d imagine it’s useful if you have several similar phrases.

The most complex example of these parameters in the text are in the ‘list the contents of’ phrase, which is defined in the standard rules as:
To list the contents of (something - an object), with newlines, indented, as a sentence, including contents, including all contents, giving inventory information, 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: ...

Example 177 is Equipment List:

Inventory listing style is a kind of value. The inventory listing styles are tall, wide, curt, minimal, divided tall, and divided wide. Current inventory listing style is an inventory listing style that varies.

Instead of taking inventory when current inventory listing style is tall:
    if the number of things enclosed by the player is 0, say "You are empty-handed." instead;
    say "You are carrying: [line break]";
    list the contents of the player, with newlines, indented, giving inventory information, including contents, with extra indentation.

Instead of taking inventory when current inventory listing style is wide:
    if the number of things enclosed by the player is 0, say "You are empty-handed." instead;
    say "You are carrying ";
    list the contents of the player, giving inventory information, as a sentence, including contents;
    say "."

There is quite a bit more than that, but it gives a taste of this complex example. I rewrite inventory rules in my Conservation extension since I model conversation topics as physical objects. I like that method because you don’t have to deal with scope (you’re either carrying the topic or not) and can assign properties easily to the topics, which I feel is harder to do when topics are just chunks of text.

11.15 is Let and temporary variables. This is just a way to make temp, local variables that only last in the current phrase:

let outer bull be 25;
let the current appearance be "reddish brown";
let the special room be Marley Wood;

You can also make temp variables without an initial value by specifying a kind:
let inner bull be a number;

Example 178 doesn’t use temporary variables at all. Instead, it just shows you can vary text with cycling substitutions, if statements, or values. One part is like this:

Tint is a kind of value. The tints are green, aquamarine and darkish purple.

The wallpaper is fixed in place in the Hôtel. The wallpaper has a tint. "In this light, the wallpaper has a distinctly [tint of the wallpaper] wash. [if the tint of the wallpaper is darkish purple]You particularly dislike purple.[end if]"

So the text has no actual examples of let statements in this section. Here’s one I have, where I use temporary variables to avoid complicated conditional statements:

Before physicality when the noun is a climbing-rock:
	let tempmax be climbingheight plus 1;
	let tempmin be climbingheight minus 1;
	if rockheight of the noun > tempmax:
		say "That's too high above you!" instead;
	otherwise if rockheight of the noun < tempmin:
		say "That's too far below you!" instead;

11.16 is New conditions, new adjectives.

I only started using this for the first time on my current game. You can make new conditional statements with the phrase ‘to decide whether’ or ‘to decide if’, and the phrases ‘decide yes’ and ‘decide no’. Once the game hits a ‘decide yes’ or ‘decide no’, it’s done:

To decide whether danger lurks:
    if in darkness, decide yes;
    if the Control Room has been visited, decide no;
    decide yes.

You can also just say ‘yes’ instead of ‘decide yes’.

I use this for complex conditionals, like this in my game (I’m probably going to replace this with ‘move without printing a room description’ at some point, although this does work just fine):

The room description heading rule does nothing when looking is stupid.
The room description body text rule does nothing when looking is stupid.
The offer items to writing a paragraph about rule does nothing when looking is stupid.

To decide whether looking is stupid:
	if the climbing-wall is nowhere, decide no;
	if the player is not enclosed by pride-room, decide no;
	if the current action is not looking, decide no;
	decide yes;

We can also define adjectives:
Definition: a supporter is occupied if it is described and something is on it.

And, a question I had earlier that was answered by Zed, I think, you can do this in a multi-line way:

Definition: a supporter is occupied:
    if it is undescribed, no;
    if something is on it, yes;
    no.

Example 179 is Owen’s Law, which provides a nice way of deciding what ‘in’ and ‘out’ should do:

A room can be indoors or outdoors. A room is usually indoors.

Definition: a room is outward:
    if it is not adjacent, no;
    if it is indoors and the location is outdoors, no;
    if it is outdoors and the location is indoors, yes;
    if the number of rooms adjacent to it is greater than the number of rooms adjacent to the location, yes;
    otherwise no.

Definition: a room is inward:
    if it is not adjacent, no;
    if it is outdoors and the location is indoors, no;
    if it is indoors and the location is outdoors, yes;
    if the number of rooms adjacent to it is less than the number of rooms adjacent to the location, yes;
    otherwise no.

It then has some extra code to help with this.

Section 11.17 is Phrases to decide other things. I’ve never used this.

To decide which treasure is the grand prize:
    if the Dark Room has been visited, decide on the silver bars;
    decide on the plover's egg.

For those familiar with other languages, ‘to decide whether’ and ‘to decide with’ are just functions, and ‘decide on’ is the same as ‘return’.

The ‘function name’ here is ‘grand prize’, so you just use it wherever you want:
if taking the grand prize, ...

I’m not sure how one would write something with an input and an output
(like To decide which color is the favorite-color of (currentperson - a person)?)

You can nest these kinds of things:

To decide if time is short:
    if the time of day is after 10 PM, decide on true;
    ...
    decide on whether or not Jennifer is hurried.

Example180 is Witnessed 2:

To decide what number is meter setting:
    if the meter is switched off, decide on 0;
    if a ghost is touchable, decide on 35;
    if a ghost is visible, decide on 12;
    decide on 0.

Example 181 is A Haughty Spirit:

To decide what number is the distance (first place - a room) rises above (second place - a room):
    let the total distance be the number of moves from the first place to the second place;
    if the total distance is less than 1, decide on 0;
    let count of down moves be 0;
    let count of up moves be 0;
    let next place be the first place;
    repeat with counter running from 1 to the total distance:
        let the way be the best route from the next place to the second place;
        if the way is down, let count of down moves be the count of down moves plus 1;
        if the way is up, let the count of up moves be the count of up moves plus 1;
        let next place be the room the way from next place;
    let the decision be the count of down moves minus the count of up moves;
    decide on the decision.

(This is a more elegant solution to my rock-climbing example earlier).

1 Like

Chapter 11, cont.

Section 11.18 is The value after and the value before. If you enumerate something like:
Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet.

then you can type
the first value of colour (here, being ‘red’)
the last value of colour
the colour after yellow
the colour before blue, etc.

Example 182 is Entropy:

Heat is a kind of value. The heats are frosty, cold, cool, room temperature, warm, hot, and scalding. Everything has a heat. The heat of a thing is usually room temperature.

Every turn:
    repeat with item running through things which are not in an insulated container:
        if the heat of the item is greater than room temperature, now the heat of the item is the heat before the heat of the item;
        if the heat of the item is less than room temperature, now the heat of the item is the heat after the heat of the item.

Example 183 is The Hang of Thursdays:

A weekday is a kind of value. The weekdays are Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday. The current weekday is a weekday that varies. The current weekday is Saturday.

A time period is a kind of value. The time periods are morning, afternoon, evening, night. The current time period is a time period that varies. The current time period is afternoon.

This is the new advance time rule:
    if the current time period is less than night:
        now the current time period is the time period after the current time period;
    otherwise:
        now the current time period is morning;
        now the current weekday is the weekday after the current weekday.

The new advance time rule is listed instead of the advance time rule in the turn sequence rules.
2 Likes

Now I just say
FlyingFlag is a truth state that varies. FlyingFlag is false.

This is fine, but if you have a “flag” object it’s usually tidier to define an either/or property:

The flag can be flying.

Then you can write “if the flag is flying” rather than “if FlyingFlag is true”. Reads more naturally.

I once raised a proposal to define truth flags with the form “X is Y” even if there was no object X. Then you could write “now X is Y”, “if X is not Y”, etc and get sensible results. This hasn’t been taken up though.

4 Likes

Chapter 12: Advanced Actions, Part 1:

This is, I think, the second longest chapter left in the book, so I might only do part of it today.

I believe most of this chapter is about defining new actions and about Check, Carry out, and Report, but we’ll see.

12.1 is A recap of actions.

This just mentions the ACTIONS testing command, the fact that actions can succeed or fail, and that we can initiate actions through the ‘try’ phrase or players can initiate them by typing.

Before rules, intended so that preliminary activities like the one above can happen before the action is tried; Instead rules, which block or divert the intention, or may cause something spectacularly different to happen; and After rules, which allow for unexpected consequences after the action has taken place.

Section 12.2 is How Actions are processed, which contains the following helpful image:

image

The orange boxes for Before, Instead and After were covered in the Basic Actions chapter, but the blue boxes are new. The orange boxes are where we put rules to handle unusual situations, or unexpected events[…]Blue boxes hold the mundane, everyday rules - the generic ways that particular actions behave. Every action provides these: “Check” rules, to see if it makes sense - for instance, to see that the player is not trying to take his or her own body, or a whole room, or something he or she already has; then “Carry out” rules, to actually do what the action is supposed to do - in the case of taking, to move an object into the player’s possession; and finally “Report” rules, which tell the player what has happened - perhaps printing up “Taken.”

I always saw the difference as ‘Check/Carry out/Report’ are for defining your own actions and ‘Before/Instead/After’ are for messing with pre-existing actions.

Section 12.3 is Giving Instructions to other people.

Inform has a lot of code for doing this, but the only places I can remember seeing this off the top of my head are the mouse robot in Curses and the whole game of Ollie Ollie Oxen Free by Caroline Van Eseltine (I know it exists elsewhere, these are just the first and only ones I thought of).

It says that the difference between go west and will, go west is that they are respectively interpreted as:
going west and
asking Will to try going west

To write rules about this, do as so:
Instead of asking Will to try going west, say "Will scratches his head, baffled by this talk of westward. Is not the ocean without bound?"

The default person getting asked is ‘the person asked’, making this different than most verbs.

Instead of asking somebody to try taking something, say "I don't think we ought to tempt [the person asked] into theft, surely?"

Example 184 is Virtue:

Attacking someone is misbehavior. Kissing someone is misbehavior.

Instead of asking someone to try misbehavior: say "[The person asked] stiffens, offended by your suggestion."

Example 185 is Latris Theon:

Hermes is a man in Corinth. The destination of Hermes is Corinth. [So he is initially happy where he is.] Persuasion rule for asking Hermes to try going vaguely: persuasion succeeds. [But he is open to suggestions.]

A person has a room called destination.

Every turn when the destination of Hermes is not the location of Hermes:
    let the right direction be the best route from the location of Hermes to the destination of Hermes;
    try Hermes going the right direction.

Section 12.4 is Persuasion, something I never understood (which is likely why I never coded in asking people to try actions).

By default, people won’t do what you want:

> will, go west
Will has better things to do.

However, we can intervene to make the

But you can change that for individual requests by creating a ‘persuasion rule’:

Persuasion rule for asking people to try going: persuasion succeeds.
Persuasion rule for asking Will to try going west: persuasion succeeds.

You can say ‘persuasion succeeds’, ‘persuasion fails’, or neither. Either way, you can say something:

Persuasion rule for asking Will to try going:
    say "Will looks put out, and mutters under his breath.";
    persuasion fails.

This replaces the “Will has better things to do” message.

Persuasion rule for asking people to try doing something: persuasion succeeds. lets you persuade everybody to everything all the time. From personal experience, many actions that others attempt to not produce a message, so you may think this isn’t working, but it is (while I don’t do persuasion, I have had NPCs copying the player).

If will, go west succeeds in persuasion, then an action happens internally called Will going west. You can say:

Instead of Will going west, say "He runs out into the waves, but soon returns, rueful.".

I have rules like this for my clone:

Cloneheadedout is a truth state that varies. Cloneheadedout is false.

Before clone-you going:
	if clone-you is enclosed by the location:
		now cloneheadedout is true;

After clone-you going:
	if clone-you is in the location of the player:
		say "The clone[setcloneact] arrives, following your movements.";
	otherwise if cloneheadedout is true:
		say "Your clone heads out to [the noun]."

Instead rules, when used in persuasion, count as failures and print failure messages. So:

Instead of Will pulling the cord:
    say "The bell rings."

produces:

>WILL, PULL CORD
The bell rings.

Will is unable to do that.

Example186 is The Hypnotist of Blois:

A person is either hypnotized or alert. A person is usually alert.

Persuasion rule for asking a hypnotized person to try doing something:
persuasion succeeds.

Understand "hypnotize [someone]" as hypnotizing.

Hypnotizing is an action applying to one thing.

Check hypnotizing:
if the noun is hypnotized, say "Already done." instead.

Carry out hypnotizing:
now the noun is hypnotized.

Report hypnotizing:
say "[The noun] slips under your control."

This is a classical example of the before, carry out, report dialog.

Although it says this command keeps other people from hypnotizing you:

Check someone hypnotizing someone:
    stop the action.

What I don’t get is, why doesn’t that prevent you from hypnotizing others?

Example 187 is Police State:

Persuasion rule for asking the policeman to try doing something: persuasion fails.

Persuasion rule for asking someone to try doing something: persuasion succeeds.

The policeman is a man in Seventh Avenue. "A policeman with a very guarded expression is watching you."

Smelling a person is disorderly conduct. Tasting a person is disorderly conduct. Jumping is disorderly conduct. Singing is disorderly conduct.

Instead of someone trying disorderly conduct in the presence of the policeman:
    say "The policeman arrests [the person asked]!";
    now the person asked is nowhere;
    the rule succeeds.

‘Rule succeeds’ here keeps Inform from counting it as a failure and printing failure messages.

Section 12.5 is Unsuccessful attempts.

This introduces some interesting notation I’ve never seen. Basically, if an action succeeds in persuasion but fails due to some check rule or something (like trying to go through a wall), inform usually prints out Will [or whoever] is unable to do that.

You replace that as so:

Unsuccessful attempt by Will going: say “Will blunders around going nowhere, as usual.”

But this prints for every failed attempt, whether it’s because doors are locked or whatever, so you can instead type:

Unsuccessful attempt by Will going:
    if the reason the action failed is the can't go through closed doors rule, say "Will looks doubtful and mumbles about doors.";
    otherwise say "Will blunders around going nowhere, as usual."

This would have been helpful to know last year, when I spent weeks typing stuff like this:

Instead of clone-you examining something:
	if clone-you is enclosed by the location:
		if the noun is something which can be seen by clone-you:
			say "Your clone[setcloneact] looks closely at [the noun].";
		otherwise:
			say "Your clone[setcloneact] tries to look at [the noun] but doesn't see it anywhere.";

I’m not going to change it now, because it works, but man, this is wild stuff.

To know the ‘reason an action failed’, you can type ACTIONS it will tell you what rule is at fault.

Oh, it looks like ‘unsuccessful attempt’ is only used for persuasion; since all of my clone’s actions are caused by ‘try’ phrases, this would have done nothing anyway. Good to know!

We should have a ‘persuasion’ theme for one of the next big comps so people can try this stuff out, because I just rarely see it in use.

Example 188 is Generation X, a pretty funny example:

Unsuccessful attempt by Jenna doing something:
repeat through Table of Retorts:
if the reason the action failed is the cause entry:
say “[response entry][paragraph break]”;
rule succeeds;
say “‘I don’t see how I’m supposed to do that, Mom,’ Jenna says.”

Table of Retorts

cause response
can’t take yourself rule “‘Is that like ‘get a grip on yourself’ or something?’ Jenna asks, momentarily diverted.”
can’t take what’s fixed in place rule “[physical impossibility]”
can’t take scenery rule “[physical impossibility]”
can’t take what’s already taken rule “[already done]”
can’t drop what’s already dropped rule “[already done]”
can’t wear what’s already worn rule “[already done]”
can’t take off what’s not worn rule “[already done]”
can’t close what’s already closed rule “[already done]”
can’t open what’s already open rule “[already done]”
can’t switch off what’s already off rule “[already done]”
can’t switch on what’s already on rule “[already done]”
can’t unlock what’s already unlocked rule “[already done]”
can’t lock what’s already locked rule

To say physical impossibility:
say "‘Maybe you should’ve brought someone a little stronger,’ Jenna says. ‘Like the Incredible Hulk.’ "

To say already done:
repeat through Table of Bored Remarks:
say “[response entry]”;
blank out the whole row;
rule succeeds;
say "‘Okay, I’m going to be, like, in the car,’ says Jenna. ‘Outside.’ ";
end the story saying “Jenna has gotten fed up”.

Table of Bored Remarks
response
“‘Did that,’ says Jenna.”
“‘Check,’ says Jenna.”
“‘Yeah, Mom, I already did that, okay?’”
“‘Look, if I have to be here doing dumb stuff, could you at least tell me to do stuff that isn’t already done?’ Jenna asks wearily.”
“Jenna gives a great upward sigh, riffling her bangs. ‘Once again… there is totally no point.’”

Section 12.6 is Spontaneous actions by other people

This is what I was talking about earlier: using ‘try’ phrases. Like this;
try Will going west.

If we tell it to try ‘silently’, it skips the ‘report rules’.

To repeat a point in the previous section: “unsuccessful attempt” rules do not apply to actions which the author has caused to happen, using “try”. When such actions fail, they invoke no special set of rules. Indeed, when “try” causes somebody other than the player to try an action, nothing will be printed to report back on success or failure.

If you have a complex person name and Inform isn’t parsing it, you can add trying after the name ends. So for a guy named Will Going:
try Will Going trying going west

Example 189 is IQ Test:

A persuasion rule for asking someone to try doing something:
    persuasion succeeds.

Before someone opening a locked thing (called the sealed chest):
    if the person asked is carrying the matching key of the sealed chest, try the person asked unlocking the sealed chest with the matching key of the sealed chest;
    if the sealed chest is locked, stop the action.

Before someone taking something which is in a closed container (called the shut chest):
    try the person asked opening the shut chest;
    if the shut chest is closed, stop the action.

The block giving rule is not listed in the check giving it to rules.

This is basically making implicit actions for people besides the player.

Example 190 is a rare 4-star example called Boston Cream, which is like the above example but fully developed.

It includes reactions like this:

Before someone opening a locked thing (called the sealed chest):
    if the person asked can see the matching key of the sealed chest:
        if the matching key of the sealed chest is enclosed by the sealed chest:
            say "Seeing the paradoxical location of [the matching key of the sealed chest], [the person asked] gives a howl of rage.";
            increment the score;
            end the story finally saying "You have thwarted Ogg";
        otherwise:
            try the person asked unlocking the sealed chest with the matching key of the sealed chest;
        stop the action.

and independent actions like this:

Every turn:
    increment the hunger of Ogg;
    if the hunger of Ogg is 2 and Ogg is visible, say "Ogg's stomach growls.";
    if the hunger of Ogg is 3 and Ogg is visible:
        if Ogg can see an edible thing (called the target):
            say "Ogg eyes [the target] with obvious intent.";
        otherwise:
            say "Ogg glances at you in a disturbingly shifty way.";
    if the hunger of Ogg is greater than 3:
        if Ogg carries an edible thing (called the target):
            try Ogg eating the target;
        otherwise:
            let new target be a random edible thing which can be seen by Ogg;
            if the new target is a thing:
                try Ogg taking the new target;
            otherwise:
                if Ogg can touch the player, end the story saying "Ogg is gnawing your ankle";
                otherwise try Ogg taking the player.

Section 12.7 is New actions.
At the top, it says

It is not often that we need to create new actions, but a large work of interactive fiction with no novelty actions is a flavourless dish.

I feel like that’s both true and not true. Very new players will often not create any new actions; somewhat experience players will often force definitions of new actions and use the ‘understand ___ as something new’ a lot; experience authors can often redirect old actions to do what they want, although some new actions are always good.

Examples of actions many games can use is ABOUT, CREDITS, HELP, and TALK TO, while a lot of games have XYZZY as an action. SING is often implemented, and there’s a running joke between a couple of people on this board about LICK being a useful action.

Here’s their example for defining an action:

The Ruins is a room. "You find this clearing in the rainforest oddly familiar." The camera is in the Ruins. "Your elephantine camera hangs from a convenient branch."

Photographing is an action applying to one visible thing and requiring light.

You know, this might be where all the ‘visible’ confusion comes from:

Summary

image

because the very first example of defining a function includes the word visible while most commands the player creates will not need to use that word.

Visible means that the action applies to directions and to things in transparent containers, among others. Touchable is the default for things; you don’t have to mention that an action applies to a touchable thing as it’s assumed.

You can create if statements based on the touchability requirements of something:

if action requires a touchable noun:
if action requires a touchable second noun:
if action requires a carried noun:
if action requires a carried second noun:
if action requires light:

This might radically change how I handle distant or immaterial objects in my games. I current just have a kind of actions called ‘physicality’ and manually list things like touching, pulling, and pushing, and then have ‘instead of physicality when the noun is ___’ rules.

Instead, it looks like I could just do

Before doing something to a distant thing:
  if the current action requires a touchable noun:
   say "[The noun] [are] too far away!;

I haven’t tested this, but I may try it out in the future.

Action names typically don’t have the nouns in them. This is awkward if it has two nouns, so you put it where the first noun goes:

Blinking is an action applying to nothing. Scraping it with is an action applying to two things.

Actions are impossible for the player to use unless you add a way for them to use them, so we have phrases like this:
Understand "photograph [something]" as photographing.

Notice we just call it photographing, with no nouns, on the right side.

Example 191 is Red Cross, which is our first example and which again uses ‘visible’:

Diagnosing is an action applying to one visible thing. Understand "diagnose [something]" as diagnosing.

Check diagnosing:
if the noun is not a person, say "Only people can have diagnoses." instead.

Carry out diagnosing:
say "You're not a medical expert."

Instead of diagnosing the player:
say "You feel fine!"

Example 192 is a very complex example called Frizz about adding a whole new set of rules to pre-existing commands:

A liquid distribution rule:
    repeat with item running through containers:
        if the item is open and the item is empty and the item is in a waterfilled container:
            now the item is waterfilled;
            if the player can see the item, say "[The item] fills up with water, of course.".

A liquid distribution rule:
    repeat with item running through things in a waterfilled container:
        if the item is porous and the item is dry:
            if the player can see the item, say "[The item] soaks through.";
            now the item is sodden.

A liquid distribution rule:
    repeat with item running through sodden things in the airing cupboard:
        if the item is not The Last Man, now the item is dry.

The last liquid distribution rule:
    if the player carries a dry copy of The Last Man, end the story finally.
The post-check rules are a rulebook.

This is the post-check stage rule:
    abide by the post-check rules.

The post-check stage rule is listed before the carry out stage rule in the specific action-processing rules.

A post-check rule (this is the dry glove rule):
    if we get wet:
        if the player wears the gloves and the gloves are dry:
            now the gloves are sodden;
            say "(soaking your gloves in the process)";
    continue the action.

A post-check rule (this is the wet glove rule):
    if the player wears the sodden gloves:
        if the The Last Man must be touched and the Last Man is not sodden:
            say "(soaking the parched pages of The Last Man with the rude touch of your sodden gloves)";
            now the The Last Man is sodden;
        continue the action.

This is only part of this very complex example. And we still haven’t seen any ways of defining actions without requiring a visible thing.

Example 193 is 3 AM:

Understand "shake [something preferably held]" as shaking.

Shaking is an action applying to one carried thing.

Carry out shaking:
say "Nothing results of your shaking [the noun]."

Instead of shaking a closed container when something is in the noun:
say "Something rattles inside [the noun]."

Instead of shaking a closed transparent container when something is in the noun:
say "Inside [the noun] there are banging noises produced by [the list of things contained by the noun]."

Instead of shaking an open container which contains something:
say "[The list of things contained by the noun] might fly out."

Hmm, I haven’t used ‘one carried thing’ in definitions before, I’m going to go fix that (I have a bunch of instead rules instead).

So every example in this chapter puts an adjective in the ‘applying to’ clause.

SEction 12.8 is irregular english verbs, and just explains why Inform doesn’t guess what the Understand phrase should be:
Understand "scrape [something] with [something]" as scraping it with.

English is so full of irregular verbs. Inform could have guessed “blink” and “photograph”, but might then have opted for “scrap” instead of “scrape”.

Inform does make past participles automatically, but if it gets it wrong, you can guess:
Squicking is an action with past participle squacked, applying to one thing.

And there we go, our first example without an adjective in the action definition.

Section 12.9 is Check, Carry out, report. This is a pretty important section!

It gives a nice and tidy example of how the rules go:

Check photographing. Here, for instance, we need to verify that the player has the camera. If any of our checks fail, we should say why and stop the action. If they succeed, we say nothing.

Carry out photographing. At this stage no further checking is needed (or allowed): the action now definitively takes place. At this point we might, for instance, deduct one from the number of exposures left on the film in the camera, or award the player points for capturing something interesting for posterity. But we should say nothing.

Report photographing. At this stage no further activity is needed (or allowed): whatever effect the action had, it has happened and is now over. All we can do is to say what has taken place.

So if you want your brand new action to require certain things, throw it in a check rule:

A check photographing rule:
    if the camera is not carried:
        say "You can hardly photograph without a camera, now can you?" instead.

or, as is more common,

Check photographing:
    if we have photographed the noun:
        say "You've already snapped [the noun]." instead.

The standard messages go in ‘report’:
Report photographing: say "Click!"

You can go on to add special cases that testers find out:

Check photographing:
    if the noun is the camera:
        say "That would require some sort of contraption with mirrors." instead.

Lots of examples!
Example 194 is The Dark Ages Revisited:

This example shows that you can add on to preexisting behavior without overwriting it using Carry On:
An electric light is a kind of device. Carry out switching on an electric light: now the noun is lit. Carry out switching off an electric light: now the noun is unlit.

It also has some nice stuff about avoiding unnecessary messages when examining things like devices or containers.

Example 195 is Paddington:
This extends a pre-existing verb (CUT) to a more complex verb (CUT ____ WITH ____). This is a great example since it comes up alot.

In this code, just ‘cutting’ by itself is the old, preexisting action, and ‘cutting it with’ is our new action:

Understand "cut [something] with [something]" as cutting it with.

Instead of cutting something:
    if a blade (called the edge) is held by the player,
        try cutting the noun with the edge;
    otherwise say "Your fingernails are not sharp enough."

Cutting it with is an action applying to two things.

Check cutting it with:
    if the noun is a person, say "That would hurt." instead;
    if the second noun is not a blade, say "[The second noun] has not got enough of a blade." instead.

Carry out cutting it with:
    increment the count of rips of the noun.

Report cutting it with:
    say "You slash [the noun] with [the second noun]."

It then adds lots of nice little rules to document your reign of terror.

Example 196 is Delicious, Delicious Rocks:
This example stops implicit actions that are clearly going to lead to dumb results.

The sanity-check rules are a rulebook.

This is the sanity-check stage rule:
abide by the sanity-check rules.

The sanity-check stage rule is listed after the before stage rule in the action-processing rules.

Sanity-check eating an inedible thing:
    say "Your digestion is so delicate -- you're sure [the noun] wouldn't agree with you." instead.

This keeps you from picking up a rock before eating it.

It then mentions the pros and cons between this method and just doing a ‘before…instead’ rule.

Example 197 is Noisemaking:
This adds a new rulebook for people reacting to actions.

The other-player response rule is listed after the report stage rule in the specific action-processing rules.

This is the other-player response rule:
follow the observation rules.

The observation rules is a rulebook.

Singing is a loud action.

Attacking the drum is a loud action.

The block attacking rule is not listed in any rulebook.

Report attacking something:
    say "THWACK!"

An observation rule for loud action in the presence of the black crow:
    let N be a random adjacent room;
    if N is a room, move the black crow to N;
    say "The crow, startled, flies off to [N]."
1 Like