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

Though you can define it yourself if you want!

To decide what real number is the real cube root of (X - a real number):
    decide on X to the power reciprocal of 3.

You can do this!

To decide whether (X - value of kind K) = (Y - K):
    decide on whether or not X is Y.

Kind variables will come up eventually, but this is the sort of thing they’re for.

I was going to blame this one on zarf, since I thought Inform just exposed the floating-point math opcodes that are built into Glulx. But actually no, Glulx has a relatively small array of floating-point operations built in: arithmetic, rounding, sqrt, exp, log, pow, the six basic trig functions, and atan2.

The rest of these are defined by Inform, with definitions like this:

To decide which real number is the hyperbolic arctangent of (R - a real number)
    (documented at ph_hyperbolicarctangent)
    (this is the arctanh function inverse to tanh):
    let x be given by x = 0.5*(log(1+R) - log(1-R)) where x is a real number;
    decide on x.

Equations in action! The “this is the arctanh function inverse to tanh” part tells Inform that, if it sees arctanh in an equation, it should call this phrase; and if it needs to calculate the inverse of that (say you have the equation x = arctanh(y) and you ask it to solve for y), it should call whatever phrase it knows as the tanh function.

I’m told that in the sequel to Jigsaw, you need to fly a B29 over long enough distances that the Earth’s curvature comes into play and Cartesian coordinates are insufficient. You have to start using haversines:

To decide which real number is the haversine of (R - a real number)
    (this is the hav function inverse to archav):
    let x be given by x = sin(R/2)^2;
    decide on x.

Then all you have to do is use the famous Haversine Formula to calculate hav(θ) from the differences in longitude and latitude, and the archaversine of that will give you your bearing!

2 Likes

Perhaps my favorite Inform easter egg is their textual representations:

  say minus infinity;
  say logarithm of -1;
  say plus infinity;

produces:

-∞⚠∞

3 Likes

It’s unfortunate (to me) that it uses “.” as a parts separator when it’s meant as a decimal point. This prevents this from working:

A complex number is a kind of value.

2.3 + 4.5i specifies a complex number with parts real and imaginary.

I will not be satisfied until I can perform complex analysis in my game.

EDIT: Ah, I see. I have to use “.0” to indicate a real number.

EDIT 2: Hmm. Seems there are more problems with modeling complex numbers: (1) the second part cannot be negative; and (2) the second part must have an upper limit.

1 Like

I suppose I could have included sinh/cosh/tanh; I’m just exposing underlying mathlib functions, which are pretty much the same in every programming language. But I’ve never in my life run into code that used the hyperbolic trig functions. Nobody’s asked either.

I’m pretty sure that the CPU cost of floating-point math is dominated by encoding and decoding 32-bit Glulx values into native floats, which we have to do every opcode. The cost of the actual math function is probably trivial, since those are intensively optimized C code. (Which I’ve never looked at, of course.)

2 Likes

I’m going to take this opportunity to give scary warnings about units even though you’re joking.

Units are made of separate integers; beware of letting the ‘.’ lull you into expecting real number behavior.

With the dollars and cents monetary values, $1.00999 > $1.90 > $1.9.

Also note that while the initial number in a specification is bounded by the usual integer bounds (other than that it can’t be negative unless the specification included a minus sign, at least), each other digit specifies the maximum value a digit in that place can have.

Also, one of my least favorite 10.1 bugs is that this won’t compile:

let x be the monetary value with dollars part 4 cents part 72;
4 Likes

I think you’ll need Dannii’s structs for that.

1 Like

Here’s the code from Code. (Egad, I was more thorough than I remembered.)


Include (-
[ codeSignedCompare x y;
if (x > y) return 1;
if (x < y) return -1;
return 0;
];

[ spaceship v1 v2 k cmp cmp_result;
  if (k == NUMBER_TY) cmp = codeSignedCompare;
  else cmp = KOVComparisonFunction(k);
  cmp_result = cmp(v1,v2);
  if (cmp_result > 0) return 1;
  if (cmp_result < 0) return -1;
  return 0;
];
-)

To decide what number is (v1 - a value of kind K) <=> (v2 - a K):
    (- spaceship({v1},{v2},{-strong-kind:K}) -)

To decide if (v1 - a value of kind K) == (v2 - a K):
  decide on whether or not v1 <=> v2 is 0;

To decide if (v1 - a value of kind K) <>/!= (v2 - a K):
  decide on whether or not v1 <=> v2 is not 0;

Edited to add: With another year of Inform, all that becomes just:

To decide if (v1 - an arithmetic value) == (v2 - an arithmetic value): decide on whether or not v1 is v2.
To decide if (v1 - a value of kind K) == (v2 - a K): (- (~~((KOVComparisonFunction({-strong-kind:K}))({v1}, {v2}))) -)
2 Likes

That was fun, Brian. Thanks for sharing!

Mike

1 Like

Chapter 16: Tables

I haven’t used tables a lot, but a ton of Emily Short’s examples use them. I feel like they’re pretty useful!

Tables are written with a top line that is a title, with the first word necessarily being the word Table, followed by a number, a name or both:

Table 2.3
Table of Population Statistics
Table 2.3 - Population Statistics

Then each column has a name, and everything in each column must be the same ‘kind’ (number, text, action, etc.)

A sample table:

Table 2.1 - Selected Elements

Element Symbol Atomic number Atomic weight
“Hydrogen” “H” 1 1
“Iron” “Fe” 26 56
“Zinc” “Zn” 30 65
“Uranium” “U” 92 238

(posting tables on here is weird so this is the way I’m posting them).

I don’t anticipate having a lot of insights in this chapter, it’s a fairly straightforward workhorse chapter.

Section 16.2 is Lookin up entries

Given the table above, you can say:
symbol in row 3 of the Table of Selected Elements

and that means ‘Zn’.

The word ‘symbol’ here is just the name of the column; if we changed that column’s name to anything else, we’d just change our sentence above to use the new name.

You can repeat through rows this way (although we’ll find another way later):

 repeat with N running from 1 to the number of rows in the Table of Selected Elements:
    say "The atomic weight of [element in row N of the Table of Selected Elements] is [atomic weight in row N of the Table of Selected Elements

and this prints out:

The atomic weight of Hydrogen is 1.
The atomic weight of Iron is 56.
The atomic weight of Zinc is 65.
The atomic weight of Uranium is 238.

Note that Inform starts counting from 1, not 0, and that we used the phrase ‘number of rows in the Table of Selected Elements’.

Section 16.3 is Corresponding Entries

This is just a way to look up rows by the entries in them rather than the row number itself:

the atomic number corresponding to a symbol of "Fe" in the Table of Selected Elements

I almost never use tables in my own code, but I had exactly one in The Magpie Takes the Train:

Table 1 - Aliases
Alias	Honorific	Costumes	PithyPhrase
"Major Springbottom"	"Major"	military costume	"'It was my turn to be demobbed, ma'am, and I thought I'd take a ride on the best rail car the States can muster up before heading back. Spent a pretty penny, too!'"
"Doctor Weatherford"	"Doctor"	doctor costume	"'The engineer conductor said I should ride in this car. In case my services are required.'"
"Professor Spinner"	"Professor"	professor costume	"'I've made a study of luxury rail cars, and I've heard that this one is the jewel of the west. May I observe it?'"
"Sir Highwater"	"Sir"	aristocrat costume	"'I believe Ms. Hogg is a distant relation on the distaff side. It's all rather dull, I know, but I thought I might make an appearance, seeing I'm in the area.'"

When play begins, I have some text like this:

"You give a small bow, letting her see your [Costumes in row CurrentAlias of the Table of Aliases]. [PithyPhrase in row CurrentAlias of the Table of Aliases][paragraph break]'Very well, [honorific in row CurrentAlias of the Table of Aliases],' she says. 'You will be permitted to visit Ms. Hogg's observation car. The following are prohibited: solicitation, disorderly behavior, religious proselytising, sales pitches, unlicensed scientific research, fireworks, poking the parrot, and wearing disguises.'"

Looking up things that don’t exist can give errors, so you may want to check it first:
if there is an atomic number of 27 in the Table of Selected Elements ...

or more specifically:
if there is an element corresponding to an atomic number of 27 in the Table of Selected Elements ...

