[I7] How does the game process more general directives that don't have an explicit "every turn:"?

In the past I was led to believe that we want to avoid “every turn:” if we can, because it can be a lot to process on every single turn for slower platforms. And that’s fair, it’s good to keep things light.

In my game I have a certain room (an intro room) where I don’t want to display the room name in bold when the description is printed. So I use:

The room description heading rule does nothing if the player is in Introductory Area.

But when is this actually evaluated? Is this running more or less every single turn, checking whether the player is in Introductory Area? Would a lot of these bog down execution?

And if I can do this, then why is “every turn:” ever necessary? Why can’t I insert random conditions wherever I want?

To make sense of this you have to understand something of the machinery of rulebooks involved in action processing and turn processing. A good introduction to action processing can be found in WWI 12.2 “How actions are processed”. [Note: “WWI” is short for “Writing With Inform”, part of the built-in documentation.] I’m not sure if there’s a similar discussion of the overall rulebook structure for the every turn rulebook, but if you take a look in the Index, you will see it under “Standards” the section titled “Rules added to the sequence of play”.

The rule that you’re referencing (the “room description heading” rule) is defined in the Standard Rules, and it is part of the “carry out looking” rulebook. The every turn rulebook (which would contain any specific every turn rule) is placed into the turn sequence rules as part of the Standard Rules, as well. The turn sequence rulebook is essentially the main loop of a running story, going from parsing to generating actions to processing actions to updating scene status and other bookkeeping like updating scores, light conditions, etc.

Because the “room description heading” rule is in the carry out looking rules, it is called only during execution of a looking action. (As WWI 12.2 shows, Carry out rules are specific to a particular action.) The rules engine doesn’t even look at that rule unless it’s processing a looking action. The every turn rules, on the other hand are executed every turn by the turn sequence rulebook, regardless of the action. So there is marginally less overhead for the “room description heading” rule than an every turn rule – though note that the way every turn rules are constructed (i.e. their preamble, see WWI 19.7 “The preamble of a rule”) means that many rules can be dismissed as inapplicable to the situation before they are executed, so that any overhead is negligible.

As a broader point, I don’t think it’s a good idea to achieve any change in the way that room names are printed via an every turn rule, so the two kinds of rules are not directly comparable in that way. Different rulebooks are invoked at different times for specific purposes, and knowing which rulebooks exist (and their purposes) is important to being able to decide what kind of rule is best to achieve any particular effect. In this case, you would probably be better off with an activity rule (see WWI 18 “Activities” and specifically 18.10 “Printing the name of something”, which is hopefully the right type of rule) , because you only want to change the way the name of that room is printed under very specific circumstances.

I know what it’s like to look at all this whirling complexity at first, but the good news is that it (nearly always) very much makes sense as a system, and it isn’t as hard as it seems once you start to get the hang of it. More importantly, it lets you work with the system instead of against it, which is what it takes to make use of its considerable power.

Get used to the idea that the Standard Rules are effectively part of the regular documentation, and don’t be afraid to open it up and look at them directly. The debugging verbs (WWI 24 “Testing and Debugging”) are very helpful for tracking the flow of execution, and the Index is extremely valuable to understanding how the program “thinks” about everything, so start poking around in that, too, at the earliest opportunity – though it doesn’t always make sense unless you’ve already read the corresponding parts of the primary documentation.

6 Likes

Thank you for the detailed breakdown of this. That makes a lot more sense.

It still feels odd though to just be able to drop that line anywhere in the code and Inform figures out that it will only take place during “carry out looking.” It’s flexible, but feels a little disorganized. I would almost rather have a “carry out looking” section where I have to insert code like that, just to make it explicit and keep everything that interacts with these rules in the same place. Or if there could be a tag on the code that would expand out to give these details without having to dig into the rules.

On the subject of the Standard Rules: is there anywhere within Inform that I can find them? I have searched and searched and never found it. The index just says “carry out rules are tied to specific actions, and there are too many to index here.” The only place I’ve been able to find them is here, by googling.

Here’s a good post about that (written to me rather than by me): Intercept parser errors

1 Like

To further what otistdog said: every rule has, right at the start, an automatic condition which checks if the rule should be run. Action rules use this to verify whether the correct action is in progress, for example. If you add a “when” clause to a rule, that gets added to the check. When you make a statement like the above, you are essentially just telling Inform to add an extra condition under which the rule shouldn’t be run.

The condition itself is only evaluated whenever the rule could theoretically be run, which in turn depends on which rulebook it’s in (as otistdog said), and also whether previous conditions in the same rule (such as if the action matches) already passed. You can see which rules are being tested at any given moment by running the RULES ALL command; the output of that is more useful if you’ve given your rules a name, though.

In a previous version of Inform 7, there was in fact a special rulebook dedicated to those sorts of things (the “procedural rules”), and that was the only way to manipulate the other rules. But having the compiler modify the conditions via assertions is typically a more natural way of expressing it (and has better performance), and the procedural rules have since been removed.

File -> Open Installed Extension -> Graham Nelson -> Standard Rules.

1 Like

Oh, sorry – I forgot that it might not be clear where the Standard Rules are, but mirality covered it.

As explained in WWI somewhere (I think), every project is compiled with the Standard Rules. They’re what erect the major infrastructure machinery of the default world model and built-in rules of every stripe. If you see a rule in the Index and you didn’t write it, it’s probably from the Standard Rules (otherwise, from some other extension that you’ve included). If you search for “room description rule” in the Standard Rules, you will find its definition there.

[Note that I’m not a real programmer, so I may be off on some of the terminology here. I’m sure I’ll be promptly corrected, if so.] I7 is mostly declarative and about rule definitions, and the ordering of rules in the source code often doesn’t matter. (Working within a given rule definition, it’s procedural and order-sensitive – closer to what you seem to be expecting.) As mirality explained, the compiler figures out where to place code for rules based on the rule’s preamble, which tell it specifically to which rulebook the rule belongs (e.g. carry out looking rules, every turn rules) and under what conditions it should be applied. The compiler also has a system for working out default rule ordering/priority within the rulebook (WWI 19.6 “Sorting and indexing of rules”) which you can override if you need to (WWI 19.4 “Listing rules explicitly”). You’ve already discovered that rules can be selectively disabled for some situations (“The X rule does nothing if/when…”), but that’s a rule-like declaration to the rules engine (again, see WWI 19.4), which, like rules in general, have a lot of freedom in their placement.

The potential disorganization issue can be tackled somewhat with the use of headings (WWI 2.5 “Headings” and WWI 2.6 “Why using headings is a good idea”), but that’s for your own organization. The Index does the job of putting the whole picture together and basically “putting tags on the code that explain everything”, so that should be good news.

I will say this: Reading all the way through the primary texts (like WWI) can seem like a daunting prospect, but it really pays off. Even skimming will give you an idea of what’s there and much of the big picture of how it all hangs together. Aaron Reed’s book (see the “List of Inform documentation” sticky post at the top of the forum) takes a hands-on approach to learning while putting together a whole story; the printed version is a bit out of date now but might be useful for a faster introduction, even if the online version hasn’t been updated (which it may have). I can’t speak to the books by Ron Newcomb or Jim Aikin, but others may chime in here.

2 Likes

Further to this part, for any action, have a look at Index -> Actions -> the action (or in some cases it’s easier to find it under Index -> Actions -> Commands). There you’ll see a lot of info about the action, including rules that are applicable to it, for example in part:

image

Note that this includes the custom modification to the rule’s condition (along with a link to quickly jump to it in your source). It will also include extra rules, and actions defined in the story itself or other extensions.

It doesn’t tell you precisely what the rule does (for that, you need to look at the source of the Standard Rules), but the rule name is reasonably descriptive to give you the basic idea, and it provides quick links to help you override the rule or to customise one or more of its default responses.

2 Likes

That’s actually the main reason that war was fought, if my memory of high school Modern History serves me correctly.

-Wade

2 Likes

Furthermore in response to this popular quote, your very post has revealed how your brain would like your code to be organised. So you can, as otistdog mentioned, use headings to make this apparent to yourself.

I find headings are really important as a project gets bigger, and you can have a lot of idiosyncratic fun using them.

My own headings fall into two major schools - those that clump material related to particular characters, locations or objects together, and others that gather all the material related to one action or mechanic together. There’s never a perfect division (I could put the looking rules related to Jimmy with Jimmy, or with the locations they affect, or in a n overall Looking section) so my decision is usually made based on whatever I anticipate will be most helpful for finding or understanding something again later. And every now and then I’ll polish the source up by moving things around between headings etc. to make the whole thing clearer.

-Wade

2 Likes