Browse Source

dijkstra impl as prep for travelling salesman algorithm

SlightlyObscure 4 years ago
parent
commit
4d687a67ff

+ 3 - 0
.gitignore

@@ -5,3 +5,6 @@
 build.xml
 .idea/
 manifest.mf
+/out
+path-game.iml
+leons_secret_bug_file.txt

+ 4 - 1
src/pathgame/PathGame.java

@@ -2,6 +2,7 @@ package pathgame;
 
 import me.hammerle.snuviengine.api.IGame;
 import me.hammerle.snuviengine.api.Renderer;
+import pathgame.algorithm.TravellingSalesAlg;
 import pathgame.gameplay.Gamestate;
 import pathgame.gameplay.Gamestates;
 import pathgame.gameplay.Keys;
@@ -23,7 +24,7 @@ public class PathGame implements IGame
     private TileMap map = TileMapGenerator.getMap(50, 50);
 
     private final PlayerRenderer playerRenderer = new PlayerRenderer();
-    private final Player player = new Player(100, 10);
+    private final Player player = new Player(10, 10);
 
     private final Menu menu = new Menu();
     private final MenuRenderer menuRenderer = new MenuRenderer();
@@ -59,6 +60,8 @@ public class PathGame implements IGame
         if(Keys.CONFIRM_KEY.isReleased())
         {
             map = TileMapGenerator.getMap(50, 50);
+
+            TravellingSalesAlg.calcSalesPathLen(map);
         }
     }
 

+ 26 - 0
src/pathgame/algorithm/Coord.java

@@ -0,0 +1,26 @@
+package pathgame.algorithm;
+
+public class Coord {
+    private int x, y;
+
+    Coord(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    int getX() {
+        return x;
+    }
+
+    int getY() {
+        return y;
+    }
+
+    public void changeX(int x) {
+        this.x += x;
+    }
+
+    public void changeY(int y) {
+        this.y += y;
+    }
+}

+ 307 - 0
src/pathgame/algorithm/DijkstraMagic.java

@@ -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();
+    }
+}

+ 7 - 0
src/pathgame/algorithm/ExtraPath.java

@@ -0,0 +1,7 @@
+package pathgame.algorithm;
+
+public class ExtraPath {
+    private int weight;
+    private int destX, destY;
+    private Node2D destNode;
+}

+ 57 - 0
src/pathgame/algorithm/Node2D.java

@@ -0,0 +1,57 @@
+package pathgame.algorithm;
+
+import java.util.ArrayList;
+
+public class Node2D {
+    private int weight;
+    private int costSoFar = Integer.MAX_VALUE;
+    private char prevOfPath = '\0';
+    private boolean isQAdded = false;
+    private boolean hasExtraPaths = false;
+    private ArrayList<ExtraPath> extraPaths = new ArrayList<>();
+
+    public Node2D(int weight) {
+        this.weight = weight;
+    }
+
+    public int getWeight() {
+        return weight;
+    }
+
+    public int getCostSoFar() {
+        return costSoFar;
+    }
+
+    public char getPrevOfPath() {
+        return prevOfPath;
+    }
+
+    public ArrayList<ExtraPath> getExtraPaths() {
+        return extraPaths;
+    }
+
+    public boolean hasExtraPaths() {
+        return hasExtraPaths;
+    }
+
+    public void setCostSoFar(int costSoFar) {
+        this.costSoFar = costSoFar;
+    }
+
+    public void setPrevOfPath(char prevOfPath) {
+        this.prevOfPath = prevOfPath;
+    }
+
+    public void addExtraPath(ExtraPath path) {
+        hasExtraPaths = true;
+        extraPaths.add(path);
+    }
+
+    public boolean isQAdded() {
+        return isQAdded;
+    }
+
+    public void setQAdded(boolean QAdded) {
+        isQAdded = QAdded;
+    }
+}

+ 21 - 0
src/pathgame/algorithm/SaleRoute.java

@@ -0,0 +1,21 @@
+package pathgame.algorithm;
+
+import java.util.ArrayList;
+
+public class SaleRoute {
+    private ArrayList<Coord> path;
+    private int totalCost;
+
+    SaleRoute(ArrayList<Coord> path, int totalCost) {
+        this.path = path;
+        this.totalCost = totalCost;
+    }
+
+    public ArrayList<Coord> getPath() {
+        return path;
+    }
+
+    public int getTotalCost() {
+        return totalCost;
+    }
+}

+ 11 - 0
src/pathgame/algorithm/TravellingSalesAlg.java

@@ -0,0 +1,11 @@
+package pathgame.algorithm;
+
+import pathgame.tilemap.TileMap;
+
+public class TravellingSalesAlg {
+    public static int calcSalesPathLen(TileMap map) {
+        DijkstraMagic dijkstra = new DijkstraMagic(map);
+
+        return 10;
+    }
+}