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