0

I'm creating a type of survival game in python, and am creating the different animals you can encounter and "battle" with (users will only encounter one animal at a time). I want certain animals with a lower number associated with them to have a higher probability of showing up then the animals with a higher number associated to them:

POSSIBLE_ANIMALS_ENCOUNTERED = {
    "deer": 50,        "elk": 75,           "mountain lion": 150,
    "rat": 5,          "raccoon": 15,       "squirrel": 5,
    "black bear": 120, "grizzly bear": 200, "snake": 5,
}

So, I would like a rat to appear more then a deer and just as much as a squirrel or snake. How can I go about creating probability for the animals inside of the dict based on their value? I'd like it so that the user will see a higher percentage of animals with lower value, and a lower percentage of animals with a higher value.

For example:

The user should see a animal with a value from 1 to 5, 50% of the time (0.5), an animal with a value from 6 to 50 %25 percent of the time (0.25), and any animal with a value higher then that 10 percent of the time (0.10).

Pyth0nicPenguin
  • 148
  • 1
  • 7
  • How exactly do the numbers compare? Will someone see 10 times more rats than deer? 3 times more squirrels than raccoons? – glibdud Oct 21 '16 at 12:17
  • @glibdud see edits, hopefully that will explain it better – Pyth0nicPenguin Oct 21 '16 at 12:51
  • Wait, so if you want anything in a range 6-50 to be encountered 25% of the time, why not just set them to 0.25? –  Oct 21 '16 at 12:52
  • @tristan The numbers they are associated with will be their HP, I guess I could probably put the value into a tuple with hp and percentage? – Pyth0nicPenguin Oct 21 '16 at 12:53
  • So multiple animals can be encountered at once? – glibdud Oct 21 '16 at 12:54
  • @glibdud I'd love that, but that's a little to much for me to handle at this point, so no, they will only be able to encounter one animal at a time. – Pyth0nicPenguin Oct 21 '16 at 12:56
  • Then I still don't understand the numbers. Maybe it would be easier to understand if you showed what you've tried so far? – glibdud Oct 21 '16 at 12:59
  • 1
    Ah, I understand what you're looking to do, even if you're making it harder than you really need to for yourself. There's a couple subproblems in here, so it will take me a second to write up an answer using only the standard lib. –  Oct 21 '16 at 13:08

1 Answers1

1

You need to codify the percentage likelihood of an encounter based on "health points" (encounter_ranges tuples are from the data in your edit), then do a weighted random choice from your elements. I've put comments inline:

from random import random
from bisect import bisect

POSSIBLE_ANIMALS_ENCOUNTERED = {
    "deer": 50,        "elk": 75,           "mountain lion": 150,
    "rat": 5,          "raccoon": 15,       "squirrel": 5,
    "black bear": 120, "grizzly bear": 200, "snake": 5,
}

# codify your ranges.  (min, max, encounter %) 
encounter_ranges = (
    (50, float('inf'), .10),
    (6, 50, .25),
    (1, 5, .50)
)

# create a list of their probability to be encountered
# replace .items() with .iteritems() if python 2.x
ANIMAL_ENCOUNTER_PERCENTAGE_PER_HP_LIST = []
for k, v in POSSIBLE_ANIMALS_ENCOUNTERED.items():
    for encounter_chance in encounter_ranges:
        if (v >= encounter_chance[0]) and (v <= encounter_chance[1]):
            # multiplied by 100 because we're going to use it in a weighted random below
            ANIMAL_ENCOUNTER_PERCENTAGE_PER_HP_LIST.append([k, encounter_chance[2] * 100])


# With our percentages in hand, we need to do a weighted random distribution
# if you're only planning on encountering one animal at a time.
# stolen from http://stackoverflow.com/a/4322940/559633
def weighted_choice(choices):
    values, weights = zip(*choices)
    total = 0
    cum_weights = []
    for w in weights:
        total += w
        cum_weights.append(total)
    x = random() * total
    i = bisect(cum_weights, x)
    return values[i]

# run this function to return the animal you will encounter:
weighted_choice(ANIMAL_ENCOUNTER_PERCENTAGE_PER_HP_LIST)

Note that this approach will always return something -- a 100% chance encounter of some animal. If you want to make the encounters more random, that's a much simpler problem, but I didn't include it as you'd need to specify how you expect this game mechanic to work (random 0-100% chance of any encounter? a percentage chance of the encounter based on the return (50% chance of encounter if rat is returned)? etc).

Note that I wrote this for Python 3, as if you're new to Python, you really should be using 3.x, but I left a comment in what you need to switch if you decide to stick with 2.x.