Ren'Py Renpy performance pitfalls?

DuniX

Well-Known Member
Dec 20, 2016
1,203
797
I am making a pretty complex management/simulation type game.
I have look at some similar projects and found Lab Rats that has some the mechanics I want.
The problem is it doesn't run that well.
So I would like to get an idea on what are the pitfalls of renpy that I have to account for.

Some tricky stuff my project will have is procedural dialog that is constructed of a lot of game state data.
I would also need the characters have AI that plans with its own Agency for the next turn/time period.
But don't expect Chat Bot AI or anything, just some swapping some details and tracking some stuff.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
So I would like to get an idea on what are the pitfalls of renpy that I have to account for.
Ren'py is relatively smooth, at least as long as you don't try to works against it, or reinvent it.

But if you use Ren'py correctly, the only real possible slow points are the screens, because they are predicted way before being displayed, then once show/called, they are updated really often (between every 1 and 5 seconds, depending of the game itself and where the screen are in it). Therefore, you have to avoid as much as possible the use of embedded Python ; especially long or slow processing. Prefer to pre-proceed the data before showing/calling the screen, or to rely on custom displayable since they are proceeded a little faster than embedded Python.
Also avoid to have too much events (action, hover, tooltip, etc) on a single screen. Partly because they rely on object often recreated, partly because the detection loop isn't this optimized.

This said, my extended variable viewer proved that a screen wrote in optimized pure Python and with less than 400 events, play smoothly if the game have a reasonable use of resources. Your game will use more resources, but you also should have way less events and computation to create the screen.
But well, anyway in the end, only your own experience will tell you what will be the slow points of your game, because it will mostly rely on what you'll do and how you'll do it.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
That's too bad since I wanted keyword hover that acts like an encyclopedia for various topics.
Well... If you need more than 20 events for this encyclopedia, you are doing it wrong. And the keyword is way more adapted to what you want than the hover one ; even for very complicated cases.

You can also optimize the whole thing by using a custom displayable that would handle its own events in a better way than Ren'py do ; but in this particular case it would be over killing it.
 

DuniX

Well-Known Member
Dec 20, 2016
1,203
797
Well... If you need more than 20 events for this encyclopedia, you are doing it wrong. And the keyword is way more adapted to what you want than the hover one ; even for very complicated cases.

You can also optimize the whole thing by using a custom displayable that would handle its own events in a better way than Ren'py do ; but in this particular case it would be over killing it.
I need more custom data than a tooltip, possibly with nested keywords so you can check multiple related things like in a wiki.
You don't have permission to view the spoiler content. Log in or register now.
But I don't doubt that I can optimize it somehow, It's good to know what I should keep in mind.

Do you have more details or links where I can read about how events are handled and why they are a problem? Some terms I can search for?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
I need more custom data than a tooltip, possibly with nested keywords so you can check multiple related things like in a wiki.
And ?

Don't you think that before starting to think about your big game and its mechanisms, it would be a good idea to start by effectively reading Ren'py documentation ? You don't wonder how you land a plane after the take off, you do it before even taking place in the cockpit.
It apply even more for game development, since the engine you'll use will define how you'll design everything to achieve the result you have in mind. It's really frustrating to plane your code in a certain way, just to discover later (sometimes weeks later) that the engine you use will need another design to do it right.

You want a wiki-like ? Then you're right, the tooltip keyword is not the right choice. Partly because it would force you to split your text, in order to separate the text by itself and the links ; which would imply a processing loop to build the screen, and so (insensibly) slow down the game. Partly because there's already something designed specifically for this kind of behavior, the text tag ; which in fact do even more than said by the documentation, like you discover after some tests.
After, the only constraint would be to not over abuse of this tag. But, because of the way Ren'py deal with events, if you split the text in paragraph displayed independently (each one in its own text statement), it should be possible to have something like 1 000 links in a single screen without really sensible slow down.


