Need a Programmer for Number-crunching

genshou

First Post
Hello everyone.

I have been thinking recently about heroic characters vs. the common rabble, specifically how many people are born with "heroic" stats and how many have to aspire to that level. This is based on one of my house rules, which was written with the premise that characters with higher ability scores are more likely to survive to high levels, and thus higher-level characters should have higher ability scores regardless of what they started with (high-level NPCs typically represent those who started with high scores and thus had the potential to reach that level, whereas high-level PCs might just be those who rose to the challenge of heroism and grew stronger as a result). I want to have a concrete set of numbers that show how many heroes are born, and how many have to be made (or never end up becoming a hero at all).

This is where you come in. I know little about statistics or programming, but I need some pretty beefy number-crunching to happen. So, I'm hoping someone would be nice enough to whip up a little programming genius for me.

When a normal person is randomly generated, their ability scores are 3d6 rolled 6 times in order. PCs are just people like these, but since we want to make heroes, we roll differently to "bias" the results. I want to find out how many people generated using the more hardcore method end up "biased", in the kind of detail you have to have a number fetish to enjoy reading about. :blush:

Each ability score has 6^3 possible rolled outcomes, and with 6 ability scores, that's 6^18, or 101,559,956,668,416 different possible sets of ability scores that can be rolled. Painstakingly generating all 101 trillion of these is utterly ridiculous, so instead, I would like you to please randomly generate a healthy population of 4 million persons (a small kingdom with one metropolis, using my demographics rolls) and store their ability scores as sets of data for later analysis. The analysis is as follows:
  • Determine the total point-buy value of each person and connect it to their set of data. Use the link to my house rule above for the point-buy value of scores below 8.
  • Flag each set of data associated with a person with a variable equal to the highest ability score they ended up with.
  • Calculate the total ability modifiers of each set, and flag each set with a boolean variable. If the total modifiers are -3 or below, and/or the highest ability score is less than 12, make the variable "False", otherwise, "True".
Now, for the data output:
I want to know:
  • The total number of people at each total point-buy value (ignoring values with 0 matches).
  • The total number of people whose highest ability score matches each value from 3 to 18 (ignoring values with 0 matches).
  • The total number of people whose total point-buy is greater than or equal to 25, and whose highest ability score is 15 or greater.
  • Recalculate the results of the first and second bulletted items in this list using only sets with the boolean value equal to "True".
Complicated, I know, but I really like having these kinds of numbers around to give me an idea of just how rare certain kinds of characters are. I'd appreciate any help to this end.
 

log in or register to remove this ad

How soon you wanting this, sounds like something I could do but not right now as I'm at work
 

This is actually not that hard to set up a program for - the only "killer" is going to be doing analytics on that many rolls.

I'll tackle next week.
 

Painstakingly generating all 101 trillion of these is utterly ridiculous, so instead, I would like you to please randomly generate a healthy population of 4 million persons (a small kingdom with one metropolis, using my demographics rolls) and store their ability scores as sets of data for later analysis.

Minor note, there's no reason to store all those people. Instead, generate a person, run the math, increment the relevant counters, then generate the next person. Run the loop till you get bored.
 

I wrote a perl script to do this. It would be good if someone else also wrote a program so we could compare the results and make sure they are reasonably close.

"Population" refers to the entire population.
"Hero" refers to people with total stat mods >= -2 and highest ability score >= 12.
"Awesome" refers to people with a point buy of at least 25 and a highest ability score of at least 15.
Blank lines mean there were 0 people for that result.

Population size: 4 million.

Code:
Population Point Buy Spread
-40 - 1
-39 - 
-38 - 
-37 - 
-36 - 
-35 - 1
-34 - 2
-33 - 4
-32 - 4
-31 - 11
-30 - 9
-29 - 16
-28 - 18
-27 - 23
-26 - 37
-25 - 65
-24 - 76
-23 - 113
-22 - 143
-21 - 216
-20 - 306
-19 - 413
-18 - 552
-17 - 727
-16 - 993
-15 - 1343
-14 - 1717
-13 - 2281
-12 - 3112
-11 - 3919
-10 - 5190
-9 - 6468
-8 - 8067
-7 - 10395
-6 - 13140
-5 - 16307
-4 - 19963
-3 - 24751
-2 - 30242
-1 - 36143
0 - 43282
1 - 50780
2 - 59828
3 - 69799
4 - 80266
5 - 91865
6 - 103699
7 - 116036
8 - 128338
9 - 140036
10 - 151264
11 - 161225
12 - 169501
13 - 175713
14 - 180009
15 - 181194
16 - 180192
17 - 175364
18 - 169209
19 - 161491
20 - 151708
21 - 139851
22 - 128473
23 - 115822
24 - 104404
25 - 92063
26 - 81194
27 - 69862
28 - 59897
29 - 51069
30 - 43850
31 - 36129
32 - 30053
33 - 24664
34 - 20000
35 - 16049
36 - 13029
37 - 10320
38 - 8285
39 - 6382
40 - 5046
41 - 3954
42 - 3026
43 - 2354
44 - 1740
45 - 1309
46 - 959
47 - 705
48 - 529
49 - 378
50 - 316
51 - 223
52 - 160
53 - 87
54 - 73
55 - 62
56 - 41
57 - 24
58 - 20
59 - 13
60 - 6
61 - 4
62 - 4
63 - 2
64 - 
65 - 1
66 - 
67 - 1
******************************************
Population Highest Stat Spread
6 - 2
7 - 71
8 - 1160
9 - 9843
10 - 51294
11 - 176263
12 - 422387
13 - 722583
14 - 849662
15 - 776391
16 - 566644
17 - 313715
18 - 109985
******************************************
Population Number of Awesome People 548856
******************************************
Hero Point Buy Spread
-5 - 10
-4 - 25
-3 - 146
-2 - 218
-1 - 800
0 - 1720
1 - 6306
2 - 9712
3 - 20824
4 - 28441
5 - 50322
6 - 75480
7 - 100505
8 - 114818
9 - 128680
10 - 142021
11 - 154390
12 - 164566
13 - 172734
14 - 178362
15 - 180422
16 - 179867
17 - 175266
18 - 169191
19 - 161491
20 - 151708
21 - 139851
22 - 128473
23 - 115822
24 - 104404
25 - 92063
26 - 81194
27 - 69862
28 - 59897
29 - 51069
30 - 43850
31 - 36129
32 - 30053
33 - 24664
34 - 20000
35 - 16049
36 - 13029
37 - 10320
38 - 8285
39 - 6382
40 - 5046
41 - 3954
42 - 3026
43 - 2354
44 - 1740
45 - 1309
46 - 959
47 - 705
48 - 529
49 - 378
50 - 316
51 - 223
52 - 160
53 - 87
54 - 73
55 - 62
56 - 41
57 - 24
58 - 20
59 - 13
60 - 6
61 - 4
62 - 4
63 - 2
64 - 
65 - 1
66 - 
67 - 1
******************************************
Hero Highest Stat Spread
12 - 296835
13 - 624652
14 - 794066
15 - 750077
16 - 555498
17 - 310127
18 - 109203
******************************************
Hero Number of Awesome People 548856

So, about 13.72% of the people in this sample are Awesome.
 
Last edited:

It wouldn't let me put this in code tags, sorry there's no indentation. I can email the code to anyone who is interested in something readable.


#!/usr/bin/perl

use strict;
use Getopt::Long;

my $size;
my $verbose;

my @stat_costs = qw[-11 -8 -5 -3 -1 0 1 2 3 4 5 6 8 10 13 16];

my @pop_point_buy;
my @pop_highest_stat;
my $pop_awesome;
my @hero_highest_stat;
my $hero_awesome;

GetOptions (
"s=s" => \$size,
"v" => \$verbose,
);

sub roll_d6_minus_1 {
return int(rand(6));
}

sub roll_3d6_minus_3 {
return &roll_d6_minus_1 + &roll_d6_minus_1 + &roll_d6_minus_1;
}

sub char_gen {
my @stats;
my $point_buy = 0;
my $highest_stat = 0;
my $net_modifiers = 0;

for (my $i = 0; $i < 6; $i++) {
$stats[$i] = &roll_3d6_minus_3; #roll this stat

$point_buy += $stat_costs[$stats[$i]]; #adjust point buy

if ($stats[$i] > $highest_stat){ #update highest ability score
$highest_stat = $stats[$i];
}

$net_modifiers += ($stats[$i] + 1) / 2 - 4; #adjust total ability modifiers
}

$pop_point_buy[$point_buy + 66]++; #adjust apropriate point-buy value tracker
$pop_highest_stat[$highest_stat]++; #adjust apropriate highest-stat value tracker
$pop_awesome++ if ($point_buy >= 25 && $highest_stat >= 12); #is this guy awesome?

if ($net_modifiers > -3 && $highest_stat >= 9) { #is this guy adventuring material?
$hero_highest_stat[$highest_stat]++; #adjust apropriate highest-stat value tracker for heroes
$hero_awesome++ if ($point_buy >= 25 && $highest_stat >= 12); #is this guy awesome?
}

if ($verbose) {
print $stats[0] + 3, " ", $stats[1] + 3, " ", $stats[2] + 3, " ", $stats[3] + 3, " ", $stats[4] + 3, " ", $stats[5] + 3, " ","\n";
}
}


