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 */

Generated on Thu Feb 4 17:20:24 2010 for OpenTTD by  doxygen 1.5.6