masses/source/my_random.hpp
2024-12-21 14:08:37 +01:00

83 lines
2.1 KiB
C++

#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