[Home]Matchup/Code

Robo Home | Matchup | Changes | Preferences | AllPages

No diff available--this is the first major revision. (minor diff)
// Matchup by Stelokim
//
// History
// version 1.3: forward/reverse pattern-matcher
// version 1.4: statistical pattern-matcher
//
// Credit: ABC for the idea
package stelo;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import robocode.*;
import robocode.util.Utils;

public class Matchup extends AdvancedRobot {
	private static final int NUM_LOGS = 2; // [0]: velocity, [1]: angleChange, [2]: distance, [3]: bearingChange, [4]: ticksSinceMyFire
	private static final int PATTERN_LENGTH = 9000;
	private static int searchLength = 20; // increasing this will slow down the game
	private static int pattern_size = 0;
	private static int bulletTravelTime = 0;

	private static double[][] theLog = new double[PATTERN_LENGTH][NUM_LOGS];
	private static int cursor = 0;
	private double movementLateralAngle = 0.2;
	private Point2D enemyLocation;
	private Point2D robotLocation;
	private double enemyDistance;
	private double enemyAbsoluteBearing;
//	private static double maxVelocity = 8;
	private static final double WALL_MARGIN = 25;
	
	private static double lastEnemyHeading = 0;
	private static double lastEnemyVelocity = 0;
	private static double lastEnemyBearing = 0;
	private static double lastEnemyEnergy;
	
//	private static int ticksSinceMyFire = 0;
//	private static double smallestDiff;
//	private static double smallestDiffReverse;
//	private static double matchedSign = 1.0;
	
	private static double enemyBulletPower = 0.1;
	private static double energyDrop = 0;
//	private static int ticksSinceDirection = 0;
	
	private static int CLOSEST_SIZE = 50;
	private static double MAX_ESCAPE_ANGLE = 0.9; 
			
//	private static int hitRobotCount = 0;

	public void run() {
		setAdjustGunForRobotTurn(true);
		setAdjustRadarForGunTurn(true);

		do {
			turnRadarRightRadians(Double.POSITIVE_INFINITY);
		} while (true);
	}