Do you have more details or links where I can read about how events are handled and why they are a problem?
[Path to the SDK]/renpy/display/*.py

But if really you want more details, it's relatively simple :
Ren'py will loop over all the elements on the screen each time an event happen, letting them decide by themselves if the even happen inside their boundaries, then if they handle this event or not. This by opposition to a more optimized design, that would test if the event happen inside the boundaries of an elements, then call the related event handler if the answer is yes.
Have to be noted that "on the screen" do not mean "displayed". If you have a viewport 5 times bigger than the game window, all the elements on this viewport will be proceeded, even those that aren't visible right now.


Basically demonstrated, it's the difference between :
Code:
for e in elements:
     e.event( x, y, event )

[...]
def CLASS.event( self, x, y, event ):
    if not self.its_for_me( x, y ):
       return
    if ( event == right_clik ) and have_action:
        return action()
    [...]
def CLASS.its_for_me( self, x, y )
    return ( self.x < x < self.x + self.width ) and ( self.y < y < self.y + self.height )
and :
Code:
for ex, ey, ew, eh, e in elements_pos:
  if ( ex < x < ex + ew ) and ( ey < y < ey + eh ):
      e.event( x, y, event )
      break

[...]
def CLASS.event( self, x, y, event ):
    if ( event == right_clik ) and have_action:
        return action()
    [...]
The difference can seem small, but the optimized version avoid two useless calls (and so two in/out with the language core stack), and stop once an event have been triggered, since it's not possible to have two elements that react to the same event.
The whole loop being proceeded each time an event happen so, among other things, each time the mouse move.



All this being said, and as I already said, nothing will ever beat your own tests ; because in the end you don't necessarily need to know why there's a slow down, but where it happen and how you can avoid it.

Edit:Oops, wrong link for the a tag.
 
Last edited:

DuniX

Well-Known Member
Dec 20, 2016
1,203
797
It apply even more for game development, since the engine you'll use will define how you'll design everything to achieve the result you have in mind. It's really frustrating to plane your code in a certain way, just to discover later (sometimes weeks later) that the engine you use will need another design to do it right.
Which is why I am asking for the performance pitfalls beforehand?
I don't know the internals of renpy beforehand so I don't know what works or not, or what kind of idiosyncrasy it has.
 

Saki_Sliz

Well-Known Member
May 3, 2018
1,403
1,005
So I just googled image searched Performance of Python vs C++, and got a lot of charts showing how various other languages competed (often trying to show other newer languages running faster than C or C++). This single google search now makes me an obvious expert, and I expect my computer science PHD certificate in the mail by tomorrow.

jokes aside, this is what I could conclude: C++ (unoptimized, right out of the box, default compiler settings) is 1 to 2 orders of magnitude faster than python, on the cpu side alone. That means, C++ could handle 10x to 100x the amount of data or background simulations. Ie: if you wanted to simulate characters moving around in the rest of the world (ie they have a schedule), and that's all I can really say to help point out how this may benefit you.

I picked C++ since it is the king of game programming in the professional environment (not that it's there for a good reason however). This is ignoring /O2 C++ compiler setting that can make C++ 3 to 4 magnitudes faster, or 1,000x, to 10,000x faster. I also specified the CPU side since doing things like graphics can be far faster or far slower depending on your graphics api solution. For example, the most common way to speed up performance is to parallelize or batch a lot of operations together, to be handled by multiple cores or by the gpu. Graphics vs normal code, graphics is more greatly impacted by this. With game engines like unity, it handles everything for you and thus the engine tries pretty hard to optimize things. Recently, Godot 2D side added batching (later to be added to their 3D side), which offered the ability to draw the same amout of things at 44 fps to 398 fps (by optimizing draw calls to the gpu). In Monogame, the sprite manager (different than renpy's), due to the engine only being a framework for code and not an actual engine, you have to directly tell the system how to draw (almost), and the sprite manager allows for batched calls to optimize draw calls.


now as far as I understand it, some of the more advanced drawing techniques in renpy, or that is to say, techniques that let you have more direct control over the visuals (manually drawing sprites), can only be done in python scripts. as far as I understand, feel free to correct me if I am mistaken yet again anne O'nymous, the way renpy works is it is an interpreter engine, with the ability to also let you execute python code. That means, renpy scripts themselves aren't python per say, because the interpreter first has to make sure your code is good. By that I mean, I think a while ago we were trying to figure something out about how renpy handles images, and from what anne O'nymous linked me (can't find it so I am trying to explain by memory and basic searches), you let the script know what all your images are, and you can't change them (or the labels?) during run time. Why I point that out is because by forcing a compile time check to make sure everything is good, that can allow the renpy system to be able to optimize draw calls. However, I don't know if it does.

As far as I can tell, the engine is made with python, I can't tell if the engine uses a python only graphics api (meaning that the system can not optimize the rendering), or a c based code with a python interface (run's slightly faster but still can not be optimized at compile time), or if the renpy engine is not in python or has dedicated c code that allows it to be able to optimize draw calls and a pre patching system at compile time, that would be the only way renpy could avoid having a terrible python limited rendering system. The SpriteManager system I pointed out in renpy, because that is python, it can not be pre batched at compile time because the python interpreter is handled separately from the renpy system and does not have a compile time optimizer, unlike java or C#. That mean draw calls with sprite manager may not be the most optimal, but from what I can tell in this ending , it's the ability to use the "show expression repulsor as repulsor" which could indicate that if renpy does utilize a compile time optimization batcher, the sprite manager may be able to take advantage of it (if not then atleast it allows less optimized systems to simple be used in the script as easy as all the other images), but given that the sprite manager is given a python based update function that means it still uses python to animate the image. So if you wanted to use python to create menus, interfaces, or control characters (other than just single image poses), you may only be able to draw a 100 to 500 or so elements before you notice an impact (frames per second starting to get close to a dangerous 30). This includes all the background, characters, and the already existing renpy gui elements like the dialog box. For a more complex game, say an rpg, if you have a lot more graphical elements, then you may need that 1 ot 2 orders of speed increase in other engines. and say you want to do 3D, which has way more than a few thousand elements to draw, its a must to use other systems.

drawing and graphic elements makes more sense since we can see them, it is harder to explain on the cpu side of things, but the only thing I can think of is for some more complex games in renpy, the characters are being simulated in the background, other than that, if you are not regularly calculating things (since the game mostly only progresses when you click), python should be good enough.

Side note: while I love C# because it makes pretty code and i feel like I can optimize it pretty well, I have been looking into the new Rust programming language, since it runs faster than C++, faster than C, is totally memory and thread-safe (allowing multi-threading speed up). While I hate the C++ syntax, and the use of symbols that kinda make the code ugly, I thought I would mention it since this is a post about performance.

also
for ex, ey, ew, eh, e in elements_pos:
YOU CAN DO MULTIPLE VARIABLE LOOPS?!?!?!?!??!
 
  • Thinking Face
Reactions: DuniX

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
now as far as I understand it, some of the more advanced drawing techniques in renpy, or that is to say, techniques that let you have more direct control over the visuals (manually drawing sprites), can only be done in python scripts.
Yes, but also no because there's an ambiguity in all this.
As game developer, yes, you'll write Python lines to use "this function", or "that object", from Ren'py's core. But despite it being wrote in Python, Ren'py don't rely exclusively on it. The most critical parts are wrote in C-Python, and Ren'py rely a lot on Pygame, which is partly wrote in C. Therefore, yes you'll be limited to Python for this, but it will not be necessarily Python script that will handle it.
I feel like I stated the obvious here, but I'm not sure that most of the readers, especially those who don't have a coding background, know/understand that behind a Python keyword, there can be whatever code. I can be Python and the execution of the keyword will be slow, or it can be optimized ASM, and the execution will be atomic.


as far as I understand, feel free to correct me if I am mistaken yet again anne O'nymous, the way renpy works is it is an interpreter engine, with the ability to also let you execute python code.
Interpreted, but more in Perl's definition of the word, than in BASIC's one.

For none technical readers, the BASIC's definition of "interpreted" is that each line is proceeded when it time come. So, when you have some BASIC program that looks like :
Code:
    print "Hello world."
    print "I'm glad to meet you."
The interpreter will :
  1. Parse the first line (decompose it in entities, here a "print" keyword and a "Hello world." text) ;
  2. Identify the keyword and find where is the associated code ;
  3. Execute the associated code by passing it the other entities in the line (so the text) ;
  4. Wait for this code to return ;
  5. Repeat with the second line.
And the Perl's definition is to pre-interpret the code. Therefore, for the same two prints code, what will happen will looks more like :
  • Initialization phase
    1. Parse the first line
    2. Identify the keyword and find where is the associated code ;
    3. Store in memory the call for this associated code, including the parameters ;
    4. Repeat with the second line.
  • Execution phase
    • Proceed the first call ;
    • wait for it to return ;
    • Proceed the second call.

In Ren'py's case, when the game is launched, the code of the game is transformed into Python code. Therefore, the fact that Ren'py use its own language have no cost, because once the game will effectively start, everything will be "in memory compiled" Python.
Paradoxically, the same can't be said about Python code used by the Ren'py code. Inline Python ($ whatever) will be converted into "in memory compiled" Python, then evaluated when the moment will come. And Python blocks (Python:\n whatever) will be converted then executed. Which imply that it will take a little (almost insensible) more time to proceed Python code than pure Ren'py code.

This applying only for Inline Python or Python block, if you intend to use a lot of python, it's better to make it a function or put it into a py file. The gain will be really small (few micro seconds) but if it happen often, it can be sensible in the end.


[...] how renpy handles images, [...] you let the script know what all your images are, and you can't change them (or the labels?) during run time.
side note: It's the images, you can totally mess with the labels at anytimes ;)
Technically you can still change the image in run time, but it will imply that Ren'py will have to proceed them again, which will take a lot of time ; look at the time needed by Lab Rats 2 to start, because the dev decided to totally mess with Ren'py and manually load all the images first.


Why I point that out is because by forcing a compile time check to make sure everything is good, that can allow the renpy system to be able to optimize draw calls. However, I don't know if it does.
It don't optimize it, but I think that what I said above made you understand that you were right, minus the optimization.


[NdA:About Ren'py SpriteManager] So if you wanted to use python to create menus, interfaces, or control characters (other than just single image poses), you may only be able to draw a 100 to 500 or so elements before you notice an impact (frames per second starting to get close to a dangerous 30).
Yes.
Technically speaking, Ren'py is slow because it use an interpreted language (and the slower of them), but practically speaking, nowadays computers made this limitation insensible until the moment when you over do it.

When I first made my Extended Variable Viewer, everything was fine and smooth until the day I tested it with a game that had around 2 000 variables/objects. The processing itself took (from memory) around 0.01 second, the display on screen around 0.2 second, and then, once those 0.21 second where done, come the 4 000 atomic events processing... But as atomic as they can be individually, when you've 4 000 of them called every time the mouse move from one unit, you put your computer on the knees.


also

YOU CAN DO MULTIPLE VARIABLE LOOPS?!?!?!?!??!
Yes... but in fact no.

for ex, ey, ew, eh, e in elements_pos: is an implicit unpacking. elements_pos is a list of ( ex, ey, ew, eh, e) tuples, and each value in the tuple will be assigned to the variable that have the same rank.
But in the end, it's just the Python syntax for :
Code:
for( i = 0 ; i < len( elements_pos ) ; i++ )
{
    int ex = elements_pos[i][0]
    int ey = elements_pos[i][1]
    [...]
}
Python don't have the usual for loop, it can only works with iteration of a list. If you want to loop between 1 and 5, you need to build a [1, 2, 3, 4, 5] list and ask Python to iterate it. Therefore,
for( i = 0 ; i <= 5 ; i++) become for i in range( 1, 6 ).
 

Saki_Sliz

Well-Known Member
May 3, 2018
1,403
1,005
Interpreted, but more in Perl's definition of the word, than in BASIC's one.
I think that is what I was getting at with how the renpy system itself may be able to optimize at complie time. fun fact, when I was doing googling about performance charts, perl was actually one of the faster languages, faster than C++ a lot of the time, while I haven't looked into perl, it sounds like a possible logic or other non declaritive language, where the code designs itself.
side note: It's the images, you can totally mess with the labels at anytimes ;)
(y)
Technically you can still change the image in run time, but it will imply that Ren'py will have to proceed them again, which will take a lot of time ; look at the time needed by Lab Rats 2 to start, because the dev decided to totally mess with Ren'py and manually load all the images first.
ah makes sence, at least it allows you to do that, so that more advance devs can take advantage of it
for ex, ey, ew, eh, e in elements_pos: is an implicit unpacking. elements_pos is a list of ( ex, ey, ew, eh, e) tuples, and each value in the tuple will be assigned to the variable that have the same rank.
That is still cool. I have heard of tuples for years but never really took advantage of them, only really forced to use them in python projects as a core data type that shows up a lot in numpy. I often use python to do quick console based tests, like tricks to randomly order the sound of foot steps/breathing, or test an ai's logic (it helps that I currently have matlab and can use pyplot to graph things, not sure what i'll do when my licence is up). I'll explore a bit to see if I can do a similar syntax with C#, since I really love nice looking code, that looks more like language than code.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
fun fact, when I was doing googling about performance charts, perl was actually one of the faster languages, faster than C++ a lot of the time, while I haven't looked into perl, it sounds like a possible logic or other non declaritive language, where the code designs itself.
Then you were viewing too specific charts. It's a punctually fast language, for specific task (like ) or specific syntax, but globally it can't be this optimized.
But you are mostly right for the rest. While coding language tend to follow the strictness of ASM and later the one of C, Perl is a totally versatile language. Whatever the task (globally speaking) there's always many way to do it, not by changing the algorithm you'll use, but by changing the way you'll transcribe this algorithm. This while with other languages there's generally only one way to transcribe an algorithm.

By example...
You don't have permission to view the spoiler content. Log in or register now.


That is still cool. I have heard of tuples for years but never really took advantage of them, [...]
Technically, they are nothing more than a struct you don't have to declare. Once you've initialized your tuple, you can address each part of it independently. But Python's immutability imply that to change one value you need to assign all of them at the same time.
Python:
t = ( 1, "a string", [ "a", "c", "d" ] )  
class.method( t )
print( t[1] )
t = ( 1, "a string", [ "a", "b", "c", "d" ] )

I often use python to do quick console based tests, like tricks to randomly order the sound of foot steps/breathing, or test an ai's logic (it helps that I currently have matlab and can use pyplot to graph things, not sure what i'll do when my licence is up).
Heretic ! For test there's Perl ;)
I know that I'm a fanboy when it come to this language, but for once I'm 100% serious. It's the most adapted language for testing. It have tons of modules dedicated only for this, some being generalist, other being dedicated to a software or data format, and even the basic modules put any test unit of another language looks like shit.
You don't have permission to view the spoiler content. Log in or register now.
 
  • Red Heart
Reactions: Saki_Sliz

DuniX

Well-Known Member
Dec 20, 2016
1,203
797
On Topic!
I have a couple of questions related to my project.

I want to make Dynamic Scenes with Procedural Dialog.
How I will do it is a While loop in a renpy label, it will have a Turn Order on who gets to act this loop/turn, so you get a natural back and forth, as well as callbacks for character reactions within the loop.
On Player's Turn he gets to act with some actions.
The Dialog Constructor of the string will be in its own python function.
It will probably be a nightmare for the rollback system so that is probably going to be disabled.
The conversation will eventually End either when things are logically resolved or when a certain number of turns are reached, with some possible leeway to forcefully resolved things in the last turns.

The problem I see is since Game Progress is represented dynamically through data and not the usual linear written scripts with label progression, that means Game World Data needs to be saved, how do I am triply sure that the data I need is saved. How do I force Renpy to save some data at a specific time?

Other then that what other kind of issues I might encounter or things to keep in mind?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
I want to make Dynamic Scenes with Procedural Dialog.
How I will do it is a While loop in a renpy label, it will have a Turn Order on who gets to act this loop/turn, so you get a natural back and forth, as well as callbacks for character reactions within the loop.
On Player's Turn he gets to act with some actions.
The Dialog Constructor of the string will be in its own python function.
It will probably be a nightmare for the rollback system so that is probably going to be disabled.
The conversation will eventually End either when things are logically resolved or when a certain number of turns are reached, with some possible leeway to forcefully resolved things in the last turns.
Said like this, it looks like an over complicated way to do something simple. Can you provide some algorithm in pseudo-code to give a better idea about what you mean ?


[...] how do I am triply sure that the data I need is saved.
Why do you want Ren'py to not save something ?
For "global" data, as long as you declared them correctly, by using the default statement, there's just absolutely no reasons for Ren'py to not save them. As for "local" data, they are saved anyway.


How do I force Renpy to save some data at a specific time?
Like said in the page of the documentation, by using . But why do you want to do this ?

Either the game is running, and the data don't need to be saved, or the player choose to quit the game, and surely have a reason to not have saved before doing it.
You can still force a save on quit with , or , but whatever the kind of game, I never saw the interest of such feature in games where you can save at anytime. If the player have to suddenly quit without having the time to save, then it's his fault ; you don't play a game, especially an adult one, at a time where it would mean troubles if you're caught.

If you fear a crash, then you can rely on the auto save feature by changing , , , and . But if you really fear a crash, you should correct your code for it to not crash, not try to limit the consequences for the player.


Other then that what other kind of issues I might encounter or things to keep in mind?
What other kind of issues you might encounter ? Well you clearly want to make your game not by using Ren'py, but by going against it, so there's a tons of possible issues that you or your future players will surely encounter.

The most obvious one is that, basically speaking, when you load a saved file, you're just using an external source to perform a massive rollback. Therefore, whatever you fear that could happen during a rollback, could also happen when the player will load a save.
There's a solution behind most of the rollback issues, but to find them you firstly need to read the documentation and make personal tests to understand what you've read.
The only unsolvable issue I encountered is when the rollback stack end being way shorter than it should, this being due to the way Ren'py handle interactions ; in short there's the right number of rollback entries, but one step back use many of them. But as annoying as can be this issue, it's an insignificant one.


In the end, and like I already said in this thread, start by learning Ren'py, and learning it like it really is, not like others use it. You'll see that, most of the time, there's no need to rely on over complicated code design to do what you want to achieve.

A game like Super Powered is a dynamic sandbox game, and still use really few Python ; and almost only to store the data. It's not a pleasant code to read, nor to works with, and there's many issues, both with the code and with its design, but it achieve to do with Ren'py's language what many tried and failed to achieve with a tons of Python.
Ren'py is not another way to write Python. It's a full engine that come with its own language, amazing possibilities, and that natively offer full dynamism. You should rely on Python only when you can't do it with Ren'py's language, not just when you don't know that Ren'py can do it.

I've looked at the code of most of the games made with Ren'py and available here. Except games made by professional studios, so that are released only in their final version, I never found a game relying massively on Python that haven't been abandoned or have small updates only every now and then.
And there's a reason for this. The devs end overwhelmed by their code, not understanding it anymore and not finding their way through the mess they created. Would they had used Ren'py and not worked against it, that their game would be still alive or updated more often. This just because the code would be clear and the way to pass to the next step easy to see.

Amazing things can be done with Ren'py, like old school 3D (Sakura Dungeon), RPG Maker-like map (Planet Stronghole 2), interesting and intuitive combat system (both games), and much more ; and all this could have been done with less Python, but well. But to do it, even in the way they did it, you first need to know and understand Ren'py.
 

DuniX

Well-Known Member
Dec 20, 2016
1,203
797
Said like this, it looks like an over complicated way to do something simple. Can you provide some algorithm in pseudo-code to give a better idea about what you mean ?
Basically I want to generate dialog from scratch for characters and let the characters interact with each other dynamically.
In other words there won't be any conventionally written lines. No "script".

Why do you want Ren'py to not save something ?
For "global" data, as long as you declared them correctly, by using the default statement, there's just absolutely no reasons for Ren'py to not save them. As for "local" data, they are saved anyway.
The problem I see is if I am going to use lots of World Data and use Python functions and Objects there might be some that I might miss. So I am looking to explicitly tell it to save or have a structure with data that I will be absolutely sure renpy will save properly.

The most obvious one is that, basically speaking, when you load a saved file, you're just using an external source to perform a massive rollback. Therefore, whatever you fear that could happen during a rollback, could also happen when the player will load a save.
I will try to support Rollback. How well does Renpy Rollback work with While loops and Recursive functions? Do conversations get saved in a log?
Like I said dialog is generated from scratch so there might not be any dialog that exists when it's loaded to rollback to.
Otherwise I will probably have certain "checkpoints" in the game where there should not be any problem to save and be loaded.
From my understanding that's what should happen with no rollback option?
In the end, and like I already said in this thread, start by learning Ren'py, and learning it like it really is, not like others use it. You'll see that, most of the time, there's no need to rely on over complicated code design to do what you want to achieve.
That's why I am trying to get a feeling for how renpy works, but I obviously don't know renpys internals yet.

A game like Super Powered is a dynamic sandbox game, and still use really few Python ;
I have looked at some other management/simulator games like Brothel King, so what I want shouldn't be impossible in Renpy one way or the other.
Super Powered using few Python sounds interesting, I will check that out.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
Basically I want to generate dialog from scratch for characters and let the characters interact with each other dynamically.
In other words there won't be any conventionally written lines. No "script".
It still mean way too many things.

[note: I'll use Ren'py/Python based pseudo-code]
Are the dialogs randomly chosen :
Code:
dial = { "scene1": 
           { "line1":
                  [ "Hello, you", "Hello, how you doing ?", "Hello, long time not seen" ],
              "line2":
                  [ "What do you want ?", "You're here because..." ],
              [...]
           }
         [...] }

label whatever:
    girl say random[scene1:line1]
    girl say random[scene1:line2]
Are they depending of the game state:
Code:
label whatever:
    if girl is angry && already seen today:
       "You again ?!!!!!"
    elif girl is in love &&already seen today:
       "Me too I missed you"
    elif girl is in love:
       "I was thinking about you"
    [...]
Are they pseudo AI generated:
Code:
init python:
    def greeting( mood, weight ):
       txt = "Hello"
       if mood == "angry":
           txt = weigthed random ( "You !", "Hello !", "Yes ?" )
       txt += " " + weighted random( "What do you want ?", "Do you think that I want to talk to you ?" )
       [...]

label whatever:
    girl say greeting( actual mood, computed weight )
Why not fully AI build dialogs like grtrader wanted (I'll not give pseudo-code here) ? And I'm surely missing some other possibilities.

Your description is way too generic to effectively mean something.


The problem I see is if I am going to use lots of World Data and use Python functions and Objects there might be some that I might miss. So I am looking to explicitly tell it to save or have a structure with data that I will be absolutely sure renpy will save properly.
Once again, why do you want Ren'py to not save properly ? It's an engine with more than 15 years of development and improvement behind it. If it wasn't saving properly, it would never have had such success.

All you need is to read the documentation, and you'll know what will be saved and what will not be saved. There's also two tutorials here, one from 79flavors and one from me, that explain this.


I will try to support Rollback. How well does Renpy Rollback work with While loops and Recursive functions?
Perfectly well. But obviously, pure Python loops and recursion will only use one Rollback point ; Ren'py isn't a Python interpreter but an engine/language.


Do conversations get saved in a log?
The is obvious for who have read the documentation.


Like I said dialog is generated from scratch so there might not be any dialog that exists when it's loaded to rollback to.
Then the game is broke ; there's ways to have purely unpredictable AI build dialog lines and still retrieve the exact same line when you rollback/load.


That's why I am trying to get a feeling for how renpy works, but I obviously don't know renpys internals yet.
I'll be totally honest, and whatever if it feel harsh: It's not just Ren'py's internals that you don't know.

You don't know what you effectively want for your game, else you would have been able to provide a quick algorithm regarding the dynamism you want for the dialogs. As for your knowledge of Ren'py it's around the basic level ; and I don't talk about Ren'py's internals or features here, but about Ren'py language itself.
What you have is an idea in your head, and what you've seen of Ren'py is the code of some games. The first one isn't enough to translate your idea into an effective game, and the later just enough to make a basic game.

For the game you want to make, which is possible with Ren'py as far as I understood your idea, you need to start with few weeks past reading the documentation, and practicing to understand the effectively possibilities and limits of each statements of Ren'py language. Then, you'll need few more weeks to build the core of your game and fully test it. And it's only when this will be done, that you'll be able to effectively works on the game itself.

While being easy to use, neither Ren'py nor Python are some magical things. Ren'py is still both a game engine and three coding languages (Script, Screen, ATL). You can't use it correctly if you don't firstly start by learning how to use it. And while there's many people here ready to help and to answer the questions, even the more basic ones, we aren't a substitute to the documentation, and we can't magically transfer our knowledge.
Whatever how go we can be at explaining things, you'll really understand them only when you'll have practiced what we said.


I have looked at some other management/simulator games like Brothel King, so what I want shouldn't be impossible in Renpy one way or the other.
Nothing is impossible with Ren'py, not even real time 3D. Which don't mean that it would be smooth, nor that it should be done with Ren'py.


Super Powered using few Python sounds interesting, I will check that out.
It even use too much Python. There's things that could be done directly with Ren'py language ; but I'm not sure that all were effectively available when the game started.
 

DuniX

Well-Known Member
Dec 20, 2016
1,203
797
Are they pseudo AI generated:
Something like that. But with a lot more Data crammed in in terms of Context, Worlds State, Character State,Previous Conversations, etc.
Once again, why do you want Ren'py to not save properly ? It's an engine with more than 15 years of development and improvement behind it. If it wasn't saving properly, it would never have had such success.
Not many simulation/management style games use the rollback system from what I have seen, so it is the exception rather than the rule.
The is obvious for who have read the documentation.
I meant for the rollback. If I put a procedural string from a python function into a renpy say function that is saved? So the python function isn't engaged again in rollback?
There might be some errors if the python function was activated again and was keeping track of some local variables that were lost after load.
And while there's many people here ready to help and to answer the questions, even the more basic ones, we aren't a substitute to the documentation, and we can't magically transfer our knowledge.
Your doing a fine job with a heads-up to know what to look for.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,355
15,269
Not many simulation/management style games use the rollback system from what I have seen, so it is the exception rather than the rule.
Because the dev decided to mess with one of the most interesting feature of Ren'py for the players. But I systematically restore the rollback feature in all Ren'py game I play, and rarely find effective problems with the rollback. There's times where it rollback too deep, but it's due to a flaw in the design of the code, not to an effectively problem with the rollback.
Anyway, will the effect of the rollback can be totally weird and all, it don't change the fact that the variables that had to be saved have been correctly handled by Ren'py. It's just that the dev didn't understood how it works. And for this there's no effective need to know Ren'py's internal.
Few lines of codes are enough. Something like this by example :
Code:
init python
    class MyClass():
        def __init__( value ):
            self.value = value
            self.internal = None

    var1 = MyClass( "init" )

define var2 = MyClass( "define" )
default var3 = MyClass( "default" )

label start:
    "interaction"
    $ var1.internal = "var1"
    $ var2.internal = "var2"
    $ var3.internal = "var3"
    "another interaction"
    "and a break to avoid optimization effect"
    "[var1.internal] / [var2.internal] / [var3.internal]"
    "Save here and load without quitting"
    "[var1.internal] / [var2.internal] / [var3.internal]"
    "Again an interaction"
    "Save here, quit Ren'py, restart then load"
    "[var1.internal] / [var2.internal] / [var3.internal]"
    "Test done"


I meant for the rollback. If I put a procedural string from a python function into a renpy say function that is saved?
If you write your code correctly, yes. If you don't, then no.


So the python function isn't engaged again in rollback?
Why should they ? Like I said, Ren'py is not a Python interpreter. It can handle Python code, but it's designed to works with its own language. The rollback keep trace of the state of the game as known by Ren'py, which include the variables. If you stop to use Ren'py, you also enter in a blind spot for Ren'py.
By example, I can write a diary of what my family do day by day. For me I can write everything, but for my children (well, when they were still living with me) I can only write what they do in the room I am. If they goes to their bedroom, I'll know that they are doing something, but not know what. But, it they goes in there saying, "I'll do my homework", or come back with their dirty clothes, then I can write what they did, because I have evidences about it. yes, I'm naive and trust them when they say that they'll do their homework

The same apply for the rollback. Ren'py can only rollback to the state it know about. If you hide what you're doing, he can't include it in its rollback system. It doesn't mean that you can't use Python and still have a full working rollback, just that you have to tell Ren'py what you did ; which globally mean changing the value of some variables.
And once again, all this come from practice.