00001
00002
00005 #include "stdafx.h"
00006 #include "debug.h"
00007 #include "direction_func.h"
00008 #include "core/bitmath_func.hpp"
00009 #include "core/alloc_func.hpp"
00010 #include "core/math_func.hpp"
00011 #include "map_func.h"
00012
00013 #if defined(_MSC_VER) && _MSC_VER >= 1400
00014
00015 extern "C" _CRTIMP void __cdecl _assert(void *, void *, unsigned);
00016 #endif
00017
00018 uint _map_log_x;
00019 uint _map_log_y;
00020 uint _map_size_x;
00021 uint _map_size_y;
00022 uint _map_size;
00023 uint _map_tile_mask;
00024
00025 Tile *_m = NULL;
00026 TileExtended *_me = NULL;
00027
00028
00034 void AllocateMap(uint size_x, uint size_y)
00035 {
00036
00037
00038 if (size_x < 64 || size_x > 2048 ||
00039 size_y < 64 || size_y > 2048 ||
00040 (size_x & (size_x - 1)) != 0 ||
00041 (size_y & (size_y - 1)) != 0)
00042 error("Invalid map size");
00043
00044 DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y);
00045
00046 _map_log_x = FindFirstBit(size_x);
00047 _map_log_y = FindFirstBit(size_y);
00048 _map_size_x = size_x;
00049 _map_size_y = size_y;
00050 _map_size = size_x * size_y;
00051 _map_tile_mask = _map_size - 1;
00052
00053 free(_m);
00054 free(_me);
00055
00056
00057
00058
00059
00060
00061 _m = CallocT<Tile>(_map_size);
00062 _me = CallocT<TileExtended>(_map_size);
00063 }
00064
00065
00066 #ifdef _DEBUG
00067 TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
00068 const char *exp, const char *file, int line)
00069 {
00070 int dx;
00071 int dy;
00072 uint x;
00073 uint y;
00074
00075 dx = add & MapMaxX();
00076 if (dx >= (int)MapSizeX() / 2) dx -= MapSizeX();
00077 dy = (add - dx) / (int)MapSizeX();
00078
00079 x = TileX(tile) + dx;
00080 y = TileY(tile) + dy;
00081
00082 if (x >= MapSizeX() || y >= MapSizeY()) {
00083 char buf[512];
00084
00085 snprintf(buf, lengthof(buf), "TILE_ADD(%s) when adding 0x%.4X and 0x%.4X failed",
00086 exp, tile, add);
00087 #if !defined(_MSC_VER) || defined(WINCE)
00088 fprintf(stderr, "%s:%d %s\n", file, line, buf);
00089 #else
00090 _assert(buf, (char*)file, line);
00091 #endif
00092 }
00093
00094 assert(TileXY(x, y) == TILE_MASK(tile + add));
00095
00096 return TileXY(x, y);
00097 }
00098 #endif
00099
00106 uint ScaleByMapSize(uint n)
00107 {
00108
00109
00110
00111 return (n * (MapSize() >> 12) + (1 << 4) - 1) >> 4;
00112 }
00113
00114
00121 uint ScaleByMapSize1D(uint n)
00122 {
00123
00124
00125
00126
00127 return (n * (MapSizeX() + MapSizeY()) + (1 << 9) - 1) >> 9;
00128 }
00129
00130
00144 TileIndex TileAddWrap(TileIndex tile, int addx, int addy)
00145 {
00146 uint x = TileX(tile) + addx;
00147 uint y = TileY(tile) + addy;
00148
00149
00150 if (x < MapMaxX() && y < MapMaxY())
00151 return tile + TileDiffXY(addx, addy);
00152
00153 return INVALID_TILE;
00154 }
00155
00157 extern const TileIndexDiffC _tileoffs_by_diagdir[] = {
00158 {-1, 0},
00159 { 0, 1},
00160 { 1, 0},
00161 { 0, -1}
00162 };
00163
00165 extern const TileIndexDiffC _tileoffs_by_dir[] = {
00166 {-1, -1},
00167 {-1, 0},
00168 {-1, 1},
00169 { 0, 1},
00170 { 1, 1},
00171 { 1, 0},
00172 { 1, -1},
00173 { 0, -1}
00174 };
00175
00185 uint DistanceManhattan(TileIndex t0, TileIndex t1)
00186 {
00187 const uint dx = Delta(TileX(t0), TileX(t1));
00188 const uint dy = Delta(TileY(t0), TileY(t1));
00189 return dx + dy;
00190 }
00191
00192
00202 uint DistanceSquare(TileIndex t0, TileIndex t1)
00203 {
00204 const int dx = TileX(t0) - TileX(t1);
00205 const int dy = TileY(t0) - TileY(t1);
00206 return dx * dx + dy * dy;
00207 }
00208
00209
00217 uint DistanceMax(TileIndex t0, TileIndex t1)
00218 {
00219 const uint dx = Delta(TileX(t0), TileX(t1));
00220 const uint dy = Delta(TileY(t0), TileY(t1));
00221 return max(dx, dy);
00222 }
00223
00224
00233 uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1)
00234 {
00235 const uint dx = Delta(TileX(t0), TileX(t1));
00236 const uint dy = Delta(TileY(t0), TileY(t1));
00237 return dx > dy ? 2 * dx + dy : 2 * dy + dx;
00238 }
00239
00245 uint DistanceFromEdge(TileIndex tile)
00246 {
00247 const uint xl = TileX(tile);
00248 const uint yl = TileY(tile);
00249 const uint xh = MapSizeX() - 1 - xl;
00250 const uint yh = MapSizeY() - 1 - yl;
00251 const uint minl = min(xl, yl);
00252 const uint minh = min(xh, yh);
00253 return min(minl, minh);
00254 }
00255
00269 bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data)
00270 {
00271 uint n, x, y;
00272 DiagDirection dir;
00273
00274 assert(proc != NULL);
00275 assert(size > 0);
00276
00277 x = TileX(tile);
00278 y = TileY(tile);
00279
00280 if (size % 2 == 1) {
00281
00282
00283 n = 2;
00284 if (proc(TileXY(x, y), data)) return true;
00285
00286
00287
00288 x += _tileoffs_by_dir[DIR_W].x;
00289 y += _tileoffs_by_dir[DIR_W].y;
00290 } else {
00291 n = 1;
00292
00293
00294
00295
00296 x++;
00297 }
00298
00299 for (; n < size; n += 2) {
00300 for (dir = DIAGDIR_NE; dir < DIAGDIR_END; dir++) {
00301 uint j;
00302 for (j = n; j != 0; j--) {
00303 if (x <= MapMaxX() && y <= MapMaxY() &&
00304 proc(TileXY(x, y), data)) {
00305 return true;
00306 }
00307
00308
00309 x += _tileoffs_by_diagdir[dir].x;
00310 y += _tileoffs_by_diagdir[dir].y;
00311 }
00312 }
00313
00314 x += _tileoffs_by_dir[DIR_W].x;
00315 y += _tileoffs_by_dir[DIR_W].y;
00316 }
00317 return false;
00318 }