The Battle for Wesnoth  1.15.1+dev
random.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include <cstdlib> //needed for RAND_MAX
18 #include <cstdint>
19 #include <iterator> //needed for std::distance
20 #include <limits>
21 
22 namespace randomness
23 {
24  /**
25  this class does not give synced random results derived classes might do.
26  */
27  class rng : private std::numeric_limits<uint32_t>
28  {
29  using base = std::numeric_limits<uint32_t>;
30  public:
31  rng();
32  /**
33  * Provides the next random draw. This is raw PRG output.
34  */
35  uint32_t next_random();
36  virtual ~rng();
37  /**
38  * Provides the number of random calls to the rng in this context.
39  * Note that this may be different from the number of random calls to
40  * the underlying rng, and to the random_calls number in save files!
41  */
42  unsigned int get_random_calls() const;
43 
44  /**
45  * This helper method provides a random int from the underlying generator,
46  * using results of next_random in a manner guaranteed to be cross platform.
47  * The result will be random in range [min,max] inclusive.
48  * @param min The minimum value produced.
49  * @param max The maximum value produced.
50  */
51  int get_random_int(int min, int max)
52  { return min + get_random_int_in_range_zero_to(max - min); }
53 
54  /**
55  * This helper method returns true with the probability supplied as a parameter.
56  * @param probability The probability of returning true, from 0 to 1.
57  */
58  bool get_random_bool(double probability);
59 
60  /**
61  * This helper method returns a floating-point number in the range [0,1[.
62  */
63  double get_random_double();
64 
65  /**
66  * This helper method selects a random element from a container of floating-point numbers.
67  * Every number has a probability to be selected equal to the number itself
68  * (e.g. a number of 0.1 is selected with a probability of 0.1). The sum of numbers
69  * should be one.
70  * @param first Iterator to the beginning of the container
71  * @param last Iterator to the end of the container
72  * @ret The index of the selected number
73  */
74  template <typename T>
75  unsigned int get_random_element(T first, T last);
76 
77  // For compatibility with the C++ UniformRandomBitGenerator concept
78  using result_type = uint32_t;
79  using base::min;
80  using base::max;
81  uint32_t operator()() { return next_random(); }
82 
83  static rng& default_instance();
84 
85  /**
86  * Is this random source networked? If it is it's very important we do actually use
87  * this random source to stay in-sync.
88  */
89  virtual bool is_networked() const { return false; }
90 
91  protected:
92  virtual uint32_t next_random_impl() = 0;
93  unsigned int random_calls_;
94 
95  private:
96  /** Does the hard work of get_random_int.
97  * The result will be random in range [0,max] inclusive.
98  * @param max The maximum value produced.
99  */
100  int get_random_int_in_range_zero_to(int max);
101  };
102 
103  /**
104  This generator is automatically synced during synced context.
105  Calling this rng during a synced context automatically makes undoing impossible.
106  Outside a synced context this has the same effect as rand()
107  */
108  extern rng* generator;
109 
110  template <typename T>
111  unsigned int rng::get_random_element(T first, T last)
112  {
113  double target = get_random_double();
114  double sum = 0.0;
115  T it = first;
116  sum += *it;
117  while (sum <= target)
118  {
119  ++it;
120  if (it != last)
121  {
122  sum += *it;
123  }
124  else
125  {
126  break;
127  }
128  }
129  return std::distance(first, it);
130  }
131 }
virtual bool is_networked() const
Is this random source networked? If it is it&#39;s very important we do actually use this random source t...
Definition: random.hpp:89
int get_random_int_in_range_zero_to(int max)
Does the hard work of get_random_int.
Definition: random.cpp:105
virtual ~rng()
Definition: random.cpp:68
double get_random_double()
This helper method returns a floating-point number in the range [0,1[.
Definition: random.cpp:111
std::numeric_limits< uint32_t > base
Definition: random.hpp:29
unsigned int get_random_calls() const
Provides the number of random calls to the rng in this context.
Definition: random.cpp:79
virtual uint32_t next_random_impl()=0
uint32_t operator()()
Definition: random.hpp:81
unsigned int get_random_element(T first, T last)
This helper method selects a random element from a container of floating-point numbers.
Definition: random.hpp:111
bool get_random_bool(double probability)
This helper method returns true with the probability supplied as a parameter.
Definition: random.cpp:136
uint32_t result_type
Definition: random.hpp:78
int get_random_int(int min, int max)
This helper method provides a random int from the underlying generator, using results of next_random...
Definition: random.hpp:51
rng * generator
This generator is automatically synced during synced context.
Definition: random.cpp:60
unsigned int random_calls_
Definition: random.hpp:93
uint32_t next_random()
Provides the next random draw.
Definition: random.cpp:84
static rng & default_instance()
Definition: random.cpp:73
this class does not give synced random results derived classes might do.
Definition: random.hpp:27