Main Loop part 2: Home

The player character's home location has to implement a number of labels expected by the main loop. This is the second part of the main loop section.
Note: The Per suffix relates to this being the date/period version in my project.

Arrival

The first label is the .arrival one that is called when the player character returns home. All this has to do is describe the player character letting themselves into their home, and then set pcLoc.

loc/homePer.rpy

    #
    # Player's home.
    # Date/Period style.
    #
label homePer:

    # -------------------------------------------------------------------------
    # Interface labels
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Player arrives home from somewhere else.
    #
label .arrive:
    $ dbgLabel('homePer', 'arrive')
    "Fishing out your key you let yourself into your home."
    $ pcLoc = 'homePer'
    return

Choice

The label that will likely be used most often is the .choice one. This is called by the main loop when the player should be offered a choice of what to do next. In this simple example I've just added some basic choices:

The implementation of these is detailed below.

loc/homePer.rpy (cont)

    # Offer player a choice of what to do.
    #
label .choice:
    $ dbgLabel('homePer', 'choice')
    menu:
        "{alt}Menu. {/alt}What to do?"
        "Breakfast" if period == 0:
            call .breakfast from home_per_choice_bfast
        "Lunch" if period == 2:
            call .lunch from ome_per_choice_lunch
        "Dinner" if period == 4:
            call .dinner from home_per_choice_dinner
        "Watch TV":
            call .tv from home_per_choice_tv
        "Go into town":
            call .goTown from home_per_choice_town
        "Go to work" if isWorkDayPer():
            call .goWork from home_per_choice_work
        "Sleep":
            call .sleep from home_per_choice_sleep
    return

Travel To

The travelTo(destLoc label implements travelling from the player character's home to other places. For the purposes of this example the only travel option the player character has from their home is to take a bus into the town centre.

loc/homePer.rpy (cont)

    # Have the player travel to a new location.
    #
label .travelTo(destLoc):
    $ dbgLabel('homePer', 'travelTo', 'destLoc={}', destLoc)
    if destLoc == 'workPer':
        if period == 1:
            "The bus is packed as you and the other commuters head into town."
        else:
            "The bus isn't nearly as busy as it is in the morning.
            It's almost pleasant. Almost."
        $ pcLoc = 'townPer'
    elif destLoc == 'townPer':
        "You get the bus into town."
        $ pcLoc = destLoc
    else:
        # Fall back if there's no specific travel message.
        "You let yourself out of the house and head to your destination."
        $ pcLoc = destLoc
    return

This code can be expanded upon as needed. Perhaps the player character obtains their own vehicle, or they get a lift with an NPC they like and chat along the way.

Wake

The final label needed is the .wake one. This just describes the player character waking up. In this example code the player character can only wake in their home, but this is left as part of the location "interface" in case the player wakes somewhere else in a future development.

loc/homePer.rpy (cont)

    # Have the player wake up.
    #
label .wake:
    $ dbgLabel('homePer', 'wake')
    "You wake up rested in your own bed."
    return

Activities

The remainder of the code for this location implements the choices the player can make. These are kept as subroutines so the choice menu can be implemented differently if desired, for example a travel option that brings up a clickable map.

Going to town

All the go to town routine has to do is to call mainPer.travelTo('townPer'). This then makes the required calls to describe the player character's travel and their arrival at the destination.

loc/homePer.rpy (cont)

    # -------------------------------------------------------------------------
    # Local activities
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Player character wants to into town.
    #
label .goTown:
    $ dbgLabel('homePer', 'goTown')
    call mainPer.travelTo('townPer') from home_per_go_town_travel
    return

The sequence of calls is:

  1. The main loop calls homePer.choice.
  2. The player chooses "Go into town" which calls the above townPer.goTown.
  3. The .goTown calls mainPer.travelTo('townPer').
  4. The mainPer.travelTo('townPer') calls homePer.travelTo('townPer') which describes the journey and sets pcLoc to townPer and returns.
  5. As the player character is now in the desired location the mainPer.travelTo('townPer') calls townPer.arrive() to describe arrival in the town and returns.
  6. The mainPer.travelTo('townPer') returns as its task is complete.
  7. The townPer.goTown routine returns.
  8. The homePer.choice returns.
  9. The main loop executes once more and calls townPer.choice.

Going to work

The go to work routine has is very similar, calling mainPer.travelTo('workPer').

loc/homePer.rpy (cont)

    # Player character wants to to work.
    #
label .goWork:
    $ dbgLabel('homePer', 'goWork')
    call mainPer.travelTo('workPer') from home_per_go_work_travel
    return

The sequence of calls is a little different:

  1. The main loop calls homePer.choice.
  2. The player chooses "Go to work" which calls the above homePer.goWork.
  3. The homePer.goWork calls mainPer.travelTo('workPer').
  4. The mainPer.travelTo('workPer') calls homePer.travelTo('workPer') which describes the journey into town and sets pcLoc to townPer and returns.
  5. As the player character isn't at work yet the mainPer.travelTo('workPer') calls townPer.travelTo('workPer') which describes the next step of the journey. It sets pcLoc to workPer and returns.
  6. As the player character is now in the desired location the mainPer.travelTo('workPer') calls workPer.arrive() to describe arrival at work and returns.
  7. The mainPer.travelTo('workPer') returns as its task is complete.
  8. The homePer.goWork routine returns.
  9. The homePer.choice returns.
  10. The main loop executes once more and calls workPer.choice.

Sleep

The sleep routine first checks that the player character is tired enough to sleep, and rejects the request with a message if they aren't tired and it's not at least evening. If they do sleep then newDay is set to True so the main loop can do the new day processing and wake the player character. If it's evening or later it advances to the next day. If the player character is so tired they can sleep during the day it uses two periods instead.

loc/homePer.rpy (cont)

    # Player wants to sleep.
    # Allow if energy is zero, and not too early.
    #
label .sleep:
    $ dbgLabel('homePer', 'sleep')
    if energy > 0 and period < 3:
        "You get into bed and toss and turn for a while,
        but it's too early to fall asleep."
        return

    "You get into bed and fall asleep."
    $ newDay = True
    if period >= 4:
        $ nextDayPer()
    else:
        $ addPeriod(2)
    return

And the rest...

The remaining routines are simple. They just produce narration and advance the period as needed.

loc/homePer.rpy (cont)

    # Player character has breakfast.
    #
label .breakfast:
    $ dbgLabel('homePer', 'breakfast')
    "A simple bowl of cereal and a cup of life-giving coffee should
    keep you going until lunchtime."
    $ nextDayPer()
    return

    # Player character makes dinner.
    #
label .dinner:
    $ dbgLabel('homePer', 'dinner')
    "A microwaved frozen meal and a beer sorts out your evening meal."
    $ nextDayPer()
    return

    # Player character makes lunch.
    #
label .lunch:
    $ dbgLabel('homePer', 'lunch')
    "You fix yourself a sandwich for lunch, and have another coffee."
    $ nextDayPer()
    return

    # Player character wants to pass time watching TV.
    #
label .tv:
    $ dbgLabel('homePer', 'tv')
    "You flop down on the couch and start channel surfing, but nothing really
    grabs you attention."
    $ nextDayPer()
    return

Summary

Hopefully the brief nature of each of these routines shows the benefit of breaking the tasks down into very small parts. Each of them can of course become more complex as needed to tell your story.

Other parts of the main loop example