def play_a_turn(gamemap: array_hlt.GameMap, prod_to_str_ratio): scoring_geo_map = array_geographic_utils.ScoringGeoMap( gamemap.width, gamemap.height, prod_to_str_ratio) scoring_geo_map.calculate_scores(gamemap=gamemap) moves = scoring_geo_map.calculate_best_moves(gamemap) # gamemap.log(str(moves) + '\n') moves = scoring_geo_map.post_process_moves(gamemap, moves) gamemap.evolve_assuming_no_enemy_and_get_origin_and_target_and_move(moves) return gamemap
def play_game(gamemap: array_hlt.GameMap, turns, prod_to_str_ratio): prods = [] strs = [] for turn in range(0, turns): play_a_turn(gamemap, prod_to_str_ratio) prods.append(gamemap.my_total_production()) strs.append(gamemap.my_total_strength()) # sys.stdout.write(str(turn) + "\t") print(str(prod_to_str_ratio) + "\t" + str(gamemap.my_total_production())) print(gamemap) return prods, strs
def mark_borders_and_get_potential_territory(self, gamemap: GameMap): grow_from_to_squares = [] for square in gamemap.my_locations_list(): # for neighbour in gamemap.neighbours(square[0], square[1]): for move in [(0, -1), (1, 0), (0, 1), (-1, 0)]: # [(y + dy) % self.height][(x + dx) % self.width] neighbour = ((square[0] + move[0]) % gamemap.height, (square[1] + move[1]) % gamemap.width) if not gamemap.is_mine(neighbour): grow_from_to_squares.append((square, neighbour)) self.step_distances[square] = 0 self.square_stati[square] = self.Status.MY_BOUNDARY self.square_stati[neighbour] = self.Status.NEW_BOUNDARY return grow_from_to_squares
def find_optimal_moves_for_this_turn(start_game_map: GameMap): """' Returns the pair best_moves, score. best_moves is a tuple of ((x,y), direction) pairs""" max_score = 0 best_moves = None # for moves in create_all_next_moves(start_game_map.my_sites()): for moves in create_all_next_moves(start_game_map.my_locations_list()): game_map = start_game_map.__deepcopy__() # print(game_map) game_map.evolve_assuming_no_enemy(moves) # print(game_map) score = game_map.my_total_production() + game_map.my_total_strength() * 0.5 if score > max_score: best_moves = moves max_score = score return [best_moves], max_score
def get_next_potential_neighbours(self, gamemap: GameMap): self.square_stati[self.square_stati == self.Status.OLD_BOUNDARY] = self.Status.DONE self.square_stati[self.square_stati == self.Status.NEW_BOUNDARY] = self.Status.OLD_BOUNDARY grow_from_to_squares = [] for square in np.argwhere(self.square_stati == self.Status.OLD_BOUNDARY): for move in [(0, -1), (1, 0), (0, 1), (-1, 0)]: neighbour = ((square[0] + move[0]) % gamemap.height, (square[1] + move[1]) % gamemap.width) if not gamemap.is_mine(neighbour) and \ (self.square_stati[neighbour] == self.Status.UNKNOWN or self.square_stati[neighbour] == self.Status.NEW_BOUNDARY): grow_from_to_squares.append((tuple(square), neighbour)) self.square_stati[neighbour] = self.Status.NEW_BOUNDARY return grow_from_to_squares
def prevent_colliding_high_impact_moves(gamemap_original: GameMap, moves): """Find all moves that move unto a square such that I lose str. First algo: update map with all moves, then find all squares with max str, then find the squares that moved into these squares and make the square with lowest str that did it, not move into this square However, if the originating square has close to max str, then we should probably just move so check if originating str > max - prod, if so, just move """ gamemap = gamemap_original.__deepcopy__() origin_target_and_moves = gamemap.evolve_assuming_no_enemy_and_get_origin_and_target_and_move(moves) target_set_with_origin_and_moves = dict() for origin, target, move in origin_target_and_moves: if target in target_set_with_origin_and_moves: target_set_with_origin_and_moves[target] += [(origin, move)] else: target_set_with_origin_and_moves[target] = [(origin, move)] # target_set_with_origin_and_moves = dict((target, (origin, move)) for origin, target, move in origin_target_and_moves) my_locations_list = gamemap.my_locations_list() problematic_target_squares = [] for square in my_locations_list: my_str = gamemap.strength[square] if my_str == 255: problematic_target_squares.append(square) new_moves = [] for problem_site in problematic_target_squares: if problem_site not in target_set_with_origin_and_moves: continue origins_and_moves = target_set_with_origin_and_moves[problem_site] max_str = -1 max_move = None max_location = None for origin_move in origins_and_moves: origin, move = origin_move my_str = gamemap_original.strength[origin] if my_str > 255 - gamemap.prod[origin]: # TODO this doesn't work. Make something that maybe moves OUTWARD instead, when str is high? Now high str squares collide... continue if my_str > max_str: # TODO make it better: if two sites move unto one, and both would have breached 255 # then obviously BOTH should have moved somewhere else/stand still! max_str = my_str max_move = move max_location = origin if max_location: new_moves.append((max_location, STILL)) moves_dict = dict(moves) new_moves_dict = dict(new_moves) moves_dict.update(new_moves_dict) return [[k, v] for k, v in moves_dict.items()]
def update_scores_from_out_to_inside(self, gamemap: GameMap): max_distance = np.amax(self.step_distances) max_distance = gamemap.fog_of_war_distance() min_distance = np.amin(self.step_distances) for distance in range(max_distance - 1, min_distance - 1, -1): # skip first outer layer as that doesn't have a NEXT nearest n. # from_squares = np.argwhere(self.step_distances == distance) from_squares = np.where(self.step_distances == distance) for square in zip(*from_squares): optimal_score = -9999 for move in [(0, -1), (1, 0), (0, 1), (-1, 0)]: neighbour = ((square[0] + move[0]) % gamemap.height, (square[1] + move[1]) % gamemap.width) if self.step_distances[neighbour] == distance + 1: if self.score[neighbour] > optimal_score: optimal_score = self.score[neighbour] # do inner area differently, we don't want everything to move inwards! if distance < 0: self.score[square] += np.int16(optimal_score) - 1 else: self.score[square] += np.int16(0.5 * optimal_score)
def calculate_best_moves(self, gamemap: GameMap): moves = [] my_total_str = gamemap.my_total_strength() my_locations_list = gamemap.my_locations_list() num_my_location = len(my_locations_list) for square in my_locations_list: my_str = gamemap.strength[square] if my_str <= 0: moves.append((square, STILL)) continue # gamemap.log("calculating best move for square: " + str(square) + '\n') # do inner area differently, but only if strength is less than half the max (if bigger, just gogo!) # also check for insignificance str of this square (compare it to average str) if self.step_distances[square] < 0 and my_str < 256 / 2 and my_str < my_total_str / num_my_location: moves.append((square, STILL)) continue if my_str > 256 / 2: best_move = STILL optimal_score = -9999 for step, move in zip([(0, -1), (1, 0), (0, 1), (-1, 0)], [WEST, SOUTH, EAST, NORTH]): neighbour = ((square[0] + step[0]) % gamemap.height, (square[1] + step[1]) % gamemap.width) # moving outward? if yes, then check for scores if (self.step_distances[neighbour] > self.step_distances[square] \ and self.score[neighbour] > optimal_score and my_str >= gamemap.strength[neighbour]): # moving outward, great! gamemap.log("finding move for strong square") best_move = move optimal_score = self.score[neighbour] if best_move == STILL: gamemap.log("\nwtf. best move not yet found!\n") gamemap.log_myself() optimal_score = -9999 for step, move in zip([(0, -1), (1, 0), (0, 1), (-1, 0)], [WEST, SOUTH, EAST, NORTH]): neighbour = ((square[0] + step[0]) % gamemap.height, (square[1] + step[1]) % gamemap.width) # moving outward? if yes, then check for scores if self.step_distances[neighbour] > self.step_distances[square] and self.score[neighbour] > optimal_score: # moving outward, great! best_move = move optimal_score = self.score[neighbour] moves.append((square, best_move)) continue best_move = STILL optimal_score = -9999 for step, move in zip([(0, -1), (1, 0), (0, 1), (-1, 0)], [WEST, SOUTH, EAST, NORTH]): neighbour = ((square[0] + step[0]) % gamemap.height, (square[1] + step[1]) % gamemap.width) # next commented section NEVER HAPPENS as neighbours cannot be enemies because of rules # if gamemap.owners[neighbour] != 0 and gamemap.owners[neighbour] != gamemap.playerID: # neighbour is enemy # optimal_score = self.score[neighbour] + 100 # just add some score for enemy locations # best_move = move if self.score[neighbour] > optimal_score and my_str >= gamemap.strength[neighbour]: # only move if target has better score or target isn't mine if gamemap.owners[neighbour] != gamemap.playerID or self.score[square] < self.score[neighbour]: optimal_score = self.score[neighbour] best_move = move # gamemap.log("updating best move to score " + str(optimal_score) + ", move: " + MOVES_STRINGS[move] + '\n') moves.append((square, best_move)) return moves
def play_range_of_games(gamemap: array_hlt.GameMap): res = [] for prod_to_str_ratio in range(1, 20): prods, strs = play_game(gamemap.__deepcopy__(), 100, prod_to_str_ratio) res.append((prod_to_str_ratio, prods, strs)) return res