	public void onScannedRobot(ScannedRobotEvent e) {
		double absbearing = e.getBearingRadians() + getHeadingRadians();
		setTurnRadarRightRadians(Utils.normalRelativeAngle(absbearing
				- getRadarHeadingRadians()) * 2); // 2 original

		robotLocation = new Point2D.Double(getX(), getY());
		enemyAbsoluteBearing = absbearing;
		enemyDistance = e.getDistance();
		enemyLocation = vectorToLocation(enemyAbsoluteBearing, enemyDistance,
				robotLocation);

		double bulletPower;
		energyDrop = lastEnemyEnergy - e.getEnergy();
		if (energyDrop >= 0.1 && energyDrop <= 3) 
			enemyBulletPower = energyDrop;
		bulletPower = enemyBulletPower;
			
		//bulletPower = limit(0.1, bulletPower, (enemyDistance < 100 || getOthers() > 5 || smallestDiff < 1) ? 3.0 : 2.0);
		bulletPower = Math.min(bulletPower, e.getEnergy() / 5.0 );
		bulletPower = limit(0.1, bulletPower, 3.0);
				
		if (getEnergy() > bulletPower && getGunHeat() / getGunCoolingRate() < 3 && getGunTurnRemainingRadians() == 0) {			
//		if (getEnergy() > bulletPower && getGunHeat() / getGunCoolingRate() < 3) {			
			double eX = e.getDistance() * Math.sin(absbearing);
			double eY = e.getDistance() * Math.cos(absbearing);
			
//			if (e.getEnergy() == 0.0) {
//				maxVelocity = 8.0;
//				goTo(new Point2D.Double(getX() + eX, getY() + eY));
//				return;
//			}
			
//			if (getGunHeat() == 0) {
				//out.println("matched index: " + index + "\tdiff: " + smallestDiff + "\tsearchLength: " + searchLength);
//				ticksSinceMyFire = 0;
//			}
	
			double bearingOffset = bestBearing(theLog, e, bulletPower, absbearing);
			if (Math.abs(bearingOffset) < MAX_ESCAPE_ANGLE) {
				setTurnGunRightRadians(Utils.normalRelativeAngle(absbearing + bearingOffset - getGunHeadingRadians()));
				setFire(bulletPower);
			}
		}
//		else {
//			setTurnGunRightRadians(Utils.normalRelativeAngle( absbearing - getGunHeadingRadians() ) );
//		}
//		ticksSinceMyFire++;
		
		if (Math.abs(e.getVelocity()) > 0 && getOthers() <= 1 && enemyDistance >= 200 && Math.abs(getEnergy() - e.getEnergy()) < 20) {
//			setMaxVelocity(maxVelocity = 8);
			mirrorMove();
		}
		else {
			randomMove();
		}
		//out.println("cursor: " + cursor);
		{
			/*
			//velocityChange[cursor] = e.getVelocity() - lastEnemyVelocity;
			velocityChange[cursor] = e.getVelocity();
			angleChange[cursor] = e.getHeadingRadians() - lastEnemyHeading;
			//angleChange[cursor] = (int) ((e.getHeadingRadians() - lastEnemyHeading) * 10000) / 10000.0;
			logDistance[cursor] = e.getDistance() / 1000;
			logEnergy[cursor] = e.getEnergy() / 1000;
			*/
			theLog[cursor][0] = e.getVelocity();
			theLog[cursor][1] = e.getHeadingRadians() - lastEnemyHeading;
			//theLog[cursor][1] = e.getHeadingRadians();
			//theLog[cursor][2] = e.getDistance() / 10000;
			//theLog[cursor][3] = (absbearing - lastEnemyBearing) / 100;
			//theLog[cursor][4] = ticksSinceMyFire / 100;
			
			cursor = (cursor + 1) % PATTERN_LENGTH;
//			out.println(cursor);
			if (pattern_size < PATTERN_LENGTH)
				pattern_size++;
		}
		lastEnemyHeading = e.getHeadingRadians();
		lastEnemyVelocity = e.getVelocity();
		lastEnemyBearing = absbearing;
		lastEnemyEnergy = e.getEnergy();
	}

//	public void onHitRobot(HitRobotEvent e) {
//		hitRobotCount++;
//	}

//    public void onHitByBullet(HitByBulletEvent e) {
//		if (getOthers() <= 1)
//			turnRadarRightRadians(Utils.normalRelativeAngle(e.getBearingRadians() + getHeadingRadians() - getRadarHeadingRadians()));
//	}

	public void onSkippedTurn(SkippedTurnEvent e) {
		out.println("SkippedTurn at: " + e.getTime());
	}

	// statistical pattern-matcher
	private double bestBearing(double[][] series, ScannedRobotEvent e, double bulletPower, double absbearing) {
		int[] closestIndexes = new int[CLOSEST_SIZE];
		double[] closestDiffs = new double[CLOSEST_SIZE];
		double[] angles = new double[CLOSEST_SIZE];
		int count = 0, i, c;
		
		for (c = 0 ; c < CLOSEST_SIZE; c++) {
			closestDiffs[c] = Double.POSITIVE_INFINITY;
		}
			
		i = (PATTERN_LENGTH + cursor - 1) % PATTERN_LENGTH;
		while (count < PATTERN_LENGTH) {
			double diff = 0;
			
			for (int j = 0; j < searchLength; j++) {
				int k = (i + j) % PATTERN_LENGTH;
				int searchIndex = (PATTERN_LENGTH + cursor - searchLength + j) % PATTERN_LENGTH;
				if (k == searchIndex) {
					diff = Double.POSITIVE_INFINITY;
					break;
				}
				diff += Math.abs(series[searchIndex][0] - series[k][0]) / 8.0; // velocity
				diff += Math.abs(series[searchIndex][1] - series[k][1]) / 0.17453292519943295769236907684886; // maximum turning, angleChange
			}
			for (c = 0 ; c < CLOSEST_SIZE; c++) {
				if (diff < closestDiffs[c] && Math.abs((i + searchLength) % PATTERN_LENGTH - cursor) > bulletTravelTime) {
					closestDiffs[c] = diff;
					closestIndexes[c] = (i + searchLength) % PATTERN_LENGTH;
					break;
				}		
			}
			count++;
			i = (PATTERN_LENGTH + i - 1) % PATTERN_LENGTH;
		}
	
		// reconstruct enemy movement
		for (c = 0 ; c < CLOSEST_SIZE; c++) {
			double eX = e.getDistance() * Math.sin(absbearing);
			double eY = e.getDistance() * Math.cos(absbearing);
			double ww = e.getHeadingRadians();
			double v = e.getVelocity();
			double db = 0;
			int index = closestIndexes[c];
	
			bulletTravelTime = 0;
			do {
				db += (20.0 - 3.0 * bulletPower);

				eX += v * Math.sin(ww);
				eY += v * Math.cos(ww);

				ww += theLog[index][1];
				v = theLog[index][0];
				
				if (index + 1 != cursor) {
					index = (index + 1) % PATTERN_LENGTH;
				}
				bulletTravelTime++;
			} while (db < Point2D.distance(0, 0, eX, eY)); 
			angles[c] = Utils.normalRelativeAngle(Math.atan2(eX, eY) - absbearing);
		}
	
		// find the most popular angle
		double angleThreshold = 36.0 / e.getDistance();
		int binSize = (int) (MAX_ESCAPE_ANGLE * 2.0 / angleThreshold) + 1;
		int[] statBin = new int[binSize];
		double[] metaAngle = new double[binSize];
		
		for (c = 0 ; c < CLOSEST_SIZE; c++) {
			int binIndex = (int) ((angles[c] + MAX_ESCAPE_ANGLE) / angleThreshold);
			metaAngle[binIndex] = angles[c];
			statBin[binIndex]++;
		}
		int maxIndex = 0;
		for (c = 0 ; c < binSize; c++) {
			if (statBin[c] > statBin[maxIndex]) {
				maxIndex = c;
			}
//			out.print(statBin[c] + " ");
		}
//		out.println();
		
		return metaAngle[maxIndex];
	}							
	
