aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Define.h6
-rw-r--r--src/common/Utilities/Containers.h (renamed from src/server/shared/Containers.h)61
-rw-r--r--src/common/Utilities/Random.cpp83
-rw-r--r--src/common/Utilities/Random.h95
-rw-r--r--src/common/Utilities/Util.cpp57
-rw-r--r--src/common/Utilities/Util.h34
6 files changed, 241 insertions, 95 deletions
diff --git a/src/common/Define.h b/src/common/Define.h
index df3dd37b503..b34edb6a549 100644
--- a/src/common/Define.h
+++ b/src/common/Define.h
@@ -83,10 +83,16 @@
# define ATTR_NORETURN __attribute__((__noreturn__))
# define ATTR_PRINTF(F, V) __attribute__ ((__format__ (__printf__, F, V)))
# define ATTR_DEPRECATED __attribute__((__deprecated__))
+# define TRINITY_CONSTEXPR constexpr
#else //COMPILER != COMPILER_GNU
# define ATTR_NORETURN
# define ATTR_PRINTF(F, V)
# define ATTR_DEPRECATED
+#if _MSC_VER >= 1900
+# define TRINITY_CONSTEXPR constexpr
+#else
+# define TRINITY_CONSTEXPR
+#endif
#endif //COMPILER == COMPILER_GNU
#define UI64FMTD "%" PRIu64
diff --git a/src/server/shared/Containers.h b/src/common/Utilities/Containers.h
index c2ebbf58a1e..f3e9432ca4c 100644
--- a/src/server/shared/Containers.h
+++ b/src/common/Utilities/Containers.h
@@ -19,10 +19,11 @@
#define TRINITY_CONTAINERS_H
#include "Define.h"
+#include "Random.h"
+#include <algorithm>
+#include <functional>
#include <list>
-
-//! Because circular includes are bad
-extern uint32 urand(uint32 min, uint32 max);
+#include <vector>
namespace Trinity
{
@@ -57,14 +58,64 @@ 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, 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 weights Chances of each element to be selected, must be in the same order as elements in container.
+ * Caller is responsible for checking that sum of all weights is greater than 0.
+ *
+ * Note: container cannot be empty
+ */
+ template <class C>
+ typename C::const_iterator SelectRandomWeightedContainerElement(C const& container, std::vector<double> weights)
+ {
+ Trinity::discrete_distribution_param<uint32> ddParam(weights.begin(), weights.end());
+ std::discrete_distribution<uint32> dd(ddParam);
+ typename C::const_iterator it = container.begin();
+ std::advance(it, dd(SFMTEngine::Instance()));
+ 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, expected to take an element of the container and returning a double
+ *
+ * Note: container cannot be empty
+ */
+ template <class C, class Fn>
+ typename C::const_iterator SelectRandomWeightedContainerElement(C const& container, Fn weightExtractor)
+ {
+ std::vector<double> weights;
+ weights.reserve(container.size());
+ double weightSum = 0.0;
+ for (auto itr = container.begin(); itr != container.end(); ++itr)
+ {
+ double weight = weightExtractor(*itr);
+ weights.push_back(weight);
+ weightSum += weight;
+ }
+ if (weightSum <= 0.0)
+ weights.assign(container.size(), 1.0);
+
+ return SelectRandomWeightedContainerElement(container, weights);
+ }
+
/**
* @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..5610651a83b
--- /dev/null
+++ b/src/common/Utilities/Random.h
@@ -0,0 +1,95 @@
+/*
+ * 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 <limits>
+#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;
+
+ static TRINITY_CONSTEXPR result_type min() { return std::numeric_limits<result_type>::min(); }
+ static TRINITY_CONSTEXPR result_type max() { return std::numeric_limits<result_type>::max(); }
+ result_type operator()() const { return rand32(); }
+
+ static SFMTEngine& Instance();
+};
+
+// Ugly, horrible, i don't even..., hack for VS2013 to work around missing discrete_distribution(iterator, iterator) constructor
+namespace Trinity
+{
+#if COMPILER == COMPILER_MICROSOFT && _MSC_VER <= 1800
+ template<typename T>
+ struct discrete_distribution_param : public std::discrete_distribution<T>::param_type
+ {
+ typedef typename std::discrete_distribution<T>::param_type base;
+
+ template<typename InIt>
+ discrete_distribution_param(InIt begin, InIt end) : base(_Noinit())
+ {
+ this->_Pvec.assign(begin, end);
+ this->_Init();
+ }
+ };
+#else
+ template<typename T>
+ using discrete_distribution_param = typename std::discrete_distribution<T>::param_type;
+#endif
+}
+
+#endif // Random_h__
diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp
index 3eb901ca35d..1360253294f 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>
#if COMPILER == COMPILER_GNU
#include <sys/socket.h>
@@ -31,61 +29,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 1f3b78a8d56..ab5cabca8d2 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>
@@ -77,39 +78,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