1998 { |
2005 { |
1999 assert(!(v->vehstatus & VS_CRASHED)); |
2006 assert(!(v->vehstatus & VS_CRASHED)); |
2000 |
2007 |
2001 TrainFindDepotData tfdd; |
2008 TrainFindDepotData tfdd; |
2002 tfdd.owner = v->owner; |
2009 tfdd.owner = v->owner; |
2003 tfdd.best_length = (uint)-1; |
2010 tfdd.best_length = UINT_MAX; |
2004 tfdd.reverse = false; |
2011 tfdd.reverse = false; |
2005 |
2012 |
2006 TileIndex tile = v->tile; |
2013 TileIndex tile = v->tile; |
2007 if (IsTileDepotType(tile, TRANSPORT_RAIL)) { |
2014 if (IsTileDepotType(tile, TRANSPORT_RAIL)) { |
2008 tfdd.tile = tile; |
2015 tfdd.tile = tile; |
2009 tfdd.best_length = 0; |
2016 tfdd.best_length = 0; |
2010 return tfdd; |
2017 return tfdd; |
2011 } |
2018 } |
2012 |
2019 |
2013 if (_patches.yapf.rail_use_yapf) { |
2020 switch (_patches.pathfinder_for_trains) { |
2014 bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse); |
2021 case VPF_YAPF: { /* YAPF */ |
2015 tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND |
2022 bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse); |
2016 } else if (_patches.new_pathfinding_all) { |
2023 tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND |
2017 Vehicle* last = GetLastVehicleInChain(v); |
2024 } break; |
2018 Trackdir trackdir = GetVehicleTrackdir(v); |
2025 |
2019 Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); |
2026 case VPF_NPF: { /* NPF */ |
2020 |
2027 Vehicle* last = GetLastVehicleInChain(v); |
2021 assert(trackdir != INVALID_TRACKDIR); |
2028 Trackdir trackdir = GetVehicleTrackdir(v); |
2022 NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY); |
2029 Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); |
2023 if (ftd.best_bird_dist == 0) { |
2030 |
2024 /* Found target */ |
2031 assert(trackdir != INVALID_TRACKDIR); |
2025 tfdd.tile = ftd.node.tile; |
2032 NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY); |
2026 /* Our caller expects a number of tiles, so we just approximate that |
2033 if (ftd.best_bird_dist == 0) { |
2027 * number by this. It might not be completely what we want, but it will |
2034 /* Found target */ |
2028 * work for now :-) We can possibly change this when the old pathfinder |
2035 tfdd.tile = ftd.node.tile; |
2029 * is removed. */ |
2036 /* Our caller expects a number of tiles, so we just approximate that |
2030 tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH; |
2037 * number by this. It might not be completely what we want, but it will |
2031 if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true; |
2038 * work for now :-) We can possibly change this when the old pathfinder |
2032 } |
2039 * is removed. */ |
2033 } else { |
2040 tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH; |
2034 /* search in the forward direction first. */ |
2041 if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true; |
2035 DiagDirection i = TrainExitDir(v->direction, v->u.rail.track); |
2042 } |
2036 NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); |
2043 } break; |
2037 if (tfdd.best_length == (uint)-1){ |
2044 |
2038 tfdd.reverse = true; |
2045 default: |
2039 /* search in backwards direction */ |
2046 case VPF_NTP: { /* NTP */ |
2040 i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track); |
2047 /* search in the forward direction first. */ |
|
2048 DiagDirection i = TrainExitDir(v->direction, v->u.rail.track); |
2041 NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); |
2049 NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); |
2042 } |
2050 if (tfdd.best_length == UINT_MAX){ |
|
2051 tfdd.reverse = true; |
|
2052 /* search in backwards direction */ |
|
2053 i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track); |
|
2054 NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); |
|
2055 } |
|
2056 } break; |
2043 } |
2057 } |
2044 |
2058 |
2045 return tfdd; |
2059 return tfdd; |
2046 } |
2060 } |
2047 |
2061 |
2361 assert((tracks & ~TRACK_BIT_MASK) == 0); |
2370 assert((tracks & ~TRACK_BIT_MASK) == 0); |
2362 |
2371 |
2363 /* quick return in case only one possible track is available */ |
2372 /* quick return in case only one possible track is available */ |
2364 if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks); |
2373 if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks); |
2365 |
2374 |
2366 if (_patches.yapf.rail_use_yapf) { |
2375 switch (_patches.pathfinder_for_trains) { |
2367 Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found); |
2376 case VPF_YAPF: { /* YAPF */ |
2368 if (trackdir != INVALID_TRACKDIR) { |
2377 Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found); |
2369 best_track = TrackdirToTrack(trackdir); |
2378 if (trackdir != INVALID_TRACKDIR) { |
2370 } else { |
2379 best_track = TrackdirToTrack(trackdir); |
2371 best_track = FindFirstTrack(tracks); |
2380 } else { |
2372 } |
2381 best_track = FindFirstTrack(tracks); |
2373 } else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */ |
2382 } |
2374 void* perf = NpfBeginInterval(); |
2383 } break; |
2375 |
2384 |
2376 NPFFindStationOrTileData fstd; |
2385 case VPF_NPF: { /* NPF */ |
2377 NPFFillWithOrderData(&fstd, v); |
2386 void *perf = NpfBeginInterval(); |
2378 /* The enterdir for the new tile, is the exitdir for the old tile */ |
2387 |
2379 Trackdir trackdir = GetVehicleTrackdir(v); |
2388 NPFFindStationOrTileData fstd; |
2380 assert(trackdir != 0xff); |
2389 NPFFillWithOrderData(&fstd, v); |
2381 |
2390 /* The enterdir for the new tile, is the exitdir for the old tile */ |
2382 NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes); |
2391 Trackdir trackdir = GetVehicleTrackdir(v); |
2383 |
2392 assert(trackdir != INVALID_TRACKDIR); |
2384 if (ftd.best_trackdir == 0xff) { |
2393 |
2385 /* We are already at our target. Just do something |
2394 NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes); |
2386 * @todo maybe display error? |
2395 |
2387 * @todo: go straight ahead if possible? */ |
2396 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
2388 best_track = FindFirstTrack(tracks); |
2397 /* We are already at our target. Just do something |
2389 } else { |
2398 * @todo maybe display error? |
2390 /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains |
2399 * @todo: go straight ahead if possible? */ |
2391 the direction we need to take to get there, if ftd.best_bird_dist is not 0, |
2400 best_track = FindFirstTrack(tracks); |
2392 we did not find our target, but ftd.best_trackdir contains the direction leading |
2401 } else { |
2393 to the tile closest to our target. */ |
2402 /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains |
2394 if (ftd.best_bird_dist != 0) path_not_found = true; |
2403 * the direction we need to take to get there, if ftd.best_bird_dist is not 0, |
2395 /* Discard enterdir information, making it a normal track */ |
2404 * we did not find our target, but ftd.best_trackdir contains the direction leading |
2396 best_track = TrackdirToTrack(ftd.best_trackdir); |
2405 * to the tile closest to our target. */ |
2397 } |
2406 if (ftd.best_bird_dist != 0) path_not_found = true; |
2398 |
2407 /* Discard enterdir information, making it a normal track */ |
2399 int time = NpfEndInterval(perf); |
2408 best_track = TrackdirToTrack(ftd.best_trackdir); |
2400 DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size); |
2409 } |
2401 } else { |
2410 |
2402 void* perf = NpfBeginInterval(); |
2411 int time = NpfEndInterval(perf); |
2403 |
2412 DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size); |
2404 TrainTrackFollowerData fd; |
2413 } break; |
2405 FillWithStationData(&fd, v); |
2414 |
2406 |
2415 default: |
2407 /* New train pathfinding */ |
2416 case VPF_NTP: { /* NTP */ |
2408 fd.best_bird_dist = (uint)-1; |
2417 void *perf = NpfBeginInterval(); |
2409 fd.best_track_dist = (uint)-1; |
2418 |
2410 fd.best_track = INVALID_TRACKDIR; |
2419 TrainTrackFollowerData fd; |
2411 |
2420 FillWithStationData(&fd, v); |
2412 NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile, |
2421 |
2413 v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd); |
2422 /* New train pathfinding */ |
2414 |
2423 fd.best_bird_dist = UINT_MAX; |
2415 /* check whether the path was found or only 'guessed' */ |
2424 fd.best_track_dist = UINT_MAX; |
2416 if (fd.best_bird_dist != 0) path_not_found = true; |
2425 fd.best_track = INVALID_TRACKDIR; |
2417 |
2426 |
2418 if (fd.best_track == 0xff) { |
2427 NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile, |
2419 /* blaha */ |
2428 v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd); |
2420 best_track = FindFirstTrack(tracks); |
2429 |
2421 } else { |
2430 /* check whether the path was found or only 'guessed' */ |
2422 best_track = TrackdirToTrack(fd.best_track); |
2431 if (fd.best_bird_dist != 0) path_not_found = true; |
2423 } |
2432 |
2424 |
2433 if (fd.best_track == INVALID_TRACKDIR) { |
2425 int time = NpfEndInterval(perf); |
2434 /* blaha */ |
2426 DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0); |
2435 best_track = FindFirstTrack(tracks); |
2427 } |
2436 } else { |
|
2437 best_track = TrackdirToTrack(fd.best_track); |
|
2438 } |
|
2439 |
|
2440 int time = NpfEndInterval(perf); |
|
2441 DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0); |
|
2442 } break; |
|
2443 } |
|
2444 |
2428 /* handle "path not found" state */ |
2445 /* handle "path not found" state */ |
2429 if (path_not_found) { |
2446 if (path_not_found) { |
2430 /* PF didn't find the route */ |
2447 /* PF didn't find the route */ |
2431 if (!HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) { |
2448 if (!HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) { |
2432 /* it is first time the problem occurred, set the "path not found" flag */ |
2449 /* it is first time the problem occurred, set the "path not found" flag */ |
2472 |
2489 |
2473 assert(v->u.rail.track); |
2490 assert(v->u.rail.track); |
2474 |
2491 |
2475 int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)]; |
2492 int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)]; |
2476 |
2493 |
2477 if (_patches.yapf.rail_use_yapf) { |
2494 switch (_patches.pathfinder_for_trains) { |
2478 reverse_best = YapfCheckReverseTrain(v); |
2495 case VPF_YAPF: { /* YAPF */ |
2479 } else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */ |
2496 reverse_best = YapfCheckReverseTrain(v); |
2480 NPFFindStationOrTileData fstd; |
2497 } break; |
2481 NPFFoundTargetData ftd; |
2498 |
2482 Trackdir trackdir, trackdir_rev; |
2499 case VPF_NPF: { /* NPF */ |
2483 Vehicle* last = GetLastVehicleInChain(v); |
2500 NPFFindStationOrTileData fstd; |
2484 |
2501 NPFFoundTargetData ftd; |
2485 NPFFillWithOrderData(&fstd, v); |
2502 Vehicle* last = GetLastVehicleInChain(v); |
2486 |
2503 |
2487 trackdir = GetVehicleTrackdir(v); |
2504 NPFFillWithOrderData(&fstd, v); |
2488 trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); |
2505 |
2489 assert(trackdir != 0xff); |
2506 Trackdir trackdir = GetVehicleTrackdir(v); |
2490 assert(trackdir_rev != 0xff); |
2507 Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); |
2491 |
2508 assert(trackdir != INVALID_TRACKDIR); |
2492 ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes); |
2509 assert(trackdir_rev != INVALID_TRACKDIR); |
2493 if (ftd.best_bird_dist != 0) { |
2510 |
2494 /* We didn't find anything, just keep on going straight ahead */ |
2511 ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes); |
2495 reverse_best = false; |
2512 if (ftd.best_bird_dist != 0) { |
2496 } else { |
2513 /* We didn't find anything, just keep on going straight ahead */ |
2497 if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) { |
2514 reverse_best = false; |
2498 reverse_best = true; |
|
2499 } else { |
2515 } else { |
2500 reverse_best = false; |
2516 if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) { |
2501 } |
2517 reverse_best = true; |
2502 } |
2518 } else { |
2503 } else { |
2519 reverse_best = false; |
2504 int best_track = -1; |
2520 } |
2505 uint reverse = 0; |
2521 } |
2506 uint best_bird_dist = 0; |
2522 } break; |
2507 uint best_track_dist = 0; |
2523 |
2508 |
2524 default: |
2509 for (;;) { |
2525 case VPF_NTP: { /* NTP */ |
2510 fd.best_bird_dist = (uint)-1; |
2526 int best_track = -1; |
2511 fd.best_track_dist = (uint)-1; |
2527 uint reverse = 0; |
2512 |
2528 uint best_bird_dist = 0; |
2513 NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd); |
2529 uint best_track_dist = 0; |
2514 |
2530 |
2515 if (best_track != -1) { |
2531 for (;;) { |
2516 if (best_bird_dist != 0) { |
2532 fd.best_bird_dist = UINT_MAX; |
2517 if (fd.best_bird_dist != 0) { |
2533 fd.best_track_dist = UINT_MAX; |
2518 /* neither reached the destination, pick the one with the smallest bird dist */ |
2534 |
2519 if (fd.best_bird_dist > best_bird_dist) goto bad; |
2535 NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd); |
2520 if (fd.best_bird_dist < best_bird_dist) goto good; |
2536 |
|
2537 if (best_track != -1) { |
|
2538 if (best_bird_dist != 0) { |
|
2539 if (fd.best_bird_dist != 0) { |
|
2540 /* neither reached the destination, pick the one with the smallest bird dist */ |
|
2541 if (fd.best_bird_dist > best_bird_dist) goto bad; |
|
2542 if (fd.best_bird_dist < best_bird_dist) goto good; |
|
2543 } else { |
|
2544 /* we found the destination for the first time */ |
|
2545 goto good; |
|
2546 } |
2521 } else { |
2547 } else { |
2522 /* we found the destination for the first time */ |
2548 if (fd.best_bird_dist != 0) { |
2523 goto good; |
2549 /* didn't find destination, but we've found the destination previously */ |
|
2550 goto bad; |
|
2551 } else { |
|
2552 /* both old & new reached the destination, compare track length */ |
|
2553 if (fd.best_track_dist > best_track_dist) goto bad; |
|
2554 if (fd.best_track_dist < best_track_dist) goto good; |
|
2555 } |
2524 } |
2556 } |
2525 } else { |
2557 |
2526 if (fd.best_bird_dist != 0) { |
2558 /* if we reach this position, there's two paths of equal value so far. |
2527 /* didn't find destination, but we've found the destination previously */ |
2559 * pick one randomly. */ |
2528 goto bad; |
2560 int r = GB(Random(), 0, 8); |
2529 } else { |
2561 if (_pick_track_table[i] == (v->direction & 3)) r += 80; |
2530 /* both old & new reached the destination, compare track length */ |
2562 if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80; |
2531 if (fd.best_track_dist > best_track_dist) goto bad; |
2563 if (r <= 127) goto bad; |
2532 if (fd.best_track_dist < best_track_dist) goto good; |
|
2533 } |
|
2534 } |
2564 } |
2535 |
|
2536 /* if we reach this position, there's two paths of equal value so far. |
|
2537 * pick one randomly. */ |
|
2538 int r = GB(Random(), 0, 8); |
|
2539 if (_pick_track_table[i] == (v->direction & 3)) r += 80; |
|
2540 if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80; |
|
2541 if (r <= 127) goto bad; |
|
2542 } |
|
2543 good:; |
2565 good:; |
2544 best_track = i; |
2566 best_track = i; |
2545 best_bird_dist = fd.best_bird_dist; |
2567 best_bird_dist = fd.best_bird_dist; |
2546 best_track_dist = fd.best_track_dist; |
2568 best_track_dist = fd.best_track_dist; |
2547 reverse_best = reverse; |
2569 reverse_best = reverse; |
2548 bad:; |
2570 bad:; |
2549 if (reverse != 0) break; |
2571 if (reverse != 0) break; |
2550 reverse = 2; |
2572 reverse = 2; |
2551 } |
2573 } |
|
2574 } break; |
2552 } |
2575 } |
2553 |
2576 |
2554 return reverse_best != 0; |
2577 return reverse_best != 0; |
2555 } |
2578 } |
2556 |
2579 |
3021 enterdir = DirToDiagDir(dir); |
3044 enterdir = DirToDiagDir(dir); |
3022 assert(IsValidDiagDirection(enterdir)); |
3045 assert(IsValidDiagDirection(enterdir)); |
3023 |
3046 |
3024 /* Get the status of the tracks in the new tile and mask |
3047 /* Get the status of the tracks in the new tile and mask |
3025 * away the bits that aren't reachable. */ |
3048 * away the bits that aren't reachable. */ |
3026 uint32 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0) & _reachable_tracks[enterdir]; |
3049 TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir)) & _reachable_tracks[enterdir]; |
3027 |
3050 TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts); |
3028 /* Combine the from & to directions. |
3051 TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts)); |
3029 * Now, the lower byte contains the track status, and the byte at bit 16 contains |
3052 |
3030 * the signal status. */ |
3053 TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); |
3031 uint32 tracks = ts | (ts >> 8); |
3054 if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) { |
3032 TrackBits bits = (TrackBits)(tracks & TRACK_BIT_MASK); |
|
3033 if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _patches.forbid_90_deg && prev == NULL) { |
|
3034 /* We allow wagons to make 90 deg turns, because forbid_90_deg |
3055 /* We allow wagons to make 90 deg turns, because forbid_90_deg |
3035 * can be switched on halfway a turn */ |
3056 * can be switched on halfway a turn */ |
3036 bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); |
3057 bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); |
3037 } |
3058 } |
3038 |
3059 |
3045 TrackBits chosen_track; |
3066 TrackBits chosen_track; |
3046 if (prev == NULL) { |
3067 if (prev == NULL) { |
3047 /* Currently the locomotive is active. Determine which one of the |
3068 /* Currently the locomotive is active. Determine which one of the |
3048 * available tracks to choose */ |
3069 * available tracks to choose */ |
3049 chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits)); |
3070 chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits)); |
3050 assert(chosen_track & tracks); |
3071 assert(chosen_track & bits); |
3051 |
3072 |
3052 /* Check if it's a red signal and that force proceed is not clicked. */ |
3073 /* Check if it's a red signal and that force proceed is not clicked. */ |
3053 if ((tracks >> 16) & chosen_track && v->u.rail.force_proceed == 0) { |
3074 if (red_signals & chosen_track && v->u.rail.force_proceed == 0) { |
3054 /* In front of a red signal |
3075 /* In front of a red signal */ |
3055 * find the first set bit in ts. need to do it in 2 steps, since |
3076 Trackdir i = FindFirstTrackdir(trackdirbits); |
3056 * FIND_FIRST_BIT only handles 6 bits at a time. */ |
|
3057 Trackdir i = FindFirstTrackdir((TrackdirBits)(uint16)ts); |
|
3058 |
3077 |
3059 if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) { |
3078 if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) { |
3060 v->cur_speed = 0; |
3079 v->cur_speed = 0; |
3061 v->subspeed = 0; |
3080 v->subspeed = 0; |
3062 v->progress = 255 - 100; |
3081 v->progress = 255 - 100; |
3456 DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track); |
3475 DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track); |
3457 /* Calculate next tile */ |
3476 /* Calculate next tile */ |
3458 TileIndex tile = v->tile + TileOffsByDiagDir(dir); |
3477 TileIndex tile = v->tile + TileOffsByDiagDir(dir); |
3459 |
3478 |
3460 /* Determine the track status on the next tile */ |
3479 /* Determine the track status on the next tile */ |
3461 uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _reachable_tracks[dir]; |
3480 TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0, ReverseDiagDir(dir)) & _reachable_tracks[dir]; |
|
3481 TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts); |
|
3482 TrackdirBits red_signals = TrackStatusToRedSignals(ts); |
3462 |
3483 |
3463 /* We are sure the train is not entering a depot, it is detected above */ |
3484 /* We are sure the train is not entering a depot, it is detected above */ |
3464 |
3485 |
3465 /* no suitable trackbits at all || wrong railtype || not our track || |
3486 /* mask unreachable track bits if we are forbidden to do 90deg turns */ |
3466 * tunnel/bridge from opposite side || depot from opposite side */ |
3487 TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); |
3467 if (GB(ts, 0, 16) == 0 || !CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner || |
3488 if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) { |
3468 (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(tile) != dir) || |
3489 bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); |
3469 (IsTileDepotType(tile, TRANSPORT_RAIL) && GetRailDepotDirection(tile) == dir) ) { |
3490 } |
|
3491 |
|
3492 /* no suitable trackbits at all || unusable rail (wrong type or owner) */ |
|
3493 if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(v, tile)) { |
3470 return TrainApproachingLineEnd(v, false); |
3494 return TrainApproachingLineEnd(v, false); |
3471 } |
3495 } |
3472 |
3496 |
3473 /* approaching red signal */ |
3497 /* approaching red signal */ |
3474 if ((ts & (ts >> 16)) != 0) return TrainApproachingLineEnd(v, true); |
3498 if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(v, true); |
3475 |
3499 |
3476 /* approaching a rail/road crossing? then make it red */ |
3500 /* approaching a rail/road crossing? then make it red */ |
3477 if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile); |
3501 if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile); |
3478 |
3502 |
3479 return true; |
3503 return true; |