Fix tunnel glitch

pull/272/head
Andreas Schmitt 3 years ago committed by Jonathan G Rennison
parent 7601720ff7
commit 2b1d73cb3d

@ -598,98 +598,123 @@ static bool IsBlockedByPreviousBridgeOrTunnel(OpenListNode *current, TileIndex s
/** AyStar callback for getting the neighbouring nodes of the given node. */
static void PublicRoad_GetNeighbours(AyStar *aystar, OpenListNode *current)
{
const TileIndex tile = current->path.node.tile;
const auto current_tile = current->path.node.tile;
const auto previous_tile = current->path.parent != nullptr ? current->path.parent->node.tile : INVALID_TILE;
const auto forward_direction = DiagdirBetweenTiles(previous_tile, current_tile);
aystar->num_neighbours = 0;
// Check if we just went through a tunnel or a bridge.
if (current->path.parent != nullptr && !AreTilesAdjacent(tile, current->path.parent->node.tile)) {
const auto previous_tile = current->path.parent->node.tile;
if (previous_tile != INVALID_TILE && !AreTilesAdjacent(current_tile, previous_tile)) {
// We went through a tunnel or bridge, this limits our options to proceed to only forward.
const auto tunnel_bridge_direction = DiagdirBetweenTiles(previous_tile, tile);
const TileIndex tunnel_bridge_end = tile + TileOffsByDiagDir(tunnel_bridge_direction);
const TileIndex tunnel_bridge_end = current_tile + TileOffsByDiagDir(forward_direction);
if (IsValidNeighbourOfPreviousTile(tunnel_bridge_end, tile)) {
if (IsValidNeighbourOfPreviousTile(tunnel_bridge_end, current_tile)) {
aystar->neighbours[aystar->num_neighbours].tile = tunnel_bridge_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
} else {
// Handle all the regular neighbours and existing tunnels/bridges.
std::vector<TileIndex> potential_neighbours;
} else if (IsTileType(current_tile, MP_TUNNELBRIDGE)) {
// Handle existing tunnels and bridges
const auto tunnel_bridge_end = GetOtherTunnelBridgeEnd(current_tile);
const auto tunnel_bridge_direction = DiagdirBetweenTiles(current_tile, tunnel_bridge_end);
// Thanks to custom bridge heads we can come towards a bridge from anywhere but the reverse direction.
if (forward_direction == ReverseDiagDir(tunnel_bridge_direction)) {
return;
}
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
auto neighbour = GetOtherTunnelBridgeEnd(tile);
// For tunnels we need to come directly towards the tunnel though.
if (IsTunnel(current_tile) && forward_direction != tunnel_bridge_direction) {
return;
}
aystar->neighbours[aystar->num_neighbours].tile = tunnel_bridge_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
// Handle regular neighbors for bridges thanks to custom bridge heads.
if (IsBridge(current_tile)) {
for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
if (d == tunnel_bridge_direction) {
// We already added this direction.
// The direct neighbor in that direction makes no sense for a bridge.
continue;
}
aystar->neighbours[aystar->num_neighbours].tile = neighbour;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
const auto neighbour = current_tile + TileOffsByDiagDir(d);
if (neighbour == previous_tile) {
// That's where we came from.
continue;
}
if (IsValidNeighbourOfPreviousTile(neighbour, current_tile)) {
aystar->neighbours[aystar->num_neighbours].tile = neighbour;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
}
}
} else {
// Handle regular neighbors.
for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
const auto neighbour = current_tile + TileOffsByDiagDir(d);
neighbour = tile + TileOffsByDiagDir(ReverseDiagDir(DiagdirBetweenTiles(tile, neighbour)));
if (neighbour == previous_tile) {
continue;
}
if (IsValidNeighbourOfPreviousTile(neighbour, tile)) {
if (IsValidNeighbourOfPreviousTile(neighbour, current_tile)) {
aystar->neighbours[aystar->num_neighbours].tile = neighbour;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
} else {
for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
const auto neighbour = tile + TileOffsByDiagDir(d);
if (IsValidNeighbourOfPreviousTile(neighbour, tile)) {
aystar->neighbours[aystar->num_neighbours].tile = neighbour;
}
// Check if we can turn this into a tunnel or a bridge.
if (current->path.parent != nullptr) {
if (IsUpwardsSlope(current_tile, forward_direction)) {
const auto tunnel_end = BuildTunnel(&current->path);
if (tunnel_end != INVALID_TILE &&
!IsBlockedByPreviousBridgeOrTunnel(current, current_tile, tunnel_end) &&
!IsSteepSlope(GetTileSlope(tunnel_end)) &&
!IsHalftileSlope(GetTileSlope(tunnel_end)) &&
(GetTileSlope(tunnel_end) == ComplementSlope(GetTileSlope(current_tile)))) {
assert(IsValidDiagDirection(DiagdirBetweenTiles(current_tile, tunnel_end)));
aystar->neighbours[aystar->num_neighbours].tile = tunnel_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
}
// Check if we can turn this into a tunnel or a bridge.
if (current->path.parent != nullptr) {
const auto road_direction = DiagdirBetweenTiles(current->path.parent->node.tile, tile);
if (IsUpwardsSlope(tile, road_direction)) {
const auto tunnel_end = BuildTunnel(&current->path);
if (tunnel_end != INVALID_TILE &&
!IsBlockedByPreviousBridgeOrTunnel(current, current->path.node.tile, tunnel_end) &&
!IsSteepSlope(GetTileSlope(tunnel_end)) &&
!IsHalftileSlope(GetTileSlope(tunnel_end)) &&
(GetTileSlope(tunnel_end) == ComplementSlope(GetTileSlope(current->path.node.tile)))) {
assert(IsValidDiagDirection(DiagdirBetweenTiles(tile, tunnel_end)));
aystar->neighbours[aystar->num_neighbours].tile = tunnel_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
}
else if (IsDownwardsSlope(tile, road_direction)) {
const auto bridge_end = BuildBridge(&current->path, road_direction);
if (bridge_end != INVALID_TILE &&
!IsBlockedByPreviousBridgeOrTunnel(current, current->path.node.tile, bridge_end) &&
!IsSteepSlope(GetTileSlope(bridge_end)) &&
!IsHalftileSlope(GetTileSlope(bridge_end)) &&
(GetTileSlope(bridge_end) == ComplementSlope(GetTileSlope(current->path.node.tile)))) {
assert(IsValidDiagDirection(DiagdirBetweenTiles(tile, bridge_end)));
aystar->neighbours[aystar->num_neighbours].tile = bridge_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
else if (IsDownwardsSlope(current_tile, forward_direction)) {
const auto bridge_end = BuildBridge(&current->path, forward_direction);
if (bridge_end != INVALID_TILE &&
!IsBlockedByPreviousBridgeOrTunnel(current, current_tile, bridge_end) &&
!IsSteepSlope(GetTileSlope(bridge_end)) &&
!IsHalftileSlope(GetTileSlope(bridge_end)) &&
(GetTileSlope(bridge_end) == ComplementSlope(GetTileSlope(current_tile)))) {
assert(IsValidDiagDirection(DiagdirBetweenTiles(current_tile, bridge_end)));
aystar->neighbours[aystar->num_neighbours].tile = bridge_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
else if (GetTileSlope(tile) == SLOPE_FLAT)
{
// 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.
const auto bridge_end = BuildRiverBridge(&current->path, road_direction);
assert(bridge_end == INVALID_TILE || GetTileSlope(bridge_end) == SLOPE_FLAT);
if (bridge_end != INVALID_TILE &&
!IsBlockedByPreviousBridgeOrTunnel(current, current->path.node.tile, bridge_end)) {
assert(IsValidDiagDirection(DiagdirBetweenTiles(tile, bridge_end)));
aystar->neighbours[aystar->num_neighbours].tile = bridge_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
}
else if (GetTileSlope(current_tile) == SLOPE_FLAT)
{
// 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.
const auto bridge_end = BuildRiverBridge(&current->path, forward_direction);
assert(bridge_end == INVALID_TILE || GetTileSlope(bridge_end) == SLOPE_FLAT);
if (bridge_end != INVALID_TILE &&
!IsBlockedByPreviousBridgeOrTunnel(current, current_tile, bridge_end)) {
assert(IsValidDiagDirection(DiagdirBetweenTiles(current_tile, bridge_end)));
aystar->neighbours[aystar->num_neighbours].tile = bridge_end;
aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
aystar->num_neighbours++;
}
}
}

Loading…
Cancel
Save