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 |