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