Ren'Py using back button and saving variable information

anonj73

Newbie
Game Developer
Apr 6, 2020
32
456
If I do something like this:

menu:
"Choice A":
jump choiceA

label choiceA:
$ variable_is_changed = True
"...."

.... if I do that and say the player gets to this point, makes Choice A and this stores the new variable (as changed), and then the player uses the back function to take a different path, is this variable not saved for the new alternate path the player has taken? It's deleted right and reverts to the original state for the new path?

I am new to python and I just need to know if I need to redeclare this variable as "false" every time I open a new branch just to make sure someone didn't store it as "true" and then not go through with the true branch.

I doubt it saves this and I'm not seeing a problem... but I don't want there to be a problem later.
 

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,490
7,035
First, the way things work with Ren'py is that every time there is an interaction with the player, Ren'py saves the entire game state as of that interaction. By "state," I mean the values of all the variables that are defined as of that point in time, all the screens that are being displayed, etc. So, when the player rolls back, they roll back to a previous state, exactly as it was when they first hit that point "on the way forward." So, in your case, if "variable_is_changed" doesn't have a value before they hit the "choiceA" label, if they roll back into or before the menu, then they roll back into a situation where that variable isn't defined. Hopefully that answers that part of the question.

As to, the rest, the "proper" way of handling this is to have a statement like this somewhere:
Code:
default variable_is_changed = False
What this will do is the following:
1. If the user starts a new game, variable_is_saved will automatically be defined to be False.
2. If the user loads a save in which variable_is_saved is not defined, variable_is_saved will be set to False automatically.
3. If the user loads a save in which variable_is_saved DOES already have a value, the value from the save will be used.

Thus, if you use the "default" statement, variable_is_saved will always have a value. If you haven't yet hit a line that sets it to True, it will automatically be False. In particular, if the player has a save from v0.2 of your game, and you introduced variable_is_changed into the game in v0.3 of your game, it still gets a value (False), even if the player is loading an old save.

If you are diligent about providing a default for every variable you're going to use whenever you add it to the game, you'll never run into a "variable not defined" error, no matter what path you take through your code. Oh, you might forget to change the default variable - that's on you. But it will always be defined, and will always have a value...
 

anonj73

Newbie
Game Developer
Apr 6, 2020
32
456
Yeah... it's defined already as false before getting to this point... what I'm getting at is just the method of "player comes across this action, clicks it and this changes the variable... then suddenly the player decides to change their mind, go back and pick a new path... saves never involved, just clicking and rolling back"... the variable reverts, right?

I think in all my playing around here, I'm pretty certain it does revert. You don't have to put too much thought into it but I appreciate the answer. You did clarify some things.

I'm concerned because of how this type of memory is stored in browsers and can cause a problem with using forms and allowing the back button... if it has the same behavior in python... and again, I don't think it does now that I've really played with it a bit since my OP.

Thanks again.

EDIT TO ADD: Rereading your comment, and I missed the top paragraph... and you explicitly answer my question... yes it does revert. Big thanks.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,268
I'm concerned because of how this type of memory is stored in browsers and can cause a problem with using forms and allowing the back button... if it has the same behavior in python... and again, I don't think it does now that I've really played with it a bit since my OP.
I'm confused here. I know what "forms" are, especially in regard of web browsers, but what they have to do with Ren'py exactly ? And if you feel that your game (?) would not really deal good with web browsers, just don't release a Web version of it. It would not prevent someone to make one, but at his own risk.

Oh, and by the way, it's not the behavior of Python, but the behavior of Ren'py. Python is just a coding language, which imply that, basically speaking, it have no behavior ; and it definitively don't know what "rollback" is.
 

anonj73

Newbie
Game Developer
Apr 6, 2020
32
456
I'm confused here. I know what "forms" are, especially in regard of web browsers, but what they have to do with Ren'py exactly ? And if you feel that your game (?) would not really deal good with web browsers, just don't release a Web version of it. It would not prevent someone to make one, but at his own risk.

Oh, and by the way, it's not the behavior of Python, but the behavior of Ren'py. Python is just a coding language, which imply that, basically speaking, it have no behavior ; and it definitively don't know what "rollback" is.

I confused an already solved issue by posting my thought process as to why I was worried about this.

They are two separate issues... forms/websites, and renpy/python... what I am saying is that "because of my experience in making websites, I understand that using a back button on form without capturing past states of forms can cause all kinds of issues... so you need to declare headers to keep forms from reloading when you use a back button."

This relates to my current question about python, only because of the behavior... I was asking if python treats history the same way when you use a back button... and according to the first response, it doesn't.

And coding languages do have behavior. What I mean by that, is how do they act? One coding language might allow for you to post variables without declaring them... and another requires it... those two conditions are part of the behavior of their respective codes.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
You've covering a few topics, some of which aren't actually related to the language you are currently attempting to use. I understand all too well the need to draw comparisons and see parallels.

The way I think about this is that at key moments, RenPy takes a snapshot of memory. That snapshot includes a number of things, but relevant to this conversation... it includes your game's variables. That snapshot becomes part of the history buffer. Whenever you rollback, RenPy just goes backward through the history buffer - reverting things (like the snapshots of memory) to how they were at that point. In effect, and not to make light of it, things are rolled back to the state a normal user would expect. No extra coding, just a simple "this was how it was when you were here last time".
As a side note, when you save a game - you are effectively saving the history buffer... which is why you can still rollback after loading a saved game.

All of which is a function of RenPy, not Python... since Python isn't a visual novel engine and doesn't need to rollback.

Now you could get caught up in a whole technical, "but when?" or "which statements trigger a snapshot?", etc... but the reality is that you don't need to... because it just works.

If you want to test it yourself, create a test project and use code similar (or identical) to this:

Python:
default var1 = 0

label start:

    scene black with fade
    "Start:.... "

    "This is just a test line (1)"
    "This is just a test line (2)"
    "This is just a test line (3)"

    $ var1 += 10
    "Var1 = [var1]"

    "This is just a test line (4)"
    "This is just a test line (5)"
    "This is just a test line (6)"

    $ var1 += 10
    "Var1 = [var1]"

    "This is just a test line (7)"
    "This is just a test line (8)"
    "This is just a test line (9)"

    "**** THE END ***"

    return
Then run your test game from the RenPy launcher... when you see "Start:....", open the developer console (shift+O) and use the watch var1 command to keep track of the value of the variable var1. (use the exit command or just right-click the mouse to return to the game). Then advance and rollback as much as you'd like until you recognize that rollback "just works".

And again, you could get caught up worrying about memory usage, how potentially inefficient it all is and such... but it's beyond your control. It's an inherent function of RenPy. So don't worry about it.
(If you really care, look at the size of the game's save files... since they are primarily the whole history buffer - it should give you a direct comparison.)