Specific input loop

I may be missing something, but it sounds like just setting a global true/false variable would be simpler than setting up a scene, especially if it’s a state that can be triggered more-or-less arbitrarily whenever the player tries to talk to someone.

[code]Limited Input Mode is a truth state that varies. Limited Input Mode is initially false.

After reading a command while Limited Input Mode is true:
[do all the funky things you’re trying to do];[/code]

It may also help to get a sense of how the various rulebooks are ordered in the main gameplay loop, since it sounds like you’re trying to make decisions based on some fairly specific timing. This chart is very detailed but thorough (it’s also slightly out of date – it references “procedural rules”, which have been deprecated – but otherwise it’s still accurate).

Here you can see why a scene doesn’t necessarily stop or start the moment you change the condition it hinges on, and why a scene might not be the best way to handle your particular problem. Scene conditions aren’t checked until near the end of the turn sequence (they’re actually checked twice, once before and once after the every turn rules are checked), after the player’s input has been parsed and translated into an action. If you’re continually interrupting the turn sequence at the “reading a command” stage, which is at the very beginning, and not allowing the player’s input to be processed in the normal way, then the turn is never going to get to the point where it checks to see if the scene should end, and so the scene never will.

Thanks matt,

The issue I’m having is ending the scene. When the external program sends back its input, I need to handle that myself with a bunch of “if the player’s command includes X” clauses, and then I have to reject the player’s command so they don’t get a “that’s not a verb I recognise” message. But this means that the turn count doesn’t increase, which seems to prevent the scene from ending even if it’s end condition becomes true.

(I also tried making my scene a recurring scene, but it sent the game into a loop.)

It does sound like Mike’s suggestion might be the way to go–the scene machinery seems like it’s causing you trouble, so maybe the best way to do things is with a true-false variable.

You may be able to solve the issues by forcing the scene changing rules to run before you reject the player’s command:

[code]Jeopardy is a room.

Answer given is a truth state variable.

Quiz is a scene. Quiz begins when play begins. Quiz ends when answer given is true. When Quiz ends: say “Quiz ended.”

After reading a command:
if the player’s command includes “xyzzy”:
now answer given is true;
follow the scene changing rules;
reject the player’s command.[/code]

but I’d be chary of messing with internals in this way; sometimes it violates other assumptions that can mess things up in unforeseeable ways. It might not, but I don’t really understand the internals, so I’d be more comfortable using truth states.

(By the way, even if you didn’t reject the player’s command, parser errors like “That’s not a verb I recognize” don’t take turns, so you wouldn’t get a scene change anyway.)

Okay, it took me a little bit, but I got it working.

[global variable]
CurrentConversation is some text that varies.  CurrentConversation is "".

[global rule]
Last after reading a command while CurrentConversation is not "":
    if the player's input matches "[terminator character]":
        now CurrentConversation is "";
    reject the player's command.

[and then something like this goes inside the code for any room where a talkable character resides]

Instead of talking to the waiter:
    now CurrentConversation is "WaiterConversation";
    [send output to external application].

After reading a command while CurrentConversation is "WaiterConversation":
    if the player's command matches "[chicken option]":
        [serve the chicken];
    if the player's command matches "[fish option]":
        [serve the fish].

Thanks everyone for helping me out. I really appreciate it.

I’m very interested to see this project–it sounds cool!

By the way, you don’t necessarily have to make the current conversation a text string–you could make a kind of value for the current conversation, or you could make the current conversation partner a person (and set it to the player when no conversation is happening). But maybe the text string is the best way of passing it to your external program.

I hope it turns out that way!

I decided the text string was best because one of the things that might change about the world state is what conversations you can have with the characters. So depending on the player’s progress through the game, the waiter might offer them the fish and chicken, or maybe the beef and pasta, or maybe the monkey brains and live baby snakes. So the CurrentConversation might be “WaiterConversation1”, “WaiterConversation2”, etc.

