changeset 13842:72b2245c3b0d draft

(svn r18371) -Codechange: unify calling of the train pathfinders
author rubidium <rubidium@openttd.org>
date Wed, 02 Dec 2009 09:57:17 +0000
parents c2bb1bf4ff1b
children 2a23885aaf5f
files src/pathfinder/npf/npf.cpp src/pathfinder/npf/npf.h src/pathfinder/npf/npf_func.h src/pathfinder/pathfinder_type.h src/pathfinder/yapf/yapf.h src/pathfinder/yapf/yapf_rail.cpp src/train_cmd.cpp
diffstat 7 files changed, 245 insertions(+), 209 deletions(-) [+]
line wrap: on
line diff
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -21,6 +21,7 @@
 #include "../../train.h"
 #include "../../ship.h"
 #include "../pathfinder_func.h"
+#include "../pathfinder_type.h"
 #include "npf.h"
 
 static AyStar _npf_aystar;
@@ -1059,30 +1060,6 @@
 	return best_result;
 }
 
-NPFFoundTargetData NPFRouteToSafeTile(const Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype)
-{
-	assert(v->type == VEH_TRAIN);
-
-	NPFFindStationOrTileData fstd;
-	fstd.v = v;
-	fstd.reserve_path = true;
-
-	AyStarNode start1;
-	start1.tile = tile;
-	/* We set this in case the target is also the start tile, we will just
-	 * return a not found then */
-	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
-	start1.direction = trackdir;
-	NPFSetFlag(&start1, NPF_FLAG_IGNORE_RESERVED, true);
-
-	RailTypes railtypes = v->compatible_railtypes;
-	if (override_railtype) railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
-
-	/* perform a breadth first search. Target is NULL,
-	 * since we are just looking for any safe tile...*/
-	return NPFRouteInternal(&start1, true, NULL, false, &fstd, NPFFindSafeTile, NPFCalcZero, TRANSPORT_RAIL, 0, v->owner, railtypes, 0);
-}
-
 void InitializeNPF()
 {
 	static bool first_init = true;
@@ -1139,3 +1116,98 @@
 	if (ftd.best_trackdir == 0xff) return INVALID_TRACK;
 	return TrackdirToTrack(ftd.best_trackdir);
 }
+
+/*** Trains ***/
+
+FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_distance)
+{
+	const Train *last = v->Last();
+	Trackdir trackdir = v->GetVehicleTrackdir();
+	Trackdir trackdir_rev = ReverseTrackdir(last->GetVehicleTrackdir());
+
+	assert(trackdir != INVALID_TRACKDIR);
+	NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->compatible_railtypes, NPF_INFINITE_PENALTY);
+	if (ftd.best_bird_dist != 0) FindDepotData();
+
+	/* Found target */
+	/* Our caller expects a number of tiles, so we just approximate that
+	 * number by this. It might not be completely what we want, but it will
+	 * work for now :-) We can possibly change this when the old pathfinder
+	 * is removed. */
+	return FindDepotData(ftd.node.tile, ftd.best_path_dist / NPF_TILE_LENGTH, NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE));
+}
+
+bool NPFTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype)
+{
+	assert(v->type == VEH_TRAIN);
+
+	NPFFindStationOrTileData fstd;
+	fstd.v = v;
+	fstd.reserve_path = true;
+
+	AyStarNode start1;
+	start1.tile = tile;
+	/* We set this in case the target is also the start tile, we will just
+	 * return a not found then */
+	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
+	start1.direction = trackdir;
+	NPFSetFlag(&start1, NPF_FLAG_IGNORE_RESERVED, true);
+
+	RailTypes railtypes = v->compatible_railtypes;
+	if (override_railtype) railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
+
+	/* perform a breadth first search. Target is NULL,
+	 * since we are just looking for any safe tile...*/
+	return NPFRouteInternal(&start1, true, NULL, false, &fstd, NPFFindSafeTile, NPFCalcZero, TRANSPORT_RAIL, 0, v->owner, railtypes, 0).res_okay;
+}
+
+bool NPFTrainCheckReverse(const Train *v)
+{
+	NPFFindStationOrTileData fstd;
+	NPFFoundTargetData ftd;
+	const Train *last = v->Last();
+
+	NPFFillWithOrderData(&fstd, v);
+
+	Trackdir trackdir = v->GetVehicleTrackdir();
+	Trackdir trackdir_rev = ReverseTrackdir(last->GetVehicleTrackdir());
+	assert(trackdir != INVALID_TRACKDIR);
+	assert(trackdir_rev != INVALID_TRACKDIR);
+
+	ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->compatible_railtypes);
+	/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
+	return ftd.best_bird_dist != 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
+}
+
+Track NPFTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, struct PBSTileInfo *target)
+{
+	NPFFindStationOrTileData fstd;
+	NPFFillWithOrderData(&fstd, v, reserve_track);
+
+	PBSTileInfo origin = FollowTrainReservation(v);
+	assert(IsValidTrackdir(origin.trackdir));
+
+	NPFFoundTargetData ftd = NPFRouteToStationOrTile(origin.tile, origin.trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->compatible_railtypes);
+
+	if (target != NULL) {
+		target->tile = ftd.node.tile;
+		target->trackdir = (Trackdir)ftd.node.direction;
+		target->okay = ftd.res_okay;
+	}
+
+	if (ftd.best_trackdir == INVALID_TRACKDIR) {
+		/* We are already at our target. Just do something
+		 * @todo maybe display error?
+		 * @todo: go straight ahead if possible? */
+		if (path_not_found) *path_not_found = false;
+		return FindFirstTrack(tracks);
+	}
+
+	/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
+	 * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
+	 * we did not find our target, but ftd.best_trackdir contains the direction leading
+	 * to the tile closest to our target. */
+	if (path_not_found != NULL) *path_not_found = (ftd.best_bird_dist != 0);
+	/* Discard enterdir information, making it a normal track */
+	return TrackdirToTrack(ftd.best_trackdir);
+}
--- a/src/pathfinder/npf/npf.h
+++ b/src/pathfinder/npf/npf.h
@@ -38,7 +38,8 @@
 };
 
 enum {
-	/** This penalty is the equivalent of "inifite", which means that paths that
+	/**
+	 * This penalty is the equivalent of "infite", which means that paths that
 	 * get this penalty will be chosen, but only if there is no other route
 	 * without it. Be careful with not applying this penalty to often, or the
 	 * total path cost might overflow..
@@ -119,12 +120,6 @@
  * of choices and accurate heuristics, such as water. */
 NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, TransportType type, uint sub_type, Owner owner, RailTypes railtypes);
 
-/**
- * Search for any safe tile using a breadth first search and try to reserve a path.
- */
-NPFFoundTargetData NPFRouteToSafeTile(const struct Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype);
-
-
 void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool reserve_path = false);
 
 
--- a/src/pathfinder/npf/npf_func.h
+++ b/src/pathfinder/npf/npf_func.h
@@ -12,6 +12,10 @@
 #ifndef NPF_FUNC_H
 #define NPF_FUNC_H
 
+#include "../../track_type.h"
+#include "../../direction_type.h"
+#include "../pathfinder_type.h"
+
 /**
  * Finds the best path for given ship using NPF.
  * @param v        the ship that needs to find a path
@@ -22,4 +26,45 @@
  */
 Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks);
 
+/**
+ * Used when user sends train to the nearest depot or if train needs servicing using NPF
+ * @param v            train that needs to go to some depot
+ * @param max_distance max distance (number of track tiles) from the current train position
+ *                     (used also as optimization - the pathfinder can stop path finding if max_distance
+ *                     was reached and no depot was seen)
+ * @return             the data about the depot
+ */
+FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_distance);
+
+/**
+ * Try to extend the reserved path of a train to the nearest safe tile using NPF.
+ *
+ * @param v    The train that needs to find a safe tile.
+ * @param tile Last tile of the current reserved path.
+ * @param td   Last trackdir of the current reserved path.
+ * @param override_railtype Should all physically compatible railtypes be searched, even if the vehicle can't run on them on its own?
+ * @return True if the path could be extended to a safe tile.
+ */
+bool NPFTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype);
+
+/**
+ * Returns true if it is better to reverse the train before leaving station using NPF.
+ * @param v the train leaving the station
+ * @return true if reversing is better
+ */
+bool NPFTrainCheckReverse(const Train *v);
+
+/**
+ * Finds the best path for given train using NPF.
+ * @param v        the train that needs to find a path
+ * @param tile     the tile to find the path from (should be next tile the train is about to enter)
+ * @param enterdir diagonal direction which the RV will enter this new tile from
+ * @param tracks   available trackdirs on the new tile (to choose from)
+ * @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess')
+ * @param reserve_track indicates whether YAPF should try to reserve the found path
+ * @param target   [out] the target tile of the reservation, free is set to true if path was reserved
+ * @return         the best track for next turn
+ */
+Track NPFTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, struct PBSTileInfo *target);
+
 #endif /* NPF_FUNC_H */
