Help with setting up a day / week cycle in Renpy

Ryder77

Member
Game Developer
Sep 9, 2017
462
384
Here's what I want to accomplish.

I want to set up a seven day cycle (a week), Monday through to Sunday.

On Monday to Friday, only Evenings will be available to play (MC has a day job). On Saturday / Sunday, absent special events, the Day, Afternoon and Evenings will be playable.

Each time period (Day / Afternoon / Evening) has a certain number of Action Points, which are used up as the MC does stuff. When the AP's are used up, the time period ends and the game moves on to the next day.

I've seen bits and pieces of this on other threads, but nothing that quite gets at such a system. If anyone can suggest some coding to achieve goal, I'd greatly appreciate it.
 

mickydoo

Fudged it again.
Game Developer
Jan 5, 2018
2,446
3,548
In my game my time/day cycle like the rest of my code is what is called kiss - keep it simple stupid. As I don't know what I am doing half the time I had to come up with a way that I could implement, control, and more importantly understand, so if something broke i could fix it. What I came up with was this.

I have two variables
$ Player_Points
$ Day_Points

At the start of the script where I have defined the names etc I have
$ Player_Points = 8 (as in the day starts at 8 am)
$ Day_Points = 1 (as in 1 is Monday)

When my character interacts with someone I make it one hour of time gone. So after the conversation I type
$ Player_Points += 1

When it is morning time, I have a list of variables I just copy and paste that include among other things
$ Player_Points = 8 (which resets the time to 8 am)
$ Day_Points += 1 (Which advances the the day by 1


I then change them to make them display better on a screen and just call it when I want to use it

Code:
if Player_Points == 8:
    text "8.00am" at top
if Day_Points == 1:
    text "Monday" at top
)


Ect ect. There are probably better ways but it works for me.
 
  • Like
Reactions: khumak

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,284
Like @mickydoo say, unless you really know what you are doing, it's better to stay as basic as possible. But here my definition of what is "basic" differ, because I think that a bit of automation make it even easier. So, you need an object that will handle the time passing, and that will let you interact with it in a verbose-like way.

Python:
init python:

    class MyTimePassing( renpy.python.RevertableObject ):

        #  All the periods of the day, and associated number of actions
        # available for this period.
        dayPeriod      = [ "Day", "Afternoon", "Evening" ]
        actionByPeriod = [  10,    10,    10 ]
        #  All the days of the week, and associated period where the day start
        # for the player.
        dayOfWeek  = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]
        #  Reminder, the first indice of a list is 0.
        startOfDOW = [  0,    2,     2,     2,     2,     2,     0 ]
        #  The live values. The game start at /Day/ on a Sunday, with 10 action
        # points.
        actualPeriod = 0
        actualDOW = 0
        actualAP = 10

        @property
        def period( self ):
            return self.dayPeriod[self.actualPeriod]

        @property
        def day( self ):
            return self.dayOfWeek[self.actualDOW]

        @property
        def AP( self ):
            return self.actualAP

        def nextPeriod( self ):
            if self.actualPeriod == len( self.dayPeriod ) -1:
                self.nextDay()
            else:
                self.actualPeriod += 1
            self.actualAP = self.actionByPeriod[self.actualPeriod]

        def nextDay( self ):
            if self.actualDOW == len( self.dayOfWeek ) -1:
                self.actualDOW = 0
            else:
                self.actualDOW += 1
            self.actualPeriod = self.startOfDOW[self.actualDOW]
            self.actualAP = self.actionByPeriod[self.actualPeriod]

        def dayIs( self, expected ):
            return expected == self.dayOfWeek[self.actualDOW]

        def periodIs( self, expected ):
            return expected == self.dayPeriod[self.actualPeriod]

        def canUseAP( self, expected=1 ):
            return self.actualAP >= expected

        def useAP( self, number=1 ):
            # Validate that the player have enough action points
            if self.canUseAP( number ) is False:
                return False
            self.actualAP -= number
            return True

        def haveAP( self ):
            return self.canUseAP()

# Create the object to be rollback compliant and savable.
default timePassing = MyTimePassing()

# Minimalist HUD
screen timeHUD:
    vbox:
        text "Today is [timePassing.day]."
        text "It's [timePassing.period] time."
        text "You have [timePassing.AP] action points."

# And here's an example of use
label dayLoop:

    show screen timeHUD

    if timePassing.dayIs( "Sun" ):
        "Tomorrow works start again."
        if timePassing.periodIs( "Day" ):
            "But I'll not complain, the day just start."
    elif timePassing.dayIs( "Fri" ):
        if timePassing.periodIs( "Evening" ):
            "Just one more night before the week-end."
        else:
            "Tomorrow's the week-end, at least."

    menu menuLoop:
        "Invite the girl to a restaurant":
            if not timePassing.canUseAP( 5 ):
                "Sorry, you don't have enough action points to do this."
            else:
                $ timePassing.useAP( 5 )
                "You go to a fancy place."
        "Kiss the girl":
            if not timePassing.useAP( 2):
                "You don't have enough actions points for this."
            else:
                "She liked it."
        "hug the girl":
            # By default the number of AP is 1.
            if not timePassing.useAP():
                "You don't have enough actions points for this."
            else:
                "Apaprently she wanted more that a simple hug."

    if timePassing.haveAP():
        jump menuLoop

    menu:
        "Continue the day":
            $ timePassing.nextPeriod()
            jump menuLoop
        "Sleep early":
            $ timePassing.nextDay()
            jump dayLoop
Easy, robust, configurable, and even more KiSS compliant, since you don't have to do the computation by yourself, just call explicitly named methods.
 

Ryder77

Member
Game Developer
Sep 9, 2017
462
384
Thank you so much, both of you. Yes, KISS is definitely the way I would want to go. Though, from my first look through, my definition of KISS is closer to Mickydoo's than it is to Anne's. ;) This will hopefully get me started and moving in the right direction. :)
 
  • Like
Reactions: mickydoo

Ryder77

Member
Game Developer
Sep 9, 2017
462
384
Like @mickydoo say, unless you really know what you are doing, it's better to stay as basic as possible. But here my definition of what is "basic" differ, because I think that a bit of automation make it even easier. So, you need an object that will handle the time passing, and that will let you interact with it in a verbose-like way.

OK, so I'm trying to work with this. I don't fully understand the python, but I can more of less see how to use it to achieve my objectives. After much around, I've come up with something that doesn't quite work.

Code:
init python:

    class MyTimePassing( renpy.python.RevertableObject ):

        #  All the periods of the day, and associated number of actions
        # available for this period.
        dayPeriod      = [ "Day", "Afternoon", "Evening" ]
        actionByPeriod = [  10,    10,    10 ]
        #  All the days of the week, and associated period where the day start
        # for the player.
        dayOfWeek  = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]
        #  Reminder, the first indice of a list is 0.
        startOfDOW = [  0,    2,     2,     2,     2,     2,     0 ]
        #  The live values. The game start at /Day/ on a Sunday, with 10 action
        # points.
        actualPeriod = 0
        actualDOW = 0
        actualAP = 10

        @property
        def period( self ):
            return self.dayPeriod[self.actualPeriod]

        @property
        def day( self ):
            return self.dayOfWeek[self.actualDOW]

        @property
        def AP( self ):
            return self.actualAP

        def nextPeriod( self ):
            if self.actualPeriod == len( self.dayPeriod ) -1:
                self.nextDay()
            else:
                self.actualPeriod += 1
            self.actualAP = self.actionByPeriod[self.actualPeriod]

        def nextDay( self ):
            if self.actualDOW == len( self.dayOfWeek ) -1:
                self.actualDOW = 0
            else:
                self.actualDOW += 1
            self.actualPeriod = self.startOfDOW[self.actualDOW]
            self.actualAP = self.actionByPeriod[self.actualPeriod]

        def dayIs( self, expected ):
            return expected == self.dayOfWeek[self.actualDOW]

        def periodIs( self, expected ):
            return expected == self.dayPeriod[self.actualPeriod]

        def canUseAP( self, expected=1 ):
            return self.actualAP >= expected

        def useAP( self, number=1 ):
            # Validate that the player have enough action points
            if self.canUseAP( number ) is False:
                return False
            self.actualAP -= number
            return True

        def haveAP( self ):
            return self.canUseAP()

