From 7bdfb382a89145ea3ce6c89992eacd0ec676babd Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Thu, 24 Dec 2020 18:37:13 -0500 Subject: [PATCH] Change: Towns don't build dead-end road bridges (#8401) --- src/town_cmd.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 374601cad2..ff63b613f5 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1087,6 +1087,48 @@ static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd) return false; } +/** + * Checks if a town road can be continued on the other side of a bridge. + * + * @param end_tile The end tile of the bridge + * @param bridge_dir The direction of the bridge + * @return true if the road can be continued, else false + */ +static bool CanRoadContinueAfterBridge(const Town* t, const TileIndex end_tile, const DiagDirection bridge_dir) +{ + const int delta = TileOffsByDiagDir(bridge_dir); // +1 tile in the direction of the bridge + TileIndex next_tile = end_tile + delta; // The tile beyond the bridge + RoadBits rcmd = DiagDirToRoadBits(ReverseDiagDir(bridge_dir)); + RoadType rt = GetTownRoadType(t); + + /* Before we try anything, make sure the tile is on the map and not the void. */ + if (!IsValidTile(next_tile)) return false; + + /* If the next tile is a bridge or tunnel, allow if it's a road bridge/tunnel continuing in the same direction. */ + if (IsTileType(next_tile, MP_TUNNELBRIDGE)) { + return GetTunnelBridgeTransportType(next_tile) == TRANSPORT_ROAD && GetTunnelBridgeDirection(next_tile) == bridge_dir; + } + + /* If the next tile is a station, allow if it's a road station facing the proper direction. Otherwise return false. */ + if (IsTileType(next_tile, MP_STATION)) { + /* If the next tile is a road station, allow if it's facing the same direction, otherwise disallow. */ + return IsRoadStop(next_tile) && GetRoadStopDir(next_tile) == ReverseDiagDir(bridge_dir); + } + + /* If the next tile is a road depot, allow if it's facing the new bridge. */ + if (IsTileType(next_tile, MP_ROAD)) { + return IsRoadDepot(next_tile) && GetRoadDepotDirection(next_tile) == ReverseDiagDir(bridge_dir); + } + + /* If the next tile is a railroad track, check if towns are allowed to build level crossings. + * If level crossing are not allowed, reject the bridge. Else allow DoCommand to determine if the rail track is buildable. */ + if (IsTileType(next_tile, MP_RAILWAY) && !_settings_game.economy.allow_town_level_crossings) return false; + + /* If a road tile can be built, the bridge is allowed. + * If not, the bridge is rejected. */ + return DoCommand(next_tile, rcmd | (rt << 4), t->index, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD).Succeeded(); +} + /** * Grows the town with a bridge. * At first we check if a bridge is reasonable. @@ -1136,9 +1178,12 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi } while (IsValidTile(bridge_tile) && (IsWaterTile(bridge_tile) || IsPlainRailTile(bridge_tile) || (IsNormalRoadTile(bridge_tile) && GetDisallowedRoadDirections(bridge_tile) != DRD_NONE))); } - /* no water tiles in between? */ + /* Don't allow a bridge where the start and end tiles are adjacent with no span between. */ if (bridge_length == 1) return false; + /* Make sure the road can be continued past the bridge. At this point, bridge_tile holds the end tile of the bridge. */ + if (!CanRoadContinueAfterBridge(t, bridge_tile, bridge_dir)) return false; + for (uint8 times = 0; times <= 22; times++) { byte bridge_type = RandomRange(MAX_BRIDGES - 1); @@ -1154,7 +1199,6 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi return false; } - /** * Checks whether at least one surrounding roads allows to build a house here *