1 //============================================================================
2 //
3 //   SSSS    tt          lll  lll
4 //  SS  SS   tt           ll   ll
5 //  SS     tttttt  eeee   ll   ll   aaaa
6 //   SSSS    tt   ee  ee  ll   ll      aa
7 //      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
8 //  SS  SS   tt   ee      ll   ll  aa  aa
9 //   SSSS     ttt  eeeee llll llll  aaaaa
10 //
11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //============================================================================
17 
18 #ifndef RANDOM_HXX
19 #define RANDOM_HXX
20 
21 #include <chrono>
22 
23 #include "bspf.hxx"
24 #include "Serializable.hxx"
25 
26 /**
27   This is a quick-and-dirty random number generator.  It is based on
28   information in Chapter 7 of "Numerical Recipes in C".  It's a simple
29   linear congruential generator.
30 
31   @author  Bradford W. Mott
32 */
33 class Random : public Serializable
34 {
35   public:
36     /**
37       Create a new random number generator with seed based on system time.
38     */
Random()39     explicit Random() {
40       initSeed(static_cast<uInt32>(std::chrono::system_clock::now().time_since_epoch().count()));
41     }
42 
43     /**
44       Create a new random number generator with given seed.
45     */
Random(uInt32 seed)46     explicit Random(uInt32 seed) { initSeed(seed); }
47 
48     /**
49       Re-initialize the random number generator with a new seed,
50       to generate a different set of random numbers.
51     */
initSeed(uInt32 seed)52     void initSeed(uInt32 seed)
53     {
54       myValue = seed;
55     }
56 
57     /**
58       Answer the next random number from the random number generator.
59 
60       @return A random number
61     */
next() const62     uInt32 next() const
63     {
64       return (myValue = (myValue * 2416 + 374441) % 1771875);
65     }
66 
67     /**
68       Save the current state of this device to the given Serializer.
69 
70       @param out  The Serializer object to use
71       @return  False on any errors, else true
72     */
save(Serializer & out) const73     bool save(Serializer& out) const override
74     {
75       try
76       {
77         out.putInt(myValue);
78       }
79       catch(...)
80       {
81         cerr << "ERROR: Random::save" << endl;
82         return false;
83       }
84 
85       return true;
86     }
87 
88     /**
89       Load the current state of this device from the given Serializer.
90 
91       @param in  The Serializer object to use
92       @return  False on any errors, else true
93     */
load(Serializer & in)94     bool load(Serializer& in) override
95     {
96       try
97       {
98         myValue = in.getInt();
99       }
100       catch(...)
101       {
102         cerr << "ERROR: Random::load" << endl;
103         return false;
104       }
105 
106       return true;
107     }
108 
109   private:
110     // Indicates the next random number
111     // We make this mutable, since it's not immediately obvious that
112     // calling next() should change internal state (ie, the *logical*
113     // state of the object shouldn't change just by asking for another
114     // random number)
115     mutable uInt32 myValue{0};
116 
117   private:
118     // Following constructors and assignment operators not supported
119     Random(const Random&) = delete;
120     Random(Random&&) = delete;
121     Random& operator=(const Random&) = delete;
122     Random& operator=(Random&&) = delete;
123 };
124 
125 #endif
126