/* $Id$
 * PINK
 *Yaniv Schiller
 * LG YS YZ
 * LAST YEARS: Group members: Eva, Jason, Cheoljoo
 */
package Rectangles;

import java.util.*;
import java.io.*;
import java.awt.*;
import ui.*;

public final class Group8Player0 implements IFCPlayer {

  public final class emptyRec{
    private int nR;//local numRobots
    public int topLeftX,topLeftY;
    public int width,height;
    private int borderx,bordery; //next border pos
    private int robotDistances[]; //for each roobt, what its distnace from the rec
    public int orderedRobotsIndexes[]; //to store the robots available to work on this rec
    public int size;
    private int closestAvailableDistance;
    public emptyRec(emptyRec orig){
      nR=orig.nR;
      topLeftX=orig.topLeftX;
      topLeftY=orig.topLeftY;
      width=orig.width;
      height=orig.height; //no need to copy Arrays
      size=orig.size;
      borderx=bordery=-1;
    }
    public emptyRec(int numRobots){
      nR=numRobots;
      this.orderedRobotsIndexes= new int[numRobots];
      this.robotDistances= new int[numRobots];
      for(int i=0;i<numRobots;i++)
        orderedRobotsIndexes[i]=i;
    }
    public char getDirectionToNextBorder(int x,int y,int[][] colors,int me) throws Exception{
      if (borderx == -1 || bordery == -1 || (x == borderx && y == bordery)) {
        //find next location
        int cnt=0;
        int[] xs=new int[2*width+2*(height-2)];
        int[] ys=new int[2*width+2*(height-2)];
        int[] ds=new int [2*width+2*(height-2)]; //distnaces
        int i;
        for(i=topLeftX;i<(topLeftX+width);i++){
          if (colors[i][topLeftY] != me) {
            xs[cnt] = i;
            ys[cnt] = topLeftY;
            ds[cnt] = distance(x, y, i, topLeftY);
            cnt++;
          }
          if (colors[i][topLeftY+height-1] != me) {
            xs[cnt] = i;
            ys[cnt] = topLeftY+height-1;
            ds[cnt] = distance(x, y, i, topLeftY+height-1);
            cnt++;
          }
          if (colors[i][topLeftY] == _CFILLED||colors[i][topLeftY+height-1]== _CFILLED) {
            return 'B'; //we have a unattainable rec
          }


        }
        for(i=topLeftY+1;i<(topLeftY+height-1);i++){
          if (colors[topLeftX][i] != me) {
           xs[cnt] = topLeftX;
           ys[cnt] = i;
           ds[cnt] = distance(x, y, topLeftX, i);
           cnt++;
         }
         if (colors[topLeftX+width-1][i] != me) {
           xs[cnt] = topLeftX+width-1;
           ys[cnt] = i;
           ds[cnt] = distance(x, y, topLeftX+width-1, i);
           cnt++;
         }
         if (colors[topLeftX][i] == _CFILLED||colors[topLeftX+width-1][i]== _CFILLED) {
           return 'B'; //we have a unattainable rec
         }
        }
        //check if size is still more than 0...
        size = getRecSize(topLeftX, topLeftY, width, height);
        if(size<=0)
           return 'B'; //we have a unattainable rec
        //find closes nonfilled...
        int minD=ds[0];
        int minP=0;
        for(i=1;i<cnt;i++)
          if(ds[i]<minD){
            minD=ds[i];
            minP=i;
          }
        borderx=xs[minP];
        bordery=ys[minP];
        //System.out.println("going to " + borderx + "," + bordery + " from " + x + "," + y + " to complete rec " + topLeftX +"," + topLeftY + " of size " + size + " with " + cnt + " spaces to fill");
      }
      if (x < borderx)
        return 'E';
      else if (x > borderx)
        return 'W';
      if (y < bordery)
        return 'S';
      else if (y > bordery)
        return 'N';
      //shouldn't be here
      return 'Y';
    }