sub main {
srand;

for (my $i = 0; $i < $size; $i++) {
&char_gen;
}

print "Population Point Buy Spread\n";
for (my $i = 0; $i < $#pop_point_buy + 1; $i++) {
print ($i - 66, " - ", $pop_point_buy[$i], "\n");
}

print "******************************************\n";
print "Population Highest Stat Spread\n";
for (my $i = 0; $i < $#pop_highest_stat + 1; $i++) {
print ($i + 3, " - ", $pop_highest_stat[$i], "\n");
}

print "******************************************\n";
print "Population Number of Awesome People $pop_awesome\n";

print "******************************************\n";
print "Hero Highest Stat Spread\n";
for (my $i = 0; $i < $#hero_highest_stat + 1; $i++) {
print ($i + 3, " - ", $hero_highest_stat[$i], "\n");
}

print "******************************************\n";
print "Hero Number of Awesome People $hero_awesome\n";
}

&main;
 
Last edited:

Here are my results:

Code:
Point buy values
Value    Count    Percent    Cum.Pct.
-41     1     0.0     0.0
-36     3     0.0     0.0
-35     2     0.0     0.0
-33     3     0.0     0.0
-32     6     0.0     0.0
-31     7     0.0     0.0
-30     10     0.0     0.0
-29     16     0.0     0.0
-28     27     0.0     0.0
-27     28     0.0     0.0
-26     44     0.0     0.0
-25     54     0.0     0.01
-24     85     0.0     0.01
-23     99     0.0     0.01
-22     159     0.0     0.01
-21     218     0.01     0.02
-20     302     0.01     0.03
-19     404     0.01     0.04
-18     531     0.01     0.05
-17     740     0.02     0.07
-16     1023     0.03     0.09
-15     1317     0.03     0.13
-14     1695     0.04     0.17
-13     2272     0.06     0.23
-12     3021     0.08     0.3
-11     3843     0.1     0.4
-10     5027     0.13     0.52
-9     6531     0.16     0.69
-8     8364     0.21     0.9
-7     10415     0.26     1.16
-6     13021     0.33     1.48
-5     16306     0.41     1.89
-4     20084     0.5     2.39
-3     24705     0.62     3.01
-2     29883     0.75     3.76
-1     36296     0.91     4.66
0     43077     1.08     5.74
1     51137     1.28     7.02
2     60084     1.5     8.52
3     69725     1.74     10.26
4     80632     2.02     12.28
5     91437     2.29     14.57
6     103765     2.59     17.16
7     116157     2.9     20.06
8     128402     3.21     23.27
9     140074     3.5     26.78
10     151104     3.78     30.55
11     161749     4.04     34.6
12     169636     4.24     38.84
13     176074     4.4     43.24
14     179678     4.49     47.73
15     180862     4.52     52.25
16     179483     4.49     56.74
17     175147     4.38     61.12
18     169864     4.25     65.37
19     160886     4.02     69.39
20     151461     3.79     73.17
21     140431     3.51     76.69
22     128661     3.22     79.9
23     115554     2.89     82.79
24     104129     2.6     85.39
25     92106     2.3     87.7
26     80579     2.01     89.71
27     69892     1.75     91.46
28     60149     1.5     92.96
29     50985     1.27     94.24
30     43923     1.1     95.33
31     36338     0.91     96.24
32     30129     0.75     97.0
33     24400     0.61     97.61
34     20056     0.5     98.11
35     16376     0.41     98.52
36     13105     0.33     98.84
37     10376     0.26     99.1
38     8429     0.21     99.31
39     6324     0.16     99.47
40     4897     0.12     99.6
41     3826     0.1     99.69
42     3005     0.08     99.77
43     2395     0.06     99.83
44     1808     0.05     99.87
45     1328     0.03     99.9
46     1016     0.03     99.93
47     775     0.02     99.95
48     540     0.01     99.96
49     413     0.01     99.97
50     284     0.01     99.98
51     256     0.01     99.99
52     168     0.0     99.99
53     135     0.0     99.99
54     69     0.0     100.0
55     57     0.0     100.0
56     36     0.0     100.0
57     27     0.0     100.0
58     20     0.0     100.0
59     10     0.0     100.0
60     5     0.0     100.0
61     3     0.0     100.0
62     3     0.0     100.0
63     2     0.0     100.0
64     2     0.0     100.0
68     1     0.0     100.0
69     1     0.0     100.0
------------------------------
Maximum ability scores
Value    Count    Percent    Cum.Pct.
6     1     0.0     0.0
7     75     0.0     0.0
8     1168     0.03     0.03
9     9869     0.25     0.28
10     51520     1.29     1.57
11     176154     4.4     5.97
12     422576     10.56     16.53
13     724012     18.1     34.63
14     847412     21.19     55.82
15     776595     19.41     75.23
16     565811     14.15     89.38
17     314908     7.87     97.25
18     109899     2.75     100.0
------------------------------
Point buy values (heroic only)
Value    Count    Percent    Cum.Pct.
-1     10     0.0     0.0
0     38     0.0     0.0
1     123     0.0     0.01
2     292     0.01     0.02
3     1106     0.04     0.05
4     3474     0.12     0.17
5     7742     0.26     0.43
6     14493     0.49     0.91
7     22992     0.77     1.68
8     40153     1.34     3.03
9     67609     2.26     5.29
10     100440     3.36     8.66
11     134027     4.49     13.15
12     157042     5.26     18.41
13     170185     5.7     24.11
14     176982     5.93     30.04
15     179566     6.01     36.05
16     179001     6.0     42.05
17     175014     5.86     47.91
18     169842     5.69     53.6
19     160886     5.39     58.99
20     151461     5.07     64.06
21     140431     4.7     68.76
22     128661     4.31     73.07
23     115554     3.87     76.94
24     104129     3.49     80.43
25     92106     3.09     83.52
26     80579     2.7     86.21
27     69892     2.34     88.56
28     60149     2.01     90.57
29     50985     1.71     92.28
30     43923     1.47     93.75
31     36338     1.22     94.97
32     30129     1.01     95.98
33     24400     0.82     96.79
34     20056     0.67     97.46
35     16376     0.55     98.01
36     13105     0.44     98.45
37     10376     0.35     98.8
38     8429     0.28     99.08
39     6324     0.21     99.29
40     4897     0.16     99.46
41     3826     0.13     99.59
42     3005     0.1     99.69
43     2395     0.08     99.77
44     1808     0.06     99.83
45     1328     0.04     99.87
46     1016     0.03     99.91
47     775     0.03     99.93
48     540     0.02     99.95
49     413     0.01     99.96
50     284     0.01     99.97
51     256     0.01     99.98
52     168     0.01     99.99
53     135     0.0     99.99
54     69     0.0     99.99
55     57     0.0     100.0
56     36     0.0     100.0
57     27     0.0     100.0
58     20     0.0     100.0
59     10     0.0     100.0
60     5     0.0     100.0
61     3     0.0     100.0
62     3     0.0     100.0
63     2     0.0     100.0
64     2     0.0     100.0
68     1     0.0     100.0
69     1     0.0     100.0
------------------------------
Maximum ability scores (heroic only)
Value    Count    Percent    Cum.Pct.
12     195907     6.56     6.56
13     462138     15.48     22.04
14     709184     23.75     45.8
15     680153     22.78     68.58
16     532534     17.84     86.41
17     298449     10.0     96.41
18     107137     3.59     100.0
------------------------------
Number heroic: 2985502
Percentage heroic: 74.64
Number superheroic: 549399
Percentage superheroic: 13.73

Notes about terminology:

The term "heroic" means that the "boolean variable" you mentioned is true. It is equivalent to "hero" in Abisashi's post.

The term "superheroic" means that the point buy is at least 25 and highest ability score is at least 15. It is equivalent to "awesome" in Abisashi's post.
 

Alex 319 got almost double the number of super-heroic people that I did, I wouldn't expect the results to vary that much. I'll see if I can figure out what happened.

Problem fixed, see below for info. I updated my post above.
 
Last edited:

for (my $i = 0; $i < 5; $i++) {
$stats[$i] = &roll_3d6_minus_3; #roll this stat

$point_buy += $stat_costs[$stats[$i]]; #adjust point buy

if ($stats[$i] > $highest_stat){ #update highest ability score
$highest_stat = $stats[$i];
}

----

Here is the problem. You are only rolling 5 stats, not 6.
 


Remove ads

Top