mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
88 lines
1.4 KiB
C++
88 lines
1.4 KiB
C++
#include "Random.h"
|
|
#include "RandomRange.h"
|
|
|
|
#include <limits>
|
|
#include <random>
|
|
|
|
#include <cstdint>
|
|
|
|
#include "globalincs/pstypes.h"
|
|
|
|
namespace util {
|
|
|
|
thread_local std::mt19937 seeder {std::random_device()()};
|
|
|
|
namespace {
|
|
template <typename RngType>
|
|
class RandomImpl {
|
|
public:
|
|
void seed(const unsigned int val)
|
|
{
|
|
static_assert(RngType::min() == 0, "RNG min must be 0");
|
|
static_assert(RngType::max() == std::numeric_limits<uint32_t>::max(), "RNG max must be INT32_MAX");
|
|
|
|
// follow srand semantics
|
|
if (val == 1) {
|
|
m_rng.seed();
|
|
} else {
|
|
m_rng.seed(val);
|
|
}
|
|
}
|
|
|
|
int next()
|
|
{
|
|
return m_rng() & Random::MAX_VALUE;
|
|
}
|
|
|
|
void advance(unsigned long long distance)
|
|
{
|
|
m_rng.discard(distance);
|
|
}
|
|
|
|
private:
|
|
RngType m_rng;
|
|
};
|
|
|
|
RandomImpl<std::mt19937> SCP_rng;
|
|
} // namespace
|
|
|
|
Random::Random() = default;
|
|
|
|
void Random::seed(unsigned int val)
|
|
{
|
|
Assert(val > 0);
|
|
SCP_rng.seed(val);
|
|
}
|
|
|
|
int Random::next()
|
|
{
|
|
return SCP_rng.next();
|
|
}
|
|
|
|
int Random::next(int modulus)
|
|
{
|
|
Assert(modulus > 0);
|
|
|
|
return SCP_rng.next() % modulus;
|
|
}
|
|
|
|
int Random::next(int low, int high)
|
|
{
|
|
const int range = high - low + 1;
|
|
Assert(range > 0);
|
|
|
|
return low + (SCP_rng.next() % range);
|
|
}
|
|
|
|
bool Random::flip_coin()
|
|
{
|
|
// [0, HALF_MAX_VALUE] and [HALF_MAX_VALUE+1,MAX_VALUE] are the same size
|
|
return SCP_rng.next() <= Random::HALF_MAX_VALUE;
|
|
}
|
|
|
|
void Random::advance(unsigned long long distance)
|
|
{
|
|
SCP_rng.advance(distance);
|
|
}
|
|
} // namespace util
|