@@ -20,8 +20,7 @@ struct RoadNodeComperatorGreater
2020 {
2121 if (lhs->estimate == rhs->estimate )
2222 {
23- // Wenn die Wegkosten gleich sind, vergleichen wir die Koordinaten, da wir für std::set eine streng
24- // monoton steigende Folge brauchen
23+ // Use a tie-breaker to get strict ordering
2524 return (lhs->GetObjId () > rhs->GetObjId ());
2625 }
2726
@@ -100,7 +99,9 @@ struct And : private T_Func1, private T_Func2
10099};
101100} // namespace SegmentConstraints
102101
103- // / Wegfinden ( A* ), O(v lg v) --> Wegfindung auf Stra�en
102+ // / Path finding on roads using A* O(n lg n)
103+ // / \tparam T_AdditionalCosts Cost for each road segment but the one to the goal building
104+ // / \tparam T_SegmentConstraints Predicate whether a road is allowed
104105template <class T_AdditionalCosts , class T_SegmentConstraints >
105106bool RoadPathFinder::FindPathImpl (const noRoadNode& start, const noRoadNode& goal, const unsigned max,
106107 const T_AdditionalCosts addCosts, const T_SegmentConstraints isSegmentAllowed,
@@ -124,9 +125,12 @@ bool RoadPathFinder::FindPathImpl(const noRoadNode& start, const noRoadNode& goa
124125 return true ;
125126 }
126127
127- // increase current_visit_on_roads, so we don't have to clear the visited-states at every run
128- currentVisit++;
128+ // If the goal is a flag (unlikely) we have no goal building
129+ // TODO(Replay): Change RoadPathFinder::FindPath to target flag instead of building for wares
130+ const noRoadNode* goalBld = (goal.GetGOT () == GO_Type::Flag) ? nullptr : &goal;
129131
132+ // Use a counter for the visited-states so we don't have to reset them on every invocation
133+ currentVisit++;
130134 // if the counter reaches its maximum, tidy up
131135 if (currentVisit == std::numeric_limits<unsigned >::max ())
132136 {
@@ -163,19 +167,20 @@ bool RoadPathFinder::FindPathImpl(const noRoadNode& start, const noRoadNode& goa
163167 if (length)
164168 *length = best.cost ;
165169
166- // Backtrace to get the last node that is not the start node (has a prev node) --> Next node from start on
167- // path
168- const noRoadNode* firstNode = &best;
169- while (firstNode->prev != &start)
170+ // Backtrack to get the last node that is not the start node (has a prev node)
171+ // --> Next node from start on path
172+ if (firstDir || firstNodePos)
170173 {
171- firstNode = firstNode->prev ;
172- }
174+ const noRoadNode* firstNode = &best;
175+ while (firstNode->prev != &start)
176+ firstNode = firstNode->prev ;
173177
174- if (firstDir)
175- *firstDir = firstNode->dir_ ;
178+ if (firstDir)
179+ *firstDir = firstNode->dir_ ;
176180
177- if (firstNodePos)
178- *firstNodePos = firstNode->GetPos ();
181+ if (firstNodePos)
182+ *firstNodePos = firstNode->GetPos ();
183+ }
179184
180185 // Done, path found
181186 return true ;
@@ -184,7 +189,7 @@ bool RoadPathFinder::FindPathImpl(const noRoadNode& start, const noRoadNode& goa
184189 const helpers::EnumArray<RoadSegment*, Direction> routes = best.getRoutes ();
185190 const noRoadNode* prevNode = best.prev ;
186191
187- // Nachbarflagge bzw. Wege in allen 6 Richtungen verfolgen
192+ // Check paths in all directions
188193 for (const auto dir : helpers::EnumRange<Direction>{})
189194 {
190195 const auto * route = routes[dir];
@@ -209,12 +214,11 @@ bool RoadPathFinder::FindPathImpl(const noRoadNode& start, const noRoadNode& goa
209214 continue ;
210215 }
211216
212- // evtl verboten?
217+ // Check if route is forbidden
213218 if (!isSegmentAllowed (*route))
214219 continue ;
215220
216- unsigned cost = best.cost + route->GetLength ();
217- cost += addCosts (best, dir);
221+ const unsigned cost = best.cost + route->GetLength () + (neighbour != goalBld ? addCosts (best, dir) : 0 );
218222
219223 if (cost > max)
220224 continue ;
@@ -283,18 +287,19 @@ bool RoadPathFinder::FindPathImpl(const noRoadNode& start, const noRoadNode& goa
283287 }
284288 }
285289
286- // Liste leer und kein Ziel erreicht --> kein Weg
290+ // Queue is empty without reaching the goal --> No allowed, existing path
287291 return false ;
288292}
289293
290294bool RoadPathFinder::FindPath (const noRoadNode& start, const noRoadNode& goal, const bool wareMode, const unsigned max,
291295 const RoadSegment* const forbidden, unsigned * const length,
292296 RoadPathDirection* const firstDir, MapPoint* const firstNodePos)
293297{
294- RTTR_Assert (length || firstDir || firstNodePos); // If none of them is set use the \ref PathExist function!
298+ RTTR_Assert_Msg (length || firstDir || firstNodePos, " Use PathExists instead! " );
295299
296300 if (wareMode)
297301 {
302+ // TODO(Replay): Change to target flag instead of its attached building
298303 if (forbidden)
299304 return FindPathImpl (start, goal, max, AdditonalCosts::Carrier (),
300305 SegmentConstraints::AvoidSegment (forbidden), length, firstDir, firstNodePos);
@@ -319,6 +324,8 @@ bool RoadPathFinder::PathExists(const noRoadNode& start, const noRoadNode& goal,
319324{
320325 if (allowWaterRoads)
321326 {
327+ // TODO(Replay): Change to target flag instead of its attached building.
328+ // Likely combine with RoadPathFinder::FindPath
322329 if (forbidden)
323330 return FindPathImpl (start, goal, max, AdditonalCosts::None (), SegmentConstraints::AvoidSegment (forbidden));
324331 else
0 commit comments