1 /*
2  *  Open Fodder
3  *  ---------------
4  *
5  *  Copyright (C) 2008-2018 Open Fodder
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License along
18  *  with this program; if not, write to the Free Software Foundation, Inc.,
19  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22 
23 class cPseudorand {
24 private:
25 	int16 mRandom_0;
26 	int16 mRandom_1;
27 	int16 mRandom_2;
28 	int16 mRandom_3;
29 
30 	int16 mStartingSeed;
31 public:
32 
cPseudorand(int16 pSeed=0)33 	cPseudorand(int16 pSeed = 0) {
34 		if (!pSeed) {
35 			const time_t now = time(0);
36 			tm* ltm;
37 #ifndef _WIN32
38 			ltm = localtime(&now);
39 #else
40 			ltm = new tm();
41 			localtime_s(ltm, &now);
42 #endif
43 			pSeed = tool_DecimalToBinaryCodedDecimal(ltm->tm_sec);
44 			pSeed |= tool_DecimalToBinaryCodedDecimal(ltm->tm_min) << 8;
45 			pSeed += 0x40B;
46 #ifdef _WIN32
47 			delete ltm;
48 #endif
49 		}
50 		setSeed(pSeed);
51 	}
52 
setSeed(int16 pSeed)53 	void setSeed(int16 pSeed) {
54 		mStartingSeed = pSeed;
55 
56 		mRandom_0 = mStartingSeed;
57 		mRandom_1 = -mStartingSeed;
58 		mRandom_2 = 1;
59 		mRandom_3 = 0;
60 	}
61 
setSeed(int16 pSeed0,int16 pSeed1,int16 pSeed2,int16 pSeed3)62 	void setSeed(int16 pSeed0, int16 pSeed1, int16 pSeed2, int16 pSeed3 ) {
63 		mStartingSeed = 0;
64 
65 		mRandom_0 = pSeed0;
66 		mRandom_1 = pSeed1;
67 		mRandom_2 = pSeed2;
68 		mRandom_3 = pSeed3;
69 	}
70 
getSeeds(int16 & pSeed0,int16 & pSeed1,int16 & pSeed2,int16 & pSeed3)71 	void getSeeds(int16& pSeed0, int16& pSeed1, int16& pSeed2, int16& pSeed3) {
72 		pSeed0 = mRandom_0;
73 		pSeed1 = mRandom_1;
74 		pSeed2 = mRandom_2;
75 		pSeed3 = mRandom_3;
76 	}
77 
getStartingSeed() const78 	int16 getStartingSeed() const {
79 		return mStartingSeed;
80 	}
81 
82 
getf(float pMin,float pMax)83 	float getf(float pMin, float pMax) {
84 
85 		return pMin + static_cast <float> (getu() % RAND_MAX) / (static_cast <float> (RAND_MAX) / (pMax - pMin));
86 	}
87 
getu()88 	uint16 getu() {
89 		return (uint16)get();
90 	}
91 
getu(size_t pMin,size_t pMax)92 	uint16 getu(size_t pMin, size_t pMax) {
93 		return (uint16)(pMin + (getu() % static_cast<int>(pMax - pMin + 1)));
94 	}
95 
get()96 	int16 get() {
97 		int16 Data0 = mRandom_0;
98 		int16 Data2 = mRandom_1;
99 		int16 Data4 = mRandom_2;
100 		int16 Data6 = mRandom_3;
101 
102 		uint32 Dat4 = Data4 | (Data6 << 16);
103 		uint8 CF = Data4 & 1;
104 		uint32 Data8 = Data0 | (Data2 << 16);
105 
106 		uint8 CF2 = Data8 & 1;
107 		Data8 >>= 1;
108 
109 		if (CF)
110 			Data8 |= 0x80000000;
111 
112 		Dat4 += CF2;
113 		Data4 = Dat4 & 0xFFFF;
114 		Data6 = Dat4 >> 16;
115 
116 		for (uint16 cx = 0x0C; cx > 0; --cx) {
117 			CF = 0;
118 
119 			if (Data0 & 0x8000)
120 				CF = 1;
121 			Data0 <<= 1;
122 			Data2 <<= 1;
123 			if (CF)
124 				Data2 |= 1;
125 		}
126 
127 		int16 DataA = Data8 >> 16;
128 
129 		Data0 ^= Data8 & 0xFFFF;
130 		Data2 ^= DataA;
131 		Data8 = Data0;
132 		DataA = Data2;
133 
134 		int16 ax = Data8;
135 		int16 bx = DataA;
136 		Data8 = bx;
137 		DataA = ax;
138 
139 		Data8 >>= 4;
140 		Data0 ^= Data8;
141 
142 		mRandom_0 = Data0;
143 		mRandom_1 = Data2;
144 		mRandom_2 = Data4;
145 		mRandom_3 = Data6;
146 		return Data0;
147 	}
148 };