BulletSimBot/Current Code
Jump to navigation
Jump to search
This is big, but here it is...
package awesomeness; import robocode.*; import robocode.util.*; import java.util.Random; import java.util.ArrayList; import java.awt.*; /** * PwnBot - a robot by (your name here) */ public class PwnBot extends AdvancedRobot { double previousEnergy = 100d; double changeInEnergy; double scannedRobotX, scannedRobotY; int movementDirection = 50; long lastTime; //The last time known, used to track bullets Random generator = new Random(); //This makes random numbers ArrayList<VirtualBullet> bullets = new ArrayList<VirtualBullet>(); VirtualBullet newBullet, bullet; AntiGravEngine engine; public void run() { engine = new AntiGravEngine(getBattleFieldWidth(), getBattleFieldHeight()); engine.setWallForce(300); scannedRobotX = -1; scannedRobotY = -1; setBodyColor(Color.red); setGunColor(Color.darkGray); setRadarColor(Color.red.darker()); setBulletColor(Color.red); lastTime = 0; setAdjustGunForRobotTurn(true); setAdjustRadarForGunTurn(true); setAdjustRadarForRobotTurn(true); while(true) turnRadarRightRadians(Double.POSITIVE_INFINITY); } /** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { //The absolute bearing, this is used a lot double absoluteBearing = e.getBearingRadians() + getHeadingRadians(); /////////////////////////////////////////////////////// ////////////////////Movement Code////////////////////// /////////////////////Bullet Code/////////////////////// scannedRobotX = getX() + Math.sin(absoluteBearing) * e.getDistance(); scannedRobotY = getY() + Math.cos(absoluteBearing) * e.getDistance(); //If there's a change in energy, it probably fired if ((changeInEnergy = previousEnergy - (previousEnergy = e.getEnergy())) > 0d && changeInEnergy<=3) { newBullet = new VirtualBullet(scannedRobotX, scannedRobotY, 20 - 3 * changeInEnergy, Utils.normalRelativeAngle(absoluteBearing + Math.PI + Math.asin((Math.sin(e.getBearingRadians()) * getVelocity())/(20 - 3 * changeInEnergy)))); engine.addPoint(new GravPoint(newBullet, -300)); bullets.add(newBullet); } for (int i = 0; i < bullets.size(); i++) { bullet = bullets.get(i); bullet.tick(getTime() - lastTime); bullets.set(i, bullet); if (bullets.get(i).checkCollide(getX(), getY())) { // I think this will work // bullets.remove(i--); // but usually I do bullets.remove(i); i--; } } engine.update(getX(), getY(),getTime() - lastTime); ///////////////////End Bullet Code///////////////////// System.out.print(engine.getXForce()); System.out.print(" "); System.out.println(engine.getYForce()); ////////////////////Movement Code////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// ///////////////////////Gun Code//////////////////////// ///////////////////////Gun Code//////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////Radar Code//////////////////////// setTurnRadarRightRadians(2 * Utils.normalRelativeAngle(absoluteBearing - getRadarHeadingRadians())); /////////////////////Radar Code//////////////////////// /////////////////////////////////////////////////////// lastTime = getTime(); } public void onHitWall(HitWallEvent e) { i(); } public void i() { movementDirection = -movementDirection; } ///////////////////////////Painting//////////////////////// // Paint a transparent square on top of the last scanned robot public void onPaint(Graphics2D g) { g.setColor(new Color(255, 255, 0)); for (int i = 0; i < bullets.size(); i++) { //Draw all the bullets bullet = bullets.get(i); g.fillOval( (int) bullet.getX() - 3, (int) (getBattleFieldHeight() - bullet.getY() - 3), 6, 6); } if(scannedRobotX == -1 && scannedRobotY == -1) { //If we have no target g.setColor(Color.green); //Draw the target g.drawString("No target", (int) getBattleFieldWidth()/80, (int) getBattleFieldHeight()/60); } else { //If we do have a target g.setColor(new Color(255, 96, 0)); //Draw the target g.drawString("Target locked", (int) getBattleFieldWidth()/80, (int) getBattleFieldHeight()/60); g.setColor(new Color(255, 32, 0)); //Draw the target g.drawLine( (int) scannedRobotX, (int) getBattleFieldHeight(), (int) scannedRobotX, 0); g.drawLine( (int) getBattleFieldWidth(), (int) (getBattleFieldHeight()-scannedRobotY), 0, (int) (getBattleFieldHeight()-scannedRobotY)); g.drawRect( (int) scannedRobotX-30, (int) (getBattleFieldHeight()-scannedRobotY-30), 60, 60); g.drawRect( (int) scannedRobotX-10, (int) (getBattleFieldHeight()-scannedRobotY-10), 20, 20); g.setColor(new Color(255, 32, 0, 64)); g.fillRect( (int) scannedRobotX-30, (int) (getBattleFieldHeight()-scannedRobotY-30), 60, 60); } } ///////////////////////////Painting//////////////////////// public void onHitByBullet(HitByBulletEvent e) { previousEnergy += 3 * e.getBullet().getPower(); } public void onBulletHit(BulletHitEvent e) { previousEnergy -= 4 * e.getBullet().getPower() + Math.max(0,2 * (e.getBullet().getPower() - 1)); } public void onHitRobot(HitRobotEvent e) { previousEnergy -= 0.6; } ///////////////////////////Bullets//////////////////////// public class VirtualBullet { //A class to simulate bullets. Basically flying GravPoints. double x, y, speed, angle; VirtualBullet(double startX, double startY, double velocity, double trajectory) { x = startX; y = startY; speed = velocity/2; angle = trajectory; } public void tick(long ticks) { //Moves the bullet the amount it would while(ticks > 0) { x += Math.sin(angle)*speed; y += Math.cos(angle)*speed; ticks --; } } public double getX() { return x; } public double getY() { return y; } public double getDistance(double botX, double botY) { return Math.sqrt(Math.pow(botX-x, 2)+Math.pow(botY-y, 2)); } public boolean checkCollide(double botX, double botY) { if (x < 0 || y < 0 || x > getBattleFieldWidth() || y > getBattleFieldHeight()) { return true; } if(botX-18<x && botX+18>x && botY-18<y && botY+18>y) { return true; } return false; } } ///////////////////////////Bullets//////////////////////// //////////////////////////Anti-Grav/////////////////////// // I learned anti-gravity from Hangi. A huge credit goes to him. public class AntiGravEngine { /** * All the points. **/ protected ArrayList<GravPoint> gravPoints = new ArrayList<GravPoint>(); /** * The forces of x and y. **/ protected double xForce = 0.0; protected double yForce = 0.0; /** * Size of battlefield. **/ protected double width, height; /** * The repulsion power of the walls- default 0, you really should * change this, otherwise your robot will inevitably crash into * the walls. **/ protected double wallForce = 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. Accoding to the laws of physics, * gravity would be 2, and magnets would be 3. **/ protected double pointDropoff = 2.0; /** * Same as pointDropOff but for the walls. **/ protected double wallDropoff = 3.0; /**Initializes the dimensions to the specified values**/ AntiGravEngine(double width, double height) { this.width = width; this.height = height; } // Now for a bunch of gets and sets I was too lazy to do myself, // all credit goes to Hanji /**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 ArrayList(); } /**return the distance between (x1,y1) and (x2,y2)*/ public double dist(double x1, double y1, double x2, double y2) { return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } /**returns the bearing from (x1,y1) to (x2,y2) in the range -pi to pi*/ public double getBearing( double x1,double y1, double x2,double y2 ) { double xo = x2-x1; double yo = y2-y1; return Math.atan2(xo,yo); } // End gets and sets // // And now the hard part... Most of it's the same, but it is // a bit different in a few places. public void update(double curX, double curY, long ticks) { xForce = 0.0; yForce = 0.0; ArrayList deadPoints = new ArrayList(); GravPoint point; double force; double angle; for(int i=0;i<gravPoints.size();i++) { point = (GravPoint) gravPoints.get(i); if(point.update(ticks)) { deadPoints.add(point); continue; } force = point.force/Math.pow( dist(curX, curY, point.x, point.y), pointDropoff); angle = getBearing(curX, curY, point.x, point.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.get(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; } } public class GravPoint { // Location public double x, y; // Force public double force; GravPoint(/*double startX, double startY,*/ VirtualBullet bullet, double mass) { x = bullet.getX(); y = bullet.getY(); force = mass; } public boolean update(long ticks) { bullet.tick(ticks); x = bullet.getX(); y = bullet.getY(); if(bullet.checkCollide(getX(), getY()) == true) { return true; } else { // The "else {" isn't needed, but makes it clearer return false; } } } }