15 #include "../../debug.h" 16 #include "../../settings_type.h" 18 extern int _total_pf_time_us;
50 template <
class Types>
53 typedef typename Types::Tpf
Tpf;
54 typedef typename Types::TrackFollower TrackFollower;
57 typedef typename NodeList::Titem
Node;
58 typedef typename Node::Key
Key;
84 : m_pBestDestNode(NULL)
85 , m_pBestIntermediateNode(NULL)
89 , m_stats_cost_calcs(0)
90 , m_stats_cache_hits(0)
102 return *
static_cast<Tpf *
>(
this);
125 #ifndef NO_DEBUG_MESSAGES 130 Yapf().PfSetStartupNodes();
131 bool bDestFound =
true;
135 Node *n = m_nodes.GetBestOpenNode();
141 if (m_pBestDestNode != NULL && m_pBestDestNode->GetCost() < n->GetCostEstimate()) {
145 Yapf().PfFollowNode(*n);
147 m_nodes.PopOpenNode(n->GetKey());
148 m_nodes.InsertClosedNode(*n);
155 bDestFound &= (m_pBestDestNode != NULL);
157 #ifndef NO_DEBUG_MESSAGES 159 if (_debug_yapf_level >= 2) {
160 int t = perf.Get(1000000);
161 _total_pf_time_us += t;
163 if (_debug_yapf_level >= 3) {
164 UnitID veh_idx = (m_veh != NULL) ? m_veh->unitnumber : 0;
165 char ttc =
Yapf().TransportTypeChar();
166 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);
167 int cost = bDestFound ? m_pBestDestNode->m_cost : -1;
168 int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1;
170 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) -- ",
171 ttc, bDestFound ?
'-' :
'!', veh_idx, t, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(),
172 cache_hit_ratio, cost, dist, m_perf_cost.Get(1000000), m_perf_slope_cost.Get(1000000),
173 m_perf_ts_cost.Get(1000000), m_perf_other_cost.Get(1000000)
196 Node &node = *m_nodes.CreateNewNode();
203 Yapf().PfNodeCacheFetch(n);
205 if (m_nodes.FindOpenNode(n.m_key) == NULL) {
206 m_nodes.InsertOpenNode(n);
220 Node &n =
Yapf().CreateNewNode();
221 n.Set(parent, tf.m_new_tile, td, is_choice);
222 Yapf().AddNewNode(n, tf);
236 while (
Yapf().m_pBestIntermediateNode != NULL && (
Yapf().m_pBestIntermediateNode->m_segment->m_end_segment_reason & ESRB_CHOICE_FOLLOWS) == 0) {
237 Yapf().m_pBestIntermediateNode =
Yapf().m_pBestIntermediateNode->m_parent;
248 bool bCached =
Yapf().PfNodeCacheFetch(n);
250 m_stats_cost_calcs++;
252 m_stats_cache_hits++;
255 bool bValid =
Yapf().PfCalcCost(n, &tf);
258 Yapf().PfNodeCacheFlush(n);
261 if (bValid) bValid =
Yapf().PfCalcEstimate(n);
267 bool bDestination =
Yapf().PfDetectDestination(n);
269 if (m_pBestDestNode == NULL || n < *m_pBestDestNode) {
270 m_pBestDestNode = &n;
272 m_nodes.FoundBestNode(n);
276 if (m_max_search_nodes > 0 && (m_pBestIntermediateNode == NULL || (m_pBestIntermediateNode->GetCostEstimate() - m_pBestIntermediateNode->GetCost()) > (n.GetCostEstimate() - n.GetCost()))) {
277 m_pBestIntermediateNode = &n;
281 Node *openNode = m_nodes.FindOpenNode(n.GetKey());
282 if (openNode != NULL) {
285 if (n.GetCostEstimate() < openNode->GetCostEstimate()) {
287 m_nodes.PopOpenNode(n.GetKey());
290 m_nodes.InsertOpenNode(*openNode);
296 Node *closedNode = m_nodes.FindClosedNode(n.GetKey());
297 if (closedNode != NULL) {
300 int node_est = n.GetCostEstimate();
301 int closed_est = closedNode->GetCostEstimate();
302 if (node_est < closed_est) {
315 m_nodes.InsertOpenNode(n);
318 const VehicleType * GetVehicle()
const 326 dmp.
WriteLine(
"m_num_steps = %d", m_num_steps);
333 inline void PfSetStartupNodes()
336 Node &n1 = *base::m_nodes.CreateNewNode();
340 base::m_nodes.InsertOpenNode(n1);
344 inline void PfFollowNode(Node &org)
346 for (each follower of node org) {
347 Node &n = *base::m_nodes.CreateNewNode();
357 inline bool PfCalcCost(Node &n)
362 n.m_cost = n.m_parent->m_cost + cost;
367 inline bool PfCalcEstimate(Node &n)
372 n.m_estimate = n.m_cost + distance;
377 inline bool PfDetectDestination(Node &n)
379 bool bDest = (n.m_key.m_x == m_x2) && (n.m_key.m_y == m_y2);
CPerformanceTimer m_perf_other_cost
stats - other CPU time
GameSettings _settings_game
Game settings of a running game or the scenario editor.
void AddNewNode(Node &n, const TrackFollower &tf)
AddNewNode() - called by Tderived::PfFollowNode() for each child node.
Types::VehicleType VehicleType
the type of vehicle
Node::Key Key
key to hash tables
Node * GetBestNode()
If path was found return the best node that has reached the destination.
int m_max_search_nodes
maximum number of nodes we are allowed to visit before we give up
int m_stats_cost_calcs
stats - how many node's costs were calculated
void CDECL WriteLine(const char *format,...) WARN_FORMAT(2
Write a line with indent at the beginning and <LF> at the end.
Node * m_pBestDestNode
pointer to the destination node found at last round
void AddStartupNode(Node &n)
Add new node (created by CreateNewNode and filled with data) into open list.
Settings related to the yet another pathfinder.
Node & CreateNewNode()
Calls NodeList::CreateNewNode() - allocates new node that can be filled and used as argument for AddS...
Types::NodeList NodeList
our node list
Node * m_pBestIntermediateNode
here should be node closest to the destination if path not found
bool FindPath(const VehicleType *v)
Main pathfinder routine:
const VehicleType * m_veh
vehicle that we are trying to drive
~CYapfBaseT()
default destructor
CYapfBaseT - A-star type path finder base class.
NodeList::Titem Node
this will be our node type
VehicleType
Available vehicle types.
CPerformanceTimer m_perf_ts_cost
stats - GetTrackStatus() CPU time
CPerformanceTimer m_perf_cost
stats - total CPU time of this run
const YAPFSettings & PfGetSettings() const
return current settings (can be custom - company based - but later)
Trackdir
Enumeration for tracks and directions.
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
#define DEBUG(name, level,...)
Output a line of debugging information.
void WriteStructT(const char *name, const S *s)
Dump nested object (or only its name if this instance is already known).
static T KillFirstBit(T value)
Clear the first bit in an integer.
static uint8 FindFirstBit2x64(const int value)
Finds the position of the first non-zero bit in an integer.
int m_stats_cache_hits
stats - how many node's costs were reused from cache
TrackdirBits
Enumeration of bitmasks for the TrackDirs.
uint16 UnitID
Type for the company global vehicle unit number.
void AddMultipleNodes(Node *parent, const TrackFollower &tf)
add multiple nodes - direct children of the given node
CPerformanceTimer m_perf_slope_cost
stats - slope calculation CPU time
int m_num_steps
this is there for debugging purposes (hope it doesn't hurt)
NodeList m_nodes
node list multi-container
const YAPFSettings * m_settings
current settings (_settings_game.yapf)
Class that represents the dump-into-string target.
CYapfBaseT()
default constructor
void PruneIntermediateNodeBranch()
In some cases an intermediate node branch should be pruned.
Tpf & Yapf()
to access inherited path finder