OpenTTD
map_func.h
Go to the documentation of this file.
1 /* $Id: map_func.h 24900 2013-01-08 22:46:42Z planetmaker $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #ifndef MAP_FUNC_H
13 #define MAP_FUNC_H
14 
15 #include "core/math_func.hpp"
16 #include "tile_type.h"
17 #include "map_type.h"
18 #include "direction_func.h"
19 
20 extern uint _map_tile_mask;
21 
28 #define TILE_MASK(x) ((x) & _map_tile_mask)
29 
36 extern Tile *_m;
37 
44 extern TileExtended *_me;
45 
46 void AllocateMap(uint size_x, uint size_y);
47 
53 static inline uint MapLogX()
54 {
55  extern uint _map_log_x;
56  return _map_log_x;
57 }
58 
64 static inline uint MapLogY()
65 {
66  extern uint _map_log_y;
67  return _map_log_y;
68 }
69 
74 static inline uint MapSizeX()
75 {
76  extern uint _map_size_x;
77  return _map_size_x;
78 }
79 
84 static inline uint MapSizeY()
85 {
86  extern uint _map_size_y;
87  return _map_size_y;
88 }
89 
94 static inline uint MapSize()
95 {
96  extern uint _map_size;
97  return _map_size;
98 }
99 
104 static inline uint MapMaxX()
105 {
106  return MapSizeX() - 1;
107 }
108 
113 static inline uint MapMaxY()
114 {
115  return MapSizeY() - 1;
116 }
117 
124 static inline uint ScaleByMapSize(uint n)
125 {
126  /* Subtract 12 from shift in order to prevent integer overflow
127  * for large values of n. It's safe since the min mapsize is 64x64. */
128  return CeilDiv(n << (MapLogX() + MapLogY() - 12), 1 << 4);
129 }
130 
131 
138 static inline uint ScaleByMapSize1D(uint n)
139 {
140  /* Normal circumference for the X+Y is 256+256 = 1<<9
141  * Note, not actually taking the full circumference into account,
142  * just half of it. */
143  return CeilDiv((n << MapLogX()) + (n << MapLogY()), 1 << 9);
144 }
145 
156 typedef int32 TileIndexDiff;
157 
165 static inline TileIndex TileXY(uint x, uint y)
166 {
167  return (y << MapLogX()) + x;
168 }
169 
181 static inline TileIndexDiff TileDiffXY(int x, int y)
182 {
183  /* Multiplication gives much better optimization on MSVC than shifting.
184  * 0 << shift isn't optimized to 0 properly.
185  * Typically x and y are constants, and then this doesn't result
186  * in any actual multiplication in the assembly code.. */
187  return (y * MapSizeX()) + x;
188 }
189 
196 static inline TileIndex TileVirtXY(uint x, uint y)
197 {
198  return (y >> 4 << MapLogX()) + (x >> 4);
199 }
200 
201 
207 static inline uint TileX(TileIndex tile)
208 {
209  return tile & MapMaxX();
210 }
211 
217 static inline uint TileY(TileIndex tile)
218 {
219  return tile >> MapLogX();
220 }
221 
233 {
234  return (tidc.y << MapLogX()) + tidc.x;
235 }
236 
237 
238 #ifndef _DEBUG
239 
246  #define TILE_ADD(x, y) ((x) + (y))
247 #else
248  extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
249  const char *exp, const char *file, int line);
250  #define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__))
251 #endif
252 
260 #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y))
261 
262 TileIndex TileAddWrap(TileIndex tile, int addx, int addy);
263 
271 {
273 
274  assert(IsValidDiagDirection(dir));
275  return _tileoffs_by_diagdir[dir];
276 }
277 
285 {
287 
288  assert(IsValidDirection(dir));
289  return _tileoffs_by_dir[dir];
290 }
291 
303 {
304  int x = TileX(tile) + diff.x;
305  int y = TileY(tile) + diff.y;
306  /* Negative value will become big positive value after cast */
307  if ((uint)x >= MapSizeX() || (uint)y >= MapSizeY()) return INVALID_TILE;
308  return TileXY(x, y);
309 }
310 
319 {
320  TileIndexDiffC difference;
321 
322  difference.x = TileX(tile_a) - TileX(tile_b);
323  difference.y = TileY(tile_a) - TileY(tile_b);
324 
325  return difference;
326 }
327 
328 /* Functions to calculate distances */
335 
344 {
346 
347  assert(IsValidDiagDirection(dir));
348  return ToTileIndexDiff(_tileoffs_by_diagdir[dir]);
349 }
350 
358 {
360 
361  assert(IsValidDirection(dir));
362  return ToTileIndexDiff(_tileoffs_by_dir[dir]);
363 }
364 
373 {
374  return TILE_ADD(tile, TileOffsByDiagDir(dir));
375 }
376 
384 static inline DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
385 {
386  int dx = (int)TileX(tile_to) - (int)TileX(tile_from);
387  int dy = (int)TileY(tile_to) - (int)TileY(tile_from);
388  if (dx == 0) {
389  if (dy == 0) return INVALID_DIAGDIR;
390  return (dy < 0 ? DIAGDIR_NW : DIAGDIR_SE);
391  } else {
392  if (dy != 0) return INVALID_DIAGDIR;
393  return (dx < 0 ? DIAGDIR_NE : DIAGDIR_SW);
394  }
395 }
396 
404 typedef bool TestTileOnSearchProc(TileIndex tile, void *user_data);
405 
406 bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data);
407 bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOnSearchProc proc, void *user_data);
408 
414 static inline TileIndex RandomTileSeed(uint32 r)
415 {
416  return TILE_MASK(r);
417 }
418 
425 #define RandomTile() RandomTileSeed(Random())
426 
427 uint GetClosestWaterDistance(TileIndex tile, bool water);
428 
429 #endif /* MAP_FUNC_H */