25 or 32...what's the REAL "standard" point buy?

stephenh said:
I don't think a faster computer will help much -- I think there are actually about 4.7e18 combinations in total. Given that my (2.7 Ghz) machine takes about 5-10 seconds to calculate 1 million random sets of stats, to calculate all possible combinations would take roughly about half a million years...... you might be able to drop this down a bit by removing redundant combinations, but its still going to be one hell of a long time.

Anyway using 1 million random stat sets and rerolling if the stats don't meed your given minimum conditions I get an average of 33.2 points.
I figured out the mathematics to simplify the solution. And honestly, it's a much better choice then using random rolls. I ran the program for myself last night, and came up with the results, but I didn't save them. I'm running the program right now to calculate the values again. The only error with my new method is about 0.000000005971% due to truncation of decimals past the double precision.

28.5277777775552 for all possible ability score arrays (using a linear negative formula for stats below 8, so 7 = -1 and 6 = -2 and so on down to 3 = -5).

The average point value for all arrays that have a total modifier of +1 or greater and with at least one value greater than 14 comes to 30.0628924089566 points (and interestingly comprises 90.719834089556% of all possible rolls. So 30 points is very close to what you want to give if you want players to have ability scores approximately the same as rolling.

Lastly, we have only examine those arrays where all numbers are at least 8. The problem with this is that it lowers the points value because there are more "greater" arrays than "lesser" arrays, so we should get a lower points value since we are examining significantly less total arrays. 26.616669536546

Code:
All values > 8	One value > 14	Total mod > 0	Average Points Value
Check		Check		Check		26.616669536546
		Check		Check		30.0628924089566 
						28.5277777775552
 

log in or register to remove this ad

Creamsteak said:
I figured out the mathematics to simplify the solution. And honestly, it's a much better choice then using random rolls.

Hmm I think there are some mistakes in what you posted.

I realised over the weekend that although there is a very large number of total combinations, there is in fact a trivial way to calculate the average for all values (assuming you treat the values all in the same way, which is not what happens when you start specifying rules such as at least 1 stat above 14). You just need to calculate the average points score for a single stat and multiply by 6. There are only 6*6*6*6=1296 combinations in total for a single stat.

For normal 4d6 drop low I can reproduce my average I listed earlier and if I use negative points for values less than 8 like you do i get the same number as you do (28.53). However beyond this I am sure your other averages are incorrect. Applying the cuts you suggest I get the following averages: 32.17 for at least 1 value greater than 14, 33.18 with the previous cut and all stats of at least 8. (using your negative scoring for values below 8 in both cases).

In fact it is pretty trivial to demonstrate that if you apply a cut where all values are equal to or above 8, then your average, relative to no cut, must be *greater*, not lower as you suggest. Consider for example, the average points score for a stat, as I discuss in my first paragrah. If you remove all rolls below 8 (i.e. totally ignore them), you are basically removing a series of low (all negative for a cut of 8) numbers -- thus your average can only increase. I wonder if you have calculated your averages by dividing by the total number of all possible rolls rather than the reduced number of combinations possible after applying the cuts? Hmm I don't think it can be that -- I would expect a bigger change.

I guess I would be interested to know how you did it in full? Once you start saying at least 1 stat above 14 I can't see a simple way of doing it (because at least one stat is being treated in a special way relative to the others). You have to generate full stat arrays -- You can't just use average stats as I do earlier in this post. I can see that you might be able to simplify things a bit by generating stat distributions and applying some sort of weighting, but I don't see how you would do it off the top of my head, and I imagine it would still be pretty complicated.

Generating sets of random stats has the advantage that is is very simple to do, and providing that you generate enough random sets the errors on the values you get are very small -- about 0.5 % (i.e. better than to nearest 0.01 of a point which I think is as accurate as we need really) for 1 million stat sets.
 
Last edited:

Al'Kelhar said:
32 points is really for "heroic" fantasy, where the PCs are so far above the norm that they are truly heroes.
That's the kind of game my players want. (Me too, when I'm a player. If I want average, I have only to live my life.)

That said, I use my own version of point buy. All stats start at zero, and I give the players some number of points, usually 74, to assign on a one-for-one basis. Then I give them additional points for including various things in their backgrounds. This way the players get the stats they want, and I get their back-story to use against them.:cool:
 
Last edited:

Faerl'Elghinn said:
I just feel that it's kind of a waste of time to run a campaign based on "average, everyday people" or those who are slightly superior. Who wants to read a book about somebody who's "pretty ok" at a few things?
I totally agree. Also, higher ability scores fit my DMing style, since I tend not to hand out magic weapons & armor. I prefer utilitarian magic items, like Handy Haversacks, Rings of Sustenance and the like.
 

Well, now 28 PB doesn't really produce average characters. :)

It depends on what the average is, of course, but if you use the by-the-book average, then 28 PB characters are already fairly heroic. With 32+ PB you often have to beef up the opposition already in my experience (not, that this is a bad thing, just noting, that it kinda raises the average), altho 32 surely isn't that high-powered already, that would be 36 or 40, or more. :D

Bye
Thanee
 

ree

Buttercup said:
I totally agree. Also, higher ability scores fit my DMing style, since I tend not to hand out magic weapons & armor. I prefer utilitarian magic items, like Handy Haversacks, Rings of Sustenance and the like.

I'm in this camp as well. I like to limit magic items more than I like to limit stats. Magic items tend to give me way more balance problems than high statistics.
 

re

Well, now 28 PB doesn't really produce average characters.

It depends on what the average is, of course, but if you use the by-the-book average, then 28 PB characters are already fairly heroic. With 32+ PB you often have to beef up the opposition already in my experience (not, that this is a bad thing, just noting, that it kinda raises the average), altho 32 surely isn't that high-powered already, that would be 36 or 40, or more.

Average is relative as well. I have better stats in real life than 32 point buy. Because of this I have a great deal of trouble playing a 28 or 32 point buy. I feel like I am playing a character not even as good as I am. I'll only do it for a DM that I feel will make the game fun irregardless of my character's stats like when I gave Destan's PbP game a shot.

Most of my players are ex-athletes. Athletes in general understand that a person doesn't have to give up intelligence and charisma to be strong and dextrous. That is why 28 or 32 point is unattractive to us as a group.

Limitations are more a matter of a matter of limited time to develop a particular skill rather than a limited statistic. I think class choices do a good job of limiting an individual character's capabilities, and don't require limitations on statistics.

The use of higher stats does require giving the bad guys higher stats to balance the advantage of our PC's. None of has a problem beefing up the bad guys.
 

Okay. I've just decided to do a very very thorough analysis, just because. The basics of it are: I have a stompy Postgres server lying around, and I figured "Hmm, I bet I can calculate the exact probabilities (within constraints of floating point accuracy) using that." So I have. First I'm listing the basic results, then the method, then the tables. I'm also including the SQL I used to calculate at the very end, in case you're interested (or in case there's a problem with my method.) (EDIT: Oops, I just realized, actually, that the average stat mod total and the average sum of attribute scores shouldn't be integers. Apologies for that, but since they're not that important, I don't plan to run the analysis again.)


The first tidbits:

1) 39.94% of all pure 3d6 rolls meet the >0 modifier and one stat >13 rule.
2) 87.33% of all 4d6 drop lowest rolls meet those constraints.


Analysis of the percentiles, first using 0 points for sub-8 stats. Remember that these are the number of valid (by the above rules) rolls which are worth at least that many points.

1) Using 3d6, the 50th percentile is somewhere between 24 and 25 points. 25 points is at 44.4527%. 28 points is at 25.9440%. 30 points is at 17.3194%. 35 points is at 5.5482%. About 50% of rolls fall between 21 and 28 points. About 75% of rolls fall between 20 and 31 points.

2) Using 4d6 drop the lowest, the 50th percentile is somewhere between 30 and 31 points. 25 points is at 78.1886%. 28 points is at 62.9516%. 30 points is at 52.5320%. 35 points is at 29.5290%. About 50% of rolls fall between 25 and 36 points. About 75% of rolls fall between 23 and 40 points.


And the same analysis using -1 point for each step below 8:

1) Using 3d6, the 50th percentile is somewhere between 23 and 24 points. 25 points is at 38.1926%. 28 points is at 22.2716%. 30 points is at 14.9498%. 35 points is at 4.8816%. About 50% of rolls fall between 20 and 27 points. About 75% of rolls fall between 18 and 30 points.

2) Using 4d6 drop the lowest, the 50th percentile is right at about 30 points. 25 points is at 75.1108%. 28 points is at 60.3289%. 30 points is at 50.3413%. 35 points is at 28.3791%. About 50% of rolls fall between 25 and 36 points. About 75% of rolls fall between 22 and 41 points.


So what can we say based on those numbers? The most obvious thing to me is that it highlights the potential for serious inequality in die rolling--using the basic system of 4d6 drop the lowest, you have a really large range of point values in the middle 50% of the spectrum (whether or not we're counting negative points.) The range of 25 to 36 is huge, considering that people have been talking about a 10 point spread maybe being worth about ECL +1.

The second thing is that the numbers are pretty much what stephenh pointed out: 4d6 drop the lowest is about on par (in the average) with 30 point buy. 3d6 and keep is about on par with 25 point buy. If I wasn't already a point buy fan, this would make me think more than twice about the "choose between point buy and 4d6 drop the lowest" strategy, unless 30 point PB is being used.

And the third is that allowing "buy downs" from 8 doesn't change things that significantly, at least in this analysis. It reduces the cost to reach a given percentile by about one point. In the real world, of course, allowing this gives a minmaxer a lot of leeway, so the averages don't really work out. (Which is also why the higher valued stats cost more.) By cutting out the choice of dropping a stat super-low and increasing the costs of higher stats, they've done a pretty nice job of keeping this system sane.

Anyway, hope these numbers are interesting to you, and apologies to stephenh for wanting to do my own test to check his results. :)


The super-brute-force approach I took was to create tables representing a d6, then the sum of 3d6, then the sum of 4d6 drop the lowest. All of these tables were of the form (value, probability, points, modifier). The next step was to create tables of the *entire possible set* of stats rolls (that is, 3d6 crossed with itself six times, or 4d6 crossed with itself six times.) Included in each row is the number of points it costs for those together, as well as the sum of the rolls, and the sum of the modifiers. (No real reason for sum of the rolls, just thought it would be interesting to display.) Generating the 3d6 or 4d6 stat rolls table for a given point cost table takes about four minutes each. Limiting by the >0 modifier and one >13 stat rules (and grouping on the point total) takes about a minute after that for each one. Then the limited data needs to be renormalized to find the probabilities out of that pool. I was actually impressed with how quick this was (and that it didn't load the machine beyond belief.)

First pass is with sub-8 stats counting as zero cost--that is, you can choose to have them, but you get no point-wise benefit by doing so. Second pass gives -1 point for each step below 8.

And now the results. In these tables, st_pc is the percentile chance of getting at least that many points. st_pt is the number of points. st_m is the average stat modifier for the rolls that have that number of points. st_s is the average stat sum for the rolls that have that number of points. I've included the full set of possibilities, although the probabilities get very very low on the high end. (The probability of the highest value for 3d6 is only 2.4653e-14.) The probabilities are only shown to four decimal places.

Code:
3d6, sorted by number of points,
0 points for sub-8 stats:
  st_pc   | st_pt | st_m | st_s
----------+-------+------+------
 100.0000 |    14 |    1 |   62
  99.9130 |    15 |    1 |   63
  99.4639 |    16 |    1 |   63
  98.0996 |    17 |    1 |   64
  95.2541 |    18 |    1 |   64
  90.6155 |    19 |    1 |   65
  84.2811 |    20 |    2 |   65
  76.6736 |    21 |    2 |   66
  68.4514 |    22 |    2 |   66
  60.1170 |    23 |    2 |   67
  52.0366 |    24 |    2 |   67
  44.4527 |    25 |    2 |   67
  37.5313 |    26 |    2 |   67
  31.3509 |    27 |    3 |   68
  25.9440 |    28 |    3 |   68
  21.2815 |    29 |    3 |   69
  17.3194 |    30 |    3 |   69
  13.9892 |    31 |    3 |   70
  11.2194 |    32 |    4 |   70
   8.9307 |    33 |    4 |   71
   7.0656 |    34 |    4 |   71
   5.5482 |    35 |    5 |   72
   4.3304 |    36 |    5 |   72
   3.3577 |    37 |    5 |   73
   2.5858 |    38 |    6 |   74
   1.9802 |    39 |    6 |   74
   1.5063 |    40 |    6 |   75
   1.1382 |    41 |    7 |   76
   0.8560 |    42 |    7 |   76
   0.6385 |    43 |    7 |   78
   0.4743 |    44 |    8 |   78
   0.3499 |    45 |    8 |   78
   0.2564 |    46 |    9 |   80
   0.1871 |    47 |    9 |   80
   0.1355 |    48 |    9 |   81
   0.0976 |    49 |   10 |   82
   0.0700 |    50 |   10 |   82
   0.0497 |    51 |   10 |   83
   0.0353 |    52 |   11 |   84
   0.0248 |    53 |   11 |   84
   0.0173 |    54 |   12 |   86
   0.0121 |    55 |   11 |   85
   0.0083 |    56 |   12 |   87
   0.0057 |    57 |   13 |   88
   0.0039 |    58 |   12 |   87
   0.0026 |    59 |   13 |   89
   0.0018 |    60 |   14 |   90
   0.0012 |    61 |   13 |   89
   0.0008 |    62 |   14 |   91
   0.0005 |    63 |   14 |   91
   0.0003 |    64 |   15 |   92
   0.0002 |    65 |   15 |   93
   0.0001 |    66 |   15 |   93
   0.0001 |    67 |   16 |   94
   0.0001 |    68 |   16 |   94
   0.0000 |    69 |   16 |   95
   0.0000 |    70 |   17 |   97
   0.0000 |    71 |   17 |   96
   0.0000 |    72 |   18 |   97
   0.0000 |    73 |   18 |   99
   0.0000 |    74 |   17 |   97
   0.0000 |    75 |   19 |   99
   0.0000 |    76 |   19 |  100
   0.0000 |    77 |   18 |   98
   0.0000 |    78 |   20 |  101
   0.0000 |    79 |   20 |  101
   0.0000 |    80 |   19 |  100
   0.0000 |    81 |   20 |  102
   0.0000 |    82 |   20 |  103
   0.0000 |    83 |   21 |  103
   0.0000 |    84 |   21 |  104
   0.0000 |    85 |   21 |  104
   0.0000 |    86 |   22 |  104
   0.0000 |    87 |   22 |  105
   0.0000 |    88 |   22 |  105
   0.0000 |    90 |   22 |  106
   0.0000 |    93 |   23 |  107
   0.0000 |    96 |   24 |  108

Code:
4d6 drop the lowest, sorted by number of points,
0 points for sub-8 stats:
  st_pc   | st_pt | st_m | st_s
----------+-------+------+------
 100.0000 |    14 |    1 |   62
  99.9891 |    15 |    1 |   63
  99.9205 |    16 |    1 |   63
  99.6773 |    17 |    1 |   64
  99.0864 |    18 |    1 |   64
  97.9732 |    19 |    1 |   65
  96.2144 |    20 |    2 |   65
  93.7607 |    21 |    2 |   66
  90.6571 |    22 |    2 |   66
  86.9730 |    23 |    2 |   67
  82.7863 |    24 |    2 |   67
  78.1886 |    25 |    2 |   67
  73.2836 |    26 |    2 |   67
  68.1708 |    27 |    3 |   68
  62.9516 |    28 |    3 |   68
  57.7107 |    29 |    3 |   69
  52.5320 |    30 |    3 |   69
  47.4779 |    31 |    3 |   70
  42.6138 |    32 |    4 |   70
  37.9726 |    33 |    4 |   71
  33.6070 |    34 |    4 |   71
  29.5290 |    35 |    5 |   72
  25.7685 |    36 |    5 |   72
  22.3289 |    37 |    5 |   73
  19.2144 |    38 |    6 |   74
  16.4190 |    39 |    6 |   74
  13.9374 |    40 |    6 |   75
  11.7434 |    41 |    7 |   76
   9.8350 |    42 |    7 |   76
   8.1732 |    43 |    7 |   78
   6.7511 |    44 |    8 |   78
   5.5369 |    45 |    8 |   78
   4.5092 |    46 |    9 |   80
   3.6494 |    47 |    9 |   80
   2.9327 |    48 |    9 |   81
   2.3394 |    49 |   10 |   82
   1.8571 |    50 |   10 |   82
   1.4596 |    51 |   10 |   83
   1.1434 |    52 |   11 |   84
   0.8876 |    53 |   11 |   84
   0.6840 |    54 |   12 |   86
   0.5254 |    55 |   11 |   85
   0.3985 |    56 |   12 |   87
   0.3017 |    57 |   13 |   88
   0.2266 |    58 |   12 |   87
   0.1679 |    59 |   13 |   89
   0.1252 |    60 |   14 |   90
   0.0913 |    61 |   13 |   89
   0.0667 |    62 |   14 |   91
   0.0485 |    63 |   14 |   91
   0.0344 |    64 |   15 |   92
   0.0249 |    65 |   15 |   93
   0.0174 |    66 |   15 |   93
   0.0122 |    67 |   16 |   94
   0.0087 |    68 |   16 |   94
   0.0058 |    69 |   16 |   95
   0.0041 |    70 |   17 |   97
   0.0028 |    71 |   17 |   96
   0.0018 |    72 |   18 |   97
   0.0013 |    73 |   18 |   99
   0.0008 |    74 |   17 |   97
   0.0005 |    75 |   19 |   99
   0.0004 |    76 |   19 |  100
   0.0002 |    77 |   18 |   98
   0.0001 |    78 |   20 |  101
   0.0001 |    79 |   20 |  101
   0.0000 |    80 |   19 |  100
   0.0000 |    81 |   20 |  102
   0.0000 |    82 |   20 |  103
   0.0000 |    83 |   21 |  103
   0.0000 |    84 |   21 |  104
   0.0000 |    85 |   21 |  104
   0.0000 |    86 |   22 |  104
   0.0000 |    87 |   22 |  105
   0.0000 |    88 |   22 |  105
   0.0000 |    90 |   22 |  106
   0.0000 |    93 |   23 |  107
   0.0000 |    96 |   24 |  108

Code:
3d6, sorted by number of points,
-1 point per step for sub-8 stats:
  st_pc   | st_pt | st_m | st_s
----------+-------+------+------
 100.0000 |    14 |    1 |   62
  99.7790 |    15 |    1 |   63
  98.6284 |    16 |    1 |   64
  95.7917 |    17 |    1 |   64
  90.9264 |    18 |    1 |   65
  84.1974 |    19 |    1 |   65
  76.3813 |    20 |    2 |   66
  68.2589 |    21 |    2 |   66
  60.1652 |    22 |    2 |   66
  52.3084 |    23 |    2 |   67
  44.9261 |    24 |    2 |   67
  38.1926 |    25 |    3 |   68
  32.1762 |    26 |    3 |   68
  26.8779 |    27 |    3 |   69
  22.2716 |    28 |    3 |   70
  18.3142 |    29 |    4 |   70
  14.9498 |    30 |    4 |   71
  12.1168 |    31 |    4 |   72
   9.7524 |    32 |    5 |   72
   7.7957 |    33 |    5 |   73
   6.1895 |    34 |    5 |   74
   4.8816 |    35 |    6 |   75
   3.8249 |    36 |    6 |   75
   2.9776 |    37 |    7 |   76
   2.3032 |    38 |    7 |   77
   1.7703 |    39 |    7 |   77
   1.3522 |    40 |    8 |   78
   1.0264 |    41 |    8 |   79
   0.7743 |    42 |    8 |   79
   0.5806 |    43 |    9 |   80
   0.4326 |    44 |    9 |   81
   0.3204 |    45 |    9 |   81
   0.2359 |    46 |   10 |   82
   0.1726 |    47 |   10 |   83
   0.1255 |    48 |   10 |   83
   0.0907 |    49 |   11 |   84
   0.0652 |    50 |   11 |   85
   0.0466 |    51 |   11 |   85
   0.0331 |    52 |   12 |   86
   0.0233 |    53 |   12 |   86
   0.0164 |    54 |   12 |   87
   0.0114 |    55 |   13 |   88
   0.0079 |    56 |   13 |   88
   0.0054 |    57 |   13 |   89
   0.0037 |    58 |   13 |   90
   0.0025 |    59 |   14 |   90
   0.0017 |    60 |   14 |   91
   0.0011 |    61 |   14 |   91
   0.0008 |    62 |   15 |   92
   0.0005 |    63 |   15 |   93
   0.0003 |    64 |   15 |   93
   0.0002 |    65 |   16 |   94
   0.0001 |    66 |   16 |   94
   0.0001 |    67 |   16 |   95
   0.0001 |    68 |   17 |   95
   0.0000 |    69 |   17 |   96
   0.0000 |    70 |   17 |   96
   0.0000 |    71 |   17 |   97
   0.0000 |    72 |   18 |   97
   0.0000 |    73 |   18 |   98
   0.0000 |    74 |   18 |   99
   0.0000 |    75 |   19 |   99
   0.0000 |    76 |   19 |  100
   0.0000 |    77 |   19 |  100
   0.0000 |    78 |   20 |  101
   0.0000 |    79 |   19 |  101
   0.0000 |    80 |   20 |  101
   0.0000 |    81 |   20 |  102
   0.0000 |    82 |   20 |  103
   0.0000 |    83 |   21 |  103
   0.0000 |    84 |   21 |  104
   0.0000 |    85 |   21 |  104
   0.0000 |    86 |   22 |  104
   0.0000 |    87 |   22 |  105
   0.0000 |    88 |   22 |  105
   0.0000 |    90 |   22 |  106
   0.0000 |    93 |   23 |  107
   0.0000 |    96 |   24 |  108

Code:
4d6 drop the lowest, sorted by number of points,
-1 point per step for sub-8 stats:
  st_pc   | st_pt | st_m | st_s
----------+-------+------+------
 100.0000 |    14 |    1 |   62
  99.9711 |    15 |    1 |   63
  99.7878 |    16 |    1 |   64
  99.2486 |    17 |    1 |   64
  98.1720 |    18 |    1 |   65
  96.4416 |    19 |    1 |   65
  94.0743 |    20 |    2 |   66
  91.1697 |    21 |    2 |   66
  87.7763 |    22 |    2 |   66
  83.9239 |    23 |    2 |   67
  79.6750 |    24 |    2 |   67
  75.1108 |    25 |    3 |   68
  70.3122 |    26 |    3 |   68
  65.3584 |    27 |    3 |   69
  60.3289 |    28 |    3 |   70
  55.3002 |    29 |    4 |   70
  50.3413 |    30 |    4 |   71
  45.5126 |    31 |    4 |   72
  40.8647 |    32 |    5 |   72
  36.4392 |    33 |    5 |   73
  32.2691 |    34 |    5 |   74
  28.3791 |    35 |    6 |   75
  24.7859 |    36 |    6 |   75
  21.4985 |    37 |    7 |   76
  18.5190 |    38 |    7 |   77
  15.8429 |    39 |    7 |   77
  13.4608 |    40 |    8 |   78
  11.3589 |    41 |    8 |   79
   9.5200 |    42 |    8 |   79
   7.9244 |    43 |    9 |   80
   6.5519 |    44 |    9 |   81
   5.3797 |    45 |    9 |   81
   4.3885 |    46 |   10 |   82
   3.5539 |    47 |   10 |   83
   2.8609 |    48 |   10 |   83
   2.2847 |    49 |   11 |   84
   1.8149 |    50 |   11 |   85
   1.4297 |    51 |   11 |   85
   1.1199 |    52 |   12 |   86
   0.8711 |    53 |   12 |   86
   0.6721 |    54 |   12 |   87
   0.5162 |    55 |   13 |   88
   0.3926 |    56 |   13 |   88
   0.2971 |    57 |   13 |   89
   0.2235 |    58 |   13 |   90
   0.1660 |    59 |   14 |   90
   0.1235 |    60 |   14 |   91
   0.0904 |    61 |   14 |   91
   0.0660 |    62 |   15 |   92
   0.0480 |    63 |   15 |   93
   0.0342 |    64 |   15 |   93
   0.0247 |    65 |   16 |   94
   0.0173 |    66 |   16 |   94
   0.0121 |    67 |   16 |   95
   0.0086 |    68 |   17 |   95
   0.0058 |    69 |   17 |   96
   0.0040 |    70 |   17 |   96
   0.0027 |    71 |   17 |   97
   0.0018 |    72 |   18 |   97
   0.0013 |    73 |   18 |   98
   0.0008 |    74 |   18 |   99
   0.0005 |    75 |   19 |   99
   0.0004 |    76 |   19 |  100
   0.0002 |    77 |   19 |  100
   0.0001 |    78 |   20 |  101
   0.0001 |    79 |   19 |  101
   0.0000 |    80 |   20 |  101
   0.0000 |    81 |   20 |  102
   0.0000 |    82 |   20 |  103
   0.0000 |    83 |   21 |  103
   0.0000 |    84 |   21 |  104
   0.0000 |    85 |   21 |  104
   0.0000 |    86 |   22 |  104
   0.0000 |    87 |   22 |  105
   0.0000 |    88 |   22 |  105
   0.0000 |    90 |   22 |  106
   0.0000 |    93 |   23 |  107
   0.0000 |    96 |   24 |  108

And here's the code I used to run the analysis. My running times were on a dual Xeon 2.66Ghz system with 2GB of memory and fast SCSI disks, so it might take a while on something smaller. I think I/O writing out the intermediate tables was the main bottleneck. Oh, also expect to burn a few GB of disk on those tables. The database used was Postgresql 7.4. For another database, you'll almost certainly have to change the code.

Code:
create table st_pt (n int, pt int);
insert into st_pt values (3, 0);
insert into st_pt values (4, 0);
insert into st_pt values (5, 0);
insert into st_pt values (6, 0);
insert into st_pt values (7, 0);
insert into st_pt values (8, 0);
insert into st_pt values (9, 1);
insert into st_pt values (10, 2);
insert into st_pt values (11, 3);
insert into st_pt values (12, 4);
insert into st_pt values (13, 5);
insert into st_pt values (14, 6);
insert into st_pt values (15, 8);
insert into st_pt values (16, 10);
insert into st_pt values (17, 13);
insert into st_pt values (18, 16);

-- used in second run: negative point values for low amounts
-- insert into st_pt values (3, -5);
-- insert into st_pt values (4, -4);
-- insert into st_pt values (5, -3);
-- insert into st_pt values (6, -2);
-- insert into st_pt values (7, -1);
-- insert into st_pt values (8, 0);
-- insert into st_pt values (9, 1);
-- insert into st_pt values (10, 2);
-- insert into st_pt values (11, 3);
-- insert into st_pt values (12, 4);
-- insert into st_pt values (13, 5);
-- insert into st_pt values (14, 6);
-- insert into st_pt values (15, 8);
-- insert into st_pt values (16, 10);
-- insert into st_pt values (17, 13);
-- insert into st_pt values (18, 16);

create table st_mod (n int, m int);
insert into st_mod values (3, -4);
insert into st_mod values (4, -3);
insert into st_mod values (5, -3);
insert into st_mod values (6, -2);
insert into st_mod values (7, -2);
insert into st_mod values (8, -1);
insert into st_mod values (9, -1);
insert into st_mod values (10, 0);
insert into st_mod values (11, 0);
insert into st_mod values (12, 1);
insert into st_mod values (13, 1);
insert into st_mod values (14, 2);
insert into st_mod values (15, 2);
insert into st_mod values (16, 3);
insert into st_mod values (17, 3);
insert into st_mod values (18, 4);

create table d6 (n int, p float);
insert into d6 values (1, 1.0/6.0);
insert into d6 values (2, 1.0/6.0);
insert into d6 values (3, 1.0/6.0);
insert into d6 values (4, 1.0/6.0);
insert into d6 values (5, 1.0/6.0);
insert into d6 values (6, 1.0/6.0);

create table s3d6 (p float, n int, pt int, m int);
insert into s3d6 (p, n, pt, m)
 select sum(a.p * b.p * c.p) as p,
        (a.n + b.n + c.n) as x,
        pt,
        m
   from d6 a, d6 b, d6 c, st_mod, st_pt
   where st_mod.n = (a.n+b.n+c.n)
     and st_pt.n = st_mod.n
 group by x, pt, m;

create table t4d6 (a int, b int, c int, d int, p float);
insert into t4d6
 select a.n, b.n, c.n, d.n, sum(a.p*b.p*c.p*d.p)
   from d6 a, d6 b, d6 c, d6 d
 group by a.n, b.n, c.n, d.n;

update t4d6 set a = 0 where a <= b and a <= c and a <= d;
update t4d6 set b = 0 where b <= a and b <= c and b <= d;
update t4d6 set c = 0 where c <= a and c <= b and c <= d;
update t4d6 set d = 0 where d <= a and d <= b and d <= c;

create table s4d6 (p float, n int, pt int, m int);
insert into s4d6 (p, n, pt, m)
 select sum(p) as p,
        (a+b+c+d) as x,
        pt,
        m
  from t4d6, st_mod, st_pt
  where st_mod.n = (a+b+c+d)
    and st_pt.n = st_mod.n
 group by x, pt, m;

create table stats3d6 (st_p float, st_pt int, st_m int, st_s int,
                       a int, b int, c int, d int, e int, f int);

select 'Started at ' || current_time;
insert into stats3d6 (a, b, c, d, e, f, st_p, st_pt, st_m, st_s)
 select a.n as a,
        b.n as b,
        c.n as c,
        d.n as d,
        e.n as e,
        f.n as f,
        a.p*b.p*c.p*d.p*e.p*f.p as st_p,
        a.pt + b.pt + c.pt + d.pt + e.pt + f.pt as st_pt,
        a.m+b.m+c.m+d.m+e.m+f.m as st_m,
        a.n+b.n+c.n+d.n+e.n+f.n as st_s
   from s3d6 a, s3d6 b, s3d6 c, s3d6 d, s3d6 e, s3d6 f;
select 'Finished at ' || current_time;

create table stats4d6 (st_p float, st_pt int, st_m int, st_s int,
                       a int, b int, c int, d int, e int, f int);

select 'Started at ' || current_time;
insert into stats4d6 (a, b, c, d, e, f, st_p, st_pt, st_m, st_s)
 select a.n as a,
        b.n as b,
        c.n as c,
        d.n as d,
        e.n as e,
        f.n as f,
        a.p*b.p*c.p*d.p*e.p*f.p as st_p,
        a.pt + b.pt + c.pt + d.pt + e.pt + f.pt as st_pt,
        a.m+b.m+c.m+d.m+e.m+f.m as st_m,
        a.n+b.n+c.n+d.n+e.n+f.n as st_s
   from s4d6 a, s4d6 b, s4d6 c, s4d6 d, s4d6 e, s4d6 f;
select 'Finished at ' || current_time;

create table stats3d6l (st_p float, st_pt int, st_m int, st_s int);

insert into stats3d6l (st_p, st_pt, st_m, st_s)
 select sum(st_p),
        st_pt,
        avg(st_m),
        avg(st_s)
   from stats3d6
   where (a > 13 or b > 13 or c > 13 or d > 13 or e > 13 or f > 13)
     and st_m > 0
 group by st_pt;

create table stats4d6l (st_p float, st_pt int, st_m int, st_s int);

select 'Started at ' || current_time;
insert into stats4d6l (st_p, st_pt, st_m, st_s)
 select sum(st_p),
        st_pt,
        avg(st_m),
        avg(st_s)
   from stats4d6
   where (a > 13 or b > 13 or c > 13 or d > 13 or e > 13 or f > 13)
     and st_m > 0
 group by st_pt;
select 'Finished at ' || current_time;

-- Normalize

create table stats3d6l_norm (st_p float, st_pt int, st_m int, st_s int);
insert into stats3d6l_norm (st_p, st_pt, st_m, st_s)
 select (st_p / (select sum(st_p) from stats3d6l)), st_pt, st_m, st_s
   from stats3d6l;

create table stats4d6l_norm (st_p float, st_pt int, st_m int, st_s int);
insert into stats4d6l_norm (st_p, st_pt, st_m, st_s)
 select (st_p / (select sum(st_p) from stats4d6l)), st_pt, st_m, st_s
   from stats4d6l;

-- And the percentile output

select
  round(cast ((select sum(b.st_p) from stats3d6l_norm b
                 where b.st_pt >= a.st_pt) as numeric)*100.0, 4) as st_pc,
  st_pt, st_m, st_s
 from stats3d6l_norm a
 order by st_pt;

select
  round(cast ((select sum(b.st_p) from stats4d6l_norm b
                 where b.st_pt >= a.st_pt) as numeric)*100.0, 4) as st_pc,
  st_pt, st_m, st_s
 from stats4d6l_norm a
 order by st_pt;
 
Last edited:

Anax said:
Anyway, hope these numbers are interesting to you, and apologies to stephenh for wanting to do my own test to check his results. :)

Well I certainly found it interesting (welcome to the boards by the way), and it looks like you have done a very thorough job. I must admit I don't really know any SQL but I can follow it well enough to see what you have done. I had some vague idea that I could do something with the probablilties, but I hadn't quite figured out what to do. Basically you reduced the problem to one with 16^6 possible outcomes (about 17 million possibilities) which is a lot more reasonable to calculate. Its quite simple really when someone shows you how....

I was also glad to see that the results agreed with me! the slight differences between my values and your values are just because I was calculating means, while you used the 50th percentile, which I admit is probably a fairer measure of the average in this case.
 

I actually started by writing a program to do the analysis in O'Caml using a monad and combinator based representation of the histograms. But after a while, it turned out that a naive approach was going to have serious memory issues, and I didn't want to spend the time to make things efficient.

Then I realized that SQL is pretty good at working with large sets, and decided to give that a whack. It turned out pretty decent, so I might use this sort of approach in the future if I have a large (but finite) set of probabilities to work with.

The monad/combinator approach can be more powerful in many cases, but in this case there's very little you can do to prune the cases--specifically because you need the individual stat rolls fairly late in the game to prune out the re-roll cases. If you can throw out the individual parts of the cross product, you get a lot less waste. (For example, if only the sum of the rolls matters, you can sum a 3d6 roll with another 3d6 roll, then sum that product with another 3d6 roll, etc.)

Anyway, it was fun to get the raw numbers, and if I ever decide I want to analyze things in a different way, regenerating the data doesn't take long at all.

Back to data: Because you mentioned it (and I didn't notice that before), here are the results for the expected number of points: (Weighted sum of points over the probabilities.)

Code:
3d6, 0 points for sub 8 scores
       mean       |      stddev
------------------+------------------
 24.6766734251838 | 5.42568950335941

4d6, 0 points for sub 8 scores
       mean       |      stddev
------------------+------------------
 30.9231285820757 | 7.70847353687699

3d6, -1 point per for sub 8 scores
       mean       |      stddev
------------------+------------------
 23.8108899861831 | 5.56102133075207

4d6, -1 point per for sub 8 scores
      mean       |      stddev
-----------------+------------------
 30.463321972604 | 7.92268735395706

I got significantly different numbers than on your first data. (You had 30 and 34 for "excluding non-viable combos".) However, your non-viable was that the modifiers had to total to +3 or better, whereas I went with the book definition of re-roll only on less than +1 total. Here's my mean and standard deviation with discard less than +3 total. (With this limit, only 23.91% of 3d6 rolls and 76.89% of 4d6-drop-one rolls qualify as "acceptable".) Still not spot-on with your numbers, but a lot closer.

Code:
3d6, 0 points for sub 8 scores
       mean       |      stddev
------------------+------------------
 27.3361208657579 | 5.08015680167603

4d6, 0 points for sub 8 scores
       mean       |      stddev
------------------+------------------
 32.2416863796721 | 7.19674902367485

3d6, -1 point per for sub 8 scores
      mean       |      stddev
-----------------+------------------
 26.782982833901 | 5.06717086696368

4d6, -1 point per for sub 8 scores
       mean       |      stddev
------------------+------------------
 31.8949012557256 | 7.30335806634089

And the very simple SQL query to get these results, tacked on to what I had before:

Code:
select sum(st_p*st_pt) as mean,
       sum(st_p*(st_pt-(select sum(st_p*st_pt)
                          from stats3d6l_norm))^2)^0.5 as stddev
  from stats3d6l_norm;

select sum(st_p*st_pt) as mean,
       sum(st_p*(st_pt-(select sum(st_p*st_pt)
                          from stats4d6l_norm))^2)^0.5 as stddev
  from stats4d6l_norm;

My stats are a bit rusty, so forgive me if I've incorrectly calculated the weighted standard deviation. I think that's how it should go, though. (Take the sum of (the weight times the difference between the value and the mean) all over the sum of the weights (in this case: 1).)

And thanks for the welcome. :) Too much flaming on any boards for my taste, really, but I can't resist crunching numbers.
 
Last edited:

Remove ads

Top