Inform7/10 Reference Manual

This works:

lab is a room.

To repeat until (c - condition) begin -- end loop:
        (- while (~~{c})  -).

When play begins:
let i be 1;
repeat until i is 4 begin;
  say i;
  increment i;
end repeat;
1 Like

I edited the post since that’s actually an error (if I’d stopped to think about it, it would’ve been obvious that continue was the same as make no decision), but I’m not so sure it’s incorrect to say that stop the action is equivalent to rule fails. After all, it stops the rulebook from processing other rules, which is pretty much what people expect from rule fails.

I can see from the definition that it indeed just returns true without calling RulebookFails(). It’s used everywhere throughout the Standard Rules in various check rules and the like. It’s not entirely clear to me how it differs from rule fails, but if what you’re saying is accurate, it sounds like a mostly undocumented fourth way that a rule can end (apart from fails, succeeds, and no decision).

  • rule fails – sets the rule failed to true and the rule succeeded to false, and the rulebook stops processing
  • rule succeeds – sets the rule succeeded to true and the rule failed to false, and the rulebook stops processing
  • make no decision or continue the action/activity – leaves the rule succeeded and the rule failed both false, and the rulebook just continues processing.
  • stop the action – leaves the rule succeeded and the rule failed both false, and the rulebook stops processing

And if that’s really how it works, it seems wrong to be using it so extensively in check rules. You’d think you’d want the check rule to fail if the action is stopped, wouldn’t you? But maybe I’m misunderstanding something else too?

Also, does this mean that decide no and make no decision are completely synonymous?

So it just doesn’t like the first word being until for some reason? I don’t really get it… but in any case, that also works in indented form, so…

I don’t remember all the cases here. I think it only matters if you check “if rule succeeded” after the rulebook runs. Most rulebook calls in the Standard Library don’t check that.

Also, does this mean that decide no and make no decision are completely synonymous?

They behave the same. But “decide no” is tagged “in to decide if only”. So the compiler objects if you use that in a “to” phrase.

(It lets you use “decide no” in a rule; I’m not sure why.)

Looks like it insists on the first word being “repeat”.

See here for how & why this can make a difference- most commonly to subsequent conditions such as ‘if we have <verbed>’- and why ending Check rules with instead or stop the action usually (but sometimes not, in unusual cases) has the desired effect.

[a salient extract:]

Inform also provides

stop the action;
... instead;        (or, equivalently, instead...;)

(NB ‘instead…’ refers to a phrase such as ‘Before drinking the yoghurt: instead try eating the yoghurt.’ rather than an Instead rule starting with, for example, ‘Instead of eating…’)

‘stop the action’ and ‘…instead’ are both at first sight a little odd. Reading the documentation, you might easily go away with the impression that these both mean the same as rule fails, but that’s not the case. Both of these mean ‘stop the rulebook immediately, but with an outcome in keeping with the last decision a previous rule or rulebook made’. The outcome of that last decision could be any of ‘failure’, ‘success’ or ‘no outcome’. To understand this, consider that both of these phrases cause the current rule to immediately return true but, crucially, and unlike ‘rule succeeds’ and ‘rule fails’, don’t modify latest_rule_result before doing so. Consequently, the calling rulebook will also immediately terminate, with whatever result was previously stored in latest_rule_result. Often this result won’t be important, but in situations where it’s of significance whether a rulebook terminates with success, failure or no outcome this behaviour can either be helpful or lead to results the author did not anticipate.

2 Likes

That all seems to suggest that stop the action or instead generally shouldn’t be used in rulebooks. I suppose it’s probably fine in places like Report or even Check though, since the Standard Rules use it in Check.

I’ve just sworn a mighty oath to never write code that depends on whether an action succeeds or fails. The standard library doesn’t either. (That I recall.) Therefore, the difference doesn’t matter in action rulebooks.

Special-use rulebooks, like DTPM or activities, are different. If a rulebook has custom outcome phrases (like “it is very likely”), I always use those phrases.

1 Like

So it just doesn’t like the first word being until for some reason? I don’t really get it… but in any case, that also works in indented form, so…

This works, too.

To while until (c - condition) begin -- end loop
        (documented at ph_while):
        (- while (~~{c})  -).

When play begins:
let i be 1;
while until i is 4 begin;
  say i;
  increment i;
end while

Seems to be the case that you can’t use original initial words for things ending begin -- end [...] – the existing values seem to be special-cased in the compiler. But I haven’t tried tracking it down in the source to verify.

1 Like

If I’m not mistaken, those are defined in the Preform. I think it the <control-structure-phrase> production? (At least in 6L38.)

Actually, a lot of the syntax for which @Celtic_Minstrel is writing a reference here is actually not set in stone and is defined by the Preform, which language extension can modify to change the syntax of Inform.

2 Likes

I believe the Unsuccessful Attempt rulebook only runs if you give a command to an NPC and the action fails.

2 Likes

So in other words, some of it probably doesn’t apply if you use eg the French language extension, right?

