Copyright Tristan Aubrey-Jones December 2005.
package tajy;
import robocode.*;
import java.awt.Color;
import java.util.HashMap;
import java.util.Iterator;
/**
* TajBot - a robot by (your name here)
*/
public class TajBot extends AdvancedRobot
{
private HashMap targets;
private boolean forward = true;
public double aimBearing = 0;
private MoveCompleteCondition moveComplete;
private RadarTurnCompleteCondition radarComplete;
private Enemy currentTarget;
private double energy = 1; // energy to fire with
private long lastSweep = 0; // time of last 360 sweep
private final long sweepDelay = 20; // 360 sweep every half second
private long holdFireTil = -1; // dont fire til this time
private double ratio = 1; // hit ratio
private final double aimAccuracy = 1; // accuracy in degrees
/**
* run: TajBot's default behavior
*/
public void run()
{
// init
setColors(Color.red,Color.blue,Color.green);
targets = new HashMap();
//setAdjustGunForRobotTurn(true);
moveComplete = new MoveCompleteCondition(this);
radarComplete = new RadarTurnCompleteCondition(this);
turnRadarRight(360);
ahead(10);
// run
while (true)
{
attack();
}
}
private Enemy getEnemy(String name)
{
return (Enemy)targets.get(name);
}
public Vector getPosition()
{
return new Vector(getX(), getY());
}
private Enemy getBestTarget()
{
double maxThreat = 0;
Enemy target = null;
for (Iterator i = targets.values().iterator(); i.hasNext(); )
{
Enemy enemy = (Enemy)i.next();
double threat = enemy.getPriority();
if ((enemy == null) || (threat > maxThreat))
{
target = enemy;
maxThreat = threat;
}
}
if (currentTarget != null) currentTarget.setTargeted(false);
currentTarget = target;
if (currentTarget != null) currentTarget.setTargeted(true);
return target;
}
private Enemy getWorstThreat()
{
double maxThreat = 0;
Enemy target = null;
for (Iterator i = targets.values().iterator(); i.hasNext(); )
{
Enemy enemy = (Enemy)i.next();
double threat = enemy.getThreat();
if ((enemy == null) || (threat > maxThreat))
{
target = enemy;
maxThreat = threat;
}
}
return target;
}
private void attack()
{
// get current threat
Vector m = getPosition();
Enemy target = getBestTarget();
if (target != null)
{
ratio = target.hitRatio();
// big energy when point blank
energy = 1;
if ((target.getVelocity() < 1) || (target.getDistance(m) < 200))
energy = 3;
// aim
double targetBearing = aimAtTarget(target);
if ((target.getDistance(m) > 400) || (target.hitRatio() < 0.3))
{
// make sure am face on to robot
double turnRight = targetBearing - getHeading();
if (turnRight < 180) setTurnRight(turnRight);
else setTurnLeft(360 - turnRight);
// move in closer
setAhead(20);
}
else
{
// low energy so dont waste bullets
if (target.hitRatio() < 1)
{
energy = target.hitRatio();
}
// calculate threat bearing
Enemy threat = getWorstThreat();
Vector t = threat.getPosition();
double threatBearing = BotMaths.getAimBearing(getPosition(), t);
// make sure am side on to target
double robotBearing = threatBearing + 90;
double turnRight = robotBearing - getHeading();
if (turnRight < 180) setTurnRight(turnRight);
else setTurnLeft(360 - turnRight);
// strife
if (moveComplete.test())
{
if (forward)
{
setAhead(200);
forward = false;
}
else
{
setBack(200);
forward = true;
}
}
}
// fire (if aiming correctly)
if ((getGunHeading() > targetBearing - aimAccuracy) &&
(getGunHeading() < targetBearing + aimAccuracy))
{
if (getGunHeat() == 0)
{
this.waitFor(new GunTurnCompleteCondition(this));
if (holdFireTil == -1) setFire(energy);
else
{
if (getTime() >= holdFireTil)
{
holdFireTil = -1;
setFire(energy);
}
}
}
}
//else out.println("Dont shoot.");
}
// execute actions
execute();
}
private Vector averageEnemyPosition()
{
Vector sum = new Vector(0, 0);
for (Iterator i = targets.values().iterator(); i.hasNext(); )
{
Enemy enemy = (Enemy)i.next();
sum = sum.add(enemy.getPosition());
}
double x = sum.getX() / targets.size();
double y = sum.getY() / targets.size();
return new Vector(x, y);
}
private double getQuietBearing()
{
Vector enemyPosition = averageEnemyPosition();
double bearing = BotMaths.getAimBearing(getPosition(), enemyPosition);
return (bearing + 180) % 360;
}
private double aimAtTarget(Enemy target)
{
// target vector
Vector t = null;
// target occilates about a point
/*if (t == null)
{
// see if target is occilating about a point
CycleSpotter c = target.getPatternWatcher();
int i = c.getBestTarget(getPosition());
int hits = c.getVisits(i);
// if good point
if (hits > 3)
{
energy = 3;
t = c.getPosition(i);
long bulletDelay = (long)BotMaths.getBulletTime(t.distanceTo(getPosition()), energy);
long nextFire = c.getNextTime(i, getTime() - bulletDelay);
if (nextFire < 100)
{
out.println("Occilating.");
holdFireTil = nextFire;
}
else t = null;
}
}*/
// no obvious pattern to movement
if (t == null)
{
// estimate position of robot when bullet hits
//out.println("Anticipating.");
energy = 1.5;
// iterate estimating target coord.
t = target.getPosition();
double delay = 0;
for (int i = 0; i != 5; i++)
{
delay = getTime() + BotMaths.getBulletTime(t.distanceTo(getPosition()), energy);
t = BotMaths.estimateTargetCoord(target.getPosition(),
target.getHeading(), target.getTimeSinceScan(delay));
}
delay -= 3;
t = BotMaths.estimateTargetCoord(target.getPosition(),
target.getHeading(), target.getTimeSinceScan(delay));
// will they hit a wall?
if ((t.getX() < 0) ||
(t.getX() > getBattleFieldWidth()) ||
(t.getY() < 0) ||
(t.getY() > getBattleFieldHeight()))
{
t = null;
energy = 0.1;
}
}
// default to last scanned local
if (t == null)
{
energy = 0.8;
t = target.getPosition();
}
// if point blank
if (getEnergy() < 10) energy = 0.1;
// if point blank
if (target.getPosition().distanceTo(getPosition()) < 200)
{
energy = 1.5;
}
// if point blank
if (target.getPosition().distanceTo(getPosition()) < 100)
{
energy = 3;
}
// calculate bearing of anticipated location
double targetBearing = BotMaths.getAimBearing(getPosition(), t);
double angle = targetBearing - getGunHeading();
aimBearing = angle;
// scanning...
if (radarComplete.test())
{
if (lastSweep + sweepDelay < getTime())
{
setTurnRadarRight(360);
lastSweep = getTime();
}
else
{
// scan target
double radarAngle = targetBearing - getRadarHeading();
if (radarAngle > 0)
{
setTurnRadarRight(radarAngle + 20);
}
else
{
setTurnRadarLeft(20 - radarAngle);
}
}
}
// aim at location
if (angle < 180)
{
setTurnGunRight(angle);
}
else if (angle > 180)
{
setTurnGunLeft(360 - angle);
}
return targetBearing;
}
public void setTurnGunRight(double d)
{
if (d >= 180)
{
out.print(d);
out.println(" right.");
}
super.setTurnGunRight(d);
}
public void setTurnGunLeft(double d)
{
if (d >= 180)
{
out.print(d);
out.println(" left.");
}
super.setTurnGunLeft(d);
}
/**
* onScannedRobot: What to do when you see another robot
*/
public void onScannedRobot(ScannedRobotEvent e)
{
// add target to table
String name = e.getName();
if (!targets.containsKey(name))
{
targets.put(name, new Enemy(name));
}
// update target scan
Enemy target = getEnemy(name);
target.scanned(e, this);
}
public void onBulletHit(BulletHitEvent event)
{
// register shot
Enemy target = getEnemy(event.getName());
if (target != null) target.gotHim();
}
public void onBulletMissed(BulletMissedEvent event)
{
// register shot
if (currentTarget != null) currentTarget.missedHim();
}
public void onRobotDeath(RobotDeathEvent event)
{
targets.remove(event.getName());
}
/**
* onHitByBullet: What to do when you're hit by a bullet
*/
public void onHitByBullet(HitByBulletEvent e)
{
// register shot
Enemy target = getEnemy(e.getName());
if (target != null) target.shotMe(this);
}
public void onHitRobot(HitRobotEvent event)
{
Enemy target = getEnemy(event.getName());
if (target != null)
{
target.hit(event, this);
}
}
public void onHitWall(HitWallEvent event)
{
//setTurnRight(90);
//setAhead(100);
}
public void onWin(WinEvent e)
{
out.println(ratio);
}
}