I spent a few hours last night trying to figure out why a particular check rule was behaving unexpectedly, and I eventually discovered that it comes down to the difference between “stop the action” and “rule fails”. (There is actually a question at the end of this, in case my explanation is old news.)
Working example
The smooping rules are a rulebook.
A smooping rule (this is the default smooping rule):
rule succeeds.
Smooping is an action applying to nothing.
To smoop is a verb.
Understand "smoop" as smooping.
Check an actor smooping (this is the smooping limitation rule):
follow the smooping rules;
[say "(smoop-checked [the actor])[line break]";]
if the actor is the player, say "[We] [can't] smoop!";
stop the action.
Report an actor smooping:
say "[The actor] [smoop]."
The Lab is a room.
Annie is a person in the Lab.
A persuasion rule for asking Annie to try doing something: persuasion succeeds.
Unsuccessful attempt by Annie smooping:
say "'I can't smoop,' says Annie."
In this example, we have a nonsense action that never succeeds (the report rule is there just to illustrate that it never happens). The check rule that prevents smooping calls a trivial rulebook and then stops the action. The puzzling part is that if you run this code and then smoop after turning on actions, it will list the action as successful. In particular, if you ask Annie to smoop, nothing gets printed.
If you replace stop the action
with rule fails
, the code works as intended.
I spent some time examining a more complicated version of this. After looking thorough the generated I6 code, I eventually discovered that Inform internally uses two methods to indicate whether a rule or rulebook succeeds or fails, and using stop the action
only affects one of them. If a check rule invokes some other rulebook, directly or indirectly, then stop the action
effectively picks up the result of that.
(This actually resolves another mystery for me. If you have a check rule that includes try other action instead
, the original action succeeds or fails based on the whether the other action succeeds or fails. This also works if you use try
without instead
and then do stop the action
later. Now I know why.)
But here is the part I haven’t figured out yet: If you uncomment the say
line in the check rule, then stop the action
works as expected (i.e., the action is considered a failure). This only seems to happen if the text being said includes bracketed expressions, but don’t know I6 well enough to dig any further.