Random Chance Label Function

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
User avatar
wyverngem
Miko-Class Veteran
Posts: 615
Joined: Mon Oct 03, 2011 7:27 pm
Completed: Simple as Snow, Lady Luck's Due,
Projects: Aether Skies, Of the Waterfall
Tumblr: casting-dreams
itch: castingdreams
Location: USA
Contact:

Random Chance Label Function

#1 Post by wyverngem »

This was inspired by helcries Random Event that used basic code to create a call system to show different labels based on if statements. I've gone beyond to show how this can be done in python with either renpy.call or renpy.jump.

It's works with the lastest Ren'Py 7.2.0

Let's say you're making a game where you have random events that only show up by chance and have different versions. This code decides if the player get to witness the scene and which one. For example, your player goes to the park and by chance gets to have a date with another character. You have 10 different date scenes or versions that could possible show up. You can use this code to quickly determined if there's a date and which one to show in a single line of code.

Code: Select all

init python:
    import random
    # Jumps or calls a random label in your game with chance.
    def random_event(odds, choices, label_prefix, type=True):
        chance = random.randint(1,100)
        if chance <=odds:
            num = random.randint(1,choices)
            label_name = str((label_prefix+str(num)))
            if type:
                renpy.jump(label_prefix)
            else:
                renpy.call(label_prefix)
random_event(odds, choices, label_prefix, type=True)
Odds is the odds of seeing the event. The code picks a number between 1 and 100. Then sees if chance is less than or equal to your odds. If your odds is 50 and the chance number is 25 you'll see the event. Otherwise the game doesn't return anything and goes to the next line.

Choices are the sequential numbers that relate to how many different version or choices of something are. If there are three labels that can be shown it will use one of those to show the event.

label_prefix is the prefix of the labels you're calling. This is a string of the label name. So if your picking which date the player sees it could be 'eileen_date'

type Doesn't have to be supplied if you want the player to jump to the label instead of call. If you want it to be called supply False.

Here's how to use it in game.

Code: Select all

label start:
    $ variable = 0

label game_loop:
    "My function uses odds and a chance to determined if the player witnesses a random scene. If you do get past the chance, the game will also randomize what label is shown to the player."
    "Let's turn the random_event() to call the labels instead of jumping to them."
    $ random_event(50,3,'choice', False)
    if variable == 1:
        "I see that you came from the first label."
    elif variable == 2:
        "You saw the second one right?"
    elif variable == 3:
        "You saw the third scene, touching."
    else:
        "Oh, I guess you weren't lucky and didn't see any of the called labels."
    "Fun right, but let's say you want to use a jump instead. Which is sometimes a nicer to prevent accidentally returning to the game's start menu."
label jump_loop:
    $ random_event(50,3,'choice')
    "You are seeing this because you didn't get the random event after a jump. My jump labels all come back to jump_loop."
    "End game."
    "Before I go, if the player rolls back it will be an entirely different option."
    return
It's not a hard code to use. There's just two things to keep in mind. If the player rolls back it will change the outcome of the choices. Also you have to set up label_prefix a specific way. The label_prefix that you create must start with 1 and go in sequential order. If the game chooses an option that is not available it will return an error that the label couldn't be found.

So they should look like this. I've given examples of called labels and jumped labels.

Code: Select all

# This is an example of the label that is called. It uses Return at the bottom to go back to where it was called from.
label choice1:
    $ variable = 1
    "I picked choice 1."
    "This is an example of a label that has been called."
    return

label choice2:
    $ variable = 2
    "I picked choice 2."
    "This is an example of a label that has been called."
    return

label eileen_choice1:
    "I've jumped to eileen_choice 1."
    jump jump_loop

label eileen_choice2:
    "I've jumped to eileen_choice 2."
    jump jump_loop
Enjoy the code. Just remember to keep your prefix labels sequential and that if the user rollsback it will make a new choice for them.


Here's a full sample for those interested in it.

Code: Select all

# Random Event by Chance credit wyverngem 2019 Ren'py Version 7.2.0
init python:
    import random
    # Jumps to a random label in your game.
    def random_event(odds, choices, label_name, type=True):
        chance = random.randint(1,100)
        if chance <=odds:
            num = random.randint(1,choices)
            label_name = str((label_name+str(num)))
            if type:
                renpy.jump(label_name)
            else:
                renpy.call(label_name)

label start:
    $ variable = 0
    "Hello"

