Internet Speed Test
Dungeons and Dragons Monte Carlo Simulation
Github Link
Spoiler alert, if things weren't already nerdy enough, we're going to turn up the nerdy to 11.
​
While some of the calculations can be easily done in your head, many damage and chance to hit calculations and comparisons require a more intensive analysis. For instance, calculating the probability of successfully hitting an enemy while dual-wielding swords, or comparing the damage in that scenario to the damage that would be done with another weapon configuration, is useful to do in Python. Since these calculations can potentially involve very large probability trees, Monte Carlo simulations become very useful.
​
Monte Carlo simulations are useful tools for determining the probabilities of outcomes that depend on the probabilities of many individual events. With enough computing power, it becomes easier to simulate these outcomes rather than analytically calculate the probability of each outcome. One cool application of Monte Carlo simulations is in the semiconductor industry. When designing MEMS, these simulations allow engineers to predict the distribution of device properties that result from semiconductor process corners. By modeling process variation of several dimension with a Gaussian probability distribution, and by knowing the effects this has on the design (via compliancy changes, spring softening, mass changes, ect...), a designer can determine the resulting distribution of device properties (ie device sensitivity, resonant frequency, ect...). When running a very large number of simulations, the resulting output should accurately represent the actual distribution.
​
In Dungeons and Dragons, I typically play as a Ranger with a longbow. Not only was I interested in determining the probability distribution of causing damage, but I was also interested in seeing how the damage output of duel wielding swords would compare. The analysis below focuses on this example.
​
Code and Setup
​
The code is located on Github here. To learn more about Dungeons and Dragons attacking basics, check this page out:
​
The code should be pretty straightforward. The iPython notebook goes through a few examples of using the code.
​
Plotting Longbow Damage Probabilities

Above are plots showing the probability of a given damage output for a given armor class (AC) using 1e6 simulations. The distribution on the left shows that probability of missing (doing 0 damage) increase 5% for point increase in AC, which is expected. The distribution on the right is show the probabilities for a certain damage given that damage is guaranteed (no misses). The initial peak is centered around 19, which is the expected value of all damage modifiers added up (4.5 from longbow, 3.5 from Hunter's Mark, 3.5 from Sneak Attack, 4.5 from Colossus Strike, 3 from dexterity). The second smaller hump is a result of critical hits which, while rare, double the damage. Interestingly, this leaves a region between the two humps where damage outputs are very unlikely (very high damage rolls that are not critical hits).
​
The results do have one confusing conclusion. If the case that misses are ignored, it seems like on average more damage is given to targets with a higher amor class. At first, I thought something was wrong with the code. After all, a target's armor class should have no impact on any damage die rolls. While this is true, it still impacts the proportion of attacks that are critical hits. When the armor class is higher, there is a higher proportion of critical attacks compared to non-critical attacks. Another way to think about this is that there will always be one D20 roll that results in a critical (20), but a reduced amount of non-critical hits with an increased AC.
​
Reducing the Number of Simulations

Above is a plot using n=1e3 simulations. Clearly the resolution is much worse, but we still get the same overall shape. The same mean analysis above is still valid, just much easier to realize.
​
Plotting Dual-Wielding Short Sword Damage

Clearly something a little more interesting is happening here. In the distribution that does not include misses, the lower damage side of the distribution shows a very sharp distribution. This makes sense when you consider all the bonuses a ranger gets almost only apply to a single weapon attack. Out of the bonuses described above, only Hunter's Mark applies to the second weapon attack. As a result, the two 1D6 attacks from this pointy distribution for one sword. The combination of damage from the two swords forms the more interesting distribution just to the right. The 2nd hump on this distribution is again due to the extra damage from a critical hit.
​
Plotting Bow vs. Sword for Armor Class = 16

The above plot is a direct comparison of using a longbow vs dual wielding short swords. The most obvious difference is that the longbow consists of a single distribution while the swords consists of two distributions. When looking at the average damage done (including misses), the short swords actually do slightly more damage due to the fact that you have two opportunities to hit, so a complete miss is much more unlikely. However, that would require being directly engaged with an enemy which is much more dangerous. Since the average damage is very similar, I would rather shoot the enemy safely from 100 feet away.