def play_out_by_heuristics(self, context_area, initial_positions, previous_moves, list_players, my_index, manhattan_cache, index_cache): start = clock() area, walls = self.initialize_play_out(context_area, initial_positions, previous_moves, list_players, my_index, index_cache) init_time = (clock() - start) * 1000 current_positions = [] for i in range(len(list_players)): current_positions.append(walls[i][-1]) msg = '' # Check if it is an early end game if len(list_players) == 2: start = clock() voronoi_area, voronoi_spaces = compute_voronoi( area, current_positions, [0, 1], index_cache) voronoi_time = (clock() - start) * 1000 #msg += 'voronoi: ' + str(round(voronoi_time,2)) + 'ms' if len( walls[list_players[0]] ) >= 10 and voronoi_spaces[0] != 0 and voronoi_spaces[1] != 0: if not self.is_separeted: r_x, r_y = current_positions[my_index][ 0], current_positions[my_index][1] g_x, g_y = current_positions[ 1 - my_index][0], current_positions[1 - my_index][1] #start = clock() #distance = compute_path(area, current_positions[my_index], index_cache[r_x][r_y],current_positions[1 - my_index], index_cache[g_x][g_y], manhattan_cache, index_cache) #path_time = (clock() - start) * 1000 #msg += ', path: ' + str(round(path_time,2)) + 'ms' if voronoi_spaces[5] == 0: self.is_separeted = True #self.is_end_game = True if self.is_separeted: start = clock() my_articulation_points = detect_articulation_points( area, initial_positions[my_index], index_cache[initial_positions[my_index][0]][ initial_positions[my_index][1]], index_cache) ennemy_articulation_points = detect_articulation_points( area, initial_positions[1 - my_index], index_cache[initial_positions[1 - my_index][0]][ initial_positions[1 - my_index][1]], index_cache) articulation_separated_time = (clock() - start) * 1000 #msg += ', AP sep: ' + str(round(articulation_separated_time,2)) + 'ms' else: start = clock() my_articulation_points = detect_articulation_points( area, initial_positions[my_index], index_cache[initial_positions[my_index][0]][ initial_positions[my_index][1]], index_cache) ennemy_articulation_points = my_articulation_points articulation_time = (clock() - start) * 1000 #msg += ', AP: ' + str(round(articulation_time,2)) + 'ms' is_in_territory = False if self.is_separeted: is_in_territory = len(my_articulation_points) > 0 else: for articulation in my_articulation_points: if voronoi_area[articulation] == my_index: is_in_territory = True break if is_in_territory: if len(walls[my_index]) < 2: previous_pos = (-1, -1) else: previous_pos = walls[my_index][-2] start = clock() my_spaces = compute_tree_of_chambers( area, voronoi_area, my_articulation_points, current_positions[my_index], previous_pos, index_cache, my_index) tree_time = (clock() - start) * 1000 #msg += ', My tree: ' + str(round(tree_time,2)) + 'ms' else: my_spaces = voronoi_spaces[my_index] is_in_territory = False if self.is_separeted: is_in_territory = len(ennemy_articulation_points) > 0 else: for articulation in ennemy_articulation_points: if voronoi_area[articulation] == (1 - my_index): is_in_territory = True break if is_in_territory: if len(walls[1 - my_index]) < 2: enn_previous_pos = (-1, -1) else: enn_previous_pos = walls[1 - my_index][-2] start = clock() ennemy_spaces = compute_tree_of_chambers( area, voronoi_area, ennemy_articulation_points, current_positions[1 - my_index], enn_previous_pos, index_cache, (1 - my_index)) tree_time = (clock() - start) * 1000 #msg += ', Ennemy tree: ' + str(round(tree_time,2)) + 'ms' else: ennemy_spaces = voronoi_spaces[1 - my_index] else: my_spaces = voronoi_spaces[my_index] ennemy_spaces = voronoi_spaces[1 - my_index] nb_walls = 0 for i in walls: nb_walls += len(walls[i]) msg += ', my: ' + str( voronoi_spaces[0]) + '/' + str(my_spaces) + ', enn: ' + str( voronoi_spaces[1]) + '/' + str( ennemy_spaces) + ', null: ' + str( voronoi_spaces[5]) + ', wall: ' + str(nb_walls) msg += ', total: ' + str(my_spaces + ennemy_spaces + voronoi_spaces[5] + nb_walls) #print(msg, flush=True) return my_spaces, my_spaces + ennemy_spaces else: # Use Voronoi for now voronoi_area, voronoi_spaces = compute_voronoi( area, current_positions, list_players, index_cache) space_max = 0 winner = None for player, space in voronoi_spaces.items(): if space > space_max: winner = player return winner == my_index, voronoi_spaces[my_index]
def compute_direction(self, input): splitted = input.split('\n') nb_players, my_index = [int(i) for i in splitted[0].split()] if self.turn == 0: for i in range(nb_players): self.list_players.append(i) self.list_players_without_me.append(i) self.list_players_without_me.remove(my_index) for i in range(nb_players): # x0: starting X coordinate of lightcycle (or -1 if lost) # y0: starting Y coordinate of lightcycle (or -1 if lost) # x1: starting X coordinate of lightcycle (can be the same as X0 if you play before this player on the second turn) # y1: starting Y coordinate of lightcycle (can be the same as Y0 if you play before this player on the second turn) x0, y0, x1, y1 = [int(j) for j in splitted[i + 1].split()] if x0 != -1: self.current_move[i] = (x1, y1) if self.turn == 0: self.previous_move[i] = (-1, -1) self.current_move[i] = (x0, y0) self.wall_cycles[i] = [(x0, y0)] self.area[self.index_cache[x0][y0]] = False if i < my_index: # players playing before me have already made a move self.previous_move[i] = (x0, y0) self.current_move[i] = (x1, y1) self.wall_cycles[i] = [(x1, y1)] self.area[self.index_cache[x1][y1]] = False else: self.previous_move[i] = self.current_move[i] self.current_move[i] = (x1, y1) self.wall_cycles[i].append((x1, y1)) self.area[self.index_cache[x1][y1]] = False else: # If player has lost, remove his wall from the game if i in self.current_move: for case in self.wall_cycles[i]: self.area[self.index_cache[case[0]][case[1]]] = True del self.current_move[i] del self.wall_cycles[i] self.list_players.remove(i) self.list_players_without_me.remove(i) offsets = [[1, 0], [-1, 0], [0, 1], [0, -1]] cur_pos = self.current_move[my_index] new_pos = {} previous_pos = {} for player in self.list_players: new_pos[player] = self.current_move[player] previous_pos[player] = self.wall_cycles[player][-1] max_space = 0 max_new_direction = (0, 0) min_ennemies_space = inf for off_x, off_y in offsets: new_x = cur_pos[0] + off_x new_y = cur_pos[1] + off_y if 0 <= new_x < 30 and 0 <= new_y < 20 and self.area[ self.index_cache[new_x][new_y]]: previous_pos[my_index] = new_pos[my_index] new_pos[my_index] = (new_x, new_y) voronoi_area, voronoi_spaces = compute_voronoi( self.area, new_pos, self.list_players, self.index_cache) articulation_points = { } #Another solution is to detect which players are separated from each other with A*.. availables_spaces = {} for player in self.list_players: articulation_points[player] = detect_articulation_points( self.area, new_pos[player], self.index_cache[ new_pos[player][0]][new_pos[player][1]], self.index_cache) if len(articulation_points[player]) == 0: availables_spaces[player] = voronoi_spaces[player] else: availables_spaces[player] = compute_tree_of_chambers( self.area, voronoi_area, articulation_points[player], new_pos[player], previous_pos, self.index_cache, my_index) ennemies_space = 0 max_ennemi_space = 0 for player in self.list_players_without_me: if availables_spaces[player] > max_ennemi_space: max_ennemi_space = availables_spaces[player] #ennemies_space += availables_spaces[player] ennemies_space = max_ennemi_space #ennemies_space += voronoi_spaces[5] #print('player-' + str(my_index) + ' cur:' + str((cur_pos[0],cur_pos[1])) + ', new:' + str((new_x,new_y)) + ': ' + str(availables_spaces[my_index]) + '/' + str(ennemies_space) + ', ' + str(voronoi_spaces), flush=True) #First maximise my own space if availables_spaces[my_index] > max_space: max_space = availables_spaces[my_index] max_new_direction = (new_x, new_y) min_ennemies_space = ennemies_space #Second minimize my ennemies space elif availables_spaces[my_index] == max_space: if ennemies_space < min_ennemies_space: min_ennemies_space = ennemies_space max_new_direction = (new_x, new_y) if max_new_direction != (0, 0): self.opposite_direction = (max_new_direction[0] * -1, max_new_direction[1] * -1) direction = '' if max_new_direction[0] - cur_pos[0] > 0: direction = 'RIGHT' elif max_new_direction[0] - cur_pos[0] < 0: direction = 'LEFT' elif max_new_direction[1] - cur_pos[1] > 0: direction = 'DOWN' elif max_new_direction[1] - cur_pos[1] < 0: direction = 'UP' self.turn += 1 return direction
def compute_direction(self, input): splitted = input.split('\n') nb_players, my_index = [int(i) for i in splitted[0].split()] if self.turn == 0: for i in range(nb_players): self.list_players.append(i) self.list_players_without_me.append(i) self.list_players_without_me.remove(my_index) for i in range(nb_players): # x0: starting X coordinate of lightcycle (or -1 if lost) # y0: starting Y coordinate of lightcycle (or -1 if lost) # x1: starting X coordinate of lightcycle (can be the same as X0 if you play before this player on the second turn) # y1: starting Y coordinate of lightcycle (can be the same as Y0 if you play before this player on the second turn) x0, y0, x1, y1 = [int(j) for j in splitted[i + 1].split()] if x0 != -1: self.current_move[i] = (x1, y1) if self.turn == 0: self.previous_move[i] = (-1,-1) self.current_move[i] = (x0, y0) self.wall_cycles[i] = [(x0, y0)] self.area[self.index_cache[x0][y0]] = False if i < my_index: # players playing before me have already made a move self.previous_move[i] = (x0, y0) self.current_move[i] = (x1, y1) self.wall_cycles[i] = [(x1, y1)] self.area[self.index_cache[x1][y1]] = False else: self.previous_move[i] = self.current_move[i] self.current_move[i] = (x1,y1) self.wall_cycles[i].append((x1, y1)) self.area[self.index_cache[x1][y1]] = False else: # If player has lost, remove his wall from the game if i in self.current_move: for case in self.wall_cycles[i]: self.area[self.index_cache[case[0]][case[1]]] = True del self.current_move[i] del self.wall_cycles[i] self.list_players.remove(i) self.list_players_without_me.remove(i) #Initial state evaluation init_voronoi_area, init_voronoi_spaces = compute_voronoi(self.area, self.current_move, self.list_players, self.index_cache) init_dist_from_me = {} r_index = self.index_cache[self.current_move[my_index][0]][self.current_move[my_index][1]] for player in self.list_players_without_me: g_index = self.index_cache[self.current_move[player][0]][self.current_move[player][1]] init_dist_from_me[player] = compute_path(self.area, self.current_move[my_index], r_index, self.current_move[player], g_index, self.manhattan_cache, self.index_cache) init_previous_pos = {} for player in self.list_players: if len(self.wall_cycles[player]) < 2: init_previous_pos[player] = (-1,-1) else: init_previous_pos[player] = self.wall_cycles[player][-2] init_articulation_points = {} # Another solution is to detect which players are separated from each other with A*.. init_availables_spaces = {} for player in self.list_players: init_articulation_points[player] = detect_articulation_points(self.area, self.current_move[player], self.index_cache[self.current_move[player][0]][ self.current_move[player][1]], self.index_cache) if len(init_articulation_points[player]) == 0: init_availables_spaces[player] = init_voronoi_spaces[player] else: init_availables_spaces[player] = compute_tree_of_chambers(self.area, init_voronoi_area, init_articulation_points[player], self.current_move[player], init_previous_pos, self.index_cache, player) init_availables_spaces[5] = init_voronoi_spaces[5] init_ennemies_space = 0 for player in self.list_players_without_me: init_ennemies_space += init_availables_spaces[player] init_ennemies_space += init_voronoi_spaces[5] #Evaluation of the different possibles moves offsets = [[1, 0], [-1, 0], [0, 1], [0, -1]] cur_pos = self.current_move[my_index] new_pos = {} previous_pos = {} for player in self.list_players: new_pos[player] = self.current_move[player] previous_pos[player] = self.wall_cycles[player][-1] max_evaluation = -inf max_new_direction = (0,0) for off_x, off_y in offsets: new_x = cur_pos[0] + off_x new_y = cur_pos[1] + off_y if 0 <= new_x < 30 and 0 <= new_y < 20 and self.area[self.index_cache[new_x][new_y]]: previous_pos[my_index] = new_pos[my_index] new_pos[my_index] = (new_x, new_y) voronoi_area, voronoi_spaces = compute_voronoi(self.area, new_pos, self.list_players, self.index_cache) articulation_points = {} #Another solution is to detect which players are separated from each other with A*.. availables_spaces = {} dist_from_me = {} r_index = self.index_cache[new_pos[my_index][0]][new_pos[my_index][1]] for player in self.list_players: g_index = self.index_cache[new_pos[player][0]][new_pos[player][1]] dist_from_me[player] = compute_path(self.area, new_pos[my_index], r_index, new_pos[player], g_index, self.manhattan_cache, self.index_cache) articulation_points[player] = detect_articulation_points(self.area, new_pos[player], self.index_cache[new_pos[player][0]][new_pos[player][1]], self.index_cache) if len(articulation_points[player]) == 0: availables_spaces[player] = voronoi_spaces[player] else: availables_spaces[player] = compute_tree_of_chambers(self.area, voronoi_area, articulation_points[player], new_pos[player], previous_pos, self.index_cache, player) availables_spaces[5] = voronoi_spaces[5] ennemies_space = 0 for player in self.list_players_without_me: ennemies_space += availables_spaces[player] ennemies_space += voronoi_spaces[5] evaluation = self.scoring(init_availables_spaces, availables_spaces, self.list_players, self.list_players_without_me, my_index, init_articulation_points, articulation_points, init_dist_from_me, dist_from_me, new_pos, init_dist_from_me, dist_from_me) #print('player' + str(my_index) + ' cur:' + str((cur_pos[0],cur_pos[1])) + ' =>' + str((new_x,new_y)) + ': init:' + str(init_availables_spaces[my_index]) + '/' + str(init_ennemies_space) + ', new: ' + str(availables_spaces[my_index]) + '/' + str(ennemies_space) + ', score: ' + str(evaluation ) + ', ' + str(voronoi_spaces), flush=True) if evaluation > max_evaluation: max_evaluation = evaluation max_new_direction = (new_x, new_y) #print('player' + str(my_index) + ' cur:' + str((cur_pos[0], cur_pos[1])) + ' =>' + str((max_new_direction[0], max_new_direction[1])), flush=True) if max_new_direction != (0, 0): self.opposite_direction = (max_new_direction[0] * -1, max_new_direction[1] * -1) direction = '' if max_new_direction[0] - cur_pos[0] > 0: direction = 'RIGHT' elif max_new_direction[0] - cur_pos[0] < 0: direction = 'LEFT' elif max_new_direction[1] - cur_pos[1] > 0: direction = 'DOWN' elif max_new_direction[1] - cur_pos[1] < 0: direction = 'UP' self.turn += 1 return direction
def evaluate(self, manhattan_cache, index_cache): ''' Evaluate the score of the leaf (based on the space remaining for the players) ''' my_index = 0 #TODO: make my_index a variable like for real game msg = '' start = clock() voronoi_area, voronoi_spaces = compute_voronoi(self.area, self.positions, [0, 1], index_cache) voronoi_time = (clock() - start) * 1000 msg += 'voronoi: ' + str(round(voronoi_time, 2)) + 'ms' if not self.is_separeted: #r_x, r_y = self.positions[my_index][0], self.positions[my_index][1] #g_x, g_y = self.positions[1 - my_index][0], self.positions[1 - my_index][1] #start = clock() #distance = compute_path(self.area, self.positions[my_index], index_cache[r_x][r_y], # self.positions[1 - my_index], index_cache[g_x][g_y], manhattan_cache, # index_cache) #path_time = (clock() - start) * 1000 # msg += ', path: ' + str(round(path_time,2)) + 'ms' if voronoi_spaces[2] == 0: self.is_separeted = True # self.is_end_game = True if self.is_separeted: start = clock() my_articulation_points = detect_articulation_points( self.area, self.positions[my_index], index_cache[ self.positions[my_index][0]][self.positions[my_index][1]], index_cache) ennemy_articulation_points = detect_articulation_points( self.area, self.positions[1 - my_index], index_cache[self.positions[1 - my_index][0]][self.positions[ 1 - my_index][1]], index_cache) articulation_separated_time = (clock() - start) * 1000 msg += ', AP sep: ' + str(round(articulation_separated_time, 2)) + 'ms' else: start = clock() my_articulation_points = detect_articulation_points( self.area, self.positions[my_index], index_cache[ self.positions[my_index][0]][self.positions[my_index][1]], index_cache) ennemy_articulation_points = my_articulation_points articulation_time = (clock() - start) * 1000 msg += ', AP: ' + str(round(articulation_time, 2)) + 'ms' is_in_territory = False if self.is_separeted: is_in_territory = len(my_articulation_points) > 0 else: for articulation in my_articulation_points: if voronoi_area[articulation] == my_index: is_in_territory = True break if is_in_territory: start = clock() my_spaces = compute_tree_of_chambers(self.area, voronoi_area, my_articulation_points, self.positions[my_index], self.prev_positions[0], index_cache, my_index) tree_time = (clock() - start) * 1000 msg += ', My tree: ' + str(round(tree_time, 2)) + 'ms' else: my_spaces = voronoi_spaces[my_index] is_in_territory = False if self.is_separeted: is_in_territory = len(ennemy_articulation_points) > 0 else: for articulation in ennemy_articulation_points: if voronoi_area[articulation] == (1 - my_index): is_in_territory = True break if is_in_territory: start = clock() ennemy_spaces = compute_tree_of_chambers( self.area, voronoi_area, ennemy_articulation_points, self.positions[1 - my_index], self.prev_positions[1], index_cache, (1 - my_index)) tree_time = (clock() - start) * 1000 msg += ', Ennemy tree: ' + str(round(tree_time, 2)) + 'ms' else: ennemy_spaces = voronoi_spaces[1 - my_index] print(msg, flush=True) if my_spaces == 0: return -inf elif ennemy_spaces == 0: return inf else: self.score = my_spaces - ennemy_spaces