D&D (and many other RPGs) have ability scores. You are supposed to roll 3d6 for each of them, but most often players want better scores and DMs allow methods that gives better scores.
Each ability has a value in the range 3-18 and it gives a bonus in the range -4 to +4 (for Classic D&D: -3 to +3).
Lets forget about child mortality and assume 3d6 is for those who reach adulthood (without racial ability modifiers). This would give that the average citizen of a fantasy world has a total ability value of 63 (6 x 10.5) and a bonus of 0. It makes sense that the player characters – adventurers – are better than average. Not everyone becomes an adventurer.
If we imagine our D&D town or village not to be so very different from how children grow up today, I think this is a reasonable way to think of it (approximately)
- 1/4: most talented among siblings
- 1/10: most talented kid on the street
- 1/30: most talented in class
- 1/200: most talented in school
- 1/1000: most talented person in a village
- 1/10000: most talented person in town
- … and beyond that, exceptional and rare talent
How does this match ability scores and bonuses?
Ability Score
6 abilities | Better than | |
63 | 47% | |
64 | 53% | |
65 | 58% | |
66 | 63% | |
67 | 68% | |
68 | 73% | Most talented sibling |
69 | 77% | |
70 | 81% | |
71 | 85% | |
72 | 88% | |
73 | Best of 10 | Most talented kid on street |
74 | Best of 14 | |
75 | Best of 18 | |
76 | Best of 24 | |
77 | Best of 32 | |
78 | Best of 45 | |
79 | Best of 64 | |
80 | Best of 92 | |
81 | Best of 136 | |
82 | Best of 205 | Most talented kid in school |
83 | Best of 316 | |
84 | Best of 499 | |
85 | Best of 808 | |
86 | Best of 1341 | Most talented person in village |
87 | Best of 2287 | |
88 | Best of 4009 | |
89 | Best of 7237 | |
90 | Best of 13472 | Most talented person in town |
So, a character with an average score of 15 would have a total of 90. On one hand that is a person who would probably have received some attention for her talents when growing up. On the other hand, it is far from unrealistic that such a person exist.
Bonuses
So what about total bonuses?
Total Bonus 6 Abilities | D&D 5e Better than Best of | D&D Classic Better than Best of |
0 | 45% | 41% |
+1 | 55% | 59% |
+2 | 66% | 75% |
+3 | 75% | 87% |
+4 | 83% | /17 |
+5 | 89% | /45 |
+6 | /15 | /135 |
+7 | /26 | /473 |
+8 | /50 | /1 924 |
+9 | /103 | /9 075 |
+10 | /229 | /49 840 |
+11 | /554 | /320 497 |
+12 | /1 476 | /2 435 080 |
+13 | /4 344 | /22 166 682 |
+14 | /14 251 | /246 959 710 |
+15 | /52 658 | /3 481 658 707 |
+16 | /221 926 | /65 692 122 012 |
+17 | /1 083 583 | /1 846 464 029 852 |
+18 | /6 251 574 | /101 983 687 214 006 |
What I find interesting with this is that it can somehow be connected to the background story of the character. If the character is just an unknown nobody who left her village for adventuring a total bonus of +6 (or +4 for Classic) is on the high side (a best-in-class-character would probably have recieved som attention). If, on the other hand, it is understood that the character is somehow distinguished, priviliged or meant for great deeds, it is not at all unreasonable with a total bonus of +12 (+8 in classic).
Even higher bonuses than that are very possible as long as it is understood that the characters are extraordinarily talented individuals in their society.
Other Rolling Methods
What if the DM allows other methods of rolling (Classic in parenthesis)?
~1/10 bad roll | Average roll | ~1/10 good roll | ||
3d6 | -5 (-2) | +0 (0) | +5 (+2) | Average person |
2d6+6 | +4 (+2) | +8 (+5) | +12 (+8) | Best in large class (~50) |
4d6 drop worst | +1 (+1) | +6 (+4) | +10 (+7) | Best kid on street (~15) |
5d6 drop worst 2 | +5 (+3) | +9 (+6) | +13 (+8) | Best in small school (~100) |
5e: [15, 14, 13, 12, 10, 8] | +5 (+2) | Best sibling | ||
5e: My House Rule | +6 | Best kid on street (~15) |
What this table says, roughly, is that if the player rolls once using this method it is likely she will get the average outcome. Only about 1/10 she will get the bad result from the bad column, or the good result from the good column. It is not at all likely that any of your players will roll a +14 (+9) character (which would correspond to best one of 10 000, or most talented in town) with any of the methods.
Conclusion
From this little experiment, two things came to me.
First, when it comes to NPC, villains and heroes (Conan and Robin Hood if you like) sometimes the stats of such figures are published and they can seem ridiculously good. But that is quite fine. They may be one-in-a-million type of humans who really made a footprint in their time.
Second, most established methods for generating abilities will produce characters that are the most talented among their siblings or perhaps the most talented in their school. For a player to roll anything significantly better there are some ways:
- Very much luck
- Rolling very many times
- Cheating
- Inventing a very powerful method
I think, more than just focusing on the rolling and the methods, it makes sense to talk to they players and ask: who do you reasonably think your character is. If they are the son of Conan, or the only one girl selected by the archmage in the country to study magic because of her extraordinary talents, then very high ability scores are perfectly reasonable.
Source Code
The source code for this is written in JavaScript and runs with Node.js on your computer. It is not quite written to be published, but here it is anyway.
Parameters are hard coded in the top of main().
const objcopy = (obj) => { return JSON.parse(JSON.stringify(obj)); }; const num2prop = (n) => { if ( n < 0 ) return '' + n; if ( 0 < n ) return '+' + n; return ' 0'; }; const numcmp = (a,b) => { return +a - +b; }; const abilities = () => { const ret = {}; let i; for ( i=3 ; i<=18 ; i++ ) ret[i] = 0; return ret; }; const dice3d6 = () => { const ret = abilities(); let i, j, k; for ( i=1;i<=6;i++ ) for ( j=1;j<=6;j++ ) for ( k=1;k<=6;k++ ) ret[i+j+k]++; return ret; }; const dice2d6p6 = () => { const ret = abilities(); let i, j; for ( i=1;i<=6;i++ ) for ( j=1;j<=6;j++ ) ret[i+j+6]++; return ret; }; const dice4d6drop = () => { const ret = abilities(); let i, j, k, l; for ( i=1;i<=6;i++ ) for ( j=1;j<=6;j++ ) for ( k=1;k<=6;k++ ) for ( l=1;l<=6;l++ ) { const a = [i,j,k,l]; a.sort(numcmp); ret[a[1]+a[2]+a[3]]++; } return ret; }; const dice5d6drop = () => { const ret = abilities(); let i, j, k, l, m; for ( i=1;i<=6;i++ ) for ( j=1;j<=6;j++ ) for ( k=1;k<=6;k++ ) for ( l=1;l<=6;l++ ) for ( m=1;m<=6;m++ ) { const a = [i,j,k,l,m]; a.sort(numcmp); ret[a[2]+a[3]+a[4]]++; } return ret; }; const multiplestats = (dist,n) => { let ret = objcopy(dist); let i; for ( i=1 ; i<n ; i++ ) { ret = multiplestats_2(ret,dist); } return ret; }; const multiplestats_2 = (total,one) => { let ret = {}; let t, o, r; for ( t in total ) for ( o in one ) { r = num2prop(+t + +o); if ( !ret[r] ) ret[r] = 0; ret[r] += (total[t] * one[o]); } return ret; }; const bonuses = { 'Classic' : () => { return { '-3' : 0, '-2' : 0, '-1' : 0, ' 0' : 0, '+1' : 0, '+2' : 0, '+3' : 0 }; }, '5e' : () => { return { '-4' : 0, '-3' : 0, '-2' : 0, '-1' : 0, ' 0' : 0, '+1' : 0, '+2' : 0, '+3' : 0, '+4' : 0 }; } }; const ability2bonus = { 'Classic' : (a) => { switch (a) { case 3: return '-3'; case 4: case 5: return '-2'; case 6: case 7: case 8: return '-1'; case 9: case 10: case 11: case 12: return ' 0'; case 13: case 14: case 15: return '+1'; case 16: case 17: return '+2'; case 18: return '+3'; }; }, '5e' : (a) => { switch (a) { case 3: return '-4'; case 4: case 5: return '-3'; case 6: case 7: return '-2'; case 8: case 9: return '-1'; case 10: case 11: return ' 0'; case 12: case 13: return '+1'; case 14: case 15: return '+2'; case 16: case 17: return '+3'; case 18: return '+4'; }; } }; const dist_ability2bonus = (distDice,version) => { const distBonus = bonuses[version](); const getBonus = ability2bonus[version]; let a; for ( a=3 ; a<=18 ; a++ ) distBonus[getBonus(a)] += distDice[a]; return distBonus; }; const toPercent = (dist) => { const ret = {}; const keys = Object.keys(dist).sort(numcmp); let total = 0; let i,k; for ( i=0 ; i<keys.length ; i++ ) { k = keys[i]; total += dist[k]; }; total = 100 / total; for ( i=0 ; i<keys.length ; i++ ) { k = keys[i]; ret[k] = dist[k] * total; }; return ret; }; const accumulate = (dist) => { const ret = {}; const keys = Object.keys(dist).sort(numcmp); let acc = 0; let i,k; for ( i=0 ; i<keys.length ; i++ ) { k = keys[i]; ret[k] = acc; acc += dist[k]; } return ret; }; const rounddecimals = (dist) => { let k,v; for ( k in dist ) { v = dist[k]; if ( !Number.isInteger(v) ) { if ( v < 10 ) dist[k] = '1/' + (100/v).toFixed(0); else if ( 90 < v ) dist[k] = '1/' + (100/(100-v)).toFixed(0); else dist[k] = v.toFixed(1); } } }; const main = () => { //const rolldist = dice3d6(); //const rolldist = dice2d6p6(); //const rolldist = dice4d6drop(); const rolldist = dice5d6drop(); //const bonus = '5e'; const bonus = 'Classic'; const rollcount = 6; const percent = true; const accumulated = true; const round = true; const printall = true; let workdata = [{ dist:rolldist , lbl:'Roll Dist'}]; const last = () => { return workdata[workdata.length-1].dist; }; if ( bonus ) workdata.push({ dist : dist_ability2bonus(last(),bonus), lbl : 'Bonus: ' + bonus }); if ( 1 < rollcount ) workdata.push({ dist : multiplestats(last(),rollcount), lbl : '' + rollcount + ' stats' }); if ( percent ) workdata.push({ dist : toPercent(last()), lbl : 'Percent' }); if ( accumulated ) workdata.push({ dist : accumulate(last()), lbl : 'Accumulated' }); if ( round ) workdata.forEach((w) => { rounddecimals(w.dist) }); if ( printall ) console.log(JSON.stringify(workdata,null,4)); else console.log(JSON.stringify(last,null,4)); }; main();
0 Comments.