How does one calculate the distribution of the Matt Colville way of rolling stats?How do I determine the probability of rolling various ranges of numbers on 4d10, 5d10, etc.?How to calculate conditional probabilities in AnyDice?How can I model Burning Wheel probabilities in AnyDice?AnyDice functions and subsequent dice rollsHow can I calculate the distribution of “roll 4d6, keep rerolling 1s and 2s, and drop the lowest die” in AnyDice?How can I model this “Party Draft Pool” ability score generation method in AnyDice?How to calculate conditional probabilities in AnyDice?Would it be fair to use 1d30 (instead of rolling 2d20 and taking the higher die) for advantage rolls?How can I calculate the probability of complete success with this mixed dice pool using AnyDice?How can I calculate the sum of 2 random dice out of a 3d6 pool in AnyDice?What are the odds of rolling specific ability score totals in D&D?
Banking system in C++
Was Locomotive BASIC significantly better than Sinclair BASIC?
Why are branches relative in many 8-bit CPUs?
Best fighting style for a pacifist
Why is the tangent of an angle called that?
How would an Isolationist Country go about opening its borders?
Fixed points of the arithmetic derivative
How to apply ifthenelse check on list member accessed via macro?
What does a little square under the wifi symbol means?
Do one quarter of Swedes named 'Ali' have a criminal record?
CORS error but only from AJAX and not from HTML form
How to get the memory state of SRAM on power up?
If you're loaning yourself a mortgage, why must you pay interest? At the bank's posted rate?
Why did we never simplify key signatures?
Why is the Toffoli gate not sufficient for universal quantum computation?
Probability estimate in classical Deutsch-Josza problem
Did the Apollo missions fly "over the top" of the Van Allen radiation belts?
How can I run a realistic open-world game with vast power differences, without resulting in constant TPKs?
Tiling on Drywall in Shower
Why can't sonic booms be heard at air shows?
I peer reviewed a paper and found it to be sound - technically and language-wise. How should I write the review report?
Variadic templates: unfold arguments in groups
Did Russia's economy boom between 1999 and 2013?
Old short about robots searching for the "Great Enemy" that wiped out mankind
How does one calculate the distribution of the Matt Colville way of rolling stats?
How do I determine the probability of rolling various ranges of numbers on 4d10, 5d10, etc.?How to calculate conditional probabilities in AnyDice?How can I model Burning Wheel probabilities in AnyDice?AnyDice functions and subsequent dice rollsHow can I calculate the distribution of “roll 4d6, keep rerolling 1s and 2s, and drop the lowest die” in AnyDice?How can I model this “Party Draft Pool” ability score generation method in AnyDice?How to calculate conditional probabilities in AnyDice?Would it be fair to use 1d30 (instead of rolling 2d20 and taking the higher die) for advantage rolls?How can I calculate the probability of complete success with this mixed dice pool using AnyDice?How can I calculate the sum of 2 random dice out of a 3d6 pool in AnyDice?What are the odds of rolling specific ability score totals in D&D?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
$begingroup$
Specifically, the Matt Colville way of rolling stats is:
- Roll 4d6, drop the lowest value die for 1 stat;
- If this roll is lower than 8, reroll it;
- Repeat steps 1 and 2 until you have a set of 6 stats greater than 8;
- If there are not at least 2 values of 15 or higher in this set, drop it entirely and start over.
I've written some AnyDice code for calculating this process's distribution but I got stuck at this:
function: ROLL:n reroll BAD:s as REROLL:d
if ROLL = BAD result: REROLL
result: ROLL
function: ROLL:d reroll BAD:s
loop I over 1..20
ROLL: [ROLL reroll BAD as ROLL]
result: ROLL
X: [highest 3 of 4d6]
Y: 6 d[dX reroll 3..7]
loop P over 1..6
output P @ Y named "Ability [P]"
This gives me the probabilities for all my abilities individually, but does not take into account the discarding of the set if there are not at least 2 15s. How should I make it take that into account? (Or how do I calculate this distribution in another way?)
dnd-5e ability-scores statistics anydice
$endgroup$
|
show 4 more comments
$begingroup$
Specifically, the Matt Colville way of rolling stats is:
- Roll 4d6, drop the lowest value die for 1 stat;
- If this roll is lower than 8, reroll it;
- Repeat steps 1 and 2 until you have a set of 6 stats greater than 8;
- If there are not at least 2 values of 15 or higher in this set, drop it entirely and start over.
I've written some AnyDice code for calculating this process's distribution but I got stuck at this:
function: ROLL:n reroll BAD:s as REROLL:d
if ROLL = BAD result: REROLL
result: ROLL
function: ROLL:d reroll BAD:s
loop I over 1..20
ROLL: [ROLL reroll BAD as ROLL]
result: ROLL
X: [highest 3 of 4d6]
Y: 6 d[dX reroll 3..7]
loop P over 1..6
output P @ Y named "Ability [P]"
This gives me the probabilities for all my abilities individually, but does not take into account the discarding of the set if there are not at least 2 15s. How should I make it take that into account? (Or how do I calculate this distribution in another way?)
dnd-5e ability-scores statistics anydice
$endgroup$
1
$begingroup$
Question: If you go into the roller view, you're rolling '4d6 drop lowest' 6 times for each ability score, and then doing this one for each of the 6 ability scores getting you a total of 36 sets of '4d6 drop lowest'. Is this intended?
$endgroup$
– JRodge01
Sep 17 at 12:37
$begingroup$
@JRodge01 That doesn't seem like it would ensure you end up with all scores 8 and above.
$endgroup$
– GcL
Sep 17 at 13:24
$begingroup$
I'm not sure the code is doing what the programmer think it does, even without ensuring 8's and above.
$endgroup$
– JRodge01
Sep 17 at 13:27
1
$begingroup$
Let me clarify my question. You define Y as "six sets of 4d6 drop the lowest, reroll 3's through 7's." This satisfies steps 1, 2, and 3 of the algorithm in the definition of Y alone. What is the purpose of the loop, and why are you running it 6 times?
$endgroup$
– JRodge01
Sep 17 at 13:43
1
$begingroup$
I suspect that this method might be mathematically equivalent to starting over from the beginning whenever you roll a 7 or lower. If true, that would make the statistical analysis much easier, even if you wouldn't do it that way in practice. However, I'm not sure how to prove this (other than trying both methods empirically and seeing if they give similar distributions).
$endgroup$
– Ryan C. Thompson
Sep 17 at 15:43
|
show 4 more comments
$begingroup$
Specifically, the Matt Colville way of rolling stats is:
- Roll 4d6, drop the lowest value die for 1 stat;
- If this roll is lower than 8, reroll it;
- Repeat steps 1 and 2 until you have a set of 6 stats greater than 8;
- If there are not at least 2 values of 15 or higher in this set, drop it entirely and start over.
I've written some AnyDice code for calculating this process's distribution but I got stuck at this:
function: ROLL:n reroll BAD:s as REROLL:d
if ROLL = BAD result: REROLL
result: ROLL
function: ROLL:d reroll BAD:s
loop I over 1..20
ROLL: [ROLL reroll BAD as ROLL]
result: ROLL
X: [highest 3 of 4d6]
Y: 6 d[dX reroll 3..7]
loop P over 1..6
output P @ Y named "Ability [P]"
This gives me the probabilities for all my abilities individually, but does not take into account the discarding of the set if there are not at least 2 15s. How should I make it take that into account? (Or how do I calculate this distribution in another way?)
dnd-5e ability-scores statistics anydice
$endgroup$
Specifically, the Matt Colville way of rolling stats is:
- Roll 4d6, drop the lowest value die for 1 stat;
- If this roll is lower than 8, reroll it;
- Repeat steps 1 and 2 until you have a set of 6 stats greater than 8;
- If there are not at least 2 values of 15 or higher in this set, drop it entirely and start over.
I've written some AnyDice code for calculating this process's distribution but I got stuck at this:
function: ROLL:n reroll BAD:s as REROLL:d
if ROLL = BAD result: REROLL
result: ROLL
function: ROLL:d reroll BAD:s
loop I over 1..20
ROLL: [ROLL reroll BAD as ROLL]
result: ROLL
X: [highest 3 of 4d6]
Y: 6 d[dX reroll 3..7]
loop P over 1..6
output P @ Y named "Ability [P]"
This gives me the probabilities for all my abilities individually, but does not take into account the discarding of the set if there are not at least 2 15s. How should I make it take that into account? (Or how do I calculate this distribution in another way?)
dnd-5e ability-scores statistics anydice
dnd-5e ability-scores statistics anydice
edited Sep 17 at 18:46
Medix2
23.9k2 gold badges89 silver badges196 bronze badges
23.9k2 gold badges89 silver badges196 bronze badges
asked Sep 17 at 12:04
Bogdan IonicăBogdan Ionică
6954 silver badges10 bronze badges
6954 silver badges10 bronze badges
1
$begingroup$
Question: If you go into the roller view, you're rolling '4d6 drop lowest' 6 times for each ability score, and then doing this one for each of the 6 ability scores getting you a total of 36 sets of '4d6 drop lowest'. Is this intended?
$endgroup$
– JRodge01
Sep 17 at 12:37
$begingroup$
@JRodge01 That doesn't seem like it would ensure you end up with all scores 8 and above.
$endgroup$
– GcL
Sep 17 at 13:24
$begingroup$
I'm not sure the code is doing what the programmer think it does, even without ensuring 8's and above.
$endgroup$
– JRodge01
Sep 17 at 13:27
1
$begingroup$
Let me clarify my question. You define Y as "six sets of 4d6 drop the lowest, reroll 3's through 7's." This satisfies steps 1, 2, and 3 of the algorithm in the definition of Y alone. What is the purpose of the loop, and why are you running it 6 times?
$endgroup$
– JRodge01
Sep 17 at 13:43
1
$begingroup$
I suspect that this method might be mathematically equivalent to starting over from the beginning whenever you roll a 7 or lower. If true, that would make the statistical analysis much easier, even if you wouldn't do it that way in practice. However, I'm not sure how to prove this (other than trying both methods empirically and seeing if they give similar distributions).
$endgroup$
– Ryan C. Thompson
Sep 17 at 15:43
|
show 4 more comments
1
$begingroup$
Question: If you go into the roller view, you're rolling '4d6 drop lowest' 6 times for each ability score, and then doing this one for each of the 6 ability scores getting you a total of 36 sets of '4d6 drop lowest'. Is this intended?
$endgroup$
– JRodge01
Sep 17 at 12:37
$begingroup$
@JRodge01 That doesn't seem like it would ensure you end up with all scores 8 and above.
$endgroup$
– GcL
Sep 17 at 13:24
$begingroup$
I'm not sure the code is doing what the programmer think it does, even without ensuring 8's and above.
$endgroup$
– JRodge01
Sep 17 at 13:27
1
$begingroup$
Let me clarify my question. You define Y as "six sets of 4d6 drop the lowest, reroll 3's through 7's." This satisfies steps 1, 2, and 3 of the algorithm in the definition of Y alone. What is the purpose of the loop, and why are you running it 6 times?
$endgroup$
– JRodge01
Sep 17 at 13:43
1
$begingroup$
I suspect that this method might be mathematically equivalent to starting over from the beginning whenever you roll a 7 or lower. If true, that would make the statistical analysis much easier, even if you wouldn't do it that way in practice. However, I'm not sure how to prove this (other than trying both methods empirically and seeing if they give similar distributions).
$endgroup$
– Ryan C. Thompson
Sep 17 at 15:43
1
1
$begingroup$
Question: If you go into the roller view, you're rolling '4d6 drop lowest' 6 times for each ability score, and then doing this one for each of the 6 ability scores getting you a total of 36 sets of '4d6 drop lowest'. Is this intended?
$endgroup$
– JRodge01
Sep 17 at 12:37
$begingroup$
Question: If you go into the roller view, you're rolling '4d6 drop lowest' 6 times for each ability score, and then doing this one for each of the 6 ability scores getting you a total of 36 sets of '4d6 drop lowest'. Is this intended?
$endgroup$
– JRodge01
Sep 17 at 12:37
$begingroup$
@JRodge01 That doesn't seem like it would ensure you end up with all scores 8 and above.
$endgroup$
– GcL
Sep 17 at 13:24
$begingroup$
@JRodge01 That doesn't seem like it would ensure you end up with all scores 8 and above.
$endgroup$
– GcL
Sep 17 at 13:24
$begingroup$
I'm not sure the code is doing what the programmer think it does, even without ensuring 8's and above.
$endgroup$
– JRodge01
Sep 17 at 13:27
$begingroup$
I'm not sure the code is doing what the programmer think it does, even without ensuring 8's and above.
$endgroup$
– JRodge01
Sep 17 at 13:27
1
1
$begingroup$
Let me clarify my question. You define Y as "six sets of 4d6 drop the lowest, reroll 3's through 7's." This satisfies steps 1, 2, and 3 of the algorithm in the definition of Y alone. What is the purpose of the loop, and why are you running it 6 times?
$endgroup$
– JRodge01
Sep 17 at 13:43
$begingroup$
Let me clarify my question. You define Y as "six sets of 4d6 drop the lowest, reroll 3's through 7's." This satisfies steps 1, 2, and 3 of the algorithm in the definition of Y alone. What is the purpose of the loop, and why are you running it 6 times?
$endgroup$
– JRodge01
Sep 17 at 13:43
1
1
$begingroup$
I suspect that this method might be mathematically equivalent to starting over from the beginning whenever you roll a 7 or lower. If true, that would make the statistical analysis much easier, even if you wouldn't do it that way in practice. However, I'm not sure how to prove this (other than trying both methods empirically and seeing if they give similar distributions).
$endgroup$
– Ryan C. Thompson
Sep 17 at 15:43
$begingroup$
I suspect that this method might be mathematically equivalent to starting over from the beginning whenever you roll a 7 or lower. If true, that would make the statistical analysis much easier, even if you wouldn't do it that way in practice. However, I'm not sure how to prove this (other than trying both methods empirically and seeing if they give similar distributions).
$endgroup$
– Ryan C. Thompson
Sep 17 at 15:43
|
show 4 more comments
4 Answers
4
active
oldest
votes
$begingroup$
The following anydice program will show you what the statistical distribution of ability score results for the Colville method looks like.
function: roll ROLL:n min MIN:n
if ROLL < MIN result: d
result: ROLL
function: colville ARRAY:s INDEX:n
if (ARRAY >= 15) < 2 result: d
result: INDEX@ARRAY
ROLL: [highest 3 of 4d6]
SCORE: [roll ROLL min 8]
ARRAY: 6dSCORE
output [colville ARRAY 1] named "Score 1"
output [colville ARRAY 2] named "Score 2"
output [colville ARRAY 3] named "Score 3"
output [colville ARRAY 4] named "Score 4"
output [colville ARRAY 5] named "Score 5"
output [colville ARRAY 6] named "Score 6"
The trick here is that we don't actually want to have to reroll anything, because recursive functions are expensive and take forever (plus there's a limit to how far Anydice will recurse). Fortunately we actually have a really neat shortcut we can use in the specific case of rerolling until we get a result that's in the range we actually want; we can use a function as a filter to check the value is in the desired range, which returns the input value if it is, or the so-called empty die, d, if it is not.
The result of the empty die is basically discarded when anydice calculates probabilities, so we are shown results based only on rolls which met our parameters; since we were just going to reroll anyway until we got a result that was in our range, this is statistically identical to actually rerolling (potentially forever).
So we have two functions, one of which discards results for individual ability scores unless they are 8 or higher, one of which discards arrays of ability scores if there aren't two scores of 15 or more.
The other trick is that the latter function also takes an index to return one of those ability scores since unfortunately we can't get anydice to return a sequence from a function, only a flat number, and we so have to use the index to inspect the individual rolls; fortunately the generated sequence is automatically sorted in descending order by default, so we can just iterate through each position to build a complete distribution.
That gives us a result that looks like this when graphed:

This seems to agree perfectly with Ryan Thompson's R-based answer so I feel pretty confident I haven't messed up how this works anywhere.
$endgroup$
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
3
$begingroup$
@RyanThompson the best way to think of it is that what the variableSCORErepresents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.
$endgroup$
– Carcer
Sep 17 at 19:59
1
$begingroup$
Thatdtrick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)
$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on thedthing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.
$endgroup$
– Carcer
Sep 18 at 8:26
add a comment
|
$begingroup$
I went ahead and implemented this in R. You can see the code here: https://gist.github.com/DarwinAwardWinner/34dd19f302bd1ef24310f6098dc3218d
This code enumerates every possible roll of "4d6 drop lowest, reroll 7 or lower" in order to determine the exact probabilities of rolling each stat from 8 to 18. Then it uses these to compute the exact probability of rolling each possible set of 6 stats, rejecting stat sets without at least 2 stats 15 or higher. Interestingly, about 54% of stat rolls with all 8 or higher will not have 2 stats of 15 or higher, which means that for each stat roll, you have better than even odds of needing to reroll from scratch. Depending on how much your players enjoy rolling stats, this may be an advantage or a disadvantage.
Here's a plot of the distributions of each stat. A is whichever stat rolled highest, B is the 2nd highest, and so on, with F being the lowest stat. The Y axis the the probability of rolling a certain number. For example, your 2nd highest stat has about a 57% chance of being a 15, and a 0% chance of being anything lower than that (by definition).

We can also get some statistics on the distributions. $Q_25$ and $Q_75$ are the 25th and 75th percentiles.
beginarrayl
textbfAbility & textbfMin & boldsymbol Q_25 & textbfMedian & textbfMean & boldsymbol Q_75 & textbfMax \ hline
textA & 15 & 16 & 16 & 16.5 & 17 & 18 \
textB & 15 & 15 & 15 & 15.5 & 16 & 18 \
textC & 8 & 13 & 14 & 14.0 & 15 & 18 \
textD & 8 & 12 & 13 & 12.7 & 14 & 18 \
textE & 8 & 10 & 11 & 11.3 & 12 & 18 \
textF & 8 & 9 & 10 & 9.8 & 11 & 18 \
endarray
Of course, my code computes the full distribution for all possible stat rolls, so if you're curious about other facets of the data, such as point buy value, feel free to run the code and experiment.
$endgroup$
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
4
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
1
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
|
show 5 more comments
$begingroup$
Through my methods, I found 5,236 unique different dice pools that result from the Colville Stat Distribution. I've posted it here, as the length of the table violate's Stack Exchange's hard limit on post length. You can review it yourself and run data processing on it if you want to examine some stats on it that haven't been provided here or in other answers.
How was this Generated?
We need to first generate an array for the 4d6 drop 1 roll. I detailed a general purpose method for generating these kinds of arrays here, and I'm going to use the same process here, although I'm shortcutting past the details because I don't want to manually step through the whole process. Look at that post to see how this starts.
In short, we need to generate a 4d6 array that also preserves the die that was lowest for each sum. It'll look something like this:
beginarrayr
textbf4d6 Drop 1 (pre drop) & textbfOdds \ hline
text[4,1] & 1 \
text[5,1] & 4 \
text[6,1] & 10 \
text[7,1] & 20 \
text[8,1] & 34 \
text[9,1] & 52 \
text[10,1] & 70 \
text[11,1] & 84 \
text[12,1] & 90 \
text[13,1] & 88 \
text[14,1] & 78 \
text[15,1] & 60 \
text[16,1] & 40 \
text[17,1] & 24 \
text[18,1] & 12 \
text[19,1] & 4 \
text[8,2] & 1 \
text[9,2] & 4 \
text[10,2] & 10 \
text--Snip-- & text--Snip-- & textit... We need to conserve space... \
text[23,5] & 4 \
text[24,6] & 1 \
endarray
And then for each one we just subtract out that lowest roll, giving us the final roll.
beginarrayrr
text4d6 Drop 1 & textOdds
\ hline
text[3] & 1\
text[4] & 4\
text[5] & 10\
text[6] & 21\
text[7] & 38\
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
We simply chop off the results that are lower than 8. We always reroll when we encounter them, so the odds of the other results are unaffected.
beginarrayrr
text4d6 Drop 1 (≥8 only) & textOdds
\ hline
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
Then we start multiplying this array against itself. My method involved multiplexing these numbers, but regardless of how you do it, you'll end up with something like this (after removing sets that do not contain at least two ≥15 rolls):
beginarrayl
textbf6x(4d6D1≥8) & textbfOdds
\ hline
text[15, 15, 8, 8, 8, 8] & 3803650531440\
text[16, 15, 8, 8, 8, 8] & 5458674045120\
text[17, 15, 8, 8, 8, 8] & 3135834025920\
text[18, 15, 8, 8, 8, 8] & 1219491010080\
text[16, 16, 8, 8, 8, 8] & 1958455573440\
text[17, 16, 8, 8, 8, 8] & 2250140446080\
text[18, 16, 8, 8, 8, 8] & 875054617920\
textit... You get the Idea & textitLook at the link I posted \
textitThere's 5236 rows of this & textitabove for the full set \
endarray
That, finally, is the entire distribution of rolls that can be gained from this method of rolling stats.
What can we learn from it?
Well, we could compare the total statpoint distribution, against a normal 6x(4d6D1) rolled stats:

So it turns out the Colville Method has a pretty consderable boost to the overall sum, raising the average from 73.468 to 79.867. This isn't surprising though: all the data it acts on (individual rolls below 8, any set that is does not have at least two ≥15 rolls) are specifically bad rolls, so it naturally tends towards higher results.
If you use the dataset I posted above, you're welcome to do your own analysis on it. I recommend heavy use of Microsoft Excel or some other Spreadsheet software.
$endgroup$
add a comment
|
$begingroup$
Ignore the actual order things are done, use an order that's easier to calculate, and don't be scared to approximate
Instead of first rolling stats and then rerolling if there aren't two 15+s, we can achieve exactly the same result by first rolling two stats that must be 15+ and then rolling the rest 'normally'.
To do this in anydice, what we want to do is take the collection of possible outcomes that is what 'highest 3 of 4d6' means and just remove all the parts that are under 15.
The easiest way to do this is manually. Looking at the results of the aforementioned distribution, we can see that '15' has a 10.11% chance of occurring, '16' a 7.25% chance, '17' a 4.17% chance, and '18' a 1.62% chance. These odds are truncated to the hundredths place, but we are going to consider that level of error acceptable. A sequence with 1011 '15's, 725 '16's, 417 '17's, and 162 '18's, then, can function as a die that gives us our two best values.
Using repetition, we can populate a sequence by using the following code:
output 15:1011,16:725,17:417,18:162
Next, we need to fix your code. It doesn't actually get you what you are looking for, I think, since it has an approximately infinitessimal chance of outputting numbers lower than 8. That may be fine with you, but we can also use truncation to get a (in my opinion) much cleaner and about equally accurate system for the remaining 4 ability scores:
output 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162
You can do something like output [highest 1 of 6d 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162] to confirm that it gives the same results.
To look at each ability score, we can just pull the appropriate number from a set of rolls, remembering that the rolls higher than 8 instead of 15 are also no better than the 3rd highest roll of such a sequence. So we end up with:
output [highest 1 of 2d15:1011,16:725,17:417,18:162] named "highest stat"
output 2 @ 2d15:1011,16:725,17:417,18:162 named "2nd highest stat"
output 3@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "highest non-forced stat"
output 4@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd highest non-forced stat"
output 5@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd lowest stat"
output 6@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "lowest stat"
Which gives results within 1 percentage point of the analytic value 1(approximately 10% error).
- thanks to @Carcer for the analytic value program.
$endgroup$
6
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Considerflip two coins, redo unless there is at least 1 headvsforce the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, dropTT), the second has 1/2 chance of 1 head (HH|HT).
$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
add a comment
|
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "122"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2frpg.stackexchange.com%2fquestions%2f156379%2fhow-does-one-calculate-the-distribution-of-the-matt-colville-way-of-rolling-stat%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
The following anydice program will show you what the statistical distribution of ability score results for the Colville method looks like.
function: roll ROLL:n min MIN:n
if ROLL < MIN result: d
result: ROLL
function: colville ARRAY:s INDEX:n
if (ARRAY >= 15) < 2 result: d
result: INDEX@ARRAY
ROLL: [highest 3 of 4d6]
SCORE: [roll ROLL min 8]
ARRAY: 6dSCORE
output [colville ARRAY 1] named "Score 1"
output [colville ARRAY 2] named "Score 2"
output [colville ARRAY 3] named "Score 3"
output [colville ARRAY 4] named "Score 4"
output [colville ARRAY 5] named "Score 5"
output [colville ARRAY 6] named "Score 6"
The trick here is that we don't actually want to have to reroll anything, because recursive functions are expensive and take forever (plus there's a limit to how far Anydice will recurse). Fortunately we actually have a really neat shortcut we can use in the specific case of rerolling until we get a result that's in the range we actually want; we can use a function as a filter to check the value is in the desired range, which returns the input value if it is, or the so-called empty die, d, if it is not.
The result of the empty die is basically discarded when anydice calculates probabilities, so we are shown results based only on rolls which met our parameters; since we were just going to reroll anyway until we got a result that was in our range, this is statistically identical to actually rerolling (potentially forever).
So we have two functions, one of which discards results for individual ability scores unless they are 8 or higher, one of which discards arrays of ability scores if there aren't two scores of 15 or more.
The other trick is that the latter function also takes an index to return one of those ability scores since unfortunately we can't get anydice to return a sequence from a function, only a flat number, and we so have to use the index to inspect the individual rolls; fortunately the generated sequence is automatically sorted in descending order by default, so we can just iterate through each position to build a complete distribution.
That gives us a result that looks like this when graphed:

This seems to agree perfectly with Ryan Thompson's R-based answer so I feel pretty confident I haven't messed up how this works anywhere.
$endgroup$
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
3
$begingroup$
@RyanThompson the best way to think of it is that what the variableSCORErepresents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.
$endgroup$
– Carcer
Sep 17 at 19:59
1
$begingroup$
Thatdtrick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)
$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on thedthing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.
$endgroup$
– Carcer
Sep 18 at 8:26
add a comment
|
$begingroup$
The following anydice program will show you what the statistical distribution of ability score results for the Colville method looks like.
function: roll ROLL:n min MIN:n
if ROLL < MIN result: d
result: ROLL
function: colville ARRAY:s INDEX:n
if (ARRAY >= 15) < 2 result: d
result: INDEX@ARRAY
ROLL: [highest 3 of 4d6]
SCORE: [roll ROLL min 8]
ARRAY: 6dSCORE
output [colville ARRAY 1] named "Score 1"
output [colville ARRAY 2] named "Score 2"
output [colville ARRAY 3] named "Score 3"
output [colville ARRAY 4] named "Score 4"
output [colville ARRAY 5] named "Score 5"
output [colville ARRAY 6] named "Score 6"
The trick here is that we don't actually want to have to reroll anything, because recursive functions are expensive and take forever (plus there's a limit to how far Anydice will recurse). Fortunately we actually have a really neat shortcut we can use in the specific case of rerolling until we get a result that's in the range we actually want; we can use a function as a filter to check the value is in the desired range, which returns the input value if it is, or the so-called empty die, d, if it is not.
The result of the empty die is basically discarded when anydice calculates probabilities, so we are shown results based only on rolls which met our parameters; since we were just going to reroll anyway until we got a result that was in our range, this is statistically identical to actually rerolling (potentially forever).
So we have two functions, one of which discards results for individual ability scores unless they are 8 or higher, one of which discards arrays of ability scores if there aren't two scores of 15 or more.
The other trick is that the latter function also takes an index to return one of those ability scores since unfortunately we can't get anydice to return a sequence from a function, only a flat number, and we so have to use the index to inspect the individual rolls; fortunately the generated sequence is automatically sorted in descending order by default, so we can just iterate through each position to build a complete distribution.
That gives us a result that looks like this when graphed:

This seems to agree perfectly with Ryan Thompson's R-based answer so I feel pretty confident I haven't messed up how this works anywhere.
$endgroup$
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
3
$begingroup$
@RyanThompson the best way to think of it is that what the variableSCORErepresents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.
$endgroup$
– Carcer
Sep 17 at 19:59
1
$begingroup$
Thatdtrick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)
$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on thedthing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.
$endgroup$
– Carcer
Sep 18 at 8:26
add a comment
|
$begingroup$
The following anydice program will show you what the statistical distribution of ability score results for the Colville method looks like.
function: roll ROLL:n min MIN:n
if ROLL < MIN result: d
result: ROLL
function: colville ARRAY:s INDEX:n
if (ARRAY >= 15) < 2 result: d
result: INDEX@ARRAY
ROLL: [highest 3 of 4d6]
SCORE: [roll ROLL min 8]
ARRAY: 6dSCORE
output [colville ARRAY 1] named "Score 1"
output [colville ARRAY 2] named "Score 2"
output [colville ARRAY 3] named "Score 3"
output [colville ARRAY 4] named "Score 4"
output [colville ARRAY 5] named "Score 5"
output [colville ARRAY 6] named "Score 6"
The trick here is that we don't actually want to have to reroll anything, because recursive functions are expensive and take forever (plus there's a limit to how far Anydice will recurse). Fortunately we actually have a really neat shortcut we can use in the specific case of rerolling until we get a result that's in the range we actually want; we can use a function as a filter to check the value is in the desired range, which returns the input value if it is, or the so-called empty die, d, if it is not.
The result of the empty die is basically discarded when anydice calculates probabilities, so we are shown results based only on rolls which met our parameters; since we were just going to reroll anyway until we got a result that was in our range, this is statistically identical to actually rerolling (potentially forever).
So we have two functions, one of which discards results for individual ability scores unless they are 8 or higher, one of which discards arrays of ability scores if there aren't two scores of 15 or more.
The other trick is that the latter function also takes an index to return one of those ability scores since unfortunately we can't get anydice to return a sequence from a function, only a flat number, and we so have to use the index to inspect the individual rolls; fortunately the generated sequence is automatically sorted in descending order by default, so we can just iterate through each position to build a complete distribution.
That gives us a result that looks like this when graphed:

This seems to agree perfectly with Ryan Thompson's R-based answer so I feel pretty confident I haven't messed up how this works anywhere.
$endgroup$
The following anydice program will show you what the statistical distribution of ability score results for the Colville method looks like.
function: roll ROLL:n min MIN:n
if ROLL < MIN result: d
result: ROLL
function: colville ARRAY:s INDEX:n
if (ARRAY >= 15) < 2 result: d
result: INDEX@ARRAY
ROLL: [highest 3 of 4d6]
SCORE: [roll ROLL min 8]
ARRAY: 6dSCORE
output [colville ARRAY 1] named "Score 1"
output [colville ARRAY 2] named "Score 2"
output [colville ARRAY 3] named "Score 3"
output [colville ARRAY 4] named "Score 4"
output [colville ARRAY 5] named "Score 5"
output [colville ARRAY 6] named "Score 6"
The trick here is that we don't actually want to have to reroll anything, because recursive functions are expensive and take forever (plus there's a limit to how far Anydice will recurse). Fortunately we actually have a really neat shortcut we can use in the specific case of rerolling until we get a result that's in the range we actually want; we can use a function as a filter to check the value is in the desired range, which returns the input value if it is, or the so-called empty die, d, if it is not.
The result of the empty die is basically discarded when anydice calculates probabilities, so we are shown results based only on rolls which met our parameters; since we were just going to reroll anyway until we got a result that was in our range, this is statistically identical to actually rerolling (potentially forever).
So we have two functions, one of which discards results for individual ability scores unless they are 8 or higher, one of which discards arrays of ability scores if there aren't two scores of 15 or more.
The other trick is that the latter function also takes an index to return one of those ability scores since unfortunately we can't get anydice to return a sequence from a function, only a flat number, and we so have to use the index to inspect the individual rolls; fortunately the generated sequence is automatically sorted in descending order by default, so we can just iterate through each position to build a complete distribution.
That gives us a result that looks like this when graphed:

This seems to agree perfectly with Ryan Thompson's R-based answer so I feel pretty confident I haven't messed up how this works anywhere.
edited Sep 17 at 20:25
answered Sep 17 at 19:40
CarcerCarcer
38.1k6 gold badges124 silver badges190 bronze badges
38.1k6 gold badges124 silver badges190 bronze badges
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
3
$begingroup$
@RyanThompson the best way to think of it is that what the variableSCORErepresents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.
$endgroup$
– Carcer
Sep 17 at 19:59
1
$begingroup$
Thatdtrick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)
$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on thedthing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.
$endgroup$
– Carcer
Sep 18 at 8:26
add a comment
|
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
3
$begingroup$
@RyanThompson the best way to think of it is that what the variableSCORErepresents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.
$endgroup$
– Carcer
Sep 17 at 19:59
1
$begingroup$
Thatdtrick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)
$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on thedthing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.
$endgroup$
– Carcer
Sep 18 at 8:26
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
$begingroup$
One possible problem is that, if I understand correctly, a single stat roll of 8 or lower will discard the entire stat array and start over instead of just re-rolling a single stat. However, based on the similarity of the graph to mine, it seems that the two procedures are probably mathematically equivalent. I'm still not 100% sure, though.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:44
3
3
$begingroup$
@RyanThompson the best way to think of it is that what the variable
SCORE represents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.$endgroup$
– Carcer
Sep 17 at 19:59
$begingroup$
@RyanThompson the best way to think of it is that what the variable
SCORE represents is actually a single die which has the possible results (and probabilities thereof) of rerolling 4d6-droplow until you get an eight or better. There is no throwing away of entire arrays; we're generating the arrays in the first place using a special die that can only possibly generate satisfactory values for individual scores.$endgroup$
– Carcer
Sep 17 at 19:59
1
1
$begingroup$
That
d trick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
That
d trick is really nice. In fact, it seems to be a better solution to this question I asked earlier than the reroll-in-a-loop hack I came up with myself. Would you like to post an answer about it there? I'd accept it if you did. (If not, I can just edit it into my own answer.)$endgroup$
– Ilmari Karonen
Sep 18 at 8:14
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on the
d thing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.$endgroup$
– Carcer
Sep 18 at 8:26
$begingroup$
@IlmariKaronen that question was actually in the back of my mind when I was writing this, I think! I twigged on the
d thing while writing this answer because I originally made a version which did recurse and realised that the results didn't actually change no matter what I set the maximum function depth to (as exceeding max depth returns the empty die, anydice must have been ignoring the empty die results). I'd like to add an answer to your question but it may have to wait until this evening depending on business.$endgroup$
– Carcer
Sep 18 at 8:26
add a comment
|
$begingroup$
I went ahead and implemented this in R. You can see the code here: https://gist.github.com/DarwinAwardWinner/34dd19f302bd1ef24310f6098dc3218d
This code enumerates every possible roll of "4d6 drop lowest, reroll 7 or lower" in order to determine the exact probabilities of rolling each stat from 8 to 18. Then it uses these to compute the exact probability of rolling each possible set of 6 stats, rejecting stat sets without at least 2 stats 15 or higher. Interestingly, about 54% of stat rolls with all 8 or higher will not have 2 stats of 15 or higher, which means that for each stat roll, you have better than even odds of needing to reroll from scratch. Depending on how much your players enjoy rolling stats, this may be an advantage or a disadvantage.
Here's a plot of the distributions of each stat. A is whichever stat rolled highest, B is the 2nd highest, and so on, with F being the lowest stat. The Y axis the the probability of rolling a certain number. For example, your 2nd highest stat has about a 57% chance of being a 15, and a 0% chance of being anything lower than that (by definition).

We can also get some statistics on the distributions. $Q_25$ and $Q_75$ are the 25th and 75th percentiles.
beginarrayl
textbfAbility & textbfMin & boldsymbol Q_25 & textbfMedian & textbfMean & boldsymbol Q_75 & textbfMax \ hline
textA & 15 & 16 & 16 & 16.5 & 17 & 18 \
textB & 15 & 15 & 15 & 15.5 & 16 & 18 \
textC & 8 & 13 & 14 & 14.0 & 15 & 18 \
textD & 8 & 12 & 13 & 12.7 & 14 & 18 \
textE & 8 & 10 & 11 & 11.3 & 12 & 18 \
textF & 8 & 9 & 10 & 9.8 & 11 & 18 \
endarray
Of course, my code computes the full distribution for all possible stat rolls, so if you're curious about other facets of the data, such as point buy value, feel free to run the code and experiment.
$endgroup$
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
4
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
1
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
|
show 5 more comments
$begingroup$
I went ahead and implemented this in R. You can see the code here: https://gist.github.com/DarwinAwardWinner/34dd19f302bd1ef24310f6098dc3218d
This code enumerates every possible roll of "4d6 drop lowest, reroll 7 or lower" in order to determine the exact probabilities of rolling each stat from 8 to 18. Then it uses these to compute the exact probability of rolling each possible set of 6 stats, rejecting stat sets without at least 2 stats 15 or higher. Interestingly, about 54% of stat rolls with all 8 or higher will not have 2 stats of 15 or higher, which means that for each stat roll, you have better than even odds of needing to reroll from scratch. Depending on how much your players enjoy rolling stats, this may be an advantage or a disadvantage.
Here's a plot of the distributions of each stat. A is whichever stat rolled highest, B is the 2nd highest, and so on, with F being the lowest stat. The Y axis the the probability of rolling a certain number. For example, your 2nd highest stat has about a 57% chance of being a 15, and a 0% chance of being anything lower than that (by definition).

We can also get some statistics on the distributions. $Q_25$ and $Q_75$ are the 25th and 75th percentiles.
beginarrayl
textbfAbility & textbfMin & boldsymbol Q_25 & textbfMedian & textbfMean & boldsymbol Q_75 & textbfMax \ hline
textA & 15 & 16 & 16 & 16.5 & 17 & 18 \
textB & 15 & 15 & 15 & 15.5 & 16 & 18 \
textC & 8 & 13 & 14 & 14.0 & 15 & 18 \
textD & 8 & 12 & 13 & 12.7 & 14 & 18 \
textE & 8 & 10 & 11 & 11.3 & 12 & 18 \
textF & 8 & 9 & 10 & 9.8 & 11 & 18 \
endarray
Of course, my code computes the full distribution for all possible stat rolls, so if you're curious about other facets of the data, such as point buy value, feel free to run the code and experiment.
$endgroup$
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
4
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
1
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
|
show 5 more comments
$begingroup$
I went ahead and implemented this in R. You can see the code here: https://gist.github.com/DarwinAwardWinner/34dd19f302bd1ef24310f6098dc3218d
This code enumerates every possible roll of "4d6 drop lowest, reroll 7 or lower" in order to determine the exact probabilities of rolling each stat from 8 to 18. Then it uses these to compute the exact probability of rolling each possible set of 6 stats, rejecting stat sets without at least 2 stats 15 or higher. Interestingly, about 54% of stat rolls with all 8 or higher will not have 2 stats of 15 or higher, which means that for each stat roll, you have better than even odds of needing to reroll from scratch. Depending on how much your players enjoy rolling stats, this may be an advantage or a disadvantage.
Here's a plot of the distributions of each stat. A is whichever stat rolled highest, B is the 2nd highest, and so on, with F being the lowest stat. The Y axis the the probability of rolling a certain number. For example, your 2nd highest stat has about a 57% chance of being a 15, and a 0% chance of being anything lower than that (by definition).

We can also get some statistics on the distributions. $Q_25$ and $Q_75$ are the 25th and 75th percentiles.
beginarrayl
textbfAbility & textbfMin & boldsymbol Q_25 & textbfMedian & textbfMean & boldsymbol Q_75 & textbfMax \ hline
textA & 15 & 16 & 16 & 16.5 & 17 & 18 \
textB & 15 & 15 & 15 & 15.5 & 16 & 18 \
textC & 8 & 13 & 14 & 14.0 & 15 & 18 \
textD & 8 & 12 & 13 & 12.7 & 14 & 18 \
textE & 8 & 10 & 11 & 11.3 & 12 & 18 \
textF & 8 & 9 & 10 & 9.8 & 11 & 18 \
endarray
Of course, my code computes the full distribution for all possible stat rolls, so if you're curious about other facets of the data, such as point buy value, feel free to run the code and experiment.
$endgroup$
I went ahead and implemented this in R. You can see the code here: https://gist.github.com/DarwinAwardWinner/34dd19f302bd1ef24310f6098dc3218d
This code enumerates every possible roll of "4d6 drop lowest, reroll 7 or lower" in order to determine the exact probabilities of rolling each stat from 8 to 18. Then it uses these to compute the exact probability of rolling each possible set of 6 stats, rejecting stat sets without at least 2 stats 15 or higher. Interestingly, about 54% of stat rolls with all 8 or higher will not have 2 stats of 15 or higher, which means that for each stat roll, you have better than even odds of needing to reroll from scratch. Depending on how much your players enjoy rolling stats, this may be an advantage or a disadvantage.
Here's a plot of the distributions of each stat. A is whichever stat rolled highest, B is the 2nd highest, and so on, with F being the lowest stat. The Y axis the the probability of rolling a certain number. For example, your 2nd highest stat has about a 57% chance of being a 15, and a 0% chance of being anything lower than that (by definition).

We can also get some statistics on the distributions. $Q_25$ and $Q_75$ are the 25th and 75th percentiles.
beginarrayl
textbfAbility & textbfMin & boldsymbol Q_25 & textbfMedian & textbfMean & boldsymbol Q_75 & textbfMax \ hline
textA & 15 & 16 & 16 & 16.5 & 17 & 18 \
textB & 15 & 15 & 15 & 15.5 & 16 & 18 \
textC & 8 & 13 & 14 & 14.0 & 15 & 18 \
textD & 8 & 12 & 13 & 12.7 & 14 & 18 \
textE & 8 & 10 & 11 & 11.3 & 12 & 18 \
textF & 8 & 9 & 10 & 9.8 & 11 & 18 \
endarray
Of course, my code computes the full distribution for all possible stat rolls, so if you're curious about other facets of the data, such as point buy value, feel free to run the code and experiment.
edited Sep 17 at 19:58
answered Sep 17 at 17:02
Ryan C. ThompsonRyan C. Thompson
26.2k2 gold badges78 silver badges151 bronze badges
26.2k2 gold badges78 silver badges151 bronze badges
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
4
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
1
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
|
show 5 more comments
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
4
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
1
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
$begingroup$
This is great! Do you have any idea how to do the same in AnyDice?
$endgroup$
– Bogdan Ionică
Sep 17 at 17:18
4
4
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
@BogdanIonică Nope, that's why I wrote in in R. I'm not an expert on the advanced functionalities of AnyDice, but I've got lots of experience doing statistics in R.
$endgroup$
– Ryan C. Thompson
Sep 17 at 17:19
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
I found through an independent method each individual set of rolls that can be rolled, satisfying the constraints of the Colville Stat Distribution, along with the odds that each will be rolled, which I posted here. If you feed those stats into your program, you could get exact odds instead of Monte-Carlo'ing the whole thing, and update the graph + table with those exact results. I'm gonna post my own answer explaining how I did that.
$endgroup$
– Xirema
Sep 17 at 17:30
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
$begingroup$
Also, if the results from running my dataset in your program gives nearly-identical results (which they shouldn't be that different) then it'll validate that we both did this correctly.
$endgroup$
– Xirema
Sep 17 at 17:33
1
1
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
$begingroup$
@Xirema I realized that if I just enumerated every possible roll of 4d6 drop lowest, I could get the exact probabilities for everything easily, so I went ahead and did it.
$endgroup$
– Ryan C. Thompson
Sep 17 at 19:21
|
show 5 more comments
$begingroup$
Through my methods, I found 5,236 unique different dice pools that result from the Colville Stat Distribution. I've posted it here, as the length of the table violate's Stack Exchange's hard limit on post length. You can review it yourself and run data processing on it if you want to examine some stats on it that haven't been provided here or in other answers.
How was this Generated?
We need to first generate an array for the 4d6 drop 1 roll. I detailed a general purpose method for generating these kinds of arrays here, and I'm going to use the same process here, although I'm shortcutting past the details because I don't want to manually step through the whole process. Look at that post to see how this starts.
In short, we need to generate a 4d6 array that also preserves the die that was lowest for each sum. It'll look something like this:
beginarrayr
textbf4d6 Drop 1 (pre drop) & textbfOdds \ hline
text[4,1] & 1 \
text[5,1] & 4 \
text[6,1] & 10 \
text[7,1] & 20 \
text[8,1] & 34 \
text[9,1] & 52 \
text[10,1] & 70 \
text[11,1] & 84 \
text[12,1] & 90 \
text[13,1] & 88 \
text[14,1] & 78 \
text[15,1] & 60 \
text[16,1] & 40 \
text[17,1] & 24 \
text[18,1] & 12 \
text[19,1] & 4 \
text[8,2] & 1 \
text[9,2] & 4 \
text[10,2] & 10 \
text--Snip-- & text--Snip-- & textit... We need to conserve space... \
text[23,5] & 4 \
text[24,6] & 1 \
endarray
And then for each one we just subtract out that lowest roll, giving us the final roll.
beginarrayrr
text4d6 Drop 1 & textOdds
\ hline
text[3] & 1\
text[4] & 4\
text[5] & 10\
text[6] & 21\
text[7] & 38\
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
We simply chop off the results that are lower than 8. We always reroll when we encounter them, so the odds of the other results are unaffected.
beginarrayrr
text4d6 Drop 1 (≥8 only) & textOdds
\ hline
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
Then we start multiplying this array against itself. My method involved multiplexing these numbers, but regardless of how you do it, you'll end up with something like this (after removing sets that do not contain at least two ≥15 rolls):
beginarrayl
textbf6x(4d6D1≥8) & textbfOdds
\ hline
text[15, 15, 8, 8, 8, 8] & 3803650531440\
text[16, 15, 8, 8, 8, 8] & 5458674045120\
text[17, 15, 8, 8, 8, 8] & 3135834025920\
text[18, 15, 8, 8, 8, 8] & 1219491010080\
text[16, 16, 8, 8, 8, 8] & 1958455573440\
text[17, 16, 8, 8, 8, 8] & 2250140446080\
text[18, 16, 8, 8, 8, 8] & 875054617920\
textit... You get the Idea & textitLook at the link I posted \
textitThere's 5236 rows of this & textitabove for the full set \
endarray
That, finally, is the entire distribution of rolls that can be gained from this method of rolling stats.
What can we learn from it?
Well, we could compare the total statpoint distribution, against a normal 6x(4d6D1) rolled stats:

So it turns out the Colville Method has a pretty consderable boost to the overall sum, raising the average from 73.468 to 79.867. This isn't surprising though: all the data it acts on (individual rolls below 8, any set that is does not have at least two ≥15 rolls) are specifically bad rolls, so it naturally tends towards higher results.
If you use the dataset I posted above, you're welcome to do your own analysis on it. I recommend heavy use of Microsoft Excel or some other Spreadsheet software.
$endgroup$
add a comment
|
$begingroup$
Through my methods, I found 5,236 unique different dice pools that result from the Colville Stat Distribution. I've posted it here, as the length of the table violate's Stack Exchange's hard limit on post length. You can review it yourself and run data processing on it if you want to examine some stats on it that haven't been provided here or in other answers.
How was this Generated?
We need to first generate an array for the 4d6 drop 1 roll. I detailed a general purpose method for generating these kinds of arrays here, and I'm going to use the same process here, although I'm shortcutting past the details because I don't want to manually step through the whole process. Look at that post to see how this starts.
In short, we need to generate a 4d6 array that also preserves the die that was lowest for each sum. It'll look something like this:
beginarrayr
textbf4d6 Drop 1 (pre drop) & textbfOdds \ hline
text[4,1] & 1 \
text[5,1] & 4 \
text[6,1] & 10 \
text[7,1] & 20 \
text[8,1] & 34 \
text[9,1] & 52 \
text[10,1] & 70 \
text[11,1] & 84 \
text[12,1] & 90 \
text[13,1] & 88 \
text[14,1] & 78 \
text[15,1] & 60 \
text[16,1] & 40 \
text[17,1] & 24 \
text[18,1] & 12 \
text[19,1] & 4 \
text[8,2] & 1 \
text[9,2] & 4 \
text[10,2] & 10 \
text--Snip-- & text--Snip-- & textit... We need to conserve space... \
text[23,5] & 4 \
text[24,6] & 1 \
endarray
And then for each one we just subtract out that lowest roll, giving us the final roll.
beginarrayrr
text4d6 Drop 1 & textOdds
\ hline
text[3] & 1\
text[4] & 4\
text[5] & 10\
text[6] & 21\
text[7] & 38\
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
We simply chop off the results that are lower than 8. We always reroll when we encounter them, so the odds of the other results are unaffected.
beginarrayrr
text4d6 Drop 1 (≥8 only) & textOdds
\ hline
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
Then we start multiplying this array against itself. My method involved multiplexing these numbers, but regardless of how you do it, you'll end up with something like this (after removing sets that do not contain at least two ≥15 rolls):
beginarrayl
textbf6x(4d6D1≥8) & textbfOdds
\ hline
text[15, 15, 8, 8, 8, 8] & 3803650531440\
text[16, 15, 8, 8, 8, 8] & 5458674045120\
text[17, 15, 8, 8, 8, 8] & 3135834025920\
text[18, 15, 8, 8, 8, 8] & 1219491010080\
text[16, 16, 8, 8, 8, 8] & 1958455573440\
text[17, 16, 8, 8, 8, 8] & 2250140446080\
text[18, 16, 8, 8, 8, 8] & 875054617920\
textit... You get the Idea & textitLook at the link I posted \
textitThere's 5236 rows of this & textitabove for the full set \
endarray
That, finally, is the entire distribution of rolls that can be gained from this method of rolling stats.
What can we learn from it?
Well, we could compare the total statpoint distribution, against a normal 6x(4d6D1) rolled stats:

So it turns out the Colville Method has a pretty consderable boost to the overall sum, raising the average from 73.468 to 79.867. This isn't surprising though: all the data it acts on (individual rolls below 8, any set that is does not have at least two ≥15 rolls) are specifically bad rolls, so it naturally tends towards higher results.
If you use the dataset I posted above, you're welcome to do your own analysis on it. I recommend heavy use of Microsoft Excel or some other Spreadsheet software.
$endgroup$
add a comment
|
$begingroup$
Through my methods, I found 5,236 unique different dice pools that result from the Colville Stat Distribution. I've posted it here, as the length of the table violate's Stack Exchange's hard limit on post length. You can review it yourself and run data processing on it if you want to examine some stats on it that haven't been provided here or in other answers.
How was this Generated?
We need to first generate an array for the 4d6 drop 1 roll. I detailed a general purpose method for generating these kinds of arrays here, and I'm going to use the same process here, although I'm shortcutting past the details because I don't want to manually step through the whole process. Look at that post to see how this starts.
In short, we need to generate a 4d6 array that also preserves the die that was lowest for each sum. It'll look something like this:
beginarrayr
textbf4d6 Drop 1 (pre drop) & textbfOdds \ hline
text[4,1] & 1 \
text[5,1] & 4 \
text[6,1] & 10 \
text[7,1] & 20 \
text[8,1] & 34 \
text[9,1] & 52 \
text[10,1] & 70 \
text[11,1] & 84 \
text[12,1] & 90 \
text[13,1] & 88 \
text[14,1] & 78 \
text[15,1] & 60 \
text[16,1] & 40 \
text[17,1] & 24 \
text[18,1] & 12 \
text[19,1] & 4 \
text[8,2] & 1 \
text[9,2] & 4 \
text[10,2] & 10 \
text--Snip-- & text--Snip-- & textit... We need to conserve space... \
text[23,5] & 4 \
text[24,6] & 1 \
endarray
And then for each one we just subtract out that lowest roll, giving us the final roll.
beginarrayrr
text4d6 Drop 1 & textOdds
\ hline
text[3] & 1\
text[4] & 4\
text[5] & 10\
text[6] & 21\
text[7] & 38\
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
We simply chop off the results that are lower than 8. We always reroll when we encounter them, so the odds of the other results are unaffected.
beginarrayrr
text4d6 Drop 1 (≥8 only) & textOdds
\ hline
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
Then we start multiplying this array against itself. My method involved multiplexing these numbers, but regardless of how you do it, you'll end up with something like this (after removing sets that do not contain at least two ≥15 rolls):
beginarrayl
textbf6x(4d6D1≥8) & textbfOdds
\ hline
text[15, 15, 8, 8, 8, 8] & 3803650531440\
text[16, 15, 8, 8, 8, 8] & 5458674045120\
text[17, 15, 8, 8, 8, 8] & 3135834025920\
text[18, 15, 8, 8, 8, 8] & 1219491010080\
text[16, 16, 8, 8, 8, 8] & 1958455573440\
text[17, 16, 8, 8, 8, 8] & 2250140446080\
text[18, 16, 8, 8, 8, 8] & 875054617920\
textit... You get the Idea & textitLook at the link I posted \
textitThere's 5236 rows of this & textitabove for the full set \
endarray
That, finally, is the entire distribution of rolls that can be gained from this method of rolling stats.
What can we learn from it?
Well, we could compare the total statpoint distribution, against a normal 6x(4d6D1) rolled stats:

So it turns out the Colville Method has a pretty consderable boost to the overall sum, raising the average from 73.468 to 79.867. This isn't surprising though: all the data it acts on (individual rolls below 8, any set that is does not have at least two ≥15 rolls) are specifically bad rolls, so it naturally tends towards higher results.
If you use the dataset I posted above, you're welcome to do your own analysis on it. I recommend heavy use of Microsoft Excel or some other Spreadsheet software.
$endgroup$
Through my methods, I found 5,236 unique different dice pools that result from the Colville Stat Distribution. I've posted it here, as the length of the table violate's Stack Exchange's hard limit on post length. You can review it yourself and run data processing on it if you want to examine some stats on it that haven't been provided here or in other answers.
How was this Generated?
We need to first generate an array for the 4d6 drop 1 roll. I detailed a general purpose method for generating these kinds of arrays here, and I'm going to use the same process here, although I'm shortcutting past the details because I don't want to manually step through the whole process. Look at that post to see how this starts.
In short, we need to generate a 4d6 array that also preserves the die that was lowest for each sum. It'll look something like this:
beginarrayr
textbf4d6 Drop 1 (pre drop) & textbfOdds \ hline
text[4,1] & 1 \
text[5,1] & 4 \
text[6,1] & 10 \
text[7,1] & 20 \
text[8,1] & 34 \
text[9,1] & 52 \
text[10,1] & 70 \
text[11,1] & 84 \
text[12,1] & 90 \
text[13,1] & 88 \
text[14,1] & 78 \
text[15,1] & 60 \
text[16,1] & 40 \
text[17,1] & 24 \
text[18,1] & 12 \
text[19,1] & 4 \
text[8,2] & 1 \
text[9,2] & 4 \
text[10,2] & 10 \
text--Snip-- & text--Snip-- & textit... We need to conserve space... \
text[23,5] & 4 \
text[24,6] & 1 \
endarray
And then for each one we just subtract out that lowest roll, giving us the final roll.
beginarrayrr
text4d6 Drop 1 & textOdds
\ hline
text[3] & 1\
text[4] & 4\
text[5] & 10\
text[6] & 21\
text[7] & 38\
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
We simply chop off the results that are lower than 8. We always reroll when we encounter them, so the odds of the other results are unaffected.
beginarrayrr
text4d6 Drop 1 (≥8 only) & textOdds
\ hline
text[8] & 62\
text[9] & 91\
text[10] & 122\
text[11] & 148\
text[12] & 167\
text[13] & 172\
text[14] & 160\
text[15] & 131\
text[16] & 94\
text[17] & 54\
text[18] & 21\
endarray
Then we start multiplying this array against itself. My method involved multiplexing these numbers, but regardless of how you do it, you'll end up with something like this (after removing sets that do not contain at least two ≥15 rolls):
beginarrayl
textbf6x(4d6D1≥8) & textbfOdds
\ hline
text[15, 15, 8, 8, 8, 8] & 3803650531440\
text[16, 15, 8, 8, 8, 8] & 5458674045120\
text[17, 15, 8, 8, 8, 8] & 3135834025920\
text[18, 15, 8, 8, 8, 8] & 1219491010080\
text[16, 16, 8, 8, 8, 8] & 1958455573440\
text[17, 16, 8, 8, 8, 8] & 2250140446080\
text[18, 16, 8, 8, 8, 8] & 875054617920\
textit... You get the Idea & textitLook at the link I posted \
textitThere's 5236 rows of this & textitabove for the full set \
endarray
That, finally, is the entire distribution of rolls that can be gained from this method of rolling stats.
What can we learn from it?
Well, we could compare the total statpoint distribution, against a normal 6x(4d6D1) rolled stats:

So it turns out the Colville Method has a pretty consderable boost to the overall sum, raising the average from 73.468 to 79.867. This isn't surprising though: all the data it acts on (individual rolls below 8, any set that is does not have at least two ≥15 rolls) are specifically bad rolls, so it naturally tends towards higher results.
If you use the dataset I posted above, you're welcome to do your own analysis on it. I recommend heavy use of Microsoft Excel or some other Spreadsheet software.
answered Sep 17 at 18:57
XiremaXirema
40.7k4 gold badges128 silver badges229 bronze badges
40.7k4 gold badges128 silver badges229 bronze badges
add a comment
|
add a comment
|
$begingroup$
Ignore the actual order things are done, use an order that's easier to calculate, and don't be scared to approximate
Instead of first rolling stats and then rerolling if there aren't two 15+s, we can achieve exactly the same result by first rolling two stats that must be 15+ and then rolling the rest 'normally'.
To do this in anydice, what we want to do is take the collection of possible outcomes that is what 'highest 3 of 4d6' means and just remove all the parts that are under 15.
The easiest way to do this is manually. Looking at the results of the aforementioned distribution, we can see that '15' has a 10.11% chance of occurring, '16' a 7.25% chance, '17' a 4.17% chance, and '18' a 1.62% chance. These odds are truncated to the hundredths place, but we are going to consider that level of error acceptable. A sequence with 1011 '15's, 725 '16's, 417 '17's, and 162 '18's, then, can function as a die that gives us our two best values.
Using repetition, we can populate a sequence by using the following code:
output 15:1011,16:725,17:417,18:162
Next, we need to fix your code. It doesn't actually get you what you are looking for, I think, since it has an approximately infinitessimal chance of outputting numbers lower than 8. That may be fine with you, but we can also use truncation to get a (in my opinion) much cleaner and about equally accurate system for the remaining 4 ability scores:
output 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162
You can do something like output [highest 1 of 6d 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162] to confirm that it gives the same results.
To look at each ability score, we can just pull the appropriate number from a set of rolls, remembering that the rolls higher than 8 instead of 15 are also no better than the 3rd highest roll of such a sequence. So we end up with:
output [highest 1 of 2d15:1011,16:725,17:417,18:162] named "highest stat"
output 2 @ 2d15:1011,16:725,17:417,18:162 named "2nd highest stat"
output 3@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "highest non-forced stat"
output 4@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd highest non-forced stat"
output 5@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd lowest stat"
output 6@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "lowest stat"
Which gives results within 1 percentage point of the analytic value 1(approximately 10% error).
- thanks to @Carcer for the analytic value program.
$endgroup$
6
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Considerflip two coins, redo unless there is at least 1 headvsforce the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, dropTT), the second has 1/2 chance of 1 head (HH|HT).
$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
add a comment
|
$begingroup$
Ignore the actual order things are done, use an order that's easier to calculate, and don't be scared to approximate
Instead of first rolling stats and then rerolling if there aren't two 15+s, we can achieve exactly the same result by first rolling two stats that must be 15+ and then rolling the rest 'normally'.
To do this in anydice, what we want to do is take the collection of possible outcomes that is what 'highest 3 of 4d6' means and just remove all the parts that are under 15.
The easiest way to do this is manually. Looking at the results of the aforementioned distribution, we can see that '15' has a 10.11% chance of occurring, '16' a 7.25% chance, '17' a 4.17% chance, and '18' a 1.62% chance. These odds are truncated to the hundredths place, but we are going to consider that level of error acceptable. A sequence with 1011 '15's, 725 '16's, 417 '17's, and 162 '18's, then, can function as a die that gives us our two best values.
Using repetition, we can populate a sequence by using the following code:
output 15:1011,16:725,17:417,18:162
Next, we need to fix your code. It doesn't actually get you what you are looking for, I think, since it has an approximately infinitessimal chance of outputting numbers lower than 8. That may be fine with you, but we can also use truncation to get a (in my opinion) much cleaner and about equally accurate system for the remaining 4 ability scores:
output 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162
You can do something like output [highest 1 of 6d 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162] to confirm that it gives the same results.
To look at each ability score, we can just pull the appropriate number from a set of rolls, remembering that the rolls higher than 8 instead of 15 are also no better than the 3rd highest roll of such a sequence. So we end up with:
output [highest 1 of 2d15:1011,16:725,17:417,18:162] named "highest stat"
output 2 @ 2d15:1011,16:725,17:417,18:162 named "2nd highest stat"
output 3@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "highest non-forced stat"
output 4@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd highest non-forced stat"
output 5@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd lowest stat"
output 6@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "lowest stat"
Which gives results within 1 percentage point of the analytic value 1(approximately 10% error).
- thanks to @Carcer for the analytic value program.
$endgroup$
6
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Considerflip two coins, redo unless there is at least 1 headvsforce the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, dropTT), the second has 1/2 chance of 1 head (HH|HT).
$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
add a comment
|
$begingroup$
Ignore the actual order things are done, use an order that's easier to calculate, and don't be scared to approximate
Instead of first rolling stats and then rerolling if there aren't two 15+s, we can achieve exactly the same result by first rolling two stats that must be 15+ and then rolling the rest 'normally'.
To do this in anydice, what we want to do is take the collection of possible outcomes that is what 'highest 3 of 4d6' means and just remove all the parts that are under 15.
The easiest way to do this is manually. Looking at the results of the aforementioned distribution, we can see that '15' has a 10.11% chance of occurring, '16' a 7.25% chance, '17' a 4.17% chance, and '18' a 1.62% chance. These odds are truncated to the hundredths place, but we are going to consider that level of error acceptable. A sequence with 1011 '15's, 725 '16's, 417 '17's, and 162 '18's, then, can function as a die that gives us our two best values.
Using repetition, we can populate a sequence by using the following code:
output 15:1011,16:725,17:417,18:162
Next, we need to fix your code. It doesn't actually get you what you are looking for, I think, since it has an approximately infinitessimal chance of outputting numbers lower than 8. That may be fine with you, but we can also use truncation to get a (in my opinion) much cleaner and about equally accurate system for the remaining 4 ability scores:
output 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162
You can do something like output [highest 1 of 6d 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162] to confirm that it gives the same results.
To look at each ability score, we can just pull the appropriate number from a set of rolls, remembering that the rolls higher than 8 instead of 15 are also no better than the 3rd highest roll of such a sequence. So we end up with:
output [highest 1 of 2d15:1011,16:725,17:417,18:162] named "highest stat"
output 2 @ 2d15:1011,16:725,17:417,18:162 named "2nd highest stat"
output 3@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "highest non-forced stat"
output 4@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd highest non-forced stat"
output 5@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd lowest stat"
output 6@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "lowest stat"
Which gives results within 1 percentage point of the analytic value 1(approximately 10% error).
- thanks to @Carcer for the analytic value program.
$endgroup$
Ignore the actual order things are done, use an order that's easier to calculate, and don't be scared to approximate
Instead of first rolling stats and then rerolling if there aren't two 15+s, we can achieve exactly the same result by first rolling two stats that must be 15+ and then rolling the rest 'normally'.
To do this in anydice, what we want to do is take the collection of possible outcomes that is what 'highest 3 of 4d6' means and just remove all the parts that are under 15.
The easiest way to do this is manually. Looking at the results of the aforementioned distribution, we can see that '15' has a 10.11% chance of occurring, '16' a 7.25% chance, '17' a 4.17% chance, and '18' a 1.62% chance. These odds are truncated to the hundredths place, but we are going to consider that level of error acceptable. A sequence with 1011 '15's, 725 '16's, 417 '17's, and 162 '18's, then, can function as a die that gives us our two best values.
Using repetition, we can populate a sequence by using the following code:
output 15:1011,16:725,17:417,18:162
Next, we need to fix your code. It doesn't actually get you what you are looking for, I think, since it has an approximately infinitessimal chance of outputting numbers lower than 8. That may be fine with you, but we can also use truncation to get a (in my opinion) much cleaner and about equally accurate system for the remaining 4 ability scores:
output 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162
You can do something like output [highest 1 of 6d 8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162] to confirm that it gives the same results.
To look at each ability score, we can just pull the appropriate number from a set of rolls, remembering that the rolls higher than 8 instead of 15 are also no better than the 3rd highest roll of such a sequence. So we end up with:
output [highest 1 of 2d15:1011,16:725,17:417,18:162] named "highest stat"
output 2 @ 2d15:1011,16:725,17:417,18:162 named "2nd highest stat"
output 3@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "highest non-forced stat"
output 4@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd highest non-forced stat"
output 5@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "2nd lowest stat"
output 6@6d8:478,9:702,10:941,11:1142,12:1289,13:1327,14:1235,15:1011,16:725,17:417,18:162 named "lowest stat"
Which gives results within 1 percentage point of the analytic value 1(approximately 10% error).
- thanks to @Carcer for the analytic value program.
answered Sep 17 at 20:50
Please stop being evilPlease stop being evil
51.3k8 gold badges114 silver badges230 bronze badges
51.3k8 gold badges114 silver badges230 bronze badges
6
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Considerflip two coins, redo unless there is at least 1 headvsforce the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, dropTT), the second has 1/2 chance of 1 head (HH|HT).
$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
add a comment
|
6
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Considerflip two coins, redo unless there is at least 1 headvsforce the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, dropTT), the second has 1/2 chance of 1 head (HH|HT).
$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
6
6
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Consider
flip two coins, redo unless there is at least 1 head vs force the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, drop TT), the second has 1/2 chance of 1 head (HH|HT).$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
Want to note that this approach is somewhat dangerous in general, and humans have terrible intuitions for this sort of thing. Consider
flip two coins, redo unless there is at least 1 head vs force the first coin to be a head, flip the second. The first has 2/3 chance of 1 head (HH|HT|TH, drop TT), the second has 1/2 chance of 1 head (HH|HT).$endgroup$
– Cireo
Sep 17 at 23:10
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
$begingroup$
@Cireo You just have to remember the consequences of what you're doing, and not use an approximation that is no good for your model. Also your example applies a different approximation than is used here-- the part of this approximation that is rolling the 8s after the 15s would be more like flipping two coins for the second check and only adding a heads if both turn up heads (3/4 chance of 1 head), but also the TT case is the sort of thing truncation is for. The earlier step where we truncate usused possibilities and scale to 100% is 100% accurate except for preexisting error in the numbers.
$endgroup$
– Please stop being evil
Sep 18 at 0:33
add a comment
|
Thanks for contributing an answer to Role-playing Games Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2frpg.stackexchange.com%2fquestions%2f156379%2fhow-does-one-calculate-the-distribution-of-the-matt-colville-way-of-rolling-stat%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
$begingroup$
Question: If you go into the roller view, you're rolling '4d6 drop lowest' 6 times for each ability score, and then doing this one for each of the 6 ability scores getting you a total of 36 sets of '4d6 drop lowest'. Is this intended?
$endgroup$
– JRodge01
Sep 17 at 12:37
$begingroup$
@JRodge01 That doesn't seem like it would ensure you end up with all scores 8 and above.
$endgroup$
– GcL
Sep 17 at 13:24
$begingroup$
I'm not sure the code is doing what the programmer think it does, even without ensuring 8's and above.
$endgroup$
– JRodge01
Sep 17 at 13:27
1
$begingroup$
Let me clarify my question. You define Y as "six sets of 4d6 drop the lowest, reroll 3's through 7's." This satisfies steps 1, 2, and 3 of the algorithm in the definition of Y alone. What is the purpose of the loop, and why are you running it 6 times?
$endgroup$
– JRodge01
Sep 17 at 13:43
1
$begingroup$
I suspect that this method might be mathematically equivalent to starting over from the beginning whenever you roll a 7 or lower. If true, that would make the statistical analysis much easier, even if you wouldn't do it that way in practice. However, I'm not sure how to prove this (other than trying both methods empirically and seeing if they give similar distributions).
$endgroup$
– Ryan C. Thompson
Sep 17 at 15:43