new file mode 100644
--- /dev/null
+++ b/src/pathfinder/pathfinder_type.h
@@ -0,0 +1,35 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file pathfinder_type.h General types related to pathfinders. */
+
+#ifndef PATHFINDER_TYPE_H
+#define PATHFINDER_TYPE_H
+
+/**
+ * Helper container to find a depot
+ */
+struct FindDepotData {
+	TileIndex tile;   ///< The tile of the depot
+	uint best_length; ///< The distance towards the depot, or UINT_MAX if not found
+	bool reverse;     ///< True if reversing is necessary for the train to get to this depot
+
+	/**
+	 * Create an instance of this structure.
+	 * @param tile        the tile of the depot
+	 * @param best_length the distance towards the depot, or UINT_MAX if not found
+	 * @param reverse     whether we need to reverse first.
+	 */
+	FindDepotData(TileIndex tile = INVALID_TILE, uint best_length = UINT_MAX, bool reverse = false) :
+		tile(tile), best_length(best_length), reverse(reverse)
+	{
+	}
+};
+
+#endif /* PATHFINDER_TYPE_H */
--- a/src/pathfinder/yapf/yapf.h
+++ b/src/pathfinder/yapf/yapf.h
@@ -14,6 +14,7 @@
 
 #include "../../direction_type.h"
 #include "../../station_type.h"
+#include "../pathfinder_type.h"
 
 /**
  * Finds the best path for given ship using YAPF.
@@ -33,7 +34,8 @@
  */
 Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir);
 
-/** Finds the best path for given train.
+/**
+ * Finds the best path for given train using YAPF.
  * @param v        the train that needs to find a path
  * @param tile     the tile to find the path from (should be next tile the train is about to enter)
  * @param enterdir diagonal direction which the RV will enter this new tile from
@@ -41,9 +43,9 @@
  * @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess')
  * @param reserve_track indicates whether YAPF should try to reserve the found path
  * @param target   [out] the target tile of the reservation, free is set to true if path was reserved
- * @return         the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
+ * @return         the best track for next turn
  */
-Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, struct PBSTileInfo *target);
+Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, struct PBSTileInfo *target);
 
 /** Used by RV multistop feature to find the nearest road stop that has a free slot.
  * @param v      RV (its current tile will be the origin)
@@ -70,31 +72,33 @@
  */
 bool YapfFindNearestRoadDepot(const Vehicle *v, int max_distance, TileIndex *depot_tile);
 
-/** Used when user sends train to the nearest depot or if train needs servicing.
+/**
+ * Used when user sends train to the nearest depot or if train needs servicing using YAPF.
  * @param v            train that needs to go to some depot
  * @param max_distance max distance (number of track tiles) from the current train position
  *                     (used also as optimization - the pathfinder can stop path finding if max_distance
  *                     was reached and no depot was seen)
- * @param reverse_penalty penalty that should be added for the path that requires reversing the train first
- * @param depot_tile   receives the depot tile if depot was found
- * @param reversed     receives true if train needs to reversed first
- * @return             true if depot was found.
+ * @return             the data about the depot
  */
-bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed);
-
-/** Returns true if it is better to reverse the train before leaving station */
-bool YapfCheckReverseTrain(const Vehicle *v);
+FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_distance);
 
 /**
- * Try to extend the reserved path of a train to the nearest safe tile.
+ * Returns true if it is better to reverse the train before leaving station using YAPF.
+ * @param v the train leaving the station
+ * @return true if reversing is better
+ */
+bool YapfTrainCheckReverse(const Train *v);
+
+/**
+ * Try to extend the reserved path of a train to the nearest safe tile using YAPF.
  *
  * @param v    The train that needs to find a safe tile.
  * @param tile Last tile of the current reserved path.
  * @param td   Last trackdir of the current reserved path.
- * @param override_railtype Should all physically compabtible railtypes be searched, even if the vehicle can't on them on it own?
+ * @param override_railtype Should all physically compatible railtypes be searched, even if the vehicle can't run on them on its own?
  * @return True if the path could be extended to a safe tile.
  */
