Understanding understand and instead

I’m trying to prevent my player from removing an item of clothing. I’ve written this:

The player wears a coat. The description of the coat is "Your heavy winter coat is necessary because 
it's extremely cold outside. The coat is a navy blue, is fluffy with insulation, and has a fur-lined hood." 

Removing is an action applying to one visible thing being worn. Understand "remove [something]" 
as removing. 

Instead of removing a coat: 
	say "It's very cold outside. You wouldn't last long without your heavy, insulating coat."

but this is my result:

>i
You are carrying:
  a coat (being worn)

>remove coat
You take off the coat.

Why isn’t it working?

“Remove” is already a synonym for the built-in taking off action. You shouldn’t need to define it. To troubleshoot this, you can type ACTIONS in the IDE and it will explain the exact actions the parser is attempting.

>actions
Actions listing on.

>remove coat
[taking off the coat]
You take off the coat.
[taking off the coat - succeeded]

So all you really need to do is block the taking off action.

Instead of taking off a coat: say "It's very cold outside. You wouldn't last long without your heavy, insulating coat."

Or even better:

Check taking off a coat:
	if the player is outdoors: [as defined by your code]
		say "It's very cold outside. You wouldn't last long without your heavy, insulating coat." instead.

The check rule allows more flexibility since it’s follows the parser’s natural order of things and you won’t have to if-else your INSTEAD rule extensively if other factors are in play.

3 Likes

I tried it without defining it but it didn’t work. I’ll change it to taking off and see what happens.

edit: Yay that worked!

The longer I use I7, the less I rely on Instead rules and the more I use Check rules. Instead can have unforseen consequences if you’re not very careful.

3 Likes

Hmm. I looked at check and it lets the player still remove the coat. It does a message and then carries out the rule.

Make sure you’re including the word INSTEAD within the rule:

Check taking off a coat (this is the too-cold rule):
say “It’s very cold outside. You wouldn’t last long without your heavy, insulating coat.” instead.

The instead is what stops the action and doesn’t let it proceed.

actions
Actions listing on.

take off coat
[taking off the coat]
It’s very cold outside. You wouldn’t last long without your heavy, insulating coat.
[taking off the coat - failed the too-cold rule]

1 Like

Oh that worked.

Why should I use a check structure instead of instead?

What you were doing was probably fine, but I got a little sidetracked since you were trying to redefine an action that already existed. (This is my usual “Heed my advice, young’ins!” speech to new Inform authors.)

INSTEAD is a different type of rulebook in that it bypasses all normal parsing and only does only exactly what you write in the rule. It’s handy if you just want to redirect or forbid certain actions, (Instead of taking off the coat: say "It's too cold." is a perfectly legitimate use of it) but when you start writing more complicated actions of your own in a bigger game, things will go wrong and you’ll end up packing conditions into the rule that are better handled in the normal parsing process using BEFORE, CHECK, CARRY OUT, AFTER and REPORT.

Consider a rule that says "Instead of examining the large book: say "You decipher pages and pages of text."

Simple enough, but you just printed a message that doesn’t take into account any of the current state of the game world. What if the book and the player are in a dark room? What if the book is inside of a glass box where the player could not logically turn the pages as you described? What if the book is being carried by the evil wizard? What if the player is trying to read the book underwater? You could write more logic into the Instead rule, but at that point, you’re not letting the parser do what it’s supposed to do.

Also, if you wrap action processes into exclusive INSTEAD rules, those conditions don’t have a chance to be considered by other actions, and you’ll end up doing more work than you have to. It might seem more daunting to learn rulebook structure instead of using the big hammer of Instead, but when you start modeling systems that work together, you’ll have a lot easier time putting logic into the correct rulebooks.

6 Likes

Another pitfall with “Instead” rules is this:

Instead of taking off a coat:
	if the location is outdoors:
		say "It's too cold."
Instead of taking off a coat when the location is outdoors:
	say "It's too cold."

