def score_planet(pw: planet_wars.PlanetWars, p: planet_wars.Planet): """ Function to give a planet a score based on many factors. :param pw: `PlanetWars` object :param p: `Planet` object :return: `float` score of planet """ raw_score = get_raw_score(p) structural_score = 1 - (pythag(MY_PLANETS_CENTER, (p.x(), p.y())) / pw.map_size) surrounding_score = 0 for planet in filter(lambda _p: _p != p, pw.planets()): temp = ( 1 - (pw.distance(p.planet_id(), planet.planet_id()) / pw.map_size))**5 surrounding_score += get_raw_score(planet) * temp surrounding_score /= pw.total_growth latency_score = p.latency / pw.map_size center_score = 1 - (pw.distance(p.planet_id(), 0) / pw.map_size) score = 0 score += raw_score score += STRUCTURAL_FACTOR * structural_score score += SURROUNDING_FACTOR * surrounding_score score += LATENCY_FACTOR * latency_score score += CENTER_FACTOR * center_score return score
def furthest_meaningful_planet(pw: planet_wars.PlanetWars, planet: planet_wars.Planet, owner: int): planets = tuple(filter(lambda p: p.owner() == owner, pw.planets())) fleets = tuple(filter(lambda f: f.owner() == owner, pw.fleets())) furthest_distance = 0 for other_planet in planets: furthest_distance = max( furthest_distance, pw.distance(other_planet.planet_id(), planet.planet_id())) for fleet in fleets: furthest_distance = max( furthest_distance, fleet.turns_remaining() + pw.distance(fleet.destination_planet(), planet.planet_id())) return furthest_distance
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