label game_loop:
    "My function uses odds and a chance to determined if the player witnesses a random scene. If you do get past the chance, the game will also randomize what label show the player."
    "Because I've added False to the end of my line I call labels instead of jumping to them. Meaning that you'll see what's past this line each time. I've added a variable check to see what scene you actually saw, but you don't need it in game."
    $ random_event(50,3,'choice', False)
    "The game will always come back to this line when using call instead of jump."
    if variable == 1:
        "I see that you came from the first label."
    elif variable == 2:
        "You saw the second one right?"
    elif variable == 3:
        "You saw the third scene, touching."
    else:
        "Oh, I guess you weren't lucky and didn't see any of the called labels."
    "Fun right, but let's say you want to use a jump instead. Which is sometimes a nicer to prevent accidentally returning to the game's start menu."
label jump_loop:
    $ random_event(50,3,'eileen_choice')
    "You are seeing this because you didn't get the random event after using random_event() with jump...I'm sorry."
    "End game."
    "Oh, before I go, rollback will choose something else."
    return

# These are the labels that are effected by choices. Feel free to name them whatever prefix you want, but keep them numbered sequential starting at one to work with the code.
label choice1:
    $ variable = 1
    "I picked choice 1."
    "This is an example of a label that has been called."
    return

label choice2:
    $ variable = 2
    "I picked choice 2."
    "This is an example of a label that has been called."
    return

label choice3:
    $ variable = 3
    "I picked choice 3."
    "This is an example of a label that has been called."
    return

# A different name for a jumping label.
label eileen_choice1:
    "I've jumped to eileen_choice 1."
    "I'm going to go back to jump_loop, and pick another random event."
    jump jump_loop

label eileen_choice2:
    "I've jumped to eileen_choice 2."
    "I'm going to go back to jump_loop, and pick another random event."
    jump jump_loop

label eileen_choice3:
    "I've jumped to eileen_choice 3, but I want to continue the game."

label end_game:
    "The previous choice was eileen_choice3."
    "This means I end the game, because sometimes you want to break the cycle of jumps."
    "Oh, before I go, rollback will choose something else."
    return

User avatar
isobellesophia
Miko-Class Veteran
Posts: 979
Joined: Mon Jan 07, 2019 2:55 am
Completed: None
Projects: Maddox and Friends! (AI Teacher friend), Friendly Universities! (Soon)
Organization: Friendly Teachers series
Deviantart: SophBelle
itch: Child Creation
Location: Philippines, Mindanao
Contact:

Re: Random Chance Label Function

#2 Post by isobellesophia »

YAY!

Finally looking for this, thank you! 😊
I am a friendly user, please respect and have a good day.


Image

Image


User avatar
ameliori
Veteran
Posts: 201
Joined: Sun Apr 06, 2014 9:20 am
Completed: Who is Mike?, Cupid
Projects: The Black Beast [Fairytale]
Organization: FERVENT
Tumblr: ameliori
itch: fervent
Contact:

Re: Random Chance Label Function

#3 Post by ameliori »

Ohh this is exactly what I was looking for! One question though. Is there a way for the labels/events to not be shown again once the player already played it? Thanks for this!
ameliori
TwitterPatreon

User avatar
nerupuff
Veteran
Posts: 211
Joined: Sat Dec 02, 2017 2:24 am
Contact:

Re: Random Chance Label Function

#4 Post by nerupuff »

wyverngem wrote: Sun Mar 03, 2019 5:27 pm This was inspired by helcries Random Event that used basic code to create a call system to show different labels based on if statements. I've gone beyond to show how this can be done in python with either renpy.call or renpy.jump.

It's works with the lastest Ren'Py 7.2.0
This is pretty useful! Been experimenting with it and now I have a ton of random events in queue for my project. Since rollback chooses a different random event for the player, I've chosen to prevent rollback/limit the number of going back a player can do while in-game.

Similar to what ameliori is asking, I'm wondering if there's a way for renpy to keep track of what has been shown/played and prevent it from coming up again as part of the random events system?
ImageImage
Hire me for proofreading, editing, and (maybe) writing! ♡ Check here!

User avatar
wyverngem
Miko-Class Veteran
Posts: 615
Joined: Mon Oct 03, 2011 7:27 pm
Completed: Simple as Snow, Lady Luck's Due,
Projects: Aether Skies, Of the Waterfall
Tumblr: casting-dreams
itch: castingdreams
Location: USA
Contact:

Re: Random Chance Label Function

#5 Post by wyverngem »