	private void mirrorMove() {
		goTo(new Point2D.Double(getBattleFieldWidth() - enemyLocation.getX(), getBattleFieldHeight() - enemyLocation.getY()));
	}
	
	// Always try to move a bit further away from the enemy.
	// Only when the walls forces us we will close in on the enemy. We never
	// bounce of walls.
	private void randomMove() {
//		if (energyDrop >= 0.1 && energyDrop <= 3) {
//			maxVelocity = Math.min(6.0, Math.random() * 20.0) + 2.0;
//		}
		
		considerChangingDirection();
		Point2D robotDestination;
		double tries = 0;
		double awayFactor = (getOthers() > 1) ? 2.0 : 1.0;
//		if (enemyDistance < 200) awayFactor = 5;

		do {
			// robotDestination =
			// vectorToLocation(absoluteBearing(enemyLocation, robotLocation) +
			// movementLateralAngle,
			// enemyDistance * (1.1 - tries / 100.0), enemyLocation);
			robotDestination = vectorToLocation(absoluteBearing(enemyLocation,
					robotLocation)
					+ movementLateralAngle, enemyDistance * awayFactor * (1.1 - tries / 100.0), enemyLocation);

			tries++;
		} while (tries < 100
				&& !fieldRectangle(WALL_MARGIN).contains(robotDestination));

		// } while (tries < 100 &&
		// !fieldRectangle(WALL_MARGIN).contains(robotDestination));

		goTo(robotDestination);
	}

	private void considerChangingDirection() {
		// Change lateral direction at random
		// Tweak this to go for flat movement
		//if (Math.random() < 0.05 || ticksSinceDirection > 35) {
		//if (Math.random() < 0.08 && ticksSinceDirection > (enemyDistance - 36) / (20 - 3 * enemyBulletPower) ) {
		if (Math.random() < 0.05) {	
			movementLateralAngle = -movementLateralAngle;
			//maxVelocity = Math.min(6.0, Math.random() * 20.0) + 2.0;
			//maxVelocity = 8;
			//ticksSinceDirection = 0;
		}
		
	//	ticksSinceDirection++;
	}

	/*
	 * RoundRectangle2D fieldRectangle(double margin) { return new
	 * RoundRectangle2D.Double(margin, margin, getBattleFieldWidth() - margin *
	 * 2, getBattleFieldHeight() - margin * 2, 75, 75); // 75 }
	 */

	private Rectangle2D fieldRectangle(double margin) {
		return new Rectangle2D.Double(margin, margin, getBattleFieldWidth()
				- margin * 2, getBattleFieldHeight() - margin * 2);
	}

