1 #ifndef KOORD_H
2 #define KOORD_H
3
4 #include "ribi.h"
5 #include "../simtypes.h"
6
7 #include <stdlib.h>
8
9 class loadsave_t;
10
11 /**
12 * 2D Coordinates
13 */
14 class koord
15 {
16 public:
17 // this is set by einstelugen_t
18 static uint32 locality_factor;
19
20 sint16 x;
21 sint16 y;
22
koord()23 koord() : x(0), y(0) {}
24
koord(short xp,short yp)25 koord(short xp, short yp) : x(xp), y(yp) {}
koord(ribi_t::ribi ribi)26 koord(ribi_t::ribi ribi) { *this = from_ribi[ribi]; }
koord(slope_t::type slope)27 koord(slope_t::type slope) { *this = from_hang[slope]; }
28
29 // use this instead of koord(simrand(x),simrand(y)) to avoid
30 // different order on different compilers
31 static koord koord_random(uint16 xrange, uint16 yrange);
32
33 void rdwr(loadsave_t *file);
34
35 const char *get_str() const;
36 const char *get_fullstr() const; // including brackets
37
38 const koord& operator += (const koord & k)
39 {
40 x += k.x;
41 y += k.y;
42 return *this;
43 }
44
45 const koord& operator -= (const koord & k)
46 {
47 x -= k.x;
48 y -= k.y;
49 return *this;
50 }
51
rotate90(sint16 y_size)52 void rotate90( sint16 y_size )
53 {
54 if( (x&y)<0 ) {
55 // do not rotate illegal coordinates
56 return;
57 }
58 sint16 new_x = y_size-y;
59 y = x;
60 x = new_x;
61 }
62
clip_min(koord k_min)63 inline void clip_min( koord k_min )
64 {
65 if (x < k_min.x) {
66 x = k_min.x;
67 }
68 if (y < k_min.y) {
69 y = k_min.y;
70 }
71 }
72
clip_max(koord k_max)73 inline void clip_max( koord k_max )
74 {
75 if (x > k_max.x) {
76 x = k_max.x;
77 }
78 if (y > k_max.y) {
79 y = k_max.y;
80 }
81 }
82
83 static const koord invalid;
84 static const koord north;
85 static const koord south;
86 static const koord east;
87 static const koord west;
88 // the 4 basic directions as an Array
89 static const koord nsew[4];
90 // 8 next neighbours
91 static const koord neighbours[8];
92
93 private:
94 static const koord from_ribi[16];
95 static const koord from_hang[81];
96 };
97
98
koord_distance(const koord & a,const koord & b)99 static inline uint32 koord_distance(const koord &a, const koord &b)
100 {
101 return abs(a.x - b.x) + abs(a.y - b.y);
102 }
103
104 // Knightly : shortest distance in cardinal (N, E, S, W) and ordinal (NE, SE, SW, NW) directions
shortest_distance(const koord & a,const koord & b)105 static inline uint32 shortest_distance(const koord &a, const koord &b)
106 {
107 const uint32 x_offset = abs(a.x - b.x);
108 const uint32 y_offset = abs(a.y - b.y);
109 // square root of 2 is estimated by 181/128; 64 is for rounding
110 if( x_offset>=y_offset ) {
111 return (x_offset - y_offset) + ( ((y_offset * 181u) + 64u) >> 7 );
112 }
113 else {
114 return (y_offset - x_offset) + ( ((x_offset * 181u) + 64u) >> 7 );
115 }
116 }
117
118 // Knightly : multiply the value by the distance weight
weight_by_distance(const sint32 value,const uint32 distance)119 static inline uint32 weight_by_distance(const sint32 value, const uint32 distance)
120 {
121 return value<=0 ? 0 : 1+(uint32)( ( ((sint64)value<<8) * koord::locality_factor ) / (sint64)( koord::locality_factor + (distance < 4u ? 4u : distance) ) );
122 }
123
124 static inline koord operator * (const koord &k, const sint16 m)
125 {
126 return koord(k.x * m, k.y * m);
127 }
128
129
130 static inline koord operator / (const koord &k, const sint16 m)
131 {
132 return koord(k.x / m, k.y / m);
133 }
134
135
136 static inline bool operator == (const koord &a, const koord &b)
137 {
138 // only this works with O3 optimisation!
139 return ((a.x-b.x)|(a.y-b.y))==0;
140 }
141
142
143 static inline bool operator != (const koord &a, const koord &b)
144 {
145 // only this works with O3 optimisation!
146 return ((a.x-b.x)|(a.y-b.y))!=0;
147 }
148
149
150 static inline koord operator + (const koord &a, const koord &b)
151 {
152 return koord(a.x + b.x, a.y + b.y);
153 }
154
155
156 static inline koord operator - (const koord &a, const koord &b)
157 {
158 return koord(a.x - b.x, a.y - b.y);
159 }
160
161
162 static inline koord operator - (const koord &a)
163 {
164 return koord(-a.x, -a.y);
165 }
166 #endif
167