-
Notifications
You must be signed in to change notification settings - Fork 672
Random increment math #114
Description
I was just looking through the code and saw your comments for the random incrementing logic where you say you'd like to "do this mathematically...".
A Linear formula:
If you want to follow a similar formula going forward, I think that a simple application of the slope-intercept to decrease the increment linearly would probably be fine. Given you want to start with a maximum increment of 6.0%
and end up with an increment of 0.5%
, you could use the following:
function maxIncrement(stat) {
var x1=0,
y1=6.0,
x2=99,
y2=0.5,
b=0, // intercept
m=0; // slope
m = (y1-y2)/(x1-x2);
b = y1-(m*x1);
// return the y-value from the formula y = m * x + b
return m*stat+b;
}
Which gives the following values:
maxIncrement(0)
> 6
maxIncrement(1)
> 5.944444444444445
maxIncrement(2)
> 5.888888888888889
...
maxIncrement(97)
> 0.6111111111111116
maxIncrement(98)
> 0.5555555555555562
maxIncrement(99)
> 0.5
That function is a bit verbose when we leave all the math inside, but you could simplify it as follows:
function maxIncrement(stat) {
return (5.5/-99)*stat+(6.0);
}
Now, your code actually uses the value we're finding above as the maximum threshold, where you choose a random value between 0 and the maximum. To re-enable this logic, we can create another method to handle it as follows:
function incrementer(stat) {
var m = maxIncrement(stat);
return (Math.random() * m) / 100;
}
Last, we still need to handle the case greater than or equal to 99%. Here's what it would be in it's final form:
if (stat >= 0.99) {
rnd = 0;
} else {
rnd = incrementer(stat);
}
To visualize all of this a bit better, check out what it looks like on Wolfram Alpha.
Using the image above, we're picking an x value (stat
) and finding the y value represented by the blue sloping line. This value becomes our upper bound. We then choose a random value between [0, 1)
using Math.random()
, and multiply to get a new value somewhere between 0 and our upper bound.
Everything together:
function maxIncrement(stat) {
return (5.5/-99)*stat+(6.0);
}
function incrementer(stat) {
var m = maxIncrement(stat);
return (Math.random() * m) / 100;
}
if (stat >= 0.99) {
rnd = 0;
} else {
rnd = incrementer(stat);
}
Obviously there's no need to keep those all as method calls, so feel free to inline things as you see fit.
Note: I deviated from your logic slightly in that you don't choose a random multiplier when stat >= 0.9 && stat < 0.99
, whereas I do.
A Non-Linear formula:
If you're looking for something non-linear like an exponential decay, take a look at this Wolfram Alpha. The only adjustment to the formula above would be:
function maxIncrement(stat) {
return 6.0*Math.exp(-5.0*(stat/100));
}
Which gives the following values:
maxIncrement(0)
> 6
maxIncrement(1)
> 5.707376547004284
maxIncrement(2)
> 5.4290245082157575
...
maxIncrement(97)
> 0.046970265295354655
maxIncrement(98)
> 0.04467949842554603
maxIncrement(99)
> 0.042500453574312716
You can see that compared to the linear formula this slows down much more rapidly and has a longer tail.
Sorry for the long post, this ended up growing more rapidly than I had originally anticipated.