private static void archonMicro(RobotController rc, RobotInfo enemyArchon)
      throws GameActionException {
    if (rc.isCoreReady()) {
      int dist = myLoc.distanceSquaredTo(enemyArchon.location);
      // When not adjacent to the archon, walk/mine through to him.
      if (dist > 2) {
        Direction desired = myLoc.directionTo(enemyArchon.location);
        Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
        if (dir != Direction.NONE) {
          rc.move(dir);
        } else if (shouldMine(rc, desired)) {
          rc.clearRubble(desired);
        } else if (shouldMine(rc, desired.rotateLeft())) {
          rc.clearRubble(desired.rotateLeft());
        } else if (shouldMine(rc, desired.rotateRight())) {
          rc.clearRubble(desired.rotateRight());
        }
      }
      // When adjacent to archon, rotate to the left/right when possible.
      else {
        Direction dir = myLoc.directionTo(enemyArchon.location);
        if (rc.canMove(dir.rotateLeft())) {
          rc.move(dir.rotateLeft());
        } else if (rc.canMove(dir.rotateRight())) {
          rc.move(dir.rotateRight());
        }
      }
    }

    if (rc.isWeaponReady()) {
      if (rc.canAttackLocation(enemyArchon.location)) {
        rc.attackLocation(enemyArchon.location);
      }
    }
  }
  private static void rushMicro(RobotController rc, RobotInfo[] hostiles)
      throws GameActionException {
    // Prioritizes attacking turrets.
    RobotInfo bestEnemy = null;
    boolean canAttackBestEnemy = false;
    int bestEnemyDist = 10000; // only care if can't hit
    for (RobotInfo hostile : hostiles) {
      // Can attack this enemy.
      int dist = myLoc.distanceSquaredTo(hostile.location);
      // Summary:
      // Prioritizes enemies over zombies.
      // Prioritizes turret enemies over other enemies.
      // Prioritizes lowest health enemy last
      if (dist <= attackRadius) {
        if (bestEnemy != null) {
          if (bestEnemy.team == enemyTeam) { // best is already enemy
            if (hostile.team == enemyTeam) { // found an enemy
              if (countsAsTurret(bestEnemy.type)) {
                if (countsAsTurret(hostile.type)) {
                  // Take lowest health
                  if (bestEnemy.health > hostile.health) bestEnemy = hostile;
                }
              } else {
                if (countsAsTurret(hostile.type)) {
                  bestEnemy = hostile;
                } else {
                  // Take lowest health
                  if (bestEnemy.health > hostile.health) bestEnemy = hostile;
                }
              }
            }
          } else { // best is not an enemy!
            if (hostile.team == enemyTeam) { // found an enemy
              bestEnemy = hostile;
            } else {
              // Take lowest health
              if (bestEnemy.health > hostile.health) bestEnemy = hostile;
            }
          }
        } else {
          bestEnemy = hostile;
        }
        canAttackBestEnemy = true;
      } else {
        // Only update best enemy if you can't attack best enemy
        if (!canAttackBestEnemy) {
          if (bestEnemy != null) {
            // Pick the closest one
            if (bestEnemyDist > dist) {
              bestEnemyDist = dist;
              bestEnemy = hostile;
            }
          } else {
            bestEnemyDist = dist;
            bestEnemy = hostile;
          }
        }
      }
    }
    rc.setIndicatorString(0, "Round: " + rc.getRoundNum() + ", Best enemy: " + bestEnemy);
    if (rc.isCoreReady()) {
      // If there is a best enemy, attack him.
      if (bestEnemy != null) {
        // Move closer only if blocking someone.
        if (rc.canAttackLocation(bestEnemy.location)) {
          if (isBlockingSomeone(rc, bestEnemy.location)) {
            Direction desired = myLoc.directionTo(bestEnemy.location);
            Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
            if (dir != Direction.NONE) {
              rc.move(dir);
            } else if (shouldMine(rc, desired)) {
              rc.clearRubble(desired);
            } else if (shouldMine(rc, desired.rotateLeft())) {
              rc.clearRubble(desired.rotateLeft());
            } else if (shouldMine(rc, desired.rotateRight())) {
              rc.clearRubble(desired.rotateRight());
            }
          }
        }
        // If can't attack it, move closer!
        else {
          Direction desired = myLoc.directionTo(bestEnemy.location);
          Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
          if (dir != Direction.NONE) {
            rc.move(dir);
          } else if (shouldMine(rc, desired)) {
            rc.clearRubble(desired);
          } else if (shouldMine(rc, desired.rotateLeft())) {
            rc.clearRubble(dir.rotateLeft());
          } else if (shouldMine(rc, desired.rotateRight())) {
            rc.clearRubble(desired.rotateRight());
          }
        }
      }
      // Otherwise move closer to destination
      else {
        if (currentDestination != null) {
          RobotInfo info = null;
          if (rc.canSenseLocation(currentDestination)) {
            info = rc.senseRobotAtLocation(currentDestination);
          }
          if (info != null) {
            // If can attack it, just only move closer if blocking someone behind.
            if (rc.canAttackLocation(info.location)) {
              if (isBlockingSomeone(rc, currentDestination)) {
                Direction desired = myLoc.directionTo(currentDestination);
                Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
                if (dir != Direction.NONE) {
                  rc.move(dir);
                } else if (shouldMine(rc, desired)) {
                  rc.clearRubble(desired);
                } else if (shouldMine(rc, desired.rotateLeft())) {
                  rc.clearRubble(desired.rotateLeft());
                } else if (shouldMine(rc, desired.rotateRight())) {
                  rc.clearRubble(desired.rotateRight());
                }
              }
            }
            // If can't attack it, move closer!
            else {
              Direction desired = myLoc.directionTo(currentDestination);
              Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
              if (dir != Direction.NONE) {
                rc.move(dir);
              } else if (shouldMine(rc, desired)) {
                rc.clearRubble(desired);
              } else if (shouldMine(rc, desired.rotateLeft())) {
                rc.clearRubble(desired.rotateLeft());
              } else if (shouldMine(rc, desired.rotateRight())) {
                rc.clearRubble(desired.rotateRight());
              }
            }
          }
          // If not there, just move closer.
          else {
            Direction desired = myLoc.directionTo(currentDestination);
            Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
            if (dir != Direction.NONE) {
              rc.move(dir);
            } else if (shouldMine(rc, desired)) {
              rc.clearRubble(desired);
            } else if (shouldMine(rc, desired.rotateLeft())) {
              rc.clearRubble(desired.rotateLeft());
            } else if (shouldMine(rc, desired.rotateRight())) {
              rc.clearRubble(desired.rotateRight());
            }
          }
        }
      }
    }

    // Attack whenever you can.
    if (bestEnemy != null) {
      if (rc.isWeaponReady()) {
        if (rc.canAttackLocation(bestEnemy.location)) {
          broadcastingAttack(rc, bestEnemy);
        }
      }
    }
  }
  public static void zombieMicro(RobotController rc) throws GameActionException {
    boolean thereIsNonKitableZombie = false;
    RobotInfo closestEnemy = null;
    int closestDist = 10000;
    for (RobotInfo hostile : nearbyEnemies) {
      if (hostile.type == RobotType.FASTZOMBIE || hostile.type == RobotType.RANGEDZOMBIE) {
        thereIsNonKitableZombie = true;
      }
      int dist = myLoc.distanceSquaredTo(hostile.location);
      if (dist < closestDist) {
        closestDist = dist;
        closestEnemy = hostile;
      }
    }

    Direction d = myLoc.directionTo(closestEnemy.location);
    // if we're too close, move further away
    if (myLoc.distanceSquaredTo(closestEnemy.location) < 5 && rc.isCoreReady()) {
      Direction desired = d.opposite();
      Direction dir = Movement.getBestMoveableDirection(desired, rc, 1);
      if (dir != Direction.NONE) {
        rc.move(dir);
      } else if (shouldMine(rc, desired)) {
        rc.clearRubble(desired);
      } else if (shouldMine(rc, desired.rotateLeft())) {
        rc.clearRubble(desired.rotateLeft());
      } else if (shouldMine(rc, desired.rotateRight())) {
        rc.clearRubble(desired.rotateRight());
      }
    }
    if (!thereIsNonKitableZombie) {
      // Only move in closer if there is no non-kitable zombie
      if (myLoc.distanceSquaredTo(closestEnemy.location) > attackRadius
          && rc.isCoreReady()) { // if we are too far, we want to move closer
        // Desired direction is d.
        Direction dir = Movement.getBestMoveableDirection(d, rc, 1);
        if (dir != Direction.NONE) {
          rc.move(dir);
        } else if (shouldMine(rc, d)) {
          rc.clearRubble(d);
        } else if (shouldMine(rc, d.rotateLeft())) {
          rc.clearRubble(d.rotateLeft());
        } else if (shouldMine(rc, d.rotateRight())) {
          rc.clearRubble(d.rotateRight());
        } else { // probably meaning you are blocked by allies
          if (closestEnemy.type == RobotType.ZOMBIEDEN) {
            // It is likely that we wanted to go to that den, but possibly coincidence
            // If not a coincidence, bug there.
            if (bugging != null) {
              if (bugging.destination.equals(closestEnemy.location)) {
                bugging.turretAvoidMove(turretLocations);
                // If coincidence, set new bugging.
              } else {
                bugging = new Bugging(rc, closestEnemy.location);
                bugging.turretAvoidMove(turretLocations);
              }
            } else {
              bugging = new Bugging(rc, closestEnemy.location);
              bugging.turretAvoidMove(turretLocations);
            }
          }
        }
      }
    }
    if (rc.isWeaponReady() && rc.canAttackLocation(closestEnemy.location)) {
      broadcastingAttack(rc, closestEnemy);
    }
  }
  public static void run(RobotController rc) {
    sightRadius = RobotType.SOLDIER.sensorRadiusSquared;
    attackRadius = RobotType.SOLDIER.attackRadiusSquared;
    myTeam = rc.getTeam();
    enemyTeam = myTeam.opponent();
    while (true) {
      try {
        numEnemySoldiers = 0;
        totalEnemySoldierHealth = 0;
        myLoc = rc.getLocation();
        nearbyAllies = rc.senseNearbyRobots(sightRadius, myTeam);
        nearbyEnemies = rc.senseHostileRobots(myLoc, sightRadius);
        newArchonLoc = null;

        // clear bad locations
        resetLocations(rc);
        // read messages and get destination
        readMessages(rc);
        // heal if need (and set the archon destination to go to)
        setRetreatingStatus(rc, nearbyEnemies);

        // Remove turret locations that you can see are not there.
        // Does NOT remove turret locations due to broadcasts. Already done in read messages.
        removeTurretLocations(rc);

        if (newArchonLoc != null) {
          nearestArchonLocation = newArchonLoc;
        }

        rc.setIndicatorString(2, "Round: " + rc.getRoundNum() + ", rushing: " + rush);
        // Reset rushing if turns since rush is > 20 and see no more enemies.
        if (rush && myLoc.distanceSquaredTo(rushLocation) <= 100) turnsSinceRush++;
        if (turnsSinceRush > 20) {
          if (rc.senseNearbyRobots(sightRadius, enemyTeam).length == 0) {
            turnsSinceRush = 0;
            rush = false;
          }
        }

        // When rushing, be mad aggressive.
        if (rush) {
          rushMicro(rc, nearbyEnemies);
        }
        // When retreating, retreat
        else if (healing) {
          if (rc.isCoreReady()) {
            if (nearestArchonLocation != null) {
              if (myLoc.distanceSquaredTo(nearestArchonLocation) > 13) {
                bugging.enemyAvoidMove(nearbyEnemies);
                // Get away from archons that are not too close together.
              } else if (myLoc.distanceSquaredTo(nearestArchonLocation) <= 2) {
                Direction radialDir = nearestArchonLocation.directionTo(myLoc);
                Direction awayDir = Movement.getBestMoveableDirection(radialDir, rc, 2);
                if (awayDir != Direction.NONE) {
                  rc.move(awayDir);
                }
              }
            }
          }
          // Make sure to attack people even when retreating.
          // Prioritize the closest enemy. Then the closest zombie.
          if (rc.isWeaponReady()) {
            // Attack the closest enemy. If there is not one, then attack the closest zombie
            int closestDist = 10000;
            RobotInfo target = null;
            for (RobotInfo hostile : nearbyEnemies) {
              int dist = myLoc.distanceSquaredTo(hostile.location);
              if (rc.canAttackLocation(hostile.location)) {
                // There is already is a target
                if (target != null) {
                  if (target.team == enemyTeam) {
                    // Target is already enemy, so prioritize the closest
                    if (hostile.team == enemyTeam) {
                      if (dist < closestDist) {
                        target = hostile;
                        closestDist = dist;
                      }
                    } // If hostile is not an enemy, not worth considering.
                  } else {
                    // Target is not on enemy team, so hostile is best choice!
                    if (hostile.team == enemyTeam) {
                      target = hostile;
                      closestDist = dist;
                      // Both are zombies, so just pick the closest.
                    } else {
                      if (dist < closestDist) {
                        target = hostile;
                        closestDist = dist;
                      }
                    }
                  }
                  // Set a target when there is not one.
                } else {
                  target = hostile;
                  closestDist = dist;
                }
              }
            }
            // We know that if there is a target, we can attack it.
            if (target != null) {
              rc.attackLocation(target.location);
            }
          }
        }

        // When viper infected and will die from the infection, do special micro
        else if (isViperInfected(rc)
            && (rc.getHealth() < rc.getViperInfectedTurns() * 2 || rc.getRoundNum() > 2100)) {
          viperInfectedMicro(rc);
        }

        // if there are enemies in range, we should focus on attack and micro
        else if (nearbyEnemies.length > 0) {
          if (shouldLure(rc, nearbyEnemies, nearbyAllies)) luringMicro(rc);
          else micro(rc);
        } else { // otherwise, we should always be moving somewhere
          moveSoldier(rc);
        }

        Clock.yield();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  // special micro if a unit is infected by a viper
  private static void viperInfectedMicro(RobotController rc) throws GameActionException {
    // If there are enemies, consider moving closer to them then to us.
    RobotInfo closestEnemy = null;
    int enemyDist = 10000;
    RobotInfo[] enemies = rc.senseNearbyRobots(sightRadius, enemyTeam);
    for (RobotInfo enemy : enemies) {
      int dist = myLoc.distanceSquaredTo(enemy.location);
      if (dist < enemyDist) {
        closestEnemy = enemy;
        enemyDist = dist;
      }
    }

    RobotInfo closestAlly = null;
    int allyDist = 10000;
    for (RobotInfo ally : nearbyAllies) {
      int dist = myLoc.distanceSquaredTo(ally.location);
      if (dist < allyDist) {
        closestAlly = ally;
        allyDist = dist;
      }
    }

    if (rc.getRoundNum() > 2100) {
      // Move toward s enemy
      if (closestEnemy != null) {
        if (rc.isCoreReady()) {
          Direction dir =
              Movement.getBestMoveableDirection(myLoc.directionTo(closestEnemy.location), rc, 2);
          if (dir != Direction.NONE) {
            rc.move(dir);
          }
        }
      }
      // Move away from allies.
      if (closestAlly != null) {
        if (rc.isCoreReady()) {
          Direction dir =
              Movement.getBestMoveableDirection(closestAlly.location.directionTo(myLoc), rc, 2);
          if (dir != Direction.NONE) {
            rc.move(dir);
          }
        }
      }
    } else if (rc.getHealth() < 2 * rc.getViperInfectedTurns()) {
      if (closestEnemy != null && closestAlly != null) {
        if (rc.isCoreReady()) {
          // When enemy is further than (or same dist) as ally, move closer to enemy.
          if (enemyDist >= allyDist) {
            Direction dir =
                Movement.getBestMoveableDirection(myLoc.directionTo(closestEnemy.location), rc, 1);
            // Move closer to enemy obviously
            if (dir != Direction.NONE) {
              rc.move(dir);
            }
            // If you could not move, see if you can attack the enemy and attack him.
            else {
              if (rc.isWeaponReady()) {
                if (rc.canAttackLocation(closestEnemy.location)) {
                  broadcastingAttack(rc, closestEnemy);
                }
              }
            }
          }
          // If closer to the enemy, then just attack them if possible. Otherwise move closer.
          else {
            if (rc.isCoreReady()) {
              if (!rc.canAttackLocation(closestEnemy.location)) {
                Direction dir =
                    Movement.getBestMoveableDirection(
                        myLoc.directionTo(closestEnemy.location), rc, 2);
                if (dir != Direction.NONE) {
                  rc.move(dir);
                }
              }
            }
            if (rc.isWeaponReady()) {
              if (rc.canAttackLocation(closestEnemy.location)) {
                broadcastingAttack(rc, closestEnemy);
              }
            }
          }
        }
      } else if (closestEnemy != null) {
        // Move closer if can't hit closest. Otherwise attack closest.
        if (rc.isCoreReady()) {
          if (!rc.canAttackLocation(closestEnemy.location)) {
            Direction dir =
                Movement.getBestMoveableDirection(myLoc.directionTo(closestEnemy.location), rc, 2);
            if (dir != Direction.NONE) {
              rc.move(dir);
            }
          }
        }
        if (rc.isWeaponReady()) {
          if (rc.canAttackLocation(closestEnemy.location)) {
            broadcastingAttack(rc, closestEnemy);
          }
        }
      }
      // Get the hell away from ally!
      else if (closestAlly != null) {
        if (rc.isCoreReady()) {
          Direction dir =
              Movement.getBestMoveableDirection(closestAlly.location.directionTo(myLoc), rc, 2);
          if (dir != Direction.NONE) {
            rc.move(dir);
          }
        }
      }
    }
  }
  private static void luringMicro(RobotController rc) throws GameActionException {
    boolean thereIsNonKitableZombie = false;
    RobotInfo closestEnemy = null;
    MapLocation closestOpponent = null;
    int closestDist = 10000;
    for (RobotInfo hostile : nearbyEnemies) {
      if (hostile.type == RobotType.FASTZOMBIE || hostile.type == RobotType.RANGEDZOMBIE) {
        thereIsNonKitableZombie = true;
      }
      int dist = myLoc.distanceSquaredTo(hostile.location);
      if (dist < closestDist) {
        closestDist = dist;
        closestEnemy = hostile;
      }
    }

    // try to get the closest place to lure zombie
    for (MapLocation loc : turretLocations) {
      if (closestOpponent == null) closestOpponent = loc;
      else if (myLoc.distanceSquaredTo(loc) < myLoc.distanceSquaredTo(closestOpponent))
        closestOpponent = null;
    }
    if (closestOpponent == null) closestOpponent = nearestEnemyLocation;
    Direction d = null;
    if (closestOpponent != null) d = myLoc.directionTo(closestOpponent);
    else d = myLoc.directionTo(rc.getInitialArchonLocations(enemyTeam)[0]);

    // if we are moving directly into the zombie, try to move to the side
    Direction temp = myLoc.directionTo(closestEnemy.location);
    if (d.equals(temp)) d = d.rotateLeft().rotateLeft();
    else if (d.equals(temp.rotateLeft())) d = d.rotateLeft();
    else if (d.equals(temp.rotateRight())) d = d.rotateRight();

    // if we're too close, move further away towards the closest turret location or the closest
    // enemy
    if (myLoc.distanceSquaredTo(closestEnemy.location) < 10 && rc.isCoreReady()) {
      Direction desired = d;
      Direction dir = Movement.getBestMoveableDirection(desired, rc, 1);
      if (dir != Direction.NONE) {
        rc.move(dir);
      } else if (shouldMine(rc, desired)) {
        rc.clearRubble(desired);
      } else if (shouldMine(rc, desired.rotateLeft())) {
        rc.clearRubble(desired.rotateLeft());
      } else if (shouldMine(rc, desired.rotateRight())) {
        rc.clearRubble(desired.rotateRight());
      }
    }
    if (!thereIsNonKitableZombie) {
      // Only move in closer if there is no non-kitable zombie
      if (myLoc.distanceSquaredTo(closestEnemy.location) > attackRadius
          && rc.isCoreReady()) { // if we are too far, we want to move closer
        // Desired direction is d.
        Direction dir = Movement.getBestMoveableDirection(d, rc, 1);
        if (dir != Direction.NONE) {
          rc.move(dir);
        } else if (shouldMine(rc, d)) {
          rc.clearRubble(d);
        } else if (shouldMine(rc, d.rotateLeft())) {
          rc.clearRubble(d.rotateLeft());
        } else if (shouldMine(rc, d.rotateRight())) {
          rc.clearRubble(d.rotateRight());
        } else { // probably meaning you are blocked by allies
          if (closestEnemy.type == RobotType.ZOMBIEDEN) {
            // It is likely that we wanted to go to that den, but possibly coincidence
            // If not a coincidence, bug there.
            if (bugging != null) {
              if (bugging.destination.equals(closestEnemy.location)) {
                bugging.turretAvoidMove(turretLocations);
                // If coincidence, set new bugging.
              } else {
                bugging = new Bugging(rc, closestOpponent);
                bugging.turretAvoidMove(turretLocations);
              }
            } else {
              bugging = new Bugging(rc, closestOpponent);
              bugging.turretAvoidMove(turretLocations);
            }
          }
        }
      }
    }
    if (rc.isWeaponReady() && rc.canAttackLocation(closestEnemy.location)) {
      broadcastingAttack(rc, closestEnemy);
    }
  }