/**
* Check whether growing on a half-tile coast tile ends up blocking a water connection
*
* @param tile The target tile
* @return true if building here blocks a water connection
*/
static bool GrowingBlocksWaterConnection(TileIndex tile)
{
if (!IsValidTile(tile)) return false;
Slope slope = GetTileSlope(tile);
/* Is this a coast tile with one corner raised ? */
if (IsSlopeWithOneCornerRaised(slope) && IsCoastTile(tile)) {
Corner corner = GetHighestSlopeCorner(slope);
Corner opposite_corner = OppositeCorner(corner);
static const Direction corner_to_direction[] = { DIR_W, DIR_S, DIR_E, DIR_N };
extern const TileIndexDiffC _tileoffs_by_dir[DIR_END];
TileIndexDiffC diffc = _tileoffs_by_dir[corner_to_direction[opposite_corner]];
TileIndex opposite_tile = TileAddWrap(tile, diffc.x, diffc.y);
if (IsValidTile(opposite_tile)) {
static const struct { TrackBits track_mask_1, track_mask_2, track_mask_1_90_deg, track_mask_2_90_deg; } track_bit_table[] = {
/* t1x,t1y,t2x,t2y, track_mask_1 , track_mask_2 track_mask_1_90_deg, track_mask_2_90_deg, opposite_tile */
/* CORNER_W 0, 1, -1, 0, */ { TRACK_BIT_X | TRACK_BIT_RIGHT, TRACK_BIT_Y | TRACK_BIT_RIGHT, TRACK_BIT_3WAY_NE, TRACK_BIT_3WAY_SE }, /* -1, 1 */
/* CORNER_S 1, 0, 0, 1, */ { TRACK_BIT_Y | TRACK_BIT_UPPER, TRACK_BIT_X | TRACK_BIT_UPPER, TRACK_BIT_3WAY_NW, TRACK_BIT_3WAY_NE }, /* 1, 1 */
/* CORNER_E 0, -1, 1, 0, */ { TRACK_BIT_X | TRACK_BIT_LEFT , TRACK_BIT_Y | TRACK_BIT_LEFT , TRACK_BIT_3WAY_SW, TRACK_BIT_3WAY_NW }, /* 1, -1 */
/* CORNER_N -1, 0, 0, -1, */ { TRACK_BIT_Y | TRACK_BIT_LOWER, TRACK_BIT_X | TRACK_BIT_LOWER, TRACK_BIT_3WAY_SE, TRACK_BIT_3WAY_SW }, /* -1, -1 */
};
TileIndex tile_1 = TileAddWrap(tile, opposite_corner & 1 ? diffc.x : 0, opposite_corner & 1 ? 0 : diffc.y);
TileIndex tile_2 = TileAddWrap(tile, opposite_corner & 1 ? 0 : diffc.x, opposite_corner & 1 ? diffc.y : 0);
bool forbid_90_deg = _settings_game.pf.forbid_90_deg;
TrackBits track_1 = TrackStatusToTrackBits(GetTileTrackStatus(tile_1, TRANSPORT_WATER, 0));
TrackBits track_2 = TrackStatusToTrackBits(GetTileTrackStatus(tile_2, TRANSPORT_WATER, 0));
TrackBits next_track_1 = (forbid_90_deg ? track_bit_table[corner].track_mask_1 : track_bit_table[corner].track_mask_1_90_deg) & track_1;
TrackBits next_track_2 = (forbid_90_deg ? track_bit_table[corner].track_mask_2 : track_bit_table[corner].track_mask_2_90_deg) & track_2;
TrackBits main_track_1 = (forbid_90_deg ? track_bit_table[opposite_corner].track_mask_2 : track_bit_table[opposite_corner].track_mask_2_90_deg) & track_1;
TrackBits main_track_2 = (forbid_90_deg ? track_bit_table[opposite_corner].track_mask_1 : track_bit_table[opposite_corner].track_mask_1_90_deg) & track_2;
/* Is there a connection between tile_1 and tile_2 via tile? */
if (main_track_1 && main_track_2) {
TrackBits opposite_track = TrackStatusToTrackBits(GetTileTrackStatus(opposite_tile, TRANSPORT_WATER, 0));
/* Is there an opposite_track that can be used to try an alternative connection? */
if (CornerToTrackBits(corner) & opposite_track) {
TrackBits mirror = TRACK_BIT_CROSS | (corner & 1 ? TRACK_BIT_HORZ : TRACK_BIT_VERT);
/* Is there a connection between tile_1 and tile_2 via opposite_tile? */
if (next_track_1 & (main_track_1 ^ mirror) && next_track_2 & (main_track_2 ^ mirror)) {
/* There is an alternative connection. Town can grow on tile. */
return false;
}
}
/* There is either no opposite_track, or an incomplete connection via opposite_tile. */
return true;
}
}
}
/* There was no connection via tile, or it was incomplete, or the opposite_tile is outside the map. */
return false;
}