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 '16 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 '16 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 '16 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 '16 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 '16 at 8:27

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.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.