User:Voidious/LocationBot

From Robowiki
< User:Voidious
Revision as of 22:48, 10 June 2012 by Voidious (talk | contribs) (add test method signature / sample)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

A little test bot I built to help me unit test my Precise Prediction code. I run it in a battle against SittingDuck on a 1000x1000 field. He goes to the center of the field, notes his start state, turns to a random heading, moves / turns a random amount, and notes where he starts and ends.

He can print all the raw info or just output a method call with all the data. Of course, you'd have to write that method yourself to use it to test your own predictor. I just take his console output, grep the lines with the method call, and paste them into my unit test.

package voidious.test;

import java.awt.geom.Point2D;

import robocode.AdvancedRobot;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.util.Utils;

public class LocationBot extends AdvancedRobot {
  private static final boolean PRINT_DEBUG_INFO = false;
  private static final boolean DISCARD_ROBOT_HITS = true;
  private static final boolean DISCARD_WALL_HITS = false;

  private boolean hitRobot;
  private boolean hitWall;
  public void run() {
    Point2D.Double startPoint = new Point2D.Double(500, 500);
    for (int x = 0; x < 100; x++) {
      hitRobot = false;
      hitWall = false;

      StringBuilder debugString = new StringBuilder();
      StringBuilder testString = new StringBuilder();
      setMaxVelocity(8);
      do {
        double goAngle = absoluteBearing(myLocation(), startPoint);
        setBackAsFront(this, goAngle);
        execute();
      } while (myLocation().distanceSq(startPoint) > 0.1);

      turnRightRadians(Math.random() * 2 * Math.PI);
      double distance = (300 + (Math.random() * 1000))
          * ((Math.random() > 0.5) ? 1 : -1);
      double turn = (Math.random() * 4 * Math.PI) - (2 * Math.PI);
      double maxVelocity;
      if (Math.random() < 0.5) {
        maxVelocity = 8;
      } else {
        maxVelocity = Math.random() * 7.5 + 0.5;
      }

      if (PRINT_DEBUG_INFO) {
        debugString.append("Start state: ");
        debugString.append("\n");
        debugString.append("  Location: " + myLocation());
        debugString.append("\n");
        debugString.append("  Heading: " + getHeadingRadians());
        debugString.append("\n");
        debugString.append("  Velocity: " + getVelocity());
        debugString.append("\n");
        debugString.append("  Time: " + getTime());
        debugString.append("\n");
        debugString.append("Distance: " + distance);
        debugString.append("\n");
        debugString.append("Turn: " + turn);
        debugString.append("\n");
        debugString.append("Max Velocity: " + maxVelocity);
        debugString.append("\n");
      }

      Point2D.Double myLocation = myLocation();
      testString.append(myLocation.x);
      testString.append(", ");
      testString.append(myLocation.y);
      testString.append(", ");
      testString.append(getHeadingRadians());
      testString.append(", ");
      testString.append(getVelocity());
      testString.append(", ");
      testString.append(getTime());
      testString.append("L, ");
      testString.append(distance);
      testString.append(", ");
      testString.append(turn);
      testString.append(", ");
      testString.append(maxVelocity);
      testString.append(", ");

      setMaxVelocity(maxVelocity);
      setAhead(distance);
      setTurnRightRadians(turn);
      do {
        execute();
      } while (Math.abs(getDistanceRemaining()) > 0.000001);

      if (PRINT_DEBUG_INFO) {
        debugString.append("End time: " + getTime());
        debugString.append("\n");
        myLocation = myLocation();
        debugString.append("End location: " + myLocation);
        debugString.append("\n");
        debugString.append("End heading: " + getHeadingRadians());
      }

      testString.append(getTime());
      testString.append("L, ");
      myLocation = myLocation();
      testString.append(myLocation.x);
      testString.append(", ");
      testString.append(myLocation.y);
      testString.append(", ");
      testString.append(getHeadingRadians());

      if ((!hitRobot || !DISCARD_ROBOT_HITS)
          && (!hitWall || !DISCARD_WALL_HITS)) {
        if (PRINT_DEBUG_INFO) {
          System.out.println(debugString.toString());
        }
        System.out.println("testPrediction(" + testString.toString() + ");");
        if (PRINT_DEBUG_INFO) {
          System.out.println("***************************************");
        }
      }
    }
  }

  @Override
  public void onHitRobot(HitRobotEvent e) {
    if (!hitRobot) {
      System.out.println("HIT A ROBOT");
      hitRobot = true;
    }
  }

  @Override
  public void onHitWall(HitWallEvent e) {
    if (!hitWall) {
      System.out.println("HIT A WALL");
      hitWall = true;
    }
  }

  private Point2D.Double myLocation() {
    return new Point2D.Double(getX(), getY());
  }

  public static double absoluteBearing(Point2D.Double sourceLocation,
       Point2D.Double target) {
    return Math.atan2(target.x - sourceLocation.x,
        target.y - sourceLocation.y);
  }

  public static void setBackAsFront(AdvancedRobot robot, double goAngle) {
    double angle =
        Utils.normalRelativeAngle(goAngle - robot.getHeadingRadians());

    if (Math.abs(angle) > (Math.PI / 2)) {
      if (angle < 0) {
        robot.setTurnRightRadians(Math.PI + angle);
      } else {
        robot.setTurnLeftRadians(Math.PI - angle);
      }
      robot.setBack(100);
    } else {
      if (angle < 0) {
        robot.setTurnLeftRadians(-1 * angle);
      } else {
        robot.setTurnRightRadians(angle);
      }
      robot.setAhead(100);
    }
  }
}

Sample test method:

  private void testPrediction(double startX, double startY,
      double startHeading, double startVelocity, long startTime,
      double distance, double turn, double maxVelocity, long endTime,
      double endX, double endY, double endHeading) {
    MovementPredictor predictor = newPredictor();
    RobotState startState = new RobotState(newLocation(startX, startY),
        startHeading, startVelocity, startTime);
    long ticks = endTime - startTime;
    RobotState endState = predictor.predict(startState, distance, turn,
        maxVelocity, ticks, false);
    assertEquals(endX, endState.location.x, 0.01);
    assertEquals(endY, endState.location.y, 0.01);
    assertEquals(Utils.normalAbsoluteAngle(endHeading),
        Utils.normalAbsoluteAngle(endState.heading), 0.01);
  }