Floyds Algorithm for path finding

I'm currently trying to figure out which path finding algorithm to use in my game. It seems most people prefer A* and I don't quite get it.
I must be missing something because as I see it Floyds Algorithm is superior in many respects.
1) You are guaranteed to get an optimal rout.
2) It's all precomputed, so you just have to look up the rout in a matrix.
What am I missing ?
Kim

A* is guaranteed to find the shortest path, as long as the function you use for the heuristic is an underestimate of the actual distance. For example, say you have a square grid where some tiles are blocked by obstacles while others aren't; then you can use the Euclidean distance (sqrt(deltaX^2 + deltaY^2)) between two tiles as your heuristic, since real paths will be as long as that, and A* will find the shortest path. Even if you use an overestimate for a heuristic, A* will find some path if a path exists; it will find it faster in fact, but it won't necessarily be the best path. Often people use overestimates on purpose in practice because this saves a lot of time and still finds pretty good paths.
Floyd's algorithm has a worse running-time than A* because A* can get "hints" of which direction to go towards while Floyd's essentially checks all possibilities. It's true that you can use it to obtain the all-pairs shortest-paths matrix however, in which case it is certainly faster than using A* on every pair of points to find the path between them (since the heuristic only gives distance to one goal). The problem is that in most games the world changes at run-time however - for example someone builds a building or chops down a tree, or someone blocks a door, or there are people in the AI object's way. Also, sometimes you try to find the path that is not shortest but also "safest" in some way - increase costs of tiles where you've seen a lot of enemy activity for example in order to avoid them, and this information changes at runtime. Recalculating the all-pairs shortest-paths matrix gets expensive then, especially in the case of moving obstacles like human players. If you have a game where the obstacles are fixed however and the map size isn't so big that an N^3 algorithm (Floyd) wouldn't do it, then do precalculate the paths.

