Ren'Py [solved]Using classes for random character generation?

Lou111

Active Member
Jun 2, 2018
538
680
I'm back...

Firstly, I'm not married to using classes, or anything for that matter. Here's where I'm at:

My goal is to use a template for generating random characters.
I've created a class thinking I could create different types of people with varying statistics which I could then modify after interacting with them in the game.
Too easy.

Here's the logic:
You don't have permission to view the spoiler content. Log in or register now.

Every dude in the list takes the parameters set by the final randomized dude.
I understand how and why the variable is taking on the same value, but I don't know how to work around it...

I've already tried using baby syntax. I spent all day on this, converting parameters using loops and returning dictionaries... (Don't laugh)
I know I said I'd tone it down but I feel like this is pretty basic... intermediate at best.

Googling how to use classes properly returns comical results and every vid I've watched doesn't really explain anything. If someone has a link to something useful it would MUCH appreciated!

Thanks all
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
I've not read the body of your message yet, but I did have an initial reaction...

If your game has any sort of story telling aspects to it (I'm assuming the VN part of AVN still applies), perhaps consider having a list of prerolled characters templates that are assigned randomly to each of your characters.

From a game balancing point of view, it's much better to know ahead of time the sort of people your MC will encounter. Whilst the player might not know initially which archetype the character is, it is helpful to know that there is still a full (balanced) rosters of characters to encounter.

For example. Let's say you had a "bisexual" marker for each characters. Random assignment would, on average, likely mean half your characters end up bisexual. Except that number feels high to me for normal demographics. Also would if fit the theme of the game? You could code around that, but there's still the risk. Or perhaps you could have a "moral" stat (range 1 to 10) for each character, where game content is gated behind if char.moral <= 4. Sounds fine, until you realize that using random numbers might mean there end up being some unlucky players where sheer bad luck means ALL their characters end up with a moral score of 9 and above... and as a result, a lot of content within the game becomes unavailable. Such is the nature of random numbers.

To my mind, it is safer to have a list of predefined attributes randomly assigned to group of characters. If you have 9 characters, then you have an array of 9 pre-rolled characters that are assigned on a 1:1 basis. That way you ensure you ALWAYS have at least one character with high moral standards and one with low moral standards (or whatever stats matter to your game). Thereby retaining game balance. That is, remove the renpy.random.whatever() code and do all that stuff yourself by hand as part of your game design.
 
Last edited:

Lou111

Active Member
Jun 2, 2018
538
680
I've not read the body of your message yet, but I did have an initial reaction...

If your game has any sort of story telling aspects to it (I'm assuming the VN part of AVN still applies), perhaps consider having a list of rerolled characters templates that are assigned randomly to each of your characters.
Thank you for your reply! No idea why the site didn't notify me...

This is for random one-off encounters while the MC is out on the town!

I'm also trying to build a combat system using this, so from that perspective, these characters will be very short-lived.
Random encounters will use an extensive image library and battle encounters will need a wide variety of stat parameters that will need to be changeable, customizable, and put through some functions and stuff.
 

Lou111

Active Member
Jun 2, 2018
538
680
I know this is cheating but let slide in a sneaky one.
How do you stop a video from looping when played in a screen?
I register the video to a channel with looping == False and also say 0 loops and it just keeps on keeping on...
I could do something really neat if I could change that.

Python:
init python:
    renpy.music.register_channel("movie", mixer="voice", loop=False, stop_on_mute=False, tight=False, file_prefix='', file_suffix='', buffer_queue=True, movie=True)
    
    setattr(store, "/movie/movie.webm", Movie(size=(480,720), play="/movie/movie.webm", channel="movie"))

label start:
    var1 = "/movie/movie.webm"


screen movie1():
    add getattr(store, var1):
        xalign 0.5
        ypos 75
        SetVariable(PleaseStopLooping, True)

Thanks! (y)
 
Last edited:

Lou111

Active Member
Jun 2, 2018
538
680
Well I got it to work. I isolated what I didn't understand and used baby syntax to work around it.

I created a list of "blank" objects and created a function that takes a random template and redistributes them directly to the predefined object variable rather than trying to duplicate an object, applying randomizers and appending it to a list...

I've never seen so many uses of global in a function so I know it's janky, but if it works it works, right?

I gotta call this solved and repost my screen question!
Thanks all
 

xj47

Member
Nov 4, 2017
240
399
From what I can tell the issue with your code is that to "generate" new people you are actually just modifying the two people you manually created and saving a reference.

When you assign an object (like an instance of the People class) to a variable you are setting a *reference* to the object.
For example if you write:
Python:
a = object()
b1 = a
b2 = a
b3 = a
Only *one* instance of the object exists even though all 4 variables hold a reference to it.

With the code you have, you are not creating a *new* randomized people objects, just modifying the 2 you had defined at the start. And if you try generating more than 2 you are guaranteed to end up with duplicated references.

To fix this you need to make a copy of the template People object when creating a random variant.

I'd suggest adding a "clone" function to your People class that looks like:
Python:
def clone(self):
    return PEOPLE(self.name,
                    self.filename,
                    self.looks,
                    self.affection)
And then your later line looks like:

Python:
# Pick a random person from the people list
template_dude = renpy.random.randomchoice(People_List)
random_dude = template_dude.clone()
 
  • Love
Reactions: Lou111

Lou111

Active Member
Jun 2, 2018
538
680
From what I can tell the issue with your code is that to "generate" new people you are actually just modifying the two people you manually created and saving a reference.

When you assign an object (like an instance of the People class) to a variable you are setting a *reference* to the object.
For example if you write:
Python:
a = object()
b1 = a
b2 = a
b3 = a
Only *one* instance of the object exists even though all 4 variables hold a reference to it.

With the code you have, you are not creating a *new* randomized people objects, just modifying the 2 you had defined at the start. And if you try generating more than 2 you are guaranteed to end up with duplicated references.

To fix this you need to make a copy of the template People object when creating a random variant.

I'd suggest adding a "clone" function to your People class that looks like:
Python:
def clone(self):
    return PEOPLE(self.name,
                    self.filename,
                    self.looks,
                    self.affection)
And then your later line looks like:

Python:
# Pick a random person from the people list
template_dude = renpy.random.randomchoice(People_List)
random_dude = template_dude.clone()
YEEEEEEEEEEEES!!!
That what I'm talkin about!
Thank you so much! I have no idea why that was so hard for me...
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
I'm being lazy here, as I still haven't gone over the original message...

But if your solution is that you weren't creating a new object and where instead just creating a link (reference) between a new and old object... then surely you don't need to create a custom function like .clone()?

Shouldn't you be able to use python's .copy()? - random_dude = template_dude.copy().
 
  • Wow
Reactions: Lou111

xj47

Member
Nov 4, 2017
240
399
Shouldn't you be able to use python's .copy()?
True, you could do that too.

Personally I like writing my own "clone" function when necessary because depending on the class a generic function like copy() might create an improper object. But ya, in this situation it should be fine.
 
  • Love
Reactions: Lou111

Lou111

Active Member
Jun 2, 2018
538
680
But if your solution is that you weren't creating a new object and where instead just creating a link (reference) between a new and old object... then surely you don't need to create a custom function like .clone()?

Shouldn't you be able to use python's .copy()? - random_dude = template_dude.copy().
Ah cmon! See? They didn't teach me about .copy().
I'm so happy to know about it now but I don't know how to justify the past 3 days :LOL:
Don't bother reading the body, you nailed the issue. Thanks for responding!

Personally I like writing my own "clone" function when necessary because depending on the class a generic function like copy() might create an improper object. But ya, in this situation it should be fine.
.copy() sounds so much easier than what I'm staring at right now so I'm going to try that out. Your solution was what I was trying to accomplish from the beginning but couldn't fit the block in the hole...
I'm just trying to create temporary people with slightly different integers for stats. The object will also have a list with a few strings in it. Hopefully this will do the trick.


Thank you both for everything. I think I'll take a day off instead of running back at it, which is how I ended up here...
Gotta convince myself the past 3 days helped me build "character" instead of building any progress in my game :ROFLMAO: :coffee:
*kisses*
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,284
If your game has any sort of story telling aspects to it (I'm assuming the VN part of AVN still applies), perhaps consider having a list of prerolled characters templates that are assigned randomly to each of your characters.
Eventually he can go as far as giving a value range for the characters, but I agree that it shouldn't go further if there's a story behind.

It would be something like:
Code:
class RandomChar( renpy.python.RevertableObject ):
    def __init__( love, corruption, BDSM ):
        self.love = renpy.random.choice( love )
        self.corruption = renpy.random.choice( corruption )
        self.BDSM = renpy.random.choice( BDSM )

default thisGirl = RandomChar( [1,2,3], [5,6,7], [0] )
"thisGirl" will then start with a love for the MC between 1 and 3, she's already a little corrupted (between 5 and 7), and do not like BDSM.

It should probably be improved, in order to pass a range ((1, 10)) instead of values like actually, but it's the idea.
 
  • Love
Reactions: Lou111

Lou111

Active Member
Jun 2, 2018
538
680
Eventually he can go as far as giving a value range for the characters, but I agree that it shouldn't go further if there's a story behind.

It would be something like:
Code:
class RandomChar( renpy.python.RevertableObject ):
    def __init__( love, corruption, BDSM ):
        self.love = renpy.random.choice( love )
        self.corruption = renpy.random.choice( corruption )
        self.BDSM = renpy.random.choice( BDSM )

default thisGirl = RandomChar( [1,2,3], [5,6,7], [0] )
"thisGirl" will then start with a love for the MC between 1 and 3, she's already a little corrupted (between 5 and 7), and do not like BDSM.

It should probably be improved, in order to pass a range ((1, 10)) instead of values like actually, but it's the idea.
Whoo!
This will cut out so much stuff I've done!
You should see the pages of loops and modifiers I have when I could've just randomly created them with this.
Lord almighty. Forget the day off tomorrow, I'm too stoked.
But seriously, it pains me to know that there's stuff like .copy() out there that I'm not aware of. I'm trying to find some kind of reference list for these cheaky codes they don't mention in courses...

Thank you for this!
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
But seriously, it pains me to know that there's stuff like .copy() out there that I'm not aware of.

At the heart of things, anytime you use $ - that's "do something with python". So some knowledge of python can be helpful when you get beyond the basics of RenPy.

My two references are:


Though, because I don't have a project of my own, researching other people's issues has taught me some off-the-beaten-track solutions that most people don't need. I also came from a commercial programming background - and whilst that wasn't in python or anything vaguely like python, a lot of of core concepts remain.

For example, I only know about .copy() due to researching a similar problem for someone. Which led me to write the lists/dictionaries/classes tutorial included in my .sig.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,284
But seriously, it pains me to know that there's stuff like .copy() out there that I'm not aware of.
Time to throw some important knowledge, and tarnish my aura:

There's stuff I'm not aware of, regarding both Python and Ren'Py. And the same apply at works, there isn't a month without someone teaching something to the senior programmer I am. Sometimes it's a junior who came with his fresh mind and see the obvious I'm blind to. Sometimes it's a senior, who have an experience different to mine, and therefore also a different knowledge.

There's no shame in not knowing something, nor need to feel pain because of this. Especially when it's not your job, your language, or your field. One is not "stupid", or whatever he think about himself, because the solution gave by someone feel so simple, natural or obvious. He wasn't "aware of", what is something different.
Smartness isn't to know everything, but to know where to search/ask, and to accept that everyone can have something to teach you regarding what is your field of knowledge, even when you're the number one expert.
 

Lou111

Active Member
Jun 2, 2018
538
680
anne O'nymous 79flavors
You guys are getting me all worked up! Thank you both, it really means the world to me.
Instead of getting all mushy I'll say the same thing I said at the start of this year when the two of you helped me get started with Ren'Py: I'll do my best to reflect my gratitude through my efforts. I want you to know that if it ever seems that I'm reluctant to ask you for help it's because I'm just itching to show you guys the monster you've created :giggle: and on that day I want a good portion of the game to be the result of my own training.
 
Last edited:
  • Like
Reactions: anne O'nymous