diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index 349c75264a..50fba32ae2 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -11,6 +11,7 @@ #include "yapf.hpp" #include "yapf_node_road.hpp" #include "../../roadstop_base.h" +#include "../../vehicle_func.h" #include "../../safeguards.h" @@ -23,6 +24,8 @@ */ const uint MAX_RV_PF_TILES = 1 << 11; +const int MAX_TARGETS = 4; + template class CYapfCostRoadT { @@ -68,6 +71,15 @@ protected: inline int OneTileCost(TileIndex tile, Trackdir trackdir) { int cost = 0; + + bool predictedOccupied = false; + for (int i = 0; i < MAX_TARGETS && Yapf().leaderTargets[i] != INVALID_TILE; ++i) { + if (Yapf().leaderTargets[i] != tile) continue; + cost += Yapf().PfGetSettings().road_curve_penalty; + predictedOccupied = true; + break; + } + /* set base cost */ if (IsDiagonalTrackdir(trackdir)) { cost += YAPF_TILE_LENGTH; @@ -91,10 +103,18 @@ protected: const RoadStop::Entry *entry = rs->GetEntry(dir); cost += entry->GetOccupied() * Yapf().PfGetSettings().road_stop_occupied_penalty / entry->GetLength(); } + + if (predictedOccupied) { + cost += Yapf().PfGetSettings().road_stop_occupied_penalty; + } } else { /* Increase cost for filled road stops */ cost += Yapf().PfGetSettings().road_stop_bay_occupied_penalty * (!rs->IsFreeBay(0) + !rs->IsFreeBay(1)) / 2; + if (predictedOccupied) { + cost += Yapf().PfGetSettings().road_stop_bay_occupied_penalty; + } } + break; } @@ -326,7 +346,31 @@ public: } }; +struct FindVehiclesOnTileProcData { + const Vehicle *originVehicle; + TileIndex (*targets)[MAX_TARGETS]; +}; +static Vehicle * FindVehiclesOnTileProc(Vehicle *v, void *_data) +{ + FindVehiclesOnTileProcData *data = (FindVehiclesOnTileProcData*)(_data); + + if (data->originVehicle == v) + return nullptr; + + TileIndex ti = v->tile + TileOffsByDir(v->direction); + + for (int i = 0; i < MAX_TARGETS; i++) { + if ((*data->targets)[i] == INVALID_TILE) { + (*data->targets)[i] = ti; + break; + } + if ((*data->targets)[i] == ti) + return nullptr; + } + + return nullptr; +} template class CYapfFollowRoadT @@ -391,6 +435,14 @@ public: /* set origin and destination nodes */ Yapf().SetOrigin(src_tile, src_trackdirs); Yapf().SetDestination(v); + + for (int i = 0; i < MAX_TARGETS; ++i) { + Yapf().leaderTargets[i] = INVALID_TILE; + } + FindVehiclesOnTileProcData data; + data.originVehicle = v; + data.targets = &Yapf().leaderTargets; + FindVehicleOnPos(tile, &data, &FindVehiclesOnTileProc); /* find the best path */ path_found = Yapf().FindPath(v); @@ -537,11 +589,16 @@ struct CYapfRoad_TypesT typedef CYapfCostRoadT PfCost; }; -struct CYapfRoad1 : CYapfT > {}; -struct CYapfRoad2 : CYapfT > {}; +template +struct CYapfRoadCommon : CYapfT { + TileIndex leaderTargets[MAX_TARGETS]; ///< the tiles targeted by vehicles in front of the current vehicle +}; -struct CYapfRoadAnyDepot1 : CYapfT > {}; -struct CYapfRoadAnyDepot2 : CYapfT > {}; +struct CYapfRoad1 : CYapfRoadCommon > {}; +struct CYapfRoad2 : CYapfRoadCommon > {}; + +struct CYapfRoadAnyDepot1 : CYapfRoadCommon > {}; +struct CYapfRoadAnyDepot2 : CYapfRoadCommon > {}; Trackdir YapfRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirs, bool &path_found, RoadVehPathCache &path_cache)