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 #include "settings_type.h"
00020 
00021 extern uint _map_tile_mask;
00022 
00029 #define TILE_MASK(x) ((x) & _map_tile_mask)
00030 
00037 extern Tile *_m;
00038 
00045 extern TileExtended *_me;
00046 
00047 void AllocateMap(uint size_x, uint size_y);
00048 
00054 static inline uint MapLogX()
00055 {
00056   extern uint _map_log_x;
00057   return _map_log_x;
00058 }
00059 
00065 static inline uint MapLogY()
00066 {
00067   extern uint _map_log_y;
00068   return _map_log_y;
00069 }
00070 
00075 static inline uint MapSizeX()
00076 {
00077   extern uint _map_size_x;
00078   return _map_size_x;
00079 }
00080 
00085 static inline uint MapSizeY()
00086 {
00087   extern uint _map_size_y;
00088   return _map_size_y;
00089 }
00090 
00095 static inline uint MapSize()
00096 {
00097   extern uint _map_size;
00098   return _map_size;
00099 }
00100 
00105 static inline uint MapMaxX()
00106 {
00107   return MapSizeX() - 1;
00108 }
00109 
00114 static inline uint MapMaxY()
00115 {
00116   return MapSizeY() - 1;
00117 }
00118 
00119 extern uint8 _head_to_head;
00120 static inline uint AreaMinY()
00121 {
00122   assert(_head_to_head > 0);
00123   uint offset = MapSizeY() / _settings_game.game_creation.head_to_head_areas;
00124   return  offset * (_head_to_head - 1);
00125 }
00126 
00127 static inline uint AreaMaxY()
00128 {
00129   assert(_head_to_head > 0);
00130   uint offset = MapSizeY() / _settings_game.game_creation.head_to_head_areas;
00131   return  offset * (_head_to_head);
00132 }
00133 
00134 static inline uint AreaMinX()
00135 {
00136   return 0;
00137 }
00138 
00139 static inline uint AreaMaxX()
00140 {
00141   return MapSizeX();
00142 }
00143 
00150 static inline uint ScaleByMapSize(uint n)
00151 {
00152   /* Subtract 12 from shift in order to prevent integer overflow
00153    * for large values of n. It's safe since the min mapsize is 64x64. */
00154   return CeilDiv(n << (MapLogX() + MapLogY() - 12), 1 << 4);
00155 }
00156 
00157 
00164 static inline uint ScaleByMapSize1D(uint n)
00165 {
00166   /* Normal circumference for the X+Y is 256+256 = 1<<9
00167    * Note, not actually taking the full circumference into account,
00168    * just half of it. */
00169   return CeilDiv((n << MapLogX()) + (n << MapLogY()), 1 << 9);
00170 }
00171 
00182 typedef int32 TileIndexDiff;
00183 
00191 static inline TileIndex TileXY(uint x, uint y)
00192 {
00193   return (y << MapLogX()) + x;
00194 }
00195 
00207 static inline TileIndexDiff TileDiffXY(int x, int y)
00208 {
00209   /* Multiplication gives much better optimization on MSVC than shifting.
00210    * 0 << shift isn't optimized to 0 properly.
00211    * Typically x and y are constants, and then this doesn't result
00212    * in any actual multiplication in the assembly code.. */
00213   return (y * MapSizeX()) + x;
00214 }
00215 
00222 static inline TileIndex TileVirtXY(uint x, uint y)
00223 {
00224   return (y >> 4 << MapLogX()) + (x >> 4);
00225 }
00226 
00227 
00233 static inline uint TileX(TileIndex tile)
00234 {
00235   return tile & MapMaxX();
00236 }
00237 
00243 static inline uint TileY(TileIndex tile)
00244 {
00245   return tile >> MapLogX();
00246 }
00247 
00248 static inline uint GetAreaByTile(TileIndex tile)
00249 {
00250   assert(tile < MapSize());
00251   return 1 + (TileY(tile) / (MapSizeY() / _settings_game.game_creation.head_to_head_areas));
00252 }
00253 
00264 static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
00265 {
00266   return (tidc.y << MapLogX()) + tidc.x;
00267 }
00268 
00269 
00270 #ifndef _DEBUG
00271 
00278   #define TILE_ADD(x, y) ((x) + (y))
00279 #else
00280   extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
00281     const char *exp, const char *file, int line);
00282   #define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__))
00283 #endif
00284 
00292 #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y))
00293 
00294 TileIndex TileAddWrap(TileIndex tile, int addx, int addy);
00295 TileIndex TileAddAreaWrap(TileIndex tile, int addx, int addy);
00296 
00303 static inline TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
00304 {
00305   extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
00306 
00307   assert(IsValidDiagDirection(dir));
00308   return _tileoffs_by_diagdir[dir];
00309 }
00310 
00317 static inline TileIndexDiffC TileIndexDiffCByDir(Direction dir)
00318 {
00319   extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
00320 
00321   assert(IsValidDirection(dir));
00322   return _tileoffs_by_dir[dir];
00323 }
00324 
00335 static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
00336 {
00337   int x = TileX(tile) + diff.x;
00338   int y = TileY(tile) + diff.y;
00339   /* Negative value will become big positive value after cast */
00340   if ((uint)x >= MapSizeX() || (uint)y >= MapSizeY()) return INVALID_TILE;
00341   return TileXY(x, y);
00342 }
00343 
00351 static inline TileIndexDiffC TileIndexToTileIndexDiffC(TileIndex tile_a, TileIndex tile_b)
00352 {
00353   TileIndexDiffC difference;
00354 
00355   difference.x = TileX(tile_a) - TileX(tile_b);
00356   difference.y = TileY(tile_a) - TileY(tile_b);
00357 
00358   return difference;
00359 }
00360 
00361 /* Functions to calculate distances */
00362 uint DistanceManhattan(TileIndex, TileIndex); 
00363 uint DistanceSquare(TileIndex, TileIndex); 
00364 uint DistanceMax(TileIndex, TileIndex); 
00365 uint DistanceMaxPlusManhattan(TileIndex, TileIndex); 
00366 uint DistanceFromEdge(TileIndex); 
00367 uint DistanceFromEdgeDir(TileIndex, DiagDirection); 
00368 
00376 static inline TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
00377 {
00378   extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
00379 
00380   assert(IsValidDiagDirection(dir));
00381   return ToTileIndexDiff(_tileoffs_by_diagdir[dir]);
00382 }
00383 
00390 static inline TileIndexDiff TileOffsByDir(Direction dir)
00391 {
00392   extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
00393 
00394   assert(IsValidDirection(dir));
00395   return ToTileIndexDiff(_tileoffs_by_dir[dir]);
00396 }
00397 
00405 static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
00406 {
00407   return TILE_ADD(tile, TileOffsByDiagDir(dir));
00408 }
00409 
00417 static inline DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
00418 {
00419   int dx = (int)TileX(tile_to) - (int)TileX(tile_from);
00420   int dy = (int)TileY(tile_to) - (int)TileY(tile_from);
00421   if (dx == 0) {
00422     if (dy == 0) return INVALID_DIAGDIR;
00423     return (dy < 0 ? DIAGDIR_NW : DIAGDIR_SE);
00424   } else {
00425     if (dy != 0) return INVALID_DIAGDIR;
00426     return (dx < 0 ? DIAGDIR_NE : DIAGDIR_SW);
00427   }
00428 }
00429 
00437 typedef bool TestTileOnSearchProc(TileIndex tile, void *user_data);
00438 
00439 bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data);
00440 bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOnSearchProc proc, void *user_data);
00441 
00447 static inline TileIndex RandomTileSeed(uint32 r)
00448 {
00449   return TILE_MASK(r);
00450 }
00451 
00458 #define RandomTile() RandomTileSeed(Random())
00459 
00463 uint GetClosestWaterDistance(TileIndex tile, bool water);
00464 
00465 TileIndex RandomTileInArea(uint area);
00466 
00467 #endif /* MAP_FUNC_H */