How does Halfling Luck (re-rolling my Nat 1's) affect my dice outcome?

The Halfling Luck racial trait lets you reroll natural 1's on checks, saves, and attack rolls, but you must keep the second result. With Advantage or Disadvantage, it lets you re-roll only one of the dice if both turned out to be 1's.

How does this affect the expected statistical outcome of the roll? Note, also consider Advantage & Disadvantage, as the trait affects that roll as well.

It adds up to a +0.5 to all rolls

The average roll of a die is 10.5, which is just the average value of the numbers 1-20.

We re-roll any die that comes up as 1, and since we stick with whatever that outcome is, we can just replace the 1 in the list with the average roll again, and recalculate the average, giving us an average roll of 10.975.

Therefore, the halfling luck trait is approximately a +0.5 to all d20 rolls.

This is the distribution, as generated from a quick and dirty matlab script I wrote. As you can expect, it's pretty uniform for all values that are not 1 (note that there's still some variation, because it comes from actual random numbers and not an analytic calculation):

I modified my script to see how it would affect advantage and disadvantage.

• Normal average: 7.17
• With Halfling luck:7.80

• Normal average: 13.82
• With Halfling luck: 14.13

We can see that there's about a +0.6 bonus for disadvantage, whereas there's only a +0.3 bonus for advantage. Of course, this makes sense, because rolling a 1 is more impactful for disadvantage than it is for advantage, as the plots make clear.

Also worth noting is that the fact that you only reroll one die doesn't really seem to change the average value. Again, this makes sense because you only have a 1/400 chance of rolling two ones.

• If I understand correctly, it adds precisely 0.5 to the average. The average roll of just the results 2 thru 20 (sum[2 to 20] ÷19) is 11, and 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 adds up to 220, divided by 20 gives an average of exactly 11. – doppelgreener May 18 '17 at 16:01
• @doppelgreener, that's only true if you re-roll all 1s. However, the feature only lets you reroll once, so it's still possible to get a 1 on the second roll, which brings the average down a bit. – Icyfire May 18 '17 at 16:06
• @thedarkwanderer, what are more important statistics? – Icyfire May 18 '17 at 16:08
• @Icyfire Factor of improvement for odds of success/failure for given target numbers. If you only fail on a 1, Lucky decreases your risk of failure by a factor of 20. If you only succeed on a 20, Lucky increases your chance of success by 5%. This is most important for attack rolls, where you can automatically miss on a 1 or hit on a 20 and Lucky drastically improves your hit rate versus large groups of weak enemies you hit on anything but a 1. For saves and checks, where critting isn't possible, Lucky can't allow you to do anything you otherwise wouldn't be able to do: you can't roll 21. – Please stop being evil May 18 '17 at 16:25
• There are only 400 possibilities for the non-advantage/disadvantage case, and 8000 for the advantage/disadvantage case. Simply pretend to roll the extra die and ignore it if you don't get at least one 1. Simulation seems overkill. – Yakk May 18 '17 at 23:19

Probabilities for exact rolls

The values below show the chances for each roll to occur exactly. I also added in straight roll calculations to provide a comparison, and color-coded the matching columns.

The column showing the odds simply show a ratio of two probabilities. In this case, the Non-Halfling probability divided by the Halfling probability shows how much more likely you are to roll exactly $x$ when you are not a halfling.

In general, you are more likely to roll the lower values when not a halfling, but not by much. The exceptions are for rolling 1's (you are really not likely to roll them) and rolling 2 through 5 if with advantage. But otherwise, the odds are generally within 0.9 to 1.1, so there is not a very large effect.

Probabilities for cumulative rolls

The values below show the chances for each roll to occur cumulatively -- ie, the row for Roll = 4 shows the chances of getting at least a 4 in the different scenarios. I also added in straight roll calculations to provide a comparison, and a column on odds.

Solution

Let's calculate $Pr(X = x)$ with a straight roll, with Advantage, and with Disadvantage.

Straight Roll

