1 /* $Id: road.cpp 24900 2013-01-08 22:46:42Z planetmaker $ */
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/>.
10 /** @file road.cpp Generic road related functions. */
16 #include <unordered_map>
20 #include "water_map.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"
28 #include "pathfinder/npf/aystar.h"
29 #include "tunnelbridge.h"
31 #include "road_func.h"
33 #include "command_func.h"
34 #include "core/backup_type.hpp"
35 #include "core/random_func.hpp"
37 #include "safeguards.h"
40 * Return if the tile is a valid tile for a crossing.
42 * @param tile the current tile
43 * @param ax the axis of the road over the rail
44 * @return true if it is a valid tile
46 static bool IsPossibleCrossing(const TileIndex tile
, Axis ax
)
48 return (IsTileType(tile
, MP_RAILWAY
) &&
49 GetRailTileType(tile
) == RAIL_TILE_NORMAL
&&
50 GetTrackBits(tile
) == (ax
== AXIS_X
? TRACK_BIT_Y
: TRACK_BIT_X
) &&
51 GetFoundationSlope(tile
) == SLOPE_FLAT
);
54 /** Whether to build public roads */
55 enum PublicRoadsConstruction
{
56 PRC_NONE
, ///< Generate no public roads
57 PRC_WITH_CURVES
, ///< Generate roads with lots of curves
58 PRC_AVOID_CURVES
, ///< Generate roads avoiding curves if possible
62 * Clean up unnecessary RoadBits of a planed tile.
63 * @param tile current tile
64 * @param org_rb planed RoadBits
65 * @return optimised RoadBits
67 RoadBits
CleanUpRoadBits(const TileIndex tile
, RoadBits org_rb
)
69 if (!IsValidTile(tile
)) return ROAD_NONE
;
70 for (DiagDirection dir
= DIAGDIR_BEGIN
; dir
< DIAGDIR_END
; dir
++) {
71 const TileIndex neighbor_tile
= TileAddByDiagDir(tile
, dir
);
73 /* Get the Roadbit pointing to the neighbor_tile */
74 const RoadBits target_rb
= DiagDirToRoadBits(dir
);
76 /* If the roadbit is in the current plan */
77 if (org_rb
& target_rb
) {
78 bool connective
= false;
79 const RoadBits mirrored_rb
= MirrorRoadBits(target_rb
);
81 if (IsValidTile(neighbor_tile
)) {
82 switch (GetTileType(neighbor_tile
)) {
83 /* Always connective ones */
84 case MP_CLEAR
: case MP_TREES
:
88 /* The conditionally connective ones */
92 if (IsNormalRoadTile(neighbor_tile
)) {
93 /* Always connective */
96 const RoadBits neighbor_rb
= GetAnyRoadBits(neighbor_tile
, ROADTYPE_ROAD
) | GetAnyRoadBits(neighbor_tile
, ROADTYPE_TRAM
); // TODO
98 /* Accept only connective tiles */
99 connective
= (neighbor_rb
& mirrored_rb
) != ROAD_NONE
;
104 connective
= IsPossibleCrossing(neighbor_tile
, DiagDirToAxis(dir
));
108 /* Check for real water tile */
109 connective
= !IsWater(neighbor_tile
);
112 /* The definitely not connective ones */
117 /* If the neighbor tile is inconnective, remove the planed road connection to it */
118 if (!connective
) org_rb
^= target_rb
;
126 * Finds out, whether given company has all given RoadTypes available
127 * @param company ID of company
128 * @param rtid RoadType to test
129 * @return true if company has the requested RoadType available
131 bool HasRoadTypeAvail(const CompanyID company
, RoadTypeIdentifier rtid
)
133 if (company
== OWNER_DEITY
|| company
== OWNER_TOWN
|| _game_mode
== GM_EDITOR
|| _generating_world
) {
136 Company
*c
= Company::GetIfValid(company
);
137 if (c
== nullptr) return false;
138 return HasBit(c
->avail_roadtypes
[rtid
.basetype
], rtid
.subtype
);
143 * Validate functions for rail building.
144 * @param rtid road type to check.
145 * @return true if the current company may build the road.
147 bool ValParamRoadType(RoadTypeIdentifier rtid
)
149 return rtid
.IsValid() && HasRoadTypeAvail(_current_company
, rtid
);
153 * Add the road types that are to be introduced at the given date.
155 * @param current The currently available roadsubtypes.
156 * @param date The date for the introduction comparisons.
157 * @return The road types that should be available when date
158 * introduced road types are taken into account as well.
160 RoadSubTypes
AddDateIntroducedRoadTypes(RoadType rt
, RoadSubTypes current
, Date date
)
162 RoadSubTypes rts
= current
;
164 for (RoadSubType rst
= ROADSUBTYPE_BEGIN
; rst
!= ROADSUBTYPE_END
; rst
++) {
165 const RoadtypeInfo
*rti
= GetRoadTypeInfo(RoadTypeIdentifier(rt
, rst
));
166 /* Unused road type. */
167 if (rti
->label
== 0) continue;
169 /* Not date introduced. */
170 if (!IsInsideMM(rti
->introduction_date
, 0, MAX_DAY
)) continue;
172 /* Not yet introduced at this date. */
173 if (rti
->introduction_date
> date
) continue;
175 /* Have we introduced all required roadtypes? */
176 RoadSubTypes required
= rti
->introduction_required_roadtypes
;
177 if ((rts
& required
) != required
) continue;
179 rts
|= rti
->introduces_roadtypes
;
182 /* When we added roadtypes we need to run this method again; the added
183 * roadtypes might enable more rail types to become introduced. */
184 return rts
== current
? rts
: AddDateIntroducedRoadTypes(rt
, rts
, date
);
188 * Get the road (sub) types the given company can build.
189 * @param company the company to get the roadtypes for.
190 * @param rt the base road type to check
191 * @return the available road sub types.
193 RoadSubTypes
GetCompanyRoadtypes(CompanyID company
, RoadType rt
)
195 RoadSubTypes rst
= ROADSUBTYPES_NONE
;
197 if (rt
== ROADTYPE_ROAD
) rst
|= ROADSUBTYPES_NORMAL
; // Road is always available. // TODO
200 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) {
201 const EngineInfo
*ei
= &e
->info
;
203 if (HasBit(ei
->climates
, _settings_game
.game_creation
.landscape
) &&
204 (HasBit(e
->company_avail
, company
) || _date
>= e
->intro_date
+ DAYS_IN_YEAR
) &&
205 rt
== (HasBit(ei
->misc_flags
, EF_ROAD_TRAM
) ? ROADTYPE_TRAM
: ROADTYPE_ROAD
)) {
206 rst
|= GetRoadTypeInfo(e
->GetRoadType())->introduces_roadtypes
;
210 return AddDateIntroducedRoadTypes(rt
, rst
, _date
);
213 /* ========================================================================= */
215 /* ========================================================================= */
217 CommandCost
CmdBuildBridge(TileIndex end_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
= nullptr);
218 CommandCost
CmdBuildTunnel(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
= nullptr);
219 CommandCost
CmdBuildRoad(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
= nullptr);
221 static std::vector
<TileIndex
> _town_centers
;
222 static std::vector
<TileIndex
> _towns_visited_along_the_way
;
223 static const uint PUBLIC_ROAD_HASH_SIZE
= 8U; ///< The number of bits the hash for river finding should have.
226 * Simple hash function for public road tiles to be used by AyStar.
227 * @param tile The tile to hash.
228 * @param dir The unused direction.
229 * @return The hash for the tile.
231 static uint
PublicRoad_Hash(uint tile
, uint dir
)
233 return GB(TileHash(TileX(tile
), TileY(tile
)), 0, PUBLIC_ROAD_HASH_SIZE
);
236 static const int32 BASE_COST
= 1; // Cost for utilizing an existing road, bridge, or tunnel.
237 static const int32 COST_FOR_NEW_ROAD
= 10; // Cost for building a new road.
238 static const int32 COST_FOR_SLOPE
= 5; // Additional cost if the road heads up or down a slope.
240 /* AyStar callback for getting the cost of the current node. */
241 static int32
PublicRoad_CalculateG(AyStar
*aystar
, AyStarNode
*current
, OpenListNode
*parent
)
243 int32 cost
= BASE_COST
;
245 if (!IsTileType(current
->tile
, MP_ROAD
)) {
246 if (!AreTilesAdjacent(parent
->path
.node
.tile
, current
->tile
))
248 // We're not adjacent, so we built a tunnel or bridge.
249 cost
+= (DistanceManhattan(parent
->path
.node
.tile
, current
->tile
)) * COST_FOR_NEW_ROAD
+ 6 * COST_FOR_SLOPE
;
251 else if (!IsTileFlat(current
->tile
)) {
252 cost
+= COST_FOR_NEW_ROAD
;
253 cost
+= COST_FOR_SLOPE
;
257 cost
+= COST_FOR_NEW_ROAD
;
261 if (_settings_game
.game_creation
.build_public_roads
== PRC_AVOID_CURVES
&&
262 parent
->path
.parent
!= nullptr &&
263 DiagdirBetweenTiles(parent
->path
.parent
->node
.tile
, parent
->path
.node
.tile
) != DiagdirBetweenTiles(parent
->path
.node
.tile
, current
->tile
)) {
270 /* AyStar callback for getting the estimated cost to the destination. */
271 static int32
PublicRoad_CalculateH(AyStar
*aystar
, AyStarNode
*current
, OpenListNode
*parent
)
273 return DistanceManhattan(*(TileIndex
*)aystar
->user_target
, current
->tile
) * BASE_COST
;
276 /* Helper function to check if a tile along a certain direction is going up an inclined slope. */
277 static bool IsUpwardsSlope(TileIndex tile
, DiagDirection road_direction
)
279 auto slope
= GetTileSlope(tile
);
281 if (!IsInclinedSlope(slope
)) return false;
283 auto slope_direction
= GetInclinedSlopeDirection(slope
);
285 return road_direction
== slope_direction
;
288 /* Helper function to check if a tile along a certain direction is going down an inclined slope. */
289 static bool IsDownwardsSlope(TileIndex tile
, DiagDirection road_direction
)
291 auto slope
= GetTileSlope(tile
);
293 if (!IsInclinedSlope(slope
)) return false;
295 auto slope_direction
= GetInclinedSlopeDirection(slope
);
297 return road_direction
== ReverseDiagDir(slope_direction
);
300 /* Helper function to check if a road along this tile path is possible. */
301 static bool CanBuildRoadFromTo(TileIndex begin
, TileIndex end
)
303 assert(DistanceManhattan(begin
, end
) == 1);
307 Slope slopeBegin
= GetTileSlope(begin
, &heightBegin
);
308 Slope slopeEnd
= GetTileSlope(end
, &heightEnd
);
311 /* Slope either is inclined or flat; rivers don't support other slopes. */
312 (slopeEnd
== SLOPE_FLAT
|| IsInclinedSlope(slopeEnd
)) &&
313 /* Slope continues, then it must be lower... or either end must be flat. */
314 ((slopeEnd
== slopeBegin
&& heightEnd
!= heightBegin
) || slopeEnd
== SLOPE_FLAT
|| slopeBegin
== SLOPE_FLAT
);
317 static TileIndex
BuildTunnel(PathNode
*current
, bool build_tunnel
= false)
319 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
320 auto build_tunnel_cmd
= CmdBuildTunnel(current
->node
.tile
, build_tunnel
? DC_EXEC
: DC_NONE
, ROADTYPES_ROAD
| (TRANSPORT_ROAD
<< 8), 0);
321 cur_company
.Restore();
323 assert(!build_tunnel
|| build_tunnel_cmd
.Succeeded());
324 assert(!build_tunnel
|| (IsTileType(current
->node
.tile
, MP_TUNNELBRIDGE
) && IsTileType(_build_tunnel_endtile
, MP_TUNNELBRIDGE
)));
326 if (!build_tunnel_cmd
.Succeeded()) return INVALID_TILE
;
327 if (!build_tunnel
&& !IsTileType(_build_tunnel_endtile
, MP_CLEAR
) && !IsTileType(_build_tunnel_endtile
, MP_TREES
)) return INVALID_TILE
;
329 return _build_tunnel_endtile
;
332 static TileIndex
BuildBridge(PathNode
*current
, TileIndex end_tile
= INVALID_TILE
, bool build_bridge
= false)
334 TileIndex start_tile
= current
->node
.tile
;
336 DiagDirection direction
= ReverseDiagDir(GetInclinedSlopeDirection(GetTileSlope(start_tile
)));
339 // We are not building yet, so we still need to find the end_tile.
340 for (TileIndex tile
= start_tile
+ TileOffsByDiagDir(direction
);
342 (GetTunnelBridgeLength(start_tile
, tile
) <= _settings_game
.construction
.max_bridge_length
) &&
343 (GetTileZ(start_tile
) < (GetTileZ(tile
) + _settings_game
.construction
.max_bridge_height
)) &&
344 (GetTileZ(tile
) <= GetTileZ(start_tile
));
345 tile
+= TileOffsByDiagDir(direction
)) {
347 // No supershort bridges and always ending up on a matching upwards slope.
348 if (!AreTilesAdjacent(start_tile
, tile
) && IsUpwardsSlope(tile
, direction
)) {
354 if (!IsValidTile(end_tile
)) return INVALID_TILE
;
355 if (!IsTileType(end_tile
, MP_CLEAR
) && !IsTileType(end_tile
, MP_TREES
)) return INVALID_TILE
;
358 assert(!build_bridge
|| IsValidTile(end_tile
));
360 std::vector
<BridgeType
> available_bridge_types
;
362 for (uint i
= 0; i
< MAX_BRIDGES
; ++i
) {
363 if (CheckBridgeAvailability((BridgeType
)i
, GetTunnelBridgeLength(start_tile
, end_tile
)).Succeeded()) {
364 available_bridge_types
.push_back((BridgeType
)i
);
368 assert(!build_bridge
|| !available_bridge_types
.empty());
369 if (available_bridge_types
.empty()) return INVALID_TILE
;
371 auto bridge_type
= available_bridge_types
[build_bridge
? RandomRange((uint32
)available_bridge_types
.size()) : 0];
373 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
374 auto build_bridge_cmd
= CmdBuildBridge(end_tile
, build_bridge
? DC_EXEC
: DC_NONE
, start_tile
, bridge_type
| (ROADTYPES_ROAD
<< 8) | (TRANSPORT_ROAD
<< 15));
375 cur_company
.Restore();
377 assert(!build_bridge
|| build_bridge_cmd
.Succeeded());
378 assert(!build_bridge
|| (IsTileType(start_tile
, MP_TUNNELBRIDGE
) && IsTileType(end_tile
, MP_TUNNELBRIDGE
)));
380 if (!build_bridge_cmd
.Succeeded()) return INVALID_TILE
;
385 static TileIndex
BuildRiverBridge(PathNode
*current
, DiagDirection road_direction
, TileIndex end_tile
= INVALID_TILE
, bool build_bridge
= false)
387 TileIndex start_tile
= current
->node
.tile
;
390 // We are not building yet, so we still need to find the end_tile.
391 // We will only build a bridge if we need to cross a river, so first check for that.
392 TileIndex tile
= start_tile
+ TileOffsByDiagDir(road_direction
);
394 if (!IsWaterTile(tile
) || !IsRiver(tile
)) return INVALID_TILE
;
396 // 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.
397 // 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
398 // should not force that on them. This is just to bridge rivers, not to make long bridges.
401 (GetTunnelBridgeLength(start_tile
, tile
) <= 5) &&
402 (GetTileZ(start_tile
) < (GetTileZ(tile
) + _settings_game
.construction
.max_bridge_height
)) &&
403 (GetTileZ(tile
) <= GetTileZ(start_tile
));
404 tile
+= TileOffsByDiagDir(road_direction
)) {
406 if ((IsTileType(tile
, MP_CLEAR
) || IsTileType(tile
, MP_TREES
)) &&
407 GetTileZ(tile
) <= GetTileZ(start_tile
) &&
408 GetTileSlope(tile
) == SLOPE_FLAT
) {
414 if (!IsValidTile(end_tile
)) return INVALID_TILE
;
415 if (!IsTileType(end_tile
, MP_CLEAR
) && !IsTileType(end_tile
, MP_TREES
)) return INVALID_TILE
;
418 assert(!build_bridge
|| IsValidTile(end_tile
));
420 std::vector
<BridgeType
> available_bridge_types
;
422 for (uint i
= 0; i
< MAX_BRIDGES
; ++i
) {
423 if (CheckBridgeAvailability((BridgeType
)i
, GetTunnelBridgeLength(start_tile
, end_tile
)).Succeeded()) {
424 available_bridge_types
.push_back((BridgeType
)i
);
428 auto bridge_type
= available_bridge_types
[build_bridge
? RandomRange((uint32
)available_bridge_types
.size()) : 0];
430 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
431 auto build_bridge_cmd
= CmdBuildBridge(end_tile
, build_bridge
? DC_EXEC
: DC_NONE
, start_tile
, bridge_type
| (ROADTYPES_ROAD
<< 8) | (TRANSPORT_ROAD
<< 15));
432 cur_company
.Restore();
434 assert(!build_bridge
|| build_bridge_cmd
.Succeeded());
435 assert(!build_bridge
|| (IsTileType(start_tile
, MP_TUNNELBRIDGE
) && IsTileType(end_tile
, MP_TUNNELBRIDGE
)));
437 if (!build_bridge_cmd
.Succeeded()) return INVALID_TILE
;
442 static bool IsValidNeighbourOfPreviousTile(TileIndex tile
, TileIndex previous_tile
)
444 if (!IsValidTile(tile
)) return false;
446 if (IsTileType(tile
, MP_TUNNELBRIDGE
))
448 if (GetOtherTunnelBridgeEnd(tile
) == previous_tile
) return true;
450 auto tunnel_direction
= GetTunnelBridgeDirection(tile
);
452 if (previous_tile
+ TileOffsByDiagDir(tunnel_direction
) != tile
) return false;
455 if (!IsTileType(tile
, MP_CLEAR
) && !IsTileType(tile
, MP_TREES
) && !IsTileType(tile
, MP_ROAD
)) return false;
457 auto slope
= GetTileSlope(tile
);
459 // Do not allow foundations. We'll mess things up later.
460 bool hasFoundation
= GetFoundationSlope(tile
) != slope
;
461 if (hasFoundation
) return false;
463 if (IsInclinedSlope(slope
)) {
464 auto slope_direction
= GetInclinedSlopeDirection(slope
);
465 auto road_direction
= DiagdirBetweenTiles(previous_tile
, tile
);
467 if (slope_direction
!= road_direction
&& ReverseDiagDir(slope_direction
) != road_direction
) return false;
468 } else if (slope
!= SLOPE_FLAT
) {
476 /* AyStar callback for getting the neighbouring nodes of the given node. */
477 static void PublicRoad_GetNeighbours(AyStar
*aystar
, OpenListNode
*current
)
479 TileIndex tile
= current
->path
.node
.tile
;
481 aystar
->num_neighbours
= 0;
483 // Check if we just went through a tunnel or a bridge.
484 if (current
->path
.parent
!= nullptr && !AreTilesAdjacent(tile
, current
->path
.parent
->node
.tile
)) {
485 auto previous_tile
= current
->path
.parent
->node
.tile
;
486 // We went through a tunnel or bridge, this limits our options to proceed to only forward.
487 auto tunnel_bridge_direction
= DiagdirBetweenTiles(previous_tile
, tile
);
489 TileIndex t2
= tile
+ TileOffsByDiagDir(tunnel_bridge_direction
);
490 if (IsValidNeighbourOfPreviousTile(t2
, tile
)) {
491 aystar
->neighbours
[aystar
->num_neighbours
].tile
= t2
;
492 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
493 aystar
->num_neighbours
++;
496 // Handle all the regular neighbours and existing tunnels/bridges.
497 std::vector
<TileIndex
> potential_neighbours
;
499 if (IsTileType(tile
, MP_TUNNELBRIDGE
)) {
500 auto neighbour
= GetOtherTunnelBridgeEnd(tile
);
502 aystar
->neighbours
[aystar
->num_neighbours
].tile
= neighbour
;
503 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
504 aystar
->num_neighbours
++;
506 neighbour
= tile
+ TileOffsByDiagDir(ReverseDiagDir(DiagdirBetweenTiles(tile
, neighbour
)));
508 if (IsValidNeighbourOfPreviousTile(neighbour
, tile
)) {
509 aystar
->neighbours
[aystar
->num_neighbours
].tile
= neighbour
;
510 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
511 aystar
->num_neighbours
++;
514 for (DiagDirection d
= DIAGDIR_BEGIN
; d
< DIAGDIR_END
; d
++) {
515 auto neighbour
= tile
+ TileOffsByDiagDir(d
);
516 if (IsValidNeighbourOfPreviousTile(neighbour
, tile
)) {
517 aystar
->neighbours
[aystar
->num_neighbours
].tile
= neighbour
;
518 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
519 aystar
->num_neighbours
++;
523 // Check if we can turn this into a tunnel or a bridge.
524 if (current
->path
.parent
!= nullptr) {
525 auto road_direction
= DiagdirBetweenTiles(current
->path
.parent
->node
.tile
, tile
);
526 if (IsUpwardsSlope(tile
, road_direction
)) {
527 auto tunnel_end
= BuildTunnel(¤t
->path
);
529 if (tunnel_end
!= INVALID_TILE
) {
530 assert(IsValidDiagDirection(DiagdirBetweenTiles(tile
, tunnel_end
)));
531 aystar
->neighbours
[aystar
->num_neighbours
].tile
= tunnel_end
;
532 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
533 aystar
->num_neighbours
++;
536 else if (IsDownwardsSlope(tile
, road_direction
)) {
537 auto bridge_end
= BuildBridge(¤t
->path
);
539 if (bridge_end
!= INVALID_TILE
) {
540 assert(IsValidDiagDirection(DiagdirBetweenTiles(tile
, bridge_end
)));
541 aystar
->neighbours
[aystar
->num_neighbours
].tile
= bridge_end
;
542 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
543 aystar
->num_neighbours
++;
546 else if (GetTileSlope(tile
) == SLOPE_FLAT
)
548 // 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.
549 auto bridge_end
= BuildRiverBridge(¤t
->path
, DiagdirBetweenTiles(current
->path
.parent
->node
.tile
, tile
));
550 assert(bridge_end
== INVALID_TILE
|| GetTileSlope(bridge_end
) == SLOPE_FLAT
);
552 if (bridge_end
!= INVALID_TILE
) {
553 assert(IsValidDiagDirection(DiagdirBetweenTiles(tile
, bridge_end
)));
554 aystar
->neighbours
[aystar
->num_neighbours
].tile
= bridge_end
;
555 aystar
->neighbours
[aystar
->num_neighbours
].direction
= INVALID_TRACKDIR
;
556 aystar
->num_neighbours
++;
565 /* AyStar callback for checking whether we reached our destination. */
566 static int32
PublicRoad_EndNodeCheck(AyStar
*aystar
, OpenListNode
*current
)
568 // Mark towns visited along the way.
569 auto search_result
= std::find(_town_centers
.begin(), _town_centers
.end(), current
->path
.node
.tile
);
571 if (search_result
!= _town_centers
.end()) {
572 _towns_visited_along_the_way
.push_back(current
->path
.node
.tile
);
575 return current
->path
.node
.tile
== *(TileIndex
*)aystar
->user_target
? AYSTAR_FOUND_END_NODE
: AYSTAR_DONE
;
578 /* AyStar callback when an route has been found. */
579 static void PublicRoad_FoundEndNode(AyStar
*aystar
, OpenListNode
*current
)
581 PathNode
* child
= nullptr;
583 for (PathNode
*path
= ¤t
->path
; path
!= nullptr; path
= path
->parent
) {
584 TileIndex tile
= path
->node
.tile
;
586 TownID townID
= CalcClosestTownFromTile(tile
)->index
;
588 if (IsTileType(tile
, MP_TUNNELBRIDGE
)) {
589 // Just follow the path; infrastructure is already in place.
591 } else if (path
->parent
== nullptr || AreTilesAdjacent(tile
, path
->parent
->node
.tile
)) {
592 RoadBits road_bits
= ROAD_NONE
;
594 if (child
!= nullptr) {
595 TileIndex tile2
= child
->node
.tile
;
596 road_bits
|= DiagDirToRoadBits(DiagdirBetweenTiles(tile
, tile2
));
598 if (path
->parent
!= nullptr) {
599 TileIndex tile2
= path
->parent
->node
.tile
;
600 road_bits
|= DiagDirToRoadBits(DiagdirBetweenTiles(tile
, tile2
));
603 if (child
!= nullptr || path
->parent
!= nullptr) {
604 // Check if we need to build anything.
605 bool need_to_build_road
= true;
607 if (IsTileType(tile
, MP_ROAD
)) {
608 RoadBits existing_bits
= GetRoadBits(tile
, ROADTYPE_ROAD
);
609 CLRBITS(road_bits
, existing_bits
);
610 if (road_bits
== ROAD_NONE
) need_to_build_road
= false;
613 // If it is already a road and has the right bits, we are good. Otherwise build the needed ones.
614 if (need_to_build_road
)
616 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
617 auto road_built
= CmdBuildRoad(tile
, DC_EXEC
, ROADTYPE_ROAD
<< 4 | road_bits
, 0);
618 cur_company
.Restore();
622 // We only get here if we have a parent and we're not adjacent to it. River/Tunnel time!
623 DiagDirection road_direction
= DiagdirBetweenTiles(tile
, path
->parent
->node
.tile
);
625 auto end_tile
= INVALID_TILE
;
627 auto start_slope
= GetTileSlope(tile
);
629 if (IsUpwardsSlope(tile
, road_direction
)) {
630 end_tile
= BuildTunnel(path
, true);
631 assert(IsValidTile(end_tile
) && IsDownwardsSlope(end_tile
, road_direction
));
632 } else if (IsDownwardsSlope(tile
, road_direction
)) {
633 // Provide the function with the end tile, since we already know it, but still check the result.
634 end_tile
= BuildBridge(path
, path
->parent
->node
.tile
, true);
635 assert(IsValidTile(end_tile
) && IsUpwardsSlope(end_tile
, road_direction
));
637 // River bridge is the last possibility.
638 assert(GetTileSlope(tile
) == SLOPE_FLAT
);
639 end_tile
= BuildRiverBridge(path
, road_direction
, path
->parent
->node
.tile
, true);
640 assert(IsValidTile(end_tile
) && GetTileSlope(end_tile
) == SLOPE_FLAT
);
648 bool FindPath(AyStar
& finder
, TileIndex from
, TileIndex to
)
650 finder
.CalculateG
= PublicRoad_CalculateG
;
651 finder
.CalculateH
= PublicRoad_CalculateH
;
652 finder
.GetNeighbours
= PublicRoad_GetNeighbours
;
653 finder
.EndNodeCheck
= PublicRoad_EndNodeCheck
;
654 finder
.FoundEndNode
= PublicRoad_FoundEndNode
;
655 finder
.user_target
= &(to
);
656 finder
.max_search_nodes
= 1 << 20; // 1,048,576
658 finder
.Init(PublicRoad_Hash
, 1 << PUBLIC_ROAD_HASH_SIZE
);
662 start
.direction
= INVALID_TRACKDIR
;
663 finder
.AddStartNode(&start
, 0);
665 bool found_path
= (finder
.Main() == AYSTAR_FOUND_END_NODE
);
671 * Build the public road network connecting towns using AyStar.
673 void GeneratePublicRoads()
677 if (_settings_game
.game_creation
.build_public_roads
== PRC_NONE
) return;
679 _town_centers
.clear();
680 _towns_visited_along_the_way
.clear();
682 vector
<TileIndex
> towns
;
686 FOR_ALL_TOWNS(town
) {
687 towns
.push_back(town
->xy
);
688 _town_centers
.push_back(town
->xy
);
692 SetGeneratingWorldProgress(GWP_PUBLIC_ROADS
, (uint
)towns
.size());
694 // Create a list of networks which also contain a value indicating how many times we failed to connect to them.
695 vector
<pair
<uint
, shared_ptr
<vector
<TileIndex
>>>> town_networks
;
696 unordered_map
<TileIndex
, shared_ptr
<vector
<TileIndex
>>> towns_reachable_networks
;
698 TileIndex main_town
= *towns
.begin();
699 towns
.erase(towns
.begin());
701 shared_ptr
<vector
<TileIndex
>> main_network
= make_shared
<vector
<TileIndex
>>();
702 main_network
->push_back(main_town
);
704 town_networks
.push_back(make_pair(0, main_network
));
705 IncreaseGeneratingWorldProgress(GWP_PUBLIC_ROADS
);
707 sort(towns
.begin(), towns
.end(), [&](auto a
, auto b
) { return DistanceManhattan(main_town
, a
) < DistanceManhattan(main_town
, b
); });
709 for (auto begin_town
: towns
) {
710 // Check if we can connect to any of the networks.
711 _towns_visited_along_the_way
.clear();
713 auto reachable_network_iter
= towns_reachable_networks
.find(begin_town
);
714 bool found_easy_path
= false;
716 if (reachable_network_iter
!= towns_reachable_networks
.end()) {
717 auto reachable_network
= reachable_network_iter
->second
;
719 sort(reachable_network
->begin(), reachable_network
->end(), [&](auto a
, auto b
) { return DistanceManhattan(begin_town
, a
) < DistanceManhattan(begin_town
, b
); });
721 TileIndex end_town
= *reachable_network
->begin();
725 found_easy_path
= FindPath(finder
, begin_town
, end_town
);
730 if (found_easy_path
) {
731 reachable_network_iter
->second
->push_back(begin_town
);
733 for (const TileIndex visited_town
: _towns_visited_along_the_way
) {
734 if (visited_town
!= begin_town
) towns_reachable_networks
[visited_town
] = reachable_network_iter
->second
;
737 // Sort networks by failed connection attempts, so we try the most likely one first.
738 sort(town_networks
.begin(), town_networks
.end(), [&](auto a
, auto b
) { return a
.first
< b
.first
; });
740 if (!any_of(town_networks
.begin(), town_networks
.end(), [&](auto network_pair
) {
743 auto network
= network_pair
.second
;
745 // Try to connect to the town in the network that is closest to us.
746 // If we can't connect to that one, we can't connect to any of them since they are all interconnected.
747 sort(network
->begin(), network
->end(), [&](auto a
, auto b
) { return DistanceManhattan(begin_town
, a
) < DistanceManhattan(begin_town
, b
); });
748 TileIndex end_town
= *network
->begin();
750 bool found_path
= FindPath(finder
, begin_town
, end_town
);
753 network
->push_back(begin_town
);
755 for (auto visited_town
: _towns_visited_along_the_way
) {
756 if (visited_town
!= begin_town
) towns_reachable_networks
[visited_town
] = network
;
760 // Increase number of failed attempts if necessary.
761 network_pair
.first
+= (found_path
? (network_pair
.first
> 0 ? -1 : 0) : 1);
768 // We failed to connect to any network, so we are a separate network. Let future towns try to connect to us.
769 shared_ptr
<vector
<TileIndex
>> new_network
= make_shared
<vector
<TileIndex
>>();
770 new_network
->push_back(begin_town
);
772 // We basically failed to connect to this many towns.
773 int towns_already_in_networks
= std::accumulate(town_networks
.begin(), town_networks
.end(), 0, [&](int accumulator
, auto network_pair
) {
774 return accumulator
+ (int)network_pair
.second
->size();
777 town_networks
.push_back(make_pair(towns_already_in_networks
, new_network
));
779 for (const TileIndex visited_town
: _towns_visited_along_the_way
) {
780 if (visited_town
!= begin_town
) towns_reachable_networks
.insert(make_pair(visited_town
, new_network
));
785 IncreaseGeneratingWorldProgress(GWP_PUBLIC_ROADS
);
791 * Get the road type for a given label.
792 * @param label the roadtype label.
793 * @param allow_alternate_labels Search in the alternate label lists as well.
794 * @return the roadtype.
796 RoadTypeIdentifier
GetRoadTypeByLabel(RoadTypeLabel label
, RoadType basetype
, bool allow_alternate_labels
)
798 RoadTypeIdentifier rtid
;
800 rtid
.basetype
= basetype
;
802 /* Loop through each road type until the label is found */
803 for (RoadSubType r
= ROADSUBTYPE_BEGIN
; r
!= ROADSUBTYPE_END
; r
++) {
805 const RoadtypeInfo
*rti
= GetRoadTypeInfo(rtid
);
806 if (rti
->label
== label
) return rtid
;
809 if (allow_alternate_labels
) {
810 /* Test if any road type defines the label as an alternate. */
811 for (RoadSubType r
= ROADSUBTYPE_BEGIN
; r
!= ROADSUBTYPE_END
; r
++) {
813 const RoadtypeInfo
*rti
= GetRoadTypeInfo(rtid
);
814 if (rti
->alternate_labels
.Contains(label
)) return rtid
;
818 /* No matching label was found, so it is invalid */
819 rtid
.basetype
= INVALID_ROADTYPE
;
820 rtid
.subtype
= INVALID_ROADSUBTYPE
;
824 uint8
RoadTypeIdentifier::Pack() const
826 assert(this->IsValid());
828 return this->basetype
| (this->subtype
<< 1);
831 bool RoadTypeIdentifier::UnpackIfValid(uint32 data
)
833 this->basetype
= static_cast<RoadType
>(GB(data
, 0, 1));
834 this->subtype
= static_cast<RoadSubType
>(GB(data
, 1, 5));
836 return this->IsValid();
839 /* static */ RoadTypeIdentifier
RoadTypeIdentifier::Unpack(uint32 data
)
841 RoadTypeIdentifier result
;
842 bool ret
= result
.UnpackIfValid(data
);
848 * Returns the available RoadSubTypes for the provided RoadType
849 * If the given company is valid then will be returned a list of the available sub types at the current date, while passing
850 * a deity company will make all the sub types available
851 * @param rt the RoadType to filter
852 * @param c the company ID to check the roadtype against
853 * @param any_date whether to return only currently introduced roadtypes or also future ones
854 * @returns the existing RoadSubTypes
856 RoadSubTypes
ExistingRoadSubTypesForRoadType(RoadType rt
, CompanyID c
)
858 /* Check only players which can actually own vehicles, editor and gamescripts are considered deities */
860 const Company
*company
= Company::GetIfValid(c
);
862 if (company
!= NULL
) return company
->avail_roadtypes
[rt
];
865 RoadSubTypes known_roadsubtypes
= ROADSUBTYPES_NONE
;
867 /* Road is always visible and available. */
868 if (rt
== ROADTYPE_ROAD
) known_roadsubtypes
|= ROADSUBTYPES_NORMAL
; // TODO
870 /* Find used roadtypes */
872 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) {
873 /* Check if the subtype can be used in the current climate */
874 if (!HasBit(e
->info
.climates
, _settings_game
.game_creation
.landscape
)) continue;
876 /* Check whether available for all potential companies */
877 if (e
->company_avail
!= (CompanyMask
)-1) continue;
879 RoadTypeIdentifier rtid
= e
->GetRoadType();
880 if (rtid
.basetype
!= rt
) continue;
882 known_roadsubtypes
|= GetRoadTypeInfo(rtid
)->introduces_roadtypes
;
885 /* Get the date introduced roadtypes as well. */
886 known_roadsubtypes
= AddDateIntroducedRoadTypes(rt
, known_roadsubtypes
, MAX_DAY
);
888 return known_roadsubtypes
;
892 * Check whether we can build infrastructure for the given RoadType. This to disable building stations etc. when
893 * you are not allowed/able to have the RoadType yet.
894 * @param rtid the roadtype to check this for
895 * @param company the company id to check this for
896 * @param any_date to check only existing vehicles or if it is possible to build them in the future
897 * @return true if there is any reason why you may build the infrastructure for the given roadtype
899 bool CanBuildRoadTypeInfrastructure(RoadTypeIdentifier rtid
, CompanyID company
)
901 if (_game_mode
!= GM_EDITOR
&& !Company::IsValidID(company
)) return false;
902 if (!_settings_client
.gui
.disable_unsuitable_building
) return true;
904 RoadSubTypes roadsubtypes
= ExistingRoadSubTypesForRoadType(rtid
.basetype
, company
);
906 /* Check if the filtered subtypes does have the subtype we are checking for
907 * and if we can build new ones */
908 if (_settings_game
.vehicle
.max_roadveh
> 0 && HasBit(roadsubtypes
, rtid
.subtype
)) {
909 /* Can we actually build the vehicle type? */
911 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) {
912 if (HasPowerOnRoad(e
->GetRoadType(), rtid
) || HasPowerOnRoad(rtid
, e
->GetRoadType())) return true;
917 /* We should be able to build infrastructure when we have the actual vehicle type */
919 FOR_ALL_VEHICLES(v
) {
920 if (v
->type
== VEH_ROAD
&& (company
== OWNER_DEITY
|| v
->owner
== company
) &&
921 HasBit(roadsubtypes
, RoadVehicle::From(v
)->rtid
.subtype
) && HasPowerOnRoad(RoadVehicle::From(v
)->rtid
, rtid
)) return true;