/** * Ensure there is no ship on the neighbouring tiles coming into or going * away from the specified tile. * @param tile the specified tile. * @param diag_dir_mask mask containing the diagonal directions to the * neighbouring tiles. * @return Succeeded command (no neighbouring ship) or failed command (a * neighbouring ship is found) */ CommandCost EnsureNoShipFromDiagDirMask(TileIndex tile, byte diag_dir_mask) { /* Get track bits of the specified tile */ TrackBits tile_tb = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0)); if ((tile_tb & TRACK_BIT_ALL) != TRACK_BIT_NONE) { /* Ships can walk on main tile, so ensure from which provided diagonal directions a neightbouring ship can't be found */ for (DiagDirection diag_dir = DIAGDIR_BEGIN; diag_dir != DIAGDIR_END; diag_dir++) { if (diag_dir_mask & 1 << diag_dir) { /* Make checks on this diagonal direction */ TileIndex tc = TileAddByDiagDir(tile, diag_dir); // Move into the neighbouring tile /* Get track bits of the neighbouring tile that can be reached from the main tile */ TrackBits tc_tb = TrackStatusToTrackBits(GetTileTrackStatus(tc, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(DiagdirBetweenTiles(tile, tc)); /* Then also check if there are track bits on the main tile that can be reached from the neighbouring tile */ if (tc_tb && DiagdirReachesTracks(DiagdirBetweenTiles(tc, tile)) & tile_tb) { /* We don't check for a ship in the neighbouring ship depots, locks or aqueducts, * because we only care about 1-tile depth, and those structures are more than 1-tile wide. */ if (!IsShipDepotTile(tc) && !(IsTileType(tc, MP_WATER) && IsLock(tc)) && !(IsTileType(tc, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tc) == TRANSPORT_WATER)) { /* Check if there are no ships on the track bits of the neighbouring tile */ if (HasVehicleOnPos(tc, &tc_tb, EnsureNoShipOnTrackProc)) { return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY); } } } } } } return CommandCost(); }