This year I actually managed to finish a game for Nanoreno! It’s called ‘reset/you’ and you can find the game page here. I thought it’d be cool to go through some of my favourite parts of working on this game in this blog post.

First: impromptu RPG battle system! I had a try at coding a very simple battle system in python/renpy. First I set up character classes with some basic skills. I’d been learning about classes in python recently in my job so this was a fun way to practice that.

init python:

    class BattleCharacter:
        # set up a generic battle character class with various stats
        def __init__(self, max_hp, strength, defence):
            self.max_hp = max_hp
            self.current_hp = self.max_hp
            self.strength = strength
            self.defence = defence

        def attack(self):
            # plus/minus up to 25% of total str stat
            variance = int(round((self.strength * 0.05)))
            rng = renpy.random.randint(-variance, variance)
            return int(round(self.strength + rng))

        def damage_taken(self, damage):
            # calculate damage taken taking defence into account
            # don't drop below zero
            reduction = damage / self.defence
            damage = int(round(damage - reduction))
            if self.current_hp - damage < 0:
                return self.current_hp
            else:
                return damage

        def defend(self):
            # increment defence on using defend
            self.defence += 5

        def heal(self):
            # return the amount healed not going above max hp
            amount = int(round(self.attack() * 1.25))
            if amount + self.current_hp > self.max_hp:
                return self.max_hp - self.current_hp
            else:
                return amount

    # extra skills
    def gravity(target):
        # reduces hp by 60% of current hp
        return int(round(target.current_hp * .6))

Then used in the script:

    # set up characters
    $ xephyr = BattleCharacter(max_hp=3000, strength=487, defence=16)
    $ boss = BattleCharacter(max_hp=5000, strength=783, defence=23)

    # screen to show the HP counter in the top left
    show screen battle with dissolve

    jump battle

label battle:
    menu:
        "Attack":
            $ damage_taken = boss.damage_taken(xephyr.attack())
            $ boss.current_hp -= damage_taken
            with vpunch
            with flashwhite
            N "[damage_taken] damage!"
        "Repair":
            $ damage_repaired = xephyr.heal()
            $ xephyr.current_hp += damage_repaired
            with flashwhite
            N "Xephyr repairs [damage_repaired] HP."

    if boss.current_hp <= 0:
        jump victory

    else:
        # make time occasionally use a powerful spell
        $ gravity_chance = renpy.random.randint(0, 5)
        if gravity_chance == 1:
            N "Time uses Gravity."
            $ damage_taken = xephyr.damage_taken(gravity(xephyr))
            $ xephyr.current_hp -= damage_taken
        else:
            N "Time attacks."
            $ damage_taken = xephyr.damage_taken(boss.attack())
            $ xephyr.current_hp -= damage_taken
        with vpunch
        with flashwhite
        N "Xephyr takes [damage_taken] damage!"

        if xephyr.current_hp <= 0:
            jump cirrus_helps

        jump battle

This part of the script basically acts as a while loop - as long as the boss’ HP is above zero you will keep looping back to the battle label where you will be shown the menu again. To add a bit of narrative going through the fight I added a counter to the loop:

label battle:
    $ counter += 1
    menu:
        "Attack":
            if counter == 2:
                Xephyr "I have to stop you!"
            if counter == 4:
                Xephyr "It's never useless!"
            if counter == 6:
                Xephyr "No!"
            $ damage_taken = boss.damage_taken(xephyr.attack())
            $ boss.current_hp -= damage_taken
            with vpunch
            with flashwhite
            N "[damage_taken] damage!"
        "Repair":
            if counter == 2:
                Xephyr "I have to stop you!"
            if counter == 4:
                Xephyr "It's never useless!"
            if counter == 6:
                Xephyr "No!"
            $ damage_repaired = xephyr.heal()
            $ xephyr.current_hp += damage_repaired
            with flashwhite
            N "Xephyr repairs [damage_repaired] HP."

The counter gets incremented each time you go through the loop so as the battle progresses you get new bits of dialogue from Xephyr (and the boss).

There are many issues with this system that I would iron out if I were using it for a bigger game but for a gimmicky little boss fight at the end of this game it serves its purpose pretty well.

On a non-coding note: it was nice to take a break from working on Metamorphoser, which is mostly written in first person, to write something totally in third person and with a very different kind of tone. Despite being a horror game, Metamorphoser’s writing is often very silly and doesn’t take itself seriously - to match its protagonist’s personality. For this game I wanted something a bit more serious, a little cold and detached as a contrast. Working on this game was also a good exercise in concentrating first and foremost on getting something finished no matter how short it is. The game ended up only being about 4k words but I think I managed to wrap up a nice little story in that amount.

On another writing note: I got to write online communication! Which was very fun. It was cool to try and think how different people type when they’re online and in what setting. The conversations Xephyr has with her online contact start on an anonymous message board and then move into an instant messaging app. It was interesting trying to figure out both characters’ typing styles according to the kind of setting they’re in.

The anonymous message board:

a screenshot of the message board

The instant messaging app:

a screenshot of the message board

Now that I’ve actually succeeded in finishing a game for Nanoreno I want to see if I can do it every year! It’s just really nice to have another complete game out there, no matter how barebones it is.