package team046;

import battlecode.common.*;

import java.util.List;
import java.util.ArrayList;

public class RobotPlayer {

    private static RobotController rc;
    private static int round;
    private static double power;
    private static int zergRushChannel = randomWithRange(0, GameConstants.BROADCAST_MAX_CHANNELS);
    private static int supplierBuilderChannel = randomWithRange(0, GameConstants.BROADCAST_MAX_CHANNELS);

	public static void run(RobotController MyJohn12LongRC) {
        rc = MyJohn12LongRC;

		while (true) {
            try {
                round = Clock.getRoundNum();
                power = rc.getTeamPower();

				if (rc.getType() == RobotType.HQ) {
					HQ();
				}
                else if (rc.getType() == RobotType.SOLDIER) {
                    Soldier();
				}

				rc.yield();
			}
            catch (Exception e) {
				e.printStackTrace();
                break;
			}
		}
	}

    private static void HQ() throws GameActionException {
        if (rc.isActive()) {
            if (rc.senseEnemyNukeHalfDone()) {
                rc.broadcast(zergRushChannel, 1);
            }
            else if (round > 250  && !rc.hasUpgrade(Upgrade.FUSION)) {
                rc.researchUpgrade(Upgrade.FUSION);
                return;
            }
            else if (round > 500  && !rc.hasUpgrade(Upgrade.DEFUSION)) {
                rc.researchUpgrade(Upgrade.DEFUSION);
                return;
            }

            // Find an available spawn direction
            MapLocation hqLocation = rc.senseHQLocation();
            MapLocation nextLoc;
            for (Direction dir : Direction.values()) {
                if (dir != Direction.NONE && dir != Direction.OMNI && rc.canMove(dir)) {
                    nextLoc = hqLocation.add(dir);
                    if (rc.senseMine(nextLoc) == null) {
                        rc.spawn(dir);
                        break;
                    }
                }
            }
        }
    }

    private static void Soldier() throws GameActionException {
        if (rc.isActive()) {
            int supplierBuilderRobotID;
            MapLocation rLoc = rc.getLocation();
            MapLocation targetLoc = null;

            // Get the supplier builder robot ID (or zero)
            if (power > GameConstants.BROADCAST_READ_COST) {
                supplierBuilderRobotID = rc.readBroadcast(supplierBuilderChannel);
                power -= GameConstants.BROADCAST_READ_COST;
            }
            else {
                supplierBuilderRobotID = -1;
            }
            if (supplierBuilderRobotID == 0) {
                rc.broadcast(supplierBuilderChannel, rc.getRobot().getID());
                supplierBuilderRobotID = rc.getRobot().getID();
            }

            // Check for zerg command
            if (power > GameConstants.BROADCAST_READ_COST && rc.readBroadcast(zergRushChannel) == 1) {
                targetLoc = rc.senseEnemyHQLocation();
                power -= GameConstants.BROADCAST_READ_COST;
            }
            // Handle supplier builder robot (including movement)
            else if (supplierBuilderRobotID == rc.getRobot().getID()) {
                BuildSupplier(rLoc);
                return;
            }
            else {
                // Get scared
                Robot[] nearbyEnemies = rc.senseNearbyGameObjects(Robot.class, 3, rc.getTeam().opponent());
                if (nearbyEnemies.length > 0) {
                    return;
                }
            }

            // Set rally point
            if (targetLoc == null) {
                MapLocation goodHQ = rc.senseHQLocation();
                if (goodHQ.x <= 1) {
                    targetLoc = new MapLocation(goodHQ.x + 3, goodHQ.y + 3);
                }
                else if (goodHQ.x >= rc.getMapWidth() - 1) {
                    targetLoc = new MapLocation(goodHQ.x - 3, goodHQ.y - 3);
                }
                else {
                    List<MapLocation> rallyPoints = new ArrayList<>();
                    rallyPoints.add(new MapLocation(goodHQ.x + randomWithRange(0,1), goodHQ.y + randomWithRange(0,1)));
                    rallyPoints.add(new MapLocation(goodHQ.x - randomWithRange(0,1), goodHQ.y - randomWithRange(0,1)));
                    targetLoc = rallyPoints.get(randomWithRange(0, rallyPoints.size() - 1));
                }
            }

            MoveRobot(rLoc, targetLoc);
        }
    }

    private static void MoveRobot(MapLocation rLoc, MapLocation targetLoc) throws GameActionException {
        Direction dir = rLoc.directionTo(targetLoc);
        if (dir == Direction.NONE) {
            return;
        }
        else if (dir == Direction.OMNI) {
            dir = Direction.EAST;
        }
        while (!rc.canMove(dir)) {
            dir = dir.rotateRight();
        }

        MapLocation nextLoc = rLoc.add(dir);

        if (rc.senseMine(nextLoc) != null) {
            rc.defuseMine(nextLoc);
        }
        else {
            rc.move(dir);
        }
    }

    private static void BuildSupplier(MapLocation rLoc) throws GameActionException {
        if (rc.senseEncampmentSquare(rLoc)) {
            rc.captureEncampment(RobotType.SUPPLIER);
        }
        else {
            MapLocation encampmentSquares[] = rc.senseAllEncampmentSquares();
            MapLocation targetLoc = encampmentSquares[0];
            int closest = 1000;

            for (MapLocation loc: encampmentSquares) {
                int dist = rLoc.distanceSquaredTo(loc);
                if (dist < closest) {
                    targetLoc = loc;
                    closest = dist;
                }
            }

            MoveRobot(rLoc, targetLoc);
        }
    }

    private static int randomWithRange(int min, int max) {
        int range = Math.abs(max - min) + 1;
        return (int)(Math.random() * range) + (min <= max ? min : max);
    }
}

@@ -44,60 +44,8 @@
 *;%0A%0A
-import java.util.List;%0Aimport java.util.ArrayList;%0A%0A
 publ
@@ -3909,21 +3909,16 @@
         
-List%3C
 MapLocat
@@ -3920,17 +3920,16 @@
 Location
-%3E
  rallyPo
@@ -3936,29 +3936,14 @@
 ints
+%5B%5D
  = 
-new ArrayList%3C%3E();
+%7B
 %0A   
@@ -3959,32 +3959,20 @@
         
-rallyPoints.add(
+    
 new MapL
@@ -4036,34 +4036,33 @@
 mWithRange(0,1))
-);
+,
 %0A               
@@ -4070,24 +4070,12 @@
     
-rallyPoints.add(
+    
 new 
@@ -4151,17 +4151,38 @@
 ge(0,1))
-)
+%0A                    %7D
 ;%0A      
@@ -4222,13 +4222,9 @@
 ints
-.get(
+%5B
 rand
@@ -4254,20 +4254,20 @@
 nts.
-size()
+length
  - 1)
-)
+%5D
 ;%0A  

VERSION 0.6.1 (no imports allowed!)