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