let's play: Inform 10's Basic Inform and Standard Rules (SR: Actions 2)

Indeed. I think this is defined elsewhere in the standard rules? It’s pretty much what it sounds – starting from the actor and getting its holder until either a room or a closed container is reached.

It might be more elegant to have the error in question be a parameter, but Inform generally avoids rulebook/activity parameters unless necessary, preferring global variables at the I6 level. It’s a relic of how the I6 library was built (where non-global variables were far harder to use than in I7).

Yeah, I don’t really know why the documentation brings up “it rained” here. The “it” there is a quirk of English: in English, one argument of a verb is treated specially in various ways, and that means it’s not possible to have a verb with zero arguments. There always has to be at least one argument to fill in that special slot. In other languages, like Hittite, all of the arguments of a verb are treated pretty much the same, which means there’s no need to stick in a meaningless “it” just to fill the slot.

(Formally, we say that English is not a “null subject” language. This is closely linked to a phenomenon called “pro-drop”, which splits European languages roughly in half; French and German act like English, while Italian and Spanish act like Hittite.)

(For the programming enthusiasts, you might draw an analogy with message-sending in object-oriented languages. In a language like Python, you can’t have an object method with zero parameters: the first parameter is special, and receives the object who owns the method, and that parameter always has to be there. I’ve sometimes wondered if single dispatch would have become so dominant if English wasn’t standard in the programming world.)

But that really has nothing to do with “supplying a missing [second] noun”! Those are about filling in objects, not subjects. There are plenty of English verbs that let you mess around with the structure of the objects, like how you can “donate $50” or “donate to charity” or “donate $50 to charity” and all of those are equally valid. The fact that you can “listen to something” or simply “listen” is not especially unusual—any more than how you can “take something” or “take something from a container”, or “go north” or “go to the store” or just “go”.

By the way, this is worth noting:

What is “the second noun” doing there? It’s some hackery in the response machinery! The I6 function that prints these responses takes up to two arguments, and it stows those in the “noun” and “second noun” globals so that I7 texts can access them. The “second noun” here is actually the actor, which unlike the noun and the second noun is not a global.

TBH I’d count this as a flaw in the library. I think it would be good for it to move towards making fuller use of the features that exist in the language wherever they’re appropriate.

Oh, but “Jump!” is totally a verb with zero arguments, is it not? :wink:
(No-one said implicit arguments count…)

But I think you’re correct about the documentation’s discussion of “it” as a dummy pronoun isn’t really relevant to the case of supplying a missing noun. After all, like you said, that dummy pronoun is filling in for a missing subject; but supplying a missing noun is referring to filling in a missing direct object.

Speaking of which, couldn’t it be said that Inform7 supports multiple dispatch? Which makes it rather unusual among programming languages (I don’t know of any others besides Lisp and its dialects off the top of my head that support multiple dispatch).

But is it really? :face_with_tongue:

  • I looked
  • I looked at myself
  • I looked at you
  • You looked
  • You looked at me
  • You looked at yourself
  • Look!
  • Look at me!
  • Look at yourself!

“-self” only appears in English when there’s something else in the sentence to trigger it, so clearly there is a “you” there—it’s just invisible. We can’t see it, but other words in the sentence can!

If you really want a verb with no arguments, you can look at expletives: “damn you”, “damn me”, “damn God”, not *“damn yourself”, *“damn myself”, or *“damn Himself”. But these also don’t act like verbs in other respects: “look at me and then leave”, *“damn you and then leave”; “look at me tomorrow”, *“damn you tomorrow”; “don’t look at me”, *“don’t damn you”. So there’s a good argument to be made that these aren’t actually verbs at all! They just happen to look like them.

(I’ve probably said it here before, but I was introduced to this fact by a very kindly older linguistics professor who refused to use profanity in the classroom, even for an example, so he insisted on “bless you” instead.)

I get what you’re saying, but even Wikipedia gives the imperative as an example of a null subject. It’s true that there’s implicitly a “you” as the subject, but it’s not actually present in the sentence.

I really don’t understand why you’re analyzing those as phrasal no-argument verbs rather than as imperatives with an object… and I’d also say that “damn yourself” and “damn myself” can work just fine, though maybe not standalone (so you may have at least a partial point here). There’s also the fact that “look at you” is a perfectly normal thing to say.

In sincerity, expletives seem to act differently from imperatives in a good handful of ways, not just with regard to reflexives. I would interpret “look at you” as an expletive—it’s not an actual command for the person to look at themself, it’s an exclamation with a fixed form. (“Go to the mirror and look at yourself” vs *“go to the mirror and look at you”; “take a good long look at yourself” vs *“take a good long look at you”.)

The seminal work on these expletives is the infamous English Sentences Without Overt Grammatical Subject, which points out that imperatives can appear in a bunch of different syntactic contexts where expletives can’t. Its example sentences are a thing of beauty. My favorite is that “fuck communism” is valid but *“describe and fuck communism” is not, suggesting that “fuck communism” has a different underlying structure than “describe communism” (compare “describe and analyze communism” which is fine, since the two clauses have the same structure). Or that *“fuck seven irregular verbs” is invalid, but “fuck these seven irregular verbs” is fine, showing that expletives can’t have indefinite objects, only definite ones (compare “analyze seven irregular verbs”).

The imperative subject thing, though, is just me splitting hairs. You’re right that from Inform’s perspective there’s no subject there.

I think I have to disagree with this. The Inform design means you (the author) can easily react to things when you see fit, rather than only at the points the library designates.

On the other hand, the TADS3 adv3 library seems to take this to the other extreme. E.g. the player’s actual typed command doesn’t seem to be exposed anywhere, it only lives in local variables within the parser and apparently you’re just not supposed to think about it at all. Which I guess is technically the more modern way to write software, but in practice what is the benefit of the library hiding that information from the author?

(Edit: the above would be true if we were talking about using a rulebook variable, but that’s not what we’re talking about.)

Are you disagreeing with something I never even said? Because I don’t see how this statement is in contradiction with a claim that (for example) “the printing a parser activity should be an activity on parser errors so that the current error can just be a parameter”. Similarly, I don’t see anything in what I said that implies the parser should not be exposed.

Sorry, I got confused between parameters and rulebook variables.

We’re talking about the “basis of a rulebook” (§19.9) when we say rulebook parameter, right?

This is always stored in a common I6 global parameter_value which is necessarily polymorphic. This leads to some headaches in the I7 type system. The matter be well-smoothed-over at this point in I7’s development, but possibly it was a pain point early on and motivated the design that avoids rulebook parameters.

On the other hand, “damn you today and damn you tomorrow” is now a phrase that I desperately want to work into a piece of dialogue somewhere.

We’ll only do posthumous activities today. Is there life after death?

Standard Rules: Activities 3

§15. Posthumous activities. The very last rules of all. The obituary is a rare example of a sequence of events in the I6 library having been rolled up into an activity, partly because it’s one of the few clear-cut moments where several unconnected things happen in succession.

The phrases end the story and end the story finally both produce the obituary “The end.” “You have won” and “You have lost” might be Inform 6 artifacts. They aren’t mentioned in the documentation and there do not appear to be related phrases in the index.

The print final score rule is a straightforward declaration that authors may wish to tailor. As we’ve discussed elsewhere, Inform’s built-in scoring systems are seen less frequently in contemporary games. All of my games feature scoring systems, as I’m fond of them, but they are each their own thing.

I haven’t seen the amusing a victorious player activity implemented in some time. For it to appear in the final question, the story must have ended finally and there must be at least one for amusing a victorious player rule.

A search for “final status line rule” on this forum finds no matches. I believe the default Inform behavior is to just keep printing the last status line from play. I have rewritten status line content when play ends to clear out room names and such. Am I mistaken?

Section 4 - Posthumous activities

Amusing a victorious player (documented at act_amuse) is an activity.

Printing the player's obituary (documented at act_obit) is an activity.
The print obituary headline rule is listed last in for printing the player's obituary.
The print final score rule is listed last in for printing the player's obituary.
The display final status line rule is listed last in for printing the player's obituary.

The print obituary headline rule translates into Inter as "PRINT_OBITUARY_HEADLINE_R"
    with " You have died " (A),
        " You have won " (B),
        " The End " (C).
The print final score rule translates into Inter as "PRINT_FINAL_SCORE_R".
The display final status line rule translates into Inter as "DISPLAY_FINAL_STATUS_LINE_R".

§16. There is one last question: the one which usually reads “Would you like to RESTART, RESTORE a saved game, or QUIT?”, but which sometimes provides other options too. The “ask the final question rule” handles this, and does so by repeatedly calling the following activity:

The final question activity, I have learned through trial and error, is more elaborate that I once would have guessed.

Handling the final question is an activity.

§17. It follows that this activity must at least sometimes do something dramatic to the execution state: perform a quit, for instance. Four primitive rules are available for the drastic things which the activity might wish to do, but these are not placed in any rulebook: instead they are available for anyone who wants to call them. (In the default implementation below, we put references to them into a table.)

There are two separate rules for quitting a game in Inform, quit the game and immediately quit. The latter, which by default is only called after play has ended, does not ask a confirmation question. By now, it follows, players know what they are asking for. In the case of immediately undo, that means rule responses must be declared.

These are mostly just features of interest. Authors who want different behaviors will likely edit the table (see below) rather than tinker with these specifics.

The immediately restart the VM rule translates into Inter as "IMMEDIATELY_RESTART_VM_R".
The immediately restore saved game rule translates into Inter as "IMMEDIATELY_RESTORE_SAVED_R".
The immediately quit rule translates into Inter as "IMMEDIATELY_QUIT_R".
The immediately undo rule translates into Inter as "IMMEDIATELY_UNDO_R" with
    "The use of 'undo' is forbidden in this story." (A),
    "You can't 'undo' what hasn't been done!" (B),
    "Your interpreter does not provide 'undo'. Sorry!" (C),
    "'Undo' failed. Sorry!" (D),
    "[bracket]Previous turn undone.[close bracket]" (E),
    "'Undo' capacity exhausted. Sorry!" (F).

§18. We structure the activity so that the printing of the question and typing of the answer take place at the “before” stage, and then the parsing and acting upon this answer take place at the “for” stage. Reading the keyboard is the last rule in “before”. With the “for” stage, the idea is that any extra rule slipped in by the user can take precedence over the default implementation, so the latter is the last there, too.

I would like to say that authors don’t usually tinker with the handling the final question activity, but, while I think that’s true, I made multiple interventions there for Portrait with Wolf at the before phase of things.

The before output (prompt and question text) are ultimately texts that, despite some unusual features, can be manipulated in familiar ways. The read portion of the activity involves more arcane techniques.

respond is written in natural language, as we’ll see below.

The print the final question rule is listed in before handling the final question.
The print the final prompt rule is listed in before handling the final question.
The read the final answer rule is listed last in before handling the final question.
The standard respond to final question rule is listed last in for handling the final question.

This is the print the final prompt rule: say "> [run paragraph on]" (A).

The read the final answer rule translates into Inter as "READ_FINAL_ANSWER_R".

§19. That clears away the underbrush and reduces us to two matching tasks: (i) to print the question, (ii) to parse the answer, given that we want to be able to vary the set of choices available.

We do this by reading the options from the Table of Final Question Options. (See below for its default contents.) Each row is an option, whose wording must be placed in the topic column. The final question wording entry can either be text describing the option — e.g., “perform a RESTART” — or can be left blank, making the option a secret one, omitted from the question but still recognised as an answer. The only if victorious entry can be set to make the option available only after a victorious ending, not after a loss; Infocom’s traditional AMUSING option behaved thus. Finally, the table specifies what to do if the option is taken: either it provides a rule, or an activity to carry out. (If it provides only an activity, but that activity is empty, then the option is omitted from the question and not recognised as an answer.)

