Пример #1
0
  /**
   * Worst case: If we could not collide anything into the nucleus, find the biggest masses and try
   * to collide them
   */
  public void finishGame(
      Asteroid[] asteroids, Asteroid nucleus, double[] energy, double[] direction) {

    if (mass_total == 0) {
      for (Asteroid a : asteroids) {
        if (a.mass > mass_total) mass_total = a.mass;
      }
    }

    if (time < next_push) return;
    if (time == next_push) {
      int index = 0;
      for (index = 0; index < asteroids.length; index++) {
        if (asteroids[index].id == push_info.asteroid.id) break;
      }
      if (index < asteroids.length) {
        energy[index] = push_info.energy;
        direction[index] = push_info.direction;
        asteroids[index] =
            Asteroid.push(asteroids[index], time, push_info.energy, push_info.direction);
      }
    }

    if (no_progress || mass_total >= target_mass) return;

    int n = asteroids.length;
    ArrayList<Asteroid> largest_asteroids = new ArrayList<Asteroid>();
    ArrayList<Push> pushes = new ArrayList<Push>();

    for (int i = 0; i < n; i++) {
      largest_asteroids.add(asteroids[i]);
    }

    // Sort asteroids in decreasing order by mass
    Collections.sort(
        largest_asteroids,
        new Comparator<Asteroid>() {
          public int compare(Asteroid a1, Asteroid a2) {
            return -1 * (Double.compare(a1.mass, a2.mass));
          }
        });

    for (int i = 0; i < largest_asteroids.size(); i++) {
      Asteroid curr_asteroid = largest_asteroids.get(i);
      long time_to_push = Hohmann.timeToPush(time, curr_asteroid, nucleus);
      if (time_to_push != -1) {
        Push push = Hohmann.generatePush(curr_asteroid, i, nucleus, time_to_push);
        if (time_to_push + push.expected_collision_time < time_limit) {
          pushes.add(push);
        }
      }
    }
    Collections.sort(pushes, new Push.TimeComparator());
    if (!pushes.isEmpty()) {
      push_info = pushes.get(0);
      next_push = push_info.time;
      System.out.println("This is " + time + ". Push will happen at " + next_push);
      mass_total += push_info.asteroid.mass;
    } else {
      no_progress = true;
    }
  }
