I think I figured out another reason I decided ‘I just don’t understand carry out’: as far as I can tell, there’s no way to stop the action from a carry out?
As far as I’ve been able to piece together, most rulebooks let you say things and do things, and then decide whether to let any other rulebook continue saying and doing things. That’s true for Before, Instead, Check, After, and Report.
But not ‘Carry Out’! Once you’re in a ‘carry out’ rule, Inform will proceed to ‘after’ and ‘report’, regardless of what the carry out routine returns:
Testing is a room.
Large hole is an open enterable container in Testing.
Before entering large hole:
say "You're thinking about crawling into the hole.";
continue the action;
Instead of entering large hole:
say "You decide to crawl into the hole.";
continue the action;
Check entering large hole:
say "You are about to crawl into the hole.";
continue the action;
Carry out entering large hole:
say "You are now crawling into the hole.";
continue the action;
After entering large hole:
say "You just crawled into the hole.";
continue the action;
Report entering large hole:
say "Yup, we crawled into the hole.";
continue the action;
If you change almost any of those ‘continue the action’ to ‘stop the action’, it’ll print out that last statement then stop. But not for carry out: it doesn’t matter whether you put ‘continue’ or ‘stop’; it just keeps on going.
The upshot is that I have to think about ‘carry out’ much differently than I think about literally any other rulebook: to do it ‘right’, I have to never ‘say’ anything, and instead put all the ‘say’ rules into the ‘report’. This became particularly confusing when I wanted to move the player during a ‘carry out’, because moving the player, by default, will print the room description! So now I have to move the player without looking in the carry out, then do the ‘say’ I want and ‘try looking’ in the report. Or say everything from the Carry Out, and add a no-op Report that stops the action.
Is that correct? Is the right way to think about it that ‘carry out’ and ‘report’ rules are inextricably combined?
That is indeed correct! Here’s the section of the Standard Rules that enforces this behavior.
A specific action-processing rule (this is the check stage rule):
anonymously abide by the specific check rulebook.
A specific action-processing rule (this is the carry out stage rule):
follow the specific carry out rulebook.
A specific action-processing rule (this is the after stage rule):
if action in world is true:
abide by the after rules.
A specific action-processing rule (this is the report stage rule):
if within the player's sight is true and action keeping silent is false,
follow the specific report rulebook;
Once an action gets past the Instead stage, the “specific action-processing” rulebook is called. There are a handful of other rules in this rulebook, but the relevant ones:
Anonymously abide by the “check” rulebook. “Abide” means “if one of those rules makes a decision, then this rule makes the same decision”, and “anonymously” means “if one of those rules makes a decision, record that rule as the source of the decision, not this one”.
Follow the “carry out” rulebook. Unlike “abide by”, “follow” doesn’t care about the result. It just throws it away. All that matters is that the rules run.
If this action is not out-of-world, abide by the “after” rulebook. Since we’re abiding rather than following, we again give these rules the opportunity to end the whole sequence if they want. But we don’t abide anonymously, because once we reach the carry out stage, we no longer care which rule exactly made the whole process crash.
If the player can perceive the action, follow the “report” rulebook. Once again we’re following, not abiding; since this is the end of the specific action-processing rules, it doesn’t matter whether we stop the action or not.
Inform’s default understanding is that any action that reaches the carry out stage has succeeded, and therefore there’s no point in stopping it. The only reason the after stage can stop the action is because one of after’s purposes (inherited from I6) is to cut off report.
Special behavior in a specific instance (so “carry out” is not a good fit)
Which only happens once the action is known to be possible (so “instead” is not a good fit)
?
Well, this is the normal Inform-y way to do it.
Unusual behavior is a rulebook.
The unusual behavior rulebook has default failure.
This is the unusual behavior stage rule:
anonymously abide by the unusual behavior rulebook.
The unusual behavior stage rule is listed before the carry out stage rule in the specific action-processing rulebook.
Unusual behavior of opening the box:
say "At this point, we know the box is reachable, unlocked,
and so on, but it hasn't yet been opened. And since this
rulebook has default failure, the carry out rules won't run.".
When you want to mess with the standard read-parse-execute loop in Inform, adding new rules to the existing rulebooks is usually the way to do it!
The easiest way to use Report is only for default outcomes of successful actions, because it is tied to Carry Out.
As soon as I want a unique message with my action, I use an After (it can run unique code, and whatever you say there replaces the default Report) or I handle the whole thing at the Check stage. I don’t bother dancing around trying to shut down the default report so there can be a special report rule, which I’d then have to write, and which may have to restate the conditions which lead to its printing.
This is why I really like the Check Slam Dunk. I know the action’s possible. I’ve tested the conditions for it and I dont have to restate them in any other rule(s). Now I just print everything I want to print, run all the code and set all the flags and stuff I want to set, then say ‘rule succeeds’ and that’s the end of it.
The most obvious con is that you don’t benefit from default stuff which would happen at Carry Out. So if the action involves dropping something, you’ll need to put the object in the room, etc. Two processes are common enough I have stubs for them - ‘complete the examination of the noun’ and ‘complete the taking of the noun’. I’m still happier doing things this way than via the multi-rulebook alternatives.
There’s a still a time for doing things in other ways, but this is sort of my base style. NPC actions depend more on Report rules if you’re handling NPCs in the most Informy way, in which case my style is less compatible.
I’m unfamiliar with ‘Check Slam Dunk’ and can’t seem to find other references to it. Do you mean using ‘last check’?
Using ‘After’ seems to match the sort of thing I’m looking for: a single place to do stuff and say stuff, where I can stop the standard parser from saying things. Thank you both! This has been quite helpful.
My method where I resolve the entire outcome of the action in one Check rule, doing and printing everything that needs to be done and printed, I christened – in that particular moment in my post – the Check Slam Dunk. Because after I do it, I don’t need to do anything else.