CS Bot
Hello. The name is Ray Mark, and I'm new to robocode. I've taken an AP Java course and all, so I'm pretty good with the Java aspect of robocoding. But the robocode api is slightly confusing and I was wondering if anyone could help me out.
Basically, I made a basic robot and followed the guess factor guide and the wave surfing guide and put those code segments together to see what would happen. After debugging it all, I compiled the code to find this result: Alone, the guess factor targeting works If the wave surfing is enabled, the robot moves... but the GFT doesn't work anymore. Instead the bot just fires like a crazy flailing fish. If the wave surfing is commented out, then the GFT code works again.
Can anyone take a look at the code and see what I need to fix? (the code is directly from the tutorials, i'm using the code to get a better idea of robocode)
|
package sd; import robocode.*; import java.util.ArrayList; import java.util.List; import robocode.util.Utils; import java.awt.geom.*; import java.util.ArrayList; import java.lang.*; import sd.EnemyWave; //import java.awt.Color; /** * ProjectBot - a robot by Saagar Deshpande */
public class ProjectBot extends AdvancedRobot
{
/** * All defined Variables go here: */ List waves = new ArrayList(); static int[][] stats = new int[13][31]; //31 is the number of unique guessfactors to be used int direction = 1; //private int timeSinceLastScan = 10; //radar vars
//static double enemyAbsoluteBearing;
public static int BINS = 47; //Wave Surf vars*
public static double _surfStats[] = new double[BINS]; public Point2D.Double _myLocation; // our bot's location public Point2D.Double _enemyLocation; // enemy bot's location
public ArrayList _enemyWaves; public ArrayList _surfDirections; public ArrayList _surfAbsBearings;
public static double _oppEnergy = 100.0;//*end
/** This rectangle represents an 800x600 battle field, used for a simple, iterative WallSmoothing method
* the wall stick indicates the amount of space to have between wall and bot. */
public static Rectangle2D.Double _fieldRect = new java.awt.geom.Rectangle2D.Double(18, 18, 764, 564);
public static double WALL_STICK = 160;
/**
* run: ProjectBot's default behavior
*/
public void run() {
// After trying out your robot, try uncommenting the import at the top,
// and the next line:
//setColors(Color.red,Color.blue,Color.green);
_enemyWaves = new ArrayList(); //surf code
_surfDirections = new ArrayList(); _surfAbsBearings = new ArrayList();
setAdjustGunForRobotTurn(true); setAdjustRadarForGunTurn(true); //
do {
// doScanner(); // execute();
turnRadarRightRadians(Double.POSITIVE_INFINITY); /*ahead(100); //re code turnGunRight(360); back(100); turnGunRight(360);*/
} while (true);
/*while(true) {
// Replace the next 4 lines with any behavior you would like
//turnRadarRight(Double.POSITIVE_INFINITY);
ahead(100);
turnGunRight(360);
back(100);
turnGunRight(360);
}*/
}
/** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { //fire(1); /****************************** *WAVE SURFING STARTS HERE *******************************/ _myLocation = new Point2D.Double(getX(), getY());
double lateralVelocity = getVelocity()*Math.sin(e.getBearingRadians()); double absBearingWS = e.getBearingRadians() + getHeadingRadians();
setTurnRadarRightRadians(Utils.normalRelativeAngle(absBearingWS - getRadarHeadingRadians()) * 2);
_surfDirections.add(0, new Integer((lateralVelocity >= 0) ? 1 : -1)); _surfAbsBearings.add(0, new Double(absBearingWS + Math.PI));
double bulletPower = _oppEnergy - e.getEnergy(); if (bulletPower < 3.01 && bulletPower > 0.09 && _surfDirections.size() > 2) { EnemyWave ew = new EnemyWave(); ew.fireTime = getTime() - 1; ew.bulletVelocity = EnemyWave.bulletVelocityMethod(bulletPower); ew.distanceTraveled = EnemyWave.bulletVelocityMethod(bulletPower); ew.direction = ((Integer)_surfDirections.get(2)).intValue(); ew.directAngle = ((Double)_surfAbsBearings.get(2)).doubleValue(); ew.fireLocation = (Point2D.Double)_enemyLocation.clone(); // last tick
_enemyWaves.add(ew); }
_oppEnergy = e.getEnergy();
// update after EnemyWave detection, because that needs the previous // enemy location as the source of the wave _enemyLocation = EnemyWave.project(_myLocation, absBearingWS, e.getDistance());
updateWaves(); doSurfing();
/************************************************ *GUESSFACTOR STARTS HERE ************************************************/ double absBearing = getHeadingRadians() + e.getBearingRadians(); //find the enemy's location: double ex = getX() + Math.sin(absBearing)*e.getDistance(); double ey = getY() + Math.cos(absBearing)*e.getDistance();
//process the waves: for (int i=0; i<waves.size(); i++) { WaveBullet currentWave = (WaveBullet)waves.get(i); if (currentWave.checkHit(ex, ey, getTime())) { waves.remove(currentWave); i--; } }
double power = Math.min(3, Math.max(.1, 10/* some function */)); //don't try to figure out the direction they're moving if they're not moving, just use the direction we had before if (e.getVelocity() != 0) if (Math.sin(e.getHeadingRadians()-absBearing)*e.getVelocity() < 0) direction = -1; else direction = 1; int[] currentStats = stats[(int)(e.getDistance()/100)]; WaveBullet newWave = new WaveBullet(getX(), getY(), absBearing, power, direction, getTime(), currentStats); int bestindex = 15; //initialize it in the middle, guessfactor 0. for (int i=0; i<31; i++) if (currentStats[bestindex] < currentStats[i]) bestindex = i;
//this should do the opposite of the math in the WaveBullet: double guessfactor = (double)(bestindex-(stats.length-1)/2)/((stats.length-1)/2); double angleOffset = direction*guessfactor*newWave.maxEscapeAngle(); setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absBearing-getGunHeadingRadians()+angleOffset)); //fire(1); if (setFireBullet(1) != null) fire(1); waves.add(newWave); //setTurnRadarRightRadians(Utils.normalRelativeAngle(e.getBearingRadians() + getHeadingRadians() - getRadarHeadingRadians())); //enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians(); //radar code
//timeSinceLastScan = 0;
}
/** * onHitByBullet: What to do when you're hit by a bullet */ public void onHitByBullet(HitByBulletEvent e) { //WAVE SURF METHOD //turnLeft(90 - e.getBearing()); //default code // If the _enemyWaves collection is empty, scan must have missed the
// detection of this wave somehow. if (!_enemyWaves.isEmpty()) { Point2D.Double hitBulletLocation = new Point2D.Double( e.getBullet().getX(), e.getBullet().getY()); EnemyWave hitWave = null;
// look through the EnemyWaves, and find one that could've hit the bot. for (int x = 0; x < _enemyWaves.size(); x++) { EnemyWave ew = (EnemyWave)_enemyWaves.get(x);
if (Math.abs(ew.distanceTraveled - _myLocation.distance(ew.fireLocation)) < 50 && Math.round(EnemyWave.bulletVelocityMethod(e.getBullet().getPower()) * 10) == Math.round(ew.bulletVelocity * 10)) { hitWave = ew; break; } }
if (hitWave != null) { logHit(hitWave, hitBulletLocation);
//remove this wave now _enemyWaves.remove(_enemyWaves.lastIndexOf(hitWave)); } }
}
/* private void doScanner() { //radar scanner
timeSinceLastScan++; double radarOffset = Double.POSITIVE_INFINITY; if(timeSinceLastScan < 3) { radarOffset = robocode.util.Utils.normalRelativeAngle(getRadarHeadingRadians() - enemyAbsoluteBearing); radarOffset += sign(radarOffset) * 0.02; } setTurnRadarLeftRadians(radarOffset); }
int sign(double v) {
return v > 0 ? 1 : -1;
}*/
/************************* *Wave Surf algo-methods **************************/ public void updateWaves() { //update distance of wave and source, delete waves behind bot.
for (int x = 0; x < _enemyWaves.size(); x++) { EnemyWave ew = (EnemyWave)_enemyWaves.get(x);
ew.distanceTraveled = (getTime() - ew.fireTime) * ew.bulletVelocity; if (ew.distanceTraveled > _myLocation.distance(ew.fireLocation) + 50) { _enemyWaves.remove(x); x--; } } }
public EnemyWave getClosestSurfableWave() { //finds closest wave in front of bot
double closestDistance = 50000; // just use some very big number here EnemyWave surfWave = null;
for (int x = 0; x < _enemyWaves.size(); x++) { EnemyWave ew = (EnemyWave)_enemyWaves.get(x); double distance = _myLocation.distance(ew.fireLocation) - ew.distanceTraveled;
if (distance > ew.bulletVelocity && distance < closestDistance) { surfWave = ew; closestDistance = distance; } }
return surfWave; }
// Given the EnemyWave that the bullet was on, and the point where we
// were hit, calculate the index into our stat array for that factor. public static int getFactorIndex(EnemyWave ew, Point2D.Double targetLocation) { double offsetAngle = (EnemyWave.absoluteBearing(ew.fireLocation, targetLocation)- ew.directAngle); double factor = Utils.normalRelativeAngle(offsetAngle) / EnemyWave.maxEscapeAngle(ew.bulletVelocity) * ew.direction;
return (int)EnemyWave.limit(0,(factor * ((BINS - 1) / 2)) + ((BINS - 1) / 2),BINS - 1); }
// Given the EnemyWave that the bullet was on, and the point where we
// were hit, update our stat array to reflect the danger in that area. public void logHit(EnemyWave ew, Point2D.Double targetLocation) { int index = getFactorIndex(ew, targetLocation);
for (int x = 0; x < BINS; x++) { // for the spot bin that we were hit on, add 1; // for the bins next to it, add 1 / 2; // the next one, add 1 / 5; and so on... _surfStats[x] += 1.0 / (Math.pow(index - x, 2) + 1); } }
public Point2D.Double predictPosition(EnemyWave surfWave, int direction) { //This code predictions the positions for angle of movement based on enemy waves, ticks, and directions and tries to orbit angle
Point2D.Double predictedPosition = (Point2D.Double)_myLocation.clone(); double predictedVelocity = getVelocity(); double predictedHeading = getHeadingRadians(); double maxTurning, moveAngle, moveDir;
int counter = 0; // number of ticks in the future boolean intercepted = false;
do { moveAngle = EnemyWave.wallSmoothing(predictedPosition, EnemyWave.absoluteBearing(surfWave.fireLocation, predictedPosition) + (direction * (Math.PI/2)), direction) - predictedHeading; moveDir = 1;
if(Math.cos(moveAngle) < 0) { moveAngle += Math.PI; moveDir = -1; }
moveAngle = Utils.normalRelativeAngle(moveAngle);
// maxTurning is built in like this, you can't turn more then this in one tick maxTurning = Math.PI/720d*(40d - 3d*Math.abs(predictedVelocity)); predictedHeading = Utils.normalRelativeAngle(predictedHeading + EnemyWave.limit(-maxTurning, moveAngle, maxTurning));
//if predictedVelocity and moveDir have // different signs you want to breack down // otherwise you want to accelerate (look at the factor "2") predictedVelocity += (predictedVelocity * moveDir < 0 ? 2*moveDir : moveDir); predictedVelocity = EnemyWave.limit(-8, predictedVelocity, 8);
// calculate the new predicted position predictedPosition = EnemyWave.project(predictedPosition, predictedHeading, predictedVelocity);
counter++;
if (predictedPosition.distance(surfWave.fireLocation) < surfWave.distanceTraveled + (counter * surfWave.bulletVelocity) + surfWave.bulletVelocity) { intercepted = true; } } while(!intercepted && counter < 500);
return predictedPosition; }
public double checkDanger(EnemyWave surfWave, int direction) {
int index = getFactorIndex(surfWave, predictPosition(surfWave, direction));
return _surfStats[index]; }
public void doSurfing() { EnemyWave surfWave = getClosestSurfableWave();
if (surfWave == null) { return; }
double dangerLeft = checkDanger(surfWave, -1); double dangerRight = checkDanger(surfWave, 1);
double goAngle = EnemyWave.absoluteBearing(surfWave.fireLocation, _myLocation); if (dangerLeft < dangerRight) { goAngle = EnemyWave.wallSmoothing(_myLocation, goAngle - (Math.PI/2), -1); } else { goAngle = EnemyWave.wallSmoothing(_myLocation, goAngle + (Math.PI/2), 1); }
EnemyWave.setBackAsFront(this, goAngle); }
}
|-