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