# map_func.h

Go to the documentation of this file.

    00001 /* $Id: map_func.h 18718 2010-01-04 18:30:10Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #ifndef MAP_FUNC_H
    00013 #define MAP_FUNC_H
    00014
    00015 #include "tile_type.h"
    00016 #include "map_type.h"
    00017 #include "direction_func.h"
    00018
    00019 extern uint _map_tile_mask;
    00020
    00027 #define TILE_MASK(x) ((x) & _map_tile_mask)
    00028
    00035 extern Tile *_m;
    00036
    00043 extern TileExtended *_me;
    00044
    00048 void AllocateMap(uint size_x, uint size_y);
    00049
    00055 static inline uint MapLogX()
    00056 {
    00057   extern uint _map_log_x;
    00058   return _map_log_x;
    00059 }
    00060
    00066 static inline uint MapLogY()
    00067 {
    00068   extern uint _map_log_y;
    00069   return _map_log_y;
    00070 }
    00071
    00076 static inline uint MapSizeX()
    00077 {
    00078   extern uint _map_size_x;
    00079   return _map_size_x;
    00080 }
    00081
    00086 static inline uint MapSizeY()
    00087 {
    00088   extern uint _map_size_y;
    00089   return _map_size_y;
    00090 }
    00091
    00096 static inline uint MapSize()
    00097 {
    00098   extern uint _map_size;
    00099   return _map_size;
    00100 }
    00101
    00106 static inline uint MapMaxX()
    00107 {
    00108   return MapSizeX() - 1;
    00109 }
    00110
    00115 static inline uint MapMaxY()
    00116 {
    00117   return MapSizeY() - 1;
    00118 }
    00119
    00126 static inline uint ScaleByMapSize(uint n)
    00127 {
    00128   /* Subtract 12 from shift in order to prevent integer overflow
    00129    * for large values of n. It's safe since the min mapsize is 64x64.
    00130    * Add (1<<4)-1 to round upwards. */
    00131   return ((n << (MapLogX() + MapLogY() - 12)) + (1 << 4) - 1) >> 4;
    00132 }
    00133
    00134
    00141 static inline uint ScaleByMapSize1D(uint n)
    00142 {
    00143   /* Normal circumference for the X+Y is 256+256 = 1<<9
    00144    * Note, not actually taking the full circumference into account,
    00145    * just half of it.
    00146    * (1<<9) - 1 is there to scale upwards. */
    00147   return ((n << MapLogX()) + (n << MapLogY()) + (1 << 9) - 1) >> 9;
    00148 }
    00149
    00160 typedef int32 TileIndexDiff;
    00161
    00169 static inline TileIndex TileXY(uint x, uint y)
    00170 {
    00171   return (y << MapLogX()) + x;
    00172 }
    00173
    00185 static inline TileIndexDiff TileDiffXY(int x, int y)
    00186 {
    00187   /* Multiplication gives much better optimization on MSVC than shifting.
    00188    * 0 << shift isn't optimized to 0 properly.
    00189    * Typically x and y are constants, and then this doesn't result
    00190    * in any actual multiplication in the assembly code.. */
    00191   return (y * MapSizeX()) + x;
    00192 }
    00193
    00194 static inline TileIndex TileVirtXY(uint x, uint y)
    00195 {
    00196   return (y >> 4 << MapLogX()) + (x >> 4);
    00197 }
    00198
    00199
    00205 static inline uint TileX(TileIndex tile)
    00206 {
    00207   return tile & MapMaxX();
    00208 }
    00209
    00215 static inline uint TileY(TileIndex tile)
    00216 {
    00217   return tile >> MapLogX();
    00218 }
    00219
    00230 static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
    00231 {
    00232   return (tidc.y << MapLogX()) + tidc.x;
    00233 }
    00234
    00235
    00236 #ifndef _DEBUG
    00237
    00244   #define TILE_ADD(x,y) ((x) + (y))
    00245 #else
    00246   extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
    00247     const char *exp, const char *file, int line);
    00248   #define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__))
    00249 #endif
    00250
    00258 #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y))
    00259
    00263 TileIndex TileAddWrap(TileIndex tile, int addx, int addy);
    00264
    00271 static inline TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
    00272 {
    00273   extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
    00274
    00275   assert(IsValidDiagDirection(dir));
    00276   return _tileoffs_by_diagdir[dir];
    00277 }
    00278
    00285 static inline TileIndexDiffC TileIndexDiffCByDir(Direction dir)
    00286 {
    00287   extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
    00288
    00289   assert(IsValidDirection(dir));
    00290   return _tileoffs_by_dir[dir];
    00291 }
    00292
    00303 static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
    00304 {
    00305   int x = TileX(tile) + diff.x;
    00306   int y = TileY(tile) + diff.y;
    00307   /* Negative value will become big positive value after cast */
    00308   if ((uint)x >= MapSizeX() || (uint)y >= MapSizeY()) return INVALID_TILE;
    00309   return TileXY(x, y);
    00310 }
    00311
    00319 static inline TileIndexDiffC TileIndexToTileIndexDiffC(TileIndex tile_a, TileIndex tile_b)
    00320 {
    00321   TileIndexDiffC difference;
    00322
    00323   difference.x = TileX(tile_a) - TileX(tile_b);
    00324   difference.y = TileY(tile_a) - TileY(tile_b);
    00325
    00326   return difference;
    00327 }
    00328
    00329 /* Functions to calculate distances */
    00330 uint DistanceManhattan(TileIndex, TileIndex);
    00331 uint DistanceSquare(TileIndex, TileIndex);
    00332 uint DistanceMax(TileIndex, TileIndex);
    00333 uint DistanceMaxPlusManhattan(TileIndex, TileIndex);
    00334 uint DistanceFromEdge(TileIndex);
    00335
    00346 #define TILE_LOOP(var, w, h, tile)                                                      \
    00347   for (uint var = tile, cur_h = (h); cur_h > 0; --cur_h, var += TileDiffXY(0, 1) - (w)) \
    00348     for (uint cur_w = (w); cur_w > 0; --cur_w, var++)
    00349
    00358 #define TILE_AREA_LOOP(var, ta) TILE_LOOP(var, ta.w, ta.h, ta.tile)
    00359
    00367 static inline TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
    00368 {
    00369   extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
    00370
    00371   assert(IsValidDiagDirection(dir));
    00372   return ToTileIndexDiff(_tileoffs_by_diagdir[dir]);
    00373 }
    00374
    00381 static inline TileIndexDiff TileOffsByDir(Direction dir)
    00382 {
    00383   extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
    00384
    00385   assert(IsValidDirection(dir));
    00386   return ToTileIndexDiff(_tileoffs_by_dir[dir]);
    00387 }
    00388
    00396 static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
    00397 {
    00398   return TILE_ADD(tile, TileOffsByDiagDir(dir));
    00399 }
    00400
    00408 static inline DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
    00409 {
    00410   int dx = (int)TileX(tile_to) - (int)TileX(tile_from);
    00411   int dy = (int)TileY(tile_to) - (int)TileY(tile_from);
    00412   if (dx == 0) {
    00413     if (dy == 0) return INVALID_DIAGDIR;
    00414     return (dy < 0 ? DIAGDIR_NW : DIAGDIR_SE);
    00415   } else {
    00416     if (dy != 0) return INVALID_DIAGDIR;
    00417     return (dx < 0 ? DIAGDIR_NE : DIAGDIR_SW);
    00418   }
    00419 }
    00420
    00428 typedef bool TestTileOnSearchProc(TileIndex tile, void *user_data);
    00429
    00433 bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data);
    00434
    00438 bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOnSearchProc proc, void *user_data);
    00439
    00445 static inline TileIndex RandomTileSeed(uint32 r)
    00446 {
    00447   return TILE_MASK(r);
    00448 }
    00449
    00456 #define RandomTile() RandomTileSeed(Random())
    00457
    00461 uint GetClosestWaterDistance(TileIndex tile, bool water);
    00462
    00463 #endif /* MAP_FUNC_H */