TrinityCore
Loading...
Searching...
No Matches
Random.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Random.h"
19#include "Errors.h"
20#include "SFMTRand.h"
21#include <boost/math/tools/roots.hpp>
22#include <memory>
23#include <random>
24
25namespace
26{
27constexpr RandomEngine engine;
28
29SFMTRand* GetRng() noexcept
30{
31 thread_local std::unique_ptr<SFMTRand> sfmtRand = std::make_unique<SFMTRand>();
32 return sfmtRand.get();
33}
34}
35
37{
38 ASSERT(max >= min);
39 std::uniform_int_distribution<int32> uid(min, max);
40 return uid(engine);
41}
42
44{
45 ASSERT(max >= min);
46 std::uniform_int_distribution<uint32> uid(min, max);
47 return uid(engine);
48}
49
51{
52 ASSERT(std::numeric_limits<uint32>::max() / Milliseconds::period::den >= max);
53 return urand(min * Milliseconds::period::den, max * Milliseconds::period::den);
54}
55
56float frand(float min, float max)
57{
58 ASSERT(max >= min);
59 std::uniform_real_distribution<float> urd(min, max);
60 return urd(engine);
61}
62
64{
65 long long diff = max.count() - min.count();
66 ASSERT(diff >= 0);
67 ASSERT(diff <= 0xFFFFFFFF);
68 return min + Milliseconds(urand(0, uint32(diff)));
69}
70
72{
73 return GetRng()->RandomUInt32();
74}
75
76float rand_norm()
77{
78 std::uniform_real_distribution<float> urd;
79 return urd(engine);
80}
81
83{
84 std::uniform_real_distribution<float> urd(0.0f, 100.0f);
85 return urd(engine);
86}
87
88uint32 urandweighted(size_t count, double const* chances)
89{
90 std::discrete_distribution<uint32> dd(chances, chances + count);
91 return dd(engine);
92}
93
94namespace
95{
96struct PseudoRandomDistributionChanceTable : std::array<float, 10000>
97{
98 PseudoRandomDistributionChanceTable()
99 {
100 (*this)[0] = 0.0f;
101 for (std::size_t i = 1; i < size(); ++i)
102 (*this)[i] = NormalizePseudoRandomDistributionChance(i * 0.0001f);
103 }
104
105 static float NormalizePseudoRandomDistributionChance(float chance)
106 {
107 std::uintptr_t iterationLimit = 10;
108 return boost::math::tools::newton_raphson_iterate([target = 1.0f / chance](float p) -> std::pair<float, float>
109 {
110 // (value, derivative) pairs
111 std::pair<float, float> chain = { 1.0f, 0.0f };
112 std::pair<float, float> result = { 1.0f - target, 0.0f };
113
114 uint32 cap = uint32(std::ceil(1.0f / p));
115 for (uint32 i = 1; i < cap; ++i)
116 {
117 float chanceToFail = 1 - p * i;
118 chain.second = chain.second * chanceToFail - chain.first * i;
119 chain.first = chain.first * chanceToFail;
120
121 result.first += chain.first;
122 result.second += chain.second;
123 }
124
125 return result;
126 }, chance * chance, 0.0f, chance, 6, iterationLimit);
127 }
128} const ChanceCache;
129}
130
132{
133 std::ptrdiff_t chanceIndex = std::ptrdiff_t(std::round(chance * 100.0f));
134 if (chanceIndex < 0)
135 return false;
136
137 if (chanceIndex >= std::ssize(ChanceCache) || state.AccumulateChance(ChanceCache[chanceIndex]) > rand_norm())
138 {
139 state.Reset();
140 return true;
141 }
142
143 return false;
144}
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ASSERT
Definition Errors.h:72
float frand(float min, float max)
Definition Random.cpp:56
uint32 urandweighted(size_t count, double const *chances)
Definition Random.cpp:88
int32 irand(int32 min, int32 max)
Definition Random.cpp:36
float rand_chance()
Definition Random.cpp:82
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition Random.cpp:63
float rand_norm()
Definition Random.cpp:76
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
uint32 rand32()
Definition Random.cpp:71
uint32 urandms(uint32 min, uint32 max)
Definition Random.cpp:50
constexpr std::size_t size()
float AccumulateChance(float progress)
Definition Random.h:89