mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-01 07:09:41 +00:00
Separate global vs world rng functions and use custom prng
This commit is contained in:
parent
08fae7be6e
commit
151770ccf1
3 changed files with 81 additions and 20 deletions
|
@ -338,6 +338,10 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||||
{
|
{
|
||||||
|
writer.startRecord(ESM::REC_RAND);
|
||||||
|
writer.writeHNT("RAND", mPrng.getSeed());
|
||||||
|
writer.endRecord(ESM::REC_RAND);
|
||||||
|
|
||||||
// Active cells could have a dirty fog of war, sync it to the CellStore first
|
// Active cells could have a dirty fog of war, sync it to the CellStore first
|
||||||
for (CellStore* cellstore : mWorldScene->getActiveCells())
|
for (CellStore* cellstore : mWorldScene->getActiveCells())
|
||||||
{
|
{
|
||||||
|
@ -359,12 +363,6 @@ namespace MWWorld
|
||||||
writer.writeHNT("LEVT", mLevitationEnabled);
|
writer.writeHNT("LEVT", mLevitationEnabled);
|
||||||
writer.endRecord(ESM::REC_ENAB);
|
writer.endRecord(ESM::REC_ENAB);
|
||||||
|
|
||||||
std::stringstream ssPrng;
|
|
||||||
ssPrng << mPrng;
|
|
||||||
writer.startRecord(ESM::REC_RAND);
|
|
||||||
writer.writeHString(ssPrng.str());
|
|
||||||
writer.endRecord(ESM::REC_RAND);
|
|
||||||
|
|
||||||
writer.startRecord(ESM::REC_CAM_);
|
writer.startRecord(ESM::REC_CAM_);
|
||||||
writer.writeHNT("FIRS", isFirstPerson());
|
writer.writeHNT("FIRS", isFirstPerson());
|
||||||
writer.endRecord(ESM::REC_CAM_);
|
writer.endRecord(ESM::REC_CAM_);
|
||||||
|
@ -384,10 +382,11 @@ namespace MWWorld
|
||||||
return;
|
return;
|
||||||
case ESM::REC_RAND:
|
case ESM::REC_RAND:
|
||||||
{
|
{
|
||||||
std::stringstream ssPrng;
|
Misc::Rng::Generator::result_type seed{};
|
||||||
ssPrng << reader.getHString();
|
reader.getHNT(seed, "RAND");
|
||||||
ssPrng.seekg(0);
|
Log(Debug::Info) << "---- World random state: " << seed << " ----";
|
||||||
ssPrng >> mPrng;
|
mPrng.seed(seed);
|
||||||
|
Misc::Rng::getGenerator().seed(seed);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ESM::REC_PLAY:
|
case ESM::REC_PLAY:
|
||||||
|
@ -3723,9 +3722,10 @@ namespace MWWorld
|
||||||
static int iNumberCreatures = mStore.get<ESM::GameSetting>().find("iNumberCreatures")->mValue.getInteger();
|
static int iNumberCreatures = mStore.get<ESM::GameSetting>().find("iNumberCreatures")->mValue.getInteger();
|
||||||
int numCreatures = 1 + Misc::Rng::rollDice(iNumberCreatures); // [1, iNumberCreatures]
|
int numCreatures = 1 + Misc::Rng::rollDice(iNumberCreatures); // [1, iNumberCreatures]
|
||||||
|
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
for (int i=0; i<numCreatures; ++i)
|
for (int i=0; i<numCreatures; ++i)
|
||||||
{
|
{
|
||||||
std::string selectedCreature = MWMechanics::getLevelledItem(list, true);
|
std::string selectedCreature = MWMechanics::getLevelledItem(list, true, prng);
|
||||||
if (selectedCreature.empty())
|
if (selectedCreature.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
namespace Misc::Rng
|
namespace Misc::Rng
|
||||||
{
|
{
|
||||||
static Generator sGenerator;
|
static Generator sGenerator;
|
||||||
|
@ -12,29 +14,51 @@ namespace Misc::Rng
|
||||||
return sGenerator;
|
return sGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int generateDefaultSeed()
|
||||||
|
{
|
||||||
|
auto res = static_cast<unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||||
|
Log(Debug::Info) << __FUNCTION__ << ": " << res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void init(unsigned int seed)
|
void init(unsigned int seed)
|
||||||
{
|
{
|
||||||
sGenerator.seed(seed);
|
sGenerator.seed(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float rollProbability()
|
||||||
|
{
|
||||||
|
return std::uniform_real_distribution<float>(0, 1 - std::numeric_limits<float>::epsilon())(getGenerator());
|
||||||
|
}
|
||||||
|
|
||||||
float rollProbability(Generator& prng)
|
float rollProbability(Generator& prng)
|
||||||
{
|
{
|
||||||
return std::uniform_real_distribution<float>(0, 1 - std::numeric_limits<float>::epsilon())(prng);
|
return std::uniform_real_distribution<float>(0, 1 - std::numeric_limits<float>::epsilon())(prng);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float rollClosedProbability()
|
||||||
|
{
|
||||||
|
return std::uniform_real_distribution<float>(0, 1)(getGenerator());
|
||||||
|
}
|
||||||
|
|
||||||
float rollClosedProbability(Generator& prng)
|
float rollClosedProbability(Generator& prng)
|
||||||
{
|
{
|
||||||
return std::uniform_real_distribution<float>(0, 1)(prng);
|
return std::uniform_real_distribution<float>(0, 1)(prng);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rollDice(int max)
|
||||||
|
{
|
||||||
|
return max > 0 ? std::uniform_int_distribution<int>(0, max - 1)(getGenerator()) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int rollDice(int max, Generator& prng)
|
int rollDice(int max, Generator& prng)
|
||||||
{
|
{
|
||||||
return max > 0 ? std::uniform_int_distribution<int>(0, max - 1)(prng) : 0;
|
return max > 0 ? std::uniform_int_distribution<int>(0, max - 1)(prng) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int generateDefaultSeed()
|
float deviate(float mean, float deviation)
|
||||||
{
|
{
|
||||||
return static_cast<unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
return std::uniform_real_distribution<float>(mean - deviation, mean + deviation)(getGenerator());
|
||||||
}
|
}
|
||||||
|
|
||||||
float deviate(float mean, float deviation, Generator& prng)
|
float deviate(float mean, float deviation, Generator& prng)
|
||||||
|
|
|
@ -9,8 +9,41 @@
|
||||||
*/
|
*/
|
||||||
namespace Misc::Rng
|
namespace Misc::Rng
|
||||||
{
|
{
|
||||||
|
class Generator
|
||||||
|
{
|
||||||
|
uint32_t mState{};
|
||||||
|
|
||||||
using Generator = std::mt19937;
|
public:
|
||||||
|
using result_type = uint32_t;
|
||||||
|
|
||||||
|
constexpr Generator() = default;
|
||||||
|
constexpr Generator(result_type seed) : mState{ seed } {}
|
||||||
|
constexpr result_type operator()() noexcept
|
||||||
|
{
|
||||||
|
mState = (214013 * mState + 2531011);
|
||||||
|
return (mState >> 16) & max();
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr result_type min() noexcept
|
||||||
|
{
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr result_type max() noexcept
|
||||||
|
{
|
||||||
|
return 0x7FFFu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void seed(result_type val) noexcept
|
||||||
|
{
|
||||||
|
mState = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getSeed() const noexcept
|
||||||
|
{
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Generator& getGenerator();
|
Generator& getGenerator();
|
||||||
|
|
||||||
|
@ -21,19 +54,23 @@ namespace Misc::Rng
|
||||||
void init(unsigned int seed = generateDefaultSeed());
|
void init(unsigned int seed = generateDefaultSeed());
|
||||||
|
|
||||||
/// return value in range [0.0f, 1.0f) <- note open upper range.
|
/// return value in range [0.0f, 1.0f) <- note open upper range.
|
||||||
float rollProbability(Generator& prng = getGenerator());
|
float rollProbability();
|
||||||
|
float rollProbability(Generator& prng);
|
||||||
|
|
||||||
/// return value in range [0.0f, 1.0f] <- note closed upper range.
|
/// return value in range [0.0f, 1.0f] <- note closed upper range.
|
||||||
float rollClosedProbability(Generator& prng = getGenerator());
|
float rollClosedProbability();
|
||||||
|
float rollClosedProbability(Generator& prng);
|
||||||
|
|
||||||
/// return value in range [0, max) <- note open upper range.
|
/// return value in range [0, max) <- note open upper range.
|
||||||
int rollDice(int max, Generator& prng = getGenerator());
|
int rollDice(int max);
|
||||||
|
int rollDice(int max, Generator& prng);
|
||||||
|
|
||||||
/// return value in range [0, 99]
|
/// return value in range [0, 99]
|
||||||
inline int roll0to99(Generator& prng = getGenerator()) { return rollDice(100, prng); }
|
inline int roll0to99(Generator& prng) { return rollDice(100, prng); }
|
||||||
|
inline int roll0to99() { return rollDice(100); }
|
||||||
float deviate(float mean, float deviation, Generator& prng = getGenerator());
|
|
||||||
|
|
||||||
|
float deviate(float mean, float deviation);
|
||||||
|
float deviate(float mean, float deviation, Generator& prng);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue