src/map_func.h
branchnoai
changeset 9723 eee46cb39750
child 9724 b39bc69bb2f2
equal deleted inserted replaced
9722:ebf0ece7d8f6 9723:eee46cb39750
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file map.h */
       
     4 
       
     5 #ifndef MAP_FUNC_H
       
     6 #define MAP_FUNC_H
       
     7 
       
     8 #include "tile_type.h"
       
     9 #include "map_type.h"
       
    10 #include "direction_func.h"
       
    11 
       
    12 extern uint _map_tile_mask;
       
    13 
       
    14 /**
       
    15  * 'Wraps' the given tile to it is within the map. It does
       
    16  * this by masking the 'high' bits of.
       
    17  * @param x the tile to 'wrap'
       
    18  */
       
    19 
       
    20 #define TILE_MASK(x) ((x) & _map_tile_mask)
       
    21 /**
       
    22  * Asserts when the tile is outside of the map.
       
    23  * @param x the tile to check
       
    24  */
       
    25 #define TILE_ASSERT(x) assert(TILE_MASK(x) == (x));
       
    26 
       
    27 /**
       
    28  * Pointer to the tile-array.
       
    29  *
       
    30  * This variable points to the tile-array which contains the tiles of
       
    31  * the map.
       
    32  */
       
    33 extern Tile *_m;
       
    34 
       
    35 /**
       
    36  * Pointer to the extended tile-array.
       
    37  *
       
    38  * This variable points to the extended tile-array which contains the tiles
       
    39  * of the map.
       
    40  */
       
    41 extern TileExtended *_me;
       
    42 
       
    43 /**
       
    44  * Allocate a new map with the given size.
       
    45  */
       
    46 void AllocateMap(uint size_x, uint size_y);
       
    47 
       
    48 /**
       
    49  * Logarithm of the map size along the X side.
       
    50  * @note try to avoid using this one
       
    51  * @return 2^"return value" == MapSizeX()
       
    52  */
       
    53 static inline uint MapLogX()
       
    54 {
       
    55 	extern uint _map_log_x;
       
    56 	return _map_log_x;
       
    57 }
       
    58 
       
    59 /**
       
    60  * Get the size of the map along the X
       
    61  * @return the number of tiles along the X of the map
       
    62  */
       
    63 static inline uint MapSizeX()
       
    64 {
       
    65 	extern uint _map_size_x;
       
    66 	return _map_size_x;
       
    67 }
       
    68 
       
    69 /**
       
    70  * Get the size of the map along the Y
       
    71  * @return the number of tiles along the Y of the map
       
    72  */
       
    73 static inline uint MapSizeY()
       
    74 {
       
    75 	extern uint _map_size_y;
       
    76 	return _map_size_y;
       
    77 }
       
    78 
       
    79 /**
       
    80  * Get the size of the map
       
    81  * @return the number of tiles of the map
       
    82  */
       
    83 static inline uint MapSize()
       
    84 {
       
    85 	extern uint _map_size;
       
    86 	return _map_size;
       
    87 }
       
    88 
       
    89 /**
       
    90  * Gets the maximum X coordinate within the map, including MP_VOID
       
    91  * @return the maximum X coordinate
       
    92  */
       
    93 static inline uint MapMaxX()
       
    94 {
       
    95 	return MapSizeX() - 1;
       
    96 }
       
    97 
       
    98 /**
       
    99  * Gets the maximum X coordinate within the map, including MP_VOID
       
   100  * @return the maximum X coordinate
       
   101  */
       
   102 static inline uint MapMaxY()
       
   103 {
       
   104 	return MapSizeY() - 1;
       
   105 }
       
   106 
       
   107 /**
       
   108  * Scales relative to the number of tiles.
       
   109  */
       
   110 uint ScaleByMapSize(uint);
       
   111 
       
   112 /**
       
   113  * Scale relative to the circumference of the map.
       
   114  */
       
   115 uint ScaleByMapSize1D(uint);
       
   116 
       
   117 /**
       
   118  * An offset value between to tiles.
       
   119  *
       
   120  * This value is used fro the difference between
       
   121  * to tiles. It can be added to a tileindex to get
       
   122  * the resulting tileindex of the start tile applied
       
   123  * with this saved difference.
       
   124  *
       
   125  * @see TileDiffXY(int, int)
       
   126  */
       
   127 typedef int32 TileIndexDiff;
       
   128 
       
   129 /**
       
   130  * Returns the TileIndex of a coordinate.
       
   131  *
       
   132  * @param x The x coordinate of the tile
       
   133  * @param y The y coordinate of the tile
       
   134  * @return The TileIndex calculated by the coordinate
       
   135  */
       
   136 static inline TileIndex TileXY(uint x, uint y)
       
   137 {
       
   138 	return (y * MapSizeX()) + x;
       
   139 }
       
   140 
       
   141 /**
       
   142  * Calculates an offset for the given coordinate(-offset).
       
   143  *
       
   144  * This function calculate an offset value which can be added to an
       
   145  * #TileIndex. The coordinates can be negative.
       
   146  *
       
   147  * @param x The offset in x direction
       
   148  * @param y The offset in y direction
       
   149  * @return The resulting offset value of the given coordinate
       
   150  * @see ToTileIndexDiff(TileIndexDiffC)
       
   151  */
       
   152 static inline TileIndexDiff TileDiffXY(int x, int y)
       
   153 {
       
   154 	/* Multiplication gives much better optimization on MSVC than shifting.
       
   155 	 * 0 << shift isn't optimized to 0 properly.
       
   156 	 * Typically x and y are constants, and then this doesn't result
       
   157 	 * in any actual multiplication in the assembly code.. */
       
   158 	return (y * MapSizeX()) + x;
       
   159 }
       
   160 
       
   161 static inline TileIndex TileVirtXY(uint x, uint y)
       
   162 {
       
   163 	return (y >> 4 << MapLogX()) + (x >> 4);
       
   164 }
       
   165 
       
   166 
       
   167 /**
       
   168  * Get the X component of a tile
       
   169  * @param tile the tile to get the X component of
       
   170  * @return the X component
       
   171  */
       
   172 static inline uint TileX(TileIndex tile)
       
   173 {
       
   174 	return tile & MapMaxX();
       
   175 }
       
   176 
       
   177 /**
       
   178  * Get the Y component of a tile
       
   179  * @param tile the tile to get the Y component of
       
   180  * @return the Y component
       
   181  */
       
   182 static inline uint TileY(TileIndex tile)
       
   183 {
       
   184 	return tile >> MapLogX();
       
   185 }
       
   186 
       
   187 /**
       
   188  * Return the offset between to tiles from a TileIndexDiffC struct.
       
   189  *
       
   190  * This function works like #TileDiffXY(int, int) and returns the
       
   191  * difference between two tiles.
       
   192  *
       
   193  * @param tidc The coordinate of the offset as TileIndexDiffC
       
   194  * @return The difference between two tiles.
       
   195  * @see TileDiffXY(int, int)
       
   196  */
       
   197 static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
       
   198 {
       
   199 	return (tidc.y << MapLogX()) + tidc.x;
       
   200 }
       
   201 
       
   202 
       
   203 #ifndef _DEBUG
       
   204 	/**
       
   205 	 * Adds to tiles together.
       
   206 	 *
       
   207 	 * @param x One tile
       
   208 	 * @param y An other tile to add
       
   209 	 * @return The resulting tile(index)
       
   210 	 */
       
   211 	#define TILE_ADD(x,y) ((x) + (y))
       
   212 #else
       
   213 	extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
       
   214 		const char *exp, const char *file, int line);
       
   215 	#define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__))
       
   216 #endif
       
   217 
       
   218 /**
       
   219  * Adds a given offset to a tile.
       
   220  *
       
   221  * @param tile The tile to add an offset on it
       
   222  * @param x The x offset to add to the tile
       
   223  * @param y The y offset to add to the tile
       
   224  */
       
   225 #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y))
       
   226 
       
   227 /**
       
   228  * Adds an offset to a tile and check if we are still on the map.
       
   229  */
       
   230 uint TileAddWrap(TileIndex tile, int addx, int addy);
       
   231 
       
   232 /**
       
   233  * Returns the TileIndexDiffC offset from a DiagDirection.
       
   234  *
       
   235  * @param dir The given direction
       
   236  * @return The offset as TileIndexDiffC value
       
   237  */
       
   238 static inline TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
       
   239 {
       
   240 	extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
       
   241 
       
   242 	assert(IsValidDiagDirection(dir));
       
   243 	return _tileoffs_by_diagdir[dir];
       
   244 }
       
   245 
       
   246 /**
       
   247  * Add a TileIndexDiffC to a TileIndex and returns the new one.
       
   248  *
       
   249  * Returns tile + the diff given in diff. If the result tile would end up
       
   250  * outside of the map, INVALID_TILE is returned instead.
       
   251  *
       
   252  * @param tile The base tile to add the offset on
       
   253  * @param diff The offset to add on the tile
       
   254  * @return The resulting TileIndex
       
   255  */
       
   256 static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
       
   257 {
       
   258 	int x = TileX(tile) + diff.x;
       
   259 	int y = TileY(tile) + diff.y;
       
   260 	if (x < 0 || y < 0 || x > (int)MapMaxX() || y > (int)MapMaxY())
       
   261 		return INVALID_TILE;
       
   262 	else
       
   263 		return TileXY(x, y);
       
   264 }
       
   265 
       
   266 /**
       
   267  * Returns the diff between two tiles
       
   268  *
       
   269  * @param tile_a from tile
       
   270  * @param tile_b to tile
       
   271  * @return the difference between tila_a and tile_b
       
   272  */
       
   273 static inline TileIndexDiffC TileIndexToTileIndexDiffC(TileIndex tile_a, TileIndex tile_b)
       
   274 {
       
   275 	TileIndexDiffC difference;
       
   276 
       
   277 	difference.x = TileX(tile_a) - TileX(tile_b);
       
   278 	difference.y = TileY(tile_a) - TileY(tile_b);
       
   279 
       
   280 	return difference;
       
   281 }
       
   282 
       
   283 /* Functions to calculate distances */
       
   284 uint DistanceManhattan(TileIndex, TileIndex); ///< also known as L1-Norm. Is the shortest distance one could go over diagonal tracks (or roads)
       
   285 uint DistanceSquare(TileIndex, TileIndex); ///< euclidian- or L2-Norm squared
       
   286 uint DistanceMax(TileIndex, TileIndex); ///< also known as L-Infinity-Norm
       
   287 uint DistanceMaxPlusManhattan(TileIndex, TileIndex); ///< Max + Manhattan
       
   288 uint DistanceFromEdge(TileIndex); ///< shortest distance from any edge of the map
       
   289 
       
   290 /**
       
   291  * Starts a loop which iterates to a square of tiles
       
   292  *
       
   293  * This macro starts 2 nested loops which iterates over a square of tiles.
       
   294  *
       
   295  * @param var The name of the variable which contains the current tile
       
   296  * @param w The width (x-width) of the square
       
   297  * @param h The heigth (y-width) of the square
       
   298  * @param tile The start tile of the square
       
   299  */
       
   300 #define BEGIN_TILE_LOOP(var, w, h, tile)                      \
       
   301 	{                                                        \
       
   302 		int h_cur = h;                                         \
       
   303 		uint var = tile;                                       \
       
   304 		do {                                                   \
       
   305 			int w_cur = w;                                       \
       
   306 			do {
       
   307 /**
       
   308  * Ends the square-loop used before
       
   309  *
       
   310  * @see BEGIN_TILE_LOOP
       
   311  */
       
   312 #define END_TILE_LOOP(var, w, h, tile)                        \
       
   313 			} while (++var, --w_cur != 0);                       \
       
   314 		} while (var += TileDiffXY(0, 1) - (w), --h_cur != 0); \
       
   315 	}
       
   316 /**
       
   317  * Convert a DiagDirection to a TileIndexDiff
       
   318  *
       
   319  * @param dir The DiagDirection
       
   320  * @return The resulting TileIndexDiff
       
   321  * @see TileIndexDiffCByDiagDir
       
   322  */
       
   323 static inline TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
       
   324 {
       
   325 	extern const TileIndexDiffC _tileoffs_by_diagdir[DIAGDIR_END];
       
   326 
       
   327 	assert(IsValidDiagDirection(dir));
       
   328 	return ToTileIndexDiff(_tileoffs_by_diagdir[dir]);
       
   329 }
       
   330 
       
   331 /**
       
   332  * Convert a Direction to a TileIndexDiff.
       
   333  *
       
   334  * @param dir The direction to convert from
       
   335  * @return The resulting TileIndexDiff
       
   336  */
       
   337 static inline TileIndexDiff TileOffsByDir(Direction dir)
       
   338 {
       
   339 	extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
       
   340 
       
   341 	assert(IsValidDirection(dir));
       
   342 	return ToTileIndexDiff(_tileoffs_by_dir[dir]);
       
   343 }
       
   344 
       
   345 /**
       
   346  * Adds a DiagDir to a tile.
       
   347  *
       
   348  * @param tile The current tile
       
   349  * @param dir The direction in which we want to step
       
   350  * @return the moved tile
       
   351  */
       
   352 static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
       
   353 {
       
   354 	return TILE_ADD(tile, TileOffsByDiagDir(dir));
       
   355 }
       
   356 
       
   357 /**
       
   358  * A callback function type for searching tiles.
       
   359  *
       
   360  * @param tile The tile to test
       
   361  * @param data additional data for the callback function to use
       
   362  * @return A boolean value, depend on the definition of the function.
       
   363  */
       
   364 typedef bool TestTileOnSearchProc(TileIndex tile, uint32 data);
       
   365 
       
   366 /**
       
   367  * Searches for some cirumstances of a tile around a given tile with a helper function.
       
   368  */
       
   369 bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data);
       
   370 
       
   371 /**
       
   372  * Get a random tile out of a given seed.
       
   373  * @param r the random 'seed'
       
   374  * @return a valid tile
       
   375  */
       
   376 static inline TileIndex RandomTileSeed(uint32 r)
       
   377 {
       
   378 	return TILE_MASK(r);
       
   379 }
       
   380 
       
   381 /**
       
   382  * Get a valid random tile.
       
   383  * @note a define so 'random' gets inserted in the place where it is actually
       
   384  *       called, thus making the random traces more explicit.
       
   385  * @return a valid tile
       
   386  */
       
   387 #define RandomTile() RandomTileSeed(Random())
       
   388 
       
   389 #endif /* MAP_FUNC_H */