Returning to in-game menu and remembering choice

CarbonBlue

Developer of Unleashed
Game Developer
Oct 25, 2018
1,119
7,692
I'm getting conflicting information in google searches and I'm wondering what's the best way to accomplish this.

Python:
Character "You have questions, ask."

menu:
    "This is my first question":
    $ first_question = "asked"
        jump first_question_answer
   
    "This is my second question":
    $ second_question = "asked"
        jump second_question_answer  

label first_question_answer:
    Character "Here's your first answer"
    #Now I want to ask the second question, if it hasn't already been asked.

label second_question_answer:
    Character "Here's 2nd answer"
    #Now I want to ask the first question, if it hasn't been asked.
Any help would be greatly appreciated!
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,685
Maybe like this:
Code:
Character "You have questions, ask."
$ Menu01 = []

menu Menu01:
    set Menu01
    "This is my first question":
        $ first_question = "asked"
        Character "Here's your first answer"
        jump Menu01

    "This is my second question":
        $ second_question = "asked"
        Character "Here's 2nd answer"
        jump Menu01

label next_text:
    Character "Okay, let's continue..."
NOTE: Seen here, thanks to anne O'nymous
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,555
2,170
Firstly, I personally wouldn't keep track of whether something happened or not by using string variables.
Don't get me wrong, it'll work... But unless the values are going to be relevant, using True or False is a better coding solution.

Using your own example...

Python:
    $ first_question = True

Okay, with that out of the way... Let's talk about some of the options you've got.

You can return to your choices with a label and a jump
(You had some indenting issues in your code... I'm correcting as I go...)

You've also named your character "Character"... Trust me, you'll get bored of typing that. Better to shorten it to something like "mc" (main character) or "p" (player). Though I realize that might be just something you've used for the example. I'm going to use "s" for Simone.

Python:
label start:

    $ first_question = False

    s "You have questions, ask."

label simone_wants_to_know_your_question:

    menu:
        "This is my first question":
            $ first_question = True
            jump first_question_answer

label first_question_answer:

    s "Here's your first answer"
    jump simone_wants_to_know_your_question

Okay. Two problems here.
Firstly, once you've asked the question... it'll still be there the next time through
Secondly, the game will loop. It'll just keep asking the question over and over and never stop.


All easily solvable by using some of the menu: code that isn't commonly used.

First problem: You can combine menu: and if statements together to only present the choice only IF the condition is true, by tagging an if statement into the choices. Especially handy if you want the reasoning to be more complicated than just if you've picked that option already.

Second problem: Once you've got if checks within your menu: there's another little feature a lot of RenPy programmers don't realize. IF all the condition checks for all the menu choices are False, then the menu is skipped. Though more commonly, programmers tend to add an extra option to allow the player to NOT pick every option.

Last note: Not really a problem... just another little something that not all RenPy programmers know... The menu: statement itself can be used as a label:.

So with that newfound knowledge... an updated version of your code (with the 2nd option added back in).

Python:
label start:

    $ first_question = False
    $ second_question = False

    s "You have questions, ask."

    menu simone_wants_to_know_your_question:
        "This is my first question" if first_question == False:
            $ first_question = True
            jump first_question_answer

        "This is my second question" if second_question == False:
            $ second_question = True
            jump second_question_answer

        "That's everything I wanted to know":
            jump continue_after_simones_question


label first_question_answer:

    s "Here's your first answer"
    jump simone_wants_to_know_your_question


label second_question_answer:

    s "Here's your second answer"
    jump simone_wants_to_know_your_question


label continue_after_simones_question:

    s "Let's continue shall we?"
    # blah, blah, more code.

    return

Note the use of if as part of the menu choices.
Also note that the label: and the menu: statements have been merged.

Finally... we reach the example both anne O'nymous and mgomez0077 have provided.

This one does a little more "behind the scenes" things related to menu:, which is why I wanted to explain the "long way around" examples first.

The new concepts in that example are a new variable which stores a list (what other languages might call an array). The other thing is the use of the set: option of your choices menu.

What the list variable and set: do is automate all those if checks I was adding to each menu option.

The first thing you need to do is "empty" the list variable. You do that with a simple $ menu_choices_list = []
Secondly, you add the statement set: to your menu.
Each time you pick a menu choice... it's identifier is automatically added to the list variable. menu: also automatically ignores menu choices that are already within the list.

I'm also going to remove the "no more questions" type choice from this example. This shows what happens when all the choices have been picked and the program just drops past the menu: because no more choices are possible. Note under these circumstances, the player would be forced to pick all the menu choices before continuing - though they could do so in any order they choose.

Python:
label start:

    $ menu_choices_list = []

    s "You have questions, ask."

    menu simone_wants_to_know_your_question:
        set menu_choices_list

        "This is my first question":
            jump first_question_answer

        "This is my second question":
            jump second_question_answer

    jump continue_after_simones_question


label first_question_answer:

    s "Here's your first answer"
    jump simone_wants_to_know_your_question


label second_question_answer:

    s "Here's your second answer"
    jump simone_wants_to_know_your_question


label continue_after_simones_question:

    s "Let's continue shall we?"
    # blah, blah, more code.

    return

In this example, I've completely removed the first_question and second_question variables because they are no longer needed to control the menu choices (set: is doing that). However, in the real world - you might want to know what choices the player made further along within the game... so you might want to include either those variables or something similar to keep track of that choice somewhere else.

Personally, I would still code things in line with my "long way around" example. The use of set: is a little too "behind the scenes voodoo" for my programming style. I prefer that the program flow be obvious to a more inexperienced programmer looking at my code. Personal preference of course... If it works... it works. And all these examples should work (except the one that loops).
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,101
14,748
Maybe like this:
You understood it perfectly.

I'll just change a little something, almost always forgot. You can put one (and only one) dialog line Inside a menu block :

Python:
# You used /$/ at level 0.
default Menu01 = []

menu Menu01:
    set Menu01

    # Most of the time, it's better looking this way.
    Character "You have questions, ask."

    "This is my first question":
        $ first_question = "asked"
        Character "Here's your first answer"
        jump Menu01

    "This is my second question":
        $ second_question = "asked"
        Character "Here's 2nd answer"
        jump Menu01

label next_text:
    Character "Okay, let's continue..."
 

CarbonBlue

Developer of Unleashed
Game Developer
Oct 25, 2018
1,119
7,692
You've also named your character "Character"... Trust me, you'll get bored of typing that.
Yeah that was just for the example. Thank you so much for the coding lesson! As someone obviously completely new to coding I can't tell you how much I appreciate it!