Changing other variables inside a class

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
EchoEcho
Newbie
Posts: 5
Joined: Tue Apr 30, 2019 3:50 am
Contact:

Changing other variables inside a class

#1 Post by EchoEcho » Sat Dec 07, 2019 9:59 pm

Hello Everyone. I tried to find the answer on my own, but I didn't see what I was looking for. Or maybe I didn't use the right keywords.

tl;dr: Can you change an unrelated variable inside another class?

Anyway, in my game, I want Characters to be in different locations at different times of the day. But I want there to be a sort of weighted system, as well. Person A isn't ALWAYS in the Bathroom in the morning, for example. But when she IS in the bathroom, she isn't anywhere else, if that makes sense.

That is easy enough to call once or twice with

Code: Select all

$ d20 = renpy.random.randInt (1,20)
if d20 > 10:
	$ aLoc = "bathroom"
else:
	$ aLoc = "somewhere else"
But I have quite a few characters. And any number of them could be in any number of places. So the code gets exponentially longer with more people/places.

That is further compounded by time. I am using a class I saw here a while ago for time/date stuff.

Code: Select all

class gameTime:
        gamePeriods = ("Early Morning","Morning","Late Morning","Afternoon","Midday","Evening","Night","Late Night")
        def __init__(self):
            self.now = 0
            self.hours = 12
            self.day = 1
            self.periodCount = 0
            self.timeSlept = 0
        def tAdvance(self, n=1):
            self.hours += n
            self.periodCount += n
            if self.hours >= 24:
                self.hours -= 24
                self.day += 1
            day = self.day
            while self.periodCount >= 3:
                self.advance()
                self.periodCount -= 3
        def advance(self, n=1):
            self.now += n
            self.update()
        def sleepMorning(self):
            self.timeSlept = 1
            self.tAdvance()
            while self.hours != 6:
                self.tAdvance()
                self.timeSlept += 1
        def hoursSlept(self):
            return self.timeSlept
        def period(self):
            return gameTime.gamePeriods[self.now % len(gameTime.gamePeriods)]
        def update(self):
            if self.now >= len(gameTime.gamePeriods):
                self.now -= 8
        def date(self):
            return str(self.day)
        def getHours(self):
            return str(self.hours)
        def tSet(self, n=1):
            self.timeSlept = 1
            while self.hours != n:
                self.tAdvance()
                self.timeSlept +=1
In my situation, I want the character's locations to change based on a weighted value every time the game updates into a new "period" (Morning, Afternoon, Night, blah blah). But I can't seem to get things to work out for me. If I change "update" to include something easy like this:

Code: Select all

default aLoc = "bathroom"

class gameTime:
(...rest of the time class)
        def update(self):
            aLoc = "kitchen"
            if self.now >= len(gameTime.gamePeriods):
                self.now -= 8
(... rest of the time class)

label start:
	$ g_time = gameTime()
	$g_time.tAdvance(12)
	a "I am in the [aLoc]!"
Nothing changes. The value itself doesn't change, and a will stay in the bathroom (poor girl). I don't know if you can affect outside variables INSIDE a class... And I'm having a dickens of a time with the cookbook finding the right info.

I'm also trying to figure out a more elegant way of dealing with the weighted nature of the character's schedules. instead of using renpy.random.randInt for everything.

Does anyone have any input? Or maybe push me in the right direction? Right place to look and all that?

Thank you so much!
Good vibes out,
EchoEcho

User avatar
deltadidirac
Regular
Posts: 121
Joined: Fri Nov 30, 2018 5:00 am
Projects: Slip Over Time
Tumblr: deltadidirac
Deviantart: Deltadidirac67
Location: Europe
Contact:

Re: Changing other variables inside a class

#2 Post by deltadidirac » Sun Dec 08, 2019 5:08 am

HI

I had the same problem even me, then I realized that to deal with situations like these without being an expert of renpy (i.e being able to change, build, recall and modify the code as you like), I would never have succeeded to find a solution, or I would have lost weeks to fix it ...

I, as an inexperienced user, can only suggest this ... DO NOT use the "random" function.
build yourself a well-defined weekly scheme and give each character two or three possibilities for outgoing events, assigning one or more variables for each events ...
  • A) Monday morning: it's in the bathroom / or it's in the livingroom / or it's in the kitchen
    Monday afternoon: etc ....
  • B) Monday morning: is in the corridor / or is in the bathroom / or is in the bedroom
    Monday afternoon: etc .....
When you did the whole scheme and assigned the variables (usually booleans are enough) .... for example "default loc_A_bath = True" - "default loc_B_bath = False" etc ...

Or build a series of discriminating labels without dialogue to use it with if / else that work as an "engine" and lead you to the final label of the event you want ... or (if you are capable, build an algorithm with some functions that do the same thing)

The trick is to give more than one possibility to each character for the same "time", so even if in reality everything is already predefined, for the player it will appear random because it will never see the same thing at the same time twice in a row (but only after a certain interval).

I do not write all my code here because it is long and composed of many different parts that do other things too .... but the concept described is this.
I am only attaching one of the many schemes that I have built and that serve precisely for this type of situation. This scheme it's one at the begin of all the structure and is build for the single location, after this scheme, there will be others that doing the same things for the different characters, and so on....
PS
About your question you must focus your attention on the "routine labels" that you can see in the scheme:

Image

User avatar
deltadidirac
Regular
Posts: 121
Joined: Fri Nov 30, 2018 5:00 am
Projects: Slip Over Time
Tumblr: deltadidirac
Deviantart: Deltadidirac67
Location: Europe
Contact:

Re: Changing other variables inside a class

#3 Post by deltadidirac » Mon Dec 09, 2019 8:32 am

EchoEcho wrote:
Sat Dec 07, 2019 9:59 pm
Hello Everyone. I tried to find the answer on my own, but I didn't see what I was looking for. Or maybe I didn't use the right keywords.

tl;dr: Can you change an unrelated variable inside another class?

Anyway, in my game, I want Characters to be in different locations at different times of the day. But I want there to be a sort of weighted system, as well. Person A isn't ALWAYS in the Bathroom in the morning, for example. But when she IS in the bathroom, she isn't anywhere else, if that makes sense.

That is easy enough to call once or twice with

Code: Select all

$ d20 = renpy.random.randInt (1,20)
if d20 > 10:
	$ aLoc = "bathroom"
else:
	$ aLoc = "somewhere else"
But I have quite a few characters. And any number of them could be in any number of places. So the code gets exponentially longer with more people/places.

That is further compounded by time. I am using a class I saw here a while ago for time/date stuff.

Code: Select all

class gameTime:
        gamePeriods = ("Early Morning","Morning","Late Morning","Afternoon","Midday","Evening","Night","Late Night")
        def __init__(self):
            self.now = 0
            self.hours = 12
            self.day = 1
            self.periodCount = 0
            self.timeSlept = 0
        def tAdvance(self, n=1):
            self.hours += n
            self.periodCount += n
            if self.hours >= 24:
                self.hours -= 24
                self.day += 1
            day = self.day
            while self.periodCount >= 3:
                self.advance()
                self.periodCount -= 3
        def advance(self, n=1):
            self.now += n
            self.update()
        def sleepMorning(self):
            self.timeSlept = 1
            self.tAdvance()
            while self.hours != 6:
                self.tAdvance()
                self.timeSlept += 1
        def hoursSlept(self):
            return self.timeSlept
        def period(self):
            return gameTime.gamePeriods[self.now % len(gameTime.gamePeriods)]
        def update(self):
            if self.now >= len(gameTime.gamePeriods):
                self.now -= 8
        def date(self):
            return str(self.day)
        def getHours(self):
            return str(self.hours)
        def tSet(self, n=1):
            self.timeSlept = 1
            while self.hours != n:
                self.tAdvance()
                self.timeSlept +=1
In my situation, I want the character's locations to change based on a weighted value every time the game updates into a new "period" (Morning, Afternoon, Night, blah blah). But I can't seem to get things to work out for me. If I change "update" to include something easy like this:

Code: Select all

default aLoc = "bathroom"

class gameTime:
(...rest of the time class)
        def update(self):
            aLoc = "kitchen"
            if self.now >= len(gameTime.gamePeriods):
                self.now -= 8
(... rest of the time class)

label start:
	$ g_time = gameTime()
	$g_time.tAdvance(12)
	a "I am in the [aLoc]!"
Nothing changes. The value itself doesn't change, and a will stay in the bathroom (poor girl). I don't know if you can affect outside variables INSIDE a class... And I'm having a dickens of a time with the cookbook finding the right info.

I'm also trying to figure out a more elegant way of dealing with the weighted nature of the character's schedules. instead of using renpy.random.randInt for everything.

Does anyone have any input? Or maybe push me in the right direction? Right place to look and all that?

Thank you so much!
Good vibes out,
EchoEcho

Since no one answered and ...
since your question also interested me, I wanted to know if I wrote nonsense or I didn't understand the meaning you wanted to give ...

bye

User avatar
EchoEcho
Newbie
Posts: 5
Joined: Tue Apr 30, 2019 3:50 am
Contact:

Re: Changing other variables inside a class

#4 Post by EchoEcho » Wed Jan 15, 2020 1:19 am

@deltadidirac
Thank you so much for your reply! To be honest, after I posted, I tried again down my own path that I was on, and got really frustrated, and decided to take a break for a while. I only JUST NOW remembered I asked about this.

Your suggestion is very nice. I was looking at the problem wrong, by trying to make things unrelated and random. In the way I was doing it, for example, there was a possibility of Character A having this schedule: "Bathroom, Shower, Shower, Kitchen, Bathroom, Bathroom, Shower, Kitchen, Sleep" for a day. Which is... No good, haha.

I think I will follow your suggestion. Have maybe 3 or 4 different possible schedules, and randomly call one every day. That way, if I label the list correct, I should be able to get values and more data out of them.

Thank you again for the time and effort you put into this response. Your help will not be in vain!

Good vibes out,
EchoEcho

User avatar
RicharDann
Veteran
Posts: 264
Joined: Thu Aug 31, 2017 11:47 am
Contact:

Re: Changing other variables inside a class

#5 Post by RicharDann » Wed Jan 15, 2020 3:26 pm

Not to take away from what has been discussed, but thought I'd explain a possible reason why the "aLoc" variable isn't being updated inside the function.

Python functions make use of local and global variables, locals being the ones defined "inside" a function, and globals being those defined outside, like the ones created with default.

Since aLoc was created with default, it is global, so to use it and change it with the update() function from your gameTime class, you'd have to tell Ren'Py to look for it in the globals, by adding a very simple line:

Code: Select all

def update(self):
    global aLoc 
    aLoc = "kitchen"
    if self.now >= len(gameTime.gamePeriods):
        self.now -= 8
This way aLoc will be properly changed. If you don't, what Ren'Py does is create a new local variable named aLoc, and set it to the string "kitchen", leaving the global aLoc intact.
The most important step is always the next one.

Post Reply

Who is online

Users browsing this forum: No registered users