Menu based Conversation system also accept a blank choice - Inform 7

I am using the extension Activity-based Simple Chat by Shadow Wolf.

It is working great for my first project I am working on but I just picked up a problem that I was not aware of.

As you might know it is a menu-based conversation system where you can choose an answer from a list that is created with possible solutions.

Currently I have made mine to choose only from “Yes” or “No” (will change it later when it works like I planned to).

The problem that presented itself to me this morning is when you leave the choice “1” or “2” blank and just press enter you go straight to the next question like:

Does your hospital have procedures for identifying and immediately removing unattended vehicles during bomb threats?

1) Yes
2) No
>> 
Does your hospital have a bomb threat kit (updated blueprints, floor plans, light sticks, pads, pencils, phone list, etc.) available?

As you can see (this is the output after compiling the game) when leaving the choice blank, press enter it still go to the next question.

That should not happen.

How can I fix this as I have no idea but have been busy trying to figure it out now for the past few hours?

When debugging an issue which involves an extension, one of the first things I’d do is to try out the included examples to see whether they work as intended.

If you do that, you’ll see from the first included example that the default behaviour is:

1) "How's tricks?" 
2) "Good bye." 
(or 0 to say nothing)
>> 
[Please answer by typing a number between 0 and 2.]
>> 0

>

So, there is an option for the player to type 0 to say nothing. But if he just presses Enter, he will get the message “[Please answer by typing a number between 0 and 2.]”.

From the second included example, we see this behaviour:

>talk to harry
Harry looks up as you approach him.

1) What was that book you told me about?
2) "Run! Fire!"
3) "See you later, Harry."
>> 
[Please answer by typing a number between 1 and 3.]
>> 0
[Please answer by typing a number between 1 and 3.]
>> 3
"Later!"

As in the first example, just pressing Enter will result in the message “[Please answer …]”.
But there is no option for the player to say nothing. He has to choose between the given options.

The example achieves that by using this:

When play begins:
	forbid exiting on zero.

By the way, this is also documented in this section of the documentation:

Section: Exiting a conversation

As with Simple Chat, the default is that the player can choose “0” to exit the menus and return to the normal prompt. The code can instead “Forbid exiting on zero” to turn this behavior off, or “Allow exiting on zero” to turn this behavior on again.

Since the extension’s examples seem to work as intended, there must be something going on in your code which causes the issue in combination with the extension. Might still be a bug in the extension, but it’s hard to diagnose without seeing your code.
You should try to isolate the issue in a small example, in a separate project, not your main project. This helps people in the forum when they try to help you, and often it results in finding and fixing the problem.

3 Likes

Thanks, I will try that.

I just checked; I do have that code in the beginning of my code.

The problem I see is with the very first question it does exactly as you described, like it should.

From the second question onwards, you can press enter and it just go straight to the next question as I explained in my original post.

What do you think could be the problem?

I know you need to see the code but I do not know which part to include.

Any advice?

Note: I just ran the sample code from the extension and it is doing exactly as I described above.

Ah, you hadn’t mentioned that point before, about it happening only from the second question onwards. That’s interesting, because when we try that in the included examples, they show the same behaviour, so it points towards a bug in the extension itself. (I see from the added note that you also tried this now.)

I think what’s happening is that the extension, when the player just presses Enter, always uses the input from the previous question, as indicated by the following tests.

Case A – player enters 1, then blank, extension “secretly chooses” 1 and shows the response (“Harry hands the book to you”) as if the player had typed 1; and then similarly on the next question if the player presses Enter again:

talk to harry
Harry looks up as you approach him.

1) What was that book you told me about?
2) "Run! Fire!"
3) "See you later, Harry."
>> 1
"It's by some guy called Finnegan Wake, and I think it's in Irish or something. Do you want it?"

1) "Sure." 
2) "No, thanks." 
>> 
Harry hands the book to you. 

1) "See you later, Harry."
>> 
"Later!"

>

Case B – player enters 2, then blank, extension “secretly chooses” 2 and shows the response (“Later!”) as if the player had typed 2:

>talk to harry
Harry looks up as you approach him.

1) What was that book you told me about?
2) "Run! Fire!"
3) "See you later, Harry."
>> 2
"We are only pixels on a two-dimensional screen. There is nowhere to run to." Harry's words shatter the fourth wall.

1) What was that book you told me about?
2) "See you later, Harry."
>> 
"Later!"

>

Case C – player enters 1, then enters 2, then blank, and the extension thinks that the input was 2, but since there is no option 2, it tells the player to choose again (and repeatedly pressing Enter repeats that result):

