I would do it this way
Mapping rand()
rand() / (float)RAND_MAX
Rand()
returns a value from 0 to RAND_MAX
so this formula maps 0 -> RAND_MAX
to
0 -> 1
(float) is used to make RAND_MAX
a float because the value returned by rand()
is an int
and int / int
in c++ returns an int
(rand() / (float)RAND_MAX) * 10
If you multiply the result by 10 it will map rand()
from 0 -> 10
(rand() / (float)RAND_MAX) * 187.5
This will map rand()
from 0 -> 187.5
1 in 187.5
We mapped the value of rand()
from 0 -> 187.5
Now everytime we call rand()
it will return a random number from 0->187.5
To simplify let's say we map rand()
from 0 -> 200
There will be a 1/2 chance that rand()
will return a number lower then 100 because every number between 0 -> 200 has an equal chance of being returned (for example rand()
can return 25.67 or 100.9 or 140.6)
( (rand() / (float)RAND_MAX) * 187.5 ) < 1
By the same principle there is a 1 in 187.5 chance that the number returned is smaller then 1
Final solution
We are still missing the 1 in 187.5 / X
To implement the encounter rate you just need to change the mapping from 0 -> 187.5
To
0 -> 187.5 / X
We can see that if X is big it means that there is a high encounter rate and 187.5 gets smaller and the number returned has a higher chance of being smaller then 1 but if the encounter rate is low X becomes small and 187.5 gets bigger (lower chance of being smaller then 1)
Final code
srand (time(NULL)); // Init rand() with a seed
bool encountered = ( (rand() / (float)RAND_MAX) * (187.5 / x) ) < 1
Optimisation
A user pointed out that with the last code you need to compute 5 rand()'s for each event but if we tweak the formula a little bit you can compute only 1 rand()
By using simple math you know that an event that occurs once (1) in 10 / 2 steps
is an event that occurs twice in (2) in 10 steps
So an event that occurs once (1) in 187.5 / X steps occurs (1 * X) in 187.5 steps
If we map rand() from 0 -> 187.5 Then for each pokemon we can calculate a unique value for it using only one rand()
float randomNumber = (rand() / (float)RAND_MAX) * 187.5
bool encountedPokemon1 = randomNumber < 1 * encounter_rate_first_pokemon
bool encountedPokemon2 = randomNumber < 1 * encounter_rate_second_pokemon