11242005 08:34
Posted by:
Jae Rune
Location:
Cheyenne, WY

I had originally intended this as a neat introductory tutorial on the differences between random numbers and biased random numbers, with a nod towards RPG battle systems, sort of a "starting point" for beginners. But I don't know TNT well enough to really clean this code up and make it flexible as hell. So here's the basic explanation of the differences and the code, as commented as I can get it without being intrusive.
Random Numbers & You  Random numbers are fine and dandy for your run of the mill dicebased RPG. As in real life, when you roll the virtual die, you have a 1:1 chance of getting any of the numbers. This is great if you're doing a simulation of a die roll, but if you want the player to have a percentage chance that's based more on probability than random dumb luck, you're going to need Biased or Weighted Numbers (same thing).
Biased/Weighted Numbers are numbers that have a probability of showing up. In typical D&D, with a d20 (20sided die), you have three outcomes: miss/fumble, hit, critical hit. These are based upon your die roll. If you roll a 1, that is a miss (fumble). If you roll a 2 through 19, that is a hit. If you roll a 20, that is a critical hit. Modifiers aside, this is pretty standard. In your game, however, you're going to want to stack the odds more in the favor of the player. If they have a 1:1 chance of rolling a miss or a critical, even though there's a wider chance they'll roll a hit, they'll still have a 1:1 chance of rolling any number.
Here's where we bias the roll. The purpose of biasing the roll is to make it more probably that the player will make a HIT roll, rather than a MISS. If we use the [1][219][20] model from D&D, we see that HITS have a 90% chance of success (18 x 5), MISSes have a 5% chance of success (1 x 5) and CRITicals have a 5% chance of success (1 x 5). If we want to make it so that the player truly has that chance, we need to bias the numbers.
Let's take a look at the code:
'First, we're going to want to make humanreadable labels, as this is only going to be printed, and we want a quick and easy reference for the outcome.
string labels[3]
labels[0] = "MISS"
labels[1] = "HIT "
labels[2] = "CRIT"
'Second, we're going to want to make the Bias Table. This shows how likely, based on a 100% total scale, each of these actions is likely to happen.
int weights[3]
weights[0] = 5 '5% likely
weights[1] = 90 '90% likely
weights[2] = 5 '5% likely
'Next, we need to doublecheck that we've got a total of 100. This is because if we had a total of 80 or 113, it would skew the results. If the numbers above were 5,10,5 the actual results would be "25%,50%,25%" based upon their total being treated as 100%. Hopefully someone else can better clarify that...
int x,totalWeight
for x = 0 to 2
totalWeight = totalWeight + weights[x]
next x
Print totalWeight
'Next, we need to create a 100dimension array to hold all the labels. This is because we're going to have certain labels that are more likely than others to appear.
string wResults[100]
'Now we add in the first possible outcome to the array however many times it is likely to appear.
for x = 0 to weights[0]  1
wResults[x] = labels[0]
next x
'Second outcome
for x = weights[0] to ((weights[0] + weights[1])  1)
wResults[x] = labels[1]
next x
'Third outcome
for x = (weights[0] + weights[1]) to ((weights[0] + weights[1] + weights[2])  1)
wResults[x] = labels[2]
next x
'Now it's time to randomly select from the Bias Table!
str output
'For the purposes of counting, we create three variables which allow us to track how often something is chosen.
int rnd,m,h,c
'We need to do this 100 times, because we want to see if our random bias is truely biased.
for x = 0 to 99
rnd = random(0,99)
'Choose the correct result from the Bias Table baeed upon the randomly selected number from 1 to 100.
print wResults[rnd]
if wResults[rnd] = "MISS" then m = m + 1
if wResults[rnd] = "HIT " then h = h + 1
if wResults[rnd] = "CRIT" then c = c + 1
next x
'You'll note that no matter what, these numbers will ALWAYS add up to 100! :)
print m
print h
print c
Now that we've seen how this works, we can see that large biases are easy to implement. However, if we make everything equal, the results don't always come out 100% biased towards any one result, as everything is returned to a 1:1 status. Try playing around with values of weights[] and see what sorts of biases you can come up with.
Hope this was helpful!
