public static void setRetreatingStatus(RobotController rc, RobotInfo[] hostiles)
     throws GameActionException {
   // Retreating is when your first hit less than a third health or when you were retreating
   // already and is not max health yet.
   // But you should not be retreating if you are infected. That's not a good idea!
   healing =
       (3 * rc.getHealth() < RobotType.SOLDIER.maxHealth
               || (wasHealing && rc.getHealth() < RobotType.SOLDIER.maxHealth))
           && (rc.getHealth() > 2 * rc.getViperInfectedTurns());
   if (!healing) {
     if (wasHealing) bugging = null;
     wasHealing = false;
   }
   if (healing) {
     RobotInfo[] nearbyRobots = rc.senseNearbyRobots(sightRadius, myTeam);
     for (RobotInfo r : nearbyRobots) {
       if (r.type == RobotType.ARCHON) nearestArchonLocation = r.location;
     }
     rc.setIndicatorString(0, "should be retreating " + nearestArchonLocation + rc.getRoundNum());
     if (!wasHealing || !bugging.destination.equals(nearestArchonLocation)) {
       if (nearestArchonLocation == null) {
         bugging = new Bugging(rc, rc.getLocation().add(Direction.EAST));
       } else {
         bugging = new Bugging(rc, nearestArchonLocation);
       }
     }
     wasHealing = true;
   }
 }
  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);
          }
        }
      }
    }
  }
 // check whether this unit is viper infected
 private static boolean isViperInfected(RobotController rc) {
   return rc.getViperInfectedTurns() > 0;
 }