Glad it's useful, guys. @nerupuff Are you using $ renpy.block_rollback() at the top of your choice labels? I haven't tested this out with renpy.fix_rollback() just yet, but if it works then it might be a better choice so your players can still roll back.
ameliori wrote: Fri Mar 08, 2019 2:19 amIs there a way for the labels/events to not be shown again once the player already played it?
There is a way to do this, but I have a different version of the script. It basically takes a list variable that it will use to check if your event has been seen. If it has it will continuously loop until it finds a event you haven't seen. You need to set up lists of seen_events that the code can check for, and provide a safety label that the game will choose if all the events are already in your seen event list.

Create a list to use for your checks and add it to the defaults or start:

Code: Select all

$ my_seen_events = []
This will house all the events the player has seen. If you want the label not to be repeated append it to the list. See example:

Code: Select all

label eileen_choice1:
    $ my_seen_events.append('eileen_choice1')
    "I've jumped to eileen_choice 1. In my list now I have [my_seen_events]."
    "I'm going to go back to jump_loop, and pick another random event."
    jump jump_loop
You can create different lists to keep track of different label names if you desire. So you could have all the random dates in one list and all the story events in another list if you so choose. The code itself just needs a list to check against if it's seen or not in that list.

So to use it you do this:

Code: Select all

$ random_event(50,4,'eileen_choice', my_seen_events)
The biggest difference is YOU HAVE TO HAVE A SAFETY NET!!! It uses a while loop that says while the label name is in the list keep changing the name. Meaning you will be in ab infinite loop if all your events have been seen and it has no way to break out of it! I can't stress this enough. It's important to follow the next paragraph carefully. If you don't! You risk being stuck in the loop and it can freeze the game.

To prevent an infinite loop create a prefix label that is never appended to the list. Follow the rules for creating label names a prefix and number. It just needs the appropriate 'return' or 'jump to_my_loop' so your game continues. You could use events that are repeatable as long as you never append their name into the list.

Examples of your Safety Net:

Code: Select all

label eileen_date_choice4:
    jump my_loop

Code: Select all

label eileen_date_choice4:
    "Eileen isn't at the park today..."
    return
So just keep that in mind. :D Enjoy the code. It's below. I've attached the new full version if you want to see it in working action.

Code: Select all

init python:
    import random
    # Jumps to a random label in your game without repeats in seen events.
    def random_event(odds, choices, label_name, event_list, type=True):
        event_list = event_list.sort()
        chance = random.randint(1,100)
        label_prefix = label_name

        if chance <=odds:
            # Generate label_name with the string.
            num = random.randint(1,choices)
            go_to_label = str((label_prefix+str(num)))

            #Use that label_name in a for loop.
            while go_to_label in event_list:
                num = random.randint(1,choices)
                go_to_label = str((label_prefix+str(num)))

            if type:
                renpy.jump(go_to_label)
            else:
                renpy.call(go_to_label)
Take care,
Gem

User avatar
wyverngem
Miko-Class Veteran
Posts: 615
Joined: Mon Oct 03, 2011 7:27 pm
Completed: Simple as Snow, Lady Luck's Due,
Projects: Aether Skies, Of the Waterfall
Tumblr: casting-dreams
itch: castingdreams
Location: USA
Contact:

Re: Random Chance Label Function

#6 Post by wyverngem »

One little update to the code. Added a function to sort the list you provide. I couldn't remember if Python thinks. 'choice1' is 'choice10' if 'choice10' is listed first in the list, because in some coding languages it doesn't match the whole case.

Code: Select all

init python:
    import random
    # Jumps to a random label in your game without repeats in seen events.
    def random_event(odds, choices, label_name, event_list, type=True):
        go_to_label = ''
        chance = random.randint(1,100)
        label_prefix = label_name

        if chance <=odds:
            # Generate label_name with the string.
            num = random.randint(1,choices)
            go_to_label = str((label_prefix+str(num)))

            #Use that label_name in a for loop.
            while go_to_label in sorted(event_list):
                num = random.randint(1,choices)
                go_to_label = str((label_prefix+str(num)))

            if type:
                renpy.jump(go_to_label)
            else:
                renpy.call(go_to_label)
Last edited by wyverngem on Mon Mar 11, 2019 6:15 pm, edited 1 time in total.

User avatar
ameliori
Veteran
Posts: 201
Joined: Sun Apr 06, 2014 9:20 am
Completed: Who is Mike?, Cupid
Projects: The Black Beast [Fairytale]
Organization: FERVENT
Tumblr: ameliori
itch: fervent
Contact:

Re: Random Chance Label Function

#7 Post by ameliori »

I've been trying the last hour or so to get the code to work, but I always get this error:

Code: Select all

  File "game/script.rpy", line 16, in random_event
    while go_to_label in event_list:
