Ren'Py Renpy menu call/return

thevenom8

New Member
May 1, 2019
4
2
Hello

I'm very new to Renpy and I get along quite good already. But I have one problem and looked over all the forums without any answer. I guess i'm just dumb as I am sure its easy to solve

I want to give the player the choice to go to different locations in the game. As example it's morning and the player can go to the kitchen, livingroom and bathroom. As some locations have nothing to do at this time, i want to use always the same labels when nothing is to do there. With a call/return

Example
Menu:
"kitchen" :
call kitchenempty
"livingroom" :
call livingroomempty

Label kitchenempty
Scene 1
"nothing here"
return

Label livingroonempty
Scene 2
"nothing here"
return

The third location would be the one which will move forward with the story..

Unfortunately the return always goes to the next scene, so not back to my menu above..
Does anyone knows why?

Thankd in advance for the support!
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,363
15,280
Unfortunately the return always goes to the next scene, so not back to my menu above..
Does anyone knows why?
Because you don't ask Ren'py to act differently.

When you write this :
Code:
menu:
              "kitchen" :
                   call kitchenempty
              "livingroom" :
                   call livingroomempty
Ren'py will proceed the content of the bloc corresponding to the choice made by the player, dot.
Here, the said content is "please, go to this label then come back when it's done". What Ren'py do, then when it come back, it's to found that the block is finished, what lead it to continue with whatever is after the menu.

For the kind of behavior you expect, you should write something like :
Code:
menu myMenuLabel:
              "kitchen" :
                   call kitchenempty
                   jump myMenuLabel
              "livingroom" :
                   call livingroomempty
                   jump myMenuLabel
 

thevenom8

New Member
May 1, 2019
4
2
Perfect.. That makes total sense.
Thanks so much anne O'nymous

I really learn a lot and it leads and require logical thinking while working with Renpy. Really fun.
Cheers
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
So far, I'm not really seeing why you would use call. Most games can be written using jump only - especially if you're already struggling with call. While jump doesn't have some of the flexibility of call, it's also simpler to implement for a new developer.

Anyway, let's talk you through it...

call will jump to the named label and execute code until it encounters a return statement.

When it encounters a return, it will jump back to the next line directly below the call statement (the "next line" may be much further down the code, depending on indentation/code blocks).

Another way to explain this is that each time call is used, the calling line identifier is added to the end of "call stack". Each time return is used, the last entry on the call stack is removed and used to be the place where the game goes next. It's also why games that don't use return properly end up doing things the developer didn't expect.

Other than that, RenPy just processes each line in order - moving down one line at a time, from code block to matching code block (matching indentation or back to the previous level of indentation).


Walking through your example...

Python:
label start:

    scene black with fade

    menu:
        "Kitchen":
            call kitchenempty
     
        "Livingroom":
            call livingroomempty

label kitchenempty:

    scene myscene1
    "Nothing here."
    return

label livingroonempty:

    scene myscene2
    "nothing here"
    return

The game starts at label start:
There's a scene and a menu: and the player gets to pick either "Kitchen" or "Livingroom".

If the player picks "Livingroom", the game calls label kitchenempty: and does the code within that block until it encounters return - at which point it returns back to the next executable line after the call.

Since there isn't another line at the same indentation level, the game passes control to the next line after the menu: - which happens to be the same label kitchenempty: and that code will be repeated until it hits the return again. With no entries left on the call stack, the game will return to the game's main menu.

The same thing will happen if the player picks "Livingroom", except it will execute "livingroomempty" and then "kitchenempty" before returning to the main menu.

If you want things to return to the menu, you need to tell your code do that.

One way would be...

Python:
label start:

    scene black with fade

label choose_room:

    menu:
        "Kitchen":
            call kitchenempty
    
        "Livingroom":
            call livingroomempty

    jump choose_room

label kitchenempty:

    # etc, etc.

Edit: I've chosen to use a separate label:, whereas anne O'nymous has used the menu: itself as a label. Both are perfectly fine. I tend to use a separate label only because I find it simpler to explain. It also means that if I see jump go_to_this_line, I can search the code for label go_to_this_line without worrying if it's a label: or a menu:.

I've also chosen to put the jump choose_room on the next line below the menu:. Picking where to put it will depend on your game's needs. I've assume that the game will always return to the room choice menu. Anne's example would allow for each menu choice to behave differently if needed.

Though personally, I think this is easier when you're just starting out...

Python:
label choose_room:

    menu:
        "Kitchen":
            jump kitchenempty
     
        "Livingroom":
            jump livingroomempty

label kitchenempty:

    scene myscene1
    "Nothing here."
    jump choose_room

label livingroonempty:

    scene myscene2
    "nothing here"
    jump choose_room

No call statements in sight.


Edit2: Oh, and a note of caution: When you build the game for distribution - the build process will normally add...
from {identifier}
...to each call statement. If you do end up using call... NEVER... EVER... edit or delete those from parts of the line.

Because RenPy allows for code to be added/updated/deleted from one version of the game to the next, those from additions are an extra level of protection that keeps RenPy straight about where to return back to when a player loads a saved game with lots of entries on the call stack. Don't feel the need to "tidy them up" or "renumber them because they're out of sequence" or anything like that. Just leave them the hell alone. :devilish:
 
Last edited:

thevenom8

New Member
May 1, 2019
4
2
I really apreciate your time and answer. Thanks a lot 79flavors
It's really interesting to learn about the work flow behind renpy or/and python.

I personally would like to use call/return because it will allow me to use the same labels for the empty rooms scenes in the future of the game again and again. For the moment I'm happy with the solutions I got from you two. But I will pay attention to use call/return in the correct way.

Thanks again and happy eastern
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
hehe. No worries.

I'm only cautious because one of the first tasks I picked for myself soon after joining F95 was to help "fix" the spelling and grammar of a particular game. The developer of that game was doing a great job, but didn't come from a programming background and clearly didn't understand what call actually did when he started using it. While ultimately it didn't break the game (well it did, but not in a way players noticed), it made my eyes bleed when I saw the code. So I tend to warn new developers away from it, rather than risk repeating what was an easily avoidable mistake.

If you can follow the logic and it makes sense for your game... all power to you.
 

thevenom8

New Member
May 1, 2019
4
2
Got it. I will take some time to read some more background information about call function to have a better understanding. I guess there are some mistakes as a neewbie that you have to make by yourselfe to really start learning and understanding. But I prefer to understand things properly first. It's just hard as a neewbie because the whole coding is a really big world. But an interessting world.