diff options
-rw-r--r-- | src/pathfinder/npf/npf.cpp | 36 | ||||
-rw-r--r-- | src/pathfinder/npf/npf.h | 10 | ||||
-rw-r--r-- | src/pathfinder/yapf/yapf_road.cpp | 33 |
3 files changed, 52 insertions, 27 deletions
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index d444d779b..9e6d0c2f3 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -21,6 +21,7 @@ #include "../../roadveh.h" #include "../../ship.h" #include "../../train.h" +#include "../../roadstop_base.h" #include "../pathfinder_func.h" #include "../pathfinder_type.h" #include "npf.h" @@ -104,8 +105,8 @@ static int32 NPFCalcStationOrTileHeuristic(AyStar *as, AyStarNode *current, Open uint dist; /* for train-stations, we are going to aim for the closest station tile */ - if (as->user_data[NPF_TYPE] == TRANSPORT_RAIL && fstd->station_index != INVALID_STATION) - to = CalcClosestStationTile(fstd->station_index, from, STATION_RAIL); + if (as->user_data[NPF_TYPE] != TRANSPORT_WATER && fstd->station_index != INVALID_STATION) + to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type); if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) { /* Since roads only have diagonal pieces, we use manhattan distance here */ @@ -279,11 +280,13 @@ static int32 NPFRoadPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty; break; - case MP_STATION: + case MP_STATION: { cost = NPF_TILE_LENGTH; /* Increase the cost for drive-through road stops */ if (IsDriveThroughStopTile(tile)) cost += _settings_game.pf.npf.npf_road_drive_through_penalty; - break; + RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile)); + cost += 8 * NPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1))); + } break; default: break; @@ -447,16 +450,14 @@ static int32 NPFFindStationOrTile(AyStar *as, OpenListNode *current) AyStarNode *node = ¤t->path.node; TileIndex tile = node->tile; - /* If GetNeighbours said we could get here, we assume the station type - * is correct */ - if ( - (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) || // We've found the tile, or - (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) // the station - ) { - return AYSTAR_FOUND_END_NODE; - } else { - return AYSTAR_DONE; + if (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) return AYSTAR_FOUND_END_NODE; + + if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) { + if (fstd->station_type == STATION_RAIL) return AYSTAR_FOUND_END_NODE; + /* Only if it is a valid station *and* we can stop there */ + if (GetStationType(tile) == fstd->station_type && (fstd->not_articulated || IsDriveThroughStopTile(tile))) return AYSTAR_FOUND_END_NODE; } + return AYSTAR_DONE; } /** @@ -1086,10 +1087,13 @@ void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool * dest_tile, not just any stop of that station. * So only for train orders to stations we fill fstd->station_index, for all * others only dest_coords */ - if (v->type == VEH_TRAIN && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) { + if (v->type != VEH_SHIP && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) { + assert(v->type == VEH_TRAIN || v->type == VEH_ROAD); fstd->station_index = v->current_order.GetDestination(); - /* Let's take the closest tile of the station as our target for trains */ - fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, STATION_RAIL); + fstd->station_type = (v->type == VEH_TRAIN) ? STATION_RAIL : (RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK); + fstd->not_articulated = v->type == VEH_ROAD && !RoadVehicle::From(v)->HasArticulatedPart(); + /* Let's take the closest tile of the station as our target for vehicles */ + fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, fstd->station_type); } else { fstd->dest_coords = v->dest_tile; fstd->station_index = INVALID_STATION; diff --git a/src/pathfinder/npf/npf.h b/src/pathfinder/npf/npf.h index 61a4409a1..bdffa164a 100644 --- a/src/pathfinder/npf/npf.h +++ b/src/pathfinder/npf/npf.h @@ -33,10 +33,12 @@ enum { /* Meant to be stored in AyStar.targetdata */ struct NPFFindStationOrTileData { - TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile - StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile - bool reserve_path; ///< Indicates whether the found path should be reserved - const Vehicle *v; ///< The vehicle we are pathfinding for + TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile + StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile + bool reserve_path; ///< Indicates whether the found path should be reserved + StationType station_type; ///< The type of station we're heading for + bool not_articulated; ///< The (road) vehicle is not articulated + const Vehicle *v; ///< The vehicle we are pathfinding for }; /* Indices into AyStar.userdata[] */ diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index af4413111..5ca3b1441 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -66,11 +66,11 @@ protected: } break; - case MP_STATION: - if (IsDriveThroughStopTile(tile)) { - cost += Yapf().PfGetSettings().road_stop_penalty; - } - break; + case MP_STATION: { + if (IsDriveThroughStopTile(tile)) cost += Yapf().PfGetSettings().road_stop_penalty; + RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile)); + cost += 8 * YAPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1))); + } break; default: break; @@ -268,12 +268,24 @@ public: protected: TileIndex m_destTile; TrackdirBits m_destTrackdirs; + StationID m_dest_station; + bool m_bus; + bool m_non_artic; public: void SetDestination(const RoadVehicle *v) { - m_destTile = v->dest_tile; - m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes)); + if (v->current_order.IsType(OT_GOTO_STATION)) { + m_dest_station = v->current_order.GetDestination(); + m_bus = v->IsBus(); + m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_bus ? STATION_BUS : STATION_TRUCK); + m_non_artic = !v->HasArticulatedPart(); + m_destTrackdirs = INVALID_TRACKDIR_BIT; + } else { + m_dest_station = INVALID_STATION; + m_destTile = v->dest_tile; + m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes)); + } } protected: @@ -292,6 +304,13 @@ public: FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir) { + if (m_dest_station != INVALID_STATION) { + return IsTileType(tile, MP_STATION) && + GetStationIndex(tile) == m_dest_station && + (m_bus ? IsBusStop(tile) : IsTruckStop(tile)) && + (m_non_artic || IsDriveThroughStopTile(tile)); + } + return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE); } |