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