Created
December 31, 2013 14:12
-
-
Save OzTamir/8197345 to your computer and use it in GitHub Desktop.
sudo's winning code, cleaned up and documented properly - now in a public gist.
Written by Oz Tamir, Tomer Schlesinger and Eden Rozen.
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
def DoTurn(pw): | |
Overtake(pw) | |
def Attack(pw, source, target, ships): | |
''' | |
A custom controller for pw built-in IssueOrder() method | |
''' | |
if source.NumShips() < ships: | |
send = source.NumShips() | |
else: | |
send = ships | |
pw.IssueOrder(source, target, send) | |
def Overtake(pw): | |
''' | |
The commanding function. Responsible for deciding what planet to attack and from what planet to launch the attacks. | |
''' | |
# Get a list of my planets, sorted by amount of ships (From high to low) | |
my_planets = sorted(pw.MyPlanets(), key = lambda planet: planet.NumShips(), reverse = True) | |
# Get a list of possible targets for attack | |
targets = pw.NotMyPlanets() | |
# Get a list of all the planet currently under attack | |
fleetTargets = [pw.GetPlanet(fleet.DestinationPlanet()) for fleet in (pw.EnemyFleets() + pw.MyFleets())] | |
# Narrow the targets down to those that can be captured without any doubt (as for the current turn) | |
targets = [target for target in targets if target not in fleetTargets] | |
if len(targets) > 0: | |
# Iterate over all the planets which are under my control and find a target (if possible) | |
for i in range(len(my_planets)): | |
planet = my_planets[i] | |
# Get a list of target that can be captured by the current planet | |
targetsForOvertake = [] | |
for target in targets: | |
# Calculate the predicted number of ships on targeted planet upon arrival | |
futureShips = futureShipsInPlanet(target, pw.Distance(planet, target)) | |
# If the planet can be captured, add it to the list of the current planet's targets | |
if planet.NumShips() > futureShips + 1: | |
targetsForOvertake.append(target) | |
# Get a list of the target's Factors (see calcFactor()) | |
optimalTargetsFactor = map(calcFactor, targetsForOvertake) | |
if optimalTargetsFactor: | |
# Find the target with the best factor... | |
maxFactor = max(optimalTargetsFactor) | |
maxIndex = 0 | |
for i in targetsForOvertake: | |
if maxFactor == i: | |
maxIndex = i | |
# ... and the corresponding target | |
target = targetsForOvertake[maxIndex] | |
# Finally, attack the selected planet with the minimal number of ships required to capture it | |
Attack(pw, planet, target , futureShipsInPlanet(target, pw.Distance(planet, target)) + 1) | |
def calcFactor(target): | |
''' | |
Calculate the factor of target as a function of it's number of ships and it's owner. | |
The factor indicate how recommended will it be to launch an attack on target. | |
''' | |
# The factor take into account the owner of the target, and friendly planet will have smaller factors. | |
ownerMult = 10 | |
if target.Owner == 1: | |
ownerMult = 15 | |
return target.GrowthRate() / ((target.NumShips() + 1) * ownerMult) | |
def futureShipsInPlanet(planet, turns): | |
''' | |
Predict the number of ships in planet in 'turns' turns (assuming that our fleet will be the first to get ther in 'turns') | |
''' | |
# Netural planet don't grow, therefore the number of ships won't change | |
if planet.Owner() == 0: | |
return planet.NumShips() | |
# Else, return the predicted number of ships as | |
return planet.NumShips() + planet.GrowthRate() * turns |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment