MicroBot champ!

Fragment of a discussion from Talk:ÉpéeistMicro
Jump to navigation Jump to search

That's what I assume.

Here's the current developmental code with all the debug code (I realize that it's quite a bit larger than 730 bytes.):

/*
EpeeistMicro v1.9.1 by Sheldor.  05/02/2013
A MicroBot with Stop and Go/Random movement and a guess factor gun.
Codesize: 730 Bytes without any colors.

Epee (pronounced ey-PEY) is one of the three forms of modern sport fencing,
along with Foil and Sabre.  http://en.wikipedia.org/wiki/Epee

Credits: 
Thanks go to the authors of the following bots:
	Targeting: Falcon, pez.micro.Aristocles, voidious.mini.Komarious, kc.micro.Thorn, jam.micro.RaikoMicro, jk.mini.CunobelinDC, mld.LittleBlackBook, jk.micro.Connavar.
	Movement : jk.micro.Toorkild, kc.micro.Thorn, wiki.nano.RaikoNano.
Special thanks to Jdev and Voidious for helping me with a math error.
And a general thanks to all open source bot authors and contributors to the RoboWiki.

EpeeistMicro is open source and released under the terms of the RoboWiki Public Code License (RWPCL) - Version 1.1.
See license here: http://robowiki.net/wiki/RWPCL
*/

package sheldor.micro;

import robocode.*;
import robocode.util.Utils;
import java.awt.geom.*;

public class EpeeistMicro extends AdvancedRobot
{
	//Constants.
	static final int    GUESS_FACTORS = 25;
	static final int    MIDDLE_FACTOR = (GUESS_FACTORS - 1) / 2;
	static final double MAXIMUM_ESCAPE_ANGLE = 0.72727272727272727272727272727273; //8 / 11
	static final double FACTOR_ANGLE = MAXIMUM_ESCAPE_ANGLE / MIDDLE_FACTOR;
	
	//Global variables.
	static double averageLateralVelocity;
	static double direction = 1;
	static double enemyBulletSpeed;
	static double enemyEnergy;
	static double enemyHeading;
	static double enemyVelocity;
	static double enemyX;
	static double enemyY;
	static double hits;
	static int    absoluteEnemyLateralVelocity;
	static int    movementMode;
	static int    timeSinceVelocityChange;
	
	static int ticks;
	
	//Array to store the number of times the enemy has visited each guess factor.
	//Segmented on acceleration, time since velocity change, absolute enemy lateral velocity, near wall, and distance.
	static int[][][][][][] guessFactors = new int[3][4][5][2][5][GUESS_FACTORS];
	
	//En garde!
	public void run()
	{
		//Set the radar and gun to turn independently.
		setAdjustRadarForGunTurn(true);
		setAdjustGunForRobotTurn(true);
	}
	
	public void onStatus(StatusEvent e)
	{
		//Turn the radar every tick.
		//Putting the code here instead of in the run() method saves one byte.
		//I believe Wompi discovered this.
    	setTurnRadarRightRadians(1);
	}
	
