#include <stdio.h>
#include <time.h>
#include "prng.h"
// You can optionally specify a seed, so there are two constructors.
PRNG::PRNG ()
{
seed = (unsigned int) time (NULL);
}
PRNG::PRNG (unsigned int s)
{
seed = s;
}
// Note: since the destructor does nothing, there's no need to define one.(?)
// Note: 'gen_number () % 100' is beteen 0 and 99, hence the +1.
// If you want to get between 0 and 100, change it to 'gen_number () % 101'.
int PRNG::operator() (void)
{
//return gen_number () % 101;
return 1 + gen_number () % 100;
}
// Similarly, 'gen_number () % (max + 1)' is between 0 and 'max'.
int PRNG::operator() (int max)
{
//return gen_number () % (max + 1);
return 1 + gen_number () % max;
}
// These two simply call private methods.
int PRNG::operator() (int min, int max)
{
return range (min, max);
}
// Be very careful with using rerolls. They're a good way to implement some
// things, probably, however their main purpose is actually to differentiate
// between this operator and the previous one. Sneaky, right?
int PRNG::operator() (int num, int sides, int rerolls)
{
return dice (num, sides, rerolls);
}
// This just sets the seed. You have to typecast the seed yourself if you're
// seeding from something other than an unsigned int. As an example, you could
// seed it with '(unsigned int) argv[1]'.
void PRNG::set_seed (unsigned int s)
{
seed = s;
return;
}
// Simple algorithm, but it has excellent distribution.
unsigned int PRNG::gen_number (void)
{
seed = seed * 1103515245 + 12345;
return (seed / 65536) % 32768;
}
// Generates numbers in a specified range.
unsigned int PRNG::range (int min, int max)
{
// Obviously there's nothing random about it.
if (min == max)
return min;
// Reverse the call so nothing funky happens.
if (min > max)
return range (max, min);
return min + gen_number () % (1 + max - min);
}
// Generates a dice roll.
unsigned int PRNG::dice (int num, int sides, int rolls)
{
unsigned int result = 0;
int i, n;
// Roll once for each die.
for (i = 0; i < num; i++)
{
// Stored in n so we can check for rerolls...
n = 1 + gen_number () % sides;
// This seemed to not work with --rolls in the 'while' condition.
while (n < sides / 3 && rolls > 0)
{
// Reroll it once and spend one of our rolls.
n = 1 + gen_number () % sides;
--rolls;
}
// Add it to the final result.
result += n;
}
return result;
}