    public char getDirectionFrom(int x,int y){

      if(x<topLeftX)
        return 'E';
      else if(x>(topLeftX+width-1))
        return 'W';
      //above or below
      if(y<topLeftY)
        return 'S';
      else if(y>(topLeftY+height-1))
        return 'N';
      return 'Y';


    }
    public void getCloseRobots(Robot[] robots) throws Exception {
      //populate the distnces Vector
      int i;
      closestAvailableDistance=2*size;
      for(i=0;i<numRobots;i++){
        int totDist = 0;
        if (robots[i].xpos() < topLeftX)
          totDist += (topLeftX - robots[i].xpos());
        if (robots[i].xpos() > (topLeftX + width - 1))
          totDist += (robots[i].xpos() - (topLeftX + width - 1));
        if (robots[i].ypos() < topLeftY)
          totDist += (topLeftY - robots[i].ypos());
        if (robots[i].ypos() > (topLeftY + height - 1))
          totDist += (robots[i].ypos() - (topLeftY + height - 1));
        robotDistances[i] = totDist;
        if(method[i]==3&&totDist<closestAvailableDistance){ //if available...
          closestAvailableDistance=totDist;
        }
      }
      //sort the indexes by Distances
      //bubble sort... too small do bother with something else
      for(i=nR-1;i>0;i--)
        for(int j=0;j<i;j++)
          if(robotDistances[j]>robotDistances[j+1]){
            int tDist,tInd;
            tDist=robotDistances[j];
            tInd=orderedRobotsIndexes[j];
            robotDistances[j]=robotDistances[j+1];
            orderedRobotsIndexes[j]=orderedRobotsIndexes[j+1];
            robotDistances[j+1]=tDist;
            orderedRobotsIndexes[j+1]=tInd;
          }
//      System.out.println("Closest Robot to rec[" + topLeftX + "," + topLeftY +
//                         "] is: " + orderedRobotsIndexes[0] );
    }
  }

  Rectangles rectangles;

  static Random random;
  static final String _CNAME = "8:FindingTheGap";
  static final Color _CCOLOR = new Color(1.0f,0.67f,0.67f);
  static final int _NORTH = 0;
  static final int _SOUTH = 1;
  static final int _WEST = 2;
  static final int _EAST = 3;

  Vector emptyRecs;
  Robot[] robots;        /* robots */
  emptyRec[] AsignedEmptyRecs; //the emptyrec asssigned to robot
  int numRobots;         /* number of robots */
  int size;              /* board size */
  int destX[], destY[];  /* destinations of robots; -1 for grid walking mode */
  int method[];          /* which method am i moving in? */
  int maxEmptySize;
  /*
   Method 1:
   Plaid, grid
   method 2:
   2 pieces starting together going oppsite directions, walk apart then come back togetehr
   */

  Robot[] closestEnemy;  /* the closest enemy of each of our Robots */
  int[] movesFollowed; /* how many moves the enemy has been chasing each Robot */
  int availableRobots;
  int direction[];       /* robot directions; one of _NORTH, ... */

  public Robot[] register(Rectangles rectangles) throws Exception {
    this.rectangles = rectangles;
    this.numRobots = rectangles.numRobots();
    this.robots = new Robot[numRobots];
    this.size = rectangles.size();
    this.destX = new int[numRobots];
    this.destY = new int[numRobots];
    this.method = new int[numRobots];
    this.AsignedEmptyRecs= new emptyRec[numRobots];
    this.direction = new int[numRobots];
    this.random = java.security.SecureRandom.getInstance("SHA1PRNG");
    this.availableRobots=0;
    this.closestEnemy = new Robot[numRobots];
    this.movesFollowed = new int[numRobots];
    this.maxEmptySize=10;

    emptyRecs = new Vector(numRobots) ;
    int size=this.size;
    if (numRobots < 5){
      size=this.size/3+8;
    }

    /* determines the initial locations of the robots */
    int inc =  (size/numRobots);//*2
      int x = size/2;
      int y = size-1-inc;
      for (int i = 0; i < numRobots/2; i++) {
        robots[i] = new Robot(x, size - 1);
        x += inc;
        destX[i] = x-1 ;
        destY[i] = size/2-1;
        method[i]=1;
      }
      destX[(numRobots/2-1)>0?(numRobots/2-1):0] = size-1;
      for (int i = numRobots/2; i < numRobots; i++) {
        robots[i] = new Robot(size-1, y);
        destX[i] = size/2-1;
        destY[i] = y + inc;
        y -= inc;
        method[i]=1;
      }

    /* if the number of robots are less than 3, then skip the plaid walking
       and do the grid walking */
//    if (numRobots < 5)
//      for (int i = 0; i < numRobots; i++)
//	destX[i] = destY[i] = -1;

    return robots;
  }

