|
|
(3 intermediate revisions by the same user not shown) |
Line 3: |
Line 3: |
| | parent = Basilisk | | | parent = Basilisk |
| | page1 = Version History | | | page1 = Version History |
| + | | page2 = Code |
| }} | | }} |
| | | |
Line 8: |
Line 9: |
| | author = [[User:Slugzilla]] | | | author = [[User:Slugzilla]] |
| | extends = [[AdvancedRobot]] | | | extends = [[AdvancedRobot]] |
− | | targeting = [[Guessfactor Targeting]] | + | | targeting = [[GuessFactor Targeting]] |
| | movement = [[Stop And Go]], [[Random Movement]] | | | movement = [[Stop And Go]], [[Random Movement]] |
| | current_version = 2.35 | | | current_version = 2.35 |
Line 28: |
Line 29: |
| '''How competitive is it?''' | | '''How competitive is it?''' |
| | | |
− | Currently #14 in the MiniRumble and #99 in the RoboRumble. | + | Currently #5 in the MiniRumble and #72 in the RoboRumble. |
| | | |
| == Strategy == | | == Strategy == |
Line 38: |
Line 39: |
| '''How does it fire?''' | | '''How does it fire?''' |
| | | |
− | Basilisk uses [[Guessfactor Targeting]]. It's based off of [[GFTargetingBot]], but has [[Energy Management]], [[Rolling Averages]], and [[Lateral Velocity]] segments, plus a change in velocity segment. | + | Basilisk uses [[GuessFactor Targeting]]. It's based off of [[GFTargetingBot]], but has [[Energy Management]], [[Rolling Averages]], and a lot of [[Segmentation]]. |
| | | |
| '''How does it dodge bullets?''' | | '''How does it dodge bullets?''' |
| | | |
− | Stop and go dodges [[HOT]] and [[Linear Targeting]], and the [[Random Movement]] dodges the rest =) | + | Stop and go dodges [[HOT]] and [[Linear Targeting]], an [[Random Movement]] dodges the rest =) |
| | | |
| '''How does the melee strategy differ from one-on-one strategy?''' | | '''How does the melee strategy differ from one-on-one strategy?''' |
Line 57: |
Line 58: |
| | | |
| Sure! See code below or decompile the .jar file. | | Sure! See code below or decompile the .jar file. |
| + | |
| '''What's next for your robot?''' | | '''What's next for your robot?''' |
| | | |
− | Top 10!!!
| + | A baby brother, maybe [[Basilite]]? |
| | | |
| '''Does it have any White Whales?''' | | '''Does it have any White Whales?''' |
Line 71: |
Line 73: |
| Basilisk is based off of many ideas and concepts from the RoboWiki. Specifically, I used code/drew inspiration from | | Basilisk is based off of many ideas and concepts from the RoboWiki. Specifically, I used code/drew inspiration from |
| | | |
− | [[RandomMovementBot]], [[GFTargetingBot]], [[Aristocles]], [[RaikoNano]], [[Tityus]], [[Raiko]], [[Cotillion]], [[BlackWidow]], [[HedgehogGF]], and [[EpeeistMicro]]. | + | [[RandomMovementBot]], [[GFTargetingBot]], [[Aristocles]], [[RaikoNano]], [[Tityus]], [[Raiko]], [[Cotillion]], [[BlackWidow]], [[HedgehogGF]], [[Vyper]], [[Thorn]], and [[EpeeistMicro]]. |
| | | |
| Special thanks to Dsekercioglu for help identifying bugs and beating bullet shielders =) | | Special thanks to Dsekercioglu for help identifying bugs and beating bullet shielders =) |
| | | |
− | == Code ==
| |
− |
| |
− | '''Version 2.35'''
| |
− |
| |
− | <syntaxhighlight>
| |
− | package slugzilla;
| |
− | import robocode.*;
| |
− | import java.awt.geom.*;
| |
− | import robocode.util.*;
| |
− | import java.awt.*;
| |
− | import static robocode.util.Utils.normalRelativeAngleDegrees;
| |
− | import robocode.BulletHitEvent;
| |
− | import robocode.HitByBulletEvent;
| |
− |
| |
− | public class Basilisk extends AdvancedRobot {
| |
− |
| |
− | private static double lateralDirection;
| |
− | private static double lastEnemyVelocity;
| |
− | static double enemyFirePower;
| |
− | static double enemyBulletVelocity;
| |
− | double enemyDistance;
| |
− | double enemyAbsoluteBearing;
| |
− | double enemyVelocity;
| |
− | static double direction = 1;
| |
− | static int movementMode;
| |
− | static double hits;
| |
− | private static double enemyEnergy;
| |
− | static double deltaT;
| |
− | static double lastDeltaT;
| |
− | static double lastReverseTime;
| |
− | static double firePower;
| |
− | public void run() {
| |
− | setAdjustRadarForGunTurn(true);
| |
− | setAdjustGunForRobotTurn(true);
| |
− | setBodyColor(new Color(40, 100, 100));
| |
− | setGunColor(new Color(34, 50, 50));
| |
− | setRadarColor(new Color(0, 255, 0));
| |
− | setScanColor(new Color(0, 255, 0));
| |
− | turnRadarRightRadians(Double.POSITIVE_INFINITY);
| |
− | do {
| |
− | scan();
| |
− | } while (true);
| |
− | }
| |
− |
| |
− | public void onScannedRobot(ScannedRobotEvent e) {
| |
− | //radar ↓
| |
− | double radarTurn = getHeadingRadians() + e.getBearingRadians() - getRadarHeadingRadians();
| |
− | setTurnRadarRightRadians(Utils.normalRelativeAngle(radarTurn));
| |
− | //movement ↓
| |
− |
| |
− | double v2;
| |
− | double offset;
| |
− | double theta = 0.5952*(20D - 3D*enemyFirePower)/enemyDistance;
| |
− |
| |
− | if (movementMode >= 1) {
| |
− | offset = 2 + 100/e.getDistance();
| |
− | } else {
| |
− | //offset = 1.5 + 100/e.getDistance();
| |
− | offset = 2 + (int)(100/e.getDistance());
| |
− | }
| |
− |
| |
− | enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians();
| |
− | double v1 = enemyAbsoluteBearing;
| |
− | enemyDistance = e.getDistance();
| |
− | enemyVelocity = e.getVelocity();
| |
− | enemyBulletVelocity = 20 - 3 * enemyFirePower;
| |
− |
| |
− | if (enemyEnergy > e.getEnergy() && enemyEnergy - 3 <= e.getEnergy()) {
| |
− | enemyFirePower = enemyEnergy - e.getEnergy();
| |
− | }
| |
− | while(!new Rectangle2D.Double(18, 18, 764, 564).
| |
− | contains(getX() + 160 * Math.sin(v2 = v1 + direction * (offset -= .02)), getY() + 160 * Math.cos(v2)));
| |
− |
| |
− | if (offset < 0.75) {
| |
− | direction = -direction;
| |
− | lastDeltaT = deltaT;
| |
− | lastReverseTime = getTime();
| |
− | }
| |
− | setTurnRightRadians(Math.tan(v2 -= getHeadingRadians()));
| |
− | deltaT = getTime() - lastReverseTime;
| |
− |
| |
− | if(movementMode >= 1) {
| |
− | setAhead(1000 * Math.cos(v2));
| |
− | if (Math.random() > Math.pow(theta, theta) && enemyDistance > 100) {
| |
− | if (deltaT >= lastDeltaT +2 || deltaT <= lastDeltaT -2) {
| |
− | direction = -direction;
| |
− | lastDeltaT = deltaT;
| |
− | lastReverseTime = getTime();
| |
− | }
| |
− | }
| |
− | } else {
| |
− | double energyDrop = enemyEnergy - e.getEnergy();
| |
− | if ((int)(100/enemyDistance) + energyDrop > 0) {
| |
− | setAhead(((3 + (int)(energyDrop * 1.999999)) << 3 ) * Math.signum(Math.cos(v2)));
| |
− | }
| |
− | }
| |
− | enemyEnergy = e.getEnergy();
| |
− | //gun ↓
| |
− | double enemyLateralVelocity = e.getVelocity() * Math.sin(e.getHeadingRadians() - enemyAbsoluteBearing);
| |
− | if (enemyVelocity != 0) {
| |
− | lateralDirection = GFTUtils.sign(enemyVelocity * Math.sin(e.getHeadingRadians() - enemyAbsoluteBearing));
| |
− | }
| |
− | GFTWave wave = new GFTWave(this);
| |
− |
| |
− | wave.bulletPower = Math.min(Math.min(e.getEnergy()/4, getEnergy()/8), Math.min(0.05 * Math.round((1.8+100/enemyDistance)/0.05), 3));
| |
− | firePower = wave.bulletPower;
| |
− | wave.MAX_ESCAPE_ANGLE = (Math.asin(8/(20 - 3 * wave.bulletPower)));
| |
− | wave.BIN_WIDTH = wave.MAX_ESCAPE_ANGLE / wave.MIDDLE_BIN;
| |
− | wave.gunLocation = new Point2D.Double(getX(), getY());
| |
− | GFTWave.targetLocation = GFTUtils.project(wave.gunLocation, enemyAbsoluteBearing, enemyDistance);
| |
− | wave.lateralDirection = lateralDirection;
| |
− | wave.setSegmentations(enemyDistance, enemyVelocity, lastEnemyVelocity, enemyLateralVelocity);
| |
− | lastEnemyVelocity = enemyVelocity;
| |
− | wave.bearing = enemyAbsoluteBearing;
| |
− |
| |
− | setTurnGunRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getGunHeadingRadians() + wave.mostVisitedBearingOffset()) + ((Math.random()/500)-0.002));
| |
− | if (getEnergy() > 0.4) {
| |
− | //fire at will! ↓
| |
− | setFire(wave.bulletPower);
| |
− | }
| |
− |
| |
− | if (getEnergy() >= wave.bulletPower) {
| |
− | addCustomEvent(wave);
| |
− | }
| |
− |
| |
− | }
| |
− | //movement ↓
| |
− | public void onHitByBullet(HitByBulletEvent e) {
| |
− | //enemyEnergy += 3 * enemyFirePower;
| |
− | enemyEnergy -= Rules.getBulletDamage(e.getBullet().getPower());
| |
− | if ((hits += (4.25 / enemyBulletVelocity)) > getRoundNum() + 1) {
| |
− | movementMode++;
| |
− | }
| |
− | }
| |
− | public void onBulletHit(BulletHitEvent e) {
| |
− | //enemyEnergy -= 4 * firePower + firePower > 1 ? 2 * firePower - 1 : 0;
| |
− | enemyEnergy -= Rules.getBulletDamage(e.getBullet().getPower());
| |
− | }
| |
− | }
| |
− | //gun ↓
| |
− | class GFTWave extends Condition {
| |
− | static Point2D targetLocation;
| |
− | double bulletPower;
| |
− | Point2D gunLocation;
| |
− | double bearing;
| |
− | double lateralDirection;
| |
− | // 1000 is the maximum space away in a 800 by 600 battlefield
| |
− | private static final double MAX_DISTANCE = 1000;
| |
− | //segment into 5 sections ↓
| |
− | private static final int DISTANCE_INDEXES = 5;
| |
− | private static final int VELOCITY_INDEXES = 5;
| |
− | private static final int ACCELERATION_INDEXES = 3;
| |
− | private static final int LATERAL_VELOCITY_INDEXES = 5;
| |
− |
| |
− | static final int BINS = 25;
| |
− | static final int MIDDLE_BIN = (BINS - 1) / 2;
| |
− | static double MAX_ESCAPE_ANGLE;
| |
− | static double BIN_WIDTH;
| |
− | private static double[][][][][][] statBuffers = new double[DISTANCE_INDEXES][VELOCITY_INDEXES][VELOCITY_INDEXES][ACCELERATION_INDEXES][LATERAL_VELOCITY_INDEXES][BINS];
| |
− |
| |
− | private double[] buffer;
| |
− | private AdvancedRobot robot;
| |
− | private double distanceTraveled;
| |
− |
| |
− | GFTWave(AdvancedRobot _robot) {
| |
− | this.robot = _robot;
| |
− | }
| |
− | public boolean test() {
| |
− | advance();
| |
− | //remove passed waves
| |
− | if (hasArrived()) {
| |
− | //buffer[currentBin()]++;
| |
− | // value = buffer[currentBin()]
| |
− | // newValue = .9*value +1
| |
− | // buffer[currentBin()] = newValue
| |
− |
| |
− | for (int i = 0; i < BINS; i++) {
| |
− | buffer[i] = 0.95 * buffer[i];
| |
− | }
| |
− | buffer[currentBin()] += 1;
| |
− | robot.removeCustomEvent(this);
| |
− | }
| |
− | return false;
| |
− | }
| |
− | double mostVisitedBearingOffset() {
| |
− | return (lateralDirection * BIN_WIDTH) * (mostVisitedBin() - MIDDLE_BIN);
| |
− | }
| |
− | void setSegmentations(double distance, double velocity, double lastVelocity, double lateralVelocity) {
| |
− | int distanceIndex = (int)(distance / (MAX_DISTANCE / DISTANCE_INDEXES));
| |
− | int velocityIndex = (int)Math.abs(velocity / 2);
| |
− | int lastVelocityIndex = (int)Math.abs(lastVelocity / 2);
| |
− | int deltaTime;
| |
− | if (velocityIndex < lastVelocityIndex) {
| |
− | deltaTime = 0;
| |
− | } else if (velocityIndex > lastVelocityIndex) {
| |
− | deltaTime = 1;
| |
− | } else {
| |
− | deltaTime = 2;
| |
− | }
| |
− | int accelerationIndex = deltaTime;
| |
− | int lateralVelocityIndex = (int)Math.abs(lateralVelocity / 2);
| |
− |
| |
− | buffer = statBuffers[distanceIndex][velocityIndex][lastVelocityIndex][accelerationIndex][lateralVelocityIndex];
| |
− | }
| |
− | private void advance() {
| |
− | distanceTraveled += GFTUtils.bulletVelocity(bulletPower);
| |
− | }
| |
− | private boolean hasArrived() {
| |
− | return distanceTraveled > gunLocation.distance(targetLocation) - 18;
| |
− | }
| |
− | private int currentBin() {
| |
− | int bin = (int)Math.round((
| |
− | (Utils.normalRelativeAngle(GFTUtils.absoluteBearing(gunLocation, targetLocation) - bearing))
| |
− | / (lateralDirection * BIN_WIDTH)
| |
− | ) + MIDDLE_BIN);
| |
− | return GFTUtils.minMax(bin, 0, BINS - 1);
| |
− | }
| |
− | private int mostVisitedBin() {
| |
− | int mostVisited = MIDDLE_BIN;
| |
− | for (int i = 0; i < BINS; i++) {
| |
− | if (buffer[i] > buffer[mostVisited]) {
| |
− | mostVisited = i;
| |
− | }
| |
− | }
| |
− | return mostVisited;
| |
− | }
| |
− | }
| |
− | //helpful utilities ↓
| |
− | class GFTUtils {
| |
− | static double bulletVelocity(double power) {
| |
− | return 20 - 3 * power;
| |
− | }
| |
− | static Point2D project(Point2D sourceLocation, double angle, double length) {
| |
− | return new Point2D.Double(sourceLocation.getX() + Math.sin(angle) * length,
| |
− | sourceLocation.getY() + Math.cos(angle) * length);
| |
− | }
| |
− | static double absoluteBearing(Point2D source, Point2D target) {
| |
− | return Math.atan2(target.getX() - source.getX(), target.getY() - source.getY());
| |
− | }
| |
− | static int sign(double v) {
| |
− | return v < 0 ? -1 : 1;
| |
− | }
| |
− | static int minMax(int v, int min, int max) {
| |
− | return Math.max(min, Math.min(max, v));
| |
− | }
| |
− | }
| |
− | </syntaxhighlight>
| |
| [[Category:MiniBots]] | | [[Category:MiniBots]] |
| [[Category:Bots]] | | [[Category:Bots]] |
| [[Category:1-vs-1 Bots]] | | [[Category:1-vs-1 Bots]] |
- Basilisk Sub-pages:
- Version History - Code
Background Information
What's special about it?
It's my first robot =)
How competitive is it?
Currently #5 in the MiniRumble and #72 in the RoboRumble.
Strategy
How does it move?
Basilisk starts out with Stop And Go, but if it gets hit often, it will switch over to Random Movement.
How does it fire?
Basilisk uses GuessFactor Targeting. It's based off of GFTargetingBot, but has Energy Management, Rolling Averages, and a lot of Segmentation.
How does it dodge bullets?
Stop and go dodges HOT and Linear Targeting, an Random Movement dodges the rest =)
How does the melee strategy differ from one-on-one strategy?
It doesn't have a melee strategy.
Additional Information
Where did you get the name?
I wanted a robot that was mean, lean, and green. Basilisks are green, and I think they're pretty mean, at least according to the legends =)
Can I use your code?
Sure! See code below or decompile the .jar file.
What's next for your robot?
A baby brother, maybe Basilite?
Does it have any White Whales?
Partial is it's arch-nemesis!!!
What other robot(s) is it based on?
Credits:
Basilisk is based off of many ideas and concepts from the RoboWiki. Specifically, I used code/drew inspiration from
RandomMovementBot, GFTargetingBot, Aristocles, RaikoNano, Tityus, Raiko, Cotillion, BlackWidow, HedgehogGF, Vyper, Thorn, and EpeeistMicro.
Special thanks to Dsekercioglu for help identifying bugs and beating bullet shielders =)