summaryrefslogtreecommitdiff
path: root/src/pathfinder
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-12-02 09:57:17 +0000
committerrubidium <rubidium@openttd.org>2009-12-02 09:57:17 +0000
commit9165c195b9609bb9db77cc23ff424802eb4ab128 (patch)
tree1a8b2370e076ace6dd5b6087e94d37bf3a5e2f78 /src/pathfinder
parentef8cc49175ae8f97c6659c3acd13fdb4434cd535 (diff)
downloadopenttd-9165c195b9609bb9db77cc23ff424802eb4ab128.tar.xz
(svn r18371) -Codechange: unify calling of the train pathfinders
Diffstat (limited to 'src/pathfinder')
-rw-r--r--src/pathfinder/npf/npf.cpp120
-rw-r--r--src/pathfinder/npf/npf.h9
-rw-r--r--src/pathfinder/npf/npf_func.h45
-rw-r--r--src/pathfinder/pathfinder_type.h35
-rw-r--r--src/pathfinder/yapf/yapf.h44
-rw-r--r--src/pathfinder/yapf/yapf_rail.cpp22
6 files changed, 217 insertions, 58 deletions
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp
index 13410a0f5..f50106fb2 100644
--- 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 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir,
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 @@ Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
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);
+}
diff --git a/src/pathfinder/npf/npf.h b/src/pathfinder/npf/npf.h
index fcd75db4d..fb10c07ec 100644
--- a/src/pathfinder/npf/npf.h
+++ b/src/pathfinder/npf/npf.h
@@ -38,7 +38,8 @@ enum {
};
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 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir t
* 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);
diff --git a/src/pathfinder/npf/npf_func.h b/src/pathfinder/npf/npf_func.h
index ef3b1001c..027e8c794 100644
--- 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 */
diff --git a/src/pathfinder/pathfinder_type.h b/src/pathfinder/pathfinder_type.h
new file mode 100644
index 000000000..95daf533e
--- /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 */
diff --git a/src/pathfinder/yapf/yapf.h b/src/pathfinder/yapf/yapf.h
index 2f39cd6c5..bfb442a2a 100644
--- 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 @@ Track YapfChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
*/
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 @@ Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection ent
* @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 YapfFindNearestRoadVehicleCompatibleStop(const RoadVehicle *v, StationID st
*/
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);
+FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_distance);
-/** Returns true if it is better to reverse the train before leaving station */
-bool YapfCheckReverseTrain(const Vehicle *v);
+/**
+ * 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.
+ * 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 @@ extern int _aystar_stats_closed_size;
/** 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 */
diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp
index f17b90262..54ea1a916 100644
--- a/src/pathfinder/yapf/yapf_rail.cpp
+++ b/src/pathfinder/yapf/yapf_rail.cpp
@@ -524,7 +524,7 @@ struct CYapfAnySafeTileRail1 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail1, CF
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 YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection ent
}
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 @@ bool YapfCheckReverseTrain(const Vehicle *vt)
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 @@ bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reve
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;