-bool YapfRailFindNearestSafeTile(const Vehicle *v, TileIndex tile, Trackdir td, bool override_railtype);
+bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype);
 
 /** Use this function to notify YAPF that track layout (or signal configuration) has change */
 void YapfNotifyTrackLayoutChange(TileIndex tile, Track track);
@@ -111,7 +115,17 @@
 /** Base tile length units */
 enum {
 	YAPF_TILE_LENGTH = 100,
-	YAPF_TILE_CORNER_LENGTH = 71
+	YAPF_TILE_CORNER_LENGTH = 71,
+
+	/**
+	 * This penalty is the equivalent of "infite", which means that paths that
+	 * get this penalty will be chosen, but only if there is no other route
+	 * without it. Be careful with not applying this penalty to often, or the
+	 * total path cost might overflow..
+	 * For now, this is just a Very Big Penalty, we might actually implement
+	 * this in a nicer way :-)
+	 */
+	YAPF_INFINITE_PENALTY = 1000 * YAPF_TILE_LENGTH,
 };
 
 #endif /* YAPF_H */
--- a/src/pathfinder/yapf/yapf_rail.cpp
+++ b/src/pathfinder/yapf/yapf_rail.cpp
@@ -524,7 +524,7 @@
 struct CYapfAnySafeTileRail2 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail2, CFollowTrackFreeRailNo90, CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
 
 
-Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target)
+Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target)
 {
 	/* default is YAPF type 2 */
 	typedef Trackdir (*PfnChooseRailTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits, bool*, bool, PBSTileInfo*);
@@ -536,13 +536,11 @@
 	}
 
 	Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track, target);
-
-	return td_ret;
+	return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
 }
 
-bool YapfCheckReverseTrain(const Vehicle *vt)
+bool YapfTrainCheckReverse(const Train *v)
 {
-	const Train *v = Train::From(vt);
 	const Train *last_veh = v->Last();
 
 	/* get trackdirs of both ends */
@@ -600,12 +598,11 @@
 	return reverse;
 }
 
-bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed)
+FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_distance)
 {
-	*depot_tile = INVALID_TILE;
-	*reversed = false;
+	FindDepotData fdd;
 
-	const Vehicle *last_veh = v->Last();
+	const Train *last_veh = v->Last();
 
 	PBSTileInfo origin = FollowTrainReservation(Train::From(v));
 	TileIndex last_tile = last_veh->tile;
@@ -619,11 +616,12 @@
 		pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail2::stFindNearestDepotTwoWay; // Trackdir, forbid 90-deg
 	}
 
-	bool ret = pfnFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_distance, reverse_penalty, depot_tile, reversed);
-	return ret;
+	bool ret = pfnFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_distance, YAPF_INFINITE_PENALTY, &fdd.tile, &fdd.reverse);
+	fdd.best_length = ret ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
+	return fdd;
 }
 
-bool YapfRailFindNearestSafeTile(const Vehicle *v, TileIndex tile, Trackdir td, bool override_railtype)
+bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
 {
 	typedef bool (*PfnFindNearestSafeTile)(const Vehicle*, TileIndex, Trackdir, bool);
 	PfnFindNearestSafeTile pfnFindNearestSafeTile = CYapfAnySafeTileRail1::stFindNearestSafeTile;
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -13,7 +13,7 @@
 #include "gui.h"
 #include "articulated_vehicles.h"
 #include "command_func.h"
-#include "pathfinder/npf/npf.h"
+#include "pathfinder/npf/npf_func.h"
 #include "news_func.h"
 #include "company_func.h"
 #include "vehicle_gui.h"
@@ -2138,77 +2138,28 @@
 	return cost;
 }
 
-struct TrainFindDepotData {
-	uint best_length;
-	TileIndex tile;
-	Owner owner;
-	/**
-	 * true if reversing is necessary for the train to get to this depot
-	 * This value is unused when new depot finding and NPF are both disabled
-	 */
-	bool reverse;
-};
-
 /** returns the tile of a depot to goto to. The given vehicle must not be
  * crashed! */
