Ren'Py Understand checkpoint and rollback

Chantajista

Newbie
May 28, 2019
73
328
Hello

Anyone can point me a good document about how checkpoints and rollbacks works?

I am trying to develop a program that doesn't use the "say" statement and use custom bubbles for text.
But I don't know how to integrate this into standard rollback system.

Thanks
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
11,425
17,391
Anyone can point me a good document about how checkpoints and rollbacks works?
The official doc, located on your computer and .


I am trying to develop a program that doesn't use the "say" statement and use custom bubbles for text.
Why? And I don't ask about the bubbles, I ask about the none use of the say statement.

You can edit the "say" screen for it to works the way you want.
You can have the "say" screen act differently depending on who's speaking through an if structure testing the value for who.
You can to punctually customize the "say" screen behavior.
And of course, all this without counting the fact that you can just decide to use ...


There's absolutely no reason to create your own way to display dialogs, and then struggle to integrate this into Ren'Py's features. With emphasis on the "s", because it don't limits to the rollback mechanism. It would also break the "skip" feature, and don't works well with the auto-forward, and even less well with the rollforward, ones. This while it can also mess with the translation and self voicing features. It would also probably mess with Ren'Py optimization.
And of course, you would also have to mimic the "say" statement behavior, and therefore force the creation of an interaction each time you display one of the dialog lines. Without this, nothing would works correctly and, whatever you feel happen on the screen, you would have a totally broken game with mostly incoherent save files.

All this for something as basic as displaying dialogs in bubbles. There's dozens of code example explaining how to do this, some being 10 years old or more. I even kind of remember that PyTom once dedicated one of his monthly post to them, prior to their addition as native feature.
 
  • Like
Reactions: bobdickgus

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,628
2,286
RenPy's rollback is effectively log of action RenPy has taken. The log is added to each time a RenPy statement is executed. Say is the most obvious example, but pretty much any command that isn't pure python hooks into the logging.

Save files are effectively a copy of that log, where the game loads the save, decides the statement that is due to be executed next and starts there. If that statement can't be found, it goes backwards through the log looking for a statement it can identify. In a very similar way to the way a player can rollback through previous actions, albeit making allowances for what happens when the programmer changes the code.

RenPy tracks everything using an Abstract Syntax Trees. The layman explanation being that RenPy numbers each statement within your script. Complicated by the fact that numbers are relative to blocks of code, and those blocks are organized in a hierarchy relative to certain RenPy statements (like label for example). The hierarchy is necessary because absolute numbering would immediately fail when you add or remove lines of code, whereas numbering within small blocks of blocks of blocks, etc means the code (and therefore the save/rollback system can adapt).
See :

As for your comments about removing Say... erm, why?
RenPy already has support for speech bubble in the later versions, and those bubbles use Say in the same way the closed-captioning type text is normally displayed. The bubbles can be highly customized (I believe).
See :

Also without say, the rollback system can sometimes behave in unpredictable ways.
I haven't touched on that area in a long while, but I have a vague recollection of people having multiple scene/pause statements coded in a sequence and when someone rolls back, it goes to the first scene not necessarily the previous one shown. It's been a long while though, I may be misremembering. But as Anne implies, any inconsistent rollback behaviors are likely going to lead to identical save issues too.

Edit: I should probably add that these explanations are my rationalizing very involved processes I don't fully understand. I think the explanations get the general theme of what RenPy is doing, even if I'm getting a lot of the actual technical details wrong.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
11,425
17,391
RenPy's rollback is effectively log of action RenPy has taken. The log is added to each time a RenPy statement is executed.
Not exactly.
Entries are added to the rollback at the starts of each interaction, but not all statement create an interaction. Statements like scene, show and show screen are among the most used that do not create one.
I don't know for pause, that you mentioned later, but like for a long time it was nothing more than a empty transition, I doubt that it create an interaction.


I haven't touched on that area in a long while, but I have a vague recollection of people having multiple scene/pause statements coded in a sequence and when someone rolls back, it goes to the first scene not necessarily the previous one shown.
Ren'Py do not include the notion of "previous node", therefore rollback isn't a way to travel by browsing the AST backward. Instead it's a succession of instant loads. And like for any load, you're sent back to the place where you were when the save have been made; here when the entry was added in the rollback stack.


So, to summarize:

If there's no interaction, there no entry point added in the rollback stack.

And if there's no entry point added in the rollback stack, there's no way to goes back "there".
You'll be sent back further in time, and you'll have to advance in order to reach again "there".

