1 #pragma once
2 
3 #include <algorithm>  // iter_swap
4 #include <iterator>   // advance
5 #include <map>
6 #include <vector>
7 
8 #include "debug.h"
9 #include "fixedvector.h"
10 #include "hash.h"
11 #include "rng-type.h"
12 #include "pcg.h"
13 
14 class CrawlVector;
15 
16 namespace rng
17 {
18     class generator
19     {
20     public:
21         generator(rng_type g);
22         generator(branch_type b);
23         ~generator();
24     private:
25         rng_type previous;
26     };
27 
28     class subgenerator
29     {
30     public:
31         subgenerator();
32         subgenerator(uint64_t seed);
33         subgenerator(uint64_t seed, uint64_t sequence);
34         ~subgenerator();
35     private:
36         PcgRNG current;
37         PcgRNG *previous;
38         rng_type previous_main;
39     };
40 
41     rng_type get_branch_generator(const branch_type b);
42     CrawlVector generators_to_vector();
43     void load_generators(const CrawlVector &v);
44     vector<uint64_t> get_states();
45     PcgRNG *get_generator(rng_type r);
46     PcgRNG &current_generator();
47 
48     void seed();
49     void seed(uint64_t seed);
50     void seed(uint64_t[], int);
51     void reset();
52 
53     uint32_t get_uint32(rng_type generator);
54     uint64_t get_uint64(rng_type generator);
55     uint32_t get_uint32();
56     uint64_t get_uint64();
57     uint32_t peek_uint32();
58     uint64_t peek_uint64();
59 
60     class ASSERT_stable
61     {
62     public:
ASSERT_stable()63         ASSERT_stable() : initial_peek(peek_uint64()) { }
~ASSERT_stable()64         ~ASSERT_stable()
65         {
66             ASSERT(peek_uint64() == initial_peek);
67         }
68 
69     private:
70         uint64_t initial_peek;
71     };
72 }
73 
74 bool coinflip();
75 int div_rand_round(int num, int den);
76 int rand_round(double x);
77 int div_round_up(int num, int den);
78 bool one_chance_in(int a_million);
79 bool x_chance_in_y(int x, int y);
80 int random2(int max);
81 int maybe_random2(int x, bool random_factor);
82 int maybe_random_div(int nom, int denom, bool random_factor);
83 int maybe_roll_dice(int num, int size, bool random);
84 int random_range(int low, int high);
85 int random_range(int low, int high, int nrolls);
86 double random_real();
87 
88 int random2avg(int max, int rolls);
89 int biased_random2(int max, int n);
90 int random2limit(int max, int limit);
91 int binomial(unsigned n_trials, unsigned trial_prob, unsigned scale = 100);
92 bool bernoulli(double n_trials, double trial_prob);
93 int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage = 2);
94 int roll_dice(int num, int size);
95 bool decimal_chance(double percent);
96 
97 int ui_random(int max);
98 
99 /** Chooses one of the objects passed in at random (by value).
100  *  @return One of the arguments.
101  *
102  *  @note All the arguments must be convertible to the type of the first.
103  */
104 template <typename T, typename... Ts>
random_choose(T first,Ts...rest)105 T random_choose(T first, Ts... rest)
106 {
107     const T elts[] = { first, rest... };
108     return elts[random2(1 + sizeof...(rest))];
109 }
110 
111 /** Chooses one of the objects passed in at random (by reference).
112  *
113  * @return A reference to one of the arguments.
114  *
115  * @note All the arguments must be of a type compatible with the type of the
116  *       first. Specifically, it must be possible to implicitly convert a
117  *       pointer to each argument into the same type as a pointer to the first
118  *       argument. So, for example, if the first argument is non-const, none
119  *       of the subsequent subsequent arguments may be const.
120  */
121 template <typename T, typename... Ts>
random_choose_ref(T & first,Ts &...rest)122 T& random_choose_ref(T& first, Ts&... rest)
123 {
124     return *random_choose(&first, &rest...);
125 }
126 
127 template <typename C>
128 auto random_iterator(C &container) -> decltype(container.begin())
129 {
130     int pos = random2(container.size());
131     auto it = container.begin();
132     advance(it, pos);
133     return it;
134 }
135 
136 /**
137  * Get a random weighted choice.
138  *
139  * Weights are assumed to be non-negative, but are allowed to be zero.
140  * @tparam  V  A map, vector of pairs, etc., with the values of the
141  *             map or the second elements of the pairs being integer
142  *             weights.
143  *
144  * @param   choices  The collection of choice-weight pairs to choose from.
145  *
146  * @return  A pointer to the item in the chosen pair, or nullptr if all
147  *          weights are zero. The pointer is const only if necessary.
148  */
149 template <typename V>
150 auto random_choose_weighted(V &choices) -> decltype(&(begin(choices)->first))
151 {
152     int total = 0;
153     for (const auto &entry : choices)
154         total += entry.second;
155     int r = random2(total);
156     int sum = 0;
157     for (auto &entry : choices)
158     {
159         sum += entry.second;
160         if (sum > r)
161             return &entry.first;
162     }
163     return nullptr;
164 }
165 
166 /**
167  * Get an index for a random weighted choice using a fixed vector of
168  * weights.
169  *
170  * Entries with a weight <= 0 are skipped.
171  * @param choices The fixed vector with weights for each item.
172  *
173  * @return  A index corresponding to the selected item, or -1 if all
174  *          weights were skipped.
175  */
176 template <typename T, int SIZE>
random_choose_weighted(const FixedVector<T,SIZE> & choices)177 int random_choose_weighted(const FixedVector<T, SIZE>& choices)
178 {
179     int total = 0;
180     for (auto weight : choices)
181         if (weight > 0)
182             total += weight;
183 
184     int r = random2(total);
185     int sum = 0;
186     for (int i = 0; i < SIZE; ++i)
187     {
188         if (choices[i] <= 0)
189             continue;
190 
191         sum += choices[i];
192         if (sum > r)
193             return i;
194     }
195     return -1;
196 }
197 
198 template <typename T>
random_choose_weighted(int,T curr)199 T random_choose_weighted(int, T curr)
200 {
201     return curr;
202 }
203 
204 template <typename T, typename... Args>
random_choose_weighted(int cweight,T curr,int nweight,T next,Args...args)205 T random_choose_weighted(int cweight, T curr, int nweight, T next, Args... args)
206 {
207     return random_choose_weighted<T>(cweight + nweight,
208                                      random2(cweight+nweight) < nweight ? next
209                                                                         : curr,
210                                      args...);
211 }
212 
213 struct dice_def
214 {
215     int num;
216     int size;
217 
dice_defdice_def218     constexpr dice_def() : num(0), size(0) {}
dice_defdice_def219     constexpr dice_def(int n, int s) : num(n), size(s) {}
220     int roll() const;
221 };
222 
223 constexpr dice_def CONVENIENT_NONZERO_DAMAGE{42, 1};
224 
225 dice_def calc_dice(int num_dice, int max_damage, bool random = true);
226 
227 // I must be a random-access iterator.
228 template <typename I>
shuffle_array(I begin,I end)229 void shuffle_array(I begin, I end)
230 {
231     size_t n = end - begin;
232     while (n > 1)
233     {
234         const int i = random2(n);
235         n--;
236         iter_swap(begin + i, begin + n);
237     }
238 }
239 
240 template <typename T>
shuffle_array(T & vec)241 void shuffle_array(T &vec)
242 {
243     shuffle_array(begin(vec), end(vec));
244 }
245 
246 template <typename T>
shuffle_array(T * arr,int n)247 void shuffle_array(T *arr, int n)
248 {
249     shuffle_array(arr, arr + n);
250 }
251 
252 /**
253  * A defer_rand object represents an infinite tree of random values, allowing
254  * for a much more functional approach to randomness. defer_rand values which
255  * have been used should not be copy-constructed. Querying the same path
256  * multiple times will always give the same result.
257  *
258  * An important property of defer_rand is that, except for rounding,
259  * `float(r.random2(X)) / X == float(r.random2(Y)) / Y` for all `X` and `Y`.
260  * In other words:
261  *
262  * - The parameter you use on any given call does not matter.
263  * - The object stores the fraction, not a specific integer.
264  * - random2() is monotonic in its argument.
265  *
266  * Rephrased: The first time any node in the tree has a method called on
267  * it, a random float between 0 and 1 (the fraction) is generated and stored,
268  * and this float is combined with the method's parameters to arrive at
269  * the result. Calling the same method on the same node with the same
270  * parameters will always give the same result, while different parameters
271  * or methods will give different results (though they'll all use the same
272  * float which was generated by the first method call). Each node in the
273  * tree has it's own float, so the same method+parameters on different
274  * nodes will get different results.
275  */
276 class defer_rand
277 {
278     vector<uint32_t> bits;
279     map<int, defer_rand> children;
280 
281     bool x_chance_in_y_contd(int x, int y, int index);
282 public:
283     // TODO It would probably be a good idea to have some sort of random
284     // number generator API, and the ability to pass RNGs into any function
285     // that wants them.
x_chance_in_y(int x,int y)286     bool x_chance_in_y(int x, int y) { return x_chance_in_y_contd(x,y,0); }
one_chance_in(int a_million)287     bool one_chance_in(int a_million) { return x_chance_in_y(1,a_million); }
288     int random2(int maxp1);
289 
290     int random_range(int low, int high);
291     int random2avg(int max, int rolls);
292 
293     defer_rand& operator[] (int i);
294 };
295 
296 template<typename Iterator>
choose_random_weighted(Iterator beg,const Iterator end)297 int choose_random_weighted(Iterator beg, const Iterator end)
298 {
299     int totalweight = 0;
300     int result = -1;
301     for (int count = 0; beg != end; ++count, ++beg)
302     {
303         totalweight += *beg;
304         if (random2(totalweight) < *beg)
305             result = count;
306     }
307     ASSERT(result >= 0);
308     return result;
309 }
310