mirror of
https://github.com/devZoGok/PlanetFleet.git
synced 2026-08-26 19:43:29 +00:00
finding paths between water and land cells
This commit is contained in:
+41
-21
@@ -25,44 +25,55 @@ namespace battleship{
|
|||||||
return heuristics;
|
return heuristics;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> Pathfinder::findPath(vector<Map::Cell> &cells, vector<float> &heuristics, int source, int dest, Vehicle *vehicle){
|
vector<int> Pathfinder::findPath(vector<Map::Cell> &cells, vector<float> &heuristics, int source, int dest, int vehicleType){
|
||||||
if(heuristics.empty() || (heuristics.size() == 1 && heuristics[0] == 0.0))
|
if(heuristics.empty() || (heuristics.size() == 1 && heuristics[0] == 0.0))
|
||||||
heuristics = calcHeuristics(cells, dest);
|
heuristics = calcHeuristics(cells, dest);
|
||||||
|
|
||||||
|
bool useHeur = !heuristics.empty();
|
||||||
|
|
||||||
const int size = cells.size();
|
const int size = cells.size();
|
||||||
u32 *distances = new u32[size];
|
u32 *distances = new u32[size];
|
||||||
vector<int> *paths = new vector<int>[size];
|
vector<int> *paths = new vector<int>[size];
|
||||||
paths[source].push_back(source);
|
|
||||||
|
|
||||||
vector<pair<int, bool>> cellsByCheck;
|
vector<pair<int, bool>> cellsByCheck;
|
||||||
|
vector<bool> posMinCellChecked;
|
||||||
vector<bool> cellChecked;
|
vector<int> possibleMinCells = vector<int>{source};
|
||||||
|
|
||||||
for(int i = 0; i < size; i++){
|
for(int i = 0; i < size; i++){
|
||||||
cellsByCheck.push_back(pair(i, false));
|
cellsByCheck.push_back(pair(i, false));
|
||||||
distances[i] = (i == source ? 0 : impassibleNodeVal);
|
distances[i] = impassibleNodeVal;
|
||||||
cellChecked.push_back(false);
|
posMinCellChecked.push_back(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useHeur = !heuristics.empty();
|
paths[source].push_back(source);
|
||||||
vector<int> possibleMinCells = vector<int>{source};
|
distances[source] = 0;
|
||||||
cellChecked[source] = true;
|
posMinCellChecked[source] = true;
|
||||||
|
|
||||||
|
int lastVertStrich = -1;
|
||||||
|
|
||||||
while(!cellsByCheck[dest].second){
|
while(!cellsByCheck[dest].second){
|
||||||
int vertStrich = possibleMinCells[0], vsId = 0;
|
int posMinCellId = 0, vertStrich = possibleMinCells[posMinCellId];
|
||||||
|
|
||||||
for(int i = 0; i < possibleMinCells.size(); i++){
|
for(int i = 0; i < possibleMinCells.size(); i++){
|
||||||
float sum1 = distances[possibleMinCells[i]] + (useHeur ? heuristics[possibleMinCells[i]] : 0);
|
float sum1 = distances[possibleMinCells[i]] + (useHeur ? heuristics[possibleMinCells[i]] : 0);
|
||||||
float sum2 = distances[possibleMinCells[vsId]] + (useHeur ? heuristics[possibleMinCells[vsId]] : 0);
|
float sum2 = distances[possibleMinCells[posMinCellId]] + (useHeur ? heuristics[possibleMinCells[posMinCellId]] : 0);
|
||||||
|
|
||||||
if(sum1 < sum2 || (useHeur && sum1 == sum2 && heuristics[i] < heuristics[vertStrich])){
|
if(sum1 < sum2 || (useHeur && sum1 == sum2 && heuristics[i] < heuristics[vertStrich])){
|
||||||
|
posMinCellId = i;
|
||||||
vertStrich = possibleMinCells[i];
|
vertStrich = possibleMinCells[i];
|
||||||
vsId = i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cellChecked[possibleMinCells[vsId]] = false;
|
if(distances[vertStrich] == impassibleNodeVal){
|
||||||
possibleMinCells.erase(possibleMinCells.begin() + vsId);
|
vector<int> path = paths[lastVertStrich];
|
||||||
|
|
||||||
|
delete[] paths;
|
||||||
|
delete[] distances;
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
posMinCellChecked[possibleMinCells[posMinCellId]] = false;
|
||||||
|
possibleMinCells.erase(possibleMinCells.begin() + posMinCellId);
|
||||||
|
|
||||||
cellsByCheck[vertStrich].second = true;
|
cellsByCheck[vertStrich].second = true;
|
||||||
|
|
||||||
@@ -73,14 +84,20 @@ namespace battleship{
|
|||||||
|
|
||||||
if(cellsByCheck[edgeNode].second) continue;
|
if(cellsByCheck[edgeNode].second) continue;
|
||||||
|
|
||||||
if(!cellChecked[edgeNode]){
|
if(!posMinCellChecked[edgeNode]){
|
||||||
cellChecked[edgeNode] = true;
|
posMinCellChecked[edgeNode] = true;
|
||||||
possibleMinCells.push_back(edgeNode);
|
possibleMinCells.push_back(edgeNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canMoveToStrichCell = true;
|
UnitType ut = (UnitType)vehicleType;
|
||||||
|
Map::Cell::Type ct = cells[edgeNode].type;
|
||||||
|
bool ship = (ut == UnitType::UNDERWATER || ut == UnitType::SEA_LEVEL);
|
||||||
|
int weightMult = 1;
|
||||||
|
|
||||||
if(vehicle){
|
if((ut == UnitType::LAND && ct == Map::Cell::WATER) || (ship && ct == Map::Cell::LAND))
|
||||||
|
weightMult = 10;
|
||||||
|
/*
|
||||||
|
if(vehicleType != -1){
|
||||||
UnitType unitType = vehicle->getType();
|
UnitType unitType = vehicle->getType();
|
||||||
bool ship = (unitType == UnitType::UNDERWATER || unitType == UnitType::SEA_LEVEL);
|
bool ship = (unitType == UnitType::UNDERWATER || unitType == UnitType::SEA_LEVEL);
|
||||||
Unit *blockingUnit = cells[vertStrich].blockedBy;
|
Unit *blockingUnit = cells[vertStrich].blockedBy;
|
||||||
@@ -106,13 +123,16 @@ namespace battleship{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if(distances[vertStrich] + cells[vertStrich].edges[i].weight < distances[edgeNode]){
|
if(distances[vertStrich] + weightMult * cells[vertStrich].edges[i].weight < distances[edgeNode]){
|
||||||
distances[edgeNode] = distances[vertStrich] + cells[vertStrich].edges[i].weight;
|
distances[edgeNode] = distances[vertStrich] + weightMult * cells[vertStrich].edges[i].weight;
|
||||||
paths[edgeNode] = paths[vertStrich];
|
paths[edgeNode] = paths[vertStrich];
|
||||||
paths[edgeNode].push_back(edgeNode);
|
paths[edgeNode].push_back(edgeNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastVertStrich = vertStrich;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> path = paths[dest];
|
vector<int> path = paths[dest];
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ namespace battleship{
|
|||||||
public:
|
public:
|
||||||
static Pathfinder* getSingleton();
|
static Pathfinder* getSingleton();
|
||||||
std::vector<float> calcHeuristics(std::vector<Map::Cell>&, int);
|
std::vector<float> calcHeuristics(std::vector<Map::Cell>&, int);
|
||||||
std::vector<int> findPath(std::vector<Map::Cell>&, std::vector<float>&, int, int, Vehicle* = nullptr);
|
std::vector<int> findPath(std::vector<Map::Cell>&, std::vector<float>&, int, int, int = -1);
|
||||||
inline vb01::u32 getImpassibleNodeVal(){return impassibleNodeVal;}
|
inline vb01::u32 getImpassibleNodeVal(){return impassibleNodeVal;}
|
||||||
inline void setImpassibleNodeVal(vb01::u32 val){this->impassibleNodeVal = val;}
|
inline void setImpassibleNodeVal(vb01::u32 val){this->impassibleNodeVal = val;}
|
||||||
private:
|
private:
|
||||||
|
|||||||
+20
-3
@@ -1,5 +1,6 @@
|
|||||||
#include "pathfinderTest.h"
|
#include "pathfinderTest.h"
|
||||||
#include "pathfinder.h"
|
#include "pathfinder.h"
|
||||||
|
#include "unit.h"
|
||||||
|
|
||||||
#include <vector.h>
|
#include <vector.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
@@ -61,9 +62,6 @@ namespace battleship{
|
|||||||
Map::Cell(Vector3::VEC_ZERO, Map::Cell::Type::LAND, vector<Map::Edge>{Map::Edge(0, 6, 6)})
|
Map::Cell(Vector3::VEC_ZERO, Map::Cell::Type::LAND, vector<Map::Edge>{Map::Edge(0, 6, 6)})
|
||||||
};
|
};
|
||||||
|
|
||||||
const u16 INF = u16(0 - 1);
|
|
||||||
pathfinder->setImpassibleNodeVal(INF);
|
|
||||||
|
|
||||||
int src = 0, dest = cells.size() - 1;
|
int src = 0, dest = cells.size() - 1;
|
||||||
vector<float> heur;
|
vector<float> heur;
|
||||||
vector<int> path = pathfinder->findPath(cells, heur, src, dest);
|
vector<int> path = pathfinder->findPath(cells, heur, src, dest);
|
||||||
@@ -93,8 +91,27 @@ namespace battleship{
|
|||||||
CPPUNIT_ASSERT(sumTime <= threshold);
|
CPPUNIT_ASSERT(sumTime <= threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathfinderTest::testFindShorePath(){
|
||||||
|
int numSideCells = 25;
|
||||||
|
cells = generateCellGraph(numSideCells);
|
||||||
|
|
||||||
|
for(int i = 0; i < numSideCells; i++)
|
||||||
|
cells[numSideCells * i + int(.5 * numSideCells)].type = Map::Cell::WATER;
|
||||||
|
|
||||||
|
vector<float> heur = vector<float>{};
|
||||||
|
vector<int> p1 = pathfinder->findPath(cells, heur, 0, 4, (int)UnitType::LAND);
|
||||||
|
|
||||||
|
int numEdges = cells[p1[p1.size() - 1]].edges.size();
|
||||||
|
//for(int i = 0; i < numEdges; i++){}
|
||||||
|
|
||||||
|
vector<int> p2 = pathfinder->findPath(cells, heur, 2, 4, (int)UnitType::SEA_LEVEL);
|
||||||
|
CPPUNIT_ASSERT(cells[p2[p2.size() - 1]].type == Map::Cell::WATER);
|
||||||
|
}
|
||||||
|
|
||||||
void PathfinderTest::setUp(){
|
void PathfinderTest::setUp(){
|
||||||
pathfinder = Pathfinder::getSingleton();
|
pathfinder = Pathfinder::getSingleton();
|
||||||
|
const u16 INF = u16(0 - 1);
|
||||||
|
pathfinder->setImpassibleNodeVal(INF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathfinderTest::tearDown(){}
|
void PathfinderTest::tearDown(){}
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ namespace battleship{
|
|||||||
CPPUNIT_TEST_SUITE(PathfinderTest);
|
CPPUNIT_TEST_SUITE(PathfinderTest);
|
||||||
CPPUNIT_TEST(testFindPath);
|
CPPUNIT_TEST(testFindPath);
|
||||||
CPPUNIT_TEST(testFindBigPath);
|
CPPUNIT_TEST(testFindBigPath);
|
||||||
|
CPPUNIT_TEST(testFindShorePath);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PathfinderTest(){}
|
PathfinderTest(){}
|
||||||
void testFindPath();
|
void testFindPath();
|
||||||
void testFindBigPath();
|
void testFindBigPath();
|
||||||
|
void testFindShorePath();
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
private:
|
private:
|
||||||
|
|||||||
+3
-5
@@ -371,7 +371,7 @@ namespace battleship{
|
|||||||
bool ship = (type == UnitType::UNDERWATER || type == UnitType::SEA_LEVEL);
|
bool ship = (type == UnitType::UNDERWATER || type == UnitType::SEA_LEVEL);
|
||||||
vector<Map::Cell> &cells = Map::getSingleton()->getCells();
|
vector<Map::Cell> &cells = Map::getSingleton()->getCells();
|
||||||
|
|
||||||
for(int i = 0; i < path.size(); i++){
|
for(int i = 1; i < path.size(); i++){
|
||||||
if((ship && cells[path[i]].type != Map::Cell::WATER) || (order.type != Order::TYPE::GARRISON && type == UnitType::LAND && cells[path[i]].type != Map::Cell::LAND)){
|
if((ship && cells[path[i]].type != Map::Cell::WATER) || (order.type != Order::TYPE::GARRISON && type == UnitType::LAND && cells[path[i]].type != Map::Cell::LAND)){
|
||||||
path = vector<int>(path.begin(), path.begin() + i);
|
path = vector<int>(path.begin(), path.begin() + i);
|
||||||
order.targets[0].unit = nullptr;
|
order.targets[0].unit = nullptr;
|
||||||
@@ -443,13 +443,11 @@ namespace battleship{
|
|||||||
|
|
||||||
vector<float> heurs;
|
vector<float> heurs;
|
||||||
Pathfinder *pf = Pathfinder::getSingleton();
|
Pathfinder *pf = Pathfinder::getSingleton();
|
||||||
vector<int> path = pf->findPath(cells, heurs, source, dest, this);
|
vector<int> path = pf->findPath(cells, heurs, source, dest, (int)type);
|
||||||
|
|
||||||
if(path.empty()) return;
|
if(path.empty() || !truncatePath(order, path, destPos, appendDestPos)) return;
|
||||||
|
|
||||||
path.erase(path.begin());
|
path.erase(path.begin());
|
||||||
|
|
||||||
if(!truncatePath(order, path, destPos, appendDestPos)) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vehicle::removePathpoint(int i){
|
void Vehicle::removePathpoint(int i){
|
||||||
|
|||||||
Reference in New Issue
Block a user