function Road::_CostHelper(self, prev_tile, new_tile, coast_cost_only = null)
{
local cost = 0;
if (coast_cost_only != true) {
/* Check for a turn. We do this by substracting the TileID of the current node from
* the TileID of the previous node and comparing that to the difference between the
* previous node and the node before that. */
cost += self._cost_tile;
if (path.GetParent() != null && (prev_tile - path.GetParent().GetTile()) != (new_tile - prev_tile) &&
AIMap.DistanceManhattan(path.GetParent().GetTile(), prev_tile) == 1) {
cost += self._cost_turn;
}
/* Check if the last tile was sloped. */
if (path.GetParent() != null && !AIBridge.IsBridgeTile(prev_tile) && !AITunnel.IsTunnelTile(prev_tile) &&
(AIMap.DistanceManhattan(path.GetParent().GetTile(), prev_tile) == 1) && self._IsSlopedRoad(path.GetParent().GetTile(), prev_tile, new_tile)) {
cost += self._cost_slope;
}
if (!AIRoad.AreRoadTilesConnected(prev_tile, new_tile)) {
cost += self._cost_no_existing_road;
}
}
if (coast_cost_only != null) {
/* Check if the new tile is a coast tile. */
if (AITile.IsCoastTile(new_tile) && AITile.HasTransportType(new_tile, AITile.TRANSPORT_WATER)) {
cost += self._cost_coast;
}
}
return cost;
}
function Road::_Cost(self, path, new_tile, new_direction)
{
/* path == null means this is the first node of a path, so the cost is 0. */
if (path == null) return 0;
local prev_tile = path.GetTile();
/* If the new tile is a bridge / tunnel tile, check whether we came from the other
* end of the bridge / tunnel or if we just entered the bridge / tunnel. */
if (AIBridge.IsBridgeTile(new_tile)) {
if (AIBridge.GetOtherBridgeEnd(new_tile) != prev_tile) {
return path.GetCost() + self._CostHelper(self, prev_tile, new_tile);
}
return path.GetCost() + (AIMap.DistanceManhattan(new_tile, prev_tile) + 1) * (self._cost_tile + self._cost_bridge_per_tile) - self._cost_tile + self._GetBridgeNumSlopes(new_tile, prev_tile) * self._cost_slope;
}
if (AITunnel.IsTunnelTile(new_tile)) {
if (AITunnel.GetOtherTunnelEnd(new_tile) != prev_tile) {
return path.GetCost() + self._CostHelper(self, prev_tile, new_tile);
}
return path.GetCost() + (AIMap.DistanceManhattan(new_tile, prev_tile) + 1) * (self._cost_tile + self._cost_tunnel_per_tile) - self._cost_tile;
}
/* If the two tiles are more than 1 tile apart, the pathfinder wants a bridge or tunnel
* to be built. It isn't an existing bridge / tunnel, as that case is already handled. */
if (AIMap.DistanceManhattan(new_tile, prev_tile) > 1) {
/* Check if we should build a bridge or a tunnel. */
if (AITunnel.GetOtherTunnelEnd(new_tile) == prev_tile) {
return path.GetCost() + (AIMap.DistanceManhattan(new_tile, prev_tile) + 1) * (self._cost_tile + self._cost_tunnel_per_tile + self._cost_no_existing_road) - self._cost_tile;
} else {
return path.GetCost() + (AIMap.DistanceManhattan(new_tile, prev_tile) + 1) * (self._cost_tile + self._cost_bridge_per_tile + self._cost_no_existing_road) - self._cost_tile + self._GetBridgeNumSlopes(new_tile, prev_tile) * self._cost_slope + self._CostHelper(self, prev_tile, new_tile, true);
}
}
return path.GetCost() + self._CostHelper(self, prev_tile, new_tile, false);
}