aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/Utilities/Containers.h (renamed from src/server/shared/Containers.h)49
-rw-r--r--src/common/Utilities/Random.cpp83
-rw-r--r--src/common/Utilities/Random.h72
-rw-r--r--src/common/Utilities/Util.cpp57
-rw-r--r--src/common/Utilities/Util.h34
5 files changed, 200 insertions, 95 deletions
diff --git a/src/server/shared/Containers.h b/src/common/Utilities/Containers.h
index 685acea05e3..df97e342932 100644
--- a/src/server/shared/Containers.h
+++ b/src/common/Utilities/Containers.h
@@ -19,10 +19,10 @@
#define TRINITY_CONTAINERS_H
#include "Define.h"
+#include "Random.h"
+#include <functional>
#include <list>
-
-//! Because circular includes are bad
-extern uint32 urand(uint32 min, uint32 max);
+#include <vector>
namespace Trinity
{
@@ -57,14 +57,53 @@ namespace Trinity
list = listCopy;
}
- /* Select a random element from a container. Note: make sure you explicitly empty check the container */
- template <class C> typename C::value_type const& SelectRandomContainerElement(C const& container)
+ /*
+ * Select a random element from a container.
+ *
+ * Note: container cannot be empty
+ */
+ template <class C>
+ typename C::value_type const& SelectRandomContainerElement(C const& container)
{
typename C::const_iterator it = container.begin();
std::advance(it, urand(0, uint32(container.size()) - 1));
return *it;
}
+ /*
+ * Select a random element from a container where each element has a different chance to be selected.
+ *
+ * @param container Container to select an element from
+ * @param weightExtractor Function retrieving chance of each element in container
+ *
+ * Note: container cannot be empty
+ */
+ template <class C>
+ typename C::const_iterator SelectRandomWeightedContainerElement(C const& container, std::function<double(typename C::value_type const&)> weightExtractor)
+ {
+ std::vector<double> weights;
+ weights.reserve(container.size());
+ std::transform(container.begin(), container.end(), std::back_inserter(weights), weightExtractor);
+ return SelectRandomWeightedContainerElement(container, weights);
+ }
+
+ /*
+ * Select a random element from a container where each element has a different chance to be selected.
+ *
+ * @param container Container to select an element from
+ * @param weights Chances of each element to be selected, must be in the same order as elements in container
+ *
+ * Note: container cannot be empty
+ */
+ template <class C>
+ typename C::const_iterator SelectRandomWeightedContainerElement(C const& container, std::vector<double> weights)
+ {
+ std::discrete_distribution<uint32> dd(weights.begin(), weights.end());
+ typename C::const_iterator it = container.begin();
+ std::advance(it, dd(SFMTEngine::Instance()));
+ return it;
+ }
+
/**
* @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
*
diff --git a/src/common/Utilities/Random.cpp b/src/common/Utilities/Random.cpp
new file mode 100644
index 00000000000..cc013110b01
--- /dev/null
+++ b/src/common/Utilities/Random.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Random.h"
+#include "Common.h"
+#include "Errors.h"
+#include "SFMT.h"
+#include <boost/thread/tss.hpp>
+
+static boost::thread_specific_ptr<SFMTRand> sfmtRand;
+
+static SFMTRand* GetRng()
+{
+ SFMTRand* rand = sfmtRand.get();
+
+ if (!rand)
+ {
+ rand = new SFMTRand();
+ sfmtRand.reset(rand);
+ }
+
+ return rand;
+}
+
+int32 irand(int32 min, int32 max)
+{
+ ASSERT(max >= min);
+ return int32(GetRng()->IRandom(min, max));
+}
+
+uint32 urand(uint32 min, uint32 max)
+{
+ ASSERT(max >= min);
+ return GetRng()->URandom(min, max);
+}
+
+uint32 urandms(uint32 min, uint32 max)
+{
+ ASSERT(max >= min);
+ ASSERT(INT_MAX / IN_MILLISECONDS >= max);
+ return GetRng()->URandom(min * IN_MILLISECONDS, max * IN_MILLISECONDS);
+}
+
+float frand(float min, float max)
+{
+ ASSERT(max >= min);
+ return float(GetRng()->Random() * (max - min) + min);
+}
+
+uint32 rand32()
+{
+ return GetRng()->BRandom();
+}
+
+double rand_norm()
+{
+ return GetRng()->Random();
+}
+
+double rand_chance()
+{
+ return GetRng()->Random() * 100.0;
+}
+
+SFMTEngine& SFMTEngine::Instance()
+{
+ static SFMTEngine engine;
+ return engine;
+}
diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h
new file mode 100644
index 00000000000..c919c28bcc8
--- /dev/null
+++ b/src/common/Utilities/Random.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef Random_h__
+#define Random_h__
+
+#include "Define.h"
+#include <random>
+
+/* Return a random number in the range min..max. */
+int32 irand(int32 min, int32 max);
+
+/* Return a random number in the range min..max (inclusive). */
+uint32 urand(uint32 min, uint32 max);
+
+/* Return a random millisecond value between min and max seconds. Functionally equivalent to urand(min*IN_MILLISECONDS, max*IN_MILLISECONDS). */
+uint32 urandms(uint32 min, uint32 max);
+
+/* Return a random number in the range 0 .. UINT32_MAX. */
+uint32 rand32();
+
+/* Return a random number in the range min..max */
+float frand(float min, float max);
+
+/* Return a random double from 0.0 to 1.0 (exclusive). */
+double rand_norm();
+
+/* Return a random double from 0.0 to 100.0 (exclusive). */
+double rand_chance();
+
+/* Return true if a random roll fits in the specified chance (range 0-100). */
+inline bool roll_chance_f(float chance)
+{
+ return chance > rand_chance();
+}
+
+/* Return true if a random roll fits in the specified chance (range 0-100). */
+inline bool roll_chance_i(int chance)
+{
+ return chance > irand(0, 99);
+}
+
+/*
+* SFMT wrapper satisfying UniformRandomNumberGenerator concept for use in <random> algorithms
+*/
+class SFMTEngine
+{
+public:
+ typedef uint32 result_type;
+
+ result_type min() const { return std::numeric_limits<result_type>::min(); }
+ result_type max() const { return std::numeric_limits<result_type>::max(); }
+ result_type operator()() const { return rand32(); }
+
+ static SFMTEngine& Instance();
+};
+
+#endif // Random_h__
diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp
index 0488978ae17..21ccb37d6e7 100644
--- a/src/common/Utilities/Util.cpp
+++ b/src/common/Utilities/Util.cpp
@@ -20,10 +20,8 @@
#include "Common.h"
#include "CompilerDefs.h"
#include "utf8.h"
-#include "SFMT.h"
#include "Errors.h" // for ASSERT
#include <stdarg.h>
-#include <boost/thread/tss.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#if COMPILER == COMPILER_GNU
@@ -32,61 +30,6 @@
#include <arpa/inet.h>
#endif
-static boost::thread_specific_ptr<SFMTRand> sfmtRand;
-
-static SFMTRand* GetRng()
-{
- SFMTRand* rand = sfmtRand.get();
-
- if (!rand)
- {
- rand = new SFMTRand();
- sfmtRand.reset(rand);
- }
-
- return rand;
-}
-
-int32 irand(int32 min, int32 max)
-{
- ASSERT(max >= min);
- return int32(GetRng()->IRandom(min, max));
-}
-
-uint32 urand(uint32 min, uint32 max)
-{
- ASSERT(max >= min);
- return GetRng()->URandom(min, max);
-}
-
-uint32 urandms(uint32 min, uint32 max)
-{
- ASSERT(max >= min);
- ASSERT(INT_MAX/IN_MILLISECONDS >= max);
- return GetRng()->URandom(min * IN_MILLISECONDS, max * IN_MILLISECONDS);
-}
-
-float frand(float min, float max)
-{
- ASSERT(max >= min);
- return float(GetRng()->Random() * (max - min) + min);
-}
-
-uint32 rand32()
-{
- return GetRng()->BRandom();
-}
-
-double rand_norm()
-{
- return GetRng()->Random();
-}
-
-double rand_chance()
-{
- return GetRng()->Random() * 100.0;
-}
-
Tokenizer::Tokenizer(const std::string &src, const char sep, uint32 vectorReserve)
{
m_str = new char[src.length() + 1];
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index 468b0201680..4126dc40f56 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -21,6 +21,7 @@
#include "Define.h"
#include "Errors.h"
+#include "Random.h"
#include <algorithm>
#include <string>
@@ -78,39 +79,6 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hou
uint32 TimeStringToSecs(const std::string& timestring);
std::string TimeToTimestampStr(time_t t);
-/* Return a random number in the range min..max. */
-int32 irand(int32 min, int32 max);
-
-/* Return a random number in the range min..max (inclusive). */
-uint32 urand(uint32 min, uint32 max);
-
-/* Return a random millisecond value between min and max seconds. Functionally equivalent to urand(min*IN_MILLISECONDS, max*IN_MILLISECONDS). */
-uint32 urandms(uint32 min, uint32 max);
-
-/* Return a random number in the range 0 .. UINT32_MAX. */
-uint32 rand32();
-
-/* Return a random number in the range min..max */
-float frand(float min, float max);
-
-/* Return a random double from 0.0 to 1.0 (exclusive). */
-double rand_norm();
-
-/* Return a random double from 0.0 to 100.0 (exclusive). */
-double rand_chance();
-
-/* Return true if a random roll fits in the specified chance (range 0-100). */
-inline bool roll_chance_f(float chance)
-{
- return chance > rand_chance();
-}
-
-/* Return true if a random roll fits in the specified chance (range 0-100). */
-inline bool roll_chance_i(int chance)
-{
- return chance > irand(0, 99);
-}
-
inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
{
if (val == -100.0f) // prevent set var to zero