Ren'Py Reset time in Python Class

Zenathos815

Newbie
Jul 26, 2017
56
26
So I am about to get super stubborn with this calendar class I have been working on because I dug it up from lemmasoft and modified it to suit my needs but I am having some major trouble getting the damn thing to reset. I don't want to totally scrap it because I have it set up with a basic display calendar and have it worked into the code all sorts of other places.

It's been a long time since I have python'ed around and 90% of what I have going is working well. the problem I have is that I plan on using "months" as stages and since this thing was more meant to lay out a full year I may be using it against it's purpose.

Here is the class I am messing with and a sample in case anyone wants to poke it

Code:
init -2 python:
    class Game_Time:
        PERIODS = ("Dawn", "Morning", "Shift2", "Afternoon", "Shift3", "Evening", "Night", "Late Night")
        MONTHS = ("week1", "week2", "week3", "week4")
        WEEK_DAYS = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
        MONTHS_DAYS = (7, 7, 7, 7)
       
        def __init__(self, now = 0):
            self.period = 0
            self.day = 0
            self.week = 0
            self.week_day = 0
            self.month = 0
            self.month_day = 0
            self.now = now
            self.update()

        def advance(self, n = 1):
            self.now += n
            self.update()
           
        def reset(self, now = 0):
            self.period = 0
            self.day = 0
            self.week = 0
            self.week_day = 0
            self.month = 0
            self.month_day = 0
            self.now = now
            self.update()
           
        def update(self):
            self.period = self.now % len(Game_Time.PERIODS)
            self.day = self.now / len(Game_Time.PERIODS)
            self.week_day = self.day % 7
            self.week = self.day / 7
            day = self.day
            self.month = 0
            #month = self.month % 4

            while day >= Game_Time.MONTHS_DAYS[self.month]:
                day -= Game_Time.MONTHS_DAYS[self.month]
                self.month += 1
            month_day = day + 1
       

        def period_name(self):
            return Game_Time.PERIODS[self.period]
           
        def week_day_name(self):
            return Game_Time.WEEK_DAYS[self.week_day]
           
        def month_name(self):
            return Game_Time. MONTHS[self.month]
           
        def date_name(self):
            return self.week_day_name() + ", " + self.month_name() + " "
The problem I am running into is when you reach past the full cycle the damn thing stops altogether. It gets caught up on that while statement. I did rename the "months" to weeks 1-4 because I plan on actually creating months as a way of formatting stages that loop so the player can replay that month either because they haven't met the requirement to move on or because they feel like it. I put a stupid time advance in there that I can call with a timeskip label which includes an if statement that is meant to reset the time if it exceeds the counter set by this however it totally skips the reset due to the while statement. I know I am missing something simple in regards to using the class to reset itself but I am fried from building the general game structure as far as locations, character art, and trying to figure out how I am actually going to work the other core mechanics. I have a nearly functional demo working if only I could get this bastard to reset when it cycles through all 4 weeks. any help would be awesome
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,957
16,190
The problem I am running into is when you reach past the full cycle the damn thing stops altogether.
Obviously since there's nothing in the code which handle this. The moment there's no more gasoline in your car, the car stop ; you don't expect it to go by itself to the gas station.
It's exactly the same thing here. The instant the code reach the end of the calendar, it stop because it don't know how to go one year further.

here's a quick little fix :
Code:
       def __init__(self, now = 0):
           [...]
           self.year = 0

        def update(self):
           [...]

            while day >= Game_Time.MONTHS_DAYS[self.month]:
                day -= Game_Time.MONTHS_DAYS[self.month]
                self.month += 1
            while self.month>= len( self.MONTHS ):
               self.month -= len( self.MONTHS )
               self.year += 1
            month_day = day + 1
But it's really just a quick fix wrote on the corner of a napkin. I'm not even sure that it really work since there's so many things that seem/are wrong in this code.
Just an example, the "month_day = day + 1" at the end of the update method. What's the meaning of this ? It increment the day of the month without a single condition, which mean that the 1st february, month_day is 32, the 1st March it will be = 61, and so on.
The better solution is probably to restart all the code from scratch.
 
  • Like
