Assuming the min,max
range is inclusive there are span = max-min+1
possible values. One approach would be define a Gaussian Probability Density Function (PDF), centered on luck * span
, with a sigma
of, for example, span/2
- you could vary this to alter the tightness of the distribution around the center.
You'd then use the PDF to calculate a 'weight' for each possible value within the range of span
- values near the center of the distribution will get a higher weight - and use a standard technique for selecting a random value within a range, where each value has an associated weight.
Here's some Java code to illustrate.
static int generatePeople(double luck, int min, int max)
{
int span = max - min + 1;
double mean = luck * span;
double sigma = span / 2;
double[] weights = new double[span];
double totWeight = 0;
for(int i=0; i<span; i++)
{
weights[i] = pdf(mean, sigma, i+0.5);
totWeight += weights[i];
}
double rnd = Math.random()*totWeight;
for(int i=0; i<span; i++)
{
if(rnd < weights[i]) return min+i;
rnd -= weights[i];
}
return max;
}
static double pdf(double mean, double sigma, double x)
{
double e = (mean - x) / sigma;
return Math.exp(-(e*e)/2)/(sigma*Math.sqrt(2*Math.PI));
}
We can illustrate the behavior of this approach by generating a large number of values and examining the distribution between min
and max
for a given value of `luck'.
static void test(double luck, int min, int max)
{
int[] score = new int[max-min+1];
for(int i=0; i<1000*score.length; i++)
score[generatePeople(luck, min, max)-min]++;
for(int i=0; i<score.length; i++)
{
System.out.println(min+i + " : " + score[i]);
}
}
Output:
test(0.5, 0, 9);
Gives:
0 : 786
1 : 878
2 : 1059
3 : 1110
4 : 1152
5 : 1162
6 : 1106
7 : 1020
8 : 962
9 : 765
While
test(0.25, 0, 9);
Gives:
0 : 1195
1 : 1236
2 : 1285
3 : 1284
4 : 1146
5 : 1078
6 : 904
7 : 771
8 : 610
9 : 491