A less painful way to handle choiceless menu? {Solved}

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
Elmiwisa
Veteran
Posts: 476
Joined: Sun Jul 21, 2013 8:08 am
Contact:

A less painful way to handle choiceless menu? {Solved}

#1 Post by Elmiwisa »

Hi. I am making a small game as practice, and I notice that it becomes very painful to make a choiceless menu. :shock:
What do I means by choiceless? What I meant is certain option in the menu is only available if certain condition are satisfied. And depend on how the player played, sometimes it turns out that the menu have only 1 choice available, or maybe even 0 choice. When such situation can happen, I wanted to be able to handle it slightly differently:
-If only 1 choice is available, the menu will never be shown to the player (this is to make it harder for the player to figure out that there is a choice here :twisted: ). That only choice will be automatically chosen instead of showing the menu.
-If no choices are available at all, the menu will never be shown to the player, and a special path will be played. That special path is never going to be available as a choice, so the only way to access it is to ensure that none of the menu choices are available. :wink:

For example, this is a menu:

Code: Select all

    "Suddenly, a hand grab me from behind. Another hand cover my eyes."
    "Looks like a guy is trying to attack me."
    menu:
        "What should I do?"
        "Fight back!" if defense_class>=4:
            call fight
        "Stab him with the ornate hairpin" if ornate_hairpin:
            call stab
        "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
            call figure
        "Panic!!!":
            call panic
Here there are 4 options, 3 of which are only available if certain conditions are true. What I wanted is that, the Panic!!! options is no longer part of the menu, but is only played when all 3 other choices are not available. And if exactly 1 of the other 3 choices are available, then that choice will be automatically played and no menu are shown.

I tried doing this:

Code: Select all

    if defense_class>=4 and not ornate_hairpin and not met_Vincent_Sat_event:
        call fight
        return
    if not defense_class>=4 and ornate_hairpin and not met_Vincent_Sat_event:
        call stab
        return
    if not defense_class>=4 and not ornate_hairpin and met_Vincent_Sat_event:
        call figure
        return
    if not defense_class>=4 and not ornate_hairpin and not met_Vincent_Sat_event:
        call panic
        return
    menu:
        "What should I do?"
        "Fight back!" if defense_class>=4:
            call fight
        "Stab him with the ornate hairpin" if ornate_hairpin:
            call stab
        "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
            call figure
    return
This managed to do what I wanted. However, this is one of the simple menu with merely 3 options. I planned to have multiple different situation where such menu are used, each having 20+ options with much more complicated set of conditions. Hence, this code would blow up in size really easily. :cry:
So I would like to know, is there a less painful way to handle this? Thanks for your help. :D
Last edited by Elmiwisa on Thu Jul 25, 2013 2:28 am, edited 2 times in total.

User avatar
jesusalva
Regular
Posts: 88
Joined: Mon Jul 22, 2013 5:05 pm
Organization: Software in Public Interest, Inc.
IRC Nick: jesusalva
Github: pazkero
itch: tmw2
Location: Brazil
Discord: Jesusalva#4449
Contact:

Re: A less painful way to handle choiceless menu

#2 Post by jesusalva »

Hmm...
try it:

Code: Select all


    "Suddenly, a hand grab me from behind. Another hand cover my eyes."
    "Looks like a guy is trying to attack me."
    if defense_class>=4 or ornate_hairpin or met_Vincent_Sat_event:
       jump menu
    else:
       call panic

label menu:
    menu:
        "What should I do?"
        "Fight back!" if defense_class>=4:
            call fight
        "Stab him with the ornate hairpin" if ornate_hairpin:
            call stab
        "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
            call figure
It should work. hope that helped.

P.S: and in your second code, change if by elif. it should work better.

Code: Select all

    if defense_class>=4 and not ornate_hairpin and not met_Vincent_Sat_event:
        call fight
        return
    elif not defense_class>=4 and ornate_hairpin and not met_Vincent_Sat_event:
        call stab
        return
    elif not defense_class>=4 and not ornate_hairpin and met_Vincent_Sat_event:
        call figure
        return
    elif not defense_class>=4 and not ornate_hairpin and not met_Vincent_Sat_event:
        call panic
        return
    else:
        menu:
         "What should I do?"
         "Fight back!" if defense_class>=4:
            call fight
         "Stab him with the ornate hairpin" if ornate_hairpin:
            call stab
         "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
            call figure
    return
P.P.S: It's better if you keep panic option, then you will have always at least 2 options.
Jesusaves/Jesusalva

Elmiwisa
Veteran
Posts: 476
Joined: Sun Jul 21, 2013 8:08 am
Contact:

Re: A less painful way to handle choiceless menu

#3 Post by Elmiwisa »

Thanks for the reply, but that doesn't quite accomplish what I am trying to do. :cry:
The main issue here is to make the menu simply hidden altogether if there is exactly 1 choice to make (the game will automatically make that choice without displaying the menu at all), so that it is not obvious to the player that there is a decision point here have they play the game differently. To do that, my original method end up producing a huge chunk of near identical code, especially if the menu I planned have a lot more choice than this.
Also, I want to make it so that having 0 choices will send you to a hidden path to access a hidden character, so it should not be available as an option if the menu appear.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: A less painful way to handle choiceless menu?