Anyone who’s built their own dynamic list (rather than using Inform’s listing mechanisms) will be familiar with counting list entries to determine whether to print and, ., or , following entries. The print the final question rule constructs a sentence containing just such a list based on the contents of the table of final question options. I don’t believe the question itself is manipulated often. I did so for Portrait with Wolf for both practical and aestetic reasons. Practically speaking, the options were too long to fit in a tidy sentence, so I printed a vertical list instead.

I suppose you have “options” now that you’ve reached the “end” of your little project.

  • Consult the GUIDE (updated!)
  • Review all ENDINGS (E) attained
  • View all collected PORTRAITS (or P)
  • SERIES [number I-VIII (or 1-8)] to revisit a previous portrait series
  • QUIT

In the typical case, though, these end-of-game options will be printed.

Would you like to RESTART, RESTORE a saved game, QUIT or UNDO the last command?

Section 5 - The Final Question

This is the print the final question rule:
    let named options count be 0;
    repeat through the Table of Final Question Options:
        if the only if victorious entry is false or the story has ended finally:
            if there is a final response rule entry
                or the final response activity entry [activity] is not empty:
                if there is a final question wording entry, increase named options count by 1;
    if the named options count is less than 1, abide by the immediately quit rule;
    say "Would you like to " (A);
    repeat through the Table of Final Question Options:
        if the only if victorious entry is false or the story has ended finally:
            if there is a final response rule entry
                or the final response activity entry [activity] is not empty:
                if there is a final question wording entry:
                    say final question wording entry;
                    decrease named options count by 1;
                    if the named options count is 1:
                        if the serial comma option is active, say ",";
                        say " or " (B);
                    otherwise if the named options count is 0:
                        say "?[line break]";
                    otherwise:
                        say ", ";

§20. And the matching rule to parse and respond to the answer:

The respond to final question rule matches snippets (the player’s command) to topics (a column in the table of final question options). Even though it might look like the game is parsing grammar at this point, it is not. If the snippet matches a topic, the corresponding rule or activity wil run.

The activity is a loop that is only broken by choosing one of the previously mentioned “drastic” measures: restoring a game, quitting, undoing, or restarting.

If we add a custom rule of our own that—for instance—prints some gameplay statistics, the program will ask the question once more, accept input, and attempt to respond again.

If the player’s input does not match a topic listed in the table of final question options, the question will be similarly asked again.

This is the standard respond to final question rule:
    repeat through the Table of Final Question Options:
        if the only if victorious entry is false or the story has ended finally:
            if there is a final response rule entry
                or the final response activity entry [activity] is not empty:
                if the player's command matches the topic entry:
                    if there is a final response rule entry, abide by final response rule entry;
                    otherwise carry out the final response activity entry activity;
                    rule succeeds;
    say "Please give one of the answers above." (A).

§21. The table of final options is the only material under the following heading to make it easier for users to replace with entirely different tables.

These settings are the traditional ones used by Inform since 1995 or so. The UNDO option has customarily been a “secret”, though not much of one, since it somewhat cheapens the announcement of a calamity to be immediately offered the chance to reverse it: death, where is thy sting?

An interesting aside regarding the sting of death. I imagine that death itself is less common, or, at least, less game-disrupting than it once. This is likely down to changing sensibilities. I haven’t taken a poll, but I wouldn’t be surprised if many players don’t save their games frequently, if at all.

Whatever the case, editing or inserting rows into the table of final question options can prove challenging because of the topic column, since a text is not a topic.

In the past, I’ve just added a (continued) table in my project while clearing the original entries.

Section 6 - Final question options

Table of Final Question Options
final question wording  only if victorious  topic       final response rule     final response activity
"RESTART"               false               "restart"   immediately restart the VM rule --
"RESTORE a saved game"  false               "restore"   immediately restore saved game rule --
"see some suggestions for AMUSING things to do" true    "amusing"   --  amusing a victorious player
"QUIT"                  false               "quit"      immediately quit rule   --
"UNDO the last command" false               "undo"      immediately undo rule   --

Quite a short update today! The locale activities should get their own post. It’s very likely that there will be many corrections, so let’s set aside a specific update just for that.

These settings are the traditional ones used by Inform since 1995 or so.

Running through the Infocom canon as I am, I was interested to realize that they didn’t invent the “RESTART, RESTORE, or QUIT” choice until 1984. It took another year to really standardize all their games on it.

Yeah, earlier versions of Inform provided “end the game in death” and “end the game in victory”. These by default printed “you have died” and “you have won”, but you could override the message if you wanted.

In one version…I think 6G60?…those were removed and replaced with “end the story” and “end the story finally”, which both printed “the end”. That was the same version that made scoring be disabled by default instead of enabled by default.

“Victorious” meaning the story ended “finally”.

I think this is the only place where a rulebook or activity being “empty” is checked in the standard rules.

I’ve never much liked this tradition, personally. Hidden game features that make everything easier but are never taught, you have to just know them from other games, are not very friendly to newcomers.

Huh! What did they do before that?

The Zork games had in-game resurrection, of course. If you ran out of chances the game just shut down. Starcross did the same thing with a sci-fi recoloring.

Otherwise, the typical handling was “Would you like to play again?” as a yes/no question. Or some variant of that.

Standard Rules: Activities 4

I haven’t been looking forward to this next bit, as I’ve always found the printing the locale description of something activity rather intimidating. However, I think a lot of beginning authors (including myself) have wanted to understand or even change its behavior at some point, so we really ought to soldier on. Let’s have a look.

There are several longer passages that I will break into more readily processed chunks. I’m also going to shuffle some things around to place code and descriptive text close together.


§24. Printing the Locale Description. This is handled by the “printing the locale description” activity. The before stage works out which objects might be of interest; the for stage actually prints paragraphs; the after stage is initially empty, but can be used to insert all kinds of interesting information into a room description.

We count the paragraphs printed in a global variable, not an activity variable, since it needs to be consulted in sub-activities whose rules are outside what would be its scope; that doesn’t matter, though, since locale descriptions are not nested. (If they were, the above table would fail in any case.)

This is a highly nonsurgical characterization, but the printing the locale description generates the text that displays after a room’s description text while looking: paragraphs and lists regarding some (not all) things visible to the player.

One common invocation—during the looking action— is carry out the printing the locale description activity with the visibility-holder of the actor.

visibility-holder might be challenging to parse—it’s adjudicated in I6—but it is ultimately a determination of the way visibility might “stack” or “nest” for an actor within a room containing supporters, containers, and so forth. In the most common case, the visibility-holder of the player will be the location.

Printing the locale description of something (documented at act_pld) is an activity.

The locale paragraph count is a number that varies.

  • (1) Disaster would ensue if the user tampered with the “initialise locale description rule”, but nobody is likely to do this other than intentionally.

The activity works from a table. This first step clears it out.

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.

  • (2) The “find notable locale objects rule” in fact only runs a further activity, the “choosing notable locale objects” activity. The task here is to identify the objects which might by virtue of their location appear in the locale, and to assign each of them a priority number.

The next step is to assign a locale priority to objects deemed relevant by the find notable locale objects rule. This is covered later, but I’m going to pull it up now because it can be hard to keep up with what’s going on. So first, the rule that invokes it:

Before printing the locale description (this is the find notable locale objects rule):
    let the domain be the parameter-object;
    carry out the choosing notable locale objects activity with the domain;
    continue the activity.

The temporary variable domain is used to refer to parameter-object throughout this project. Let’s look at the named actitiy:

§25. Choosing Notable Locale Objects. By default, the notable objects are exactly the children of the domain, and they all have equal priority (1). Since table sorting is stable, and thus preserves the row order of rows with equal priority, the eventual order of listing is by default the same as the order in which things are added to the table, which in turn is the object-tree traversal order.

OK. By default, all items with equal priority (the default) will be added to the table according to “object-tree traversal order.” Said order is the product of a number of factors that can be hard to anticipate. CF this thread for ideas for managing priority in a systemic way.

The code itself is unusual, though, so let’s have a look at that.

Choosing notable locale objects of something (documented at act_cnlo) is an activity.

For choosing notable locale objects (this is the standard notable locale objects rule):
    let the domain be the parameter-object;
    let the held item be the first thing held by the domain;
    while the held item is a thing:
        set the locale priority of the held item to 5;
        now the held item is the next thing held after the held item;
    continue the activity.

It might not be immediately clear that we are looking at a loop. Inform is working through each thing held by the domain (parameter-object) until the collection is exhausted (when the held item is nothing).

The phrase set the locale priority of the held item to 5 writes to the recently-blanked-out table of Locale Priorities. More on that soon.

Just to keep track of things: at this point we have a table populated by things held by the domain, each with a locale priority value assigned (5 by default).


  • (3) The “interesting locale paragraphs rule” goes through all of the notable objects chosen at stage (2), in order of priority, and offers each to yet another activity: the “printing a locale paragraph about” activity. This can either print a paragraph related to the item in question, or demote it as being not even nondescript (by changing its priority to 0). The default is to do nothing, in which case the item becomes nondescript.

If we authors have written interesting (a technical term) paragraphs for objects, those objects will be sorted before being processed by the the printing a locale paragraph about activity.

For printing the locale description (this is the interesting locale paragraphs rule):
    let the domain be the parameter-object;
    sort the Table of Locale Priorities in locale description priority order;
    repeat through the Table of Locale Priorities:
        carry out the printing a locale paragraph about activity with the notable-object entry;
    continue the activity.

The printing a locale paragraph about activity is rather complex, so pasting it here would likely be confusing. We’ll get to it soon. The important takeaway is that by default the only sort of interesting paragraph is one set by initial description. All other things in a default room description are handled as nondescript items.


  • (4) The “you-can-also-see rule” prints what is, ordinarily, the final paragraph of the locale description, listing the nondescript items. It goes to some trouble to find out whether these all have a common object tree parent, listing them with “list contents of” if they do: this is so that people who have written rules such as “Rule for printing the name of the blur while listing contents…” will take effect, because the “listing contents” activity will be going on. Provided that the notable objects chosen in (2) are all children of the locale domain, this will always happen. If the user should add rules to make quite different objects also notable, then the “you-can-also-see rule” has to resort to listing in a way which doesn’t use the “listing contents” activity — since the list is not in fact a list of the contents of anything.

This is the most elaborate phase of the printing the locale description of something activity. There may be more than one list of nondescript objects to print, depending on the object-tree parent (the term holder might often apply) involved.

This is an unusual case in which we have an activity running across multiple lines of code rather than running and stopping in sequence. That activity, the listing the nondescript items of something, is written in Inform 6, so it’s behavior is not described at the natural language layer. We know it is happening, and we can see what the printing the locale description of something is doing while it runs.

At the outset, we have some pretty familiar looking code using Inform’s list writer.

For printing the locale description (this is the you-can-also-see rule):
    let the domain be the parameter-object;
    let the mentionable count be 0;
    repeat with item running through things:
        now the item is not marked for listing;
    repeat through the Table of Locale Priorities:
        if the locale description priority entry is greater than 0,
            now the notable-object entry is marked for listing;
        increase the mentionable count by 1;
    if the mentionable count is greater than 0:
        repeat with item running through things:
            if the item is mentioned:
                now the item is not marked for listing;

At the end of this process, we have either zero or some in-game things marked for listing based on their locale priority and mentioned properties.

        begin the listing nondescript items activity with the domain;
        if the number of marked for listing things is 0:
            abandon the listing nondescript items activity with the domain;

Here, the listing nondescript items activity begins. Should there be zero things marked for listing, the activity is manually stopped.

