/**
*
*/
package rampancy.util.weapon;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.util.Arrays;
import rampancy.RampantRobot;
import rampancy.standard.*;
import rampancy.util.*;
import rampancy.util.data.segmentTree.*;
import rampancy.util.wave.RBulletWave;
import robocode.util.Utils;
/**
* @author Matthew Chun-Lum
*
*/
public class RAGFGun extends RGun {
public static final int ROLL_DEPTH = 10;
public static final String AGF_GUN = "average guess factor gun";
private RDefaultSegmentTree mainSegmentTree;
private RSmallSegmentTree smallSegmentTree;
public RAGFGun() {
super(AGF_GUN);
mainSegmentTree = new RDefaultSegmentTree();
smallSegmentTree = new RSmallSegmentTree();
}
/* (non-Javadoc)
* @see rampancy.util.weapon.RGun#getFiringSolution(rampancy.util.REnemyRobot)
*/
@Override
public RFiringSolution getFiringSolution(REnemyRobot enemy) {
RRobotState enemyState = enemy.getCurrentState();
RSTNode mainLeaf = mainSegmentTree.getSegmentForState(enemyState);
RSTNode smallLeaf = smallSegmentTree.getSegmentForState(enemyState);
double[] average = RUtil.average(mainLeaf.getGuessFactors(), smallLeaf.getGuessFactors());
int bestIndex = RUtil.indexOfLargest(average);
double guessFactor = RUtil.getGuessFactorForIndex(bestIndex, average.length);
double power;
if(enemy.getCurrentState().distance < 100) {
power = 3.0;
} else {
power = (1 - enemy.getCurrentState().distance / 1500.0) * 3.0;
}
power = RUtil.limit(0.1, power, 3.0);
double offsetAngle = enemyState.directionTraveling * guessFactor * RUtil.computeMaxEscapeAngle(RUtil.computeBulletVelocity(power));
offsetAngle = Utils.normalRelativeAngle(offsetAngle);
double maxPreciseEscapeAngle = RUtil.computePreciceMaxEscapeAngle(RUtil.computeBulletVelocity(power),
enemy.getReference(), enemy, RUtil.nonZeroSign(enemyState.directionTraveling * guessFactor));
double preciseOffsetAngle = enemyState.directionTraveling * guessFactor * maxPreciseEscapeAngle;
preciseOffsetAngle = Utils.normalRelativeAngle(preciseOffsetAngle);
double gunBearingToTarget = enemyState.absoluteBearing - enemy.getReference().getGunHeadingRadians();
gunBearingToTarget = Utils.normalRelativeAngle(gunBearingToTarget);
GFDrawableObject drawableObject = new GFDrawableObject(average);
return new RFiringSolution(null,
power,
gunBearingToTarget + preciseOffsetAngle,
0,
guessFactor,
Color.green,
this,
drawableObject);
}
/* (non-Javadoc)s
* @see rampancy.util.weapon.RGun#update(rampancy.util.wave.RBulletWave)
*/
@Override
public void update(RBulletWave wave) {
super.update(wave);
RSTNode mainLeaf = mainSegmentTree.getSegmentForState(wave.getTargetState());
double desiredDirection = RUtil.computeAbsoluteBearing(wave.getOrigin(), wave.getTarget().getLastState().location);
double angleOffset = Utils.normalRelativeAngle(desiredDirection - wave.getTargetState().absoluteBearing);
double guessFactor = Math.max(-1, Math.min(1, angleOffset / RUtil.computeMaxEscapeAngle(wave.getVelocity()))) * wave.getTargetState().directionTraveling;
int index = RUtil.computeBin(guessFactor, mainLeaf.getGuessFactors().length);
RSTNode.updateGuessFactors(mainLeaf, index, 2.0, ROLL_DEPTH);
// repeat for the small leaf
RSTNode smallLeaf = smallSegmentTree.getSegmentForState(wave.getTargetState());
desiredDirection = RUtil.computeAbsoluteBearing(wave.getOrigin(), wave.getTarget().getLastState().location);
angleOffset = Utils.normalRelativeAngle(desiredDirection - wave.getTargetState().absoluteBearing);
guessFactor = Math.max(-1, Math.min(1, angleOffset / RUtil.computeMaxEscapeAngle(wave.getVelocity()))) * wave.getTargetState().directionTraveling;
index = RUtil.computeBin(guessFactor, smallLeaf.getGuessFactors().length);
RSTNode.updateGuessFactors(smallLeaf, index, 2.0, ROLL_DEPTH);
}
public String getOverview() {
String str = super.getOverview() + "\n";
str += "Main tree\n";
str += mainSegmentTree.toString();
str += "Small tree\n";
str += smallSegmentTree.toString();
return str;
}
class GFDrawableObject implements RDrawableObject {
public double[] guessFactors;
public GeneralPath curve;
public double max;
public int max_index;
public GFDrawableObject(double[] guessFactors) {
this.guessFactors = Arrays.copyOf(guessFactors, guessFactors.length);
max = 0;
max_index = 0;
for(int i = 0; i < guessFactors.length; i++)
if(guessFactors[i] > max) {
max = guessFactors[i];
max_index = i;
}
// normalize
if(max != 0)
for(int i = 0; i < guessFactors.length; i++)
this.guessFactors[i] = (guessFactors[i] / max) * 200.0;
curve = new GeneralPath(GeneralPath.WIND_EVEN_ODD, guessFactors.length);
curve.moveTo(0, 0);
for(int i = 0; i < guessFactors.length; i++) {
curve.lineTo(i * 12 + 10, (int) Math.round(this.guessFactors[i]));
}
}
public void draw(Graphics2D g) {
Color lastColor = g.getColor();
g.setColor(Color.white);
g.draw(curve);
g.setColor(Color.red);
RUtil.drawOval(new RPoint(max_index * 12 + 10, guessFactors[max_index]), 3, g);
g.setColor(lastColor);
}
}
}