public double getBaseValue(PlanetUtility p, Location averageLocation, double variance) {
   double distanceFactor =
       (variance + BASE_DISTANCE_FACTOR)
           / (averageLocation.distance(p.planet) + BASE_DISTANCE_FACTOR);
   return (PlayerUtils.getCurrentEventualOwner(p.planet, fleets, this) == PlanetOwner.NOBODY
           ? 1.0
           : AGGRESSION)
       * Math.pow(distanceFactor, DISTANCE_WEIGHTING)
       / p.planet.PRODUCTION_TIME
       / (unitBaseCost + p.units);
 }
 public double getAggressiveValue(PlanetUtility p, Location averageLocation, double variance) {
   double distanceFactor =
       (variance + BASE_DISTANCE_FACTOR)
           / (averageLocation.distance(p.planet) + BASE_DISTANCE_FACTOR);
   double baseValue =
       (PlayerUtils.getCurrentEventualOwner(p.planet, fleets, this) == PlanetOwner.NOBODY
               ? 1.0
               : AGGRESSION * AGGRESSION_MULTIPLIER)
           * Math.pow(distanceFactor, DISTANCE_WEIGHTING)
           / p.planet.PRODUCTION_TIME
           / (unitBaseCost + p.units);
   // double stratValue = getDefensiveValue(p.planet, baseValue) / getOffensiveValue(p.planet,
   // baseValue);
   return baseValue;
 }
  @Override
  protected void turn() {
    List<Planet> myPlanets = PlayerUtils.getPlanetsOwnedByPlayer(planets, this);
    //      List<Planet> notMyPlanets = PlayerUtils.getPlanetsNotOwnedByPlayer(planets, this);
    //      List<Planet> enemyPlanets = PlayerUtils.getOpponentsPlanets(planets, this);
    //      List<Planet> unownedPlanets = PlayerUtils.getUnoccupiedPlanets(planets);

    int myTotalUnits = PlayerUtils.getMyUnitCount(fleets, planets, this);
    int enemyTotalUnits = PlayerUtils.getOpponentUnitCount(fleets, planets, this);
    int mySpareUnits = 0;
    double myProduction = PlayerUtils.getMyTotalProductionFrequency(planets, this);
    double enemyProduction = PlayerUtils.getEnemyTotalProductionFrequency(planets, this);
    double currentUnitRatio = (myTotalUnits + 0.0001) / (enemyTotalUnits + 0.0001);
    double currentProductionRatio = (myProduction + 0.0001) / (enemyProduction + 0.0001);

    Location averageLocation = Location.center(myPlanets);
    double variance = Location.variance(myPlanets);

    PlayMode mode;
    if (currentUnitRatio > UNIT_ADVANTAGE_RATIO) { // cover more units
      if (currentProductionRatio > PRODUCTION_DISADVANTAGE_RATIO) { // cover more/same production
        mode = PlayMode.CONFIDENT;
      } else { // cover less production
        mode = PlayMode.AGGRESSIVE;
      }
    } else if (currentUnitRatio < UNIT_DISADVANTAGE_RATIO) { // cover less units
      if (currentProductionRatio > PRODUCTION_ADVANTAGE_RATIO) { // cover more production
        mode = PlayMode.DEFENSIVE;
      } else { // cover less/equal production
        mode = PlayMode.DESPARATE;
      }
    } else { // cover same units
      if (currentProductionRatio > PRODUCTION_DISADVANTAGE_RATIO) { // cover more/same production
        mode = PlayMode.NORMAL;
      } else { // cover less production
        mode = PlayMode.DESPARATE;
      }
    }

    // System.out.println("myUnits: " + myTotalUnits + " enemyUnits: " + enemyTotalUnits);
    // System.out.println("unitRatio: " + currentUnitRatio + " prdnRatio: " +
    // currentProductionRatio);
    // System.out.println(mode);

    // aggregate information about planets
    for (int i = 0; i < allPlanetInfo.size(); i++) {
      PlanetUtility temp = allPlanetInfo.get(i);
      temp.units = temp.planet.getNumUnits();
      temp.eventualOwner = PlayerUtils.getCurrentEventualOwner(temp.planet, fleets, this);
      temp.minBaseConquerCost = PlayerUtils.getUnitsToCapture(temp.planet, fleets, this);
      temp.extraUnits =
          temp.units - PlayerUtils.getOpponentsIncomingFleetCount(temp.planet, fleets, this);
      temp.defensiveValue = getDefensiveValue(temp.planet, temp.baseStrategicValue);
      temp.offensiveValue = getOffensiveValue(temp.planet, temp.baseStrategicValue);

      // System.out.println("num: "+i+" own: "+temp.planet.getOwner()+" units: "+temp.units+"
      // evenOwn: "+temp.eventualOwner+" conCost: "+temp.minBaseConquerCost);
    }

    // defense loop
    for (PlanetUtility p : allPlanetInfo) {
      if (p.planet.ownedBy(this) && p.eventualOwner != PlanetOwner.PLAYER) {
        for (PlanetUtility other : allPlanetInfo) {
          if (other.planet.ownedBy(this)
              && other != p
              && other.minBaseConquerCost
                  < 0) { // planet is under no threat itself and not the same one
            // send as many units as required or as many as can be spared if not enough
            int willSend =
                other.extraUnits > p.minBaseConquerCost ? p.minBaseConquerCost : other.extraUnits;
            other.units -= willSend;
            other.extraUnits -= willSend;
            p.minBaseConquerCost -= willSend;
            addAction(other.planet, p.planet, willSend);
          }
        }
      }
    }

    for (PlanetUtility p : allPlanetInfo) {
      if (p.minBaseConquerCost < 0 && p.units > 0) {
        mySpareUnits +=
            p.units - PlayerUtils.getOpponentsIncomingFleetCount(p.planet, fleets, this);
      }
    }

    ArrayList<PlanetUtility> targets;
    currentUnitRatio = currentUnitRatio > 1 ? 1 : currentUnitRatio;

    switch (mode) {
      case CONFIDENT:
        mySpareUnits *= AGGRESSIVE_SPARE_UNIT_RATIO;
        // mySpareUnits = (int) Math.max(mySpareUnits * AGGRESSIVE_SPARE_UNIT_RATIO, mySpareUnits *
        // currentUnitRatio); //AGGRESSIVE_SPARE_UNIT_RATIO;
        targets = sortByAggressiveValue(allPlanetInfo, averageLocation, variance);
        break;
      case AGGRESSIVE:
        mySpareUnits *= AGGRESSIVE_SPARE_UNIT_RATIO;
        // mySpareUnits = (int) Math.max(mySpareUnits * AGGRESSIVE_SPARE_UNIT_RATIO, mySpareUnits *
        // currentUnitRatio);
        targets = sortByOverallValue(allPlanetInfo, averageLocation, variance);
        break;
      case DEFENSIVE:
        mySpareUnits *= DEFENSIVE_SPARE_UNIT_RATIO;
        // mySpareUnits = (int) Math.max(mySpareUnits * DEFENSIVE_SPARE_UNIT_RATIO, mySpareUnits *
        // currentUnitRatio);
        targets = sortByDefensiveValue(allPlanetInfo, averageLocation, variance);
        break;
      case DESPARATE:
        mySpareUnits *= AGGRESSIVE_SPARE_UNIT_RATIO;
        // mySpareUnits = (int) Math.min(mySpareUnits * AGGRESSIVE_SPARE_UNIT_RATIO, mySpareUnits *
        // currentUnitRatio);
        targets = sortByOverallValue(allPlanetInfo, averageLocation, variance);
        break;
      case NORMAL:
        mySpareUnits *= NORMAL_SPARE_UNIT_RATIO;
        // mySpareUnits = (int) Math.min(mySpareUnits * NORMAL_SPARE_UNIT_RATIO, mySpareUnits *
        // currentUnitRatio);
        targets = sortByOverallValue(allPlanetInfo, averageLocation, variance);
        break;
      default:
        System.out.println("Error - in default of switch");
        return;
    }

    // System.out.println("spareUnits: " + mySpareUnits);

    for (int i = 0; i < allPlanetInfo.size() && targets.size() > 0; i++) {
      PlanetUtility current = allPlanetInfo.get(i);

      if (targets.get(0).planet.ownedBy(this)) {
        targets.remove(0);
        i--;
        continue;
      }

      if (current.planet.ownedBy(this)) {
        PlanetUtility temp = targets.get(0);
        // System.out.println("target: " + temp.planet.getOwner() + " u: " +
        // temp.planet.getNumUnits());
        int extraUnitsNeeded = 3;
        if (temp.planet.ownedByOpponentOf(this)) {
          extraUnitsNeeded +=
              (int) temp.planet.distanceTo(current.planet)
                  / (FLEET_SPEED * temp.planet.PRODUCTION_TIME);
        }
        if (mySpareUnits > temp.minBaseConquerCost) {
          if (current.minBaseConquerCost < 0 && current.units > 0) {
            int willSend =
                current.extraUnits > temp.minBaseConquerCost + extraUnitsNeeded
                    ? temp.minBaseConquerCost + extraUnitsNeeded
                    : current.extraUnits;
            current.units -= willSend;
            current.extraUnits -= willSend;
            temp.minBaseConquerCost -= willSend;
            if (willSend == temp.minBaseConquerCost) {
              targets.remove(0);
            }
            addAction(current.planet, temp.planet, willSend);
          }
        } else {
          targets.remove(0);
          i--;
        }
      }
    }
  }