MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / ExtendTrainReservation

Function ExtendTrainReservation

src/train_cmd.cpp:2513–2614  ·  view source on GitHub ↗

* Extend a train path as far as possible. Stops on encountering a safe tile, * another reservation or a track choice. * @return INVALID_TILE indicates that the reservation failed. */

Source from the content-addressed store, hash-verified

2511 * @return INVALID_TILE indicates that the reservation failed.
2512 */
2513static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir)
2514{
2515 PBSTileInfo origin = FollowTrainReservation(v);
2516
2517 CFollowTrackRail ft(v);
2518
2519 std::vector<std::pair<TileIndex, Trackdir>> signals_set_to_red;
2520
2521 TileIndex tile = origin.tile;
2522 Trackdir cur_td = origin.trackdir;
2523 while (ft.Follow(tile, cur_td)) {
2524 if (KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
2525 /* Possible signal tile. */
2526 if (HasOnewaySignalBlockingTrackdir(ft.new_tile, FindFirstTrackdir(ft.new_td_bits))) break;
2527 }
2528
2529 if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
2530 ft.new_td_bits &= ~TrackdirCrossesTrackdirs(ft.old_td);
2531 if (ft.new_td_bits == TRACKDIR_BIT_NONE) break;
2532 }
2533
2534 /* Station, depot or waypoint are a possible target. */
2535 bool target_seen = ft.is_station || (IsTileType(ft.new_tile, MP_RAILWAY) && !IsPlainRail(ft.new_tile));
2536 if (target_seen || KillFirstBit(ft.new_td_bits) != TRACKDIR_BIT_NONE) {
2537 /* Choice found or possible target encountered.
2538 * On finding a possible target, we need to stop and let the pathfinder handle the
2539 * remaining path. This is because we don't know if this target is in one of our
2540 * orders, so we might cause pathfinding to fail later on if we find a choice.
2541 * This failure would cause a bogous call to TryReserveSafePath which might reserve
2542 * a wrong path not leading to our next destination. */
2543 if (HasReservedTracks(ft.new_tile, TrackdirBitsToTrackBits(TrackdirReachesTrackdirs(ft.old_td)))) break;
2544
2545 /* If we did skip some tiles, backtrack to the first skipped tile so the pathfinder
2546 * actually starts its search at the first unreserved tile. */
2547 if (ft.tiles_skipped != 0) ft.new_tile -= TileOffsByDiagDir(ft.exitdir) * ft.tiles_skipped;
2548
2549 /* Choice found, path valid but not okay. Save info about the choice tile as well. */
2550 if (new_tracks != nullptr) *new_tracks = TrackdirBitsToTrackBits(ft.new_td_bits);
2551 if (enterdir != nullptr) *enterdir = ft.exitdir;
2552 return PBSTileInfo(ft.new_tile, ft.old_td, false);
2553 }
2554
2555 tile = ft.new_tile;
2556 cur_td = FindFirstTrackdir(ft.new_td_bits);
2557
2558 Trackdir rev_td = ReverseTrackdir(cur_td);
2559 if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) {
2560 bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg);
2561 if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break;
2562 /* Green path signal opposing the path? Turn to red. */
2563 if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
2564 signals_set_to_red.emplace_back(tile, rev_td);
2565 SetSignalStateByTrackdir(tile, rev_td, SIGNAL_STATE_RED);
2566 MarkTileDirtyByTile(tile);
2567 }
2568 /* Safe position is all good, path valid and okay. */
2569 return PBSTileInfo(tile, cur_td, true);
2570 }

Callers 1

ChooseTrainTrackFunction · 0.85

Calls 15

FollowTrainReservationFunction · 0.85
KillFirstBitFunction · 0.85
FindFirstTrackdirFunction · 0.85
Rail90DegTurnDisallowedFunction · 0.85
GetTileRailTypeFunction · 0.85
TrackdirCrossesTrackdirsFunction · 0.85
IsTileTypeFunction · 0.85
IsPlainRailFunction · 0.85
HasReservedTracksFunction · 0.85
TrackdirBitsToTrackBitsFunction · 0.85
TrackdirReachesTrackdirsFunction · 0.85

Tested by

no test coverage detected