Created
February 24, 2013 17:52
-
-
Save tobiassjosten/5024799 to your computer and use it in GitHub Desktop.
My contribution to [Google AI Challenge 2010](http://planetwars.aichallenge.org/).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf8 -*- | |
from planetwars import BaseBot, Game | |
from planetwars.player import NOBODY, ME, PLAYER2, PLAYER3, PLAYER4, ENEMIES | |
from planetwars.universe import Universe | |
from planetwars.planet import Planet | |
from copy import copy | |
from logging import getLogger | |
import math | |
log = getLogger(__name__) | |
class PlagueBot(BaseBot): | |
def do_turn(self): | |
if len(self.universe.my_planets) == 0: | |
return | |
for source in self.universe.my_planets: | |
self.do_defend(source) | |
self.do_expand(source) | |
self.do_attack(source) | |
def do_defend(self, source): | |
allies = source.allies | |
if not allies: | |
return | |
for ally in allies: | |
if len(ally.attacking_fleets) > 0: | |
log.debug('%d incoming fleets %s' % (len(ally.attacking_fleets), ally.attacking_fleets)) | |
ally_distance = source.distance(ally) | |
ally_future = ally.future(ally_distance) | |
if ally_future.owner != ME: | |
source.send_fleet(ally, min(source.ship_count - 1, ally_future.ship_count + 1)) | |
return | |
log.debug('ally will withstand attack') | |
def do_expand(self, source): | |
for i in range(5): | |
expansion = source.find_nearest_neighbor(owner=NOBODY, growth_rate=5-i) | |
# TODO: Prioritize good ship_count/growth ratio. | |
if not expansion or len(expansion.attacking_fleets) > 0: | |
return | |
if source.ship_count - 1 > expansion.ship_count + 1: | |
source.send_fleet(expansion, min(source.ship_count - 1, expansion.ship_count + 1)) | |
def do_attack(self, source): | |
enemy = source.find_nearest_neighbor(owner=ENEMIES) | |
if not enemy or len(enemy.attacking_fleets) > 0: | |
return | |
# TODO: Don't attack if planet is under attack and cannot withstand it. | |
if source.ship_count - 1 > enemy.ship_count: | |
source.send_fleet(enemy, min(source.ship_count - 1, enemy.growth_rate * 5)) | |
_closest_cache = {} | |
class PlaguePlanet(Planet): | |
@property | |
def closest_planets(self): | |
"""List of planets planets, ordered by distance.""" | |
if not self in _closest_cache: | |
planets = [] | |
for planet in self.universe.planets: | |
if self == planet: | |
continue | |
for i in range(len(planets)): | |
if self.distance(planet) < self.distance(planets[i]): | |
planets.insert(i, planet) | |
break | |
planets.append(planet) | |
_closest_cache[self] = planets | |
return _closest_cache[self] | |
@property | |
def closest_my_planets(self): | |
"""List of planets, ordered by distance and filtered by ownership.""" | |
planets = [] | |
for planet in self.closest_planets: | |
if planet.owner == ME: | |
planets.append(planet) | |
return planets | |
@property | |
def closest_enemy_planets(self): | |
"""List of planets, ordered by distance and filtered by ownership.""" | |
planets = [] | |
for planet in self.closest_planets: | |
if planet.owner in [PLAYER2, PLAYER3, PLAYER4]: | |
planets.append(planet) | |
return planets | |
@property | |
def closest_nobodies_planets(self): | |
"""List of planets, ordered by distance and filtered by ownership.""" | |
planets = [] | |
for planet in self.closest_planets: | |
if planet.owner == NOBODY: | |
planets.append(planet) | |
return planets | |
@property | |
def closest_not_my_planets(self): | |
"""List of planets, ordered by distance and filtered by ownership.""" | |
planets = [] | |
for planet in self.closest_planets: | |
if planet.owner != ME: | |
planets.append(planet) | |
return planets | |
@property | |
def allies(self): | |
ally = self.find_nearest_neighbor(owner=self.owner) | |
if not ally: | |
return [] | |
allies = [self.find_nearest_neighbor(owner=self.owner)] | |
for planet in self.universe.find_planets(owner=self.owner): | |
if self == planet.find_nearest_neighbor(owner=planet.owner): | |
allies.append(planet) | |
return allies | |
def future(self, turns): | |
log.debug('divining future for %s' % self) | |
future = copy(self) | |
incoming_fleets = len(future.attacking_fleets) + len(future.reinforcement_fleets) | |
if future.owner == NOBODY and incoming_fleets == 0: | |
log.debug('.. neutral planet with no incoming fleet, so we have status quo') | |
return future | |
for i in range(1, turns + 1): | |
log.debug('.. %d turn(s) into the future' % i) | |
if future.owner != NOBODY: | |
future.ship_count += future.growth_rate | |
log.debug('.. .. growth by %d gives %d ships' % (future.growth_rate, future.ship_count)) | |
for fleet in self.reinforcement_fleets: | |
if fleet.turns_remaining != i: | |
continue | |
future.ship_count += fleet.ship_count | |
log.debug('.. .. %d strong fleet reinforces power to %d' % (fleet.ship_count, future.ship_count)) | |
for fleet in self.attacking_fleets: | |
if fleet.turns_remaining != i: | |
continue | |
if future.ship_count < fleet.ship_count: | |
log.debug('.. .. %d strong fleet changes owner to %s' % (fleet.ship_count, fleet.owner)) | |
future.owner = fleet.owner | |
future.ship_count = fleet.ship_count - future.ship_count | |
else: | |
future.ship_count -= max(future.ship_count - 1, fleet.ship_count) | |
log.debug('.. .. %d strong fleet decreases power to %d' % (fleet.ship_count, future.ship_count)) | |
return future | |
Game(PlagueBot, Universe, PlaguePlanet) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment