Menu
News
All News
Dungeons & Dragons
Level Up: Advanced 5th Edition
Pathfinder
Starfinder
Warhammer
2d20 System
Year Zero Engine
Industry News
Reviews
Dragon Reflections
White Dwarf Reflections
Columns
Weekly Digests
Weekly News Digest
Freebies, Sales & Bundles
RPG Print News
RPG Crowdfunding News
Game Content
ENterplanetary DimENsions
Mythological Figures
Opinion
Worlds of Design
Peregrine's Nest
RPG Evolution
Other Columns
From the Freelancing Frontline
Monster ENcyclopedia
WotC/TSR Alumni Look Back
4 Hours w/RSD (Ryan Dancey)
The Road to 3E (Jonathan Tweet)
Greenwood's Realms (Ed Greenwood)
Drawmij's TSR (Jim Ward)
Community
Forums & Topics
Forum List
Latest Posts
Forum list
*Dungeons & Dragons
Level Up: Advanced 5th Edition
D&D Older Editions, OSR, & D&D Variants
*TTRPGs General
*Pathfinder & Starfinder
EN Publishing
*Geek Talk & Media
Search forums
Chat/Discord
Resources
Wiki
Pages
Latest activity
Media
New media
New comments
Search media
Downloads
Latest reviews
Search resources
EN Publishing
Store
EN5ider
Adventures in ZEITGEIST
Awfully Cheerful Engine
What's OLD is NEW
Judge Dredd & The Worlds Of 2000AD
War of the Burning Sky
Level Up: Advanced 5E
Events & Releases
Upcoming Events
Private Events
Featured Events
Socials!
EN Publishing
Twitter
BlueSky
Facebook
Instagram
EN World
BlueSky
YouTube
Facebook
Twitter
Twitch
Podcast
Features
Top 5 RPGs Compiled Charts 2004-Present
Adventure Game Industry Market Research Summary (RPGs) V1.0
Ryan Dancey: Acquiring TSR
Q&A With Gary Gygax
D&D Rules FAQs
TSR, WotC, & Paizo: A Comparative History
D&D Pronunciation Guide
Million Dollar TTRPG Kickstarters
Tabletop RPG Podcast Hall of Fame
Eric Noah's Unofficial D&D 3rd Edition News
D&D in the Mainstream
D&D & RPG History
About Morrus
Log in
Register
What's new
Search
Search
Search titles only
By:
Forums & Topics
Forum List
Latest Posts
Forum list
*Dungeons & Dragons
Level Up: Advanced 5th Edition
D&D Older Editions, OSR, & D&D Variants
*TTRPGs General
*Pathfinder & Starfinder
EN Publishing
*Geek Talk & Media
Search forums
Chat/Discord
Menu
Log in
Register
Install the app
Install
Upgrade your account to a Community Supporter account and remove most of the site ads.
Rocket your D&D 5E and Level Up: Advanced 5E games into space! Alpha Star Magazine Is Launching... Right Now!
Community
General Tabletop Discussion
*Dungeons & Dragons
Randomly generating point-buy arrays
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="m00" data-source="post: 7215970" data-attributes="member: 6905775"><p>Hi guys,</p><p></p><p>Here's a simple method for randomly generating ability score arrays of a fixed point-buy value. It's simple enough to use at the table: all it requires is a bunch of 6-sided dice! (I'm sure you can find enough.) It can be adjusted for different point-buy values and for different ability score cost tables, but what I'm presenting is assuming the default point buy described in the PHB.</p><p></p><p>I'm not advocating for or against point buy vs. rolled stats; mostly this is just an interesting statistical exercise!</p><p></p><p><strong>The Algorithm</strong></p><p></p><p><em>Step 0</em>: Decide the value (call it n) of the array and grab that many 6-sided dice and put them in a dice pool.</p><p></p><p><em>Step 1</em>: Roll all n dice in the pool. Count how many are equal to 1. Find the largest cost on the "Ability Score Point Cost" table in the PHB that is equal to or less than this value (call this value x). Assign the corresponding score for value x to the first place in the ability score array. Remove x dice from the dice pool.</p><p></p><p>For example, say there are 2 dice that show a 1, so x=2. The score corresponding to x=2 is 10, so the first score in the array is 10. Then, remove x=2 dice from the dice pool. Alternatively, imagine there are 6 dice that show a 1; in this case, x=5, since 5 is the largest cost that is less than or equal to 6 (the next highest cost is 7, which is larger than 6). In this case, the first score is set to 13 and 5 dice are removed from the pool.</p><p></p><p><em>Step 2</em>: As step 1, but count how many dice are less than or equal to 2. (Remember to keep removing dice from the pool from here on!)</p><p></p><p><em>Step 3</em>: As step 1, but count how many dice are less than or equal to 3.</p><p></p><p><em>Step 4</em>: As step 1, but count how many dice are less than or equal to 4.</p><p></p><p><em>Step 5</em>: As step 1, but count how many dice are less than or equal to 5.</p><p></p><p><em>Step 6</em>: As step 1, but count how many dice are less than or equal to 6. Obviously, this step is not really random, so you can just assign the remaining points to the last slot in the array.</p><p></p><p><em>Step 7</em>: Done!</p><p></p><p>Steps 1-6 will guarantee that the point-buy value of the generated array is exactly equal to 27 (or whatever n you used). The distribution for each spot in the array is different, so if you also want to randomize which scores are assigned to each stat, you should shuffle them up first. I assume that the players assign the scores as they wish, so for the below summary and examples I assume the array has been sorted from high-to-low.</p><p></p><p><strong>Some Statistical Properties</strong></p><p></p><p>Here is a summary of (sorted) outcomes from this distribution (I don't know of an analytical solution for this distribution, so these are all computed from a 1 million simulations):</p><p></p><p>[TABLE="class: grid, width: 500"]</p><p>[TR]</p><p>[TD]<strong>Score</strong>[/TD]</p><p>[TD]<strong>Mean</strong>[/TD]</p><p>[TD]<strong>95% quantile</strong>[/TD]</p><p>[/TR]</p><p>[TR]</p><p>[TD]highest[/TD]</p><p>[TD]14.72[/TD]</p><p>[TD]14-15[/TD]</p><p>[/TR]</p><p>[TR]</p><p>[TD]2[/TD]</p><p>[TD]13.90[/TD]</p><p>[TD]13-15[/TD]</p><p>[/TR]</p><p>[TR]</p><p>[TD]3[/TD]</p><p>[TD]12.99[/TD]</p><p>[TD]12-14[/TD]</p><p>[/TR]</p><p>[TR]</p><p>[TD]4[/TD]</p><p>[TD]11.89[/TD]</p><p>[TD]10-13[/TD]</p><p>[/TR]</p><p>[TR]</p><p>[TD]5[/TD]</p><p>[TD]10.28[/TD]</p><p>[TD]9-12[/TD]</p><p>[/TR]</p><p>[TR]</p><p>[TD]lowest[/TD]</p><p>[TD]8.48[/TD]</p><p>[TD]8-10[/TD]</p><p>[/TR]</p><p>[/TABLE]</p><p></p><p>The overall mean ability score is 12.04. 72% of arrays have at least one score of 15; 59% have at least one score of 8; 93% have at least one 8 or 9.</p><p></p><p>Here are what 20 outcomes look like. Feel free to confirm that their values are all 27!</p><p></p><p>15,14,13,12,10,8</p><p>14,14,14,11,10,9</p><p>15,13,13,12,11,9</p><p>15,14,13,12,10,8</p><p>15,13,13,12,12,8</p><p>15,14,13,11,11,8</p><p>15,13,13,12,12,8</p><p>15,13,13,12,11,9</p><p>14,14,13,12,12,8</p><p>15,14,13,12,10,8</p><p>15,13,13,12,12,8</p><p>15,13,13,12,11,9</p><p>15,14,12,12,11,8</p><p>15,13,13,12,12,8</p><p>14,13,13,12,12,10</p><p>15,14,13,11,11,8</p><p>14,14,13,12,10,10</p><p>15,15,12,11,10,8</p><p>14,14,13,13,11,8</p><p></p><p><strong>Some Code</strong></p><p></p><p>Here is some R code for simulating this process:</p><p></p><p>[CODE]</p><p>############################</p><p># randomly sampling arrays #</p><p>############################</p><p></p><p>ability_scores = 8:15</p><p></p><p>score_cost = c(</p><p> "8" = 0,</p><p> "9" = 1,</p><p> "10" = 2,</p><p> "11" = 3,</p><p> "12" = 4,</p><p> "13" = 5,</p><p> "14" = 7,</p><p> "15" = 9</p><p>)</p><p></p><p>sampleArray = function(ability_scores, score_cost, num_scores, points) {</p><p></p><p> current_points = points</p><p> scores = numeric(num_scores)</p><p> for(i in 1:num_scores) {</p><p></p><p> # 'roll' #points dice</p><p> rolls = sample.int(num_scores, current_points, replace=TRUE)</p><p></p><p> # keep any that are <= i</p><p> num_this_stat = sum(rolls <= i)</p><p></p><p> # find the score that has at most this many points</p><p> this_score = ability_scores[max(which(score_cost <= num_this_stat))]</p><p></p><p> # assign the score to the current array slot</p><p> scores[i] = this_score</p><p></p><p> # decrement the number of dice in the pool</p><p> current_points = current_points - as.numeric(score_cost[as.character(this_score)])</p><p></p><p> }</p><p></p><p> return(sort(scores, decreasing=TRUE))</p><p></p><p>}</p><p></p><p></p><p>sampleArray(ability_scores, score_cost, 6, 27)</p><p>[/CODE]</p></blockquote><p></p>
[QUOTE="m00, post: 7215970, member: 6905775"] Hi guys, Here's a simple method for randomly generating ability score arrays of a fixed point-buy value. It's simple enough to use at the table: all it requires is a bunch of 6-sided dice! (I'm sure you can find enough.) It can be adjusted for different point-buy values and for different ability score cost tables, but what I'm presenting is assuming the default point buy described in the PHB. I'm not advocating for or against point buy vs. rolled stats; mostly this is just an interesting statistical exercise! [B]The Algorithm[/B] [I]Step 0[/I]: Decide the value (call it n) of the array and grab that many 6-sided dice and put them in a dice pool. [I]Step 1[/I]: Roll all n dice in the pool. Count how many are equal to 1. Find the largest cost on the "Ability Score Point Cost" table in the PHB that is equal to or less than this value (call this value x). Assign the corresponding score for value x to the first place in the ability score array. Remove x dice from the dice pool. For example, say there are 2 dice that show a 1, so x=2. The score corresponding to x=2 is 10, so the first score in the array is 10. Then, remove x=2 dice from the dice pool. Alternatively, imagine there are 6 dice that show a 1; in this case, x=5, since 5 is the largest cost that is less than or equal to 6 (the next highest cost is 7, which is larger than 6). In this case, the first score is set to 13 and 5 dice are removed from the pool. [I]Step 2[/I]: As step 1, but count how many dice are less than or equal to 2. (Remember to keep removing dice from the pool from here on!) [I]Step 3[/I]: As step 1, but count how many dice are less than or equal to 3. [I]Step 4[/I]: As step 1, but count how many dice are less than or equal to 4. [I]Step 5[/I]: As step 1, but count how many dice are less than or equal to 5. [I]Step 6[/I]: As step 1, but count how many dice are less than or equal to 6. Obviously, this step is not really random, so you can just assign the remaining points to the last slot in the array. [I]Step 7[/I]: Done! Steps 1-6 will guarantee that the point-buy value of the generated array is exactly equal to 27 (or whatever n you used). The distribution for each spot in the array is different, so if you also want to randomize which scores are assigned to each stat, you should shuffle them up first. I assume that the players assign the scores as they wish, so for the below summary and examples I assume the array has been sorted from high-to-low. [B]Some Statistical Properties[/B] Here is a summary of (sorted) outcomes from this distribution (I don't know of an analytical solution for this distribution, so these are all computed from a 1 million simulations): [TABLE="class: grid, width: 500"] [TR] [TD][B]Score[/B][/TD] [TD][B]Mean[/B][/TD] [TD][B]95% quantile[/B][/TD] [/TR] [TR] [TD]highest[/TD] [TD]14.72[/TD] [TD]14-15[/TD] [/TR] [TR] [TD]2[/TD] [TD]13.90[/TD] [TD]13-15[/TD] [/TR] [TR] [TD]3[/TD] [TD]12.99[/TD] [TD]12-14[/TD] [/TR] [TR] [TD]4[/TD] [TD]11.89[/TD] [TD]10-13[/TD] [/TR] [TR] [TD]5[/TD] [TD]10.28[/TD] [TD]9-12[/TD] [/TR] [TR] [TD]lowest[/TD] [TD]8.48[/TD] [TD]8-10[/TD] [/TR] [/TABLE] The overall mean ability score is 12.04. 72% of arrays have at least one score of 15; 59% have at least one score of 8; 93% have at least one 8 or 9. Here are what 20 outcomes look like. Feel free to confirm that their values are all 27! 15,14,13,12,10,8 14,14,14,11,10,9 15,13,13,12,11,9 15,14,13,12,10,8 15,13,13,12,12,8 15,14,13,11,11,8 15,13,13,12,12,8 15,13,13,12,11,9 14,14,13,12,12,8 15,14,13,12,10,8 15,13,13,12,12,8 15,13,13,12,11,9 15,14,12,12,11,8 15,13,13,12,12,8 14,13,13,12,12,10 15,14,13,11,11,8 14,14,13,12,10,10 15,15,12,11,10,8 14,14,13,13,11,8 [B]Some Code[/B] Here is some R code for simulating this process: [CODE] ############################ # randomly sampling arrays # ############################ ability_scores = 8:15 score_cost = c( "8" = 0, "9" = 1, "10" = 2, "11" = 3, "12" = 4, "13" = 5, "14" = 7, "15" = 9 ) sampleArray = function(ability_scores, score_cost, num_scores, points) { current_points = points scores = numeric(num_scores) for(i in 1:num_scores) { # 'roll' #points dice rolls = sample.int(num_scores, current_points, replace=TRUE) # keep any that are <= i num_this_stat = sum(rolls <= i) # find the score that has at most this many points this_score = ability_scores[max(which(score_cost <= num_this_stat))] # assign the score to the current array slot scores[i] = this_score # decrement the number of dice in the pool current_points = current_points - as.numeric(score_cost[as.character(this_score)]) } return(sort(scores, decreasing=TRUE)) } sampleArray(ability_scores, score_cost, 6, 27) [/CODE] [/QUOTE]
Insert quotes…
Verification
Post reply
Community
General Tabletop Discussion
*Dungeons & Dragons
Randomly generating point-buy arrays
Top