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;
}
}
}
}