Well, I got a little impatient and wrote some code so that computes a cdf for Beta probabilities. I'll include the code and some explanation. Hopefully this can help someone in the future. Also, if there is someway to implement LaTeX style equations in here that someone knows of, that would be awesome to include in the comments to make this a little easier to understand.
If you want to get a little bit of background on a Beta distribution, check out the wikipedia link here;
https://en.wikipedia.org/wiki/Beta_distribution.
There are three functions used in this set-up;
- A function to pull a nCr (combinations of choose 'r' of 'n' items) value when we do some integration of the incomplete beta equation.
- A function to find B(a,b) in the form of factorials which were converted form their gamma functions.
- A function that does the integral of the incomplete beta equation.
For the function in item 1 ('ncr' in the code), it finds which is smaller of r or (n-r), then computes the left, non-truncated portion of n! and computers that over r! or (n-r)!, whichever is smaller. This is the equivalent of using the formula n!/(r!(n-r)!, though with a quicker computation for large factorials.
For the function in item 2 ('betas' in the code), it determines the formula B(a,b) = [G(a)G(b)]/G(a+b) where G is the gamma function. It uses a shortcut where G(z)=(z-1)! and then computes the factorials normally.
For the function in item 3 ('betaInt' in the code), it takes the very specific integral of the incomplete beta function given as B(x; a,b)=INT^x_0 t^(a-1)*(1-t)^(b-1)dt. This integral follows a specific pattern of having a number of x values with an index of 'a' and there will be a number of x's, incrementing by 1 each time after the first, of 'b'. For example, if a=8 and b=4. There will be an ?x^8, ?x^9, ?x^10, ?x^11, where the question marks represent the unknown coefficients. To determine the coefficients, we use Pascal's Triange, which is a derivative of our nCr function. We then divide the nCr value of each step by the index of the variable, and we are able to get a quick and dirty derivative by stepping through each variable.
Note that you have to import two libraries to get this to work;
Code: Select all
init python:
import math
import operator
## Finds the combinations available to choose r items from n choices
def ncr(n, r):
r = min(r, n-r)
numer = reduce(operator.mul, xrange(n, n-r, -1), 1)
denom = reduce(operator.mul, xrange(1, r+1), 1)
return numer//denom
## Determines the values from our simplified gamma functions from B(a,b). a is our alpha shape variable and b is our beta shape variable. Note that a and b can only be passed as integers.
def betas(a,b):
return float(math.factorial(a-1))*math.factorial(b-1)/math.factorial(a+b-1)
## Takes the specific integral of the incomplete beta function. a is our alpha shape variable, b is our beta shape variable, x is the random probability chosen.
def betaInt(a,b,x):
sign=1
total=0.0
for i in range(a-1,a+b-1):
if (sign % 2 == 1):
total += float(ncr(b-1,sign-1))*(1.0/(i+1))*math.pow(x,i+1)
else:
total -= float(ncr(b-1,sign-1))*(1.0/(i+1))*math.pow(x,i+1)
sign += 1
return total/betas(a,b)
label start:
$core=betaInt(4,8,0.7)
"Around 0.995709106; [core]"
$core=betaInt(8,4,0.7)
"Around 0.5695623388; [core]"
You can feel free to check the values here to make sure the code is working well for you;
https://www.danielsoper.com/statcalc/ca ... aspx?id=94
You may be asking yourself, "Why would I ever need this?!?" Well, the beta probability is pretty good at giving you a weighted curve of success.
Let us consider something where you want to check the opposition between two skills. Under the normal renpy random number distributions, you will get some number between 0 through 1, with no consideration to any skill. This is the uniform distribution I mentioned in the first post. If you were to map the cdf of this function, it would be a perfectly horizontal line.
Now we can take this renpy generated random number and apply our weights. Look at the example above in the code. You will notice I have x=0.7. This is assuming that 0.7 is what we got from our renpy random number generation. Let's have our skill for the person we are interacting with be our alpha shape variable 'a' and our skill for our PC be the beta shape variable 'b'. You will notice that the skill goes down when our opponent has the advantage (a>b) and our number goes up when we have the advantage (b>a).
Note that for this code to work, a>0 and b>0 and a and b must be natural numbers. The best values are between 1 and 5 as your curve will not be "smashed" too much in the middle and have "long" tails. You can go between 1 and 10, though make sure to have increments above 5 be more rare the closer they are to 10.