Is there any way to get the name of the rule that decided the outcome of an object based rulebook? Basically, the same as the “reason the action failed”, but without an action involved.
I only wanted it for an out-of-world debugging action, so it’s not the end of the world if the answer is “no”, but…
This code creates a reason the rule stopped phrase, which returns the most recent rule to have either succeeded or failed. It’s probably good enough for use in debugging, but the whole enterprise is kind of fraught.
lab is a room.
oblong is an object based rulebook
oblong lab (this is the labial rule): say "Good job."; rule succeeds.
oblong yourself (this is the hyperspheroid rule): say "Why can't you be more like your brother?"; rule fails.
when play begins:
follow the oblong rules for lab;
if rule failed, say reason the rule stopped;
follow the oblong rules for yourself;
if rule failed, say reason the rule stopped;
To decide what rule is the reason the/-- rule stopped: (- latest_rule_result-->3 -).
Include (-
Array latest_rule_result --> 4;
-) replacing "latest_rule_result".
Include (-
[ FollowRulebook rulebook parameter no_paragraph_skips
rv ss spv;
ss = self;
if ((Protect_I7_Arrays-->0 ~= 16339) || (Protect_I7_Arrays-->1 ~= 12345)) {
print "^^*** Fatal programming error: I7 arrays corrupted ***^^";
@quit;
}
if (parameter) { self = parameter; parameter_object = parameter; }
spv = parameter_value; parameter_value = parameter;
! we won't need parameter again, so can reuse it
parameter = debugging_rules;
if (debugging_rules) {
DebugRulebooks(rulebook, parameter);
process_rulebook_count = process_rulebook_count + debugging_rules;
}
if ((rulebook >= 0) && (rulebook < NUMBER_RULEBOOKS_CREATED)) {
rv = rulebooks_array-->rulebook;
if (rv ~= EMPTY_RULEBOOK) {
if (rulebook ~= ACTION_PROCESSING_RB) MStack_CreateRBVars(rulebook);
if (say__p) RulebookParBreak(no_paragraph_skips);
rv = rv(no_paragraph_skips);
if (rulebook ~= ACTION_PROCESSING_RB) MStack_DestroyRBVars(rulebook);
} else {
rv = 0;
}
} else {
if (say__p) RulebookParBreak(no_paragraph_skips);
rv = rulebook();
if (rv == 2) rv = reason_the_action_failed;
else if (rv) rv = rulebook;
}
if (rv) {
latest_rule_result-->3 = rv;
if (debugging_rules) {
process_rulebook_count = process_rulebook_count - debugging_rules;
if (process_rulebook_count < 0) process_rulebook_count = 0;
spaces(2*process_rulebook_count);
if (latest_rule_result-->0 == RS_SUCCEEDS) print "[stopped: success]^";
if (latest_rule_result-->0 == RS_FAILS) print "[stopped: fail]^";
}
} else {
if (debugging_rules)
process_rulebook_count = process_rulebook_count - debugging_rules;
latest_rule_result-->0 = RS_NEITHER;
}
debugging_rules = parameter;
self = ss; parameter_value = spv;
return rv;
];
-) replacing "FollowRulebook";
[edited: oops. I had working code that I broke before I posted. revising.]
[ok, now it should work.]
Hmm. Zed’s approach is cool, but it feels a bit excessive to replace FollowRulebook solely for a debugging feature.
That doesn’t really work well, as the intent is to have a command I type in that runs the rulebook on a bunch of objects and summarizes the results.
I think I’m gonna go with something a bit similar to that though – make each rule set a variable, and show a default value if a rule fails but forgets to set the variable.
If that’s what you want, this approach would probably work:
Make it an activity. In not for release sections add Before and After rules. Before sets debug_rules to 1 and starts capturing text with Text Capture by Eric Eve. Through whatever combination of having rewritten DB_Rule and processing in after rules, the output gets stored somewhere.
for release only don’t carry out the activity; just follow the for <doing the activity> rulebook in isolation.
I did also consider making it a rulebook that produces some text, but that would require flipping the logic (that is, switching successes and failures around) which seemed like it would be too confusing.
The variable approach works, so that should be good enough.