|
@@ -6,69 +6,69 @@
|
|
|
* 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_ship.cpp Implementation of YAPF for ships. */
|
|
|
|
|
|
#include "../../stdafx.h"
|
|
|
#include "../../ship.h"
|
|
|
|
|
|
#include "yapf.hpp"
|
|
|
#include "yapf_node_ship.hpp"
|
|
|
|
|
|
/** Node Follower module of YAPF for ships */
|
|
|
template <class Types>
|
|
|
class CYapfFollowShipT
|
|
|
{
|
|
|
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
|
|
|
|
|
|
protected:
|
|
|
/** to access inherited path finder */
|
|
|
FORCEINLINE Tpf& Yapf()
|
|
|
inline Tpf& Yapf()
|
|
|
{
|
|
|
return *static_cast<Tpf*>(this);
|
|
|
}
|
|
|
|
|
|
public:
|
|
|
/**
|
|
|
* Called by YAPF to move from the given node to the next tile. For each
|
|
|
* reachable trackdir on the new tile creates new node, initializes it
|
|
|
* and adds it to the open list by calling Yapf().AddNewNode(n)
|
|
|
*/
|
|
|
inline void PfFollowNode(Node& old_node)
|
|
|
{
|
|
|
TrackFollower F(Yapf().GetVehicle());
|
|
|
if (F.Follow(old_node.m_key.m_tile, old_node.m_key.m_td)) {
|
|
|
Yapf().AddMultipleNodes(&old_node, F);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** return debug report character to identify the transportation type */
|
|
|
FORCEINLINE char TransportTypeChar() const
|
|
|
inline char TransportTypeChar() const
|
|
|
{
|
|
|
return 'w';
|
|
|
}
|
|
|
|
|
|
static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)
|
|
|
{
|
|
|
/* handle special case - when next tile is destination tile */
|
|
|
if (tile == v->dest_tile) {
|
|
|
/* convert tracks to trackdirs */
|
|
|
TrackdirBits trackdirs = (TrackdirBits)(tracks | ((int)tracks << 8));
|
|
|
/* choose any trackdir reachable from enterdir */
|
|
|
trackdirs &= DiagdirReachesTrackdirs(enterdir);
|
|
|
return (Trackdir)FindFirstBit2x64(trackdirs);
|
|
|
}
|
|
|
|
|
|
/* move back to the old tile/trackdir (where ship is coming from) */
|
|
|
TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
|
|
|
Trackdir trackdir = v->GetVehicleTrackdir();
|
|
|
assert(IsValidTrackdir(trackdir));
|
|
|
|
|
|
/* convert origin trackdir to TrackdirBits */
|
|
|
TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
|
|
|
/* get available trackdirs on the destination tile */
|
|
|
TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
|
|
@@ -102,49 +102,49 @@ public:
|
|
|
|
|
|
/** Cost Provider module of YAPF for ships */
|
|
|
template <class Types>
|
|
|
class CYapfCostShipT
|
|
|
{
|
|
|
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
|
|
|
|
|
|
protected:
|
|
|
/** to access inherited path finder */
|
|
|
Tpf& Yapf()
|
|
|
{
|
|
|
return *static_cast<Tpf*>(this);
|
|
|
}
|
|
|
|
|
|
public:
|
|
|
/**
|
|
|
* Called by YAPF to calculate the cost from the origin to the given node.
|
|
|
* Calculates only the cost of given node, adds it to the parent node cost
|
|
|
* and stores the result into Node::m_cost member
|
|
|
*/
|
|
|
FORCEINLINE bool PfCalcCost(Node& n, const TrackFollower *tf)
|
|
|
inline bool PfCalcCost(Node& n, const TrackFollower *tf)
|
|
|
{
|
|
|
/* base tile cost depending on distance */
|
|
|
int c = IsDiagonalTrackdir(n.GetTrackdir()) ? YAPF_TILE_LENGTH : YAPF_TILE_CORNER_LENGTH;
|
|
|
/* additional penalty for curves */
|
|
|
if (n.m_parent != NULL && n.GetTrackdir() != NextTrackdir(n.m_parent->GetTrackdir())) {
|
|
|
/* new trackdir does not match the next one when going straight */
|
|
|
c += YAPF_TILE_LENGTH;
|
|
|
}
|
|
|
|
|
|
/* Skipped tile cost for aqueducts. */
|
|
|
c += YAPF_TILE_LENGTH * tf->m_tiles_skipped;
|
|
|
|
|
|
/* Ocean/canal speed penalty. */
|
|
|
const ShipVehicleInfo *svi = ShipVehInfo(Yapf().GetVehicle()->engine_type);
|
|
|
byte speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WATER_CLASS_SEA) ? svi->ocean_speed_frac : svi->canal_speed_frac;
|
|
|
if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->m_tiles_skipped) * speed_frac / (256 - speed_frac);
|
|
|
|
|
|
/* apply it */
|
|
|
n.m_cost = n.m_parent->m_cost + c;
|
|
|
return true;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/**
|