diff --git a/config.lib b/config.lib index 2abf190c2d..c3ee998ecc 100644 --- a/config.lib +++ b/config.lib @@ -1301,7 +1301,8 @@ make_cflags_and_ldflags() { CFLAGS="$CFLAGS -DWITH_ICU" CFLAGS="$CFLAGS `$icu_config --cppflags | tr '\n\r' ' '`" - LIBS="$LIBS `$icu_config --ldflags-libsonly | tr '\n\r' ' '`" + # Some icu-configs have the 'feature' of not adding a space where others do add the space + LIBS="$LIBS `$icu_config --ldflags-searchpath` `$icu_config --ldflags-libsonly | tr '\n\r' ' '`" fi @@ -2296,9 +2297,9 @@ detect_icu() { log 2 " returned $version" log 2 " exit code $ret" - if [ -z "$version" ] || [ "$ret" != "0" ] || [ "$shortversion" -lt "20" ]; then - if [ -n "$shortversion" ] && [ "$shortversion" -lt "20" ]; then - log 1 "checking libicu... needs at least version 2.0.0, icu NOT enabled" + if [ -z "$version" ] || [ "$ret" != "0" ] || [ "$shortversion" -lt "22" ]; then + if [ -n "$shortversion" ] && [ "$shortversion" -lt "22" ]; then + log 1 "checking libicu... needs at least version 2.2.0, icu NOT enabled" else log 1 "checking libicu... not found" fi diff --git a/src/misc/blob.hpp b/src/misc/blob.hpp index 56e10a7cf7..d65d6e1369 100644 --- a/src/misc/blob.hpp +++ b/src/misc/blob.hpp @@ -297,6 +297,7 @@ public: /** all deallocations should happen here */ static FORCEINLINE void RawFree(CHdr *p) { + /* In case GCC warns about the following, see GCC's PR38509 why it is bogus. */ free(p); } /** fixing the four bytes at the end of blob data - useful when blob is used to hold string */ diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index a2ebf5abe8..504168837b 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -675,22 +675,8 @@ TileIndex RoadVehicle::GetOrderStationLocation(StationID station) { if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION; - TileIndex dest = INVALID_TILE; - const RoadStop *rs = GetStation(station)->GetPrimaryRoadStop(this); - if (rs != NULL) { - uint mindist = UINT_MAX; - - for (; rs != NULL; rs = rs->GetNextRoadStop(this)) { - uint dist = DistanceManhattan(this->tile, rs->xy); - - if (dist < mindist) { - mindist = dist; - dest = rs->xy; - } - } - } - - if (dest != INVALID_TILE) { + TileIndex dest; + if (YapfFindNearestRoadVehicleCompatibleStop(this, station, &dest)) { return dest; } else { /* There is no stop left at the station, so don't even TRY to go there */ diff --git a/src/unix.cpp b/src/unix.cpp index 29d8ad388a..f108276d24 100644 --- a/src/unix.cpp +++ b/src/unix.cpp @@ -133,11 +133,10 @@ static const char *GetLocalCode() #endif } -/** FYI: This is not thread-safe. - * convert between locales, which from and which to is set in the calling - * functions OTTD2FS() and FS2OTTD(). You should NOT use this function directly - * NOTE: iconv was added in OSX 10.3. 10.2.x will still have the invalid char - * issues. There aren't any easy fix for this */ +/** + * Convert between locales, which from and which to is set in the calling + * functions OTTD2FS() and FS2OTTD(). + */ static const char *convert_tofrom_fs(iconv_t convd, const char *name) { static char buf[1024]; @@ -145,7 +144,7 @@ static const char *convert_tofrom_fs(iconv_t convd, const char *name) * non-const. Correct implementation is at * http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html */ #ifdef HAVE_BROKEN_ICONV - char *inbuf = (char*)name; + char *inbuf = const_cast(name); #else const char *inbuf = name; #endif diff --git a/src/yapf/yapf.h b/src/yapf/yapf.h index 6d42b2b7e3..a7f75647b2 100644 --- a/src/yapf/yapf.h +++ b/src/yapf/yapf.h @@ -8,6 +8,7 @@ #include "../debug.h" #include "../depot_type.h" #include "../direction_type.h" +#include "../station_type.h" #include "../pbs.h" /** Finds the best path for given ship. @@ -46,6 +47,14 @@ Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection ent */ uint YapfRoadVehDistanceToTile(const Vehicle *v, TileIndex tile); +/** Used to determinine the closest reachable compatible road stop for a given vehicle. + * @param v vehicle that needs to go to the road stop + * @param station the station the road stop must belong to + * @param stop_tile receives the stop tile if a stop was found + * @return true if stop was found. + */ +bool YapfFindNearestRoadVehicleCompatibleStop(const Vehicle *v, StationID station, TileIndex *stop_tile); + /** Used when user sends RV to the nearest depot or if RV needs servicing. * Returns the nearest depot (or NULL if depot was not found). */ diff --git a/src/yapf/yapf_road.cpp b/src/yapf/yapf_road.cpp index fbb7c6fa3c..1e5ba5ef20 100644 --- a/src/yapf/yapf_road.cpp +++ b/src/yapf/yapf_road.cpp @@ -4,6 +4,10 @@ #include "../stdafx.h" #include "../depot_base.h" +#include "../station_base.h" +#include "../roadveh.h" +#include "../cargotype.h" +#include "../newgrf_cargo.h" #include "yapf.hpp" #include "yapf_node_road.hpp" @@ -177,6 +181,78 @@ public: }; +template +class CYapfDestinationAnyRoadVehicleCompatibleStopOfGivenStationT +{ +public: + typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) + typedef typename Types::TrackFollower TrackFollower; + typedef typename Types::NodeList::Titem Node; ///< this will be our node type + typedef typename Node::Key Key; ///< key to hash tables + + TileIndex m_destTile; + StationID m_dest_station; + bool m_bus; + bool m_non_artic; + + /** to access inherited path finder */ + Tpf& Yapf() + { + return *static_cast(this); + } + + void SetDestination(const Vehicle *v, StationID sid, TileIndex destTile) + { + m_dest_station = sid; + m_destTile = destTile; + m_bus = IsCargoInClass(v->cargo_type, CC_PASSENGERS); + m_non_artic = !RoadVehHasArticPart(v); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(Node& n) + { + return PfDetectDestinationTile(n.m_segment_last_tile, INVALID_TRACKDIR); + } + + FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir) + { + return + IsTileType(tile, MP_STATION) && + GetStationIndex(tile) == m_dest_station && + (m_bus ? IsBusStop(tile) : IsTruckStop(tile)) && + (m_non_artic || IsDriveThroughStopTile(tile)); + } + + /** Called by YAPF to calculate cost estimate. Calculates distance to the destination + * adds it to the actual cost from origin and stores the sum to the Node::m_estimate */ + FORCEINLINE bool PfCalcEstimate(Node& n) + { + static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0}; + static const int dg_dir_to_y_offs[] = {0, 1, 0, -1}; + if (PfDetectDestination(n)) { + n.m_estimate = n.m_cost; + return true; + } + + TileIndex tile = n.m_segment_last_tile; + DiagDirection exitdir = TrackdirToExitdir(n.m_segment_last_td); + int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir]; + int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir]; + int x2 = 2 * TileX(m_destTile); + int y2 = 2 * TileY(m_destTile); + int dx = abs(x1 - x2); + int dy = abs(y1 - y2); + int dmin = min(dx, dy); + int dxy = abs(dx - dy); + int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2); + n.m_estimate = n.m_cost + d; + assert(n.m_estimate >= n.m_parent->m_estimate); + return true; + } +}; + + template class CYapfDestinationTileRoadT { @@ -405,6 +481,30 @@ public: Depot *ret = GetDepotByTile(depot_tile); return ret; } + + static bool stFindNearestRoadVehicleCompatibleStop(const Vehicle *v, TileIndex tile, TileIndex destTile, Trackdir td, StationID sid, TileIndex *stop_tile) + { + Tpf pf; + return pf.FindNearestRoadVehicleCompatibleStop(v, tile, destTile, td, sid, stop_tile); + } + + FORCEINLINE bool FindNearestRoadVehicleCompatibleStop(const Vehicle *v, TileIndex tile, TileIndex destTile, Trackdir td, StationID sid, TileIndex *stop_tile) + { + /* set origin and destination nodes */ + Yapf().SetOrigin(tile, TrackdirToTrackdirBits(td)); + Yapf().SetDestination(v, sid, destTile); + + /* find the best path */ + bool bFound = Yapf().FindPath(v); + if (!bFound) return false; + + /* some path found + * get found depot tile */ + const Node *n = Yapf().GetBestNode(); + + *stop_tile = n->m_segment_last_tile; + return true; + } }; template class Tdestination> @@ -429,6 +529,9 @@ struct CYapfRoad2 : CYapfT > {}; struct CYapfRoadAnyDepot2 : CYapfT > {}; +struct CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation1 : CYapfT > {}; +struct CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation2 : CYapfT > {}; + Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir) { @@ -492,3 +595,29 @@ Depot *YapfFindNearestRoadDepot(const Vehicle *v) Depot *ret = pfnFindNearestDepot(v, tile, trackdir); return ret; } + +bool YapfFindNearestRoadVehicleCompatibleStop(const Vehicle *v, StationID station, TileIndex *stop_tile) +{ + *stop_tile = INVALID_TILE; + + const RoadStop *rs = GetStation(station)->GetPrimaryRoadStop(v); + if (rs == NULL) return false; + + TileIndex tile = v->tile; + Trackdir trackdir = GetVehicleTrackdir(v); + if ((TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes)) & TrackdirToTrackdirBits(trackdir)) == 0) { + return false; + } + + /* default is YAPF type 2 */ + typedef bool (*PfnFindNearestRoadVehicleCompatibleStop)(const Vehicle*, TileIndex, TileIndex, Trackdir, StationID, TileIndex*); + PfnFindNearestRoadVehicleCompatibleStop pfnFindNearestRoadVehicleCompatibleStop = &CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation2::stFindNearestRoadVehicleCompatibleStop; + + /* check if non-default YAPF type should be used */ + if (_settings_game.pf.yapf.disable_node_optimization) { + pfnFindNearestRoadVehicleCompatibleStop = &CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation1::stFindNearestRoadVehicleCompatibleStop; // Trackdir, allow 90-deg + } + + bool ret = pfnFindNearestRoadVehicleCompatibleStop(v, tile, rs->xy, trackdir, station, stop_tile); + return ret; +}