MCPcopy Create free account
hub / github.com/OpenXcom/OpenXcom / aStarPath

Method aStarPath

src/Battlescape/Pathfinding.cpp:184–236  ·  view source on GitHub ↗

* Calculates the shortest path using a simple A-Star algorithm. * The unit information and movement type must have already been set. * The path information is set only if a valid path is found. * @param startPosition The position to start from. * @param endPosition The position we want to reach. * @param target Target of the path. * @param sneak Is the unit sneaking? * @param maxTUCost Maxi

Source from the content-addressed store, hash-verified

182 * @return True if a path exists, false otherwise.
183 */
184bool Pathfinding::aStarPath(const Position &startPosition, const Position &endPosition, BattleUnit *target, bool sneak, int maxTUCost)
185{
186 // reset every node, so we have to check them all
187 for (std::vector<PathfindingNode>::iterator it = _nodes.begin(); it != _nodes.end(); ++it)
188 it->reset();
189
190 // start position is the first one in our "open" list
191 PathfindingNode *start = getNode(startPosition);
192 start->connect(0, 0, 0, endPosition);
193 PathfindingOpenSet openList;
194 openList.push(start);
195 bool missile = (target && maxTUCost == -1);
196 // if the open list is empty, we've reached the end
197 while(!openList.empty())
198 {
199 PathfindingNode *currentNode = openList.pop();
200 Position const &currentPos = currentNode->getPosition();
201 currentNode->setChecked();
202 if (currentPos == endPosition) // We found our target.
203 {
204 _path.clear();
205 PathfindingNode *pf = currentNode;
206 while (pf->getPrevNode())
207 {
208 _path.push_back(pf->getPrevDir());
209 pf = pf->getPrevNode();
210 }
211 return true;
212 }
213
214 // Try all reachable neighbours.
215 for (int direction = 0; direction < 10; direction++)
216 {
217 Position nextPos;
218 int tuCost = getTUCost(currentPos, direction, &nextPos, _unit, target, missile);
219 if (tuCost >= 255) // Skip unreachable / blocked
220 continue;
221 if (sneak && _save->getTile(nextPos)->getVisible()) tuCost *= 2; // avoid being seen
222 PathfindingNode *nextNode = getNode(nextPos);
223 if (nextNode->isChecked()) // Our algorithm means this node is already at minimum cost.
224 continue;
225 _totalTUCost = currentNode->getTUCost(missile) + tuCost;
226 // If this node is unvisited or has only been visited from inferior paths...
227 if ((!nextNode->inOpenSet() || nextNode->getTUCost(missile) > _totalTUCost) && _totalTUCost <= maxTUCost)
228 {
229 nextNode->connect(_totalTUCost, currentNode, direction, endPosition);
230 openList.push(nextNode);
231 }
232 }
233 }
234 // Unble to reach the target
235 return false;
236}
237
238/**
239 * Gets the TU cost to move from 1 tile to the other (ONE STEP ONLY).

Callers

nothing calls this directly

Calls 15

connectMethod · 0.80
pushMethod · 0.80
popMethod · 0.80
setCheckedMethod · 0.80
getPrevNodeMethod · 0.80
getPrevDirMethod · 0.80
isCheckedMethod · 0.80
inOpenSetMethod · 0.80
resetMethod · 0.45
emptyMethod · 0.45
getPositionMethod · 0.45
clearMethod · 0.45

Tested by

no test coverage detected