package neh; import java.util.Vector; import neh.RobocodeUtils; import neh.GravPoint; /** * AGravEngine -> an engine encapsulating the Anti-gravity movement * algorithm. By NEH (aka Hanji) **/ public class AGravEngine { /**The Points that it is concerned with.**/ protected Vector gravPoints = new Vector(); /** * The force, if any, of the walls. It is assumed that the walls will * never attract, so this is always positive (meaning repulsion in this * case). **/ protected double wallForce = 0.0; /**The width of the battlefield.**/ protected double width; /**The height of the battlefield**/ protected double height; /*The components of the force**/ protected double xForce = 0.0; protected double yForce = 0.0; /** * The exponent used in cacluating a point's effect on a location. * The effect is proportionate to distance^pointDropoff. This field * has an initial value of 2.0. **/ protected double pointDropoff = 2.0; /** * The exponent used in cacluating the walls' effect on a location. * The effect is proportionate to distance^wallDropoff. This field * has an initial value of 3.0. **/ protected double wallDropoff = 3.0; /**Initializes the width and height to 0**/ public AGravEngine() { this(0,0); } /**Initializes the dimensions to the specified values**/ public AGravEngine(double width, double height) { this.width = width; this.height = height; } /**Adds a point to the list.**/ public void addPoint(GravPoint g) { gravPoints.add(g); } /**Removes a point from the list.**/ public boolean removePoint(GravPoint g) { return gravPoints.remove(g); } /**Returns the number of points currently contained.**/ public long getNumPoints() { return gravPoints.size(); } /**Returns the force with which the walls repel.**/ public double getWallForce() { return wallForce; } /**Sets the force with which the walls repel.**/ public void setWallForce(double wf) { wallForce = wf; } /**Returns the value of the point dropoff exponent.**/ public double getPointDropoff() { return pointDropoff; } /**Sets the value of the point dropoff exponent.**/ public void setPointDropoff(double pdf) { pointDropoff = pdf; } /**Returns the value of the wall dropoff exponent.**/ public double getWallDropoff() { return wallDropoff; } /**Sets the value of the wall dropoff exponent.**/ public void setWallDropoff(double wdf) { wallDropoff = wdf; } /**Removes all points from the list.**/ public void reset() { gravPoints = new Vector(); } /** * Calculates the current force and kills any GravPoints * that have gone past their lifetimes * @param curX The X coordinate of the point for which * gravity is being calculated. * @param curY The Y coordinate of the point for which * gravity is being calculated. * @param time The current time. **/ public void update(double curX, double curY, long time) { xForce = 0.0; yForce = 0.0; Vector deadPoints = new Vector(); GravPoint g; double force; double angle; for(int i=0;i<gravPoints.size();i++) { g = (GravPoint) gravPoints.elementAt(i); if(g.update(time)) { deadPoints.add(g); continue; } force = g.strength/Math.pow( RobocodeUtils.dist(curX, curY, g.x, g.y), pointDropoff); angle = RobocodeUtils.getBearing(curX, curY, g.x, g.y); xForce += force * Math.sin(angle); yForce += force * Math.cos(angle); } xForce += wallForce/Math.pow(curX, wallDropoff); xForce -= wallForce/Math.pow(width-curX, wallDropoff); yForce -= wallForce/Math.pow(height-curY, wallDropoff); yForce += wallForce/Math.pow(curY, wallDropoff); for(int i=0;i<deadPoints.size();i++) { gravPoints.remove(deadPoints.elementAt(i)); } } /** * Returns the force in the X direction (calculated in * update()) **/ public double getXForce() { return xForce; } /** * Returns the force in the Y direction (calculated in * update()) **/ public double getYForce() { return yForce; } }This class also requires the /GravPoint class, and you will have to either replace the calls to RobocodeUtils.* with your own equivalents, or grab that class as well.
I'm working on a bot with this engine. It took me quite a while to find some good values for the dropoffs and wallforce. I neeeded to change the lines:
xForce += force * Math.sin(angle); yForce += force * Math.cos(angle);
into:
xForce -= force * Math.sin(angle); yForce -= force * Math.cos(angle);
otherwise other bots attracted my bot. It works pretty good if you place some additional points (e.g. center and corners).
Noran