def get_info(pw: planet_wars.PlanetWars): """ Gets basic info about the map. Saves everything in global variables. :param pw: `PlanetWars` object :return: None """ # get the euclidean center of my and enemy's planets global MY_PLANETS_CENTER, ENEMY_PLANETS_CENTER MY_PLANETS_CENTER = sum(map(lambda p: p.x(), pw.my_planets())) / len(pw.my_planets()), \ sum(map(lambda p: p.y(), pw.my_planets())) / len(pw.my_planets()) ENEMY_PLANETS_CENTER = sum(map(lambda p: p.x(), pw.enemy_planets())) / len(pw.enemy_planets()), \ sum(map(lambda p: p.y(), pw.enemy_planets())) / len(pw.enemy_planets())
def defensible(pw: planet_wars.PlanetWars, planet: planet_wars.Planet): quickest_planet = min(pw.my_planets(), key=lambda p: turn_to_take(pw, p, planet)) quickest_turns = turn_to_take(pw, quickest_planet, planet) for t in range(quickest_turns + 1, furthest_meaningful_planet(pw, planet, 2) + 2): my_maximum_ships = max( 0, sum(planet.my_maximum_ships[:t - 1]) - planet.num_ships() + planet.growth_rate() * (t - quickest_turns)) enemy_maximum_ships = sum(planet.enemy_maximum_ships[:t]) if my_maximum_ships < enemy_maximum_ships: return False return True
def expand(pw: planet_wars.PlanetWars, expand_limit: int = 99, possible_planets=None, reckless: bool = False): """ Expand to neutral planets with all ships. Designed to come after `defend_possible()` because this doesn't account for possible attacks from the opponent. :param pw: `PlanetWars` object :param expand_limit: `int` the maximum number of planets to expand to. :param possible_planets: `list` of `Planet` objects, the planets to consider expanding to. None -> all :param reckless: `bool` whether to care about the defensibility of the planet :return: None """ expand_limit = min(expand_limit, len(pw.neutral_planets())) if possible_planets is None: possible_planets = filter(lambda p: p not in pw.my_future_neutrals, pw.neutral_planets()) possible_planets = filter(lambda p: p not in pw.enemy_future_neutrals, possible_planets) sorted_planets = sorted( possible_planets, key=lambda p: (score_planet(pw, p) - get_raw_score(p) + return_ships(pw, p) / (pw.map_size / 2)) / (p.num_ships() + 1), reverse=True) for _ in range(expand_limit): for attack_planet in sorted_planets[:expand_limit]: if not (attack_planet.latency > 0 and attack_planet.num_ships() < attack_planet.growth_rate()) and \ not reckless and not defensible(pw, attack_planet): continue # if not reckless and not defensible(pw, attack_planet): # continue quickest_planet = min( pw.my_planets(), key=lambda p: turn_to_take(pw, p, attack_planet)) closest_distance = pw.map_size for enemy_planet in pw.enemy_planets(): closest_distance = min( closest_distance, pw.distance(enemy_planet.planet_id(), attack_planet.planet_id())) for enemy_planet in pw.enemy_future_neutrals: closest_distance = min( closest_distance, pw.distance(enemy_planet.planet_id(), attack_planet.planet_id()) + pw.enemy_future_neutrals[enemy_planet][0]) if turn_to_take(pw, quickest_planet, attack_planet) > closest_distance: continue if quickest_planet.num_ships() > attack_planet.num_ships(): pw.issue_order(quickest_planet.planet_id(), attack_planet.planet_id(), attack_planet.num_ships() + 1) quickest_planet.remove_ships(attack_planet.num_ships() + 1) pw.my_future_neutrals[attack_planet] = (pw.distance( quickest_planet.planet_id(), attack_planet.planet_id()), 1) for planet in pw.planets(): planet.my_maximum_ships[pw.distance(quickest_planet.planet_id(), planet.planet_id()) - 1] -= \ attack_planet.num_ships() planet.my_maximum_ships[ pw.distance(quickest_planet.planet_id(), attack_planet.planet_id()) + pw.distance(attack_planet.planet_id(), planet.planet_id())] += 1 for t in range( pw.distance(quickest_planet.planet_id(), attack_planet.planet_id()) + pw.distance(attack_planet.planet_id(), planet.planet_id()), 2 * pw.map_size): planet.my_maximum_ships[ t] += attack_planet.growth_rate() expand_limit -= 1 sorted_planets.remove(attack_planet) break else: quickest_planet.num_ships(0) return else: break
def return_ships(pw: planet_wars.PlanetWars, planet: planet_wars.Planet): quickest_planet = min(pw.my_planets(), key=lambda p: turn_to_take(pw, p, planet)) quickest_turns = turn_to_take(pw, quickest_planet, planet) return planet.growth_rate() * (pw.map_size / 2 - quickest_turns)