	private void goTo(Point2D destination) {
		destination.setLocation(limit(35, destination.getX(),
				getBattleFieldWidth() - 35), limit(35, destination.getY(),
				getBattleFieldHeight() - 35));

		double angle = Utils.normalRelativeAngle(absoluteBearing(robotLocation,
				destination)
				- getHeadingRadians());
		double turnAngle = Math.atan(Math.tan(angle));
		setTurnRightRadians(turnAngle);
		setAhead(robotLocation.distance(destination)
				* (angle == turnAngle ? 1 : -1));
		// Hit the brake pedal hard if we need to turn sharply
		setMaxVelocity(Math.abs(getTurnRemaining()) > 30 ? 0 : 8);

		// vibrate
		//if (Math.abs(getTurnRemaining()) < 1) {
		//	setTurnRight(Math.random() < 0.5 ? 10 : -10);
		//}
	}

	private static Point2D vectorToLocation(double angle, double length,
			Point2D sourceLocation) {
		return vectorToLocation(angle, length, sourceLocation,
				new Point2D.Double());
	}

	private static Point2D vectorToLocation(double angle, double length,
			Point2D sourceLocation, Point2D targetLocation) {
		targetLocation.setLocation(sourceLocation.getX() + Math.sin(angle)
				* length, sourceLocation.getY() + Math.cos(angle) * length);
		return targetLocation;
	}

	private static double absoluteBearing(Point2D source, Point2D target) {
		return Math.atan2(target.getX() - source.getX(), target.getY()
				- source.getY());
	}

	public static double limit(double min, double value, double max) {
		return Math.max(min, Math.min(value, max));
	}
}


// Matchup by Stelokim
//
// History
// version 1.3: forward/reverse pattern-matcher
// version 1.4: statistical pattern-matcher
// version 1.5: optimization
// version 1.6: random movement only (better), targeting bounded in battle field
//
// Credit: ABC for the idea
package stelo;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import robocode.*;
import robocode.util.Utils;

public class Matchup extends AdvancedRobot {
	private static final int NUM_LOGS = 2; // [0]: velocity, [1]: angleChange, [2]: distance, [3]: bearingChange, [4]: ticksSinceMyFire
	private static final int PATTERN_LENGTH = 9000;
	private static int searchLength = 20; // increasing this will slow down the game. 20
	private static int pattern_size = 0;

	private static double[][] theLog = new double[PATTERN_LENGTH][NUM_LOGS];
	private static int cursor = 0;
	private double movementLateralAngle = 0.4;
	private Point2D enemyLocation;
	private Point2D robotLocation;
	private double enemyDistance;
	private double enemyAbsoluteBearing;
//	private static double maxVelocity = 8;
	private static final double WALL_MARGIN = 25;
	
	private static double lastEnemyHeading = 0;
	private static double lastEnemyVelocity = 0;
	private static double lastEnemyBearing = 0;
	private static double lastEnemyEnergy;
	
//	private static int ticksSinceMyFire = 0;
//	private static double smallestDiff;
//	private static double smallestDiffReverse;
//	private static double matchedSign = 1.0;
	
	private static double enemyBulletPower = 0.1;
	private static double energyDrop = 0;
//	private static int ticksSinceDirection = 0;
	
	private static int CLOSEST_SIZE = 50;
	private static double MAX_ESCAPE_ANGLE = 0.9;

	private static double maxX, maxY;
			
//	private static int hitRobotCount = 0;

	public void run() {
		setAdjustGunForRobotTurn(true);
		setAdjustRadarForGunTurn(true);
		
		maxX = getBattleFieldWidth() - 18;
		maxY = getBattleFieldHeight() - 18;

		do {
			turnRadarRightRadians(Double.POSITIVE_INFINITY);
		} while (true);
	}