Example 271 is Dubai. It implements an elevator with a table of floors:

Table of Floors

level floor
0 Al Mahara
1 Burj al-Arab Lobby
2 Al Iwan
3 Juna Lounge
4 Sahn Eddar
15 Al Falak Ballroom
18 Assawan Spa
24 Presidential Suite
25 Royal Suite
27 Al Muntaha
The elevator exterior is a backdrop. It is not scenery. The initial appearance of the elevator exterior is "You can enter the elevator here." It is in Generic Floor, Al Mahara, the Lobby, Al Iwan, Juna Lounge, Sahn Eddar, Al Falak, Assawan Spa, Presidential Suite, Royal Suite, and Al Muntaha.

Before entering the elevator exterior, try going inside instead.

Instead of going inside in the presence of the elevator exterior:
    if there is a level corresponding to a floor of the location in the Table of Floors:
        let the present level be the level corresponding to a floor of the location in the Table of Floors;
        now the current level of the Lift is the present level;
    otherwise:
        now the current level of the Lift is the current level of Generic Floor;
    move the player to the Lift.

Carry out pressing button:
    now the current level of the Lift is the number understood;
    say "You press button [the number understood]. The lift whirs into action and moves to the correct level."

Section 16.4 is Changing entries:

Are we almost to the part about blanking lines? Every time I see a fancy Emily Short game there’s some part about repeating through a table and blanking lines. But I think that’s not yet.

Here is a sample table for this section:

Table 4 - Recent Monarchs

Name Accession Family
“Anne” 1702 Stuart
“George I” 1714 Hanover
“George II” 1720 Hanover
“George III” 1760 Hanover
“George IV” 1820 Hanover
“William IV” 1830 Hanover
“Victoria” 1837 Hanover
“Edward VII” 1901 Saxe-Coburg-Gotha
“George V” 1910 Windsor
“Edward VIII” 1936 Windsor
“George VI” 1936 Windsor
“Elizabeth II” 1952 Windsor

The right side is defined by this:
Dynasty is a kind of value. The dynasties are Stuart, Hanover, Saxe-Coburg-Gotha and Windsor.

And we can change it as so:

Instead of attacking the Succession:
    now the family corresponding to an accession of 1720 in the Table of Recent Monarchs is Stuart;
    now the name in row 4 of the Table of Recent Monarchs is "Graham I";
    now the name in row 5 of the Table of Recent Monarchs is "Trixibelle IV";
    say "You deface the English succession, making suitable amendments with a quill pen. Considering it is supposed to be mightier than the sword the effect is a little disappointing."

So we just use ‘now’ and ‘is’ with a description specifying the entry we want to change.

If we type ‘Showme the contents of ______’ in th code, it will print the table during testing.

We can also say [current table row] to print entries from a whole row (although we haven’t talked yet about how to make a current row), or say [row 5 in table ___] to print row 5, or print a column with the column name like say [element in table ____] in the table of elements.

Section 16.5 is Choosing rows.

This is a lot like [regarding the noun] for text. It just establishes the current context. Once that is established, you can just say ‘such and such entry’ instead of saying what row it’s in:

To list the succession:
    say "The Succession List runs as follows...";
    repeat with N running from 1 to the number of rows in the Table of Recent Monarchs:
        choose row N in the Table of Recent Monarchs;
        say "[accession entry]: [name entry] ([family entry]).";

Here the words before ‘entry’ are just the names of columns.

You can also ‘choose’ rows like so:
choose row with a name of "Victoria" in the Table of Recent Monarchs;

You can also choose a random row:
choose a /the/-- random row in /from (table name)

Hmm, I was looking back to see if I did use tables in the past, and apparently my very first game Ether used tables (I made that game by taking Emily Short’s Glass and copying bits, and I think she used tables). So I had a table like this:

Table of Weather
level	temperature	wind	pressure
-4	"Thin strands of steam are leaking from your tentacles[if the player is in Battlezone] and flames lick your shell[end if]. You may not be able to withstand further heat."	"[if the player is in Aloft]The air is still and peaceful. You find yourself tired, your tentacles drooping. Any further west and you might fall asleep.[otherwise]You stand right on the edge of the great horror to the west. You are close enough to touch the eye.[end if]"	"The thick air squeezes your shell from all sides. You find yourself somewhat uncomfortable, and wonder if your shell could take any more pressure."
-3	"Waves of heat roll at you from every direction[if the player is in Battlezone] and jets of flame scorch your shell from time to time."	"[If the player is in Aloft]The air flows slowly here, with torpid spirals that you idly spin in[otherwise]The air is thick and dull here, like the eye of a storm. To the west lies the enormous eye.[end if]."	"The air is soupy and uncomfortably thick down here."
-2	"The air is hot and humid[first time] here, in stark contrast to the north. The southern horizon is filled with nebulous masses that glow red and churn slowly, occasionally flaring out bursts of steam. A dry heat bakes your tentacles, only to be suddenly replaced by a shell-drenching humidity that is quickly swept away. The air gets quite a bit hotter to the south, although it is still manageable[only]."	"[if the player is in Aloft]The wind here is slower and mild[otherwise]You are still some distance from the great eye to the west, but its red glare chills your soul[end if][first time]. Unlike the other directions, you notice that the west is peaceful, clear, and free, with gentle air and thick, pillowy cloud formations that drift slowly by. You realize when you see it how deeply tired you are. You shake yourself, determined to press on[only]."	"You notice that the air is thicker than usual down here[first time]. The air far below you is so compressed and thick that it has become liquid, its surface constantly bubbling and popping. Even here, much higher, you can feel a slight, uncomfortable pressure on your shell.[only]."
-1	"The air is warm and moist."	"There is a faint breeze[if the player is in Battlezone], nudging you towards the eye to the west[end if]."	"The air weighs on your shell a bit more than usual."
0	"The temperature is [if the player is in Aloft]pleasant and [end if]mild."	"You feel a mild breeze."	"The air pressure matches your natural buoyancy."
1	"The air is cool and fresh[first time]. You pause in awe at the wintry spectacle to the north. Massive pillowy clouds blot out the horizon, shedding enormous snowflakes that hurl about in blizzards to the northeast and clump together in snowbergs and icebergs to the northwest. Even here, close to you, a few small snowflakes spill out and dance around you. The air becomes noticeably chiller to the north[only]."	"The brisk wind ruffles your tentacles."	"The air is a bit thin up here."
2	"You feel a chill in the air."	"The stiff wind blows you off course for a moment. You struggle to remain in place[first time]. A particularly nasty blast of wind comes from the east, whose vast space is filled by colossal black stormclouds constantly shredded by small tornadoes and gales. Occasional lightning bolts flash, followed by deep grumbling thunder. Even this far away, the wind is still uncomfortably strong[only]."	"The atmosphere is weak and thin here[first time]. You look up, and far above you, the clouds and snowflakes and all other details that enrich this world slowly phase out into empty nothingness. Here, where you are, the air is thin, but you can still manage to go up a bit further[only]."
3	"Thin snowflakes litter the air here. Puffs of mist come from your gills."	"A gale blows here, making it difficult to fly. You feel your shell trembling."	"You find yourself slightly drowsy in the thin air."
4	"Thick frost clusters on your shell and sticks your tentacles together. You may not be able to go any further to the north."	"Terrifying winds buffet you about. You revel in the excitement, but know that you may not be able to withstand stronger winds."	"You struggle mightily to keep alert and aloft in the thin atmosphere. You may not be able to go any higher."

and code like this:

choose the row with a level of eastness in Table of Weather;
say "[wind entry][if QuantOnOff is 1] The windspeed is [eastness plus four].[paragraph break][otherwise][paragraph break][end if]";

Anyway, Section 16.6 is repeating through tables:

To list the succession:
    say "The Succession List runs as follows...";
    repeat through the Table of Recent Monarchs:
        say "[accession entry]: [name entry] ([family entry])."

This is the same as finding the number of rows, repeating from 1 through the number of rows, and then choosing that row.

Note that there is no loop variable here, unlike in other forms of “repeat”, because it’s the choice of row which keeps track of how far we have got.

To go backwards:
repeat through (table name) in reverse order:

