3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
12 #ifndef __FELIB_FEMATH_H__
13 #define __FELIB_FEMATH_H__
22 #define RAND femath::Rand
23 #define RAND_N femath::RandN
24 #define RAND_2 (femath::Rand() & 1)
25 #define RAND_4 (femath::Rand() & 3)
26 #define RAND_8 (femath::Rand() & 7)
27 #define RAND_16 (femath::Rand() & 15)
28 #define RAND_32 (femath::Rand() & 31)
29 #define RAND_64 (femath::Rand() & 63)
30 #define RAND_128 (femath::Rand() & 127)
31 #define RAND_256 (femath::Rand() & 255)
32 #define RAND_GOOD femath::RandGood
37 template <class type
> struct fearray
;
43 static void SetSeed (feuLong
);
44 static sLong
RandN (sLong N
) { return sLong(double(N
)*Rand()/0x80000000); }
45 static sLong
RandGood (sLong N
) { return sLong(double(N
)*Rand()/0x80000000); }
46 static int WeightedRand (sLong
*Possibility
, sLong TotalPossibility
);
47 static int WeightedRand (const std::vector
<sLong
> &Possibility
, sLong TotalPossibility
);
48 static double CalculateAngle (v2 Direction
);
49 static void CalculateEnvironmentRectangle (rect
&Rect
, const rect
&MotherRect
, v2 Origo
, int Radius
);
50 static truth
Clip (int &SourceX
, int &SourceY
, int &DestX
, int &DestY
, int &Width
, int &Height
,
51 int XSize
, int YSize
, int DestXSize
, int DestYSize
);
52 static void SaveSeed ();
53 static void LoadSeed ();
54 static sLong
SumArray (const fearray
<sLong
> &Vector
);
55 static int LoopRoll (int ContinueChance
, int Max
);
56 static void GenerateFractalMap (int **Map
, int Side
, int StartStep
, int Randomness
);
67 sLong
Randomize () const { return Min
< Max
? Min
+ RAND() % (Max
- Min
+ 1) : Min
; }
74 v2
Randomize () const { return v2(X
.Randomize(), Y
.Randomize()); }
80 void ReadData (interval
&I
, inputfile
&SaveFile
);
81 void ReadData (region
&R
, inputfile
&SaveFile
);
83 outputfile
&operator << (outputfile
&SaveFile
, const interval
&I
);
84 inputfile
&operator >> (inputfile
&SaveFile
, interval
&I
);
85 outputfile
&operator << (outputfile
&SaveFile
, const region
&R
);
86 inputfile
&operator >> (inputfile
&SaveFile
, region
&R
);
89 template <class controller
> class mapmath
{
91 static truth
DoLine (int X1
, int Y1
, int X2
, int Y2
, int Flags
=0);
92 static void DoArea ();
93 static void DoQuadriArea (int, int, int, int, int);
97 template <class controller
> inline truth mapmath
<controller
>::DoLine (int X1
, int Y1
, int X2
, int Y2
, int Flags
) {
98 if (!(Flags
& SKIP_FIRST
)) controller::Handler(X1
, Y1
);
99 cint DeltaX
= abs(X2
- X1
);
100 cint DeltaY
= abs(Y2
- Y1
);
101 cint DoubleDeltaX
= DeltaX
<<1;
102 cint DoubleDeltaY
= DeltaY
<<1;
103 cint XChange
= X1
<X2
? 1 : -1;
104 cint YChange
= Y1
<Y2
? 1 : -1;
106 if (DeltaX
>= DeltaY
) {
112 if (c
>= DoubleDeltaX
) {
116 if (!controller::Handler(x
, y
)) return x
== End
&& !(Flags
& ALLOW_END_FAILURE
);
124 if (c
>= DoubleDeltaY
) {
128 if (!controller::Handler(x
, y
)) return y
== End
&& !(Flags
& ALLOW_END_FAILURE
);
135 struct basequadricontroller
{
136 static cint OrigoDeltaX
[4];
137 static cint OrigoDeltaY
[4];
138 static int OrigoX
, OrigoY
;
139 static int StartX
, StartY
;
140 static int XSize
, YSize
;
141 static int RadiusSquare
;
142 static truth SectorCompletelyClear
;
146 template <class controller
> struct quadricontroller
: public basequadricontroller
{
147 static truth
Handler (int, int);
148 static int GetStartX (int I
) {
149 SectorCompletelyClear
= true;
150 return StartX
= (OrigoX
<<1)+OrigoDeltaX
[I
];
152 static int GetStartY (int I
) {
153 return StartY
= (OrigoY
<<1)+OrigoDeltaY
[I
];
158 template <class controller
> truth quadricontroller
<controller
>::Handler (int x
, int y
) {
159 cint HalfX
= x
>>1, HalfY
= y
>>1;
160 if (HalfX
>= 0 && HalfY
>= 0 && HalfX
< XSize
&& HalfY
< YSize
) {
161 feuLong
& SquareTick
= controller::GetTickReference(HalfX
, HalfY
);
162 cint SquarePartIndex
= (x
&1)+((y
&1)<<1);
163 culong Mask
= SquarePartTickMask
[SquarePartIndex
];
164 if ((SquareTick
& Mask
) < controller::ShiftedTick
[SquarePartIndex
]) {
165 SquareTick
= (SquareTick
& ~Mask
) | controller::ShiftedQuadriTick
[SquarePartIndex
];
166 int DeltaX
= OrigoX
-HalfX
, DeltaY
= OrigoY
-HalfY
;
167 if (DeltaX
*DeltaX
+DeltaY
*DeltaY
<= RadiusSquare
) {
168 if (SectorCompletelyClear
) {
169 if (controller::Handler(x
, y
)) return true;
170 SectorCompletelyClear
= false;
172 return mapmath
<controller
>::DoLine(StartX
, StartY
, x
, y
, SKIP_FIRST
|ALLOW_END_FAILURE
);
181 const cint ChangeXArray
[4][3] = {
187 const cint ChangeYArray
[4][3] = {
195 template <class controller
> inline void mapmath
<controller
>::DoArea () {
197 int *OldStack
= Buffer
[0];
198 int *NewStack
= Buffer
[1];
199 for (int c1
= 0; c1
< 4; ++c1
) {
200 cint
*ChangeX
= ChangeXArray
[c1
], *ChangeY
= ChangeYArray
[c1
];
201 int OldStackPos
= 0, NewStackPos
= 0;
202 int StartX
= controller::GetStartX(c1
);
203 int StartY
= controller::GetStartY(c1
);
204 for (int c2
= 0; c2
< 3; ++c2
) {
205 OldStack
[OldStackPos
] = StartX
+ChangeX
[c2
];
206 OldStack
[OldStackPos
+ 1] = StartY
+ChangeY
[c2
];
209 while (OldStackPos
) {
210 while (OldStackPos
) {
212 cint X
= OldStack
[OldStackPos
], Y
= OldStack
[OldStackPos
+1];
213 if (controller::Handler(X
, Y
)) {
214 for (int c2
= 0; c2
< 3; ++c2
) {
215 NewStack
[NewStackPos
] = X
+ChangeX
[c2
];
216 NewStack
[NewStackPos
+1] = Y
+ChangeY
[c2
];
221 OldStackPos
= NewStackPos
;
231 template <class controller
> inline void mapmath
<controller
>::DoQuadriArea (int OrigoX
, int OrigoY
, int RadiusSquare
, int XSize
, int YSize
) {
232 basequadricontroller::OrigoX
= OrigoX
;
233 basequadricontroller::OrigoY
= OrigoY
;
234 basequadricontroller::RadiusSquare
= RadiusSquare
;
235 basequadricontroller::XSize
= XSize
;
236 basequadricontroller::YSize
= YSize
;
237 for (int c
= 0; c
< 4; ++c
) {
238 controller::Handler((OrigoX
<<1)+basequadricontroller::OrigoDeltaX
[c
], (OrigoY
<<1)+basequadricontroller::OrigoDeltaY
[c
]);
240 mapmath
<quadricontroller
<controller
> >::DoArea();
244 /* Chance for n < Max to be returned is (1-CC)*CC^n, for n == Max chance is CC^n. */
245 inline int femath::LoopRoll (int ContinueChance
, int Max
) {
247 for (R
= 0; RAND_N(100) < ContinueChance
&& R
< Max
; ++R
);
252 template <class type
, class predicate
> type
*&ListFind (type
*&Start
, predicate Predicate
) {
254 for(E
= &Start
; *E
&& !Predicate(*E
); E
= &(*E
)->Next
);
259 template <class type
> struct pointercomparer
{
260 pointercomparer (const type
*Element
) : Element(Element
) { }
261 truth
operator()(const type
*E
) const { return E
== Element
; }