map.c
changeset 5118 9640617e1abb
parent 4559 aa0c13e39840
child 5170 817550aa5a5f
equal deleted inserted replaced
5117:d64bf0093ff4 5118:9640617e1abb
     4 #include "openttd.h"
     4 #include "openttd.h"
     5 #include "debug.h"
     5 #include "debug.h"
     6 #include "functions.h"
     6 #include "functions.h"
     7 #include "macros.h"
     7 #include "macros.h"
     8 #include "map.h"
     8 #include "map.h"
       
     9 #include "direction.h"
     9 
    10 
    10 #if defined(_MSC_VER) && _MSC_VER >= 1400 /* VStudio 2005 is stupid! */
    11 #if defined(_MSC_VER) && _MSC_VER >= 1400 /* VStudio 2005 is stupid! */
    11 /* Why the hell is that not in all MSVC headers?? */
    12 /* Why the hell is that not in all MSVC headers?? */
    12 _CRTIMP void __cdecl _assert(void *, void *, unsigned);
    13 _CRTIMP void __cdecl _assert(void *, void *, unsigned);
    13 #endif
    14 #endif
   177 	const uint yh = MapSizeY() - 1 - yl;
   178 	const uint yh = MapSizeY() - 1 - yl;
   178 	const uint minl = xl < yl ? xl : yl;
   179 	const uint minl = xl < yl ? xl : yl;
   179 	const uint minh = xh < yh ? xh : yh;
   180 	const uint minh = xh < yh ? xh : yh;
   180 	return minl < minh ? minl : minh;
   181 	return minl < minh ? minl : minh;
   181 }
   182 }
       
   183 
       
   184 /**
       
   185  * Function performing a search around a center tile and going outward, thus in circle.
       
   186  * Although it really is a square search...
       
   187  * Every tile will be tested by means of the callback function proc,
       
   188  * which will determine if yes or no the given tile meets criteria of search.
       
   189  * @param tile to start the search from
       
   190  * @param size: number of tiles per side of the desired search area
       
   191  * @param proc: callback testing function pointer.
       
   192  * @param data to be passed to the callback function. Depends on the implementation
       
   193  * @result of the search
       
   194  * @pre proc != NULL
       
   195  * @pre size > 0
       
   196  */
       
   197 bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data)
       
   198 {
       
   199 	uint n, x, y;
       
   200 	DiagDirection dir;
       
   201 
       
   202 	assert(proc != NULL);
       
   203 	assert(size > 0);
       
   204 
       
   205 	x = TileX(tile);
       
   206 	y = TileY(tile);
       
   207 
       
   208 	if (size % 2 == 1) {
       
   209 		/* If the length of the side is uneven, the center has to be checked
       
   210 		 * separately, as the pattern of uneven sides requires to go around the center */
       
   211 		n = 2;
       
   212 		if (proc(TileXY(x, y), data)) return true;
       
   213 
       
   214 		/* If tile test is not successfull, get one tile down and left,
       
   215 		 * ready for a test in first circle around center tile */
       
   216 		x += _tileoffs_by_dir[DIR_W].x;
       
   217 		y += _tileoffs_by_dir[DIR_W].y;
       
   218 	} else {
       
   219 		n = 1;
       
   220 		/* To use _tileoffs_by_diagdir's order, we must relocate to
       
   221 		 * another tile, as we now first go 'up', 'right', 'down', 'left'
       
   222 		 * instead of 'right', 'down', 'left', 'up', which the calling
       
   223 		 * function assume. */
       
   224 		x++;
       
   225 	}
       
   226 
       
   227 	for (; n < size; n += 2) {
       
   228 		for (dir = DIAGDIR_NE; dir < DIAGDIR_END; dir++) {
       
   229 			uint j;
       
   230 			for (j = n; j != 0; j--) {
       
   231 				if (x <= MapMaxX() && y <= MapMaxY() && ///< Is the tile within the map?
       
   232 						proc(TileXY(x, y), data)) {     ///< Is the callback successfulll?
       
   233 					return true;                        ///< then stop the search
       
   234 				}
       
   235 
       
   236 				/* Step to the next 'neighbour' in the circular line */
       
   237 				x += _tileoffs_by_diagdir[dir].x;
       
   238 				y += _tileoffs_by_diagdir[dir].y;
       
   239 			}
       
   240 		}
       
   241 		/* Jump to next circle to test */
       
   242 		x += _tileoffs_by_dir[DIR_W].x;
       
   243 		y += _tileoffs_by_dir[DIR_W].y;
       
   244 	}
       
   245 	return false;
       
   246 }