* Finds the distance for the closest tile with water/land given a tile * @param tile the tile to find the distance too * @param water whether to find water or land * @return distance to nearest water (max 0x7F) / land (max 0x1FF; 0x200 if there is no land) */
| 261 | * @return distance to nearest water (max 0x7F) / land (max 0x1FF; 0x200 if there is no land) |
| 262 | */ |
| 263 | uint GetClosestWaterDistance(TileIndex tile, bool water) |
| 264 | { |
| 265 | if (HasTileWaterGround(tile) == water) return 0; |
| 266 | |
| 267 | uint max_dist = water ? 0x7F : 0x200; |
| 268 | |
| 269 | int x = TileX(tile); |
| 270 | int y = TileY(tile); |
| 271 | |
| 272 | uint max_x = Map::MaxX(); |
| 273 | uint max_y = Map::MaxY(); |
| 274 | uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0; |
| 275 | |
| 276 | /* go in a 'spiral' with increasing manhattan distance in each iteration */ |
| 277 | for (uint dist = 1; dist < max_dist; dist++) { |
| 278 | /* next 'diameter' */ |
| 279 | y--; |
| 280 | |
| 281 | /* going counter-clockwise around this square */ |
| 282 | for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { |
| 283 | static const int8_t ddx[DIAGDIR_END] = { -1, 1, 1, -1}; |
| 284 | static const int8_t ddy[DIAGDIR_END] = { 1, 1, -1, -1}; |
| 285 | |
| 286 | int dx = ddx[dir]; |
| 287 | int dy = ddy[dir]; |
| 288 | |
| 289 | /* each side of this square has length 'dist' */ |
| 290 | for (uint a = 0; a < dist; a++) { |
| 291 | /* MP_VOID tiles are not checked (interval is [min; max) for IsInsideMM())*/ |
| 292 | if (IsInsideMM(x, min_xy, max_x) && IsInsideMM(y, min_xy, max_y)) { |
| 293 | TileIndex t = TileXY(x, y); |
| 294 | if (HasTileWaterGround(t) == water) return dist; |
| 295 | } |
| 296 | x += dx; |
| 297 | y += dy; |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | if (!water) { |
| 303 | /* no land found - is this a water-only map? */ |
| 304 | for (const auto t : Map::Iterate()) { |
| 305 | if (!IsTileType(t, MP_VOID) && !IsTileType(t, MP_WATER)) return 0x1FF; |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | return max_dist; |
| 310 | } |
no test coverage detected