	public void onScannedRobot(ScannedRobotEvent e)
	{
		//Local variables.	
		//Declare most used integer before most used double to save several bytes.
		int    antiRam;
		double enemyDistance;
		double absoluteBearing;
		double enemyDirection;
		double lateralVelocity;
		double offset;
		double theta;
		int    acceleration;
		
		ticks = (int)getTime();
		
		//Fire a wave.
		Wave wave;
		addCustomEvent(wave = new Wave());
		
		enemyX = (wave.sourceX = getX()) + Math.sin(wave.absoluteBearing = absoluteBearing = 
			(e.getBearingRadians() + getHeadingRadians())) * (enemyDistance = e.getDistance());
		enemyY = (wave.sourceY = getY()) + Math.cos(absoluteBearing) * enemyDistance;
		
		/*********************************************
		 *---------------MOVEMENT CODE---------------*
		 *********************************************/
				
		//Retreat very heavily when the enemy is ramming.
		offset = 2 + (antiRam = (int)(100 / (wave.enemyDistance = enemyDistance = e.getDistance())));
		
		//Wall smoothing based on Toorkild's.
		//Subtract current coordinates from lower wall bounds instead of adding 
		//current coordinates to every fieldRectangle.contains() projection to save six bytes.  Thanks go to Skilgannon.
		Rectangle2D.Double fieldRectangle;
		while(!(fieldRectangle = new Rectangle2D.Double(18 - getX(), 18 - getY(), 764, 564)).
			contains(160 * Math.sin(theta = (wave.absoluteBearing = absoluteBearing = 
			(e.getBearingRadians() + getHeadingRadians())) + direction * (offset -= .02)), 160 * Math.cos(theta)));
		setTurnRightRadians(Math.tan(theta -= getHeadingRadians()));
			
		//Stop and Go movement based on Toorkild's.
		//Move when the enemy fires, or when the robot is moving randomly, or when the enemy is ramming.
		double energyDelta;
		if ((energyDelta = (enemyEnergy - (enemyEnergy = e.getEnergy()))) > movementMode - antiRam)
		{			
			//Calculate the length of Stop and Go movement based on enemy bullet power.
			setAhead(((3 + (int)(energyDelta / 0.5000001)) << 3) * Math.signum(Math.cos(theta)));
		}
		
		//Random movement from Toorkild.
		//Don't move randomly if the enemy is ramming, or if the bot is in Stop and Go mode.
		//Reverse direction if the bot gets too close to a wall.
		if (Math.random() + antiRam < (-0.6 * Math.sqrt(enemyBulletSpeed / enemyDistance) + 0.04) * movementMode || offset < Math.PI/3.5)
		{
			direction = -direction;
		}
		
		/********************************************
		 *--------------TARGETING CODE--------------*
		 ********************************************/
		
		//Determine the enemy's lateral velocity and movement direction.
		//Use a simple rolling average to store the previous lateral direction
		//if enemy lateral velocity == 0.  Inspired by LittleBlackBook.
		wave.enemyDirection = enemyDirection = (averageLateralVelocity = ((averageLateralVelocity * .01) +
			(lateralVelocity = ((enemyVelocity = e.getVelocity()) * Math.sin((enemyHeading = e.getHeadingRadians()) - absoluteBearing))))) < 0 ? -FACTOR_ANGLE : FACTOR_ANGLE;
		
		//Determine if the enemy is accelerating or decelerating.
		if ((acceleration = (int)Math.signum(absoluteEnemyLateralVelocity - (absoluteEnemyLateralVelocity = (int)Math.abs(lateralVelocity)))) != 0)
		{
			timeSinceVelocityChange = 0;
		}
					
		//Determine the current situation.
		//Declaring a local array saves two bytes.
		double angle;
		int[] guessFactorsLocal = wave.guessFactors = guessFactors
			[1 + acceleration] //Acceleration.
			[Math.min(3, (int)(Math.pow(280 * timeSinceVelocityChange++ / enemyDistance, .7)))] //Ticks since velocity change.
			[absoluteEnemyLateralVelocity / 2] //Absolute enemy lateral velocity.
			[(int)Math.signum(fieldRectangle.outcode(Math.sin(angle = (absoluteBearing +
				enemyDirection * MIDDLE_FACTOR)) * enemyDistance, Math.cos(angle) * enemyDistance))] //Near wall.  Many thanks go to Skilgannon for the outcode trick.
			[(int)enemyDistance / 200]; //Distance.

		//Find the most visited guess factor for the current situation.
		//Looping like this is ugly, but it saves two bytes over the proper way.
		int mostVisited = MIDDLE_FACTOR;
		int i = 0;
		try
		{
			while (true)
			{
				if (guessFactorsLocal[i] > guessFactorsLocal[mostVisited])
				{
					mostVisited = i;
				}
				i++;
			}			
		}
		catch(Exception ex)
		{
		}
		
		//Turn the gun to the most visited guess factor.
		//The slight offset helps to defeat simple bullet shielding.
		setTurnGunRightRadians(0.0005 + Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians()
			+ (enemyDirection * (mostVisited - MIDDLE_FACTOR))));
		
		//Fire medium power bullets most of the time, but use full power at very close range.
		//If the enemy is weak, fire the minimum power needed to destroy them.
		setFire(Math.min(2 + antiRam, enemyEnergy / 4));
		
		//Narrow lock radar.
		setTurnRadarRightRadians(2 * Utils.normalRelativeAngle(absoluteBearing - getRadarHeadingRadians()));
	}
	
	public void onBulletHit(BulletHitEvent e)
	{
		//Adjust enemy energy variable when the bot hits the enemy.
		//This makes a big difference against linear targeting.
		enemyEnergy -= 10;
	}
	
	public void onHitByBullet(HitByBulletEvent e)
	{
		//Adjust enemy energy variable when the bot gets hit.
		//Store the velocity of the enemy bullet for the random movement.
		enemyEnergy += 20 - (enemyBulletSpeed = e.getVelocity());	
		
		//If the bot takes a lot of damage on average in Stop and Go mode, switch to Random Movement.
		//Thanks go to Skilgannon.
		if ((hits += (4.25 / enemyBulletSpeed)) > getRoundNum() + 2)
		{
			movementMode = -1;
		}
    }	
	
	static class Wave extends Condition
	{
		//Global variables.
		double absoluteBearing;
		double bearingOffset;
		double enemyDirection;
		double enemyDistance;
		double sourceX;
		double sourceY;	
		double waveDistanceTraveled;
		double distanceTraveled;
		int[]  guessFactors;
		
		public boolean test()
		{
			//Update the bearing offset with angular velocities.
			bearingOffset += (enemyVelocity * Math.sin(enemyHeading -= absoluteBearing)) / (enemyDistance += (enemyVelocity * Math.cos(enemyHeading/* - absoluteBearing*/)));
			
			//Check if the wave has passed the enemy's current location.
			if (Math.abs((waveDistanceTraveled += 14) - enemyDistance) <= 7)
			{
				//Calculate the guess factor that would have hit the enemy.
				//Increment the bin that represents that guess factor.
				guessFactors[(int)Math.round((bearingOffset / enemyDirection) + MIDDLE_FACTOR)]++;
				
				System.out.println("New Method - Tick: " + ticks + " - "  + bearingOffset);
			}
			
			if (Math.abs((distanceTraveled += 14) - Point2D.distance(sourceX, sourceY, enemyX, enemyY)) <= 7)
			{
				//Calculate the guess factor that would have hit the enemy.
				//Increment the bin that represents that guess factor.
				System.out.println("Old Method - Tick: " + ticks + " - "  + Utils.normalRelativeAngle(Math.atan2(enemyX - sourceX,
					enemyY - sourceY) - absoluteBearing));
			}
			return false;
		}
	}
}

Thanks

Sheldor16:22, 2 May 2013