Or to sort through things in alphabetical/numerical/lexicographical order:

repeat through the Table of Recent Monarchs in name order: ...
repeat through the Table of Recent Monarchs in accession order: ...

Or reversing that order:

repeat through the Table of Recent Monarchs in reverse name order: ...
repeat through the Table of Recent Monarchs in reverse accession order: ...

Example 272 is Port Royal 4. We haven’t revisited Port Royal for many chapters!

To say current denizen:
    repeat through the Table of Occupations and People:
        if the date attested entry is the current year:
            say "[nickname entry] [family entry], [trade entry]";
            blank out the whole row;
            rule succeeds;
    say "absolutely no one"

Table of Occupations and People

Trade nickname family Date attested
“architect” “Robert” “Snead” 1684
“baker” “William” “Wingar” 1683
“barber” “William” “Alcocke” 1676
“blacksmith” “William” “Davidson” 1679
“bricklayer” “Samuel” “Richardson” 1683

(The above table was truncated)
New New Prison is a room. "You have a not very interesting room. Through the window you see passing [current denizen]."

Section 16.7 is Blank entries

You can leave things blank with two hyphens:

Table 2.1 - Selected Elements

Element Symbol Atomic number Atomic weight
“Hydrogen” “H” 1 1
“Iron” “Fe” 56
“Zinc” 30 65
“Uranium” “U” 92 238

(this forum converts two hyphens to an m-dash when displaying text)

You can check for blankness with:

if there is a symbol corresponding to an atomic number of 30 in the Table of Selected Elements ...
if there is an atomic number in row 2 of the Table of Selected Elements ...

if there is no symbol corresponding to an atomic number of 30 in the Table of Selected Elements ...
if there is no atomic number in row 2 of the Table of Selected Elements ...

An entirely blank column is bad because Inform can’t tell what data type it is:

Table 2 - Selected Elements

Element Symbol Atomic number Atomic weight
“Hydrogen” “H” 1
“Iron” “Fe” 26
“Zinc” “Zn” 30
“Uranium” “U” 92

So as long as you have a blank column, put the kind you will use in the top spot of the column:

Table 2 - Selected Elements

Element Symbol Atomic number Atomic weight
“Hydrogen” “H” 1 a number
“Iron” “Fe” 26
“Zinc” “Zn” 30
“Uranium” “U” 92

This won’t conflict with actual entries because if you have actual entries the column isn’t blank in the first place.

The end of a row can be left blank without typing --.

Table 2 - Selected Elements

Element Symbol Atomic number Density Specific gravity
“Hydrogen” “H” 1 a number a number
“Iron” “Fe” 26
“Zinc” “Zn” 30
“Uranium” “U” 92

Example 16.9 is blank rows. You can just tell Inform to throw some blank rows in at the end of a table:

Table 2 - Selected Elements

Element Symbol Atomic number Atomic weight
“Hydrogen” “H” 1 a number
“Iron” “Fe” 26
“Zinc” “Zn” 30
“Uranium” “U” 92
with 3 blank rows

Or just have an entirely blank table (this example uses the previously undocumented ability to specify kinds in parentheses after the column name. Does this only work for completely blank tables?)

Table 3 - Undiscovered Periodic Table

Element (text) Symbol (text) Atomic number (a number) Atomic weight (a number)
with 92 blank rows

Blank rows are skipped when repeating through rows. You can check if the whole table is empty as so:

if the Undiscovered Periodic Table is empty, ...

I think blank rows are there because you can’t dynamically add rows (maybe?)

Example 273 is If it hadn’t been for:

Table of Recorded Content

time stamp sound
a time some text
with 60 blank rows.
To record (noise - some text):
    if the number of blank rows in the Table of Recorded Content is 0, rule succeeds;
    choose a blank row in the Table of Recorded Content;
    now time stamp entry is the time of day;
    now sound entry is noise.

Carry out someone closing something in the presence of the switched on recorder:
    record "A creaking followed by a slam."

Carry out someone going to a room (called destination) in the presence of the switched on recorder:
    if the destination is the holder of the recorder, record "Footsteps, growing louder.";
    otherwise record "Footsteps, fading out."

etc.

Section 16.10 is adding and removing rows.

Yeah, looks like we can’t add rows dynamically, just edit old ones:

choose a blank row in Table 3;
now element entry is "Fluorine";
now symbol entry is "F";
now atomic number entry is 9;
now atomic weight entry is 19;

That’s reasonable to me.

You can count rows like this:

the number of blank rows in Table 3
the number of filled rows in Table 3

You can’t say ‘now such and such entry is blank’ since ‘blank’ isn’t a value.

So you just say ‘blank out’ (all of this stuff is very standard database stuff).

choose row 1 in the Table of Fish Habitats;
blank out the salinity entry;

We can also do what I’ve seen Emily Short do a lot:

choose row 1 in the Table of Fish Habitats;
blank out the whole row;

and what I’ve never really seen:
blank out the whole salinity column in the Table of Fish Habitats;

Or remove the whole table!
blank out the whole of the Table of Fish Habitats;

It says:

This is only really useful when a Table is being used to hold working space for some calculation or other.

Hmm, interesting.

Example 274 is Odyssey:

Table of Athena's Movement
destination
Thebes
Delphi
Thebes
Athens
Corinth
Mycenae

Every turn when Athena is active:
    repeat through the Table of Athena's Movement:
        let last space be the location of Athena;
        if Athena can be seen by the player, say "Athena heads to [the destination entry].";
        move Athena to destination entry;
        if Athena can be seen by the player, say "Athena arrives from [the last space].";
        blank out the whole row;
        break.

I don’t really see why we blank out the line. It says:

By blanking out the table line by line, we make sure that we never lose our place in the path.

But what does that mean? If someone can explain it to me that would make me feel smart.

Oh…wait…Thebes is in here twice! So then we have to delete the first Thebes so we can get different behavior the second time.

Section 16.11 is Sorting:

This is specifically about sorting the order of rows.

sort the Table of Recent Monarchs in random order;

sort the Table of Recent Monarchs in accession order;
(accession being the name of a column)

sort the Table of Recent Monarchs in reverse name order;
(here name being the name of a column in that Table)

Sorting text puts all uppercase letters before all lowercase and puts accented letters at the end.

Even when sorting by reverse, rows with the same value remain in the same order. So if there’s a column, for instance, where everything has the same value ‘1’, and you sort that column in reverse order, nothing happns.

Example 275 is a deck of cards. It has a table with 52 lines in it (which I will not represent here), as well as some shuffling code:

Understand "shuffle" as shuffling. Shuffling is an action applying to nothing.

Carry out shuffling:
    sort the Table of Cards in random order;
    say "You expertly rearrange the cards.".

When play begins:
    sort the Table of Cards in random order.

This gives me fond memories of the Tarot deck in Curses!, although the implementation is wildly different (I assume).

Section 16.12 is Listed in…

Using ‘listed in’ is a way of searching for something in a table and selecting the row it is found in.

if the newfound object is an item listed in the Table of Treasures...

or, a different, bigger, example:

  if there is no time entry:
        now the time entry is the time of day;
        increase the score by the value entry;
    say "Taken!"

Table of Treasures

Item Value Time
brooch 5 a time
tiara 8
coronet 10

So the table is a convenient way to handle three rules at once (which is what the book says, although I’m only seeing two rules here).

Example 276 is Noisy Cricket:

It has a bunch of fluid rules, and a table:

Table of Mixtures

rating creme de menthe comp vodka comp cacao comp adjectival descriptor nominal descriptor
0.0 fl oz 1 0 0 minty creme de menthe
0.0 fl oz 0 1 0 chocolatey vodka
0.0 fl oz 0 0 1 chocolatey creme de cacao
0.0 fl oz 1 2 0 chocolatey mintini
0.0 fl oz 1 0 1 chocolatey grasshopper
(only partially reproduced)

And some very complex code scoring how well the drink matches the various descriptions. It also includes the reciprocal square root but laid out in a table, which is pretty wild.

Section 16.13 is Topic Columns

Text in quotes is always assumed to be the ‘text’ kind in tables, unless you specifically call a column ‘topic’, then that’s used for “comparing against what the player has typed”.

Apparently the only thing you can do with columns is the ‘listed in’ thing.

