Make it possible to stop road vehicles from slowing down in curves so "diagonal"...
[openttd-joker.git] / src / road.cpp
blob42d58872e2ee088d0d94e69517cb876be3b51f55
1 /* $Id: road.cpp 24900 2013-01-08 22:46:42Z planetmaker $ */
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file road.cpp Generic road related functions. */
12 #include "stdafx.h"
13 #include <algorithm>
14 #include <memory>
15 #include <numeric>
16 #include <unordered_map>
17 #include <vector>
18 #include "rail_map.h"
19 #include "road_map.h"
20 #include "water_map.h"
21 #include "genworld.h"
22 #include "company_func.h"
23 #include "company_base.h"
24 #include "engine_base.h"
25 #include "date_func.h"
26 #include "landscape.h"
27 #include "town.h"
28 #include "pathfinder/npf/aystar.h"
29 #include "tunnelbridge.h"
30 #include "command_func.h"
31 #include "core/backup_type.hpp"
32 #include "core/random_func.hpp"
34 #include "safeguards.h"
36 /**
37 * Return if the tile is a valid tile for a crossing.
39 * @param tile the current tile
40 * @param ax the axis of the road over the rail
41 * @return true if it is a valid tile
43 static bool IsPossibleCrossing(const TileIndex tile, Axis ax)
45 return (IsTileType(tile, MP_RAILWAY) &&
46 GetRailTileType(tile) == RAIL_TILE_NORMAL &&
47 GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) &&
48 GetFoundationSlope(tile) == SLOPE_FLAT);
51 /** Whether to build public roads */
52 enum PublicRoadsConstruction {
53 PRC_NONE, ///< Generate no public roads
54 PRC_WITH_CURVES, ///< Generate roads with lots of curves
55 PRC_AVOID_CURVES, ///< Generate roads avoiding curves if possible
58 /**
59 * Clean up unnecessary RoadBits of a planed tile.
60 * @param tile current tile
61 * @param org_rb planed RoadBits
62 * @return optimised RoadBits
64 RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
66 if (!IsValidTile(tile)) return ROAD_NONE;
67 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
68 const TileIndex neighbor_tile = TileAddByDiagDir(tile, dir);
70 /* Get the Roadbit pointing to the neighbor_tile */
71 const RoadBits target_rb = DiagDirToRoadBits(dir);
73 /* If the roadbit is in the current plan */
74 if (org_rb & target_rb) {
75 bool connective = false;
76 const RoadBits mirrored_rb = MirrorRoadBits(target_rb);
78 if (IsValidTile(neighbor_tile)) {
79 switch (GetTileType(neighbor_tile)) {
80 /* Always connective ones */
81 case MP_CLEAR: case MP_TREES:
82 connective = true;
83 break;
85 /* The conditionally connective ones */
86 case MP_TUNNELBRIDGE:
87 case MP_STATION:
88 case MP_ROAD:
89 if (IsNormalRoadTile(neighbor_tile)) {
90 /* Always connective */
91 connective = true;
92 } else {
93 const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM);
95 /* Accept only connective tiles */
96 connective = (neighbor_rb & mirrored_rb) != ROAD_NONE;
98 break;
100 case MP_RAILWAY:
101 connective = IsPossibleCrossing(neighbor_tile, DiagDirToAxis(dir));
102 break;
104 case MP_WATER:
105 /* Check for real water tile */
106 connective = !IsWater(neighbor_tile);
107 break;
109 /* The definitely not connective ones */
110 default: break;
114 /* If the neighbor tile is inconnective, remove the planed road connection to it */
115 if (!connective) org_rb ^= target_rb;
119 return org_rb;
123 * Finds out, whether given company has all given RoadTypes available
124 * @param company ID of company
125 * @param rts RoadTypes to test
126 * @return true if company has all requested RoadTypes available
128 bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts)
130 RoadTypes avail_roadtypes;
132 if (company == OWNER_DEITY || company == OWNER_TOWN || _game_mode == GM_EDITOR || _generating_world) {
133 avail_roadtypes = ROADTYPES_ROAD;
134 } else {
135 Company *c = Company::GetIfValid(company);
136 if (c == nullptr) return false;
137 avail_roadtypes = (RoadTypes)c->avail_roadtypes | ROADTYPES_ROAD; // road is available for always for everybody
139 return (rts & ~avail_roadtypes) == 0;
143 * Validate functions for rail building.
144 * @param rt road type to check.
145 * @return true if the current company may build the road.
147 bool ValParamRoadType(const RoadType rt)
149 return HasRoadTypesAvail(_current_company, RoadTypeToRoadTypes(rt));
153 * Get the road types the given company can build.
154 * @param company the company to get the roadtypes for.
155 * @return the road types.
157 RoadTypes GetCompanyRoadtypes(CompanyID company)
159 RoadTypes rt = ROADTYPES_NONE;
161 Engine *e;
162 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
163 const EngineInfo *ei = &e->info;
165 if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
166 (HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) {
167 SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
171 return rt;
174 /* ========================================================================= */
175 /* PUBLIC ROADS */
176 /* ========================================================================= */
178 CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text = nullptr);
179 CommandCost CmdBuildTunnel(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text = nullptr);
180 CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text = nullptr);
182 static std::vector<TileIndex> _town_centers;
183 static std::vector<TileIndex> _towns_visited_along_the_way;
184 static const uint PUBLIC_ROAD_HASH_SIZE = 8U; ///< The number of bits the hash for river finding should have.
187 * Simple hash function for public road tiles to be used by AyStar.
188 * @param tile The tile to hash.
189 * @param dir The unused direction.
190 * @return The hash for the tile.
192 static uint PublicRoad_Hash(uint tile, uint dir)
194 return GB(TileHash(TileX(tile), TileY(tile)), 0, PUBLIC_ROAD_HASH_SIZE);
197 static const int32 BASE_COST = 1; // Cost for utilizing an existing road, bridge, or tunnel.
198 static const int32 COST_FOR_NEW_ROAD = 10; // Cost for building a new road.
199 static const int32 COST_FOR_SLOPE = 5; // Additional cost if the road heads up or down a slope.
201 /* AyStar callback for getting the cost of the current node. */
202 static int32 PublicRoad_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
204 int32 cost = BASE_COST;
206 if (!IsTileType(current->tile, MP_ROAD)) {
207 if (!AreTilesAdjacent(parent->path.node.tile, current->tile))
209 // We're not adjacent, so we built a tunnel or bridge.
210 cost += (DistanceManhattan(parent->path.node.tile, current->tile)) * COST_FOR_NEW_ROAD + 6 * COST_FOR_SLOPE;
212 else if (!IsTileFlat(current->tile)) {
213 cost += COST_FOR_NEW_ROAD;
214 cost += COST_FOR_SLOPE;
216 else
218 cost += COST_FOR_NEW_ROAD;
222 if (_settings_game.game_creation.build_public_roads == PRC_AVOID_CURVES &&
223 parent->path.parent != nullptr &&
224 DiagdirBetweenTiles(parent->path.parent->node.tile, parent->path.node.tile) != DiagdirBetweenTiles(parent->path.node.tile, current->tile)) {
225 cost += 1;
228 return cost;
231 /* AyStar callback for getting the estimated cost to the destination. */
232 static int32 PublicRoad_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
234 return DistanceManhattan(*(TileIndex*)aystar->user_target, current->tile) * BASE_COST;
237 /* Helper function to check if a tile along a certain direction is going up an inclined slope. */
238 static bool IsUpwardsSlope(TileIndex tile, DiagDirection road_direction)
240 auto slope = GetTileSlope(tile);
242 if (!IsInclinedSlope(slope)) return false;
244 auto slope_direction = GetInclinedSlopeDirection(slope);
246 return road_direction == slope_direction;
249 /* Helper function to check if a tile along a certain direction is going down an inclined slope. */
250 static bool IsDownwardsSlope(TileIndex tile, DiagDirection road_direction)
252 auto slope = GetTileSlope(tile);
254 if (!IsInclinedSlope(slope)) return false;
256 auto slope_direction = GetInclinedSlopeDirection(slope);
258 return road_direction == ReverseDiagDir(slope_direction);
261 /* Helper function to check if a road along this tile path is possible. */
262 static bool CanBuildRoadFromTo(TileIndex begin, TileIndex end)
264 assert(DistanceManhattan(begin, end) == 1);
266 int heightBegin;
267 int heightEnd;
268 Slope slopeBegin = GetTileSlope(begin, &heightBegin);
269 Slope slopeEnd = GetTileSlope(end, &heightEnd);
271 return
272 /* Slope either is inclined or flat; rivers don't support other slopes. */
273 (slopeEnd == SLOPE_FLAT || IsInclinedSlope(slopeEnd)) &&
274 /* Slope continues, then it must be lower... or either end must be flat. */
275 ((slopeEnd == slopeBegin && heightEnd != heightBegin) || slopeEnd == SLOPE_FLAT || slopeBegin == SLOPE_FLAT);
278 static TileIndex BuildTunnel(PathNode *current, bool build_tunnel = false)
280 Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
281 auto build_tunnel_cmd = CmdBuildTunnel(current->node.tile, build_tunnel ? DC_EXEC : DC_NONE, ROADTYPES_ROAD | (TRANSPORT_ROAD << 8), 0);
282 cur_company.Restore();
284 assert(!build_tunnel || build_tunnel_cmd.Succeeded());
285 assert(!build_tunnel || (IsTileType(current->node.tile, MP_TUNNELBRIDGE) && IsTileType(_build_tunnel_endtile, MP_TUNNELBRIDGE)));
287 if (!build_tunnel_cmd.Succeeded()) return INVALID_TILE;
288 if (!build_tunnel && !IsTileType(_build_tunnel_endtile, MP_CLEAR) && !IsTileType(_build_tunnel_endtile, MP_TREES)) return INVALID_TILE;
290 return _build_tunnel_endtile;
293 static TileIndex BuildBridge(PathNode *current, TileIndex end_tile = INVALID_TILE, bool build_bridge = false)
295 TileIndex start_tile = current->node.tile;
297 DiagDirection direction = ReverseDiagDir(GetInclinedSlopeDirection(GetTileSlope(start_tile)));
299 if (!build_bridge) {
300 // We are not building yet, so we still need to find the end_tile.
301 for (TileIndex tile = start_tile + TileOffsByDiagDir(direction);
302 IsValidTile(tile) &&
303 (GetTunnelBridgeLength(start_tile, tile) <= _settings_game.construction.max_bridge_length) &&
304 (GetTileZ(start_tile) < (GetTileZ(tile) + _settings_game.construction.max_bridge_height)) &&
305 (GetTileZ(tile) <= GetTileZ(start_tile));
306 tile += TileOffsByDiagDir(direction)) {
308 // No supershort bridges and always ending up on a matching upwards slope.
309 if (!AreTilesAdjacent(start_tile, tile) && IsUpwardsSlope(tile, direction)) {
310 end_tile = tile;
311 break;
315 if (!IsValidTile(end_tile)) return INVALID_TILE;
316 if (!IsTileType(end_tile, MP_CLEAR) && !IsTileType(end_tile, MP_TREES)) return INVALID_TILE;
319 assert(!build_bridge || IsValidTile(end_tile));
321 std::vector<BridgeType> available_bridge_types;
323 for (uint i = 0; i < MAX_BRIDGES; ++i) {
324 if (CheckBridgeAvailability((BridgeType)i, GetTunnelBridgeLength(start_tile, end_tile)).Succeeded()) {
325 available_bridge_types.push_back((BridgeType)i);
329 assert(!build_bridge || !available_bridge_types.empty());
330 if (available_bridge_types.empty()) return INVALID_TILE;
332 auto bridge_type = available_bridge_types[build_bridge ? RandomRange((uint32)available_bridge_types.size()) : 0];
334 Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
335 auto build_bridge_cmd = CmdBuildBridge(end_tile, build_bridge ? DC_EXEC : DC_NONE, start_tile, bridge_type | (ROADTYPES_ROAD << 8) | (TRANSPORT_ROAD << 15));
336 cur_company.Restore();
338 assert(!build_bridge || build_bridge_cmd.Succeeded());
339 assert(!build_bridge || (IsTileType(start_tile, MP_TUNNELBRIDGE) && IsTileType(end_tile, MP_TUNNELBRIDGE)));
341 if (!build_bridge_cmd.Succeeded()) return INVALID_TILE;
343 return end_tile;
346 static TileIndex BuildRiverBridge(PathNode *current, DiagDirection road_direction, TileIndex end_tile = INVALID_TILE, bool build_bridge = false)
348 TileIndex start_tile = current->node.tile;
350 if (!build_bridge) {
351 // We are not building yet, so we still need to find the end_tile.
352 // We will only build a bridge if we need to cross a river, so first check for that.
353 TileIndex tile = start_tile + TileOffsByDiagDir(road_direction);
355 if (!IsWaterTile(tile) || !IsRiver(tile)) return INVALID_TILE;
357 // Now let's see if we can bridge it. But don't bridge anything more than 4 river tiles. Cities aren't allowed to, so public roads we are not either.
358 // Only bridges starting at slopes should be longer ones. The others look like crap when built this way. Players can build them but the map generator
359 // should not force that on them. This is just to bridge rivers, not to make long bridges.
360 for (;
361 IsValidTile(tile) &&
362 (GetTunnelBridgeLength(start_tile, tile) <= 5) &&
363 (GetTileZ(start_tile) < (GetTileZ(tile) + _settings_game.construction.max_bridge_height)) &&
364 (GetTileZ(tile) <= GetTileZ(start_tile));
365 tile += TileOffsByDiagDir(road_direction)) {
367 if ((IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES)) &&
368 GetTileZ(tile) <= GetTileZ(start_tile) &&
369 GetTileSlope(tile) == SLOPE_FLAT) {
370 end_tile = tile;
371 break;
375 if (!IsValidTile(end_tile)) return INVALID_TILE;
376 if (!IsTileType(end_tile, MP_CLEAR) && !IsTileType(end_tile, MP_TREES)) return INVALID_TILE;
379 assert(!build_bridge || IsValidTile(end_tile));
381 std::vector<BridgeType> available_bridge_types;
383 for (uint i = 0; i < MAX_BRIDGES; ++i) {
384 if (CheckBridgeAvailability((BridgeType)i, GetTunnelBridgeLength(start_tile, end_tile)).Succeeded()) {
385 available_bridge_types.push_back((BridgeType)i);
389 auto bridge_type = available_bridge_types[build_bridge ? RandomRange((uint32)available_bridge_types.size()) : 0];
391 Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
392 auto build_bridge_cmd = CmdBuildBridge(end_tile, build_bridge ? DC_EXEC : DC_NONE, start_tile, bridge_type | (ROADTYPES_ROAD << 8) | (TRANSPORT_ROAD << 15));
393 cur_company.Restore();
395 assert(!build_bridge || build_bridge_cmd.Succeeded());
396 assert(!build_bridge || (IsTileType(start_tile, MP_TUNNELBRIDGE) && IsTileType(end_tile, MP_TUNNELBRIDGE)));
398 if (!build_bridge_cmd.Succeeded()) return INVALID_TILE;
400 return end_tile;
403 static bool IsValidNeighbourOfPreviousTile(TileIndex tile, TileIndex previous_tile)
405 if (!IsValidTile(tile)) return false;
407 if (IsTileType(tile, MP_TUNNELBRIDGE))
409 if (GetOtherTunnelBridgeEnd(tile) == previous_tile) return true;
411 auto tunnel_direction = GetTunnelBridgeDirection(tile);
413 if (previous_tile + TileOffsByDiagDir(tunnel_direction) != tile) return false;
414 } else {
416 if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES) && !IsTileType(tile, MP_ROAD)) return false;
418 auto slope = GetTileSlope(tile);
420 // Do not allow foundations. We'll mess things up later.
421 bool hasFoundation = GetFoundationSlope(tile) != slope;
422 if (hasFoundation) return false;
424 if (IsInclinedSlope(slope)) {
425 auto slope_direction = GetInclinedSlopeDirection(slope);
426 auto road_direction = DiagdirBetweenTiles(previous_tile, tile);
428 if (slope_direction != road_direction && ReverseDiagDir(slope_direction) != road_direction) return false;
429 } else if (slope != SLOPE_FLAT) {
430 return false;
434 return true;
437 /* AyStar callback for getting the neighbouring nodes of the given node. */
438 static void PublicRoad_GetNeighbours(AyStar *aystar, OpenListNode *current)
440 TileIndex tile = current->path.node.tile;
442 aystar->num_neighbours = 0;
444 // Check if we just went through a tunnel or a bridge.
445 if (current->path.parent != nullptr && !AreTilesAdjacent(tile, current->path.parent->node.tile)) {
446 auto previous_tile = current->path.parent->node.tile;
447 // We went through a tunnel or bridge, this limits our options to proceed to only forward.
448 auto tunnel_bridge_direction = DiagdirBetweenTiles(previous_tile, tile);
450 TileIndex t2 = tile + TileOffsByDiagDir(tunnel_bridge_direction);
451 if (IsValidNeighbourOfPreviousTile(t2, tile)) {
452 aystar->neighbours[aystar->num_neighbours].tile = t2;
453 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
454 aystar->num_neighbours++;
456 } else {
457 // Handle all the regular neighbours and existing tunnels/bridges.
458 std::vector<TileIndex> potential_neighbours;
460 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
461 auto neighbour = GetOtherTunnelBridgeEnd(tile);
463 aystar->neighbours[aystar->num_neighbours].tile = neighbour;
464 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
465 aystar->num_neighbours++;
467 neighbour = tile + TileOffsByDiagDir(ReverseDiagDir(DiagdirBetweenTiles(tile, neighbour)));
469 if (IsValidNeighbourOfPreviousTile(neighbour, tile)) {
470 aystar->neighbours[aystar->num_neighbours].tile = neighbour;
471 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
472 aystar->num_neighbours++;
474 } else {
475 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
476 auto neighbour = tile + TileOffsByDiagDir(d);
477 if (IsValidNeighbourOfPreviousTile(neighbour, tile)) {
478 aystar->neighbours[aystar->num_neighbours].tile = neighbour;
479 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
480 aystar->num_neighbours++;
484 // Check if we can turn this into a tunnel or a bridge.
485 if (current->path.parent != nullptr) {
486 auto road_direction = DiagdirBetweenTiles(current->path.parent->node.tile, tile);
487 if (IsUpwardsSlope(tile, road_direction)) {
488 auto tunnel_end = BuildTunnel(&current->path);
490 if (tunnel_end != INVALID_TILE) {
491 assert(IsValidDiagDirection(DiagdirBetweenTiles(tile, tunnel_end)));
492 aystar->neighbours[aystar->num_neighbours].tile = tunnel_end;
493 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
494 aystar->num_neighbours++;
497 else if (IsDownwardsSlope(tile, road_direction)) {
498 auto bridge_end = BuildBridge(&current->path);
500 if (bridge_end != INVALID_TILE) {
501 assert(IsValidDiagDirection(DiagdirBetweenTiles(tile, bridge_end)));
502 aystar->neighbours[aystar->num_neighbours].tile = bridge_end;
503 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
504 aystar->num_neighbours++;
507 else if (GetTileSlope(tile) == SLOPE_FLAT)
509 // Check if we could bridge a river from a flat tile. Not looking pretty on the map but you gotta do what you gotta do.
510 auto bridge_end = BuildRiverBridge(&current->path, DiagdirBetweenTiles(current->path.parent->node.tile, tile));
511 assert(bridge_end == INVALID_TILE || GetTileSlope(bridge_end) == SLOPE_FLAT);
513 if (bridge_end != INVALID_TILE) {
514 assert(IsValidDiagDirection(DiagdirBetweenTiles(tile, bridge_end)));
515 aystar->neighbours[aystar->num_neighbours].tile = bridge_end;
516 aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
517 aystar->num_neighbours++;
526 /* AyStar callback for checking whether we reached our destination. */
527 static int32 PublicRoad_EndNodeCheck(AyStar *aystar, OpenListNode *current)
529 // Mark towns visited along the way.
530 auto search_result = std::find(_town_centers.begin(), _town_centers.end(), current->path.node.tile);
532 if (search_result != _town_centers.end()) {
533 _towns_visited_along_the_way.push_back(current->path.node.tile);
536 return current->path.node.tile == *(TileIndex*)aystar->user_target ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
539 /* AyStar callback when an route has been found. */
540 static void PublicRoad_FoundEndNode(AyStar *aystar, OpenListNode *current)
542 PathNode* child = nullptr;
544 for (PathNode *path = &current->path; path != nullptr; path = path->parent) {
545 TileIndex tile = path->node.tile;
547 TownID townID = CalcClosestTownFromTile(tile)->index;
549 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
550 // Just follow the path; infrastructure is already in place.
551 continue;
552 } else if (path->parent == nullptr || AreTilesAdjacent(tile, path->parent->node.tile)) {
553 RoadBits road_bits = ROAD_NONE;
555 if (child != nullptr) {
556 TileIndex tile2 = child->node.tile;
557 road_bits |= DiagDirToRoadBits(DiagdirBetweenTiles(tile, tile2));
559 if (path->parent != nullptr) {
560 TileIndex tile2 = path->parent->node.tile;
561 road_bits |= DiagDirToRoadBits(DiagdirBetweenTiles(tile, tile2));
564 if (child != nullptr || path->parent != nullptr) {
565 // Check if we need to build anything.
566 bool need_to_build_road = true;
568 if (IsTileType(tile, MP_ROAD)) {
569 RoadBits existing_bits = GetRoadBits(tile, ROADTYPE_ROAD);
570 CLRBITS(road_bits, existing_bits);
571 if (road_bits == ROAD_NONE) need_to_build_road = false;
574 // If it is already a road and has the right bits, we are good. Otherwise build the needed ones.
575 if (need_to_build_road)
577 Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
578 auto road_built = CmdBuildRoad(tile, DC_EXEC, ROADTYPE_ROAD << 4 | road_bits, 0);
579 cur_company.Restore();
582 } else {
583 // We only get here if we have a parent and we're not adjacent to it. River/Tunnel time!
584 DiagDirection road_direction = DiagdirBetweenTiles(tile, path->parent->node.tile);
586 auto end_tile = INVALID_TILE;
588 auto start_slope = GetTileSlope(tile);
590 if (IsUpwardsSlope(tile, road_direction)) {
591 end_tile = BuildTunnel(path, true);
592 assert(IsValidTile(end_tile) && IsDownwardsSlope(end_tile, road_direction));
593 } else if (IsDownwardsSlope(tile, road_direction)) {
594 // Provide the function with the end tile, since we already know it, but still check the result.
595 end_tile = BuildBridge(path, path->parent->node.tile, true);
596 assert(IsValidTile(end_tile) && IsUpwardsSlope(end_tile, road_direction));
597 } else {
598 // River bridge is the last possibility.
599 assert(GetTileSlope(tile) == SLOPE_FLAT);
600 end_tile = BuildRiverBridge(path, road_direction, path->parent->node.tile, true);
601 assert(IsValidTile(end_tile) && GetTileSlope(end_tile) == SLOPE_FLAT);
605 child = path;
609 bool FindPath(AyStar& finder, TileIndex from, TileIndex to)
611 finder.CalculateG = PublicRoad_CalculateG;
612 finder.CalculateH = PublicRoad_CalculateH;
613 finder.GetNeighbours = PublicRoad_GetNeighbours;
614 finder.EndNodeCheck = PublicRoad_EndNodeCheck;
615 finder.FoundEndNode = PublicRoad_FoundEndNode;
616 finder.user_target = &(to);
617 finder.max_search_nodes = 1 << 20; // 1,048,576
619 finder.Init(PublicRoad_Hash, 1 << PUBLIC_ROAD_HASH_SIZE);
621 AyStarNode start;
622 start.tile = from;
623 start.direction = INVALID_TRACKDIR;
624 finder.AddStartNode(&start, 0);
626 bool found_path = (finder.Main() == AYSTAR_FOUND_END_NODE);
628 return found_path;
632 * Build the public road network connecting towns using AyStar.
634 void GeneratePublicRoads()
636 using namespace std;
638 if (_settings_game.game_creation.build_public_roads == PRC_NONE) return;
640 _town_centers.clear();
641 _towns_visited_along_the_way.clear();
643 vector<TileIndex> towns;
644 towns.clear();
646 Town* town;
647 FOR_ALL_TOWNS(town) {
648 towns.push_back(town->xy);
649 _town_centers.push_back(town->xy);
653 SetGeneratingWorldProgress(GWP_PUBLIC_ROADS, (uint)towns.size());
655 // Create a list of networks which also contain a value indicating how many times we failed to connect to them.
656 vector<pair<uint, shared_ptr<vector<TileIndex>>>> town_networks;
657 unordered_map<TileIndex, shared_ptr<vector<TileIndex>>> towns_reachable_networks;
659 TileIndex main_town = *towns.begin();
660 towns.erase(towns.begin());
662 shared_ptr<vector<TileIndex>> main_network = make_shared<vector<TileIndex>>();
663 main_network->push_back(main_town);
665 town_networks.push_back(make_pair(0, main_network));
666 IncreaseGeneratingWorldProgress(GWP_PUBLIC_ROADS);
668 sort(towns.begin(), towns.end(), [&](auto a, auto b) { return DistanceManhattan(main_town, a) < DistanceManhattan(main_town, b); });
670 for (auto begin_town : towns) {
671 // Check if we can connect to any of the networks.
672 _towns_visited_along_the_way.clear();
674 auto reachable_network_iter = towns_reachable_networks.find(begin_town);
675 bool found_easy_path = false;
677 if (reachable_network_iter != towns_reachable_networks.end()) {
678 auto reachable_network = reachable_network_iter->second;
680 sort(reachable_network->begin(), reachable_network->end(), [&](auto a, auto b) { return DistanceManhattan(begin_town, a) < DistanceManhattan(begin_town, b); });
682 TileIndex end_town = *reachable_network->begin();
684 AyStar finder;
686 found_easy_path = FindPath(finder, begin_town, end_town);
688 finder.Free();
691 if (found_easy_path) {
692 reachable_network_iter->second->push_back(begin_town);
694 for (const TileIndex visited_town : _towns_visited_along_the_way) {
695 if (visited_town != begin_town) towns_reachable_networks[visited_town] = reachable_network_iter->second;
697 } else {
698 // Sort networks by failed connection attempts, so we try the most likely one first.
699 sort(town_networks.begin(), town_networks.end(), [&](auto a, auto b) { return a.first < b.first; });
701 if (!any_of(town_networks.begin(), town_networks.end(), [&](auto network_pair) {
702 AyStar finder;
704 auto network = network_pair.second;
706 // Try to connect to the town in the network that is closest to us.
707 // If we can't connect to that one, we can't connect to any of them since they are all interconnected.
708 sort(network->begin(), network->end(), [&](auto a, auto b) { return DistanceManhattan(begin_town, a) < DistanceManhattan(begin_town, b); });
709 TileIndex end_town = *network->begin();
711 bool found_path = FindPath(finder, begin_town, end_town);
713 if (found_path) {
714 network->push_back(begin_town);
716 for (auto visited_town : _towns_visited_along_the_way) {
717 if (visited_town != begin_town) towns_reachable_networks[visited_town] = network;
721 // Increase number of failed attempts if necessary.
722 network_pair.first += (found_path ? (network_pair.first > 0 ? -1 : 0) : 1);
724 finder.Free();
726 return found_path;
728 })) {
729 // We failed to connect to any network, so we are a separate network. Let future towns try to connect to us.
730 shared_ptr<vector<TileIndex>> new_network = make_shared<vector<TileIndex>>();
731 new_network->push_back(begin_town);
733 // We basically failed to connect to this many towns.
734 int towns_already_in_networks = std::accumulate(town_networks.begin(), town_networks.end(), 0, [&](int accumulator, auto network_pair) {
735 return accumulator + (int)network_pair.second->size();
738 town_networks.push_back(make_pair(towns_already_in_networks, new_network));
740 for (const TileIndex visited_town : _towns_visited_along_the_way) {
741 if (visited_town != begin_town) towns_reachable_networks.insert(make_pair(visited_town, new_network));
746 IncreaseGeneratingWorldProgress(GWP_PUBLIC_ROADS);