14 #if defined(_MSC_VER) && _MSC_VER >= 1400 /* VStudio 2005 is stupid! */ |
14 #if defined(_MSC_VER) && _MSC_VER >= 1400 /* VStudio 2005 is stupid! */ |
15 /* Why the hell is that not in all MSVC headers?? */ |
15 /* Why the hell is that not in all MSVC headers?? */ |
16 extern "C" _CRTIMP void __cdecl _assert(void *, void *, unsigned); |
16 extern "C" _CRTIMP void __cdecl _assert(void *, void *, unsigned); |
17 #endif |
17 #endif |
18 |
18 |
19 uint _map_log_x; |
19 uint _map_log_x; ///< 2^_map_log_x == _map_size_x |
20 uint _map_size_x; |
20 uint _map_size_x; ///< Size of the map along the X |
21 uint _map_size_y; |
21 uint _map_size_y; ///< Size of the map along the Y |
22 uint _map_tile_mask; |
22 uint _map_size; ///< The number of tiles on the map |
23 uint _map_size; |
23 uint _map_tile_mask; ///< _map_size - 1 (to mask the mapsize) |
24 |
24 |
25 Tile *_m = NULL; |
25 Tile *_m = NULL; ///< Tiles of the map |
26 TileExtended *_me = NULL; |
26 TileExtended *_me = NULL; ///< Extended Tiles of the map |
27 |
27 |
28 |
28 |
|
29 /** |
|
30 * (Re)allocates a map with the given dimension |
|
31 * @param size_x the width of the map along the NE/SW edge |
|
32 * @param size_y the 'height' of the map along the SE/NW edge |
|
33 */ |
29 void AllocateMap(uint size_x, uint size_y) |
34 void AllocateMap(uint size_x, uint size_y) |
30 { |
35 { |
31 /* Make sure that the map size is within the limits and that |
36 /* Make sure that the map size is within the limits and that |
32 * the x axis size is a power of 2. */ |
37 * the x axis size is a power of 2. */ |
33 if (size_x < 64 || size_x > 2048 || |
38 if (size_x < 64 || size_x > 2048 || |
34 size_y < 64 || size_y > 2048 || |
39 size_y < 64 || size_y > 2048 || |
35 (size_x&(size_x-1)) != 0 || |
40 (size_x & (size_x - 1)) != 0 || |
36 (size_y&(size_y-1)) != 0) |
41 (size_y & (size_y - 1)) != 0) |
37 error("Invalid map size"); |
42 error("Invalid map size"); |
38 |
43 |
39 DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y); |
44 DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y); |
40 |
45 |
41 _map_log_x = FindFirstBit(size_x); |
46 _map_log_x = FindFirstBit(size_x); |
90 |
95 |
91 return TileXY(x, y); |
96 return TileXY(x, y); |
92 } |
97 } |
93 #endif |
98 #endif |
94 |
99 |
95 |
100 /** |
|
101 * Scales the given value by the map size, where the given value is |
|
102 * for a 256 by 256 map |
|
103 * @param n the value to scale |
|
104 * @return the scaled size |
|
105 */ |
96 uint ScaleByMapSize(uint n) |
106 uint ScaleByMapSize(uint n) |
97 { |
107 { |
98 /* First shift by 12 to prevent integer overflow for large values of n. |
108 /* First shift by 12 to prevent integer overflow for large values of n. |
99 * >>12 is safe since the min mapsize is 64x64 |
109 * >>12 is safe since the min mapsize is 64x64 |
100 * Add (1<<4)-1 to round upwards. */ |
110 * Add (1<<4)-1 to round upwards. */ |
101 return (n * (MapSize() >> 12) + (1 << 4) - 1) >> 4; |
111 return (n * (MapSize() >> 12) + (1 << 4) - 1) >> 4; |
102 } |
112 } |
103 |
113 |
104 |
114 |
105 /* Scale relative to the circumference of the map */ |
115 /** |
|
116 * Scales the given value by the maps circumference, where the given |
|
117 * value is for a 256 by 256 map |
|
118 * @param n the value to scale |
|
119 * @return the scaled size |
|
120 */ |
106 uint ScaleByMapSize1D(uint n) |
121 uint ScaleByMapSize1D(uint n) |
107 { |
122 { |
108 /* Normal circumference for the X+Y is 256+256 = 1<<9 |
123 /* Normal circumference for the X+Y is 256+256 = 1<<9 |
109 * Note, not actually taking the full circumference into account, |
124 * Note, not actually taking the full circumference into account, |
110 * just half of it. |
125 * just half of it. |
111 * (1<<9) - 1 is there to scale upwards. */ |
126 * (1<<9) - 1 is there to scale upwards. */ |
112 return (n * (MapSizeX() + MapSizeY()) + (1 << 9) - 1) >> 9; |
127 return (n * (MapSizeX() + MapSizeY()) + (1 << 9) - 1) >> 9; |
113 } |
128 } |
114 |
129 |
115 |
130 |
116 /* This function checks if we add addx/addy to tile, if we |
131 /** |
|
132 * This function checks if we add addx/addy to tile, if we |
117 * do wrap around the edges. For example, tile = (10,2) and |
133 * do wrap around the edges. For example, tile = (10,2) and |
118 * addx = +3 and addy = -4. This function will now return |
134 * addx = +3 and addy = -4. This function will now return |
119 * INVALID_TILE, because the y is wrapped. This is needed in |
135 * INVALID_TILE, because the y is wrapped. This is needed in |
120 * for example, farmland. When the tile is not wrapped, |
136 * for example, farmland. When the tile is not wrapped, |
121 * the result will be tile + TileDiffXY(addx, addy) */ |
137 * the result will be tile + TileDiffXY(addx, addy) |
|
138 * @param tile the 'starting' point of the adding |
|
139 * @param addx the amount of tiles in the X direction to add |
|
140 * @param addy the amount of tiles in the Y direction to add |
|
141 * @return translated tile, or INVALID_TILE when it would've wrapped. |
|
142 */ |
122 uint TileAddWrap(TileIndex tile, int addx, int addy) |
143 uint TileAddWrap(TileIndex tile, int addx, int addy) |
123 { |
144 { |
124 uint x = TileX(tile) + addx; |
145 uint x = TileX(tile) + addx; |
125 uint y = TileY(tile) + addy; |
146 uint y = TileY(tile) + addy; |
126 |
147 |
129 return tile + TileDiffXY(addx, addy); |
150 return tile + TileDiffXY(addx, addy); |
130 |
151 |
131 return INVALID_TILE; |
152 return INVALID_TILE; |
132 } |
153 } |
133 |
154 |
|
155 /** 'Lookup table' for tile offsets given a DiagDirection */ |
134 extern const TileIndexDiffC _tileoffs_by_diagdir[] = { |
156 extern const TileIndexDiffC _tileoffs_by_diagdir[] = { |
135 {-1, 0}, ///< DIAGDIR_NE |
157 {-1, 0}, ///< DIAGDIR_NE |
136 { 0, 1}, ///< DIAGDIR_SE |
158 { 0, 1}, ///< DIAGDIR_SE |
137 { 1, 0}, ///< DIAGDIR_SW |
159 { 1, 0}, ///< DIAGDIR_SW |
138 { 0, -1} ///< DIAGDIR_NW |
160 { 0, -1} ///< DIAGDIR_NW |
139 }; |
161 }; |
140 |
162 |
|
163 /** 'Lookup table' for tile offsets given a Direction */ |
141 extern const TileIndexDiffC _tileoffs_by_dir[] = { |
164 extern const TileIndexDiffC _tileoffs_by_dir[] = { |
142 {-1, -1}, ///< DIR_N |
165 {-1, -1}, ///< DIR_N |
143 {-1, 0}, ///< DIR_NE |
166 {-1, 0}, ///< DIR_NE |
144 {-1, 1}, ///< DIR_E |
167 {-1, 1}, ///< DIR_E |
145 { 0, 1}, ///< DIR_SE |
168 { 0, 1}, ///< DIR_SE |
147 { 1, 0}, ///< DIR_SW |
170 { 1, 0}, ///< DIR_SW |
148 { 1, -1}, ///< DIR_W |
171 { 1, -1}, ///< DIR_W |
149 { 0, -1} ///< DIR_NW |
172 { 0, -1} ///< DIR_NW |
150 }; |
173 }; |
151 |
174 |
|
175 /** |
|
176 * Gets the Manhattan distance between the two given tiles. |
|
177 * The Manhattan distance is the sum of the delta of both the |
|
178 * X and Y component. |
|
179 * Also known as L1-Norm |
|
180 * @param t0 the start tile |
|
181 * @param t1 the end tile |
|
182 * @return the distance |
|
183 */ |
152 uint DistanceManhattan(TileIndex t0, TileIndex t1) |
184 uint DistanceManhattan(TileIndex t0, TileIndex t1) |
153 { |
185 { |
154 const uint dx = delta(TileX(t0), TileX(t1)); |
186 const uint dx = delta(TileX(t0), TileX(t1)); |
155 const uint dy = delta(TileY(t0), TileY(t1)); |
187 const uint dy = delta(TileY(t0), TileY(t1)); |
156 return dx + dy; |
188 return dx + dy; |
157 } |
189 } |
158 |
190 |
159 |
191 |
|
192 /** |
|
193 * Gets the 'Square' distance between the two given tiles. |
|
194 * The 'Square' distance is the square of the shortest (straight line) |
|
195 * distance between the two tiles. |
|
196 * Also known as euclidian- or L2-Norm squared. |
|
197 * @param t0 the start tile |
|
198 * @param t1 the end tile |
|
199 * @return the distance |
|
200 */ |
160 uint DistanceSquare(TileIndex t0, TileIndex t1) |
201 uint DistanceSquare(TileIndex t0, TileIndex t1) |
161 { |
202 { |
162 const int dx = TileX(t0) - TileX(t1); |
203 const int dx = TileX(t0) - TileX(t1); |
163 const int dy = TileY(t0) - TileY(t1); |
204 const int dy = TileY(t0) - TileY(t1); |
164 return dx * dx + dy * dy; |
205 return dx * dx + dy * dy; |
165 } |
206 } |
166 |
207 |
167 |
208 |
|
209 /** |
|
210 * Gets the biggest distance component (x or y) between the two given tiles. |
|
211 * Also known as L-Infinity-Norm. |
|
212 * @param t0 the start tile |
|
213 * @param t1 the end tile |
|
214 * @return the distance |
|
215 */ |
168 uint DistanceMax(TileIndex t0, TileIndex t1) |
216 uint DistanceMax(TileIndex t0, TileIndex t1) |
169 { |
217 { |
170 const uint dx = delta(TileX(t0), TileX(t1)); |
218 const uint dx = delta(TileX(t0), TileX(t1)); |
171 const uint dy = delta(TileY(t0), TileY(t1)); |
219 const uint dy = delta(TileY(t0), TileY(t1)); |
172 return dx > dy ? dx : dy; |
220 return dx > dy ? dx : dy; |
173 } |
221 } |
174 |
222 |
175 |
223 |
|
224 /** |
|
225 * Gets the biggest distance component (x or y) between the two given tiles |
|
226 * plus the Manhattan distance, i.e. two times the biggest distance component |
|
227 * and once the smallest component. |
|
228 * @param t0 the start tile |
|
229 * @param t1 the end tile |
|
230 * @return the distance |
|
231 */ |
176 uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1) |
232 uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1) |
177 { |
233 { |
178 const uint dx = delta(TileX(t0), TileX(t1)); |
234 const uint dx = delta(TileX(t0), TileX(t1)); |
179 const uint dy = delta(TileY(t0), TileY(t1)); |
235 const uint dy = delta(TileY(t0), TileY(t1)); |
180 return dx > dy ? 2 * dx + dy : 2 * dy + dx; |
236 return dx > dy ? 2 * dx + dy : 2 * dy + dx; |
181 } |
237 } |
182 |
238 |
|
239 /** |
|
240 * Param the minimum distance to an edge |
|
241 * @param tile the tile to get the distance from |
|
242 * @return the distance from the edge in tiles |
|
243 */ |
183 uint DistanceFromEdge(TileIndex tile) |
244 uint DistanceFromEdge(TileIndex tile) |
184 { |
245 { |
185 const uint xl = TileX(tile); |
246 const uint xl = TileX(tile); |
186 const uint yl = TileY(tile); |
247 const uint yl = TileY(tile); |
187 const uint xh = MapSizeX() - 1 - xl; |
248 const uint xh = MapSizeX() - 1 - xl; |