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