There should be better warnings not to do this in Renpy.

KiaAzad

Member
Feb 27, 2019
277
207
It's amazing how this topic have blown up, for such a simple issue.
(I didn't read all the replies, just few lines here and there, so forgive me if I'm repeating something already said)
The return stack is not your problem, you just have to use the "call" and "jump" statements correctly and the correct way to use it is:
- Only use jumps.

calls are not for moving through the story, it is used to call a label, go through it and return to the same place you've left. for example a short event or minigame. if there's a chance to not return to the same place in the script, you never use a call. ever!
 

User #1751331

Member
Oct 30, 2019
193
156
We are talking about Ren'py, so about Python, and I explicitly talked about "most modern languages". Plus, by itself what I said explicitly limited the subject to dynamic arrays.
You realize there is only 5 years difference in age between C++ and python and 10 years between C++ and java.
That said pascal is 50yo and C is 48yo. But C++'s vector which is a dynamic array of sorts is created using C and then later recompiled using C++ because once the libraries were created the first time it was possible to rebuild the libraries using C++.
So in that effect even C++ has a dynamic array because All of Pythons, Java's and pretty much every modern languages compiler comes back to code that was created with C and C++.

There aren't many modern languages that where created without using C or C++. Sure someone could create a modern language with ASM take it from someone that has done that it's not much fun.

Why mention all that well. The point is the root of all these languages comes back to effectively two C and ASM. There is only a few ways in which a dynamic array can be created.
The first is one in which you reallocate and create a copy. It will get slower over time because the more you copy the longer it takes.
The second is a variant of the list method. It won't get slower over time when used for a stack because the pointer always sits at the end also won't run out of space and has a constant time. It will get slower if someone needs to traverse that list.
The third is pre-allocation in which you don't tell the user memory has been allocated for a lot larger space and you keep track of what is used with an end point variable. The draw back is that it uses a set amount of space that can still be expanded using the first method.
To be clear I haven't seen 2 used in a very long time. I think the last time I see someone do that was in college when creating a dynamic array was the assignment the prof gave out.

All of them will however cause a slow down when it comes to something like Renpy's Roll Back feature copying it because that requires traversing the entire array regardless the type. The first and third will be relatively fast the second will be really slow in comparison.

So lets say we have a game and the variables and content remains the same through out the game. We load initialize everything at the start of the game. The Rollback system should after it reaches its limit have the exact same time effect each new scene.
It pushes one off at one end and adds the new scene at the other. That means rollback routine is a constant factor. It's performance should have the exact same effect every scene / frame.

The only way the roll back feature gets slower over time is if there is a growth in data it needs to copy. In C and C++ copying an array is a bit faster than in python that is especially true if the C and C++ is optimized and fits in the CPU memory space entirely.
Renpy's language though isn't purely python. There is some interpretation in effect going on as well that python is dealing with. So that makes and additional difference in this performance. So I'm not sure how well that ends up being optimized. A well written program isn't going to have an ever expanding call stack. In fact you should be able to set the call stack to a fixed size and never have to worry about it exceeding it. You can do that in C and C++. The times that becomes an issue is when dealing with recursion. All three language C,C++ and python have recursion limits. C and C++ are caused by stack over flow limits. You can however specify stack size when compiling the program.

So the fact the rollback feature copies the stack isn't the issue. The issue is the growth in the stack that shouldn't exist.
Over time even if you disable the rollback entirely it would still cause a problem at some point. Either you are going to run into the limit of the python array size or you will run into a set stack size limit. Apparently this was realize at some point or they wouldn't really had a need to make pop_call() public function it could have just been used by the return function.


Trying to say the problem is the roll back is tantamount to saying the car is bad because the breaks need replacing.
The underlying issue that is a problem is the breaks need fixing or in this case the program is poorly written causing stack growth.

It will be a bit before I can respond. Great talk AON
 
  • Like
Reactions: hiya02

Kinderalpha

Pleb
Donor
Dec 2, 2019
198
262
This discussion has officially gone over my head. Not sure why there is so much discussion of other languages when the topic is about RenPy (and subsequently python). Just kinda seems like a flex match instead of getting to a point.

That aside, if you believe it's such a problem tacm , you clearly have the knowledge to contribute towards documentation or the RenPy codebase. You should consider it, and see how the author and other contributers feel about this matter.

Otherwise, not sure what other outcome can be reached here.
 
  • Like
Reactions: sakosux and riktor

User #1751331

Member
Oct 30, 2019
193
156
I can't recall a single renpy game that actually suffers from this, granted I've played fewer than 100. if i were to nitpick devs general use of the call function it would be that much of the time what they are using it for would be better accomplished (imo) with custom functions (or even screen calls in some cases) rather than renpy label calls.
Actually if I was nit picking one of the two of these it would be jump. If you read my posts I point out in the programming industry jump and GOTO are effectively 4 letter words or foul and looked at as bad practice, laziness and ... so on.
 

User #1751331

Member
Oct 30, 2019
193
156
This discussion has officially gone over my head. Not sure why there is so much discussion of other languages when the topic is about RenPy (and subsequently python). Just kinda seems like a flex match instead of getting to a point.

That aside, if you believe it's such a problem tacm , you clearly have the knowledge to contribute towards documentation or the RenPy codebase. You should consider it, and see how the author and other contributers feel about this matter.

Otherwise, not sure what other outcome can be reached here.
Renpy is built with python, python is built using C. There are only a few ways in which things are created regarding what we are discussing when it comes to computers.
The discussion got carried off into the tangent because some of us disagree on the facts or the scope of the issue and the only real answer to addressing that is to trace the issue to a root cause which means analyzing the underlying structures and what is the primary issue and or if issues will occur regardless or not.

