1 // ==============================================================
2 //	This file is part of MegaGlest Shared Library (www.megaglest.org)
3 //
4 //	Copyright (C) 2012 Mark Vejvoda, Titus Tscharntke
5 //                2001-2008 Martiño Figueroa
6 //
7 //	You can redistribute this code and/or modify it under
8 //	the terms of the GNU General Public License as published
9 //	by the Free Software Foundation; either version 2 of the
10 //	License, or (at your option) any later version
11 // ==============================================================
12 
13 #include "randomgen.h"
14 #include <cassert>
15 #include "util.h"
16 #include <stdexcept>
17 #include "platform_util.h"
18 #include "math_util.h"
19 #include "leak_dumper.h"
20 
21 using namespace std;
22 using namespace Shared::Graphics;
23 
24 namespace Shared { namespace Util {
25 
26 // =====================================================
27 //	class RandomGen
28 // =====================================================
29 
30 const int RandomGen::m= 714025;
31 const int RandomGen::a= 1366;
32 const int RandomGen::b= 150889;
33 
RandomGen()34 RandomGen::RandomGen() {
35 	lastNumber= 0;
36 	disableLastCallerTracking = false;
37 }
38 
init(int seed)39 void RandomGen::init(int seed){
40 	lastNumber= seed % m;
41 }
42 
rand(string lastCaller)43 int RandomGen::rand(string lastCaller) {
44 	if(lastCaller != "") {
45 		this->lastCaller.push_back(lastCaller);
46 	}
47 	this->lastNumber = (a*lastNumber + b) % m;
48 	return lastNumber;
49 }
50 
getLastCaller() const51 std::string RandomGen::getLastCaller() const {
52 	std::string result = "";
53 	if(lastCaller.empty() == false) {
54 		for(unsigned int index = 0; index < lastCaller.size(); ++index) {
55 			result += lastCaller[index] + "|";
56 		}
57 	}
58 	return result;
59 }
60 
clearLastCaller()61 void RandomGen::clearLastCaller() {
62 	if(lastCaller.empty() == false) {
63 		lastCaller.clear();
64 	}
65 }
addLastCaller(std::string text)66 void RandomGen::addLastCaller(std::string text) {
67 	if(disableLastCallerTracking == false) {
68 		lastCaller.push_back(text);
69 	}
70 }
71 
randRange(int min,int max,string lastCaller)72 int RandomGen::randRange(int min, int max,string lastCaller) {
73 	if(min > max) {
74 		char szBuf[8096]="";
75 		snprintf(szBuf,8096,"In [%s::%s Line: %d] min > max, min = %d, max = %d",__FILE__,__FUNCTION__,__LINE__,min,max);
76 		throw megaglest_runtime_error(szBuf);
77 	}
78 
79 	int diff= max-min;
80 	float numerator = static_cast<float>(diff + 1) * static_cast<float>(this->rand(lastCaller));
81 	int res= min + static_cast<int>(truncateDecimal<float>(numerator / static_cast<float>(m),6));
82 	if(res < min || res > max) {
83 		char szBuf[8096]="";
84 		snprintf(szBuf,8096,"In [%s::%s Line: %d] res < min || res > max, min = %d, max = %d, res = %d",__FILE__,__FUNCTION__,__LINE__,min,max,res);
85 		throw megaglest_runtime_error(szBuf);
86 	}
87 	return res;
88 }
89 
randRange(float min,float max,string lastCaller)90 float RandomGen::randRange(float min, float max,string lastCaller) {
91 	if(min > max) {
92 		char szBuf[8096]="";
93 		snprintf(szBuf,8096,"In [%s::%s Line: %d] min > max, min = %f, max = %f",__FILE__,__FUNCTION__,__LINE__,min,max);
94 		throw megaglest_runtime_error(szBuf);
95 	}
96 
97 	float rand01 = static_cast<float>(this->rand(lastCaller)) / (m-1);
98 	float res= min + (max - min) * rand01;
99 	res = truncateDecimal<float>(res,6);
100 
101 	if(res < min || res > max) {
102 		char szBuf[8096]="";
103 		snprintf(szBuf,8096,"In [%s::%s Line: %d] res < min || res > max, min = %f, max = %f, res = %f",__FILE__,__FUNCTION__,__LINE__,min,max,res);
104 		throw megaglest_runtime_error(szBuf);
105 	}
106 	return res;
107 }
108 
109 }}//end namespace
110