bool PathFindingApp::doPathfinding(int startX, int startY, int endX, int endY) { // Set color for start and end pos to path color setPathColor(m_texturePathFound, startX, startY); setPathColor(m_texturePathFound, endX, endY); bool done = true; // Some variables for path finding OpenList openList; ClosedList closedList; SearchLevel searchLevel(m_textureStartCase); SearchNode *result = 0; // Start A* search: // Add start node to open list. Position startPosition = Position(startX, startY); Position endPosition = Position(endX, endY); SearchNode *newNode = new SearchNode(startPosition, searchLevel.getH(startPosition, endPosition), 0, 0); openList.insertToOpenList(newNode); // 1. Get the square on the open list which has the lowest score. Let's call this square S (or prey) while (!openList.isEmpty()) { SearchNode *prev = openList.removeSmallestFFromOpenList(); if (prev->pos == endPosition) { // Goal found! result = prev; break; } else { // 2. Remove S from the open list and add S to the closed list. closedList.addToClosedList(prev); // 3. for each square T in S's walkable adjacent tiles: std::vector<Position> adjacentNodes = searchLevel.getAdjacentNodes(prev->pos.first, prev->pos.second); for (size_t i = 0; i < adjacentNodes.size(); ++i) { // If T is in the closed list : Ignore it. if (closedList.isInClosedList(adjacentNodes[i])) { continue; } SearchNode *n = openList.findFromOpenList(adjacentNodes[i]); if (n == 0) { // If T is not in the open list : Add it and compute its score SearchNode * newNode = new SearchNode(adjacentNodes[i], searchLevel.getH(adjacentNodes[i], endPosition), searchLevel.getG(prev, adjacentNodes[i]), prev); openList.insertToOpenList(newNode); } else { // If T is already in the open list : Check if the F score is lower // when we use the current generated path to get there. If it is update // it's score and update its parent as well. SearchNode *newNode = new SearchNode(adjacentNodes[i], searchLevel.getH(adjacentNodes[i], endPosition), searchLevel.getG(prev, adjacentNodes[i]), prev); if (n->distance() < newNode->distance()) { n->resetPrev(newNode->prevNode, searchLevel.getG(newNode->prevNode, n->pos)); } } } } } if (result == 0) { printf("Path not found!!!\n"); return true; } while (result != 0) { setPathColor(m_texturePathFound, result->pos.first, result->pos.second); result = result->prevNode; } return true; // TODO: Remove that search end and delay hack as seen below.. //static int i = 0; //i = ((i+1)%10); // 10*100ms = ~500 ms of total //Sleep(100); //return i==0; }
bool GraphUtility::graph_contains_loop(const Graph& graph) { // Type definitions typedef typename Graph::vertex_descriptor VertexType; typedef typename Graph::edge_descriptor EdgeType; typedef std::stack<std::pair<VertexType, VertexType>> OpenList; typedef std::vector<bool> ClosedList; // Some local variables size_t num_node_explored = 0; const auto num_vertices = boost::num_vertices(graph); if (num_vertices == 0) return false; // Closed List inizialization ClosedList closedList(num_vertices, false); // Open List inizialization OpenList openList; const auto p_firstVertex = boost::vertices(graph).first; const auto p_nullVertex = boost::vertices(graph).second; openList.push(std::make_pair(*p_firstVertex, *p_nullVertex)); closedList[*p_firstVertex] = true; ++num_node_explored; while (openList.empty() == false) { // Pop the next node const auto current_element = openList.top(); const auto& current_node = current_element.first; const auto& current_parent = current_element.second; openList.pop(); // Explore all adjacent vertices const auto adj_vertices = boost::adjacent_vertices(current_node, graph); // Look for a back vertices which is not the parent const auto finder = std::find_if( adj_vertices.first, adj_vertices.second, [&] (const VertexType& a_v) { if (closedList[a_v] == true) { if (a_v != current_parent) { // Found a back edge. A cycle is here! return true; } } else { openList.push(std::make_pair(a_v, current_node)); closedList[a_v] = true; ++num_node_explored; } return false; }); if (finder != adj_vertices.second) { return true; } } // while openList is not empty // Assertion all nodes are explored. In case the graph is disconnected assert(num_node_explored == num_vertices); // No cycle found! return false; }
std::vector<slm::vec2> PathFindingApp::doPathfinding(int startX, int startY, int endX, int endY) { bool done = true; // Some variables for path finding OpenList openList; ClosedList closedList; SearchLevel searchLevel(mapLayer); SearchNode *result = 0; std::vector<slm::vec2> mapPoints; // Start A* search: // Add start node to open list. Position startPosition = Position(startX, startY); Position endPosition = Position(endX, endY); SearchNode *newNode = new SearchNode(startPosition, searchLevel.getH(startPosition, endPosition), 0, 0); openList.insertToOpenList(newNode); // 1. Get the square on the open list which has the lowest score. Let's call this square S (or prey) while (!openList.isEmpty()) { SearchNode *prev = openList.removeSmallestFFromOpenList(); if (prev->pos == endPosition) { // Goal found! result = prev; break; } else { // 2. Remove S from the open list and add S to the closed list. closedList.addToClosedList(prev); // 3. for each square T in S's walkable adjacent tiles: std::vector<Position> adjacentNodes = searchLevel.getAdjacentNodes(prev->pos.first, prev->pos.second); for (size_t i = 0; i < adjacentNodes.size(); ++i) { // If T is in the closed list : Ignore it. if (closedList.isInClosedList(adjacentNodes[i])) { continue; } SearchNode *n = openList.findFromOpenList(adjacentNodes[i]); if (n == 0) { // If T is not in the open list : Add it and compute its score SearchNode * newNode = new SearchNode(adjacentNodes[i], searchLevel.getH(adjacentNodes[i], endPosition), searchLevel.getG(prev, adjacentNodes[i]), prev); openList.insertToOpenList(newNode); } else { // If T is already in the open list : Check if the F score is lower // when we use the current generated path to get there. If it is update // it's score and update its parent as well. SearchNode *newNode = new SearchNode(adjacentNodes[i], searchLevel.getH(adjacentNodes[i], endPosition), searchLevel.getG(prev, adjacentNodes[i]), prev); if (n->distance() < newNode->distance()) { n->resetPrev(newNode->prevNode, searchLevel.getG(newNode->prevNode, n->pos)); } } } } } if (result == 0) { std::cout << "Path not found!!!\n"; return mapPoints; } while (result != 0) { std::cout << "Path found!\n"; result = result->prevNode; if (result != nullptr) { slm::vec2 mapPoint; mapPoint.x = result->pos.first; mapPoint.y = result->pos.second; mapPoints.push_back(mapPoint); } } return mapPoints; }
void GraphUtility::find_all_disjointed_graph( const Graph& graph, std::vector<VertexFilter>* dis_graphs, bool unitary_subgraph) { assert(dis_graphs != nullptr); // Some type definitions typedef typename Graph::vertex_descriptor VertexType; typedef std::queue<VertexType> OpenList; typedef std::vector<bool> ClosedList; // Some local variable const auto num_vertices = boost::num_vertices(graph); VertexFilter* current_filter = nullptr; // Clean the output dis_graphs->clear(); // Initialize the closed list. All vertices are unexplored ClosedList closedList(num_vertices, false); size_t explored_node = 0; // Inizialize the open list. Insert the first vertex OpenList openList; const auto first_vertex = boost::vertices(graph).first; openList.push(*first_vertex); ++explored_node; closedList[*first_vertex] = true; while (explored_node < num_vertices) { // Check if the open list is empty. In that case find another node if (openList.empty() == true) { // Force next iteration to create a new filter current_filter = nullptr; const auto all_vertices = boost::vertices(graph); const auto finder = std::find_if( all_vertices.first, all_vertices.second, [&] (const VertexType& v) { return (closedList[v] == false); }); // There must to be another vertex to explore assert(finder != all_vertices.second); // Insert this new node in the openlist openList.push(*finder); closedList[*finder] = true; ++explored_node; } while (openList.empty() == false) { // Get the first vertex in the open list and remove from it const auto current_vertex = openList.front(); openList.pop(); // Check if the current vertex is a isolated node. // In that case, and the option for unitary graph is disabled // then you can skip that node if (unitary_subgraph == true || (boost::out_degree(current_vertex, graph) > 0)) { // If the current filter is null, create a new one and // use it if (current_filter == nullptr) { dis_graphs->emplace_back(num_vertices, false); current_filter = &(dis_graphs->back()); } // Add the current vertex to the current filter (*current_filter)[current_vertex] = true; // Get all adjacent vertices from the current vertex const auto adj_vertices = boost::adjacent_vertices(current_vertex, graph); // Add all adjacent vertices to the open list std::for_each( adj_vertices.first, adj_vertices.second, [&] (const VertexType& a_v) { // Check the vertex is not in the closed list if (closedList[a_v] == false) { openList.push(a_v); // Add it to the closed list closedList[a_v] = true; ++explored_node; } }); } } // end while on openList } // end while on all vertices explored // Assertion on disjointed property assert(GraphUtility::check_all_disjointed( *dis_graphs, num_vertices) == true); }
Path::Path(Unit* unit, Tile* targetTile, bool attack) : m_path (), m_attack(attack) { Q_ASSERT(unit != nullptr); Q_ASSERT(targetTile != nullptr); OpenList open; open.push(new Node(unit->tile(), 0, distance(unit->tile(), targetTile))); ClosedList closed; while (!open.isEmpty()) { Node* current = open.pop(); closed.push(current); if (current->tile() == targetTile) { // Target found constructPath(current); break; } for (Tile* neighbour : current->tile()->neighbours()) { if (closed.contains(neighbour)) { continue; } QScopedPointer<Node> newNode(new Node( neighbour, current->g() + 1, distance(neighbour, targetTile), current )); auto existing = open.find(neighbour); if (existing == open.end()) { // Tile we haven't check before - make sure we can enter if (unit->canEnter(neighbour) || (attack && neighbour == targetTile)) { open.push(newNode.take()); } else { // If we can't enter, don't check again closed.push(newNode.take()); } } else if (newNode->g() < (*existing)->g()) { open.replace(existing, newNode.take()); } } } }