If you roll a $2$ through $20$, you must keep it. But if you roll a $1$, you reroll it and keep the second result. The second roll has a $\frac{1}{20}$ chance of happening, but branches out to a further $20$ equally-likely possibilities. This means if we want to get a specific roll of $x$, the chances are:

\begin{align*} Pr(X = x) = \frac{1}{20} + (\frac{1}{20} \times \frac{1}{20}) = \frac{21}{400} = 5.25\%\ \end{align*}

But to roll a $1$, you must roll $1$'s both times:

\begin{align*} Pr(X = x) = \frac{1}{20} \times \frac{1}{20} = \frac{1}{400} = 0.25\%\ \end{align*}

There are many sub-cases here that we have to go over. Let's say we wanted to roll a $10$ exactly:

• If you roll a $10$ on the first dice, and not a $1$ or a $10$ or higher on the second (and count this twice, by symmetry);

• If you roll a $10$ on both dice;

• If you roll a $1$ on the first dice, and not a $1$ or a $10$ or higher on the second, and you roll a $10$ on the re-roll (and count this twice, by symmetry);

• If you roll a $1$ on both dice, and roll a $10$ on the re-roll;

• If you roll a $10$ on the first dice, a $1$ on the second, and you roll a $10$ or less on the re-roll (and count this twice, by symmetry).

The probabilities are (with the terms in order of the above):

\begin{align*} Pr(X = 10) = (2 \times \frac{1}{20} \times \frac{8}{20}) + (\frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{8}{20} \times \frac{1}{20}) + (\frac{1}{20} \times \frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{1}{20} \times \frac{10}{20}) \end{align*} \begin{align*} Pr(X = 10) = \frac{377}{8000} = 4.7125\% \end{align*}

If you can spot the pattern above, we can generalize that as:

\begin{align*} Pr(X = x) = (2 \times \frac{1}{20} \times \frac{x-2}{20}) + (\frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{x-2}{20} \times \frac{1}{20}) + (\frac{1}{20} \times \frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{1}{20} \times \frac{x}{20}) \end{align*} \begin{align*} Pr(X = x) = \frac{21 \times (x-2)}{4000} + \frac{x}{4000} + \frac{21}{8000} \end{align*}

Where $x$ is the number we want to roll exactly.

Note that the probability for $Pr(X = 1)$ is derived here differently. You must roll a $1$ on all three rolls for this to happen, or:

\begin{align*} Pr(X = 1) = \frac{1}{20} \times \frac{1}{20} \times \frac{1}{20} = \frac{1}{8000} = 0.0125\% \end{align*}

Once again, we have a few sub-cases when rolling with Disadvantage. Again, let us roll a $10$ exactly:

• If you roll a $10$ on the first dice, and not a $10$ or lower on the second (and count this twice, by symmetry);

• If you roll a $10$ on both dice;

• If you roll a $1$ on the first dice, and not a $10$ or lower on the second, and a $10$ on the re-roll (and count this twice, by symmetry);

• If you roll a $1$ on the first dice, a $10$ on the second, and a $10$ or higher on the re-roll (and count this twice, by symmetry);

The probabilities are (with the terms in order of the above):

\begin{align*} Pr(X = 10) = (2 \times \frac{1}{20} \times \frac{10}{20}) + (\frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{10}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{1}{20} \times \frac{11}{20}) \end{align*}

And once again, spotting the pattern, we have:

\begin{align*} Pr(X = x) = (2 \times \frac{1}{20} \times \frac{20-x}{20}) + (\frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{20-x}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{1}{20} \times \frac{21-x}{20}) \end{align*}

And simplified:

\begin{align*} Pr(X = x) = \frac{21 \times (20-x)}{4000} + \frac{21-x}{4000} + \frac{1}{400} \end{align*}

Where $x$ is the number we want to roll exactly.

Once again, the probability for rolling a $1$ is different. You get a $1$:

• If both the first and second dice come up as $1$;

• If the first dice comes up as $1$, and not the second dice, and the re-roll comes up as $1$ (and count this twice, by symmetry).

