yapf_base.hpp
Go to the documentation of this file.00001
00002
00005 #ifndef YAPF_BASE_HPP
00006 #define YAPF_BASE_HPP
00007
00008 #include "../debug.h"
00009
00010 extern int _total_pf_time_us;
00011
00041 template <class Types>
00042 class CYapfBaseT {
00043 public:
00044 typedef typename Types::Tpf Tpf;
00045 typedef typename Types::TrackFollower TrackFollower;
00046 typedef typename Types::NodeList NodeList;
00047 typedef typename NodeList::Titem Node;
00048 typedef typename Node::Key Key;
00049
00050
00051 NodeList m_nodes;
00052 protected:
00053 Node* m_pBestDestNode;
00054 Node* m_pBestIntermediateNode;
00055 const YapfSettings *m_settings;
00056 int m_max_search_nodes;
00057 const Vehicle* m_veh;
00058
00059 int m_stats_cost_calcs;
00060 int m_stats_cache_hits;
00061
00062 public:
00063 CPerformanceTimer m_perf_cost;
00064 CPerformanceTimer m_perf_slope_cost;
00065 CPerformanceTimer m_perf_ts_cost;
00066 CPerformanceTimer m_perf_other_cost;
00067
00068 public:
00069 int m_num_steps;
00070
00071 public:
00073 FORCEINLINE CYapfBaseT()
00074 : m_pBestDestNode(NULL)
00075 , m_pBestIntermediateNode(NULL)
00076 , m_settings(&_patches.yapf)
00077 , m_max_search_nodes(PfGetSettings().max_search_nodes)
00078 , m_veh(NULL)
00079 , m_stats_cost_calcs(0)
00080 , m_stats_cache_hits(0)
00081 , m_num_steps(0)
00082 {
00083 }
00084
00086 ~CYapfBaseT() {}
00087
00088 protected:
00090 FORCEINLINE Tpf& Yapf() {return *static_cast<Tpf*>(this);}
00091
00092 public:
00094 FORCEINLINE const YapfSettings& PfGetSettings() const
00095 {
00096 return *m_settings;
00097 }
00098
00106 inline bool FindPath(const Vehicle *v)
00107 {
00108 m_veh = v;
00109
00110 #ifndef NO_DEBUG_MESSAGES
00111 CPerformanceTimer perf;
00112 perf.Start();
00113 #endif
00114
00115 Yapf().PfSetStartupNodes();
00116
00117 while (true) {
00118 m_num_steps++;
00119 Node *n = m_nodes.GetBestOpenNode();
00120 if (n == NULL)
00121 break;
00122
00123
00124 if (m_pBestDestNode != NULL && m_pBestDestNode->GetCost() < n->GetCostEstimate())
00125 break;
00126
00127 Yapf().PfFollowNode(*n);
00128 if (m_max_search_nodes == 0 || m_nodes.ClosedCount() < m_max_search_nodes) {
00129 m_nodes.PopOpenNode(n->GetKey());
00130 m_nodes.InsertClosedNode(*n);
00131 } else {
00132 m_pBestDestNode = m_pBestIntermediateNode;
00133 break;
00134 }
00135 }
00136
00137 bool bDestFound = (m_pBestDestNode != NULL) && (m_pBestDestNode != m_pBestIntermediateNode);
00138
00139 #ifndef NO_DEBUG_MESSAGES
00140 perf.Stop();
00141 if (_debug_yapf_level >= 2) {
00142 int t = perf.Get(1000000);
00143 _total_pf_time_us += t;
00144
00145 if (_debug_yapf_level >= 3) {
00146 UnitID veh_idx = (m_veh != NULL) ? m_veh->unitnumber : 0;
00147 char ttc = Yapf().TransportTypeChar();
00148 float cache_hit_ratio = (m_stats_cache_hits == 0) ? 0.0f : ((float)m_stats_cache_hits / (float)(m_stats_cache_hits + m_stats_cost_calcs) * 100.0f);
00149 int cost = bDestFound ? m_pBestDestNode->m_cost : -1;
00150 int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1;
00151
00152 DEBUG(yapf, 3, "[YAPF%c]%c%4d- %d us - %d rounds - %d open - %d closed - CHR %4.1f%% - c%d(sc%d, ts%d, o%d) -- ",
00153 ttc, bDestFound ? '-' : '!', veh_idx, t, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(),
00154 cache_hit_ratio, cost, dist, m_perf_cost.Get(1000000), m_perf_slope_cost.Get(1000000),
00155 m_perf_ts_cost.Get(1000000), m_perf_other_cost.Get(1000000)
00156 );
00157 }
00158 }
00159 #endif
00160 return bDestFound;
00161 }
00162
00166 FORCEINLINE Node* GetBestNode()
00167 {
00168 return (m_pBestDestNode != NULL) ? m_pBestDestNode : m_pBestIntermediateNode;
00169 }
00170
00174 FORCEINLINE Node& CreateNewNode()
00175 {
00176 Node& node = *m_nodes.CreateNewNode();
00177 return node;
00178 }
00179
00181 FORCEINLINE void AddStartupNode(Node& n)
00182 {
00183 Yapf().PfNodeCacheFetch(n);
00184
00185 if (m_nodes.FindOpenNode(n.m_key) == NULL) {
00186 m_nodes.InsertOpenNode(n);
00187 } else {
00188
00189
00190
00191 }
00192 }
00193
00195 FORCEINLINE void AddMultipleNodes(Node* parent, const TrackFollower &tf)
00196 {
00197 bool is_choice = (KillFirstBit(tf.m_new_td_bits) != TRACKDIR_BIT_NONE);
00198 for (TrackdirBits rtds = tf.m_new_td_bits; rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
00199 Trackdir td = (Trackdir)FindFirstBit2x64(rtds);
00200 Node& n = Yapf().CreateNewNode();
00201 n.Set(parent, tf.m_new_tile, td, is_choice);
00202 Yapf().AddNewNode(n, tf);
00203 }
00204 }
00205
00208 void AddNewNode(Node &n, const TrackFollower &tf)
00209 {
00210
00211 bool bCached = Yapf().PfNodeCacheFetch(n);
00212 if (!bCached) {
00213 m_stats_cost_calcs++;
00214 } else {
00215 m_stats_cache_hits++;
00216 }
00217
00218 bool bValid = Yapf().PfCalcCost(n, &tf);
00219
00220 if (bCached) {
00221 Yapf().PfNodeCacheFlush(n);
00222 }
00223
00224 if (bValid) bValid = Yapf().PfCalcEstimate(n);
00225
00226
00227 if (!bValid) return;
00228
00229
00230 bool bDestination = Yapf().PfDetectDestination(n);
00231 if (bDestination) {
00232 if (m_pBestDestNode == NULL || n < *m_pBestDestNode) {
00233 m_pBestDestNode = &n;
00234 }
00235 m_nodes.FoundBestNode(n);
00236 return;
00237 }
00238
00239 if (m_max_search_nodes > 0 && (m_pBestIntermediateNode == NULL || (m_pBestIntermediateNode->GetCostEstimate() - m_pBestIntermediateNode->GetCost()) > (n.GetCostEstimate() - n.GetCost()))) {
00240 m_pBestIntermediateNode = &n;
00241 }
00242
00243
00244 Node* openNode = m_nodes.FindOpenNode(n.GetKey());
00245 if (openNode != NULL) {
00246
00247
00248 if (n.GetCostEstimate() < openNode->GetCostEstimate()) {
00249
00250 m_nodes.PopOpenNode(n.GetKey());
00251 *openNode = n;
00252
00253 m_nodes.InsertOpenNode(*openNode);
00254 }
00255 return;
00256 }
00257
00258
00259 Node* closedNode = m_nodes.FindClosedNode(n.GetKey());
00260 if (closedNode != NULL) {
00261
00262
00263 int node_est = n.GetCostEstimate();
00264 int closed_est = closedNode->GetCostEstimate();
00265 if (node_est < closed_est) {
00266
00267
00268
00269
00270
00271
00272 assert(0);
00273
00274 return;
00275 }
00276 return;
00277 }
00278
00279
00280 m_nodes.InsertOpenNode(n);
00281 }
00282
00283 const Vehicle* GetVehicle() const {return m_veh;}
00284
00285 void DumpBase(DumpTarget &dmp) const
00286 {
00287 dmp.WriteStructT("m_nodes", &m_nodes);
00288 dmp.WriteLine("m_num_steps = %d", m_num_steps);
00289 }
00290
00291
00292
00293 #if 0
00294
00295 FORCEINLINE void PfSetStartupNodes()
00296 {
00297
00298 Node& n1 = *base::m_nodes.CreateNewNode();
00299 .
00300 .
00301 .
00302 base::m_nodes.InsertOpenNode(n1);
00303 }
00304
00306 FORCEINLINE void PfFollowNode(Node& org)
00307 {
00308 for (each follower of node org) {
00309 Node& n = *base::m_nodes.CreateNewNode();
00310 .
00311 .
00312 .
00313 n.m_parent = &org;
00314 AddNewNode(n);
00315 }
00316 }
00317
00319 FORCEINLINE bool PfCalcCost(Node& n)
00320 {
00321
00322 int cost = ...;
00323
00324 n.m_cost = n.m_parent->m_cost + cost;
00325 return true;
00326 }
00327
00329 FORCEINLINE bool PfCalcEstimate(Node& n)
00330 {
00331
00332 int distance = ...;
00333
00334 n.m_estimate = n.m_cost + distance;
00335 return true;
00336 }
00337
00339 FORCEINLINE bool PfDetectDestination(Node& n)
00340 {
00341 bool bDest = (n.m_key.m_x == m_x2) && (n.m_key.m_y == m_y2);
00342 return bDest;
00343 }
00344 #endif
00345 };
00346
00347 #endif