#ifndef MY_RANDOM_HPP #define MY_RANDOM_HPP #include <vector> #include <random> /* For spawning a truck, we would like to have a system where they mostly come from a lane. * However, that would be too predictable. * For this reason we implement our own distribution of probabilities, * where they scew to both sides. * Very roughly this: * .. .. * .-` `-.-` `-. */ class RadicalNumberGenerator { public: const int range_max = 100; private: std::mt19937 gen; std::discrete_distribution<> dist; /* To achieve the desired form, * we use the sum of 2 normal distributions. */ double normal_probability_density_function(double x, double mean, double variance) { return (1 / sqrt(2*M_PI*pow(variance, 2))) * exp(-0.5 * (pow(x-mean, 2) / (2*pow(variance, 2)))) ; } double radical_probability_density_function(double x) { double variance = 6.8d; return normal_probability_density_function(x, range_max * 0.2, variance) + normal_probability_density_function(x, range_max - (range_max * 0.2), variance); } public: RadicalNumberGenerator(int seed) : gen(seed) { std::vector<double> probabilities(range_max); for (int i = 0; i < range_max; i++) { probabilities[i] = std::max( 0.0, radical_probability_density_function((double)i) ); } dist = std::discrete_distribution(probabilities.begin(), probabilities.end()); } double operator()(void) { return dist(gen); } } radical_number_generator(rand()); /* We would like to spawn enemies and trucks at semi-random intervals, * without too much RNG involved. */ class Spawner { public: int last_blaze = 0; int min_distance; int denominator; void reset() { last_blaze = 0; } bool blaze(int current_distance) { if ((current_distance - last_blaze) > min_distance && rand() % denominator) { last_blaze = current_distance; return true; } return false; } }; #endif