2006-05-27 16:12:16 +00:00
|
|
|
/* $Id$ */
|
|
|
|
|
2009-08-21 20:21:05 +00:00
|
|
|
/*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2008-05-06 15:11:33 +00:00
|
|
|
/** @file yapf_common.hpp Commonly used classes for YAPF. */
|
2007-02-23 08:37:33 +00:00
|
|
|
|
2006-05-27 16:12:16 +00:00
|
|
|
#ifndef YAPF_COMMON_HPP
|
|
|
|
#define YAPF_COMMON_HPP
|
|
|
|
|
2006-05-29 18:39:42 +00:00
|
|
|
/** YAPF origin provider base class - used when origin is one tile / multiple trackdirs */
|
2006-05-27 16:12:16 +00:00
|
|
|
template <class Types>
|
|
|
|
class CYapfOriginTileT
|
|
|
|
{
|
|
|
|
public:
|
2006-05-29 18:39:42 +00:00
|
|
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
2006-05-27 16:12:16 +00:00
|
|
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
2006-05-29 18:39:42 +00:00
|
|
|
typedef typename Node::Key Key; ///< key to hash tables
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
protected:
|
2006-05-29 18:39:42 +00:00
|
|
|
TileIndex m_orgTile; ///< origin tile
|
|
|
|
TrackdirBits m_orgTrackdirs; ///< origin trackdir mask
|
2006-05-27 16:12:16 +00:00
|
|
|
|
2009-03-15 00:32:18 +00:00
|
|
|
/** to access inherited path finder */
|
2009-03-04 08:02:16 +00:00
|
|
|
FORCEINLINE Tpf& Yapf()
|
|
|
|
{
|
|
|
|
return *static_cast<Tpf*>(this);
|
|
|
|
}
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-15 00:32:18 +00:00
|
|
|
/** Set origin tile / trackdir mask */
|
2006-05-27 16:12:16 +00:00
|
|
|
void SetOrigin(TileIndex tile, TrackdirBits trackdirs)
|
|
|
|
{
|
|
|
|
m_orgTile = tile;
|
|
|
|
m_orgTrackdirs = trackdirs;
|
|
|
|
}
|
|
|
|
|
2009-03-15 00:32:18 +00:00
|
|
|
/** Called when YAPF needs to place origin nodes into open list */
|
2006-05-27 16:12:16 +00:00
|
|
|
void PfSetStartupNodes()
|
|
|
|
{
|
2007-11-04 23:06:39 +00:00
|
|
|
bool is_choice = (KillFirstBit(m_orgTrackdirs) != TRACKDIR_BIT_NONE);
|
|
|
|
for (TrackdirBits tdb = m_orgTrackdirs; tdb != TRACKDIR_BIT_NONE; tdb = KillFirstBit(tdb)) {
|
2006-05-27 16:12:16 +00:00
|
|
|
Trackdir td = (Trackdir)FindFirstBit2x64(tdb);
|
|
|
|
Node& n1 = Yapf().CreateNewNode();
|
2006-06-07 21:16:43 +00:00
|
|
|
n1.Set(NULL, m_orgTile, td, is_choice);
|
2006-05-27 16:12:16 +00:00
|
|
|
Yapf().AddStartupNode(n1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2006-05-29 18:39:42 +00:00
|
|
|
/** YAPF origin provider base class - used when there are two tile/trackdir origins */
|
2006-05-27 16:12:16 +00:00
|
|
|
template <class Types>
|
|
|
|
class CYapfOriginTileTwoWayT
|
|
|
|
{
|
|
|
|
public:
|
2006-05-29 18:39:42 +00:00
|
|
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
2006-05-27 16:12:16 +00:00
|
|
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
2006-05-29 18:39:42 +00:00
|
|
|
typedef typename Node::Key Key; ///< key to hash tables
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
protected:
|
2006-05-29 18:39:42 +00:00
|
|
|
TileIndex m_orgTile; ///< first origin tile
|
|
|
|
Trackdir m_orgTd; ///< first origin trackdir
|
|
|
|
TileIndex m_revTile; ///< second (reversed) origin tile
|
|
|
|
Trackdir m_revTd; ///< second (reversed) origin trackdir
|
|
|
|
int m_reverse_penalty; ///< penalty to be added for using the reversed origin
|
|
|
|
bool m_treat_first_red_two_way_signal_as_eol; ///< in some cases (leaving station) we need to handle first two-way signal differently
|
|
|
|
|
2009-03-15 00:32:18 +00:00
|
|
|
/** to access inherited path finder */
|
2009-03-04 08:02:16 +00:00
|
|
|
FORCEINLINE Tpf& Yapf()
|
|
|
|
{
|
|
|
|
return *static_cast<Tpf*>(this);
|
|
|
|
}
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-15 00:32:18 +00:00
|
|
|
/** set origin (tiles, trackdirs, etc.) */
|
2006-05-27 16:12:16 +00:00
|
|
|
void SetOrigin(TileIndex tile, Trackdir td, TileIndex tiler = INVALID_TILE, Trackdir tdr = INVALID_TRACKDIR, int reverse_penalty = 0, bool treat_first_red_two_way_signal_as_eol = true)
|
|
|
|
{
|
|
|
|
m_orgTile = tile;
|
|
|
|
m_orgTd = td;
|
|
|
|
m_revTile = tiler;
|
|
|
|
m_revTd = tdr;
|
|
|
|
m_reverse_penalty = reverse_penalty;
|
|
|
|
m_treat_first_red_two_way_signal_as_eol = treat_first_red_two_way_signal_as_eol;
|
|
|
|
}
|
|
|
|
|
2009-03-15 00:32:18 +00:00
|
|
|
/** Called when YAPF needs to place origin nodes into open list */
|
2006-05-27 16:12:16 +00:00
|
|
|
void PfSetStartupNodes()
|
|
|
|
{
|
|
|
|
if (m_orgTile != INVALID_TILE && m_orgTd != INVALID_TRACKDIR) {
|
|
|
|
Node& n1 = Yapf().CreateNewNode();
|
2006-06-07 21:16:43 +00:00
|
|
|
n1.Set(NULL, m_orgTile, m_orgTd, false);
|
2006-05-27 16:12:16 +00:00
|
|
|
Yapf().AddStartupNode(n1);
|
|
|
|
}
|
|
|
|
if (m_revTile != INVALID_TILE && m_revTd != INVALID_TRACKDIR) {
|
|
|
|
Node& n2 = Yapf().CreateNewNode();
|
2006-06-07 21:16:43 +00:00
|
|
|
n2.Set(NULL, m_revTile, m_revTd, false);
|
2006-05-27 16:12:16 +00:00
|
|
|
n2.m_cost = m_reverse_penalty;
|
|
|
|
Yapf().AddStartupNode(n2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-15 00:32:18 +00:00
|
|
|
/** return true if first two-way signal should be treated as dead end */
|
2006-05-27 16:12:16 +00:00
|
|
|
FORCEINLINE bool TreatFirstRedTwoWaySignalAsEOL()
|
|
|
|
{
|
|
|
|
return Yapf().PfGetSettings().rail_firstred_twoway_eol && m_treat_first_red_two_way_signal_as_eol;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2006-05-29 18:39:42 +00:00
|
|
|
/** YAPF destination provider base class - used when destination is single tile / multiple trackdirs */
|
2006-05-27 16:12:16 +00:00
|
|
|
template <class Types>
|
|
|
|
class CYapfDestinationTileT
|
|
|
|
{
|
|
|
|
public:
|
2006-05-29 18:39:42 +00:00
|
|
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
2006-05-27 16:12:16 +00:00
|
|
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
2006-05-29 18:39:42 +00:00
|
|
|
typedef typename Node::Key Key; ///< key to hash tables
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
protected:
|
2006-05-29 18:39:42 +00:00
|
|
|
TileIndex m_destTile; ///< destination tile
|
|
|
|
TrackdirBits m_destTrackdirs; ///< destination trackdir mask
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-15 00:32:18 +00:00
|
|
|
/** set the destination tile / more trackdirs */
|
2006-05-27 16:12:16 +00:00
|
|
|
void SetDestination(TileIndex tile, TrackdirBits trackdirs)
|
|
|
|
{
|
|
|
|
m_destTile = tile;
|
|
|
|
m_destTrackdirs = trackdirs;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2009-03-15 00:32:18 +00:00
|
|
|
/** to access inherited path finder */
|
2009-03-04 08:02:16 +00:00
|
|
|
Tpf& Yapf()
|
|
|
|
{
|
|
|
|
return *static_cast<Tpf*>(this);
|
|
|
|
}
|
2006-05-27 16:12:16 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-15 00:32:18 +00:00
|
|
|
/** Called by YAPF to detect if node ends in the desired destination */
|
2006-05-27 16:12:16 +00:00
|
|
|
FORCEINLINE bool PfDetectDestination(Node& n)
|
|
|
|
{
|
|
|
|
bool bDest = (n.m_key.m_tile == m_destTile) && ((m_destTrackdirs & TrackdirToTrackdirBits(n.GetTrackdir())) != TRACKDIR_BIT_NONE);
|
|
|
|
return bDest;
|
|
|
|
}
|
|
|
|
|
2010-08-01 19:22:34 +00:00
|
|
|
/**
|
|
|
|
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
2010-08-01 19:44:49 +00:00
|
|
|
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate
|
|
|
|
*/
|
2006-05-27 16:12:16 +00:00
|
|
|
inline bool PfCalcEstimate(Node& n)
|
|
|
|
{
|
2009-09-20 23:11:01 +00:00
|
|
|
static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
|
|
|
|
static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
|
2007-07-15 11:45:38 +00:00
|
|
|
if (PfDetectDestination(n)) {
|
|
|
|
n.m_estimate = n.m_cost;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TileIndex tile = n.GetTile();
|
|
|
|
DiagDirection exitdir = TrackdirToExitdir(n.GetTrackdir());
|
|
|
|
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);
|
2006-05-27 16:12:16 +00:00
|
|
|
int dxy = abs(dx - dy);
|
2009-03-29 18:20:02 +00:00
|
|
|
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
2007-07-15 11:45:38 +00:00
|
|
|
n.m_estimate = n.m_cost + d;
|
|
|
|
assert(n.m_estimate >= n.m_parent->m_estimate);
|
2006-05-27 16:12:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-08-01 19:22:34 +00:00
|
|
|
/**
|
|
|
|
* YAPF template that uses Ttypes template argument to determine all YAPF
|
2006-09-04 20:40:33 +00:00
|
|
|
* components (base classes) from which the actual YAPF is composed.
|
|
|
|
* For example classes consult: CYapfRail_TypesT template and its instantiations:
|
2010-08-01 19:44:49 +00:00
|
|
|
* CYapfRail1, CYapfRail2, CYapfRail3, CYapfAnyDepotRail1, CYapfAnyDepotRail2, CYapfAnyDepotRail3
|
|
|
|
*/
|
2006-05-27 16:12:16 +00:00
|
|
|
template <class Ttypes>
|
|
|
|
class CYapfT
|
2006-05-29 18:39:42 +00:00
|
|
|
: public Ttypes::PfBase ///< Instance of CYapfBaseT - main YAPF loop and support base class
|
|
|
|
, public Ttypes::PfCost ///< Cost calculation provider base class
|
|
|
|
, public Ttypes::PfCache ///< Segment cost cache provider
|
|
|
|
, public Ttypes::PfOrigin ///< Origin (tile or two-tile origin)
|
|
|
|
, public Ttypes::PfDestination ///< Destination detector and distance (estimate) calculation provider
|
|
|
|
, public Ttypes::PfFollow ///< Node follower (stepping provider)
|
2006-05-27 16:12:16 +00:00
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* YAPF_COMMON_HPP */
|