|
@@ -0,0 +1,307 @@
|
|
|
|
+package pathgame.algorithm;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+import pathgame.gameplay.PlayerAbilities;
|
|
|
|
+import pathgame.tilemap.TileMap;
|
|
|
|
+
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+
|
|
|
|
+public class DijkstraMagic {
|
|
|
|
+ private int townID = -1;
|
|
|
|
+ private ArrayList<Coord> towns = new ArrayList<>();
|
|
|
|
+ private TileMap map;
|
|
|
|
+ private Node2D[][] weightMap;
|
|
|
|
+ private ArrayList<ArrayList<SaleRoute>> salesPitch = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ public DijkstraMagic(TileMap map) {
|
|
|
|
+ this.map = map;
|
|
|
|
+
|
|
|
|
+ //weightMap = new Node2D[map.getWidth()][map.getHeight()];
|
|
|
|
+ weightMap = new Node2D[5][5];
|
|
|
|
+
|
|
|
|
+ setup();
|
|
|
|
+
|
|
|
|
+ for(int i = 0; i < towns.size(); i++) {
|
|
|
|
+ doMagicforTown(i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ printDijkstraResult();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void doMagicforTown(int fromIndex) {
|
|
|
|
+ if(fromIndex != 0) {
|
|
|
|
+ resetWeightMap();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Coord origin = towns.get(fromIndex);
|
|
|
|
+ int posX = origin.getX(), posY = origin.getY();
|
|
|
|
+
|
|
|
|
+ weightMap[posX][posY].setCostSoFar(0);
|
|
|
|
+ weightMap[posX][posY].setQAdded(true);
|
|
|
|
+
|
|
|
|
+ ArrayList<Coord> tileQ = new ArrayList<>();
|
|
|
|
+ tileQ.add(new Coord(posX, posY));
|
|
|
|
+
|
|
|
|
+ while(tileQ.size() > 0) {
|
|
|
|
+ int leastCost = Integer.MAX_VALUE;
|
|
|
|
+ int leastIndex = -1;
|
|
|
|
+
|
|
|
|
+ for(int i = 0; i < tileQ.size(); i++) {
|
|
|
|
+ int iX = tileQ.get(i).getX();
|
|
|
|
+ int iY = tileQ.get(i).getY();
|
|
|
|
+ if(weightMap[iX][iY].getCostSoFar() < leastCost) {
|
|
|
|
+ leastCost = weightMap[iX][iY].getCostSoFar();
|
|
|
|
+ leastIndex = i;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dijkstraOnTile(tileQ.get(leastIndex).getX(), tileQ.get(leastIndex).getY(), tileQ, leastIndex);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ makeListForPitch(fromIndex);
|
|
|
|
+
|
|
|
|
+ printDijkstraMap();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void makeListForPitch(int fromIndex) {
|
|
|
|
+ ArrayList<SaleRoute> listForPitch = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ for(int i = fromIndex+1; i < towns.size(); i++) {
|
|
|
|
+ ArrayList<Coord> listForRoute = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ Coord curPos = new Coord(towns.get(i).getX(), towns.get(i).getY());
|
|
|
|
+
|
|
|
|
+ int totalCost = weightMap[curPos.getX()][curPos.getY()].getCostSoFar();
|
|
|
|
+
|
|
|
|
+ while(true) {
|
|
|
|
+ char dir = weightMap[curPos.getX()][curPos.getY()].getPrevOfPath();
|
|
|
|
+
|
|
|
|
+ listForRoute.add(new Coord(curPos.getX(), curPos.getY()));
|
|
|
|
+
|
|
|
|
+ if(dir == 'n') {
|
|
|
|
+ curPos.changeY(-1);
|
|
|
|
+ }
|
|
|
|
+ else if(dir == 'e') {
|
|
|
|
+ curPos.changeX(1);
|
|
|
|
+ }
|
|
|
|
+ else if(dir == 's') {
|
|
|
|
+ curPos.changeY(1);
|
|
|
|
+ }
|
|
|
|
+ else if(dir == 'w') {
|
|
|
|
+ curPos.changeX(-1);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ listForPitch.add(new SaleRoute(listForRoute, totalCost));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ salesPitch.add(listForPitch);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void dijkstraOnTile(int posX, int posY, ArrayList<Coord> tileQ, int qIndex) {
|
|
|
|
+ int prevCost = weightMap[posX][posY].getCostSoFar();
|
|
|
|
+
|
|
|
|
+ if(posX < weightMap.length-1) {
|
|
|
|
+ checkNeighbor(posX + 1, posY, prevCost, 'w');
|
|
|
|
+ }
|
|
|
|
+ if(posX > 0) {
|
|
|
|
+ checkNeighbor(posX - 1, posY, prevCost, 'e');
|
|
|
|
+ }
|
|
|
|
+ if(posY < weightMap[0].length-1) {
|
|
|
|
+ checkNeighbor(posX, posY + 1, prevCost, 'n');
|
|
|
|
+ }
|
|
|
|
+ if(posY > 0) {
|
|
|
|
+ checkNeighbor(posX, posY - 1, prevCost, 's');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(weightMap[posX][posY].hasExtraPaths()) {
|
|
|
|
+ //TODO: implement extra path stuff
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tileQ.remove(qIndex);
|
|
|
|
+
|
|
|
|
+ if(posX < weightMap.length-1) {
|
|
|
|
+ if(!weightMap[posX+1][posY].isQAdded()) {
|
|
|
|
+ weightMap[posX+1][posY].setQAdded(true);
|
|
|
|
+ tileQ.add(new Coord(posX+1, posY));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(posX > 0) {
|
|
|
|
+ if(!weightMap[posX-1][posY].isQAdded()) {
|
|
|
|
+ weightMap[posX-1][posY].setQAdded(true);
|
|
|
|
+ tileQ.add(new Coord(posX-1, posY));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(posY < weightMap[0].length-1) {
|
|
|
|
+ if(!weightMap[posX][posY+1].isQAdded()) {
|
|
|
|
+ weightMap[posX][posY+1].setQAdded(true);
|
|
|
|
+ tileQ.add(new Coord(posX, posY+1));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(posY > 0) {
|
|
|
|
+ if(!weightMap[posX][posY-1].isQAdded()) {
|
|
|
|
+ weightMap[posX][posY-1].setQAdded(true);
|
|
|
|
+ tileQ.add(new Coord(posX, posY-1));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(weightMap[posX][posY].hasExtraPaths()) {
|
|
|
|
+ //TODO: implement extra path stuff
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void checkNeighbor(int posX, int posY, int prevCost, char origin) {
|
|
|
|
+ int newCost = prevCost + weightMap[posX][posY].getWeight();
|
|
|
|
+
|
|
|
|
+ if(newCost < weightMap[posX][posY].getCostSoFar()) {
|
|
|
|
+ weightMap[posX][posY].setCostSoFar(newCost);
|
|
|
|
+ weightMap[posX][posY].setPrevOfPath(origin);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void resetWeightMap() {
|
|
|
|
+ for(int x = 0; x < weightMap.length; x++) {
|
|
|
|
+ for (int y = 0; y < weightMap[0].length; y++) {
|
|
|
|
+ weightMap[x][y].setCostSoFar(Integer.MAX_VALUE);
|
|
|
|
+ weightMap[x][y].setQAdded(false);
|
|
|
|
+ weightMap[x][y].setPrevOfPath('0');
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void setup() {
|
|
|
|
+ //find towns
|
|
|
|
+ //mock implementation
|
|
|
|
+
|
|
|
|
+ //test start
|
|
|
|
+ towns.add(new Coord(0, 0));
|
|
|
|
+ towns.add(new Coord(2, 3));
|
|
|
|
+ towns.add(new Coord(4, 1));
|
|
|
|
+
|
|
|
|
+ weightMap[0][0] = new Node2D(1);
|
|
|
|
+ weightMap[1][0] = new Node2D(5);
|
|
|
|
+ weightMap[2][0] = new Node2D(1);
|
|
|
|
+ weightMap[3][0] = new Node2D(5);
|
|
|
|
+ weightMap[4][0] = new Node2D(5);
|
|
|
|
+
|
|
|
|
+ weightMap[0][1] = new Node2D(1);
|
|
|
|
+ weightMap[1][1] = new Node2D(10);
|
|
|
|
+ weightMap[2][1] = new Node2D(1);
|
|
|
|
+ weightMap[3][1] = new Node2D(5);
|
|
|
|
+ weightMap[4][1] = new Node2D(1);
|
|
|
|
+
|
|
|
|
+ weightMap[0][2] = new Node2D(1);
|
|
|
|
+ weightMap[1][2] = new Node2D(10);
|
|
|
|
+ weightMap[2][2] = new Node2D(1);
|
|
|
|
+ weightMap[3][2] = new Node2D(1);
|
|
|
|
+ weightMap[4][2] = new Node2D(1);
|
|
|
|
+
|
|
|
|
+ weightMap[0][3] = new Node2D(1);
|
|
|
|
+ weightMap[1][3] = new Node2D(10);
|
|
|
|
+ weightMap[2][3] = new Node2D(1);
|
|
|
|
+ weightMap[3][3] = new Node2D(1);
|
|
|
|
+ weightMap[4][3] = new Node2D(5);
|
|
|
|
+
|
|
|
|
+ weightMap[0][4] = new Node2D(1);
|
|
|
|
+ weightMap[1][4] = new Node2D(1);
|
|
|
|
+ weightMap[2][4] = new Node2D(1);
|
|
|
|
+ weightMap[3][4] = new Node2D(5);
|
|
|
|
+ weightMap[4][4] = new Node2D(5);
|
|
|
|
+
|
|
|
|
+ //test end
|
|
|
|
+
|
|
|
|
+ /*towns.add(new Coord(6, 10));
|
|
|
|
+ towns.add(new Coord(30, 29));
|
|
|
|
+ towns.add(new Coord(41, 20));
|
|
|
|
+ towns.add(new Coord(42, 24));
|
|
|
|
+ towns.add(new Coord(26, 41));
|
|
|
|
+
|
|
|
|
+ towns.add(new Coord(39, 26));
|
|
|
|
+ towns.add(new Coord(16, 8));
|
|
|
|
+ towns.add(new Coord(6, 27));
|
|
|
|
+ towns.add(new Coord(26, 7));
|
|
|
|
+ towns.add(new Coord(28, 13));
|
|
|
|
+
|
|
|
|
+ towns.add(new Coord(49, 4));
|
|
|
|
+ towns.add(new Coord(34, 47));
|
|
|
|
+ towns.add(new Coord(20, 20));
|
|
|
|
+ towns.add(new Coord(43, 32));
|
|
|
|
+ towns.add(new Coord(43, 21));
|
|
|
|
+
|
|
|
|
+ towns.add(new Coord(3, 43));
|
|
|
|
+ towns.add(new Coord(34, 8));
|
|
|
|
+ towns.add(new Coord(30, 17));
|
|
|
|
+ towns.add(new Coord(35, 49));
|
|
|
|
+ towns.add(new Coord(28, 10));*/
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /*for(int x = 0; x < map.getWidth(); x++) {
|
|
|
|
+ for(int y = 0; y < map.getHeight(); y++) {
|
|
|
|
+
|
|
|
|
+ //actual implementation - find towns; townID needs to be set to correct value
|
|
|
|
+
|
|
|
|
+ /*if(map.getTile(x, y).getId() == townID) {
|
|
|
|
+ towns.add(new Coord(x, y));
|
|
|
|
+ }*/
|
|
|
|
+
|
|
|
|
+ //translate map to weightMap
|
|
|
|
+ //TODO: boats
|
|
|
|
+
|
|
|
|
+ /*PlayerAbilities test = new PlayerAbilities(0, 0, 0, 0, 0, 0, 0);
|
|
|
|
+
|
|
|
|
+ weightMap[x][y] = new Node2D(map.getTile(x, y).getEnergyCost(test));
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }*/
|
|
|
|
+
|
|
|
|
+ for(int y = 0; y < weightMap[0].length; y++) {
|
|
|
|
+ for(int x = 0; x < weightMap.length; x++) {
|
|
|
|
+ System.out.print(weightMap[x][y].getWeight() + " ");
|
|
|
|
+ }
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void printDijkstraMap() {
|
|
|
|
+ for(int y = 0; y < weightMap[0].length; y++) {
|
|
|
|
+ for(int x = 0; x < weightMap.length; x++) {
|
|
|
|
+ int cost = weightMap[x][y].getCostSoFar();
|
|
|
|
+ if(cost == Integer.MAX_VALUE) {
|
|
|
|
+ System.out.print("- ");
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+
|
|
|
|
+ System.out.print(cost + " ");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void printDijkstraResult() {
|
|
|
|
+ System.out.println();
|
|
|
|
+
|
|
|
|
+ for(int origNum = 0; origNum < salesPitch.size(); origNum++) {
|
|
|
|
+ for (int lNum = 0; lNum < salesPitch.get(origNum).size(); lNum++) {
|
|
|
|
+ System.out.print("Total Cost: " + salesPitch.get(origNum).get(lNum).getTotalCost() + " ");
|
|
|
|
+
|
|
|
|
+ for (int lInd = 0; lInd < salesPitch.get(origNum).get(lNum).getPath().size(); lInd++) {
|
|
|
|
+ System.out.print(salesPitch.get(origNum).get(lNum).getPath().get(lInd).getX() + "/" + salesPitch.get(origNum).get(lNum).getPath().get(lInd).getY() + " ");
|
|
|
|
+ }
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ System.out.println();
|
|
|
|
+ }
|
|
|
|
+}
|