This illustrates neatly how rulebooks can operate similarly to ‘switch’ statements, where the variable to be switched on is the basis of the rulebook (I have always assumed that this is why Inform 7’s switch syntax:
if <variable of kind K> is:
-- <constant 1 of kind K>: <phrase>
-- <constant 2 of kind K>: <phrase>
... -- <constant n of kind K>: <phrase>
[-- otherwise: <phrase>]
is so limited- you’re supposed to make rulebooks for anything more complex).
But here’s a problem. The rules of a rulebook act on a description of the basis of that rulebook. So for the example given above, a description of numbers. Which is fine for constant values such as 1
or 5
or 10
. Or even for adjectives defined by a calculation:
Definition: A number (called the candidate-prime) is prime rather than composite if:
if the candidate-prime is 2:
decide yes;
if the candidate-prime is even or the candidate-prime is at most 1:
decide no;
let n be 3;
while 1 is 1:
if the candidate-prime is less than n multiplied by n:
break;
if the remainder after dividing the candidate-prime by n is 0:
decide no;
now n is n plus 2;
decide yes.
Announcing prime: say "You are truly a prime candidate!".
Announcing a composite number: say "You are truly a divisive candidate!"
note that we can use just the adjective, or specify both the adjective and the base
We can use ‘which’ to extend this, applying either a named adjective, or a condition which is applied to the base value but which is not a named adjective:
Announcing a number which is prime: say "You are truly a prime candidate!".
Announcing a number which is at least 7: say "Now we're really cooking!"
The constraint with using ‘which’ is that it can only be followed by a single simple condition, i.e. we can’t construct complex conditions using ‘and’ or ‘or’
The way round that is to use ‘when’, which can be used with complex conditions:
Announcing a number (called n) when n is at least 7 and n is at most 15: say "Moving up through the gears!".
but even by I7’s standards this is rather longwinded (and not particularly literate) compared to the equivalent line of an I6 switch statement, which would be:*
7 to 15: print "Moving up through the gears!";
We can start to improve things by using the knowledge that the parameter of a value-based rulebook is always held in the I6 variable parameter_object
- this is true even when the rulebook is not based on an object but, for example as here, a number. We can expose this I6 variable to I7 by:
To decide which number is po: (- parameter_object -).
Armed with this, we can dispense with the a number (called n)
part of the rule:
Announcing when po is at least 7 and po is at most 15: say "Moving up through the gears!".
It can be seen from this that the effect of a number (called n)
was to assign parameter_object
to n
. We no longer need that, because we have separately told Inform to always read ‘po’ as the number held in the I6 variable parameter_object
.
This is definitely an improvement, but we really want to be able to write 7 to 15
rather than that longwinded po is at least 7 and po is at most 15
. Unfortunately trying to implement 7 to 15
or 7 - 15
both confuse the I7 compiler because they cause an overlap with existing phrase definitions. But we can do this:
To decide whether (lo - a number) -> (hi - a number): if po is at least lo and po is at most hi, yes.
after which this works:
Announcing when 7 -> 15: say "Now we're really cooking!".
Similarly, we can succinctly implement the ‘list’ version of an I6 switch statement:
3, 5, 11: print "You're one of the chosen ones!";
in I7:
To decide whether in (L - a list of numbers): if po is listed in L, yes.
Announcing when in {3, 5, 11}: say "You're one of the chosen ones!"
We can also use ‘or’ or ‘and’ to include several conditions in the preamble of one rule:
Announcing when in {1, 3, 6} or 9 -> 12 or in {12, 17, 21}: say "A random number!".
It would be nice to just be able to write
Announcing 7 -> 15: ...
etc. but I can’t see any way of doing that, because only named adjectives can be used in that way, and declarations of named adjectives can’t have parameters other than the value they apply to. So we can write:
Definition: a number (called n) is divisible by 3 if the remainder after dividing n by 3 is 0.
but not
Definition: a number (called n) is divisible by a number (called d) if the remainder after dividing n by d is 0.
- small print The I6 → Inter compiler used for ‘Include’ statements is more limited in regard to
switch
statements than the I6 compiler that ultimately produces a story file, in that the former doesn’t recognise conditions in the form ‘x to y’, so that even if writing directly in I6 these can’t be used by switch
statements within ‘Include’ segments