  public String name() throws Exception {
    return _CNAME;
  }

  public Color color() throws Exception {
    return _CCOLOR;
  }

  public boolean interactive() throws Exception {
    return false;
  }

  /* determine the next moves of robots */
  public char[] move() throws Exception {
    char[] moves = new char[numRobots];
    if(availableRobots>0){
      //System.out.println("using A");
      findEmptyRecs();
    }
    int i;
    for (i = 0; i < numRobots; i++)
      moves[i] = nextMove(i);
    i=0;
    //find a robot to do an empty recatangle
    if(availableRobots>0){
//      System.out.println("using B");
      findEmptyRecs();
    }
    int iavail=availableRobots;
    emptyRec maxER=new emptyRec(0);
    int maxERsize=0;
    while(availableRobots>0&&i<emptyRecs.size()){
//      System.out.println("We have " + availableRobots + "Availble Robots");
      emptyRec ER=(emptyRec)emptyRecs.elementAt(i);
      if(ER.size>maxERsize){
        maxER=new emptyRec(ER);
        maxERsize=ER.size;
      }
      //System.out.println(i + "Checking out Rec: " + ER.topLeftX +"," +ER.topLeftY +
//                         " " +ER.width + "X" + ER.height +" of size " + ER.size );

      boolean notAssigned=true;
      for(int j=0;j<numRobots&&notAssigned;j++)
        if(method[ER.orderedRobotsIndexes[j]]==3){
          int myRNum=ER.orderedRobotsIndexes[j];
          //System.out.println("sending robot "+ myRNum + "b/c it is closest available");
          //assign this one
          method[myRNum] = 4;
          if(iavail>1&&availableRobots==1)
            AsignedEmptyRecs[myRNum]=maxER;
          else
            AsignedEmptyRecs[myRNum]=new emptyRec(ER);
          availableRobots--;
          notAssigned=false;
          moves[myRNum]=nextMove(myRNum);
        }
      if (notAssigned)
        System.out.print("BIG PROBLEM... MISCOUNTED\n");

      i++;
    }
//    for (int i = 0; i < numRobots; i++)
//      //System.out.print(direction[i]) ;
    for (i = 0; i < numRobots; i++) {
      if(method[i]==3){ //get real direction if jus assigned an emptyRec
        moves[i] = nextMove(i);
        method[i]=2;
        availableRobots--;
      }
//      System.out.print(moves[i]) ;
      direction[i] = charDir(moves[i]);
//      System.out.print(direction[i]) ;
    }
//    System.out.print("\n");

    return moves;
  }

