Insteads are Generally Bad Practice

[Edit: This opinion is mostly off-base in a general sense, but I’ll leave it here as a point-of-interest for those using the Modified Timekeeping extension; this thread is only accurate/specifically applicable in those circumstances]

In my opinion, there is a large problem with the way Instead statements are often portrayed in the documentation, as well as a large amount of the example code offered.

Insteads don’t take a turn. Carry out does. This isn’t very clear unless you’re well-versed in Inform, and there is a lot of Instead “abuse” which seemingly works fine unless you have a story which depends on turn timing. I think it should be highlighted more often that Insteads are powerful, yet “dangerous” because they are so easy to misuse. It is very easy to use them in the wrong context and get the right result, yet behind the scenes things aren’t operating as they should.

Examples? Here’s something someone might suggest using an Instead for, and (in my opinion) it is improper coding.

Instead of eating the apple: say "[The noun] is simply delicious. Its juices run down [our] chin with every bite."; now the apple is off-stage.

Does that work to provide flavor (no pun intended) text to eating a specific item? Yep. Does it seem to work perfectly in this circumstance? Yep. Does it work properly insofar as actions are designed to be implemented. Nope.

If you’re trying to do something like this, then it would be more proper to do something like:

[code]A fruit is a kind of thing.
An apple is a fruit. A pear is a fruit.

Carry out eating a fruit:
now the noun is off-stage.
Report eating a fruit:
“[The noun] is simply delicious. Its juices run down [our] chin with every bite.”[/code]

Forgive me if my examples aren’t coded 100% correctly, but you get the idea.

The Instead is an ungraceful kludge that kind of works, but breaks a turn-based game. The second implementation is actually how you should do it, if you want to do it properly. Using Insteads instead of Carry Out/Report has little or nothing to do with generalities versus one-offs and exceptions, and everything to do with what you’re really trying to accomplish, regardless of what the documentation or other people may teach. I feel like people just say to use Insteads because they are convenient in cases like this, but I think that’s setting people up for failure.

A proper use of Instead would be something like:

Instead of going nowhere when location is Thick Jungle: say "[We] have no inclination to bushwhack [our] way through the entire jungle."

That’s the negation of an action (which doesn’t take a turn because it shouldn’t be followed through with, period) and works similarly to a parser error, so Instead is okay to use here.

I don’t mean this to sound like arrogant soap-boxing, and I’m sure this isn’t any revelation to any of the regulars here but it’s something I think is glossed over and the subtleties are lost to anyone that hasn’t spent a significant amount of time coding Inform.

Am I right? If anyone thinks I’m off-base with this opinion, please do let me know; my understanding of Inform is constantly evolving.

Insteads can be suboptimal compared to dividing things up nicely into check/carry out/report rules, but they do take up turns. What code is giving you a bug in a turn-based game?

Are you using Modified Timekeeping? That extension modifies things so that “failed” actions (including ones blocked by Instead) don’t take up turns.

Yes.

I guess that changes the whole worldview, doesn’t it?

Not to worry, there’s a simple fix. Just add “take full time” to those rules if you want them to count as a turn. That’ll ensure the clock advances as normal. (Glad to see the extension in use by the way!)

I think it’s so essential that I (clearly) forgot it wasn’t native Inform behavior. I don’t understand why anyone would work without it.

I’m not quite following this. In reading the comments for the extension, it says something about that not applying to Instead, Before, etc. so how would you implement that without resorting to the approach I initially discussed about Carry Out?

Oops. I need to experiment with that, but I believe it was an error on my part when writing the documentation. It should apply to an Instead rule so long as that rule stops the action (which Instead rules usually do).

What’s the syntax for how it’s intended to work?

I.E. Instead of throwing the golden apple at the oak tree (take full time):

Tested and it works in Instead rules. I’ll change the documentation.

Just add it as a separate line in the rule, like this.

Instead of throwing the apple at the tree:
    say "You throw the apple, and magic happens!";
    move the apple to the tree;
    take full time.

Ahhhh… that’s terrific.

That will help me a great deal.

Actually, I don’t think it does. There are other good reasons to avoid lazy use of Instead rules like:

  1. Cutting off action processing with an Instead rule puts the burden on that rule to make necessary logic tests and world-state changes that would otherwise be handled more reliably by other rules or rulebooks. In your throwing-the-apple scenario, for example, any “Check throwing…” rules won’t even be consulted, which means the world-changing parts of the action will occur even though something would normally interfere (e.g. “Check throwing when the player wears the blindfold” which stops the throwing action). This kind of pitfall is a common way for beginners to create bugs in their code, or to write functional but really messy code.

  2. There is only one Instead rulebook; in a large game you can end up with a huge number of rules there. Check rules are attached to a specific action, so irrelevant ones are more easily ignored in the index.

  3. By default, using an Instead rule that prints text will cause the action to register as a failure. This makes it harder to use I7’s built-in action tracking (with conditions like “if we have…”) because the action intercepted by the Instead rule registers as having failed. Your particular example of throwing the apple at the oak tree wouldn’t work anyway because action tracking can’t track two-noun commands, but you get the idea. [edit: Oops, sorry, that was Draconis’s example. Your original eating-the-apple example is more applicable to this point.]

  4. Only check rules can return a reason indicating why an action failed, so Instead rules can’t be used in conditions that make use of “the reason the action failed.”

That said, there are many situations where none of the above really matters, and a quickie instead rule gets the job done in a way that looks no different to the player (and is a lot less work).

I sometimes use “Instead of…: instead try…” to convert one action to another action. For example, in HL I had something (similar to):

Instead of putting the player on a supporter (this is the put-me is entering rule):
	instead try entering the second noun.

This catches commands like PUT ME ON BED (not a likely player phrasing, but somebody might try it) and has higher priority than my (very large) list of “Check putting X on Y” rules.

You don’t have to do stuff this way. It’s the style I’m used to.

Yes, but I got the impression that Rasputin’s main complaint was that Insteads are a crude and frequently misused tool because “behind the scenes things aren’t operating as they should,” i.e. “as actions are designed to be implemented.” To me, that narrowed the category to “Insteads that try to do something in the model world,” though I guess I should have made that clearer. (And, in light of his edit, that may not have been the kind of “bad practice” to which he was pointing.)

Your example is very much in keeping with the spirit of proper use of action processing rules, I would think – a reroute instead of a short circuit.

I was using that technique for some time, but “Before , try instead” seems to work a lot better. I was running into the Instead being preempted by other Insteads related to , which doesn’t make sense because ultimately we’re aiming for a direct action substitution (as if the player had actually typed at the parser) that has logically nothing at all to do with .

It seems to me that action substitutions should be one of the very first things to happen after a command has been entered.

As a non-sequitur, this is by far the best forum I’ve ever been a part of. Lots of knowledge, lots of help, super-quick replies, and high signal to noise. Pretty much everything you could ask for.

Thank you all for the continued responses.

That was my main complaint, although like I said in my edit, some of the particulars of my gripes don’t really apply unless you’re using Modified Timekeeping. But you’ve put your finger on far more proper examples where not actually implementing actions (like the standard library does) creates issues.

I guess another example where Insteads are bad practice is when they apply to actions that NPCs follow. If you’re in the habit of using them then you’ll expect something like,

[code]Forest is a room.
A man called Burt is in Forest.
an apple is a thing in Forest.

Persuasion rule for asking Burt to try doing something:
persuasion succeeds.

Instead of Burt eating the apple:
say “He bites into the apple, and then throws away the core.”;
now apple is off-stage.[/code]

to come out properly, but really it will run the Instead but still result in failure for Burt.

Is the “instead” before “try” necessary? I thought those inline “instead” meant “end the rule in failure,” and that that isn’t necessary in Instead rules because the rulebook has default failure anyway.

I think the underlying issue here is that most of the time, what you do in Inform will proceed happily whether or not your action succeeded or failed. Text will print, world state will change, and so on; as long as you avoid the “check” issue that Otis mentioned, and you’re not using slightly more esoteric stuff like “if we have…” or “reason the action failed” or things that depend on rule success, then you’ll be OK. But if you start using that kind of stuff, you have to be very very careful.

(Also, in the “eating the apple” case, the Standard Rules for eating something already have a Carry out eating rule that removes the noun from play! So all you have to do is change the printed message with an After or Report rule.)

For trying an action, instead basically means “abide by whatever rules apply to this action,” I think. See the result of the instead rule in output from this example:

[code]“Example” by Otis

Icy Meadow is a room. A fixed in place container called an oak tree is in Icy Meadow. “The kite-eating tree is here, looking dangerously thin this late in the winter.”

Check inserting something into the oak tree (this is the can’t reach branches rule):
say “It’s a tall tree; you can’t reach the branches unaided.”;
rule fails.

The player carries a stick. The player carries an enterable supporter called a stepladder. Understand “ladder” as the stepladder. The player carries a burning torch. The player carries an edible thing called an apple.

Check inserting the burning torch into the oak tree (this is the don’t burn tree rule):
say “I don’t think so. Trees are flammable, you know.”;
rule fails.

Instead of eating something (this is the better the tree eats it rule):
say “You decide the tree needs it more than you do.”;
try inserting the noun into the oak tree instead.

The can’t reach branches rule does nothing when the player is supported by the stepladder.

Every turn when something (called the snack) is in the oak tree (this is the tree eats things in it rule):
try the oak tree eating the snack.

Check the oak tree eating something not edible (called the tidbit) (this is the trees can’t eat inedible things rule):
say “The tree gnaws on [the tidbit], but [they’re] too tough to eat.”;
rule fails.

Check an actor eating (this is the revised can’t eat portable food without carrying it rule):
if the actor is not a person:
continue the action;
if the noun is portable and the actor is not carrying the noun:
carry out the implicitly taking activity with the noun;
if the actor is not carrying the noun, stop the action.

The revised can’t eat portable food without carrying it rule is listed instead of the can’t eat portable food without carrying it rule in the check eating rulebook.

After the oak tree eating something (called the snack) (this is the trees can eat edible things rule):
say “The tree gratefully chomps down [the snack].”

test me with “put stick in tree / put torch in tree / actions / eat apple / actions off / drop stepladder / stand on it / put stick in tree / put torch in tree / actions / eat apple”[/code]

No, but it’s easier to always write “instead try fooing” than to remember when the “instead” is optional. (I use this sort of action redirection in both Instead and Check rules.)

Yes. I long ago made the executive decision to never rely on the action success result.