diff --git a/src/road.cpp b/src/road.cpp index 1551453a66..2abf1375f3 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "rail_map.h" #include "road_map.h" @@ -252,14 +253,13 @@ static bool _has_tunnel_in_path; static RoadType _public_road_type; static const uint _public_road_hash_size = 8U; ///< The number of bits the hash for river finding should have. -static const int32 BASE_COST = 1; // Cost for utilizing an existing road, bridge, or tunnel. -static const int32 COST_FOR_NEW_ROAD = 10; // Cost for building a new road. -static const int32 COST_FOR_SLOPE = 5; // Additional cost if the road heads up or down a slope. +static const int32 COST_FOR_NEW_ROAD = 100; // Cost for building a new road. +static const int32 COST_FOR_SLOPE = 50; // Additional cost if the road heads up or down a slope. /** AyStar callback for getting the cost of the current node. */ static int32 PublicRoad_CalculateG(AyStar *, AyStarNode *current, OpenListNode *parent) { - int32 cost = BASE_COST; + int32 cost = 0; if (!IsTileType(current->tile, MP_ROAD)) { if (!AreTilesAdjacent(parent->path.node.tile, current->tile)) @@ -289,7 +289,7 @@ static int32 PublicRoad_CalculateG(AyStar *, AyStarNode *current, OpenListNode * /** AyStar callback for getting the estimated cost to the destination. */ static int32 PublicRoad_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent) { - return DistanceManhattan(*static_cast(aystar->user_target), current->tile) * BASE_COST; + return DistanceManhattan(*static_cast(aystar->user_target), current->tile) * COST_FOR_NEW_ROAD; } /** Helper function to check if a tile along a certain direction is going up an inclined slope. */ @@ -715,7 +715,8 @@ bool FindPath(AyStar& finder, const TileIndex from, TileIndex to) finder.EndNodeCheck = PublicRoad_EndNodeCheck; finder.FoundEndNode = PublicRoad_FoundEndNode; finder.user_target = &(to); - finder.max_search_nodes = 1 << 20; // 1,048,576 + finder.max_search_nodes = 1 << 18; // 1,048,576 + finder.max_path_cost = 1000 * COST_FOR_NEW_ROAD; finder.Init(1 << _public_road_hash_size); @@ -780,6 +781,7 @@ void GeneratePublicRoads() towns.erase(towns.begin()); _public_road_type = GetTownRoadType(Town::GetByTile(main_town)); + std::unordered_set checked_towns; auto main_network = make_shared(); main_network->towns.push_back(main_town); @@ -796,6 +798,8 @@ void GeneratePublicRoads() // Check if we can connect to any of the networks. _towns_visited_along_the_way.clear(); + checked_towns.clear(); + auto reachable_from_town = town_to_network_map.find(start_town); bool found_path = false; @@ -805,6 +809,7 @@ void GeneratePublicRoads() sort(reachable_network->towns.begin(), reachable_network->towns.end(), [&](auto a, auto b) { return DistanceManhattan(start_town, a) < DistanceManhattan(start_town, b); }); const TileIndex end_town = *reachable_network->towns.begin(); + checked_towns.emplace(end_town); AyStar finder {}; { @@ -833,11 +838,21 @@ void GeneratePublicRoads() sort(networks.begin(), networks.end(), [](const std::shared_ptr &a, const std::shared_ptr &b) { return a->failures_to_connect < b->failures_to_connect; }); std::function can_reach = [&](const std::shared_ptr &network) { + if (reachable_from_town != town_to_network_map.end() && network.get() == reachable_from_town->second.get()) { + return false; + } + // Try to connect to the town in the network that is closest to us. // If we can't connect to that one, we can't connect to any of them since they are all interconnected. sort(network->towns.begin(), network->towns.end(), [&](auto a, auto b) { return DistanceManhattan(start_town, a) < DistanceManhattan(start_town, b); }); const TileIndex end_town = *network->towns.begin(); + if (checked_towns.find(end_town) != checked_towns.end()/* || DistanceManhattan(start_town, end_town) > 2000*/) { + return false; + } + + checked_towns.emplace(end_town); + AyStar finder {}; { found_path = FindPath(finder, start_town, end_town);