When to use which action processing rules

Continuing the discussion from Typical Beginner's Mistakes in Parser Game Programming:

This might be an interesting question for other authors, so I made a separate thread:

Let’s think about the entering action. It’s a framework for entering things that applies to a wide variety of situations. Now, I could make a game with 30 enterable containers (or even not enterable containers, since instead doesn’t check that), but troubleshooting them individually gets hard after a while. I also can’t track them with things like

after entering something:
	increment the enter count;
	continue the action;

There can be a cost to opting out of built in behaviors, even if it seems that there is no practical difference.

Before rules are quite powerful, they can ignore accessibility rules. That is, they can apply to things that are visible but not touchable (items in closed transparent containers), objects (like directions). They can set values at the very beginning of a turn. They don’t have to stop anything, and they often don’t.

before doing something:
	unless clicking:
		now the pending action is "frob";

A lot of this stuff isn’t obvious at first. In a short game, INSTEAD can feel like everything we need. But we’re missing out on learning about the full capabilities of Inform, whether it’s choreographing the player’s turn or else managing the state of the world.

I haven’t said anything about the other turns; I don’t want to write a thesis! But you asked about them. I could come back later and update. I’d be interested to see what others say, though, this isn’t a comprehensive answer re: INSTEAD.

3 Likes

Here’s how I would summarize the I7 action-processing model:

  • The reading a command activity fetches a command from the keyboard.
  • The parser converts that command into an action. This is where something like EAT APLE will fail, but also where EAT APPLE will fail if the apple isn’t in the room: to the parser, both of those come down to “that isn’t an object in scope”.
  • Before rules are run. Since no other processing has happened yet, this is the best place to redirect one action to another, like opening a desk → opening the desk drawer.
  • Various rules check that the action is feasible: if the action requires light, is there enough light? If the action requires a touchable noun, can you touch the noun? These are sometimes called the accessibility rules, and this is where EAT APPLE will fail if the apple is in a glass case.
  • Instead rules are run. This is the best place for specific exceptions to the general rules of an action: you know that the action is broadly feasible, but no action-specific checks have happened.
  • Check rules are run. These are the rules that test whether a specific action is reasonable: you can’t eat something that’s not edible, or drop something you’re not holding. This is where EAT WRENCH will fail.
  • Carry out rules are run. These make the action happen in its standard, expected way: eating an apple removes it from play, dropping a wrench moves it to the floor.
  • After rules are run. These ones are a bit weird, because they fulfill two separate purposes: they’re used both to override the report rules (see below), and to implement the aftereffects of an action. The former has to stop the action, the latter has to not stop the action, so you have to be careful about sequencing them properly.
  • Report rules are run. These describe the action happening in its standard, expected way.

Or for a shorter summary:

  • Before to redirect one action to another
  • Instead for exceptional circumstances that shouldn’t be handled by the normal action-processing rules
  • After for exceptional circumstances that should be processed normally, but reported in some special way
  • Check, Carry out, and Report for the standard, default processing of an action
9 Likes

I defer to Draconis’s expertise, though I usually use INSTEAD for actions that stop and BEFORE for actions that continue. I wrote this on my blog maybe six months ago.

I’m still learning, though, and the post might be different today.

  • BEFORE: first to process. Can bypass checks for visibility and accessibility. Support for “big” rules that can cover multiple actions and such.
  • INSTEAD: Best used to redirect actions, prevent broad categories for action, or otherwise get in front of CHECK rules.
  • CHECK: Perform checks on specific actions and stop or redirect as needed.
  • CARRY OUT: Perform specific actions, print output, update world state as needed.
  • AFTER: Good for action follow ups (score systems, property changes). Alternately: a way to get in front of REPORT. Support for “big” rules accommodating multiple actions.
  • REPORT: Print output once actions are complete. Like CHECK and CARRY OUT, REPORT does not support “big” rules.
  • EVERY TURN: Rules that execute every turn, independent of player action. Best used for checking and updating world state.

