Skip to content

Instantly share code, notes, and snippets.

@tobiassjosten
Created February 24, 2013 17:52
Show Gist options
  • Save tobiassjosten/5024799 to your computer and use it in GitHub Desktop.
Save tobiassjosten/5024799 to your computer and use it in GitHub Desktop.
My contribution to [Google AI Challenge 2010](http://planetwars.aichallenge.org/).
# -*- 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