preparation for a*search

master
Peter Babič 9 years ago
parent b94ddd1067
commit d5f469013e
  1. 2
      .classpath
  2. 82
      src/environment/AStar.java
  3. 136
      src/environment/Node.java
  4. 84
      src/environment/Point.java
  5. 44
      src/environment/RouteFinder.java
  6. 169
      src/environment/World.java
  7. 142
      src/myrobot/FirstRobot.java
  8. 144
      src/myrobot/RouteFindingRobot.java
  9. 129
      src/world/Generator.java
  10. 90
      src/world/Node.java
  11. 66
      src/world/Point.java

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry excluding="world/Node_.java|environment/Node_.java" kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="lib" path="/opt/robocode/libs/robocode.jar" sourcepath="robocode-source/robocode-1.9.2.3-src.zip">
<attributes>

@ -0,0 +1,82 @@
package environment;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class AStar {
private Set<Node> open = new HashSet<Node>();
private Set<Node> closed = new HashSet<Node>();
private List<Node> nodes = new ArrayList<Node>();
public AStar(Node start, Node goal) {
start.setG(0);
start.setH(manhattanDistance(start, goal));
start.setF(start.getH());
open.add(start);
while (true) {
Node current = null;
if (open.size() == 0) {
throw new RuntimeException("no route");
}
for (Node node : open) {
if (current == null || node.getF() < current.getF()) {
current = node;
}
}
if (current == goal) {
break;
}
open.remove(current);
closed.add(current);
for (Node neighbor : current.getNeighbors()) {
if (neighbor == null) {
continue;
}
int nextG = current.getG() + neighbor.getCost();
if (nextG < neighbor.getG()) {
open.remove(neighbor);
closed.remove(neighbor);
}
if (!open.contains(neighbor) && !closed.contains(neighbor)) {
neighbor.setG(nextG);
neighbor.setH(manhattanDistance(neighbor, goal));
neighbor.setF(neighbor.getG() + neighbor.getH());
neighbor.setParent(current);
open.add(neighbor);
}
}
}
Node current = goal;
while (current.getParent() != null) {
nodes.add(current);
current = current.getParent();
}
nodes.add(start);
}
public List<Node> getNodes() {
return nodes;
}
private int manhattanDistance(Node node1, Node node2) {
return Math.abs(node1.getX() - node2.getX()) + Math.abs(node1.getY() - node2.getY());
}
}

@ -0,0 +1,136 @@
package environment;
import java.util.List;
import java.util.ArrayList;
public class Node {
private List<Node> neighbors = new ArrayList<Node>();
private Node parent;
private int f;
private int g;
private int h;
private int x;
private int y;
private int cost;
/**
* @return the neighbors
*/
public List<Node> getNeighbors() {
return neighbors;
}
/**
* @param neighbors
* the neighbors to set
*/
public void setNeighbors(List<Node> neighbors) {
this.neighbors = neighbors;
}
/**
* @return the parent
*/
public Node getParent() {
return parent;
}
/**
* @param parent
* the parent to set
*/
public void setParent(Node parent) {
this.parent = parent;
}
/**
* @return the f
*/
public int getF() {
return f;
}
/**
* @param f
* the f to set
*/
public void setF(int f) {
this.f = f;
}
/**
* @return the g
*/
public int getG() {
return g;
}
/**
* @param g
* the g to set
*/
public void setG(int g) {
this.g = g;
}
/**
* @return the h
*/
public int getH() {
return h;
}
/**
* @param h
* the h to set
*/
public void setH(int h) {
this.h = h;
}
/**
* @return the x
*/
public int getX() {
return x;
}
/**
* @param x
* the x to set
*/
public void setX(int x) {
this.x = x;
}
/**
* @return the y
*/
public int getY() {
return y;
}
/**
* @param y
* the y to set
*/
public void setY(int y) {
this.y = y;
}
/**
* @return the cost
*/
public int getCost() {
return cost;
}
/**
* @param cost
* the cost to set
*/
public void setCost(int cost) {
this.cost = cost;
}
}