E: it might be helpful to think of things in terms of wide and narrow:

  • BEFORE: widest
  • INSTEAD: wide
  • CHECK: narrow
  • CARRY OUT: narrowest
  • AFTER: wide
  • REPORT: narrow
1 Like

I found this nice table: Action Processing — Summary - I7 Handbook

Some examples, imagine a game where you can CAST [SPELLNAME]:

Before casting a spell:
     if playerclass is not "mage":
          say "You aren't the wizarding type, [playerclass]." instead.
          [ie don't even bother running these rules]

Instead of casting armageddon:
     end the story saying "The entirety of existence ends, as expected.";
     [note the BEFORE rule prevents this if the player is not a mage]

First before casting armageddon when playerclass is not "mage":
     if a random spellcaster is in the location:
          say "[Spellcaster] goes white as a sheet, "Don't even joke about that!".

Check casting supernova:
     if the location is enclosed:
          say "Ignoring the advice of your mentor, you cast Supernova inside the tight quarters of [the location]...there is a deafening KER-BLAOW but you are vaporized before you hear it.";
          end the story saying "That was an unusual strategy..."

First check casting supernova when Mentor Todd is in the location and the location is enclosed:
     say "Sensing what you are about to do, Mentor Todd claps his hand over your mouth. "Not...here..." he hisses in your ear.";
     stop the action.

Carry out casting electrozap:
     now the location is lit.

Report casting electrozap:
     say "The room lights up with sparks of harmless electricity."

After casting electrozap when the player is wet: 
     say "The room lights up with - OW THAT HURTS.";
     decrease HP by 1;
     evaluate the player's health.
[overrides Report rules by running first; After by default stops the action so the player won't see the Report rule, but the spell effects have already been carried out previously]

First report casting breeze when the location is stanky:
     say "You pinch your nose as the breezes rise..."
     [Report does not stop the action by default]

Last carry out casting breeze when the location is stanky and the number of living people in the location is not 0:
     [assuming "living people" is defined as not including the player]
     repeat with soul running through living people in the location:
          now soul is in the Flower Shop;
          now notifyfled is true.

Report casting breeze:
     say "Gentle breezes ruffle your hair and light loose objects around you."

Last report casting breeze when the location is stanky and nofifyfled is true:
     say "Anyone alive around you begins coughing and backing away due to the funk you've stirred up in the room, then bolts toward the Flower Shop.";
     now notifyfled is false.
4 Likes

I vibe with that chart! It lines up with my own interpretation. I use instead to stop things and before rules usually continue (though sometimes there is a need to preempt INSTEAD). I enjoy hearing about how people use these rules, as there’s a lot to learn from the experience of others.

EDIT: just to add some data, Marbles, D, and the Sinister Spotlight has 29 before rules, 293 instead rules, 214 carry out rules, and 19 after rules. It has around 57,000 words

This is a great thread… Thanks

Since this was prompted by the perennial discussion about how newcomers to Inform 7 tend to overuse Instead rules, I thought it might help to list some of the situations where (to my understanding) an Instead rule isn’t the best choice:

  • To prevent the usual interaction in a specific situation with a custom message (use a Check rule)
  • To prevent the usual interaction in a specific situation with a custom message, disregarding normal checks for reachability, visibility, etc (use a Before rule)
  • To have an interaction take place in the usual way but give a custom message (use a Report rule)
  • To have an interaction take place in a slightly different way to usual but still subject to all the usual checks (use a Carry Out rule)
  • To redirect all possible attempts at a particular action (use a Before rule)

But you might want to use one in these situations:

  • To have an interaction take place in a different way to usual, in a situation where the usual checks don’t matter, and where we explicitly state that the rule succeeds if we want “if we have petted the duck” type conditions to recognise the successful attempt in future
  • To redirect attempts at a particular action, but only if they would pass basic checks for reachability, visibility, etc.
  • To interrupt an action and have a “cut scene” play out instead, such that “if we have petted the duck” type conditions should not be considered true in the future

I haven’t written anything hugely substantial in Inform 7, so am I on the right track?

4 Likes

A good yardstick: If your Instead rule gets really tall requiring more than 3-5 lines of conditions to prevent breaking other rules and actions and is making huge alterations in the model world, you’re probably better off doing it another way.

Good:

Instead of entering the waterlogged canoe: say "Nope. Too dangerous."

Bad: (might work for a one off, but breaks parsing if the canoe is used multiple times)

Instead of entering the waterlogged canoe:
     if the player is in the canoe:
          say "You're already in the canoe.";
     if the location is River:
          say "You can't get more in the river than this unless you dive overboard.";
     if the player's sailing ability is greater than 5:
          if the player carries an oar:
               say "You got this!"
               now the player is in the canoe;
               now the canoe is in River;
               start the leak timer;
          otherwise:
               say "You'd be up the creek without a paddle. You need an oar.";
     otherwise:
          say "Your boatmanship is not up to snuff to handle this watercraft."
1 Like

Honestly, I don’t think overuse of Instead rules is as big of a problem as it’s sometimes made out to be. After reading a command rules are a much bigger issue, imo.

My rule of thumb is:

  • If it’s a general rule about how this action functions, without regard to specific game scenarios, use Check/Carry out/Report
  • If it’s a specific rule about a situation in your particular game, use Before/Instead/After
  • Use Before rules if the action shouldn’t be checked for feasibility first (e.g. if you’re redirecting one action to another, or you’re doing an implicit action first)
  • Use Instead rules if the action should be checked for general feasibility, but not for actual practicality (e.g. “instead of eating the rock” will require that the player can touch the rock, but not require that the rock be edible)
  • Use After rules if the action should be processed normally, but reported differently (e.g. you want to describe taking a treasure differently from taking a normal thing, but still check that it’s portable, and still move it to the player’s inventory)

In other words, most authors don’t need to write Check rules for the standard actions, only for new actions they’re implementing from scratch. I would only recommend doing it if you’re making a fundamental change to how the action works as a whole, for example:

Check going a nautical direction when the location is not nautical:
    say "Nautical directions only have meaning when you're on a ship." instead.

This is a fundamental change to how the going action works, so a Check rule is more appropriate than an Instead one.

1 Like

Is it bad to write: check eating the rock: say "You can't eat that!" instead instead of making an Instead rule? I’m reading all of these Instead usecases and I’ve realized that I’ve used check...instead for all of them.

1 Like

You can definitely get yourself in way more trouble with after reading a command rules, but I think in practice beginners are way more likely to trip themselves up with Instead rules, in part because of how the docs are organized; instead rules are in the first substantive section in the actions chapter, so go figure that they’re the thing people just getting a grip on Inform tend to overuse! Meanwhile, check/carry out/etc. are only discussed in detail in the advanced actions chapter (13, vs. 7 for basic actions), and reading a command I think is just mentioned in chapter 18 – if you’ve made it that far, you’re probably making 201-level mistakes :slight_smile:

Nah I think that’s pretty solid style.

3 Likes

As a matter of style, I prefer to keep Check for general rules for the action and Instead for specific situations for the game, but nothing will actually break if you cross the streams. That’s just my particular preference.

2 Likes

Yeah, to be clear, when I say I like something better, that’s all I’m saying. IMO any code that works well that the author can troubleshoot and read well is “good code.”

The issue I have with overuse of instead by beginners is the opportunity cost of delays to understanding action processing, inability to manage world state around actions, etc.

This thread split off from a thread about mistakes beginners make, so I’ve really just focused on helping people learn initially. Anyone who has a handle on action processing will settle on a personal style that works for them. (I hardly ever use check personally but that’s not because it’s bad)

3 Likes

My style is like this, and extremely check-heavy in general. And my WIP is approaching half a million words and travelling solidly.

If I ask myself why I’m so check heavy, it started out that I never liked the carry out / report / after nexus somehow, at least for irregular actions. I often felt I was restating conditions across multiple rules. So instead I’d hit all the conditions and the outcomes in one check rule so they were attached to each other. I think now (a decade+ later!) I understand things better and would be less phased by the initial situation.

There was also a period where I and others were scared of having too many Befores and Insteads and Afters for lag-avoiding reasons, because those are all consulted every move whereas the other books aren’t. But if it ever was a potential concern, Inform evolved and it no longer was. Still, I thought I might be writing the longest Inform game ever, so I had to think about things like that before I found out it was a problem too late.

-Wade

3 Likes

Trying to summarise what I understand of that which has been said so far:

  • Referring to a thing that is not in scope is a parser failure, not an accessibility failure.
  • Accessibility rules run between before and instead, and this is what makes those two rulebooks different, even if the before rule is given a stop the action.
  • Since accessibility checks happen after before rules, we can redirect a inadmissible action to an admissible action with a before rule, but not with an instead rule.

Combined with the idea that check/carry out/report is used only for standard, generic behaviour, and before/instead/after is used for special cases, that paints a fairly clear picture of when to use each sort of rule.

That said, there seems to be some active debate around this last division between generic behaviour and special cases. There are no strong arguments in favour of either side, that I can find, and it seems like personal preference dominates. For example, HanonO’s spellcasting example violates that principle in multiple locations:

  • The only a wizarding type can cast spells rule is in the before rulebook, rather than check. Are we expecting that some accessibility rule will give a misleading response to non-wizarding types?
  • The cannot the armageddon ends the game rule is not listed in the carry out rulebook, unlike electrozap. With the supernova spell, the game-ending action is in check instead, which also seems inconsistent.
  • The Mentor Todd special case is a check rule rather than an instead rule. I was under the impression that such special cases would be the domain of instead.

This debate ties in to Hidnook’s question about a rock eating failure rule: this is not part of the normal eating behaviour, so according to the division of rules it should be an instead rule, but if one does not believe in the division of rules, a check rule works just as well.

Though as Drew Cook clarifies: the overuse of instead rules has more to do with failing to manually implement normal check and carry out behaviour. Whereas the proper rule might be

After taking the apple:
    now the player is cursed;
    say "As you pick it up, you notice an unnatural sheen on its skin."

a beginner might be inclined to write

Instead of taking the apple:
    now the player is cursed;
    now the player is carrying the apple;
    say "As you pick it up, you notice an unnatural sheen on its skin."

which can yield a transcript like


>get apple
As you pick it up, you notice an unnatural sheen on its skin.

>i
You are carrying:
  an apple

>get apple
As you pick it up, you notice an unnatural sheen on its skin.

instead of what we get with the after rule, which is the intended


>get apple
As you pick it up, you notice an unnatural sheen on its skin.

>get apple
You already have that.

Being a beginner myself, I still make this mistake a lot!

5 Likes

Instead of [action]: [do something else] is theoretically equivalent to Check [action]: [do something else] instead. but the check rule is less open-ended than instead.

INSTEAD rules by design cause the parser to relinquish control and let the author ignore most of the world-model rules and parsing (except for stuff like scope/reachability) for the duration.

CHECK is notating a potentially closed road on the bus route for the driver; INSTEAD is grabbing the wheel and saying “lemme navigate us around this construction despite you having all the bus-driving expertise…[tires squeal]”

Right, which is basically what I’m saying: Check rules are rules about how the action works in general, Instead rules override the general ones for specific situations in the game. Check rules say you can’t eat something that’s inedible; Instead rules say that if you eat the magic beans you die horribly.

1 Like

Given all of this… I’d like opinions on the best way to open a “shade”… I currently did it the newbie way of “instead of opening” and then I describe the view out of the window since it’s just a scenery item. (similar instead for closing) It’s just a scenery item, so it doesn’t need to actually “open” and “close”… This seems to work fine. Perhaps players could find a way that this does not work well… Opinions on the best “shade” approach for a window with a view? (but no entrance/exit, eg: it’s not a door)

While I think I get it, does an instead rule grab the wheel more than a check rule with an instead qualifier at the end? I don’t feel that it does.

Unless we are talking about potential reach/scope (the wide/narrow distinction I made above)! Instead can do things like

instead of doing something other than examining or taking to the apple:

Which check cannot. So while check can be general about nouns, it cannot be equally general about actions. So I often think about these things in terms of their reach.

2 Likes