My point is no matter how you look at it it will cause issues eventually. It is also the underlying root cause to what is a secondary issue. So no matter what it is bad practice and needs to be avoided and there for programmers should be warned of it.
 

Basilicata

Radioactive Member
Game Developer
Oct 24, 2017
1,345
3,118
I'm not a fraction as experienced as you guys but this might help the issue:
 

TDoddery

Member
Apr 28, 2020
170
160
I didn't see this thread before Basilicata bumped it.

I first coded (we didn't call it coding then) on basic mainframe when GOTO was the "go-to" function (pun intended).

If I remember correctly we would do GOTO [line number] and not even have a label or anything like that.

So in Ren'py I like the jump to label thing because it fits my oldskool mindset. But here's my question, in coding a game why would you want to call the label anyway, rather than just jump to it?

All that calling it seems to do is to allow for a return statement which can just as easily be written explicitly if needed.

Sorry if I'm being dumb.
 

Basilicata

Radioactive Member
Game Developer
Oct 24, 2017
1,345
3,118
I didn't see this thread before Basilicata bumped it.

I first coded (we didn't call it coding then) on basic mainframe when GOTO was the "go-to" function (pun intended).

If I remember correctly we would do GOTO [line number] and not even have a label or anything like that.

So in Ren'py I like the jump to label thing because it fits my oldskool mindset. But here's my question, in coding a game why would you want to call the label anyway, rather than just jump to it?

All that calling it seems to do is to allow for a return statement which can just as easily be written explicitly if needed.

Sorry if I'm being dumb.
Maybe I can answer this. I'm doing a tabletop game ATM. Imagine a pawn jumping in various squares after a diceroll. I have a label diceroll and I call it wherever my pawn is in the 28 different squares. If I had to use a jump it would have been much more difficult to do so. And this is just one aspect of the usage of call command.
 

TDoddery

Member
Apr 28, 2020
170
160
Well thanks and I do appreciate the response but not intending any offense that doesn't make it any clearer for me at all.

I don't get what the 28 squares is about. Pawn = chess so 64 squares total, but maybe you mean there are only 28 accessible squares to a given pawn ?

But what's with the dice roll. In chess ?

Sorry you've just lost me completely.
 

TDoddery

Member
Apr 28, 2020
170
160
Actually, I don't waste your time trying to explain it to me at the moment unless you think it's something I might run into problems with, which seems unlikely as I'm not planning on calling any labels.
:)
 
  • Like
Reactions: Basilicata

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,391
15,307
So in Ren'py I like the jump to label thing because it fits my oldskool mindset. But here's my question, in coding a game why would you want to call the label anyway, rather than just jump to it?

All that calling it seems to do is to allow for a return statement which can just as easily be written explicitly if needed.
Because the return point can be anywhere in the code.

Let's say that you write an Interactive Visual Novel with some basic free roaming. While most of the story will be linear, the interactive and free roaming part imply that sometime you'll not have a single piece of code, but parallel piece of code. What happen on day 2 evening, will be, by example, either a scene at home, a scene a the park, or a scene at work.
While all this can, and should, be done with jump, things became more complicated when you have to handle the time passing. You two possibilities, either you write the code everytime :
Code:
label day2EveningHome:
    [...]
    $ period = 0
    $ day += 1
    jump somewhere

label day2EveningPark:
    [...]
    $ period = 0
    $ day += 1
    jump somewhere

label day2EveningWork:
    [...]
    $ period = 0
    $ day += 1
    jump somewhere
or you call a label that will take care of the time passing :
Code:
label day2EveningHome:
    [...]
    call timePassing
    jump day2HomeEmpty

label day2EveningPark:
    [...]
    call timePassing
    jump day2ParkEmpty

label day2EveningWork:
    [...]
    call timePassing
    jump day2WorkEmpty

label timePassing:
    $ period += 1
    if period >= 5:
       $ period = 0
       $ day += 1
    return
Using the later offer you the possibility to not temporally fix the events. In place of a label named "day2EveningHome", you've now a label named "HomeEvent3", because the event can happen at anytime, as long as the MC is at home and have seen the two previous events.
With a call free approach, the said "HomeEvent3" have to end with the full time passing code:
Code:
label HomeEvent3:
    [...]
    $ period += 1
    if period >= 5:
       $ period = 0
       $ day += 1
    jump homeEmpty
Because you don't know at which period of the day the event will happen for the player.
Therefore, the use of call is just a way to avoid having to repeat the same piece of code again and again, with all the possibility of errors that it imply.
 
  • Like
Reactions: Basilicata

hiya02

Member
Oct 14, 2019
169
95
actually, it is the goto/jump that should be removed from renpy, that way first time game devs wouldn't run into this issue.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,391
15,307
actually, it is the goto/jump that should be removed from renpy, that way first time game devs wouldn't run into this issue.
You want to remove goto from a script language that is massively sequential ?

There less than 5% of Ren'py games that call labels, and among them less than 10% that do it wrong. So, there's no reason to change something ; teaching those devs is enough.
 
  • Like
Reactions: 79flavors

It's Danny

Member
Game Developer
Jun 9, 2021
159
659
I'm using a lot of calls in my game but also some jumps.
From the beginning I decided to go with a naming convention.
All my labels that are called start with a "c_" in their name.
E.g. label c_my_label:
This way I never forget that I have 1. Call but never jump to this label and 2. use a return at it's end.