mirror of https://github.com/OpenTTD/OpenTTD
(svn r18371) -Codechange: unify calling of the train pathfinders
parent
ef8cc49175
commit
9165c195b9
|
@ -21,6 +21,7 @@
|
||||||
#include "../../train.h"
|
#include "../../train.h"
|
||||||
#include "../../ship.h"
|
#include "../../ship.h"
|
||||||
#include "../pathfinder_func.h"
|
#include "../pathfinder_func.h"
|
||||||
|
#include "../pathfinder_type.h"
|
||||||
#include "npf.h"
|
#include "npf.h"
|
||||||
|
|
||||||
static AyStar _npf_aystar;
|
static AyStar _npf_aystar;
|
||||||
|
@ -1059,30 +1060,6 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir,
|
||||||
return best_result;
|
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()
|
void InitializeNPF()
|
||||||
{
|
{
|
||||||
static bool first_init = true;
|
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;
|
if (ftd.best_trackdir == 0xff) return INVALID_TRACK;
|
||||||
return TrackdirToTrack(ftd.best_trackdir);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
* 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
|
* without it. Be careful with not applying this penalty to often, or the
|
||||||
* total path cost might overflow..
|
* total path cost might overflow..
|
||||||
|
@ -119,12 +120,6 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir t
|
||||||
* of choices and accurate heuristics, such as water. */
|
* 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);
|
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);
|
void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool reserve_path = false);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
#ifndef NPF_FUNC_H
|
#ifndef NPF_FUNC_H
|
||||||
#define 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.
|
* Finds the best path for given ship using NPF.
|
||||||
* @param v the ship that needs to find a path
|
* @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);
|
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 */
|
#endif /* NPF_FUNC_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 */
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "../../direction_type.h"
|
#include "../../direction_type.h"
|
||||||
#include "../../station_type.h"
|
#include "../../station_type.h"
|
||||||
|
#include "../pathfinder_type.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the best path for given ship using YAPF.
|
* 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);
|
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 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 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 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 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 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
|
* @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.
|
/** 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)
|
* @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);
|
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 v train that needs to go to some depot
|
||||||
* @param max_distance max distance (number of track tiles) from the current train position
|
* @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
|
* (used also as optimization - the pathfinder can stop path finding if max_distance
|
||||||
* was reached and no depot was seen)
|
* was reached and no depot was seen)
|
||||||
* @param reverse_penalty penalty that should be added for the path that requires reversing the train first
|
* @return the data about the depot
|
||||||
* @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.
|
|
||||||
*/
|
*/
|
||||||
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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 v The train that needs to find a safe tile.
|
||||||
* @param tile Last tile of the current reserved path.
|
* @param tile Last tile of the current reserved path.
|
||||||
* @param td Last trackdir 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.
|
* @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 */
|
/** Use this function to notify YAPF that track layout (or signal configuration) has change */
|
||||||
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track);
|
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track);
|
||||||
|
@ -111,7 +115,17 @@ extern int _aystar_stats_closed_size;
|
||||||
/** Base tile length units */
|
/** Base tile length units */
|
||||||
enum {
|
enum {
|
||||||
YAPF_TILE_LENGTH = 100,
|
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 */
|
#endif /* YAPF_H */
|
||||||
|
|
|
@ -524,7 +524,7 @@ struct CYapfAnySafeTileRail1 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail1, CF
|
||||||
struct CYapfAnySafeTileRail2 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail2, CFollowTrackFreeRailNo90, CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
|
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 */
|
/* default is YAPF type 2 */
|
||||||
typedef Trackdir (*PfnChooseRailTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits, bool*, bool, PBSTileInfo*);
|
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);
|
Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track, target);
|
||||||
|
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
|
||||||
return td_ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool YapfCheckReverseTrain(const Vehicle *vt)
|
bool YapfTrainCheckReverse(const Train *v)
|
||||||
{
|
{
|
||||||
const Train *v = Train::From(vt);
|
|
||||||
const Train *last_veh = v->Last();
|
const Train *last_veh = v->Last();
|
||||||
|
|
||||||
/* get trackdirs of both ends */
|
/* get trackdirs of both ends */
|
||||||
|
@ -600,12 +598,11 @@ bool YapfCheckReverseTrain(const Vehicle *vt)
|
||||||
return reverse;
|
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;
|
FindDepotData fdd;
|
||||||
*reversed = false;
|
|
||||||
|
|
||||||
const Vehicle *last_veh = v->Last();
|
const Train *last_veh = v->Last();
|
||||||
|
|
||||||
PBSTileInfo origin = FollowTrainReservation(Train::From(v));
|
PBSTileInfo origin = FollowTrainReservation(Train::From(v));
|
||||||
TileIndex last_tile = last_veh->tile;
|
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
|
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);
|
bool ret = pfnFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_distance, YAPF_INFINITE_PENALTY, &fdd.tile, &fdd.reverse);
|
||||||
return ret;
|
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);
|
typedef bool (*PfnFindNearestSafeTile)(const Vehicle*, TileIndex, Trackdir, bool);
|
||||||
PfnFindNearestSafeTile pfnFindNearestSafeTile = CYapfAnySafeTileRail1::stFindNearestSafeTile;
|
PfnFindNearestSafeTile pfnFindNearestSafeTile = CYapfAnySafeTileRail1::stFindNearestSafeTile;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "articulated_vehicles.h"
|
#include "articulated_vehicles.h"
|
||||||
#include "command_func.h"
|
#include "command_func.h"
|
||||||
#include "pathfinder/npf/npf.h"
|
#include "pathfinder/npf/npf_func.h"
|
||||||
#include "news_func.h"
|
#include "news_func.h"
|
||||||
#include "company_func.h"
|
#include "company_func.h"
|
||||||
#include "vehicle_gui.h"
|
#include "vehicle_gui.h"
|
||||||
|
@ -2138,77 +2138,28 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||||
return cost;
|
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
|
/** returns the tile of a depot to goto to. The given vehicle must not be
|
||||||
* crashed! */
|
* crashed! */
|
||||||
static TrainFindDepotData FindClosestTrainDepot(Train *v, int max_distance)
|
static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
|
||||||
{
|
{
|
||||||
assert(!(v->vehstatus & VS_CRASHED));
|
assert(!(v->vehstatus & VS_CRASHED));
|
||||||
|
|
||||||
TrainFindDepotData tfdd;
|
if (IsRailDepotTile(v->tile)) return FindDepotData(v->tile, 0);
|
||||||
tfdd.owner = v->owner;
|
|
||||||
tfdd.reverse = false;
|
|
||||||
|
|
||||||
if (IsRailDepotTile(v->tile)) {
|
|
||||||
tfdd.tile = v->tile;
|
|
||||||
tfdd.best_length = 0;
|
|
||||||
return tfdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
PBSTileInfo origin = FollowTrainReservation(v);
|
PBSTileInfo origin = FollowTrainReservation(v);
|
||||||
if (IsRailDepotTile(origin.tile)) {
|
if (IsRailDepotTile(origin.tile)) return FindDepotData(origin.tile, 0);
|
||||||
tfdd.tile = origin.tile;
|
|
||||||
tfdd.best_length = 0;
|
|
||||||
return tfdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
tfdd.best_length = UINT_MAX;
|
|
||||||
|
|
||||||
switch (_settings_game.pf.pathfinder_for_trains) {
|
switch (_settings_game.pf.pathfinder_for_trains) {
|
||||||
case VPF_YAPF: { // YAPF
|
case VPF_NPF: return NPFTrainFindNearestDepot(v, max_distance);
|
||||||
bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
|
case VPF_YAPF: return YapfTrainFindNearestDepot(v, max_distance);
|
||||||
tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case VPF_NPF: { // NPF
|
default: NOT_REACHED();
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
return tfdd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
|
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 (tfdd.best_length == UINT_MAX) return false;
|
||||||
|
|
||||||
if (location != NULL) *location = tfdd.tile;
|
if (location != NULL) *location = tfdd.tile;
|
||||||
|
@ -2556,71 +2507,14 @@ static const byte _initial_tile_subcoord[6][4][3] = {
|
||||||
* @param dest [out] State and destination of the requested path
|
* @param dest [out] State and destination of the requested path
|
||||||
* @return The best track the train should follow
|
* @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) {
|
switch (_settings_game.pf.pathfinder_for_trains) {
|
||||||
case VPF_YAPF: { // YAPF
|
case VPF_NPF: return NPFTrainChooseTrack(v, tile, enterdir, tracks, path_not_found, do_track_reservation, dest);
|
||||||
Trackdir trackdir = YapfChooseRailTrack(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);
|
||||||
if (trackdir != INVALID_TRACKDIR) {
|
|
||||||
best_track = TrackdirToTrack(trackdir);
|
default: NOT_REACHED();
|
||||||
} 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PF_BENCHMARK
|
|
||||||
TOC("PF time = ", 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return best_track;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2717,15 +2611,16 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
||||||
* @param v The vehicle.
|
* @param v The vehicle.
|
||||||
* @param tile The tile the search should start from.
|
* @param tile The tile the search should start from.
|
||||||
* @param td The trackdir 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.
|
* @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)
|
static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_tailtype)
|
||||||
{
|
{
|
||||||
if (_settings_game.pf.pathfinder_for_trains == VPF_YAPF) {
|
switch (_settings_game.pf.pathfinder_for_trains) {
|
||||||
return YapfRailFindNearestSafeTile(v, tile, td, override_tailtype);
|
case VPF_NPF: return NPFTrainFindNearestSafeTile(v, tile, td, override_tailtype);
|
||||||
} else {
|
case VPF_YAPF: return YapfTrainFindNearestSafeTile(v, tile, td, override_tailtype);
|
||||||
return NPFRouteToSafeTile(v, tile, td, override_tailtype).res_okay;
|
|
||||||
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3069,7 +2964,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool CheckReverseTrain(Train *v)
|
static bool CheckReverseTrain(const Train *v)
|
||||||
{
|
{
|
||||||
if (_settings_game.difficulty.line_reverse_mode != 0 ||
|
if (_settings_game.difficulty.line_reverse_mode != 0 ||
|
||||||
v->track == TRACK_BIT_DEPOT || v->track == TRACK_BIT_WORMHOLE ||
|
v->track == TRACK_BIT_DEPOT || v->track == TRACK_BIT_WORMHOLE ||
|
||||||
|
@ -3077,31 +2972,13 @@ static bool CheckReverseTrain(Train *v)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(v->track);
|
assert(v->track != TRACK_BIT_NONE);
|
||||||
|
|
||||||
switch (_settings_game.pf.pathfinder_for_trains) {
|
switch (_settings_game.pf.pathfinder_for_trains) {
|
||||||
case VPF_YAPF: // YAPF
|
case VPF_NPF: return NPFTrainCheckReverse(v);
|
||||||
return YapfCheckReverseTrain(v);
|
case VPF_YAPF: return YapfTrainCheckReverse(v);
|
||||||
|
|
||||||
case VPF_NPF: { // NPF
|
default: NOT_REACHED();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4313,7 +4190,7 @@ static void CheckIfTrainNeedsService(Train *v)
|
||||||
return;
|
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. */
|
/* 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 (tfdd.best_length == UINT_MAX || tfdd.best_length > MAX_ACCEPTABLE_DEPOT_DIST) {
|
||||||
if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
||||||
|
|
Loading…
Reference in New Issue