Programming Style question: making decisions with rulebooks

I just read Ron Newcomb’s “Inform 7 for Programmers.” What a great resource - thanks Ron!

The section on “paradigm leaning” gave me a lot to think about regarding rulebooks and rule-based vs. function-based code. But I’m not quite sure how to use rulebooks to make a decision:

For purposes of this example, let’s assume that “say [text]” doesn’t have the disambiguating power that it does, and we must choose an interlocutor to say the text to. How does this solution look to you?

[code]The alley is a room. The street is north of the alley. Bob is a man in the street. Carol is a woman in the street. The Bank is north of the street. The manager is a woman in the bank. The teller is a man in the bank. The Office is north of the Bank. The insurance salesman is a man in the office.

The current interlocutor is a person that varies.

choosing an interlocutor rules is a rulebook.

Definition: a person is other if it is not the player.

A choosing an interlocutor rule:
If there is exactly one other person in the location:
now the current interlocutor is a random other person in the location;
rule succeeds;
If there is no other person in the location, say “There’s no one to talk to.”;
If the number of other people in the location is greater than one, say “Please be more specific about who to say that to.”;
rule fails;

Rule for choosing an interlocutor when the player is in the bank:
now the current interlocutor is the teller;
rule succeeds;

Understand the command “say” as something new.

Generally talking is an action applying to one topic. Understand “say [text]” as generally talking.

Check generally talking:
Consider the choosing an interlocutor rules;
If the rule failed, stop the action.

Carry out generally talking:
try answering the current interlocutor that the topic understood.

Instead of answering:
say “’[the topic understood],’ you say to [the noun].”

test me with “say hello/n/say hello/n/say hello/n/say hello”

My questions are these:

Do I have to use a global variable to get my rules to return a usable value? Is it the best way or is there a more I7-like way?

Is it appropriate to use “If the rule failed, stop the action” or is there a more elegant way to do that?

Should I used “abide” instead of “consider?” If I do, then “rule succeeds” is the wrong outcome, and we’re back to the old problem that you can’t skip the remaining rules in a rulebook without aborting the current action.

I’m glad you found it useful. It doesn’t quite cover all of Inform, and since it’s a few builds out of date, some of the syntax it uses is dated. I will of course update it again after leapfrogging a build or three.

To have a rulebook return a value sans global, read “18.12. Rulebooks producing values” in the official manual. This part was significantly changed with the release of the 6E builds.

For your “A choosing an interlocutor rule”, you may wish to declare it to be “last”. (See 18.6 “The Preamble of a rule”.) Since it is sort of the default, it would likely wish to hang back unless no other rule steps in.

Since this particular rulebook is designed to basically run only one rule (like the Instead rules do), rather than all applicable rules (like the Every Turn rules do), you can specify the default outcome with “The choosing an interlocutor rules have default success.” (Or failure, or no outcome.) It tacks on a “rule succeeds” (or rule fails, or make no decision) onto the end of each rule in its rulebook. See “18.10 Success and Failure” about halfway down the page – the cosmic analysis example. This might be a moot point of course if your rulebook produces a value.

Generally, that’s what “abide by” is for. It “considers”, then issues the same rule fails/succeeds/no-decision as what was considered did. (Related is “anonymously abide by”, which won’t change the value of the variable “reason the action failed”, allowing your rule to play silent middle-man.) But if you want the action to continue, then the Choosing rulebook would need to produce a value at the same time as make no decision, which it cannot do per 18.12. So the solution you have is the only one – unless you want to write a “make no decision with result…” :slight_smile:

Thanks. I ended up splitting my one big default rule into several more fine-grained rules (with the “if” statements moved into the rule’s conditions) - this was satisfying and I felt like it was doing things the I7 way, but I discovered how tricky it is to get rules to fire in the correct order. Rules for special cases such as the bank teller had to be explicitly placed before other rules that looked more general to me. I guess Inform did not agree.