prng/
#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;
}