@Override
  public List<Command> makeStrategy() {
    List<Command> commands = new ArrayList<Command>();

    double power = 1;
    for (int i = 0; i < canShoot.length; i++) {
      if (currentSituation.myPlayersDetail()[canShoot[i]].getPower() < power) {
        power = currentSituation.myPlayersDetail()[canShoot[i]].getPower();
      }
    }
    if (isShootSituation(power)) {
      double maxVertAngle = Constants.ANGULO_VERTICAL_MAX * Math.PI / 180;
      double angleVert;
      double angle =
          currentSituation
              .ballPosition()
              .angle(Constants.posteDerArcoSup.movePosition(-Constants.RADIO_BALON, 0));
      angle =
          Math.min(
              angle + 0.5 * Constants.getErrorAngular(1.0) / 2 * Math.PI,
              currentSituation.ballPosition().angle(Constants.centroArcoSup));
      double maxAngle =
          currentSituation
              .ballPosition()
              .angle(Constants.posteIzqArcoSup.movePosition(Constants.RADIO_BALON, 0));
      maxAngle =
          Math.max(
              maxAngle - 0.5 * Constants.getErrorAngular(1.0) / 2 * Math.PI,
              currentSituation.ballPosition().angle(Constants.centroArcoSup));

      ShootInfo shoot = new ShootInfo();
      while (angle <= maxAngle) {
        angleVert = 0;
        while (angleVert <= maxVertAngle) {
          shoot = compareShoot(shoot, evaluateShoot(power, angle, angleVert));
          angleVert += Math.PI / 180;
        }
        angle += Math.PI / 180;
      }

      for (int player : canShoot) {
        commands.add(
            new CommandHitBall(
                player, shoot.angle * 180 / Math.PI, 1, shoot.angleVert * 180 / Math.PI));
      }
    }

    return commands;
  }
 private ShootInfo evaluateShoot(double power, double angle, double angleVert) {
   TrajectoryMasia trajectory =
       new TrajectoryMasia(
           currentSituation.ballPosition(), Constants.getVelocidadRemate(power), angle, angleVert);
   double fitness = 0, f;
   for (int i = 0; i < trajectory.length; i++) {
     if (i == 0) {
       f =
           calculateFitness(
               trajectory.positions[i],
               trajectory.z[i],
               i + 1,
               currentSituation.ballPosition(),
               0);
     } else {
       f =
           calculateFitness(
               trajectory.positions[i],
               trajectory.z[i],
               i + 1,
               trajectory.positions[i - 1],
               trajectory.z[i - 1]);
     }
     fitness += f;
     if (f > 1 || f == -1) {
       break;
     }
   }
   return new ShootInfo(angle, angleVert, fitness);
 }
 private boolean isShootSituation(double power) {
   double factor =
       Math.abs(Math.sin(currentSituation.ballPosition().angle(Constants.centroArcoSup)));
   factor = 1 - (1 - factor) * (1 - factor);
   return currentSituation.ballPosition().distance(Constants.centroArcoSup)
       <= THRESHOLD
           * factor
           * Constants.getVelocidadRemate(power)
           / Constants.REMATE_VELOCIDAD_MAX;
 }