TypeError: argument of type 'NoneType' is not iterable
Here is a sample of my code. I added "event_list" because if not, I get a different error which says "event_list not defined". I also added only 3 animals to the list so I can check if they get hidden after player has seen them.

Code: Select all

# Random Event by Chance credit wyverngem 2019 Ren'py Version 7.2.0
init python:
    import random
    # Jumps to a random label in your game without repeats in seen events.
    def random_event(odds, choices, label_name, event_list, type=True):
        event_list = event_list.sort()
        chance = random.randint(1,100)
        label_prefix = label_name

        if chance <=odds:
            # Generate label_name with the string.
            num = random.randint(1,choices)
            go_to_label = str((label_prefix+str(num)))

            #Use that label_name in a for loop.
            while go_to_label in event_list:
                num = random.randint(1,choices)
                go_to_label = str((label_prefix+str(num)))

            if type:
                renpy.jump(go_to_label)
            else:
                renpy.call(go_to_label)

init:
    $ seen_animals = []
    $ event_list = []
    
label start:
    $ variable = 0
    "Hello"
    "Let's look for cute animals?"
    menu:
        "Yes":
            jump jump_loop
        "No":
            jump end_game
label jump_loop:
    $ random_event(100,6,'zoo',seen_animals)
    
return

# A different name for a jumping label.
label zoo1:
    $ seen_animals.append('zoo1')
    $ event_list.append('zoo1')
    "You saw a cat."
    call searchmore
    return

label zoo2:
    $ seen_animals.append('zoo2')
    $ event_list.append('zoo2')
    "You saw a duck"
    call searchmore
    return

label zoo3:
    $ seen_animals.append('zoo3')
    $ event_list.append('zoo3')
    "You saw a doggo."
    call searchmore
    return

label zoo4:
    "You saw a piglet."
    call searchmore
    return
    
label zoo5:
    "You saw a racoon."
    call searchmore
    return

label zoo6:
    "You saw a chicken."
    call searchmore
    return

label zoo7:
    "Hm.. I don't see anymore animals"
    return

label searchmore:
    menu:
        "Do you want to look more?"
        "Yes":
            jump jump_loop
        "No":
            call end_game
    return

label end_game:
    "Okay bye!"
return
ameliori
TwitterPatreon

User avatar
wyverngem
Miko-Class Veteran
Posts: 615
Joined: Mon Oct 03, 2011 7:27 pm
Completed: Simple as Snow, Lady Luck's Due,
Projects: Aether Skies, Of the Waterfall
Tumblr: casting-dreams
itch: castingdreams
Location: USA
Contact:

Re: Random Chance Label Function

#8 Post by wyverngem »

ameliori wrote: Sun Mar 10, 2019 11:55 pm I've been trying the last hour or so to get the code to work, but I always get this error:

Code: Select all

  File "game/script.rpy", line 16, in random_event
    while go_to_label in event_list:
TypeError: argument of type 'NoneType' is not iterable
Take away the event_list in your init block. You don't need to have that, because the code is using the seen_animals list and never that one you made up, even though it matches. It was an error on my part when I sorted the list. It should be this. Change it to this and let me know if there's any errors.

Code: Select all

init python:
    import random
    # Jumps to a random label in your game without repeats in seen events.
    def random_event(odds, choices, label_name, event_list, type=True):
        go_to_label = ''
        chance = random.randint(1,100)
        label_prefix = label_name

        if chance <=odds:
            # Generate label_name with the string.
            num = random.randint(1,choices)
            go_to_label = str((label_prefix+str(num)))

            #Use that label_name in a for loop.
            while go_to_label in sorted(event_list):
                num = random.randint(1,choices)
                go_to_label = str((label_prefix+str(num)))

            if type:
                renpy.jump(go_to_label)
            else:
                renpy.call(go_to_label)

User avatar
ameliori
Veteran
Posts: 201
Joined: Sun Apr 06, 2014 9:20 am
Completed: Who is Mike?, Cupid
Projects: The Black Beast [Fairytale]
Organization: FERVENT
Tumblr: ameliori
itch: fervent
Contact:

Re: Random Chance Label Function

#9 Post by ameliori »

Yaaay Yes! It works perfectly! :3 Thank you so much!

I do have another request/question. Is there a way to make certain events have higher odds than other events? My idea was to put one set of "higher possibility" events together, and the normal events in another set. And then change the odds to make the high-possibility events more likely to appear. I am having a hard time implementing it though.. As always thanks for this great code!
ameliori
TwitterPatreon

Post Reply

Who is online

Users browsing this forum: No registered users