A easy (and hacky) way to detect the failure of such actions (same fore SAVE and RESTORE), is to hook on the failure response.
Transcript failed is initially false.
After issuing the response text of the switch the story transcript on rule response (C):
now transcript failed is true.
If you really want to modify the I6 template instead, I know it’s possible to run a rule or an activity instead of showing the response. You’d have to change the line marked with ! failure case.
Failing to start a transcript is an activity.
[In the Inform 6 template.
(Beginning of the routine cut for brevity.)]
[ SWITCH_TRANSCRIPT_ON_R; ! Glulx version
CarryOutActivity( (+ Failing to start a transcript +) ); ! failure case
(Z-code version left as an exercise to the reader. )
I haven’t tested it right now, it’s based on an old extension I wrote, which worked at the time I wrote it.
In I7’s default model, an action “succeeds” if it gets to the carry out stage, regardless of what happens during carry out, after, and report. So in that model, there’s no way for e.g. the player hitting “cancel” in the save dialogue to cause the action to fail: if it’s calling the @save opcode at all, it’s already succeeded.
The simplest solution I can think of is to have a global flag that tracks success and failure for all these things that the interpreter handles (transcripting, saving, restoring, etc). But most of the time what you’ll want to do with that value is print a custom message—and that can be handled already within the Response system.
(As a side note, the one place the “success” or “failure” of an action actually matters iirc is for the “unsuccessful attempt” rulebook, which is called when you tell an NPC to do something and the action fails (never reaches the carry out stage). And that’s not relevant for out-of-world actions, since NPCs can’t attempt those anyway.)
Some precisions on what Draconis said (if I’m not mistaken), even if a bit off-topic.
That’s what is officially told by the documentation, but I think all that matters is that one of the action rulebooks succeeds? If I recall correctly, making an Instead rule succeed will mark the action as successful.
It also matters if we are testing an action in the past, e.g. if we have taken the lamp. If an instead rule intercepted the taking the lamp action, the condition will be false.
(That’s why it can be useful to make an Instead rule succeed. If we use an instead rule only to print a special message, but the action can be considered to have succeeded “in-world”, you can make the Instead rule succeed. Or you can never use a condition in the past because it’s confusing and bugs will be created.)
For actions that have no standard Carry Out rules at all, maybe. But even there, I tend to prefer making it go through the “normal” action flow. And I unequivocally favour doing this for actions that do have a standard Carry Out even though they’re blocked by default (such as giving it to).
The block burning rule does nothing when the noun is the paper.
Carry out burning: now the noun is nowhere.
Report burning: say "You burn [the noun]."
Now if you want to define a second object that can be burned, all it takes is to repeat just the first line with the new object. And you can define extra After rules for special effects or messages (if burning a pile of leaves reveals something underneath, for example).
@Natrium729, thank you for this! I had tried to set up something similar with an after rule for the action itself, but after rules for out of world actions are disallowed in 6M62. Very clever to use the response activity rules.
I was really hoping for something that would allow forcing genuine failure of the action (for the purposes of keeping coherence with built-in action success tracking), but this is a useful workaround.
Also, I’ve observed the same as you with respect to being able to force success/failure by calling rule succeeds or rule fails at non-standard points in the action processing rules. (Not a bug, in my book.) Like you, I sometimes find it useful for keeping the built-in action success/failure tracking consistent. (Though I generally adhere to the style that @mirality espouses.)
In this case, even trying to modify the failure point with an I6-level RulebookSucceeds(); calls didn’t work. (Perhaps I didn’t do use that routine right; I didn’t trace things very far.)