00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "bridge_map.h"
00008 #include "station_map.h"
00009 #include "depot.h"
00010 #include "tile_cmd.h"
00011 #include "landscape.h"
00012 #include "pathfind.h"
00013 #include "rail_type.h"
00014 #include "debug.h"
00015 #include "tunnel_map.h"
00016 #include "settings_type.h"
00017 #include "depot.h"
00018 #include "tunnelbridge_map.h"
00019 #include "core/random_func.hpp"
00020 #include "tunnelbridge.h"
00021
00022
00023 static bool TPFSetTileBit(TrackPathFinder *tpf, TileIndex tile, int dir)
00024 {
00025 uint hash, val, offs;
00026 TrackPathFinderLink *link, *new_link;
00027 uint bits = 1 << dir;
00028
00029 if (tpf->disable_tile_hash)
00030 return true;
00031
00032 hash = PATHFIND_HASH_TILE(tile);
00033
00034 val = tpf->hash_head[hash];
00035
00036 if (val == 0) {
00037
00038
00039 tpf->hash_head[hash] = bits;
00040 tpf->hash_tile[hash] = tile;
00041 return true;
00042 } else if (!(val & 0x8000)) {
00043
00044
00045 if (tile == tpf->hash_tile[hash]) {
00046
00047
00048 if (val & bits)
00049 return false;
00050
00051
00052
00053 tpf->hash_head[hash] = val | bits;
00054 return true;
00055 } else {
00056
00057
00058
00059
00060 if (tpf->num_links_left == 0) {
00061 return false;
00062 }
00063 tpf->num_links_left--;
00064 link = tpf->new_link++;
00065
00066
00067
00068 link->tile = tpf->hash_tile[hash];
00069 tpf->hash_tile[hash] = PATHFIND_GET_LINK_OFFS(tpf, link);
00070
00071 link->flags = tpf->hash_head[hash];
00072 tpf->hash_head[hash] = 0xFFFF;
00073
00074 link->next = 0xFFFF;
00075 }
00076 } else {
00077
00078
00079
00080
00081 offs = tpf->hash_tile[hash];
00082 do {
00083 link = PATHFIND_GET_LINK_PTR(tpf, offs);
00084 if (tile == link->tile) {
00085
00086
00087
00088 if (link->flags & bits)
00089 return false;
00090 link->flags |= bits;
00091 return true;
00092 }
00093 } while ((offs=link->next) != 0xFFFF);
00094 }
00095
00096
00097
00098 if (tpf->num_links_left == 0) {
00099 return false;
00100 }
00101 tpf->num_links_left--;
00102 new_link = tpf->new_link++;
00103
00104
00105
00106 new_link->tile = tile;
00107 new_link->flags = bits;
00108 new_link->next = 0xFFFF;
00109
00110 link->next = PATHFIND_GET_LINK_OFFS(tpf, new_link);
00111 return true;
00112 }
00113
00114 static const byte _bits_mask[4] = {
00115 0x19,
00116 0x16,
00117 0x25,
00118 0x2A,
00119 };
00120
00121 static const DiagDirection _tpf_new_direction[14] = {
00122 DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE,
00123 INVALID_DIAGDIR, INVALID_DIAGDIR,
00124 DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE,
00125 };
00126
00127 static const DiagDirection _tpf_prev_direction[14] = {
00128 DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW,
00129 INVALID_DIAGDIR, INVALID_DIAGDIR,
00130 DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_NW,
00131 };
00132
00133
00134 static const byte _otherdir_mask[4] = {
00135 0x10,
00136 0,
00137 0x5,
00138 0x2A,
00139 };
00140
00141 static void TPFMode2(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
00142 {
00143 RememberData rd;
00144
00145 assert(tpf->tracktype == TRANSPORT_WATER);
00146
00147
00148
00149
00150 tile = TILE_MASK(tile + TileOffsByDiagDir(direction));
00151
00152 if (++tpf->rd.cur_length > 50)
00153 return;
00154
00155 TrackStatus ts = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
00156 TrackBits bits = (TrackBits)(TrackStatusToTrackBits(ts) & _bits_mask[direction]);
00157 if (bits == TRACK_BIT_NONE) return;
00158
00159 assert(TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());
00160
00161 bool only_one_track = true;
00162 do {
00163 Track track = RemoveFirstTrack(&bits);
00164 if (bits != TRACK_BIT_NONE) only_one_track = false;
00165 rd = tpf->rd;
00166
00167
00168 if (!only_one_track && track != tpf->rd.last_choosen_track) {
00169 if (++tpf->rd.depth > 4) {
00170 tpf->rd = rd;
00171 return;
00172 }
00173 tpf->rd.last_choosen_track = track;
00174 }
00175
00176 tpf->the_dir = (Trackdir)(track + (HasBit(_otherdir_mask[direction], track) ? 8 : 0));
00177
00178 if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length)) {
00179 TPFMode2(tpf, tile, _tpf_new_direction[tpf->the_dir]);
00180 }
00181
00182 tpf->rd = rd;
00183 } while (bits != TRACK_BIT_NONE);
00184
00185 }
00186
00196 static inline bool CanAccessTileInDir(TileIndex tile, DiagDirection side, TransportType tracktype)
00197 {
00198 if (tracktype == TRANSPORT_RAIL) {
00199
00200 if (IsTileDepotType(tile, TRANSPORT_RAIL) && GetRailDepotDirection(tile) != side) return false;
00201 } else if (tracktype == TRANSPORT_ROAD) {
00202
00203 if (IsTileDepotType(tile, TRANSPORT_ROAD) && GetRoadDepotDirection(tile) != side) return false;
00204
00205 if (IsStandardRoadStopTile(tile) && GetRoadStopDir(tile) != side) return false;
00206 }
00207
00208 return true;
00209 }
00210
00211 static const uint16 _tpfmode1_and[4] = { 0x1009, 0x16, 0x520, 0x2A00 };
00212
00213 static void TPFMode1(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
00214 {
00215 const TileIndex tile_org = tile;
00216
00217 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
00218
00219 if (GetTunnelBridgeTransportType(tile) != tpf->tracktype) return;
00220
00221 DiagDirection dir = GetTunnelBridgeDirection(tile);
00222
00223 if (dir == direction) {
00224 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
00225
00226 tpf->rd.cur_length += GetTunnelBridgeLength(tile, endtile) + 1;
00227
00228 TPFSetTileBit(tpf, tile, 14);
00229 TPFSetTileBit(tpf, endtile, 14);
00230
00231 tile = endtile;
00232 } else {
00233
00234 if (ReverseDiagDir(dir) != direction) return;
00235 }
00236 } else {
00237
00238 if (!CanAccessTileInDir(tile, direction, tpf->tracktype)) return;
00239 }
00240
00241 tile += TileOffsByDiagDir(direction);
00242
00243
00244 if (!CanAccessTileInDir(tile, ReverseDiagDir(direction), tpf->tracktype)) return;
00245
00246
00247
00248 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
00249 if (GetTunnelBridgeDirection(tile) != direction ||
00250 GetTunnelBridgeTransportType(tile) != tpf->tracktype) {
00251 return;
00252 }
00253 }
00254
00255 uint32 bits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type));
00256
00257
00258 if (tpf->tracktype == TRANSPORT_RAIL) {
00259 if (bits != 0 && TrackStatusToTrackdirBits(GetTileTrackStatus(tile_org, TRANSPORT_RAIL, 0)) != TRACKDIR_BIT_NONE) {
00260 if (GetTileOwner(tile_org) != GetTileOwner(tile)) return;
00261 }
00262 }
00263
00264 tpf->rd.cur_length++;
00265
00266 if ((byte)bits != tpf->var2) {
00267 bits &= _tpfmode1_and[direction];
00268 bits |= bits >> 8;
00269 }
00270 bits &= 0xBF;
00271
00272 if (bits != 0) {
00273 if (!tpf->disable_tile_hash || (tpf->rd.cur_length <= 64 && (KillFirstBit(bits) == 0 || ++tpf->rd.depth <= 7))) {
00274 do {
00275 int i = FIND_FIRST_BIT(bits);
00276 bits = KillFirstBit(bits);
00277
00278 tpf->the_dir = (Trackdir)((_otherdir_mask[direction] & (byte)(1 << i)) ? (i + 8) : i);
00279 RememberData rd = tpf->rd;
00280
00281
00282 if (TPFSetTileBit(tpf, tile, tpf->the_dir) && CanAccessTileInDir(tile, TrackdirToExitdir(tpf->the_dir), tpf->tracktype) &&
00283 !tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length) ) {
00284 TPFMode1(tpf, tile, _tpf_new_direction[tpf->the_dir]);
00285 }
00286 tpf->rd = rd;
00287 } while (bits != 0);
00288 }
00289 }
00290 }
00291
00292 void FollowTrack(TileIndex tile, uint16 flags, uint sub_type, DiagDirection direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data)
00293 {
00294 TrackPathFinder tpf;
00295
00296 assert(direction < 4);
00297
00298
00299 tpf.userdata = data;
00300 tpf.enum_proc = enum_proc;
00301 tpf.new_link = tpf.links;
00302 tpf.num_links_left = lengthof(tpf.links);
00303
00304 tpf.rd.cur_length = 0;
00305 tpf.rd.depth = 0;
00306 tpf.rd.last_choosen_track = INVALID_TRACK;
00307
00308 tpf.var2 = HasBit(flags, 15) ? 0x43 : 0xFF;
00309
00310 tpf.disable_tile_hash = HasBit(flags, 12);
00311
00312
00313 tpf.tracktype = (TransportType)(flags & 0xFF);
00314 tpf.sub_type = sub_type;
00315
00316 if (HasBit(flags, 11)) {
00317 tpf.enum_proc(tile, data, INVALID_TRACKDIR, 0);
00318 TPFMode2(&tpf, tile, direction);
00319 } else {
00320
00321 memset(tpf.hash_head, 0, sizeof(tpf.hash_head));
00322 TPFMode1(&tpf, tile, direction);
00323 }
00324
00325 if (after_proc != NULL)
00326 after_proc(&tpf);
00327 }
00328
00329 struct StackedItem {
00330 TileIndex tile;
00331 uint16 cur_length;
00332 uint16 priority;
00333 TrackdirByte track;
00334 byte depth;
00335 byte state;
00336 byte first_track;
00337 };
00338
00339 static const Trackdir _new_trackdir[6][4] = {
00340 {TRACKDIR_X_NE, INVALID_TRACKDIR, TRACKDIR_X_SW, INVALID_TRACKDIR,},
00341 {INVALID_TRACKDIR, TRACKDIR_Y_SE, INVALID_TRACKDIR, TRACKDIR_Y_NW,},
00342 {INVALID_TRACKDIR, TRACKDIR_UPPER_E, TRACKDIR_UPPER_W, INVALID_TRACKDIR,},
00343 {TRACKDIR_LOWER_E, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LOWER_W,},
00344 {TRACKDIR_LEFT_N, TRACKDIR_LEFT_S, INVALID_TRACKDIR, INVALID_TRACKDIR,},
00345 {INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_RIGHT_S, TRACKDIR_RIGHT_N,},
00346 };
00347
00348 struct HashLink {
00349 TileIndex tile;
00350 uint16 typelength;
00351 uint16 next;
00352 };
00353
00354 struct NewTrackPathFinder {
00355 NTPEnumProc *enum_proc;
00356 void *userdata;
00357 TileIndex dest;
00358
00359 TransportType tracktype;
00360 RailTypes railtypes;
00361 uint maxlength;
00362
00363 HashLink *new_link;
00364 uint num_links_left;
00365
00366 uint nstack;
00367 StackedItem stack[256];
00368
00369 uint16 hash_head[0x400];
00370 TileIndex hash_tile[0x400];
00371
00372 HashLink links[0x400];
00373
00374 };
00375 #define NTP_GET_LINK_OFFS(tpf, link) ((byte*)(link) - (byte*)tpf->links)
00376 #define NTP_GET_LINK_PTR(tpf, link_offs) (HashLink*)((byte*)tpf->links + (link_offs))
00377
00378 #define ARR(i) tpf->stack[(i)-1]
00379
00382 static inline void HeapifyUp(NewTrackPathFinder *tpf)
00383 {
00384 StackedItem si;
00385 int i = ++tpf->nstack;
00386
00387 while (i != 1 && ARR(i).priority < ARR(i>>1).priority) {
00388
00389
00390 si = ARR(i); ARR(i) = ARR(i >> 1); ARR(i >> 1) = si;
00391 i >>= 1;
00392 }
00393 }
00394
00396 static inline void HeapifyDown(NewTrackPathFinder *tpf)
00397 {
00398 StackedItem si;
00399 int i = 1, j;
00400 int n;
00401
00402 assert(tpf->nstack > 0);
00403 n = --tpf->nstack;
00404
00405 if (n == 0) return;
00406
00407
00408 ARR(1) = ARR(n + 1);
00409
00410 while ((j = i * 2) <= n) {
00411
00412 if (j != n && ARR(j).priority > ARR(j + 1).priority)
00413 j++;
00414
00415 assert(i <= n && j <= n);
00416 if (ARR(i).priority <= ARR(j).priority)
00417 break;
00418
00419
00420 si = ARR(i); ARR(i) = ARR(j); ARR(j) = si;
00421 i = j;
00422 }
00423 }
00424
00428 static bool NtpVisit(NewTrackPathFinder* tpf, TileIndex tile, DiagDirection dir, uint length)
00429 {
00430 uint hash,head;
00431 HashLink *link, *new_link;
00432
00433 assert(length < 16384-1);
00434
00435 hash = PATHFIND_HASH_TILE(tile);
00436
00437
00438 if ((head=tpf->hash_head[hash]) == 0) {
00439 tpf->hash_tile[hash] = tile;
00440 tpf->hash_head[hash] = dir | (length << 2);
00441 return true;
00442 }
00443
00444 if (head != 0xffff) {
00445 if (tile == tpf->hash_tile[hash] && (head & 0x3) == (uint)dir) {
00446
00447
00448 if (length >= (head >> 2)) return false;
00449
00450 tpf->hash_head[hash] = dir | (length << 2);
00451 return true;
00452 }
00453
00454
00455
00456 if (tpf->num_links_left == 0) {
00457 DEBUG(ntp, 1, "No links left");
00458 return false;
00459 }
00460
00461 tpf->num_links_left--;
00462 link = tpf->new_link++;
00463
00464
00465
00466 link->tile = tpf->hash_tile[hash];
00467 tpf->hash_tile[hash] = NTP_GET_LINK_OFFS(tpf, link);
00468
00469 link->typelength = tpf->hash_head[hash];
00470 tpf->hash_head[hash] = 0xFFFF;
00471 link->next = 0xFFFF;
00472 } else {
00473
00474
00475
00476
00477 uint offs = tpf->hash_tile[hash];
00478 do {
00479 link = NTP_GET_LINK_PTR(tpf, offs);
00480 if (tile == link->tile && (link->typelength & 0x3U) == (uint)dir) {
00481 if (length >= (uint)(link->typelength >> 2)) return false;
00482 link->typelength = dir | (length << 2);
00483 return true;
00484 }
00485 } while ((offs = link->next) != 0xFFFF);
00486 }
00487
00488
00489
00490 if (tpf->num_links_left == 0) {
00491 DEBUG(ntp, 1, "No links left");
00492 return false;
00493 }
00494 tpf->num_links_left--;
00495 new_link = tpf->new_link++;
00496
00497
00498
00499 new_link->tile = tile;
00500 new_link->typelength = dir | (length << 2);
00501 new_link->next = 0xFFFF;
00502
00503 link->next = NTP_GET_LINK_OFFS(tpf, new_link);
00504 return true;
00505 }
00506
00514 static bool NtpCheck(NewTrackPathFinder *tpf, TileIndex tile, uint dir, uint length)
00515 {
00516 uint hash,head,offs;
00517 HashLink *link;
00518
00519 hash = PATHFIND_HASH_TILE(tile);
00520 head=tpf->hash_head[hash];
00521 assert(head);
00522
00523 if (head != 0xffff) {
00524 assert( tpf->hash_tile[hash] == tile && (head & 3) == dir);
00525 assert( (head >> 2) <= length);
00526 return length == (head >> 2);
00527 }
00528
00529
00530 offs = tpf->hash_tile[hash];
00531 for (;;) {
00532 link = NTP_GET_LINK_PTR(tpf, offs);
00533 if (tile == link->tile && (link->typelength & 0x3U) == dir) {
00534 assert((uint)(link->typelength >> 2) <= length);
00535 return length == (uint)(link->typelength >> 2);
00536 }
00537 offs = link->next;
00538 assert(offs != 0xffff);
00539 }
00540 }
00541
00542
00543 static uint DistanceMoo(TileIndex t0, TileIndex t1)
00544 {
00545 const uint dx = Delta(TileX(t0), TileX(t1));
00546 const uint dy = Delta(TileY(t0), TileY(t1));
00547
00548 const uint straightTracks = 2 * min(dx, dy);
00549
00550
00551
00552
00553 const uint diagTracks = dx + dy - straightTracks;
00554
00555 return diagTracks*DIAG_FACTOR + straightTracks*STR_FACTOR;
00556 }
00557
00558
00559
00560
00561 static const byte _length_of_track[16] = {
00562 DIAG_FACTOR, DIAG_FACTOR, STR_FACTOR, STR_FACTOR, STR_FACTOR, STR_FACTOR, 0, 0,
00563 DIAG_FACTOR, DIAG_FACTOR, STR_FACTOR, STR_FACTOR, STR_FACTOR, STR_FACTOR, 0, 0
00564 };
00565
00566
00567
00568
00569
00570 static void NTPEnum(NewTrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
00571 {
00572 TrackBits bits, allbits;
00573 Trackdir track;
00574 TileIndex tile_org;
00575 StackedItem si;
00576 int estimation;
00577
00578
00579
00580
00581
00582 si.cur_length = 1;
00583 si.depth = 0;
00584 si.state = 0;
00585 si.first_track = 0xFF;
00586 goto start_at;
00587
00588 for (;;) {
00589
00590 do {
00591 if (tpf->nstack == 0)
00592 return;
00593 si = tpf->stack[0];
00594 tile = si.tile;
00595
00596 HeapifyDown(tpf);
00597
00598 } while (!NtpCheck(tpf, tile, _tpf_prev_direction[si.track], si.cur_length));
00599
00600
00601 si.cur_length += _length_of_track[si.track];
00602
00603 callback_and_continue:
00604 if (tpf->enum_proc(tile, tpf->userdata, si.first_track, si.cur_length))
00605 return;
00606
00607 assert(si.track <= 13);
00608 direction = _tpf_new_direction[si.track];
00609
00610 start_at:
00611
00612
00613 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
00614 if (GetTunnelBridgeDirection(tile) != ReverseDiagDir(direction)) {
00615
00616 if (GetTunnelBridgeDirection(tile) != direction ||
00617 GetTunnelBridgeTransportType(tile) != tpf->tracktype) {
00618
00619 continue;
00620 }
00621 if (!HasBit(tpf->railtypes, GetRailType(tile))) {
00622 bits = TRACK_BIT_NONE;
00623 break;
00624 }
00625
00626 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
00627 si.cur_length += DIAG_FACTOR * (GetTunnelBridgeLength(tile, endtile) + 1);
00628 tile = endtile;
00629
00630 }
00631 }
00632
00633
00634
00635 tile_org = tile;
00636 for (;;) {
00637 assert(direction <= 3);
00638 tile += TileOffsByDiagDir(direction);
00639
00640
00641 if (si.cur_length >= tpf->maxlength) {
00642 DEBUG(ntp, 1, "Cur_length too big");
00643 bits = TRACK_BIT_NONE;
00644 break;
00645 }
00646
00647
00648
00649 if (!IsTileType(tile, MP_RAILWAY) || !IsPlainRailTile(tile)) {
00650
00651
00652 TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _tpfmode1_and[direction];
00653 bits = TrackStatusToTrackBits(ts);
00654
00655
00656 if (bits == 0 || KillFirstBit(bits) != 0) break;
00657
00658 if (!HasBit(tpf->railtypes, GetRailType(tile))) {
00659 bits = TRACK_BIT_NONE;
00660 break;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669 si.track = _new_trackdir[FIND_FIRST_BIT(bits)][direction];
00670 si.cur_length += _length_of_track[si.track];
00671 goto callback_and_continue;
00672 }
00673
00674
00675 allbits = GetTrackBits(tile);
00676
00677 bits = allbits & DiagdirReachesTracks(direction);
00678
00679
00680
00681
00682 if (bits == TRACK_BIT_NONE || TracksOverlap(allbits)) break;
00683
00684 if (!HasBit(tpf->railtypes, GetRailType(tile))) {
00685 bits = TRACK_BIT_NONE;
00686 break;
00687 }
00688
00689
00690
00691
00692 track = _new_trackdir[FIND_FIRST_BIT(bits)][direction];
00693 assert(track != INVALID_TRACKDIR);
00694
00695 si.cur_length += _length_of_track[track];
00696
00697
00698 if (IsDiagonalTrackdir(track) && IsUphillTrackdir(GetTileSlope(tile, NULL), track)) {
00699
00700 si.cur_length += 4 * DIAG_FACTOR;
00701 }
00702
00703
00704 if (HasSignals(tile)) {
00705 if (!HasSignalOnTrackdir(tile, track)) {
00706
00707 if (HasSignalOnTrackdir(tile, ReverseTrackdir(track))) {
00708 bits = TRACK_BIT_NONE;
00709 break;
00710 }
00711 } else if (GetSignalStateByTrackdir(tile, track) == SIGNAL_STATE_GREEN) {
00712
00713 si.state |= 3;
00714 } else {
00715
00716 if (HasSignalOnTrackdir(tile, ReverseTrackdir(track))) {
00717
00718
00719
00720 if (!(si.state & 1)) {
00721 bits = TRACK_BIT_NONE;
00722 break;
00723 }
00724 }
00725 if (!(si.state & 2)) {
00726
00727 si.cur_length += 10 * DIAG_FACTOR;
00728 si.state += 2;
00729
00730
00731
00732 break;
00733 }
00734 }
00735
00736 if (tpf->enum_proc(tile, tpf->userdata, si.first_track, si.cur_length))
00737 return;
00738 }
00739
00740
00741 direction = _tpf_new_direction[track];
00742
00743
00744 if (tile == tile_org) {
00745 bits = TRACK_BIT_NONE;
00746 break;
00747 }
00748 }
00749
00750
00751
00752 if (bits == TRACK_BIT_NONE)
00753 continue;
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 if (!NtpVisit(tpf, tile, direction, si.cur_length))
00764 continue;
00765
00766
00767
00768
00769
00770
00771
00772 estimation = 0;
00773 if (tpf->dest != 0)
00774 estimation = DistanceMoo(tile, tpf->dest);
00775
00776 si.depth++;
00777 if (si.depth == 0)
00778 continue;
00779 si.tile = tile;
00780 while (bits != TRACK_BIT_NONE) {
00781 Track track = RemoveFirstTrack(&bits);
00782 si.track = _new_trackdir[track][direction];
00783 assert(si.track != 0xFF);
00784 si.priority = si.cur_length + estimation;
00785
00786
00787 if (tpf->nstack >= lengthof(tpf->stack)) {
00788 DEBUG(ntp, 1, "Out of stack");
00789 break;
00790 }
00791
00792 tpf->stack[tpf->nstack] = si;
00793 HeapifyUp(tpf);
00794 };
00795
00796
00797
00798
00799 if (si.depth == 1) {
00800 assert(tpf->nstack == 1 || tpf->nstack == 2 || tpf->nstack == 3);
00801 if (tpf->nstack != 1) {
00802 uint32 r = Random();
00803 if (r & 1) Swap(tpf->stack[0].track, tpf->stack[1].track);
00804 if (tpf->nstack != 2) {
00805 TrackdirByte t = tpf->stack[2].track;
00806 if (r & 2) Swap(tpf->stack[0].track, t);
00807 if (r & 4) Swap(tpf->stack[1].track, t);
00808 tpf->stack[2].first_track = tpf->stack[2].track = t;
00809 }
00810 tpf->stack[0].first_track = tpf->stack[0].track;
00811 tpf->stack[1].first_track = tpf->stack[1].track;
00812 }
00813 }
00814
00815
00816 }
00817 }
00818
00819
00821 void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypes railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data)
00822 {
00823 NewTrackPathFinder tpf;
00824
00825 tpf.dest = dest;
00826 tpf.userdata = data;
00827 tpf.enum_proc = enum_proc;
00828 tpf.tracktype = TRANSPORT_RAIL;
00829 tpf.railtypes = railtypes;
00830 tpf.maxlength = min(_patches.pf_maxlength * 3, 10000);
00831 tpf.nstack = 0;
00832 tpf.new_link = tpf.links;
00833 tpf.num_links_left = lengthof(tpf.links);
00834 memset(tpf.hash_head, 0, sizeof(tpf.hash_head));
00835
00836 NTPEnum(&tpf, tile, direction);
00837 }