Executing before every prompt (Questions, Michael Callaghan)

I’m wondering if it’s possible to execute something every prompt, not just before doing something. Here’s the code:

Include Questions by Michael Callaghan.

There is a room.

Before doing anything:
	ask an open question, in text mode;

A text question rule (this is the you had better get it right rule):
	if the current answer matches the regular expression "foo":
		say "YOU WIN";
		end the story finally.

Test me with "x self / lkjlkasjdla / foo / foo / x self / foo".

Which produces:

>test me
(Testing.)

>[1] x self
As good-looking as ever.

>[2] lkjlkasjdla
I didn't understand that sentence.

>[3] foo
I didn't understand that sentence.

>[4] foo
I didn't understand that sentence.

>[5] x self
As good-looking as ever.

>[6] foo
YOU WIN

    *** The End ***

What’s happening here is that “ask an open question, in text mode;” runs once at the beginning of each action, but not actually before each prompt. From the source code of Custom Library Messages by David Fisher it looks like these messages are coming from the I6 API, through LibMsg “”, “”, etc. I don’t understand what I just said, but I’ve been digging around trying to figure it out for the past couple of hours.

Now, because of this, when an incorrect command is typed, the next response is going straight to the parser as it’s not yet time to process a new action (there was no previous one that completed), and this explains why “ask an open question” isn’t called again. Thus, the following “foo” (sent to the parser) isn’t understood, which returns another LibMsg error and this scenario repeats until the user has entered a command that the parser doesn’t reject.

I’m inclined to think this isn’t a bug in Questions nor really a bug in Inform – rather, I’m doing it wrong by saying “Before doing anything:”, when, what I really mean, is “Before any prompt:”. Does that exist?

Or, does there exist some workaround like saying, “if an invalid command is entered, just go to the next turn, treating the entered command like a noop”?

Alright, I got it (from example 414 under regular expression matching):

Before reading a command:
	ask an open question, in text mode;

Note that this approach is not used in the Questions documentation. Hopefully this helps someone.

You have to watch out for some corner cases here. There is no entirely ideal solution.

Inform can execute several actions in a row after a single “reading a command” activity. For example, the player might type “N. E. S. W” or “GET SWORD, LAMP”.

Inform can do several “reading a command” activities with no “doing anything” between them. For example, inputs that trigger parser errors.

Some line inputs do not trigger “reading a command”. For example, noun disambiguation responses. Also blank line inputs (and the subsequent “I beg your pardon”).

This is from an older version of Inform–the whole LibMsg thing was an old system for printing various messages that were hardcoded into the I6 templates, and Custom Library Messages was an extension that let you change them from within I7. They have now been superseded by the rule response system described in the documentation.

Anyway, what you’re experiencing has nothing in particular to do with the system for printing messages. “Before doing something” is something that works on actions. Actions only take place when a command has been successfully parsed. If you enter an invalid command, you get a parser error (as zarf has already alluded to), which doesn’t result in an action and which doesn’t advance the turn count or invoke the Every Turn rules.

I’m not entirely sure what you’re trying to do here; if the point is to ask the question over and over until you get the right answer, then you want a closed question rather than an open question. If the point is to process the command in an ordinary fashion except something cool happens when the player enters the magic word, then the thing to do is to define a new action:

Winning is an action applying to nothing. Understand "foo" as winning. Instead of winning: say "YOU WIN"; end the story finally.

If you reaaaaaaaallly reaaallllly want something to happen every time you print the command prompt and only then, you could change the command prompt to include a say phrase that calls your effect, like this:

[code]Include Questions by Michael Callaghan.

There is a room.

When play begins:
now the command prompt is “[open question asking]>”.

To say open question asking:
ask an open question, in text mode;

A text question rule (this is the you had better get it right rule):
if the current answer matches the regular expression “foo”:
say “YOU WIN”;
end the story finally.

A blue dog is here. A yellow dog is here.

Test one with "x self / lkjlkasjdla / foo ".

Test arrggh with “x dog/ foo/ z”.[/code]

The second test shows that the question gets asked even in response to a disambiguation response, which wouldn’t happen with Before reading a question rules. However, “end the story” doesn’t actually take effect until the next time the turn advances (I think), and the disambiguation response produces a parser error, so that leaves us in limbo with the story about to end the next time a command gets parsed successfully. (This problem doesn’t arise if you define “foo” as a current action, because then Inform knows that “foo” is the start of a valid command, and it doesn’t try to process it as a disambiguation response.)

So, it kind of looks like you might not be trying the right way to do what you’re trying to do anyway.

Neither – the point is to have a full-fledged conversation with an NPC responding to various texts, while the player interacts with the world. So the open question is what I was looking for and the Questions extension is doing exactly what it should. I just reduced the problem to a minimal example, not to show intent, but to concisely demonstrate the misbehavior.

The initial confusion arose as a result of the examples in the Questions extension’s documentation, where the author does this:

Every turn when introduction is happening (this is the set open sesame rule):
	now current question is "";
	now current prompt is ">";
	now punctuation removal is true;
	ask an open question, in text mode.

The problem with asking the open question “Every turn” is that if the user misspells the answer to a question and gets the “I didn’t understand that sentence” response from the parser, then if they immediately correct their spelling, their now-correct answer doesn’t have the intended result. That’s confusing to the player (and in the worst possible way: by making the correct answer appear wrong).

I tried to fix that behavior by replacing “Every turn:” with “Before doing anything:”, hoping that would make the “ask an open question” run more frequently, but it didn’t work. Eventually I tried “Before reading a command:”, and that does work (well enough, subject to the caveats generously shared by zarf).

The fact that you can even do this is excellent. (I think) that’s not necessary here, but it’s great to know about, and I’ve copied it into my notes for reference.