This works out to be:

\begin{align*} Pr(X = 1) = (\frac{1}{20} \times \frac{1}{20}) + (2 \times \frac{1}{20} \times \frac{19}{20} \times \frac{1}{20}) = \frac{29}{4000} = 0.725\% \end{align*}

Now that we have all the formulas of $x$ for any value of the d20, we can tabulate them. All values below are exact values.

\begin{array}{|c|c|} \hline \text{Roll} & \text{Advantage} & \text{Straight Roll} & \text{Disadvantage} \\ \hline 1 & 0.0125\% & 0.25\% & 0.725\% \\ \hline 2 & 0.3125\% & 5.25\% & 10.175\% \\ \hline 3 & 0.8625\% & 5.25\% & 9.625\% \\ \hline 4 & 1.4125\% & 5.25\% & 9.075\% \\ \hline 5 & 1.9625\% & 5.25\% & 8.525\% \\ \hline 6 & 2.5125\% & 5.25\% & 7.975\% \\ \hline 7 & 3.0625\% & 5.25\% & 7.425\% \\ \hline 8 & 3.6125\% & 5.25\% & 6.875\% \\ \hline 9 & 4.1625\% & 5.25\% & 6.325\% \\ \hline 10 & 4.7125\% & 5.25\% & 5.775\% \\ \hline 11 & 5.2625\% & 5.25\% & 5.225\% \\ \hline 12 & 5.8125\% & 5.25\% & 4.675\% \\ \hline 13 & 6.3625\% & 5.25\% & 4.125\% \\ \hline 14 & 6.9125\% & 5.25\% & 3.575\% \\ \hline 15 & 7.4625\% & 5.25\% & 3.025\% \\ \hline 16 & 8.0125\% & 5.25\% & 2.475\% \\ \hline 17 & 8.5625\% & 5.25\% & 1.925\% \\ \hline 18 & 9.1125\% & 5.25\% & 1.375\% \\ \hline 19 & 9.6625\% & 5.25\% & 0.825\% \\ \hline 20 & 10.2125\% & 5.25\% & 0.275\% \\ \hline \end{array}

And the cumulative distribution to roll at least $x$. All values below are exact values.

\begin{array}{|c|c|} \hline & \text{Advantage} & \text{Straight Roll} & \text{Disadvantage} \\ \hline 1 & 1 & 1 & 1 \\ \hline 2 & 0.999875 & 0.9975 & 0.99275 \\ \hline 3 & 0.99675 & 0.945 & 0.891 \\ \hline 4 & 0.988125 & 0.8925 & 0.79475 \\ \hline 5 & 0.974 & 0.84 & 0.704 \\ \hline 6 & 0.954375 & 0.7875 & 0.61875 \\ \hline 7 & 0.92925 & 0.735 & 0.539 \\ \hline 8 & 0.898625 & 0.6825 & 0.46475 \\ \hline 9 & 0.8625 & 0.63 & 0.396 \\ \hline 10 & 0.820875 & 0.5775 & 0.33275 \\ \hline 11 & 0.77375 & 0.525 & 0.275 \\ \hline 12 & 0.721125 & 0.4725 & 0.22275 \\ \hline 13 & 0.663 & 0.42 & 0.176 \\ \hline 14 & 0.599375 & 0.3675 & 0.13475 \\ \hline 15 & 0.53025 & 0.315 & 0.099 \\ \hline 16 & 0.455625 & 0.2625 & 0.06875 \\ \hline 17 & 0.3755 & 0.21 & 0.044 \\ \hline 18 & 0.289875 & 0.1575 & 0.02475 \\ \hline 19 & 0.19875 & 0.105 & 0.011 \\ \hline 20 & 0.102125 & 0.0525 & 0.00275 \\ \hline \end{array}

• Halfling/Non generates a prettier value at least for "strait roll" than non/half. – Yakk May 18 '17 at 23:21
• @Yakk I think the Non/Halfling values better exaggerate the differences at lower values though, so I went that way. – user27327 May 19 '17 at 4:12
• you people are insane, in all the best ways – René Roth May 20 '17 at 14:14

