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