package taqho;
import robocode.*;
import java.awt.Color;
/**
* Seed - My first robot
*
* Step 1: Focus on learning to move around.
* There seem to be wall huggers and corner huggers, but the in thing seems to be anti-grav
* robots which move randomly but avoiding walls.
* This version will stick to basics. Corners to start with.
*
* Things to learn later:
* - avoiding walls
* - avoiding other robots (is this necessary)
* - When locating a target, track them if they move
* - when locating a target, track them when I move
* - when locating a target, track them when we both move
* - what to do when I get hit by a robot
* - what to do when I get hit by a bullet
* - can I optimise usage of heat to shot as soon as possible thereafter
* - scanning quickly
* - strobing an enemy in target to avoid bullets from it
* - float close to the wall
**/
public class Seed extends Robot {
// General class variables
final double wallMargin = 35;
final int STATE_GOTOCORNER = 1;
final int STATE_INCORNER = 2;
int state = STATE_GOTOCORNER;
// Corner variables
double cornerX;
double cornerY;
int currentCorner = 0;
int newCorner = 0;
// Scanning variables
final int SCAN_RIGHT = 1;
final int SCAN_LEFT = 2;
double scanStart;
double scanEnd;
int scanDirection = SCAN_RIGHT;
int scanSweeps = 10;
int scanStep = 5;
// Movement variables
final boolean MOVE_FORWARD = true;
final boolean MOVE_BACKWARD = false;
boolean moveDirection;
boolean damaged = false;
public void run() {
setColors(Color.green, Color.black, Color.yellow);
double distance;
while (true) {
distance = 50;
// Check distance in case I get waylaid or blocked
while (distance > 40) {
choseCorner();
gotoXY(cornerX, cornerY);
distance = distanceToXY(cornerX, cornerY);
}
state = STATE_INCORNER;
currentCorner = newCorner;
scanArenaFromCorner();
state = STATE_GOTOCORNER;
}
}
public void choseCorner() {
while (newCorner == currentCorner) {
newCorner = (int)(Math.random()*4+1);
}
switch (newCorner) {
case 1:
cornerX = wallMargin;
cornerY = wallMargin;
scanStart = -5;
scanEnd = 95;
break;
case 2:
cornerX = wallMargin;
cornerY = getBattleFieldHeight() - wallMargin;
scanStart = 85;
scanEnd = 185;
break;
case 3:
cornerX = getBattleFieldWidth() - wallMargin;
cornerY = getBattleFieldHeight() - wallMargin;
scanStart = 175;
scanEnd = 275;
break;
case 4:
cornerX = getBattleFieldWidth() - wallMargin;
cornerY = wallMargin;
scanStart = 265;
scanEnd = 365;
break;
}
}
public double distanceToXY(double x, double y) {
double xDiff = Math.abs(x - getX());
double yDiff = Math.abs(y - getY());
return Math.sqrt(xDiff*xDiff + yDiff+yDiff);
}
public void scanArenaFromCorner() {
// Start aiming
double needToTurn = scanStart - getGunHeading();
out.println("needToTurn=" + needToTurn + " = " + scanStart + " - " + getGunHeading());
turnGunRight(needToTurn);
scanDirection = SCAN_RIGHT;
int sweeps = 0;
// Determine duration of scanning from here
if (getOthers() > 2) {
scanSweeps = 5;
} else { // Fewer robots, move more...
scanSweeps = 1;
}
damaged = false;
while (sweeps < scanSweeps && !damaged) {
if (scanDirection == SCAN_RIGHT) {
turnGunRight(scanStep);
if (getGunHeading() > scanEnd) {
scanDirection = SCAN_LEFT;
sweeps += 1;
}
} else {
turnGunLeft(scanStep);
if (getGunHeading() < scanStart) {
scanDirection = SCAN_RIGHT;
sweeps += 1;
}
}
}
}
public void gotoXY(double toX, double toY) {
if (getX() + toX < getWidth()) toX += (getWidth()/2);
else if (getX() + toX > (getBattleFieldWidth() - getWidth())) toX -= (getWidth()/2);
if (getY() + toY < getWidth()) toY += (getWidth()/2);
else if (getY() + toY > (getBattleFieldHeight() - getWidth())) toY -= (getWidth()/2);
double relativeToX = toX - getX();
double relativeToY = toY - getY();
double headingToXY = radToDeg(this.arctan(relativeToX, relativeToY));
double tankTurn = headingToXY - getHeading();
double distance = Math.sqrt(relativeToX*relativeToX + relativeToY*relativeToY);
tankTurn = normalRelativeAngle(tankTurn);
if (tankTurn > 90 || tankTurn < -90) {
moveDirection = MOVE_BACKWARD;
} else {
moveDirection = MOVE_FORWARD;
}
if (moveDirection) {
turnRight(tankTurn);
ahead(distance);
} else {
turnRight(normalRelativeAngle(tankTurn-180));
back(distance);
}
}
/**
* onScannedRobot: Fire!
*/
public void onScannedRobot(ScannedRobotEvent e) {
if (e.getDistance() < 50 && getEnergy() > 50)
fire(3);
else
fire(1);
if (!damaged) scan();
}
/**
* onHitRobot: Aim at it. Fire Hard!
*/
public void onHitRobot(HitRobotEvent e) {
double turnGunAmt = normalRelativeAngle(e.getBearing() + getHeading() - getGunHeading());
turnGunRight(turnGunAmt);
fire(3);
}
/**
* onHitByBullet: What to do when you're hit by a bullet
*/
public void onHitByBullet(HitByBulletEvent e) {
damaged = true;
double turnGunAmt = normalRelativeAngle(e.getBearing() + getHeading() - getGunHeading());
turnGunRight(turnGunAmt);
fire(3);
}
/**
* normalRelativeAngle: returns angle such that -180<angle<=180
*/
public double normalRelativeAngle(double angle) {
if (angle > -180 && angle <= 180)
return angle;
double fixedAngle = angle;
while (fixedAngle <= -180)
fixedAngle += 360;
while (fixedAngle > 180)
fixedAngle -= 360;
return fixedAngle;
}
private double normalizeAngle(double r)
{
while(r>Math.PI) r-=2*Math.PI;
while(r<-Math.PI) r+=2*Math.PI;
return r;
}
public double radToDeg(double rad) {
return rad * 180.0 / Math.PI;
}
public double degToRad(double deg) {
return deg * Math.PI / 180.0;
}
public double arctan( double dy, double dx) {
if (dx == 0.0) {
if (dy > 0.0) return Math.PI*0.5;
else return Math.PI*1.5;
} else {
if ((dx > 0.0) && (dy > 0.0)) return normalizeAngle(Math.atan(dy/dx));
else if ((dx < 0.0) && (dy > 0.0)) return normalizeAngle(Math.PI - Math.atan(dy/Math.abs(dx)));
else if ((dx < 0.0) && (dy < 0.0)) return normalizeAngle(Math.PI + Math.atan(dy/dx));
else return normalizeAngle(Math.PI*2 - Math.atan(Math.abs(dy)/dx));
}
}
}