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(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 n.m_cost = n.m_parent->m_cost + c;
00114 return true;
00115 }
00116 };
00117
00121 template <class Tpf_, class Ttrack_follower, class Tnode_list>
00122 struct CYapfShip_TypesT
00123 {
00125 typedef CYapfShip_TypesT<Tpf_, Ttrack_follower, Tnode_list> Types;
00126
00128 typedef Tpf_ Tpf;
00130 typedef Ttrack_follower TrackFollower;
00132 typedef Tnode_list NodeList;
00134 typedef CYapfBaseT<Types> PfBase;
00135 typedef CYapfFollowShipT<Types> PfFollow;
00136 typedef CYapfOriginTileT<Types> PfOrigin;
00137 typedef CYapfDestinationTileT<Types> PfDestination;
00138 typedef CYapfSegmentCostCacheNoneT<Types> PfCache;
00139 typedef CYapfCostShipT<Types> PfCost;
00140 };
00141
00142
00143 struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater , CShipNodeListTrackDir> > {};
00144
00145 struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater , CShipNodeListExitDir > > {};
00146
00147 struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
00148
00150 Trackdir YapfChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
00151 {
00152
00153 typedef Trackdir (*PfnChooseShipTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits);
00154 PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack;
00155
00156
00157 if (_patches.forbid_90_deg)
00158 pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack;
00159 else if (_patches.yapf.disable_node_optimization)
00160 pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack;
00161
00162 Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);
00163 return td_ret;
00164 }
00165
00167 void* NpfBeginInterval()
00168 {
00169 CPerformanceTimer& perf = *new CPerformanceTimer;
00170 perf.Start();
00171 return &perf;
00172 }
00173
00175 int NpfEndInterval(void* vperf)
00176 {
00177 CPerformanceTimer& perf = *(CPerformanceTimer*)vperf;
00178 perf.Stop();
00179 int t = perf.Get(1000000);
00180 delete &perf;
00181 return t;
00182 }