Difference between revisions of "GFTargetingBot"

From Robowiki
Jump to navigation Jump to search
m (fixing a heading)
(Minor fixes)
 
(2 intermediate revisions by 2 users not shown)
Line 5: Line 5:
 
| movement        = [[RandomMovement|Random Movement]], Orbit movement
 
| movement        = [[RandomMovement|Random Movement]], Orbit movement
 
| current_version = 1.02
 
| current_version = 1.02
| license        = None
+
| license        = Public domain
| download_link  = http://www.robocoderepository.com/BotDetail.jsp?id=2913
 
 
| isOneOnOne      = true
 
| isOneOnOne      = true
 
| isMelee        = false
 
| isMelee        = false
Line 12: Line 11:
 
}}
 
}}
  
If you were looking for the discussion between Martin and Justin, it's on the [[Talk:GFTargetingBot|talk page]].
+
=== What's special about it? ===
 
+
It's a simple [[Statistical Targeting]] bot using [[GuessFactors]], if not literal so the general idea. My goal is that people who want to start out with Statistical Targeting can do so with this bot without having to figure it all out first. This bot is quite competitive out-of-the-box, but with just some little work it can be made to kick ass.
----
 
__NOTOC__ __NOEDITSECTION__
 
=== GFTargetingBot, by [[PEZ]] ===
 
 
 
==== What's special about it? ====
 
It's a simple StatisticalTargeting bot using GuessFactors, if not literal so the general idea. My goal is that people who want to start out with StatisticalTargeting can do so with this bot without having to figure it all out first. This bot is quite competetive out-of-the-box, but with just some little work it can be made to kick ass.
 
  
 
It features:
 
It features:
* [[Wave]]s, to collect the data
+
* [[Waves]], to collect the data.
* [[VisitCountStats]], accumulating data into simple int arrays
+
* [[Visit Count Stats]], accumulating data into simple int arrays.
* [[Segmentation]] (really simple, just to show how it can be done)
+
* [[Segmentation]] (really simple, just to show how it can be done).
 
It lacks:
 
It lacks:
* [[EnergyManagement]]
+
* [[Energy Management]]
* Advanced [[Segmentation]]
+
* Advanced [[segmentation]]
* Gun alignment nitty-gritty.
+
* Gun alignment nitty-gritty
* [[RollingAverage]]s
+
* Rolling averages
* [[DataSaving]]
+
* [[Saving|Data saving]]
* Anything advanced really.
+
* Anything advanced really
  
 
==== Great, I want to try it. Where can I download it? ====
 
==== Great, I want to try it. Where can I download it? ====
http://www.robocoderepository.com/BotDetail.jsp?id=2913
+
Compile it from the source below.
* Note: It would be good to update this bot on the repository with MAX_DISTANCE = 1000 or calculated based on battle field width and height. I've updated it in the code on this page. -- [[Voidious]]
+
 
 +
[Note: There used to be a download link, but the link is now broken. If someone still has a copy of <code>wiki.tutorial.GFTargetingBot_1.02.jar</code>, please upload it.]
  
 
==== How competitive is it? ====
 
==== How competitive is it? ====
Quite so for something this simple
+
Quite so for something this simple.
  
 
==== How does it [[Movement|move]]? ====
 
==== How does it [[Movement|move]]? ====
Random, fluid, orbit movement. Almost verbatim [[Aristocles]] movement. (Minus MusashiTrick)
+
Random, fluid, orbit movement. Almost verbatim [[Aristocles]] movement. (Minus [[Musashi Trick]]).
  
 
==== How does it fire? ====
 
==== How does it fire? ====
A GuessFactorTargeting gun segmented on distance, velocity, last-scan-velocity.  
+
A [[GuessFactor Targeting (traditional)|GuessFactor Targeting]] gun segmented on distance, velocity, last-scan-velocity.  
  
==== How does it [[DodgingBullets|dodge bullets]]? ====
+
==== How does it [[Dodging Bullets|dodge bullets]]? ====
It tries to create a flat MovementProfile.
+
It tries to create a flat Movement Profile.
  
 
==== How does the [[Melee|melee]] strategy differ from [[OneOnOne|one-on-one]]  strategy? ====
 
==== How does the [[Melee|melee]] strategy differ from [[OneOnOne|one-on-one]]  strategy? ====
Line 56: Line 50:
  
 
==== Where did you get the name? ====
 
==== Where did you get the name? ====
Duh... It's a GuessFactorTargeting tutorial bot.
+
Duh... It's a GuessFactor Targeting tutorial bot.
  
 
==== Can I use your code? ====
 
==== Can I use your code? ====
 