Examples:
After asking the Sybil about a topic listed in the Table of Sybil's Replies, say "The Sybil declaims for a while, the gist being that the muse in question looks after [muse entry]."

Table of Sybil’s Replies

Topic Muse
“calliope” “epic poetry”
“clio” “history”
“erato” “love poetry”
“euterpe” “music”
“melpomene” “tragedy”
“polyhymnia” “sacred poetry”
“terpsichore” “dancing”
“thalia” “comedy”
“urania” “astronomy”
“monica” “tidiness”
“phoebe” “massage”
“rachel” “oval hair-cuts”

Nice Friends references.

Topics can be more elaborate like this:
"Bridget" or "Bridge" or "Bridget Jones"

or

"flora/eve"

Example 277 is Merlin:

Understand "remember [text]" as remembering.

Remembering is an action applying to one topic.

Carry out remembering:
say "Nothing comes to mind.".

Instead of remembering a topic listed in the Table of Recollections:
say "[response entry][paragraph break]".

Table of Recollections
Topic Response
“rain/weather” “You’ve seen worse, but not often: it’s falling so hard now that the tin rattles and the runoff, on the low side of the roof, would be a tenable source of hydroelectric power.”
“hydroelectric power” or “power/hydroelectric” “It’s not as though you have any sort of light bulb in here to turn on, even if you could power it.”
“light bulb” or “light/bulb” “Light bulbs, like so much else, are a thing of your past. Or is it your future? Tricky, the way the world loops round on itself.”
“past/time/future” “Living backwards has its drawbacks. A tendency to confuse and annoy your friends, being one; the total inability to maintain a stable relationship; and a deep dissatisfaction with most of the bodily processes people enjoy, since they ultimately make you hungrier, colder, or-- no point dwelling on it, really.”
“backwards” “It’s not even exactly backwards, now is it? It’s more like a series of forwardses stuck back to back. As though someone had taken each track of a CD and put them in the exactly wrong order. You miss that. The music on demand.”

Section 16.14 is Another Scoring example:

To record (T - text) as achieved:
choose row with a citation of T in the Table of Tasks Achieved;
if there is no time entry:
now time entry is the time of day;
increase the score by the points entry.

The phrase above expects to see a table like this one:

Table of Tasks Achieved

Points Citation Time
1 “pride” a time
3 “anger”
2 “avarice”
4 “envy”
1 “lust”
2 “gluttony”
3 “sloth”

I guess this is a cool way of doing this, since, it prevents the score from being assigned twice.

Wait, I have an exact situation I could use this! I have an escape room in my game with seven rooms themed after the seven deadly sins, with 1 score point assigned per room and a place where past winners brag about their completion times. I could put this directly in my game! Probably won’t but it’s pretty funny.

Before eating, record "gluttony" as achieved.

Example 280, Goat-chese and Sage Chicken, is similar. It uses the kind of table shown above and then assigns the ‘table of rankings’ as we saw earlier in another chapter.

1 Like

#Chapter 16, continued

Section 16.15 is Varying which table to look at

This is just make a table name that varies. So check this out:

Table 1 - Nifty Opening Plays in US Scrabble

word score
“muzjiks” 128

Table 2 - Nifty Opening Plays in UK Scrabble

word score
“quartzy” 126
“squeezy” 126
The lexicon is a table name that varies. The lexicon is Table 1.

To flip tables:
    say "You exchange dictionaries, lexically crossing the Atlantic. ";
    if the lexicon is Table 1, now the lexicon is Table 2;
    otherwise now the lexicon is Table 1;
    choose a random row in the lexicon;
    say "Did you know that according to [the lexicon], [word entry] scores [score entry]?"

Example 281 is Farewell

Table of Tina’s Chatter

topic reply summary turn stamp
“aasvogel” “‘Oh, it’s a vulture.’” “that an aasvogel is a vulture” a number
“acaudate” “She shrugs, mid-pour. ‘Means something doesn’t have a tail.’” “that acaudate means ‘tailless’”
“absorptiometer” “‘It’s a thing that measures the solubility of gases in a liquid,’ she explains gently, as to a child.” “that an absorptiometer measures solubility of gasses in a liquid”

Table of George’s Chatter

topic reply summary turn stamp
“baccaceous” “‘Something that has or bears berries,’ says George, without looking up.” “that baccaceous means berry-bearing or berry-like” a number
“bagheera” “‘Oh, that’d be a velvet-like textile.’” “that bagheera is a velvet-like textile”
“balistarius” “‘That’s a crossbow-man,’ George replies instantly.” “that a balistarius is a crossbow-man”
A person has a table name called conversation.

Instead of asking someone about something:
    let the source be the conversation of the noun;
    if topic understood is a topic listed in source:
        if there is a turn stamp entry:
            say "[The noun] has already told you that [summary entry].";
        otherwise:
            now turn stamp entry is the turn count;
            say "[reply entry][paragraph break]";
    otherwise:
        say "[The noun] stares at you blankly."

Hmm, this is pretty similar to my own conversation extension, but I didn’t use tables, as a lot of the responses are quite long and often have extra effects.

Section 16.16 is Defining things with tables

This is used when you want to define a large group of similar objects but don’t want to fill out a long and tedious template:

The Staging Area is a room. A jersey is a kind of thing. A jersey is wearable. Some jerseys in the Staging Area are defined by the Table of Honorary Jerseys. The description of a jersey is "Since [year established], the Tour de France has awarded this jersey to the [citation]."

Table of Honorary Jerseys
jersey year established citation
a yellow jersey 1919 “race leader”
a polkadot jersey 1933 “King of the Mountains”
a green jersey 1953 “highest point scorer on sprints”
a white jersey 1975 “best cyclist aged 25 or less”

The first column provides names for the things, and it automatically creates the properties ‘year established’ and ‘citation’ for each thing.

Given a blank space, that thing is just not input. You can also make kinds this way, like ‘some kinds of jerseys are’).

This would be a convenient way of handling boring scenery items. You could have a column for the internal name, a column for the room it’s in, a column for its description, a column for synonyms, a column for printed name, and a column for interaction message.

Example 282 is Sweeney:

This is a complex example I won’t reproduce here. It has multiple tables, each table corresponding to a conversation topic, and each table having multiple questions and answers.

Example 283 is Introduction to Juggling:

toy cost restriction description difficulty outcome
an economy bounce ball set $10.00 “comes in set of three” “A fairly ordinary rubber ball, solid color.” moderate “You create of the balls a cascade of moving color.”
an acrylic contact ball $14.00 “should be bought with ball polish” “A large clear ball, not for throwing but for using in various hand tricks.” hard “You rotate the ball between your fingers and pass it over the backs of your hands.”
a UV-reactive contact ball $55.00 “appears to glow in dark rooms” “Similar to the ordinary acrylic contact ball, but UV-reactive.” hard “The ball glows as it passes between your fingers and over the backs of your hands, rolls up to your wrist, snaps through the air-- all apparently of its own accord.”
a ball polish set $10.00 “useful only with acrylic contact balls” “Three bottles of polish and a rag for keeping acrylic contact balls scratch-free.” hard “You juggle the polish bottles with difficulty, since they are full of sloshing liquid.”
a teaching beanbag set $8.00 “set of three” “Soft, easily-juggled bag.” easy “You juggle the beanbags with basic competence.”
a stage ball set $13.50 “comes in set of three” “Not much different in appearance from the economy bounce ball, but larger so as to be visible from a stage.” moderate “You create of the balls a cascade of moving color, visible from quite a distance.”
a fireball set $33.00 “will not be sold to minors” “A ball has wicking and a fuel-source inside so that it will burn while being juggled.” hard “You juggle the fireballs rapidly, careful never to hold any of them a moment longer than necessary.”

Section 16.17 is Defining values with tables

It’s a convenient way for defining values with associated properties:

Solar distance is a kind of value. 1000 AU specifies a solar distance. Planet is a kind of value. The planets are defined by the Table of Outer Planets.

Table of Outer Planets

planet semimajor axis
Jupiter 5 AU
Saturn 10 AU
Uranus 19 AU
Neptune 30 AU
Pluto 39 AU

With these definitions, one can say:
say "Pluto orbits at [semimajor axis of Pluto]."