	public void onScannedRobot(ScannedRobotEvent e) {
		double absbearing = e.getBearingRadians() + getHeadingRadians();
		setTurnRadarRightRadians(Utils.normalRelativeAngle(absbearing
				- getRadarHeadingRadians()) * 2); // 2 original

		robotLocation = new Point2D.Double(getX(), getY());
		enemyAbsoluteBearing = absbearing;
		enemyDistance = e.getDistance();
		enemyLocation = vectorToLocation(enemyAbsoluteBearing, enemyDistance,
				robotLocation);
				
		double bulletPower;
		energyDrop = lastEnemyEnergy - e.getEnergy();
		if (energyDrop >= 0.1 && energyDrop <= 3) 
			enemyBulletPower = energyDrop;
		bulletPower = enemyBulletPower;
			
		//bulletPower = limit(0.1, bulletPower, (enemyDistance < 100 || getOthers() > 5 || smallestDiff < 1) ? 3.0 : 2.0);
		bulletPower = Math.min(bulletPower, e.getEnergy() / 5.0 );
		bulletPower = limit(0.1, bulletPower, 3.0);
				
		if (getEnergy() > bulletPower && getGunHeat() / getGunCoolingRate() < 3 && getGunTurnRemainingRadians() == 0) {			
//		if (getEnergy() > bulletPower && getGunHeat() / getGunCoolingRate() < 3) {			
			double eX = e.getDistance() * Math.sin(absbearing);
			double eY = e.getDistance() * Math.cos(absbearing);
			
//			if (e.getEnergy() == 0.0) {
//				maxVelocity = 8.0;
//				goTo(new Point2D.Double(getX() + eX, getY() + eY));
//				return;
//			}
			
//			if (getGunHeat() == 0) {
				//out.println("matched index: " + index + "\tdiff: " + smallestDiff + "\tsearchLength: " + searchLength);
//				ticksSinceMyFire = 0;
//			}
	
			double bearingOffset = bestBearing(theLog, e, bulletPower, absbearing);
//			if (Math.abs(bearingOffset) < MAX_ESCAPE_ANGLE) {
				setTurnGunRightRadians(Utils.normalRelativeAngle(absbearing + bearingOffset - getGunHeadingRadians()));
				setFire(bulletPower);
//			}
		}
//		else {
//			setTurnGunRightRadians(Utils.normalRelativeAngle( absbearing - getGunHeadingRadians() ) );
//		}
//		ticksSinceMyFire++;
		
//		if (Math.abs(e.getVelocity()) > 0 && getOthers() <= 1 && enemyDistance >= 200 && Math.abs(getEnergy() - e.getEnergy()) < 20) {
//			setMaxVelocity(maxVelocity = 8);
//			mirrorMove();
//		}
//		else {
			randomMove();
//		}
//		if (getTime() % 60 < 30)
//			mirrorMove();
//		else
//			randomMove();

		//out.println("cursor: " + cursor);
		{
			/*
			//velocityChange[cursor] = e.getVelocity() - lastEnemyVelocity;
			velocityChange[cursor] = e.getVelocity();
			angleChange[cursor] = e.getHeadingRadians() - lastEnemyHeading;
			//angleChange[cursor] = (int) ((e.getHeadingRadians() - lastEnemyHeading) * 10000) / 10000.0;
			logDistance[cursor] = e.getDistance() / 1000;
			logEnergy[cursor] = e.getEnergy() / 1000;
			*/
			theLog[cursor][0] = e.getVelocity();
			theLog[cursor][1] = e.getHeadingRadians() - lastEnemyHeading;
//			theLog[cursor][2] = e.getDistance() / 10000;
			//theLog[cursor][3] = (absbearing - lastEnemyBearing) / 100;
			//theLog[cursor][4] = ticksSinceMyFire / 100;
			
			cursor = (cursor + 1) % PATTERN_LENGTH;
//			out.println(cursor);
			if (pattern_size < PATTERN_LENGTH)
				pattern_size++;
		}
		lastEnemyHeading = e.getHeadingRadians();
		lastEnemyVelocity = e.getVelocity();
		lastEnemyBearing = absbearing;
		lastEnemyEnergy = e.getEnergy();
	}

//	public void onHitRobot(HitRobotEvent e) {
//		hitRobotCount++;
//	}

//    public void onHitByBullet(HitByBulletEvent e) {
//		if (getOthers() <= 1)
//			turnRadarRightRadians(Utils.normalRelativeAngle(e.getBearingRadians() + getHeadingRadians() - getRadarHeadingRadians()));
//	}

	public void onSkippedTurn(SkippedTurnEvent e) {
		out.println("SkippedTurn at: " + e.getTime());
	}

	// statistical pattern-matcher
	private double bestBearing(double[][] series, ScannedRobotEvent e, double bulletPower, double absbearing) {
		int[] closestIndexes = new int[CLOSEST_SIZE];
		double[] closestDiffs = new double[CLOSEST_SIZE];
		double[] angles = new double[CLOSEST_SIZE];
		int count = 0, i, c;
		final double bulletSpeed = (20.0 - 3.0 * bulletPower);
		final double bulletTravelTime = enemyDistance / bulletSpeed;
		
		for (c = 0 ; c < CLOSEST_SIZE; c++) {
			closestDiffs[c] = Double.POSITIVE_INFINITY;
		}
			
		i = (PATTERN_LENGTH + cursor - 1) % PATTERN_LENGTH;
		while (count < PATTERN_LENGTH) {
			double diff = 0;
			
			for (int j = 0; j < searchLength; j++) {
				int k = (i + j) % PATTERN_LENGTH;
				int searchIndex = (PATTERN_LENGTH + cursor - searchLength + j) % PATTERN_LENGTH;
				if (k == searchIndex) {
					diff = Double.POSITIVE_INFINITY;
					break;
				}
				diff += Math.abs(series[searchIndex][0] - series[k][0]) / 8.0; // velocity
				diff += Math.abs(series[searchIndex][1] - series[k][1]) / 0.17453292519943295769236907684886; // maximum turning, angleChange
				//diff += Math.abs(series[searchIndex][2] - series[k][2]); // distance
			}
		
			// find maximum difference index
			int maxDiffIndex = 0;
			for (c = 0; c < CLOSEST_SIZE; c++) {
				if (closestDiffs[c] > closestDiffs[maxDiffIndex])
					maxDiffIndex = c;
			}
		
			// insert into the maximum difference index
			if (diff < closestDiffs[maxDiffIndex] && Math.abs((i + searchLength) % PATTERN_LENGTH - cursor) > bulletTravelTime) {
				closestDiffs[maxDiffIndex] = diff;
				closestIndexes[maxDiffIndex] = (i + searchLength) % PATTERN_LENGTH;
			}		
			count++;
			i = (PATTERN_LENGTH + i - 1) % PATTERN_LENGTH;
		}
	
		double initialEX = enemyDistance * Math.sin(absbearing);
		double initialEY = enemyDistance * Math.cos(absbearing);
		double eV = e.getVelocity();
	
		// reconstruct enemy movement
		for (c = 0 ; c < CLOSEST_SIZE; c++) {
			double eX = initialEX;
			double eY = initialEY;
			double ww = e.getHeadingRadians();
			double v = eV;
			double db = 0;
			int index = closestIndexes[c];
	
			do {
				db += bulletSpeed;

				eX += v * Math.sin(ww);
				eY += v * Math.cos(ww);

				ww += theLog[index][1];
				v = theLog[index][0];
				
//				if (index + 1 != cursor) {
					index = (index + 1) % PATTERN_LENGTH;
//				}
			} while (db < Point2D.distance(0, 0, eX, eY));

			double absoluteEX = limit(18, eX + robotLocation.getX(), maxX);
			double absoluteEY = limit(18, eY + robotLocation.getY(), maxY);
			//angles[c] = Utils.normalRelativeAngle(Math.atan2(eX, eY) - absbearing);
			angles[c] = Utils.normalRelativeAngle(Math.atan2(absoluteEX - robotLocation.getX(), absoluteEY - robotLocation.getY()) - absbearing);
			
		}
	
		// find the most popular angle
		double angleThreshold = 36.0 / e.getDistance();
		int binSize = (int) (MAX_ESCAPE_ANGLE * 2.0 / angleThreshold) + 1;
		int[] statBin = new int[binSize];
		//double[] statBin = new double[binSize];
		
		double[] metaAngle = new double[binSize];
		
		for (c = 0 ; c < CLOSEST_SIZE; c++) {
			int binIndex = (int) ((angles[c] + MAX_ESCAPE_ANGLE) / angleThreshold);
			metaAngle[binIndex] = angles[c];
			statBin[binIndex]++;
			//statBin[binIndex] += 1.0 / closestDiffs[c]; // weighted
		}
		int maxIndex = 0;
		for (c = 0 ; c < binSize; c++) {
			if (statBin[c] > statBin[maxIndex]) {
				maxIndex = c;
			}
//			out.print(statBin[c] + " ");
		}
//		out.println();
		
		return metaAngle[maxIndex];
	}							
	
//	private void mirrorMove() {
//		goTo(new Point2D.Double(getBattleFieldWidth() - enemyLocation.getX(), getBattleFieldHeight() - enemyLocation.getY()));
//	}
	
	private static final double REVERSE_TUNER = 0.421075;
	private static final double WALL_BOUNCE_TUNER = 0.699484;	
	private void randomMove() {
//		if (energyDrop >= 0.1 && energyDrop <= 3) {
//			maxVelocity = Math.min(6.0, Math.random() * 20.0) + 2.0;
//		}
		
			
		Point2D robotDestination;
		double tries = 0;
		double awayFactor = (getOthers() > 1) ? 2.0 : 1.0;
		// if (enemyDistance < 200) awayFactor = 4.0;

		do {
			// robotDestination =
			// vectorToLocation(absoluteBearing(enemyLocation, robotLocation) +
			// movementLateralAngle,
			// enemyDistance * (1.1 - tries / 100.0), enemyLocation);
			robotDestination = vectorToLocation(absoluteBearing(enemyLocation,
					robotLocation)
					+ movementLateralAngle, enemyDistance * awayFactor * (1.2 - tries / 100.0), enemyLocation); // 1.1
					
			tries++;
		} while (tries < 125
				&& !fieldRectangle(WALL_MARGIN).contains(robotDestination));
				
		double bv = 20.0 - 3.0 * enemyBulletPower;
		if ((Math.random() < (bv / REVERSE_TUNER) / enemyDistance ||
				tries > (enemyDistance / bv / WALL_BOUNCE_TUNER))) {
			movementLateralAngle = -movementLateralAngle;	
		}									

		// } while (tries < 100 &&
		// !fieldRectangle(WALL_MARGIN).contains(robotDestination));

		goTo(robotDestination);
	}					

	/*
	 * RoundRectangle2D fieldRectangle(double margin) { return new
	 * RoundRectangle2D.Double(margin, margin, getBattleFieldWidth() - margin *
	 * 2, getBattleFieldHeight() - margin * 2, 75, 75); // 75 }
	 */

	private Rectangle2D fieldRectangle(double margin) {
		return new Rectangle2D.Double(margin, margin, getBattleFieldWidth()
				- margin * 2, getBattleFieldHeight() - margin * 2);
	}

	private void goTo(Point2D destination) {
//		destination.setLocation(limit(35, destination.getX(),
//				getBattleFieldWidth() - 35), limit(35, destination.getY(),
//				getBattleFieldHeight() - 35));

		double angle = Utils.normalRelativeAngle(absoluteBearing(robotLocation,
				destination)
				- getHeadingRadians());
		double turnAngle = Math.atan(Math.tan(angle));
		
		setTurnRightRadians(turnAngle);
		setAhead(robotLocation.distance(destination)
				* (angle == turnAngle ? 1 : -1));
		// Hit the brake pedal hard if we need to turn sharply
		setMaxVelocity(Math.abs(getTurnRemaining()) > 30 ? 0 : 8);

		// vibrate
		//if (Math.abs(getTurnRemaining()) < 1) {
		//	setTurnRight(Math.random() < 0.5 ? 10 : -10);
		//}
	}

	private static Point2D vectorToLocation(double angle, double length,
			Point2D sourceLocation) {
		return vectorToLocation(angle, length, sourceLocation,
				new Point2D.Double());
	}

	private static Point2D vectorToLocation(double angle, double length,
			Point2D sourceLocation, Point2D targetLocation) {
		targetLocation.setLocation(sourceLocation.getX() + Math.sin(angle)
				* length, sourceLocation.getY() + Math.cos(angle) * length);
		return targetLocation;
	}

	private static double absoluteBearing(Point2D source, Point2D target) {
		return Math.atan2(target.getX() - source.getX(), target.getY()
				- source.getY());
	}

	public static double limit(double min, double value, double max) {
		return Math.max(min, Math.min(value, max));
	}
}


Robo Home | Matchup | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited October 12, 2007 9:40 EST by Stelokim (diff)
Search: