Files
openttd/src/pathfinder/yapf/yapf_destrail.hpp
Jonathan G Rennison b7ddd486cf Merge branch 'master' into jgrpp
# Conflicts:
#	cmake/CompileFlags.cmake
#	src/aircraft_cmd.cpp
#	src/blitter/32bpp_anim.cpp
#	src/cargopacket.cpp
#	src/cheat_gui.cpp
#	src/company_cmd.cpp
#	src/company_gui.cpp
#	src/core/pool_func.hpp
#	src/date.cpp
#	src/economy.cpp
#	src/error_gui.cpp
#	src/ground_vehicle.cpp
#	src/ground_vehicle.hpp
#	src/group_gui.cpp
#	src/industry_cmd.cpp
#	src/lang/dutch.txt
#	src/lang/french.txt
#	src/lang/german.txt
#	src/linkgraph/linkgraph_gui.cpp
#	src/linkgraph/mcf.cpp
#	src/network/network_content.cpp
#	src/network/network_server.cpp
#	src/network/network_udp.cpp
#	src/newgrf_engine.cpp
#	src/newgrf_station.cpp
#	src/order_cmd.cpp
#	src/order_gui.cpp
#	src/pathfinder/follow_track.hpp
#	src/pathfinder/yapf/yapf_common.hpp
#	src/saveload/saveload.cpp
#	src/settings_gui.cpp
#	src/station_cmd.cpp
#	src/station_kdtree.h
#	src/string_func.h
#	src/table/settings.ini
#	src/tgp.cpp
#	src/timetable_cmd.cpp
#	src/timetable_gui.cpp
#	src/toolbar_gui.cpp
#	src/town_cmd.cpp
#	src/train_cmd.cpp
#	src/train_gui.cpp
#	src/tree_gui.cpp
#	src/tunnelbridge_cmd.cpp
#	src/vehicle.cpp
#	src/vehicle_gui.cpp
#	src/video/sdl2_v.cpp
#	src/video/sdl_v.cpp
#	src/video/win32_v.cpp
#	src/viewport.cpp
#	src/viewport_sprite_sorter_sse4.cpp
#	src/window.cpp
2021-02-01 17:07:34 +00:00

233 lines
7.6 KiB
C++

/*
* 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 yapf_destrail.hpp Determining the destination for rail vehicles. */
#ifndef YAPF_DESTRAIL_HPP
#define YAPF_DESTRAIL_HPP
class CYapfDestinationRailBase {
protected:
RailTypes m_compatible_railtypes;
public:
void SetDestination(const Train *v, bool override_rail_type = false)
{
m_compatible_railtypes = v->compatible_railtypes;
if (override_rail_type) m_compatible_railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
}
bool IsCompatibleRailType(RailType rt)
{
return HasBit(m_compatible_railtypes, rt);
}
RailTypes GetCompatibleRailTypes() const
{
return m_compatible_railtypes;
}
};
template <class Types>
class CYapfDestinationAnyDepotRailT : public CYapfDestinationRailBase {
public:
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
typedef typename Node::Key Key; ///< key to hash tables
/** to access inherited path finder */
Tpf& Yapf()
{
return *static_cast<Tpf *>(this);
}
/** Called by YAPF to detect if node ends in the desired destination */
inline bool PfDetectDestination(Node &n)
{
return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir());
}
/** Called by YAPF to detect if node ends in the desired destination */
inline bool PfDetectDestination(TileIndex tile, Trackdir td)
{
bool bDest = IsRailDepotTile(tile);
return bDest;
}
/**
* 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
*/
inline bool PfCalcEstimate(Node &n)
{
n.m_estimate = n.m_cost;
return true;
}
inline int TeleportCost(TileIndex cur_tile, TileIndex prev_tile)
{
return 0;
}
};
template <class Types>
class CYapfDestinationAnySafeTileRailT : public CYapfDestinationRailBase {
public:
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
typedef typename Node::Key Key; ///< key to hash tables
typedef typename Types::TrackFollower TrackFollower; ///< TrackFollower. Need to typedef for gcc 2.95
/** to access inherited path finder */
Tpf& Yapf()
{
return *static_cast<Tpf *>(this);
}
/** Called by YAPF to detect if node ends in the desired destination */
inline bool PfDetectDestination(Node &n)
{
return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir());
}
/** Called by YAPF to detect if node ends in the desired destination */
inline bool PfDetectDestination(TileIndex tile, Trackdir td)
{
return IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) &&
IsWaitingPositionFree(Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns());
}
/**
* 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.
*/
inline bool PfCalcEstimate(Node &n)
{
n.m_estimate = n.m_cost;
return true;
}
inline int TeleportCost(TileIndex cur_tile, TileIndex prev_tile)
{
return 0;
}
};
template <class Types>
class CYapfDestinationTileOrStationRailT : public CYapfDestinationRailBase {
public:
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
typedef typename Node::Key Key; ///< key to hash tables
protected:
TileIndex m_destTile;
TrackdirBits m_destTrackdirs;
StationID m_dest_station_id;
/** to access inherited path finder */
Tpf& Yapf()
{
return *static_cast<Tpf *>(this);
}
public:
void SetDestination(const Train *v)
{
switch (v->current_order.GetType()) {
case OT_GOTO_WAYPOINT:
if (!Waypoint::Get(v->current_order.GetDestination())->IsSingleTile()) {
/* In case of 'complex' waypoints we need to do a look
* ahead. This look ahead messes a bit about, which
* means that it 'corrupts' the cache. To prevent this
* we disable caching when we're looking for a complex
* waypoint. */
Yapf().DisableCache(true);
}
FALLTHROUGH;
case OT_GOTO_STATION:
m_destTile = CalcClosestStationTile(v->current_order.GetDestination(), v->tile, v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT);
m_dest_station_id = v->current_order.GetDestination();
m_destTrackdirs = INVALID_TRACKDIR_BIT;
break;
default:
m_destTile = v->dest_tile;
m_dest_station_id = INVALID_STATION;
m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0));
break;
}
CYapfDestinationRailBase::SetDestination(v);
}
/** Called by YAPF to detect if node ends in the desired destination */
inline bool PfDetectDestination(Node &n)
{
return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir());
}
/** Called by YAPF to detect if node ends in the desired destination */
inline bool PfDetectDestination(TileIndex tile, Trackdir td)
{
if (m_dest_station_id != INVALID_STATION) {
return HasStationTileRail(tile)
&& (GetStationIndex(tile) == m_dest_station_id)
&& (GetRailStationTrack(tile) == TrackdirToTrack(td));
}
return (tile == m_destTile) && HasTrackdir(m_destTrackdirs, td);
}
/**
* 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
*/
inline 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.GetLastTile();
DiagDirection exitdir = TrackdirToExitdir(n.GetLastTrackdir());
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 = std::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;
}
inline int TeleportCost(TileIndex cur_tile, TileIndex prev_tile)
{
auto calculate_distance_cost = [&](TileIndex t, int d_adjust) -> int {
int x1 = 2 * TileX(t);
int y1 = 2 * TileY(t);
int x2 = 2 * TileX(m_destTile);
int y2 = 2 * TileY(m_destTile);
int dx = abs(x1 - x2) + d_adjust;
int dy = abs(y1 - y2);
int dmin = std::min(dx, dy) + d_adjust; // up to 2x track exit dir tile offsets in opposite directions
int dxy = abs(dx - dy) + d_adjust; // "
return dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
};
return std::max<int>(0, calculate_distance_cost(prev_tile, 8) - calculate_distance_cost(cur_tile, 0));
}
};
#endif /* YAPF_DESTRAIL_HPP */