2 커밋 dc50c564c8 ... 85fe8ad671

작성자 SHA1 메시지 날짜
  Kajetan Johannes Hammerle 85fe8ad671 animation per selected character trait, swimming / boat idle animation 4 년 전
  SlightlyObscure 1b89d43121 added comments to algorithm classes 4 년 전

+ 51 - 8
src/pathgame/algorithm/Coord.java

@@ -1,46 +1,89 @@
 package pathgame.algorithm;
 package pathgame.algorithm;
 
 
+/** Simple class for storing 2D x and y coordinates
+ *
+ */
 public class Coord {
 public class Coord {
     private int x, y;
     private int x, y;
-    private boolean boatTile = false;
+    private boolean isBoatTile = false;
 
 
+    /** Create new coordinate with given x and y value
+     *
+     * @param x position of Coord
+     * @param y position of Coord
+     */
     Coord(int x, int y) {
     Coord(int x, int y) {
         this.x = x;
         this.x = x;
         this.y = y;
         this.y = y;
     }
     }
 
 
-    Coord(int x, int y, boolean boatTile) {
+    /** Creates new cooridnate with given x and y value and sets isBoatTile to given value
+     *
+     * @param x position of Coord
+     * @param y position of Coord
+     * @param isBoatTile set to true if part of a boat path; used for debug purposes
+     */
+    Coord(int x, int y, boolean isBoatTile) {
         this.x = x;
         this.x = x;
         this.y = y;
         this.y = y;
-        this.boatTile = boatTile;
+        this.isBoatTile = isBoatTile;
     }
     }
 
 
-    int getX() {
+    /** Returns x position of Coord
+     *
+     * @return x position
+     */
+    public int getX() {
         return x;
         return x;
     }
     }
 
 
-    int getY() {
+    /** Returns y position of Coord
+     *
+     * @return y position
+     */
+    public int getY() {
         return y;
         return y;
     }
     }
 
 
+    /** Adds given value to x position of Coord
+     *
+     * @param x value to be added to x position
+     */
     public void changeX(int x) {
     public void changeX(int x) {
         this.x += x;
         this.x += x;
     }
     }
 
 
+    /** Adds given value to y position of Coord
+     *
+     * @param y value to be added to y position
+     */
     public void changeY(int y) {
     public void changeY(int y) {
         this.y += y;
         this.y += y;
     }
     }
 
 
+    /** Sets x and y position of Coord to given values
+     *
+     * @param x new x position of Coord
+     * @param y new y position of Coord
+     */
     public void setCoord(int x, int y) {
     public void setCoord(int x, int y) {
         this.x = x;
         this.x = x;
         this.y = y;
         this.y = y;
     }
     }
 
 
+    /** Returns isBoatTile, which is true if Coord is part of a boat path
+     *
+     * @return isBoatTile of Coord
+     */
     public boolean isBoatTile() {
     public boolean isBoatTile() {
-        return boatTile;
+        return isBoatTile;
     }
     }
 
 
-    public void setBoatTile(boolean boatTile) {
-        this.boatTile = boatTile;
+    /** Sets isBoatTile to given value
+     *
+     * @param isBoatTile value isBoatTile gets set to
+     */
+    public void setBoatTile(boolean isBoatTile) {
+        this.isBoatTile = isBoatTile;
     }
     }
 }
 }

+ 12 - 1
src/pathgame/algorithm/DijkstraMagic.java

@@ -1,6 +1,5 @@
 package pathgame.algorithm;
 package pathgame.algorithm;
 
 
-import org.w3c.dom.Node;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.TileType;
 import pathgame.tilemap.TileType;
 import pathgame.tilemap.Tiles;
 import pathgame.tilemap.Tiles;
@@ -8,6 +7,9 @@ import pathgame.tilemap.Tiles;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import pathgame.gameplay.Player;
 import pathgame.gameplay.Player;
 
 
+/** Class that takes a TileMap, finds all towns in it and generates a table of shortest paths between each town using the Dijkstra algorithm
+ *
+ */
 public class DijkstraMagic {
 public class DijkstraMagic {
     private int TOWN_ID = Tiles.TOWN.getId();
     private int TOWN_ID = Tiles.TOWN.getId();
     private int START_ID = Tiles.HOME_TOWN.getId();
     private int START_ID = Tiles.HOME_TOWN.getId();
@@ -19,6 +21,11 @@ public class DijkstraMagic {
     private Node2D[][] weightMap;
     private Node2D[][] weightMap;
     private ArrayList<ArrayList<SaleRoute>> salesPitch = new ArrayList<>();
     private ArrayList<ArrayList<SaleRoute>> salesPitch = new ArrayList<>();
 
 
+    /** Generates a table of shortest paths between each town in the given TileMap
+     *
+     * @param map TileMap that the algorithm should use
+     * @param player that is traversing the map
+     */
     public DijkstraMagic(TileMap map, Player player) {
     public DijkstraMagic(TileMap map, Player player) {
         this.map = map;
         this.map = map;
 
 
@@ -39,6 +46,10 @@ public class DijkstraMagic {
         //printDijkstraResult();
         //printDijkstraResult();
     }
     }
 
 
+    /** Returns the generated table of Dijkstra results
+     *
+     * @return generated table of Dijkstra results
+     */
     public ArrayList<ArrayList<SaleRoute>> getSalesPitch() {
     public ArrayList<ArrayList<SaleRoute>> getSalesPitch() {
         return salesPitch;
         return salesPitch;
     }
     }

+ 58 - 44
src/pathgame/algorithm/ExtraPath.java

@@ -1,44 +1,58 @@
-package pathgame.algorithm;
-
-import java.util.ArrayList;
-
-public class ExtraPath {
-    private int pathWeight;
-    private int destX, destY;
-    private ArrayList<Coord> pathCoords;
-
-    public ExtraPath(int destX, int destY, int pathWeight, ArrayList<Coord> pathCoords) {
-        this.destX = destX;
-        this.destY = destY;
-        this.pathWeight = pathWeight;
-        this.pathCoords = pathCoords;
-    }
-
-    public int getDestX() {
-        return destX;
-    }
-
-    public void setDestX(int destX) {
-        this.destX = destX;
-    }
-
-    public int getDestY() {
-        return destY;
-    }
-
-    public void setDestY(int destY) {
-        this.destY = destY;
-    }
-
-    public int getPathWeight() {
-        return pathWeight;
-    }
-
-    public void setPathWeight(int pathWeight) {
-        this.pathWeight = pathWeight;
-    }
-
-    public ArrayList<Coord> getPathCoords() {
-        return pathCoords;
-    }
-}
+package pathgame.algorithm;
+
+import java.util.ArrayList;
+
+/** Class that stores data on paths to nodes that are not adjacent to each other
+ *
+ */
+public class ExtraPath {
+    private int pathWeight;
+    private int destX, destY;
+    private ArrayList<Coord> pathCoords;
+
+    /** Creates an ExtraPath with the given parameters
+     *
+     * @param destX x position of the other end of the path
+     * @param destY y position of the other end of the path
+     * @param pathWeight total weight of the path
+     * @param pathCoords list of all coordinates that make up the path, in order
+     */
+    public ExtraPath(int destX, int destY, int pathWeight, ArrayList<Coord> pathCoords) {
+        this.destX = destX;
+        this.destY = destY;
+        this.pathWeight = pathWeight;
+        this.pathCoords = pathCoords;
+    }
+
+    /** Returns x position of path destination
+     *
+     * @return x position of path destination
+     */
+    public int getDestX() {
+        return destX;
+    }
+
+    /** Returns y position of path destination
+     *
+     * @return y position of path destination
+     */
+    public int getDestY() {
+        return destY;
+    }
+
+    /** Returns total weight of the path
+     *
+     * @return total weight of the path
+     */
+    public int getPathWeight() {
+        return pathWeight;
+    }
+
+    /** Returns a list of the coordinates that make up the path
+     *
+     * @return coordinates of path
+     */
+    public ArrayList<Coord> getPathCoords() {
+        return pathCoords;
+    }
+}

+ 177 - 96
src/pathgame/algorithm/Node2D.java

@@ -1,96 +1,177 @@
-package pathgame.algorithm;
-
-import pathgame.tilemap.TileType;
-
-import java.util.ArrayList;
-
-public class Node2D {
-    private int weight;
-    private int costSoFar = Integer.MAX_VALUE;
-    private char prevOfPath = '\0';
-    private int prevBoatPath = -1;
-    private TileType type = TileType.LAND;
-    private boolean isQAdded = false;
-    private boolean hasExtraPaths = false;
-    private boolean isBlocked = false;
-    private boolean isTown = 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(Coord dest, int pathWeight, ArrayList<Coord> pathCoords) {
-        hasExtraPaths = true;
-        extraPaths.add(new ExtraPath(dest.getX(), dest.getY(), pathWeight, pathCoords));
-    }
-
-    public boolean isQAdded() {
-        return isQAdded;
-    }
-
-    public void setQAdded(boolean QAdded) {
-        isQAdded = QAdded;
-    }
-
-    public boolean isBlocked() {
-        return isBlocked;
-    }
-
-    public void setBlocked(boolean blocked) {
-        isBlocked = blocked;
-    }
-
-    public TileType getType() {
-        return type;
-    }
-
-    public void setType(TileType type) {
-        this.type = type;
-    }
-
-    public int getPrevBoatPath() {
-        return prevBoatPath;
-    }
-
-    public void setPrevBoatPath(int prevBoatPath) {
-        this.prevBoatPath = prevBoatPath;
-    }
-
-    public boolean isTown() {
-        return isTown;
-    }
-
-    public void setTown(boolean town) {
-        isTown = town;
-    }
-}
+package pathgame.algorithm;
+
+import pathgame.tilemap.TileType;
+
+import java.util.ArrayList;
+
+/** Class for storing node data for the Dijkstra algorithm
+ *
+ */
+public class Node2D {
+    private int weight;
+    private int costSoFar = Integer.MAX_VALUE;
+    private char prevOfPath = '\0';
+    private int prevBoatPath = -1;
+    private TileType type = TileType.LAND;
+    private boolean isQAdded = false;
+    private boolean hasExtraPaths = false;
+    private boolean isBlocked = false;
+    private boolean isTown = false;
+
+    private ArrayList<ExtraPath> extraPaths = new ArrayList<>();
+
+    /** Create new Node2D with given weight
+     *
+     * @param weight cost it takes to travel to this node
+     */
+    public Node2D(int weight) {
+        this.weight = weight;
+    }
+
+    /** Returns the weight of the node
+     *
+     * @return the weight of the node
+     */
+    public int getWeight() {
+        return weight;
+    }
+
+    /** Returns the lowest total cost of travelling to this node from where the algorithm started
+     *
+     * @return lowest cost to get to this node
+     */
+    public int getCostSoFar() {
+        return costSoFar;
+    }
+
+    /** Sets the currently lowest total cost of travelling to this node from where the algorithm started
+     *
+     * @param costSoFar currently lowest cost to get to this node
+     */
+    public void setCostSoFar(int costSoFar) {
+        this.costSoFar = costSoFar;
+    }
+
+    /** Returns a character indicating the previous node of the shortest path from the algorithm's starting point to this node
+     *
+     * @return direction of previous node
+     */
+    public char getPrevOfPath() {
+        return prevOfPath;
+    }
+
+    /** Sets the character indicating the previous node of the shortest path from the algorithm's starting point to this node
+     *
+     * @param prevOfPath direction of previous node
+     */
+    public void setPrevOfPath(char prevOfPath) {
+        this.prevOfPath = prevOfPath;
+    }
+
+    /** Returns the list of all ExtraPaths of this node
+     *
+     * @return list of ExtraPaths
+     */
+    public ArrayList<ExtraPath> getExtraPaths() {
+        return extraPaths;
+    }
+
+    /** Creates an ExtraPath using the given parameters and adds it to the node
+     *
+     * @param dest coordinate of the destination of the path
+     * @param pathWeight total weight to travel this path
+     * @param pathCoords list of coordinates of the path
+     */
+    public void addExtraPath(Coord dest, int pathWeight, ArrayList<Coord> pathCoords) {
+        hasExtraPaths = true;
+        extraPaths.add(new ExtraPath(dest.getX(), dest.getY(), pathWeight, pathCoords));
+    }
+
+    /** Returns hasExtraPaths, which is true, if this node has ExtraPaths
+     *
+     * @return whether node has ExtraPaths
+     */
+    public boolean hasExtraPaths() {
+        return hasExtraPaths;
+    }
+
+    /** Returns isQAdded, which is true, if the node has been added to the queue
+     *
+     * @return whether node has been added to the queue
+     */
+    public boolean isQAdded() {
+        return isQAdded;
+    }
+
+    /** Sets isQAdded, which is true, if the node has been added to the queue
+     *
+     * @param QAdded whether node has been added to the queue
+     */
+    public void setQAdded(boolean QAdded) {
+        isQAdded = QAdded;
+    }
+
+    /** Returns isBlocked, which is true, if this node can't be travelled to from adjacent nodes
+     *
+     * @return whether node is blocked from travel
+     */
+    public boolean isBlocked() {
+        return isBlocked;
+    }
+
+    /** Sets isBlocked, which is true, if this node can't be travelled to from adjacent nodes
+     *
+     * @param blocked whether node is blocked from travel
+     */
+    public void setBlocked(boolean blocked) {
+        isBlocked = blocked;
+    }
+
+    /** Returns the type of the Tile that is represented by this node
+     *
+     * @return the type of the tile
+     */
+    public TileType getType() {
+        return type;
+    }
+
+    /** Sets the type of the Tile that is represented by this node
+     *
+     * @param type the type of the tile
+     */
+    public void setType(TileType type) {
+        this.type = type;
+    }
+
+    /** Returns the index of the the previous ExtraPath
+     *
+     * @return the index of the the previous ExtraPath
+     */
+    public int getPrevBoatPath() {
+        return prevBoatPath;
+    }
+
+    /** Sets the index of the the previous ExtraPath
+     *
+     * @param prevBoatPath the index of the the previous ExtraPath
+     */
+    public void setPrevBoatPath(int prevBoatPath) {
+        this.prevBoatPath = prevBoatPath;
+    }
+
+    /** Returns isTown, which is true if the node is a town
+     *
+     * @return whether node is a town
+     */
+    public boolean isTown() {
+        return isTown;
+    }
+
+    /** Sets isTown, which is true if the node is a town
+     *
+     * @param town whether node is a town
+     */
+    public void setTown(boolean town) {
+        isTown = town;
+    }
+}

+ 79 - 57
src/pathgame/algorithm/OddDegreeList.java

@@ -1,57 +1,79 @@
-package pathgame.algorithm;
-
-import java.util.ArrayList;
-
-public class OddDegreeList {
-    private ArrayList<Integer> items = new ArrayList<>();
-    private ArrayList<Boolean> itemUsed = new ArrayList<>();
-
-    public void add(int vertex) {
-        items.add(vertex);
-        itemUsed.add(false);
-    }
-
-    public int size() {
-        return items.size();
-    }
-
-    public void resetUsed() {
-        for(int i = 0; i < itemUsed.size(); i++) {
-            itemUsed.set(i, false);
-        }
-    }
-
-    public int getUnused(int offSet) {
-        return items.get(getOffsetPos(offSet));
-    }
-
-    public int makeOffsetUsed(int offSet) {
-        int pos = getOffsetPos(offSet);
-        itemUsed.set(pos, true);
-        return pos;
-    }
-
-    public void makePosUsed(int pos) {
-        itemUsed.set(pos, true);
-    }
-
-    public void makeUnused(int pos) {
-        itemUsed.set(pos, false);
-    }
-
-    private int getOffsetPos(int offSet) {
-        int foundValid = 0;
-
-        for (int i = 0; i < items.size(); i++) {
-            if (!itemUsed.get(i)) {
-                if (offSet == foundValid) {
-                    return i;
-                    /*itemUsed.set(i, true);
-                    return items.get(i);*/
-                }
-                foundValid++;
-            }
-        }
-        return -1;
-    }
-}
+package pathgame.algorithm;
+
+import java.util.ArrayList;
+
+/** Class for storing and managing a list of graph vertexes with odd degrees
+ *
+ */
+public class OddDegreeList {
+    private ArrayList<Integer> items = new ArrayList<>();
+    private ArrayList<Boolean> itemUsed = new ArrayList<>();
+
+    /** Adds a vertex to the list
+     *
+     * @param vertex index of the vertex in the list of all vertexes
+     */
+    public void add(int vertex) {
+        items.add(vertex);
+        itemUsed.add(false);
+    }
+
+    /** Returns the size of the list of vertexes
+     *
+     * @return the size of the list of vertexes
+     */
+    public int size() {
+        return items.size();
+    }
+
+    /** Resets which vertexes have already been used for the permutation
+     *
+     */
+    public void resetUsed() {
+        for(int i = 0; i < itemUsed.size(); i++) {
+            itemUsed.set(i, false);
+        }
+    }
+
+    /** Returns the next unused vertex after the given offset
+     *
+     * @param offSet number of unused vertexes that are skipped before returning a vertex
+     * @return the next unused vertex after the offset
+     */
+    public int getUnused(int offSet) {
+        return items.get(getOffsetPos(offSet));
+    }
+
+    /** Makes an unused vertex used after the given offset
+     *
+     * @param offSet number of unused vertexes that are skipped before making the vertex used
+     * @return the index of the vertex that was made used
+     */
+    public int makeOffsetUsed(int offSet) {
+        int pos = getOffsetPos(offSet);
+        itemUsed.set(pos, true);
+        return pos;
+    }
+
+    /** makes the vertex at the given position unused
+     *
+     * @param pos index of the vertex that is made unused
+     */
+    public void makeUnused(int pos) {
+        itemUsed.set(pos, false);
+    }
+
+    private int getOffsetPos(int offSet) {
+        int foundValid = 0;
+
+        for (int i = 0; i < items.size(); i++) {
+            if (!itemUsed.get(i)) {
+                if (offSet == foundValid) {
+                    return i;
+                }
+                foundValid++;
+            }
+        }
+        return -1;
+    }
+}

+ 117 - 92
src/pathgame/algorithm/Permutation.java

@@ -1,92 +1,117 @@
-package pathgame.algorithm;
-
-public class Permutation {
-    private int size;
-    private int[] vals;
-    private int[] minVals;
-    private int minCost = Integer.MAX_VALUE;
-    private int thingsPerPos;
-    private boolean overFlow = false;
-    //public int tempCounter1 = 0;
-    //public int tempCounter2 = 0;
-
-    public Permutation(int listSize, int thingsPerPos) {
-        this.thingsPerPos = thingsPerPos;
-        this.size = (listSize/thingsPerPos) - 1;
-        vals = new int[size];
-
-    }
-
-    public int getValAtPos (int pos) {
-        return vals[pos];
-    }
-
-    public boolean isPosAtMax (int pos) {
-        if(vals[pos] == getMaxOfPos(pos)) {
-            return true;
-        }
-        return false;
-    }
-
-    public int getMaxOfPos (int pos) {
-        return thingsPerPos * (size - pos);
-    }
-
-    public int size() {
-        return size;
-    }
-
-    public void increaseAtPos (int pos) {
-        vals[pos]++;
-        for(int i = pos+1; i < size; i++) {
-            vals[i] = 0;
-        }
-    }
-
-    public void increaseLowest() {
-        boolean over = true;
-
-        for(int i = size-1; i >= 0; i--) {
-            if(getValAtPos(i) < getMaxOfPos(i)) {
-                increaseAtPos(i);
-                over = false;
-                break;
-            }
-        }
-
-        if(over) {
-            overFlow = true;
-        }
-    }
-
-    public int getMinCost() {
-        return minCost;
-    }
-
-    public void setMinCost(int minCost) {
-        this.minCost = minCost;
-        minVals = vals.clone();
-    }
-
-    public void makePermutMinimal() {
-        vals = minVals.clone();
-    }
-
-    public void printPermut() {
-        for(int i = 0; i < size; i++) {
-            System.out.print(vals[i] + " ");
-        }
-        System.out.println();
-    }
-
-    public boolean isOverFlowing() {
-        return overFlow;
-    }
-
-    public void printMinPermut() {
-        for(int i = 0; i < size; i++) {
-            System.out.print(minVals[i] + " ");
-        }
-        System.out.println();
-    }
-}
+package pathgame.algorithm;
+
+/** Class for generating all possible permutations of travelling salesman paths
+ *
+ */
+public class Permutation {
+    private int size;
+    private int[] vals;
+    private int[] minVals;
+    private int minCost = Integer.MAX_VALUE;
+    private int thingsPerPos;
+
+    /** Creates a new Permutation based on the given parameters
+     *
+     * @param listSize size of the list the permutation is for
+     * @param thingsPerPos number of list items per permutation position - for pairs: 2, for single items: 1
+     */
+    public Permutation(int listSize, int thingsPerPos) {
+        this.thingsPerPos = thingsPerPos;
+        this.size = (listSize/thingsPerPos) - 1;
+        vals = new int[size];
+
+    }
+
+    /** Returns the offset stored at the given position
+     *
+     * @param pos position of the permutation from which the value should be returned
+     * @return an offset of the Permutation
+     */
+    public int getValAtPos (int pos) {
+        return vals[pos];
+    }
+
+    /** Returns true if the offset value at the given position can't be increased further
+     *
+     * @param pos position of the permutation that should be checked
+     * @return whether offset at the given position is at its maximum
+     */
+    public boolean isPosAtMax (int pos) {
+        if(vals[pos] == getMaxOfPos(pos)) {
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns the maximum value an offset can have at the given position
+     *
+     * @param pos position of the permutation that should be checked
+     * @return the maximum value an offset can have at the given position
+     */
+    public int getMaxOfPos (int pos) {
+        return thingsPerPos * (size - pos);
+    }
+
+    /** Returns the size of the permutation
+     *
+     * @return the size of the permutation
+     */
+    public int size() {
+        return size;
+    }
+
+    /** Increases the offset at the given position by 1 and sets all offsets of higher positions back to 0
+     *
+     * @param pos position of the permutation that should be increased
+     */
+    public void increaseAtPos (int pos) {
+        vals[pos]++;
+        for(int i = pos+1; i < size; i++) {
+            vals[i] = 0;
+        }
+    }
+
+    /** Returns the minimum cost stored in this Permutation
+     *
+     * @return the minimum cost stored in this Permutation
+     */
+    public int getMinCost() {
+        return minCost;
+    }
+
+    /** Sets the minimum cost stored in this Permutation
+     *
+     * @param minCost the new minimum cost to be set
+     */
+    public void setMinCost(int minCost) {
+        this.minCost = minCost;
+        minVals = vals.clone();
+    }
+
+    /** Makes the current permutation the new minimum permutation to be stored
+     *
+     */
+    public void makePermutMinimal() {
+        vals = minVals.clone();
+    }
+
+    /** Prints the current permutation
+     *
+     */
+    public void printPermut() {
+        for(int i = 0; i < size; i++) {
+            System.out.print(vals[i] + " ");
+        }
+        System.out.println();
+    }
+
+    /** Prints the stored minimum permutation
+     *
+     */
+    public void printMinPermut() {
+        for(int i = 0; i < size; i++) {
+            System.out.print(minVals[i] + " ");
+        }
+        System.out.println();
+    }
+}

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

@@ -1,21 +1,37 @@
-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;
-    }
-}
+package pathgame.algorithm;
+
+import java.util.ArrayList;
+
+/** Class for storing one value of the Dijkstra results table
+ *
+ */
+public class SaleRoute {
+    private ArrayList<Coord> path;
+    private int totalCost;
+
+    /** Creates a new SaleRoute with the given parameters
+     *
+     * @param path the list of coordinates making up this path
+     * @param totalCost the total cost of this path
+     */
+    SaleRoute(ArrayList<Coord> path, int totalCost) {
+        this.path = path;
+        this.totalCost = totalCost;
+    }
+
+    /** Returns a list of coordinates making up this path
+     *
+     * @return a list of coordinates making up this path
+     */
+    public ArrayList<Coord> getPath() {
+        return path;
+    }
+
+    /** Returns the total cost of this path
+     *
+     * @return the total cost of this path
+     */
+    public int getTotalCost() {
+        return totalCost;
+    }
+}

+ 344 - 402
src/pathgame/algorithm/TravellingSalesAlg.java

@@ -1,403 +1,345 @@
-package pathgame.algorithm;
-
-import pathgame.gameplay.Player;
-import pathgame.logging.Logger;
-import pathgame.tilemap.TileMap;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-public class TravellingSalesAlg {
-    public static int calcSalesPathLen(TileMap map, Player player) {
-        DijkstraMagic dijkstra = new DijkstraMagic(map, player);
-
-        ArrayList<ArrayList<SaleRoute>> salesPitch = dijkstra.getSalesPitch();
-
-        //make minimum spanning tree
-        ArrayList<TreeEdge> MSTree = makeMSTree(salesPitch);
-
-        //find pairs-shortest path for verteces with odd degree and add those edges to MSTree
-        ArrayList<TreeEdge> oddDegEdges = makeOddDegEdges(MSTree, salesPitch);
-        MSTree.addAll(oddDegEdges);
-
-        //finde euler tour
-        ArrayList<Integer> eulerTour = getEulerTour(MSTree);
-
-        //cut short
-        cutShort(eulerTour);
-
-        Logger.onAlgoDone(salesPitch, eulerTour);
-
-        //calculate the total weight of the tour using the edge table (salesPitch)
-        int tourWeight = calcTourWeight(eulerTour, salesPitch);
-        System.out.println("min cost: " + tourWeight);
-        return tourWeight;
-
-        //brute force
-        //return bruteForce(salesPitch);
-    }
-
-    private static int calcTourWeight(ArrayList<Integer> tour, ArrayList<ArrayList<SaleRoute>> salesPitch) {
-        int totalWeight = 0;
-
-        for(int i = 0; i < tour.size()-1; i++) {
-            int startNode, endNode;
-
-            if(tour.get(i) < tour.get(i+1)) {
-                startNode = tour.get(i);
-                endNode = tour.get(i+1) - startNode - 1;
-            }
-            else {
-                startNode = tour.get(i+1);
-                endNode = tour.get(i) - startNode - 1;
-            }
-            totalWeight += salesPitch.get(startNode).get(endNode).getTotalCost();
-        }
-        return totalWeight;
-    }
-
-    private static void cutShort(ArrayList<Integer> eulerTour) {
-        int counter = 2;
-
-        while(counter < eulerTour.size()-1) {
-            int current = eulerTour.get(counter);
-
-            boolean found = false;
-
-            for(int i = 0; i < counter; i++) {
-                if(eulerTour.get(i) == current) {
-                    found = true;
-                    break;
-                }
-            }
-
-            if(found) {
-                eulerTour.remove(counter);
-            }
-            else {
-                counter++;
-            }
-        }
-    }
-
-    private static ArrayList<Integer> getEulerTour(ArrayList<TreeEdge> graph) {
-        ArrayList<Integer> tour = new ArrayList<>();
-
-        while (graph.size() > 0) {
-            if(tour.size() == 0) {
-                tour = getSubtour(graph, graph.get(0).getSrc());
-            }
-            else {
-                int start = -1;
-
-                for(int e = 0; e < graph.size(); e++) {
-                    TreeEdge edge = graph.get(e);
-                    for(int tp = 0; tp < tour.size(); tp++) {
-                        if(edge.getSrc() == tour.get(tp)) {
-                            start = edge.getSrc();
-                            break;
-                        }
-                        else if(edge.getDest() == tour.get(tp)) {
-                            start = edge.getDest();
-                            break;
-                        }
-                    }
-                    if(start!= -1) {
-                        break;
-                    }
-                }
-
-                ArrayList<Integer> subTour = getSubtour(graph, start);
-
-                mergeTours(tour, subTour);
-            }
-        }
-
-        return tour;
-    }
-
-    private static ArrayList<Integer> getSubtour(ArrayList<TreeEdge> graph, int start) {
-        ArrayList<Integer> tour = new ArrayList<>();
-        tour.add(start);
-
-        int pos = nextTourEdgePos(graph, start);
-        int next = graph.get(pos).getOtherVertex(start);
-        graph.remove(pos);
-        tour.add(next);
-
-        while (next != start) {
-            pos = nextTourEdgePos(graph, next);
-            next = graph.get(pos).getOtherVertex(next);
-            graph.remove(pos);
-            tour.add(next);
-        }
-
-        return tour;
-    }
-
-    private static int nextTourEdgePos(ArrayList<TreeEdge> graph, int vertex) {
-        for(int i = 0; i < graph.size(); i++) {
-            if(graph.get(i).getSrc() == vertex || graph.get(i).getDest() == vertex) {
-                return i;
-            }
-        }
-
-        return -1;
-    }
-
-    private static void mergeTours(ArrayList<Integer> tour, ArrayList<Integer> subTour) {
-        int mergeTo = subTour.get(0);
-
-        int mergePos = -1;
-
-        for(int i = 0; i < tour.size(); i++) {
-            if (tour.get(i) == mergeTo) {
-                mergePos = i;
-            }
-        }
-
-        for(int i = subTour.size()-1; i > 0; i--) {
-            tour.add(mergePos+1, subTour.get(i));
-        }
-    }
-
-    private static ArrayList<TreeEdge> makeOddDegEdges(ArrayList<TreeEdge> msTree, ArrayList<ArrayList<SaleRoute>> salesPitch) {
-        int numOfEdges[] = new int[salesPitch.size()];
-
-        for (int i = 0; i < msTree.size(); i++) {
-            numOfEdges[msTree.get(i).getSrc()]++;
-            numOfEdges[msTree.get(i).getDest()]++;
-        }
-
-        OddDegreeList oddDegs = new OddDegreeList();
-
-        for (int i = 0; i < numOfEdges.length; i++) {
-            //System.out.println(numOfEdges[i]);
-            if (numOfEdges[i] % 2 == 1) {
-                oddDegs.add(i);
-            }
-        }
-
-        Permutation permut = new Permutation(oddDegs.size(), 2);
-
-        calcPairShortest(oddDegs, salesPitch, permut, 0, 0);
-        permut.makePermutMinimal();
-
-        //System.out.println(permut.tempCounter1);
-        //System.out.println(permut.tempCounter2);
-        //System.out.println("min cost: " + permut.getMinCost());
-        //permut.printPermut();
-
-        ArrayList<TreeEdge> oddEdges = new ArrayList<>();
-        oddDegs.resetUsed();
-        for(int i = 0; i < permut.size(); i++) {
-            int offSet = permut.getValAtPos(i);
-
-            addOddEdge(oddEdges, oddDegs, salesPitch, offSet);
-        }
-
-        addOddEdge(oddEdges, oddDegs, salesPitch, 0);
-
-        return oddEdges;
-    }
-
-    private static void addOddEdge(ArrayList<TreeEdge> oddEdges, OddDegreeList oddDegs, ArrayList<ArrayList<SaleRoute>> salesPitch, int offSet) {
-        int orig = oddDegs.getUnused(0);
-        oddDegs.makeOffsetUsed(0);
-        int dest = oddDegs.getUnused(offSet);
-        oddDegs.makeOffsetUsed(offSet);
-
-        oddEdges.add(new TreeEdge(orig, dest, salesPitch.get(orig).get(dest - orig - 1).getTotalCost()));
-    }
-
-    private static void calcPairShortest(OddDegreeList oddDegs, ArrayList<ArrayList<SaleRoute>> salesPitch, Permutation permut, int permutPos, int costSoFar) {
-        while(true) {
-            int offSet;
-
-            if(permutPos == permut.size()) {
-                offSet = 0;
-            }
-            else {
-                offSet = permut.getValAtPos(permutPos);
-            }
-
-            int orig = oddDegs.getUnused(0);
-            int dest = oddDegs.getUnused(1 + offSet);
-
-            int edgeWeight = salesPitch.get(orig).get(dest - orig - 1).getTotalCost();
-            int newCost = costSoFar + edgeWeight;
-            //permut.tempCounter1++;
-
-            /*System.out.println();
-            System.out.println("permut pos: " + permutPos);
-            System.out.println(orig + " : " + dest);
-            System.out.println("newCost: " + newCost);
-            permut.printPermut();*/
-
-            if(newCost < permut.getMinCost()) {
-                if(permutPos == permut.size()) {
-                    permut.setMinCost(newCost);
-                    /*System.out.println();
-                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-                    System.out.println("New Min: " + newCost);
-                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");*/
-                }
-                else {
-                    int used1 = oddDegs.makeOffsetUsed(0);
-                    int used2 = oddDegs.makeOffsetUsed(offSet);
-                    calcPairShortest(oddDegs, salesPitch, permut, permutPos+1, costSoFar+edgeWeight);
-                    oddDegs.makeUnused(used1);
-                    oddDegs.makeUnused(used2);
-                }
-            }
-
-            if(permutPos == permut.size()) {
-                //permut.tempCounter2++;
-                break;
-            }
-            if(permut.isPosAtMax(permutPos)) {
-                break;
-            }
-
-            permut.increaseAtPos(permutPos);
-        }
-    }
-
-    public static ArrayList<TreeEdge> makeMSTree(ArrayList<ArrayList<SaleRoute>> salesPitch) {
-        ArrayList<TreeEdge> allEdges = new ArrayList<>();
-        ArrayList<TreeEdge> msTree = new ArrayList<>();
-
-        int vertNum = salesPitch.size();
-
-        for (int orig = 0; orig < salesPitch.size(); orig++) {
-            for (int dest = 0; dest < salesPitch.get(orig).size(); dest++) {
-                allEdges.add(new TreeEdge(orig, dest + 1 + orig, salesPitch.get(orig).get(dest).getTotalCost()));
-                //System.out.println(edge.getSrc() + " " + edge.getDest() + " " + edge.getWeight());
-                //System.out.println(salesPitch.get(orig).get(dest).getTotalCost());
-            }
-        }
-
-        //System.out.println(vertNum);
-
-        Collections.sort(allEdges);
-
-        while (msTree.size() < vertNum - 1) {
-
-            if (notCycle(msTree, allEdges.get(0))) {
-                msTree.add(allEdges.get(0));
-                //System.out.println(allEdges.get(0).getSrc() + " " + allEdges.get(0).getDest() + " " + allEdges.get(0).getWeight());
-            }
-            allEdges.remove(0);
-        }
-
-        return msTree;
-    }
-
-    private static void qEdges(ArrayList<TreeEdge> tree, ArrayList<TreeEdge> edgeQ, int vertex) {
-        for(int i = 0; i < tree.size(); i++) {
-            TreeEdge edge = tree.get(i);
-            if(edge.getSrc() == vertex || edge.getDest() == vertex) {
-                if(!edge.isChecked()) {
-                    edgeQ.add(edge);
-                    //System.out.println("src: " + edge.getSrc() + "; dest: " + edge.getDest());
-                    edge.setChecked(true);
-                }
-            }
-        }
-    }
-
-    private static boolean notCycle(ArrayList<TreeEdge> tree, TreeEdge additon) {
-        ArrayList<TreeEdge> edgeQ = new ArrayList<>();
-        int dest = additon.getDest();
-        resetEdges(tree);
-
-        qEdges(tree, edgeQ, additon.getSrc());
-
-        while(edgeQ.size() > 0) {
-            TreeEdge edge = edgeQ.get(0);
-            edgeQ.remove(0);
-            if(edge.getSrc() == dest || edge.getDest() == dest) {
-                return false;
-            }
-            else {
-                qEdges(tree, edgeQ, edge.getSrc());
-                qEdges(tree, edgeQ, edge.getDest());
-            }
-        }
-
-        return true;
-    }
-
-    private static void resetEdges(ArrayList<TreeEdge> tree) {
-        for(int i = 0; i < tree.size(); i++) {
-            tree.get(i).setChecked(false);
-        }
-    }
-
-    /*private static int bruteForce(ArrayList<ArrayList<SaleRoute>> salesPitch) {
-        Permutation permutation = new Permutation(salesPitch.size(), 1);
-        OddDegreeList nodeList = new OddDegreeList();
-        for(int i = 0; i < salesPitch.size()+1; i++) {
-            nodeList.add(i);
-        }
-
-        while(!permutation.isOverFlowing()) {
-            int newSum = bruteSumPermut(permutation, salesPitch, nodeList);
-            if(newSum < permutation.getMinCost()) {
-                permutation.setMinCost(newSum);
-            }
-            /*permutation.printPermut();
-            System.out.println(newSum);
-            System.out.println();*/
-            /*permutation.increaseLowest();
-        }
-        permutation.makePermutMinimal();
-        permutation.printPermut();
-        System.out.println("min cost: " + permutation.getMinCost());
-
-
-        return 0;
-    }
-
-    private static int bruteSumPermut(Permutation permutation, ArrayList<ArrayList<SaleRoute>> salesPitch, OddDegreeList nodeList) {
-        int sum = 0;
-        nodeList.resetUsed();
-
-        int first = -1;
-        int last = -1;
-
-        for(int i = 0; i < permutation.size(); i++) {
-            int pos = nodeList.getUnused(permutation.getValAtPos(i));
-            //System.out.println("pos: " + pos);
-
-            if(first == -1) {
-                first = pos;
-            }
-            else {
-                //System.out.println(last + " - " + pos);
-                sum += bruteWeight(last, pos, salesPitch);
-                //System.out.println(sum);
-            }
-            last = pos;
-
-            nodeList.makePosUsed(pos);
-        }
-        //System.out.println(last + " - " + nodeList.getUnused(0));
-        int pos = nodeList.getUnused(0);
-        sum += bruteWeight(last, pos, salesPitch);
-
-        //System.out.println(pos + " - " + first);
-        sum += bruteWeight(pos, first, salesPitch);
-
-        return sum;
-    }
-
-    private static int bruteWeight(int first, int sec, ArrayList<ArrayList<SaleRoute>> salesPitch) {
-        if(first < sec) {
-            return salesPitch.get(first).get(sec-first-1).getTotalCost();
-        }
-        else {
-            return salesPitch.get(sec).get(first-sec-1).getTotalCost();
-        }
-    }*/
+package pathgame.algorithm;
+
+import pathgame.gameplay.Player;
+import pathgame.logging.Logger;
+import pathgame.tilemap.TileMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/** Class for calculating an approximation of the travelling salesman problem, using the Christofides algorithm
+ *
+ */
+public class TravellingSalesAlg {
+    /** Calculates an approximation of the travelling salesman problem, using the Christofides algorithm
+     *
+     * @param map the TileMap that the algorithm should be used on
+     * @param player that is traversing the map
+     * @return
+     */
+    public static int calcSalesPathLen(TileMap map, Player player) {
+        DijkstraMagic dijkstra = new DijkstraMagic(map, player);
+
+        ArrayList<ArrayList<SaleRoute>> salesPitch = dijkstra.getSalesPitch();
+
+        //make minimum spanning tree
+        ArrayList<TreeEdge> MSTree = makeMSTree(salesPitch);
+
+        //find pairs-shortest path for verteces with odd degree and add those edges to MSTree
+        ArrayList<TreeEdge> oddDegEdges = makeOddDegEdges(MSTree, salesPitch);
+        MSTree.addAll(oddDegEdges);
+
+        //finde euler tour
+        ArrayList<Integer> eulerTour = getEulerTour(MSTree);
+
+        //cut short
+        cutShort(eulerTour);
+
+        Logger.onAlgoDone(salesPitch, eulerTour);
+
+        //calculate the total weight of the tour using the edge table (salesPitch)
+        int tourWeight = calcTourWeight(eulerTour, salesPitch);
+        System.out.println("min cost: " + tourWeight);
+        return tourWeight;
+
+        //brute force
+        //return bruteForce(salesPitch);
+    }
+
+    private static int calcTourWeight(ArrayList<Integer> tour, ArrayList<ArrayList<SaleRoute>> salesPitch) {
+        int totalWeight = 0;
+
+        for(int i = 0; i < tour.size()-1; i++) {
+            int startNode, endNode;
+
+            if(tour.get(i) < tour.get(i+1)) {
+                startNode = tour.get(i);
+                endNode = tour.get(i+1) - startNode - 1;
+            }
+            else {
+                startNode = tour.get(i+1);
+                endNode = tour.get(i) - startNode - 1;
+            }
+            totalWeight += salesPitch.get(startNode).get(endNode).getTotalCost();
+        }
+        return totalWeight;
+    }
+
+    private static void cutShort(ArrayList<Integer> eulerTour) {
+        int counter = 2;
+
+        while(counter < eulerTour.size()-1) {
+            int current = eulerTour.get(counter);
+
+            boolean found = false;
+
+            for(int i = 0; i < counter; i++) {
+                if(eulerTour.get(i) == current) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if(found) {
+                eulerTour.remove(counter);
+            }
+            else {
+                counter++;
+            }
+        }
+    }
+
+    private static ArrayList<Integer> getEulerTour(ArrayList<TreeEdge> graph) {
+        ArrayList<Integer> tour = new ArrayList<>();
+
+        while (graph.size() > 0) {
+            if(tour.size() == 0) {
+                tour = getSubtour(graph, graph.get(0).getSrc());
+            }
+            else {
+                int start = -1;
+
+                for(int e = 0; e < graph.size(); e++) {
+                    TreeEdge edge = graph.get(e);
+                    for(int tp = 0; tp < tour.size(); tp++) {
+                        if(edge.getSrc() == tour.get(tp)) {
+                            start = edge.getSrc();
+                            break;
+                        }
+                        else if(edge.getDest() == tour.get(tp)) {
+                            start = edge.getDest();
+                            break;
+                        }
+                    }
+                    if(start!= -1) {
+                        break;
+                    }
+                }
+
+                ArrayList<Integer> subTour = getSubtour(graph, start);
+
+                mergeTours(tour, subTour);
+            }
+        }
+
+        return tour;
+    }
+
+    private static ArrayList<Integer> getSubtour(ArrayList<TreeEdge> graph, int start) {
+        ArrayList<Integer> tour = new ArrayList<>();
+        tour.add(start);
+
+        int pos = nextTourEdgePos(graph, start);
+        int next = graph.get(pos).getOtherVertex(start);
+        graph.remove(pos);
+        tour.add(next);
+
+        while (next != start) {
+            pos = nextTourEdgePos(graph, next);
+            next = graph.get(pos).getOtherVertex(next);
+            graph.remove(pos);
+            tour.add(next);
+        }
+
+        return tour;
+    }
+
+    private static int nextTourEdgePos(ArrayList<TreeEdge> graph, int vertex) {
+        for(int i = 0; i < graph.size(); i++) {
+            if(graph.get(i).getSrc() == vertex || graph.get(i).getDest() == vertex) {
+                return i;
+            }
+        }
+
+        return -1;
+    }
+
+    private static void mergeTours(ArrayList<Integer> tour, ArrayList<Integer> subTour) {
+        int mergeTo = subTour.get(0);
+
+        int mergePos = -1;
+
+        for(int i = 0; i < tour.size(); i++) {
+            if (tour.get(i) == mergeTo) {
+                mergePos = i;
+            }
+        }
+
+        for(int i = subTour.size()-1; i > 0; i--) {
+            tour.add(mergePos+1, subTour.get(i));
+        }
+    }
+
+    private static ArrayList<TreeEdge> makeOddDegEdges(ArrayList<TreeEdge> msTree, ArrayList<ArrayList<SaleRoute>> salesPitch) {
+        int numOfEdges[] = new int[salesPitch.size()];
+
+        for (int i = 0; i < msTree.size(); i++) {
+            numOfEdges[msTree.get(i).getSrc()]++;
+            numOfEdges[msTree.get(i).getDest()]++;
+        }
+
+        OddDegreeList oddDegs = new OddDegreeList();
+
+        for (int i = 0; i < numOfEdges.length; i++) {
+            //System.out.println(numOfEdges[i]);
+            if (numOfEdges[i] % 2 == 1) {
+                oddDegs.add(i);
+            }
+        }
+
+        Permutation permut = new Permutation(oddDegs.size(), 2);
+
+        calcPairShortest(oddDegs, salesPitch, permut, 0, 0);
+        permut.makePermutMinimal();
+
+        //System.out.println(permut.tempCounter1);
+        //System.out.println(permut.tempCounter2);
+        //System.out.println("min cost: " + permut.getMinCost());
+        //permut.printPermut();
+
+        ArrayList<TreeEdge> oddEdges = new ArrayList<>();
+        oddDegs.resetUsed();
+        for(int i = 0; i < permut.size(); i++) {
+            int offSet = permut.getValAtPos(i);
+
+            addOddEdge(oddEdges, oddDegs, salesPitch, offSet);
+        }
+
+        addOddEdge(oddEdges, oddDegs, salesPitch, 0);
+
+        return oddEdges;
+    }
+
+    private static void addOddEdge(ArrayList<TreeEdge> oddEdges, OddDegreeList oddDegs, ArrayList<ArrayList<SaleRoute>> salesPitch, int offSet) {
+        int orig = oddDegs.getUnused(0);
+        oddDegs.makeOffsetUsed(0);
+        int dest = oddDegs.getUnused(offSet);
+        oddDegs.makeOffsetUsed(offSet);
+
+        oddEdges.add(new TreeEdge(orig, dest, salesPitch.get(orig).get(dest - orig - 1).getTotalCost()));
+    }
+
+    private static void calcPairShortest(OddDegreeList oddDegs, ArrayList<ArrayList<SaleRoute>> salesPitch, Permutation permut, int permutPos, int costSoFar) {
+        while(true) {
+            int offSet;
+
+            if(permutPos == permut.size()) {
+                offSet = 0;
+            }
+            else {
+                offSet = permut.getValAtPos(permutPos);
+            }
+
+            int orig = oddDegs.getUnused(0);
+            int dest = oddDegs.getUnused(1 + offSet);
+
+            int edgeWeight = salesPitch.get(orig).get(dest - orig - 1).getTotalCost();
+            int newCost = costSoFar + edgeWeight;
+            //permut.tempCounter1++;
+
+            /*System.out.println();
+            System.out.println("permut pos: " + permutPos);
+            System.out.println(orig + " : " + dest);
+            System.out.println("newCost: " + newCost);
+            permut.printPermut();*/
+
+            if(newCost < permut.getMinCost()) {
+                if(permutPos == permut.size()) {
+                    permut.setMinCost(newCost);
+                    /*System.out.println();
+                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+                    System.out.println("New Min: " + newCost);
+                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");*/
+                }
+                else {
+                    int used1 = oddDegs.makeOffsetUsed(0);
+                    int used2 = oddDegs.makeOffsetUsed(offSet);
+                    calcPairShortest(oddDegs, salesPitch, permut, permutPos+1, costSoFar+edgeWeight);
+                    oddDegs.makeUnused(used1);
+                    oddDegs.makeUnused(used2);
+                }
+            }
+
+            if(permutPos == permut.size()) {
+                //permut.tempCounter2++;
+                break;
+            }
+            if(permut.isPosAtMax(permutPos)) {
+                break;
+            }
+
+            permut.increaseAtPos(permutPos);
+        }
+    }
+
+    private static ArrayList<TreeEdge> makeMSTree(ArrayList<ArrayList<SaleRoute>> salesPitch) {
+        ArrayList<TreeEdge> allEdges = new ArrayList<>();
+        ArrayList<TreeEdge> msTree = new ArrayList<>();
+
+        int vertNum = salesPitch.size();
+
+        for (int orig = 0; orig < salesPitch.size(); orig++) {
+            for (int dest = 0; dest < salesPitch.get(orig).size(); dest++) {
+                allEdges.add(new TreeEdge(orig, dest + 1 + orig, salesPitch.get(orig).get(dest).getTotalCost()));
+                //System.out.println(edge.getSrc() + " " + edge.getDest() + " " + edge.getWeight());
+                //System.out.println(salesPitch.get(orig).get(dest).getTotalCost());
+            }
+        }
+
+        //System.out.println(vertNum);
+
+        Collections.sort(allEdges);
+
+        while (msTree.size() < vertNum - 1) {
+
+            if (notCycle(msTree, allEdges.get(0))) {
+                msTree.add(allEdges.get(0));
+                //System.out.println(allEdges.get(0).getSrc() + " " + allEdges.get(0).getDest() + " " + allEdges.get(0).getWeight());
+            }
+            allEdges.remove(0);
+        }
+
+        return msTree;
+    }
+
+    private static void qEdges(ArrayList<TreeEdge> tree, ArrayList<TreeEdge> edgeQ, int vertex) {
+        for(int i = 0; i < tree.size(); i++) {
+            TreeEdge edge = tree.get(i);
+            if(edge.getSrc() == vertex || edge.getDest() == vertex) {
+                if(!edge.isChecked()) {
+                    edgeQ.add(edge);
+                    //System.out.println("src: " + edge.getSrc() + "; dest: " + edge.getDest());
+                    edge.setChecked(true);
+                }
+            }
+        }
+    }
+
+    private static boolean notCycle(ArrayList<TreeEdge> tree, TreeEdge additon) {
+        ArrayList<TreeEdge> edgeQ = new ArrayList<>();
+        int dest = additon.getDest();
+        resetEdges(tree);
+
+        qEdges(tree, edgeQ, additon.getSrc());
+
+        while(edgeQ.size() > 0) {
+            TreeEdge edge = edgeQ.get(0);
+            edgeQ.remove(0);
+            if(edge.getSrc() == dest || edge.getDest() == dest) {
+                return false;
+            }
+            else {
+                qEdges(tree, edgeQ, edge.getSrc());
+                qEdges(tree, edgeQ, edge.getDest());
+            }
+        }
+
+        return true;
+    }
+
+    private static void resetEdges(ArrayList<TreeEdge> tree) {
+        for(int i = 0; i < tree.size(); i++) {
+            tree.get(i).setChecked(false);
+        }
+    }
 }
 }

+ 85 - 46
src/pathgame/algorithm/TreeEdge.java

@@ -1,46 +1,85 @@
-package pathgame.algorithm;
-
-public class TreeEdge implements Comparable< TreeEdge > {
-    private int src, dest, weight;
-    private boolean checked = false;
-
-    public TreeEdge(int src, int dest, int weight) {
-        this.src = src;
-        this.dest = dest;
-        this.weight = weight;
-    }
-
-    public int getSrc() {
-        return src;
-    }
-
-    public int getDest() {
-        return dest;
-    }
-
-    public int getOtherVertex(int other) {
-        if(other == src) {
-            return dest;
-        }
-        else  {
-            return src;
-        }
-    }
-
-    public Integer getWeight() {
-        return weight;
-    }
-
-    public boolean isChecked() {
-        return checked;
-    }
-
-    public void setChecked(boolean checked) {
-        this.checked = checked;
-    }
-
-    @Override
-    public int compareTo(TreeEdge o) {
-        return this.getWeight().compareTo(o.getWeight());
-    }
-}
+package pathgame.algorithm;
+
+/** Class that stores data for a graph edge
+ *
+ */
+public class TreeEdge implements Comparable< TreeEdge > {
+    private int src, dest, weight;
+    private boolean checked = false;
+
+    /** Creates a new TreeEdge with the given parameters
+     *
+     * @param src the index of the source vertex of the edge
+     * @param dest the index of the destination vertex of the edge
+     * @param weight the weight of the edge
+     */
+    public TreeEdge(int src, int dest, int weight) {
+        this.src = src;
+        this.dest = dest;
+        this.weight = weight;
+    }
+
+    /** Returns the index of the source vertex of the edge
+     *
+     * @return the index of the source vertex of the edge
+     */
+    public int getSrc() {
+        return src;
+    }
+
+    /** Returns the index of the destination vertex of the edge
+     *
+     * @return the index of the destination vertex of the edge
+     */
+    public int getDest() {
+        return dest;
+    }
+
+    /** Returns the index of the other vertex, using the given vertex
+     *
+     * @param other the vertex index that shouldn't be returned
+     * @return the other vertex index
+     */
+    public int getOtherVertex(int other) {
+        if(other == src) {
+            return dest;
+        }
+        else  {
+            return src;
+        }
+    }
+
+    /** Returns the weight of the edge
+     *
+     * @return the weight of the edge
+     */
+    public Integer getWeight() {
+        return weight;
+    }
+
+    /** Returns isChecked, which is true if the TreeEdge has been checked
+     *
+     * @return whether this TreeEdge has been checked
+     */
+    public boolean isChecked() {
+        return checked;
+    }
+
+    /** Sets isChecked, which is true if the TreeEdge has been checked
+     *
+     * @param checked new status of whether this TreeEdge has been checked
+     */
+    public void setChecked(boolean checked) {
+        this.checked = checked;
+    }
+
+    /** Used for sorting Collections of TreeEdges
+     *
+     * @param o the TreeEdge that this one is being compared to
+     * @return the result of compareTo()
+     */
+    @Override
+    public int compareTo(TreeEdge o) {
+        return this.getWeight().compareTo(o.getWeight());
+    }
+}

+ 21 - 0
src/pathgame/gameplay/Facing.java

@@ -0,0 +1,21 @@
+package pathgame.gameplay;
+
+public enum Facing
+{
+    NORTH(3), 
+    EAST(2), 
+    SOUTH(0), 
+    WEST(1);
+    
+    private final int index;
+    
+    private Facing(int index)
+    {
+        this.index = index;
+    }
+    
+    public int getIndex()
+    {
+        return index;
+    }
+}

+ 33 - 1
src/pathgame/gameplay/Player.java

@@ -5,6 +5,7 @@ import java.util.LinkedList;
 import pathgame.logging.Logger;
 import pathgame.logging.Logger;
 import pathgame.tilemap.Tile;
 import pathgame.tilemap.Tile;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.TileMap;
+import pathgame.tilemap.Tiles;
 
 
 /**
 /**
  * A container for holding everything about the player
  * A container for holding everything about the player
@@ -15,6 +16,8 @@ public class Player
 {
 {
     private static final float SPEED = 0.25f;
     private static final float SPEED = 0.25f;
 
 
+    private int ticksLived = 0;
+
     private PlayerAbilities abilities = PlayerAbilities.NORMAL;
     private PlayerAbilities abilities = PlayerAbilities.NORMAL;
 
 
     private float lastX = 0;
     private float lastX = 0;
@@ -34,7 +37,9 @@ public class Player
     private int objectivesAmount;
     private int objectivesAmount;
     private int objectivesVisited = 0;
     private int objectivesVisited = 0;
     private final LinkedList<MinusStepsValues> steps = new LinkedList<>();
     private final LinkedList<MinusStepsValues> steps = new LinkedList<>();
-    private Tile currentTile;// = Tiles.GRASS;
+    private Tile currentTile = Tiles.HOME_TOWN;
+    
+    private Facing facing = Facing.SOUTH;
 
 
     /**
     /**
      * Constructor of the player
      * Constructor of the player
@@ -104,6 +109,7 @@ public class Player
      */
      */
     public void tick(TileMap map)
     public void tick(TileMap map)
     {
     {
+        ticksLived++;
         tickSteps();
         tickSteps();
 
 
         int currentTileX = Math.round(x);
         int currentTileX = Math.round(x);
@@ -131,6 +137,7 @@ public class Player
 
 
         if(Keys.LEFT_KEY.isDown() && !isMoving && currentTileX > 0 && !map.getTile(currentTileX - 1, currentTileY).isBlockingMovement(this))
         if(Keys.LEFT_KEY.isDown() && !isMoving && currentTileX > 0 && !map.getTile(currentTileX - 1, currentTileY).isBlockingMovement(this))
         {
         {
+            facing = Facing.WEST;
             velX = -SPEED;
             velX = -SPEED;
             isMoving = true;
             isMoving = true;
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
@@ -138,6 +145,7 @@ public class Player
         }
         }
         else if(Keys.RIGHT_KEY.isDown() && !isMoving && currentTileX < map.getWidth() - 1 && !map.getTile(currentTileX + 1, currentTileY).isBlockingMovement(this))
         else if(Keys.RIGHT_KEY.isDown() && !isMoving && currentTileX < map.getWidth() - 1 && !map.getTile(currentTileX + 1, currentTileY).isBlockingMovement(this))
         {
         {
+            facing = Facing.EAST;
             velX = SPEED;
             velX = SPEED;
             isMoving = true;
             isMoving = true;
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
@@ -145,6 +153,7 @@ public class Player
         }
         }
         else if(Keys.UP_KEY.isDown() && !isMoving && currentTileY > 0 && !map.getTile(currentTileX, currentTileY - 1).isBlockingMovement(this))
         else if(Keys.UP_KEY.isDown() && !isMoving && currentTileY > 0 && !map.getTile(currentTileX, currentTileY - 1).isBlockingMovement(this))
         {
         {
+            facing = Facing.NORTH;
             velY = -SPEED;
             velY = -SPEED;
             isMoving = true;
             isMoving = true;
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
@@ -152,6 +161,7 @@ public class Player
         }
         }
         else if(Keys.DOWN_KEY.isDown() && !isMoving && currentTileY < map.getHeight() - 1 && !map.getTile(currentTileX, currentTileY + 1).isBlockingMovement(this))
         else if(Keys.DOWN_KEY.isDown() && !isMoving && currentTileY < map.getHeight() - 1 && !map.getTile(currentTileX, currentTileY + 1).isBlockingMovement(this))
         {
         {
+            facing = Facing.SOUTH;
             velY = SPEED;
             velY = SPEED;
             isMoving = true;
             isMoving = true;
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
             Logger.onTileLeave(this, map, currentTileX, currentTileY);
@@ -386,6 +396,8 @@ public class Player
      */
      */
     public void reset(int sx, int sy, int energySupply, int objectivesAmount)
     public void reset(int sx, int sy, int energySupply, int objectivesAmount)
     {
     {
+        ticksLived = 0;
+
         lastX = sx;
         lastX = sx;
         lastY = sy;
         lastY = sy;
         x = sx;
         x = sx;
@@ -455,4 +467,24 @@ public class Player
     {
     {
         return currentTile;
         return currentTile;
     }
     }
+
+    /**
+     * Returns how much ticks this player is alive.
+     *
+     * @return how much ticks this player is alive
+     */
+    public int getTicksLived()
+    {
+        return ticksLived;
+    }
+    
+    /**
+     * Returns the direction the player is facing.
+     *
+     * @return the direction the player is facing
+     */
+    public Facing getFacing()
+    {
+        return facing;
+    }
 }
 }

+ 45 - 4
src/pathgame/rendering/PlayerRenderer.java

@@ -2,9 +2,11 @@ package pathgame.rendering;
 
 
 import me.hammerle.snuviengine.api.Renderer;
 import me.hammerle.snuviengine.api.Renderer;
 import me.hammerle.snuviengine.api.Texture;
 import me.hammerle.snuviengine.api.Texture;
+import pathgame.gameplay.Facing;
 import pathgame.gameplay.Player;
 import pathgame.gameplay.Player;
+import pathgame.gameplay.PlayerAbilities;
 import pathgame.tilemap.TileMap;
 import pathgame.tilemap.TileMap;
-import pathgame.tilemap.Tiles;
+import pathgame.tilemap.TileRenderType;
 
 
 /**
 /**
  * A container for holding everything about the renderer for the player
  * A container for holding everything about the renderer for the player
@@ -14,6 +16,10 @@ import pathgame.tilemap.Tiles;
 public class PlayerRenderer
 public class PlayerRenderer
 {
 {
     private static final Texture CHARACTER = new Texture("resources/character.png");
     private static final Texture CHARACTER = new Texture("resources/character.png");
+    private static final Texture CHARACTER_HIKER = new Texture("resources/hiker.png");
+    private static final Texture CHARACTER_HUNTER = new Texture("resources/hunter.png");
+    private static final Texture CHARACTER_SAILOR = new Texture("resources/sailor.png");
+    private static final Texture CHARACTER_SWIMMER = new Texture("resources/swimmer.png");
 
 
     /**
     /**
      * Recalculates the rendering positions and settings of the menu-elements on
      * Recalculates the rendering positions and settings of the menu-elements on
@@ -29,6 +35,7 @@ public class PlayerRenderer
      */
      */
     public void renderTick(TileMap map, TileMapRenderer mapR, Renderer r, Player p, float lag, float offX, float offY)
     public void renderTick(TileMap map, TileMapRenderer mapR, Renderer r, Player p, float lag, float offX, float offY)
     {
     {
+        boolean inWater = p.getCurrTile().getRenderType() == TileRenderType.WATER;
         float playerSize = mapR.getScale() * TileRenderer.TILE_SIZE;
         float playerSize = mapR.getScale() * TileRenderer.TILE_SIZE;
 
 
         r.setMixColorEnabled(false);
         r.setMixColorEnabled(false);
@@ -52,7 +59,8 @@ public class PlayerRenderer
         float xTexOff = 0;
         float xTexOff = 0;
         float yTexOff = 0;
         float yTexOff = 0;
 
 
-        CHARACTER.bind();
+        bindTexture(p, inWater);
+        
         if(p.getVelX() > 0)
         if(p.getVelX() > 0)
         {
         {
             //go right
             //go right
@@ -80,14 +88,19 @@ public class PlayerRenderer
         else
         else
         {
         {
             //stand still
             //stand still
-            yIndex = 0;
+            yIndex = p.getFacing().getIndex();
+            // idle animation on water
+            if(inWater && (p.getTicksLived() % 20) < 10)
+            {
+                tIndex = 1;
+            }
         }
         }
 
 
         if(p.isSailing())
         if(p.isSailing())
         {
         {
             yTexOff = 0.5f;
             yTexOff = 0.5f;
         }
         }
-        else if(p.getCurrTile() == Tiles.SHALLOW_WATER)
+        else if(inWater)
         {
         {
             xTexOff = 0.5f;
             xTexOff = 0.5f;
         }
         }
@@ -105,4 +118,32 @@ public class PlayerRenderer
     {
     {
         return ((int) (base * 4 * 2)) % 4;
         return ((int) (base * 4 * 2)) % 4;
     }
     }
+    
+    private void bindTexture(Player p, boolean inWater)
+    {
+        if(p.isSailing() || inWater || p.getAbilities() == PlayerAbilities.NORMAL)
+        {
+            CHARACTER.bind();
+        }
+        else if(p.getAbilities() == PlayerAbilities.HIKER)
+        {
+            CHARACTER_HIKER.bind();
+        }
+        else if(p.getAbilities() == PlayerAbilities.HUNTER)
+        {
+            CHARACTER_HUNTER.bind();
+        }
+        else if(p.getAbilities() == PlayerAbilities.SAILOR)
+        {
+            CHARACTER_SAILOR.bind();
+        }
+        else if(p.getAbilities() == PlayerAbilities.SWIMMER)
+        {
+            CHARACTER_SWIMMER.bind();
+        }
+        else
+        {
+            CHARACTER.bind();
+        }
+    }
 }
 }