  /* determine the next move of the i-th robot */
  public char nextMove(int i) throws Exception {
    if (isBeingChased(i))
{
	//System.out.println("Robot " + i + " is being chased.");
	return 'Y';
}
    char move = 'S';
    int x = robots[i].xpos();  /* current x-pos of the i-th robot */
    int y = robots[i].ypos();  /* current y-pos of the i-th robot */
    int destx = destX[i];      /* destination x-pos of the i-th robot */
    int desty = destY[i];      /* destination y-pos of the i-th robot */


    switch(method[i])
    {
    case 0:
      /* if grid walking mode */
      int validCont = validMoveDir(x, y, direction[i]);
      int rnd = random.nextInt(15);
      if (numRobots < 5)
        rnd = random.nextInt(10);
      if (validCont > 0) {
        int validRight = validMoveDir(x, y, nextDirection(direction[i]));
        int validLeft = validMoveDir(x, y, prevDirection(direction[i]));
        if (validRight > 0 && rnd < 3) {
          if (validLeft > 0 && rnd == 0)
            return dirChar(prevDirection(direction[i]));
          else
            return dirChar(nextDirection(direction[i]));
        }
        else
          return dirChar(direction[i]);
      }
      else if (validCont == 0) /* out of range */
        return dirChar(nextDirection(direction[i]));
      else if (validCont == _CFILLED)
        return dirChar(nextDirection(direction[i]));
      break;
    case 1://move to desitnation
      move=goToDest(x,y,destx,desty);
      if(Character.toUpperCase(move)=='Y'){
        /* now arrived at the destination; get new destination */
        //System.out.println("Robot " + i + " arrived\n");
//  destX[i] = random.nextInt(size);
//  destY[i] = random.nextInt(size);
//  destY[i] = -1;
        method[i] = 3;
        availableRobots++;
        return nextMove(i);
      }
      return move;
    case 2:
      //circle border...
      if(this.maxEmptySize==10){
        this.maxEmptySize = size - 2;
        findEmptyRecs();
        method[i]=3;
        return nextMove(i);
      }

      method[i] = 4;
      emptyRec e=new emptyRec(numRobots);
      e.topLeftX = 0;
      e.topLeftY = 0;
      e.width = size;
      e.height = size;
      e.size = getRecSize(e.topLeftX, e.topLeftY, e.width, e.height);
      if(e.size<=0)
        method[i] = 5;
      AsignedEmptyRecs[i]=e;
      availableRobots--;
      return nextMove(i);

    case 3:
      //look for closest rec
      return 'Y'; //handled in the move function when returned '3'
    case 4:

      //on a mission to closest rec
      //move towards it, then aroound it...

//      System.out.print("robot " + i + " Heading for rec: "  + AsignedEmptyRecs[i].topLeftX + "," + AsignedEmptyRecs[i].topLeftY + " via " );
      char dir=AsignedEmptyRecs[i].getDirectionFrom(x,y);
//      System.out.println(dir);
      if(dir=='Y'){
        //walk the border... closest non-filled
        int me=rectangles.indexOf(this);
        //System.out.println("my index: " + me);
         //System.out.print("Robot "+i + " ");
        dir=AsignedEmptyRecs[i].getDirectionToNextBorder(x,y,rectangles.colors(),me);
        if(dir=='B'){
          method[i] = 3;
          availableRobots++;
          return nextMove(i);
        }
      }
//      else
//        System.out.println("Robot "+i + " going " + dir + " to "+ AsignedEmptyRecs[i].topLeftX + "[" + AsignedEmptyRecs[i].width +"], "+ AsignedEmptyRecs[i].topLeftY + "[" + AsignedEmptyRecs[i].height +"];" );
      return dir;
      //check if still available.
      //if not then free
    case 5: //set smile
      switch(i){
        case 0:destX[i]=size/2+2;destY[i]=size/2-1;  break;
        case 1:destX[i]=size/2-2;destY[i]=size/2-1;  break;
        case 2:destX[i]=size/2;destY[i]=size/2; break;
        case 3:destX[i]=size/2;destY[i]=size/2+3; break;
        case 4:destX[i]=size/2-1;destY[i]=size/2+3; break;
        case 5:destX[i]=size/2+1;destY[i]=size/2+3; break;
        case 6:destX[i]=size/2-2;destY[i]=size/2+2; break;
        case 7:destX[i]=size/2+2;destY[i]=size/2+2; break;
        case 8:destX[i]=size/2-3;destY[i]=size/2+1; break;
        case 9:destX[i]=size/2+3;destY[i]=size/2+1; break;
        default:destX[i]=0;destY[i]=0;method[i]=1; break;
      }
      destx = destX[i];desty = destY[i];
//System.out.println("robot " + i + " at: " + x + " " + y + " going to " + destX[i] + " " + destY[i]);
      return goToDest(x,y,destx,desty);
    }
    //shouldn't be here...
    return '0';
  }

  /* checks if moving to the given direction from [x, y] is valid */
  public int validMoveDir(int x, int y, int dir) throws Exception {
    switch (dir) {
    case  _EAST: return validMove(x + 1, y);
    case  _WEST: return validMove(x - 1, y);
    case _SOUTH: return validMove(x, y + 1);
    case _NORTH: return validMove(x, y - 1);
    default: return 1;
    }
  }

