반응형
JAVA Robocode
2007 대회 우승자 소스
package kdh;
import java.awt.Color;
import java.awt.geom.*;
import robocode.*;
import robocode.util.Utils;
public class LambOfGod extends AdvancedRobot
{
double frameFigure = 1, prevEnergy = 100, counter = 0;
double enemyLatVelocity, enemyVelocity, lastenemyVelocity, lastenemyLatVelocity;
double lastVelocityChangeTime;
double wallDistance, reverseWallDistance;
double nextAngle, qualifiedAngle;
double enemyDirection, firePower;
boolean yAxis;
Point2D myPosition, enemyPosition, nextPosition, centerPosition, predictedPosition;
Rectangle2D battleField, movingField, meleeField;
static int MIDDLE_FACTOR = 16;
static int TOTAL_FACTORS = 33;
static double[][][][][][][] Data1 = new double[3][5][5][5][10][3][TOTAL_FACTORS];
static double[][][][][][][] Data2 = new double[3][5][5][5][8][3][TOTAL_FACTORS];
Wave root, current;
public void run()
{
setColors(new Color(200,0,50), new Color(150,0,50), new Color(100,0,50), Color.red, Color.pink);
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
do {
turnRadarRightRadians(Double.POSITIVE_INFINITY);
execute();
} while (true);
}
public void onScannedRobot(ScannedRobotEvent e)
{
double enemyDistance = e.getDistance();
double enemyAbsBearing = e.getBearingRadians() + getHeadingRadians();
double optimumAngle = enemyAbsBearing;
double battleFieldWidth = getBattleFieldWidth(), battleFieldHeight = getBattleFieldHeight();
boolean melee = (getOthers() > 2);
if(melee)
{
setTurnRadarRightRadians(Utils.normalRelativeAngle(enemyAbsBearing - getRadarHeadingRadians()) * Math.PI*4);
}else
{
setTurnRadarRightRadians(Utils.normalRelativeAngle(enemyAbsBearing - getRadarHeadingRadians()) * Math.PI/2);
}
firePower = Math.min(e.getEnergy()/4, ( enemyDistance > 250 ? 1.9 : 3));
if(melee)
{
if(getEnergy() < 10) firePower *= 0.5;
}else
{
if(getEnergy() < 10) firePower = 0;
if(getEnergy() < 10 && e.getEnergy() < 0.7) firePower = e.getEnergy()/4;
}
double bulletVelocity = 20 - 3 * firePower;
lastenemyLatVelocity = enemyLatVelocity;
lastenemyVelocity = enemyVelocity;
enemyVelocity = e.getVelocity();
myPosition = new Point2D.Double(getX(), getY());
centerPosition = new Point2D.Double(battleFieldWidth / 2, battleFieldHeight / 2);
enemyPosition = project(myPosition, enemyAbsBearing, enemyDistance);
battleField = new Rectangle2D.Double(18, 18, battleFieldWidth - 36, battleFieldHeight - 36);
movingField = new Rectangle2D.Double(50, 50, battleFieldWidth - 100, battleFieldHeight - 100);
meleeField = new Rectangle2D.Double(150, 150, battleFieldWidth - 300, battleFieldHeight - 300);
enemyLatVelocity = enemyVelocity * Math.sin(e.getHeadingRadians() - enemyAbsBearing);
enemyDirection = (enemyLatVelocity >= 0 ? 1 : -1) * Math.asin(8 / bulletVelocity);
wallDistance = 1.1;
while (wallDistance >= 0.1 && !battleField.contains(project(myPosition, enemyAbsBearing + (wallDistance -= 0.1) * enemyDirection, enemyDistance)));
reverseWallDistance = 1.1;
while (reverseWallDistance >= 0.1 && !battleField.contains(project(myPosition, enemyAbsBearing - (reverseWallDistance -= 0.1) * enemyDirection, enemyDistance)));
double moveTime = bulletVelocity * lastVelocityChangeTime++ / enemyDistance;
int accelIndex = (int)Math.round(Math.abs(enemyVelocity) - Math.abs(lastenemyVelocity));
if (accelIndex != 0) accelIndex = accelIndex > 0 ? 2 : 1;
int velIndex = (int)Math.abs(enemyLatVelocity/2);
int fastVelIndex = (int)Math.abs(enemyLatVelocity/2.66);
int timerIndex = moveTime < 0.4 ? 1 : moveTime < 0.8 ? 2 : moveTime < 1.2 ? 3 : 4;
int fastTimerIndex = moveTime < 0.6 ? 1 : 2;
int wallIndex = (int)(wallDistance * 3);
int fastWallIndex = (int)(wallDistance * 1.5);
int distanceIndex = (int)enemyDistance / 240;
int fastDistanceIndex = (int)enemyDistance / 360;
int reverseWallIndex = (int)(reverseWallDistance * 2);
int fastReverseWallIndex = (int)(reverseWallDistance * 1.25);
if (accelIndex > 0)
{
lastVelocityChangeTime = 0;
timerIndex = fastTimerIndex = 0;
}
Wave wave = new Wave();
wave.bulletOrigin = myPosition;
wave.targetOrigin = wave.currentTarget = project(enemyPosition, e.getHeadingRadians(), enemyVelocity);
wave.bulletAngle = Math.atan2(wave.targetOrigin.getX() - wave.bulletOrigin.getX() ,wave.targetOrigin.getY() - wave.bulletOrigin.getY());
wave.bulletVelocity = bulletVelocity;
wave.fireTime = wave.lastTime = getTime() - 1;
wave.enemyDirection = enemyDirection;
wave.Segment1 = Data1[accelIndex][velIndex][timerIndex][wallIndex][distanceIndex][reverseWallIndex];
wave.Segment2 = Data2[accelIndex][fastVelIndex][fastTimerIndex][fastWallIndex][fastDistanceIndex][fastReverseWallIndex];
if (getGunHeat() == 0) wave.real = true;
if (root == null) current = root = wave;
else current = (current.next = wave);
while (root != null && root.update(getTime(), enemyPosition)) root = root.next;
if (root != null)
{
Wave waveIterator = root.next;
while (waveIterator != null)
{
waveIterator.update(getTime(), enemyPosition);
waveIterator = waveIterator.next;
}
}
int bestIndex = MIDDLE_FACTOR;
double bestValue = smoothed(bestIndex,wave.Segment1,TOTAL_FACTORS) + smoothed(bestIndex,wave.Segment2,TOTAL_FACTORS);
for (int i = MIDDLE_FACTOR * 2 - 1; i >= 1; i--)
{
double currentValue = smoothed(i,wave.Segment1,TOTAL_FACTORS) + smoothed(i,wave.Segment2,TOTAL_FACTORS);
if(currentValue > bestValue)
{
bestIndex = i;
bestValue = currentValue;
}
}
if(melee)
{
double deltaTime = 0;
predictedPosition = enemyPosition;
while((++deltaTime) * bulletVelocity < myPosition.distance(predictedPosition)){
predictedPosition.setLocation(
predictedPosition.getX() + Math.sin(e.getHeadingRadians()) * enemyVelocity,
predictedPosition.getY() + Math.cos(e.getHeadingRadians()) * enemyVelocity);
if(!battleField.contains(predictedPosition))
{
predictedPosition.setLocation(
Math.min(Math.max(18.0, predictedPosition.getX()), battleFieldWidth - 18.0),
Math.min(Math.max(18.0, predictedPosition.getY()), battleFieldHeight - 18.0));
break;
}
}
double theta = Arctangent(myPosition, predictedPosition);
setTurnGunRightRadians(Utils.normalRelativeAngle(theta - getGunHeadingRadians()));
} else
{
double reviseAngle = enemyDirection * (bestIndex / (double)MIDDLE_FACTOR - 1);
setTurnGunRightRadians(Utils.normalRelativeAngle(enemyAbsBearing - getGunHeadingRadians() + reviseAngle));
}
setFireBullet(firePower);
if (frameFigure-- < 0)
{
if(melee)
{
if(counter==0)
{
nextPosition = new Point2D.Double(
(getX() > battleFieldWidth/2 ? battleFieldWidth - getX() : getX()),
(getY() > battleFieldHeight/2 ? battleFieldHeight - getY() : getY()));
if(nextPosition.getX() < nextPosition.getY())
{
if(getX() > battleFieldWidth/2) Initialize(Math.PI/2, nextPosition.getX(), -1);
else Initialize(-Math.PI/2, nextPosition.getX(), 1);
yAxis = true;
} else
{
if(getY() > battleFieldHeight/2) Initialize(0, nextPosition.getY(), 1);
else Initialize(Math.PI, nextPosition.getY(), -1);
yAxis = false;
}
counter++;
}
if(Math.atan(Math.tan(getTime() * Math.PI/40)) > 0)
{
do { nextPosition = new Point2D.Double(Math.random() * battleFieldWidth, Math.random() * battleFieldHeight);
} while (!movingField.contains(nextPosition) || meleeField.contains(nextPosition));
setAhead(yAxis ? nextPosition.getY() - getY() : nextPosition.getX() - getX());
}
optimumAngle = getHeadingRadians();
} else
{
do {
while(!movingField.contains(nextPosition = new Point2D.Double(Math.random() * battleFieldWidth ,Math.random() * battleFieldHeight)));
nextAngle = Arctangent(myPosition, nextPosition);
if (Comparison(nextAngle,enemyAbsBearing) > Comparison(optimumAngle,enemyAbsBearing)) optimumAngle = nextAngle;
} while (Comparison(optimumAngle,enemyAbsBearing) < Math.PI/2);
}
qualifiedAngle = nextAngle = Utils.normalRelativeAngle(optimumAngle - getHeadingRadians());
while(qualifiedAngle < -Math.PI/2) qualifiedAngle += Math.PI;
while(qualifiedAngle > Math.PI/2) qualifiedAngle -= Math.PI;
setTurnRightRadians(qualifiedAngle);
double movement = (qualifiedAngle == nextAngle ? 1 : -1) * myPosition.distance(nextPosition);
if(Math.random() > 0.7) movement *= -frameFigure/Math.PI/2;
if(!melee) setAhead(movement);
double deltaEnergy = e.getEnergy() - prevEnergy;
if(deltaEnergy >= -3 && deltaEnergy < 0) frameFigure = enemyDistance / (20 - 3 * deltaEnergy);
prevEnergy = e.getEnergy();
frameFigure *= (frameFigure >= 0 ? 1 : -1);
}
}
public double Comparison(double angle1,double angle2)
{
return Math.abs(Math.tan(angle1 - angle2));
}
public double Arctangent(Point2D point1, Point2D point2)
{
return Utils.normalAbsoluteAngle(Math.atan2(point2.getX() - point1.getX(), point2.getY() - point1.getY()));
}
public void Reposition(Point2D target)
{
double targetX, targetY;
targetX = (getX() > getBattleFieldWidth()/2) ? getBattleFieldWidth() - target.getX() : target.getX();
targetY = (getY() > getBattleFieldHeight()/2) ? getBattleFieldHeight() - target.getY() : target.getY();
target.setLocation(targetX, targetY);
}
public void Initialize(double angle, double distance, double sign)
{
turnRightRadians(Utils.normalRelativeAngle(angle - getHeadingRadians()));
ahead(distance - 25);
turnRightRadians(sign * Math.PI/2);
}
public Point2D project(Point2D position, double angle, double distance)
{
return new Point2D.Double(position.getX() + Math.sin(angle) * distance, position.getY() + Math.cos(angle) * distance);
}
public double Section(double min, double max, double value)
{
return value > max ? max : value < min ? min : value;
}
public double findGF(double startAngle, double newAngle, double enemyDirection, double middleFactor)
{
return Section(1, middleFactor * 2 - 1, Math.round((1 + Utils.normalRelativeAngle(newAngle - startAngle) / enemyDirection) * middleFactor));
}
public double smoothed(int GF, double[] seg, int TOTAL_FACTORS)
{
double x = 0;
for (int y = 1; y < TOTAL_FACTORS - 1; y++)
{
x += (double)seg[y] / Math.sqrt((double)(Math.abs(GF - y) + 1.0));
}
return x;
}
class Wave
{
Wave next;
Point2D bulletOrigin, targetOrigin, currentTarget;
double bulletAngle, bulletVelocity, enemyDirection;
double fireTime, lastTime;
double[] Segment1, Segment2;
boolean real = false;
boolean update(double time, Point2D enemy)
{
double deltaX = (enemy.getX() - currentTarget.getX()) / (time-lastTime);
double deltaY = (enemy.getY() - currentTarget.getY()) / (time-lastTime);
do{ if(bulletOrigin.distance(currentTarget) <= bulletVelocity * (lastTime - fireTime))
{
double currentAngle = Arctangent(bulletOrigin, currentTarget);
int index = (int)findGF(bulletAngle, currentAngle, enemyDirection, MIDDLE_FACTOR);
double weightReal = 1;
if(real) weightReal = 5;
for (int i = 1; i < MIDDLE_FACTOR * 2; i++)
{
Segment1[i] /= (1+weightReal / Segment1[0]);
Segment2[i] /= (1+weightReal / Segment2[0]);
}
Segment1[0] += weightReal;
Segment2[0] += weightReal;
Segment1[index] += (weightReal / Segment1[0]);
Segment2[index] += (weightReal / Segment2[0]);
return true;
}
lastTime++;
currentTarget.setLocation(currentTarget.getX() + deltaX, currentTarget.getY() + deltaY);
}while (lastTime < time);
return false;
}
}
}
반응형
'Technote > JAVA' 카테고리의 다른 글
| RoboCode -ActionSchool Team - 2rd (0) | 2009.05.29 |
|---|---|
| 10주차 10번문제 (0) | 2009.05.14 |
| 10주차 9번문제 (0) | 2009.05.14 |
| 10주차 8번문제 (0) | 2009.05.14 |
| 10주차 7번문제 (0) | 2009.05.14 |