/** * 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) || !IsCoastTile(tile)) return false; Slope slope = GetTileSlope(tile); /* Is this a coast tile with one corner raised ? */ if (IsSlopeWithOneCornerRaised(slope)) { const Track main_track_mask = TrackBitsToTrack(TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0))); const Track oppo_track_mask = TrackToOppositeTrack(main_track_mask); const Trackdir main_trackdir = TrackToTrackdir(main_track_mask); const Trackdir oppo_trackdir = TrackToTrackdir(oppo_track_mask); const DiagDirection main_dir_1 = TrackdirToExitdir(main_trackdir); const DiagDirection main_dir_2 = TrackdirToExitdir(ReverseTrackdir(main_trackdir)); const DiagDirection oppo_dir_1 = TrackdirToExitdir(oppo_trackdir); const DiagDirection oppo_dir_2 = TrackdirToExitdir(ReverseTrackdir(oppo_trackdir)); TrackBits main_trackbits_mask_1 = DiagdirReachesTracks(main_dir_1); TrackBits main_trackbits_mask_2 = DiagdirReachesTracks(main_dir_2); TrackBits oppo_trackbits_mask_1 = DiagdirReachesTracks(oppo_dir_1); TrackBits oppo_trackbits_mask_2 = DiagdirReachesTracks(oppo_dir_2); if (_settings_game.pf.forbid_90_deg) { main_trackbits_mask_1 &= ~TrackCrossesTracks(main_track_mask); main_trackbits_mask_2 &= ~TrackCrossesTracks(main_track_mask); oppo_trackbits_mask_1 &= ~TrackCrossesTracks(oppo_track_mask); oppo_trackbits_mask_2 &= ~TrackCrossesTracks(oppo_track_mask); } Corner corner = GetHighestSlopeCorner(slope); static const Direction corner_to_direction[] = { DIR_W, DIR_S, DIR_E, DIR_N }; TileIndex opposite_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(corner_to_direction[OppositeCorner(corner)])); if (IsValidTile(opposite_tile)) { TileIndex tile_1 = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(main_dir_1)); TileIndex tile_2 = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(main_dir_2)); TrackBits track_1 = TrackStatusToTrackBits(GetTileTrackStatus(tile_1, TRANSPORT_WATER, 0)); TrackBits track_2 = TrackStatusToTrackBits(GetTileTrackStatus(tile_2, TRANSPORT_WATER, 0)); TrackBits main_track_1 = main_trackbits_mask_1 & track_1; TrackBits main_track_2 = main_trackbits_mask_2 & track_2; TrackBits oppo_track_1 = oppo_trackbits_mask_1 & track_1; TrackBits oppo_track_2 = oppo_trackbits_mask_2 & track_2; /* Is there a connection between tile_1 and tile_2 via tile? */ if (main_track_1 && main_track_2) { TrackBits oppo_trackbits = TrackStatusToTrackBits(GetTileTrackStatus(opposite_tile, TRANSPORT_WATER, 0)); /* Is there a track in the opposite_tile that can be used to try an alternative connection? */ if (HasTrack(oppo_trackbits, oppo_track_mask)) { 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 (oppo_track_1 & (main_track_1 ^ mirror) && oppo_track_2 & (main_track_2 ^ mirror)) { /* There is an alternative connection. Town can grow on tile. */ return false; } } /* There is either no 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; }