  /* checks if moving to [x, y] is valid; returns _CFILLED (-1) if the
   * position is already filled with black paint, returns 0 if it's
   * out of range, and returns 1 if it's ok
   */
  public int validMove(int x, int y) throws Exception {
    int[][] col = rectangles.colors();
    if (((x >= 0) && (x <= size-1)) && ((y >= 0) && (y <= size-1))) {
      if (col[x][y] == _CFILLED)
	return _CFILLED;
      else
	return 1;
    }
    else
      return 0;
  }

  /* returns a random direction */
  public int randomDirection() {
    int dir = random.nextInt(4);
    switch (dir) {
    case 0: return _EAST;
    case 1: return _WEST;
    case 2: return _SOUTH;
    case 3: return _NORTH;
    default: return _SOUTH;
    }
  }

  /* returns the 'char' of the given direction */
  public char dirChar(int dir) {
    switch (dir) {
    case  _EAST: return 'E';
    case  _WEST: return 'W';
    case _SOUTH: return 'S';
    case _NORTH: return 'N';
    case _CSTAY: return 'Y';
    default: return 'S';
    }
  }

  /* inverse function of dirChar */
  public int charDir(char ch) {
    switch (ch) {
    case 'E': return _EAST;
    case 'W': return _WEST;
    case 'S': return _SOUTH;
    case 'N': return _NORTH;
    case 'Y': return _CSTAY;
    default: return _CSTAY;
    }
  }

  /* returns the next direction in grid walking */
  public int nextDirection(int dir) {
    switch (dir) {
      case  _EAST: return _SOUTH;
      case  _WEST: return _NORTH;
      case _SOUTH: return _WEST;
      case _NORTH: return _EAST;
    default: return _EAST;
    }
  }
  /* returns the previous direction in grid walking */
  public int prevDirection(int dir) {
  switch (dir) {
    case  _EAST: return _NORTH;
    case  _WEST: return _SOUTH;
    case _SOUTH: return _EAST;
    case _NORTH: return _WEST;
  default: return _EAST;
  }
}


  /* determine if the given direction (_NORTH, _SOUTH, ...) of [x, y]
   * is filled or not
   */
  public boolean filled(int x, int y, int direction) throws Exception {
    int[][] colors = rectangles.colors();

    switch (direction) {
    case _EAST:
      return (x + 1 < size) ? (colors[x + 1][y] == _CFILLED) : false;
    case _WEST:
      return (x - 1 >= 0) ? (colors[x - 1][y] == _CFILLED) : false;
    case _SOUTH:
      return (y + 1 < size) ? (colors[x][y + 1] == _CFILLED) : false;
    case _NORTH:
      return (y - 1 >= 0) ? (colors[x][y - 1] == _CFILLED) : false;
    default:
      return true;
    }
  }

  /* Manhattan distance between two points */
  public int distance(int x, int y, int dx, int dy) {
    return Math.abs(x - dx) + Math.abs(y - dy);
  }

  public char goToDest(int x, int y, int destx, int desty)  throws Exception{
    char move = 'Y';
    if (x > destx) /* destx <-- x */
      move = 'W';
    else if (x < destx) /* x --> destx */
      move = 'E';
    else if (x == destx) {
      /* now move along y-axis */
      if (y > desty) /* desty --> y */
        move = 'N';
      else if (desty > y)
        move = 'S';
      else if (y == desty) {
        move = 'Y';
      }
    }
    if(validMoveDir(x,y,charDir(move))!=0)
       return move;
    else
      return 'Y';

  }
  public void emptyRecSort(Vector vER){
    int i,j;
    emptyRec a,b;
    //bubble sort again
    for(i=vER.size()-1;i>0;i--)
       for(j=0;j<i;j++){
         a=(emptyRec)vER.elementAt(j);
         b=(emptyRec)vER.elementAt(j+1);
//took out sort by size
//         if (a.size < b.size) {
//added sort by distance
         if(a.closestAvailableDistance > b.closestAvailableDistance){
           vER.removeElementAt(j+1);
           vER.removeElementAt(j);
           vER.add(j,b);
           vER.add(j+1,a);
         }
       }
//     for(i=0;i<vER.size();i++)
//       System.out.print(((emptyRec)vER.elementAt(i)).size + " " );
  }
  int getMaxX(int tX,int tY) throws Exception{
    int tx2;
    for (tx2 = tX; tx2 < size && (rectangles.colors()[tx2][tY] != _CFILLED); tx2++)
      ;
    tx2--; //to fix the extra one incounting : endbound=tx2
    return tx2;
  }
  boolean checkBorders(int tx, int tx2, int ty) throws Exception{
//    System.out.print("cb:"+tx+","+tx2+","+ty+" ");
    return rectangles.colors()[tx][ty] != _CFILLED &&
        rectangles.colors()[tx2][ty] != _CFILLED;
  }

