I need to generate discrete integer variables that each have meaning, so does their sum. I am essentially looking to partition a normal distribution into n bins. You can think of them as stats. The total obviously matters, but if we always equally distribute them, an item with higher total stats would be strictly better than one with lower total. We can't have that. Therefore, I had the idea to "reward" the player with bigger variation if the generated sum is low. I just do not know how to achieve this.

Generating a total value from a normal distribution is easy. However, I don't know how to distribute them in the way I described. Below are methods I have tried:

  1. Start with an equal partition, for a random number of steps, increase a random stat by 1 and decrease another by 1. Problem: the values always seem to be stuck near the beginning.

  2. Start with an equal partition that is higher than the desired average. For a random number of steps, increase a random stat by 1 an decrease all others by 1. Problem: this seems to just universally lower all the stats without producing the variation I wanted. The sum total is also not normally distributed.

  3. Randomly generate the first (n-1) variables from normal distributions, and fix the last one. Problem: this produces very predictable results. Each sample looks more or less the same.

Is there an algorithm that achieves this except just to generate many samples until it has the desired distribution?

  • \$\begingroup\$ Keep in mind that all stats are not equal as well. If you simply add or substract one, stats like life gain, movementspeed or crit chance are different affected than hp, mana or strength. \$\endgroup\$
    – Zibelas
    Apr 23, 2023 at 14:48
  • \$\begingroup\$ Zibelas I know that. "Stats" is just an explanation here. There is a balance mechanism elsewhere so this function (and this question) deals with equal numbers only. \$\endgroup\$
    – Amilia C
    Apr 23, 2023 at 14:53
  • 2
    \$\begingroup\$ What rule says that 40/40/60/60 "should" have the same weight as 35/50/50/65? These both have the same sum, so the player should get a similar "reward" in terms of the range of variation, but they differ here (both in terms of min-max range and sample variance). If you want a rule that favours wider spreads for lower sums, shouldn't one of these two have a greater weight than the other (depending on whether a sum of 200 is deemed "high" or "low")? \$\endgroup\$
    – DMGregory
    Apr 23, 2023 at 15:50

2 Answers 2


Differently sized dice

Disclaimer: this is only a partial answer since it does not guarantee high variance outcomes for low sums and also does not guarantee the same chance for all results with the same variance. However it might still be suitable for the described problem.

Basic principle

if we look into the results of random numbers generated through dice, using multiple 4d6 - 4 results in values between 0 and 20 with much smaller variance than using a single d20 (which would be 1 to 20 but close enough for demonstration)

how to use this for your problem

If your generated sum is high, use "small dice" to determine how much to add to a bucket in each step, if the sum is low, use "bigger dice" for each step, until your desired total is reached.

pseudo code

targetSum diceSize


while(targetSum > sum(buckets)){
   buckets[random] += randomBetween(1,diceSize)

For items with a high generated targetSum choose a small diceSize (1 or 2) and scale the dice size with decreasing targetSum (for example up to 40). For the exact formular to convert targetSum into diceSize you will need to try out what works best for you.


reverse preprocessing

In preprocessing for machine learning it is usual to scale values so they have a deviation of 1 and a mean of 0. We can reverse these steps to achive a solution to your problem.

Step 1:
decide on a total target sum: targetSum and a targetDeviation that you want to achive. You can decide for yourself how these two values exaclty correlate but from your questions high targetSums should come with low targetDeviation and vice versa. As a derived value also calculate your targetMean = targetSum / numberOfBuckets

Step 2:
generate a floating point number between 0 and 1 for each bucket individually.

Step 3:
calculate the mean and substract it from each bucket

Step 4:
calculate the deviation and divide each bucket by it

Step 5:
multiply each bucket by your targetDeviation

Step 6: add targetMean to each bucket

Now you have all buckets filled in a way that their sum is equal to your generated total value and their deviation is equal to the input deviation. (of course there will be rounding errors but if your stats have a sufficient range like 0-100 these will be marginal)


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .