--- a/pathfind.c Tue Jan 02 16:43:05 2007 +0000
+++ b/pathfind.c Tue Jan 02 18:40:37 2007 +0000
@@ -725,50 +725,59 @@
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_TUNNEL)) {
- if (GetTunnelDirection(tile) != ReverseDiagDir(direction)) {
- FindLengthOfTunnelResult flotr;
-
- /* We are not just driving out of the tunnel */
- if (GetTunnelDirection(tile) != direction ||
- GetTunnelTransportType(tile) != tpf->tracktype) {
- // We are not driving into the tunnel, or it is an invalid tunnel
- continue;
- }
- if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
- bits = 0;
- break;
- }
- flotr = FindLengthOfTunnel(tile, direction);
- si.cur_length += flotr.length * DIAG_FACTOR;
- tile = flotr.tile;
- // tile now points to the exit tile of the tunnel
- }
- }
-
- if (IsTileType(tile, MP_STREET_BRIDGE) || IsTileType(tile, MP_RAILWAY_BRIDGE)) {
- TileIndex tile_end;
- if (GetBridgeRampDirection(tile) != ReverseDiagDir(direction)) {
- // We are not just leaving the bridge
- if (GetBridgeRampDirection(tile) != direction ||
- GetBridgeTransportType(tile) != tpf->tracktype) {
- // Not entering the bridge or not compatible
- continue;
- }
- }
- tile_end = GetOtherBridgeEnd(tile);
- si.cur_length += DistanceManhattan(tile, tile_end) * DIAG_FACTOR;
- tile = tile_end;
- }
-
// This is a special loop used to go through
// a rail net and find the first intersection
tile_org = tile;
for (;;) {
+ uint16 warp_length;
assert(direction <= 3);
- tile += TileOffsByDiagDir(direction);
+ // move 'tile' forward in our 'direction'
+ // tunnel/bridge can move us more than by just one tile forward if it is in our direction
+ if (IsTileType(tile, MP_RAILWAY_BRIDGE) && GetBridgeRampDirection(tile) == direction) {
+ // entering bridge ramp
+ TileIndex end_tile;
+ if (GetBridgeTransportType(tile) != tpf->tracktype) {
+ // wrong track type
+ bits = 0;
+ break;
+ }
+ // pass the bridge wormhole
+ end_tile = GetOtherBridgeEnd(tile);
+ warp_length = DistanceManhattan(tile, end_tile) * DIAG_FACTOR;
+ tile = end_tile;
+ } else if (IsTileType(tile, MP_TUNNEL) && GetTunnelDirection(tile) == direction) {
+ // entering tunnel
+ FindLengthOfTunnelResult flotr;
+ if (GetTunnelTransportType(tile) != tpf->tracktype) {
+ // wrong track type
+ bits = 0;
+ break;
+ }
+ // pass the tunnel wormhole
+ flotr = FindLengthOfTunnel(tile, direction);
+ warp_length = flotr.length * DIAG_FACTOR;
+ tile = flotr.tile;
+ } else {
+ // not a tunnel/bridge, move just one tile forward
+ tile += TileOffsByDiagDir(direction);
+ warp_length = 0;
+ // disable entering bridge from under-bridge track
+ if (IsTileType(tile, MP_RAILWAY_BRIDGE)) {
+ // it is allowed only when we are just at the start of pathfinding (si.first_track == 0xFF)
+ if (GetBridgeRampDirection(tile) == ReverseDiagDir(direction) && si.first_track != 0xFF) {
+ // entered bridge ramp from its back
+ bits = 0;
+ break;
+ }
+ } else if (IsTileType(tile, MP_TUNNEL)) {
+ // disable entering tunnel from regular track in the opposite direction
+ if (GetTunnelDirection(tile) == ReverseDiagDir(direction)) {
+ // entered tunnel from its back
+ bits = 0;
+ break;
+ }
+ }
+ }
// too long search length? bail out.
if (si.cur_length >= tpf->maxlength) {
@@ -779,8 +788,8 @@
// Not a regular rail tile?
// Then we can't use the code below, but revert to more general code.
- if (!IsTileType(tile, MP_RAILWAY) || !IsPlainRailTile(tile)) {
- // We found a tile which is not a normal railway tile.
+ if (!(IsTileType(tile, MP_RAILWAY) || IsTileType(tile, MP_RAILWAY_BRIDGE)) || !IsPlainRailTile(tile)) {
+ // We found a tile which is not a normal railway tile or bridge ramp (cbh behaves as normal railway).
// Determine which tracks that exist on this tile.
bits = GetTileTrackStatus(tile, TRANSPORT_RAIL) & _tpfmode1_and[direction];
bits = (bits | (bits >> 8)) & 0x3F;
@@ -825,7 +834,7 @@
track = _new_track[FIND_FIRST_BIT(bits)][direction];
assert(track != 0xff);
- si.cur_length += _length_of_track[track];
+ si.cur_length += _length_of_track[track] + warp_length;
// Check if this rail is an upwards slope. If it is, then add a penalty.
// Small optimization here.. if (track&7)>1 then it can't be a slope so we avoid calling GetTileSlope