Columns are created one at a time, so you can use earlier columns in later columns:

Table of Outer Planets

planet semimajor axis centre of government
Jupiter 5 AU Jupiter
Saturn 10 AU Saturn
Uranus 19 AU Saturn
Neptune 30 AU Pluto
Pluto 39 AU Pluto

Column names can’t coincide with any other names of properties of other things, so goofier column names are better here.

Two technical footnotes. In a table used to define a kind of value, blank entries are not left blank: they are filled in with suitable default values. For instance, if the semimajor axis column had been all "–"s except for listing Neptune at “30 AU”, say, Inform would deduce that the column was meant to hold a value of kind “solar distance”, and would set the solar distances for all of the other planets to be “0 AU”. It does this to ensure that “solar distance of P” exists for any planet P.

The second technical note is that we must not sort such a table, because it is used during play to store the properties, and if it were to get rearranged then so would the properties be - with probably disastrous results.

Section 16.18 is Table continuations

This is something vital for using many extnsions and even some core Inform stuff (like the table used for questions after beating the game).

You can start making a table:

Table of Outer Planets

planet semimajor axis
Jupiter 5 AU
Saturn 10 AU
Uranus 19 AU
Neptune 30 AU
Pluto 39 AU

and then finish it later:

Table of Outer Planets (continued)

planet semimajor axis
Orcus 39 AU
Quaoar 43 AU
Xena 68 AU
Sedna 524 AU

This is useful for extensions especially.

The continuation must have the same name as the original, because it is the original.

Some fun side notes are included in this section:

At time of writing the International Astronomical Union has not yet consented to name 2003 UB313 after Xena, the Warrior Princess, but this is surely only a bureaucratic delay. (Footnote: on 24 August 2006 it was demoted to dwarf planet status, like the luckless Pluto, and on 13 September renamed Eris; though its moon’s official name, Dysnomia, is an ingenious double-meaning to do with the name of Xena’s actress, Lucy Lawless.)

Example 284 is Food Network Interactive

It shows how to continue a table used in extensions.

Include Basic Screen Effects by Emily Short. Include Menus by Emily Short. Include Basic Help Menu by Emily Short.

Table of Basic Help Options (continued)
|title|subtable|description|toggle|
| — | — | — | — |
|“Recipes in This Game”|Table of Recipes|–|–|
|“Contacting the Author”|–|“If you have any difficulties with [story title], please contact me at fakeaddress@gmail.com.”|

And then another table later for a sub-menu (this is not a continuation, just a feature of the extension that turns tables into submenus:

Table of Recipes

title subtable description toggle
“Salmon Tartare” “First, be sure to buy extremely fresh salmon. Raw fish should be served on the day it was caught, if possible. To guarantee this, visit an Asian supermarket or specialty store, and buy salmon marked ‘sashimi grade’…”
“Pecan Brownies” “Begin by shelling half a pound of pecans…”

Whole Foods is a room.

Finally, section 16.19 is Table amendments

It just replaces rows in a table.

Table of Plans

moment outcome
10 AM “takeover of Mars”
11:30 AM “canals reflooded”
11:45 AM “chocolate bar production doubled”

Table of Plans (amended)

moment outcome
11:45 AM “volcanic cave production doubled”

Amendment rows may be given in any order. The process of matching a row begins at the left-most column: Inform tries to see if any single row in the original table has a matching entry. If none does, a Problem is issued. If more than one do, Inform then looks at the second column, and so on. For instance:

Enthusiasm is a kind of value. The enthusiasms are pumped, wired and languid.

Table of Mental States

feeling extent consequence
pumped 1 “you feel able to run for your life”
pumped 2 “you feel able to run for President”
wired 1 “you feel able to run”
languid 1 “you feel”

Table of Mental States (amended)

feeling extent consequence
pumped 2 “you feel able to run for the Nebraska State Legislature”

Here the amendment is made to the second row of the original table. The value in the leftmost column, “pumped”, matches two rows in the original, so Inform moves on to the next column, reads “2”, and finds that only one row in the original still qualifies - so that is the one replaced.

Example 285 is Trieste:

This just modifies an extension’s help menu:

Table of Standard Instructions (amended)

help-topic reply
commands “The only commands this game recognizes are HOLD, MOVE, CONVOY, SUPPORT MOVE, and SUPPORT HOLD. No others are necessary.”

I don’t have many comments here; tables seem like straightforward implementations of relational databases (is that the phrase?) and I don’t really use them much. To me this is like browsing a hardware store and getting to the fastener aisle. Essential, useful, but dull.

Any table fans reading along that want to speak up in favor of tables?

2 Likes

Oh, I’m not technically savvy enough to advocate for tables, but I did use several in the WIP.

Excluding my large (bloated?) menus implementation and adding to table of final q’s, my soon-to-be-released game has fourteen.

I think a big part of it was my decision to use something close to the footnote example in the Ibid. recipe early on. I figured it out and it seemed reliable, so I looked around for other stuff to do with tables. Mechanically, it turned out to be a good way to track actions/events and feed them back to the player on demand.

Though really, anything I figured out once I wanted to use again, which is probably not much of a design principle :joy_cat:

1 Like

Nope, it works for any table. It’s sometimes useful when Inform can’t decide what type the column should be—for example, a literal topic can look a lot like literal text, so you can put “(topic)” after the column name to clarify.

Yeah, tables are just chunks of memory allocated at compile-time, so you can’t change their size at runtime.

The Standard Rules use this to keep track of all the things that need to be printed in a room description: they’re kept in the Table of Locale Priorities. Oddly enough, it doesn’t use that phrase:

Before printing the locale description (this is the initialise locale description rule):
    now the locale paragraph count is 0;
    repeat through the Table of Locale Priorities:
        blank out the whole row.

Emily Short likes to do this: every turn, the rule finds the first non-blank row of the table, does something with it, then blanks out that row and returns. I don’t like it because it means you can’t go backward or reset to the beginning, so I just use another variable to keep track of the current position instead.

3 Likes

Tables are kind of like statically allocated relational database tables without any of the power of SQL and keys and joins and all that. That said, they’re indispensable to me. I use tables to organize loads of little bits of text in one place rather than scattered all over the file like object descriptions are. I have a table to hold all the custom “can’t go that way” messages for instance. When combined with a To decide phrase it’s pretty convenient.

1 Like

Heh, I haven’t used much of Inform’s novel math stuff, but I used logarithms once. It was to create a counter that goes down every turn, but the amount it goes down decreases at an exponential (logarithmic?) rate. I understand exponents fine but I don’t know what logarithms really are, these days. I haven’t since high school.

-Wade

1 Like

The way you can eliminate rows, find non-blank rows at random etc. is all pretty good fire-and-forget stuff when it suits what you’re doing. It won’t always.

I guess that’s what I’d say about tables in general. For banks of data I create before the game is run, I almost always use a table (and not a list). Even if sometimes the table is only three entries long.

I have by now acquired an instinct about when a table will be handier or when a list will be easier, but it’d take a lot of typing to articulate it all here.

Tables can also be handy when they’re easy to parse with your eyes. However if a table is NOT going to be easy to read (i.e. each rows is very long so they don’t line up visually), and I want to be able to read or edit it at speed over time, I find that to be a PITA.

-Wade

2 Likes

Tables are great for defining a bunch of values (things or otherwise) and their properties, and they’re the only viable way to pre-define a list of topics (but not the only possible way).

But for me, their greatest value is as a versatile workaround for one of the things I find to be one of I7’s biggest pain points: the inability to build dynamic data structures and pass them as values.

Tables can be associative arrays (“dicts” in Python, “hashes” in Perl or Ruby) mapping one value to another, or to a collection of values. They can be a passable 2-D array. They can be a means of passing or receiving multiple parameters of different kinds to functions or rulebooks. (Of course, since things can only return one value, and rulebooks can only receive one, it’d have to be the table row and the table name would have to be some predefined constant for the purpose, or you could have some more complicated global variable scheme).

Lists are truly dynamic, but building and manipulating them is so painfully slow they quickly become unviable. Given that lookup (other than by row number) is by linear search, tables aren’t speed demons, but they’re statically allocated and typically better than lists.

6 Likes

Chapter 17: Understanding

17.1 Understand

This chapter is about player input. The concept is fundamental, and its basics are covered in earlier chapters.

‘Understand’ sentences, this section teaches, are used to convert typed player commands into computer-understood stuff.

For actions specifically, we usually put one ‘variable’ in our understand statement for each variable declared, as so:

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

Understand "photograph [someone]" as photographing.

Understand "photograph [an open door]" as photographing.

What would be bad is not having them match up:

Understand "photograph" as photographing.
Understand "photograph [someone] standing next to [something]" as photographing.

The first is probably bad because it supplies no things at all, the second is certainly because it supplies two: what we want, of course, is just the one. (The reason the first is only probably bad is that it’s possible to tell Inform how to choose the object if the player doesn’t: see the “supplying a missing noun” activity.)

Example 286 is Indirection:

Using colors as directions (in reference to the Mayans).

Understand "white" and "sac" as north. Understand "red" and "chac" as east. Understand "yellow" and "kan" as south. Understand "black" and "chikin" as west.

Example 287 is XYZZY:

Understand "xyzzy" or "say xyzzy" or "cast xyzzy" as casting xyzzy.

Casting xyzzy is an action applying to nothing.

Check casting xyzzy:
if the player does not wear the amulet of elocution, say "You are unable to articulate the second 'z' separately from the first, and the spell fails in a disdainful puff. Must be Parisian magic." instead;
if the player has the plate, say "The plate of cheeses twitches uncomfortably, aware that it should be doing something, but not sure what." instead.

Carry out casting xyzzy:
move the plate to the player.

Report casting xyzzy:
say "Under the influence of the Amulet of Elocution, you pronounce this as Xhi-zee. And lo, from nowhere, a [plate] appears!"

This is intended to show an example of an action requiring no objects/variables.

Example 288 is Xylan:

Understand "hydrolyze [something]" as hydrolyzing. Hydrolyzing is an action applying to one thing.

Carry out hydrolyzing:
    say "[The noun] cannot be hydrolyzed."

Instead of hydrolyzing the xylan:
    move the xylose to the holder of the xylan;
    now the xylan is nowhere;
    say "At once the xylan becomes xylose."

There is a xylose sample. The xylan sample is a thing in Plant Cell Wall. The description of the xylan is "A polysaccharide. Totally useless. If only you had some xylose, instead!" The description of the xylose is "Awesome!"

This is given as a ‘bad example’, since it’s kind of a guess the verb situation.

So the suggestion is to add synonyms, alternative spellings, and in-game nudges and full-fledged hints:

Understand "break down [something] with water" or "break [something] down with water" as hydrolyzing.

Understand "hydrolyse [something]" as hydrolyzing.

Instead of examining the player, say “You’re a drop of water, which means that you can break down certain chemicals!”

Understand "break down [something]" or "break [something] down" as hydrolyzing.

Understand "help" or "hint" or "hints" or "instructions" or "info" or "about" as asking for help. Asking for help is an action out of world. Carry out asking for help: say "The following commands are understood, in addition to the standard ones: EVAPORATE, FREEZE, HYDROLYZE, SUBLIME..."

Man, this stuff is very helpful. It’s a shame this chapter is so late in the book; I remember the ‘actions’ chapter seemed like it was missing a lot of key examples, and I guess they’re all here. I get why this chapter is delayed, since it includes complex things like understanding by relations, but I wonder if it could be split up into 'Understanding" and ‘Advanced Understanding’, and the first part moved earlier.

Section 17.2 is New commands for old grammar.

This just says that you can add synonyms to pre-existing inform commands:

Understand "deposit [something] in [an open container]" as inserting it into.

We can also flip the orders of things around:

Understand "fill [an open container] with [something]" as inserting it into (with nouns reversed).

This next part is so revelatory to me that I will quote it in full:

The following example:

Understand "access [something]" as opening.

might look as if it makes “access” behave just like “open” when the player types it, but that’s not so: “open” can also be used in constructions like “open the door with the brass key”, in which case it is understood as the unlocking action. We could add another line to make “access” behave this way too, but if what we really want is to make “access” behave just like “open”, it’s easier simply to say so:

Understand the command "access" as "open".

Example 289 is Alpaca Farm, which shows how one verb can be given many meanings:

Understand "use [an edible thing]" as eating.

Understand "use [a wearable thing]" as wearing.

Understand "use [a closed openable container]" as opening. Understand "use [an open openable container]" as closing.

Understand "use [something preferably held] on [a locked lockable thing]" as unlocking it with (with nouns reversed). Understand "use [something preferably held] on [an unlocked lockable thing]" as locking it with (with nouns reversed).

Understand "use [a switched off device]" as switching on.

Understand "use [something]" as using. Using is an action applying to one thing. Carry out using: say "You will have to be more specific about your intentions."

Understand "use [a door]" as opening. Understand "use [an open door]" as entering.

(Note the ‘something preferably held’ up above, which I think there was a section on earlier but hasn’t been used much so far).

Example 290 is Anchorite:

Understand "get down" as exiting.

Instead of going down when the player is on a supporter:
    try exiting.

Example 291 is…Cloak of Darkness! A rare 4-star example. As the documentation says:

“Cloak of Darkness” is a brief example game that has been implemented in nearly every IF system currently used. It hasn’t got much claim to complexity or richness, but it does exemplify many of the standard things one might want an IF language to be able to do: define descriptions and the results of actions, assign synonyms to nouns, create new verbs, handle darkness, track repeated acts, and so on.

Section 17.3 is Overriding existing commands.

This is where Inform already has a certain behavior for a command and you want to eliminate it. For instance, ‘discard’ already means ‘drop’, but maybe you don’t want it to. So you can type this to remove its previous associations:

Understand the command "discard" as something new.

I’d like to give a personal warning here from my own experience and from watching other coders:

So often new players think, like, ‘I want to be able to CLEAN GLASSES’, but ‘CLEAN’ is mapped to RUB! I’ll just disconnect them and make a new ‘clean’ action!

But…the thing is, rub/clean is already a cleaning action! People just don’t like that the in-code name is rubbing. They want to type, ‘instead of cleaning the glasses’.

But if you just leave the command alone and type, ‘instead of rubbing the glasses’, it involves way less work. That’s just my opinion: if you’re doing the ‘something new’ commands to make room for a new command, but never use the old command for anything, you might as well have just used the old command all along.

Anyway, once you say ‘understand…as something new’, you can just use it like any other word:

Understand "discard [something]" as discarding.

You can also say ‘as something new’ for stuff that isn’t actually a command already. That’s on purpose, to make your code still be good even if an extension you are using changes.

You can also, instead of removing meaning from a word, remove all words from a meaning:

Understand nothing as taking.

Then no command will cause the taking action. But for this specific example:

The commands “take” and “get” will still exist, but now they’ll only have their other senses (for taking off clothes, for getting out of boxes).

Example 292 is The Trouble with Printing

This is a classic example that lets you make 'read’ing and 'examin’ing different.

A thing has some text called printing. The printing of a thing is usually “blank”.

Understand the command "read" as something new. Understand "read [something]" as reading. Reading is an action applying to one thing, requiring light. Check reading: if the printing of the noun is "blank", say "Nothing is written on [the noun]." instead. Carry out reading: say "You read: [printing of the noun][line break]". Report reading: do nothing.

Example 293 is Lanista 2 (I don’t really remember Lanista 1):

Understand the commands "attack" and "punch" and "destroy" and "kill" and "murder" and "hit" and "thump" and "break" and "smash" and "torture" and "wreck" as something new.

(couldn’t we just say 'understand nothing as attacking?)

Attacking it with is an action applying to one visible thing and one carried thing. Understand "attack [someone] with [something preferably held]" as attacking it with.

Section 17.4 is Standard tokens of grammar.

This is another essential section. Honestly, this chapter should probably be one of the first a new author reads, after Actions.

Tokens are things like [something] or [someone] that matches patterns.

This section contains the following enigmatic phrase:

“[someone]” matches the same possibilities as “[a person]” would, but the parser handles it a little better in cases of failure.

You can modify tokens like this:

Understand "wear [something preferably held]" as wearing.

This is used to resolve ambiguities. You could also make commands that require you absolutely to be holding something, but doesn’t give an example of how to do so.

If you want to allow multiple things, you can type ‘things’:

Understand "take [things]" as taking.
Understand "drop [things preferably held]" as dropping.

You can use special phrases I’ve never seen to exclude everything in a container or everything not in a container:

Understand "put [other things] in/inside/into [something]" as inserting it into.

Understand "take [things inside] from [something]" as removing.

Finally is the thing that really screw up new authors: [any things]. This can include any object in the entire game, and objects ‘off stage’ and never seen. Typing ‘all’ with it would do your action to every single thing in the game!

Example 294 is Shawn’s Bad Day, which allows Examine All.

Understand "examine [things]" as examining.

Example 295 is The Left Hand of Autumn

Understand "examine [things]" or "look at [things]" as multiply-examining. Multiply-examining is an action applying to one thing.

Carry out multiply-examining:
    let L be the list of matched things;
    if the number of entries in L is 0, try examining the noun instead;
    if the number of entries in L is 1, try examining entry 1 of L instead;
    describe L;
    say line break;
    now group-description-complete is true.

There’s a lot more highly technical code here that gives special code for looking at a group of things that happens to have deep meaning.

Section 17.5 is ‘The text token’.

This is for commands where people should be able to type in stuff like a locker combination, or a question.

The token for “accept any text here” is just “[text]”

For instance:

Getting help about is an action applying to one topic.

Understand "help on [text]" as getting help about.

(Notice we say ‘one topic’ and later say ‘the topic understood’, instead of ‘one text’ or ‘the text understood’. That really tripped me up).

The fact that “[text]” can match anything means that it’s difficult to tell which version of a command was intended if they disagree only from a “[text]” onwards. For example, given:

Yelling specifically is an action applying to one topic. Understand "yell [text]" as yelling specifically. Understand "yell [text] at/to [someone]" as answering it that (with nouns reversed).

Example 296 is Ish.

Understand "help [text]" or "help about [text]" as getting help about. Understand the commands "instructions" or "hint" or "hints" or "menu" or "info" or "about" as "help".

Getting help about is an action applying to one topic.

Carry out getting help about:
    if the topic understood is a topic listed in the Table of Standard Help:
        say "[explanation entry][paragraph break]";
    otherwise:
        say "You're out of ideas."

Table of Standard Help

topic title summary explanation
“sushi” “sushi” “Really it’s just vinegary rice” “Popular misconception says that sushi inevitably entails raw fish, but it is in fact just rice with rice vinegar on it. It’s just that the really good kinds have raw fish in.”
“cucumber roll” or “cucumber” “Cucumber roll” “Sushi for people who are afraid of sushi” “It is just rice and slivers of cucumber in the middle, and as long as you don’t go too crazy with the wasabi, all should be well.”
“california roll” or “california” “California roll” “Travesty of the sushi concept” “It’s. Fake. Crab.”
“monkfish liver” “monkfish liver” “Expert eaters only” “The odds of Ichiro’s having this unusual delicacy is near zero.”
“microdot” “microdot” “What you came here to deliver” “There’ll be time enough for that later. If Fowler ever turns up. Where is she, anyway?”

Example 297 is Nameless:
This lets you ask about physical objects (I did this in Grooverland):

A thing can be known or unknown. The Nameless Advisor is known.

Understand "ask [someone] about [any known thing]" as interrogating it about. interrogating it about is an action applying to two visible things.

Instead of asking Nameless Advisor about a topic listed in the Table of Nameless Advisor Topics:
    say "[reply entry][paragraph break]".

Table of Nameless Advisor Items

item reply
letter “‘It is enciphered,’ she remarks[if the advisor can see the letter], glancing over the contents[otherwise], after you have offered a detailed description[end if]. ‘A substitution cipher of some complexity, I believe.’”
Advisor “She listens to your inquiries about her identity and parentage with a placid smile, but does not answer.”

Section 17.6 is Actions applying to kinds of value

Most actions apply to things, but they don’t have to. They can apply to specific kinds of values!

Adjusting it to is an action applying to one thing and one number.

Understand "adjust [something] to [a number]" as adjusting it to.

But if you type ‘applying to one number’, you have to put [a number] in the token area.

Example 298 is Safety:
(I have the text for this copied almost word for word in my game. Or, actually, I think I removed it and replaced it with another example from later on in this chapter, though I’ve never read the whole chapter).

In the Safe is a silver florin. The Safe is closed and fixed in place. Understand "dial" as the Safe.

Spinning it to is an action applying to one thing and one number. Check spinning it to: if the noun is not the Safe, say "[The noun] does not spin." instead. Report spinning it to: say "Click! and nothing else happens."

Understand "spin [something] to [a number]" as spinning it to.

After spinning the closed Safe to 1384: now the Safe is open; say "Clonk! and the safe door swings slowly open, revealing [a list of things in the Safe]."

Example 299 is Tom’s Midnight Garden:

Understand "set [clock] to [time]" as setting it by time. Setting it by time is an action applying to one thing and one time.

Instead of setting a clock to something:
    say "[The noun] can be set only to a time of day, such as 8:00 AM, or midnight."

Carry out setting a clock by time:
    now the current time of the noun is the time understood.

Report setting a clock by time:
    say "You set [the noun] to [time understood]."

Every turn:
    repeat with item running through switched on clocks:
        now the current time of the item is one minute after the current time of the item.

Example 300 (woohoo! We’ve gotten far):

This example, Ibid, shows how to make a footnote system. I won’t reproduce chunks here, but it lets the game say something like [Footnote 3] and then have the player be able to look up that footnote, with only the revealed footnotes being allowed to be looked up, and numbering of footnotes being in order of their being revealed.

Example 17.7 is Understanding any, understanding rooms

The token [something] only matches what is within reach (most of the time) or in sight (if we typed one visible thing).

If we want to be able to ignore scope, we can say:

Understand "manipulate [any door]".

To avoid this perhaps too-strong power, you can restrict it by a description:

Understand "go to [any adjacent visited room]" as going by name.

Going by name is an action applying to one thing.

As might be expected, “[anything]” means the same as “[any thing]”; “[anybody]” and “[anyone]” mean the same as “[any person]”; and “[anywhere]” means the same as “[any room]”.

Example 301 is One of Those Mornings:

Understand “find [any thing]” as finding.

Finding is an action applying to one visible thing.

Carry out finding:
    if the player is carrying the noun:
        say "You're holding [the noun]!";
    otherwise:
        say "You left [the noun] [if the noun is on a supporter]on[otherwise]in[end if] [the holder of the noun]."

Example 302 is Actaeon:

A person has a room called last location.

Understand "follow [any person]" as following. Understand the commands "chase" and "pursue" as "follow".

Following is an action applying to one visible thing.

Check following:
if the noun is the player, say "Wherever you go, there you are." instead;
if the noun is visible, say "[The noun] is right here." instead;
if the last location of the noun is not the location, say "It's not clear where [the noun] has gone." instead.

Carry out following:
    let the destination be the location of the noun;
    if the destination is not a room, say "[The noun] isn't anywhere you can follow." instead;
    let aim be the best route from the location to the destination;
    say "(heading [aim])[line break]";
    try going aim.

To move (pawn - a person) tidily to (target - a room):
    now the last location of the pawn is the holder of the pawn;
    move the pawn to the target.

Section 17.8 is Understanding names

This mentions that we can use ‘understand’ to name objects, and not just actions.

This…is one of the absolute most fundamental things in Inform. Bizarre that it’s in the middle of a chapter 3/4 of the way through the book.

For instance, writing

The St Bernard is an animal in the Monastery Cages.

makes ST BERNARD refer to the dog, and MONASTERY CAGES refer to the room. But sometimes, as here, that isn’t really enough. Why shouldn’t the player type EXAMINE DOG? One way to allow this is to write:

Understand "dog" as the St Bernard.

If you make a kind and make multiples of a kind, inform automatically makes a plural for it. So if you code in:

The Lake is a room. A duck is a kind of animal. Four ducks are in
    the Lake.

then you can type TAKE DUCKS.

In that situation, you can make your own plurals:

Understand "birds" and "ruddy ducks" as the plural of duck.

And you can make a plural for a single item:

The magpie is in the Lake. Understand “birds” as the plural of the magpie.\

Why? So you can do this:

And now TAKE BIRDS tries to take all four ducks and the magpie too.

17.9 is Understanding kinds of value

Given any kind of value you create, you can just put the name of it in brackets and Inform will understand it.

Limb is a kind of value. The limbs are left leg, left arm, right leg and right arm.

Detailing is an action applying to one limb and one visible thing, requiring light. Check detailing: if the camera is not carried then say "You can hardly photograph without a camera, now can you?" instead. Report detailing: say "Click! You take a detail photograph of the [limb understood] of [the second noun]."

Understand "photograph [limb] of [a person]" as detailing.

If you use [a time], inform understands that as Time of Day only. But it won’t understand a duration of time, which needs something like [a time period].

Example 303 is Pages:
Understand "read [number] in/from/of [something]" or "read page [number] in/from/of [something]" or "look up page [number] in/from/of [something]" or "consult page [number] in/from/of [something]" as reading it in. Reading it in is an action applying to one number and one thing, requiring light.

There’s quite a bit of other work in here as well.

Example 304 is Down in Oodville.

This is a way to give numbered options that don’t interrupt regular text.

Understand "[number]" as selecting.

Selecting is an action applying to one number.

Check selecting:
    if the number understood is greater than the number of filled rows in the Table of Transport Options or the number understood is less than one:
        say "[The number understood] is not a valid option. ";
        list the transport options instead.

To list the transport options:
    let N be 1;
    say "From here you could choose to go to: [line break]";
    repeat through the Table of Transport Options:
        say " [N]: [transport entry][line break]";
        increment N.

Table of Transport Options
transport
an object
with 3 blank rows. [In the current scenario, the number of blank rows need never be greater than the number of rooms in the game, minus the transport room itself.]

After entering the transporter pad:
    say "The transporter beeps and glows amber as you step onto its surface. A moment later a hologram displays your options. [run paragraph on]";
    empty the transport options;
    load the transport options;
    list the transport options.

(This reminds me of Hybrid Choices, which was a super popular extension for several years).

Example 305 is Straw to Gold:

R-name is a kind of value. The R-names are dwarf, guy, dude, and man-thing. Rumpelstiltskin has an R-name. Understand "[R-name]" as Rumpelstiltskin.

After reading a command:
    if the player's command includes "[R-name]",
        now the R-name of Rumpelstiltskin is the R-name understood;
    if the player's command includes "Rumpelstiltskin":
        now Rumpelstiltskin is identified;
        now Rumpelstiltskin is proper-named.

Rule for printing the name of Rumpelstiltskin when Rumpelstiltskin is unidentified:
    if the R-name of Rumpelstiltskin is man-thing:
        say "man";
    otherwise:
        say "[R-name]".

I’m guessing at the very end we don’t have to mention which r-name we’re printing because we referred to rumpelstiltskin earlier?

Example 17.10 is Commands consisting only of nouns. I’ve done this before with my conversation system, which models topics as nouns; many people find it desirable to say just the name of the topic to bring it up.

You can do it like this:

Understand "[something]" as examining.

One caveat here is that you can’t use this kind of verb and command other people to use it. Why?

It also has what may be a serious limitation: verbless commands like this work only when typed by the player as actions to follow - they do not work as instructions for other people. So for instance SVEN, BALL would not ask Sven to try examining the ball - instead it would generate the action “answering ball to Sven”. (This is because the Inform parser decides whether PERSON, SOME TEXT is a request or just conversation by looking at the first word after the comma to see if it’s a command.)

Example 306 is Misadventure

Understand "[any room]" as going by name. Understand "go to [any room]" as going by name.

Going by name is an action applying to one thing.

Check going by name:
    if the noun is the location, say "You're already in [the location]." instead;
    if the noun is not adjacent and the noun is unvisited, say "That noun did not make sense in this context." instead.

Carry out going by name:
    let aim be the best route from the location to the noun, using doors;
    if aim is not a direction, say "You can't think how to get there from here." instead;
    say "(heading [aim])[command clarification break]";
    try going aim;
    if the location is not the noun, say "You'll have to stop here."

Example 307 is Safari Guide

Understand "go to [any room]" as going by name. Understand "[any room]" as going by name. Understand "[door]" as entering.

Going by name is an action applying to one thing.

Check going by name:
    if the noun is the location, say "You're already in [the location]." instead.

Carry out going by name:
    while the player is not in the noun:
        let heading be the best route from the location to the noun, using even locked doors;
        if heading is not a direction, say "You can't think how to get there from here." instead;
        let destination be the room heading from the location;
        say "(heading [heading])[command clarification break]";
        try going heading;
        if the player is not in the destination, rule fails.

Section 17.11 is Understanding values.

You can use ‘understand’ to refer to an entire kind of thing at once! So you can make ‘machine’ a synonym of every device like so:

Understand "machine" as a device.

You can write new names for individual values:

Understand "eleventy-one" as 111.

Example 308 is Palette:

Colour is a kind of value. The colours are white, red, blue and green.

The canvas has a colour. The canvas is white. The printed name of the canvas is "largely [colour] canvas".

Painting is an action applying to one thing and one colour. Check painting: if the noun is not the canvas, say "Centuries of tradition suggest that canvas is the natural home of paint." instead. Carry out painting: now the colour of the canvas is the colour understood. Report painting: say "You splash away at the now [canvas]."

Understand "paint [something] [a colour]" as painting.

Understand "calico" as white. Understand "cerulean" or "cerulean blue" as blue.

Example 309 is Baritone, Bass

Gender is a kind of value. The genders are masculine, feminine, and unknown. Understand "male" or "man" or "M" as masculine. Understand "female" or "woman" or "F" as feminine.

A person has a gender. The gender of the player is unknown.

When play begins:
    now the command prompt is "Please choose a gender for your character. >".

After reading a command when the gender of the player is unknown:
    if the player's command includes "[gender]":
        now the gender of the player is the gender understood;
        if the gender of the player is unknown:
            say "This story requires a selection of male or female. [run paragraph on]";
            reject the player's command;
        if the gender of the player is masculine, now the player is male;
        if the gender of the player is feminine, now the player is female;
        say "[line break]Thank you. We now begin...";
        now the command prompt is ">";
        move the player to Sandy Beach;
        reject the player's command;
    otherwise:
        say "Sorry, we're not ready to go on yet. [run paragraph on]";
        reject the player's command.

And I’ll stop there for the day! This is a big chapter, after all. I’ll probably split Activities up into multiple days as well (40 sections!) while most of the rest are fairly short.

1 Like

Usually true, but sometimes you need to do this to change the requirements of an action. The Standard Rules have “Wearing is an action applying to one carried thing,” but if you want to remove that “carried” requirement, you have to make a new command.

(Okay, I found a way to hack around that, but it’s terrible.)

No, I think it’s because we’re in an activity rule where the object is Rumpelstiltskin. I wouldn’t rely on this, honestly. It feels shaky.

2 Likes

It’s important to note that these examples generally use synonyms rather than the most obvious verb: “interrogating” instead of “asking”, “spinning” instead of “setting”. That’s because it’s best to have every action in the game use a different verb for its internal name—Inform is less likely to get confused in some technically-ambiguous-but-intuitively-clear edge cases.

That’s why the Standard Rules have “inserting it into” instead of “putting it into”: the verb “putting” is used for “putting it on”. (And similarly “wearing” instead of “putting on”, etc.)

This only applies to the internal names, of course; it’s just fine to let the player type “ask” for interrogating, “set” for spinning, “put” for inserting, and so on.

2 Likes

Inform’s parser treats verbs in a fundamentally different way from other words, which made sense in the early days (it’s more efficient to just parse the verb, then use that as an index into a lookup table) but in the era of I7 is just kind of awkward. It leads to all sorts of bugs, like NPCs not being able to use actions that don’t start with verbs, and the parser not considering verbless grammar lines if the first word is a verb (even if that’s the only line that would match), and some nasty hacks are required to make “out of world” work properly (since it’s set by the verb word, not by the action).

It’s one of the many things that would be nice to change if we could fundamentally redesign the parser, but it hasn’t been fully rewritten for longer than I’ve been alive, so the odds of that get lower every year.

1 Like