Sure. That's the whole idea. It's included in the jar. Use it as you see fit. Of course if I do not mind credits. And here's the code for version 1.0 (meaning it might not always be up to date.):
 
Sure. That's the whole idea. It's included in the jar. Use it as you see fit. Of course if I do not mind credits. And here's the code for version 1.0 (meaning it might not always be up to date.):
<pre>
+
<syntaxhighlight>
 
package wiki.tutorial;
 
package wiki.tutorial;
 
import robocode.*;
 
import robocode.*;
Line 251: Line 245:
 
}
 
}
 
}
 
}
</pre>
+
</syntaxhighlight>
  
 
==== What's next for your robot? ====
 
==== What's next for your robot? ====
* I must document the code to make this tutorial thing to really work. You're more than welcome to help in this.
+
I must document the code to make this tutorial thing to really work. You're more than welcome to help in this.
  
 
==== What other robot(s) is it based on? ====
 
==== What other robot(s) is it based on? ====
[[Aristocles]] - both gun and movement
+
[[Aristocles]] both gun and movement
 
 
  
[[Category:Source Code]] [[Category:Bots]]
+
[[Category:Source Code]]
 +
[[Category:Bots]]

Latest revision as of 17:34, 18 August 2017

GFTargetingBot
Author(s) PEZ
Extends AdvancedRobot
Targeting GuessFactor Targeting
Movement Random Movement, Orbit movement
Current Version 1.02
Code License Public domain

What's special about it?

It's a simple Statistical Targeting bot using GuessFactors, if not literal so the general idea. My goal is that people who want to start out with Statistical Targeting can do so with this bot without having to figure it all out first. This bot is quite competitive out-of-the-box, but with just some little work it can be made to kick ass.

It features:

It lacks:

Great, I want to try it. Where can I download it?

Compile it from the source below.

[Note: There used to be a download link, but the link is now broken. If someone still has a copy of wiki.tutorial.GFTargetingBot_1.02.jar, please upload it.]

How competitive is it?

Quite so for something this simple.

How does it move?

Random, fluid, orbit movement. Almost verbatim Aristocles movement. (Minus Musashi Trick).

How does it fire?

A GuessFactor Targeting gun segmented on distance, velocity, last-scan-velocity.

How does it dodge bullets?

It tries to create a flat Movement Profile.

How does the melee strategy differ from one-on-one strategy?

This bot doesn't know about Melee battles.

What does it save between rounds and matches?

The visit counts are saved between rounds. Nothing is saved between matches.

Where did you get the name?

Duh... It's a GuessFactor Targeting tutorial bot.

Can I use your code?

Sure. That's the whole idea. It's included in the jar. Use it as you see fit. Of course if I do not mind credits. And here's the code for version 1.0 (meaning it might not always be up to date.):

package wiki.tutorial;
import robocode.*;
import robocode.util.Utils;
import java.awt.Color;
import java.awt.geom.*;

// GFTargetingBot, by PEZ. A simple GuessFactorTargeting bot for tutorial purposes.
// Use the code as you see fit. Of course if I do not mind credits.

public class GFTargetingBot extends AdvancedRobot {
	private static final double BULLET_POWER = 1.9;
	
	private static double lateralDirection;
	private static double lastEnemyVelocity;
	private static GFTMovement movement;
	
	public GFTargetingBot() {
		movement = new GFTMovement(this);	
	}
	
	public void run() {
		setColors(Color.BLUE, Color.BLACK, Color.YELLOW);
		lateralDirection = 1;
		lastEnemyVelocity = 0;
		setAdjustRadarForGunTurn(true);
		setAdjustGunForRobotTurn(true);
		do {
			turnRadarRightRadians(Double.POSITIVE_INFINITY); 
		} while (true);
	}
	
	public void onScannedRobot(ScannedRobotEvent e) {
		double enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians();
		double enemyDistance = e.getDistance();
		double enemyVelocity = e.getVelocity();
		if (enemyVelocity != 0) {
			lateralDirection = GFTUtils.sign(enemyVelocity * Math.sin(e.getHeadingRadians() - enemyAbsoluteBearing));
		}
		GFTWave wave = new GFTWave(this);
		wave.gunLocation = new Point2D.Double(getX(), getY());
		GFTWave.targetLocation = GFTUtils.project(wave.gunLocation, enemyAbsoluteBearing, enemyDistance);
		wave.lateralDirection = lateralDirection;
		wave.bulletPower = BULLET_POWER;
		wave.setSegmentations(enemyDistance, enemyVelocity, lastEnemyVelocity);
		lastEnemyVelocity = enemyVelocity;
		wave.bearing = enemyAbsoluteBearing;
		setTurnGunRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getGunHeadingRadians() + wave.mostVisitedBearingOffset()));
		setFire(wave.bulletPower);
		if (getEnergy() >= BULLET_POWER) {
			addCustomEvent(wave);
		}
		movement.onScannedRobot(e);
		setTurnRadarRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getRadarHeadingRadians()) * 2);
	}
}

class GFTWave extends Condition {
	static Point2D targetLocation;

	double bulletPower;
	Point2D gunLocation;
	double bearing;
	double lateralDirection;

	private static final double MAX_DISTANCE = 1000;
	private static final int DISTANCE_INDEXES = 5;
	private static final int VELOCITY_INDEXES = 5;
	private static final int BINS = 25;
	private static final int MIDDLE_BIN = (BINS - 1) / 2;
	private static final double MAX_ESCAPE_ANGLE = 0.7;
	private static final double BIN_WIDTH = MAX_ESCAPE_ANGLE / (double)MIDDLE_BIN;
	
	private static int[][][][] statBuffers = new int[DISTANCE_INDEXES][VELOCITY_INDEXES][VELOCITY_INDEXES][BINS];

	private int[] buffer;
	private AdvancedRobot robot;
	private double distanceTraveled;
	
	GFTWave(AdvancedRobot _robot) {
		this.robot = _robot;
	}
	
	public boolean test() {
		advance();
		if (hasArrived()) {
			buffer[currentBin()]++;
			robot.removeCustomEvent(this);
		}
		return false;
	}

	double mostVisitedBearingOffset() {
		return (lateralDirection * BIN_WIDTH) * (mostVisitedBin() - MIDDLE_BIN);
	}
	
	void setSegmentations(double distance, double velocity, double lastVelocity) {
		int distanceIndex = (int)(distance / (MAX_DISTANCE / DISTANCE_INDEXES));
		int velocityIndex = (int)Math.abs(velocity / 2);
		int lastVelocityIndex = (int)Math.abs(lastVelocity / 2);
		buffer = statBuffers[distanceIndex][velocityIndex][lastVelocityIndex];
	}

	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;
	}	
}

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));
	}
}

class GFTMovement {
	private static final double BATTLE_FIELD_WIDTH = 800;
	private static final double BATTLE_FIELD_HEIGHT = 600;
	private static final double WALL_MARGIN = 18;
	private static final double MAX_TRIES = 125;
	private static final double REVERSE_TUNER = 0.421075;
	private static final double DEFAULT_EVASION = 1.2;
	private static final double WALL_BOUNCE_TUNER = 0.699484;

	private AdvancedRobot robot;
	private Rectangle2D fieldRectangle = new Rectangle2D.Double(WALL_MARGIN, WALL_MARGIN,
		BATTLE_FIELD_WIDTH - WALL_MARGIN * 2, BATTLE_FIELD_HEIGHT - WALL_MARGIN * 2);
	private double enemyFirePower = 3;
	private double direction = 0.4;

	GFTMovement(AdvancedRobot _robot) {
		this.robot = _robot;
	}
	
	public void onScannedRobot(ScannedRobotEvent e) {
		double enemyAbsoluteBearing = robot.getHeadingRadians() + e.getBearingRadians();
		double enemyDistance = e.getDistance();
		Point2D robotLocation = new Point2D.Double(robot.getX(), robot.getY());
		Point2D enemyLocation = GFTUtils.project(robotLocation, enemyAbsoluteBearing, enemyDistance);
		Point2D robotDestination;
		double tries = 0;
		while (!fieldRectangle.contains(robotDestination = GFTUtils.project(enemyLocation, enemyAbsoluteBearing + Math.PI + direction,
				enemyDistance * (DEFAULT_EVASION - tries / 100.0))) && tries < MAX_TRIES) {
			tries++;
		}
		if ((Math.random() < (GFTUtils.bulletVelocity(enemyFirePower) / REVERSE_TUNER) / enemyDistance ||
				tries > (enemyDistance / GFTUtils.bulletVelocity(enemyFirePower) / WALL_BOUNCE_TUNER))) {
			direction = -direction;
		}
		// Jamougha's cool way
		double angle = GFTUtils.absoluteBearing(robotLocation, robotDestination) - robot.getHeadingRadians();
		robot.setAhead(Math.cos(angle) * 100);
		robot.setTurnRightRadians(Math.tan(angle));
	}
}

What's next for your robot?

I must document the code to make this tutorial thing to really work. You're more than welcome to help in this.

What other robot(s) is it based on?

Aristocles ‒ both gun and movement