Reactions: Zenathos815

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,957
16,190
Code:
    class RenpyCalendar( object ):

        # Times of the day by their name
        todByName = [ "Dawn", "Morning", "Shift2", "Afternoon", "Shift3", "Evening", "Night", "Late Night" ]
        # Days of the week by their name
        dowByName = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]
        # Month by their name
        monthByName = [ "month1", "month2", "month3", "month4" ]
        # Number of days in a week
        dayInMonth = [ 6, 6, 6, 6 ]

        def __init__(self, tod=0, dow=0, dom=0, month=0 ):
            self._tod = tod   # Time of the day
            self._dow = dow   # Day of the week
            self._dom = dom   # Day of the month
            self._month = month # Month
            self._year = 0      # Year
            self._days = 0  # Total number of days since (in game) day 0

        def _advanceDay( self, n=1 ):
            self._days += n
            self._advanceDow( n )
            self._advanceDom( n )

        def _advanceDow( self, n ):
            self._dow += n
            while self._dow >= len( self.dowByName ):
                self._dow -= len( self.dowByName )
           
        def _advanceDom( self, n ):
            self._dom += n
            while self._dom >= self.dayInMonth[ self._month ]:
                self._dom -= self.dayInMonth[ self._month ]
                self._month += 1
                if self._month >= len( self.monthByName ):
                    self._month = 0
                    self._year += 1
           
        def reset( self ):
            self._tod = 0
            self._dow = 0
            self._dom = 0
            self._month = 0
            self._year = 0
            self._days = 0
       
        def advancePeriod( self, n=1 ):
            self._tod += n
            while self._tod >= len( self.todByName ):
                self._tod -= len( self.todByName )
                self._advanceDay()

        def timeOfDay( self ):
            return self.todByName[self._tod]
           
        def dayOfWeek( self ):
            return self.dowByName[self._dow]

        def month( self ):
            return self.monthByName[self._month]

        # "{2} {1} {3} - {0}".format( obj.fullDate )
        def fullDate( self ):
            return ( self.timeOfDay(), self._dom+1, self.dayOfWeek(), self.month(), self._year+1 )
Alright, I haven't tested it as deeply as I should have, but it should do it without problem.

Create the object this way :
Code:
 myCalendar= RenpyCalendar()
First day of the first month of the first year, first period of the day.
Code:
 myCalendar= RenpyCalendar( tod=2, dow=2, dom=0, month=1 )
Tuesday 1 month2, first year, shift2

As stated by the __init__ declaration, each argument is optional.

Advance should work like the class you posted, as long as I understand it ; by increasing the period/tod.
The other methods are implicitly privates, but well, what's a private method in Python...

The fullDate method is designed for ease the use of format.
Code:
  text "{2}, {1} {3} - {0}".format( obj.fullDate() )
will display "Tuesday, 1 month2 - shift 2"
Code:
  text "{0} - {1} {3} ({2})".format( obj.fullDate() )
will display "shift2 - 1 month2 (Tuesday)". And so on, it's the usual format usage.
 
  • Like
Reactions: Zenathos815

Zenathos815

Newbie
Jul 26, 2017
56
26
@anne O'nymous Holy Shit! That did it! I converted some of the things back to my nomenclature since I had so many functions defined throughout a few different scripts, but the loop works perfectly! I also saw alot of errors after you made the gas in the car analogy, I need to really brush up on my python again I seriously glazed over that part when I decided to make a game with so many mechanics and hand drawn characters. On a macro level everything is planned out and the thought process is good, the fine details in the actual code writing definitely need revisiting before I release this first demo. You saved me a major headache, the time advancement is working perfectly I just need to get some more things in place and finish more than just the one character. Much appreciated!
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,957
16,190
Holy Shit! That did it!
Well, in fact there's three (really minor) errors. But don't know why, I can't edit the message. So here they are :
In the declaration of _advanceDom and _advanceDow I forgot to put a default value to 'n'.
Code:
    def _advanceDom( self, n=1):
    def _advanceDow( self, n=1):
The third error was in my explanations :
Code:
text "{0} - {1} {3} ({2})".format( obj.fullDate() )
will not work. I forgot too often that list/tuple need to be unpacked first. It should have be :
Code:
text "{0} - {1} {3} ({2})".format( [b]*[/b]obj.fullDate() )

Conclusion: Don't fully rely on tests wrote in the middle of the night. Especially if they need to validate something you also wrote in the middle of the night.