>talk to harry
Harry looks up as you approach him.

1) What was that book you told me about?
2) "Run! Fire!"
3) "See you later, Harry."
>> 1
"It's by some guy called Finnegan Wake, and I think it's in Irish or something. Do you want it?"

1) "Sure." 
2) "No, thanks." 
>> 2
Harry sighs. "I'm never going to get rid of it."

1) "See you later, Harry."
>> 
[Please answer by typing a number between 1 and 1.]
>> 
[Please answer by typing a number between 1 and 1.]
>> 

I took a quick look at the extension’s code, but the cause did not immediately jump out at me. But I also tested Mark Tilford’s Simple Chat, which the extension you’re using is based on, and it shows the same issue, as far as I see.

It seems as if the previous choice is cached/buffered and not properly cleared/overwritten, and is erroneously taken as the current choice when the player enters an empty input.

Both extensions (Activity-Based Simple Chat and Simple Chat) include a bit of Inform6 code to achieve their goals:

Include (-
[ ReadChoice low high i;
  for (::) {
    print (I7_string) (+ Chat prompt +);
    KeyboardPrimitive (buffer, parse);
    i = TryNumber (1);
    if (i >= low && i <= high) return i;
    else print "[Please answer by typing a number between ", low, " and ", high, ".]^";
  }
];
-).

To decide what number is the choice made from (low value - a number) to (high value - a number): (- ReadChoice ( {low value}, {high value} ) -).

(This is from ABSC, but SC is similar.)

Maybe the problem has to do with the way blank input is handled inside the KeyboardPrimitive function; but it might also be something else entirely, I’m only speculating here, sorry.

Hopefully some other people can jump in with their insights.

Otherwise, I’d probably recommend, as I’ve done in several threads, to use the Hybrid Choices extension by AW Freyr (I just checked the included example there, and it doesn’t have that problem).

Ha! Now there’s an interesting bug!

The buffer that holds the player’s command isn’t generally cleared, because why would it need to be? The new contents are just written over the old ones. To make sure you don’t read past the end of what’s actually been typed, the length of the command is stored in a particular variable, and whatever leftovers are beyond that point are just ignored.

i = TryNumber (1);

This says to interpret word number 1 of the player’s command as a number. Notably, it doesn’t check if word number 1 of the player’s command actually exists! Because why would you have to check? Surely they’ll always enter at least one word?

But if the player doesn’t—if they enter a blank line—then this looks at the first word of the previous command, which is still in the buffer because nothing overwrote it.

You can detect this case with if(WordCount() == 0), and have it return whatever you like. -1 seems like a good choice.

1 Like

Neat, thanks for the explanation and the WordCount suggestion!

I changed that section to this now:

Include (-
[ ReadChoice low high i;
  for (::) {
    print (I7_string) (+ Chat prompt +);
    KeyboardPrimitive (buffer, parse);
    if (WordCount() ~= 0) {
        i = TryNumber (1);
        if (i >= low && i <= high) return i;
        }
    print "[Please answer by typing a number between ", low, " and ", high, ".]^";
  }
];
-).

I tested it with both blank input and wrong-number input, and it seems to work as intended.

It’s not my extension, but I don’t know if the author @Shadow_Wolf is still active here, so here’s the updated version; I also bumped the version number from 4/130219 to 5/220730:
Activity Based Simple Chat for Inform7.i7x (14.3 KB)

1 Like

Thanks, just loaded the new version and tested my project and it seems to work now.

Thanks everybody for your quick response in solving this problem.

You guys’ rock.

Where can I learn or see that code of the extension and can I write my own private extension, only for personal use in my projects?

But I would love to see and learn this coding.

Include (-
[ ReadChoice low high i;
  for (::) {
    print (I7_string) (+ Chat prompt +);
    KeyboardPrimitive (buffer, parse);
    if (WordCount() ~= 0) {
        i = TryNumber (1);
        if (i >= low && i <= high) return i;
        }
    print "[Please answer by typing a number between ", low, " and ", high, ".]^";
  }
];

There’s an option somewhere in the menu to open any extension and see its code, though where exactly that option is differs by platform. For me, it’s under File > Open Extension > [author’s name].

And, yes, you certainly can write your own extensions!

That snippet you posted is Inform 6 code, which is what Inform 7 is translated into; it’s much less readable, but it’s the best way to handle low-level features outside Inform 7’s model.

1 Like

Thanks, will have a look if I can find it.