EpeeistDC/Code
Jump to navigation
Jump to search
/*
EpeeistDC v3.0 by Sheldor. 04/08/2025 748 bytes
multimode movement and basic dynamic clustering targeting
v3.0 -- rename, targeting, energy management, movement, radar
Épée is one of the three forms of modern sport fencing,
along with foil and sabre. https://en.wikipedia.org/wiki/Epee
Previously named FoilistMicro.
Credits:
Targeting: jk.mini.CunobelinDC, Falcon, pez.micro.Aristocles, voidious.mini.Komarious, kc.micro.Thorn, jk.micro.Connavar, nz.jdc.HedgehogGF, pez.mini.Pugilist, sheldor.micro.Epeeist
Movement : jk.micro.Cotillion, jk.micro.Toorkild, kc.micro.Thorn, nz.jdc.HedgehogGF, wiki.nano.RaikoNano
Also, a general thanks to all open source bot authors and contributors to the RoboWiki.
EpeeistDC 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.*;
import java.util.ArrayList;
import java.util.*;
public class EpeeistDC extends AdvancedRobot
{
//constants
static final int GUESS_FACTORS = 37;
static final int MIDDLE_FACTOR = (GUESS_FACTORS - 1) / 2;
static final double MAXIMUM_ESCAPE_ANGLE = 8.0 / 11;
static final double FACTOR_ANGLE = MAXIMUM_ESCAPE_ANGLE / MIDDLE_FACTOR;
// static final int RESULT = 0;
static final int SITUATION = 0;
static final int A_BEARING = 1;
static final int E_DIRECTION = 2;
static final int B_OFFSET = 3;
static final int E_DISTANCE = 4;
static final int WEIGHT = 5;
static final int W_DIST_TRAVELED = 6;
static double[][] waves = new double[100000][W_DIST_TRAVELED + 1];
static int lastLogged;
static int newest;
public static final char FW1 = 6;
public static final char FW2 = 12;
public static final char FW3 = 18;
public static final char RW1 = (char)-6;
public static final char RW2 = (char)-12;
public static final char VELOCITY_VALUE = 16;//192;//4096;
public static final int WALL_VALUE = 5;//32;
//global variables
static double direction = 1;
static double enemyBulletSpeed;
static double enemyDirection;
static double enemyEnergy;
static double hits;
static int movementMode;
static int ticksSinceHit;
static int ticksSinceVelocityChange;
static int previousEnemyVelocity;
static double enemyVelocity;
// static ArrayList<Wave> waves = new ArrayList();
public void run(){
newest = lastLogged;
//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 a while(true) loop in the run() method saves one byte.
//I believe Wompi discovered this.
setTurnRadarRightRadians(1);
}
public void onScannedRobot(ScannedRobotEvent e)
{
//local variables
int i;
double absoluteBearing;
double enemyDistance;
double offset;
double localEnemyDirection;
double theta;
int integer;
double[] wave;
//energy management based on distance, energy, and enemy energy
//retreat very heavily when the enemy is ramming
if (setFireBullet(Math.min(enemyEnergy / 4,
(offset =
(2 + (integer = ((i = 112) / (int)((wave = waves[++newest])[E_DISTANCE] = enemyDistance = e.getDistance())))))
- BULLET_POWER_TABLE.charAt((int)getEnergy())))
!= null){
/* if (setFireBullet((offset = (2 + (integer = ((i = 112) / (int)((wave = waves[newest++])[E_DISTANCE] = enemyDistance = e.getDistance())) << 5)
)) - (BULLET_POWER_TABLE
.charAt((((int)getEnergy() >> 3) * 127) + (int)e.getEnergy()) / 100.01)
) != null){*/
wave[WEIGHT] = 12;
}
/*********************************************
*---------------MOVEMENT CODE---------------*
*********************************************/
//wall smoothing based on HedgehogGF's
while(fieldContains(theta = (wave[A_BEARING] = absoluteBearing =
(e.getBearingRadians() + getHeadingRadians())) + direction * (offset -= 0.02), 160) > 0);
setTurnRightRadians(Math.tan(theta -= getHeadingRadians()));
//stop and go movement
//move when the enemy fires, or when the robot is moving randomly, or when the enemy is very close
double energyDrop;
if ((energyDrop = (enemyEnergy - (enemyEnergy = e.getEnergy()))) > movementMode - integer)
{
//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
//reverse direction if the bot gets too close to a wall
if (Math.random() + integer < (-0.6 * Math.sqrt(enemyBulletSpeed / enemyDistance) + 0.04)
* movementMode || offset < Math.PI/3.5)
{
direction = -direction;
}
/********************************************
*--------------TARGETING CODE--------------*
********************************************/
int temp;
double latVel;
double enemyHeading;
//calculate deceleration and whether or not to reset ticks since velocity change
if ((temp = Integer.signum((int)(enemyVelocity - (enemyVelocity = e.getVelocity())))) != 0)
{
ticksSinceVelocityChange = temp;
}
//determine enemy wall proximity
//inspired by Pugilist and HedgehogGF
do
{
integer += 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[E_DIRECTION] = localEnemyDirection = (enemyDirection = Math.signum(0.00000000000001 +
// ((enemyVelocity) * (Math.sin((enemyHeading = e.getHeadingRadians()) - absoluteBearing)))
(latVel = (enemyVelocity) * (Math.sin((enemyHeading = e.getHeadingRadians()) - absoluteBearing)))
+ (enemyDirection / 100))) * FACTOR_ANGLE)
* ((short)WALL_TABLE.charAt(i))), enemyDistance);
}
while(--i > 0);
//determine current situation
double localSituation = wave[SITUATION] =
(integer << 5) +
VELOCITY_HISTORY_TABLE.charAt(ticksSinceVelocityChange += 3) +
//((int)enemyDistance >> 8) +
//((int)Math.abs(enemyVelocity) / 3) +
// ((int)Math.round(Math.abs(latVel) / 2)) +
(Math.abs(latVel) );
// enemyDistance / 250;
// enemyDistance / 2000;
double[] scores = new double[GUESS_FACTORS + 1];
// int j = -MIDDLE_FACTOR;
int best = 0;//MIDDLE_FACTOR + 4;
//offset = 0;
// do{
i = newest;
double relativeHeading;
// double angleScore = 0;
try{
do
{
// if (Math.abs(j - (wave = waves.get(i++)).result) < 1)
wave = waves[--i];
if (i > lastLogged){
wave[B_OFFSET] += ((enemyVelocity * Math.sin(relativeHeading = (enemyHeading - wave[A_BEARING]))) / (wave[E_DISTANCE] += (enemyVelocity * Math.cos(relativeHeading))));
//check if the wave has passed the enemy's current location
if ((wave[W_DIST_TRAVELED] += 14) > wave[E_DISTANCE])
{
//wave[RESULT] = wave[B_OFFSET] / wave[E_DIRECTION];
lastLogged++;
//waves.add(this);
//waveDistanceTraveled = Double.NEGATIVE_INFINITY;
}
}
//calculate angle scores and select aim angle
else// if ((firstActive - i) < 5000)
// if (i < firstActive)
{
if ((scores[temp = ((int)Math.round(wave[B_OFFSET] / wave[E_DIRECTION]) + MIDDLE_FACTOR)]
+= ((wave[WEIGHT] + 1) * i) / (1 + Math.abs(wave[SITUATION] - localSituation))) >= scores[best]){
//best = angle;
setTurnGunRightRadians((Math.random() * 0.007)//(theta / localSituation)
+ Utils.normalRelativeAngle(absoluteBearing
- getGunHeadingRadians() + (//Math.signum(enemyEnergy) *
localEnemyDirection * ((best = temp) - MIDDLE_FACTOR))));
}
}
}while (true);
}catch (Exception ex){}
//radar
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 += (e.getPower() )) >= (getRoundNum() << 3) + 12)
// if ((hits += Math.sqrt(e.getPower() / ticksSinceHit)) >= (getRoundNum() + 1) )
{
movementMode = -1;
}
//ticksSinceHit = 0;
}
//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 for wall tests
static final String WALL_TABLE = ""
+ (char)MIDDLE_FACTOR
+ FW1 + FW1 + FW1 + FW1 + FW1
+ FW1 + FW1 + FW1 + FW1 + FW1
+ FW1 + FW1 + FW1 + FW1 + FW1
+ FW1 + FW1 + FW1 + FW1 + FW1
+ FW1 + FW1 + FW1 + FW1 + FW1
+ FW1 + FW1 + FW1 + FW1 + FW1
+ FW1 + FW1
+ FW2 + FW2 + FW2 + FW2 + FW2
+ FW2 + FW2 + FW2 + FW2 + FW2
+ FW2 + FW2 + FW2 + FW2 + FW2
+ FW2 + FW2 + FW2 + FW2 + FW2
+ FW2 + FW2 + FW2 + FW2 + FW2
+ FW2 + FW2 + FW2 + FW2 + FW2
+ FW2 + FW2
+ FW3 + FW3 + FW3 + FW3 + FW3
+ FW3 + FW3 + FW3 + FW3 + FW3
+ FW3 + FW3 + FW3 + FW3 + FW3
+ FW3 + FW3 + FW3 + FW3 + FW3
+ FW3 + FW3 + FW3 + FW3 + FW3
+ FW3 + FW3 + FW3 + FW3 + FW3
+ FW3 + FW3
+ RW1 + RW1 + RW1 + RW1
+ RW1 + RW1 + RW1 + RW1
+ RW2 + RW2 + RW2 + RW2
+ RW2 + RW2 + RW2 + RW2;
//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
+ (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 BULLET_POWER_TABLE = ""
+ (char)2 + (char)2 + (char)2 + (char)2
+ (char)2 + (char)2 + (char)2 + (char)2
+ (char)1 + (char)1 + (char)0 + (char)0
+ 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;
//velocity history tables
//substrings for deceleration information
static final String D0 = ""
+ (char)4*VELOCITY_VALUE + (char)4*VELOCITY_VALUE + (char)4*VELOCITY_VALUE;
static final String D1 = ""
+ (char)3*VELOCITY_VALUE + (char)3*VELOCITY_VALUE + (char)3*VELOCITY_VALUE;
static final String D2 = ""
+ (char)2*VELOCITY_VALUE + (char)2*VELOCITY_VALUE + (char)2*VELOCITY_VALUE;
static final String D3 = ""
+ (char)1*VELOCITY_VALUE + (char)1*VELOCITY_VALUE + (char)1*VELOCITY_VALUE;
static final String D4 = ""
+ (char)0*VELOCITY_VALUE + (char)0*VELOCITY_VALUE + (char)0*VELOCITY_VALUE;
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*VELOCITY_VALUE
+ (char)0 + (char)6*VELOCITY_VALUE + (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_;
}