-static TrainFindDepotData FindClosestTrainDepot(Train *v, int max_distance)
+static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
 {
 	assert(!(v->vehstatus & VS_CRASHED));
 
-	TrainFindDepotData tfdd;
-	tfdd.owner = v->owner;
-	tfdd.reverse = false;
-
-	if (IsRailDepotTile(v->tile)) {
-		tfdd.tile = v->tile;
-		tfdd.best_length = 0;
-		return tfdd;
-	}
+	if (IsRailDepotTile(v->tile)) return FindDepotData(v->tile, 0);
 
 	PBSTileInfo origin = FollowTrainReservation(v);
-	if (IsRailDepotTile(origin.tile)) {
-		tfdd.tile = origin.tile;
-		tfdd.best_length = 0;
-		return tfdd;
-	}
-
-	tfdd.best_length = UINT_MAX;
+	if (IsRailDepotTile(origin.tile)) return FindDepotData(origin.tile, 0);
 
 	switch (_settings_game.pf.pathfinder_for_trains) {
-		case VPF_YAPF: { // YAPF
-			bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
-			tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
-		} break;
-
-		case VPF_NPF: { // NPF
-			const Vehicle *last = v->Last();
-			Trackdir trackdir = v->GetVehicleTrackdir();
-			Trackdir trackdir_rev = ReverseTrackdir(last->GetVehicleTrackdir());
-
-			assert(trackdir != INVALID_TRACKDIR);
-			NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->compatible_railtypes, NPF_INFINITE_PENALTY);
-			if (ftd.best_bird_dist == 0) {
-				/* Found target */
-				tfdd.tile = ftd.node.tile;
-				/* Our caller expects a number of tiles, so we just approximate that
-				 * number by this. It might not be completely what we want, but it will
-				 * work for now :-) We can possibly change this when the old pathfinder
-				 * is removed. */
-				tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
-				if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
-			}
-		} break;
-
-		default:
-			NOT_REACHED();
+		case VPF_NPF: return NPFTrainFindNearestDepot(v, max_distance);
+		case VPF_YAPF: return YapfTrainFindNearestDepot(v, max_distance);
+
+		default: NOT_REACHED();
 	}
-
-	return tfdd;
 }
 
 bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
 {
-	TrainFindDepotData tfdd = FindClosestTrainDepot(this, 0);
+	FindDepotData tfdd = FindClosestTrainDepot(this, 0);
 	if (tfdd.best_length == UINT_MAX) return false;
 
 	if (location    != NULL) *location    = tfdd.tile;
@@ -2556,71 +2507,14 @@
  * @param dest [out] State and destination of the requested path
  * @return The best track the train should follow
  */
-static Track DoTrainPathfind(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation, PBSTileInfo *dest)
+static Track DoTrainPathfind(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation, PBSTileInfo *dest)
 {
-	Track best_track;
-
-#ifdef PF_BENCHMARK
-	TIC()
-#endif
-
-	if (path_not_found) *path_not_found = false;
-
 	switch (_settings_game.pf.pathfinder_for_trains) {
-		case VPF_YAPF: { // YAPF
-			Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, path_not_found, do_track_reservation, dest);
-			if (trackdir != INVALID_TRACKDIR) {
-				best_track = TrackdirToTrack(trackdir);
-			} else {
-				best_track = FindFirstTrack(tracks);
-			}
-		} break;
-
-		case VPF_NPF: { // NPF
-			void *perf = NpfBeginInterval();
-
-			NPFFindStationOrTileData fstd;
-			NPFFillWithOrderData(&fstd, v, do_track_reservation);
-
-			PBSTileInfo origin = FollowTrainReservation(v);
-			assert(IsValidTrackdir(origin.trackdir));
-
-			NPFFoundTargetData ftd = NPFRouteToStationOrTile(origin.tile, origin.trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->compatible_railtypes);
-
-			if (dest != NULL) {
-				dest->tile = ftd.node.tile;
-				dest->trackdir = (Trackdir)ftd.node.direction;
-				dest->okay = ftd.res_okay;
-			}
-
-			if (ftd.best_trackdir == INVALID_TRACKDIR) {
-				/* We are already at our target. Just do something
-				 * @todo maybe display error?
-				 * @todo: go straight ahead if possible? */
-				best_track = FindFirstTrack(tracks);
-			} else {
-				/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
-				 * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
-				 * we did not find our target, but ftd.best_trackdir contains the direction leading
-				 * to the tile closest to our target. */
-				if (ftd.best_bird_dist != 0 && path_not_found != NULL) *path_not_found = true;
-				/* Discard enterdir information, making it a normal track */
-				best_track = TrackdirToTrack(ftd.best_trackdir);
-			}
-
-			int time = NpfEndInterval(perf);
-			DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
-		} break;
-
-		default:
-			NOT_REACHED();
+		case VPF_NPF: return NPFTrainChooseTrack(v, tile, enterdir, tracks, path_not_found, do_track_reservation, dest);
+		case VPF_YAPF: return YapfTrainChooseTrack(v, tile, enterdir, tracks, path_not_found, do_track_reservation, dest);
+
+		default: NOT_REACHED();
 	}
-
-#ifdef PF_BENCHMARK
-	TOC("PF time = ", 1)
-#endif
-
-	return best_track;
 }
 
 /**
@@ -2717,15 +2611,16 @@
  * @param v The vehicle.
  * @param tile The tile the search should start from.
  * @param td The trackdir the search should start from.
- * @param override_tailtype Whether all physically compatible railtypes should be followed.
+ * @param override_railtype Whether all physically compatible railtypes should be followed.
  * @return True if a path to a safe stopping tile could be reserved.
  */
 static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_tailtype)
 {
-	if (_settings_game.pf.pathfinder_for_trains == VPF_YAPF) {
-		return YapfRailFindNearestSafeTile(v, tile, td, override_tailtype);
-	} else {
-		return NPFRouteToSafeTile(v, tile, td, override_tailtype).res_okay;
+	switch (_settings_game.pf.pathfinder_for_trains) {
+		case VPF_NPF: return NPFTrainFindNearestSafeTile(v, tile, td, override_tailtype);
+		case VPF_YAPF: return YapfTrainFindNearestSafeTile(v, tile, td, override_tailtype);
+
+		default: NOT_REACHED();
 	}
 }
 
@@ -3069,7 +2964,7 @@
 }
 
 
-static bool CheckReverseTrain(Train *v)
+static bool CheckReverseTrain(const Train *v)
 {
 	if (_settings_game.difficulty.line_reverse_mode != 0 ||
 			v->track == TRACK_BIT_DEPOT || v->track == TRACK_BIT_WORMHOLE ||
@@ -3077,31 +2972,13 @@
 		return false;
 	}
 
-	assert(v->track);
+	assert(v->track != TRACK_BIT_NONE);
 
 	switch (_settings_game.pf.pathfinder_for_trains) {
-		case VPF_YAPF: // YAPF
-			return YapfCheckReverseTrain(v);
-
-		case VPF_NPF: { // NPF
-			NPFFindStationOrTileData fstd;
-			NPFFoundTargetData ftd;
-			Vehicle *last = v->Last();
-
-			NPFFillWithOrderData(&fstd, v);
-
-			Trackdir trackdir = v->GetVehicleTrackdir();
-			Trackdir trackdir_rev = ReverseTrackdir(last->GetVehicleTrackdir());
-			assert(trackdir != INVALID_TRACKDIR);
-			assert(trackdir_rev != INVALID_TRACKDIR);
-
-			ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->compatible_railtypes);
-			/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
-			return ftd.best_bird_dist != 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
-		} break;
-
-		default:
-			NOT_REACHED();
+		case VPF_NPF: return NPFTrainCheckReverse(v);
+		case VPF_YAPF: return YapfTrainCheckReverse(v);
+
+		default: NOT_REACHED();
 	}
 }
 
@@ -4313,7 +4190,7 @@
 		return;
 	}
 
-	TrainFindDepotData tfdd = FindClosestTrainDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
+	FindDepotData tfdd = FindClosestTrainDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
 	/* Only go to the depot if it is not too far out of our way. */
 	if (tfdd.best_length == UINT_MAX || tfdd.best_length > MAX_ACCEPTABLE_DEPOT_DIST) {
 		if (v->current_order.IsType(OT_GOTO_DEPOT)) {