def findMaxExpenditureWhileKeeping(self): """ Assumes we own the planet in question """ # May have to adjust increment to prevent timeout increment = 4 # what if we do nothing? left = self.simulate() # we're gonna lose it, can't spend a dime if left <= 0: return 0 else: startingShips = self.startingShips maxSpend = 0 while left > 0: # can't spend more than you have if maxSpend + increment >= startingShips: break maxSpend += increment if startingShips <= increment: break self.startingShips -= maxSpend left = self.simulate() debug("left: " + str(left) + " spent: " + str(maxSpend)) # restore startingShips state self.startingShips = startingShips # check if we failed on last simulation # if so, take 2 back if left <= 0: return maxSpend - increment return maxSpend
def send(pw, my_planet, target, available_invasion_ships, distance): target_type = PlanetHelper.get_planet_type(target) if target.Owner() == 1: debug( "Send relief force {0} ships from planet id {1} to {2} planet id {3} which currently has {4} ships landed " "on it ".format(available_invasion_ships, my_planet.PlanetID(), target_type, target.PlanetID(), target.NumShips())) else: debug( "Send invasion force {0} ships from planet id {1} to {2} planet id {3} which currently has {4} ships " "landed on it ".format(available_invasion_ships, my_planet.PlanetID(), target_type, target.PlanetID(), target.NumShips())) # endif pw.IssueOrderByIds(my_planet.PlanetID(), target.PlanetID(), available_invasion_ships) pw._fleets.append( Fleet( 1, # Owner is ME available_invasion_ships, # Num ships my_planet, # Source target, # Destination distance, # Total trip length distance)) # Turns remaining) my_planet.NumShips(new_num_ships=my_planet.NumShips() - available_invasion_ships)
def identifyOpportunities(my_center_of_gravity, enemy_center_of_gravity, foreign_planets): calculated_opportunities = {} for foreign_planet in foreign_planets: distance_to_my_center = ( max_distance - (math.pow(my_center_of_gravity[0] - foreign_planet.X(), 2) + math.pow(my_center_of_gravity[1] - foreign_planet.Y(), 2)) ) / float(max_distance) distance_to_enemy_center = ( max_distance - (math.pow(enemy_center_of_gravity[0] - foreign_planet.X(), 2) + math.pow(enemy_center_of_gravity[1] - foreign_planet.Y(), 2)) ) / float(max_distance) values = [ foreign_planet.GrowthRate() / float(max_planet_size), float(distance_to_my_center), float(distance_to_enemy_center), foreign_planet.NumShips() / float(max_planet_ships), float(foreign_planet.Owner() - 1) ] opportunity = numpy.matmul(values, theta) calculated_opportunities[foreign_planet] = opportunity debug("Opportunity for planet {0} with {1} ships is {2}".format( foreign_planet, foreign_planet.NumShips(), opportunity)) # endfor return sorted(calculated_opportunities.items(), key=lambda x: x[1], reverse=True)
def BreakEvenTurns(pw, planet, fleetDistance): """Returns number of turns it will take to break even on taking this planet. """ if planet.GrowthRate() == 0: debug("wtf, ZERO GROWTH") return 10000 return int(ceil(FleetRequiredToTake(pw, planet, fleetDistance) + \ planet.NumShips() / float(planet.GrowthRate())))
def GeneralDefenseRequired(pw, planet, enemies): """How many reserves do I need to leave if they send everything at me?""" defense = 0 rate = planet.GrowthRate() for enemy in enemies: defense += enemy.NumShips() - \ rate * pw.Distance(enemy, planet) defense = int(ceil(defense)) debug("GeneralDefenseRequired planet " + str(planet.PlanetID()) + " " + str(defense)) return defense
def GeneralDefenseRequired(pw, planet, enemies): """How many reserves do I need to leave if they send everything at me?""" defense = 0 rate = planet.GrowthRate() for enemy in enemies: defense += enemy.NumShips() - \ rate*pw.Distance(enemy, planet) defense = int(ceil(defense)) debug("GeneralDefenseRequired planet " + str(planet.PlanetID()) + " " + str(defense)) return defense
def main(): debug("starting") map_data = '' while True: current_line = raw_input() if len(current_line) >= 2 and current_line.startswith("go"): pw = PlanetWars(map_data) DoTurn(pw) pw.FinishTurn() map_data = '' else: map_data += current_line + '\n'
def calculate_all_opportunities(turn, my_planet, pw, ignored_planets, total_invasion_ships_for_planet, max_ship_planets): targets_of_opportunity = {} for nearest_neighbour_ids in nearestNeighbors[my_planet.PlanetID()]: nearest_neighbour = pw.GetPlanet(nearest_neighbour_ids[0]) if my_planet.PlanetID() != nearest_neighbour.PlanetID( ) and not ignored_planets.count(nearest_neighbour.PlanetID()) > 0: distance_to_planet = distances[my_planet.PlanetID()][ nearest_neighbour.PlanetID()] necessary_ships_to_invade = utils.PlanetHelper.get_necessary_invasion_ships( nearest_neighbour, distance_to_planet, pw, max_distance) distance_percentage = distance_to_planet * 100.0 / max_distance fleet_percentage = total_invasion_ships_for_planet * 100.0 / max_ship_planets if necessary_ships_to_invade > 0: opportunity = fuzzy_logic.FuzzyFCL.crisp_output( turn, int(distance_percentage), total_invasion_ships_for_planet - necessary_ships_to_invade, nearest_neighbour.GrowthRate() * 100.0 / max_planet_size, int(fleet_percentage)) opportunity *= (11 - distance_percentage / 100.0) / 11.0 if nearest_neighbour.Owner() == 2: opportunity *= 1.07 elif nearest_neighbour.Owner() == 1: opportunity *= 1.25 targets_of_opportunity[nearest_neighbour] = opportunity debug( "processed neighbor {0} planet {1} currently contains {2} ships " " at distance {3} ({4}%). Necessary ships to take: {5}. Opp: {6}" .format( utils.PlanetHelper.get_planet_type(nearest_neighbour), nearest_neighbour.PlanetID(), nearest_neighbour.NumShips(), distance_percentage, distance_to_planet, necessary_ships_to_invade, opportunity)) else: debug("Ignoring planet {0} with {1} ships on it. It's fine.". format(nearest_neighbour.PlanetID(), nearest_neighbour.NumShips())) ignored_planets.append(nearest_neighbour.PlanetID()) # endif # endif # endfor return targets_of_opportunity
def FleetRequiredToTake(pw, planet, fleetDistance): """Returns the exact size of a fleet required to take the given planet. """ sim = PlanetSim(-planet.NumShips(), planet.GrowthRate(), planet.Owner()==0) for f in pw.Fleets(): if f.DestinationPlanet() == planet.PlanetID(): if f.Owner() == 2: sim.addFleet(f.TurnsRemaining(), -f.NumShips()) else: sim.addFleet(f.TurnsRemaining(), f.NumShips()) minFleet = sim.findMinFleetOwn(fleetDistance) debug(str(minFleet) + " required to take " + str(planet.PlanetID())) return minFleet
def FleetRequiredToTake(pw, planet, fleetDistance): """Returns the exact size of a fleet required to take the given planet. """ sim = PlanetSim(-planet.NumShips(), planet.GrowthRate(), planet.Owner() == 0) for f in pw.Fleets(): if f.DestinationPlanet() == planet.PlanetID(): if f.Owner() == 2: sim.addFleet(f.TurnsRemaining(), -f.NumShips()) else: sim.addFleet(f.TurnsRemaining(), f.NumShips()) minFleet = sim.findMinFleetOwn(fleetDistance) debug(str(minFleet) + " required to take " + str(planet.PlanetID())) return minFleet
def findMinFleetOwn(self, turn): # what if we do nothing left = self.simulate() if left > 0: # Already have it debug("Already have it") return 0 currFleetSize = 0 while left < 0: # May have to adjust increment to prevent timeout currFleetSize += 4 self.addFleet(turn, currFleetSize) left = self.simulate() #debug("currfleet: " + str(currFleetSize) + " left: " + str(left)) self.delFleet(turn, currFleetSize) if left == 0: currFleetSize += 1 return currFleetSize
def findMinFleetOwn(self, turn): # what if we do nothing left = self.simulate() if left > 0: # Already have it debug("Already have it") return 0 currFleetSize = 0 while left < 0: # May have to adjust increment to prevent timeout currFleetSize += 4 self.addFleet(turn, currFleetSize) left = self.simulate() # debug("currfleet: " + str(currFleetSize) + " left: " + str(left)) self.delFleet(turn, currFleetSize) if left == 0: currFleetSize += 1 return currFleetSize
def DefenseRequiredForIncoming(pw, planet): """How many reserves do I need to leave to protect me from the incoming waves?""" defense = 0 rate = planet.GrowthRate() for f in pw.EnemyFleets(): if f.DestinationPlanet() == planet.PlanetID(): adj = f.NumShips() - int(ceil(rate * f.TurnsRemaining())) if adj > 0: defense += adj # TODO, take into account incoming reinforcements # for f in pw.MyFleets(): # if f.DestinationPlanet() == planet.PlanetID(): # adj = f.NumShips() - int(ceil(rate*f.TurnsRemaining())) # if adj > 0: # defense -= adj defense = int(ceil(defense)) if defense != 0: debug("DefenseRequiredForIncoming planet " + str(planet.PlanetID()) + " " + str(defense)) return defense
def main(): global theta abs_path = os.path.dirname(os.path.abspath(__file__)) print "cwd:", os.path.dirname(os.path.abspath(__file__)) print "\r\n\r\n" with open(os.path.join(abs_path, "theta.txt")) as f: line = f.readline().split(" ") theta = map(lambda x: float(x), line) #endwith debug("starting") map_data = '' while True: current_line = raw_input() if len(current_line) >= 2 and current_line.startswith("go"): pw = PlanetWars(map_data) DoTurn(pw) pw.FinishTurn() map_data = '' else: map_data += current_line + '\n'
def DefenseRequiredForIncoming(pw, planet): """How many reserves do I need to leave to protect me from the incoming waves?""" defense = 0 rate = planet.GrowthRate() for f in pw.EnemyFleets(): if f.DestinationPlanet() == planet.PlanetID(): adj = f.NumShips() - int(ceil(rate*f.TurnsRemaining())) if adj > 0: defense += adj # TODO, take into account incoming reinforcements #for f in pw.MyFleets(): # if f.DestinationPlanet() == planet.PlanetID(): # adj = f.NumShips() - int(ceil(rate*f.TurnsRemaining())) # if adj > 0: # defense -= adj defense = int(ceil(defense)) if defense != 0: debug("DefenseRequiredForIncoming planet " + str(planet.PlanetID()) + " " + str(defense)) return defense
def identify_opportunities(my_center_of_gravity, enemy_center_of_gravity, foreign_planets, my_planets, enemy_planets): calculated_opportunities = {} if len(my_planets) > 0 and len(enemy_planets) > 0: for foreign_planet in foreign_planets: distance_to_my_center = ( max_distance - (math.pow(my_center_of_gravity[0] - foreign_planet.X(), 2) + math.pow(my_center_of_gravity[1] - foreign_planet.Y(), 2)) ) / float(max_distance) distance_to_enemy_center = ( max_distance - (math.pow(enemy_center_of_gravity[0] - foreign_planet.X(), 2) + math.pow(enemy_center_of_gravity[1] - foreign_planet.Y(), 2)) ) / float(max_distance) growth_rate = foreign_planet.GrowthRate() / float(max_planet_size) values = [ growth_rate, growth_rate * distance_to_my_center / distance_to_enemy_center, (foreign_planet.NumShips() * distance_to_my_center) / (float(max_planet_ships) * distance_to_enemy_center), float(3 - foreign_planet.Owner() * 2.0), float(3 - foreign_planet.Owner() * 2.0) * growth_rate, growth_rate * len(my_planets) / (len(enemy_planets) + 1), ] assert (len(values) == NUMBER_OF_FEATURES - 3 ) # last feature decides to carry out unsuccessful attacks opportunity = numpy.matmul(values, theta[:-3]) calculated_opportunities[foreign_planet] = opportunity debug("Opportunity for planet {0} with {1} ships is {2}".format( foreign_planet, foreign_planet.NumShips(), opportunity)) # endfor return sorted(calculated_opportunities.items(), key=lambda x: x[1], reverse=True) else: return None
def main(): debug("starting") map_data = '' while(True): current_line = raw_input() if len(current_line) >= 2 and current_line.startswith("go"): pw = PlanetWars(map_data) debug("NEW TURN") DoTurn(pw) pw.FinishTurn() debug("TURN FINISHED") map_data = '' else: map_data += current_line + '\n'
def main(): import sys global theta if len(sys.argv) >= NUMBER_OF_FEATURES: debug("theta from commandline args") theta = sys.argv[1:] new_list = [] for element in theta: new_list.append([float(element)]) theta = new_list else: debug("random theta") # theta = [1.07668319, -4.67252562, -4.83999886, -3.78736198, -2.50656436, 3.8234228, 0.2380] theta = [ 0.25499724, -0.03653183, -0.04419227, -0.34623976, 0.67157856, 0.39569266, 0.05, 0.27693781, 0.5 ] # endif debug("starting for theta: {0}".format(str(theta))) # with open("results.txt", "a+") as f: # for i in range(NUMBER_OF_FEATURES): # elem = theta[i][0] # f.write("{0} ".format(elem)) map_data = '' while True: current_line = raw_input() if len(current_line) >= 2 and current_line.startswith("go"): pw = PlanetWars(map_data) DoTurn(pw) pw.FinishTurn() map_data = '' else: map_data += current_line + '\n'
def DoTurn(pw): defendedPlanets = [] vulnerablePlanets = [] enemyPlanets = pw.EnemyPlanets() neutralPlanets = pw.NeutralPlanets() myFleets = pw.MyFleets() enemyFleets = pw.EnemyFleets() enemySize = 0 mySize = 0 # How am I doing? debug("status") for p in pw.MyPlanets(): mySize = mySize + p.NumShips() if p.NumShips() > DefenseRequiredForIncoming(pw, p) and \ p.NumShips() > .5*GeneralDefenseRequired(pw, p, enemyPlanets): defendedPlanets.append(p) else: vulnerablePlanets.append(p) # How is the enemy doing? for p in enemyPlanets: enemySize = enemySize + p.NumShips() if ( enemySize <= 0 ): winRatio = 0 else: winRatio = float(mySize)/enemySize debug("Ratio: " + str(winRatio)) # Should I go for the kill? if winRatio > 1.5: debug("Kill Kill Kill!!!!") for p in enemyPlanets: alreadySent = 0 for mp in pw.MyPlanets(): defenseReq = max(DefenseRequiredForIncoming(pw,mp), int(ceil(.05*GeneralDefenseRequired(pw, mp, enemyPlanets)))) toSend = mp.NumShips() # Don't put youtself at too much risk if defenseReq > 0: toSend -= defenseReq # Only send enough to kill necToKill = FleetRequiredToTake(pw, p, pw.Distance(mp, p)) if necToKill > 0: if necToKill - alreadySent < toSend: toSend = necToKill - alreadySent else: toSend = 0 if toSend > 0 and mp.NumShips() - toSend > 0: pw.IssueOrder(mp, p, toSend) debug(str(mp.PlanetID()) + " sent " + str(toSend) + \ " to " + str(p.PlanetID())) mp.NumShips(mp.NumShips()-toSend) debug(str(mp.NumShips()) + " left") alreadySent += toSend return # Look for a good bargin debug("looking for bargins") attackedPlanets = [] for f in myFleets: attackedPlanets.append(f.DestinationPlanet()) if len(defendedPlanets)==0: debug("no defense, might as well attack") defendedPlanets = vulnerablePlanets for taker in defendedPlanets: debug(str(taker.PlanetID())) for p in enemyPlanets+neutralPlanets: if attackedPlanets.count(p.PlanetID()) > 0: continue dist = pw.Distance(p, taker) if BreakEvenTurns(pw, p, dist) < 50: defenseReq = max(DefenseRequiredForIncoming(pw, p), int(ceil(.25*GeneralDefenseRequired(pw, p, enemyPlanets)))) attackFleetSize = FleetRequiredToTake(pw, p, dist) if defenseReq > 0: attackFleetSize = attackFleetSize + defenseReq if attackFleetSize > 0 and taker.NumShips() > attackFleetSize: debug(str(taker.PlanetID()) + " sent " + str(attackFleetSize) + \ " to " + str(p.PlanetID())) pw.IssueOrder(taker, p, attackFleetSize) taker.NumShips(taker.NumShips()-attackFleetSize) attackedPlanets.append(p.PlanetID()) break else: debug("not enough ships")
def DoTurn(pw): my_planets = utils.PlanetHelper.get_my_planets(pw) enemy_planets = utils.PlanetHelper.get_enemy_planets(pw) foreign_planets = utils.PlanetHelper.get_foreign_planets(pw) my_center_of_gravity = utils.CenterOfGravity.calculate_center_of_gravity( my_planets) enemy_center_of_gravity = utils.CenterOfGravity.calculate_center_of_gravity( enemy_planets) all_center_of_gravity = utils.CenterOfGravity.calculate_center_of_gravity( pw.Planets()) global game_turn global max_planet_ships my_size = sum(p.NumShips() for p in my_planets) enemy_size = sum(p.NumShips() for p in enemy_planets) max_planet_ships = max(p.NumShips() for p in pw.Planets()) if my_size <= 0: win_ratio = 0 elif enemy_size <= 0: win_ratio = 1 else: win_ratio = float(my_size) / enemy_size # endif try: start_time = time.time() debug("DO TURN {0}. I have {1} planets".format(game_turn, len(my_planets))) debug("WIN Ratio: " + str(win_ratio) + "\n") if len(distances) == 0: debug("Computing distances") compute_planet_distances_and_max_planet_size(pw) # endif # debug("I have {0} planets".format(len(my_planets))) index = 0 planet_opportunities = identifyOpportunities(my_center_of_gravity, enemy_center_of_gravity, foreign_planets) for target_planet, opportunity_number in planet_opportunities[:5]: my_sorted_planets_for_target = sorted( my_planets, key=lambda x: distances[target_planet.PlanetID()][x.PlanetID() ]) for my_planet in my_sorted_planets_for_target: if my_planet.NumShips() <= 1: continue # endif distance_to_planet = distances[target_planet.PlanetID()][ my_planet.PlanetID()] total_invasion_ships_for_planet = utils.PlanetHelper.get_available_invasion_ships( my_planet, pw) debug( "Planet nr. {0} with {1} ships. {2} available for attack". format(index, my_planet.NumShips(), total_invasion_ships_for_planet)) necessary_ships_to_invade = utils.PlanetHelper.get_necessary_invasion_ships( target_planet, distance_to_planet, pw, max_distance) if necessary_ships_to_invade > 0 and total_invasion_ships_for_planet > 0: necessary_ships_to_invade += 1 sent_ships = min(total_invasion_ships_for_planet, necessary_ships_to_invade) assert (my_planet.Owner() == 1) utils.Utils.send( pw, my_planet, target_planet, sent_ships, math.ceil(distances[my_planet.PlanetID()][ target_planet.PlanetID()])) necessary_ships_to_invade = \ utils.PlanetHelper.get_necessary_invasion_ships(target_planet, distance_to_planet, pw, max_distance) debug( "AFTER SENDING SHIPS! Target of opportunity {0} planet {1} currently contains {2} ships " "at distance {3}. Necessary ships to take: {4}".format( utils.PlanetHelper.get_planet_type(target_planet), target_planet.PlanetID(), target_planet.NumShips(), distance_to_planet, necessary_ships_to_invade)) # endif # endfor # endfor debug("END TURN {0} in time: {1} ms\n".format( game_turn, (time.time() - start_time) * 1000)) game_turn += 1 except Exception, e: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] debug(str(exc_type) + str(fname) + str(exc_tb.tb_lineno)) debug(str(e) + str(e.message)) raise e
print "ships surplus index:", ships_surplus_index for planet_size_percentage in range(0, PLANET_SIZE_MAX_LIMIT + 1): print "planet size index:", planet_size_percentage for fleet_size_percentage in range( 0, PLANET_SIZE_MAX_LIMIT + 1): try: result = crisp_output(game_time_index, distance_index, ships_surplus_index, planet_size_percentage, fleet_size_percentage) # line = "{0} : {1},\n".format( # (game_time_index, distance_index, ships_surplus_index, planet_size_percentage, fleet_size_percentage), result) #print line except Exception, e: print "ships", ships_surplus_index print "planet size", planet_size_percentage print "fleet size", fleet_size_percentage exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split( exc_tb.tb_frame.f_code.co_filename)[1] debug( str(exc_type) + str(fname) + str(exc_tb.tb_lineno)) raise e #endfor #endfor #endfor #endif
def DoTurn(pw): orders = [] urgentPlanets = [] myPlanets = [] enemyTargets = [] enemyPlanets = pw.EnemyPlanets() neutralPlanets = pw.NeutralPlanets() myFleets = pw.MyFleets() enemyFleets = pw.EnemyFleets() enemySize = 0 mySize = 0 # Interplanetary distances will come in handy if not distances: ComputePlanetDistances(pw) # How am I doing? debug("Status") for p in pw.MyPlanets(): mySize = mySize + p.NumShips() defInc = DefenseRequiredForIncoming(pw, p) # Who needs help urgently, and how much? if p.NumShips() < defInc: urgentPlanets.append((p, defInc)) else: myPlanets.append( (p, int(ceil(.75 * GeneralDefenseRequired(pw, p))))) # How is the enemy doing? for p in enemyPlanets: enemySize = enemySize + p.NumShips() if (enemySize <= 0): winRatio = 0 else: winRatio = float(mySize) / enemySize debug("Ratio: " + str(winRatio)) # Defend myself first debug("Defense") # some urgent planets are more urgent urgentPlanets.sort(key=lambda x: x[0].GrowthRate(), reverse=True) for helpme in urgentPlanets: totalNeeded = helpme[1] helpsofar = 0 plannedSend = [] # Make a defense plan. Prefer close help for helper in sorted(myPlanets, key=lambda x: Distance(x[0], helpme[0])): # Don't undefend yourself tosend = helper[0].NumShips() defReq = helper[1] if defReq > 0: tosend -= defReq if tosend <= 0: continue # Only send what is still needed stillNeeded = totalNeeded - helpsofar if tosend > stillNeeded: tosend = stillNeeded plannedSend.append((helper[0], helpme[0], tosend)) helpsofar += tosend if helpsofar >= totalNeeded: break # issue actual orders if helpsofar >= totalNeeded: for p in plannedSend: pw.IssueOrder(p[0], p[1], p[2]) remaining = p[0].NumShips() - p[2] DebugOrder(p[0], p[1], p[2], remaining) orders.append(p) p[0].NumShips(remaining) # else, TODO: this planet is BONED until I fix # Maximize investments, Minimize enemy if winRatio >= 1.5: debug("KILL KILL KILL!!!") targets = enemyPlanets else: targets = enemyPlanets + neutralPlanets debug("Offense") for taker in myPlanets: debug(str(taker[0].PlanetID())) defenseReq = max(DefenseRequiredForIncoming(pw, taker[0]), \ int(ceil(.10 * GeneralDefenseRequired(pw, taker[0])))) surplus = taker[0].NumShips() if defenseReq > 0: surplus -= defenseReq debug("surplus " + str(surplus) + " defenseReq: " + str(defenseReq)) potTargets = [] # Calculate investement risks for this taker for p in targets: dist = Distance(p.PlanetID(), taker[0].PlanetID()) breakEvenTurns = BreakEvenTurns(pw, p, dist) potTargets.append((p, breakEvenTurns)) # Prefer lower risk, take as many targets as possible potTargets.sort(key=lambda x: x[1]) for potTarget in potTargets: needed = FleetRequiredToTake(pw, potTarget[0], \ Distance(potTarget[0].PlanetID(), p.PlanetID())) isenemy = False if potTarget[0].Owner() == 2: isenemy = True debug("need " + str(needed) + " to take " + str(potTarget[0].PlanetID()) + " isenemy? " + str(isenemy)) # take if we can if needed > 0 and surplus > needed: pw.IssueOrder(taker[0], potTarget[0], needed) remaining = taker[0].NumShips() - needed DebugOrder(taker[0], potTarget[0], needed, remaining) taker[0].NumShips(remaining) surplus -= needed # remove this from the targets list for t in targets: if t.PlanetID() == potTarget[0].PlanetID(): targets.remove(t) break elif surplus <= 0: break
def DoTurn(pw): global actual_distances, nearest_neighbors, distances, game_turn, max_planet_ships, max_distance my_planets = utils.PlanetHelper.get_my_planets(pw) enemy_planets = utils.PlanetHelper.get_enemy_planets(pw) foreign_planets = utils.PlanetHelper.get_foreign_planets(pw) my_center_of_gravity = utils.CenterOfGravity.calculate_center_of_gravity( my_planets) enemy_center_of_gravity = utils.CenterOfGravity.calculate_center_of_gravity( enemy_planets) all_center_of_gravity = utils.CenterOfGravity.calculate_center_of_gravity( pw.Planets()) my_size = sum(p.NumShips() for p in my_planets) enemy_size = sum(p.NumShips() for p in enemy_planets) max_planet_ships = max(p.NumShips() for p in pw.Planets()) if my_size <= 0: win_ratio = 0 elif enemy_size <= 0: win_ratio = 1 else: win_ratio = float(my_size) / enemy_size # endif try: start_time = time.time() debug("DO TURN {0}. I have {1} planets".format(game_turn, len(my_planets))) debug("WIN Ratio: " + str(win_ratio) + "\n") if len(distances) == 0: debug("Computing distances") actual_distances, nearest_neighbors, distances, max_distance = \ compute_planet_distances_and_max_planet_size(pw, max_planet_size, max_distance, nearest_neighbors) # endif # Defense first! for my_planet in my_planets: result = utils.PlanetHelper.get_needed_defense_ships(my_planet, pw) if result is not None: turn, ships_needed = result debug( "I have {0} planet that needs help of {1} ships in {2} turns" .format(my_planet, ships_needed, turn)) mp_without_target = my_planets mp_without_target.remove(my_planet) if mp_without_target is not None: my_sorted_planets_for_target = sorted( mp_without_target, key=lambda x: distances[my_planet.PlanetID()][ x.PlanetID()]) for my_closest_planet in my_sorted_planets_for_target: available_ships = utils.PlanetHelper.get_available_invasion_ships( my_closest_planet, pw) debug( "Available ships on planet {0} = {1} ships".format( my_closest_planet.PlanetID(), available_ships)) if available_ships > 0: send( pw, my_closest_planet, my_planet, available_ships, math.ceil( distances[my_closest_planet.PlanetID()][ my_planet.PlanetID()])) ships_needed = ships_needed - available_ships # endif if ships_needed <= 0: break # endif # endfor # endif # endif # endfor index = 0 planet_opportunities = identify_opportunities(my_center_of_gravity, enemy_center_of_gravity, foreign_planets, my_planets, enemy_planets) if planet_opportunities is not None: # Attack for target_planet, opportunity_number in planet_opportunities[:10]: if target_planet.GrowthRate() > 0: my_sorted_planets_for_target = sorted( my_planets, key=lambda x: distances[target_planet.PlanetID()][ x.PlanetID()]) for my_planet in my_sorted_planets_for_target: available_ships = utils.PlanetHelper.get_available_invasion_ships( my_planet, pw) if my_planet.NumShips() <= 4 or available_ships <= 1: continue # endif distance_to_planet = distances[ target_planet.PlanetID()][my_planet.PlanetID()] total_invasion_ships_for_planet = utils.PlanetHelper.get_available_invasion_ships( my_planet, pw) debug( "Planet nr. {0} with {1} ships. {2} available for attack" .format(index, my_planet.NumShips(), total_invasion_ships_for_planet)) necessary_ships_to_invade = utils.PlanetHelper.get_necessary_invasion_ships( target_planet, distance_to_planet, pw, max_distance) if necessary_ships_to_invade > 0 and total_invasion_ships_for_planet > 0: necessary_ships_to_invade += 1 ship_ratio = available_ships / necessary_ships_to_invade invade_factor = ship_ratio * theta[-2] + ship_ratio * theta[-1] * \ distances[my_planet.PlanetID()][target_planet.PlanetID()] / max_distance + \ ship_ratio * theta[-3] * win_ratio if invade_factor > .1: sent_ships = min( total_invasion_ships_for_planet, necessary_ships_to_invade) assert (my_planet.Owner() == 1) send( pw, my_planet, target_planet, sent_ships, math.ceil(distances[my_planet.PlanetID()][ target_planet.PlanetID()])) necessary_ships_to_invade = \ utils.PlanetHelper.get_necessary_invasion_ships(target_planet, distance_to_planet, pw, max_distance) debug( "AFTER SENDING SHIPS! Target of opportunity {0} planet {1} " "currently contains {2} ships at distance {3}. Necessary ships to take: {4}" .format( utils.PlanetHelper.get_planet_type( target_planet), target_planet.PlanetID(), target_planet.NumShips(), distance_to_planet, necessary_ships_to_invade)) else: debug( "DIDN'T SEND SHIPS! Target of opportunity {0} planet {1} currently contains {2} ships " "at distance {3}. Necessary ships to take: {4}" .format( utils.PlanetHelper.get_planet_type( target_planet), target_planet.PlanetID(), target_planet.NumShips(), distance_to_planet, necessary_ships_to_invade)) # endif # endfor # endif # endfor # endif debug("END TURN {0} in time: {1} ms\n".format( game_turn, (time.time() - start_time) * 1000)) game_turn += 1 except Exception, e: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] debug(str(exc_type) + str(fname) + str(exc_tb.tb_lineno)) debug(str(e) + str(e.message)) raise e
def DebugOrder(attacker, to, amount, remaining): debug(str(attacker.PlanetID()) + " sent " + \ str(amount) + " to " + str(to.PlanetID()) + \ ", " + str(remaining) + " remaining")
def DoTurn(pw): my_planets = pw.MyPlanets() enemy_planets = pw.EnemyPlanets() enemy_size = 0 my_size = 0 global game_turn global max_planet_ships max_planet_ships = 0 for planet in my_planets: my_size += planet.NumShips() if planet.NumShips() > max_planet_ships: max_planet_ships = planet.NumShips() # endif # endfor for planet in enemy_planets: enemy_size += planet.NumShips() if planet.NumShips() > max_planet_ships: max_planet_ships = planet.NumShips() # endif # endfor if (enemy_size <= 0) or (my_size <= 0): winRatio = 0 else: winRatio = float(my_size) / enemy_size # endif try: start_time = time.time() debug("DO TURN {0}. I have {1} planets".format(game_turn, len(my_planets))) debug("WIN Ratio: " + str(winRatio) + "\n") if len(distances) == 0: compute_planet_distances(pw) # endif my_planets = utils.PlanetHelper.get_my_planets(pw) # debug("I have {0} planets".format(len(my_planets))) index = 0 ignored_planets = [] for my_planet in sorted(my_planets, key=lambda x: x.NumShips(), reverse=True): total_invasion_ships_for_planet = utils.PlanetHelper.get_available_invasion_ships( my_planet, pw) # debug("Planet nr. {0} with {1} ships. {2} available for attack" # .format(index, my_planet.NumShips(), total_invasion_ships_for_planet)) index += 1 if total_invasion_ships_for_planet > 0: # debug("Planning invasions from planet {0} that contains currently {1} ships. " # "Available for invasion: {2} ships" # .format(my_planet.PlanetID(), my_planet.NumShips(), total_invasion_ships_for_planet)) ignored_planets = invade_planets( my_planet, pw, total_invasion_ships_for_planet, game_turn, ignored_planets, winRatio, max_planet_ships) debug("ignored planets {0}".format(len(ignored_planets))) else: debug( "Planet {0} with {1} ships cannot attack, it will be overrun soon..." .format(my_planet.PlanetID(), my_planet.NumShips())) # endif if index > 4: return # endfor debug("END TURN {0} in time: {1} ms\n".format( game_turn, (time.time() - start_time) * 1000)) game_turn += 1 except Exception, e: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] debug(str(exc_type) + str(fname) + str(exc_tb.tb_lineno)) debug(str(e) + str(e.message)) raise e
def invade_planets(my_planet, pw, total_invasion_ships_for_planet, turn, ignored_planets, win_ratio, max_ship_planets): global max_planet_size, max_distance try: debug( "invade planets from planet {0}. Invasion fleet available: {1} out of {2} ships. Neighbors: {3}" .format(my_planet.PlanetID(), total_invasion_ships_for_planet, my_planet.NumShips(), len(nearestNeighbors[my_planet.PlanetID()]))) targets_of_opportunity = calculate_all_opportunities( turn, my_planet, pw, ignored_planets, total_invasion_ships_for_planet, max_ship_planets) opportunity_targets = reversed( sorted(targets_of_opportunity, key=targets_of_opportunity.get)) own_planets_index = 0 opportunity_targets_own_planets_first = [] for opportunity_target in opportunity_targets: if opportunity_target.Owner() == 1: opportunity_targets_own_planets_first.insert( own_planets_index, opportunity_target) own_planets_index += 1 # endif else: opportunity_targets_own_planets_first.append( opportunity_target) # endif # endfor limit_index = 0 for opportunity_target in opportunity_targets_own_planets_first: distance_to_planet = distances[my_planet.PlanetID()][ opportunity_target.PlanetID()] debug( "{0} Target: {1} planet {2} at distance {3} with currently {4} ships on it. Opportunity: {5}" .format(limit_index, utils.PlanetHelper.get_planet_type(opportunity_target), opportunity_target.PlanetID(), distance_to_planet, opportunity_target.NumShips(), targets_of_opportunity[opportunity_target])) if limit_index > ATTACK_LIMIT: break # endif limit_index += 1 if targets_of_opportunity[ opportunity_target] < 0.12 and opportunity_target.Owner( ) != 1 and win_ratio < 5: if opportunity_target.Owner != 1: debug( "finished own defense. better wait opportunity is: {0}. target was: {1} with {2} ships. " "distance percentage to max distance ever: {3}".format( targets_of_opportunity[opportunity_target], opportunity_target.PlanetID(), opportunity_target.NumShips(), distance_to_planet * 100.0 / max_distance)) return ignored_planets # endif # endif sent_ships = 0 necessary_ships_to_invade = \ utils.PlanetHelper.get_necessary_invasion_ships(opportunity_target, distance_to_planet, pw, max_distance) debug( "Target of opportunity {0} planet {1} currently contains {2} ships with " "opportunity {3} at distance {4}. Necessary ships to take: {5}" .format(utils.PlanetHelper.get_planet_type(opportunity_target), opportunity_target.PlanetID(), opportunity_target.NumShips(), targets_of_opportunity[opportunity_target], distance_to_planet, necessary_ships_to_invade)) if necessary_ships_to_invade > 0: necessary_ships_to_invade += 1 sent_ships = min(total_invasion_ships_for_planet, necessary_ships_to_invade) utils.Utils.send( pw, my_planet, opportunity_target, sent_ships, math.ceil(distances[my_planet.PlanetID()][ opportunity_target.PlanetID()])) necessary_ships_to_invade = \ utils.PlanetHelper.get_necessary_invasion_ships(opportunity_target, distance_to_planet, pw, max_distance) debug( "AFTER SENDING SHIPS! Target of opportunity {0} planet {1} currently contains {2} ships with " "opportunity {3} at distance {4}. Necessary ships to take: {5}" .format( utils.PlanetHelper.get_planet_type(opportunity_target), opportunity_target.PlanetID(), opportunity_target.NumShips(), targets_of_opportunity[opportunity_target], distance_to_planet, necessary_ships_to_invade)) if sent_ships > necessary_ships_to_invade: ignored_planets.append(opportunity_target.PlanetID()) # endif # endif total_invasion_ships_for_planet -= sent_ships if total_invasion_ships_for_planet <= 0: debug("finished invasion ships {0}".format( total_invasion_ships_for_planet)) return ignored_planets # endif # endfor return ignored_planets except Exception, e: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] debug(str(exc_type) + str(fname) + str(exc_tb.tb_lineno)) debug(str(e) + str(e.message)) raise e
def DoTurn(pw): orders = [] urgentPlanets = [] myPlanets = [] enemyTargets = [] enemyPlanets = pw.EnemyPlanets() neutralPlanets = pw.NeutralPlanets() myFleets = pw.MyFleets() enemyFleets = pw.EnemyFleets() enemySize = 0 mySize = 0 # Interplanetary distances will come in handy if not distances: ComputePlanetDistances(pw) # How am I doing? debug("Status") for p in pw.MyPlanets(): mySize = mySize + p.NumShips() defInc = DefenseRequiredForIncoming(pw, p) # Who needs help urgently, and how much? if p.NumShips() < defInc: urgentPlanets.append((p, defInc)) else: myPlanets.append((p, int(ceil(.75*GeneralDefenseRequired(pw, p))))) # How is the enemy doing? for p in enemyPlanets: enemySize = enemySize + p.NumShips() if ( enemySize <= 0 ): winRatio = 0 else: winRatio = float(mySize)/enemySize debug("Ratio: " + str(winRatio)) # Defend myself first debug("Defense") # some urgent planets are more urgent urgentPlanets.sort(key=lambda x: x[0].GrowthRate(), reverse=True) for helpme in urgentPlanets: totalNeeded = helpme[1] helpsofar = 0 plannedSend = [] # Make a defense plan. Prefer close help for helper in sorted(myPlanets, key=lambda x: Distance(x[0],helpme[0])): # Don't undefend yourself tosend = helper[0].NumShips() defReq = helper[1] if defReq > 0: tosend -= defReq if tosend <= 0: continue # Only send what is still needed stillNeeded = totalNeeded - helpsofar if tosend > stillNeeded: tosend = stillNeeded plannedSend.append((helper[0], helpme[0], tosend)) helpsofar += tosend if helpsofar >= totalNeeded: break # issue actual orders if helpsofar >= totalNeeded: for p in plannedSend: pw.IssueOrder(p[0], p[1], p[2]) remaining = p[0].NumShips()-p[2] DebugOrder(p[0], p[1], p[2], remaining) orders.append(p) p[0].NumShips(remaining) # else, TODO: this planet is BONED until I fix # Maximize investments, Minimize enemy if winRatio >= 1.5: debug("KILL KILL KILL!!!") targets = enemyPlanets else: targets = enemyPlanets+neutralPlanets debug("Offense") for taker in myPlanets: debug(str(taker[0].PlanetID())) defenseReq = max(DefenseRequiredForIncoming(pw, taker[0]), \ int(ceil(.10*GeneralDefenseRequired(pw, taker[0])))) surplus = taker[0].NumShips() if defenseReq > 0: surplus -= defenseReq debug("surplus " + str(surplus) + " defenseReq: " + str(defenseReq)) potTargets = [] # Calculate investement risks for this taker for p in targets: dist = Distance(p.PlanetID(), taker[0].PlanetID()) breakEvenTurns = BreakEvenTurns(pw, p, dist) potTargets.append((p, breakEvenTurns)) # Prefer lower risk, take as many targets as possible potTargets.sort(key=lambda x: x[1]) for potTarget in potTargets: needed = FleetRequiredToTake(pw, potTarget[0], \ Distance(potTarget[0].PlanetID(), p.PlanetID())) isenemy = False if potTarget[0].Owner() == 2: isenemy = True debug("need " + str(needed) + " to take " + str(potTarget[0].PlanetID()) + " isenemy? " + str(isenemy)) # take if we can if needed > 0 and surplus > needed: pw.IssueOrder(taker[0], potTarget[0], needed) remaining = taker[0].NumShips() - needed DebugOrder(taker[0], potTarget[0], needed, remaining) taker[0].NumShips(remaining) surplus -= needed # remove this from the targets list for t in targets: if t.PlanetID() == potTarget[0].PlanetID(): targets.remove(t) break elif surplus <= 0: break
def DoTurn(pw): defendedPlanets = [] vulnerablePlanets = [] enemyPlanets = pw.EnemyPlanets() neutralPlanets = pw.NeutralPlanets() myFleets = pw.MyFleets() enemyFleets = pw.EnemyFleets() enemySize = 0 mySize = 0 # How am I doing? debug("status") for p in pw.MyPlanets(): mySize = mySize + p.NumShips() if p.NumShips() > DefenseRequiredForIncoming(pw, p) and \ p.NumShips() > .5*GeneralDefenseRequired(pw, p, enemyPlanets): defendedPlanets.append(p) else: vulnerablePlanets.append(p) # How is the enemy doing? for p in enemyPlanets: enemySize = enemySize + p.NumShips() if (enemySize <= 0): winRatio = 0 else: winRatio = float(mySize) / enemySize debug("Ratio: " + str(winRatio)) # Should I go for the kill? if winRatio > 1.5: debug("Kill Kill Kill!!!!") for p in enemyPlanets: alreadySent = 0 for mp in pw.MyPlanets(): defenseReq = max( DefenseRequiredForIncoming(pw, mp), int( ceil(.05 * GeneralDefenseRequired(pw, mp, enemyPlanets)))) toSend = mp.NumShips() # Don't put youtself at too much risk if defenseReq > 0: toSend -= defenseReq # Only send enough to kill necToKill = FleetRequiredToTake(pw, p, pw.Distance(mp, p)) if necToKill > 0: if necToKill - alreadySent < toSend: toSend = necToKill - alreadySent else: toSend = 0 if toSend > 0 and mp.NumShips() - toSend > 0: pw.IssueOrder(mp, p, toSend) debug(str(mp.PlanetID()) + " sent " + str(toSend) + \ " to " + str(p.PlanetID())) mp.NumShips(mp.NumShips() - toSend) debug(str(mp.NumShips()) + " left") alreadySent += toSend return # Look for a good bargin debug("looking for bargins") attackedPlanets = [] for f in myFleets: attackedPlanets.append(f.DestinationPlanet()) if len(defendedPlanets) == 0: debug("no defense, might as well attack") defendedPlanets = vulnerablePlanets for taker in defendedPlanets: debug(str(taker.PlanetID())) for p in enemyPlanets + neutralPlanets: if attackedPlanets.count(p.PlanetID()) > 0: continue dist = pw.Distance(p, taker) if BreakEvenTurns(pw, p, dist) < 50: defenseReq = max( DefenseRequiredForIncoming(pw, p), int(ceil(.25 * GeneralDefenseRequired(pw, p, enemyPlanets)))) attackFleetSize = FleetRequiredToTake(pw, p, dist) if defenseReq > 0: attackFleetSize = attackFleetSize + defenseReq if attackFleetSize > 0 and taker.NumShips() > attackFleetSize: debug(str(taker.PlanetID()) + " sent " + str(attackFleetSize) + \ " to " + str(p.PlanetID())) pw.IssueOrder(taker, p, attackFleetSize) taker.NumShips(taker.NumShips() - attackFleetSize) attackedPlanets.append(p.PlanetID()) break else: debug("not enough ships")