Index: source/lib/rand.h =================================================================== --- source/lib/rand.h +++ source/lib/rand.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -27,6 +27,9 @@ #ifndef INCLUDED_RAND #define INCLUDED_RAND +#include +#include + /** * return random integer in [min, max). * avoids several common pitfalls; see discussion at @@ -34,4 +37,40 @@ **/ LIB_API size_t rand(size_t min_inclusive, size_t max_exclusive); +/** + * Low randomness, quite-a-lot-faster-than-std::mt19937 random number generator. + * It matches the interface of UniformRandomBitGenerator for use in std::shuffle. + */ +class CFastRand +{ +public: + using result_type = u32; + + constexpr static result_type min() { return 0; } + constexpr static result_type max() { return 0xFFFF; } + + static result_type Rand(result_type& seed) + { + // This is a mixed linear congruential random number generator. + // The magic numbers are chosen so that they generate pseudo random numbers over a big enough period (0xFFFF). + seed = 214013 * seed + 2531011; + return (seed >> 16) & max(); + } + + static float RandFloat(result_type& seed, float min, float max) + { + return (static_cast(Rand(seed)) / (0xFFFF)) * (max - min) + min; + } + + CFastRand() {}; + CFastRand(result_type init) : m_Seed(init) {}; + + result_type operator()() + { + return Rand(m_Seed); + } + + result_type m_Seed; +}; + #endif // #ifndef INCLUDED_RAND Index: source/simulation2/tests/test_EntityMap.h =================================================================== --- source/simulation2/tests/test_EntityMap.h +++ source/simulation2/tests/test_EntityMap.h @@ -23,6 +23,9 @@ #include "simulation2/system/EntityMap.h" +#include +#include + class TestEntityMap : public CxxTest::TestSuite { public: @@ -226,7 +229,8 @@ std::vector vec; for (int i = 1; i <= 200000; ++i) vec.push_back(i); - std::random_shuffle(vec.begin(), vec.end()); + + std::shuffle(vec.begin(), vec.end(), std::mt19937{std::random_device{}}); for (int i = 1; i <= 200000; ++i) test.insert(i,i); Index: source/soundmanager/scripting/SoundGroup.h =================================================================== --- source/soundmanager/scripting/SoundGroup.h +++ source/soundmanager/scripting/SoundGroup.h @@ -81,9 +81,6 @@ void SetDefaultValues(); #if CONFIG2_AUDIO - inline u32 FastRand(); - // Contains the current sound seed for the generator - float RandFloat(float min, float max); // We store the handles so we can load now and play later std::vector m_SoundGroups; #endif Index: source/soundmanager/scripting/SoundGroup.cpp =================================================================== --- source/soundmanager/scripting/SoundGroup.cpp +++ source/soundmanager/scripting/SoundGroup.cpp @@ -36,21 +36,6 @@ extern CGame *g_Game; -#if CONFIG2_AUDIO -inline u32 CSoundGroup::FastRand() -{ - // This is a mixed linear congruential random number generator. - // The magic numbers are chosen so that they generate pseudo random numbers over a big enough period (0xFFFF). - m_Seed = 214013 * m_Seed + 2531011; - return (m_Seed >> 16) & 0xFFFF; -} - -float CSoundGroup::RandFloat(float min, float max) -{ - return (static_cast(FastRand()) / (0xFFFF)) * (max - min) + min; -} -#endif - void CSoundGroup::SetGain(float gain) { m_Gain = std::min(gain, 1.0f); @@ -194,10 +179,10 @@ if (cmpVisual) m_Seed = cmpVisual->GetActorSeed(); - hSound->SetPitch(TestFlag(eRandPitch) ? RandFloat(m_PitchLower, m_PitchUpper) : m_Pitch); + hSound->SetPitch(TestFlag(eRandPitch) ? CFastRand::RandFloat(m_Seed, m_PitchLower, m_PitchUpper) : m_Pitch); if (TestFlag(eRandGain)) - m_Gain = RandFloat(m_GainLower, m_GainUpper); + m_Gain = CFastRand::RandFloat(m_Seed, m_GainLower, m_GainUpper); hSound->SetCone(m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain); static_cast(g_SoundManager)->PlayGroupItem(hSound, m_Gain); @@ -242,7 +227,7 @@ } if (TestFlag(eRandOrder)) - random_shuffle(m_SoundGroups.begin(), m_SoundGroups.end()); + std::shuffle(m_SoundGroups.begin(), m_SoundGroups.end(), CFastRand(m_Seed)); #endif }