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