def DoTurn(pw): try: # (1) If we currently have a fleet in flight, just do nothing. if len(pw.MyFleets()) >= 3: log.debug('Returning since more than 2 fleets are out') return # (2) Find my strongest planet. source = -1 source_score = -999999.0 source_num_ships = 0 my_planets = pw.MyPlanets() for p in my_planets: score = float(p.NumShips()) if score > source_score: source_score = score source = p.PlanetID() source_num_ships = p.NumShips() # (3) Find the weakest enemy or neutral planet. dest = -1 dest_score = -999999.0 not_my_planets = pw.NotMyPlanets() for p in not_my_planets: score = 1.0 / (1 + p.NumShips()) if score > dest_score: dest_score = score dest = p.PlanetID() # (4) Send half the ships from my strongest planet to the weakest # planet that I do not own. if source >= 0 and dest >= 0: num_ships = source_num_ships / 2 pw.IssueOrder(source, dest, num_ships) except Exception, e: log.error(str(e))
def main(): map_data = '' while(True): current_line = raw_input() if len(current_line) >= 2 and current_line.startswith("go"): log.startTurn() pw = PlanetWars(map_data) DoTurn5(pw) pw.FinishTurn() map_data = '' log.debug('finished turn') else: map_data += current_line + '\n'
def getBestOrders1(gains, availableShips): #gains: dict, key = planetId, list of (ships required, gain, other planetID()) #available ships: dict, key = planetId, int of available ships for attacking orders = [] #list of (source planetId, destinationPlanetId, number of attackers) for planet in availableShips: log.debug('planet: ' + str(planet) + ' available ships: ' + str(availableShips[planet])) log.debug('gains: \n' + '\n'.join([str(x) for x in gains[planet]])) if availableShips[planet] == 0: continue # should probably do some recursive optimization crazyness here... if gains[planet][0][0] < availableShips[planet]: orders.append((planet, gains[planet][0][2], gains[planet][0][0])) return orders
def DoTurn3(pw): global turn_number turn_number += 1 try: #if turn_number == 1: #if FirstTurn.doFirstTurn(pw): # return #for each of my planets #for each of the other planets #find the total number of fleets when we could get there from our planet, then determine the best planet to attack orders = [] allGains = {} availableShips = {} for my_planet in pw.MyPlanets(): availableShips[my_planet.PlanetID()] = max(0, my_planet.NumShips() - extra_ships) gains = [] for other_planet in pw.Planets(): if other_planet.GrowthRate() == 0: # not worth taking over continue if my_planet.PlanetID() == other_planet.PlanetID(): #same planet continue shipsAtArriveTime, time = pw.GetShipsAtArriveTime(my_planet.PlanetID(), other_planet.PlanetID()) if shipsAtArriveTime[1] == 1: # we will have control of that planet, don't bother with it pass else: # should we try to take over? gain = 0 if time >= turns_ahead else (turns_ahead - time) * other_planet.GrowthRate() * (1 if shipsAtArriveTime == 0 else 2) gains.append((shipsAtArriveTime[0] + extra_ships, gain, other_planet.PlanetID())) allGains[my_planet.PlanetID()] = sorted(gains) log.debug('got all gains') orders = getBestOrders2(allGains, availableShips, pw) log.debug('got orders from getBestOrders1(): \n' + '\n'.join([str(x) for x in orders])) log.debug('Starting to issue all orders') for order in orders: try: pw.IssueOrder(order[0], order[1], order[2]) except Exception, e: log.exc(e) log.debug('done issueing orders')
def addStreamOrders(orders, stayHomeGain, pw): new_orders = [] for my_planet in pw.MyPlanets(): totalOrdersSent = sum([order[2] for order in orders if order[0] == my_planet.PlanetID()]) available = stayHomeGain[my_planet.PlanetID()] bestGainStaying = -1 for ships in available: if available[ships] > bestGainStaying: bestGainStaying = available[ships] shipsLeft = my_planet.NumShips() - totalOrdersSent - ships log.debug('for planet : ' + str(my_planet)) log.debug('total orders sent: ' + str(totalOrdersSent)) log.debug('ships left: ' + str(shipsLeft)) log.debug('availableShips: ' + str(available)) if availableShips > 0: log.debug('find a potential planet to send to') return new_orders
def getPlanetsToGoToFirst(planetTuples, availableShips): """ takes a list of the physically closest planets to the home returns a list of planets that should immediately be attacked """ planetTuples.sort(cmp = fleetSizeSort) #sorted with the largets fleet first, recursively keep adding fleets until you run out of space #if it gets the most growth, keep track of it #log.debug('planets sorted by fleet size: \n' + '\n'.join([str(x) for x in planetTuples])) log.debug('before recursiveIndexFinder()') best = recursiveIndexFinder(planetTuples, [], availableShips) #planetsToAttack = log.debug('best planets to go to first: ' + str(best)) result = [] # list of planet, number of ships for index in best[0]: result.append((planetTuples[index][3], planetTuples[index][0])) return result
def PlanetWorthinessToTakeOver(myPlanet, otherPlanet, minFleetSize, distance): try: enemyLoss = int(otherPlanet.Owner() == 2) * otherPlanet.GrowthRate() growthRate = otherPlanet.GrowthRate() log.debug('enemy loss: ' + str(enemyLoss)) log.debug('growth rate: ' + str(growthRate)) log.debug('min fleet size: ' + str(minFleetSize)) result = 1.0 * (growthRate + enemyLoss) / (minFleetSize * ( 1.0 + distance)**2.0) log.debug('result of planet worthiness: ' + str(result)) return result except Exception, e: log.exc(e) log.error('due to error, PlanetWorthinessToTakeOver() will return 0') return 0.0
def getBestOrders3(allGains, allAvailableShips, pw): #gains: dict, key = planetId, list of (ships required, gain, other planetID()) #available ships: dict, key = planetId, int of available ships for attacking #has the 'stay here' gains orders = [] #list of (source planetId, destinationPlanetId, number of attackers) for planet in allAvailableShips: #log.debug('started planet ' + str(planet)) availableShips = allAvailableShips[planet] gains = sorted(allGains[planet], reverse = True) if len(gains) == 0: #log.debug('no planets left to conquer?') continue if availableShips == 0: continue #now recursively optimize the gain indeces = [] strategy = optimizeFleets(gains, availableShips, []) log.debug('planet: ' + str(planet) + ' strategy: ' + str(strategy)) for index in strategy[1]: planet_to_attack = gains[index][2] ships = gains[index][0] if planet_to_attack == planet: if ships > 0: log.debug('decided to leave ' + str(ships) + ' fleets at home planet') pass else: orders.append((planet, planet_to_attack, ships)) log.debug('planet: ' + str(planet) + ' best places to attack: ' + str(strategy[1])) #log.debug('getBestOrders3 returning : ' + str(orders)) return orders
def doFirstTurn(pw): try: log.debug('Start of doFirstTurn()') myPlanets = pw.MyPlanets() if len(myPlanets) != 1: raise Exception("should always have 1 planet on turn on") myPlanet = myPlanets[0] if myPlanet.NumShips() != 100: raise Exception("should always have 100 ships on initial planet") availableShips = 99 # leave 5 behind minimum planets = [] #try to get as much growth as possible, while also minimizing distance to planets, (and possible fleet loss) for planet in pw.NeutralPlanets(): growthRate = planet.GrowthRate() distance = pw.Distance(myPlanet.PlanetID(), planet.PlanetID()) minShips = planet.NumShips() + 1 planets.append((minShips, growthRate, distance, planet)) #log.debug('before sort: ' + '\n'.join([str(p) for p in planets])) planets.sort(cmp = distanceSort) #log.debug('after sort: ' + '\n'.join([str(p) for p in planets])) #not sure if the next line should be commented, or changed in some way planets = planets[:len(planets)/3] #log.debug('planets to actually consider: ' + '\n'.join([str(p) for p in planets])) planetsToConquer = getPlanetsToGoToFirst(planets, availableShips) for planet in planetsToConquer: log.debug('issueing order: planetId: ' + str(planet[0].PlanetID()) + ' with ' + str(planet[1]) + ' ships') pw.IssueOrder(myPlanet.PlanetID(), planet[0].PlanetID(), planet[1]) log.debug('end of doFirstTurn()') return True except Exception, e: log.exc(e) return False
def filterOrders(orders, distanceFunc): try: destinations = {} removeIndeces =[] for index, (source, destination, fleet) in enumerate(orders): if destinations.has_key(destination): distance1 = distanceFunc(source, destination) distance2 = distanceFunc(destinations[destination][0][0], destinations[destination][0][1]) if distance1 < distance2: removeIndeces.append(destinations[destination][1]) else: removeIndeces.append(index) else: destinations[destination] = ((source, destination, fleet), index) log.debug('orders: ' + str(orders)) log.debug('remove indeces: ' + str(removeIndeces)) for index in sorted(removeIndeces, reverse = True): orders.pop(index) log.debug('orders after: ' + str(orders)) except Exception, e: log.exc(e)
def DoTurn5(pw): global wait_for_enemy global turn_number turn_number += 1 try: if turn_number == 1: distance_to_enemy = pw.Distance(pw.MyPlanets()[0].PlanetID(), pw.EnemyPlanets()[0].PlanetID()) if distance_to_enemy < distance_to_wait_first_turn: wait_for_enemy = True if wait_for_enemy: if len(pw.Fleets()) > 0: wait_for_enemy = False else: return #for each of my planets #for each of the other planets #find the total number of fleets when we could get there from our planet, then determine the best planet to attack orders = [] allGains = {} stayHomeGain = getAvailableShips(pw) availableShips = {} log.debug('starting to get planet gains') for my_planet in pw.MyPlanets(): gains = [] for other_planet in pw.Planets(): gainsDict = getPlanetGains(my_planet, other_planet, pw) #allGains[my_planet.PlanetID()] = getPlanetGains(my_planet, other_planet, pw) for ships in gainsDict: if gainsDict[ships] > 0: gains.append((ships, gainsDict[ships], other_planet.PlanetID())) log.debug('gains for planet ' + str(my_planet.PlanetID()) + ' : \n' + '\n'.join([(str(x) + ' : ' + str(gainsDict[x])) for x in gainsDict if gainsDict[x] > 0])) availableShips[my_planet.PlanetID()] = max(0, my_planet.NumShips() - extra_ships) allGains[my_planet.PlanetID()] = gains log.debug('done getting planet gains') log.debug('gains: ' + str(allGains)) """ allGains = {} for my_planet in pw.MyPlanets(): gains = [] #add the gains attained by leaving ships here for ships in stayHomeGain[my_planet.PlanetID()]: gains.append((ships, stayHomeGain[my_planet.PlanetID()][ships], my_planet.PlanetID())) for other_planet in pw.Planets(): if other_planet.GrowthRate() == 0: # not worth taking over continue if my_planet.PlanetID() == other_planet.PlanetID(): #same planet continue availableShips[my_planet.PlanetID()] = max(0, my_planet.NumShips() - extra_ships) shipsAtArriveTime, time = pw.GetShipsAtArriveTime(my_planet.PlanetID(), other_planet.PlanetID()) if shipsAtArriveTime[1] == 1: # we will have control of that planet, don't bother with it pass else: # should we try to take over? gain = 0 if time >= turns_ahead else (turns_ahead - time) * other_planet.GrowthRate() * (1 if shipsAtArriveTime == 0 else 2) gains.append((shipsAtArriveTime[0] + extra_ships, gain, other_planet.PlanetID())) allGains[my_planet.PlanetID()] = sorted(gains) """ log.debug('got all gains') orders = getBestOrders3(allGains, availableShips, pw) log.debug('got orders from getBestOrders3(): \n' + '\n'.join([str(x) for x in orders])) log.debug(str(orders)) log.debug('Starting to issue all orders') for order in orders: try: pw.IssueOrder(order[0], order[1], order[2]) except Exception, e: log.exc(e) log.debug('done issueing orders')
def getBestOrders2(gains, availableShips, pw): #gains: dict, key = planetId, list of (ships required, gain, other planetID()) #available ships: dict, key = planetId, int of available ships for attacking orders = [] #list of (source planetId, destinationPlanetId, number of attackers) for planet in availableShips: log.debug('planet: ' + str(planet) + ' available ships: ' + str(availableShips[planet])) log.debug('gains: \n' + '\n'.join([str(x) for x in gains[planet]])) if len(gains[planet]) == 0: log.debug('no planets left to conquer?') continue if availableShips[planet] == 0: continue # should probably do some recursive optimization crazyness here... if gains[planet][0][0] < availableShips[planet]: previousDistance = orderAlreadyPlaced(orders, gains[planet][0][2], pw) log.debug('orders: ' + str(orders)) log.debug('order to place: ' + str((planet, gains[planet][0][2], gains[planet][0][0]))) log.debug('previous distance: ' + str(previousDistance)) if previousDistance is None: orders.append((planet, gains[planet][0][2], gains[planet][0][0])) #if there has already been an order placed, choose the one that's closest if previousDistance < pw.Distance(planet, gains[planet][0][2]): # do nothing, the previous one is better pass else: # replace the order to be sent from the current planet, with the current fleet size(since it may vary due to different distance) for i in range(len(orders)): if orders[i][1] == gains[planet][0][2]: orders[i] = (planet, gains[planet][0][2], gains[planet][0][0]) log.debug('getBestOrders2 returning : ' + str(orders)) return orders
def DoTurn2(pw): global turn_number turn_number += 1 log.debug('turn number: ' + str(turn_number)) try: if turn_number == 1: if FirstTurn.doFirstTurn(pw): return orders = [] for myPlanet in pw.MyPlanets(): closestPlanet = None #find the closest planet that we can take over for planet in pw.NotMyPlanets(): if FleetIsEnRoute(myPlanet.PlanetID(), planet.PlanetID(), pw.MyFleets()): continue try: if planet.Owner() == 0: minFleetSize = planet.NumShips() + 1 else: minFleetSize = planet.NumShips() + 1 + planet.GrowthRate() * pw.Distance(myPlanet.PlanetID(), planet.PlanetID()) except Exception, e: log.exc(e) if minFleetSize >= myPlanet.NumShips(): # we can't take it over with just one planet continue distance = pw.Distance(myPlanet.PlanetID(), planet.PlanetID()) worthiness = PlanetWorthinessToTakeOver(myPlanet, planet, minFleetSize, distance) log.debug('worthiness: ' + str(worthiness)) if closestPlanet is None or worthiness > closestPlanet[1]: closestPlanet = (planet, worthiness, minFleetSize) log.debug('assigned, closestPlanet = ' + str(closestPlanet)) log.debug('closest planet for planet: ' + str(myPlanet.PlanetID()) + ' : ' + str(closestPlanet)) if closestPlanet is None: log.debug('from planet' + str(myPlanet.PlanetID()) + ', no closest planet to attack') else: log.debug('planet ' + str(myPlanet.PlanetID()) + ' will attack planet ' + str(closestPlanet[0].PlanetID()) + ' with worthiness' + str(closestPlanet[1]) + ', with a fleet of ' + str(closestPlanet[2])) orders.append((myPlanet.PlanetID(), closestPlanet[0].PlanetID(), closestPlanet[2])) filterOrders(orders, pw.Distance) log.debug('Starting to issue all orders') for order in orders: try: pw.IssueOrder(order[0], order[1], order[2]) except Exception, e: log.exc(e)
if closestPlanet is None: log.debug('from planet' + str(myPlanet.PlanetID()) + ', no closest planet to attack') else: log.debug('planet ' + str(myPlanet.PlanetID()) + ' will attack planet ' + str(closestPlanet[0].PlanetID()) + ' with worthiness' + str(closestPlanet[1]) + ', with a fleet of ' + str(closestPlanet[2])) orders.append((myPlanet.PlanetID(), closestPlanet[0].PlanetID(), closestPlanet[2])) filterOrders(orders, pw.Distance) log.debug('Starting to issue all orders') for order in orders: try: pw.IssueOrder(order[0], order[1], order[2]) except Exception, e: log.exc(e) log.debug('done issueing orders') except Exception, e: log.exc(e) def getBestOrders1(gains, availableShips): #gains: dict, key = planetId, list of (ships required, gain, other planetID()) #available ships: dict, key = planetId, int of available ships for attacking orders = [] #list of (source planetId, destinationPlanetId, number of attackers) for planet in availableShips: log.debug('planet: ' + str(planet) + ' available ships: ' + str(availableShips[planet])) log.debug('gains: \n' + '\n'.join([str(x) for x in gains[planet]])) if availableShips[planet] == 0: continue # should probably do some recursive optimization crazyness here...
def GetShipsAtArriveTime(self, source_planet, destination_planet): #log.debug('start GetShipsAtArriveTime() for source: ' + str(source_planet) + ' , destination: ' + str(destination_planet)) distance = self.Distance(source_planet, destination_planet) #log.debug('distance: ' + str(distance)) currentShips = [self._planets[destination_planet].NumShips(), self._planets[destination_planet].Owner()] #log.debug('current ships_: ' + str(currentShips)) growthRate = self._planets[destination_planet].GrowthRate() my_fleets = [fleet for fleet in self.MyFleets() if fleet.DestinationPlanet() == destination_planet] enemy_fleets = [fleet for fleet in self.EnemyFleets() if fleet.DestinationPlanet() == destination_planet] #log.debug('enemy fleets: ' + str(enemy_fleets)) #log.debug('my fleets: ' + str(my_fleets)) allFleets = {} for fleet in my_fleets + enemy_fleets: turns = fleet.TurnsRemaining() if turns > distance: continue ships = fleet.NumShips() owner = fleet.Owner() if not allFleets.has_key(turns): allFleets[turns] = (ships, owner) else: if allFleets[turns][1] == owner: allFleets[turns] = (allFleets[turns][1] + ships, owner) else: s = allFleets[turns][0] - ships if s < 0: allFleets[turns] = (-s, 1 if allFleets[turns][1] == 2 else 2) else: allFleets[turns] = (s, allFleets[turns][1]) #log.debug('all Fleets: ' + str(allFleets)) #now we get to figure out what happens once all the fleets have shown up # up until we can get there if we leave this turn #log.debug('before figuring out future of planet, currentShips = ' + str(currentShips)) lastTurn = 0 for turn in sorted(allFleets.keys()): fleet = allFleets[turn] turnsSinceLast = turn - lastTurn lastTurn = turn if currentShips[1] == 0: #planet is neutral, no growing pass else: #planet is either mine or enemy's, regardless grow by growthRate * turnsSinceLast currentShips[0] += growthRate * turnsSinceLast if fleet[1] == currentShips[1]: #fleet is from the owner of the planet currentShips[0] += fleet[0] else: currentShips[0] -= fleet[0] if currentShips[0] < 0: currentShips[1] = fleet[1] currentShips[0] = -currentShips[0] log.debug('after fleet ' + str(fleet) + ' showed up: ' + str(currentShips)) #add the growth between the last fleet showing up and when my fleet can get there if currentShips[1] != 0: currentShips[0] += (distance - lastTurn) * growthRate #log.debug('end of getShipsAtArriveTime()') return currentShips, distance