Using this Anydice program, anydice's statistical calculations show that your chance to roll a 1 on a d20 (since you can reroll a 1 on most checks) is reduced to 0.25%, and your chance to roll any other number on that roll increases by 0.25%, going from 5% to 5.25% (the 5% chance of rolling a 1 is distributed evenly across all 20 numbers in the reroll).

With advantage, you have almost no chance of rolling 1 as your highest number, and with disadvantage, your chance of rolling 1 as your lowest number is greatly reduced. Advantage changes from 0.25% down to 0.0125% chance of a result of 1, and disadvantage's chance of a 1 is reduced from 9.75% to 0.725%.

Getting other results with advantage and disadvantage also change. From the Export panel of the Normal readout of the Anydice program, these are the chances to get each possible result:

\begin{array}{|c|c|}\hline \ & \text{Normal} & \text{Lucky} & \\ \ \text{Result} & \text{% Chance} & \text{% Chance} & \text{Difference} \\ \hline 1 & 0.25 & 0.0125 & -0.2375\\ \hline 2 & 0.75 & 0.3125 & -0.4375\\ \hline 3 & 1.25 & 0.8625 & -0.3875\\ \hline 4 & 1.75 & 1.4125 & -0.3375\\ \hline 5 & 2.25 & 1.9625 & -0.2875\\ \hline 6 & 2.75 & 2.5125 & -0.2375\\ \hline 7 & 3.25 & 3.0625 & -0.1875\\ \hline 8 & 3.75 & 3.6125 & -0.1375\\ \hline 9 & 4.25 & 4.1625 & -0.0875\\ \hline 10 & 4.75 & 4.7125 & -0.0375\\ \hline 11 & 5.25 & 5.2625 & 0.0125\\ \hline 12 & 5.75 & 5.8125 & 0.0625\\ \hline 13 & 6.25 & 6.3625 & 0.1125\\ \hline 14 & 6.75 & 6.9125 & 0.1625\\ \hline 15 & 7.25 & 7.4625 & 0.2125\\ \hline 16 & 7.75 & 8.0125 & 0.2625\\ \hline 17 & 8.25 & 8.5625 & 0.3125\\ \hline 18 & 8.75 & 9.1125 & 0.3625\\ \hline 19 & 9.25 & 9.6625 & 0.4125\\ \hline 20 & 9.75 & 10.2125 & 0.4625\\ \hline \end{array}

\begin{array}{|c|c|}\hline \ & \text{Normal} & \text{Lucky} & \\ \ \text{Result} & \text{% Chance} & \text{% Chance} & \text{Difference} \\ \hline 1 & 9.75 & 0.725 & -9.025\\ \hline 2 & 9.25 & 10.175 & 0.925\\ \hline 3 & 8.75 & 9.625 & 0.875\\ \hline 4 & 8.25 & 9.075 & 0.825\\ \hline 5 & 7.75 & 8.525 & 0.775\\ \hline 6 & 7.25 & 7.975 & 0.725\\ \hline 7 & 6.75 & 7.425 & 0.675\\ \hline 8 & 6.25 & 6.875 & 0.625\\ \hline 9 & 5.75 & 6.325 & 0.575\\ \hline 10 & 5.25 & 5.775 & 0.525\\ \hline 11 & 4.75 & 5.225 & 0.475\\ \hline 12 & 4.25 & 4.675 & 0.425\\ \hline 13 & 3.75 & 4.125 & 0.375\\ \hline 14 & 3.25 & 3.575 & 0.325\\ \hline 15 & 2.75 & 3.025 & 0.275\\ \hline 16 & 2.25 & 2.475 & 0.225\\ \hline 17 & 1.75 & 1.925 & 0.175\\ \hline 18 & 1.25 & 1.375 & 0.125\\ \hline 19 & 0.75 & 0.825 & 0.075\\ \hline 20 & 0.25 & 0.275 & 0.025\\ \hline \end{array}

As you can see, the chances of getting under 11 decrease slightly with Lucky Advantage, and while individual low results increase with disadvantage, even the chance of a 20 is marginally increased via Lucky Disadvantage.

Program used:

function: reroll R:n under N:n {
if R < N { result: 1d20 } else {result: R}
}

function: rerolladv ONE:n and TWO:n under N:n {
if ONE < N {
result: [highest of 1d20 and TWO]
}
else if TWO < N {
result: [highest of ONE and 1d20]
}
else {
result: [highest of ONE and TWO]
}
}

function: rerolldis ONE:n and TWO:n under N:n {
if ONE < N {
result: [lowest of 1d20 and TWO]
}
else if TWO < N {
result: [lowest of ONE and 1d20]
}
else {
result: [lowest of ONE and TWO]
}
}

LUCK: [reroll 1d20 under 2]
LUCKY_ADV: [rerolladv 1d20 and 1d20 under 2]
LUCKY_DIS: [rerolldis 1d20 and 1d20 under 2]
output 1d20 named "Normal 1d20"
output LUCK named "Lucky 1d20"
output [highest 1 of 2d20] named "Normal Advantage"
output [lowest 1 of 2d20] named "Normal Disadvantage"
output LUCKY_DIS named "Lucky Disadvantage"


Good answers: wrong question

Lots of good answers here but they miss the point of Halfling Luck. The real question is not how it affects the distribution of the die but how often it turns a failure into a success. It really doesn't' matter if Halfling luck turns your 1 into a 7 if a 7 is still a fail.

Methodology

What is critical is the Target number - the actual number you have to roll equal to or above on the die to succeed. This can be calculated from the AC or DC by subtracting your bonus from that number because +7 to hit AC 17 is the same as +0 to hit AC 10.

Using this very elegant technique from Ilmari Karonen we can construct a success die in anydice for each target number from 1 to 20 for both save/ability checks and attacks (since attacks have autofail and critical success they have to be treated differently).

Saves and Ability Checks

loop TARGET over {1..20} {

FAIL: [lowest of 20 and [highest of 0 and TARGET-1]]
SUCCESS: [lowest of 20 and [highest of 0 and 21-TARGET]]

SAVE: {0:FAIL, 1:SUCCESS}
HALFLINGSAVE: {SAVE, 0: 20*(FAIL-1), 1: 20*SUCCESS}

output dSAVE named "Normal: [TARGET]"
output dHALFLINGSAVE named "Halfling: [TARGET]"
}


Implemented here.

What this does is build for the normal save a 20 sided die that doesn't have the numbers 1 to 20 on it but rather has a number of 0's and 1's (fails & successes) against each target number. The halfling save uses this die to create a 400 sided die ($20\times20$) to represent the reroll.

There is a very simple linear relationship in absolute terms between the increased chance Halfling luck gives you for the range 2-20 (at 1 it makes no difference since you will always pass):

$$\text{Increase}=0.0525-0.0025\times\text{Target}$$

That is, the harder the task, the less benefit it gives you. This is the straight increase in your chance of succeeding.

However, in relative terms a Halfling has 1.05 times anyone else's chance.

Attacks

loop TARGET over {1..20} {

FAIL: [lowest of 19 and [highest of 0 and TARGET-1]]
SUCCESS: [lowest of 19 and [highest of 0 and 21-TARGET]]

ATTACK: {0, 0:[highest of 0 and FAIL-1], 1:[highest of 0 and SUCCESS-1], 2}
HALFLINGATTACK: {ATTACK, 0:20*[highest of 0 and FAIL-1], 1:20*[highest of 0 and SUCCESS-1], 2:20}

output dATTACK named "Normal: [TARGET]"
output dHALFLINGATTACK named "Halfling: [TARGET]"
}


Implemented here.

Similar to the above except we ensure that there is always one fail (representing a 1) and introduce a 2 to represent a critical hit.

Unsurprisingly, the results are very similar. There is a straight $0.0025$ increase in critical hit chance (from 0.05 to 0.0525) and the formula for the range 2-20 for regular hits is:

$$\text{Increase}=0.05-0.0025\times\text{Target}$$

If you add back in critical hits the formula is exactly the same as for saves/ability checks.

The relative improvement is still 1.05 (for both normal and critical hits).

Halfling Luck, on average, increases your d20 roll by 0.47 on normal rolls, 0.620 for disadvantage rolls, and 0.308 for advantage rolls.

Disclaimer: While never having played D&D, I lurk on rpg.se quite a lot because the game in itself interests me, although I never have had a chance to play it yet... Thank you markovchain for helping me understand the basic rules better.

Using a quick and dirty Python script I made, here are my results:

~~~~~Normal Rolls~~~~~

Total number of rolls: 1000000
Total number of rerolls: 50201
Percentage of rerolls compared to total number of rolls:
0.050201
Average value of a die across all rolls without Halfling Luck:
10.505604
Average value of a die across all rolls with Halfling Luck:
10.983658
Difference of values:
0.478054

Total number of pairs rolled: 1000000
Total number of rerolls: 97346
Total number of die rolls (pairs plus rerolls): 1097346
Percentage of rerolls compared to total number of pairs rolled:
0.097346
Average value of a disadvantage die across all pairs rolled without Halfling Luck:
7.181028
Average value of a disadvantage die across all pairs rolled with Halfling Luck:
7.801206
Average value of an advantage die across all pairs rolled without Halfling Luck:
13.831522
Average value of an advantage die across all pairs rolled with Halfling Luck:
14.139669
Difference of values between disadvantage dice values with Halfling Luck due to [1][1] vs without Halfling Luck:
0.620178
Difference of values between advantage dice values with Halfling Luck due to [1][1] vs without Halfling Luck:
0.308147


Here is my script. I apologize for my variable names:

from random import randint
import numpy as np

end = 1000000

# Normal rolls

a = np.zeros(20)
areroll = np.zeros(20)
average = 0
averagereroll = 0
numberofrerolls = 0

for i in range(0, end):
x = randint(1, 20)
a[x - 1] = a[x - 1] + 1
if x is 1:
x = randint(1, 20)
numberofrerolls = numberofrerolls + 1
areroll[x - 1] = areroll[x - 1] + 1

for q in range(1, 21):
average = average + (q * a[q - 1])

for q in range(1, 21):
averagereroll = averagereroll + (q * areroll[q - 1])

print("~~~~~Normal Rolls~~~~~")
print()
print("Total number of rolls: %d" % end)
print("Total number of rerolls: %d" % numberofrerolls)
print("Percentage of rerolls compared to total number of rolls:")
print(numberofrerolls / end)
print("Average value of a die across all rolls without Halfling Luck:")
print(average / end)
print("Average value of a die across all rolls with Halfling Luck:")
print(averagereroll / end)
print("Difference of values: ")
print((averagereroll / end) - (average / end))

numberofrerolls = 0
averagea = 0
averaged = 0
averagear = 0
averagedr = 0