# Create the object to be rollback compliant and savable.
default timePassing = MyTimePassing()

# Minimalist HUD
screen timeHUD:
    vbox:
        text "Today is [timePassing.day]."
        text "It's [timePassing.period] time."
        text "You have [timePassing.AP] action points."



# And here's an example of use


label start:

    # This will be the prologue

    "This is the prologue..."



label dayLoop:

    show screen timeHUD

    if timePassing.dayIs( "Sat" ):
        jump Saturday
        
    if timePassing.dayIs( "Sun" ):
        jump Sunday        
        
    else:
        jump Weekday
 
 
 
label Weekday:
    
    "Hey, it's a weekday."

    menu menuLoop1:
        "Invite the girl to a restaurant":
            if not timePassing.canUseAP( 5 ):
                "Sorry, you don't have enough action points to do this."
            else:
                $ timePassing.useAP( 5 )
                "You go to a fancy place."
                
        "Kiss the girl":
            if not timePassing.useAP( 2):
                "You don't have enough actions points for this."
            else:
                "She liked it."
                
        "Hug the girl":
            # By default the number of AP is 1.
            if not timePassing.useAP():
                "You don't have enough actions points for this."
            else:
                "Apaprently she wanted more that a simple hug."

    if timePassing.haveAP():
        jump menuLoop1

    jump Bedtime



# SATURDAY
    
label Saturday:
    
    "Hey, it's Saturday."    
    

    menu menuLoop2:
        "Invite the girl to a restaurant":
            
            if not timePassing.canUseAP( 5 ):
                "Sorry, you don't have enough action points to do this."
            else:
                $ timePassing.useAP( 5 )
                "You go to a fancy place."
                
        "Kiss the girl":
            if not timePassing.useAP( 2):
                "You don't have enough actions points for this."
            else:
                "She liked it."
                
        "Hug the girl":
            # By default the number of AP is 1.
            if not timePassing.useAP():
                "You don't have enough actions points for this."
            else:
                "Apaprently she wanted more that a simple hug."

    if timePassing.haveAP():
        jump menuLoop2

    if dayPeriod == Evening:
        jump Bedtime


    menu:
       
        "Continue with what you're doing":
            $ timePassing.nextPeriod()
            jump menuLoop2
            
        "Do something else":
            jump Somethingelse








label Sunday:
    
    "Hey, it's Sunday."

    menu menuLoop3:
        "Invite the girl to a restaurant":
            if not timePassing.canUseAP( 5 ):
                "Sorry, you don't have enough action points to do this."
            else:
                $ timePassing.useAP( 5 )
                "You go to a fancy place."
        "Kiss the girl":
            if not timePassing.useAP( 2):
                "You don't have enough actions points for this."
            else:
                "She liked it."
        "hug the girl":
            # By default the number of AP is 1.
            if not timePassing.useAP():
                "You don't have enough actions points for this."
            else:
                "Apaprently she wanted more that a simple hug."

    if timePassing.haveAP():
        jump menuLoop3
 
    if dayPeriod == Evening:
        jump Bedtime


    menu:      
        "Continue with what you're doing":
            $ timePassing.nextPeriod()
            jump menuLoop3
            
        "Do something else":
            jump Somethingelse


label Somethingelse:
    
    "You do something else"
    

label Bedtime:
    
    "It's late. Time for bed."
    $ timePassing.nextDay()
    jump dayLoop

[/quote]


For the weekend, where there is more than one dayperiod, I wanted to have an option to continue (ie. move on to the next period) or do something else.   However, after the expiry of the Evening dayperiod, I want to go to sleep right away.   I tried to do this with an if statement (if dayPeriod == Evening:) but dayPeriod doesn't seem to have been defined?  I'm a bit unclear on that.

The other thing I want, and should be able to figure out but can't for some reason, is how to start on a Monday?

Thanks in advance for the help.
 

Ryder77

Member
Game Developer
Sep 9, 2017
462
384
OK, please ignore my previous message. I've figured it out, more or less. :)