|
1 /* $Id$ */ |
|
2 |
|
3 /** @file map.h */ |
|
4 |
|
5 #ifndef MAP_FUNC_H |
|
6 #define MAP_FUNC_H |
|
7 |
|
8 #include "tile_type.h" |
|
9 #include "map_type.h" |
|
10 #include "direction_func.h" |
|
11 |
|
12 extern uint _map_tile_mask; |
|
13 |
|
14 /** |
|
15 * 'Wraps' the given tile to it is within the map. It does |
|
16 * this by masking the 'high' bits of. |
|
17 * @param x the tile to 'wrap' |
|
18 */ |
|
19 |
|
20 #define TILE_MASK(x) ((x) & _map_tile_mask) |
|
21 /** |
|
22 * Asserts when the tile is outside of the map. |
|
23 * @param x the tile to check |
|
24 */ |
|
25 #define TILE_ASSERT(x) assert(TILE_MASK(x) == (x)); |
|
26 |
|
27 /** |
|
28 * Pointer to the tile-array. |
|
29 * |
|
30 * This variable points to the tile-array which contains the tiles of |
|
31 * the map. |
|
32 */ |
|
33 extern Tile *_m; |
|
34 |
|
35 /** |
|
36 * Pointer to the extended tile-array. |
|
37 * |
|
38 * This variable points to the extended tile-array which contains the tiles |
|
39 * of the map. |
|
40 */ |
|
41 extern TileExtended *_me; |
|
42 |
|
43 /** |
|
44 * Allocate a new map with the given size. |
|
45 */ |
|
46 void AllocateMap(uint size_x, uint size_y); |
|
47 |
|
48 /** |
|
49 * Logarithm of the map size along the X side. |
|
50 * @note try to avoid using this one |
|
51 * @return 2^"return value" == MapSizeX() |
|
52 */ |
|
53 static inline uint MapLogX() |
|
54 { |
|
55 extern uint _map_log_x; |
|
56 return _map_log_x; |
|
57 } |
|
58 |
|
59 /** |
|
60 * Get the size of the map along the X |
|
61 * @return the number of tiles along the X of the map |
|
62 */ |
|
63 static inline uint MapSizeX() |
|
64 { |
|
65 extern uint _map_size_x; |
|
66 return _map_size_x; |
|
67 } |
|
68 |
|
69 /** |
|
70 * Get the size of the map along the Y |
|
71 * @return the number of tiles along the Y of the map |
|
72 */ |
|
73 static inline uint MapSizeY() |
|
74 { |
|
75 extern uint _map_size_y; |
|
76 return _map_size_y; |
|
77 } |
|
78 |
|
79 /** |
|
80 * Get the size of the map |
|
81 * @return the number of tiles of the map |
|
82 */ |
|
83 static inline uint MapSize() |
|
84 { |
|
85 extern uint _map_size; |
|
86 return _map_size; |
|
87 } |
|
88 |
|
89 /** |
|
90 * Gets the maximum X coordinate within the map, including MP_VOID |
|
91 * @return the maximum X coordinate |
|
92 */ |
|
93 static inline uint MapMaxX() |
|
94 { |
|
95 return MapSizeX() - 1; |
|
96 } |
|
97 |
|
98 /** |
|
99 * Gets the maximum X coordinate within the map, including MP_VOID |
|
100 * @return the maximum X coordinate |
|
101 */ |
|
102 static inline uint MapMaxY() |
|
103 { |
|
104 return MapSizeY() - 1; |
|
105 } |
|
106 |
|
107 /** |
|
108 * Scales relative to the number of tiles. |
|
109 */ |
|
110 uint ScaleByMapSize(uint); |
|
111 |
|
112 /** |
|
113 * Scale relative to the circumference of the map. |
|
114 */ |
|
115 uint ScaleByMapSize1D(uint); |
|
116 |
|
117 /** |
|
118 * An offset value between to tiles. |
|
119 * |
|
120 * This value is used fro the difference between |
|
121 * to tiles. It can be added to a tileindex to get |
|
122 * the resulting tileindex of the start tile applied |
|
123 * with this saved difference. |
|
124 * |
|
125 * @see TileDiffXY(int, int) |
|
126 */ |
|
127 typedef int32 TileIndexDiff; |
|
128 |
|
129 /** |
|
130 * Returns the TileIndex of a coordinate. |
|
131 * |
|
132 * @param x The x coordinate of the tile |
|
133 * @param y The y coordinate of the tile |
|
134 * @return The TileIndex calculated by the coordinate |
|
135 */ |
|
136 static inline TileIndex TileXY(uint x, uint y) |
|
137 { |
|
138 return (y * MapSizeX()) + x; |
|
139 } |
|
140 |
|
141 /** |
|
142 * Calculates an offset for the given coordinate(-offset). |
|
143 * |
|
144 * This function calculate an offset value which can be added to an |
|
145 * #TileIndex. The coordinates can be negative. |
|
146 * |
|
147 * @param x The offset in x direction |
|
148 * @param y The offset in y direction |
|
149 * @return The resulting offset value of the given coordinate |
|
150 * @see ToTileIndexDiff(TileIndexDiffC) |
|
151 */ |
|
152 static inline TileIndexDiff TileDiffXY(int x, int y) |
|
153 { |
|
154 /* Multiplication gives much better optimization on MSVC than shifting. |
|
155 * 0 << shift isn't optimized to 0 properly. |
|
156 * Typically x and y are constants, and then this doesn't result |
|
157 * in any actual multiplication in the assembly code.. */ |
|
158 return (y * MapSizeX()) + x; |
|
159 } |
|
160 |
|
161 static inline TileIndex TileVirtXY(uint x, uint y) |
|
162 { |
|
163 return (y >> 4 << MapLogX()) + (x >> 4); |
|
164 } |
|
165 |
|
166 |
|
167 /** |
|
168 * Get the X component of a tile |
|
169 * @param tile the tile to get the X component of |
|
170 * @return the X component |
|
171 */ |
|
172 static inline uint TileX(TileIndex tile) |
|
173 { |
|
174 return tile & MapMaxX(); |
|
175 } |
|
176 |
|
177 /** |
|
178 * Get the Y component of a tile |
|
179 * @param tile the tile to get the Y component of |
|
180 * @return the Y component |
|
181 */ |
|
182 static inline uint TileY(TileIndex tile) |
|
183 { |
|
184 return tile >> MapLogX(); |
|
185 } |
|
186 |
|
187 /** |
|
188 * Return the offset between to tiles from a TileIndexDiffC struct. |
|
189 * |
|
190 * This function works like #TileDiffXY(int, int) and returns the |
|
191 * difference between two tiles. |
|
192 * |
|
193 * @param tidc The coordinate of the offset as TileIndexDiffC |
|
194 * @return The difference between two tiles. |
|
195 * @see TileDiffXY(int, int) |
|
196 */ |
|
197 static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc) |
|
198 { |
|
199 return (tidc.y << MapLogX()) + tidc.x; |
|
200 } |
|
201 |
|
202 |
|
203 #ifndef _DEBUG |
|
204 /** |
|
205 * Adds to tiles together. |
|
206 * |
|
207 * @param x One tile |
|
208 * @param y An other tile to add |
|
209 * @return The resulting tile(index) |
|
210 */ |
|
211 #define TILE_ADD(x,y) ((x) + (y)) |
|
212 #else |
|
213 extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add, |
|
214 const char *exp, const char *file, int line); |
|
215 #define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__)) |
|
216 #endif |
|
217 |
|
218 /** |
|
219 * Adds a given offset to a tile. |
|
220 * |
|
221 * @param tile The tile to add an offset on it |
|
222 * @param x The x offset to add to the tile |
|
223 * @param y The y offset to add to the tile |
|
224 */ |
|
225 #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y)) |
|
226 |
|
227 /** |
|
228 * Adds an offset to a tile and check if we are still on the map. |
|
229 */ |
|
230 uint TileAddWrap(TileIndex tile, int addx, int addy); |
|
231 |
|
232 /** |
|
233 * Returns the TileIndexDiffC offset from a DiagDirection. |
|
234 * |
|
235 * @param dir The given direction |
|
236 * @return The offset as TileIndexDiffC value |
|
237 */ |
|
238 static inline TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir) |
|
239 { |
|
240 extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END]; |
|
241 |
|
242 assert(IsValidDiagDirection(dir)); |
|
243 return _tileoffs_by_diagdir[dir]; |
|
244 } |
|
245 |
|
246 /** |
|
247 * Add a TileIndexDiffC to a TileIndex and returns the new one. |
|
248 * |
|
249 * Returns tile + the diff given in diff. If the result tile would end up |
|
250 * outside of the map, INVALID_TILE is returned instead. |
|
251 * |
|
252 * @param tile The base tile to add the offset on |
|
253 * @param diff The offset to add on the tile |
|
254 * @return The resulting TileIndex |
|
255 */ |
|
256 static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff) |
|
257 { |
|
258 int x = TileX(tile) + diff.x; |
|
259 int y = TileY(tile) + diff.y; |
|
260 if (x < 0 || y < 0 || x > (int)MapMaxX() || y > (int)MapMaxY()) |
|
261 return INVALID_TILE; |
|
262 else |
|
263 return TileXY(x, y); |
|
264 } |
|
265 |
|
266 /** |
|
267 * Returns the diff between two tiles |
|
268 * |
|
269 * @param tile_a from tile |
|
270 * @param tile_b to tile |
|
271 * @return the difference between tila_a and tile_b |
|
272 */ |
|
273 static inline TileIndexDiffC TileIndexToTileIndexDiffC(TileIndex tile_a, TileIndex tile_b) |
|
274 { |
|
275 TileIndexDiffC difference; |
|
276 |
|
277 difference.x = TileX(tile_a) - TileX(tile_b); |
|
278 difference.y = TileY(tile_a) - TileY(tile_b); |
|
279 |
|
280 return difference; |
|
281 } |
|
282 |
|
283 /* Functions to calculate distances */ |
|
284 uint DistanceManhattan(TileIndex, TileIndex); ///< also known as L1-Norm. Is the shortest distance one could go over diagonal tracks (or roads) |
|
285 uint DistanceSquare(TileIndex, TileIndex); ///< euclidian- or L2-Norm squared |
|
286 uint DistanceMax(TileIndex, TileIndex); ///< also known as L-Infinity-Norm |
|
287 uint DistanceMaxPlusManhattan(TileIndex, TileIndex); ///< Max + Manhattan |
|
288 uint DistanceFromEdge(TileIndex); ///< shortest distance from any edge of the map |
|
289 |
|
290 /** |
|
291 * Starts a loop which iterates to a square of tiles |
|
292 * |
|
293 * This macro starts 2 nested loops which iterates over a square of tiles. |
|
294 * |
|
295 * @param var The name of the variable which contains the current tile |
|
296 * @param w The width (x-width) of the square |
|
297 * @param h The heigth (y-width) of the square |
|
298 * @param tile The start tile of the square |
|
299 */ |
|
300 #define BEGIN_TILE_LOOP(var, w, h, tile) \ |
|
301 { \ |
|
302 int h_cur = h; \ |
|
303 uint var = tile; \ |
|
304 do { \ |
|
305 int w_cur = w; \ |
|
306 do { |
|
307 /** |
|
308 * Ends the square-loop used before |
|
309 * |
|
310 * @see BEGIN_TILE_LOOP |
|
311 */ |
|
312 #define END_TILE_LOOP(var, w, h, tile) \ |
|
313 } while (++var, --w_cur != 0); \ |
|
314 } while (var += TileDiffXY(0, 1) - (w), --h_cur != 0); \ |
|
315 } |
|
316 /** |
|
317 * Convert a DiagDirection to a TileIndexDiff |
|
318 * |
|
319 * @param dir The DiagDirection |
|
320 * @return The resulting TileIndexDiff |
|
321 * @see TileIndexDiffCByDiagDir |
|
322 */ |
|
323 static inline TileIndexDiff TileOffsByDiagDir(DiagDirection dir) |
|
324 { |
|
325 extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END]; |
|
326 |
|
327 assert(IsValidDiagDirection(dir)); |
|
328 return ToTileIndexDiff(_tileoffs_by_diagdir[dir]); |
|
329 } |
|
330 |
|
331 /** |
|
332 * Convert a Direction to a TileIndexDiff. |
|
333 * |
|
334 * @param dir The direction to convert from |
|
335 * @return The resulting TileIndexDiff |
|
336 */ |
|
337 static inline TileIndexDiff TileOffsByDir(Direction dir) |
|
338 { |
|
339 extern const TileIndexDiffC _tileoffs_by_dir[DIR_END]; |
|
340 |
|
341 assert(IsValidDirection(dir)); |
|
342 return ToTileIndexDiff(_tileoffs_by_dir[dir]); |
|
343 } |
|
344 |
|
345 /** |
|
346 * Adds a DiagDir to a tile. |
|
347 * |
|
348 * @param tile The current tile |
|
349 * @param dir The direction in which we want to step |
|
350 * @return the moved tile |
|
351 */ |
|
352 static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir) |
|
353 { |
|
354 return TILE_ADD(tile, TileOffsByDiagDir(dir)); |
|
355 } |
|
356 |
|
357 /** |
|
358 * A callback function type for searching tiles. |
|
359 * |
|
360 * @param tile The tile to test |
|
361 * @param data additional data for the callback function to use |
|
362 * @return A boolean value, depend on the definition of the function. |
|
363 */ |
|
364 typedef bool TestTileOnSearchProc(TileIndex tile, uint32 data); |
|
365 |
|
366 /** |
|
367 * Searches for some cirumstances of a tile around a given tile with a helper function. |
|
368 */ |
|
369 bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data); |
|
370 |
|
371 /** |
|
372 * Get a random tile out of a given seed. |
|
373 * @param r the random 'seed' |
|
374 * @return a valid tile |
|
375 */ |
|
376 static inline TileIndex RandomTileSeed(uint32 r) |
|
377 { |
|
378 return TILE_MASK(r); |
|
379 } |
|
380 |
|
381 /** |
|
382 * Get a valid random tile. |
|
383 * @note a define so 'random' gets inserted in the place where it is actually |
|
384 * called, thus making the random traces more explicit. |
|
385 * @return a valid tile |
|
386 */ |
|
387 #define RandomTile() RandomTileSeed(Random()) |
|
388 |
|
389 #endif /* MAP_FUNC_H */ |