Module/Targeting/GFTargetingWaves

From Robowiki
< Module‎ | Targeting
Revision as of 20:06, 25 March 2008 by Jab (talk | contribs)
Jump to navigation Jump to search

A screenshot before the code showing a Module Bot throwing waves to get the offsets, and turning the gun accordingly.

A Module Bot throwing waves

package jab.targeting;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.Enumeration;
import java.util.Vector;

import robocode.util.Utils;

import jab.Module;
import jab.Targeting;

/**
 * Credits
 * GFTargetingWaves by jab. Code license: RWPCL
 * A simple GuessFactorTargeting using waves and without segmentation
 */
public class GFTargetingWaves extends Targeting {

	public GFTargetingWaves(Module bot) {
		super(bot);
	}

	// The last waves of the historical to calculate the meanOffset
	static final int LIMIT = 10;

	// Throw a wave
	static final int TICKS = 3;

	Vector<Wave> waves = new Vector<Wave>();
	Vector<Offset> offsets = new Vector<Offset>();

	public void target() {
		updateWaves();
		if ((int) bot.getTime() % TICKS == 0)
			throwWave();
		calculateMeanOffsetAndTurnGun();
	}

	private void updateWaves() {
		Enumeration<Wave> e = waves.elements();
		while (e.hasMoreElements()) {
			Wave wave = e.nextElement();
			wave.time++;

			// The current enemy has changed
			if (!wave.enemyName.equals(bot.enemy.name)) {
				waves.remove(wave);
				offsets.clear();
			}
			// The wave breaks
			else if (wave.velocity * wave.time > Point2D.distance(wave.originX,
					wave.originY, bot.enemy.x, bot.enemy.y)) {
				double thetaFireTime = Utils
						.normalAbsoluteAngle(Math.atan2(wave.enemyX
								- wave.originX, wave.enemyY - wave.originY));
				double thetaBreak = Utils
						.normalAbsoluteAngle(Math.atan2(bot.enemy.x
								- wave.originX, bot.enemy.y - wave.originY));
				offsets.add(new Offset(bot.enemy.name, Utils
						.normalRelativeAngle(thetaFireTime - thetaBreak)));
				waves.remove(wave);
			}
		}
	}

	private void throwWave() {
		waves.add(new Wave(bot.getX(), bot.getY(), bot.bulletPower,
				bot.enemy.name, bot.enemy.x, bot.enemy.y));
	}

	private void calculateMeanOffsetAndTurnGun() {
		double meanOffset = 0;
		double offsetsCounter = 0;
		int i = offsets.size() - 1;
		while (i >= 0 && offsetsCounter < LIMIT) {
			Offset o = offsets.get(i);
			if (o.enemyName.equals(bot.enemy.name) && offsetsCounter <= LIMIT) {
				meanOffset += o.offset;
				offsetsCounter++;
			}
			i--;
		}
		if (offsetsCounter != 0)
			meanOffset /= offsetsCounter;

		double absoluteBearing = bot.getHeadingRadians()
				+ bot.enemy.bearingRadians - meanOffset;
		bot.setTurnGunRightRadians(robocode.util.Utils
				.normalRelativeAngle(absoluteBearing
						- bot.getGunHeadingRadians()));
	}

	// Draw the waves
	public void onPaint(Graphics2D g) {
		Enumeration<Wave> e = waves.elements();
		while (e.hasMoreElements()) {
			g.setColor(Color.BLUE);
			Wave wave = e.nextElement();
			double travelledDistance = wave.time * wave.velocity;
			g.drawOval((int) wave.originX - (int) travelledDistance,
					(int) wave.originY - (int) travelledDistance,
					(int) travelledDistance * 2, (int) travelledDistance * 2);
			g.drawLine((int) wave.originX, (int) wave.originY,
					(int) wave.enemyX, (int) wave.enemyY);
			g.setColor(Color.GREEN);
			g.drawLine((int) wave.originX, (int) wave.originY,
					(int) bot.enemy.x, (int) bot.enemy.y);
		}
	}

	public class Wave {
		public double time;
		public double originX, originY;
		public double velocity;
		public double enemyX, enemyY;
		public String enemyName;

		public Wave(double x, double y, double bulletPower, String enemyName,
				double enemyX, double enemyY) {
			originX = x;
			originY = y;
			velocity = 20.0 - 3.0 * bulletPower;
			time = 0;
			this.enemyName = enemyName;
			this.enemyX = enemyX;
			this.enemyY = enemyY;
		}
	}

	public class Offset {
		public double offset;
		public String enemyName;

		public Offset(String enemyName, double offset) {
			this.enemyName = enemyName;
			this.offset = offset;
		}
	}
}