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 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 get_raw_score(p: planet_wars.Planet): """ Returns the basic score of the planet. :param p: `Planet` object :return: `float` score of the planet """ return p.growth_rate()
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 test_advancement(self): self.add_fleets_and_planets() pl5 = Planet(4, 0, 10, 100, 0, 0) self.eng.pw.planets.append(pl5) check = self.eng.pw.my_fleets[0].turns_remaining self.eng._advancement() self.assertEqual(10, self.eng.pw.planets[4].num_ships) self.assertEqual(2, self.eng.pw.planets[3].num_ships) self.assertEqual(check - 1, self.eng.pw.my_fleets[0].turns_remaining)
def test_is_game_over(self): self.pw.turn = 10 self._game_over_true(9) self.pw.turn = 1 self._game_over_true(1) self.pw.planets.append(Planet(1, 1, 10, 5, 10, 10)) self._game_over_true(1) self.pw.planets.append(Planet(2, 2, 10, 5, 10, 10)) self._game_over_false(1) self.pw.planets = [] self._game_over_true(1) self.pw.fleets.append(Fleet(1, 10, 1, 2, 10, 10)) self._game_over_true(1) self.pw.fleets.append(Fleet(2, 10, 1, 2, 10, 10)) self._game_over_false(1)
class TestPlanet(unittest.TestCase): def setUp(self): self.planet = Planet(0, 1, 10, 5, 10, 10) def test_init_should_not_fail(self): self.assertEqual(self.planet._id, 0) self.assertEqual(self.planet.owner, 1) self.assertEqual(self.planet.num_ships, 10) self.assertEqual(self.planet.growth_rate, 5) self.assertEqual(self.planet.x, 10) self.assertEqual(self.planet.y, 10) def test_should_add_ships(self): self.planet.add_ships(10) self.assertEqual(self.planet.num_ships, 20) def test_should_remove_ships(self): self.planet.remove_ships(5) self.assertEqual(self.planet.num_ships, 5) def test_should_fail_when_removing_too_many_ships(self): self.assertRaises(Exception, lambda: self.planet.remove_ships(20))
def turn_to_take(pw: planet_wars.PlanetWars, my_planet: planet_wars.Planet, neutral_planet: planet_wars.Planet): """ Finds the minimum turns to take `neutral_planet` with `my_planet`. :param pw: `PlanetWars` object :param my_planet: `Planet` object :param neutral_planet: `Planet` object :return: `int` turns to take the planet """ distance = pw.distance(my_planet.planet_id(), neutral_planet.planet_id()) if my_planet.num_ships() > neutral_planet.num_ships(): return distance else: lacking_ships = neutral_planet.num_ships() - my_planet.num_ships() + 1 for t in range(pw.map_size): lacking_ships -= my_planet.my_arriving_ships[ t] + my_planet.growth_rate() if lacking_ships <= 0: break else: return 999999 return distance + t
def setUp(self): self.planet = Planet(0, 1, 10, 5, 10, 10)
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)
def add_planets(self): pl1 = Planet(0, 2, 35, 2, 0, 0) pl2 = Planet(1, 1, 7, 2, 10, 0) pl3 = Planet(2, 1, 15, 2, 0, 20) pl4 = Planet(3, 2, 0, 2, 10, 20) self.eng.pw.planets = [pl1, pl2, pl3, pl4]
def test_process_arrival(self): pl = Planet(0, 1, 40, 1, 0, 0) winner = Fleet(2, 21) second = Fleet(2, 10) self.eng._process_arrival(pl, winner, second) self.assertEqual(11, pl.num_ships)