#4 Post by trooper6 »

So first off...no matter how you code your game, if you have 20+ conditionals, it is going to get big.

But that said, this is what I come up with. There is some repetition, but it shouldn't be too bad.

Code: Select all

#This is a function that you can use for any menu that will check how many valid choices there are for your menu variables. It returns a number representing the valid choices
init python:
    def menuchecker (*args):
        vchoices = 0
        for x in args:
            if x:
                vchoices += 1
        return vchoices
        
        
# The game starts here.
label start:
    #Here are your variables
    $ defense_class = 0
    $ ornate_hairpin = False
    $ met_Vincent_Sat_event = False
    
    "Suddenly, a hand grabs me from behind. Another hand covers my eyes."
    "Looks like a guy is trying to attack me."

    #Here you check to see how many valid choices there are in your possible menu items, you can put however many you like in the parentheses. You assign the number to the variable "valid_choices"
    $ valid_choices = menuchecker(defense_class>=4, ornate_hairpin, met_Vincent_Sat_event)

    #Now you check! If there are no valid choices it goes directly to panic, if there is only one valid choice, it tests the choices and then goes directly to that choice, or it makes a menu. Note: You really, really want this to be if, elif, else. This way when you return from the call return after all the menu stuff.
    if valid_choices == 0:
        call panic
    elif valid_choices == 1:
        if defense_class>=4:
            call fight
        elif ornate_hairpin:
            call stab
        elif met_Vincent_Sat_event:
            call figure
    else:
        menu:
            "What should I do?"
            "Fight back!" if defense_class>=4:
                call fight
            "Stab him with the ornate hairpin" if ornate_hairpin:
                call stab
            "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
                call figure

    "And that is how my evening went."
    return

#Here are the calls
label panic:
    "I totally panic and start screaming!"
    return
    
label fight:
    "I punch the figure in the windpipe, crushing it!"
    if met_Vincent_Sat_event:
        "Only then do you realize the man was Vincent!"
    return
    
label stab:
    "I take my ornate hairpin and stab him in the neck!"
    if met_Vincent_Sat_event:
        "Only then do I realize the man was Vincent!"
        "Oh well."
    return
    
label figure:
    "I peer in the darkness waiting for an answer."
    "Vincent steps out of the shadows with a bright friendly smile."
    return
So...that should do what you want, and it doesn't involve really complicated if statements. I don't know if that works for you...and I don't know if there is an easier way to do it...but this is how I got your idea to work.

:)
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

apricotorange
Veteran
Posts: 479
Joined: Tue Jun 05, 2012 2:01 am
Contact:

Re: A less painful way to handle choiceless menu?

#5 Post by apricotorange »

Here's the more clever solution:

Code: Select all

# Put this somewhere in your project; in menus with only one choice,
# this automatically chooses that choice. 
init python:
    def menu(items):
        if len(items) == 1:
            return items[0][1]
        return renpy.display_menu(items)

# Example menu. There's another interesting trick here: menus without
# any active options automatically fall through to the following code.
label attack_menu:
    menu:
        "What should I do?"
        "Fight back!" if defense_class>=4:
            jump fight
        "Stab him with the ornate hairpin" if ornate_hairpin:
            jump stab
        "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
            jump figure
    jump panic

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: A less painful way to handle choiceless menu?

#6 Post by trooper6 »

apricotorange wrote:Here's the more clever solution:

Code: Select all

# Put this somewhere in your project; in menus with only one choice,
# this automatically chooses that choice. 
init python:
    def menu(items):
        if len(items) == 1:
            return items[0][1]
        return renpy.display_menu(items)

# Example menu. There's another interesting trick here: menus without
# any active options automatically fall through to the following code.
label attack_menu:
    menu:
        "What should I do?"
        "Fight back!" if defense_class>=4:
            jump fight
        "Stab him with the ornate hairpin" if ornate_hairpin:
            jump stab
        "\"Vincent, is that you?\"" if met_Vincent_Sat_event:
            jump figure
    jump panic
What exciting code apricotorange! How elegant! You've taught me some new things! Might I ask one question about it? In the menu function you have this:

Code: Select all

init python:
    def menu(items):
        if len(items) == 1:
            return items[0][1]
        return renpy.display_menu(items)
The line "return items[0][1]"
I get that the [0] is the first item in the array. (Right?)
But what is the [1]?
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Elmiwisa
Veteran
Posts: 476
Joined: Sun Jul 21, 2013 8:08 am
Contact:

Re: A less painful way to handle choiceless menu?

#7 Post by Elmiwisa »

Wow thank you so much apricot :D It is an amazingly simple trick, and it is better than what I hoped to get :o
I am not sure why it works yet, but I guess I can learn those technical trick later. Unless it is something rather simple? In any case, I will mark this as solved.

Thank you too trooper for adding details to the dialogue that I didn't thought about :)

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot]