I\'m a web-game developer and I got a problem with random numbers. Let\'s say that a player has 20% chance to get a critical hit with his sword. That means, 1 out of 5 hits
How about replacing mt_rand() with something like this?
(RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.)
From XKCD.
this one is really predictable... but you can never be sure.
That means, 1 out of 5 hits should be critical. The problem is I got very bad real life results - sometimes players get 3 crits in 5 hits, sometimes none in 15 hits.
What you need is a shuffle bag. It solves the problem of true random being too random for games.
The algorithm is about like this: You put 1 critical and 4 non-critical hits in a bag. Then you randomize their order in the bag and pick them out one at a time. When the bag is empty, you fill it again with the same values and randomize it. That way you will get in average 1 critical hit per 5 hits, and at most 2 critical and 8 non-critical hits in a row. Increase the number of items in the bag for more randomness.
Here is an example of an implementation (in Java) and its test cases that I wrote some time ago.
First, define "proper" distribution. Random numbers are, well, random - the results you're seeing are entirely consistent with (pseudo) randomness.
Expanding on this, I assume what you want is some feeling of "fairness", so the user can't go 100 turns without a success. If so, I'd keep track of the number of failures since the last success, and weight the generated result. Let's assume you want 1 in 5 rolls to "succeed". So you randomly generate a number from 1 to 5, and if it's 5, great.
If not, record the failure, and next time, generate a number from 1 to 5, but add on say, floor(numFailures / 2). So this time, again, they have a 1 in 5 chance. If they fail, next time the winning interval is 4 and 5; a 2 in 5 chance of success. With these choices, after 8 failures, they are certain to succeed.
Surely any random number generation has the chance of producing such runs? You're not going to get a big enough sample set in 3-10 rolls to see appropriate percentages.
Maybe what you want is a mercy threshold ... remember the last 10 rolls, and if they haven't had a critical hit, give them a freebie. Smooth out the slings and arrows of randomness.
I think perhaps you are using the wrong random distribution function. You probably don't want an even distribution over the numbers. Try a normal distribution instead so that the critical hits become more uncommon than the 'regular' hits.
I work with Java so I'm not sure where you can find something for C++ that gives you random numbers with a normal distribution but there has to be something out there.