|
@@ -8,24 +8,25 @@
|
|
|
#include "station_map.h"
|
|
|
#include "depot.h"
|
|
|
#include "tile_cmd.h"
|
|
|
#include "landscape.h"
|
|
|
#include "pathfind.h"
|
|
|
#include "rail_type.h"
|
|
|
#include "debug.h"
|
|
|
#include "tunnel_map.h"
|
|
|
#include "settings_type.h"
|
|
|
#include "depot.h"
|
|
|
#include "tunnelbridge_map.h"
|
|
|
#include "core/random_func.hpp"
|
|
|
#include "tunnelbridge.h"
|
|
|
|
|
|
/* remember which tiles we have already visited so we don't visit them again. */
|
|
|
static bool TPFSetTileBit(TrackPathFinder *tpf, TileIndex tile, int dir)
|
|
|
{
|
|
|
uint hash, val, offs;
|
|
|
TrackPathFinderLink *link, *new_link;
|
|
|
uint bits = 1 << dir;
|
|
|
|
|
|
if (tpf->disable_tile_hash)
|
|
|
return true;
|
|
|
|
|
|
hash = PATHFIND_HASH_TILE(tile);
|
|
@@ -183,50 +184,24 @@ static void TPFMode2(TrackPathFinder* tp
|
|
|
continue_here:
|
|
|
tpf->the_dir = (Trackdir)(i + (HasBit(_otherdir_mask[direction], i) ? 8 : 0));
|
|
|
|
|
|
if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length, NULL)) {
|
|
|
TPFMode2(tpf, tile, _tpf_new_direction[tpf->the_dir]);
|
|
|
}
|
|
|
|
|
|
tpf->rd = rd;
|
|
|
} while (ClrBit(bits, i) != 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
/* Returns the end tile and the length of a tunnel. The length does not
|
|
|
* include the starting tile (entry), it does include the end tile (exit).
|
|
|
*/
|
|
|
FindLengthOfTunnelResult FindLengthOfTunnel(TileIndex tile, DiagDirection dir)
|
|
|
{
|
|
|
TileIndexDiff delta = TileOffsByDiagDir(dir);
|
|
|
uint z = GetTileZ(tile);
|
|
|
FindLengthOfTunnelResult flotr;
|
|
|
|
|
|
flotr.length = 0;
|
|
|
|
|
|
dir = ReverseDiagDir(dir);
|
|
|
do {
|
|
|
flotr.length++;
|
|
|
tile += delta;
|
|
|
} while(
|
|
|
!IsTunnelTile(tile) ||
|
|
|
GetTunnelBridgeDirection(tile) != dir ||
|
|
|
GetTileZ(tile) != z
|
|
|
);
|
|
|
|
|
|
flotr.tile = tile;
|
|
|
return flotr;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Checks if any vehicle can enter/leave tile in given diagdir
|
|
|
* Checks only for rail/road depots and road non-drivethrough stations
|
|
|
* @param tile tile to check
|
|
|
* @param side side of tile we are trying to leave/enter
|
|
|
* @param tracktype type of transport
|
|
|
* @pre tile has trackbit at that diagdir
|
|
|
* @return true iff vehicle can enter/leve the tile in given side
|
|
|
*/
|
|
|
static inline bool CanAccessTileInDir(TileIndex tile, DiagDirection side, TransportType tracktype)
|
|
|
{
|
|
|
if (tracktype == TRANSPORT_RAIL) {
|
|
@@ -248,25 +223,25 @@ static void TPFMode1(TrackPathFinder* tp
|
|
|
{
|
|
|
const TileIndex tile_org = tile;
|
|
|
|
|
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
|
|
/* wrong track type */
|
|
|
if (GetTunnelBridgeTransportType(tile) != tpf->tracktype) return;
|
|
|
|
|
|
DiagDirection dir = GetTunnelBridgeDirection(tile);
|
|
|
/* entering tunnel / bridge? */
|
|
|
if (dir == direction) {
|
|
|
TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
|
|
|
|
|
|
tpf->rd.cur_length += DistanceManhattan(tile, endtile);
|
|
|
tpf->rd.cur_length += GetTunnelBridgeLength(tile, endtile) + 1;
|
|
|
|
|
|
TPFSetTileBit(tpf, tile, 14);
|
|
|
TPFSetTileBit(tpf, endtile, 14);
|
|
|
|
|
|
tile = endtile;
|
|
|
} else {
|
|
|
/* leaving tunnel / bridge? */
|
|
|
if (ReverseDiagDir(dir) != direction) return;
|
|
|
}
|
|
|
} else {
|
|
|
/* can we leave tile in this dir? */
|
|
|
if (!CanAccessTileInDir(tile, direction, tpf->tracktype)) return;
|
|
@@ -656,53 +631,52 @@ callback_and_continue:
|
|
|
if (tpf->enum_proc(tile, tpf->userdata, si.first_track, si.cur_length))
|
|
|
return;
|
|
|
|
|
|
assert(si.track <= 13);
|
|
|
direction = _tpf_new_direction[si.track];
|
|
|
|
|
|
start_at:
|
|
|
/* If the tile is the entry tile of a tunnel, and we're not going out of the tunnel,
|
|
|
* need to find the exit of the tunnel. */
|
|
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
|
|
if (IsTunnel(tile)) {
|
|
|
if (GetTunnelBridgeDirection(tile) != ReverseDiagDir(direction)) {
|
|
|
FindLengthOfTunnelResult flotr;
|
|
|
|
|
|
/* We are not just driving out of the tunnel */
|
|
|
if (GetTunnelBridgeDirection(tile) != direction ||
|
|
|
GetTunnelBridgeTransportType(tile) != tpf->tracktype) {
|
|
|
/* We are not driving into the tunnel, or it is an invalid tunnel */
|
|
|
continue;
|
|
|
}
|
|
|
if (!HasBit(tpf->railtypes, GetRailType(tile))) {
|
|
|
bits = TRACK_BIT_NONE;
|
|
|
break;
|
|
|
}
|
|
|
flotr = FindLengthOfTunnel(tile, direction);
|
|
|
si.cur_length += flotr.length * DIAG_FACTOR;
|
|
|
tile = flotr.tile;
|
|
|
|
|
|
TileIndex endtile = GetOtherTunnelEnd(tile);
|
|
|
si.cur_length += DIAG_FACTOR * (GetTunnelBridgeLength(tile, endtile) + 1);
|
|
|
tile = endtile;
|
|
|
/* tile now points to the exit tile of the tunnel */
|
|
|
}
|
|
|
} else { // IsBridge(tile)
|
|
|
TileIndex tile_end;
|
|
|
if (GetTunnelBridgeDirection(tile) != ReverseDiagDir(direction)) {
|
|
|
/* We are not just leaving the bridge */
|
|
|
if (GetTunnelBridgeDirection(tile) != direction ||
|
|
|
GetTunnelBridgeTransportType(tile) != tpf->tracktype) {
|
|
|
/* Not entering the bridge or not compatible */
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
tile_end = GetOtherBridgeEnd(tile);
|
|
|
si.cur_length += DistanceManhattan(tile, tile_end) * DIAG_FACTOR;
|
|
|
si.cur_length += DIAG_FACTOR * (GetTunnelBridgeLength(tile, tile_end) + 1);
|
|
|
tile = tile_end;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* This is a special loop used to go through
|
|
|
* a rail net and find the first intersection */
|
|
|
tile_org = tile;
|
|
|
for (;;) {
|
|
|
assert(direction <= 3);
|
|
|
tile += TileOffsByDiagDir(direction);
|
|
|
|
|
|
/* too long search length? bail out. */
|