private Point teleport(Point location, double offset, Map<Integer, Point> id_lut) { Point self = id_lut.get(self_id); double x = Math.max(Math.min(location.x, 20), 0); double y = Math.max(Math.min(location.y, 20), 0); double dx = x - self.x; double dy = y - self.y; double r = Math.hypot(dx, dy) - offset; if (Math.abs(r) > 6) { r = Math.signum(r) * 6; } double th = Math.atan2(dy, dx); return new Point(r * Math.cos(th), r * Math.sin(th), self_id); }
public static double heuristicCostEstimate(Cell start, Cell goal) { return Math.hypot(start.x - goal.x, start.y - goal.y); // return Math.abs(goal.x - start.x) + Math.abs(goal.y - start.y); }
// 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); } } } }
private double dist(Point a, Point b) { return Math.hypot(a.x - b.x, a.y - b.y); }
/** Return distance between this location and another */ public double distanceTo(Location other) { return Math.hypot(this.x - other.x, this.y - other.y); }