One total aside - while I was trying to debug, I tried to store the player’s command so that I could look at it later. But I found when I wrote “now [text variable] is the player’s command”, the compiler interpreted it as a condition. And when I wrote “now [text variable] is “[the player’s command]””, this seemed to create a reference to wherever in memory the last command is stored, rather than storing the value of the then-current last command. Which meant that trying to recall the value in-game simply gave me back my most recent command, rather than the command from back when the “now [text variable] is “[the player’s command]”” code was executed.

(It’s possible that there’s a much better way of debugging, and seeing what values are in what variables, that I just don’t know of.)

For something like that, you want:

now the stored command is the substituted form of "[the player's command]"

See §20.7 of Writing with Inform. If you assign a text substitution like “[the player’s command]” to a text variable, it turns into a call by reference, as I think they’re called in other languages. Saying “the substituted form of…” freezes it to a call by value–that is, it’ll stay at whatever “[the player’s command]” is at that moment rather than continuing to change as that changes.

(This is a recent addition to Inform and still gets me a lot!)

Sorry for bumping an old thread!

I’m trying to do something very similar to this, but the choice is between 2 different verbs. Basicaly I’m trying to write:

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

But it doesn’t like it. It says “doing anything excpet buying the chicken” and “rejecting the chicken” are both okay, “but the combination was ambiguous, so I am unable to place this rule into any rulebook.”

To be clear, I can get it working as:

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

(or equivalent with rejecting). It’s just having both with ‘or’ which messes it up. (I can’t find anything in the documentation about ‘or’, but I also can’t find anything anywhere about what I’m supposed to be using instead. Sorry I’m 1 day into Inform, I know nothing!)

(obviously in my example it’s not about buying or rejecting chicken…)

(also using the latest version of Inform 7 (or 10?), if that makes a difference.)

Buying the chicken is menu behavior.
Rejecting the chicken is menu behavior.
Instead of doing anything except menu behavior...
2 Likes

Thanks so much! Although it’s still not working and I have no idea why.

If I do:

Before doing anything except menu behaviour when ordering from the menu is happening: say "Sorry, that isn't a valid option."

That works, in that it adds “Sorry, that isn’t a valid option” to everything else that I try to do (save menu behaviour), before doing the other thing anyway. But when I try “Instead of” in place of “Before”, suddenly everything becomes permissable (but when I change ‘menu behaviour’ back to ‘buy the chicken’, ‘instead’ works fine and blocks anything other than buying chicken). I’m really sorry, I have 0 idea what could be wrong, each part works fine on its own but when I put it together it just mysteriously doesn’t?

(edit removed because the fix I thought I found didn’t actually work…)

Before rules don’t stop the action by default, they just add something before the action. You can add an “instead” to the statement in the rule body to stop the action there:

Before doing anything other than menu behaviour when ordering from the menu is happening:
	say "Sorry, that isn't a valid option." instead;
	[equivalently with instead at the beginning: instead say "Sorry, that isn't a valid option.";]

See 7.3. Before rules.

1 Like

Thank you thank you! Yes, that works. I didn’t think ‘before’ would stop the action, I was just using as a test to see what was going on.

I’m still confused why making it an instead rule (having ‘instead’ at the front, so to speak) worked when it was taking a single action but not when it was taking a behaviour. So:

Instead of doing anything except buying the chicken when ordering from the menu is happening: say "Sorry, that isn't a valid option."

Did block all other actions, while:

Instead of doing anything except menu behaviour when ordering from the menu is happening: say "Sorry, that isn't a valid option."

just let everything else run. Is it something to do with specificity effecting order of opperations? Either way, it’s a purely academic question now. Thank you both!

The latter should work to block all unwanted actions (and I just tried a tiny example to confirm!) so there must be something wonky elsewhere in the code, unfortunately. Are you sure there isn’t a typo about what scene is happening or anything like that?

If not, and you can write a compact example that demonstrates the error I’m sure we can figure it out (though if your workaround is working it might not be worth it, of course!)

1 Like