Index: src/landscape.cpp =================================================================== --- src/landscape.cpp (revision 27795) +++ src/landscape.cpp (working copy) @@ -992,6 +992,32 @@ } /** + * Check whether a river could (logically) flow into a lock. + * @param tile the middle tile of a lock. + * @return true iff the water can be flowing into a lock. + */ +static bool FlowsLock(TileIndex tile) +{ + DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); + if (dir == INVALID_DIAGDIR) return false; + + int delta = TileOffsByDiagDir(dir); + + int height_tile; + if (DistanceFromEdge(tile - delta) <= 1 || !(GetTileSlope(tile - 2 * delta, &height_tile) == SLOPE_FLAT) && height_tile != 0 || + DistanceFromEdge(tile - 2 * delta) <= 1 || !(GetTileSlope(tile - 2 * delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT)), &height_tile) == SLOPE_FLAT) && height_tile != 0 || + !(GetTileSlope(tile - 2 * delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT)), &height_tile) == SLOPE_FLAT) && height_tile != 0 || + DistanceFromEdge(tile - 2 * delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT))) <= 1 || !(GetTileSlope(tile - 3 * delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT)), &height_tile) == SLOPE_FLAT) && height_tile != 0 || + !(GetTileSlope(tile - 3 * delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT)), &height_tile) == SLOPE_FLAT) && height_tile != 0) return false; + + if (DistanceFromEdge(tile + delta) <= 1 || !IsTileFlat(tile + delta + delta) || + DistanceFromEdge(tile + delta + delta) <= 1 || !IsTileFlat(tile + delta + delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT))) || + !IsTileFlat(tile + delta + delta + TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT)))) return false; + + return true; +} + +/** * Check whether a river at begin could (logically) flow down to end. * @param begin The origin of the flow. * @param end The destination of the flow. @@ -1008,9 +1034,9 @@ return heightEnd <= heightBegin && /* Slope either is inclined or flat; rivers don't support other slopes. */ - (slopeEnd == SLOPE_FLAT || IsInclinedSlope(slopeEnd)) && + (slopeEnd == SLOPE_FLAT || (IsInclinedSlope(slopeEnd) && FlowsLock(end))) && /* Slope continues, then it must be lower... or either end must be flat. */ - ((slopeEnd == slopeBegin && heightEnd < heightBegin) || slopeEnd == SLOPE_FLAT || slopeBegin == SLOPE_FLAT); + ((slopeEnd == slopeBegin && heightEnd < heightBegin) || slopeEnd == SLOPE_FLAT || (slopeBegin == SLOPE_FLAT && GetTileMaxZ(end) == heightBegin)); } /* AyStar callback for checking whether we reached our destination. */ @@ -1056,6 +1082,32 @@ MakeRiver(tile, Random()); /* Remove desert directly around the river tile. */ CircularTileSearch(&tile, 5, RiverModifyDesertZone, NULL); + + /* Connect the water if a lock would be build on the inclined slope */ + Slope slope = GetTileSlope(path->node.tile); + if (IsInclinedSlope(slope)) { + DiagDirection dir = GetInclinedSlopeDirection(slope); + int delta_mid = TileOffsByDiagDir(dir); + int delta = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT)); + TileIndex tile_upper = path->node.tile + 2 * delta_mid; + TileIndex tile_upper_right = tile_upper + delta; + TileIndex tile_upper_right_far = tile_upper_right + delta_mid; + TileIndex tile_upper_left = tile_upper - delta; + TileIndex tile_upper_left_far = tile_upper_left + delta_mid; + TileIndex tile_lower = path->node.tile - 2 * delta_mid; + TileIndex tile_lower_right = tile_lower + delta; + TileIndex tile_lower_right_far = tile_lower_right - delta_mid; + TileIndex tile_lower_left = tile_lower - delta; + TileIndex tile_lower_left_far = tile_lower_left - delta_mid; + TileIndex tiles[] = {tile_upper, tile_upper_right, tile_upper_right_far, tile_upper_left, tile_upper_left_far, tile_lower, tile_lower_right, tile_lower_right_far, tile_lower_left, tile_lower_left_far}; + for (int i = 0; i < lengthof(tiles); i++) { + if (!IsWaterTile(tiles[i]) && IsTileFlat(tiles[i])) { + MakeRiver(tiles[i], Random()); + /* Remove desert directly around the river tile. */ + CircularTileSearch(&tiles[i], 5, RiverModifyDesertZone, NULL); + } + } + } } } }