for i in range(0, end):
x = randint(1, 20)
y = randint(1, 20)
if x is 1 and y is 1:
z = randint(1, 20)
numberofrerolls = numberofrerolls + 1
disadvantagewithrerolls[x - 1] = disadvantagewithrerolls[x - 1] + 1
advantagewithrerolls[z - 1] = advantagewithrerolls[z - 1] + 1
disadvantage[x - 1] = disadvantage[x - 1] + 1
advantage[x - 1] = advantage[x - 1] + 1
else:
if x is y:
disadvantage[x - 1] = disadvantage[x - 1] + 1
advantage[x - 1] = advantage[x - 1] + 1
disadvantagewithrerolls[x - 1] = disadvantagewithrerolls[x - 1] + 1
advantagewithrerolls[x - 1] = advantagewithrerolls[x - 1] + 1
elif x is 1:
z = randint(1, 20)
numberofrerolls = numberofrerolls + 1
if z > y:
advantagewithrerolls[z - 1] = advantagewithrerolls[z - 1] + 1
disadvantagewithrerolls[y - 1] = disadvantagewithrerolls[y - 1] + 1
else:
advantagewithrerolls[y - 1] = advantagewithrerolls[y - 1] + 1
disadvantagewithrerolls[z - 1] = disadvantagewithrerolls[z - 1] + 1
disadvantage[x - 1] = disadvantage[x - 1] + 1
advantage[y - 1] = advantage[y - 1] + 1
elif y is 1:
z = randint(1, 20)
numberofrerolls = numberofrerolls + 1
if z > x:
advantagewithrerolls[z - 1] = advantagewithrerolls[z - 1] + 1
disadvantagewithrerolls[x - 1] = disadvantagewithrerolls[x - 1] + 1
else:
advantagewithrerolls[x - 1] = advantagewithrerolls[x - 1] + 1
disadvantagewithrerolls[z - 1] = disadvantagewithrerolls[z - 1] + 1
disadvantage[y - 1] = disadvantage[y - 1] + 1
advantage[x - 1] = advantage[x - 1] + 1
elif x < y:
disadvantage[x - 1] = disadvantage[x - 1] + 1
advantage[y - 1] = advantage[y - 1] + 1
disadvantagewithrerolls[x - 1] = disadvantagewithrerolls[x - 1] + 1
advantagewithrerolls[y - 1] = advantagewithrerolls[y - 1] + 1
else:
disadvantage[y - 1] = disadvantage[y - 1] + 1
advantage[x - 1] = advantage[x - 1] + 1
disadvantagewithrerolls[y - 1] = disadvantagewithrerolls[y - 1] + 1
advantagewithrerolls[x - 1] = advantagewithrerolls[x - 1] + 1

for q in range(1, 21):
averaged = averaged + (q * disadvantage[q - 1])
averagea = averagea + (q * advantage[q - 1])
averagedr = averagedr + (q * disadvantagewithrerolls[q - 1])
averagear = averagear + (q * advantagewithrerolls[q - 1])

d = averaged / end
dr = averagedr / end
a = averagea / end
ar = averagear / end

print()
print()
print("Total number of pairs rolled: %d" % end)
print("Total number of rerolls: %d" % numberofrerolls)
print("Total number of die rolls (pairs plus rerolls): %d" % (numberofrerolls + end))
print("Percentage of rerolls compared to total number of pairs rolled:")
print(numberofrerolls / end)
print("Average value of a disadvantage die across all pairs rolled without Halfling Luck:")
print(d)
print("Average value of a disadvantage die across all pairs rolled with Halfling Luck:")
print(dr)
print("Average value of an advantage die across all pairs rolled without Halfling Luck:")
print(a)
print("Average value of an advantage die across all pairs rolled with Halfling Luck:")
print(ar)
print("Difference of values between disadvantage dice values with Halfling Luck vs without Halfling Luck: ")
print(dr - d)
print("Difference of values between advantage dice values with Halfling Luck vs without Halfling Luck: ")
print(ar - a)


A trait that allows you to reroll a die, at least some of the time, is, in my opinion, always a good thing to have, although on average the results are not drastic. Rerolling a guaranteed failure and getting a successful result makes for great roleplaying though.

• Also, welcome to RPG.SE, and thanks for pitching in! I love getting different solutions via different methods of solving the same problem. It really shows the breadth and depth you can have with just a simple D&D mechanic. Please do take the tour if you haven't yet, and I look forward to seeing your updates on this answer! – user27327 May 31 '17 at 12:18
• @markovchain thank for you taking the time to provide some of your knowledge of the game to me. I have updated the script based on your explanations of the rules and the results now agree with other answers. Getting down and dirty with mechanics such as this makes me even more excited to play my first game of d&d, whenever that will be :) – A.B. May 31 '17 at 14:36
• Glad to have helped, and good answer! I've deleted my comments as they are now obsolete. If you are looking for a D&D game but unsure where to look for, there's Adventurer's League (if you have it in your area) or online places like Roll20.net. – user27327 May 31 '17 at 14:43