  boolean allEmpty(int tx, int tx2, int ty) throws Exception {
//    System.out.print("ae:"+tx+","+tx2+","+ty+" ");
    for (int t = tx; t <= tx2; t++)
      if (rectangles.colors()[t][ty] == _CFILLED) {
        return false;
      }
    return true;
  }

  int getRecSize(int tx, int ty, int w, int h) throws Exception {
//      System.out.print("r:"+tx+","+ty+","+w+" "+","+h+" ");
    if (w < 3 || h < 3)
      return 0;

    int i, j, cnt = 0;
    //count inside boxes....
    for (i = tx+1; i <= (tx + w - 2 < size ? tx + w - 2 : 0); i++)
      for (j = ty+1; j <= (ty + h - 2 < size ? ty + h - 2 : 0); j++)
        if (rectangles.colors()[i][j] != _CFILLED)
          cnt++;
    return cnt;
  }

  void findEmptyRecs() throws Exception {
    /*find empty Recs*/
    int[][] colors = rectangles.colors();
    int[] maxY = new int[size];
    for (int i = 0; i < size; i++)
      maxY[i] = -1;

    emptyRecs.clear();
    int tX, tY;
    int rX, rY;
    int rW, rH;
    for (tY = 0; tY < size; tY++) { //size
      for (tX = 0; tX < size; tX++) {
//        System.out.print("["+tX+","+tY+"]");
        if (colors[tX][tY] != _CFILLED) {
          //loop through existing roobts, make sure none are looking for this rec
          boolean skip=false;
          for(int j=0;j<numRobots;j++)
            if(method[j]==4){//if on a mission
              emptyRec ER = AsignedEmptyRecs[j];
              if(ER.topLeftX==tX&&ER.topLeftY==tY){
                for (int tx5 = ER.topLeftX; tx5 <= ER.topLeftX + ER.width - 1; tx5++)
                  maxY[tx5] = ER.topLeftY + ER.height - 2;
                tX = ER.topLeftX + ER.width- 2;
                skip=true;
              }
            }
          if (tY > maxY[tX]&&!skip) {
            boolean looking = true;
            int tx2 = 0, tx3 = 0, endX = 0;
            int ty2 = 0, ty3 = 0, endY = 0;
            //see how far you can go to the right,first line
            tx2 = getMaxX(tX, tY);
            if (tx2 - tX + 1 > this.maxEmptySize) //mazimum width of 10
              tx2 = tX + this.maxEmptySize-1;

              //tx2 contains the maximum size...
            for (tx3 = (tx2 - tX) + 1; tx3 >= 3 && ty3 == 0; tx3--) { //loop over all possible widths, start with max...
//              System.out.print("Tw:"+tx3+" ");
              boolean bordersOK;
              for (ty2 = tY + 1, bordersOK = true;
                   bordersOK && ty2 < size && (ty2 - tY) + 1 <= this.maxEmptySize; ty2++) { //max height of 10
//                System.out.print("Ty2:"+ty2+" ");
                bordersOK = checkBorders(tX, tX + tx3 - 1, ty2); //checkif borders are ok
                if (allEmpty(tX, tX + tx3 - 1, ty2))
                  ty3 = ty2;
              }
            }
            tx3++;
//System.out.print(".");
            emptyRec e = new emptyRec(numRobots);
            e.topLeftX = tX;
            e.topLeftY = tY;
            e.width = (tx3);
            e.height = (ty3 - tY) + 1;
            e.size = getRecSize(e.topLeftX, e.topLeftY, e.width, e.height);
//System.out.print(e.size);
            if (e.width >= 3 && e.height >= 3 && e.size > 0) {
              e.getCloseRobots(robots);
              emptyRecs.add(e);
/*              System.out.println("FOund a box at " + e.topLeftX + "]" + "["
                                 + e.topLeftY + "] " + e.width + "X" + e.height +
                                 "size: " + e.size);
 */
//              System.out.println("Added");
              int heightToUse = e.height;
              int widthToUse = e.width;
              //include only normal sized boxes
              /*              if(>8)
                          heightToUse=(heightToUse>16?8:heightToUse/2);
                        if(widthToUse>8)
                          widthToUse=(widthToUse>16?8:widthToUse/2);
               */
//              System.out.println("setting maxy to:" + (e.topLeftY + heightToUse-1) );
              for (tx2 = e.topLeftX; tx2 <= e.topLeftX + e.width - 1; tx2++)
                maxY[tx2] = e.topLeftY + heightToUse - 2;
              tX = e.topLeftX + widthToUse - 2; //resume search from end...
            }
          }
        }
      }
    }
    emptyRecSort(emptyRecs);
    //System.out.println(emptyRecs.size() + " Sorted Rectangles Found..");

  }

//anti-chasing algorithm taken from Group1 and Group3.

//from Group 3
		public char getLastMove(Robot robot) throws Exception {
			MoveResult[] history = rectangles.history();
			MoveResult last = history[history.length - 1];
			return last.moves()[robot.playerIndex()][robot.ID()];
		}

