The Battle for Wesnoth  1.19.5+dev
random.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
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  * @return The index of the selected number
73  */
74  template <typename T>
75  typename T::difference_type 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  typename T::difference_type 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 }
this class does not give synced random results derived classes might do.
Definition: random.hpp:28
virtual ~rng()
Definition: random.cpp:68
unsigned int get_random_calls() const
Provides the number of random calls to the rng in this context.
Definition: random.cpp:79
uint32_t next_random()
Provides the next random draw.
Definition: random.cpp:84
static rng & default_instance()
Definition: random.cpp:73
std::numeric_limits< uint32_t > base
Definition: random.hpp:29
T::difference_type 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
uint32_t result_type
Definition: random.hpp:78
virtual uint32_t next_random_impl()=0
unsigned int random_calls_
Definition: random.hpp:93
virtual bool is_networked() const
Is this random source networked? If it is it's very important we do actually use this random source t...
Definition: random.hpp:89
int get_random_int(int min, int max)
Definition: random.hpp:51
bool get_random_bool(double probability)
This helper method returns true with the probability supplied as a parameter.
Definition: random.cpp:136
double get_random_double()
This helper method returns a floating-point number in the range [0,1[.
Definition: random.cpp:111
int get_random_int_in_range_zero_to(int max)
Does the hard work of get_random_int.
Definition: random.cpp:105
uint32_t operator()()
Definition: random.hpp:81
rng * generator
This generator is automatically synced during synced context.
Definition: random.cpp:60