Archived talk:Kenran

From Robowiki
Revision as of 05:37, 6 December 2009 by Rednaxela (talk | contribs) (Follow your own advice Nat ;-))
Jump to navigation Jump to search

Welcome!

Hello, Kenran, and welcome to RoboWiki! This place contains a wealth information about Robocode, from basic to more advanced. I hope you enjoy creating robots and being a robocoder!

If you are posting a comment on this wiki, please sign your messages using four tildes (--~~~~); this will automatically insert your username and the date stamp. If you are not familiar with MediaWiki, these links might help you out:

If you need help, check out the frequently asked questions or ask it on this page. Again, welcome!

—— Rednaxela 15:59, 28 November 2009 (UTC)

Welcome to the wiki! :) --Rednaxela 15:59, 28 November 2009 (UTC)

Hello, and thank you. :-) --Kenran 09:07, 29 November 2009 (UTC)

My first try at Pattern Matching

So this my first attempt to write a simple pattern matching gun. As you can see, my in some sense my code is similar to that of PEZ's LeachPMC, where I looked at to help me do it. (Thanks for that, PEZ :-)).

But now I'm having some trouble and would be very happy if someone with Robocode and Java knowledge could overlook it and / or help me with it:

  • As you can see aimed is superfluous at the moment. I tried to make the bot faster by only calculating predictedPosition at moments where I actually want to shoot. But I can't seem to handle this: I wanted to do sth like if (getGunHeat() > getGunCoolingRate()*3 && getRoundNum() != 0), then predict and set aimed = true, and finally fire if aimed == true && getGunTurnRemaining() == 0.0 (and set aimed = false again). But that doesn't work, at a certain point it just stops firing at all then :-/
  • I don't understand why, e.g. versus Walls, it can't handle the movement in the edges: it seems to predict the right "position" but at the wrong time, so the bullets just impact before Walls is at that position. Any ideas why this could be the case? Maybe sth with my predictPosition algorithm.

I hope, my code is not too sloppy, as I mentioned, I'm not a very good programmer. Anyway, great site, I wouldn't have been able to get any kind of targeting working without it :-)

package kenran.mega;

import robocode.*;
import kenran.util.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;

public class Pantheist extends AdvancedRobot
{
  private static final int PM_LENGTH = 7000;
  private static final int RECENT_PATTERN_LENGTH = 10;

  private static Point2D _enemyPosition = new Point2D.Double();
  private static Point2D _robotPosition = new Point2D.Double();
  private static double _enemyHeading = 0;
  private static double _enemyBearing;
  private static double _enemyVelocity;
  private static double _enemyDistance;
  private static double _deltaHeading;

  private static ArrayList _record = new ArrayList(PM_LENGTH);
  private static MovementDeque _recent = new MovementDeque();
  private static MovementDeque _iterator = new MovementDeque();
  private static int _recordSize = 0;
  private static boolean _recordIsFull = false;

  private static boolean aimed;


  public void run()
  {
    setAdjustGunForRobotTurn(true);
    setAdjustRadarForGunTurn(true);
    aimed = false;
    if (getRoundNum() == 0)
      for (int i = 0; i < RECENT_PATTERN_LENGTH; i++)
	_recent.add(0, 8.0);
    turnRadarRightRadians(Double.POSITIVE_INFINITY);
    do
    {
      scan();
    } while (true);
  }


  public void onScannedRobot(ScannedRobotEvent e)
  {
    _robotPosition.setLocation(getX(), getY());
    _enemyDistance = e.getDistance();
    _deltaHeading = e.getHeadingRadians() - _enemyHeading;
    _enemyHeading = e.getHeadingRadians();
    _enemyBearing = getHeadingRadians() + e.getBearingRadians();
    _enemyVelocity = e.getVelocity();
    _enemyPosition.setLocation(Utils.project(_robotPosition, _enemyBearing, _enemyDistance));
    record(_deltaHeading, _enemyVelocity);
    _recent.add(_deltaHeading, _enemyVelocity);
    if (getRoundNum() != 0)
    {
      Point2D predictedPosition = new Point2D.Double();
      predictedPosition.setLocation(predictPosition(1.5));
      double angle = Utils.absoluteBearing(_robotPosition, predictedPosition);
      setTurnGunRightRadians(Utils.normalRelativeAngle(angle - getGunHeadingRadians()));
      aimed = true;
    }
    if (getRoundNum() != 0 && aimed)
    {
      setFire(1.5);
      aimed = false;
    }
    double radarTurn = _enemyBearing - getRadarHeadingRadians();
    setTurnRadarRightRadians(2.0*Utils.normalRelativeAngle(radarTurn));
  }


  private void record(double dh, double v)
  {
    _record.add(new MovementState(dh, v));
    if (_recordIsFull)
      _record.remove(0);
    else
    {
      _recordSize++;
      _recordIsFull = (_recordSize >= PM_LENGTH);
    }
  }


  private double compare(MovementDeque md1, MovementDeque md2)
  {
    double sum = 0;
    for (int i = 0; i < RECENT_PATTERN_LENGTH; i++)
    {
      sum += Math.abs(md1.get(i).getDeltaHeading()-md2.get(i).getDeltaHeading()) + Math.abs(md1.get(i).getVelocity()-md2.get(i).getVelocity());
    }
    return sum;
  }


  private int lastIndexOfMatchingSeries()
  {
    for (int i = 0; i < RECENT_PATTERN_LENGTH; i++)
      _iterator.add((MovementState)_record.get(i));
    double min = compare(_iterator, _recent);
    int minPos = RECENT_PATTERN_LENGTH - 1;
    int i = RECENT_PATTERN_LENGTH;
    do
    {
      MovementState ms = (MovementState)_record.get(i);
      _iterator.add(ms.getDeltaHeading(), ms.getVelocity());
      double comp = compare(_iterator, _recent);
      if (comp < min)
      {
	min = comp;
	minPos = i;
      }
      i++;
    } while (i < _recordSize - 50);
    return minPos;
  }


  private Point2D predictPosition(double power)
  {
    int index = lastIndexOfMatchingSeries();
    double px = _enemyPosition.getX();
    double py = _enemyPosition.getY();
    double heading = _enemyHeading;
    double bulletTravelTime = 0;
    double travelTime = 0;
    for (int i = index+1; i < _recordSize && travelTime <= bulletTravelTime; i++)
    {
      MovementState ms = (MovementState)_record.get(i);
      px += Math.sin(heading) * ms.getVelocity();
      py += Math.cos(heading) * ms.getVelocity();
      heading += ms.getDeltaHeading();
      bulletTravelTime = (int)Utils.bulletTravelTime(_robotPosition.distance(px, py), power);
      travelTime++;
    }
    return new Point2D.Double(px, py);
  }


  static class MovementDeque
  {
    private MovementState[] msArray = new MovementState[RECENT_PATTERN_LENGTH];

    MovementDeque() {}

    void add(double dh, double v)
    {
      for (int i = 0; i < RECENT_PATTERN_LENGTH-1; i++)
	msArray[i] = msArray[i+1];
      msArray[RECENT_PATTERN_LENGTH-1] = new MovementState(dh, v);
    }

    void add(MovementState ms)
    {
      add(ms.getDeltaHeading(), ms.getVelocity());
    }

    MovementState get(int i)
    {
      if (0 <= i && i < RECENT_PATTERN_LENGTH)
	return msArray[i];
      else
	return null;
    }
  }
}

--Kenran 15:48, 5 December 2009 (UTC)

What is the propose of getRoundNum() != 0? That means it won't fire in the first round. If you remove all reference to the getRoundNum() == 0 or getRoundNum() !== 0, I think it will perform much better.

Actually I would say, don't use the PMC robot as a codebase, as it is very optimized to the PMChallenge. Try to read the robot with normal PM, e.g. Waylander, before. If you can't figure out what is behind the shrunk code of Waylander, feel free to ask again. —Preceding unsigned comment added by Nat (talkcontribs)