Difference between revisions of "Yatagan/Source"
< Yatagan
Jump to navigation
Jump to search
Skilgannon (talk | contribs) (1.0.1) |
|||
(57 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | == Version | + | == Development Version == |
− | + | Codesize: 249 | |
− | <syntaxhighlight> | + | <syntaxhighlight lang="Java"> |
− | |||
/* | /* | ||
− | Yatagan 1. | + | Yatagan 1.2.3 by Sheldor & Skilgannon; Release date: 2013/06/13 |
The yatagan is a short sabre which was used extensively in the Ottoman Empire. | The yatagan is a short sabre which was used extensively in the Ottoman Empire. | ||
+ | Codesize: 249 bytes without any colors | ||
Credits: | Credits: | ||
− | Pattern Matching code from simonton.WeekendObsession_S and mld.Moebius, heavily modified | + | Pattern Matching code from simonton.WeekendObsession_S and mld.Moebius, heavily modified. |
− | + | And a general thanks to all open source bot authors and contributors to the RoboWiki. | |
− | Yatagan is open source and released under the terms of the RoboWiki Public Code License (RWPCL) - Version 1.1 | + | Yatagan 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. | + | package jk.sheldor.nano; |
import robocode.*; | import robocode.*; | ||
import robocode.util.Utils; | import robocode.util.Utils; | ||
− | public class Yatagan extends AdvancedRobot | + | public class Yatagan extends AdvancedRobot{ |
− | { | + | |
− | //Global | + | public static final double DESIRED_BULLET_POWER = 2.0; |
+ | |||
+ | //round to nearest multiple of 0.33333... | ||
+ | public static final int BULLET_POWER = 2;//(int)(DESIRED_BULLET_POWER*3 + 0.5)/3.0; | ||
+ | public static final int BULLET_VELOCITY = (int)(20 - 3 * BULLET_POWER); | ||
+ | |||
+ | //Skilgannon: make this odd otherwise we can get errors in the beginning when a match of length 2 isn't found. | ||
+ | public static final int MAX_MATCH_LENGTH = 40; //Keep this under 128 to save a byte. | ||
+ | |||
+ | public static final int ORBIT_DISTANCE = 220; | ||
+ | //public static final double MOVE_AMOUNT = 1e+200; | ||
+ | public static final double DISTANCE_FACTOR = 3000; | ||
+ | |||
+ | public static final int ANTI_RAMBOT_DISTANCE = 127; //Keep this under 128 to save a byte. | ||
+ | |||
+ | //NB! Generate new RANDOM when changing ORBIT_DISTANCE! | ||
+ | /*public static void main(String[] args){ | ||
+ | System.out.println("RANDOM = " + (int)Math.round(3.0/(0.6*Math.sqrt((20 - 3*2.5)/ORBIT_DISTANCE) - 0.04))); | ||
+ | }//*/ | ||
+ | |||
+ | //public static final char ONE_WAY_ORBIT = 65535; | ||
+ | //public static final char REVERSE_ON_ENEMY_FIRE = 0; | ||
+ | //public static final char RANDOM = 29; //SHELDOR: This is no longer flat, but it works better against PM. | ||
+ | |||
+ | public static final char NO_FLIP = 65535; | ||
+ | public static final char FLIP = 0; | ||
+ | public static final char RANDOM_FLIP = 10; | ||
+ | |||
+ | //Global Variables | ||
static double direction; | static double direction; | ||
static double enemyEnergy; | static double enemyEnergy; | ||
− | static int deathCount; | + | static int deathCount; |
− | |||
public void run() | public void run() | ||
{ | { | ||
− | // | + | //Skilgannon: sacrifice this for anti-rambot code |
+ | //SHELDOR: Now we have enough room for both! | ||
+ | setAdjustRadarForGunTurn(true); | ||
− | + | //start spinning radar and initialize direction | |
setTurnRadarRightRadians(direction = Double.POSITIVE_INFINITY); | setTurnRadarRightRadians(direction = Double.POSITIVE_INFINITY); | ||
} | } | ||
Line 39: | Line 68: | ||
public void onScannedRobot(ScannedRobotEvent e) | public void onScannedRobot(ScannedRobotEvent e) | ||
{ | { | ||
− | + | //Local Variables | |
− | int integer = | + | int integer = MAX_MATCH_LENGTH; |
double absoluteBearing; | double absoluteBearing; | ||
− | |||
int matchPosition; | int matchPosition; | ||
− | //Oscillating/Random movement. | + | //SHELDOR: Debugging Tools |
− | if( (char) ((enemyEnergy | + | //System.out.println(enemyEnergy - e.getEnergy()); |
+ | //System.out.println(deathCount); | ||
+ | //System.out.println((deathCount + (100 + (int)(enemyEnergy - e.getEnergy())))); | ||
+ | //System.out.println((int)chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - e.getEnergy())))); | ||
+ | //System.out.println(((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (e.getEnergy())))) * Math.random()) - 1)); | ||
+ | |||
+ | //Orbiting/Oscillating/Random movement, all depending on the size of the number you multiply the random with | ||
+ | setAhead(direction *= ((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (enemyEnergy = e.getEnergy())))) * Math.random()) - 1)); | ||
+ | /*if( | ||
+ | (char) ( chancesOfReversing.charAt(deathCount)*Math.random() | ||
+ | + enemyEnergy - (enemyEnergy = e.getEnergy()) - (1.1 - 1e-8) ) <= 1) | ||
{ | { | ||
− | direction | + | //Reverse direction. |
+ | //Calling the onHitWall event to reverse direction saves two bytes. Credit to Simonton. | ||
+ | onHitWall(null); | ||
} | } | ||
− | setAhead(direction); | + | setAhead(direction);*/ |
+ | |||
+ | //record the current enemy lateral velocity | ||
+ | enemyHistory = String.valueOf((char) Math.round(e.getVelocity() * (Math.sin(e.getHeadingRadians() - (absoluteBearing = e.getBearingRadians() + getHeadingRadians()))))).concat(enemyHistory); | ||
− | + | //Pattern Matching | |
− | + | //find the longest match in the enemy history | |
+ | do{}while((matchPosition = enemyHistory.indexOf(enemyHistory.substring(0, (--integer)), 64)) < 0); | ||
− | + | //stay mostly perpendicular to the enemy, but try to maintain a distance of ORBIT_DISTANCE pixels | |
− | + | //If DISTANCE_FACTOR is smaller it tries harder to get to the desired distance, but may 'SpinBot' if it is too small. | |
+ | setTurnRightRadians(Math.cos(e.getBearingRadians() + | ||
+ | ((ORBIT_DISTANCE - (integer = (int)(e.getDistance()))) * (getVelocity() / DISTANCE_FACTOR/*direction / DISTANCE_FACTOR*/)) | ||
+ | )); | ||
− | + | //fire BULLET_POWER power bullets most of the time, but use higher power bullets when the distance is less than ANTI_RAMBOT_DISTANCE | |
− | + | //This greatly improves scores against rambots and other extremely aggressive bots. | |
+ | setFire(BULLET_POWER + (ANTI_RAMBOT_DISTANCE / integer)); | ||
− | + | //assume that the enemy will repeat their movements in the ticks following the recording of the original pattern | |
− | + | //generate a firing angle based on that assumption | |
− | |||
do { | do { | ||
− | absoluteBearing += ((short) enemyHistory.charAt(--matchPosition)) / | + | //go through the log of enemy movements right after the original pattern was recorded |
− | } while ((integer -= | + | //add the Angular Velocities directly to the absoluteBearing variable |
− | + | absoluteBearing += ((short) enemyHistory.charAt(--matchPosition)) / e.getDistance(); | |
− | + | } | |
− | + | while ((integer -= BULLET_VELOCITY) > 0); //keep projecting the enemy's movement forward until our bullet would reach their predicted location | |
− | + | //aim at the predicted target | |
− | + | setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians())); | |
− | + | //Pseudo-infinite Radar Lock | |
− | setTurnRadarLeftRadians( | + | setTurnRadarLeftRadians(getRadarTurnRemaining()); |
} | } | ||
public void onDeath(DeathEvent e) | public void onDeath(DeathEvent e) | ||
{ | { | ||
− | deathCount++; | + | //when the bot dies, move to the next cell in the table |
+ | deathCount += 127; | ||
+ | //deathCount++; | ||
} | } | ||
public void onHitWall(HitWallEvent e) | public void onHitWall(HitWallEvent e) | ||
{ | { | ||
− | + | //reverse movement direction when the bot hits a wall | |
direction = -direction; | direction = -direction; | ||
} | } | ||
− | + | ||
− | + | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
//Preloaded log of enemy movements for pattern matcher so it doesn't need error checking | //Preloaded log of enemy movements for pattern matcher so it doesn't need error checking | ||
+ | //Skilgannon - this didn't need to be quite as long as it was, only max bullet flight time + one of each possible character | ||
+ | //unless we want to try pre-loading some common movement patterns? | ||
static String enemyHistory = "" | static String enemyHistory = "" | ||
− | + (char) | + | + (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) | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 |
− | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 1 | |
− | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 | |
− | + (char) | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 |
− | + | + (char) 1 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 | |
− | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 | |
− | + (char) | + | + (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) | + | + (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) | + | + (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) 1 + (char) 0 + (char) 0 + (char) 0 | |
− | + (char) | + | + (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) | + | + (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) 1 + (char) 0 + (char) 0 | |
− | + (char) | + | + (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) | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 |
− | + | + (char)-1 + (char)-2 + (char)-3 + (char)-4 + (char)-5 + (char)-6 | |
− | + | + (char)-7 + (char)-8 + (char) 8 + (char) 7 + (char) 6 + (char) 5 | |
− | + (char) | + | + (char) 4 + (char) 3 + (char) 2 + (char) 1 + (char) 0 + (char) 0 |
− | + | ; | |
− | + | ||
− | + (char) | + | |
− | + | ||
− | + | public static final String ONE_WAY_ORBIT = "" + | |
− | + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + (char) 1 + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP; | |
− | + | ||
− | + | //SHELDOR: Because this will be part of a larger string, we should start from 1 instead of 0. | |
− | + | public static final String REVERSE_ON_ENEMY_FIRE = "" + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | FLIP + FLIP + FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP; | |
− | + | ||
− | + | public static final String RANDOM = "" + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + |
− | + | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + |
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP; | ||
+ | |||
+ | //The chance that Yatagan will reverse direction when the enemy fires. | ||
+ | //values are referenced by number of deaths experienced | ||
+ | //when chancesOfReversing is 0, reverse on enemy fire only | ||
+ | //when chancesOfReversing is very large, almost never reverse (unless Math.random() is very small) | ||
+ | //when chancesOfReversing is > 3, reverse with probability 3/chancesOfReversing | ||
+ | private static final String chancesOfReversing = "" | ||
+ | + NO_FLIP | ||
+ | + ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT //SHELDOR: Let's try oscillating movement first. | ||
+ | + REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | ; | ||
} | } | ||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == Version 1. | + | == Latest Released Version (1.2.3) == |
<syntaxhighlight> | <syntaxhighlight> | ||
/* | /* | ||
− | Yatagan 1. | + | Yatagan 1.2.3 by Sheldor & Skilgannon; Release date: 2013/06/13 |
The yatagan is a short sabre which was used extensively in the Ottoman Empire. | The yatagan is a short sabre which was used extensively in the Ottoman Empire. | ||
+ | Codesize: 249 bytes without any colors | ||
Credits: | Credits: | ||
− | Pattern Matching code from simonton.WeekendObsession_S and mld.Moebius, heavily modified | + | Pattern Matching code from simonton.WeekendObsession_S and mld.Moebius, heavily modified. |
− | + | And a general thanks to all open source bot authors and contributors to the RoboWiki. | |
− | Yatagan is open source and released under the terms of the RoboWiki Public Code License (RWPCL) - Version 1.1 | + | Yatagan 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. | + | package jk.sheldor.nano; |
import robocode.*; | import robocode.*; | ||
import robocode.util.Utils; | import robocode.util.Utils; | ||
− | public class Yatagan extends AdvancedRobot | + | public class Yatagan extends AdvancedRobot{ |
− | { | + | |
− | //Global | + | public static final double DESIRED_BULLET_POWER = 2.0; |
+ | |||
+ | //round to nearest multiple of 0.33333... | ||
+ | public static final int BULLET_POWER = 2;//(int)(DESIRED_BULLET_POWER*3 + 0.5)/3.0; | ||
+ | public static final int BULLET_VELOCITY = (int)(20 - 3 * BULLET_POWER); | ||
+ | |||
+ | //Skilgannon: make this odd otherwise we can get errors in the beginning when a match of length 2 isn't found. | ||
+ | public static final int MAX_MATCH_LENGTH = 40; //Keep this under 128 to save a byte. | ||
+ | |||
+ | public static final int ORBIT_DISTANCE = 220; | ||
+ | //public static final double MOVE_AMOUNT = 1e+200; | ||
+ | public static final double DISTANCE_FACTOR = 3000; | ||
+ | |||
+ | public static final int ANTI_RAMBOT_DISTANCE = 127; //Keep this under 128 to save a byte. | ||
+ | |||
+ | //NB! Generate new RANDOM when changing ORBIT_DISTANCE! | ||
+ | /*public static void main(String[] args){ | ||
+ | System.out.println("RANDOM = " + (int)Math.round(3.0/(0.6*Math.sqrt((20 - 3*2.5)/ORBIT_DISTANCE) - 0.04))); | ||
+ | }//*/ | ||
+ | |||
+ | //public static final char ONE_WAY_ORBIT = 65535; | ||
+ | //public static final char REVERSE_ON_ENEMY_FIRE = 0; | ||
+ | //public static final char RANDOM = 29; //SHELDOR: This is no longer flat, but it works better against PM. | ||
+ | |||
+ | public static final char NO_FLIP = 65535; | ||
+ | public static final char FLIP = 0; | ||
+ | public static final char RANDOM_FLIP = 10; | ||
+ | |||
+ | //Global Variables | ||
static double direction; | static double direction; | ||
static double enemyEnergy; | static double enemyEnergy; | ||
− | static int deathCount; | + | static int deathCount; |
− | |||
public void run() | public void run() | ||
{ | { | ||
− | // | + | //Skilgannon: sacrifice this for anti-rambot code |
− | + | //SHELDOR: Now we have enough room for both! | |
− | + | setAdjustRadarForGunTurn(true); | |
+ | |||
+ | //start spinning radar and initialize direction | ||
setTurnRadarRightRadians(direction = Double.POSITIVE_INFINITY); | setTurnRadarRightRadians(direction = Double.POSITIVE_INFINITY); | ||
} | } | ||
Line 285: | Line 361: | ||
public void onScannedRobot(ScannedRobotEvent e) | public void onScannedRobot(ScannedRobotEvent e) | ||
{ | { | ||
− | + | //Local Variables | |
− | int integer = | + | int integer = MAX_MATCH_LENGTH; |
double absoluteBearing; | double absoluteBearing; | ||
− | |||
int matchPosition; | int matchPosition; | ||
− | + | ||
− | //Oscillating/Random movement. | + | //SHELDOR: Debugging Tools |
− | if( (char) ((enemyEnergy | + | //System.out.println(enemyEnergy - e.getEnergy()); |
+ | //System.out.println(deathCount); | ||
+ | //System.out.println((deathCount + (100 + (int)(enemyEnergy - e.getEnergy())))); | ||
+ | //System.out.println((int)chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - e.getEnergy())))); | ||
+ | //System.out.println(((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (e.getEnergy())))) * Math.random()) - 1)); | ||
+ | |||
+ | //Orbiting/Oscillating/Random movement, all depending on the size of the number you multiply the random with | ||
+ | setAhead(direction *= ((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (enemyEnergy = e.getEnergy())))) * Math.random()) - 1)); | ||
+ | /*if( | ||
+ | (char) ( chancesOfReversing.charAt(deathCount)*Math.random() | ||
+ | + enemyEnergy - (enemyEnergy = e.getEnergy()) - (1.1 - 1e-8) ) <= 1) | ||
{ | { | ||
− | direction | + | //Reverse direction. |
+ | //Calling the onHitWall event to reverse direction saves two bytes. Credit to Simonton. | ||
+ | onHitWall(null); | ||
} | } | ||
− | setAhead(direction); | + | setAhead(direction);*/ |
− | + | ||
− | + | //record the current enemy lateral velocity | |
− | + | enemyHistory = String.valueOf((char) (e.getVelocity() * (Math.sin(e.getHeadingRadians() - (absoluteBearing = e.getBearingRadians() + getHeadingRadians()))))).concat(enemyHistory); | |
− | + | ||
− | + | //Pattern Matching | |
− | enemyHistory = String.valueOf((char) (e.getVelocity() * (Math.sin(e.getHeadingRadians() - (absoluteBearing + | + | //find the longest match in the enemy history |
− | + | while((matchPosition = enemyHistory.indexOf(enemyHistory.substring(0, (--integer)), 64)) < 0); | |
− | + | ||
− | while((matchPosition = enemyHistory.indexOf(enemyHistory.substring(0, | + | //stay mostly perpendicular to the enemy, but try to maintain a distance of ORBIT_DISTANCE pixels |
− | + | //If DISTANCE_FACTOR is smaller it tries harder to get to the desired distance, but may 'SpinBot' if it is too small. | |
− | integer = (int)(distance); | + | setTurnRightRadians(Math.cos(e.getBearingRadians() + |
− | + | ((ORBIT_DISTANCE - (integer = (int)(e.getDistance()))) * (getVelocity() / DISTANCE_FACTOR/*direction / DISTANCE_FACTOR*/)) | |
− | + | )); | |
+ | |||
+ | //fire BULLET_POWER power bullets most of the time, but use higher power bullets when the distance is less than ANTI_RAMBOT_DISTANCE | ||
+ | //This greatly improves scores against rambots and other extremely aggressive bots. | ||
+ | setFire(BULLET_POWER + (ANTI_RAMBOT_DISTANCE / integer)); | ||
+ | |||
+ | //assume that the enemy will repeat their movements in the ticks following the recording of the original pattern | ||
+ | //generate a firing angle based on that assumption | ||
do { | do { | ||
− | absoluteBearing += ((short) enemyHistory.charAt(--matchPosition)) / | + | //go through the log of enemy movements right after the original pattern was recorded |
− | } while ((integer -= | + | //add the Angular Velocities directly to the absoluteBearing variable |
− | + | absoluteBearing += ((short) enemyHistory.charAt(--matchPosition)) / e.getDistance(); | |
− | + | } | |
− | setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians())); | + | while ((integer -= BULLET_VELOCITY) > 0); //keep projecting the enemy's movement forward until our bullet would reach their predicted location |
− | + | ||
− | + | //aim at the predicted target | |
− | + | setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians())); | |
− | + | ||
− | + | //Pseudo-infinite Radar Lock | |
− | setTurnRadarLeftRadians( | + | setTurnRadarLeftRadians(getRadarTurnRemaining()); |
} | } | ||
public void onDeath(DeathEvent e) | public void onDeath(DeathEvent e) | ||
{ | { | ||
− | deathCount++; | + | //when the bot dies, move to the next cell in the table |
+ | deathCount += 127; | ||
+ | //deathCount++; | ||
} | } | ||
public void onHitWall(HitWallEvent e) | public void onHitWall(HitWallEvent e) | ||
{ | { | ||
− | + | //reverse movement direction when the bot hits a wall | |
direction = -direction; | direction = -direction; | ||
} | } | ||
− | + | ||
− | + | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
//Preloaded log of enemy movements for pattern matcher so it doesn't need error checking | //Preloaded log of enemy movements for pattern matcher so it doesn't need error checking | ||
+ | //Skilgannon - this didn't need to be quite as long as it was, only max bullet flight time + one of each possible character | ||
+ | //unless we want to try pre-loading some common movement patterns? | ||
static String enemyHistory = "" | static String enemyHistory = "" | ||
− | + (char) | + | + (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) | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 |
− | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 1 | |
− | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 | |
− | + (char) | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 |
− | + | + (char) 1 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 | |
− | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 | |
− | + (char) | + | + (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) | + | + (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) | + | + (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) 1 + (char) 0 + (char) 0 + (char) 0 | |
− | + (char) | + | + (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) | + | + (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) 1 + (char) 0 + (char) 0 | |
− | + (char) | + | + (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) | + | + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 + (char) 0 |
− | + | + (char)-1 + (char)-2 + (char)-3 + (char)-4 + (char)-5 + (char)-6 | |
− | + | + (char)-7 + (char)-8 + (char) 8 + (char) 7 + (char) 6 + (char) 5 | |
− | + (char) | + | + (char) 4 + (char) 3 + (char) 2 + (char) 1 + (char) 0 + (char) 0 |
− | + | ; | |
− | + | ||
− | + (char) | + | |
− | + | ||
− | + | public static final String ONE_WAY_ORBIT = "" + | |
− | + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + (char) 1 + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + (char) | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP; | |
− | + | ||
− | + | //SHELDOR: Because this will be part of a larger string, we should start from 1 instead of 0. | |
− | + | public static final String REVERSE_ON_ENEMY_FIRE = "" + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | FLIP + FLIP + FLIP + NO_FLIP + NO_FLIP + | |
− | + | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + | |
− | + | NO_FLIP + NO_FLIP; | |
− | + | ||
− | + | public static final String RANDOM = "" + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | |
− | + | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + |
− | + | + | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + |
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + | ||
+ | RANDOM_FLIP + RANDOM_FLIP; | ||
+ | |||
+ | //The chance that Yatagan will reverse direction when the enemy fires. | ||
+ | //values are referenced by number of deaths experienced | ||
+ | //when chancesOfReversing is 0, reverse on enemy fire only | ||
+ | //when chancesOfReversing is very large, almost never reverse (unless Math.random() is very small) | ||
+ | //when chancesOfReversing is > 3, reverse with probability 3/chancesOfReversing | ||
+ | private static final String chancesOfReversing = "" | ||
+ | + NO_FLIP | ||
+ | + ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT //SHELDOR: Let's try oscillating movement first. | ||
+ | + REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM | ||
+ | ; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 23:18, 2 October 2024
Development Version
Codesize: 249
/*
Yatagan 1.2.3 by Sheldor & Skilgannon; Release date: 2013/06/13
The yatagan is a short sabre which was used extensively in the Ottoman Empire.
Codesize: 249 bytes without any colors
Credits:
Pattern Matching code from simonton.WeekendObsession_S and mld.Moebius, heavily modified.
And a general thanks to all open source bot authors and contributors to the RoboWiki.
Yatagan 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 jk.sheldor.nano;
import robocode.*;
import robocode.util.Utils;
public class Yatagan extends AdvancedRobot{
public static final double DESIRED_BULLET_POWER = 2.0;
//round to nearest multiple of 0.33333...
public static final int BULLET_POWER = 2;//(int)(DESIRED_BULLET_POWER*3 + 0.5)/3.0;
public static final int BULLET_VELOCITY = (int)(20 - 3 * BULLET_POWER);
//Skilgannon: make this odd otherwise we can get errors in the beginning when a match of length 2 isn't found.
public static final int MAX_MATCH_LENGTH = 40; //Keep this under 128 to save a byte.
public static final int ORBIT_DISTANCE = 220;
//public static final double MOVE_AMOUNT = 1e+200;
public static final double DISTANCE_FACTOR = 3000;
public static final int ANTI_RAMBOT_DISTANCE = 127; //Keep this under 128 to save a byte.
//NB! Generate new RANDOM when changing ORBIT_DISTANCE!
/*public static void main(String[] args){
System.out.println("RANDOM = " + (int)Math.round(3.0/(0.6*Math.sqrt((20 - 3*2.5)/ORBIT_DISTANCE) - 0.04)));
}//*/
//public static final char ONE_WAY_ORBIT = 65535;
//public static final char REVERSE_ON_ENEMY_FIRE = 0;
//public static final char RANDOM = 29; //SHELDOR: This is no longer flat, but it works better against PM.
public static final char NO_FLIP = 65535;
public static final char FLIP = 0;
public static final char RANDOM_FLIP = 10;
//Global Variables
static double direction;
static double enemyEnergy;
static int deathCount;
public void run()
{
//Skilgannon: sacrifice this for anti-rambot code
//SHELDOR: Now we have enough room for both!
setAdjustRadarForGunTurn(true);
//start spinning radar and initialize direction
setTurnRadarRightRadians(direction = Double.POSITIVE_INFINITY);
}
public void onScannedRobot(ScannedRobotEvent e)
{
//Local Variables
int integer = MAX_MATCH_LENGTH;
double absoluteBearing;
int matchPosition;
//SHELDOR: Debugging Tools
//System.out.println(enemyEnergy - e.getEnergy());
//System.out.println(deathCount);
//System.out.println((deathCount + (100 + (int)(enemyEnergy - e.getEnergy()))));
//System.out.println((int)chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - e.getEnergy()))));
//System.out.println(((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (e.getEnergy())))) * Math.random()) - 1));
//Orbiting/Oscillating/Random movement, all depending on the size of the number you multiply the random with
setAhead(direction *= ((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (enemyEnergy = e.getEnergy())))) * Math.random()) - 1));
/*if(
(char) ( chancesOfReversing.charAt(deathCount)*Math.random()
+ enemyEnergy - (enemyEnergy = e.getEnergy()) - (1.1 - 1e-8) ) <= 1)
{
//Reverse direction.
//Calling the onHitWall event to reverse direction saves two bytes. Credit to Simonton.
onHitWall(null);
}
setAhead(direction);*/
//record the current enemy lateral velocity
enemyHistory = String.valueOf((char) Math.round(e.getVelocity() * (Math.sin(e.getHeadingRadians() - (absoluteBearing = e.getBearingRadians() + getHeadingRadians()))))).concat(enemyHistory);
//Pattern Matching
//find the longest match in the enemy history
do{}while((matchPosition = enemyHistory.indexOf(enemyHistory.substring(0, (--integer)), 64)) < 0);
//stay mostly perpendicular to the enemy, but try to maintain a distance of ORBIT_DISTANCE pixels
//If DISTANCE_FACTOR is smaller it tries harder to get to the desired distance, but may 'SpinBot' if it is too small.
setTurnRightRadians(Math.cos(e.getBearingRadians() +
((ORBIT_DISTANCE - (integer = (int)(e.getDistance()))) * (getVelocity() / DISTANCE_FACTOR/*direction / DISTANCE_FACTOR*/))
));
//fire BULLET_POWER power bullets most of the time, but use higher power bullets when the distance is less than ANTI_RAMBOT_DISTANCE
//This greatly improves scores against rambots and other extremely aggressive bots.
setFire(BULLET_POWER + (ANTI_RAMBOT_DISTANCE / integer));
//assume that the enemy will repeat their movements in the ticks following the recording of the original pattern
//generate a firing angle based on that assumption
do {
//go through the log of enemy movements right after the original pattern was recorded
//add the Angular Velocities directly to the absoluteBearing variable
absoluteBearing += ((short) enemyHistory.charAt(--matchPosition)) / e.getDistance();
}
while ((integer -= BULLET_VELOCITY) > 0); //keep projecting the enemy's movement forward until our bullet would reach their predicted location
//aim at the predicted target
setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians()));
//Pseudo-infinite Radar Lock
setTurnRadarLeftRadians(getRadarTurnRemaining());
}
public void onDeath(DeathEvent e)
{
//when the bot dies, move to the next cell in the table
deathCount += 127;
//deathCount++;
}
public void onHitWall(HitWallEvent e)
{
//reverse movement direction when the bot hits a wall
direction = -direction;
}
//Preloaded log of enemy movements for pattern matcher so it doesn't need error checking
//Skilgannon - this didn't need to be quite as long as it was, only max bullet flight time + one of each possible character
//unless we want to try pre-loading some common movement patterns?
static String enemyHistory = ""
+ (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) 1
+ (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) 1 + (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 + (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) 1 + (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 + (char) 0
+ (char) 0 + (char) 0 + (char) 0 + (char) 1 + (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)-1 + (char)-2 + (char)-3 + (char)-4 + (char)-5 + (char)-6
+ (char)-7 + (char)-8 + (char) 8 + (char) 7 + (char) 6 + (char) 5
+ (char) 4 + (char) 3 + (char) 2 + (char) 1 + (char) 0 + (char) 0
;
public static final String ONE_WAY_ORBIT = "" +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP;
//SHELDOR: Because this will be part of a larger string, we should start from 1 instead of 0.
public static final String REVERSE_ON_ENEMY_FIRE = "" +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
FLIP + FLIP + FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP;
public static final String RANDOM = "" +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP;
//The chance that Yatagan will reverse direction when the enemy fires.
//values are referenced by number of deaths experienced
//when chancesOfReversing is 0, reverse on enemy fire only
//when chancesOfReversing is very large, almost never reverse (unless Math.random() is very small)
//when chancesOfReversing is > 3, reverse with probability 3/chancesOfReversing
private static final String chancesOfReversing = ""
+ NO_FLIP
+ ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT //SHELDOR: Let's try oscillating movement first.
+ REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
;
}
Latest Released Version (1.2.3)
/*
Yatagan 1.2.3 by Sheldor & Skilgannon; Release date: 2013/06/13
The yatagan is a short sabre which was used extensively in the Ottoman Empire.
Codesize: 249 bytes without any colors
Credits:
Pattern Matching code from simonton.WeekendObsession_S and mld.Moebius, heavily modified.
And a general thanks to all open source bot authors and contributors to the RoboWiki.
Yatagan 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 jk.sheldor.nano;
import robocode.*;
import robocode.util.Utils;
public class Yatagan extends AdvancedRobot{
public static final double DESIRED_BULLET_POWER = 2.0;
//round to nearest multiple of 0.33333...
public static final int BULLET_POWER = 2;//(int)(DESIRED_BULLET_POWER*3 + 0.5)/3.0;
public static final int BULLET_VELOCITY = (int)(20 - 3 * BULLET_POWER);
//Skilgannon: make this odd otherwise we can get errors in the beginning when a match of length 2 isn't found.
public static final int MAX_MATCH_LENGTH = 40; //Keep this under 128 to save a byte.
public static final int ORBIT_DISTANCE = 220;
//public static final double MOVE_AMOUNT = 1e+200;
public static final double DISTANCE_FACTOR = 3000;
public static final int ANTI_RAMBOT_DISTANCE = 127; //Keep this under 128 to save a byte.
//NB! Generate new RANDOM when changing ORBIT_DISTANCE!
/*public static void main(String[] args){
System.out.println("RANDOM = " + (int)Math.round(3.0/(0.6*Math.sqrt((20 - 3*2.5)/ORBIT_DISTANCE) - 0.04)));
}//*/
//public static final char ONE_WAY_ORBIT = 65535;
//public static final char REVERSE_ON_ENEMY_FIRE = 0;
//public static final char RANDOM = 29; //SHELDOR: This is no longer flat, but it works better against PM.
public static final char NO_FLIP = 65535;
public static final char FLIP = 0;
public static final char RANDOM_FLIP = 10;
//Global Variables
static double direction;
static double enemyEnergy;
static int deathCount;
public void run()
{
//Skilgannon: sacrifice this for anti-rambot code
//SHELDOR: Now we have enough room for both!
setAdjustRadarForGunTurn(true);
//start spinning radar and initialize direction
setTurnRadarRightRadians(direction = Double.POSITIVE_INFINITY);
}
public void onScannedRobot(ScannedRobotEvent e)
{
//Local Variables
int integer = MAX_MATCH_LENGTH;
double absoluteBearing;
int matchPosition;
//SHELDOR: Debugging Tools
//System.out.println(enemyEnergy - e.getEnergy());
//System.out.println(deathCount);
//System.out.println((deathCount + (100 + (int)(enemyEnergy - e.getEnergy()))));
//System.out.println((int)chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - e.getEnergy()))));
//System.out.println(((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (e.getEnergy())))) * Math.random()) - 1));
//Orbiting/Oscillating/Random movement, all depending on the size of the number you multiply the random with
setAhead(direction *= ((chancesOfReversing.charAt(deathCount + (100 + (int)(enemyEnergy - (enemyEnergy = e.getEnergy())))) * Math.random()) - 1));
/*if(
(char) ( chancesOfReversing.charAt(deathCount)*Math.random()
+ enemyEnergy - (enemyEnergy = e.getEnergy()) - (1.1 - 1e-8) ) <= 1)
{
//Reverse direction.
//Calling the onHitWall event to reverse direction saves two bytes. Credit to Simonton.
onHitWall(null);
}
setAhead(direction);*/
//record the current enemy lateral velocity
enemyHistory = String.valueOf((char) (e.getVelocity() * (Math.sin(e.getHeadingRadians() - (absoluteBearing = e.getBearingRadians() + getHeadingRadians()))))).concat(enemyHistory);
//Pattern Matching
//find the longest match in the enemy history
while((matchPosition = enemyHistory.indexOf(enemyHistory.substring(0, (--integer)), 64)) < 0);
//stay mostly perpendicular to the enemy, but try to maintain a distance of ORBIT_DISTANCE pixels
//If DISTANCE_FACTOR is smaller it tries harder to get to the desired distance, but may 'SpinBot' if it is too small.
setTurnRightRadians(Math.cos(e.getBearingRadians() +
((ORBIT_DISTANCE - (integer = (int)(e.getDistance()))) * (getVelocity() / DISTANCE_FACTOR/*direction / DISTANCE_FACTOR*/))
));
//fire BULLET_POWER power bullets most of the time, but use higher power bullets when the distance is less than ANTI_RAMBOT_DISTANCE
//This greatly improves scores against rambots and other extremely aggressive bots.
setFire(BULLET_POWER + (ANTI_RAMBOT_DISTANCE / integer));
//assume that the enemy will repeat their movements in the ticks following the recording of the original pattern
//generate a firing angle based on that assumption
do {
//go through the log of enemy movements right after the original pattern was recorded
//add the Angular Velocities directly to the absoluteBearing variable
absoluteBearing += ((short) enemyHistory.charAt(--matchPosition)) / e.getDistance();
}
while ((integer -= BULLET_VELOCITY) > 0); //keep projecting the enemy's movement forward until our bullet would reach their predicted location
//aim at the predicted target
setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians()));
//Pseudo-infinite Radar Lock
setTurnRadarLeftRadians(getRadarTurnRemaining());
}
public void onDeath(DeathEvent e)
{
//when the bot dies, move to the next cell in the table
deathCount += 127;
//deathCount++;
}
public void onHitWall(HitWallEvent e)
{
//reverse movement direction when the bot hits a wall
direction = -direction;
}
//Preloaded log of enemy movements for pattern matcher so it doesn't need error checking
//Skilgannon - this didn't need to be quite as long as it was, only max bullet flight time + one of each possible character
//unless we want to try pre-loading some common movement patterns?
static String enemyHistory = ""
+ (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) 1
+ (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) 1 + (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 + (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) 1 + (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 + (char) 0
+ (char) 0 + (char) 0 + (char) 0 + (char) 1 + (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)-1 + (char)-2 + (char)-3 + (char)-4 + (char)-5 + (char)-6
+ (char)-7 + (char)-8 + (char) 8 + (char) 7 + (char) 6 + (char) 5
+ (char) 4 + (char) 3 + (char) 2 + (char) 1 + (char) 0 + (char) 0
;
public static final String ONE_WAY_ORBIT = "" +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP;
//SHELDOR: Because this will be part of a larger string, we should start from 1 instead of 0.
public static final String REVERSE_ON_ENEMY_FIRE = "" +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
FLIP + FLIP + FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP + NO_FLIP +
NO_FLIP + NO_FLIP;
public static final String RANDOM = "" +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP + RANDOM_FLIP +
RANDOM_FLIP + RANDOM_FLIP;
//The chance that Yatagan will reverse direction when the enemy fires.
//values are referenced by number of deaths experienced
//when chancesOfReversing is 0, reverse on enemy fire only
//when chancesOfReversing is very large, almost never reverse (unless Math.random() is very small)
//when chancesOfReversing is > 3, reverse with probability 3/chancesOfReversing
private static final String chancesOfReversing = ""
+ NO_FLIP
+ ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT //SHELDOR: Let's try oscillating movement first.
+ REVERSE_ON_ENEMY_FIRE + ONE_WAY_ORBIT + REVERSE_ON_ENEMY_FIRE
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
+ RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM + RANDOM
;
}