There are several ways to approach writing complex behavior in Inform 7. Two common ones are what I’ll call “action oriented” and “subject oriented”. It might make more sense to use “object oriented”, but that term already has enough associated connotation and confusion.
The “action oriented” style seems to be the one used most consistently in the Inform 7 documentation, and as you would expect it’s very useful and readable. An example is something like this:
Instead of examining something in the presence of Dan when Dan is bored: say "'Quit gawking at the scenery and entertain me!'";
Note that this code applies to the player whenever he or she examines anything. Although there are additional qualifiers attached that limit the scope of the rule, and we could certainly add more, it fundamentally works as a modifier (or in this case, a replacement) for a single action against a range of possible objects.
But it’s often the case that you want specialized responses for a number of different actions performed in certain circumstances. You can achieve this using a more “subject oriented” style:
Instead of doing something to the teak table in the presence of Dan when Dan is bored: say "'Quit screwing around with the table and entertain me!'";
We now have a rule that makes anything you do — to the table, and the table only — trigger a generic complaint message.
All this is great as far as it goes, but what if we want to get more ambitious yet? Let’s say Dan mocks you when he’s bored, and you’d like him to have something different to say depending on what you happen to be doing. How would we express this?
If we went by the book we could make a bunch of “action oriented” rules, arrange them in a rulebook, and run that rulebook when the proper conditions apply. If we did that, we’d have something that looked like this (code changed due to Andrew Plotkin pointing out that the Report rulebook doesn’t have a generic version):
The block singing rule is not listed in any rulebook. After doing something in the presence of Dan when Dan is bored: consider the mockery rulebook; A mockery rule when examining: say "'Ooooh, look at me! I'm wasting time looking at something completely irrelevant!'"; A mockery rule when singing: say "'Hold on there, pal! Ryan Seacrest is holding on line one! He wants you to be the next audition reject on American Idol!'";
etc.
This works, and works well. In the case where you want to do anything dynamic to the rules on the fly, this is definitely the way to go.
But there’s another syntax that allows expressing these kinds of constructs in a more straightforward manner, particularly if you don’t need the full power of a rulebook. The Inform 7 documentation hints at this, but doesn’t always give you full examples of the syntax. Here are the above rules expressed in this other format:
The block singing rule is not listed in any rulebook. After doing something in the presence of Dan when Dan is bored: if examining: say "'Ooooh, look at me! I'm wasting time looking at something completely irrelevant!'"; otherwise if singing: say "'Hold on there, pal! Ryan Seacrest is holding on line one! He wants you to be the next audition reject on American Idol!'";
This is good — I like it because it groups together all the special responses when a particular condition obtains — but often we might want to specify an action that can involve multiple nouns. In that case, you can use the following syntax (if you have a filling action defined):
... otherwise if filling something with something: say "'You're wasting your time with that...'";
and, of course, you can specify either or both of the nouns as well:
otherwise if attacking Dan: say "He easily dodges. 'C'mon, wimp! You'll need to do better than that!'";
It would be nice, as long as we’re valuing brevity, to be able to use the “switch/case” syntax for this — something like:
The block singing rule is not listed in any rulebook. After doing something in the presence of Dan when Dan is bored: if the current action is: -- examining: say "'Ooooh, look at me! I'm wasting time looking at something completely irrelevant!'"; -- singing: say "'Hold on there, pal! Ryan Seacrest is holding on line one! He wants you to be the next audition reject on American Idol!'";
… but I haven’t been able to find a variant of this syntax that works properly. Perhaps the new version of Inform 7, scheduled to be released today, will allow this.
At any rate, I hope this was useful. Rulebooks are exceptionally powerful and many times they are the proper solution to your design issues, but don’t underestimate the power of the “subject oriented” approach. By keeping your related actions in close proximity like this, you can keep your code clean, readable, and well-organized.
#1 by Andrew Plotkin on April 28, 2010 - 10:45 am
Quote
Let me back up…
“Last report doing something in the presence of Dan when Dan is bored” *doesn’t* work. Check/carryout/report rules can only be used with a specific action, not with “doing something” or multiple actions. (This is an illogical restriction and I hope it goes away in some future version, but it is the case now.)
You *can* say:
Last report examining in the presence of Dan when Dan is bored: …
Last report taking in the presence of Dan when Dan is bored: …
Your if/otherwise syntax is really just a slightly agglomerated version of this — you’re doing a conditional test yourself instead of embedding it in the rule structure. That’s fine; it’s a matter of taste. I like separate rules because I can go on to add
Last report pushing in the presence of Dan when Dan is excited: …
…without making the “if” structure any more complicated.
A separate problem: the singing action doesn’t hit the report phase, by default. It’s blocked by a library check rule. You’d have to change that before “report singing” has any effect.
And finally, the new I7 release will be “on or around” today.
I’ve seen some last-week bug reports in the past, well, week — it might have slipped some.
#2 by Matt Wigdahl on April 28, 2010 - 11:19 am
Quote
Thanks, Andrew. I should have realized that there wouldn’t be generic versions of these rulebooks, knowing that Inform automatically creates the appropriate specific check/carry out/report rulebooks on creation of a new action (although I agree with you that it would be nice if there were default versions available).
I should have tested these snippets before including them. I pulled them from similar constructs from my WIP, which use “after” rules. I’ll edit the post and change them so they are compilable. And as far as the singing action goes, I’ll add a comment to reflect that you have to have additional code to bypass the block — I just picked an interesting action here without considering what other requirements would have to be satisfied to get you here.
I agree that what I’ve laid out is pretty close to equivalent syntax and a matter of taste; I happen to like this particular format when doing a lot of mode-specific behavior for a character or item just because it keeps a lot of related behavior together nicely.
Pingback: The week in IF #4 « IF URLs