moved almost all hardcoded constants to "define.dat"
[k8-i-v-a-n.git] / src / felib / femath.cpp
blobc9d4bbc29a9813227e140479d345dd03dd68564f
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 #include <cmath>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <time.h>
18 #include <unistd.h>
20 #include "femath.h"
21 #include "feerror.h"
22 #include "fesave.h"
23 #include "feparse.h"
26 cint basequadricontroller::OrigoDeltaX[4] = { 0, 1, 0, 1 };
27 cint basequadricontroller::OrigoDeltaY[4] = { 0, 0, 1, 1 };
28 int basequadricontroller::OrigoX, basequadricontroller::OrigoY;
29 int basequadricontroller::StartX, basequadricontroller::StartY;
30 int basequadricontroller::XSize, basequadricontroller::YSize;
31 int basequadricontroller::RadiusSquare;
32 truth basequadricontroller::SectorCompletelyClear;
33 PCG32 femath::prng = PCG32(0x29a, 42);
34 PRNGSeed femath::savedSeed;
37 // ////////////////////////////////////////////////////////////////////////// //
38 void PCG32::rndseed () {
39 seed.state = time(NULL);
40 seed.inc = 1;
41 int fd = open("/dev/urandom", O_RDONLY);
42 if (fd < 0) return;
43 read(fd, &seed.state, sizeof(seed.state));
44 //read(fd, &inc, sizeof(inc));
45 close(fd);
49 // ////////////////////////////////////////////////////////////////////////// //
50 void femath::SetSeed (const PRNGSeed aseed) {
51 prng.setSeed(aseed);
55 void femath::SetSeed (feuLong aseed) {
56 prng.setSeed(aseed);
60 void femath::RandSeed () {
61 prng.rndseed();
65 void femath::SaveSeed () {
66 savedSeed = prng.getSeed();
70 void femath::LoadSeed () {
71 prng.setSeed(savedSeed);
75 sLong femath::Rand () {
76 return (prng.rand32()&0x7FFFFFFF);
80 int femath::WeightedRand (sLong *Possibility, sLong TotalPossibility) {
81 sLong Rand = RAND()%TotalPossibility, PartialSum = 0;
82 for (int c = 0; ; ++c) {
83 PartialSum += Possibility[c];
84 if (PartialSum > Rand) return c;
89 int femath::WeightedRand (const std::vector<sLong> &Possibility, sLong TotalPossibility) {
90 sLong Rand = RAND()%TotalPossibility, PartialSum = 0;
91 for (int c = 0;; ++c) {
92 PartialSum += Possibility[c];
93 if (PartialSum > Rand) return c;
98 double femath::CalculateAngle (v2 Direction) {
99 if (Direction.X < 0) return atan(double(Direction.Y)/Direction.X)+FPI;
100 if (Direction.X > 0) {
101 if (Direction.Y < 0) return atan(double(Direction.Y)/Direction.X)+2*FPI;
102 return atan(double(Direction.Y)/Direction.X);
104 if (Direction.Y < 0) return 3*FPI/2;
105 if (Direction.Y > 0) return FPI/2;
106 ABORT("Illegal direction (0, 0) passed to femath::CalculateAngle()!");
107 return 0;
111 void femath::CalculateEnvironmentRectangle (rect &Rect, const rect &MotherRect, v2 Origo, int Radius) {
112 Rect.X1 = Origo.X-Radius;
113 Rect.Y1 = Origo.Y-Radius;
114 Rect.X2 = Origo.X+Radius;
115 Rect.Y2 = Origo.Y+Radius;
116 if (Rect.X1 < MotherRect.X1) Rect.X1 = MotherRect.X1;
117 if (Rect.Y1 < MotherRect.Y1) Rect.Y1 = MotherRect.Y1;
118 if (Rect.X2 > MotherRect.X2) Rect.X2 = MotherRect.X2;
119 if (Rect.Y2 > MotherRect.Y2) Rect.Y2 = MotherRect.Y2;
123 truth femath::Clip (int &SourceX, int &SourceY, int &DestX, int &DestY, int &Width, int &Height, int XSize, int YSize, int DestXSize, int DestYSize) {
124 /* This sentence is usually true */
125 if (SourceX >= 0 && SourceY >= 0 && DestX >= 0 && DestY >= 0 &&
126 SourceX+Width <= XSize && SourceY+Height <= YSize &&
127 DestX+Width <= DestXSize && DestY+Height <= DestYSize) return true;
128 if (SourceX < 0) {
129 Width += SourceX;
130 DestX -= SourceX;
131 SourceX = 0;
133 if (SourceY < 0) {
134 Height += SourceY;
135 DestY -= SourceY;
136 SourceY = 0;
138 if (DestX < 0) {
139 Width += DestX;
140 SourceX -= DestX;
141 DestX = 0;
143 if (DestY < 0) {
144 Height += DestY;
145 SourceY -= DestY;
146 DestY = 0;
148 if (SourceX+Width > XSize) Width = XSize-SourceX;
149 if (SourceY+Height > YSize) Height = YSize-SourceY;
150 if (DestX+Width > DestXSize) Width = DestXSize-DestX;
151 if (DestY+Height > DestYSize) Height = DestYSize-DestY;
152 return Width>0 && Height>0;
156 void ReadData (interval &I, TextInput &SaveFile) {
157 I.Min = SaveFile.ReadNumber(HIGHEST, true);
158 festring Word;
159 SaveFile.ReadWord(Word);
160 if (Word == ";" || Word == ",") I.Max = I.Min;
161 else if (Word == ":") I.Max = Max(SaveFile.ReadNumber(), I.Min);
162 else ABORT("Odd interval terminator %s detected, file %s line %d!", Word.CStr(), SaveFile.GetFileName().CStr(), SaveFile.TokenLine());
166 void ReadData (region &R, TextInput &SaveFile) {
167 ReadData(R.X, SaveFile);
168 ReadData(R.Y, SaveFile);
172 outputfile &operator << (outputfile &SaveFile, const interval &I) {
173 SaveFile.Write(reinterpret_cast<cchar *>(&I), sizeof(I));
174 return SaveFile;
178 inputfile &operator >> (inputfile &SaveFile, interval &I) {
179 SaveFile.Read(reinterpret_cast<char *>(&I), sizeof(I));
180 return SaveFile;
184 outputfile &operator << (outputfile &SaveFile, const region &R) {
185 SaveFile.Write(reinterpret_cast<cchar *>(&R), sizeof(R));
186 return SaveFile;
190 inputfile &operator >> (inputfile &SaveFile, region &R) {
191 SaveFile.Read(reinterpret_cast<char *>(&R), sizeof(R));
192 return SaveFile;
196 outputfile &operator << (outputfile &SaveFile, const PRNGSeed &R) {
197 SaveFile.Write((cchar *)R.seed, sizeof(R.seed));
198 return SaveFile;
202 inputfile &operator >> (inputfile &SaveFile, PRNGSeed &R) {
203 SaveFile.Read((char *)R.seed, sizeof(R.seed));
204 return SaveFile;
208 void femath::SavePRNG (outputfile &SaveFile) {
209 PRNGSeed seed = prng.getSeed();
210 SaveFile << seed;
214 void femath::LoadPRNG (inputfile &SaveFile) {
215 PRNGSeed seed;
216 SaveFile >> seed;
217 prng.setSeed(seed);
221 sLong femath::SumArray (const fearray<sLong> &Vector) {
222 sLong Sum = 0;
223 for (uInt c = 0; c < Vector.Size; ++c) Sum += Vector.Data[c];
224 return Sum;
228 void femath::GenerateFractalMap (int **Map, int Side, int StartStep, int Randomness) {
229 cint Limit = Side-1;
230 Map[0][0] = 0;
231 Map[0][Limit] = 0;
232 Map[Limit][0] = 0;
233 Map[Limit][Limit] = 0;
234 for (int Step = StartStep, HalfStep = Step>>1; HalfStep;
235 Step = HalfStep, HalfStep>>=1, Randomness = ((Randomness<<3)-Randomness)>>3)
237 int x, y, RandMod = (Randomness<<1)+1;
239 for (x = HalfStep; x < Side; x += Step)
240 for (y = HalfStep; y < Side; y += Step)
241 Map[x][y] =
242 ((Map[x-HalfStep][y-HalfStep]+
243 Map[x-HalfStep][y+HalfStep]+
244 Map[x+HalfStep][y-HalfStep]+
245 Map[x+HalfStep][y+HalfStep])>>2)-Randomness+RAND()%RandMod;
247 for (x = HalfStep; x < Side; x += Step) {
248 for (y = 0; y < Side; y += Step) {
249 int HeightSum = Map[x-HalfStep][y]+Map[x+HalfStep][y];
250 int Neighbours = 2;
251 if (y) {
252 HeightSum += Map[x][y-HalfStep];
253 ++Neighbours;
255 if (y != Limit) {
256 HeightSum += Map[x][y+HalfStep];
257 ++Neighbours;
259 if (Neighbours == 4) HeightSum >>= 2; else HeightSum /= Neighbours;
260 Map[x][y] = HeightSum-Randomness+RAND()%RandMod;
264 for (x = 0; x < Side; x += Step) {
265 for (y = HalfStep; y < Side; y += Step) {
266 int HeightSum = Map[x][y-HalfStep]+Map[x][y+HalfStep];
267 int Neighbours = 2;
268 if (x) {
269 HeightSum += Map[x-HalfStep][y];
270 ++Neighbours;
272 if (x != Limit) {
273 HeightSum += Map[x+HalfStep][y];
274 ++Neighbours;
276 if (Neighbours == 4) HeightSum >>= 2; else HeightSum /= Neighbours;
277 Map[x][y] = HeightSum-Randomness+RAND()%RandMod;