@ -0,0 +1,84 @@
package environment;
import environment.World;
public class Point{
private World world;
private int col, row;
/**
* @Point world
* @param col
* @param row
*/
public Point(World world, int col, int row) {
this.world = world;
this.col = col;
this.row = row;
}
/**
* @return
*/
public int getCol() {
return col;
}
/**
* @param col
*/
public void setCol(int col) {
this.col = col;
}
/**
* @return
*/
public int getRow() {
return row;
}
/**
* @param row
*/
public void setRow(int row) {
this.row = row;
}
/**
* @return true x position in pixels on the world map
*/
public int getX() {
return col * world.getSquareEdgeLenght() + world.getSquareCornerOffset();
}
/**
* @return true y position in pixels on the world map
*/
public int getY() {
return row * world.getSquareEdgeLenght() + world.getSquareCornerOffset();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
if (col != point.col) return false;
if (row != point.row) return false;
return true;
}
@Override
public int hashCode() {
int result = col;
result = world.getSquareEdgeLenght() * result + row;
return result;
}
}

@ -1,4 +1,4 @@
package world;
package environment;
import robocode.control.*;
//import world.Coordinate;
@ -10,7 +10,7 @@ public class RouteFinder {
public static void main(String[] args) {
// Location of the robocode, e.g. "C:/robocode"
String location = "/opt/robocode";
final String location = "/opt/robocode";
// Setup battle parameters
int numberOfRounds = 1;
@ -24,42 +24,36 @@ public class RouteFinder {
// Show the Robocode battle view
engine.setVisible(true);
Generator gen = new Generator();
// The world instance with the obstacles, the start and the stop position
World world = new World();
// Create the battlefield
int NumPixelCols = Generator.COLS * Generator.PX_STEP;
int NumPixelRows = Generator.ROWS * Generator.PX_STEP;
BattlefieldSpecification battlefield = new BattlefieldSpecification(NumPixelCols, NumPixelRows);
BattlefieldSpecification battlefield = new BattlefieldSpecification(world.getWorldWidth(), world.getWorldHeight());
/*
* Create obstacles and place them at random so that no pair of obstacles are at the same position
*/
RobotSpecification[] modelRobots = engine.getLocalRepository("sample.SittingDuck,myrobot.FirstRobot*");
// Create obstacles and place them at random so that no pair of obstacles are at the same position
RobotSpecification[] modelRobots = engine.getLocalRepository("sample.SittingDuck,myrobot.RouteFindingRobot*");
RobotSpecification[] existingRobots = new RobotSpecification[Generator.NUM_OBSTACLES + 1];
RobotSetup[] robotSetups = new RobotSetup[Generator.NUM_OBSTACLES + 1];
RobotSpecification[] existingRobots = new RobotSpecification[world.getNumObstacles() + 1];
RobotSetup[] robotSetups = new RobotSetup[world.getNumObstacles() + 1];
int NdxObstacle = 0;
for (Point p : gen.obstacles) {
for (Point point : world.getObstacles()) {
// added offset so the tanks are in the middle of the tiles
double InitialObstacleCol = (double) p.getX();
double InitialObstacleRow = (double) p.getY();
double InitialObstacleCol = (double) point.getX();
double InitialObstacleRow = (double) point.getY();
existingRobots[NdxObstacle] = modelRobots[0];
robotSetups[NdxObstacle++] = new RobotSetup(InitialObstacleCol, InitialObstacleRow, 0.0);
}
/*
* Create the agent and place it in a random position without obstacle
*/
existingRobots[Generator.NUM_OBSTACLES] = modelRobots[1];
double InitialAgentCol = (double) gen.start.getX();
double InitialAgentRow = (double) gen.start.getY();
robotSetups[Generator.NUM_OBSTACLES] = new RobotSetup(InitialAgentCol, InitialAgentRow, 0.0);
// Create the agent and place it in a random position without obstacle
existingRobots[world.getNumObstacles()] = modelRobots[1];
double InitialAgentCol = (double) world.getStart().getX();
double InitialAgentRow = (double) world.getStart().getY();
robotSetups[world.getNumObstacles()] = new RobotSetup(InitialAgentCol, InitialAgentRow, 0.0);
/* Create and run the battle */
// Create and run the battle
BattleSpecification battleSpec = new BattleSpecification(battlefield, numberOfRounds, inactivityTime, gunCoolingRate,
sentryBorderSize, hideEnemyNames, existingRobots, robotSetups);

@ -0,0 +1,169 @@
package environment;
import java.util.Set;
import java.util.HashSet;
import java.util.Random;
public class World {
// PRNG seed - level
private final int LEVEL = 2;
// Dimensional constants to match the background's grid pattern
private final int SQUARE_EDGE_LENGHT = 64;
private final int SQUARE_CORNER_OFFSET = 32;
// Map size
private final int NUM_COLS = 16;
private final int NUM_ROWS = 10;
// Obstacle (sitting ducks) count
private final int NUM_OBSTACLES = (int) (NUM_COLS * NUM_ROWS * 0.25);
// Contains poistions of obstacles, start point and destination
private Set<Point> obstacles = new HashSet<>();
private Point start, stop;
// PRNG instance
private Random rand;
// Excuse the crudity of the code, never programmed in Java before
// Could not resolve "pass-by-reference" in Java, thus the code is repeating :/
public World() {
// Seed the PRNG with the level
rand = new Random();
rand.setSeed(LEVEL);
// Generate the obstacles
for (int i = 0; i < getNumObstacles(); i++)
obstacles.add(fillEmptyPosition());
// Generate start/stop positions
start = fillEmptyPosition();
stop = fillEmptyPosition();
}
/**
* @return the level
*/
public int getLevel() {
return LEVEL;
}
/**
* @return the squareEdgeLenght
*/
public int getSquareEdgeLenght() {
return SQUARE_EDGE_LENGHT;
}
/**
* @return the squareCornerOffset
*/
public int getSquareCornerOffset() {
return SQUARE_CORNER_OFFSET;
}
/**
* @return the numCols
*/
public int getNumCols() {
return NUM_COLS;
}
/**
* @return the numRows
*/
public int getNumRows() {
return NUM_ROWS;
}
/**
* @return the numObstacles
*/
public int getNumObstacles() {
return NUM_OBSTACLES;
}
/**
* @return the obstacles
*/
public Set<Point> getObstacles() {
return obstacles;
}
/**
* @return the start point
*/
public Point getStart() {
return start;
}
/**
* @return the stop point
*/
public Point getStop() {
return stop;
}
/**
* @return the worldWidth in px
*/
public int getWorldWidth() {
return getNumCols() * getSquareEdgeLenght();
}
/**
* @return the worldHeight in px
*/
public int getWorldHeight() {
return getNumRows() * getSquareEdgeLenght();
}
private Point fillEmptyPosition() {
// try to find free place for an obstacle
while (true) {
int col = randInt(0, getNumCols() - 1);
int row = randInt(0, getNumRows() - 1);
// Generate point in this world
Point point = new Point(this, col, row);
// Check if the point is still free
if (!obstacles.contains(point) && start != point && stop != point) {
return point;
}
}
}
/**
* Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* @param min
* Minimum value
* @param max
* Maximum value. Must be greater than min.
* @return Integer between min and max, inclusive.
* @see java.util.Random#nextInt(int)
*/
private int randInt(int min, int max) {
// Make sure the randomizer was initialised
if (rand == null)
throw new RuntimeException("PRNG not initialised prior to call");
// nextInt is normally exclusive of the top value, so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}

@ -1,142 +0,0 @@
package myrobot;
import java.util.TreeSet;
import robocode.Robot;
import world.Generator;
import world.Node;
import world.Point;
public class FirstRobot extends Robot {
private Generator gen = new Generator();
private TreeSet<Node> open = new TreeSet<Node>();
private TreeSet<Node> closed = new TreeSet<Node>();
// private Node[] open, closed = new Node[];
// private
// private static
public void run() {
Node n = new Node(gen.start, new Point());
open.add(n);
while (true) {
n = open.first();
open.remove(n);
closed.add(n);
Point[] points = new Point[4];
// Upper square
points[0] = new Point(n.getCurrent().getX(), n.getCurrent().getY() + Generator.PX_STEP);
// Right square
points[1] = new Point(n.getCurrent().getX() + Generator.PX_STEP, n.getCurrent().getY());
// Lower square
points[2] = new Point(n.getCurrent().getX(), n.getCurrent().getY() - Generator.PX_STEP);
// Left square
points[3] = new Point(n.getCurrent().getX() - Generator.PX_STEP, n.getCurrent().getY());
for (Point p : points) {
if (isInsideMap(p) && isClear(p)) {
Node adj = new Node(p, n.getCurrent());
if (!closed.contains(adj)) {
open.add(adj);
}
else if (open.contains(adj)) {
}
}
}
// Node nu = new Node(pu, n.getCurrent());
// Node nr = new Node(pr, n.getCurrent());
// Node nd = new Node(pd, n.getCurrent());
// Node nl = new Node(pl, n.getCurrent());
//
//
//
//// if (lowestP)
}
}
// private void processPoint(Point p) {
// if (isWalkable(p) && !closed.contains(p) && !open.contains(p)) {
//// open.add(p);
//
// }
// }
//
private boolean isClear(Point p) {
return !gen.obstacles.contains(p);
}
private boolean isInsideMap(Point p) {
return (p.getX(true) >= 0 &&
p.getX(true) < Generator.COLS * Generator.PX_STEP &&
p.getY(true) >= 0 &&
p.getY(true) < Generator.ROWS * Generator.PX_STEP);
}
private void turn(int dest) {
int curr = (int) getHeading();
if (curr != dest) {
int diff = curr - dest;
if (Math.abs(diff) > 180)
turnRight(diff % 180);
else
turnLeft(diff);
}
}
public void steps(int num) {
ahead(num * Generator.PX_STEP);
}
public void up() {
north();
steps(1);
}
public void right() {
east();
steps(1);
}
public void down() {
south();
steps(1);
}
public void left() {
west();
steps(1);
}
public void north() {
turn(0);
}
public void east() {
turn(90);
}
public void south() {
turn(180);
}
public void west() {
turn(270);
}
}

@ -0,0 +1,144 @@
package myrobot;
import java.util.TreeSet;
import environment.World;
import environment.Node;
import environment.Point;
import robocode.Robot;
public class RouteFindingRobot extends Robot {
private World world = new World();
// private TreeSet<Node> open = new TreeSet<Node>();
// private TreeSet<Node> closed = new TreeSet<Node>();
// private Node[] open, closed = new Node[];
// private
// private static
public void run() {
doNothing();
// Node n = new Node(gen.start, new Point());
// open.add(n);
//
// while (true) {
// n = open.first();
// open.remove(n);
// closed.add(n);
//
// Point[] points = new Point[4];
//
// // Upper square
// points[0] = new Point(n.getCurrent().getX(), n.getCurrent().getY() + Generator.PX_STEP);
// // Right square
// points[1] = new Point(n.getCurrent().getX() + Generator.PX_STEP, n.getCurrent().getY());
// // Lower square
// points[2] = new Point(n.getCurrent().getX(), n.getCurrent().getY() - Generator.PX_STEP);
// // Left square
// points[3] = new Point(n.getCurrent().getX() - Generator.PX_STEP, n.getCurrent().getY());
//
// for (Point p : points) {
// if (isInsideMap(p) && isClear(p)) {
// Node adj = new Node(p, n.getCurrent());
// if (!closed.contains(adj)) {
// open.add(adj);
// }
// else if (open.contains(adj)) {
//// open.
// }
// }
// }
// Node nu = new Node(pu, n.getCurrent());
// Node nr = new Node(pr, n.getCurrent());
// Node nd = new Node(pd, n.getCurrent());
// Node nl = new Node(pl, n.getCurrent());
//
//
//
//// if (lowestP)
// }
}
// private void processPoint(Point p) {
// if (isWalkable(p) && !closed.contains(p) && !open.contains(p)) {
//// open.add(p);
//
// }
// }
//
// private boolean isClear(Point p) {
// return !world.obstacles.contains(p);
// }
//
// private boolean isInsideMap(Point p) {
// return (p.getX() >= 0 &&
// p.getX() < World.NUM_COLS * World.SQUARE_EDGE_LENGHT &&
// p.getY() >= 0 &&
// p.getY() < World.NUM_ROWS * World.SQUARE_EDGE_LENGHT);
// }
private void turn(int dest) {
int curr = (int) getHeading();
if (curr != dest) {
int diff = curr - dest;
if (Math.abs(diff) > 180)
turnRight(diff % 180);
else
turnLeft(diff);
}
}
public void steps(int num) {
ahead(num * world.getSquareEdgeLenght());
}
public void up() {
north();
steps(1);
}
public void right() {
east();
steps(1);
}
public void down() {
south();
steps(1);
}
public void left() {
west();
steps(1);
}
public void north() {
turn(0);
}
public void east() {
turn(90);
}
public void south() {
turn(180);
}
public void west() {
turn(270);
}
}

@ -1,129 +0,0 @@
package world;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Generator {
private static final int SEED = 2;
public static final int PX_STEP = 64;
public static final int PX_OFFSET = 32;
public static final int COLS = 16;
public static final int ROWS = 10;
public static final int NUM_OBSTACLES = (int) (COLS * ROWS * 0.25);
// Contains poistions of obstacles, start point and destination
// public static Point[] obstacles = new Point[NUM_OBSTACLES];
// public static Point[] agent = new Point[2];
public Set<Point> obstacles = new HashSet<>();
public Point start, stop;
Random rand;
// Excuse the crudity of the code, never programmed in Java before
// Could not resolve "pass-by-reference" in Java, thus the code is repeating :/
public Generator() {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
rand = new Random();
rand.setSeed(SEED);
// add the obstacles
for (int NdxObstacle = 0; NdxObstacle < NUM_OBSTACLES; NdxObstacle++) {
addPoint();
}
// Add the starting position
addStart();
// Add the
}
public void addPoint() {
// try to find free place for an obstacle
while (true) {
int x = randInt(0, COLS -1);
int y = randInt(0, ROWS -1);
Point point = new Point(x, y);
if (!obstacles.contains(point)) {
obstacles.add(point);
return;
}
}
}
public void addStart() {
// try to find free place for an obstacle
while (true) {
// -1 is due the offset
int x = randInt(0, COLS -1);
int y = randInt(0, ROWS -1);
Point point = new Point(x, y);
if (!obstacles.contains(point)) {
start = point;
return;
}
}
}
public void addStop() {
// try to find free place for an obstacle
while (true) {
// -1 is due the offset
int x = randInt(0, COLS -1);
int y = randInt(0, ROWS -1);
Point point = new Point(x, y);
if (!obstacles.contains(point) && start != point) {
stop = point;
return;
}
}
}
//
// public boolean isObstacle(int x, int y) {
// return this.obstacles
// }
//
/**
* Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* @param min
* Minimum value
* @param max
* Maximum value. Must be greater than min.
* @return Integer between min and max, inclusive.
* @see java.util.Random#nextInt(int)
*/
private int randInt(int min, int max) {
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}

@ -1,90 +0,0 @@
package world;
import world.Point;
public class Node implements Comparable<Node>{
//
// public static int lowestF;
//
// public static Point lowestP;
public static final int COST = 1;
private Point current, parent;
private int F, G, H;
public Node(Point current, Point parent) {
this.current = current;
this.parent = parent;
G += COST;
H = manhattan(parent, current);
F = G + H;
}
//
// public Node(Point current) {
// this.current = current;
//
// H = manhattan(new Point(), current);
// F = G + H;
// }
private int manhattan(Point start, Point stop) {
return Math.abs(start.getX() - stop.getX()) + Math.abs(start.getX() - stop.getY());
}
public int getF() {
return F;
}
public int getG() {
return G;
}
public int getH() {
return H;
}
public Point getCurrent() {
return current;
}
public Point getParent() {
return parent;
}
@Override
public int compareTo(Node compareNode) {
int compareQuantity = ((Node) compareNode).getF();
//ascending order
return this.F - compareQuantity;
//descending order
//return compareQuantity - this.quantity;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
if (current.getX() != node.current.getX()) return false;
if (current.getY() != node.current.getY()) return false;
return true;
}
@Override
public int hashCode() {
int result = current.getX();
result = Generator.PX_STEP * result + current.getY();
return result;
}
}

@ -1,66 +0,0 @@
package world;
public class Point{
private int x,y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point() {
this.x = -1;
this.y = -1;
}
public int getX() {
return x * Generator.PX_STEP + Generator.PX_OFFSET;
}
public int getX(boolean withoutOffset) {
if (withoutOffset)
return x;
else
return this.getX();
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y * Generator.PX_STEP + Generator.PX_OFFSET;
}
public int getY(boolean withoutOffset) {
if (withoutOffset)
return y;
else
return this.getY();
}
public void setY(int y) {
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
if (x != point.x) return false;
if (y != point.y) return false;
return true;
}
@Override
public int hashCode() {
int result = x;
result = Generator.PX_STEP * result + y;
return result;
}
}
Loading…
Cancel
Save