is it raining (this is the usually not raining rule): rule fails.
The usually not raining rule is listed last in the is it raining rulebook.
is it raining when the player is yourself and the location is wet (this is the lucky player rule): rule fails.
The lucky player rule is listed before the usually not raining rule in the is it raining rulebook.
is it raining when the location is New York City : rule succeeds.
New York City is a room. New York City can be wet. New York City is wet.
follow the is it raining rules;
if rule succeeded, say “It’s raining.”;
otherwise say “It’s not raining.”
test me with “rules/z”[/code]
So I have a rule that’s listed last, and rule listed before that one, and a third rule without an explicit order. My assumption was that the two named rules would be anchored at the end of the rulebook and the anonymous one would end up first. Unfortunately this is not what happens. The lucky player rule runs first because it is more specific than the anonymous rule, which never gets checked at all. Is this a bug, or is there something I don’t understand about rule sorting?
Maybe “listed before” doesn’t mean “listed immediately before”?
You have an extension that creates a rulebook with one default rule. The default rule is listed last.
You create a general behavior (maybe in a second extension) that adds some rules that should run right before the default, but are still in some sense too general to come before anything else.
You want to create some specific rules in your main story file that come first, without having to think about all the default cases. You’ll list them “first” if you have to, but why should you have to? What if the extensions have some “first” rules you don’t want to interfere with? Then you have to go searching for rules to put them “before” or “after.”
The principle of most specific rule first still applies in your intention, but for some reason naming one particular object is considered less specific than naming two properties. So you want to tell your extensions to hold off until the rules from the story file have had a chance.
Now, in the Standard Library, this is done by listing every single rule “last,” which requires that the rules must be declared in reverse order of execution. That’s fine within one single extension, but an extension that is included later can’t put a “last” rule before any rules that were already declared. So I thought the thing to do would be to put it “before” the other last rules.
Can anyone argue that this should NOT be the way rulebooks are ordered? Would it be worth suggesting on uservoice if it is not actually a bug?
You’d want this
The last is it raining rule (this is the usually not raining rule): rule fails.
I might be a bit off in the syntax, but “last” is the word you want there. Then you don’t need the “is listed” statement for it.
Reason being, I submitted a bug about a month ago about how several “is listed before/after” statements don’t work together right in some cases.
I’d say the first extension should list its default last, simply because it isn’t its job to make the 2nd extension’s life easy, but to make its own general usage easy.
The 2nd extension should list its default last, but un-list the original default completely. Within its own (new) default, it can call the unlisted old default if need be.
Then the game can just make rules for the book without worrying about explicit ordering.
EDIT to add: Oh, if the 2nd really makes the default behavior complicated, then the 2nd may wish to make a whole 'nother rulebook to decide that, so the original rulebook needs only one default rule which asks the 2nd rulebook to do whatever default behavior. You may or may not wish to use the ability of the 2nd rulebook to return a value, which isn’t used much in Inform, but has nice syntax now.
It’s based on my actual WIP, so it’s certainly not convoluted on purpose. Perhaps my example doesn’t describe a logical situation, but I was just trying to come up with three rules that didn’t rely on a bunch of new objects and properties.
There is only one extension involved, but my game has a couple general-principle rules and then some object-specific rules. The general-principle rules look very specific to the compiler, but they’re checking for broad swaths of objects that have common properties set.
I thought I might get away with phrasing the “general” rules in the negative (succeeding when the opposite was true) and listing them first. But that didn’t do the right thing, and I decided that listing the object-specific rules first instead would involve less debugging.
It’s funny because when I read this thread I realized I had read many others like it: but usually on CSS forums. In case the reference isn’t clear I’m referring to Cascading Style Sheets used in web site design wherein formatting and other elements are given as CSS rules that are applied in specificity order and that rely on a cascade of effects until something “stops” or “contradicts” the currently “successful” rule.
It’s intriguing to me that Inform seems to be using a rule-based approach that is very similar to what CSS does and that has the same issues as CSS. I realize this is not just a simple thing of CSS since rules-based systems do tend to have the same mechanics.
Of all the design choices of Inform, I think the one that interests me the most is a combination of the fact that (1) it went rule-based and (2) was extension-based as well. Either one is fine. Together, you almost allow for a recipe of confusion and convolutedness not to mention possible side-effects, edge cases, and corner cases that can be extremely hard to debug until you determine the entire chain path of execution.
It’s not accidental. I argued early on both for rules and for a strong extension mechanism, and I thought that rules were the right way to handle extension.
I still think this. A rule model means, at a minimum, that it’s always possible for two independent pieces of code to be compiled together; two rule lists can always be merged. So you always have a hope of customizing the thing that you want to customize, as long as it is broken up into manageably small rule-chunks.
(This is unlike procedural or OO code, in which a given point can only be customized if the original code calls a function or method hook there.)
The problem, which I admit that nobody has solved, is finding a control mechanism which lets the rules come together in a way which is predictable, controllable, and scalable. Source-code order – which is CSS’s main fallback – is not very controllable, because rearranging your code sucks. The ability to say “this rule is first” is predictable and controllable, but not scalable. (You can’t use "first"s effectively in a situation where someone has already "first"ed.)
(This is where traditional programming wins. You can stack functions on functions as high as you like, and the results will always be predictable and easy to rearrange – as long as you’re the author of all the functions, of course.)
You’ve basically argued (at least in my mind) for why I wouldn’t choose a rule-based system and an extension-based mechanic. I hear you saying you still think it’s the right way to go – but I don’t hear why. There are functional programming approaches that languages like Clojure, Scala, or Haskell take that obviate the problem you mention with non-rule based setups. Even Ruby removes the assumption about what can and can’t be dynamically customized, unless I’m misunderstanding how you’re using that phrase.
All that being said, I’m actually somewhat happy to see a rules-based system being attempted because I do think they have their places, although moreso in the “expert system” or “domain knowledge” area rather than in the DSL space.
What if I need to place a rule between those two rules? Now I have to replace both of them and add the new one. It seems like a good idea, but I think it might create at least as many problems as it solves.
Then it would fall back to the order of the declarations in the source. If I were to write:
[code]The AB rule is listed immediately before the CD rule in the badabing rulebook.
The EF rule is listed immediately before the CD rule in the badabing rulebook.[/code]
…then the order would be:
…because EF would interpose itself between AB and CD. This would also apply to extensions. If two extensions both try to insert a rule immediately before another rule, then you could change the order of rules in the rulebook by changing the order of the Include lines for the extensions.
It’s no more of a problem than declaring that a rule is listed last or first, as Jim demonstrated. I like Jim’s suggestion, but I’m not sure what would be lost by making “listed before” and “listed after” behave exactly the same way.