		public boolean isBeingChased(int myRobot) throws Exception {
			Robot closestEnemyBot = closestEnemyRobot(myRobot);
			int dist = distance(closestEnemyBot.xpos(), closestEnemyBot.ypos(), robots[myRobot].xpos(), robots[myRobot].ypos());
			if (robotsEqual(closestEnemyBot, closestEnemy[myRobot])) {
				if(getLastMove(robots[myRobot]) == getLastMove(closestEnemyBot))
				{
					//maybe the robot has chased someone else
					boolean another = false;
					for(int i = 0; i < numRobots; i++)
					{
						//the enemy robot is on the same spot as one of my robots
						if(closestEnemyBot.xpos() == robots[i].xpos() && closestEnemyBot.ypos() == robots[i].ypos())
						{
							//now find out which one
							if(i == myRobot) //the robot is on my spot. I need to stop.
							{
								another = false;
								break;
							}
							another = true;	//the robot is on one of my teammate's spots
						}
					}
					if (!another)
					{
						movesFollowed[myRobot]++;
					}
					else	//the robot is chasing someone else
					  movesFollowed[myRobot] = 0;
				}
			} else {
				movesFollowed[myRobot] = 0;
			}

			closestEnemy[myRobot] = closestEnemyBot;
			if (movesFollowed[myRobot] >= 5 &&
					dist <= 2) {
				return true;
			}

			return false;
		}

		private boolean robotsEqual(Robot r1, Robot r2) throws Exception {
			if (r1 == null) {
				return (r2 == null);
			}

			if (r2 == null) {
				return false;
			}

			return (r1.playerIndex() == r2.playerIndex() && r1.ID() == r2.ID());
		}

		/**
		 * Routine for determining the closest enemy robot was taken from
		 * OldGroup5Robot.java and refactored to save time.
		 */
		private Robot closestEnemyRobot(int myRobot) throws Exception {
			Robot[][] allRobots = rectangles.allRobots();
			int closest = Integer.MAX_VALUE;
			Robot closestRobot = null;

			for (int i = 0; i < allRobots.length; i++) {
				if (i == rectangles.indexOf(this) ) {
					continue;
				}

				for (int j = 0; j < allRobots[i].length; j++) {
					Robot enemyRobot = allRobots[i][j];
					int dist = distance(robots[myRobot].xpos(), robots[myRobot].ypos(), enemyRobot.xpos(), enemyRobot.ypos());
					if (dist < closest) {
						closest = dist;
						closestRobot = enemyRobot;
					}
				}
			}

			return closestRobot;
		}
}