But I bet a lot of it does still apply, even if the exact wordings are different. And the Preform isn’t the most readable quick reference. I’ve been able to glean a few things from it (like the structure of a table entry reference… which as it happens haven’t been covered here, so maybe I still have a few missing things to add), but I wouldn’t recommend it for someone asking “How do I X?”.

I’m planning to eventually convert all of the big posts I wrote in here into an HTML document which I can then post on my website, though I’m not sure how long that’ll take (days, weeks, months, even a year or two if I get distracted and wander off to something else). Whenever it’s ready for viewer consumption, I’ll probably edit it into the first post in addition to adding a link in a new post.

That sounds right; when I wrote some puzzles involving giving orders to NPCs via persuasion, I had to do tons of rules about why actions failed. I copied the “Under Contract” example, which has code such as the following:

Unsuccessful attempt by Clark doing something:
	repeat through table of Clark Retorts:
		if the reason the action failed is the cause entry:
			say "[response entry][paragraph break]";
			rule succeeds;
	say "'I don't think that's in the script,' says Clark dubiously."

Table of Clark Retorts
cause	response
can't take yourself rule	"'I'm always self-possessed,' Clark remarks. You've heard that line before, but it sounds so much more convincing from him."
can't take other people rule	"'I don't think it would be appreciated if I tried to do that to [the noun],' he rumbles."
can't take component parts rule	"'I don't want to rip [the noun] out,' Clark remarks."
can't take people's possessions rule	"'I don't cotton to acting like a thief,' Clark replies. 'It ain't proper.'"

This doesn’t work, either.

lab is room.

Include (-

<control-structure-phrase> ::=
        if ... is begin |
        if ... is |
        if/unless ... |
        repeat ... |
        while ... |
        until ... |
        else/otherwise |
        else/otherwise if/unless ... |
        else/otherwise ... |
        -- otherwise |
        -- ...

<end-control-structure-phrase> ::=
        end if/unless |
        end while |
        end repeat |
        end until

-) in the Preform grammar.

To until (c - condition) begin -- end loop:
(- while (~~{c})  -).

When play begins:
let i be 1;
until i is 4 begin;
  say i;
  increment i;
end until

produces

You wrote ‘until i is 4 begin’ (source text, line 31): but this is an ‘else’ or ‘otherwise’ with no matching ‘if’ (or ‘unless’), which must be wrong.
Because of this problem, the source could not be translated into a working game. (Correct the source text to remove the difficulty and click on Go once again.)

(in the current dev version)

Some syntax, like string literals, are baked into the compiler, so that won’t change.

But all that is defined by the Preform can be totally different depending on the language. The wording, the order of the words, and so on. For example, in French, I made it possible to write adjectives after the noun in descriptions.

So yeah, the reference will only apply to those who write their source in English, but that’s the majority so it’s still useful. As far as I know, only the French translation went as far as translating the Preform, and it’s only compatible with 6L38, and doesn’t fully work, and authors aren’t even forced to use the French syntax. I find the Preform quite poorly documented.

I believe those lines in the Preform grammar are indexed by number; when Preform says “this matches the sixth pattern in <control-structure-phrase>”, the compiler says “ah, that pattern is for ‘else’, so this is an ‘else’ block”. That’s why you get that error message, because “until” is now the sixth pattern in <control-structure-phrase>.

Try putting “while/until” in the fifth line instead of adding a new one. (There’s a fancy way to mix up the ordering without confusing the compiler but I don’t understand it well enough to use it.)

2 Likes

Ha, this works. Good to know, thanks.

Include (-

<control-structure-phrase> ::=
        if ... is begin |
        if ... is |
        if/unless ... |
        repeat ... |
        while/until ... |
        else/otherwise |
        else/otherwise if/unless ... |
        else/otherwise ... |
        -- otherwise |
        -- ...

<end-control-structure-phrase> ::=
        end if/unless |
        end while/until |
        end repeat

-) in the Preform grammar.
2 Likes

Each line has an implicit label, starting with /a/. If you need to add a line (if the formulation is too complicated to be expressed as a simple slash alternative), you have to make all label explicit by adding /a/, /b/, and so on in front of each line. You can have duplicate labels, so you’d use the same letter for while and until. (Again, that’s for 6L38. It could have changed since.)

2 Likes

Ha, even this works!

[...]
<control-structure-phrase> ::= [...]
while/until/for ... | [...]

<end-control-structure-phrase> ::= [...]
       end while/until/for |
[...]

to for each/-- (i - nonexisting K variable) in (L - list of values of kind K)
  begin -- end loop:
  (- {-primitive-definition:repeat-through-list} -).

to for each/-- (loopvar - nonexisting K variable) in (OS - description of values of kind K)
  begin -- end loop:
  (- {-primitive-definition:repeat-through} -)
2 Likes

This is good stuff, and potentially very useful as a high-level quick reference similar to the “I7 Cheat Sheet.” Thank you for putting it together!

If it does get made into a standalone document, please be sure to post here with its location (and get it into the IF Archive). It would make a nice addition to the content on the I7 Resources pinned topic.

What do you mean by this?

I mean to submit it at https://ifarchive.org/.