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

Yes, they are. Noun or second noun.

-Wade

2 Likes

For cases where you’d want this activity, single-fooing is just going to select a default noun and then do “try fooing”. So if you have an “Instead of fooing” rule, that will catch it without any additional work.

You’re right that you need extra words for an “Instead of doing anything other than fooing…” rule. But I find these are very rare, and if they get complicated I’m using a kind-of-behavior anyway.

2 Likes

Chapter 19: Rules

Rules! I feel like I get these a bit better than before, but this chapter will help a lot.

Section 19.1 is On Rules

This just lists all the rulebooks we’ve seen before:

before
instead
after
check taking, carry out taking, report taking
and three similar rulebooks for each of the 90 or so actions
persuasion
unsuccessful attempt
reaching inside
reaching outside
visibility
does the player mean

when play begins
when play ends
every turn
when Confrontation Scene begins
when Confrontation Scene ends
and two similar rulebooks for each scene we create, if any

before printing the name of
for printing the name of
after printing the name of
and three similar rulebooks for each of the 20 or so activities

(The book estimates this as around 340 rulebooks!)

The following are not rulebooks:

At 11:10 PM: ...
To dislodge the shelf: ...
Definition: ...

Section 19.2 is Named rules and rulebooks

Rules can have names or not names. Having a name makes it possible to override it later, which is moderately nice for a small game and massively important for an extension and, even more, the standard rules.

All rules in a rulebook are ordered, and are checked one at a time until one of them makes a decision. ‘Instead’ rules always make a decision, so only one instead rule will fire at a time.

Instead of taking something: say "You have no particular need just now."
Instead of taking a fish: say "It's all slimy."

In the above code, taking a fish is checked first, even though it was written second, because it’s more specific.

Rulebooks always have a name, even if rules don’t. Here are some ways of writing the same rule in different ways, and same rulebook in different ways:

advance time = the advance time rule

the instead rules = instead rulebook = instead

Example 388 is Nine AM Appointment:

This example shows how the named rulebook ‘turn sequence rules’ can be used:

Waiting more is an action applying to one number.

Understand "wait [a time period]" or "wait for [a time period]" or "wait for a/an [a time period]" or "wait a/an [a time period]" as waiting more.

Carry out waiting more:
    let the target time be the time of day plus the time understood;
    decrease the target time by one minute;
    while the time of day is not the target time:
        follow the turn sequence rules.

Report waiting more:
    say "It is now [time of day + 1 minute]."

Check waiting more:
    if the time understood is greater than one hour, say "You really haven't got that kind of patience." instead.

Section 19.3 is New Rules

It’s easy to write new rules, and people do it all the time:

Every turn, say "The summer breeze shakes the apple-blossom."

This makes a rule in the ‘every turn’ rulebook, but that rule has no name. This is the way most people name rules when they start out and even when experienced.

This is the blossom shaking rule: say "The summer breeze shakes the apple-blossom."

This names a rule but doesn’t put it in a rulebook, so it does nothing right now. A separate line can be used to put it in a rulebook.

Alternatively:

Every turn (this is the alternative blossom rule): say "The summer breeze shakes the apple-blossom."

This can be used to simultaneously name it and put it in a rulebook.

Example390 is The Crane’s Leg 2:

This is the comparative observation rule:
    let the sample be the ideal of the noun;
    if the sample is not a thing:
        say "Nothing special, really.";
        rule succeeds;
    if the material of the noun is not the material of the sample:
        if the height of the noun is not the height of the sample:
            if the noun is shorter than the sample, say "Unusually short at [height of the noun], and made of [material of the noun].";
            otherwise say "Unusually tall at [height of the noun], and made of [material of the noun].";
        otherwise:
            say "Distinct mostly in being made of [material of the noun].";
    otherwise:
        if the height of the noun is not the height of the sample:
            if the noun is shorter than the sample, say "Unusually short at [height of the noun].";
            otherwise say "Unusually tall at [height of the noun].";
        otherwise:
            say "In every respect [a sample]."
character instructions
yourself comparative observation rule
crane bird observation rule
The description of a thing is usually "[comparison with ideal][run paragraph on]".

To say comparison with ideal:
    say "You observe [the noun]:[paragraph break]";
    choose row with character of the player in Table of Descriptive Reporting;
    follow instructions entry.

Example 391 is Stone

This is an example with rules as properties

A food is a kind of thing that is edible. A food has a rule called the food effect.

Carry out eating a food:
    if a food is part of the noun:
        repeat with item running through things which are part of the noun:
            if item is a food, follow the food effect of the item;
    follow the food effect of the noun.

Some carrots are a food. The food effect of carrots is the bright-eye rule. This is the bright-eye rule: now the player is bright-eyed.

Some potatoes are a food. The food effect of the potatoes is the sleepiness rule. This is the sleepiness rule: now the player is sleepy.

The broth is a food. The indefinite article of the broth is "some". The food effect of broth is the filling rule. This is the filling rule: now the player is full.

The hambone is a food. The food effect of the hambone is the heartiness rule. This is the heartiness rule: now the player is strong. Instead of eating the hambone: say "You cannot just eat a bone!"

The poison ivy is a food. "Poison ivy grows nearby." The food effect of poison is the illness rule. This is the illness rule: now the player is ill.

Example 392 is Bribery

A lot of Inform’s default rules have a ‘block’ in them, like ‘block giving’, that you have to turn off.

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

As it happens, correct behavior is built into the GIVE command once “block giving” is turned off, so we do not have to write a replacement report or carry-out rule; the object will be transferred to the possession of the caterpillar.

Carry out giving (this is the gratitude for gifts rule): improve the mood of the second noun.

Mood is a kind of value. The moods are hostile, suspicious, indifferent, friendly, and adoring. An animal has a mood. An animal is usually indifferent.

To improve the mood of (character - an animal):
    if the mood of character is less than friendly, now the mood of the character is the mood after the mood of the character.

Section 19.4 is Listing Rules Explicitly

This is how you put rules in a rulebook if they aren’t in one already (although they can be in multiple rulebooks):

The blossom rule is listed in the every turn rules.

Listing also lets you manually pick which rule is listed first:

The collapsing bridge rule is listed before the moving doorways rule in the instead rules.

This doesn’t mean ‘directly before’, it just means that it’s somewhere before it.

You can also list a rule first or last:

The collapsing bridge rule is listed first in the instead rules.

Again, if we make several such instructions about the same rulebook then the most recent one wins: “A is listed first in X. B is listed first in X. C is listed first in X.” causes rulebook X to begin C, B, A.

You can substitute one rule for another:

My darkness rule is listed instead of the can't act in the dark rule in the visibility rules.

And you can destroy rules utterly (okay just make it so they don’t do anything unless you call them explicitly with ‘follow’ which we discuss later):

The can't act in the dark rule is not listed in the visibility rules.
The can't remove from people rule is not listed in any rulebook.

Tons of examples!

Example 393 is Saint Eligius

This is a way to add a set of text when entering a room that appears after entering a room for the first time but before all the ‘every turn’ rules:

The first look rule is listed after the room description paragraphs about objects rule in the carry out looking rules. A room can be commented or uncommented. A room is usually uncommented.

This is the first look rule:
    if the location is uncommented, carry out the gawking at activity with the location.

Gawking at something is an activity.

Rule for gawking at the Diamond Market:
    say "Your throat closes and your eyes begin to sting. You have long disdained pomp and luxury, and railed against the oppression that brings such wealth to some men at the cost of the lives of others; you were not prepared for the magnificence."

After gawking at a room (called the target): now the target is commented.

Example 394 is Uptempo:

The fast time rule is listed instead of the advance time rule in the turn sequence rules.

This is the fast time rule:
    increment the turn count;
    increase the time of day by 15 minutes.

I just checked to see if I use rules much in my game. I found this for the part where a clone is copying you; it goes through all the possibilities of actions you might have performed, and then has a generic reaction for everything else:

Every turn (this is the clone reacting rule):
	if cloneacted is false:
		if clone-you is enclosed by the location:
			if clonesubmerged is false:
				say "Your clone looks around, confused at how to imitate you.";
	now cloneacted is false;
	
The clone reacting rule is listed last in the every turn rulebook.

Anyway, back to examples:

Example 395 is Verbosity 2:

This is for altering the behavior of BRIEF, SUPERBRIEF and VERBOSE. These can’t be altered by Instead rules since they are ‘out of world’. So we do this:

The prefer unabbreviated room descriptions rule is not listed in the carry out preferring unabbreviated room descriptions rulebook.

The prefer sometimes abbreviated room descriptions rule is not listed in the carry out preferring sometimes abbreviated room descriptions rulebook.

The prefer abbreviated room descriptions rule is not listed in the carry out preferring abbreviated room descriptions rulebook.

Carry out preferring unabbreviated room descriptions:
    say "[story title] always provides full-length descriptions for your reading pleasure."

Carry out preferring sometimes abbreviated room descriptions:
    say "For your playing protection, [story title] provides only full-length room descriptions."

Carry out preferring abbreviated room descriptions:
    try preferring sometimes abbreviated room descriptions instead.

The standard report preferring abbreviated room descriptions rule is not listed in the report preferring abbreviated room descriptions rulebook.

The standard report preferring unabbreviated room descriptions rule is not listed in the report preferring unabbreviated room descriptions rulebook.

The standard report preferring sometimes abbreviated room descriptions rule is not listed in the report preferring sometimes abbreviated room descriptions rulebook.

Example 396 is Slouching. This adds multiple ‘postures’.

Carry out an actor exiting (this is the departure-posture rule):
    let N be the holder of the actor;
    if N is a container or N is a supporter,
        now the posture of the actor is the posture of N;
    otherwise now the posture of the actor is standing.

The departure-posture rule is listed after the standard exiting rule in the carry out exiting rulebook.
The departure-posture rule is listed after the standard getting off rule in the carry out getting off rulebook.

