package Rectangles;

import java.util.*;

public class OldGroup5Robot extends Robot implements IFCConstants {
  Vertex dest;
  public char inertia;
  Rectangles rectangles;  
  Random random;
  int me;
  boolean unleashed;
  int board_size;
  int skipped_turns;

  public OldGroup5Robot(int __xpos, int __ypos, Rectangles rectangles, 
                     int me, Random random) 
    throws Exception 
  {
    super (__xpos, __ypos);
    this.rectangles = rectangles;
    this.me = me;
    board_size = rectangles.size();
    this.random = random;
    inertia = _CSTAY;
    unleashed = false;
    dest = null;
    skipped_turns = 0;
  }

  public char move(OldGroup5PlayerU owner) throws Exception {
    int closest = closest();

    if (closest < 4) {
      skipped_turns++;
      
      if (closest == 3 && skipped_turns < 2)
        return _CSTAY;
      
      if (closest == 2 && skipped_turns < 4)
        return _CSTAY;
      
      if (closest == 1 && skipped_turns < 8)
        return _CSTAY;
      
      if (closest == 0 && skipped_turns < 8)
        return _CSTAY;
    }
    
    skipped_turns = 0;

    if (crowded() && random.nextInt (2) == 0)
        return _CSTAY;

    if (unleashed) {
      char dir = wander();
      inertia = dir;
      return dir;
    }

    while(true) {
      if (dest == null) {
        dest = owner.whereNext (_position, this);
      }
      
      int deltaX = dest.xpos() - _position.xpos();
      int deltaY = dest.ypos() - _position.ypos();
      
      int absX = deltaX < 0 ? -deltaX : deltaX;
      int absY = deltaY < 0 ? -deltaY : deltaY;

      if (absX > absY) {
        if (deltaX > 0) {
          inertia = _CEAST;
          return _CEAST;
        }
        else if (deltaX < 0) {
          inertia = _CWEST;
          return _CWEST;
        }
      } else {
        if (deltaY > 0) {
          inertia = _CSOUTH;
          return _CSOUTH;
        }
        else if (deltaY < 0) {
          inertia = _CNORTH;
          return _CNORTH;
        } else {
          dest = null;
        }
      }
    }
  }

  private boolean crowded () throws Exception {
    Robot all[][] = rectangles.allRobots();
    Robot mine[] = all[me];
    int count = 0;

    for (int i = 0; i < mine.length; i++) {
      Robot robot = mine[i];
      if (robot.xpos() == this.xpos() && robot.ypos() == this.ypos())
        count++;
    }

    if (count < 1) throw new Exception ("Huh?");

    return count > 1;
  }

  private int closest () throws Exception {
    int myX = this.xpos();
    int myY = this.ypos();

    Robot all[][] = rectangles.allRobots();
    
    int closest = 4;

    for (int player = 0; player < all.length; player++) {
      if (player == me) continue;
      for (int i = 0; i < all[player].length; i++) {
        Robot robot = all[player][i];
        int theirX = robot.xpos();
        int theirY = robot.ypos();
        
        int deltaX = theirX - myX;
        int deltaY = theirY - myY;

        if (deltaX < 0) deltaX = -deltaX;
        if (deltaY < 0) deltaY = -deltaY;

        if (deltaX <= 3 && deltaY == 0) 
          if (closest > deltaX)
            closest = deltaX;

        if (deltaX == 0 && deltaY <= 3)
          if (closest > deltaY)
            closest = deltaY;
      }
    }
    return closest;
  }

  private char wander() throws Exception {
    int x = this.xpos();
    int y = this.ypos();

    Vector last = new Vector();

    if (x > 0)              last.add (new Vertex (x - 1, y));
    if (x < board_size - 1) last.add (new Vertex (x + 1, y));
    if (y > 0)              last.add (new Vertex (x, y - 1));
    if (y < board_size - 1) last.add (new Vertex (x, y + 1));

    Vector current;
    
    current = eliminateBlack (last);
    if (current.size() == 1) return pickOne (current);
    if (current.size() == 0) current = last;
    last = current;

    current = eliminateBlue (last);
    if (current.size() == 1) return pickOne (current);
    if (current.size() == 0) current = last;
    last = current;

    current = eliminateEnemies (last);
    if (current.size() == 1) return pickOne (current);
    if (current.size() == 0) current = last;
    last = current;

    current = eliminateTurns (last);
    if (current.size() == 1) return pickOne (current);
    if (current.size() == 0) current = last;

    return pickOne (current);
  }

  private Vector eliminateBlack (Vector v) throws Exception {
    Vector out = new Vector ();
    int board[][] = rectangles.colors();
    for (int i = 0; i < v.size(); i++) {
      Vertex ver = (Vertex) v.elementAt (i);
      if (board[ver.xpos()][ver.ypos()] != _CFILLED)
        out.add (ver);
    }
    return out;
  }

  private Vector eliminateBlue (Vector v) throws Exception {
    Vector out = new Vector ();
    int board[][] = rectangles.colors();
    for (int i = 0; i < v.size(); i++) {
      Vertex ver = (Vertex) v.elementAt (i);
      if (board[ver.xpos()][ver.ypos()] != me)
        out.add (ver);
    }
    return out;
  }

  private Vector eliminateEnemies (Vector v) throws Exception {
    Vector out = new Vector ();
    int board[][] = rectangles.colors();
    for (int i = 0; i < v.size(); i++) {
      Vertex ver = (Vertex) v.elementAt (i);
      if (board[ver.xpos()][ver.ypos()] == _CEMPTY ||
          board[ver.xpos()][ver.ypos()] == _CCONTESTED)
        out.add (ver);
    }
    return out;
  }

  private Vector eliminateTurns (Vector v) throws Exception {
    Vector out = new Vector ();
    int board[][] = rectangles.colors();
    for (int i = 0; i < v.size(); i++) {
      Vertex ver = (Vertex) v.elementAt (i);
      if (getDirection (this._position, ver) == inertia)
        out.add (ver);
    }
    return out;
  }

  private char pickOne (Vector v) throws Exception {
    Object o = v.elementAt (random.nextInt(v.size()));
    return getDirection (this._position, (Vertex) o);
  }

  private char getDirection (Vertex here, Vertex there) throws Exception {
    int hereX = here.xpos();
    int hereY = here.ypos();
    int thereX = there.xpos();
    int thereY = there.ypos();

    if (hereX < thereX) return _CEAST;
    if (hereX > thereX) return _CWEST;
    if (hereY < thereY) return _CSOUTH;
    if (hereY > thereY) return _CNORTH;

    throw new Exception ("What?");
  }

}
