map_func.h

Go to the documentation of this file.
00001 /* $Id$ */
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 "core/math_func.hpp"
00016 #include "tile_type.h"
00017 #include "map_type.h"
00018 #include "direction_func.h"
00019 
00020 extern uint _map_tile_mask;
00021 
00028 #define TILE_MASK(x) ((x) & _map_tile_mask)
00029 
00036 extern Tile *_m;
00037 
00044 extern TileExtended *_me;
00045 
00051 extern TileHeightData *_map_heightdata;
00052 
00053 void AllocateMap(uint size_x, uint size_y, bool allocate_map_heightdata);
00054 
00055 void CopyHeightlevelDataFromOldToExtended();
00056 
00057 bool CopyHeightlevelDataFromExtendedToOld();
00058 
00064 static inline uint MapLogX()
00065 {
00066   extern uint _map_log_x;
00067   return _map_log_x;
00068 }
00069 
00075 static inline uint MapLogY()
00076 {
00077   extern uint _map_log_y;
00078   return _map_log_y;
00079 }
00080 
00085 static inline uint MapSizeX()
00086 {
00087   extern uint _map_size_x;
00088   return _map_size_x;
00089 }
00090 
00095 static inline uint MapSizeY()
00096 {
00097   extern uint _map_size_y;
00098   return _map_size_y;
00099 }
00100 
00105 static inline uint MapSize()
00106 {
00107   extern uint _map_size;
00108   return _map_size;
00109 }
00110 
00115 static inline uint MapMaxX()
00116 {
00117   return MapSizeX() - 1;
00118 }
00119 
00124 static inline uint MapMaxY()
00125 {
00126   return MapSizeY() - 1;
00127 }
00128 
00135 static inline uint ScaleByMapSize(uint n)
00136 {
00137   /* Subtract 12 from shift in order to prevent integer overflow
00138    * for large values of n. It's safe since the min mapsize is 64x64. */
00139   return CeilDiv(n << (MapLogX() + MapLogY() - 12), 1 << 4);
00140 }
00141 
00142 
00149 static inline uint ScaleByMapSize1D(uint n)
00150 {
00151   /* Normal circumference for the X+Y is 256+256 = 1<<9
00152    * Note, not actually taking the full circumference into account,
00153    * just half of it. */
00154   return CeilDiv((n << MapLogX()) + (n << MapLogY()), 1 << 9);
00155 }
00156 
00167 typedef int32 TileIndexDiff;
00168 
00176 static inline TileIndex TileXY(uint x, uint y)
00177 {
00178   return (y << MapLogX()) + x;
00179 }
00180 
00192 static inline TileIndexDiff TileDiffXY(int x, int y)
00193 {
00194   /* Multiplication gives much better optimization on MSVC than shifting.
00195    * 0 << shift isn't optimized to 0 properly.
00196    * Typically x and y are constants, and then this doesn't result
00197    * in any actual multiplication in the assembly code.. */
00198   return (y * MapSizeX()) + x;
00199 }
00200 
00207 static inline TileIndex TileVirtXY(uint x, uint y)
00208 {
00209   return (y >> 4 << MapLogX()) + (x >> 4);
00210 }
00211 
00212 
00218 static inline uint TileX(TileIndex tile)
00219 {
00220   return tile & MapMaxX();
00221 }
00222 
00228 static inline uint TileY(TileIndex tile)
00229 {
00230   return tile >> MapLogX();
00231 }
00232 
00243 static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
00244 {
00245   return (tidc.y << MapLogX()) + tidc.x;
00246 }
00247 
00248 
00249 #ifndef _DEBUG
00250 
00257   #define TILE_ADD(x, y) ((x) + (y))
00258 #else
00259   extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
00260     const char *exp, const char *file, int line);
00261   #define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__))
00262 #endif
00263 
00271 #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y))
00272 
00273 TileIndex TileAddWrap(TileIndex tile, int addx, int addy);
00274 
00281 static inline TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
00282 {
00283   extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
00284 
00285   assert(IsValidDiagDirection(dir));
00286   return _tileoffs_by_diagdir[dir];
00287 }
00288 
00295 static inline TileIndexDiffC TileIndexDiffCByDir(Direction dir)
00296 {
00297   extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
00298 
00299   assert(IsValidDirection(dir));
00300   return _tileoffs_by_dir[dir];
00301 }
00302 
00313 static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
00314 {
00315   int x = TileX(tile) + diff.x;
00316   int y = TileY(tile) + diff.y;
00317   /* Negative value will become big positive value after cast */
00318   if ((uint)x >= MapSizeX() || (uint)y >= MapSizeY()) return INVALID_TILE;
00319   return TileXY(x, y);
00320 }
00321 
00329 static inline TileIndexDiffC TileIndexToTileIndexDiffC(TileIndex tile_a, TileIndex tile_b)
00330 {
00331   TileIndexDiffC difference;
00332 
00333   difference.x = TileX(tile_a) - TileX(tile_b);
00334   difference.y = TileY(tile_a) - TileY(tile_b);
00335 
00336   return difference;
00337 }
00338 
00339 /* Functions to calculate distances */
00340 uint DistanceManhattan(TileIndex, TileIndex); 
00341 uint DistanceSquare(TileIndex, TileIndex); 
00342 uint DistanceMax(TileIndex, TileIndex); 
00343 uint DistanceMaxPlusManhattan(TileIndex, TileIndex); 
00344 uint DistanceFromEdge(TileIndex); 
00345 uint DistanceFromEdgeDir(TileIndex, DiagDirection); 
00346 
00354 static inline TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
00355 {
00356   extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
00357 
00358   assert(IsValidDiagDirection(dir));
00359   return ToTileIndexDiff(_tileoffs_by_diagdir[dir]);
00360 }
00361 
00368 static inline TileIndexDiff TileOffsByDir(Direction dir)
00369 {
00370   extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
00371 
00372   assert(IsValidDirection(dir));
00373   return ToTileIndexDiff(_tileoffs_by_dir[dir]);
00374 }
00375 
00383 static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
00384 {
00385   return TILE_ADD(tile, TileOffsByDiagDir(dir));
00386 }
00387 
00395 static inline DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
00396 {
00397   int dx = (int)TileX(tile_to) - (int)TileX(tile_from);
00398   int dy = (int)TileY(tile_to) - (int)TileY(tile_from);
00399   if (dx == 0) {
00400     if (dy == 0) return INVALID_DIAGDIR;
00401     return (dy < 0 ? DIAGDIR_NW : DIAGDIR_SE);
00402   } else {
00403     if (dy != 0) return INVALID_DIAGDIR;
00404     return (dx < 0 ? DIAGDIR_NE : DIAGDIR_SW);
00405   }
00406 }
00407 
00415 typedef bool TestTileOnSearchProc(TileIndex tile, void *user_data);
00416 
00417 bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data);
00418 bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOnSearchProc proc, void *user_data);
00419 
00425 static inline TileIndex RandomTileSeed(uint32 r)
00426 {
00427   return TILE_MASK(r);
00428 }
00429 
00436 #define RandomTile() RandomTileSeed(Random())
00437 
00438 uint GetClosestWaterDistance(TileIndex tile, bool water);
00439 
00440 // TODO: convert copypaste to TILE_AREA_LOOP fix it and remove the function below.
00441 
00452 #define TILE_LOOP(var, w, h, tile)                                                    \
00453 for (uint var = tile, cur_h = (h); cur_h > 0; --cur_h, var += TileDiffXY(0, 1) - (w)) \
00454 for (uint cur_w = (w); cur_w > 0; --cur_w, var++)
00455 
00456 #endif /* MAP_FUNC_H */