diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 25064123ce..a1eb958ed1 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -19,14 +19,14 @@ namespace MWMechanics { /// @return ID of resulting item, or empty if none - inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Seed& seed = Misc::Rng::getSeed()) + inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng = Misc::Rng::getGenerator()) { const std::vector& items = levItem->mList; const MWWorld::Ptr& player = getPlayer(); int playerLevel = player.getClass().getCreatureStats(player).getLevel(); - if (Misc::Rng::roll0to99(seed) < levItem->mChanceNone) + if (Misc::Rng::roll0to99(prng) < levItem->mChanceNone) return std::string(); std::vector candidates; @@ -55,7 +55,7 @@ namespace MWMechanics } if (candidates.empty()) return std::string(); - std::string item = candidates[Misc::Rng::rollDice(candidates.size(), seed)]; + std::string item = candidates[Misc::Rng::rollDice(candidates.size(), prng)]; // Vanilla doesn't fail on nonexistent items in levelled lists if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item))) @@ -74,9 +74,9 @@ namespace MWMechanics else { if (ref.getPtr().getType() == ESM::ItemLevList::sRecordId) - return getLevelledItem(ref.getPtr().get()->mBase, false, seed); + return getLevelledItem(ref.getPtr().get()->mBase, false, prng); else - return getLevelledItem(ref.getPtr().get()->mBase, true, seed); + return getLevelledItem(ref.getPtr().get()->mBase, true, prng); } } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 1bed36bf9c..a096231f2d 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -514,12 +514,12 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor return count - toRemove; } -void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Seed& seed) +void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Generator& prng) { for (const ESM::ContItem& iter : items.mList) { std::string id = Misc::StringUtils::lowerCase(iter.mItem); - addInitialItem(id, owner, iter.mCount, &seed); + addInitialItem(id, owner, iter.mCount, &prng); } flagAsModified(); @@ -540,7 +540,7 @@ void MWWorld::ContainerStore::fillNonRandom (const ESM::InventoryList& items, co } void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, - Misc::Rng::Seed* seed, bool topLevel) + Misc::Rng::Generator* prng, bool topLevel) { if (count == 0) return; //Don't restock with nothing. try @@ -548,13 +548,13 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); if (ref.getPtr().getClass().getScript(ref.getPtr()).empty()) { - addInitialItemImp(ref.getPtr(), owner, count, seed, topLevel); + addInitialItemImp(ref.getPtr(), owner, count, prng, topLevel); } else { // Adding just one item per time to make sure there isn't a stack of scripted items for (int i = 0; i < std::abs(count); i++) - addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, seed, topLevel); + addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, prng, topLevel); } } catch (const std::exception& e) @@ -564,26 +564,26 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: } void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const std::string& owner, int count, - Misc::Rng::Seed* seed, bool topLevel) + Misc::Rng::Generator* prng, bool topLevel) { if (ptr.getType()==ESM::ItemLevList::sRecordId) { - if(!seed) + if(!prng) return; const ESM::ItemLevList* levItemList = ptr.get()->mBase; if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each) { for (int i=0; i 0 ? 1 : -1, seed, true); + addInitialItem(ptr.getCellRef().getRefId(), owner, count > 0 ? 1 : -1, prng, true); return; } else { - std::string itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false, *seed); + std::string itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false, *prng); if (itemId.empty()) return; - addInitialItem(itemId, owner, count, seed, false); + addInitialItem(itemId, owner, count, prng, false); } } else @@ -619,8 +619,8 @@ void MWWorld::ContainerStore::resolve() { for(const auto&& ptr : *this) ptr.getRefData().setCount(0); - Misc::Rng::Seed seed{mSeed}; - fill(mPtr.get()->mBase->mInventory, "", seed); + Misc::Rng::Generator prng{mSeed}; + fill(mPtr.get()->mBase->mInventory, "", prng); addScripts(*this, mPtr.mCell); } mModified = true; @@ -640,8 +640,8 @@ MWWorld::ResolutionHandle MWWorld::ContainerStore::resolveTemporarily() { for(const auto&& ptr : *this) ptr.getRefData().setCount(0); - Misc::Rng::Seed seed{mSeed}; - fill(mPtr.get()->mBase->mInventory, "", seed); + Misc::Rng::Generator prng{mSeed}; + fill(mPtr.get()->mBase->mInventory, "", prng); addScripts(*this, mPtr.mCell); } return {listener}; diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index ef0d7b5e57..1951f0708e 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -126,8 +126,8 @@ namespace MWWorld std::weak_ptr mResolutionListener; ContainerStoreIterator addImp (const Ptr& ptr, int count, bool markModified = true); - void addInitialItem (const std::string& id, const std::string& owner, int count, Misc::Rng::Seed* seed, bool topLevel=true); - void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, Misc::Rng::Seed* seed, bool topLevel=true); + void addInitialItem (const std::string& id, const std::string& owner, int count, Misc::Rng::Generator* prng, bool topLevel=true); + void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, Misc::Rng::Generator* prng, bool topLevel=true); template ContainerStoreIterator getState (CellRefList& collection, @@ -221,7 +221,7 @@ namespace MWWorld virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const; ///< @return true if the two specified objects can stack with each other - void fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Seed& seed = Misc::Rng::getSeed()); + void fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Generator& seed = Misc::Rng::getGenerator()); ///< Insert items into *this. void fillNonRandom (const ESM::InventoryList& items, const std::string& owner, unsigned int seed); diff --git a/components/misc/rng.cpp b/components/misc/rng.cpp index 113e7b1d5b..78c2a44434 100644 --- a/components/misc/rng.cpp +++ b/components/misc/rng.cpp @@ -3,50 +3,42 @@ #include #include -namespace +namespace Misc::Rng { - Misc::Rng::Seed sSeed; -} - -namespace Misc -{ - Rng::Seed::Seed(unsigned int seed) - { - mGenerator.seed(seed); - } + static Generator sGenerator; - Rng::Seed& Rng::getSeed() + Generator& getGenerator() { - return sSeed; + return sGenerator; } - void Rng::init(unsigned int seed) + void init(unsigned int seed) { - sSeed.mGenerator.seed(seed); + sGenerator.seed(seed); } - float Rng::rollProbability(Seed& seed) + float rollProbability(Generator& prng) { - return std::uniform_real_distribution(0, 1 - std::numeric_limits::epsilon())(seed.mGenerator); + return std::uniform_real_distribution(0, 1 - std::numeric_limits::epsilon())(prng); } - float Rng::rollClosedProbability(Seed& seed) + float rollClosedProbability(Generator& prng) { - return std::uniform_real_distribution(0, 1)(seed.mGenerator); + return std::uniform_real_distribution(0, 1)(prng); } - int Rng::rollDice(int max, Seed& seed) + int rollDice(int max, Generator& prng) { - return max > 0 ? std::uniform_int_distribution(0, max - 1)(seed.mGenerator) : 0; + return max > 0 ? std::uniform_int_distribution(0, max - 1)(prng) : 0; } - unsigned int Rng::generateDefaultSeed() + unsigned int generateDefaultSeed() { return static_cast(std::chrono::high_resolution_clock::now().time_since_epoch().count()); } - float Rng::deviate(float mean, float deviation, Seed& seed) + float deviate(float mean, float deviation, Generator& prng) { - return std::uniform_real_distribution(mean - deviation, mean + deviation)(seed.mGenerator); + return std::uniform_real_distribution(mean - deviation, mean + deviation)(prng); } } diff --git a/components/misc/rng.hpp b/components/misc/rng.hpp index 06e94897be..8d300f0913 100644 --- a/components/misc/rng.hpp +++ b/components/misc/rng.hpp @@ -4,47 +4,35 @@ #include #include -namespace Misc -{ - /* Provides central implementation of the RNG logic */ -class Rng +namespace Misc::Rng { -public: - class Seed - { - std::mt19937 mGenerator; - public: - Seed() = default; - Seed(const Seed&) = delete; - Seed(unsigned int seed); - friend class Rng; - }; - - static Seed& getSeed(); + + using Generator = std::mt19937; + + Generator& getGenerator(); + + /// returns default seed for RNG + unsigned int generateDefaultSeed(); /// seed the RNG - static void init(unsigned int seed = generateDefaultSeed()); + void init(unsigned int seed = generateDefaultSeed()); /// return value in range [0.0f, 1.0f) <- note open upper range. - static float rollProbability(Seed& seed = getSeed()); + float rollProbability(Generator& prng = getGenerator()); /// return value in range [0.0f, 1.0f] <- note closed upper range. - static float rollClosedProbability(Seed& seed = getSeed()); + float rollClosedProbability(Generator& prng = getGenerator()); /// return value in range [0, max) <- note open upper range. - static int rollDice(int max, Seed& seed = getSeed()); + int rollDice(int max, Generator& prng = getGenerator()); /// return value in range [0, 99] - static int roll0to99(Seed& seed = getSeed()) { return rollDice(100, seed); } - - /// returns default seed for RNG - static unsigned int generateDefaultSeed(); + inline int roll0to99(Generator& prng = getGenerator()) { return rollDice(100, prng); } - static float deviate(float mean, float deviation, Seed& seed = getSeed()); -}; + float deviate(float mean, float deviation, Generator& prng = getGenerator()); }