NP/Source Code

From Robowiki
< NP
Revision as of 20:16, 19 June 2009 by Nat (talk | contribs) (add the code)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the code for more shrank prototype2. Codesize: 532 bytes. 217 bytes to play with.

package nat.micro;

import robocode.AdvancedRobot;
import robocode.BulletHitEvent;
import robocode.Condition;
import robocode.HitByBulletEvent;
import robocode.HitWallEvent;
import robocode.ScannedRobotEvent;
import robocode.util.Utils;

import java.awt.geom.Point2D;

/**
 * 
 * NP - Nat Pavasant
 * 
 * A micro-bot by Nat Pavasant; named after the author. This robot perform a
 * Wave Surfing-like movement called Velocity Surfing and fire using a very
 * simple GuessFactor targeting.
 * 
 * Gun base on Falcon, by PEZ and Kawigi; Movement base on WaveSnake, by Kev.
 */
public class NP extends AdvancedRobot {
	// //////////////////////////////////////////
	// Falcon's Gun
	
	static final double BULLET_POWER = 2.5; // 2.5 is the best by the way =)
	static final double BULLET_VELOCITY = 12.5; // bullet velocity for 2.5-size
	// bullet
	
	static final int BINS = 31; // 31 bins is fine for non-smoothed array.
	static final int MIDDLE_BIN = 15; // middle gin
	static final double MEA = 0.694498266 / MIDDLE_BIN; // hard-coded for 2.5 bullet power
	static final double MAX_PASSED_DISTANCE = 12.5 / 2;
	
	static double _enemyX; // enemy location
	static double _enemyY; // enemy location
	static int _enemyDirection = 1;
	
	// Segment: Lateral Velocity
	static int[][] _gunStats = new int[6][BINS];
	
	// Gun
	// //////////////////////////////////////////
	
	// //////////////////////////////////////////
	// Movement
	
	// Distance controller constant
	static final double PREFERRED_DISTANCE = 150d;
	static final double CLOSING_FACTOR = 7500d;
	
	static double _moveFactor = 20; // length to move, story the direction as
	// sign
	static double _enemyEnergy; // keep track of enemy energy
	static int _currentVelocity;
	static int _myLateralVelocity;
	static int[] _surfStats = new int[9];
	
	public void run() {
		setAdjustRadarForGunTurn(true);
		setAdjustGunForRobotTurn(true);
		
		do {
			turnRadarRightRadians(1);
		} while (true);
	}
	
	public void onScannedRobot(ScannedRobotEvent e) {
		Wave wave;
		double enemyAbsoluteBearing;
		double distance;
		
		// /////////////////////////////////////
		// Wave (Velocity) Surfing movement
		// Base loosly on WaveSnake, by Kev
		//
		
		// Turn Perpendicular with distance controller
		setTurnRightRadians(Math.cos((enemyAbsoluteBearing = e
				.getBearingRadians())
				- ((distance = e.getDistance()) - PREFERRED_DISTANCE)
				* _moveFactor / CLOSING_FACTOR));
		
		if (_enemyEnergy > (_enemyEnergy = e.getEnergy())) {
			int testVel = 8;
			do {
				if (_surfStats[testVel] < _surfStats[_currentVelocity]) {
					_currentVelocity = testVel;
				}
				
				// Prevent robot to move at velocity 0 and 2
				if (testVel == 6)
					testVel = 3;
			} while (testVel-- > 0);
			
			if (_currentVelocity < 4) {
				onHitWall(null);
			}
		}
		
		setMaxVelocity(2 * (_currentVelocity - 4));
		setAhead(_moveFactor);
		// /////////////////////////////////////
		
		// /////////////////////////////////////
		// GuessFactor targeting gun
		// Base loosly on Falcon gun.
		//
		addCustomEvent(wave = new Wave());
		
		_enemyX = (wave.wGunX = getX())
				+ Math.sin(enemyAbsoluteBearing += getHeadingRadians())
				* distance;
		_enemyY = (wave.wGunY = getY()) + Math.cos(enemyAbsoluteBearing)
				* distance;
		
		double enemyLatVel;
		
		// check for enemy movement direction, preserve old direction if current
		// velocity is 0
		int direction;
		if ((direction = (int) Math.signum(enemyLatVel = e.getVelocity()
				* Math.sin(e.getHeadingRadians() - enemyAbsoluteBearing))) != 0)
			_enemyDirection = direction;
		
		// Radar - add here due the codesize shrinking
		setTurnRadarRightRadians(Utils
				.normalRelativeAngle((wave.wBearing = enemyAbsoluteBearing)
						- getRadarHeadingRadians()) * 2);
		
		// Segment: lateralVelocity
		wave.stats = _gunStats[(Math.abs(enemyLatVel) >= 7.75) ? 4 : (int) (1.4427 * Math
				.log(Math.abs(enemyLatVel) + 1.75))];
		
		int mostVisited = MIDDLE_BIN; // default at head-on
		int i = BINS;
		
		do {
			i--;
			if (wave.stats[i] > wave.stats[mostVisited])
				mostVisited = i;
		} while (i > 0);
		
		setTurnGunRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing
				- getGunHeadingRadians()
				+ (wave.wBearingDirection = MEA * _enemyDirection)
				* (mostVisited - MIDDLE_BIN)));
		setFire(BULLET_POWER);
		// /////////////////////////////////////////
	}
	
	static class Wave extends Condition {
		double wGunX;
		double wGunY;
		// Point2D.Double gunLocation;
		double wBearing;
		double wBearingDirection;
		double wDistance;
		
		int[] stats;
		
		public boolean test() {
			if (Math.abs((wDistance += BULLET_VELOCITY)
					- Point2D.distance(wGunX, wGunY, _enemyX, _enemyY)) <= MAX_PASSED_DISTANCE) {
				stats[(int) ((Utils.normalRelativeAngle(Math.atan2(_enemyX
						- wGunY, _enemyY - wGunX)
						- wBearing)) / wBearingDirection)
						+ MIDDLE_BIN]++;
				// removeCustomEvent(this);
			}
			
			return false;
		}
	}
	
	public void onBulletHit(BulletHitEvent e) {
		_enemyEnergy -= 12.5;
	}
	
	public void onHitByBullet(HitByBulletEvent e) {
		_surfStats[_currentVelocity]++;
	}
	
	public void onHitWall(HitWallEvent e) {
		_moveFactor = -_moveFactor;
	}
}