Similar Messages

  • Solution: A-Star Path Finding Algorithm (games)

    Hello everyone. I have developed several A-Star implementations for games, if you come across anyone with questions relating to path finding, please direct them to [email protected]

    I'll also be directing several rich Nigerians who need your help, too, if that is OK.

  • Path finding based on an image

    I know its possible to create a path finding algorithm based on an image... That is, if the color map is blue then there is water, if it is brown then there is land. So detection of land and water is not the problem.
    What I want to know is, is there an easy way to set up a path finder aside having a for loop try all the possibilities? The loop should follow logical paths rather than iterate through each turn...

    I'd try an image processing forum. This forum is typically for Java-specific issues and there might not be that many people who've done this here. Sorry I couldn't help. Have you read some image processing books?

  • Path Finder in a 2D Grid Map With Different Terrain Types

         I have been thinking for a while on path finding game algoritms and I can up with one idea witch I want to publish. The goal of my project is when I have a 2 dimensional grid map where squares can have different movement cost, like in Civilization II, to find the shortest way from one point in the map to another. I've used the Breathed First Search Engine. If you are not familiar to this search engine it is better to read about it first because I am not fcusing on it and I assume that you now how it works. You can read about it at the book "Practical Artificial Intelligence Programming in Java" writen by Mark Watson, witch is freely distributed at www.markwatson.com.
         Actually the idea of this 2D grid path finder is to use a third dimension witch have a size equal to the highest movement cost among all terrain types. This helps solving the problem with the different movement cost of the squates. By adding this abstract third dimension it is posible to use the Breadth First Search Engine.
         I this example the movementcost of a terrain type is always the same, no matter from witch square to with are you going (like in Civilization II but I haven't included roads or railroads). For example if you want to go from one square A to another square B with movement cost X (A and B are attached) you must go "up stairs" in the third dimension X - 1 times and then move to square B. But when you step on square B you are again at the lowest floor. So if you want to come back to the previous square A and it have movement cost Y first you must go floor Y and then jump in square A. And now you are again at the lowest floor at square A. When you move from one square to another you go always at the lowest floor. This is the way I handle with different movement costs.
         When you find the path to the goal point it is in 3 dimensions. So you must just project it in the 2D map and that's all you have the shortest path.
         I am sure this is not the best way to code this search engine but this is just the first scratch with no optimisation and so on. If I make a 100x100 randomly generated map it takes on my configuration(400Mhz Pentium II CPU with ASUS P2B MotherBoard on 100 MHz and 256 MB SD RAM on 133 MHz but because of my MB on 100MHz) around 1000 miliseconds (1000 miliseconds = 1 second) to find the shortest path from (1, 1) to (100, 100) witch is pretty good compare to the goTo function in Civilization II witch does not finds the shortest path at all and have made hundrets of gamers angry. This is amazing that nowadays there are so many games with bad path finding.
         This project includes:
    1. The PathFinder class witch does the jub.
    2. The Map class witch has a generator for a random map in it.
    3. The class TerrainType, every square on the map is based on this class.
    4. The class TerrainTypes witch is the set of all terrain types used in the map.
    5. The class PathFinderTest witch just test the path finder.
    To test this project put all files in one directory and run PathFinderTest.java.
    Map.java:
    import java.util.Vector;
    import java.util.Random;
    //This class just creates a random map and keeps it. I will not comment on this.
    class Map {
      //here is kept the information about the terrain types placed in the map. Where
      //every terrain type has a specific movement cost.
      private int[][] terrain;
      public TerrainTypes terrainTypes;
      private int landMass;
      private int width;
      private int height;
      private int highestMovementCost;
      public Map(int aWidth, int aHeight) {
        width = aWidth;
        height = aHeight;
        terrainTypes = new TerrainTypes();
        highestMovementCost = terrainTypes.getHighestMovementCost();
        terrain = new int[width][height];
        landMass = 0;
        generateRandomMap();
      public void clearGoalAndStartLocFromWater(int sx, int sy, int gx, int gy) {
        terrain[gx][gy] = 0;
        terrain[sx][sy] = 0;
      private void expandWater() {
        int waterConstant = 40;
        int waterExpansion = 2;
        int[][] moreWater = new int[width][height];
        Random randomizer = new Random();
        for (int t = 0; waterExpansion > t; t++) {
          for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
              if (i + 1 >= 0 && j >= 0 && i + 1 < width && j < height) {
                if (terrain[i + 1][j] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i + 1][j] = 1;
              if (i + 1 >= 0 && j - 1 >= 0 && i + 1 < width && j - 1 < height) {
                if (terrain[i + 1][j - 1] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i + 1][j - 1] = 1;
              if (i >= 0 && j - 1 >= 0 && i < width && j - 1 < height) {
                if (terrain[i][j - 1] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i][j - 1] = 1;
              if (i - 1 >= 0 && j - 1 >= 0 && i - 1 < width && j - 1 < height) {
                if (terrain[i - 1][j - 1] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i - 1][j - 1] = 1;
              if (i - 1 >= 0 && j >= 0 && i - 1 < width && j < height) {
                if (terrain[i - 1][j] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i - 1][j] = 1;
              if (i - 1 >= 0 && j + 1 >= 0 && i - 1 < width && j + 1 < height) {
                if (terrain[i - 1][j + 1] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i - 1][j + 1] = 1;
              if (i >= 0 && j + 1 >= 0 && i < width && j + 1 < height) {
                if (terrain[i][j + 1] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i][j + 1] = 1;
              if (i + 1 >= 0 && j + 1 >= 0 && i + 1 < width && j + 1 < height) {
                if (terrain[i + 1][j + 1] != 4) {
                  if (randomizer.nextInt(waterConstant) == 0)
                    moreWater[i + 1][j + 1] = 1;
        for (int i = 0; i < width; i++) {
          for (int j = 0; j < height; j++) {
            if (moreWater[i][j] == 1) {
              terrain[i][j] = 4;
      private void generateRandomMap() {
        Random randomizer = new Random();
        for (int i = 0; i < width; i++) {
          for (int j = 0; j < height; j++) {
            if (randomizer.nextInt(3) == 1)
              terrain[i][j] = 0;
            else if (randomizer.nextInt(2) == 1)
              terrain[i][j] = 1;
            else if (randomizer.nextInt(2) == 1)
              terrain[i][j] = 3;
            else if (randomizer.nextInt(2) == 1)
              terrain[i][j] = 2;
            else if (randomizer.nextInt(2) == 1)
              terrain[i][j] = 2;
            else if (randomizer.nextInt(2) == 1)
              terrain[i][j] = 1;
            else if (randomizer.nextInt(2) == 1)
              terrain[i][j] = 3;
            else
              terrain[i][j] = randomizer.nextInt(5);
        expandWater();
        for (int i = 0; i < width; i++) {
          for (int j = 0; j < height; j++) {
            if (terrain[i][j] != 0)
              landMass++;
      public int getMapHeight() {
        return height;
      public int getMapWidth() {
        return width;
      public int getSquareID(int x, int y) {
        return terrain[x][y];
      public int getSquareMovementCost(int x, int y) {
        return terrainTypes.getMovementCost(terrain[x][y]);
    }PathFinder.java:
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Vector;
    public class PathFinder {
      private BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
      //The array t3D[][] represents the 2D square map where t3D.leght = map width
      //and t3D[x].lenght = map width (-1 < x < t3D.leght). The third dimension
      //is refered to the square's movement cost, witch is definite by terrain.
      //The fourth dimension will be with lenght = 3. When running the search engine
      //(expanding the explored squares) this 3 values will keep the position of
      //the previous square in 3 dimension, witch are width, height and the maximum
      //movement cost among all squares.
      private int[][][][] squares3DReference;
      //Keeps information witch squares are visited.
      private boolean[][][] visitedSquares;
      private Map map;
      //this is the queue used in the Breathed First Seatch.
      private Vector queue3D;
      //Here is saved the shortest path
      private Vector path2D;
      private int highestMovementCost;
      public PathFinder(Map aMap) {
        map = aMap;
        queue3D = new Vector();
        path2D = new Vector();
        squares3DReference = new int[map.getMapWidth()][map.getMapHeight()][][];
        visitedSquares = new boolean[map.getMapWidth()][map.getMapHeight()][];
        highestMovementCost = map.terrainTypes.getHighestMovementCost();
        buildAbstract3DTerrain();
      private void buildAbstract3DTerrain() {
        for (int x = 0; x < map.getMapWidth(); x++) {
          for (int y = 0; y <map.getMapHeight(); y++) {
            int movementCost = map.terrainTypes.getMovementCost(map.getSquareID(x, y));
            if ( movementCost > 0) {
              visitedSquares[x][y] = new boolean[highestMovementCost];
              squares3DReference[x][y] = new int[highestMovementCost][3];
              for (int z = 0; z < highestMovementCost; z++) {
                for (int t = 0; t < 3; t++) {
                  squares3DReference[x][y][z][t] = -1;
      private boolean isMoveValid(int x, int y, int z, int x2, int y2, int z2) {
        if ( x < 0 || y < 0 || z < 0 || x2 < 0 || y2 < 0 || z2 < 0 || x >= map.getMapWidth() || y >= map.getMapHeight() || z >= highestMovementCost ||  x2 >= map.getMapWidth() || y2 >= map.getMapHeight() || z2 >= highestMovementCost)
          return false;
        if (map.terrainTypes.getMovementCost(map.getSquareID(x2, y2)) < 1)
          return false;
        if (visitedSquares[x2][y2][z2])
          return false;
        if (x == x2 && y == y2)
          return true;
        else {
          if (z == map.terrainTypes.getMovementCost(map.getSquareID(x2, y2)) - 1)
            return true;
          else
            return false;
      private void clearPreviousSearchData() {
        queue3D.clear();
        path2D.clear();
        for (int x = 0; x < map.getMapWidth(); x++) {
          for (int y = 0; y < map.getMapHeight(); y++) {
            if (squares3DReference[x][y] != null) {
              for (int z = 0; z < highestMovementCost; z++) {
                visitedSquares[x][y][z] = false;
                for (int t = 0; t < 3; t++) {
                  squares3DReference[x][y][z][t] = -1;
      private Vector copyPath2D() {
        Vector path = new Vector();
        for (int i = 0; i < path2D.size(); i++) {
          path.add(path2D.get(i));
        return path;
      public Vector findPath(int sX, int sY, int gX, int gY) {
        int head = 0;
        int tail = 0;
        int x = sX;
        int y = sY;
        int z = 0;
        visitedSquares[x][y][z] = true;
        mainLoop: {
          while (tail <= head) {
            int[][] moves = getPosibleMoves(x, y, z);
            for (int i = 0; i < 9; i++) {
              if (moves[i] != null) {
                squares3DReference[moves[0]][moves[i][1]][moves[i][2]][0] = x;
    squares3DReference[moves[i][0]][moves[i][1]][moves[i][2]][1] = y;
    squares3DReference[moves[i][0]][moves[i][1]][moves[i][2]][2] = z;
    queue3D.add(moves[i]);
    if (moves[i][0] == gX && moves[i][1] == gY) {
    break mainLoop;
    visitedSquares[moves[i][0]][moves[i][1]][moves[i][2]] = true;
    head++;
    if (queue3D.size() == 0 || queue3D.size() == tail)
    break mainLoop;
    int[] nextInQueue = ((int[]) queue3D.get(tail));
    x = nextInQueue[0];
    y = nextInQueue[1];
    z = nextInQueue[2];
    tail++;
    if (squares3DReference[gX][gY][0][0] == -1) {
    clearPreviousSearchData();
    return path2D;
    fillpath2D(sX, sY, gX, gY);
    Vector path = copyPath2D();
    clearPreviousSearchData();
    return path;
    private int[][] getPosibleMoves(int x, int y, int z) {
    int[][] moves = new int[9][3];
    if (isMoveValid(x, y, z, x + 1, y, 0)) {
    moves[0][0] = x + 1;
    moves[0][1] = y;
    moves[0][2] = 0;
    else
    moves[0] = null;
    if (isMoveValid(x, y, z, x + 1, y - 1, 0)) {
    moves[1][0] = x + 1;
    moves[1][1] = y - 1;
    moves[1][2] = 0;
    else
    moves[1] = null;
    if (isMoveValid(x, y, z, x, y - 1, 0)) {
    moves[2][0] = x;
    moves[2][1] = y - 1;
    moves[2][2] = 0;
    else
    moves[2] = null;
    if (isMoveValid(x, y, z, x - 1, y - 1, 0)) {
    moves[3][0] = x - 1;
    moves[3][1] = y - 1;
    moves[3][2] = 0;
    else
    moves[3] = null;
    if (isMoveValid(x, y, z, x - 1, y, 0)) {
    moves[4][0] = x - 1;
    moves[4][1] = y;
    moves[4][2] = 0;
    else
    moves[4] = null;
    if (isMoveValid(x, y, z, x - 1, y + 1, 0)) {
    moves[5][0] = x - 1;
    moves[5][1] = y + 1;
    moves[5][2] = 0;
    else
    moves[5] = null;
    if (isMoveValid(x, y, z, x, y + 1, 0)) {
    moves[6][0] = x;
    moves[6][1] = y + 1;
    moves[6][2] = 0;
    else
    moves[6] = null;
    if (isMoveValid(x, y, z, x + 1, y + 1, 0)) {
    moves[7][0] = x + 1;
    moves[7][1] = y + 1;
    moves[7][2] = 0;
    else
    moves[7] = null;
    if (isMoveValid(x, y, z, x, y, z + 1)) {
    moves[8][0] = x;
    moves[8][1] = y;
    moves[8][2] = z + 1;
    else
    moves[8] = null;
    return moves;
    private void fillpath2D(int sX, int sY, int gX, int gY) {
    int[] gLoc = {gX, gY};
    path2D.add(gLoc);
    int x = gX;
    int y = gY;
    int z = 0;
    while (x != sX || y != sY) {
    int x2 = squares3DReference[x][y][z][0];
    int y2 = squares3DReference[x][y][z][1];
    int z2 = squares3DReference[x][y][z][2];
    x = x2;
    y = y2;
    z = z2;
    if (z == 0) {
    int[] loc = {x, y};
    path2D.insertElementAt(loc, 0);
    PathFinderTest.java
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Vector;
    public class PathFinderTest {
      static BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
      static Map map;
      static int startX;
      static int startY;
      static int goalX;
      static int goalY;
      public static void main(String[] args) throws Exception {
        System.out.print("Enter map size.\nx = ");
        int width = Integer.parseInt(consoleReader.readLine());
        System.out.print("y = ");
        int height = Integer.parseInt(consoleReader.readLine());
        System.out.print("Enter strting location.\nx = ");
        startX = Integer.parseInt(consoleReader.readLine()) - 1;
        System.out.print("y = ");
        startY = Integer.parseInt(consoleReader.readLine()) - 1;
        System.out.print("Enter goal location.\nx = ");
        goalX = Integer.parseInt(consoleReader.readLine()) - 1;
        System.out.print("y = ");
        goalY = Integer.parseInt(consoleReader.readLine()) - 1;
        if (goalX < 0 || goalY < 0 || startX < 0 || startY < 0 || goalX >= width || goalY >= height || startX >= width || startY >= height) {
          System.out.println("Invalid parameters found. Program will exit");
          System.exit(0);
        map = new Map(width, height);
        map.clearGoalAndStartLocFromWater(startX, startY, goalX, goalY);
        printSolution(new Vector());
        PathFinder pathFinder = new PathFinder(map);
        long before = System.currentTimeMillis();
        Vector path = pathFinder.findPath(startX, startY, goalX, goalY);
        long after = System.currentTimeMillis();
        long time = after - before;
        printSolution(path);
        if (path.size() == 0)
          System.out.println("No path found.");
        else
          System.out.println("Path found.");
        System.out.println("Finding the path took " + time + " milliseconds");
      static void printSolution(Vector path) {
        boolean[][] pathOnMap = new boolean[map.getMapWidth()][map.getMapHeight()];
        for (int i = 0; path.size() > i; i++) {
          int[] move = (int[]) path.get(i);
          pathOnMap[move[0]][move[1]] = true;
        for (int y = 0; y < map.getMapHeight(); y++) {
          for (int x = 0; x < map.getMapWidth(); x++) {
            System.out.print(" ");
            if (pathOnMap[x][y] == false)
              System.out.print(" ");
            else
              System.out.print("0");
            if (x == startX && y == startY)
              System.out.print("S");
            else if (x == goalX && y == goalY)
              System.out.print("G");
            else
              System.out.print(map.terrainTypes.getNameFirstLetter(map.getSquareID(x, y)));
          System.out.println();
        System.out.println();
    }TerrainType.java:
    public class TerrainType {
      private int movementCost;
      private String name;
      TerrainType(int aMovementCost, String aName) {
        movementCost = aMovementCost;
        name = aName;
      public int getMovementCost() {
        return movementCost;
      public String getName() {
        return name;
      public String getNameFirstLetter() {
        return name.substring(0, 1).toUpperCase();
    }TerrainTypes.java:
    import java.util.Vector;
    public class TerrainTypes {
      //Here are saved the terrain types with the map has. ElementAt 'i' in
      //setOfTypes is represented by the number in Map.terrain[x][y] witch is
      //equal to i, were x, y are random integer as soon as they do not
      //throw ArrayIndexOutOfBoundsException. Actually this is a coding to know
      //a specific square in the map to witch terrain type is refered in setOfTypes.
      private Vector setOfTypes;
      public TerrainTypes() {
        setOfTypes = new Vector();
        setOfTypes.add(new TerrainType(1, "Plains"));
        setOfTypes.add(new TerrainType(2, "Forst"));
        setOfTypes.add(new TerrainType(3, "Jungle"));
        setOfTypes.add(new TerrainType(4, "Mountain"));
        setOfTypes.add(new TerrainType(-1, "X"));
      public int getMovementCost(int i) {
        return ((TerrainType) setOfTypes.get(i)).getMovementCost();
      public String getName(int i) {
        return ((TerrainType) setOfTypes.get(i)).getName();
      public String getNameFirstLetter(int i) {
        return ((TerrainType) setOfTypes.get(i)).getNameFirstLetter();
      public int getHighestMovementCost() {
        int max = 1;
        for (int i = 0; setOfTypes.size() > i; i++) {
          int movementCost = ((TerrainType) setOfTypes.get(i)).getMovementCost();
          if ( movementCost > 0) {
            if (max < movementCost)
              max = movementCost;
        return max;
    }I hope this program will be helpful.
    Sogartar

    Why is such a smart guy like you not using A*
    It is a general known algorithm which will find the
    optimal solution in a finite search-space (within a minimal time).
    The calculation time for the A* algorithm is influenced by two parameters:
    1 - cumulative cost
    2 - minimal expected additional cost
    The calculation of these two costs has a great influence on the
    solution.
    I think the actual problems most games experience with shortest path calculatoin are
    1 - very little time to spent calculating the shortest path
    The quickest solution might be the best for the game
    If your solution takes 1 second for the calculation of a path for one element on the board (100x100)
    What would it take for the game to calculate the path for all elements controlled by the computer ??
    If the computer controls two players which each have 50 elements to control, it would take forever...
    Don't even consider the usage of a larger board (200x200 would take 4 seconds/element when
    algorithm has complexity O(n))
    2 - low priority.
    Users tend to forgive a bad shortest path-algorithm most of the time,
    but not a bad display, bad pictures,...
    This is why most shortest-path algorithms within games were
    developed as a depth first search,
    within some earlier games this was even developed as
    a rule which went straight to the endlocation and
    takes a right/left turn when blocked by water/wall/...
    So the actual steps you should take are:
    1 - develop a normal breath-first search (to get going)
    2 - develop a normal depth-first search (to compare speed and solution with)
    3 - develop a normal dijkstra algorithm (sometimes called A)
    4 - develop a best first algorithm (called A*)
    5 - develop other AI-algorithms building upon A* (tabu-search, limited memory A*,...)
    6 - develop some other AI-algorithms (Genetic Algorithms, Simulated Annealing,...)
    7 - compare and tweak/change all search-algorithms for
    7 - a - size of maps (small versus huge)
    7 - b - optimality of the solution
    7 - c - actual usage for your game
    8 - !!! very important !!!
    Share the developed path algorithms along with remarks about speed, map-size,...
    with the rest of us. I would be very interested in such library.
    kind regards,

  • Help on path finding

    Hello everyone!
    Help me please!
    Have you ever played games like Baldur's gate or Diablo or classic adventure games (like Monkey island)?
    What I'm saying is:
    I'm trying to implement a way to move my character, on a 2D space, to the point I clicked on.
    If there is no obstacle between the start and the finish points, I can make it work pretty easily (I just let the charachter walk the straight line connecting the points).
    The problem is when I introduce obstacles.
    I'm trying to implement the A* algorithm for the path finding process.
    Since the character and the obstacles lay on a 2D plane not divided into tiles or any sort of sub-division, it is quite hard to calculate a path.
    What I thought of doing is:
    when I click on a destination point, I create a 2D grid surrounding the character, at its actual position, and the destination point.
    The intersections between the horizontal and the vertical lines of this grid, will be the possible nodes of the path to the destination. (I hope it's clear).
    The A* will calculate the best path among these nodes, considering whether a node is reachable (i.e. not overlapping an obstacle) or not.
    I still haven't implemented it, so it's just an idea, and I don't even know if it works!
    Is it possible there is no other way of doing that?
    How do the games I mentioned above work?
    My problem is finding a way to determine the possible nodes (2D points on the 2D plane) for the A* algorithm to work on.
    Please help, I'm stuck.
    Any suggestion?
    Thank you!
    P.S: If you need me to make it more clear, I'll give it a try!

    So far as I've tested it they haven't gotten stuck.
    The best way I can think of to do it is with the Line2D.Double class.
    - I draw a line between me and the enemy
    - create two lines that are equal to that first line
    - rotate the first line, from the enemy, to the left
    - rotate the first line, from the enemy, to the right
    - if both still intersect the obstacle, I rotate the two again
    - if one of them no longer intersects the obstacle, that new line becomes my path
    Once the clear path is found, I can use the endpoint of that line as the destination, rather than saying that MY coordinates are the destination. It takes a lot of math figuring so it gets messy written out, but in words it's very clean :)
    For simplicity you could try:
    - if he hits an obstacle do the following:
    - draw a line between the entity and the center of the obstacle
    - if you're on the left side of that line, make him turn left 90 degrees
    - if you're on the right side, turn right 90 degrees
    Based on how you're creating your obstacles you could think further how you want to do it, like tell them to move in that direction a set distance, that sort of thing.
    Or you could give them set paths to follow, that's another solution, and just have them be able to aim at you freely to fire, provided that's how they attack.

  • Help Using Path Finding Code

    Hi all.
    I found some open source code which implements the A Star algorithm to achieve path finding for the purpose of navigating something in a game (although it could really be used for anything). Problem is, I can't get it to work. I've e-mailed the author but no reply yet so I was hoping someone could shed some light on my situation.
    The code is meant to find a path on a 2 dimensional grid filled with obstacles using the following methods:
    PathFinder star = new PathFinder(grid);
    Path p = star.findShortest(startRow,startCol,goalRow,goalCol);
    I've made a simple Test class with a small 2D array but when I compile the code I recieve the error:
    Incompatible types.
    Found: int.
    Required: Test.Path
    on Path p = star.findShortest(1,1,2,2);
    I don't understand this error at all. The findShortest method takes 4 integers and I'm passing it 4 integers! Any ideas what this error means?
    Here's my Test class:
    import java.util.*;
    import javax.swing.plaf.basic.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.io.*;
    import javax.swing.filechooser.*;
    import java.util.Random;
    public class Test
            public static void main(String args[])
                    Test test = new Test();
                    test.run();
           public final static class Path
                    /** 2 for down, 0 is up, 1 is right and 3 is left */
                    public int giveMove() {
                        if (size() < 2)
                            return -1;
                        Position last = (Position)positions.get(size() - 1);
                        Position forlast = (Position)positions.get(size() - 2);
                        if (forlast.col - last.col == 1)
                            return 2; //down
                        else if (forlast.col - last.col == -1)
                            return 0; //up
                        else if (forlast.row - last.row == 1)
                            return 1;//right
                        else if (forlast.row - last.row == -1)
                            return 3; //left
                        return -1;
                    /** list of positions */
                    public List positions;
                    public int getCost() { return positions.size() - 1; }
                    public int size() { return positions.size(); }
                    public void add(Object o) { positions.add(o); }
                    /** add (r,c) to the path */
                    public void add(int r, int c) {
                        positions.add(new Position(r,c));
                    /** get first position */
                    public Position head() { return (Position) positions.get(0); }
                    public Path(ArrayList positions) { this.positions = positions; }
                    public Path(Position initial) {
                        positions = new ArrayList(1);
                        positions.add(initial);
                    public Path(int cap) { positions = new ArrayList(cap); }
                    public void set(Position front, Path old) {
                        positions.add(front);
                        Iterator i = old.positions.iterator();
                        while (i.hasNext())
                            positions.add(i.next());
            /** position on the grid */
           public static final  class Position
                    public int row, col;
                    public Position(int row, int col) {
                        this.row = row; this.col = col;
            public void run()
                    System.out.println("Test");
                    PathFinder star = new PathFinder(grid);
                    for(int counter = 0; counter < grid.length; counter++)
                            for (int j=0; j < grid[counter].length; j++)
                                    grid[counter][j] = 0;
                    Path p = star.findShortest(1, 1, 2, 2);
         private static int[][] grid = new int[2][2];    
    } Here's the PathFinder class I downloaded:
    import java.util.*;
    import javax.swing.plaf.basic.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.io.*;
    import javax.swing.filechooser.*;
    import java.util.Random;
    public final class PathFinder {
        /** the map grid to look on */
        private final int [][] grid;
        /** keep distances to each position here */
        private final int [][] distances;
        /** is gridposition (r, c) empty (empty is -1) ? */
        private boolean isEmpty(int r, int c) {
            return grid[r][c] == -1 ;
        /** pathfinder for grid */
        public PathFinder(int[][] grid) {
            this.grid = grid;
            this.distances = new int [grid.length][grid.length];
        /** clear distances */
        private void clear() {
            for (int i = 0 ; i < distances.length ; i++)
                for (int j = 0 ; j < distances.length ; j++)
    distances[i][j] = Integer.MAX_VALUE;
    /** position on the grid */
    public final static class Position {
    public int row, col;
    public Position(int row, int col) {
    this.row = row; this.col = col;
    /** path from start to a certain position */
    public final static class Path {
    /** 2 for down, 0 is up, 1 is right and 3 is left */
    public int giveMove() {
    if (size() < 2)
    return -1;
    Position last = (Position)positions.get(size() - 1);
    Position forlast = (Position)positions.get(size() - 2);
    if (forlast.col - last.col == 1)
    return 2; //down
    else if (forlast.col - last.col == -1)
    return 0; //up
    else if (forlast.row - last.row == 1)
    return 1;//right
    else if (forlast.row - last.row == -1)
    return 3; //left
    return -1;
    /** list of positions */
    public List positions;
    public int getCost() { return positions.size() - 1; }
    public int size() { return positions.size(); }
    public void add(Object o) { positions.add(o); }
    /** add (r,c) to the path */
    public void add(int r, int c) {
    positions.add(new Position(r,c));
    /** get first position */
    public Position head() { return (Position) positions.get(0); }
    public Path(ArrayList positions) { this.positions = positions; }
    public Path(Position initial) {
    positions = new ArrayList(1);
    positions.add(initial);
    public Path(int cap) { positions = new ArrayList(cap); }
    public void set(Position front, Path old) {
    positions.add(front);
    Iterator i = old.positions.iterator();
    while (i.hasNext())
    positions.add(i.next());
    /** gives the move to take for the shortest path from startRow to startCol
    * 0 up, 1 right, 2 down, 3 left
    * -1 if no move possible
    public final int findShortest
    (int startRow, int startCol, int goalRow, int goalCol) {
    clear();
    Position initial = new Position(startRow, startCol);
    //LinkedList list = new LinkedList();
    Position goal = new Position(goalRow, goalCol);
    BinaireHoop list = new BinaireHoop(200, new Path(goal), goal);
    list.add(new Path(initial));
    Position [] successors = new Position[4];
    int trie = 0;
    for ( ; ! list.isEmpty() && trie < 10000 ; trie++) {
    Path first = (Path) list.remove();
    Position firstPos = first.head();
    int r = firstPos.row; int c = firstPos.col;
    if (r == goalRow && c == goalCol) {  //goal found !             
    return first.giveMove();
    } else {
    int successorsCount = 0;
    if (isEmpty(r-1,c)) {
    successors[successorsCount++]
    = new Position(r-1, c);
    if (isEmpty(r+1,c)) {
    successors[successorsCount++]
    = new Position(r+1, c);
    if (isEmpty(r,c-1)) {
    successors[successorsCount++]
    = new Position(r, c-1);
    if (isEmpty(r,c+1)) {
    successors[successorsCount++]
    = new Position(r, c+1);
    while (successorsCount-- > 0) {
    Position succ = successors[successorsCount];
    int newPathCost = first.getCost() + 1;
    //add newPath if shorter than other path to this position
    if (distances[succ.row][succ.col] > newPathCost) { //shorter
    distances[succ.row][succ.col] = newPathCost;
    Path newPath = new Path(newPathCost + 1);
    newPath.set(succ, first);
    //add path to binary heap
    list.add(newPath);
    } // else longer: discard
    return -1;
    There's also a BinaireHoop class which the PathFinder class uses. I'll post that code if anyone thinks it's relevant but the error appears to be soley on my implementation. The Path and Position and just small subclass which for the sake of quickness I just placed into my Test class too instead of into a new class to themselves.
    Any thoughts appreciated! I would really like to get this working =)
    Thanks.

    Thanks for your reply. Doh, totally missed that one =)
    Anyway, I got the code working but it's still very buggy. I think this must just be a problem with the PathFinder class I downloaded.
    I create a 2D array
          int[][] array = {       
                                  {-1, -1, -1, -1, -1, -1, -1, -1},          
                                  {-1, -1, -1, -1, -1, -1, -1, -1},
                                  {-1, -1, -1, -1, -1, -1, -1, -1},
                                  {-1, -1, -1, -1, -1, -1, -1, -1},
                                  {-1, -1, -1, -1, -1, -1, -1, -1},
                                  {-1, -1, -1, -1, -1, -1, -1, -1},
                                  {-1, -1, -1, -1, -1, -1, -1, -1},
                                  {-1, -1, -1, -1, -1, -1, -1, -1}
                          };and choose starting and goal coordinates
    int p = star.findShortest(1, 1, 2, 2);The PathFinder will generate the coordinates to move to (I just stuck it all in a loop and updated the starting coordinates as appropriate to lead me to the goal). This is great!
    However, there seem to be a lot of bugs when I introduce "occupied squares". Basically, -1 in the array means that that square is empty whereas anything else means its full and the path finder should, in theory, generate a path around these obstacles. This isn't working correctly though.
    Sometimes a path wil be found around the obstacle, sometimes the path will go straight through it, and many times it just throws an array index out of bounds exception error!
    Anyone got any ideas? Or does anyone have any examples of a working path finder? =)
    Cheers

  • HTTP Status 500 - No action instance for path /deletescmeetnot could be cre

    Hello,
    I am maintaining a JSP/struts program already in production. The client asked us to add the ability a record when certain criteria are met. Since this is my first Struts work, I have been following the examples of other actions in the app. I easily added the link to the form (and it only displays if the conditions where you may delete if you choose are met). I made the action and added it to the struts-config file. This is the node:
    //struts-config.xml
        <action input="/subcommittees.jsp" path="/deletescmeetnot" type="com.xxyzz.abcdef.DeleteSubcommitteeMeetingNoticeAction">
          <forward name="success" path="/subcommittees.jsp" />
          <forward name="failure" path="/subcommittees.jsp" />
        </action>These are the first two lines of the action:
    //DeleteSubcommitteeMeetingNoticeAction.java
    public class DeleteSubcommitteeMeetingNoticeAction {
      public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException {This is where I attempt to execute the action:
    //SubcommitteeListTag.java
                        writer.print(" - <a title=\"Permanantly delete this Subcommittee meeting notice\" href=\"" +
                                response.encodeURL("/cf/deletescmeetnot.do?noticeID=" +
                                                      notice.getNoticeIdField().getAsString()) +
                                 "\" onClick=\"return confirmDeleteSubcommitteeMeetingNotice();\">Delete</a>");The javascript executes properly, but I get the error below when I click "OK."
    //Apache Tomcat/6.0.18 - Error report
    HTTP Status 500 - No action instance for path /deletescmeetnot could be created
    type Status report
    message No action instance for path /deletescmeetnot could be created
    description The server encountered an internal error (No action instance for path /deletescmeetnot could be created) that prevented it from fulfilling this request.Can anyone help me find what I am missing?
    Thank you,
    Frank Luke

    Found it. I needed to add "extends action" to the class.

  • Path finder & Line Question

    Hello Illustrators.
    I'm having an issue with the pathfinder tool. Im using the pathfiners DIVIDE and some of my lines go missing. from 1px stroke they go to just turn to a thin line other lines go thicker, other times some lines merge together
    distorting the shape of the of my design. I am expanding the lines fill and stroke to to clear all the unwanted lines hanging off the edges if that makes sense..The reason why im doing this is, because I need the inner parts
    within the black border strokes.
    thank you.

    Hello Forum.
    Heres a better understanding of what Im doing. on A side, Im drawing out lines using the line tool, and also the pen tool.
    then on B side, im joining the anchor points to make up the shape.
    on C i lay over the lines a rectangle so when I use the path finder tool, to make the shape fill up.
    and on D is the result which some lines break up,some go thickers, some go thiner, leaving gaps where the rectnagle was supposed to fill up.
    on D the lines have ruined, some have go thick for what reason?

  • NaN/PathRefnum? function producing useless answers for Path, Refnum

    I have found similar threads to this, but not quite the same, AFAICT.
    I'm trying simply to see if an INI file exists, so I created the following snippet:
    I also created a small file, put it in my C:\ directory, which I have attached here.
    When I run the LV program with C:\test.ini, my indicators come out as NaN/Path?: False, NaN/Refnum?: True
    which I tried to interpret as (1) a valid path (file exists) and (2) a nonexisting refnum (although the refnum came from an LV-supplied subVI).
    I then changed the control (file to find) to C:\test.in (lopped off final "i") and the two indicators gave me the same results. That blew away my first interpretation, and I can't come up with anything else which makes sense.
    So, for paths and refnums, what is going on here, if anything?
    I did see that the second test threw an error from the "Open Config Data" subVI, so I can use that for my test, but I'd like to know if the NaN... function is actually good for anything but numbers. If not, IMHO LV should change its designation on the palette.
    Cameron
    To err is human, but to really foul it up requires a computer.
    The optimist believes we are in the best of all possible worlds - the pessimist fears this is true.
    Profanity is the one language all programmers know best.
    An expert is someone who has made all the possible mistakes.
    To learn something about LabVIEW at no extra cost, work the online LabVIEW tutorial(s):
    LabVIEW Unit 1 - Getting Started
    Learn to Use LabVIEW with MyDAQ
    Solved!
    Go to Solution.
    Attachments:
    test.ini ‏1 KB

    Thanks, Nathand,
    That clears it up a lot (and then digging down into the layers below the "Open Config Data" VI brings back the opacity). That's just one of the things which has confused me about the Config File VIs subpalette, but the explanation and the fact that you have to use a special "Not a Config Data Refnum.vi" with these instead of the normal "NaN/Path/Refnum?" (I never saw it until you pointed it out) answers several of the other questions, too. Like I said at first, in this case I just wanted to see if the file was there, so there are alternatives. But when I need to do more than what the prepackaged VIs do (which I expect I will), then it's just a matter of digging down in with my hip boots on. (Yuck.) But it's all fun, or I wouldn't be doing it in the first place.
    Cameron
    To err is human, but to really foul it up requires a computer.
    The optimist believes we are in the best of all possible worlds - the pessimist fears this is true.
    Profanity is the one language all programmers know best.
    An expert is someone who has made all the possible mistakes.
    To learn something about LabVIEW at no extra cost, work the online LabVIEW tutorial(s):
    LabVIEW Unit 1 - Getting Started
    Learn to Use LabVIEW with MyDAQ

  • Uncrackable algorithm for serial-numbers

    In the last few days, Ive been thinking:
    Whats the use of sofisticated programs that cost millions to develope, and cost a few hundred dollars and there you can download a pirate version?
    There must be an uncrackable algorithm for protecting serial numbers or something like that.
    I would like to find out something like that
    R. Hollenstein

    So, tschodt, what you are suggesting is that I only
    provide the user interface and some core functions to
    anyone and then, I must create a database with
    registered (paying) users and everytime a user wants
    to make use of some function, he must have an
    internet connection?
    That is indeed the only uncrackable software, and the only way to ensure you get paid for pirated versions.
    But then, the performance of the program would be
    decreased...
    Not necessarilly. You just need enough resources to serve the expected number of clients and they need a fast enough network connection.
    I will think in some other solution.
    Maybe, you can deal it that the user must connect
    only once in order to get full functionality.
    In that case someone can buy the software, figure out what you do to unlock the functionality when he logs on, and use that to crack the system.
    As soon as you let any of your code (compiled or otherwise) out of your company someone WILL find a way to crack it.

  • Help me to get the algorithm for this assingment.

    I have tried to draw the x-y axis and the rectangle. I hava a problem to draw the rectangle inside of the lablled grid.
    NEED EVERYONE'S HELP HERE!
    Assignment #4
    Goal:
    �     This lab gives students more experience in
    �     developing proper algorithms for real-life problems;
    �     using program constructs � sequential, selection, and repetition.
    Algorithm. An algorithm is a description of steps to solve a problem that is unambiguous, executable, and terminating. In order to solve a problem by computer, you must know an algorithm for finding a solution.
    Problem Description
    Develop an algorithm and then write a java program that can accept commands from the user to draw a rectangle. The program should accept the xy-coordinate pair of the upper-left corner, and the width and height of a rectangle. It should then draw the rectangle pattern on a 40 X 20 labelled grid. For example, if the upper-left corner is (5, 10) with a width of 10 and height of 5, then the program would display:
    ^
    20+
    |     
    |
    |
    |
    |     
    15+
    |
    |
    |
    |     
    10+
    | ++++++++++
    | ++++++++++
    | ++++++++++
    | ++++++++++
    5+ ++++++++++
    |
    |
    |
    |     
    ________________________________>
    0 5 10 15 20 25 30 35 40     
         Upper Left (5,10) width:10, Height: 5
    NOTE:
    �     Your display should include the labelled axis, as shown on the previous page, and also the lines that are drawn horizontally across the page.
    �     Make sure the rectangle will fit on the 40X20 grid.
    �     Appropriate error messages must be displayed for invalid data provided by the user.

    If you format your code, it looks like thispublic class Rectangle {
      public static void main(String[] args) {
        int maxYAxisPoint = 20;
        int maxXAxisPoint = 40;
        int xCoodinate = 5;
        int yCoodinate = 10;
        int width = 5;
        int height = 10;
        int leftLowPoint;
        System.out.println("This program draw a rectangle pattern on a 40*20 labelled grid.");
        System.out.println("Please enter the x-coordinate of the upper left point: ");
        xCoodinate = MyIO.readLineInt();
        System.out.println("Please enter the y-coordinate of the upper left point: ");
        yCoodinate = MyIO.readLineInt();
        System.out.println("Please enter the width of the rectangle: ");
        width = MyIO.readLineInt();
        System.out.print("Enter the height of the rectangle:");
        height = MyIO.readLineInt();
        if (yCoodinate < maxYAxisPoint && yCoodinate + width < 40 ||
            xCoodinate + width < maxXAxisPoint &&
            xCoodinate + height < maxYAxisPoint) {
          System.out.println(" ^");
          for (maxYAxisPoint = 20; maxYAxisPoint >= 0; maxYAxisPoint--) {
            if ( (maxYAxisPoint % 5) == 0) {
              System.out.println(maxYAxisPoint + "+");
              for (leftLowPoint = (maxYAxisPoint - height) + 1;
                   leftLowPoint <= yCoodinate; leftLowPoint--) {
                System.out.println("+");
              //Draw the x-axis
              for (maxXAxisPoint = 0; maxXAxisPoint <= 40; maxXAxisPoint++) {
                System.out.print("+____");
                System.out.println("+>");
              for (maxXAxisPoint = 0; maxXAxisPoint <= 40; maxXAxisPoint++) {
                System.out.print(maxXAxisPoint + " ");
            } else {
              System.out.print(" | \n" + " |\n" + " |\n" + " |");
        } else {
          System.out.print("You entered a wrong x-y coordinate of the rectangle,\n the rectangle is not in the labelled grid.");
        System.out.print("Upper Left(" + xCoodinate + "," + yCoodinate + ")");
        System.out.print("width:" + width);
        System.out.println("height: " + height);
    }You have nested your loops. I'm pretty sure you don't want to do this. Here's an example of the difference. First a nested looppublic class Test2 {
      public static void main(String[] args) {
        for (int i=0; i<3; i++) {
          System.out.println("i="+i);
          for (int j=0; j<4; j++) {
            System.out.println("  j="+j);
    Outputs this
    i=0
      j=0
      j=1
      j=2
      j=3
    i=1
      j=0
      j=1
      j=2
      j=3
    i=2
      j=0
      j=1
      j=2
      j=3Now an unnested looppublic class Test2 {
      public static void main(String[] args) {
        for (int i=0; i<3; i++) {
          System.out.println("i="+i);
        for (int j=0; j<4; j++) {
          System.out.println("  j="+j);
    outputs this
    i=0
    i=1
    i=2
      j=0
      j=1
      j=2
      j=3This means you are printing the x-axis for every point on the graph.

  • Can't mount drive? Finder or Path Finder

    By pressing Apple K or going Go, Connect servers from finder I am unable to make connects to network resoureces. I've shown this to several Apple employees at the Tech Talk in Chicago. None of them was able to figure it out.
    You click on the Connect button and its like the button isn't even there.
    I've tried installing Path Finder since it too has something like the Apple K screen. But it appears to have the same problem. I looked at my console log and am getting this each time I try to map a drive.
    "FSMountServerVolumeAsync: -36, ioErr, I/O error(bummers)"
    This happen with any user logged into the system.

    Follow my posts this is a serious problem. I guess I'm the only one getting this and can't believe that Apples intention was for my G4 667 make my MBP 2.16 chug away as if it were an Apple II. I guess I'm just the lucky one who gets to experience all the issues. It is a "generic" I/O error as it does not pertain to an individual item and can effect many.
    It is a kernel error in this I/O Kit. Please report it to Apple Feedback. As this very same I/O is preventing the normal process of Bug reporter.
    FWIW

  • Announce: Generic Algorithms for Java, 0.3 release

    The latest release of jga: Generic Algorithms for Java is now available at
    http://jga.sf.net/
    Included in this release are a collection of algorithms adapted from STL that operate over generic collections and iterations. What's included are the algorithms that do not attempt to modify the collection/iteration that they're given: in other words, all of the find/search/count algorithms. Also included are the complete set of functors and predicates that were present in the last release, with a few modifications for easier use.
    The library is released under the LGPL, and includes the source for the library, the test framework, and a non-genericized version of the test framework that verifies that the library may be used without having the generic environment available.

    A (similar, it seems) parameterized collections library for JSR-14 Java.I had looked at JUtil some time ago, and I'm not sure of the similarity: JUtil looks to provide a number of interesting (if somewhat specialized) collections. JGA provides functors & predicates, and STL-ish algorithms that operate on collections and iterators. Looks to me to be more complimentary than similar.
    Mr. Ananian/Astaire's site is also the source of SinjDoc, the javadoc tool that I used to generate the javadoc at jga.sf.net, and with which I replaced the munge4doc.pl and mungedoclist.pl scripts that I had previously used and posted on this forum.

  • Path Finder 7 is it acceptable

    Is Path Finder 7 a safe and good software for Yosemite?

    We need to know what Mac you are using and what version of OS X, then we can get your question transferred to the correct forum.

  • Algorithm for File IO

    Hello All
    Can any one inform me on how to find out if a binary file is a text file or a try binary. There is a class that reads all files as binary (both text and binary). I need to be able to distinguish at run-time whether the file is text (i.e. .txt, .rtf, .sql files are considered text) and binary
    Thanks

    You can have some heuristics, both on octet value distribution and also some unicode byte-order marks (see the XML spec for some algorithms for guessing different text encodings). For RTF and SQL you also have definite grammars they must obey. But you won't ever get a 100% accurate test.
    Pete

Maybe you are looking for

  • How to delete the entries in the given field box

    Hi Every One, How can I delete the entries which I have given in example SE37 box. When I press Backspace button the entries which I have given will appear so I want to delete these entries. With Regards, Venkat

  • Folio builder login error: invalid_request

    Hi InDesig CC. When I start Foli Buildre send the message: An error occurred when trying to log in Folio Builder panel. [invalid_request]. Thank you

  • Database DATE field

    I have a process on a page that loads a form's field data into a %rowtype variable and passes it to a package in the database. The package then performs an update to the table holding the data. There is a DATE field that I can not validate on the APE

  • New I pad cover lock not working

    I bought the new I pad with Targus leather cover. Till yesterday I didn't notice I pad cover lock feature.but my friend tried I pad cover lock option in settings.my I pad was able to lock without smart cover till today. Suddenly it's not working anym

  • I disabled autocomplete but it continues to fill out my forms.

    I have done everything to keep autocomplete from filling out my forms...it continues to do so. I have gone to privacy settings, reset firefox and nothing seems to work. There are pages that I am forwarding to others that have my private information a