When dealing with % chance in a game what are the most effective ways to achieve this? When I use random.random()[python] or Math.random()[javascript] and use an if/elif/else conditional it seems like the things with a very low chance of happening, happened far more often than they should have.

For example, a python game I worked on used something like this:

qaul_eq = random.random()
if qual_eq <= .5:
   quality = common
elif qual_eq <= .75:
   quality = uncommon
elif qual_eq <=.9:
   quality = rare
elif qual_eq <=.97:
   quality = epic
   quality = legendary

Javascript DEMO

There is a 2% chance that quality will be legendary yet when printed 20 times every time it is run at least 1 item in almost every test run is legendary. In my python game it isn't uncommon for 2 or 3 of the items to be legendary. I'd chalk it up to good luck if not for the large amount of test runs I have conducted.

  • 1
    \$\begingroup\$ To use an aphorism commonly credited to Einstein, "everything should be as simple as possible, but not simpler" \$\endgroup\$
    – DMGregory
    Apr 28, 2016 at 21:31
  • \$\begingroup\$ It's important to think about the user's mental model: can they understand the algorithms? Ultimately, in RPGs, knowing (and sometimes mastering) algorithms can be a critical part of the game. \$\endgroup\$
    – ashes999
    Apr 28, 2016 at 21:49
  • \$\begingroup\$ @Philipp I looked around at other questions that were broad and unrelated to code that had + ratings and assumed it was okay to ask a question such as this. I'll take note that it isn't. I'll also edit my question to be focused on the second one. \$\endgroup\$
    – Shniper
    Apr 28, 2016 at 21:53
  • 6
    \$\begingroup\$ With the code you show (Legendary has about a 3% chance, not 2%, since a roll of 0.970001 still goes to legendary), we would expect a batch of 20 drops to include at least 1 Legendary almost half the time (45.6%). We'd expect 2-3 Legendaries in a batch about 12% of the time, which matches your description that it "isn't uncommon." So, rather than a mysterious code glitch, this sounds like you might just need to recalibrate your expectations for how low you need to set an outcome's probability to get the desired result over repeated trials. \$\endgroup\$
    – DMGregory
    Apr 28, 2016 at 23:00
  • \$\begingroup\$ Not a duplicate, but related: How can I make a “random” generator that is biased by prior events?. The techniques described in that question might be an inspiration for alternative methods than just rolling a random number whenever an event occurs. \$\endgroup\$
    – Philipp
    Apr 29, 2016 at 8:27

1 Answer 1


There is a 2% chance that quality will be legendary yet when printed 20 times every time it is run at least 1 item in almost every test run is legendary.

Your algorithm generates a "legendary" rarity whenever a random number in the range 0..1 rolls above 0.97. That's a 3% chance or a chance of one in 33. It's not a 2% chance because random() generates double-precision floating-point numbers. 0.970000000023 is just as likely as 0.9999998735.

As DMGregory calculated in a comment, you will have at least one legendary in 20 samples 45.6% of the time.

If you want an event to happen every nth times on average, do if (random() < 1.0 / n). So to get something to happen once in 50, do random() < 0.02. Or random() > 0.98 when you prefer that form. Checking randomly-generated floating-point numbers for equality is quite pointless because of their high presision (by the way: this also applies to floating-point numbers in most other situations).

However, keep in mind that random numbers have no memory (ok, techncally they do, because pseudorandom number generators are actually deterministic, but they do their best to hide that fact). Everytime you roll you have the same chance of success (further reading Gambler's Fallacy). This leads to winning-streaks and losing-streaks which last far longer than you would expect intuitively and often have a tendency to feel much longer than the player finds plausible (this effect is known as the Clustering Illusion).

Although both are psychological phenomenons where the game is working as intended and the player's perception of the game is skewed, we as game designers do well when we work around these and instead try to make the randomness in our games feel right and not be right. We have an interesting question with various techniques to mitigate this streak-effect and have rare events happen with pauses between them.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .