Pseudo-Random Distribution (henceforce PRD) is a neat little trick I learned from Warcraft III of all places that allows you to make random variables less 'random'. The idea is, instead of having say a 20% chance to critical strike for your main character, you can have a distributed chance to critical strike on each attack that gets progressively higher, forcing an average of "one in five", a 20% chance overall, while making it extremely unlikely to get chains of criticals in a row, and making it impossible to go an entire game without getting any.
All random variables on computers are not actually random, but pseudorandom in nature; its impossible to create a program that will return a truly random number. Instead the computer uses some ridiculously complicated formula that comes out to be approximately the proper chance of returning each number. Thats not what this article is about. But because of the limitation of these formulas, theres a special importance on making random events in games better distributed. This is where PRD comes in. Especially in games that are player vs player, it cuts down on the 'luck' factor, and makes random skills more 'consistent'.
In its basic form, PRD works like this:
You have an event that has an X% chance of occuring on some call, for example, in MMF2:
Random(100) < 30
Would give you a 30% chance. Now you keep track of how many SUCCESS'es and how many FAILURE's this event has; every time the check fails, you add 1 to a counter, every time the event succeeds, you reset that counter to 0. Now, you use a variable called "Q", a predetermined constant, and alter the formula to this:
Random(100) < Q * #Failures
In the case of 30%, Q happens to be 11.895, or 0.11895. Obviously you need to use a Random(100000) if you want to this be more exacting. What happens when you do this is this; one the first attack, you have an 12% chance of striking. One the 2nd attack, you have a 24% chance. On the 3rd, a 36% chance. And so on. If you made it to the 9th attack, you have more than a 100% chance to strike. Overall, the distribution of these chances will mean you have a 30% chance to strike on average, but it will be 'less random'.
Now if you've followed this so far, the thing you probably noticed is this magic number Q. Its very hard to calculate, and I'm not going to get into how you do that, but instead just provide a table. For every % chance, this constant is always the same. Hence, for actions that fall on these specific odds, you can use this distribution:
I'll include a more expansive list below. But these cover most of it. In general, this lets you create a much more 'stable' random event system, which further improves upon the random number generators in MMF2. The built in one is extremely weak and repeats alot, and thus you need to use extensions for some projects, and this is a good way to improve upon those extensions to get good distribution. This example file will demonstrate a graph of HOW the normally distributed and PRD differ in a large sample size when working with a 1/10 chance; it records the # of 'attacks' inbetween each '30%' critical strike;
As you can see, 30% of the time it occurs on your first strike for normal distribution, then 20%, then 15%, 10%, 7.5%, etc. Hence it is very LEFT-skewed distribution; it favors chains of critical strikes in a row, yet, at the same time, the #10 is very heavy because it includes all the outlier (>10) data, showing that a good 5-10% of the time, you will take MORE than 10 strikes in a row on a 30% chance of attack, something that should occur roughly every 3-4 strikes.
Meanwhile, in our PRD graph, the distribution is directly curved to the 3-4 strike zone; it will always take 2, 3, or 4 strikes between attacks, a bell curve distribution centered properly. You will NEVER seen any outlier data here; you can't go long streaks without getting a strike.
Big list of constants;
5-50% in intervals of 5:
5% 0.00380
10% 0.01475
15% 0.03221
20% 0.05570
25% 0.08475
30% 0.11895
35% 0.15800
40% 0.20155
45% 0.24933
50% 0.30213
I lost my list of constants of each for up to 100%, but it is NOT a very good idea to apply PRD to events with a 50% or more chance of occuring, anyway; if it would have had a 99% chance of occuring, the PRD would effectively be 99, FORCING the strike to occur on an odd numbered attack. Plus, when in gods name do you use > 50% chances of things occuring? Why not use the chance of the event NOT occuring? Hence theres no reason whatsoever to use above 50%. Sorry I don't have non-5 intervals between 30 & 50
Very good. I have always been slightly dissapointed with the results of random number generators I come up with. Hopefully,this will improve results a bit. Oh, and I was wondering how you would account for successes. Random(100) < Q * #Successes? Or something like that. That way, you'd have a more complete set of data results. Then randomly bounce from one to the other for extra discrepency.
well your chance is at a minimum after each success, so strings of successes are already unlikely; if you have a 30% 'chance', then the constant is ~12%, thus after each successful hit you have a 12% chance on the next one; the odds of a string of hits is 0.12^N, as opposed to the normal distribution of 0.30^N, which is considerably more likely.
But yes it IS important not to use this for things you want to be utterly random, like a 0.01% chance for your weapon to explode or something; every character would find their weapon explode roughly at the same point in the game eventually, since after maybe 100000 failed attempts it would be over 100% odds.
But its VERY nice to use for things like critical strikes or random bonuses; I actually learned about it from Warcraft III, which uses it on Critical Strikes, Evasion, Attack Modifiers, etc.
Seemingly simple and also complicated, but it does outline the problem with computer-generated random numbers and how to create a system that uses consistent, more realistic way to calculate actual percentage chances.
I usually make a bunch of events that check on a specific stat and each of those has a better chance of success the higher you go. It's not the best way perhaps but it seems to work.
Well implementing it in any klik game actually only takes one 'line of code', its just the mechanics behind it are complicated. For example, if your event was this:
+On Pressing Space Bar:
+Random(100) < 30
=Kill Baddy!
Then it becomes:
+On Pressing Space Bar:
=Add 1 to *Fail Counter*
+On Pressing Space Bar:
+Random(1000) < 119 * Fail Counter
=Kill Baddy
=Set *Fail Counter* to 0
btw del duio I used that same approach for Gridquest for creating random items. It would pass through a line of code that looks like this:
so you'd have twice the chance of getting shields than armor, twice the chance of armor than weapons, so on and so on. That way, at the very end, you would have a < 1% chance of finding rare items, actually a 1 in 5461 chance of finding the biggest sword Comment edited by Pixelthief on 1/6/2009
This is one of those things that's easier to explain with pictures and example-comments than words
I'm personally not fond of PRD. It's a bit like artificial flavoring, IMHO, a lazy solution to a problem. Normal randomness creates a much more interesting game - can't make a fun poker or soccer game with PRD. And it invites abuse from people who expect their third hit to be more likely.
The normal random system actually works very well if you take it into account of the game design. But.. it works very well with inexperienced gamers - Blizzard's main customer base. Most inexperienced gamers will cry foul on another person's luck streak and PRD eliminates luck streaks completely. Also good for RPGs with perma-death where a streak of bad rolls are much more noticable than a streak of good rolls. Comment edited by Muz on 1/7/2009
wow... I was using a PRD-like system before WC3 came into existence. I had come up with it after playing Final Fantasy I and getting 12 misses in a row... that hurt. Anyways, nice article!