I welcome corrections here, but my read of this next bit of code is that a lot is going to depend on what the listing nondescript items activity is up to. We appear to be looking at the innards of a loop here. If the player were in a room with both occupied supporters and containers, these mutually exclusive otherwise conditions would both apply.

       otherwise:
            if handling the listing nondescript items activity with the domain:
                if the domain is the location:
                    say "[We] " (A);
                otherwise if the domain is a supporter or the domain is an animal:
                    say "On [the domain] [we] " (B);
                otherwise:
                    say "In [the domain] [we] " (C);
                if the locale paragraph count is greater than 0:
                    say "[regarding the player][can] also see " (D);
                otherwise:
                    say "[regarding the player][can] see " (E);

Next, some more familiar listwriting code with a few unusual features.

                let the common holder be nothing;
                let contents form of list be true;
                repeat with list item running through marked for listing things:
                    if the holder of the list item is not the common holder:
                        if the common holder is nothing,
                            now the common holder is the holder of the list item;
                        otherwise now contents form of list is false;
                    if the list item is mentioned, now the list item is not marked for listing;
                filter list recursion to unmentioned things;
                if contents form of list is true and the common holder is not nothing,
                    list the contents of the common holder, as a sentence, including contents,
                        giving brief inventory information, tersely, not listing
                        concealed items, listing marked items only;
                otherwise say "[a list of marked for listing things including contents]";
                if the domain is the location, say " here" (F);
                say ".[paragraph break]";
                unfilter list recursion;
            end the listing nondescript items activity with the domain;
    continue the activity.

unfilter list recursion calls Inform 6 code. I am not certain what it does. Perhaps it performs a bit of cleanup while the cyclical nondescript items activity is running? I feel I might have a philosophical understanding of what happens in this activity, but not a practical one. In any case, the activity ends here.

All that remains is to review the writing a paragraph about activity in greater detail.


§26. Printing a Locale Paragraph. By default there are four kinds of “interesting” locale paragraph, and the following setup is fairly complicated because it implements conventions gradually built up between 1978 and 2008.

To recap, this activity is run on each notable thing in turn, in priority order. (It is only run on notable things for efficiency reasons.)

The basic principle is that, at every stage, we should consider an item only if it is not “mentioned” already. This will happen if it has been named by a previous paragraph, but also if it has been explicitly marked as such to get rid of it. In considering an item, we have three basic options:

  • (a) Print a paragraph about the item and mark it as mentioned — this is good for interesting items deserving a paragraph of their own.
  • (b) Print a paragraph, but do not mark it as mentioned — this is only likely to be useful if we want to print information related to the item without mentioning the thing itself. (For instance, if the presence of a mysterious parcel resulted in a ticking noise, we could print a paragraph about the ticking noise without mentioning the parcel, which would then appear later.)
  • (c) Mark the item as mentioned but print nothing — this gets rid of the item, ensuring that it will not appear in the final “you can also see” sentence, and will not be considered by subsequent rules.
  • (d) Do nothing at all — the item then becomes “nondescript” and appears in the final “you can also see” sentence, unless somebody else mentions it in the mean time.

The documentation is far more ample here. I doubt this is because the subject matter is more complex. Rather, I believe it is because we are far more likely to intervene here as authors.

Briefly, then, the following is the standard method:

  • (1) The “don’t mention player’s supporter in room descriptions rule” excludes anything the player is directly or indirectly standing on or, less frequently, in. The header of the room description has probably already said something like “Boudoir (on the four-poster bed)”, so the player can’t be unaware of this item.
  • (2) The “don’t mention scenery in room descriptions rule” excludes scenery.
  • (3) The “don’t mention undescribed items in room descriptions rule” excludes the player object. (It’s redundant to say “You can also see yourself here.”) At present nothing else in I7 is “undescribed” in this sense.
  • (4) The “set pronouns from items in room descriptions rule” adjusts the meaning of pronouns like IT and HER to pick up items mentioned. Thus if a room description ends “Mme Tourmalet glares at you.”, then HER would be adjusted to mean Mme Tourmalet.
  • (5) The “offer items to writing a paragraph about rule” gives the “printing a paragraph about” activity a chance to intervene. We detect whether it does intervene or not by looking to see if it has printed any text.
  • (6) The “use initial appearance in room descriptions rule” uses the initial appearance property of an object which has never been handled as a paragraph.
  • (7) The “describe what’s on scenery supporters in room descriptions rule” is a somewhat controversial feature: whereas the rest of Inform’s room description conventions are generally consensus, this one is much disliked by some users for its occasional inappropriateness. It prints text such as “On the mantelpiece is a piece of chalk.” for items which, like the mantelpiece, are scenery mentioned (we assume) in the main room description. (It is assumed that scenery supporters make their contents more prominently visible than scenery containers, which we do not announce the contents of.) The ability to modify, replace or abolish this rule was one of the main motivations to break room description up into activities in March 2008.

There’s a lot of useful information here that is otherwise distributed across the documentation!

These rules don’t always generate paragraphs. Sometimes they suppress them.

Printing a locale paragraph about something (documented at act_plp) is an activity.

For printing a locale paragraph about a thing (called the item)
    (this is the don't mention player's supporter in room descriptions rule):
    if the item encloses the player, set the locale priority of the item to 0;
    continue the activity.

If the player is standing on podium that isn’t scenery, Inform wiil not say You see a podium here.

