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