Simulating runs of Bernoulli successes with JavaScript
Everyone has a personal vice or two. Mine is Dota 2, a computer game that is vaguely similar to an action role-playing game, except that you’re playing against other players online in an arena, in teams of five, with the goal of destroying a special building at the other team’s corner of the map. You can play as one of 110 unique heroes (with two more heroes in the pipeline), each of which has at least four spells or abilities that determine its capabilities and role in a team. A few of these abilities have probabilistic effects: the hero Spirit Breaker, for instance, has an ability that gives him a 17% chance to “bash,” or deal extra damage and briefly stun an enemy, when he attacks. Being completely random, it is possible to bash several times in a row, and this can be a big source of frustation when a Spirit Breaker is on the other team.
Inspired by the many jokes and complaints about this ability, I decided to examine just how lucky these Spirit Breaker players were getting. Each attack is an independent Bernoulli trial, where a “success” means that the Spirit Breaker bashes his enemy, with probability 0.17. Attacking several times in a row amounts to repeating the Bernoulli trial several times in a row, and a lucky string of bashes amounts to a run of Bernoulli successes. As it turns out, there is a closed-form expression for the probability of a success run. Now all that remains is to plug in the numbers describing just how unlucky you are — say, the enemy Spirit Breaker gets off a run of 4 or 5 bashes in 5 attacks, which is enough to kill you from full health — and compute the probability of your misfortune (in this case it’s just over 3 in 2,000).
Instead of doing the computations by hand, I decided to brush up on my JavaScript/HTML/CSS skills and build a calculator (source on GitHub). Click the “Show” button to view it.
It’s amazing how even a simple project like this can make you feel more at home with a set of tools. I remember struggling with the Javascript/HTML/CSS toolkit when we were learning how to use D3.js in my data visualization class at QMSS. This calculator is a very small project, but I feel a lot more confident with these tools than before. As I was finishing up, I discovered that I could have used an HTML 5 <form>
element instead of a plain <div>
, and that I could have had the input boxes validate their inputs automatically with <input type=number>
, rather than cluttering up the calculator function. I’ll definitely consider using these in the future.
By the way, Spirit Breaker’s bash is one of the only probabilistic skills in the game that uses a true independent Bernoulli distribution for each trial. Most others follow a “pseudo-random distribution” that helps prevent runs while preserving the long-run expected probability of success. At the end of the day, designing a game is largely about making sure the players are having fun, and frustratingly long streaks of successes are (usually) not fun. Humans hold some interesting cognitive biases about clustering in random numbers, and the PRD is a great way to make the game feel more fair and fun, without removing the illusion of randomness.