Épéeist/Code

From Robowiki
< Épéeist
Revision as of 15:34, 2 March 2026 by Sheldor2 (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
/*
Epeeist(Micro) v3.7 by Sheldor.  05/01/2024  Code size:  749 bytes
a microbot with stop and go/random movement and a guess factor gun
v3.7 -- targeting based on v2.1, radar, fix table


Épée is one of the three forms of modern sport fencing,
along with foil and sabre.  https://en.wikipedia.org/wiki/Epee


Credits:
	Targeting: pez.micro.Aristocles, nz.jdc.HedgehogGF, kc.micro.Thorn, pez.mini.Pugilist, jam.mini.Raiko, Falcon, voidious.mini.Komarious, jam.micro.RaikoMicro, jk.mini.CunobelinDC, jk.micro.Connavar, mld.LittleBlackBook
	Movement : nz.jdc.HedgehogGF, jk.micro.Cotillion, jk.micro.Toorkild, kc.micro.Thorn, wiki.nano.RaikoNano
Special thanks go to Jdev and Voidious for helping me with a mathematical error.
Also, a general thanks to all open source bot authors and contributors to the RoboWiki.


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


package sheldor.micro;


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


public class Epeeist 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;
		
	static final char FW1 = 6;
	static final char FW2 = 12;
	static final char RW1 = (char)-6;
	
	//global variables
	static double direction = 1;
	static double enemyBulletSpeed;	
	static double enemyDirection;
	static double enemyEnergy;	
	static double enemyHeading;
	static double hits;
	static int    movementMode;
	static int    previousEnemyVelocity;
	
	static int mostVisited = 4 + MIDDLE_FACTOR;
	
	static double enemyVelocity;
	static int ticksSinceVelocityChange;
	
	//array to store the number of times the enemy has visited each guess factor
	//segmented on velocity history, velocity, forward and reverse wall proximity, and distance
	static int[][][][][] guessFactors = new int[7][3][6][4][GUESS_FACTORS];
	
	public void onStatus(StatusEvent e)
	{		
		//colors
		setColors(java.awt.Color.white, java.awt.Color.black, java.awt.Color.lightGray);


		//turn the radar every tick
		//Putting the code here instead of in a while(true) loop in the run() method saves one byte.
		//I believe Wompi discovered this.
    	setTurnRadarRightRadians(1);
		
		//set the radar and gun to turn independently
		//Putting these here with the radar code lets me get rid of the run() method, saving one byte.  credit to Cotillion
		setAdjustRadarForGunTurn(true);
		setAdjustGunForRobotTurn(true);
	}
	
	public void onScannedRobot(ScannedRobotEvent e)
	{
		//local variables	
		//declare the most used integer before the most used double to save several bytes
		int    i = 4;
		double absoluteBearing;
		double enemyDistance;
		double localEnemyDirection;
		double offset;
		double theta;
		int    antiRam;
		
		//fire a wave
		Wave wave;
		addCustomEvent(wave = new Wave());
		
		//energy management based on distance, energy, and enemy energy
		//retreat very heavily when the enemy is ramming
		setFire((offset = (2 + (antiRam = (100 / (int)(wave.enemyDistance = enemyDistance = e.getDistance())))
				)) + antiRam - (BULLET_POWER_TABLE
				.charAt((((int)getEnergy() >> 3) * 127) + (int)e.getEnergy()) / 100.01)
			);
		
		/*********************************************
		 *---------------MOVEMENT CODE---------------*
		 *********************************************/				
					
		//wall smoothing based on HedgehogGF's
		do{}while(fieldContains(theta = (wave.absoluteBearing = absoluteBearing = 
			(e.getBearingRadians() + getHeadingRadians())) + direction * (offset -= 0.02), 160) > 0);
		setTurnRightRadians(Math.tan(theta -= getHeadingRadians()));
			
		//stop and go movement originally based on Thorn's
		//move when the enemy fires, or when the robot is moving randomly, or when the enemy is ramming
		double energyDrop;
		if ((energyDrop = (enemyEnergy - (enemyEnergy = e.getEnergy()))) > movementMode - antiRam)
		{			
			//credit to Cotilion for stop and go length calculator
			//credit to HedgehogGF for the copySign trick						
			setAhead(Math.copySign(((3 + (int)(energyDrop * 1.999999)) << 3), 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 enemy wall proximity
		//inspired by Pugilist and HedgehogGF
		int wallScore = 0;	
		do
		{
			wallScore += fieldContains(absoluteBearing + (


				//determine the enemy's lateral movement direction
				//use a simple rolling average to store the previous lateral direction if enemy lateral velocity == 0
				//credit to HedgehogGF
				(wave.enemyDirection = localEnemyDirection = (enemyDirection = Math.signum(0.00000000000001 + 
				 ((enemyVelocity = e.getVelocity()) * Math.sin((enemyHeading = e.getHeadingRadians()) - absoluteBearing))
				 + (enemyDirection / 100))) * FACTOR_ANGLE)


				 * ((short)WALL_TABLE.charAt(i))), enemyDistance);
		}
		while(--i >= 0);
		
		//calculate deceleration and whether or not to reset ticks since velocity change
		int deceleration;
		if ((deceleration = Integer.signum(previousEnemyVelocity - (previousEnemyVelocity = (int)Math.abs(enemyVelocity)))) != 0)
		{
			ticksSinceVelocityChange = deceleration;
		}
		
		//determine the current situation
		//Declaring a local array saves two bytes.
		int[] guessFactorsLocal = wave.guessFactors = guessFactors
			[VELOCITY_HISTORY_TABLE.charAt(ticksSinceVelocityChange += 3)] //deceleration and ticks since velocity change
			[previousEnemyVelocity / 3] //velocity
			[wallScore] //wall proximity
			[(int)enemyDistance >> 8]; //distance


		//find the most visited guess factor for the current situation
		//default to previous most visited
		//Looping like this is ugly, but it saves two bytes over the proper way.		
		try
		{
			while (true)
			{
				if ((guessFactorsLocal[++i]) > guessFactorsLocal[mostVisited])
				{
					mostVisited = i;
				}
			}
		}
		catch(Exception ex)
		{
		}		
		
		//turn the gun to the most visited guess factor
		//random offset to resist bullet shielding
		//aim directly at current enemy location when enemy energy == 0
		setTurnGunRightRadians((0.007 * Math.random()) + Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians()
			+ (localEnemyDirection * (mostVisited - MIDDLE_FACTOR) * Math.signum(enemyEnergy))));
		
		//radar lock
		setTurnRadarRightRadians(2 * Utils.normalRelativeAngle(absoluteBearing - getRadarHeadingRadians()));
	}
	
	public void onBulletHit(BulletHitEvent e)
	{
		//adjust the 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 the enemy energy variable when the bot gets hit
		//store the velocity of the enemy's bullet for the random movement
		double damage;
		enemyEnergy += (damage = 20 - (enemyBulletSpeed = e.getVelocity()));
		
		//if the bot takes an unacceptable amount of damage relative to the number of rounds
		//that have passed while in stop and go mode, switch to random movement
		if ((hits += damage) > (getRoundNum() * 23) + 40)
		{
			movementMode = -1;
		}
    }
	
	static class Wave extends Condition
	{
		//global variables	
		double absoluteBearing;
		double enemyDirection;
		double bearingOffset;
		double enemyDistance;
		double waveDistanceTraveled;
		int[]  guessFactors;
		
		public boolean test()
		{
			//velocity-based bearing offset for code size
			//velocity and heading updated each tick
			double relativeHeading;
			bearingOffset += (enemyVelocity * Math.sin(relativeHeading = (enemyHeading - absoluteBearing))) / (enemyDistance += (enemyVelocity * Math.cos(relativeHeading)));
			
			//check if the wave has passed the enemy's current location
			if ((waveDistanceTraveled += 14) > enemyDistance)
			{				
				//calculate the guess factor that the enemy has visited
				//increment the bin that represents that guess factor
				guessFactors[(int)Math.round(bearingOffset / enemyDirection) + MIDDLE_FACTOR]++;
				
				//one result per wave
				waveDistanceTraveled = Double.NEGATIVE_INFINITY;
			}
			return false;
		}
	}
	
	//This method returns 1 if a point projected from the bot's location by the 
	//"heading" and "distance" parameters is outside of the battlefield, and 0 if it is not.
	//credit to HedgehogGF
	private int fieldContains(double heading, double distance)
	{
		return Integer.signum(new Rectangle2D.Double(18, 18, 764, 564).outcode(getX() + distance * Math.sin(heading), getY() + distance * Math.cos(heading)));
	}
	
	//table to look up wall tests
	static final String WALL_TABLE = ""
	+ FW1 + FW1
	+ FW2 + FW2
	+ RW1;
	
	//tables for energy management
	static final String BP0 = ""
	+ (char)0 + (char)0 + (char)0 + (char)0 
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0 + (char)0 
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0 + (char)0;	
	
	static final String MAIN = ""	
	+ (char)175 + (char)150 + (char)125 + (char)100
	+ (char)83 + (char)66 + (char)50 + (char)33
	+ (char)16 + (char)0
	
		+ BP0	
		+ BP0	
		+ BP0	
		+ BP0	
		+ BP0
	
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0;	


	static final String BP190 = ""	
	+ (char)190 + (char)190 + (char)190 + (char)190
	+ (char)190 + (char)190 + (char)190 + (char)190
	+ (char)190 + (char)190 + (char)190 + (char)190
	+ (char)190 + (char)190 + (char)190 + (char)190
	+ (char)190 + (char)190 + (char)190 + (char)190;
	
	static final String BULLET_POWER_TABLE = ""
	//0 * 127
	+ BP190	
	+ BP190
	
	+ BP0 + BP0 + BP0 + BP0
	
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0
	
	//1 * 127	
	+ (char)175 + (char)150 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	+ (char)170 + (char)170 + (char)170 + (char)170
	
	+ BP0 + BP0 + BP0
	
	+ (char)0 + (char)0 + (char)0 + (char)0
	+ (char)0 + (char)0 + (char)0
	
	//2 * 127	
	+ MAIN
	
	//3 * 127			
	+ MAIN
	
	//4 * 127	
	+ MAIN
	
	//5 * 127	
	+ MAIN
	
	//6 * 127
	+ MAIN
	
	//7 * 127		
	+ MAIN
	
	//8 * 127		
	+ MAIN
		
	//9 * 127		
	+ MAIN
	
	//10 * 127	
	+ MAIN
	
	//11 * 127		
	+ MAIN
	
	//12 * 127	
	+ MAIN
	
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0
	+ BP0 + BP0 + BP0 + BP0 + BP0 + BP0 + BP0;
	
	//tables to look up velocity history segment
	//substrings for deceleration information	
	static final String D0 = ""
	+ (char)0 + (char)0 + (char)0;
	
	static final String D1 = ""
	+ (char)1 + (char)1 + (char)1;
	
	static final String D2 = ""
	+ (char)2 + (char)2 + (char)2;
	
	static final String D3 = ""
	+ (char)3 + (char)3 + (char)3;
	
	static final String D4 = ""
	+ (char)4 + (char)4 + (char)4;
	
	static final String D4_ = ""
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4 
		+ D4 + D4 + D4 + D4 + D4 + D4 + D4;
	
	static final String VELOCITY_HISTORY_TABLE = ""	
		+ (char)0 + (char)0 + (char)5
		+ (char)0 + (char)6 + (char)0
		
		+ D0 + D0 + D0 + D0 + D0
		
		+ D1 + D1 + D1 + D1 + D1
		+ D1 + D1 + D1 + D1 + D1
		+ D1 + D1
		
		+ D2 + D2 + D2 + D2 + D2
		+ D2 + D2 + D2 + D2 + D2
		+ D2 + D2 + D2 + D2 + D2
		+ D2 + D2 + D2
		
		+ D3 + D3 + D3 + D3 + D3
		+ D3 + D3 + D3 + D3 + D3
		+ D3 + D3 + D3 + D3 + D3
		+ D3 + D3 + D3 + D3 + D3
		+ D3 + D3 + D3 + D3
		
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_
		+ D4_ + D4_ + D4_ + D4_ + D4_ + D4_ + D4_;
}