yapf_ship.cpp
Go to the documentation of this file.00001
00002
00005 #include "../stdafx.h"
00006
00007 #include "yapf.hpp"
00008
00010 template <class Types>
00011 class CYapfFollowShipT
00012 {
00013 public:
00014 typedef typename Types::Tpf Tpf;
00015 typedef typename Types::TrackFollower TrackFollower;
00016 typedef typename Types::NodeList::Titem Node;
00017 typedef typename Node::Key Key;
00018
00019 protected:
00021 FORCEINLINE Tpf& Yapf() {return *static_cast<Tpf*>(this);}
00022
00023 public:
00027 inline void PfFollowNode(Node& old_node)
00028 {
00029 TrackFollower F(Yapf().GetVehicle());
00030 if (F.Follow(old_node.m_key.m_tile, old_node.m_key.m_td))
00031 Yapf().AddMultipleNodes(&old_node, F);
00032 }
00033
00035 FORCEINLINE char TransportTypeChar() const {return 'w';}
00036
00037 static Trackdir ChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
00038 {
00039
00040 if (tile == v->dest_tile) {
00041
00042 TrackdirBits trackdirs = (TrackdirBits)(tracks | ((int)tracks << 8));
00043
00044 trackdirs &= DiagdirReachesTrackdirs(enterdir);
00045 return (Trackdir)FindFirstBit2x64(trackdirs);
00046 }
00047
00048
00049 TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
00050 Trackdir trackdir = GetVehicleTrackdir(v);
00051 assert(IsValidTrackdir(trackdir));
00052
00053
00054 TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
00055
00056 TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
00057
00058
00059 Tpf pf;
00060
00061 pf.SetOrigin(src_tile, trackdirs);
00062 pf.SetDestination(v->dest_tile, dest_trackdirs);
00063
00064 pf.FindPath(v);
00065
00066 Trackdir next_trackdir = INVALID_TRACKDIR;
00067
00068 Node *pNode = pf.GetBestNode();
00069 if (pNode != NULL) {
00070
00071 Node *pPrevNode = NULL;
00072 while (pNode->m_parent != NULL) {
00073 pPrevNode = pNode;
00074 pNode = pNode->m_parent;
00075 }
00076
00077 Node& best_next_node = *pPrevNode;
00078 assert(best_next_node.GetTile() == tile);
00079 next_trackdir = best_next_node.GetTrackdir();
00080 }
00081 return next_trackdir;
00082 }
00083 };
00084
00086 template <class Types>
00087 class CYapfCostShipT
00088 {
00089 public:
00090 typedef typename Types::Tpf Tpf;
00091 typedef typename Types::TrackFollower TrackFollower;
00092 typedef typename Types::NodeList::Titem Node;
00093 typedef typename Node::Key Key;
00094
00095 protected:
00097 Tpf& Yapf() {return *static_cast<Tpf*>(this);}
00098
00099 public:
00103 FORCEINLINE bool PfCalcCost(Node& n, const TrackFollower *tf)
00104 {
00105
00106 int c = IsDiagonalTrackdir(n.GetTrackdir()) ? 10 : 7;
00107
00108 if (n.m_parent != NULL && n.GetTrackdir() != NextTrackdir(n.m_parent->GetTrackdir())) {
00109
00110 c += 10;
00111 }
00112
00113 c += YAPF_TILE_LENGTH * tf->m_tiles_skipped;
00114
00115
00116 n.m_cost = n.m_parent->m_cost + c;
00117 return true;
00118 }
00119 };
00120
00124 template <class Tpf_, class Ttrack_follower, class Tnode_list>
00125 struct CYapfShip_TypesT
00126 {
00128 typedef CYapfShip_TypesT<Tpf_, Ttrack_follower, Tnode_list> Types;
00129
00131 typedef Tpf_ Tpf;
00133 typedef Ttrack_follower TrackFollower;
00135 typedef Tnode_list NodeList;
00137 typedef CYapfBaseT<Types> PfBase;
00138 typedef CYapfFollowShipT<Types> PfFollow;
00139 typedef CYapfOriginTileT<Types> PfOrigin;
00140 typedef CYapfDestinationTileT<Types> PfDestination;
00141 typedef CYapfSegmentCostCacheNoneT<Types> PfCache;
00142 typedef CYapfCostShipT<Types> PfCost;
00143 };
00144
00145
00146 struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater , CShipNodeListTrackDir> > {};
00147
00148 struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater , CShipNodeListExitDir > > {};
00149
00150 struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
00151
00153 Trackdir YapfChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
00154 {
00155
00156 typedef Trackdir (*PfnChooseShipTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits);
00157 PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack;
00158
00159
00160 if (_settings_game.pf.forbid_90_deg) {
00161 pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack;
00162 } else if (_settings_game.pf.yapf.disable_node_optimization) {
00163 pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack;
00164 }
00165
00166 Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);
00167 return td_ret;
00168 }
00169
00171 void * NpfBeginInterval()
00172 {
00173 CPerformanceTimer& perf = *new CPerformanceTimer;
00174 perf.Start();
00175 return &perf;
00176 }
00177
00179 int NpfEndInterval(void *vperf)
00180 {
00181 CPerformanceTimer& perf = *(CPerformanceTimer*)vperf;
00182 perf.Stop();
00183 int t = perf.Get(1000000);
00184 delete &perf;
00185 return t;
00186 }