Specific input loop

Is there a way to force the game into a loop wherein it will only accept specific input?

Like (and this is just an example) could I create a situation where the player is asked a question, and the game won’t let them perform any action other than answering?

So, for instance, they asked “Do you want the fish or the chicken?”

At which point, the only two acceptable inputs are either “fish” or “chicken”. If they type anything else, the game would say “I’m sorry, we don’t have that on the menu.” It wouldn’t allow them to walk away, or look at something else, or use an inventory object, until they’d answered the question. Is that possible?

Ordering from the menu is a scene. Before doing anything except buying when ordering from the menu is happening: say "Sorry, that isn't a valid option." Some fish is here. Some chicken is here.

Note that this will still allow SAVE, RESTART, QUIT, etc. It’s generally a very bad idea to block those.

Also, the “choosing a gender” example is probably a good start: dhayton.haverford.edu/wp-content … Rex21.html

That’s the other way to do it. The main difference is that “choosing a gender” circumvents the standard parser entirely, meaning you can’t QUIT or invoke any other action. Using a “before” rule (see example “Sagittarius”) allows the parser to run, then cuts off the action if it’s not the one you want.

The easiest way is to word it as a yes-no question and use “if the player consents”, which is built in and will require the player to answer before proceeding.

Before entering the obviously-dangerous passageway: say "Are you sure you want to do this?"; if the player consents: say "Okay, here goes..."; continue the action; otherwise: say "I figured you'd listen to reason!"; stop the action.

In your case, you could word it as “Do you want the fish? If not, you’ll get the chicken…”

These are all decent solutions. I suppose it boils down to how you want it played out :slight_smile:

The Extension Questions by Michael Callaghan is designed for uses like this. I think this version works with the latest version of Inform.

This is pretty much exactly what I needed. Not entirely sure which solution I’ll use, it’ll take a bit of fiddling to figure out, but thanks guys!

I’m attempting to modify the “choosing a gender” code to suit my purposes, but I’m getting errors.

Here’s what I’ve got:

Instead of ordering from the menu:
let outcome be “”;
[perform an action];
After reading a command while outcome is “”:
change outcome to “[the player’s command]”;
[do some stuff with the player’s command]

But Inform7 doesn’t seem to like my while clause.

Also, I’m unsure how scope works in Inform7. If I’m creating the variable “outcome” inside the Instead rule, is it a local/temporary variable? Or is it global? Will it still exist once the code inside the Instead rule is completed?

Variables created within a rule are local to that rule. Your code should work if you declare “outcome” as a global variable:

The outcome is a text that varies.

Also, “change outcome to [something]” won’t work; you need a “now” statement:

now the outcome is "[player's command]";

I’m afraid that didn’t work.

Perhaps it’d be better if I explained what I’m trying to do. I tried to make my original question as simple as possible, because the details of what I’m attempting are fairly complicated and I didn’t want to get bogged down in extraneous explanations. But here goes:

I’m “filtering” the Inform7 output through an external program that acts as my user interface. Part of this is so that I could add a talking mechanic to the game that would be impossible using just Inform7 alone.

How it works is, whenever a player talks to a character, the game spits out a bunch of nonsense that the external program captures and translates into something its interface understands. The player then interacts with this (think of it as a minigame within the game, maybe?). Once the player completes this, the external program sends input back to Inform7 based on the player’s actions.

So, whenever the player talks to a character, I want Inform7 to:

  1. Output the text that my external program can interpret.
  2. Go into a state where it’s awaiting specific input.
  3. Once it receives that input, perform actions based on what the input is
  4. Return to a normal state where the player can type commands in

So the code for this would, I imagine, look something like this:

Instead of talking to Steve:
outcome is some text that varies;
outcome is “”;
[output text to be interpreted by external program]
After reading a command while output is “”:
output is [player’s command];
if output is “option 1”:
[do action 1]
if output is “option 2”:
[do action 2]
otherwise:
say “ERROR - malformed return value!”.

I’ve already got the [output text to be interpreted by external program] part working. It setting the game to a state where its awaiting the result of the talking minigame that I’m struggling with.

(I know this is sort of advanced stuff, and I’m an Inform7 beginner - but I wanted to make sure I could do what I wanted to do before committing to learning the language in detail.)

In your example, you’re still declaring the “outcome” variable inside a rule (the instead rule), so your after reading a command rule won’t recognize it. I think you’re going for something like this:

[code]Test Chamber is a room.

A man called Steve is in the Test Chamber.

The outcome is some text that varies.

Instead of asking Steve about something:
now outcome is “”;

After reading a command while outcome is “”:
now outcome is “[player’s command]”;
if outcome is “foo”:
say “FOO!”;
otherwise if outcome is “BAR”:
say “BAR!”;
otherwise:
say “ERROR!”;
reject the player’s command;
[/code]

