# Struggling with rolling for stats probability calculation

I tried finding a specific statistic calculator, even tried playing with anydice.com, with no success. My friends love to roll dice, but we also want the same playing field when starting a campaign, so we thought of this idea: Each player rolls for their starting stats and those are the viable arrays to pick from (assumptions is everyone picks the same best one rolled by one of the players). Of course you can't do 4d6 drop lowest as that would be too strong compared to regular style.

So how can I calculate a statistical fairness as close to original 4d6 drop lowest? Can we do just straight up 3d6 rolling? If there are 4 players, each rolling 3d6 6 times, and all pick the best array that feels OK-ish.

I've read this article and tried to use the commands to simulate my result. When I tried it out with 3d6 it showed up to 4 times lower odds of 18, compared to 4d6 drop lowest, so if we roll it 4 times, it should equal in theory, or be sliiightly better?

I understand the more players, the better this variant score would be. So I'm counting with 4 players rolling.

• @Trish Isn't the idea that the players choose (presumably the better) of the set of four? And if you roll a thing four times and choose the highest that should affect the distribution, no? May 18, 2021 at 23:48
• The answer to this (really interesting) question is very complicated. First, if you just consider one ability score, the distribution of the max of n rolls is not the same as the distribution of one roll. Second, if you consider an entire array, the act of choosing an array induces covariance among the scores: the probability of a given array (chosen as the array with the maximum sum of scores, say) is not simply the product of the probabilities of the individual scores (chosen as the max of n individual scores), nor is its distribution the same as the distribution of one array. May 19, 2021 at 2:26
• I'm not convinced this question has an answer. Consider the simpler case of two players using this method, therefore choosing between two arrays of stats, which I'll assume are collections of six numbers each (i.e., D&D style.) Array A: [13, 13, 13, 13, 15, 11], Array B: [13, 13, 13, 13, 17, 9]. Which one is better? Until you answer that question (in the general sense of ranking each outcome), I don't think you can calculate the statistics on the outcome of that choice, which is what I think you're trying to do. May 19, 2021 at 3:41
• @Novak you're absolutely correct. We can only approach this problem if we have a concrete model of how players choose among arrays. I provide an approximate solution below when players choose the array that has the highest sum of scores. May 19, 2021 at 4:02
• @Novak An alternative method would be the array with the highest point-buy value. Makes the calculation more difficult but theoretically produces a more consistent "best array". May 19, 2021 at 8:23

# 4 arrays of 3D6 is slightly worse than 4D6d1

In essence this question is asking what the roll mechanic should be, such that when able to choose from a set of four arrays the expected power is approximately the same as the 4D6D1 method. This question sparked my interest so I set about writing a program to simulate it.

I choose to evaluate the quality of an array by the number of points it would require to purchase using the point buy system. (More details further down).

I'm going to put the results right up front because the methodology is a little complex. But simple put here is the probability distribution for the proposed system.

The average point buy values of each system are:

• Standard 4D6d1: 31.00
• Simple 3d6: 16.00
• Choose 4x 4d6d1: 42.00
• Choose 4x 3d6: 27.00

So we can quickly conclude that 4 arrays of 3D6 is slightly worse that the standard 4D6d1 method, but is closer than either of the other methods.

## Methodology

I used a script to simulate 10,000 iterations per method. However I needed a method to objectively assess which array was the 'best' among the set of available options. Luckily D&D 5e already has a method for determining the value of a set of stats, point buy.

### Why point buy?

The point buy system attached a value to the various ability scores, a single high score is often more valuable than a few medium scores, the point buy system reflects this. Normally point buy is limited to a maximum of 15 and a mimimum of 8 however since dice rolls can fall outside this range I ignored this and used the point costs from this calculator for higher and lower values.

The reasons this is a better metric for quality of an array can be demonstrated with the following example from OP's comment on another answer. Take 2 arrays:

• Array 1: 18, 18, 18, 10, 10, 10
• Array 2: 15, 14, 14, 14, 14, 14

As experience players we can determine that the first array is distinctly better. However a simplistic summation of the scores gives 84 and 85 respectively. The would indicate that Array 2 is, objectively, better. This is incorrect.

Using the point buy system instead Array 1 has a point-buy cost of 63 while Array 2 is only 44. Indicating the Array 1 is significantly better than Array 2. This aligns with our view of these stats as subjective players and is therefore a better metric.

Other systems (e.g pathfinder) use different values for point buy and therefore would have slightly different results. However I believe that using point-buy instead of total score would consistently show the 'better' array more often.

### Code details

To figure this out I wrote a python program to simulate the varies scenarios. First I simulate a dice roll. Then simulate the 2 attribute generation methods.

def RollD6():
return np.random.randint(1,7)

def RollNDice(n):
diceValues = np.random.randint(1,7,n)
return diceValues

def Roll3D6():
return sum(RollNDice(3))

def Roll4D6D1():
rolls = RollNDice(4)
rolls = np.delete(rolls, rolls.argmin()) # delete lowest value
return sum(rolls)


Next I created functions to generate arrays of stats based on the two mechanics and used a dictionary to look determine the point-buy value of that array.

PointBuyValue = {
3: -9,
4: -6,
5: -4,
6: -2,
7: -1,
8: 0,
9: 1,
10: 2,
11: 3,
12: 4,
13: 5,
14: 7,
15: 9,
16: 12,
17: 15,
18: 19
}

def RollStats4D6D1():
stats = []
for i in range(6):
stats.append(Roll4D6D1())
return stats

def RollStats3D6():
stats = []
for stat in range(6):
stats.append(Roll3D6())
return stats

for stat in stats:



I verified that my normal versions were working as expected with 4D6d1 performing better than 3d6, then created functions to answer the question. The two functions below calculate the maximum point buy value from 4 sets of attributes generated, this assumes that all players would choose the 'optimal' array based on this method.

def Choose4D6D1():
pb_max = 0
for i in range(4):
if pb > pb_max:
pb_max = pb
return pb_max

def Choose3D6():
pb_max = 0
for i in range(4):
if pb > pb_max:
pb_max = pb
return pb_max


Finally I rapped it all up, chucked it in a juypter notebook and ran 10,000 iterations to generate some distributions. I used a fixed seed so others should be able to replicate my results.

np.random.seed(42)

n_sims = 10000
record_4d6d1 = []
record_3d6 = []
record_pick4d6d1 = []
record_pick3d6 = []

for runs in range(n_sims):
record_pick4d6d1.append(Choose4D6D1())
record_pick3d6.append(Choose3D6())

print ("Average Point buy (4d6d1): %.2f" % (np.sum(record_4d6d1)/n_sims))
print ("Average Point buy (3d6): %.2f" % (np.sum(record_3d6)/n_sims))
print ("Average Point buy (Choose 4d6d1): %.2f" %
(np.sum(record_pick4d6d1)/n_sims))
print ("Average Point buy (Choose 3d6): %.2f" %
(np.sum(record_pick3d6)/n_sims))

ax = sns.distplot(record_4d6d1)
plt.title("Histogram of %d simulated rolls" % n_sims)
ax.set_ylabel("Count")

sns.distplot(record_3d6)
sns.distplot(record_pick4d6d1)
sns.distplot(record_pick3d6)
plt.legend(labels=['4d6d1', '3d6', 'Choose 4d6d1', 'Choose 3d6'])


I've posted the full code here so that you can see that the calculations are not actually that complex. There is just a lot of steps involved.

## Detailed Results

Looking at the distributions in the chart and averages given above we can see that the Choose 3D6 method and the standard 4D6d1 method are the closest in terms of average. With 3D6 being much lower and Choose 4D6d1 much higher. Therefore we can conclude that your system is a reasonable approximation and shouldn't have any issues during play.

However, the choosing method also results in a tighter distribution, meaning the expected arrays from this method will vary by less than the traditional method. The smaller standard deviation and lower average mean that you can expect slightly fewer 'great' arrays to arise from this system that the standard one, but also for the worst arrays to not be quite so bad.

So while you could over-analysis this data and fiddle with the exact mechanics to try to better approximate the 4D6d1 distribution. Your system of choosing from 4 arrays of 3d6 will likely result in similar enough arrays that you can safely use it at the table.

## Scaling to more players

Out of interest I modified my script to run work for more players. When modelling for eight players the average point buy value is 31, the same as the traditional 4D6d1.

• Wow. This is amasing to read through. Thank you very much for such a thorough answer. I had a hunch that it would be close enough, but seeing the data behind it makes it much better. May 19, 2021 at 12:47
• ideone.com/3KuyuU - if you get the players to roll 3d6 for 7 stats and drop the lowest stat, then take the best of the 4 players, you get an average close to 4d6d1.
– Yakk
May 19, 2021 at 14:18
• Nice answer! I went and reimplemented the same logic in AnyDice to avoid the sampling noise in your simulation results. May 19, 2021 at 15:31
• (Also, all those weird peaks in your histogram plots seem to be caused by improper binning in distplot; the actual distributions are smooth with no sharp peaks, and sampling noise isn't nearly strong enough to explain them either. Unfortunately I'm not familiar enough with seaborn / matplotlib to fix them easily.) May 19, 2021 at 18:46
• @IlmariKaronen I fixed the bug in the last chart, it was indeed a typo in my code leading to the same function being called twice rather than calculating the version for 8 players. Regarding the binning issue, I played with a few settings without significant improvement. Not sure I understand Seaborn well enough to know what is really going on. But the logic of the answer stands so I'm not going to spend any more time on it. May 20, 2021 at 14:42

Linksassin's idea of ranking stat arrays by their total point buy cost seems like a decent way to make this problem sufficiently well specified to be numerically answerable. Instead of doing a stochastic simulation as in linksassin's answer, however, it's also possible calculate the distributions of these point buy costs for different rolling methods exactly in AnyDice. I would almost say it's easy, but we do need a couple of non-trivial helper functions.

TL;DR: Picking the best of four arrays rolled with 3d6 per stat gives an average point buy cost of 27.1 points, which happens to be very close to the standard 5e point buy budget of 27 points (and is significantly better than the average of 16.9 points for a single 3d6-based array).

For the best of eight arrays, this method gives an average point buy cost of 31.4 points, which is nearly the same as the average point cost of a standard array rolled with 4d6 drop lowest. The variance in point costs is noticeably lower for the best-of-eight method, but how that actually translates to the practical distribution of stats is hard to say.

In practice, for any reasonable number of arrays to choose from, this method is likely to yield perfectly decent and playable stats. Whether the method feels good in play or achieves the OP's subjective goal of "a level playing field" is something that can really only be answered by playtesting it.

The first helper function we need is for calculating the 5e point buy cost of an arbitrary ability score from 3 to 18. Luckily, I already had a function to do that for Pathfinder 1e, so it was pretty easy to plug in the extended D&D 5e costs from linksassin's answer into it:

\ point buy cost of a single ability score using extended D&D 5e cost table \
\ from https://chicken-dinner.com/5e/5e-point-buy.html via https://rpg.stackexchange.com/a/185268 \
function: cost of SCORE:n {
if SCORE < 3 { result: -1000 }    \ safety check 1: rolling below 3 should be impossible \
if SCORE > 18 { result: 1000000 } \ safety check 2: rolling above 18 should also be impossible \
result: (SCORE - 2) @ { -9, -6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 7, 9, 12, 15, 19 }
}


Using this function, we can calculate the distribution of point buy costs for 6 stat arrays rolled using various methods, just like in the PF 1e answer I referenced above. This time, instead of outputting these distributions directly, I'll save them in variables for later use:

\ point cost distributions for 6 stat arrays rolled with different methods \
STANDARD: 6d[cost of [highest 3 of 4d6]]  \ standard (4d6 drop lowest) \
CLASSIC: 6d[cost of 3d6]  \ classic (3d6) \


Now, in principle you could just loop over various values of N from, say, 1 to 10 and plot the distribution of point costs for the best (= highest point cost) classic 3d6 array out of N using output 1@Nd(CLASSIC+0). (The +0 is needed to avoid weird behavior when N = 1.)

Unfortunately, if you try that, you'll find out that it times out for N > 4 because AnyDice uses an inefficient algorithm for calculating the distribution of the highest roll in a large pool. Fortunately I already had a solution to this problem in the form of another custom function:

\ optimized alternative to 1@(NdD) from https://rpg.stackexchange.com/a/176183 \
function: highest of N:n x D:d {
if N = 0 { result: 0 }
if N = 1 { result: D }
RES: 1@2d[highest of N/2 x D]
if N - (N/2)*2 = 1 { RES: [highest of D and RES] }
result: RES
}


With the help of that function, we can now finish the program:

output STANDARD named "5e point cost of standard 4d6 drop lowest array"
loop N over {1..10} {
output [highest of N x CLASSIC] named "highest 5e point cost of [N] classic 3d6 arrays"
}


The output of this code should look something like this (click image to enlarge):

As can be seen, picking the best of eight arrays rolled with 3d6 per stat gives almost exactly the same average point buy cost (31.37 points) as rolling a single standard array with 4d6 drop lowest for each stat (avg. 31.44 points).

With only four arrays to choose from the average cost drops to 27.10 points, which is less than with the standard rolling method but still considerably more than the average of only 16.94 points for a single 3d6 array. It's also coincidentally very close to the normal 5e point buy budget of 27 points, although of course the random rolling means that even if you do happen to get a 27-point array or better, the points might not have been spent quite the way you would've liked.

(These results also seem to be fairly robust to variations in the point buy costs. In particular, I also tried running the same code with the PF 1e point buy costs from my old answer and, which the actual summed costs are obviously quite different, best-out-of-8 with 3d6 still seems to be the closest match to 4d6 drop 1. Tweaking the point buy cost of scores below 8 also doesn't seem to make much difference, suggesting that they're fairly rare using either method.)

Ps. The variance using the best-out-of-N method is a lot lower than for the standard method, which in general tends to suggest that it would be less "swingy" and more likely to yield consistently decent but not exceptional results. However, I'd take that with a grain of salt here, since what we're really doing here is comparing summed point buy costs, not the ability scores in the arrays themselves, and those summed costs can conceal a lot of variation. In general, rolling stats with 3d6 will tend to yield more swingy arrays than 4d6 drop lowest, which may somewhat counteract the reduced variance from being able to pick one array out of N.

In practice, I'd say the only way to find out how well this stat generation method really works is to try it out in a couple of games. At least it should be more or less in the same ballpark as other commonly used stat generation methods, and so probably fairly reasonable. And at the end of the day D&D is really quite tolerant of variations in stat generation anyway, especially if the DM adjusts encounters appropriately to fit the party.

• Just a curiosity: you say that Anydice computes the exact probabilities, instead of doing stochastic simulations. Maybe I found here what you mean (it lists all the possible sequences and then counts the occurrences), but I did not find anything in the documentation of Anydice. May 19, 2021 at 19:43
• @Eddymage: Yes, AnyDice is basically a domain-specific scripting language for doing math with finitely supported probability distributions over the integers. It never makes any random (or pseudorandom) dice rolls, but merely calculates what the mathematical probability distribution of the results would be if you did roll dice and count the results in a particular way. As a consequence its results contain no random noise and their accuracy is only limited by that of the floating-point math it uses internally. May 19, 2021 at 20:24
• I'm surprised this is practical, given that there are almost half a trillion (unordered) arrays. May 19, 2021 at 20:37
• @cereal_killer: That's because it doesn't generate all those arrays. What it does first is generate the distribution of all possible sums of a single 3d6 (or 4d6 drop 1) stat roll. Then it converts that into the distribution of point buy costs for one such stat roll, and from that it calculates the distribution of the sum of point costs for six independent stat rolls. Then it finally calculates the distribution of the highest of N independent samples from that distribution (which is the part I had to kluge, since AnyDice's built-in algorithm for that is needlessly slow). May 19, 2021 at 22:06
• @IlmariKaronen of course! Makes sense. May 19, 2021 at 22:30

We can only make progress on this problem if we make an assumption about how players choose arrays, as @Novak notes in comments to the OP. This answer assumes that players pick the array that has the maximum sum of ability scores. We can argue about how reasonable that is, but it is a place to start!

Let's imagine we roll each score as 4d6, drop the lowest. Each score will be (approximately) normally distributed. The sum of the scores for one array will also be quite normal. We can compute the mean and variance of the normal distribution for the sum of one array straightforwardly, as the sum of the means and variances of the individual rolls.

We then repeat this procedure 3 more times, so there are a total of 4 sums. The largest sum is the maximum value of 4 normal random variables. The expected value of the max can be computed using existing equations here. (I cannot find solutions for the full distribution of the max).

I simulated sums of arrays with the standard method (4d6, drop the lowest, but don't choose among arrays, blue in below graph), as well as for two other methods: 1) 4d6 drop lowest, choose among 4 (orange); 2) 3d6 drop, choose among 4 (green), and; 3) 3d6+1, choose among 4 (purple). The vertical lines correspond to the means (dashed lines are means of the simulations, solid lines are analytical calculations based on the above linked equations), and the blue normal density is the normal approximation for the 4d6 drop lowest method.

Unsurprisingly, none of the methods are exactly the same as the standard method (blue). The 3d6 methods are clearly the closest, within +/- 3 of the standard method.

• Thank you for this. I genuinely didn't expect my variant (3d6k3p4) be almost objectively worse than simple 4d6k3. I might just have an option for them to roll for stats and then pick standart DnD 5e array if they dislike what they rolled. May 19, 2021 at 7:48

## This Question Cannot Be Properly Answered

I would ordinarily just vote to close because there is not enough information, but in this case I think the full explanation of why I think the question cannot be answered is a form of (disappointing) answer in itself, because it's probably not obvious to the casual reader.

Concisely restated, what we want is:

• Some Process A for generating for generating a complete set of character stats;
• Repeat this Process A some number of times N, choosing the best of the N results;
• Manipulate or design Process A such that it closely resembles some other Process B;

There are some real problems with this:

First, there is no single definition of "how close" two probability functions are. To get into even some of the most common ones, you usually need to be studying statistics or a related field (data science, machine learning) at a professional level. But this is a quibble, as most people have an intuitive idea of what they mean by this.

But more importantly, there is no definition of what a "best" result is, for a number of different reasons. For one, this will be heavily informed by the game you are playing. But more than that, I can't think of any game which is so simple that you can always define one set of stats as being better, worse, or exactly equivalent to another set of stats, because players have different preferences over these numbers.

Consider playing ooooold school AD&D 1e, where Player A wants to be a magic-user and might rightly conclude that any array with an 18 as long as it contains at least one 6 or higher (such as 18-10-10-10-10-10) is superior to any array without (such as 12-9-13-9-17-10) because his spellcasting abilities depend on that, and only that, and he really wants to be able to cast those sweet, sweet 9th level spells if he just cowers behind the Paladin long enough to survive. (The 6 is for the minimum dexterity requirement.)

On the other hand, consider Player B in the same game who wants to be a paladin, so that first array is useless to her-- she just can't be a paladin unless she picks that second array. She has a fundamental, inarguable, but very rational preference that differs from his.

Nor is this a quirk of only archaic and weirdly designed systems. Just about any mechanical system that assigns bonuses and penalties is going to generate different preferences among players that aren't strictly tied to classes or other in-game choices. In a more modern D&D system, the two arrays [11, 11, 11, 11, 13, 9] and [11, 11, 11, 11, 17, 5] seem similar-- they sum to the same number-- but some players like generalized competence (the first array) while others like to play bold strengths and weaknesses (the second.)

So this can't be fixed just by filling in a tag to clarify what system you want to use-- I'm not aware of any system where you can get a proper order to these stats.

Without that, you cannot execute the "Choose the best of the N rolls," and without that you cannot calculate the statistics you want to compute.

• A harsh take indeed! An economist, sociologist, decision theorist, behavioral ecologist, etc., might tell you that utility functions are designed to solve this problem. Preferences (and how they vary among agents) can even be modeled and measured empirically. Of course, one could argue that that task is beyond the scope of a stack answer. Alternatively, one could argue that taking the array with the largest sum is a reasonable first approximation. "All models are wrong, but some are useful" -- Box (after whom the box plot is not named) May 19, 2021 at 5:43
• @cereal_killer yes, but you'd actually have to elicit those utility functions for the players (which is not trivial) and if they differ then there is no single answer, only answers for each individual player. May 19, 2021 at 5:58
• Populations of agents may exhibit distributions of preferences that can be averaged over. In any case, I’ve already conceded that this approach is beyond the scope of an answer in this venue, but that’s not the same as the question being fundamentally unanswerable. May 19, 2021 at 6:16
• At least for 5e in general you want the highest sum total. So I completely forgot to write that most likely players would pick the array that has the biggest numbers overall. From the two example arrays : Array 1: 18,18,18,10,10,10 - 84 points total. And Array 2: 15,14,14,14,14,14 - 85 points total. It is true that most players would pick array 1 despite it having it's total just slightly lower to Array 2, but still, most likely we can go with just "What would be the highest total sum. " May 19, 2021 at 7:53
• @Fisho An alternative method would be the array with the highest point-buy value. Makes the calculation more difficult but theoretically produces a more consistent "best array". As per your example above, array 1 has a point-buy value of 63, while array 2 is only 44. Therefore we can objectively assess that array 1 is better. May 19, 2021 at 8:20

As I have noted in a comment elsewhere, have each player roll 3d6 7 times, drop the lowest stat, then let all 4 players pick any array they want for their PC, results in a point-buy that is very close to the expected one for 4d6d1.

See https://ideone.com/3KuyuU -- on a 1000 roll simulation, we get:

Average Point buy (4d6d1): 31.36
Average Point buy (3d6): 21.77
Average Point buy (Choose 4d6d1): 43.23
Average Point buy (Choose 3d6): 31.61


But as a frame challenge, there are games that have random stat generation that is more fair in a fundamental way. One in particular I'll mention; the one roll engine.

In it, instead of randomly determining how good you are at each attribute, you instead randomly pick which attribute you are good at.

In 5e terms, instead of rolling some dice for strength, then dexterity, then constitution etc, you instead roll dice for which attribute gets a +1 bonus.

If two players have the same number of dice, then their attribute total comes to the same value. This isn't the same as "the stats are equally good", but it is getting close.

As D&D has 6 stats and a d6 has 6 numbers, the easy solution is to just roll a bucket of dice, and count how many 1s, 2s, 3s etc. You can then bolt on a mechanism to allow customization.

Suppose we start out with a base of 8 in each statistic. 4d6d1 has an average of about 12.25. So, for a first approximation, roll 26d6, and you'll get an average of 12.3 in the result.

Customization can consist of being allowed to swap stats, being allowed to reroll dice, or even being allowed to pick up a die and set it to a specific value.

Unless we get extremely lucky, the standard deviation/variance won't be the same. Let us check!

4d6k3 has a SD of 2.8468.

1d6 has a Variance for a given stat of (5/6)(1/6), times 26 is 3.6. The square root is then 1.90. Also, unlike for 4d6k3, each stat is correlated (negatively) with each other.

But what this tells me is that rolling 26d6 for stat points leads to a problem, in that we get a flatter distribution of stats. That is going to be worse, because all 13s is worse than a mixture of 18s and 8s for most PCs. Especially if you pick your class and race after you roll.

We need a way to increase the standard deviation. An easy method is to halve the number of dice, and make the bonus twice as big.

So roll 13d6, each one giving a +1 to a stat. Then roll 1d6 twice for flavor, adding +1 to the stat you roll and rerolling duplicates.

1d6 has a Variance for a given stat of (5/6)(1/6), times 13 is 1.81. The square root is then 1.34, which we then double for 2.68.

This is much closer to 4d6k3's variance of 2.8468.

So two systems:

1. Roll 3d6 7 times. Drop the lowest stat. Pick any array any of the 4 players rolled.

This results in a similar average to 4d6k3.

1. Each player starts with 8 in each stat, and gives each stat a number from 1 to 6. They rolls 13d6 13 times, adding +2 to the stat assigned to the number rolled. You now get 4 customization dice.

For each customization die, you can either roll it to get +1 to a random stat, or get +1 to a stat of your choice and then roll it to get a -1 to a random stat (reroll if you suffer a -1 to the stat you boosted).

This results in a similar average to 4d6k3 and a similar standard deviation. As stats are rolled "in order" unlike how 4d6k3 is usually done, the customization step is intended to permit you to tweak your stats be less crazy and compensate for that inability to some extent.

Sample rolls using #2

4,5,1,4,1,4,3,6,1,1,3,5,4

Str .... (16)
Dex (8)
Con .. (12)
Int .... (16)
Wis .. (12)
Cha . (10)


We then don't customize. This earns us 4 bonus dice.

4,5,6,4

Str .... (16)
Dex (8)
Con .. (12)
Int .... (16) +2
Wis .. (12) +1
Cha . (10) +1


Resulting stats:

Str 16
Dex 8
Con 12
Int 18
Wis 13
Cha 11


a viable EK.

Now suppose we really want strength. We burn all 4 customization dice on it.

Str 16 +4
Dex 8
Con 12
Int 16 -2
Wis 12 -1
Cha 10 -1


The result:

Str 20
Dex 8
Con 12
Int 14
Wis 11
Cha 9