Last active
February 28, 2017 16:32
-
-
Save sandordargo/705965bc55a0e9cafca9b6852c0fcf97 to your computer and use it in GitHub Desktop.
ghost in the cell bronze top 50
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
import sys | |
from collections import defaultdict | |
# send to multiples from one, if can | |
# if closest is enemy and three or two, bomb | |
# zero prod could bomb | |
class Increase(object): | |
def __init__(self, factory): | |
self.factory = factory | |
def __str__(self): | |
return "INC {}".format(self.factory) | |
class Move(object): | |
def __init__(self, source, target, size=100): | |
self.source = source | |
self.target = target | |
self.size = size | |
def __str__(self): | |
return "MOVE {} {} {}".format(self.source, self.target, self.size) | |
class BombAction(object): | |
def __init__(self, source, target): | |
self.source = source | |
self.target = target | |
def __str__(self): | |
return "BOMB {} {}".format(self.source, self.target) | |
class Link(object): | |
def __init__(self, factory_1, factory_2, distance): | |
self.factory_1 = factory_1 | |
self.factory_2 = factory_2 | |
self.distance = distance | |
def __str__(self): | |
return "LINK from {} to {} takes {}".format(self.factory_1, self.factory_2, self.distance) | |
class Factory(object): | |
def __init__(self, entity_id, owner, population, production): | |
self.entity_id = entity_id | |
self.owner = owner | |
self.population = population | |
self.production = production | |
def __repr__(self): | |
return "*** id: {id}, owner: {owner}, population: {population}, production: {production}\n***".format( | |
id=self.entity_id, owner=self.owner, | |
population=self.population, production=self.production) | |
def __str__(self): | |
return self.__repr__() | |
class Troop(object): | |
def __init__(self, entity_id, owner, source, target, size, turns_to_arrive): | |
self.entity_id = entity_id | |
self.owner = owner | |
self.source = source | |
self.target = target | |
self.size = size | |
self.turns_to_arrive = turns_to_arrive | |
def __repr__(self): | |
return "*** id: {id}, owner: {owner}, source: {source}, target: {target}, size: {size}: arrival {arrival}***".format( | |
id=self.entity_id, owner=self.owner, source=self.source, target=self.target, | |
size=self.size, arrival=self.turns_to_arrive) | |
class Bomb(object): | |
def __init__(self, entity_id, owner, source, target, turns_to_arrive): | |
self.entity_id = entity_id | |
self.owner = owner | |
self.source = source | |
self.target = target | |
self.turns_to_arrive = turns_to_arrive | |
def get_factory_by_id(factories, id): | |
for factory in factories: | |
if factory.entity_id == id: | |
return factory | |
class Game(object): | |
def __init__(self, links, bombs_available): | |
self.links = links | |
self.bombs_available = bombs_available | |
self.turns = 0 | |
self.turns_since_last_bomb = 0 | |
self.factories = [] | |
self.bombs = [] | |
def get_next_turn(self): | |
actions = [] | |
for factory in self.get_own_factories(): | |
new_actions = self.get_next_action_of_factory(factory) | |
if new_actions: | |
actions.extend(new_actions) | |
action_strings = [str(action) for action in actions] | |
if not action_strings: | |
print("WAIT") | |
return | |
print(";".join(action_strings)) | |
def get_own_factories(self): | |
return [factory for factory in self.factories if factory.owner == 1] | |
def get_next_action_of_factory(self, factory): | |
moves = [] | |
candidate_points_map = defaultdict(float) | |
for candidate in self.factories: | |
if candidate == factory: | |
continue | |
candidate_points_map[candidate] = self.calculate_value_of(candidate, factory) | |
print("NEW TURN for factory {}".format(factory.entity_id), file=sys.stderr) | |
for w in sorted(candidate_points_map, key=candidate_points_map.get, reverse=True): | |
print(w, candidate_points_map[w], file=sys.stderr) | |
candidates = sorted(candidate_points_map, key=candidate_points_map.get, reverse=True) | |
if not candidates: | |
return | |
while factory.population > 0: | |
action = self.add_move(factory, candidates) | |
if not action: | |
break | |
if isinstance(action, Move): | |
factory.population -= action.size | |
moves.append(action) | |
candidates.pop(0) | |
if not candidates: | |
return moves | |
return moves | |
def add_move(self, source, candidates): | |
if source.production == 0 and source.population > 10: | |
print("increase man", file=sys.stderr) | |
return Increase(source.entity_id) | |
if candidates[0].owner == -1 and candidates[0].production in [2, 3] and self.bombs_available > 0 and not self.is_bomb_targeting(candidates[0]): | |
self.bombs_available -= 1 | |
return BombAction(source.entity_id, candidates[0].entity_id) | |
if candidates[0].owner != 1: | |
return Move(source.entity_id, candidates[0].entity_id, candidates[0].population + 1) | |
else: | |
return Move(source.entity_id, candidates[0].entity_id, source.population // 2) | |
def calculate_value_of(self, candidate, factory): | |
value_of_candidate = candidate.production | |
distance = self.get_distance_between(candidate, factory) | |
if candidate.owner == 1 and candidate.population < 10: | |
value_of_candidate += 1 | |
if candidate.owner == 1 and candidate.population > 10: | |
value_of_candidate -= 1 | |
if distance: | |
value_of_candidate += 10 * (1/distance) | |
else: | |
value_of_candidate = -1 | |
return value_of_candidate | |
def get_distance_between(self, candidate, factory): | |
for link in self.links: | |
if link.factory_1 == candidate.entity_id and link.factory_2 == factory.entity_id: | |
return link.distance | |
if link.factory_2 == candidate.entity_id and link.factory_1 == factory.entity_id: | |
return link.distance | |
return None | |
def is_bomb_targeting(self, candidate): | |
for bomb in self.bombs: | |
if bomb.target == candidate.entity_id: | |
return True | |
return False | |
factory_count = int(input()) # the number of factories | |
link_count = int(input()) # the number of links between factories | |
links = [] | |
for i in range(link_count): | |
factory_1, factory_2, distance = [int(j) for j in input().split()] | |
links.append(Link(factory_1, factory_2, distance)) | |
# for link in links: | |
# print(link, file=sys.stderr) | |
bombs_available = 2 | |
game = Game(links, bombs_available) | |
while True: | |
factories = [] | |
troops = [] | |
bombs = [] | |
entity_count = int(input()) # the number of entities (e.g. factories and troops) | |
for i in range(entity_count): | |
entity_id, entity_type, arg_1, arg_2, arg_3, arg_4, arg_5 = input().split() | |
entity_id = int(entity_id) | |
arg_1 = int(arg_1) | |
arg_2 = int(arg_2) | |
arg_3 = int(arg_3) | |
arg_4 = int(arg_4) | |
arg_5 = int(arg_5) | |
if entity_type == "FACTORY": | |
factories.append(Factory(entity_id, arg_1, arg_2, arg_3)) | |
if entity_type == "TROOP": | |
troops.append(Troop(entity_id, arg_1, arg_2, arg_3, arg_4, arg_5)) | |
if entity_type == "BOMB": | |
bombs.append(Bomb(entity_id, arg_1, arg_2, arg_3, arg_4)) | |
game.factories = factories | |
game.bombs = bombs | |
game.get_next_turn() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment