I am making a Diablo-like game and I want to randomly generate the stats of the loot that gets dropped. I'll use "damage per second" as an example. I've filled a spreadsheet with two columns of numbers. The first column is the level, the second column is the average damage per second. So when you look at a row of the spreadsheet it'll say something like, "at level 50, the average damage per second should be 100". From here there are many branches I could take:

  1. Decide that the range values are not weighted. In which case, all you have to do is find a range below and above the average and randomly generate numbers in that range. For example, I'll arbitrarily decide that 20% is a good number and then the random range goes from 80 to 120. AFAIK, as long as that same % is added and subtracted to the number, then it should average out to 100.
  2. Decide that the range values are weighted. In this case, I want the higher stats to be more rare than the lower stats. So if the range were between 10 to 20, it would be more common to get a 10 than a 20. But, I think that there are other unknowns I have to solve first. Like, I probably need to figure out how I want the numbers weighted. I know how to set up weighted random values. But I don't know how to guarantee the average of the values is the number I want. How would I figure that out?

1) Seems way easier to code and balance. But I'm wondering if it's a poor choice for a loot system. If all the popular games out there use this, that's good enough for me and I'd consider that an answer.

On the other hand, if they use something like 2), I'd like to figure out how I can use the average as input to get the weighted range as output.

And if there's a 3) I haven't thought of that most games use, I'd like to hear about that.

  • 1
    \$\begingroup\$ For 2, you could sample your values from a limited normal distribution. That way, you would be guaranteed to have a set mean and variance that you define, and extreme values would be less likely than those closer to the mean. This seems better to me than 1 which I assume would be uniformly sampled. \$\endgroup\$ – Jemmy Sep 21 '13 at 23:34
  • \$\begingroup\$ @Jeremy Would you be able to show me how? My research shows that normal distribution is around 0. How could I make it around my average? \$\endgroup\$ – Daniel Kaplan Sep 21 '13 at 23:40
  • \$\begingroup\$ A normal distribution is defined entirely by its mean and variance. The standard normal has mean 0 and variance 1. If, for instance, you wanted your values to have mean 100 and for 95% of all samples to be between 90 and 110, you could define the mean to be 100 and the variance to be 10^2/3^2 (since 95% of all values in the normal distribution lie within 3 standard deviations (sqrt(variance)) from the mean. I know python has a normal distribution in their random module. You define it as random.gauss(mean, standard deviation). en.wikipedia.org/wiki/Normal_distribution \$\endgroup\$ – Jemmy Sep 21 '13 at 23:49
  • \$\begingroup\$ That wiki article gives the explicit formula for the pdf of the normal. \$\endgroup\$ – Jemmy Sep 21 '13 at 23:49
  • \$\begingroup\$ @Jeremy an answer sould be better than comments. \$\endgroup\$ – ashes999 Sep 22 '13 at 10:38

For 2, you could sample your values from a limited normal distribution. That way, you would be guaranteed to have a set mean and variance that you define, and extreme values would be less likely than those closer to the mean. This seems better to me than 1 which I assume would be uniformly sampled.

I use Python most, so the numpy docs give a good overview of how to use the normal distribution: http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.normal.html#numpy.random.normal

Of course, with a normal distribution, it's possible (but extremely unlikely) to get extreme values, so you would want to put explicit bounds on it, like:

while s<90 or s>100:
    s = np.random.normal(mu, sigma)

I'm not a programmer by nature, so maybe there's a better way to do that, but hopefully you get the picture. Hopefully you would play around with the variance enough to where that loop wouldn't run more than a couple times.

  • \$\begingroup\$ If I had that library available, I'd use it. But this is JavaScript, unfortunately. I had to build my own approximation which was surprisingly easy to do. See my answer provided here. \$\endgroup\$ – Daniel Kaplan Sep 24 '13 at 20:54

If you decide to go with 1, I would strongly encourage you to use a standard random deviation. To do this, you would have your mean (average) value for every level and then the standard deviation for everyone level. You could really just use the same deviation for all of the different levels if you wanted to. 95% of the random values would be between your mean+- your deviation. This would give you control over what the 'normal' values would be and still allow 'rare' items buffs. You could even determine buffs such as 'legendary' or 'great' by how many deviations to item is from the mean.

This question should tell you all you need to know about generating the numbers based on a standard deviation.

Wikipedia on Standard Deviation Wikipedia on Box-Muller transform

  • \$\begingroup\$ Would you mind showing me an example in pseudo code? \$\endgroup\$ – Daniel Kaplan Sep 22 '13 at 3:29
  • \$\begingroup\$ This is what Jeremy mentioned in his com ment. \$\endgroup\$ – ashes999 Sep 22 '13 at 10:37

I found an answer here that gives a really easy to understand algorithm that can be used. He says himself it's not correct, but rather an approximation, but that's good enough for my needs. I'd like to know if this is an accurate approximation. I'll inline a summary in case it goes down some time:

Random numbers are an essential part of computer games and simulations. Functions in most software development tools output random numbers with uniform distribution. Simulations often need random numbers in normal distribution. An easy way to approximate normal distribution is to add three random numbers:

G = X + X + X

X = a uniformly distributed random number between -1 and 1.

G ~ a standard normal random number.

To adjust the result for your needs, just multiply by your desired standard deviation and add your desired mean.

R = Gσ + μ
  • \$\begingroup\$ You don't need an accurate approximation of the normal distribution. You need a probability distribution that fits your game. The distribution outlined here is probably a better fit than the one it approximates. \$\endgroup\$ – Marcks Thomas Sep 24 '13 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.