Carry out an actor entering something (this is the arrival-posture rule):
    if the noun is a container or the noun is a supporter,
        now the posture of the actor is the posture of the noun.

The arrival-posture rule is listed after the standard entering rule in the carry out entering rulebook.

Example 397 is Swigmore U.

This adds a new kind of supporter that won’t hold things when you drop it. That’s useful for a couple of things in my game (like rocks on a climbing wall).

A perch is a kind of supporter. A perch is always enterable. The stool is a perch in Moe's.

The player carries a dead field mouse and a tomacco fruit.

The sophisticated dropping rule is listed instead of the standard dropping rule in the carry out dropping rulebook.

This is the sophisticated dropping rule:
    if the player is on a perch (called the awkward position):
        let place be the holder of the awkward position;
        move the noun to the place;
    otherwise:
        move the noun to the holder of the player.

The sophisticated report dropping rule is listed instead of the standard report dropping rule in the report dropping rulebook.

This is the sophisticated report dropping rule:
    say "You drop [the noun] on [if the holder of the noun is a room]the ground[otherwise][the holder of the noun][end if]."

Section 19.5 is Changing the Behaviour of Rules

We can remove rules:

The print final score rule does nothing.

Or put conditions on it:
The print final score rule does nothing if the score is 0.

Or substitute it, even conditionally:
The print fancy final score rule substitutes for the print final score rule when the score is greater than 100.

Example 398 is Access All Areas. This gives you a hat that lets you walk through closed doors:

The extremely difficult door is north of the Standing Room and south of the Room of Walking Upside Down. It is a locked door.

The player is carrying the Pointy Hat of Liminal Transgression. The hat is wearable.

The can't go through closed doors rule does nothing when the Hat is worn.

We get this useful tip in this example:

If somebody tries to walk through a closed door, the “can’t go through closed doors rule” usually stops them. This is a rule belonging to the “check going” rulebook. These names are fairly explanatory when written out, but hard to remember: fortunately we don’t need to remember them, as the Index panel contains a full inventory of the check, carry out and report rules for every action, showing all of their names and the order in which they are checked. (We can also find out which rules are stopping an action by typing the testing command ACTIONS.)

Hmm, I never knew about the detailed view of actions. I tried it out by looking at the Commands tab in the index and clicking on the magnifying glass. For ‘taking’, I got a huge list, with this chunk near the middle/bottom:

image

Section 19.6 is Sorting and indexing of rules

The taking rulebook I just looked at was to big to fit into the general rulebooks index, and so are scenes, but all others are in the rulebook index. These indexes let you look up the name of rules. (I usually just type RULES and see what rules are running!)

It also says this:

The rules are given in order, and icons are used which indicate which rules are more specific than which others. Hovering the mouse over such an icon should bring up a “tooltip” which explains Inform’s reasoning.

As this suggests, Inform performs its automatic sorting using a precise collection of Laws (the term “rules” would be ambiguous here, so we call these guidelines Laws instead), and the tooltip shows which Law was applied. It is bad style to write source text which absolutely depends on detailed points of these Laws, but they are documented at the end of this chapter for those who do wish to see the full details.

But I don’t see which icons it’s referring to.

Wait, there they are:
image

Wow, that’s pretty neat!

Section 19.7 is the Preamble of a rule

The preamble is like the definition part. When making a rule, it’s the part before a colon:

preamble : list of one or more phrases divided by semicolons

Three things you write like this are not rules:

To ... - a new phrase: see the chapter on Phrases
At ... - something due to happen at a given time: see Time
Definition: ... - a new adjective: see Descriptions

All others are.

The preamble can either just be a name, which is required to end with the word “rule”, or it can give circumstances and have no name, or it can do both:

This is the ...name of rule...
...circumstances...
...circumstances... (this is the ...name of rule...)

Here’s what can go in the cirumstances rule:

first or last
followed by …rulebook name…
followed by about or for or of or on or rule
followed by …what to apply to…
followed by while or when …condition…
followed by during …a scene…

Inform doesn’t actually use any of the following words!!!:

of
rule about
rule for
rule on

It’s just there to make the author feel good.

In the rule definition
Instead of kissing Clark: ..., ‘of’ is optional. You can just type instead kissing Clark: ...

Section 19.8 is New rulebooks

This is pretty easy to make:

The Passage is east of the Tomb. The green-eyed idol is in the Tomb. A Speak-Your-Progress machine is in the Passage.

Appraisal rules is a rulebook.

An appraisal rule: say "Click... whirr... the score is [the score in words] points."

An appraisal rule:
    if we have taken the idol, say "Most importantly of all, the idol has been found."

Instead of switching on the machine, follow the appraisal rules.

You have to include the ‘follow’ thing at the end or they’ll never run.

‘Follow’ tells inform to run a rule or a rulebook:

follow the advance time rule; follow the appraisal rulebook;

Rule and Rulebook are both kinds in Inform. A rulebook is actually a special kind of rule! So if you make something apply to or accept a rule, you can pass it a rulebook. You can use the adjectives ‘empty’ and ‘non-empty’ to see if a rulebook has any rules in it.

Example 399 is Solitude:

Before reading a command when novice mode is true:
    say "[line break]Some options to try:[line break]";
    follow the novice suggestion rules.

The novice suggestion rules is a rulebook.

A novice suggestion rule (this is the suggestion that he look rule):
    if not looking and not going, say " [bold type]look[roman type]".

A novice suggestion rule (this is the suggestion that he check inventory rule):
    if the player carries something and we are not taking inventory, say " [bold type]inventory[roman type] (I)".

A novice suggestion rule (this is the suggestion that he put things on rule):
    if the player carries something and a free-standing supporter is relevant, say " [bold type]put[roman type] something [bold type]on[roman type] [the list of relevant supporters]".

A novice suggestion rule (this is the suggestion that he take things rule):
    if a gettable thing is relevant, say " [bold type]take[roman type] [the list of gettable relevant things]".

A novice suggestion rule (this is the suggestion that he examine things rule):
    if an unexamined thing is relevant, say " [bold type]examine[roman type] (X) [the list of unexamined relevant things]".

A novice suggestion rule (this is the suggestion that he enter things rule):
    if a relevant thing is worth entering, say " [bold type]enter[roman type] [the list of worth entering relevant things], or [bold type]get out[roman type]".

A novice suggestion rule (this is the suggestion that he open things rule):
    if an unlocked openable thing is relevant, say " [bold type]open[roman type] or [bold type]close[roman type] [the list of unlocked openable relevant things]".

A novice suggestion rule (this is the suggestion that he lock things rule):
    if a closed lockable thing is relevant, say " [bold type]lock[roman type] or [bold type]unlock[roman type] [the list of closed lockable relevant things]".

A novice suggestion rule (this is the suggestion that he eat things rule):
    if the player carries an edible relevant thing, say " [bold type]eat[roman type] [the list of edible relevant things carried by the player]".

A novice suggestion rule (this is the suggestion that he wear things rule):
    if the player carries a wearable relevant thing, say " [bold type]wear[roman type] [the list of wearable relevant things carried by the player]".

A novice suggestion rule (this is the suggestion that he turn things on rule):
    if a device is relevant, say " [bold type]turn on[roman type] or [bold type]turn off[roman type] [the list of relevant devices]".

A novice suggestion rule (this is the suggestion that he go places rule):
    if a room is adjacent, say " [bold type]go[roman type][exit list][if in darkness] or try other directions in the dark[otherwise]".

A novice suggestion rule (this is the suggestion that he enter doors rule):
    if an open door is relevant, say " [bold type]go through[roman type] [the list of relevant open doors]".

A novice suggestion rule (this is the suggestion that he interact with people rule):
    if another person is relevant, say " [bold type]kiss[roman type] or [bold type]wake[roman type] [the list of relevant other people][if the player carries something], or [bold type]give[roman type] things [bold type]to[roman type] someone[end if]".

When using Dialog, you can make stuff like this clickable links for a mobile-friendly game. I wonder if Vorple can do this too?

Notice the ‘last novice suggestion rule’ prints a line break.

Example 400 is In Fire or in Flood

Every turn when something is flaming:
    follow the fire rules.

The fire rules is a rulebook.