Пример #2
0
  // try to push asteroid
  public void play(Asteroid[] asteroids, double[] energy, double[] direction) {
    time++;

    if (time > 0.9 * time_limit) {
      finish_flag = true;
    }

    int n = asteroids.length;

    /* fix orbits of troublemaker asteroids that intially shared the same orbit with nucleus */
    if (!troublemakers.isEmpty()) {
      ArrayList<Long> temp = new ArrayList<Long>();
      for (long id : troublemakers) {
        int t = Utils.findAsteroidIndexById(asteroids, id);
        Point p1 = asteroids[t].orbit.positionAt(time);
        Point p2 = asteroids[t].orbit.positionAt(time + 1);
        if (Math.hypot(p1.x, p1.y) > Math.hypot(p2.x, p2.y)) {
          Push push = Hohmann.generateCorrection(asteroids[t], t, time);
          energy[t] = push.energy;
          direction[t] = push.direction;
        } else {
          temp.add(id);
        }
      }
      troublemakers = temp;
    }

    if (asteroids.length < number_of_asteroids) {
      System.out.println("A collision just occurred at time " + time);
      // Check for non-circular orbit
      int new_asteroid_idx = 0;
      for (int i = 0; i < asteroids.length; i++) {
        if (!seenId.contains(asteroids[i].id)) {
          new_asteroid_idx = i;
          seenId.add(asteroids[i].id);

          if (Math.abs(asteroids[i].orbit.a - asteroids[i].orbit.b) > EPSILON) {
            // Correct for non-circular orbit
            System.out.println("CORRECTION");
            Push push = Hohmann.generateCorrection(asteroids[i], i, time);
            energy[i] = push.energy;
            direction[i] = push.direction;

            asteroids[i] = Asteroid.push(asteroids[i], time, energy[i], direction[i]);

            // Redo the queue

            Queue<Push> new_queue = new PriorityQueue<>(new Push.TimeComparator());
            for (Push p : push_queue) {
              Asteroid a = p.asteroid;
              long time_to_push = Hohmann.timeToPush(time, a, asteroids[i]);
              if (time_to_push != -1) {
                Push np = Hohmann.generatePush(a, -1, asteroids[i], time_to_push);
                if (time_to_push + np.expected_collision_time <= time_limit) {
                  new_queue.add(np);
                } else {
                  usedId.remove(a.id);
                }
              } else {
                System.out.println("WTF");
                usedId.remove(a.id);
              }
            }
            push_queue = new_queue;
          }
        }
      }

      if (Utils.findAsteroidById(asteroids, nucleus_id) == null) {
        nucleus_id = asteroids[new_asteroid_idx].id;
        System.out.println("NUCLEUS ID CHANGED");
        usedId.add(nucleus_id);
      }
      number_of_asteroids = asteroids.length;

      unlock_time = -1;

      no_progress = false;
    }

    nucleus = Utils.findAsteroidById(asteroids, nucleus_id);

    /* push out asteroids that share the same orbit with nucleus */
    for (int i = 0; i < asteroids.length; i++) {
      Asteroid ast = asteroids[i];
      if (nucleus == ast) {
        continue;
      }
      if (Math.abs(ast.orbit.a - nucleus.orbit.a) <= EPSILON
          && Math.abs(ast.orbit.b - nucleus.orbit.b) <= EPSILON) {
        troublemakers.add(ast.id);
        Push push = Hohmann.generatePushToRadius(ast, i, ast.orbit.a * orbit_multiplier, time);
        energy[i] = push.energy;
        direction[i] = push.direction;
      }
    }

    if (finish_flag) {
      finishGame(asteroids, nucleus, energy, direction);
      return;
    }

    if (time < unlock_time) return;

    while (!push_queue.isEmpty() && time == push_queue.peek().time) {
      Push push_info = push_queue.remove();

      int index;
      for (index = 0; index < asteroids.length; index++) {
        if (asteroids[index].id == push_info.asteroid.id) {
          break;
        }
      }
      if (index != asteroids.length) {
        Asteroid a = Asteroid.push(asteroids[index], time, push_info.energy, push_info.direction);
        long collision_time =
            CollisionChecker.checkCollision(
                a, nucleus, push_info.expected_collision_time, time, time_limit);
        if (collision_time != -1) {
          energy[index] = push_info.energy;
          direction[index] = push_info.direction;
          asteroids[index] =
              Asteroid.push(asteroids[index], time, push_info.energy, push_info.direction);
          System.out.println(
              "This is "
                  + time
                  + ". Collision will happen at "
                  + time
                  + push_info.expected_collision_time);

          unlock_time = time + push_info.expected_collision_time;
          while (!push_queue.isEmpty()
              && push_queue.peek().time < time + push_info.expected_collision_time) {
            usedId.remove(push_queue.remove().asteroid.id);
          }
        } else {
          System.out.println("Didn't happen");
          usedId.remove(push_info.asteroid.id);
        }
      }
    }

    if (time < unlock_time) return;

    double used_mass = 0;
    for (Asteroid a : asteroids) {
      if (usedId.contains(a.id)) {
        used_mass += a.mass;
      }
    }

    if (used_mass < target_mass) {
      // Of all remaining asteroids, find the one with lowest energy push
      System.out.println("There are " + n + " asteroids to be considered.");
      ArrayList<Push> pushes = new ArrayList<>();
      for (int i = 0; i < n; i++) {
        if (asteroids[i].id == nucleus_id) {
          continue;
        }
        int curr_asteroid_index = i;
        Asteroid curr_asteroid = asteroids[curr_asteroid_index];
        // Ignore asteroids with elliptical orbits
        if (usedId.contains(curr_asteroid.id)) {
          continue;
        }
        long time_to_push = Hohmann.timeToPush(time, curr_asteroid, nucleus);
        if (time_to_push != -1) {
          Push push =
              Hohmann.generatePush(curr_asteroid, curr_asteroid_index, nucleus, time_to_push);
          if (time_to_push + push.expected_collision_time <= time_limit) {
            pushes.add(push);
          }
        }
      }

      Collections.sort(pushes, new Push.EnergyComparator());

      double mass_considered = 0;
      ArrayList<Push> valid_pushes = new ArrayList<>();
      for (Push p : pushes) {
        if (mass_considered < target_mass - used_mass) {
          mass_considered += p.asteroid.mass;
          valid_pushes.add(p);
          System.out.println(
              "Time: " + p.time / 365.0 + " Energy: " + p.energy + " Mass: " + target_mass);
          push_queue.add(p);
          usedId.add(p.asteroid.id);
        }
      }
    }
  }