These superficially look the same, but the first one is going to cut off taking the coat every time (and won’t print a message if the location is not indoors)! It starts processing when it realizes that the action is “taking off the coat,” and then when the “if” doesn’t fire it… just stops, the way Instead rules do (if you don’t tell them to “continue the action”). The second rule only fires when taking the coat off in an outdoors location, so it is much more benign.

Check rules won’t have that problem, as long as you put “instead” in the line that prints the refusal message. If a check rule fires and doesn’t explicitly tell the action to stop (with “instead” or “stop the action”), the action keeps processing.

7 Likes

Something that seems minor, but I always feel the need to point out: Check/Carry out/Report should be used for systematic changes to the simulation (in fact, they’re really designed for defining new verbs), and Before/Instead/After for unique and exceptional behavior and nonce things. If there are a lot of different coats in the game, Check might fit, but most likely in this case Before would be safer.

Part of this is to make sure your code plays well with others’, as in collaborations or when you’re authoring an extension; it also makes it easier to read the index, because all Before/Instead/After rules are crammed into a single rulebook for each rather than broken out by verb. But even if you’re coding only for yourself and you don’t care about the legibility of the index, it’s still good practice to keep with the structure used by the Standard Rules, because it can have unintended side effects. For instance, some built-in rules depend on whether an action “succeeds” or “fails”—e.g. Instead rules fail, Before rules specify no outcome, and After rules succeed (unless you specify otherwise)—so if you’re not doing things the way the engine expects you to, it can cause issues behind the scenes.

2 Likes

I think you explained it better than I did. I never thought of categorizing Check/Carry out/Report and Before/Instead/After as groups like that, but it makes a whole lot of sense.

I always think of the main rulebooks like this:

Before - The player tries an action and you want to check something or alter the game state or try another action first regardless of what happens with the main action.

  • Before opening the creaky security door which leads to a room filled with nerve gas, check if the player has a gas mask and have them put it on implicitly before proceeding. The door may be locked, but the player doesn’t know this yet, so putting on the mask can run and succeed or not on its own without interfering with the typed command.
  • Before opening the creaky security door, check whether there is a guard is watching the player through the one-way glass. If so, you’re going to send the guard toward the player, but then the door opening action will check and proceed as normal. Whether the player gets the door open or not, that guard is on his way.

Check - The player tries an action. There are many existing checks that Inform takes care of such as Is there enough light? Can the player actually reach this thing? Is the door locked? Any check can fail and stop the action. These are the types of supplementary checks that won’t happen if you used an Instead rule to handle all the different situational elements involved in opening this door.

  • Check whether any guard is close enough to the location to interrupt the player opening the door.

Carry Out - All the checks have passed, the action is going to occur. Here is where the world-state changes.

  • Carry out opening the door: If the door hasn’t been oiled, send any guard in the vicinity who can hear toward the player.
  • Carry out opening the door: If the player didn’t shut off the gas valve, now move the deadly nerve gas backdrop to this room as well.

After - The action has occurred. These rules might trigger a special reaction different from the default report messages. After rules normally stop the action so Report won’t occur unless the author specifies to continue the action.

  • After opening the door, if the player hasn’t disabled the security system, sound an alarm and alert all the guards. If one of the guards is close enough, start a fight scene - unless he’s not wearing a gas mask in which case remove the guard and add a corpse to the room. Send all the other guards running for their own gas masks.
  • After opening the door: If the player doesn’t have the gas mask on, end the game in death.

Report - Where the normal outcome of the action is communicated to the player. Multiple report rules can fire.

  • Report if the door creaks based on whether it’s been oiled or not.
  • Report to the player that deadly nerve gas billows out from the next room if they didn’t shut it off earlier and they aren’t dead because they’re wearing the gas mask.
  • The standard “You open the security door.” default response will occur whether the special report rules do or not (unless the author overrides it by making one the special report rules stop the action, or by an After rule which prevents Report from running since the fight with the guards or deadly neurotoxin takes precedence over the door opening.)
7 Likes

Thank you for this really useful explanation.