A fire rule (this is the can't hold flaming objects rule):
    repeat with item running through flaming things:
        if the item is held by the player:
            let turns remaining be the endurance of the item minus the turns of burning of the item;
            if turns remaining is less than two:
                say "[The item] becomes too hot to hold! ";
                try dropping the item;
                if the item is held by the player, say "This is certainly painful."

A fire rule (this is the flames spread rule):
    repeat with item running through flaming things:
        if the turns of burning of the item is one:
            spread the flames from the item.

A fire rule (this is the fire destroys things rule):
    now started printing is false;
    repeat with item running through flaming things:
        increment the turns of burning of the item;
        if the turns of burning of the item is greater than the endurance of the item, destroy the item;
    if started printing is true, say "[paragraph break]";
    now started printing is false.

There’s more to it than that, but that’s the main rule part.

Example 401 (I didn’t notice we were in the 400s!) is a rare 4-star example, Patient Zero.

The character movement rules are a rulebook.

The first character movement rule:
    now group size is 1;
    now the last person named is the player;
    now the last thing named is the player;
    now the player is passive.

A character movement rule:
    repeat with mover running through innocent people:
        now the current actor is the mover;
        follow the shopper rules;
        now the current actor is passive;
    follow the movement reporting rule.

A character movement rule:
    repeat with next mover running through mercantile people:
        now the current owner is the next mover;
        follow the shopowner rules;
        now the current owner is passive;
    follow the infection rule.

The shopowner rules is a rulebook.

A shopowner rule:
    let the shop be a random room owned by the current owner;
    if the shop is air-conditioned and an open door (called the escape) protects the shop, try the current owner closing the escape instead.

A shopowner rule:
    if the location of the current owner encloses a submitted artwork (called the target):
        try the current owner filing the target.

The shopper rules is a rulebook.

A shopper rule:
    if the current actor carries something (called the problem), try the current actor resolving the problem instead.

A shopper rule:
    if the current actor is not in the pool hall and the air conditioner is switched on:
        try the current actor approaching the pool hall;
    otherwise:
        let way be a random direction;
        try the current actor going the way.

This is just part of this absolutely massive example.

Chapter 19, Cont.

Section 19.9 is Basis of a rulebook

I had never heard of this before today. The basis of a rulebook is what kind of parameter you can pass into it. Just like an action can apply to a thing or a value, etc., a rulebook has a thing as a basis. For instance, there are action-based rulebooks which apply to actions:

Instead of eating the cake: ...

and object-based rulebooks that apply to objects:

Rule for reaching inside the flask: ...

and there are even number-based rulebooks that apply to numbers:

Grading is a number based rulebook.
Grading 5: say "It's five. What can I say?" instead.
Grading an odd number (called N): say "There's something odd about [N]." instead.
Grading a number (called N): say "Just [N]." instead.

When play begins:
repeat with N running from 1 to 10:
    say "Grading [N]: ";
    follow the grading rulebook for N.

which produces:

Grading 1: There's something odd about 1.
Grading 2: Just 2.
Grading 3: There's something odd about 3.
Grading 4: Just 4.
Grading 5: It's five. What can I say?
Grading 6: Just 6.
Grading 7: There's something odd about 7.
Grading 8: Just 8.
Grading 9: There's something odd about 9.
Grading 10: Just 10.

To follow the rules for a specific input:

follow the reaching inside rulebook for the electrified cage;

More examples:

The flotation rules are an object based rulebook.
A flotation rule for the cork: rule succeeds.
A flotation rule for an inflated thing: rule succeeds.
A flotation rule: rule fails.

After inserting something into the well:
    follow the flotation rules for the noun;
    if the rule succeeded:
        say "[The noun] bobs on the surface.";
    otherwise:
        now the noun is nowhere;
        say "[The noun] sinks out of sight."

I think this is our first time seeing ‘if the rule succeeded’, which I suspect just refers to the most recent rule ran.

Example 402, flotation, uses those rules from earlier:

The flotation rules are an object-based rulebook.

A flotation rule for the cork: rule succeeds.
A flotation rule for an inflated thing: rule succeeds.
A flotation rule when the big switch is switched on: rule fails.

After inserting something into the well:
    follow the flotation rules for the noun;
    if the rule succeeded:
        say "[The noun] bobs on the surface.";
    otherwise:
        move the noun to the well bottom;
        say "[The noun] sinks out of sight."

A thing can be sinking, rising, or static. A thing is usually static.

Definition: a thing is wet:
    if it is in the well, yes;
    if it is in the well bottom, yes;
    no.

Every turn:
    now every thing is static;
    repeat with item running through wet things:
        follow the flotation rules for the item;
        if the rule failed and the item is in the well, now the item is sinking;
        if the rule succeeded and the item is in the well bottom, now the item is rising;
    now every rising thing is in the well;
    now every sinking thing is in the well bottom;
    if something is rising, say "[The list of rising things] rise[if the number of rising things is 1]s[end if] to the surface of the well.";
    if something is sinking, say "[The list of sinking things] sink[if the number of sinking things is 1]s[end if] out of sight."

Finally, there is this interesting tidbit:

activities are themselves structured as sets of object-based rulebooks. The activity “writing a paragraph about” uses three object-based rulebooks (before writing…, for writing…, after writing…).

Section 19.10 is Rulebook variables.

These are basically private variables created when the rulebook starts and destroyed at the end.

Aptitude is a rulebook. The aptitude rulebook has a number called the aptitude mark.

An aptitude rule:
    if in darkness:
        decrease the aptitude mark by 3.

An aptitude rule:
    if we have taken the idol:
        increase the aptitude mark by 10.

The last aptitude rule: say "Your aptitude rating is [aptitude mark]."

Section 19.11 is Success and Failure

Every rule either ends in success, failure, or either (called ‘no outcome’.)

When a rulebook runs, it does everything in the rulebook one at a time until it reaches a success or failure. If not, it just stops at the end.

For some rulebooks, we don’t do that, like ‘every turn’, which just looks at everything. For other things, like ‘check rules’, a rule that fails should stop everything.

For instance, we might find that the “can’t take yourself rule” produces no outcome (because we aren’t trying to do that), and then likewise the “can’t take other people rule” (ditto) but that the “can’t take component parts rule” prints up a complaint, and fails the action: the rulebook stops, and never goes on to (for instance) the “can’t take scenery rule”. This is good, because an impossible action often fails for several reasons at once, and we only want to print up one objection, not a whole list.

Here are some words that affect this:

continue the action; means "end this rule with no outcome"
stop the action; means "end this rule in failure"
... instead; means "end this rule in failure"

So this rule ends in failure:

Before taking something: say "The sentry won't let you!" instead.

You can also just say:

rule succeeds
rule fails
make no decision

If we don’t specify using these special words, each rule will revert to default behavior. That’s usually ‘no outcome’, making the ‘action continue’ (on to the next rulebook). But the instead rulebook
defaults to failure.

You can set the default outcome:

The cosmic analysis rules are a rulebook. The cosmic analysis rules have default failure.

And you can test the latest outcome (this is what I wondered earlier!):

if rule succeeded:

if rule failed:

Example 403 is Kyoto:

These are the current ‘check’ rules for throwing:

Throwing something at something (past tense thrown it at)
    "drop [something held] at/against/on/onto [something]"

check an actor throwing something at implicitly remove thrown clothing rule check

an actor throwing something at futile to throw things at inanimate objects rule

check an actor throwing something at block throwing at rule

we can modify this as so:

The block throwing at people rule is listed instead of the block throwing at rule in the check throwing it at rules.

This is the block throwing at people rule:
    if the second noun is a person, say "That might be construed as an attack." instead.

Carry out throwing it at (this is the contact rule):
    say "[The noun] hits [the second noun].[paragraph break]";
    if the second noun is fragile and the noun is hard:
        destroy the second noun.

Section 19.12 is Named outcomes. I’ve used named outcomes for scenes before, but not rules.

Rules can have outcomes, like ‘success’ or ‘failure’, but we can also name them. The visibility rulebook has these outcomes:

there is sufficient light;
there is insufficient light;

You can have more than two outcomes. In the standard rules we have:

The does the player mean rules are a rulebook. The does the player mean rules have outcomes it is very likely, it is likely, it is possible, it is unlikely and it is very unlikely.

All five are counted as versions of ‘success’.

If you want some named outcomes to be failure, you have to say so:

Visibility rules have outcomes there is sufficient light (failure) and there is insufficient light (success).

More than one rulebook can have the same rulebook (although that sounds like a bad thing to me!)

You can also make some named outcomes the default:

Audibility rules have outcomes high background noise (failure), low background noise (success - the default) and absolute silence (success).

You can test it like so:

follow the audibility rules;
if the outcome of the rulebook is the absolute silence outcome:
    say "You could hear a pin drop in here."

Example 404 is Being Peter:

The attitude rules are a rulebook. The attitude rules have outcomes she stays calm (no outcome - default), she gets angry (failure), she has a stroke (failure), she is only mildly annoyed (success), and she is elated (success).

Quizzing it about is an action applying to one thing and one visible thing. Understand "ask [someone] about [any thing]" as quizzing it about.

Instead of quizzing Maggie about something:
    follow the attitude rules;
    say "Everyone waits to see what the reaction will be: [outcome of the rulebook].";
    if rule succeeded, say "There is general relief.";
    otherwise say "Everyone is pointedly silent."

A subject is a kind of thing. income, love life, and children are subjects.

An attitude rule for quizzing Maggie about love life:
    she gets angry.

An attitude rule:
    if the player wears the top hat, she gets angry.

The last attitude rule:
    she is only mildly annoyed.

Section 19.13 is Rulebooks producing values

We have now seen two ways to write the outcome of a rule: as simple success or failure, with more or less explicit phrases like:

rule succeeds;
rule fails;
continue the action;
stop the action;

and by using a named outcome for the current rulebook as if it were a phrase, as in:

low background noise;

You can also stop a rule and produce a value. This doesn’t happen for any of the Standard Rules!

If a rulebook produces a value L, you say ‘producing L’. Here are different ways to define rulebooks:

rulebook
K based rulebook
rulebook producing L
K based rulebook producing L

The default is ‘nothing’:

Drum summons rules is a rulebook.

Drum summons rules is an action based rulebook producing nothing.

But you could do this instead:

The cat behavior rules is a rulebook producing an object.

Cat behavior when Austin can see the ball of wool:
    rule succeeds with result the ball of wool.

There are two ways to use this rulebook now. The first is
follow cat behavior, which ignores the object provided at the end.

To actually use it, use the phrase:

object produced by the cat behavior rules

For instance, like this:

Every turn:
    let the destroyed object be the object produced by the cat behavior rules;
    if the destroyed object is not nothing:
        say "Austin pounces on [the destroyed object] in a flurry.";
        now the destroyed object is nowhere.

Example 405 is Feline Behavior:

The cat behavior rules is a rulebook producing an object.

A cat behavior rule when the cat can touch the catnip:
    say "The cat frolics with the catnip until nothing remains of it.";
    rule succeeds with result catnip.

A cat behavior rule when the cat can touch the cream:
    say "The cat laps up the cream.";
    rule succeeds with result cream.

A cat behavior rule when the cat can touch the ball of wool:
    say "The cat makes the ball of wool into a useless tangle which must be discarded.";
    rule succeeds with result ball.

A cat behavior rule when the cat can touch the newspaper:
    say "The cat bats playfully at the newspaper until all the nasty boring articles are destroyed.";
    rule succeeds with result newspaper.

A cat behavior rule:
    say "The cat looks miffed at the lack of ready entertainment, and glares at you with yellow eyes as though wondering whether your pants leg is good for claw-sharpening.";
    rule fails.

Every turn:
    let the destroyed object be the object produced by the cat behavior rules;
    if the destroyed object is not nothing:
        now the destroyed object is nowhere;
        say "[line break]Good thing you have no use for [the destroyed object] yourself.[paragraph break]".

If even the standard rules don’t use this, this must be very rare. Anyone have an example of a game they or someone else wrote, or an extension, using rulebooks producing an object?

Example 406 is Tilt 2:

This is very complex, but includes code like:

The hand-ranking rules is a rulebook. The hand-ranking rules have outcomes royal flush, straight flush, four of a kind, full house, flush, straight, three of a kind, two pairs, pair, high card.

The hand-ranking rulebook has a truth state called the flushness.
The hand-ranking rulebook has a truth state called the straightness.

The hand-ranking rulebook has a number called the pair count.
The hand-ranking rulebook has a number called the triple count.
The hand-ranking rulebook has a number called the quadruple count.

It doesn’t seem to use the ‘producing’ feature anywhere.

Section 19.14 is Abide by.

Abide by is like follow by, but only used when nested inside a different rule. Whatever the outcome of the inner rule becomes the outcome of the inner rule.

If ‘no outcome’ is given, it passes on to the rest of the rule.

The omnibus rule:
    abide by the first rule;
    abide by the second rule;
    abide by the third rule;
    abide by the fourth rule.

This just puts all of them together.

Here’s one example of usage:

A thing can be fragile or robust.
This is the can't handle fragile things roughly rule: if the noun is fragile, say "[The noun] is too fragile for such rough handling." instead.
A check dropping rule: abide by the can't handle fragile things roughly rule. A check throwing it at rule: abide by the can't handle fragile things roughly rule.

This is basically just saying ‘repeat what I said over there’, so abstraction.

You can also ‘anonymously abide’. This is used when you have at least triple nested rules, and passes the outcome of the inner rule directly to the outer rule.

With all this rule stuff, it makes more sense to me than activities, but I just don’t see myself using my own rulebooks. Maybe someday…I feel like scenes handle most of the things that take place over time, and phrases handle most of the things that take place in an instant, and the built-in rulebooks of Check, Instead, etc. are useful for actions, so I’m not sure I’d ever use my own rulebooks.

Section 10.15 is Two rulebooks used internally.

These are the ‘action processing rules’ and the ‘turn sequence rules’:

The action processing rules are used whenever an action must be tried, by whoever tries it. This usually happens in response to player commands, but not always: it might happen because of a “try…”, and it can certainly interrupt an existing action.

The turn sequence rules are used at the end of each turn, and include housekeeping as well as timekeeping. They consult the “every turn” rulebook, and advance the time of day, among other useful tasks.

Plenty of examples!

Example 407 is Electrified:

This is the electrocution-wisdom rule:
    if the player wears the very thick rubber glove, make no decision;
    if the action requires a touchable noun and the noun is electrified, say "You fear touching [the noun]." instead;
    if the action requires a touchable second noun and the second noun is electrified, say "You fear touching [the second noun]." instead.

The electrocution-wisdom rule is listed before the basic accessibility rule in the action-processing rules.

Before touching the scary box:
    say "You can't help noticing a bright red sticker on the surface of the box." [This rule will fire even if we are not wearing the glove, because Before rules occur before basic accessibility.]

Instead of opening the scary box:
    say "The scary box seems to be super-glued shut." [This one won't, because Instead rules occur after basic accessibility.]

Example 408 is Timeless:

Examining something is acting fast. Looking is acting fast.

The take visual actions out of world rule is listed before the every turn stage rule in the turn sequence rules.

This is the take visual actions out of world rule: if acting fast, rule succeeds.

This makes looking and examining ‘out of world’ actions that don’t process the end-of-turn rules.

Example 409 is Endurance:

Work duration is a number that varies.

Every turn:
    now work duration is 0;
    increment the turn count;
    follow the time allotment rules;
    if work duration is 0, rule succeeds;
    increase the time of day by (work duration minutes - 1 minute).

The time allotment rules are a rulebook.

A time allotment rule for examining or looking:
    now work duration is 0;
    rule succeeds.

A time allotment rule for going:
    now work duration is 2;
    rule succeeds.

Example 410 is escape from the seraglio:

The number of takes this turn is a number that varies. Every turn: now the number of takes this turn is 0.

The friskily announce items from multiple object lists rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

This is the friskily announce items from multiple object lists rule:
    if taking:
        if the current item from the multiple object list is not nothing:
            increment the number of takes this turn;
            say "[if number of takes this turn is 1]First [otherwise if the number of takes this turn is 2]And then [otherwise if the number of takes this turn is 3]And I suppose also [otherwise if the number of takes this turn is 7]And on we wearily go with [otherwise if the number of takes this turn is 9]Oh, and not forgetting [otherwise]And [end if][the current item from the multiple object list]: [run paragraph on]";
    otherwise:
        if the current item from the multiple object list is not nothing, say "[current item from the multiple object list]: [run paragraph on]".

Rule for deciding whether all includes the person asked: it does not.
Rule for deciding whether all includes a person when taking: it does not.

Section 19.16 is The Laws for Sorting Rulebooks

These section gives in excruciating detail the laws that dictate the order rules are processed.

They are (summarized, each law describing what it prioritizes):

Law 1: Number of constraints, with constraints on location, using the ‘pushing’ clause, mentioning the actor or noun, the phrase ‘in the presence of’, etc.

Law 2 is having a when/while requirement;

Law 3 is an action requirement like describing where an action takes place, etc. This one is by far the most complex.

Law 4 is having a scene restriction.

And that’s it! Whew! Somehow I really don’t anticipate using 90% of the stuff in this chapter, but I imagine the 10% will be really useful.

1 Like

I had a look in my WIP. I’m using rulebooks to subgroup every turn rules. This may be of interest to you, as you’re also working on a multi-chapter game. In other words, every turn rules that I only want to run in chapter 3 are in a rulebook called the ‘c3 et rules’. (et = every turn). The same for every other chapter. e.g.

The c3 et rules are a rulebook.

Every turn when the current-chapter is 3:
	follow the c3 et rules;

A c3 et rule (this is the flicker Tarni's apartment rule):
yada yada yada

A c3 et rule (this is the print sculpture reminders rule):
yada yada yada

This reduces processing (perhaps only microscopically – but the game’s now only considering 1/12th the number of chapter-based every turn rules per turn) but it’s more useful to me as an organisation and peace of mind tool. It’s easy to reorder rules within a chapter, and it means that within any one chapter, I don’t have to worry about peculiarities or bugs leaking out of rules that are only to do with other chapters.

I also have a rulebook for the tutorial, with an associated tutorial daemon list that I already forget how it works :roll_eyes:

If you have something that “takes place in an instant” but requires a lot of calculation, that’s probably where rulebooks are most powerful. I had a look at my Leadlight Gamma source and it has a rulebook for combat, the Do Battle rules. What’s cute about them is that they have a number called the line number, which corresponds to the line numbering in the original Apple II program, as it’s a translation. That was a handy way to be able to write them.

-Wade

3 Likes

Hmm, organization is actually really compelling! I love organizing my source code nicely so this actually encourages me.

1 Like

Hehe, me too.

-Wade

1 Like

Anything you could do with a rulebook, you could do with one giant function. But that would suck! Organization-wise.

That is the key insight for rulebooks.

4 Likes

An accurate explanation of “visible thing” shows it to be a really, really terrible, misleading name, and the docs seem truly dedicated to doubling-down on being misleading to act as apologist for it. I think the confusion comes from the docs not even trying to say what it actually means.

WI 12.7:

It’s not things plus directions, and line of sight has nothing to do with anything. The crucial thing to understand is that visible thing is the option that indicates the absence of constraint and potentially refers to any object, in or out of play, in or out of scope.

WI 12.17:

“in practice” is doing a lot of work here: if the associated grammar token doesn’t use any then this is true (ignoring things manually placed in scope and some edge cases). This is why people applying actions to a “visible thing” when “touchable thing” is what they really want doesn’t get people in trouble more often than it does: the parser acts as a gatekeeper.

But this code:

a bar is a kind of object.
fubar is a bar.
understand "fubar" as fubar.
fooing is an action applying to one visible thing.
understand "foo [any object]" as fooing.
report fooing: say "foo [the noun]".

allows you to > foo fubar when fubar is none of:

  • in scope (or at least I think it’s more accurate to say that an any token means scope is ignored than that it means the object is in scope, but I’m not positive)
  • a game object (i.e., a region, room, direction, or thing)
  • on-stage (this one’s redundant with it not being a game object)

RB 6.2 comes closest to the truth:

visible thing has so much to do with visibility that if you want to act on a not visible thing, be sure to specify visible thing.

3 Likes

“After” also, by default! Before, check, carry out, and report rules make no decision by default.

But it’s not anything magical about these rulebooks; as noted later, every rulebook has a default result (success, failure, make no decision), and you can specify it for each one.

Every turn, the Goal-Setting rulebook (person => object) is called for each active NPC, to set their “goal” property. Then the Autonomy rulebook (person => nothing) is called for each active NPC, to make them take one action toward that goal.

I find rulebooks convenient for this, because I want each NPC to take only one action per turn. So once a rule tries an action, it returns true (“rule succeeds”) to cut off the rest of the rulebook. The lowest-priority rules in the rulebook are things like “if you have a goal, pathfind toward it, then try going that way” and “if nothing else applies, try waiting”; the higher-priority rules are things like “if you see the player carrying an illegal thing, try confiscating it” and “if the chief engineer sees the jammed rudder, try fixing it”.

4 Likes

Chapter 20: Advanced Text

This is a smaller chapter, with only 7 or so examples. (edit: turns out there were more than that!)

Section 20.1 is Changing Texts.

This chapter will deal with stuff like regular expressions, matching snippets, selecting text letter by letter, like so:

if character number 1 in "[time of day]" is "1", ...

Apparently Inform used to have ‘text’ and ‘indexed text’, but since 2012 (before I started coding in Inform) it’s just all ‘text’.

Section 20.2 is Memory Limitations. It mentions that Inform runs on virtual machines (one reason it’s so platform-robust) that are pretty small.

Using too much text can make your memory overflow! In glulx, the game just grabs more memory. But Z-machine games need extra memory declared, like this:

Use dynamic memory allocation of at least 16384.

Next, there is a maximum text length of around 1000 characters. I swear I actually hit that once, but I don’t remember why; I usually hate having multiple pages of text and try to avoid ever printing more than one screen at once, but I think there was some poem or something that I was printing…Oh, I think I made the xyzzy response in one game cycle between every single XYZZY response recorded by David Welbourn. I didn’t know you could increase the text length so I just split it into smaller strings and cycled through the smaller strings which cycled through even smaller ones. I’m pretty sure I took it out of the finished game, though.

Another limitation is that the Z-Machine can only use ‘ZSCII’ characters, which are mostly ASCII.

Section 20.3 is Characters, words, punctuated words, unpunctuated words, lines, paragraphs.

Here we can select specific characters in a string:

character number 8 in "numberless projects of social reform"

or count the number of characters in a string:

number of characters in "War and Peace"
number of characters in ""

Or check if a text is the empty string:
if the description of the location is empty, ...

We can also select single words out of the text:

word number 3 in "ice-hot, don't you think?"
(this would produce ‘don’t’, since we slice it along spaces, punctuation, etc.)

We can find the number of words in the text:

number of words in "ice-hot, don't you think?" (which gives the number 5)

We can also count punctuation as a word:

punctuated word number 2 in "ice-hot, don't you think?" gives the hyphen -.

The punctuated words here are “ice”, “-”, “hot”, “,”, “don’t”, “you”, “think”, “?”. If two or more punctuation marks are adjacent, they are counted as different words, except for runs of dashes or periods: thus “,” has two punctuated words, but “–” and “…” have only one each. If the index is less than 1 or more than the number of punctuated words in the text, the result is an empty text, “”.

Similarly, you can count the number of punctuated words:

number of punctuated words in "ice-hot, don't you think?"

We can also deal with unpunctuated words:

unpunctuated word number 1 in "ice-hot, don't you think?"

number of unpunctuated words in "ice-hot, don't you think?"

I guess the difference between just ‘word’ and ‘unpunctuated word’ is that ‘ice-hot’ is two normal words and one unpunctuated words.

I’ve only used this machinery once, in a puzzle with levers corresponding to individual letters where a letter can’t repeat:

LetterTyping is an action applying to one thing and one topic. 

Understand "set [letter-levers] to [text]" as lettertyping when the hideous-contraption is in the location.

The letterlevertext is some text that varies. 
Tempchecker is a number that varies. Tempchecker is 0.
Firstchar is some text that varies.
Secondchar is some text that varies.

Carry out lettertyping:
	let tempword be the topic understood;
	if the number of words in the topic understood > 1:
		say "You can only set the levers to one word at a time!";
	otherwise:
		now tempchecker is 0;
		let wordlength be the number of characters in tempword;
		repeat with currentnum running from 1 to wordlength:
			repeat with comparenum running from 1 to wordlength:
				now firstchar is the character number currentnum in tempword;
				now secondchar is the character number comparenum in tempword;
				if currentnum is not comparenum:
					if "[firstchar]" matches the text "[secondchar]":
						increment tempchecker;
		if tempchecker > 0:
			say "You can only set the levers to a word without repeated characters!";
		otherwise:
			say "You set the levers to '[the topic understood]'. [randomsloth].

You can also select line numbers (which I didn’t know!)

line number (number) in (text) ... text number of lines in (text) … number`
These refer to explicit line breaks, since we won’t know how big the player’s monitor will be. Similarly:

paragraph number 3 in ...
number of paragraphs in ...

Section 20.4 is Upper and Lower case letters.

It mentions that some letters in some languages don’t have upper case or lower case equivalents or have multiple ones.

We can test for case:

if...is in lower case:
if...is in upper case:

And you can change the text to another case:

...in lower case
...in upper case
...in title case (which only capitalises the first letter of each word)
...in sentence case (only capitalises first letter of each sentence)

I’ve found that Inform really struggles with combing a description and case changes all at once (so if you say something like [the description of the book in Upper Case] or [a list of things enclosed by the room in lower case], more than half of the time it just doesn’t compile for me. I haven’t checked these specific examples. So I generally make a temporary text variable like ‘let X be the description of the book’ and then print ‘x in upper case’).

Accents (for greek, for instance) is perserved when changing case.

Title and sentence casing cannot recognize proper nouns.

All command input automatically makes input lower case.

There follows a bizarre account of how ÿ exists only in lower case in the Z-machine, which I hope will never be something I need to know in the future (maybe the $500 Inform Jeopardy question).

We now have two of the very few examples in this chapter.

Example 411 (nice) is Capital City:

To say the player's capitalised surroundings:
    let the masthead be "[the player's surroundings]" in upper case;
    say the masthead.

When play begins:
    now the left hand status line is "[the player's capitalised surroundings]".

Hmmm, this actually explains that weird hack I always did! They say:

Not much is needed for this. The only noteworthy point is that it doesn’t work by changing the LHSL to “[the player’s surroundings in upper case]”: it cannot do this because “the player’s surroundings” is not a value. Instead, “[the player’s surroundings]” is a text substitution sometimes printing the name of a room, sometimes printing “Darkness”, and so on. We must therefore load it into a text first, and then apply “…in upper case”.

Nice to know there wasn’t any better way!

Example 412 is Rocket Man, which uses a similar hack:

Instead of going somewhere from the spaceport when the player carries something:
    let N be "[is-are the list of things carried by the player] really suitable gear to take to the moon?" in sentence case;
    say "[N][paragraph break]".

The Spaceport is a room. North of the Spaceport is the Rocket Launch Pad. The player carries a stuffed bear, a chocolate cookie, and a book.

The description of the book is "It is entitled [italic type]Why Not To Take [sentence cased inventory] To The Moon[roman type]."

To say sentence cased inventory:
    let N be "[a list of things carried by the player]" in title case;
    say "[N]".

Section 20.5 is Matching and exactly matching

‘Matching’ in Inform means inclusion:

if "[score]" matches the text "3", ...

(this just texts if the number 3 is anywhere in the text)

if the printed name of the location matches the text "the", ... just checks if the lower-case string of letters ‘the’ occurs in the text, even inside other words, but it doesn’t match upper case letters! Unless you say:

if the printed name of the location matches the text "the", case insensitively: ...

We can check for inclusion both ways (i.e. the two texts having the same contents) with:

if "[score]" exactly matches the text "[best score]", ...

This is not ‘equality’, since equality means that they are always the same text, while exactly matching just means they are at this moment equal.

You can also count the number of times it matches:

number of times "pell-mell sally" matches the text "ll" = 3
number of times "xyzzy" matches the text "Z" = 0
number of times "xyzzy" matches the text "Z", case insensitively = 2
number of times "aaaaaaaa" matches the text "aaaa" = 2

Hmm, that would have made my code from before nicer with making sure no letters are repeated.

Section 20.6 is Regular expression matching.

Regular expressions are a standard thing in most text files, and can be super useful (you can also make fractals out of them! You can look up Finite Subdivision Rules to see some).

We can use them for search like so:

if "taramasalata" matches the regular expression "a.*l", ...

(which we can add the words ‘case insensitively’ to if we desire)

or we can say ‘exactly matches’, with or without ‘case insensitively’.

Or ‘the number of times … matches the regular expression …’

Since regular expressions can match a lot of things, it can be useful to figure out what exactly got matched. Right after using a regex, you can say text matching regular expression:

if "taramasalata" matches the regular expression "m.*l": say "[text matching regular expression].";

The section then goes on to explain how regular expressions work, which is a complicated subject and one probably better learned somewhere else through the numerous tutorials, only returning to this page to see exactly what notation Inform uses.

Example 413 is useful for beta testing:

After reading a command (this is the ignore beta-comments rule):
    if the player's command matches the regular expression "^\p":
        say "(Noted.)";
        reject the player's command.

This is better than my current stuff, which I never noticed had a typo in it to prevent it working:

Understand "* [text]" as a mistake ("Noted."). 

Understand "*#[text]" as a mistake ("Noted.").

(There shouldn’t have been a space after the asterisk, but oh well).

Example 414 is an explanatory essay about how Inform’s regex was chosen. It’s basically a stripped down version of the PCRE regular expression. It omits things like carriage returns, character codes, etc, and specifies which test cases Inform was unable to match well.

Section 20.7 is Making new text with text substitutions.

It mentions two older ways we learned how to write text:

say "The clock reads [time of day].";

To decide what text is (T - text) doubled:
    decide on "[T][T]".

and you can use them like this:

let the Gerard Kenny reference be "NewYork" doubled;

Now, the reason all of this is discussed is because when we set something equal to a substitution, Inform quietly decides whether to bring over the internal logic of the substitution or just print it out once and keep it that way forever.

Here’s how it decides:

What's going on here is this: Inform substitutes text immediately if it contains references to a temporary value such as "T", and otherwise only if it needs to access the contents. This is why "[time of day]" isn't substituted until we need to print it out (or, say, access the third character): "time of day" is a value which always exists, not a temporary one.

If we want, we can exclusively use the ‘print out exactly what it says now and keep it that way’ version by saying ‘the substituted form of’:

now the accumulated tally is the substituted form of "[the accumulated tally]X";

You can test if text has been substituted or not:

now the left hand status line is "[time of day]";
if the left hand status line is unsubstituted, say "Yes!";

An amusing in-text example is given:

The player is holding a temporal bomb.

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

After dropping the temporal bomb:
    now the left hand status line is the substituted form of the left hand status line;
    say "Time itself is now broken. Well done."

The last three examples are now given.

Example 415 is Identity theft:

The player's forename is a text that varies. The player's full name is a text that varies.

When play begins:
    now the command prompt is "What is your name? > ".

To decide whether collecting names:
    if the command prompt is "What is your name? > ", yes;
    no.

After reading a command when collecting names:
    if the number of words in the player's command is greater than 5:
        say "[paragraph break]Who are you, a member of the British royal family? No one has that many names. Let's try this again.";
        reject the player's command;
    now the player's full name is the player's command;
    now the player's forename is word number 1 in the player's command;
    now the command prompt is ">";
    say "Hi, [player's forename]![paragraph break]";
    say "[banner text]";
    move the player to the location;
    reject the player's command.

Instead of looking when collecting names: do nothing.

Rule for printing the banner text when collecting names: do nothing.

Rule for constructing the status line when collecting names: do nothing.

Example 415 is Mirror, mirror:

The player carries a magic mirror. The magic mirror has a text called the mirror vision.

To erase the mirror: now mirror vision of the mirror is "The mirror is polished clean, and has no impression upon it."

To say current room description: try looking.
To expose the mirror:
    say "The mirror shines momentarily with a dazzling light.[paragraph break]";
    now mirror vision of the mirror is the substituted form of "The hazy image in the mirror preserves a past sight:[line break][current room description]All is distorted and yet living, as though the past and present are coterminous in the mirror."

Understand "hold up [something preferably held]" or "hold [something preferably held] up" as holding aloft. Holding aloft is an action applying to one carried thing. Report holding aloft: say "You hold [the noun] aloft."

Instead of rubbing the mirror: erase the mirror; try examining the mirror. Instead of holding aloft the mirror: expose the mirror.

Example 417 is The Cow Exonerated:

This example doesn’t really seem to have anything to do with the chapter, besides the fact that it mentions we can’t have objects called ‘matches’ since that’s part of Inform’s matching phraseology. But the example has some neat tricks, like this:

Every turn:
    let N be 0; [here we track how many matches are being put out during this turn, so that we don't have to mention each match individually if several go out during the same move]
    repeat with item running through flaming s-matches:
        decrement the duration of the item;
        if the duration of the item is 0:
            now the item is burnt;
            now the item is unlit;
            if the item is visible, increment N;
    if N is 1:
        say "[if the number of visible flaming s-matches is greater than 0]One of the matches [otherwise if the number of burnt visible s-matches is greater than 1]Your last burning match [otherwise]The match [end if]goes out.";
    otherwise if N is greater than 1:
        let enumeration be "[N in words]";
        if N is the number of visible s-matches:
            if N is two, say "Both";
            otherwise say "All [enumeration]";
        otherwise:
            say "[enumeration in title case]";
        say " matches go out[if a visible strikable-match is flaming], leaving [number of visible flaming s-matches in words] still lit[end if]."

Section 20.8 is Replacements

You can edit a text (that you’ve defined via let or so on) with some of the following phrases:

let V be "mope";
replace character number 3 in V with "lecul";
say V;

says “molecule”.

let V be "Does the well run dry?";
replace word number 3 in V with "jogger";
say V;

says “Does the jogger run dry?”.

let V be "Frankly, yes, I agree.";
replace punctuated word number 2 in V with ":";
say V;

says “Frankly: yes, I agree.”.

let V be "Frankly, yes, I agree.";
replace unpunctuated word number 2 in V with "of course";
say V;

says “Frankly, of course I agree.”.

And replace line number ... in ... with... and paragraph number work as well.

You can also replace all instances of a text:

replace the text "a" in V with "z"

If you only want to replace whole words, we do it as so:
replace the word "Bob" in V with "Robert"

Instead of saying ‘word’ we can also say ‘punctuated word’ or ‘regular expression’.

When replacing regular expression (with the ‘case insensitively’ option or not), you can use special characters to print back part of the expression matched.

\0 is the exact text matched, while \1,\2,\3, up to \9 represent the different clusters of symbols matched. Two examples:

replace the regular expression "\d+" in V with "roughly \0"

adds the word “roughly” in front of any run of digits in V, because \0 becomes in turn whichever run of digits matched. And

replace the regular expression "(\w+) (.*)" in V with "\2, \1"

performs the transformation “Frank Booth” to “Booth, Frank”.

Putting an ‘l’ or ‘u’ in between the backslash and the number forces it to be upper case or lower case respectively.

Oh! It looks like I missed a few examples when I browsed earlier. There are a ton here!

Example 418 is Blackout:

Rule for printing the name of a dark room:
    let N be "[location]";
    replace the regular expression "\w" in N with "*";
    say "[N]".

This just censors the name of a room with a matching number of asterisks.

Example 419 is Fido:

A dog is an animal in Back Yard. The dog has some text called the nickname. The nickname of the dog is "nothing". Understand the nickname property as describing the dog.

Rule for printing the name of the dog when the nickname of the dog is not "nothing":
    say "[nickname of the dog]"

Naming it with is an action applying to one thing and one topic. Understand "name [something] [text]" as naming it with. Check naming it with: say "You can't name that."

Instead of naming the dog with "nothing":
    now the nickname of the dog is "nothing";
    now the dog is improper-named;
    say "You revoke your choice of dog-name."

Instead of naming the dog with something:
    let N be "[the topic understood]";
    replace the text "'" in N with "";
    now the nickname of the dog is "[N]";
    now the dog is proper-named;
    say "The dog is now known as [nickname of the dog]."

Example 430 is Igpay Atinlay, which turns the player’s comman into pig latin:

After reading a command:
    let N be "[the player's command]";
    replace the regular expression "\b(<aeiou>+)(\w*)" in N with "\1\2ay";
    replace the regular expression "\b(<bcdfghjklmnpqrstvwxz>+)(\w*)" in N with "\2\1ay";
    say "[N][paragraph break]";
    reject the player's command.

Example 421 is Mr. Burns’ repast:

Rule for printing the name of the unknown fish:
    if the supposed name of the unknown fish is "", say the printed name of the unknown fish;
    otherwise say the supposed name of the unknown fish.

After reading a command:
    if the unknown fish is visible and player's command matches the regular expression "\b\w+fish":
        let N be "[the player's command]";
        replace the regular expression ".*(?=\b\w+fish)" in N with "";
        now N is "[N](?)";
        now the supposed name of the unknown fish is N;
        respond with doubt;
        reject the player's command;
    otherwise if the unknown fish is visible and the player's command includes "[fish variety]":
        now supposed name of the fish is "[fish variety understood](?)";
        respond with doubt;
        reject the player's command.

To respond with doubt:
    say "You're not [italic type]sure[roman type] you're seeing any such thing."

This reminds me of a project I abandoned, which was to make ‘the game with no pictures’, a play on BJ Nowak’s ‘the book with no pictures’, and do fun responses to text like this, but I didn’t know how to do any of this at the time. Could be fun to revisit eventually.

Example 422 is Northstar:

After reading a command:
    let N be "[the player's command]";
    replace the regular expression "\b(ask|tell|order) (.+?) to (.+)" in N with "\2, \3";
    change the text of the player's command to N.

Example 423 is Cave-troll:

This example is by John Clemens.

This removes some stuff from a player’s command if it comes after a part that was already understood:

Rule for printing a parser error when the latest parser error is the only understood as far as error and the player's command matches the text "with":
    now the last command is the player's command;
    now the parser error flag is true;
    let n be "[the player's command]";
    replace the regular expression ".* with (.*)" in n with "with \1";
    say "(ignoring the unnecessary words '[n]')[line break]";
    replace the regular expression "with .*" in the last command with "".

Rule for reading a command when the parser error flag is true:
    now the parser error flag is false;
    change the text of the player's command to the last command.

Finally, section 20.9 summarizes regular expressions in Inform’s house style, which I suppose I could include here:

Summary

Positional restrictions

^ Matches (accepting no text) only at the start of the text
$ Matches (accepting no text) only at the end of the text
\b Word boundary: matches at either end of text or between a \w and a \W
\B Matches anywhere where \b does not match

Backslashed character classes

\char If char is other than a-z, A-Z, 0-9 or space, matches that literal char
|For example, this matches literal backslash ""
\n Matches literal line break character
\t Matches literal tab character (but use this only with external files)
\d Matches any single digit
\l Matches any lower case letter (by Unicode 4.0.0 definition)
\p Matches any single punctuation mark: . , ! ? - / " : ; ( ) { }
\s Matches any single spacing character (space, line break, tab)
\u Matches any upper case letter (by Unicode 4.0.0 definition)
\w Matches any single word character (neither \p nor \s)
\D Matches any single non-digit
\L Matches any non-lower-case-letter
\P Matches any single non-punctuation-mark
\S Matches any single non-spacing-character
\U Matches any non-upper-case-letter
\W Matches any single non-word-character (i.e., matches either \p or \s)

Other character classes

. Matches any single character
<…> Character range: matches any single character inside
<^…> Negated character range: matches any single character not inside

Inside a character range

e-h Any character in the run “e” to “h” inclusive (and so on for other runs)
>… Starting with “>” means that a literal close angle bracket is included
|Backslash has the same meaning as for backslashed character classes: see above

Structural

Divides alternatives: "fish fowl" matches either
(?i) Always matches: switches to case-insensitive matching from here on
(?-i) Always matches: switches to case-sensitive matching from here on

Repetitions

…? Matches “…” either 0 or 1 times, i.e., makes “…” optional
…* Matches “…” 0 or more times: e.g. “\s*” matches an optional run of space
…+ Matches “…” 1 or more times: e.g. “x+” matches any run of "x"s
…{6} Matches “…” exactly 6 times (similarly for other numbers, of course)
…{2,5} Matches “…” between 2 and 5 times
…{3,} Matches “…” 3 or more times
…? “?” after any repetition makes it “lazy”, matching as few repeats as it can

Numbered subexpressions

(…) Groups part of the expression together: matches if the interior matches
\1 Matches the contents of the 1st subexpression reading left to right
\2 Matches the contents of the 2nd, and so on up to “\9” (but no further)

Unnumbered subexpressions

(# …) Comment: always matches, and the contents are ignored
(?= …) Lookahead: matches if the text ahead matches “…”, but doesn’t consume it
(?! …) Negated lookahead: matches if lookahead fails
(?<= …) Lookbehind: matches if the text behind matches “…”, but doesn’t consume it
(?<! …) Negated lookbehind: matches if lookbehind fails
(> …) Possessive: tries to match “…” and if it succeeds, never backtracks on this
(?(1)…) Conditional: if \1 has matched by now, require that “…” be matched
(?(1)… …) Conditional: ditto, but if \1 has not matched, require the second part
(?(?=…)… …) Conditional with lookahead as its condition for which to match
(?(?<=…)… …) Conditional with lookbehind as its condition for which to match

IN REPLACEMENT TEXT

\char If char is other than a-z, A-Z, 0-9 or space, expands to that literal char
|In particular, “\” expands to a literal backslash ""
\n Expands to a line break character
\t Expands to a tab character (but use this only with external files)
\0 Expands to the full text matched
\1 Expands to whatever the 1st bracketed subexpression matched
\2 Expands to whatever the 2nd matched, and so on up to “\9” (but no further)
\l0 Expands to \0 converted to lower case (and so on for “\l1” to “\l9”)
\u0 Expands to \0 converted to upper case (and so on for “\u1” to “\u9”)

Though ZSCII can be customized, to some extent, and there are new special opcodes for printing Unicode characters, so you’re not just locked to Latin-1. But using any of those fancy things consumes a lot more memory (since strings are encoded under the assumption that most text is lowercase ASCII).

This is one of those obscure implementation details that you almost never need to know, except that one time when you’re writing a game about the wanderings of Odysseus and you have to print Mount Taÿgetus in all-caps. And that’s why the documentation talks about it. But honestly it doesn’t deserve more than a footnote.

When comparing texts, but not when comparing snippets—remember above, when hacking at the player’s command, we had to use “matches” for start-to-end matching and “includes” for matching anywhere in the command. While this is clearly the intended behavior, it’s so misleading I still maintain it’s a bug.

If you’re used to Perl-style regexes (i.e. the ones that you’ll find in basically any other programming language, which computer scientists get annoyed about because they’re not actually the same thing as “regular expressions” in computer science), Inform’s syntax is basically exactly the same, except that it uses < > instead of for categories. (This is just for usability purposes: typing “[bracket]abc[close bracket]” every time would get annoying and unreadable very quickly.)

One of my exes had well more than that, though he only used the first two in everyday life (and I only remember the first seven). Patronymics are fun!

Another thing I never knew!

A good usability improvement, this one. And a good use of regular expressions. Note that it behaves well with periods and THEN: TELL ALICE TO OPEN THE DOOR THEN GO NORTH becomes ALICE, OPEN THE DOOR THEN GO NORTH (and similarly, GO NORTH THEN TELL ALICE TO OPEN THE DOOR becomes GO NORTH THEN ALICE, OPEN THE DOOR). That’s a common trap people fall into when using regexes in after-reading-a-command rules!

2 Likes

Chapter 21: Lists

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

Section 21.1 is Lists and entries.

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

We can declare a list at any time:

let L be a list of numbers;

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

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

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

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

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

prints out:

L is now 2, 3 and 5.

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

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

Section 21.2 is Constant lists.

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

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

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

or for texts:

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

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

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

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

To make a list of lists:

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

You can also declare lists in a table:

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

Table of Requirements

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

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

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

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

Section 21.3 is Saying lists of values

You just say them like any other variable:

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

produces the text "2,

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

For debugging, you might use this:

"[list of people in brace notation]"

while for more general use you can use this:

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

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

or this:

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

which prints this: a piano and a music stand

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

Example 424 is Oyster Wide Shut:

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

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

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

Section 21.4 is Testing and iterating over lists.

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

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

You can also repeat through a list:

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

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

We build lists in multiple ways like:

adding single value:

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

producing:
{60, 168, 360}

concatenating lists:

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

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

adding values in certain spots:

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

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

adding a list in the middle of another list:

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

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

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

We can also remove entries or sublists:

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

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

or

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

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

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

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

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

After doing something when Robo is watching and Robo can see the player:
    now the actor is Robo;
    add the current action to the current instruction set;
    now the actor is the player;
    say "Robo watches you [the current action][one of], his yellow eyes lamp-like and observant[or]. In his metal head, gears whirr[or], his brushed-copper handlebar moustaches twitching[or] impassively[at random].";
    continue the action.

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

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

Section 21.6 is Lists of objects.

You can make constant ones like the notation used earlier:

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

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

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

etc.

And you can add and remove things like normal:

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

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

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

and sort them:

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

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

Section 426 is What Makes You Tick:

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

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

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

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

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

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

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

Table of Outcome Objects

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

Example 427 is Formicidae

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

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

A thing has a number called dramatic potential.

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

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

Section 21.7 is Lists of values matching a description

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

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

We just can’t do ‘infinite’ lists:

let N be the list of even numbers;

Section 21.8 is Sorting, reversing and rotating lists:

You can reverse a list:

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

Sort it (in ascending order):

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

Sort it (in reverse order):

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

and sort in random order:

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

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

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

or in reverse:

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

You can also ‘rotate’ a list:

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

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

or rotate it backwards:

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

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

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

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

Example 21.9 is Accessing entries in a list

You do this with number of entries in ...

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

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

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

The hard drive is a container. A program is a kind of thing. 15 programs are in hard drive. A program has some text called the starter command. A program has a list of stored actions called the script. Understand the starter command property as describing a program.

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

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

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

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

Section 21.10 is lengthening or shortening a list

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

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

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

We can also say
`extend L to 80 entries1

Section 429 is Leopard-skin

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

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

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

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

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

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

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

Example 430 is The Facts Were These

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

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

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

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

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

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

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

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

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

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

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

add the new customer to the queue;

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

You can also simulate a Stack:

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

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

add 8 to T, if absent; sort T;

You could do set intersections like this:

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

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

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

rotate the ring;
rotate the ring backwards;

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

You can mess with a list then put it back:

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

Now we get 7 examples, all one-star.

Example 431 is Circle of Misery:

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

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

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

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

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

(That one’s honestly pretty funny)

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

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

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

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

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

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

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

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

Example 433 is the fibonacci sequence

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

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

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

The tally is a list of stored actions that varies.

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

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

Example 435 is Lugubrious Pete’s Delicatessen

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

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

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

Example 436 is the Sieve of eratosthenes:

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

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

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

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

Big Mike Spivey energy.

Example 437 is Your mother doesn’t work here:

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

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

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

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

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

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

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

1 Like

Sadly no.

2 Likes

Yeah, the list-writer (what’s going on here) is actually thoroughly separate from lists, and probably deserves to go in the Descriptions chapter instead.

It’s basically a single incredibly-convoluted phrase which the Standard Library invokes in various fancy ways and authors generally don’t need to care about, because “[the list of things on the table]” does what you want in 90% of cases.

Yep, you’re correct that they’re linked lists. Basically all their properties and limitations stem from this. (This also means that checking if something is included in a list is O(n).)

Stored actions still exist, you can just usually use the word “action” now without causing problems.

(I’m curious about the reference here and Google isn’t helping. Who is this?)

1 Like

Mike Spivey is the author of A Beauty Cold and Austere, which contains the Sieve of Eratosthenes as a puzzle, and also Junior Arithmancer, which is an arithmetic-heavy IF game. I referenced him in the arithmetic chapter, and he responded somewhere a few dozen posts upthread.

1 Like

Ahh, right, our own Mike Spivey! I thought you were referencing a textbook author or the like.

1 Like

Constant lists are arrays. Mutable lists are, hm, I think they’re stored as “arrays” in a block, but blocks are linked lists? So there’s linked-list behavior, but at a lower level.

If you insert (or delete) an item at the front of list, it has to do the array thing of shifting every item forward (backward) by one.

1 Like

Chapter 22: Advanced Phrases

This is one of the smallest chapters: only 10 sections, and I think only a single example (but I’m wrong almost every time I guess).

Section 22.1 is A review of kinds. We’re going to go meta, so we need to know the four components of kinds:

  1. Base kinds:

object, number, real number, time, truth state, text, snippet, Unicode character, action, scene, table name, equation name, use option, action name, figure name, sound name, external file, rulebook outcome, parser error

With a couple of more hidden ones like ‘verb’ and then any the player made up.

  1. Constructions:
    list of K
    description of K
    relation of K to L
    K based rule producing L
    K based rulebook producing L
    activity on K
    phrase K → L
    K valued property
    K valued table column

Already we can make complex things like:
phrase (phrase number -> (phrase number -> number)) -> nothing

  1. Variables
    We can include variable names in our construction of new kinds:

To hunt for (needle - value of kind K) in (haystack - list of Ks): ...

(Huh, that actually compiles, with a ‘do nothing’ thrown underneath it. I thought it was just placeholder text, but apparently inform takes in a variable that’s a kind and understands its plural automatically!)

Section 4 is Kinds of kind:

value, arithmetic value, enumerated value, sayable value
These aren’t technically kinds, and are only used in matching like this:

To announce (X - sayable value): say "I declare that [X] has arrived."

  1. is Secret Inner Workings, which is stuff used with inline Inform 6 definitions.

Section 22.2 is Descriptions as values:

(This is the kind of section I always skipped due to intimidation. I am only reading this due to self-imposed social pressure)

Here we are referring to Descriptions in the Ch. 6 sense. If you have a description D (like ‘all closed lockable doors’), you can use it in constructions like these:

say "You gaze mournfully at [the list of D].";
let the tally be the number of D;
let the surprise prize be a random D;
repeat with item running through D:

It turns out that you can actually make a variable D and make stuff like that run! the kind of D would be ‘description of objects’ or ‘description of numbers’, etc.

So you can do stuff like this:

To enumerate (collection - a description of objects):
    repeat with the item running through the collection:
        say "-- [The item]."

or if you use a name that sounds goofy (the above makes it sound like the names ‘enumerate’ or ‘collection’ matter):

To exhaustively-detail (MyHeapOfJunk - a description of objects):
    repeat with the item running through MyHeapOfJunk:
        say "-- [The item]."

If you have a description (like ‘even numbers’) you can check if something matches that description:

if 4 matches D, ...

Example 438 is Curare:

To decide which thing is cyclically random (collection - a description of objects):
    let choice be the oldest member of the collection;
    now the last use of the choice is the turn count;
    decide on choice.

A thing has a number called the last use. The last use of a thing is usually 0.

Definition: a thing is old if its last use is 12 or less.

This is a powerful tool, it seems like to me, the ability to customize things like ‘a random such and such’.

Section 22.3 is Phrases as values

Now this is meta: a phrase can itself be a value, so you can have phrases applying to phrases!

Given a Phrase F, you can get inputs out of it, like:
apply F to V;

or

apply F to V and W

or even

Apply F

depending on how many inputs something has.

The number of inputs depends on its ‘kind’. So To decide which text is (T - text) repeated (N - a number) times: ... has kind phrase (text, number) -> text so we could apply that to two inputs.

We haven’t had an example yet of how to name a phrase; I tried something like P is always the phrase To beat up the player, and then I defined the phrase To beat up the player, and it compiled but made P into an object that wasn’t a phrase and wouldn’t let me apply it. So I hope we see later how to name phrases.

Section 22.4 is Default values for phrase kinds.

You can say something like this:

let S be a phrase numbers -> nothing;

This will create a phrase S which by default does nothing. For a phrase K → L, the default value is just the default value of L.

Here is an amusingly absurd example, in a game where ‘colours’ are a kind with ‘red’ as the default:

let R be a phrase numbers -> (phrase numbers -> colours);
showme R;
showme R applied to 3;
showme (R applied to 3) applied to 2;

which produces the following:

"r" = phrase number -> (phrase number -> colour): default value of phrase
number -> (phrase number -> colour)
"r applied to 3" = phrase number -> colour: default value of phrase number
-> colour
"( r applied to 3 ) applied to 2" = colour: red

Section 22.5 is Map, Filter, and reduce. We still haven’t learned how to name phrases, just make blank ones with names or have unnamed ones that do things.

This section explains how instead of using for loops, you can use a modern approach of Mapping, Filtering, and Reducing (I’m not part of language discourse, although I followed a C++ professor on Twitter once who was, so I’m not really aware this).

Mapping plugs a list of things into a function (or, in our case, a phrase):

To decide what number is double (N - a number) (this is doubling):
    decide on N plus N.

doubling applied to {2, 3, 4}

So you just ‘apply’ to a list of values of the correct kind.

You can also chain these functions:

To decide what text is the longhand form of (N - a number)
    (this is spelling out):
    decide on "[N in words]".

To decide what text is the consonant form of (T - text)
    (this is txtng):
    replace the regular expression "<aeiou>" in T with "";
    decide on T.

txtng applied to spelling out applied to doubling applied to {3, 8, 4, 19, 7}

Anyone used phrases applied to lists in their own code? I haven’t (didn’t know this stuff yet).

Now we can filter; given a description, you can restrict a list to things fitting that description:

filter to even numbers of {3, 8, 4, 19, 7}

which outputs {8,4}.

You can combine filtering and mapping/applying:

Definition: a text (called T) is lengthy if the number of characters in it is greater than 6.

let L be the filter to lengthy texts of spelling out applied to {15, 2, 20, 29, -4};
showme L;

which produces {"fifteen", "twenty-nine", "minus four"}.

Finally, there is reduction, which collates the resulting list into a single response of some kind:

To decide what number is the larger of (N - number) and (M - number)
    (this is maximization):
    if N > M, decide on N;
    decide on M.

To decide what text is the concatenation of (X - text) and (Y - text)
    (this is concatenation):
    decide on "[X][Y]".

let X be the maximization reduction of {3, 8, 4, 19, 7};
let Y be the concatenation reduction of txtng applied to spelling out
    applied to doubling applied to {3, 8, 4, 19, 7};

sets X to 19, the highest of the values, and Y to the text “sxsxtnghtthrty-ghtfrtn”

Oh ho! I just noticed (though we did it earlier) that this is how we name phrases! The word ‘reduction’ here isn’t part of the phrase name, you add it after the phrase name when using phrases of the form (value, value)->value, and it works through the list doing that operation repeatedly, first to the first two, then the result of that and the third.

Man, has anyone ever used ‘reduction of’? It seems to have been put in place to satisfy proponents of functional programming:

Is map/filter/reduce always a good idea? Devotees point out that almost any computation can be thought of in this way, and in systems where the work has to be distributed around multiple processors it can be a very powerful tool. (There are programming languages without loops where it’s essentially the only tool.) At its best, it reads very elegantly: one assembles all of the tools needed - definitions of doubling, lengthy, spelling out, concatenation and so on - and then each actual task is expressed in a single line at the end.

Section 22.6 is Generic phrases:

To say (V - value) twice: say "[V]. [V], I say!"

How does this work? V is a value, not a kind! It’s too generic!

But it does indeed work; it basically creates a different phrase for each input. I got this supremely dumb program to run:

To say (V - value) twice: say "[V]. [V], I say!"

When play begins:
	let S be a phrase nothing -> nothing;
	say S twice;

The kinds index tells you if something counts as a ‘value’ or a ‘sayable’ value, etc:

image

(only ‘top level’ kinds have this, and since most player-made kinds are things, you won’t see this until you scroll to the top of ‘things’ or past it.

Section 22.7 is Kind Variables:

You can have a phrase with a kind that takes in a value and returns nothing (just doing its own code):

To triple (V - arithmetic value): say "[V times 3]."

But if you want to return it, you need to know what to return, and we can’t use kinds, since ‘value’ matches all sorts of kinds. So we use the word ‘original’:

To decide which K is triple (original - arithmetic value of kind K):
    decide on 3 times the original.

Here’s another example:

To decide what list of L is (function - phrase K -> value of kind L)
    applied to (original list - list of values of kind K):
    let the result be a list of Ls;
    repeat with item running through the original list:
        let the mapped item be the function applied to the item;
        add the mapped item to the result;
    decide on the result.

(I’m really kind of getting lost here so I’m not commenting much)

Note also the way that the temporary variable “result” is created:

let the result be a list of Ls;

Ordinarily, of course, “L” is not a kind. But within the body of a phrase definition, it means whatever kind L matched against.

These things both compile:

To hunt for (V - value of kind K) in (L - list of Ks): ...
To hunt for (V - K) in (L - list of values of kind K): ...

but apparently behave differently if V is not the same kind as the list but can be used as if it were (like a snippet, which can be used as a text).

So, sorry for all those authors out there who yearned for uniqueness in definition of phrases of the kind
phrase (K, list of Ks) -> nothing

(btw those two examples with K’s and L’s compile if I put ‘do nothing’ after them but not if I name them, even if I only name one and delete the other, so that this gives an error):

To hunt for (V - value of kind K) in (L - list of Ks)
	(this is hunting):
	do nothing;

But deleting ‘this is hunting’ or changing the inputs to normal things like ‘numbers’ gets rid of the error.

Section 22.8 is Matching the names of kinds:
This is for when you have a name of a kind as an input and your going to repeat through it: if your kind isn’t repeatable, you’ll get an error.

For instance:

To assay (name of kind of value K):
    repeat with item running through Ks:
        say "There's [item].";
    say "But the default is [default value of K].";

works well with assay vehicles but fails with assay numbers and descriptions that aren’t kinds (like assay open doors)

Man, this chapter is right where it belongs: at the end of the coding section! It’s obscure and not super practical. Although this particular assaying example could be useful for debugging.

Section 22.9 is In What Oder? which already looks like a section I’d like to skip.

Oh I see, it asks, if the player defines a phrase twice, which one fires?

  1. More specific ones fire first
  2. If both are equally specific, the later-defined one is fired
  3. If one phrase is used in the definition of the other, then it comes before what it’s used in.

Finally, Section 22.10: Ambiguities!

What if for some reason you thought it was fun to define two almost-identical phrases like this:

say the (something - a thing)
say (something - a thing)

and you have this line:

say the dishcloth;

Which phrase fires? The one that has the most words (say the (...))

And that’s it for most programming stuff! The rest is like multimedia, debugging, etc., with I think some heavy I6 stuff in the extensions chapter.

1 Like

Here’s a collection of vagueries the compiler accepts, some of which surprised me:

To x0 (v - value): say "".
To x1 (r - relation): say "".
To x2 (r - rule): say "".
To x3 (r - rulebook): say "".
To x4 (ac - activity): say "".
To x5 (L - list of values): say "".
To x6 (p - property): say "".
To x7 (tc - table column): say "".
To x8 (dv - description of values): say "".
To x9 (n - name of kind of value): say "".

[with I6 inclusion only ]
To y0 (p - phrase): (- 0; -).