Plus if there's no entry point added in the rollback stack, then there's also no way to actually save where you actually are.
The save file will be created, but with the context stored in the last rollback entry. Therefore, when loading you'll be sent in whatever place in the past.
Years ago, there were a thread about this. Someone who worked on a game, but where everything was handled through a single screen called only one.
Whatever how long you were playing, any save loaded were sending you back at the very starts of the game, forgetting everything that happened in between.
 
  • Heart
Reactions: 79flavors

Chantajista

Newbie
May 28, 2019
73
328
Why? And I don't ask about the bubbles, I ask about the none use of the say statement.
Messing with Renpy. Trying different things to see how it works. Sure, that are plenty of codes. Copying other's code is a way to learn. But building your own solution, even not optimal, helps you to understand better. That doesn't mean I don't check functional code. Probably later I will find better ways to do it, but meanwhile I will have learned something.

As you have seen, I haven't asked for a solution. I have asked for docs where I could learn how to build the solution.

As for your comments about removing Say... erm, why?
RenPy already has support for speech bubble in the later versions, and those bubbles use Say in the same way the closed-captioning type text is normally displayed. The bubbles can be highly customized (I believe).
See :
This is something I will check. And thanks for the help.

Where can I find information about "interactions"? It seems it is the core for understanding checkpoints and rollbacks, as points anne O'nymous
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
11,425
17,391
As you have seen, I haven't asked for a solution. I have asked for docs where I could learn how to build the solution.
And you can see, you asked without knowing what you actually need to know about. The rollback is just the tip of the iceberg you've to deal with when creating an equivalent to the "say" statement.

I'm also tempted to say that there's way more to learn by tweaking the "say" screen and playing with the say arguments, than by rewriting a "say" statement equivalent from scratch. Knowing the fundamental concepts behind Ren'Py is useful; yet 75% of Ren'Py devs don't know them. But knowing how they actually operate is useless. Especially since this can change from a version to another, without the behavior itself being affected by that change.
It's by example what happened with the 7.5.x/8.x branches of Ren'Py, when the screen language was finally separated from its roots. What was true before those the 7.5.0 and 8.0.0 versions (all screen language statement have an ui equivalent that can be used to build a screen and inside creator defined displayable) stopped to be true. All the screen language statements added starting those version are totally independent of the old obsolete ui structure.

After all, Ren'Py languages are its script language, screen language, and it's animation and transformation language. It's what one have to learn to use in order to efficiently deal with Ren'Py. It's only once assimilated that diving a bit further, can possibly help, through the creator defined statements and displayable.
But starting there is mostly a lost of time. It's like wanting to know how to sprint before knowing how to walk. It's something totally possible, it would create a strong perception bias that would then follow you all your life.
Whatever the situation, "running" would be your first option. Someone knock at the door? You'll run to it. You want to eat something? You'll run to the kitchen. Then will come situations where running isn't appropriated, like by example stairs. Yet, due to the perception bias, you'll pass a really long time trying to find a way to safely run through them, and only remember that "walking" is also an option after you injured yourself long enough.
And the same would apply for Ren'Py, whatever you want to do, your answer will be "Python", even if there's already something, bug proof and easy as hell, that exist in Ren'Py language.


Where can I find information about "interactions"? It seems it is the core for understanding checkpoints and rollbacks, as points anne O'nymous
Not just checkpoints and rollbacks, that in fact are the same things. It's the core of all Ren'Py process.
And there's just no information about them. They aren't even clearly defined, otherwise than by their importance, in the doc. Even diving in the core code wouldn't answer the question, because it's more a concept than an actual thing.
The "say" statement is an interaction, as are call screen that is something totally different, and input that is yet again something radically different.

It's like when planning a long journey. You will get something like:
  • Drive to the train station;
  • Take [whatever] train to [whatever];
  • Take a taxi to the airport;
  • Take [whatever] plane to [whatever];
  • Take a taxi to the hotel.
    [/quote]
    Each entry in the list imply something different, but each one would be an interaction because explicitly marking a step of the journey and all implying a stop.


    This being said, creating your own interaction is relatively easy, and even explained in the doc; I gave you the link to this part:
    Python:
    # Automatically populate the rollforward structure, if it have to.
    roll_forward = renpy.roll_forward_info()
    
    # Do whatever you have to prepare the interaction.
    
    # Start the interaction and get the return value useful only in case of actual input interaction.
    rv = ui.interact(roll_forward=roll_forward)
    
    # Automatically populate the rollback structure.
    renpy.checkpoint(rv)
    But this will still not solve the issue with the auto-forward, nor the one with the "skip" feature. Both playing a big role in the reason why peoples prefer Ren'Py games. This is intended for creator defined statement that would, for a reason or another, need to create a new kind of interaction or, if you remove the ui call, want to enforce a rollback/rollforward entry.