tron@2186: /* $Id$ */ tron@2186: tron@679: #ifndef MAP_H tron@679: #define MAP_H tron@679: tron@1210: #include "stdafx.h" tron@1210: ludde@2051: // Putting externs inside inline functions seems to confuse the aliasing ludde@2051: // checking on MSVC6. Never use those variables directly. ludde@2051: extern uint _map_log_x; ludde@2051: extern uint _map_size_x; ludde@2051: extern uint _map_size_y; ludde@2051: extern uint _map_tile_mask; ludde@2051: extern uint _map_size; ludde@2051: ludde@2051: #define TILE_MASK(x) ((x) & _map_tile_mask) tron@1394: #define TILE_ASSERT(x) assert(TILE_MASK(x) == (x)); tron@926: tron@2049: typedef struct Tile { tron@2049: byte type_height; tron@2360: byte m1; tron@2049: uint16 m2; tron@2049: byte m3; tron@2049: byte m4; tron@2049: byte m5; tron@2049: byte extra; tron@2049: } Tile; tron@2049: tron@2049: extern Tile* _m; tron@1218: ludde@2051: void AllocateMap(uint size_x, uint size_y); ludde@2051: tron@689: // binary logarithm of the map size, try to avoid using this one ludde@2051: static inline uint MapLogX(void) { return _map_log_x; } tron@689: /* The size of the map */ ludde@2051: static inline uint MapSizeX(void) { return _map_size_x; } ludde@2051: static inline uint MapSizeY(void) { return _map_size_y; } tron@689: /* The maximum coordinates */ ludde@2051: static inline uint MapMaxX(void) { return _map_size_x - 1; } ludde@2051: static inline uint MapMaxY(void) { return _map_size_y - 1; } tron@689: /* The number of tiles in the map */ ludde@2051: static inline uint MapSize(void) { return _map_size; } tron@689: tron@1202: // Scale a number relative to the map size tron@1202: uint ScaleByMapSize(uint); // Scale relative to the number of tiles tron@1202: uint ScaleByMapSize1D(uint); // Scale relative to the circumference of the map tron@1202: tron@1174: typedef uint32 TileIndex; tron@1981: typedef int32 TileIndexDiff; tron@1981: tron@1981: static inline TileIndex TileXY(uint x, uint y) tron@1981: { ludde@2051: return (y * MapSizeX()) + x; tron@1981: } tron@1981: tron@1981: static inline TileIndexDiff TileDiffXY(int x, int y) tron@1981: { ludde@2051: // Multiplication gives much better optimization on MSVC than shifting. ludde@2051: // 0 << shift isn't optimized to 0 properly. ludde@2051: // Typically x and y are constants, and then this doesn't result ludde@2051: // in any actual multiplication in the assembly code.. ludde@2051: return (y * MapSizeX()) + x; tron@1981: } matthijs@1330: tron@1980: static inline TileIndex TileVirtXY(uint x, uint y) tron@1980: { tron@1980: return (y >> 4 << MapLogX()) + (x >> 4); tron@1980: } tron@1980: Darkvater@4849: typedef byte Owner; Darkvater@4849: enum Owners { tron@4000: OWNER_TOWN = 0x0F, // a town owns the tile tron@4000: OWNER_NONE = 0x10, // nobody owns the tile tron@4000: OWNER_WATER = 0x11, // "water" owns the tile Darkvater@4846: OWNER_END = 0x12, Darkvater@4849: }; matthijs@1330: matthijs@1247: enum { tron@1977: INVALID_TILE = (TileIndex)-1 matthijs@1247: }; tron@926: matthijs@1942: enum { matthijs@1942: TILE_SIZE = 16, /* Tiles are 16x16 "units" in size */ matthijs@1942: TILE_PIXELS = 32, /* a tile is 32x32 pixels */ rubidium@4344: TILE_HEIGHT = 8, /* The standard height-difference between tiles on two levels is 8 (z-diff 8) */ matthijs@1942: }; matthijs@1942: matthijs@1942: tron@926: static inline uint TileX(TileIndex tile) tron@926: { tron@926: return tile & MapMaxX(); tron@926: } tron@926: tron@926: static inline uint TileY(TileIndex tile) tron@926: { tron@926: return tile >> MapLogX(); tron@926: } tron@926: tron@926: tron@909: typedef struct TileIndexDiffC { tron@909: int16 x; tron@909: int16 y; tron@909: } TileIndexDiffC; tron@909: tron@909: static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc) tron@909: { tron@909: return (tidc.y << MapLogX()) + tidc.x; tron@909: } tron@900: tron@955: tron@955: #ifndef _DEBUG tron@955: #define TILE_ADD(x,y) ((x) + (y)) tron@955: #else tron@955: extern TileIndex TileAdd(TileIndex tile, TileIndexDiff add, tron@955: const char *exp, const char *file, int line); tron@955: #define TILE_ADD(x, y) (TileAdd((x), (y), #x " + " #y, __FILE__, __LINE__)) tron@955: #endif tron@955: tron@1981: #define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TileDiffXY(x, y)) tron@955: matthijs@1247: uint TileAddWrap(TileIndex tile, int addx, int addy); matthijs@1247: glx@4561: static inline TileIndexDiffC TileIndexDiffCByDiagDir(uint dir) { glx@4561: extern const TileIndexDiffC _tileoffs_by_diagdir[4]; glx@4561: glx@4561: assert(dir < lengthof(_tileoffs_by_diagdir)); glx@4561: return _tileoffs_by_diagdir[dir]; matthijs@1247: } matthijs@1247: matthijs@1247: /* Returns tile + the diff given in diff. If the result tile would end up matthijs@1247: * outside of the map, INVALID_TILE is returned instead. matthijs@1247: */ matthijs@1247: static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff) { matthijs@1247: int x = TileX(tile) + diff.x; matthijs@1247: int y = TileY(tile) + diff.y; matthijs@1247: if (x < 0 || y < 0 || x > (int)MapMaxX() || y > (int)MapMaxY()) matthijs@1247: return INVALID_TILE; matthijs@1247: else tron@1981: return TileXY(x, y); matthijs@1247: } tron@955: tron@1245: // Functions to calculate distances matthijs@1677: uint DistanceManhattan(TileIndex, TileIndex); // also known as L1-Norm. Is the shortest distance one could go over diagonal tracks (or roads) tron@1245: uint DistanceSquare(TileIndex, TileIndex); // euclidian- or L2-Norm squared tron@1245: uint DistanceMax(TileIndex, TileIndex); // also known as L-Infinity-Norm tron@1245: uint DistanceMaxPlusManhattan(TileIndex, TileIndex); // Max + Manhattan tron@1245: uint DistanceFromEdge(TileIndex); // shortest distance from any edge of the map tron@1245: tron@1245: tron@2159: #define BEGIN_TILE_LOOP(var,w,h,tile) \ tron@2159: { \ tron@2159: int h_cur = h; \ tron@2159: uint var = tile; \ tron@2159: do { \ tron@2159: int w_cur = w; \ tron@2159: do { tron@2159: tron@2159: #define END_TILE_LOOP(var,w,h,tile) \ tron@2159: } while (++var, --w_cur != 0); \ tron@2159: } while (var += TileDiffXY(0, 1) - (w), --h_cur != 0); \ tron@2159: } tron@2159: glx@4561: static inline TileIndexDiff TileOffsByDiagDir(uint dir) Darkvater@4559: { Darkvater@4559: extern const TileIndexDiffC _tileoffs_by_diagdir[4]; tron@2159: Darkvater@4559: assert(dir < lengthof(_tileoffs_by_diagdir)); Darkvater@4559: return ToTileIndexDiff(_tileoffs_by_diagdir[dir]); Darkvater@4559: } Darkvater@4559: glx@4561: static inline TileIndexDiff TileOffsByDir(uint dir) tron@900: { Darkvater@4559: extern const TileIndexDiffC _tileoffs_by_dir[8]; tron@900: tron@900: assert(dir < lengthof(_tileoffs_by_dir)); tron@909: return ToTileIndexDiff(_tileoffs_by_dir[dir]); tron@900: } tron@900: belugas@5118: typedef bool TestTileOnSearchProc(TileIndex tile, uint32 data); belugas@5118: bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data); belugas@5118: matthijs@1677: /* Approximation of the length of a straight track, relative to a diagonal matthijs@1677: * track (ie the size of a tile side). #defined instead of const so it can matthijs@1677: * stay integer. (no runtime float operations) Is this needed? matthijs@1679: * Watch out! There are _no_ brackets around here, to prevent intermediate matthijs@1679: * rounding! Be careful when using this! matthijs@1677: * This value should be sqrt(2)/2 ~ 0.7071 */ matthijs@1679: #define STRAIGHT_TRACK_LENGTH 7071/10000 matthijs@1677: Darkvater@2436: #endif /* MAP_H */