That compiles, although I’m not 100% it will do what you want. A few observations:

  1. When you declare outcome as a text that varies, it will initially start out as an empty string (""), which means that the very first command of the game will trigger your after reading a command rule. Unless that’s what you want to happen, you might want to set outcome initially to some arbitrary default value.

  2. Be aware that the “reading a command” rules are checked long before the instead rules are ever triggered. That means that when you try to talk to Steve, the game will first do nothing, then it will start the next turn, and THEN it will check the player’s input for “foo” or “bar”.

  3. When the after reading a command rules are finished, they allow the parser to proceed as normal unless you specify to “reject the player’s command.” Otherwise you’ll get output like this:

Which was why I wanted to make the outcome a local variable. I was hoping that by declaring the “After reading a command” rule inside the “Instead” rule, the “after reading” rule would be within scope to see that local variable.

But otherwise, thanks, that’s really helpful.

You can’t declare a rule inside another rule. Inform is assuming that when you declare the after reading a command rule, you’re starting a brand new rule, and it’s filing each of them away in their respective rulebooks where they belong.

Putting a rule inside a rule is somewhat like trying to define a function inside another function in C. Doesn’t work that way.

I’ve been toying with combining this approach with a scene, where the scene is effectively a conditional. The scene is triggered by talking to a character. While the scene is happening, enter an input loop.

The issue I’m having now is ending the scene. Is there a condition that goes “The scene ends when a command is read.” Or even “The scene ends when a command is read during the scene.”?

It sounds like you’re trying to have Inform interact with an external program that handles the input some of the time. This will require some non-standard kind of extension or interface. Maybe Vorple or something involving Unified Glulx Input (I’m not sure if the latest version is on zarf’s official sites, but here is a version that fixes a bug that popped up recently.) There was also something someone did that had Inform talking to Javascript but I can’t find it at the moment.

(It might in theory be possible to hack it up by manipulating the “For reading a command” activity and using external files, but I wouldn’t try this. That is to say, I did try this, and it hurt my head.)

One thing is that almost all the things we’ve suggested presuppose a normal input loop in which the player types something and the game processes it. You can’t do “The scene ends when a command is read”–a scene ends at the end of a turn, and the turn is going to be triggered by a command being entered and processed. (There can be exceptions, I guess, but they won’t help here.) The normal “For reading a command” rules also have the player type in something; using them, you can’t have the program go into a state where it awaits input and then run the “After reading a command” rules, because the way the program awaits input is by having the player type something.

Again, there are ways to have Inform talk to an external program, but it’s not something that you can make happen out of the box.

Sorry if I’ve misunderstood what you’re asking here, but insofar as you want Inform to be drawing inputs from an external program, that’s not something Inform routinely does.

The sending output and receiving input to an external program part I’ve already got sorted. I just need a tidy way to end the scene as soon as a valid command has been entered.

(I’ve also tried using a truth state that I set to true as soon as a valid command is received, but my “The scene ends when [truth state] is true” doesn’t seem to get triggered by the “now [truth state] is true”.)

Although I’ve just noticed that scenes only fire once? It won’t fire each time the player talks to a character. So maybe scenes aren’t the best way to do this.

OK, I think I misunderstood what you were using scenes for and what you meant by “a command is read.” Is this the current situation:

Sometimes you start a scene that activates your special input program.

The player interacts with an input program to eventually produce an output. (I’m picturing something like Ultimate Flirt-Off.)

Once the program produces an output, it gets sent to the Inform program.

Now you need a way to end the scene?

I’m not a scene expert, but this seems like something that should be doable. You can set a flag that determines whether the scene ends:

[code]Conversation happened is a truth state that varies. [note: The name of the variable is “conversation happenedd.” It’s like conversation_happened; the individual words don’t have a special role]

Talking to Steve is a scene. Talking to Steve begins when [your condition here]. Talking to Steve ends when conversation happened is true.

When talking to Steve begins: now conversation happened is false.[/code]

And the question is where to set the flag. You can set it at the beginning of the action-processing rules:

First before during Taking to Steve: now conversation happened is true.

…I was going to add something here about trying it during the After reading a command rules, but the scene-changing machinery doesn’t run until the end of a turn. so that won’t work. It might be possible to make the machinery run other times, but I’m not sure if that’ll work.

Here’s a sample of scene-changing machinery, without the cool external conversation mechanics of course:

[code]Lab is a room. The huge box is an enterable closed openable container in Lab. Steve is a man in the huge box.

Conversation happened is a truth state that varies.

Talking to Steve is a scene. Talking to Steve begins when Steve is visible. Talking to Steve ends when conversation happened is true.

When Talking to Steve begins: now conversation happened is false.

First before during Talking to Steve: now conversation happened is true.

When Talking to Steve ends: say “Conversation ended.”[/code]

This scene will only run once. If you want a scene that runs more than once, you have to declare it a “recurring” scene. (And while I was typing, I see that you’ve asked a question about this! Yes, recurring scenes are what you want.)

Hope this helps–let me know what I’ve misunderstood!