-1

I'm working on a personal project to develop a stat generator for Tabletop RPGs like D&D. I need the generated numbers to meet the following criteria:

  • The numbers must be within 1 and d (the size of the die).
  • The sum of n random numbers must always be (d+1)n\2.

As an example, if d = 20 and n = 6, the sum should be S = 63 and the random numbers should be between 1 and 20. This would mean an average output of something like [10, 11, 10, 11, 10, 11]

The issue of generating numbers with a constant sum is covered in this post, and I'm quite familiar with generating numbers within a certain range, but I wanted to know if there was a simple algorithm that ensured both of these criteria were met.

  • Maybe dupe: https://stackoverflow.com/questions/288739/generate-random-numbers-uniformly-over-an-entire-range – NathanOliver Mar 08 '18 at 21:09
  • I believe you're looking for this? https://stackoverflow.com/a/19728404/845092 – Mooing Duck Mar 08 '18 at 21:10
  • Could you please add an example of what you are trying to do and what you actually are getting instead? – Bob__ Mar 08 '18 at 21:19
  • Wow - I remember doing this 35 years ago on my C64. How time flies while the fun projects stay the same. – Michael Dorgan Mar 08 '18 at 21:23
  • 2
    Are you aware that statistically the average of the sum of d n-sided dice throws is d*(n+1)/2, not d*n/2? I ask because I suspect that your sum condition relates to this. – Yunnosch Mar 08 '18 at 21:39
  • You need to determine the range of each random number so that afterwards the number of remaining throws does not force you below or above the targeted sum. Probably easiest to do that with a recursive approach. – Yunnosch Mar 08 '18 at 21:45
  • Please improve your question by giving a few sets of sample input and several acceptable outputs for each of them. – Yunnosch Mar 08 '18 at 21:48
  • @Yunnosch Yeah I was getting the impression that a recursive algorithm would be the best solution. – Geoffrey Carlton Mar 08 '18 at 22:46
  • How about an alternative approach: Rolling a random stat to increment by 1, `d - n` times (from a base 1 stat each). –  Mar 08 '18 at 22:56
  • 1
    @Thebluefish I'll actually try that. Would you post this as an answer? – Geoffrey Carlton Mar 08 '18 at 22:59
  • @Yunnosch your sum formula is wrong. Right one is (d+1)*n/2 http://www.mathwords.com/a/arithmetic_series.htm – Severin Pappadeux Mar 09 '18 at 01:44
  • @SeverinPappadeux I think our formulas are identical. I just have accidentally swapped d and n (and defined that in my comment). Seems that n==6 got me on the wrong track. However, I consider both to be better than what OP requires. Assuming that the idea of the sum requirement is statistically based as I suspect. – Yunnosch Mar 09 '18 at 06:05

1 Answers1

0

I'm going to offer pseudo-code, due to having switched from C++ to JS in job duties, I am very rusty.

The idea here is that we are randomly distributing individual points across each stat.

d = 20;
n = 6;
stats = [1, 1, 1, 1, 1, 1];

sum = (d+1)n\2 - n;

int i = 0;
while(i < sum)
{
    // Assuming rand(0,5) produces integer values in range [0..5]
    r = rand(0,5);
    if(stats[r] < 20)
    {
        stats[r]++;
        i++;
    }
}
  • Please post that as an answer, an actual implementation is certainly better. –  Mar 08 '18 at 23:58
  • 1
    @Bob__ your code is wrong, I believe - it calls distribution twice to get a position. You check position once and increment it if it is below – Severin Pappadeux Mar 09 '18 at 01:36
  • This answer doesn't take care of the first constraint. @SeverinPappadeux's code seems correr. Please post that as an answer! Or Thebluefish update your answer to include the test. – Cris Luengo Mar 09 '18 at 03:02
  • @CrisLuengo Good catch. I have updated my pseudo-code accordingly. I still believe the author of *actual usable code* should write a proper answer. –  Mar 09 '18 at 04:46
  • @SeverinPappadeux You are right. I forgot to change that when I added the condition. – Bob__ Mar 09 '18 at 07:44
  • The idea is yours. Feel free to add the corrected code to your answer. – Bob__ Mar 09 '18 at 07:47
  • 1
    I've actually come up with a code sample (that's what this question is about). The link is https://ideone.com/w1GQgc. Feedback is desired. – Geoffrey Carlton Mar 09 '18 at 16:17
  • @SeverinPappadeux Thanks for pointing out that bug. That might have been what was giving me weirdly large numbers before. As for your recommendations, I'm using a vector now but the other stuff I don't know about (I don't know C++ that well). – Geoffrey Carlton Mar 09 '18 at 17:46
  • @GeoffreyCarlton post new snippet and I'll take a look at it again – Severin Pappadeux Mar 09 '18 at 18:29
  • @SeverinPappadeux https://ideone.com/Wb6JGd I have a runtime error but there isn't an error message. I am also working on a version in Rust that I can message you if you want. – Geoffrey Carlton Mar 09 '18 at 19:44
  • @GeoffreyCarlton Here I put code with comments which I think is reasonable approximation to what you might want https://ideone.com/SV2JJR – Severin Pappadeux Mar 09 '18 at 22:34