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 bool bDestFound = true;
00132
00133 while (true) {
00134 m_num_steps++;
00135 Node *n = m_nodes.GetBestOpenNode();
00136 if (n == NULL) {
00137 break;
00138 }
00139
00140
00141 if (m_pBestDestNode != NULL && m_pBestDestNode->GetCost() < n->GetCostEstimate()) {
00142 break;
00143 }
00144
00145 Yapf().PfFollowNode(*n);
00146 if (m_max_search_nodes == 0 || m_nodes.ClosedCount() < m_max_search_nodes) {
00147 m_nodes.PopOpenNode(n->GetKey());
00148 m_nodes.InsertClosedNode(*n);
00149 } else {
00150 bDestFound = false;
00151 break;
00152 }
00153 }
00154
00155 bDestFound &= (m_pBestDestNode != NULL);
00156
00157 #ifndef NO_DEBUG_MESSAGES
00158 perf.Stop();
00159 if (_debug_yapf_level >= 2) {
00160 int t = perf.Get(1000000);
00161 _total_pf_time_us += t;
00162
00163 if (_debug_yapf_level >= 3) {
00164 UnitID veh_idx = (m_veh != NULL) ? m_veh->unitnumber : 0;
00165 char ttc = Yapf().TransportTypeChar();
00166 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);
00167 int cost = bDestFound ? m_pBestDestNode->m_cost : -1;
00168 int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1;
00169
00170 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) -- ",
00171 ttc, bDestFound ? '-' : '!', veh_idx, t, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(),
00172 cache_hit_ratio, cost, dist, m_perf_cost.Get(1000000), m_perf_slope_cost.Get(1000000),
00173 m_perf_ts_cost.Get(1000000), m_perf_other_cost.Get(1000000)
00174 );
00175 }
00176 }
00177 #endif
00178 return bDestFound;
00179 }
00180
00185 FORCEINLINE Node *GetBestNode()
00186 {
00187 return (m_pBestDestNode != NULL) ? m_pBestDestNode : m_pBestIntermediateNode;
00188 }
00189
00194 FORCEINLINE Node& CreateNewNode()
00195 {
00196 Node& node = *m_nodes.CreateNewNode();
00197 return node;
00198 }
00199
00201 FORCEINLINE void AddStartupNode(Node& n)
00202 {
00203 Yapf().PfNodeCacheFetch(n);
00204
00205 if (m_nodes.FindOpenNode(n.m_key) == NULL) {
00206 m_nodes.InsertOpenNode(n);
00207 } else {
00208
00209
00210
00211 }
00212 }
00213
00215 FORCEINLINE void AddMultipleNodes(Node *parent, const TrackFollower &tf)
00216 {
00217 bool is_choice = (KillFirstBit(tf.m_new_td_bits) != TRACKDIR_BIT_NONE);
00218 for (TrackdirBits rtds = tf.m_new_td_bits; rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
00219 Trackdir td = (Trackdir)FindFirstBit2x64(rtds);
00220 Node& n = Yapf().CreateNewNode();
00221 n.Set(parent, tf.m_new_tile, td, is_choice);
00222 Yapf().AddNewNode(n, tf);
00223 }
00224 }
00225
00230 void AddNewNode(Node &n, const TrackFollower &tf)
00231 {
00232
00233 bool bCached = Yapf().PfNodeCacheFetch(n);
00234 if (!bCached) {
00235 m_stats_cost_calcs++;
00236 } else {
00237 m_stats_cache_hits++;
00238 }
00239
00240 bool bValid = Yapf().PfCalcCost(n, &tf);
00241
00242 if (bCached) {
00243 Yapf().PfNodeCacheFlush(n);
00244 }
00245
00246 if (bValid) bValid = Yapf().PfCalcEstimate(n);
00247
00248
00249 if (!bValid) return;
00250
00251
00252 bool bDestination = Yapf().PfDetectDestination(n);
00253 if (bDestination) {
00254 if (m_pBestDestNode == NULL || n < *m_pBestDestNode) {
00255 m_pBestDestNode = &n;
00256 }
00257 m_nodes.FoundBestNode(n);
00258 return;
00259 }
00260
00261 if (m_max_search_nodes > 0 && (m_pBestIntermediateNode == NULL || (m_pBestIntermediateNode->GetCostEstimate() - m_pBestIntermediateNode->GetCost()) > (n.GetCostEstimate() - n.GetCost()))) {
00262 m_pBestIntermediateNode = &n;
00263 }
00264
00265
00266 Node *openNode = m_nodes.FindOpenNode(n.GetKey());
00267 if (openNode != NULL) {
00268
00269
00270 if (n.GetCostEstimate() < openNode->GetCostEstimate()) {
00271
00272 m_nodes.PopOpenNode(n.GetKey());
00273 *openNode = n;
00274
00275 m_nodes.InsertOpenNode(*openNode);
00276 }
00277 return;
00278 }
00279
00280
00281 Node *closedNode = m_nodes.FindClosedNode(n.GetKey());
00282 if (closedNode != NULL) {
00283
00284
00285 int node_est = n.GetCostEstimate();
00286 int closed_est = closedNode->GetCostEstimate();
00287 if (node_est < closed_est) {
00288
00289
00290
00291
00292
00293
00294 NOT_REACHED();
00295 }
00296 return;
00297 }
00298
00299
00300 m_nodes.InsertOpenNode(n);
00301 }
00302
00303 const VehicleType * GetVehicle() const
00304 {
00305 return m_veh;
00306 }
00307
00308 void DumpBase(DumpTarget &dmp) const
00309 {
00310 dmp.WriteStructT("m_nodes", &m_nodes);
00311 dmp.WriteLine("m_num_steps = %d", m_num_steps);
00312 }
00313
00314
00315
00316 #if 0
00317
00318 FORCEINLINE void PfSetStartupNodes()
00319 {
00320
00321 Node& n1 = *base::m_nodes.CreateNewNode();
00322 .
00323 .
00324 .
00325 base::m_nodes.InsertOpenNode(n1);
00326 }
00327
00329 FORCEINLINE void PfFollowNode(Node& org)
00330 {
00331 for (each follower of node org) {
00332 Node& n = *base::m_nodes.CreateNewNode();
00333 .
00334 .
00335 .
00336 n.m_parent = &org;
00337 AddNewNode(n);
00338 }
00339 }
00340
00342 FORCEINLINE bool PfCalcCost(Node& n)
00343 {
00344
00345 int cost = ...;
00346
00347 n.m_cost = n.m_parent->m_cost + cost;
00348 return true;
00349 }
00350
00352 FORCEINLINE bool PfCalcEstimate(Node& n)
00353 {
00354
00355 int distance = ...;
00356
00357 n.m_estimate = n.m_cost + distance;
00358 return true;
00359 }
00360
00362 FORCEINLINE bool PfDetectDestination(Node& n)
00363 {
00364 bool bDest = (n.m_key.m_x == m_x2) && (n.m_key.m_y == m_y2);
00365 return bDest;
00366 }
00367 #endif
00368 };
00369
00370 #endif