Skip to main content
gamedev.net
🔒 Locked

Random Stat Rolling

Started by bugbear Dec 30, 2006 at 1:41 AM 4 replies 1k views
Original Post
bugbear
bugbear
I'm trying to write a stat rolling system in C++ that allows the user to choose to re-roll their stats continuously, but I can not find an algorithm for this. I planned for the limitations on the stats to be: -4 different types -the total of all 4 must equal 30 -4 points is the minimum allowed for a stat -10 points is the maximum allowed For Example: Total points available: 30 Random Roll 1: Stat1 - 10 Stat2 - 7 Stat3 - 9 Stat4 - 4 The overly simplistic code I had originally thought would just roll a random 4-10 for the first 3 stats, then make the remaining points go into stat4. The obvious problem is that you could have a combination that could end up in: Stat1 - 10 Stat1 - 4 Stat2 - 10 Stat2 - 4 Stat3 - 10 Stat3 - 4 Stat4 - 0 Stat4 - 18 Or something similar where the last stat would be higher than 10 or lower than 4. Does anyone have a reference or any comments on how to implement this algorithm?
Icefox
Icefox
Well. A hard-and-clever way would be with each stat you roll, see if it's above or below average. If it's above average, then you have fewer points left over, and you fudge the roll a little to make the next stat lower than average. Statistically speaking, in the end it'll all work out, or at least cause fewer big errors.

More practically, if you end up with three stats of 4 and one of 18, I would just chop the last one down to 10 and allocate 8 more points at random to each stat.

That suggests an even better way of going about the whole thing, if a slightly less efficient way:
Start with a pool of 30 points. Run a loop; for each iteration, check to see if a stat is less than 10, and if it is, add 1 to it and decrement 1 from the pool. Stop the loop when the pool reaches 0.

Slightly janky example code:
int pool = 14;  // 30 - (4*4)int[] stats = {4,4,4,4};while( pool > 0 ) {   int choice = randInt( 4 );   if( stats[choice] == 10 ) continue;   stats[choice]++;   pool--;}
-----http://alopex.liLet's Program: http://youtube.com/user/icefox192
Kylotan
Kylotan
Another way is to set all stats to a level that fits the requirement (eg. 8/7/8/7, or some permutation of), and then repeatedly subtract one point from a random stat and add that point to another stat, making sure not to subtract from a stat of 4 or lower, or to add to one of 10 or above.
GPxz
GPxz
Roll the first.

Then subtract the result by 20, this is will be the minimum number for the second.

Roll the second.

Then, subtract the second roll by 10, this is will be the the minimum for 3rd dice.

Fill the 4th dice with the remainings points.

Example:

1st dice result: 5

30-5=25

25-20=5, 5 is the minimum

2nd dice result: (5<->10) = 8

25-8=17
17-10 = 7, 7 is the minimum

3rd dice result (7<->10) = 10

17-10=7

7 = 4th dice (remaining points)


5+8+10+7=30

If you want, you may then random their order to get a more natural feeling

[Edited by - GPxz on December 30, 2006 12:21:24 PM]
My MSN: gerunbaum@hotmail.com
Vorpy
Vorpy
Allocating or moving around stat points randomly one at a time as said in some of the above replies will result in the stats following something like a normal distribution (or a binomial distribution, which is pretty close). This could be a perfectly valid solution. It means stats near the middle values will be more common than stats near the extremes.

If you want the stats to be uniformly distributed (so low and high stats are as common as medium values) then do this:

1. r = uniformly distributed random value from 0 to 342
2. stat1 = 4 + r%7
3. stat2 = 4 + (r/7)%7
4. stat3 = 4 + (r/49)
5. stat4 = 30 - stat1 - stat2 - stat3
6. If stat4 is not within the valid range, repeat from step 1

There are 343 possible stat combinations for the first 3 stats. This method works by generating a number from 0 to 342 and then converting it to stat values by looking at each of the places in the number when it is written in base 7. The divisions are all integer division. This is a one to one mapping between values and combinations of stats, so each stat combination is equally likely. If an invalid combination is chosen, we repeat until we get a valid combination so that all valid combinations are equally likely.

Hmm...I think this method and the method listed by GPxz could be combined into a more complicated method that would provide a uniform distribution over all of the valid stat combinations with only one randomly generated number needed and no rerolling...

edit: the lowest number that results in valid stats is 20, and the highest is 338, so you can generate the random number in the range [20,338] instead. This suggests that to generate the stats without rerolling, you could go through all the stats this method can generate, place the indices into a lookup table, and pick a random entry in that lookup table. This probably isn't worth actually doing since most of the stats are valid and so the expected number of rolls needed to get a valid set of stats is less than 2...

[Edited by - Vorpy on December 30, 2006 4:04:44 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.