yapf_ship.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../../stdafx.h"
00013 #include "../../ship.h"
00014
00015 #include "yapf.hpp"
00016 #include "yapf_node_ship.hpp"
00017
00019 template <class Types>
00020 class CYapfFollowShipT
00021 {
00022 public:
00023 typedef typename Types::Tpf Tpf;
00024 typedef typename Types::TrackFollower TrackFollower;
00025 typedef typename Types::NodeList::Titem Node;
00026 typedef typename Node::Key Key;
00027
00028 protected:
00030 FORCEINLINE Tpf& Yapf()
00031 {
00032 return *static_cast<Tpf*>(this);
00033 }
00034
00035 public:
00041 inline void PfFollowNode(Node& old_node)
00042 {
00043 TrackFollower F(Yapf().GetVehicle());
00044 if (F.Follow(old_node.m_key.m_tile, old_node.m_key.m_td)) {
00045 Yapf().AddMultipleNodes(&old_node, F);
00046 }
00047 }
00048
00050 FORCEINLINE char TransportTypeChar() const
00051 {
00052 return 'w';
00053 }
00054
00055 static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)
00056 {
00057
00058 if (tile == v->dest_tile) {
00059
00060 TrackdirBits trackdirs = (TrackdirBits)(tracks | ((int)tracks << 8));
00061
00062 trackdirs &= DiagdirReachesTrackdirs(enterdir);
00063 return (Trackdir)FindFirstBit2x64(trackdirs);
00064 }
00065
00066
00067 TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
00068 Trackdir trackdir = v->GetVehicleTrackdir();
00069 assert(IsValidTrackdir(trackdir));
00070
00071
00072 TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
00073
00074 TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
00075
00076
00077 Tpf pf;
00078
00079 pf.SetOrigin(src_tile, trackdirs);
00080 pf.SetDestination(v->dest_tile, dest_trackdirs);
00081
00082 path_found = pf.FindPath(v);
00083
00084 Trackdir next_trackdir = INVALID_TRACKDIR;
00085
00086 Node *pNode = pf.GetBestNode();
00087 if (pNode != NULL) {
00088
00089 Node *pPrevNode = NULL;
00090 while (pNode->m_parent != NULL) {
00091 pPrevNode = pNode;
00092 pNode = pNode->m_parent;
00093 }
00094
00095 Node& best_next_node = *pPrevNode;
00096 assert(best_next_node.GetTile() == tile);
00097 next_trackdir = best_next_node.GetTrackdir();
00098 }
00099 return next_trackdir;
00100 }
00101 };
00102
00104 template <class Types>
00105 class CYapfCostShipT
00106 {
00107 public:
00108 typedef typename Types::Tpf Tpf;
00109 typedef typename Types::TrackFollower TrackFollower;
00110 typedef typename Types::NodeList::Titem Node;
00111 typedef typename Node::Key Key;
00112
00113 protected:
00115 Tpf& Yapf()
00116 {
00117 return *static_cast<Tpf*>(this);
00118 }
00119
00120 public:
00126 FORCEINLINE bool PfCalcCost(Node& n, const TrackFollower *tf)
00127 {
00128
00129 int c = IsDiagonalTrackdir(n.GetTrackdir()) ? YAPF_TILE_LENGTH : YAPF_TILE_CORNER_LENGTH;
00130
00131 if (n.m_parent != NULL && n.GetTrackdir() != NextTrackdir(n.m_parent->GetTrackdir())) {
00132
00133 c += YAPF_TILE_LENGTH;
00134 }
00135
00136 c += YAPF_TILE_LENGTH * tf->m_tiles_skipped;
00137
00138
00139 n.m_cost = n.m_parent->m_cost + c;
00140 return true;
00141 }
00142 };
00143
00148 template <class Tpf_, class Ttrack_follower, class Tnode_list>
00149 struct CYapfShip_TypesT
00150 {
00152 typedef CYapfShip_TypesT<Tpf_, Ttrack_follower, Tnode_list> Types;
00153
00155 typedef Tpf_ Tpf;
00157 typedef Ttrack_follower TrackFollower;
00159 typedef Tnode_list NodeList;
00160 typedef Ship VehicleType;
00162 typedef CYapfBaseT<Types> PfBase;
00163 typedef CYapfFollowShipT<Types> PfFollow;
00164 typedef CYapfOriginTileT<Types> PfOrigin;
00165 typedef CYapfDestinationTileT<Types> PfDestination;
00166 typedef CYapfSegmentCostCacheNoneT<Types> PfCache;
00167 typedef CYapfCostShipT<Types> PfCost;
00168 };
00169
00170
00171 struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater , CShipNodeListTrackDir> > {};
00172
00173 struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater , CShipNodeListExitDir > > {};
00174
00175 struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
00176
00178 Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)
00179 {
00180
00181 typedef Trackdir (*PfnChooseShipTrack)(const Ship*, TileIndex, DiagDirection, TrackBits, bool &path_found);
00182 PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack;
00183
00184
00185 if (_settings_game.pf.forbid_90_deg) {
00186 pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack;
00187 } else if (_settings_game.pf.yapf.disable_node_optimization) {
00188 pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack;
00189 }
00190
00191 Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks, path_found);
00192 return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
00193 }