For printing a locale paragraph about a thing (called the item)
    (this is the don't mention scenery in room descriptions rule):
    if the item is scenery, set the locale priority of the item to 0;
    continue the activity.

Why isn’t scenery listed in room descriptions? This is why!

For printing a locale paragraph about a thing (called the item)
    (this is the don't mention undescribed items in room descriptions rule):
    if the item is undescribed:
        set the locale priority of the item to 0;
    continue the activity.

Undescribed things are similarly dispensed with.

For printing a locale paragraph about a thing (called the item)
    (this is the set pronouns from items in room descriptions rule):
    if the item is not mentioned, set pronouns from the item;
    continue the activity.

Since the activity is run against all objects in the table of locale priorities, the last processed item will be assigned its applicable pronoun. Since there are multiple possible assignments (she, it, etc), there may be multiple pronouns set during this process.

At this point, the activity carries out the writing a paragraph about activity with regard to each item in the table. So far as I can tell, the writing a paragraph rulebooks are empty by default, so nothing will happen here unless we have written our own rules for writing a paragraph about something. The default output at this stage of the printing a locale paragraph about something, then, is nothing.

For printing a locale paragraph about a thing (called the item)
    (this is the offer items to writing a paragraph about rule):
    if the item is not mentioned:
        if a paragraph break is pending, say "[conditional paragraph break]";
        carry out the writing a paragraph about activity with the item;
        if a paragraph break is pending:
            increase the locale paragraph count by 1;
            now the item is mentioned;
            say "[conditional paragraph break]";
    continue the activity.

The locale paragraph count increments as new paragraphs print. So far as I can tell, this number is only checked to determine if it is greater than one, in which case "[regarding the player][can] also see " will precede a list of nondescript items.

Next, Inform will determine if the locale object has an initial appearance (i.e., the initial appearance is not ""), and, if it does, it will print that appearance as a paragraph. That isn’t all; if there is something relevant on it, the listwriter will produce a list of things on the locale object.

We won’t get to this until later, but the activity uses the calculated property locale-supportable to determine eligibility.

For printing a locale paragraph about a thing (called the item)
    (this is the use initial appearance in room descriptions rule):
    if the item is not mentioned:
        if the item provides the property initial appearance and the
            item is not handled and the initial appearance of the item is
            not "":
            increase the locale paragraph count by 1;
            say "[initial appearance of the item]";
            say "[paragraph break]";
            if a locale-supportable thing is on the item:
                repeat with possibility running through things on the item:
                    now the possibility is marked for listing;
                    if the possibility is mentioned:
                        now the possibility is not marked for listing;
                say "On [the item] " (A);
                list the contents of the item, as a sentence, including contents,
                    giving brief inventory information, tersely, not listing
                    concealed items, prefacing with is/are, listing marked items only;
                say ".[paragraph break]";
            now the item is mentioned;
    continue the activity.

But what about the initial appearance of things on supporters?

For printing a locale paragraph about a supporter (called the tabletop)
    (this is the initial appearance on supporters rule):
    repeat with item running through not handled things on the tabletop which
        provide the property initial appearance:
        if the item is not a person and the initial appearance of the item is not ""
            and the item is not undescribed:
            now the item is mentioned;
            say initial appearance of the item;
            say paragraph break;
    continue the activity.

The locale-supportable property is used in most of these later printing a locale paragraph rules.

Definition: a thing (called the item) is locale-supportable if the item is notscenery and the item is not mentioned and the item is not undescribed.

Next, the controverial rule listing the contents of scenery supporters.

For printing a locale paragraph about a thing (called the item)
    (this is the describe what's on scenery supporters in room descriptions rule):
    if the item is scenery and the item does not enclose the player:
        if a locale-supportable thing is on the item:
            set pronouns from the item;
            repeat with possibility running through things on the item:
                now the possibility is marked for listing;
                if the possibility is mentioned:
                    now the possibility is not marked for listing;
            increase the locale paragraph count by 1;
            say "On [the item] " (A);
            list the contents of the item, as a sentence, including contents,
                giving brief inventory information, tersely, not listing
                concealed items, prefacing with is/are, listing marked items only;
            say ".[paragraph break]";
    continue the activity.

I can see how this behavior might be undesirable, though I haven’t really been affected by it personally. In Repeat the Ending, I did in fact want to list the nerd stuff and later the wallet in room descriptions. In Marbles, D, and the Sinister Spotlight, the protagonist cannot carry things, so items on supporters are not a consideration. Nevertheless, the rule is named here and authors can delist it if they choose.

An author testing the edges of things might discover that declaring a supporter mentioned will not prevent the printing the locale description activity from listing its contents. In fact, Inform is prepared for this scenario specifically!

For printing a locale paragraph about a thing (called the item)
    (this is the describe what's on mentioned supporters in room descriptions rule):
    if the item is mentioned and the item is not undescribed and the item is
        not scenery and the item does not enclose the player:
        if a locale-supportable thing is on the item:
            set pronouns from the item;
            repeat with possibility running through things on the item:
                now the possibility is marked for listing;
                if the possibility is mentioned:
                    now the possibility is not marked for listing;
            increase the locale paragraph count by 1;
            say "On [the item] " (A);
            list the contents of the item, as a sentence, including contents,
                giving brief inventory information, tersely, not listing
                concealed items, prefacing with is/are, listing marked items only;
            say ".[paragraph break]";
    continue the activity.

As we discussed last time, Inform provides authors with many “hooks” into the printing the locale description of something activity, and these opportunities are documented. They involve writing custom rules for sub-activities like listing the nondescript items of or writing a paragraph about. I’ll list them here, with comments:

  • writing a paragraph about something—Write custom paragraph about something (this applies the mentioned property to the item)
  • listing nondescript items of something—customize content, format, etc of a list printed during the you-can-also-see rule
  • choosing notable locale objects for something—intervene in the locale prioritization process, setting our own locale priority values via the set the locale priority of [something] to [number]
  • printing a locale paragraph about—from the documentation: “If all that’s required is to supply an interesting paragraph of room description about something then it’s always better to use the “writing a paragraph about” activity, not this one. This activity should only be used when the mechanism itself needs to be adjusted.”
  • printing the locale description of something—the provided examples involve stopping, prefacing or afterwording the process entirely. For tweaking outcomes, we are better off using one of the above entry points.

That, I believe, is that! I am curious about the operation of the you-can-also-see rule, since it involves a loop that I don’t really understand. But otherwise, we have hopefully gotten to the far end of this without too many errors. I do appreciate the many “onramps” available for authors to customize the locale description.

This is the end of the “Activities” section of the Standard Rules. Next come "Actions’ which will probably take quite a while to get through.

  • Basic Inform: Preamble
  • Standard Rules: Preamble
  • Basic Inform: Miscellaneous Definitions
  • Standard Rules: Physical World Model
  • Standard Rules: Variables and Rulebooks
  • Standard Rules: Activities
  • Standard Rules: Actions
  • Standard Rules: Command Grammar
  • Basic Inform: Phrase Definitions
  • Basic Inform: Adjectival Definitions
  • Standard Rules: Phrase Definitions

“Filter list recursion to X” and “unfilter list recursion” set a filter on the list-writer: when it’s listing the contents of something, it will ignore any items that don’t match the filter. So this ensures that the list-writer doesn’t re-mention a mentioned thing that happens to be inside an unmentioned thing.

This is an undocumented feature of the Standard Library which authors are not supposed to touch, since it might go away at any time.

The Actions section of the Standard Rules is HUGE! So we have to keep moving. I’d like to do shorter, more frequent posts, but we’ll see how that goes.

For a first, small bite: inventory and taking.

Standard Rules: Actions

§1. Inform comes with no actions built in, and Basic Inform defines none either. The compiler makes only one (perhaps unexpected) assumption: that the 8th action defined is “going”.

The order, and the subheadings, here are responsible for the order and subheadings used in the Actions page of the Index.

The section begins with several declared verbs that the Standard Rules will use in adaptive responses.

Part Five - Actions

Section 1 - Verbs needed for adaptive text

To achieve is a verb. To appreciate is a verb. To arrive is a verb. To care is a verb.
To close is a verb. To die is a verb. To discover is a verb. To drop is a verb.
To eat is a verb. To feel is a verb. To find is a verb. To get is a verb.
To give is a verb. To go is a verb. To happen is a verb. To hear is a verb.
To jump is a verb. To lack is a verb. To lead is a verb. To like is a verb.
To listen is a verb. To lock is a verb. To look is a verb. To need is a verb.
To open is a verb. To pass is a verb. To pick is a verb. To provoke is a verb.
To pull is a verb. To push is a verb. To put is a verb. To rub is a verb.
To say is a verb. To search is a verb. To see is a verb. To seem is a verb.
To set is a verb. To smell is a verb. To sniff is a verb. To squeeze is a verb.
To switch is a verb. To take is a verb. To talk is a verb. To taste is a verb.
To touch is a verb. To turn is a verb. To wait is a verb. To wave is a verb.
To win is a verb.

§2. Taking inventory.

Inventory is, a “classic” action dating back to the original Adventure. Many parser games—most, perhaps—are concerned with collecting things.

Section 2 - Standard actions concerning the actor's possessions

Taking inventory is an action applying to nothing.
The taking inventory action translates into Inter as "Inv".

The specification of the taking inventory action is "Taking an inventory of
one's immediate possessions: the things being carried, either directly or in
any containers being carried. When the player performs this action, either
the inventory listing, or else a special message if nothing is being carried
or worn, is printed during the carry out rules: nothing happens at the report
stage. The opposite happens for other people performing the action: nothing
happens during carry out, but a report such as 'Mr X looks through his
possessions.' is produced (provided Mr X is visible)."

§3. There used to be a rule, documented here, to do with pronouns, and this was explained in terms of Missee Lee, a black and white cat living in North Oxford; named for a Cambridge-educated pirate queen in the South China seas who is the heroine — or villainess — of the tenth in Arthur Ransome’s Swallows and Amazons series of children’s books, “Missee Lee” (1941). The rule was then removed, but it seemed sad to delete the only mention of Missee, and all the more so since she died (at a grand old age and in mid-spring) in 2008.

A marvelous anecdote! This must mean there was once a “check taking inventory” rule. I’m glad that Missee Lee will not be forgotten. Hopefully this is carried forward to Inform 11’s Standard Rules.

§4. Carry out.

Carry out taking inventory (this is the print empty inventory rule):
    if the first thing held by the player is nothing,
        say "[We] [are] carrying nothing." (A) instead.

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

Something every new author might try is writing a taking inventory rule of their own. I’ve done so in each of my games, and I think it adds a bit of flavor (above and beyond any mechanical significance). I got my practice studying the above example as well as the more complex implementation of the Equipment List example.


§5. Report.

Report an actor taking inventory (this is the report other people taking
    inventory rule):
    if the actor is not the player and the action is not silent:
        say "[The actor] [look] through [their] possessions." (A);

While there is no mechanical upshot to NPCs taking inventory, the Standard Rules consistently account for actions performed by players and NPCs alike.


§6. Taking.

There’s a lot more to this one.

Taking is an action applying to one thing.
The taking action translates into Inter as "Take".

The specification of the taking action is "The taking action is the only way
an action in the Standard Rules can cause something to be carried by an actor.
It is very simple in operation (the entire carry out stage consists only of
'now the actor carries the noun') but many checks must be performed before it
can be allowed to happen."

I suspect that the only action more ubiquitous and significant within the protypical parser game than taking might be going. I was surprised to see all of the checks involved, which of course are familiar, but I hadn’t considered how much verification happened before a take, er, takes place.


§7. Check.

I’m going to list these rules one at a time for clarity’s sake.

Check an actor taking (this is the can't take yourself rule):
    if the actor is the noun:
        if the actor is the player, say "[We] [are] always self-possessed." (A);
        stop the action.

A simple one to start: the player cannot take themselves, and neither can NPCs.

Check an actor taking (this is the can't take other people rule):
    if the noun is a person:
        if the actor is the player, say "I don't suppose [the noun] [would care] for that." (A);
        stop the action.

Furthermore: a person (the kind of thing) cannot take another person.

Check an actor taking (this is the can't take other people rule):
    if the noun is a person:
        if the actor is the player, say "I don't suppose [the noun] [would care] for that." (A);
        stop the action.

A person cannot take something that is part of something else. For instance, if a handle is part of a knife, the player can take the knife but not the handle separately.

Check an actor taking (this is the can't take component parts rule):
    if the noun is part of something (called the whole):
        if the actor is the player:
            say "[regarding the noun][Those] [seem] to be a part of [the whole]." (A);
        stop the action.

Here, things get a little more spicy. I had to ask around and think about this one a bit. This rule (the can't take people's possessions rule) uses a loop to make sure that the owner is as close to the noun) as possible. What do I mean?

Consider this code:

lab is a room.

an elephant is an animal in lab.
the elephant is wearing a chair.
the chair is an enterable supporter.
bob is on the chair.
bob is holding a rare collectible Pokémon card.

Bob is holding the card, yes, but the card is enclosed by the elephant. Using a while loop, the Standard Rules will reply that the card belongs to Bob rather than the elephant, even though both have a claim to it.

>get card
That seems to belong to bob.

Check an actor taking (this is the can't take people's possessions rule):
    let the local ceiling be the common ancestor of the actor with the noun;
    let the owner be the not-counting-parts holder of the noun;
    while the owner is not nothing and the owner is not the local ceiling:
        if the owner is a person:
            if the actor is the player:
                say "[regarding the noun][Those] [seem] to belong to [the owner]." (A);
            stop the action;
        let the owner be the not-counting-parts holder of the owner;

What about something that begins the turn in-scope but is not available at the time of a taking action? It’s important to remember that, because of implicit taking and other circumstances, this could happen after the turn has been firing for a while.

Check an actor taking (this is the can't take items out of play rule):
    let H be the noun;
    while H is not nothing and H is not a room:
        let H be the not-counting-parts holder of H;
    if H is nothing:
        if the actor is the player:
            say "[regarding the noun][Those] [aren't] available." (A);
        stop the action.

An easier one: a person cannot take something containing or supporting them. This is the first appearance of the common ancestor, a thing computed by I6. The common ancestor is more or less the closest shared holder between two things. Why handle things this way? If we just checked for taking something when the noun holds the player we might have trouble with a chair stacked on a table, or a bed inside a box.

Check an actor taking (this is the can't take what you're inside rule):
    let the local ceiling be the common ancestor of the actor with the noun;
    if the local ceiling is the noun:
        if the actor is the player:
            say "[We] [would have] to get
                [if noun is a supporter]off[otherwise]out of[end if] [the noun] first." (A);
        stop the action.

Another easy one: we can’t take what we already have.

Check an actor taking (this is the can't take what's already taken rule):
    if the actor is carrying the noun or the actor is wearing the noun:
        if the actor is the player:
            say "[We] already [have] [regarding the noun][those]." (A);
        stop the action.

This message is familiar: scenery can’t be taken.

Check an actor taking (this is the can't take scenery rule):
    if the noun is scenery:
        if the actor is the player:
            say "[regarding the noun][They're] hardly portable." (A);
        stop the action.

Things can be taken. What else is there? Directions, of course, though they have their own error message. Rooms. Authors make their own object kinds, of course, and should they be placed in scope, this will prevent players from taking them. It wouldn’t make sense for non-things to be “held” in a traditional sense, anyway.

Check an actor taking (this is the can only take things rule):
    if the noun is not a thing:
        if the actor is the player:
            say "[We] [cannot] carry [the noun]." (A);
        stop the action.

There is a separate rule for things that aren’t scenery yet are fixed in place:

Check an actor taking (this is the can't take what's fixed in place rule):
    if the noun is fixed in place:
        if the actor is the player:
            say "[regarding the noun][They're] fixed in place." (A);
        stop the action.

As part of Inform’s holdall implementation, the Standard Rules will automatically stow away items when the player attempts a take at (or beyond) carrying capacity.

Check an actor taking (this is the use player's holdall to avoid exceeding
    carrying capacity rule):
    if the number of things carried by the actor is at least the
        carrying capacity of the actor:
        if the actor is holding a player's holdall (called the current working sack):
            let the transferred item be nothing;
            repeat with the possible item running through things carried by
                the actor:
                if the possible item is not lit and the possible item is not
                    the current working sack, let the transferred item be the possible item;
            if the transferred item is not nothing:
                if the actor is the player:
                    say "(putting [the transferred item] into he current working sack
                        to make room)[command clarification break]" (A);
                silently try the actor trying inserting the transferred item
                    into the current working sack;
                if the transferred item is not in the current working sack:
                    stop the action.

A last bit regarding carrying capacity, though as we’ve discussed throughout this thread games tend to lean on this less and less as the years go by.

Check an actor taking (this is the can't exceed carrying capacity rule):
    if the number of things carried by the actor is at least the
        carrying capacity of the actor:
        if the actor is the player:
            say "[We]['re] carrying too many things already." (A);
        stop the action.

§8. Carry out.

The hard part is over!

Carry out an actor taking (this is the standard taking rule):
    now the actor carries the noun;
    if the actor is the player, now the noun is handled.

§9. Report.

As a general note, one form frequently observed throughout the Standard Rules is separation of outcomes (in this case, the player holding the noun) from printed output (the report rule below). In my own work, I’m not too rigorous in this regard, but paying attention to the way actions are structured here can at least give us something to think about as we organize our own custom actions.

Report an actor taking (this is the standard report taking rule):
    if the action is not silent:
        if the actor is the player:
            say "Taken." (A);
        otherwise:
            say "[The actor] [pick] up [the noun]." (B).

OK, yes. even a short post takes a bit, so we’ll stop there for today. Next time: removing it from and dropping.

Two interesting thing:

first, the can’t take other people rule is a bit problematic for an heroic firefighter or policeman PC…

second, replacing the elephant with a dresser, the chair with a drawer and bob with a rather possessive mouse, one got a rather interesting puzzle about getting the mouse’s possession…

Best regards from Italy,
dott. Piergiorgio.

Not really when Inform has plenty of ways to tinker with this behaviour:

The can't take other people rule does nothing when the player is heroic and the location is perilous.