mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-05 15:55:45 +00:00
Refactor and rename some things around Misc::Rng
This commit is contained in:
parent
9396cc7592
commit
d83a381f79
@ -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<ESM::LevelledListBase::LevelItem>& 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<std::string> 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<ESM::ItemLevList>()->mBase, false, seed);
|
||||
return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false, prng);
|
||||
else
|
||||
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, seed);
|
||||
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, prng);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<ESM::ItemLevList>()->mBase;
|
||||
|
||||
if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each)
|
||||
{
|
||||
for (int i=0; i<std::abs(count); ++i)
|
||||
addInitialItem(ptr.getCellRef().getRefId(), owner, count > 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<ESM::ItemLevList>()->mBase, false, *seed);
|
||||
std::string itemId = MWMechanics::getLevelledItem(ptr.get<ESM::ItemLevList>()->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<ESM::Container>()->mBase->mInventory, "", seed);
|
||||
Misc::Rng::Generator prng{mSeed};
|
||||
fill(mPtr.get<ESM::Container>()->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<ESM::Container>()->mBase->mInventory, "", seed);
|
||||
Misc::Rng::Generator prng{mSeed};
|
||||
fill(mPtr.get<ESM::Container>()->mBase->mInventory, "", prng);
|
||||
addScripts(*this, mPtr.mCell);
|
||||
}
|
||||
return {listener};
|
||||
|
@ -126,8 +126,8 @@ namespace MWWorld
|
||||
std::weak_ptr<ResolutionListener> 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<typename T>
|
||||
ContainerStoreIterator getState (CellRefList<T>& 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);
|
||||
|
@ -3,50 +3,42 @@
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
|
||||
namespace
|
||||
namespace Misc::Rng
|
||||
{
|
||||
Misc::Rng::Seed sSeed;
|
||||
}
|
||||
static Generator sGenerator;
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
Rng::Seed::Seed(unsigned int seed)
|
||||
Generator& getGenerator()
|
||||
{
|
||||
mGenerator.seed(seed);
|
||||
return sGenerator;
|
||||
}
|
||||
|
||||
Rng::Seed& Rng::getSeed()
|
||||
void init(unsigned int seed)
|
||||
{
|
||||
return sSeed;
|
||||
sGenerator.seed(seed);
|
||||
}
|
||||
|
||||
void Rng::init(unsigned int seed)
|
||||
float rollProbability(Generator& prng)
|
||||
{
|
||||
sSeed.mGenerator.seed(seed);
|
||||
return std::uniform_real_distribution<float>(0, 1 - std::numeric_limits<float>::epsilon())(prng);
|
||||
}
|
||||
|
||||
float Rng::rollProbability(Seed& seed)
|
||||
float rollClosedProbability(Generator& prng)
|
||||
{
|
||||
return std::uniform_real_distribution<float>(0, 1 - std::numeric_limits<float>::epsilon())(seed.mGenerator);
|
||||
return std::uniform_real_distribution<float>(0, 1)(prng);
|
||||
}
|
||||
|
||||
float Rng::rollClosedProbability(Seed& seed)
|
||||
int rollDice(int max, Generator& prng)
|
||||
{
|
||||
return std::uniform_real_distribution<float>(0, 1)(seed.mGenerator);
|
||||
return max > 0 ? std::uniform_int_distribution<int>(0, max - 1)(prng) : 0;
|
||||
}
|
||||
|
||||
int Rng::rollDice(int max, Seed& seed)
|
||||
{
|
||||
return max > 0 ? std::uniform_int_distribution<int>(0, max - 1)(seed.mGenerator) : 0;
|
||||
}
|
||||
|
||||
unsigned int Rng::generateDefaultSeed()
|
||||
unsigned int generateDefaultSeed()
|
||||
{
|
||||
return static_cast<unsigned int>(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<float>(mean - deviation, mean + deviation)(seed.mGenerator);
|
||||
return std::uniform_real_distribution<float>(mean - deviation, mean + deviation)(prng);
|
||||
}
|
||||
}
|
||||
|
@ -4,47 +4,35 @@
|
||||
#include <cassert>
|
||||
#include <random>
|
||||
|
||||
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;
|
||||
|
||||
/// seed the RNG
|
||||
static void init(unsigned int seed = generateDefaultSeed());
|
||||
|
||||
/// return value in range [0.0f, 1.0f) <- note open upper range.
|
||||
static float rollProbability(Seed& seed = getSeed());
|
||||
|
||||
/// return value in range [0.0f, 1.0f] <- note closed upper range.
|
||||
static float rollClosedProbability(Seed& seed = getSeed());
|
||||
|
||||
/// return value in range [0, max) <- note open upper range.
|
||||
static int rollDice(int max, Seed& seed = getSeed());
|
||||
|
||||
/// return value in range [0, 99]
|
||||
static int roll0to99(Seed& seed = getSeed()) { return rollDice(100, seed); }
|
||||
Generator& getGenerator();
|
||||
|
||||
/// returns default seed for RNG
|
||||
static unsigned int generateDefaultSeed();
|
||||
unsigned int generateDefaultSeed();
|
||||
|
||||
static float deviate(float mean, float deviation, Seed& seed = getSeed());
|
||||
};
|
||||
/// seed the RNG
|
||||
void init(unsigned int seed = generateDefaultSeed());
|
||||
|
||||
/// return value in range [0.0f, 1.0f) <- note open upper range.
|
||||
float rollProbability(Generator& prng = getGenerator());
|
||||
|
||||
/// return value in range [0.0f, 1.0f] <- note closed upper range.
|
||||
float rollClosedProbability(Generator& prng = getGenerator());
|
||||
|
||||
/// return value in range [0, max) <- note open upper range.
|
||||
int rollDice(int max, Generator& prng = getGenerator());
|
||||
|
||||
/// return value in range [0, 99]
|
||||
inline int roll0to99(Generator& prng = getGenerator()) { return rollDice(100, prng); }
|
||||
|
||||
float deviate(float mean, float deviation, Generator& prng = getGenerator());
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user