# How do I make hit damage a Gaussian distribution centered around a value?

I'd like my character's attacks to on average 10 damage, but to vary anywhere from 0 to 20.

Instead of a linear spread, I would like a normal distribution, so most of their hits are between 10-15, but they can still hit between 0-20. How can I do this?

I am using PHP.

Second (harder) aproach. I used that in c# to get a gaussian distribution (link) i think you can easly traslate in php.

private double  nextGaussian(double mean,double variance ) {
// https://stackoverflow.com/questions/218060/random-gaussian-variables

//with mean = 0.5 and variance = 0.5 we get uniform distribution over [0..1]

double u1 = r.NextDouble(); //these are uniform(0,1) random doubles
double u2 = r.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
//Math.Sin( Math.PI * u2); //random normal(0,1)
double randNormal =
mean + variance * randStdNormal; //random normal(mean,stdDev^2)

return randNormal;

}


You can try

 damage = nextGaussian(0.5, 0.2) *MAXDAMAGE ;


and play with second parameter of nextGaussian (variance).

Here follow a test I made distributing points over x axe changing the variance :

An easy way is roll 4 dice (6 faces) add them , then subtract 4. You get 0..20 with more distribution in the middle. Or 2 * 12 FACE dice - 2.

• surely 5 * 4d rolls would be better due to no subtraction, and with a higher number of rolls (granted its only one) the distribution becomes more pronounced (less likely to get those extremes). 2 12d rolls would result in large variance in the numbers, whilst this still leans in favor of the median numbers, it would also allow the extremes to be more likely. I prefer your other answer as numbers, however this stands as a good visual representation Commented Sep 8, 2015 at 10:04
• you're right but with 5 * 4d you miss 0..3 values requested by Thomas in his question Commented Sep 8, 2015 at 10:07
• You are correct, using any dice system without subtraction would eliminate any number fewer than the number of dice, therefore the subtraction is a necessary stage in order to include those numbers Commented Sep 8, 2015 at 10:40

Would personally suggest the following KISS technique to convert uniform distribution to slanted distribution:

Randomly (uniformly), draw a number x between 0 and 1. Now raise x by some const predetermined p value (likely) in the range between 1.1 to 7. The larger p is, the more slanted (and less likely to hit extreme results) it'll be. Lets call x by the power of p our offset coefficient. Now randomly pick a sign (i.e plus or minus [negative, positive]). OK, the center of your desired range is 10 == the max offset from the center.

// Essentially
// center +/- offset = min/max
// 10 - 10 = 0
// 10 + 10 = 20

//  So now, you simply do in pseudo code:
small_buffer = ~ 0.1 * range;
rand   = randomize_float_between(0, 1);
coefficient = pow(rand, p);
sign   = pick_one_of_these(-1, 1);
result = center + sign * coefficient * (offset + small_buffer);
result = max(0, min(result, 20)); // Keep it in range


This is the simplest way to get and tweak the effect you are looking for.

• +1 Good alternative. A mathematically correct Gaussian distribution is difficult to tune right, expensive to calculate, and overkill for most games.
– Anko
Commented Sep 8, 2015 at 15:23
• @Anko thanks, any monotonously increasing function from (0, 1) to (0, 1) should work (assuming it's starts with f(0) = 0 and ends with f(1) = 1). For instance, instead of x^p we could do (2^(x * 10) - 1) / 1023 for a possibly more extreme slant. Commented Sep 8, 2015 at 15:37