def head_to_food_to_tail_direction(data, aStar, walls, nearest_food, survival_directions): you_x = data['you']['body'][0]['x'] you_y = data['you']['body'][0]['y'] aStar.reset_grid_and_start((you_x, you_y), (nearest_food[0], nearest_food[1])) to_food_path = aStar.solve() single_lane = check_if_path_in_between_walls(data, aStar, to_food_path, walls) if (single_lane): #print("Attack Path is between walls, ignore it: " + str(path)) to_food_path = None return None #can get to food if (to_food_path != None): tail_x = data['you']['body'][len(data['you']['body']) - 1]['x'] tail_y = data['you']['body'][len(data['you']['body']) - 1]['y'] head_blocking_aStar, new_walls = init_astar(data, True) head_blocking_aStar.reset_grid_and_start( (nearest_food[0], nearest_food[1]), (tail_x, tail_y)) to_tail_path = head_blocking_aStar.solve() if (to_tail_path != None): single_lane = check_if_path_in_between_walls( data, head_blocking_aStar, to_tail_path, new_walls) if (single_lane): #print("Attack Path is between walls, ignore it: " + str(path)) to_tail_path = None return None path_directions = get_directions(you_x, you_y, to_food_path[1][0], to_food_path[1][1]) #if direction of food not in viable direction, remove option revised_path_directions = [] for direction in path_directions: if (direction in survival_directions): revised_path_directions.append(direction) if (DEBUG_LOGS): print("To Food to Tail direction : ", revised_path_directions) if (len(revised_path_directions) > 0): return revised_path_directions return None
def find_own_tail_path(aStar, walls, data, growing, valid_move_tiles): #reset grid to have tail space as goal tail_x = data['you']['body'][len(data['you']['body']) - 1]['x'] tail_y = data['you']['body'][len(data['you']['body']) - 1]['y'] #if head and tail are the same space, ie starting turn if ((tail_x == data['you']['body'][0]['x']) and (tail_y == data['you']['body'][0]['y'])): directions = [] if (DEBUG_LOGS): print("Tail and head are on the same tile: " + str(tail_x) + " " + str(tail_y)) return directions #if growing, need to find path to space before tail and solid tail if (growing): new_aStar, new_walls = init_astar(data, False, True) new_aStar.set_ending_for_init_grid((tail_x, tail_y)) path = new_aStar.solve() else: aStar.reset_grid((tail_x, tail_y)) path = aStar.solve() if (DEBUG_LOGS): print("Path to tail = " + str(path)) if (path != None and check_if_path_goes_through_valid_survival_tiles( path, valid_move_tiles)): directions = get_directions(data['you']['body'][0]['x'], data['you']['body'][0]['y'], path[1][0], path[1][1]) if (growing): single_lane = path_single_lane_check(data, aStar, new_walls, path) else: single_lane = path_single_lane_check(data, aStar, walls, path) for i in range(len(directions)): directions[i] = (directions[i], single_lane) if (DEBUG_LOGS): print("Path to tail direction = " + str(directions)) return directions if (DEBUG_LOGS): print("No path to tail") return [(None, False)]
def find_other_snake_tail_path(data, aStar, walls, valid_move_tiles): shortest_path = None snake_following_name = '' short_walls = walls #reset grid to have tail space as goal for i in range(len(data['board']['snakes'])): if (data['board']['snakes'][i]['id'] == data['you']['id']): continue #skip self tail_x = data['board']['snakes'][i]['body'][ len(data['board']['snakes'][i]['body']) - 1]['x'] tail_y = data['board']['snakes'][i]['body'][ len(data['board']['snakes'][i]['body']) - 1]['y'] #if head and tail are the same space, ie starting turn if ((tail_x == data['board']['snakes'][i]['body'][0]['x']) and (tail_y == data['board']['snakes'][i]['body'][0]['y'])): directions = [] #if (DEBUG_LOGS): #print("Tail and head of snake " + str(data['board']['snakes'][i]['name']) + " are on the same tile: " + str(tail_x) + " " + str(tail_y)) return directions growing = determine_if_snake_growing(data, i) #if growing, need to find path to space before tail and solid tail if (growing): new_aStar, new_walls = init_astar(data, False, False, i) new_aStar.set_ending_for_init_grid((tail_x, tail_y)) path = new_aStar.solve() #if path is just 2, it is current head and tail spot, and since growing that path will not be valid #and if not enough valid tiles to rework path, path is none if (path != None and len(path) <= 2 and len(valid_move_tiles) < 2): path = None else: aStar.reset_grid((tail_x, tail_y)) path = aStar.solve() #if (DEBUG_LOGS): #print("Path to opposing tail = " + str(path)) if (path != None and (shortest_path == None or len(path) < len(shortest_path)) and check_if_path_goes_through_valid_survival_tiles( path, valid_move_tiles)): shortest_path = path snake_following_name = str(data['board']['snakes'][i]['name']) if (growing): short_walls = new_walls else: short_walls = walls if (shortest_path != None): directions = get_directions(data['you']['body'][0]['x'], data['you']['body'][0]['y'], shortest_path[1][0], shortest_path[1][1]) single_lane = path_single_lane_check(data, aStar, short_walls, shortest_path) for i in range(len(directions)): directions[i] = (directions[i], single_lane) if (DEBUG_LOGS): print("Path to snake " + snake_following_name + " tail direction = " + str(directions)) return directions if (DEBUG_LOGS): print("No path to snake opposing snakes tails") return [(None, False)]
def find_closest_tile_to_enemy(self, possible_tiles, possible_directions): #grab closest tile and distance for each snake, choose tile closest to the most snakes, not just closest tile to a snake closest_tiles = {} smallest_distances = {} closest_directions = {} #determine closest opposing snake for i in range(len(self.data['board']['snakes'])): if (self.data['board']['snakes'][i]['id'] == self.data['you']['id'] ): continue #skip self temp_data = copy.deepcopy(self.data) #if turn 0, body len 3 and all on same tile lost_head = temp_data['board']['snakes'][i]['body'].pop(0) if (self.data['turn'] == 0): for j in range(2): temp_data['board']['snakes'][j]['body'].pop(0) temp_data['board']['snakes'][i]['head'] = temp_data['board'][ 'snakes'][i]['body'][0] aStar, walls = init_astar(temp_data, False, self.growing) closest_tiles[self.data['board']['snakes'][i]['id']] = [] smallest_distances[self.data['board']['snakes'][i]['id']] = [] closest_directions[self.data['board']['snakes'][i]['id']] = [] #print("Snake: " + str(self.data['board']['snakes'][i]['name'])) j = 0 while (j < len(possible_tiles)): path = None aStar.reset_grid_and_start( (possible_tiles[j]), (self.data['board']['snakes'][i]['body'][0]['x'], self.data['board']['snakes'][i]['body'][0]['y'])) path = aStar.solve() if (path == None): j += 1 continue distance = len(path) #if (DEBUG_LOGS): #print("Tile: " + str(possible_tiles[j]) + " distance: " + str(distance)) if (len(smallest_distances[self.data['board']['snakes'][i] ['id']]) == 0 or distance < smallest_distances[ self.data['board']['snakes'][i]['id']][0]): closest_tiles[self.data['board']['snakes'][i]['id']] = [] smallest_distances[self.data['board']['snakes'][i] ['id']] = [] closest_directions[self.data['board']['snakes'][i] ['id']] = [] smallest_distances[self.data['board']['snakes'][i] ['id']].append(distance) closest_tiles[self.data['board']['snakes'][i] ['id']].append(possible_tiles[j]) closest_directions[self.data['board']['snakes'][i] ['id']].append(possible_directions[j]) elif (distance == smallest_distances[self.data['board'] ['snakes'][i]['id']][0]): direct_distance_old = math.sqrt(( (closest_tiles[self.data['board']['snakes'][i] ['id']][0][0] - self.data['board']['snakes'][i]['body'][0]['x'])**2 ) + ((closest_tiles[self.data['board']['snakes'][i] ['id']][0][1] - self.data['board']['snakes'][i]['body'][0]['y'])**2)) direct_distance_new = math.sqrt(( (possible_tiles[j][0] - self.data['board']['snakes'][i]['body'][0]['x'])**2 ) + ((possible_tiles[j][1] - self.data['board']['snakes'][i]['body'][0]['y'])**2)) if (DEBUG_LOGS): print("Tile: " + str(possible_tiles[j]) + " distance old: " + str(direct_distance_old) + " distance new: " + str(direct_distance_new)) if (direct_distance_new < direct_distance_old): closest_tiles[self.data['board']['snakes'][i] ['id']] = [] smallest_distances[self.data['board']['snakes'][i] ['id']] = [] closest_directions[self.data['board']['snakes'][i] ['id']] = [] smallest_distances[self.data['board']['snakes'][i] ['id']].append(distance) closest_tiles[self.data['board']['snakes'][i] ['id']].append(possible_tiles[j]) closest_directions[self.data['board']['snakes'][i] ['id']].append( possible_directions[j]) elif (direct_distance_new == direct_distance_old): smallest_distances[self.data['board']['snakes'][i] ['id']].append(distance) closest_tiles[self.data['board']['snakes'][i] ['id']].append(possible_tiles[j]) closest_directions[self.data['board']['snakes'][i] ['id']].append( possible_directions[j]) j += 1 if (DEBUG_LOGS): print("Closest Directions: " + str(closest_directions)) average_directions = {} #go through possible directions for each snake, and take most commmon direction for i in range(len(self.data['board']['snakes'])): if (self.data['board']['snakes'][i]['id'] == self.data['you']['id'] ): continue #skip self for direction in closest_directions[self.data['board']['snakes'][i] ['id']]: if direction in average_directions: average_directions[direction] += 1 else: average_directions[direction] = 1 most_used_direction_count = 0 best_directions = [] for direction in average_directions: if (average_directions[direction] > most_used_direction_count): best_directions = [] best_directions.append(direction) most_used_direction_count = average_directions[direction] elif (average_directions[direction] == most_used_direction_count): best_directions.append(direction) return best_directions
def get_move(data): aStar, walls = init_astar(data) #directions = ["up", "down", "left", "right"] survival_directions = survival_choices( data, walls, aStar) #get bad options, remove them from contention growing = determine_if_growing(data) #check spacing spacing_directions, tail_directions, other_snake_tail_directions, can_follow_tail, can_follow_other_snake_tail, protectable_area = get_spacing_directions( data, aStar, walls, survival_directions, growing) if (DEBUG_LOGS): print("Final spacing directions: " + str(spacing_directions)) food_directions, nearest_food = consumption_choices( data, aStar, walls, protectable_area) consumption_directions = directions1_in_directions2( food_directions, survival_directions) if (DEBUG_LOGS): print("Food move after survival direction clear: ", consumption_directions) #check to see if can attack snake attack_directions = get_attack_directions(data, aStar, walls, survival_directions) if (DEBUG_LOGS): print("Attack Directions: " + str(attack_directions)) """priority, survive, avoid_collisions, space, attack, food all directions already filtered thorugh survival directions need to check if food fits in space, than space fits in avoid collisions than collision fits in survive Downward check in terms of prioity, make sure each less pressing thing fits in more pressing issue """ #if viable path to tail, and a viable path to food, see if viable path from head -> food -> tail food_tail_directions = None if (can_follow_tail and consumption_directions != None and len(consumption_directions) > 0): food_tail_directions = head_to_food_to_tail_direction( data, aStar, walls, nearest_food, survival_directions) if (food_tail_directions != None): for direction in food_tail_directions: if (direction in survival_directions and not (direction in spacing_directions)): spacing_directions.append(direction) if (DEBUG_LOGS): print( "Own snake tail follow and spacing after survival direction clear: ", spacing_directions) #if viable path to opponent tail, and a viable path to food, see if viable path from head -> food -> opponent tail food_opponent_tail_directions = None if (can_follow_other_snake_tail and consumption_directions != None and len(consumption_directions) > 0): food_opponent_tail_directions = head_to_food_to_opponent_tail_direction( data, aStar, walls, nearest_food, survival_directions) if (food_opponent_tail_directions != None): for direction in food_opponent_tail_directions: if (direction in survival_directions and not (direction in spacing_directions)): spacing_directions.append(direction) if (DEBUG_LOGS): print( "Other snake tail follow and spacing after survival direction clear: ", spacing_directions) #temp until add collision avoidance no_head_collisions_directions = avoid_death_collisions( data, walls, survival_directions) #if can attack, set as preffered actions if (len(attack_directions) > 0): preferred_directions = attack_directions #if no viable attack, try to eat else: preferred_directions = get_directions_through_food_space_collision( consumption_directions, spacing_directions, no_head_collisions_directions, survival_directions, food_tail_directions, food_opponent_tail_directions) final_directions = get_directions_with_space_and_collision_merge( preferred_directions, spacing_directions, no_head_collisions_directions, survival_directions) #no path availabe that won't kill us, so just return any response if (len(final_directions) <= 0 and len(survival_directions) > 0): final_directions = survival_directions elif (len(final_directions) <= 0): final_directions = ["up", "down", "left", "right"] if (DEBUG_LOGS): print("Final Directions before last reform: " + str(final_directions)) #multiple good options if (len(final_directions) > 1): #go around protectable area if possible if (DEBUG_LOGS): print("Protected area len: " + str(len(protectable_area))) if (len(protectable_area) >= 1): protect_directions = get_direction_to_protect_area( protectable_area, data, final_directions, growing) else: protect_directions = [] #if multiple options continue with narrowing if (len(protect_directions) == 1): final_directions = protect_directions if (DEBUG_LOGS): print("Final Direction after protected area: " + str(final_directions)) direction = random.choice(final_directions) return direction #if some directions chosen, use them as next fliter, otherwise ignore if (len(protect_directions) > 1): final_directions = protect_directions if (DEBUG_LOGS): print("Final diretions before tail check: " + str(final_directions)) print("Tail diretions before tail check: " + str(tail_directions)) #follow tail if possible pos_tail_directions = directions1_in_directions2( tail_directions, final_directions) if (pos_tail_directions != None and len(pos_tail_directions) > 0): final_directions = pos_tail_directions if (DEBUG_LOGS): print("Final Directions after tail: " + str(final_directions)) direction = random.choice(final_directions) return direction #follow opponent tail if possible pos_tail_directions = directions1_in_directions2( other_snake_tail_directions, final_directions) if (pos_tail_directions != None and len(pos_tail_directions) > 0): final_directions = pos_tail_directions if (DEBUG_LOGS): print("Final Directions after opponent tail: " + str(final_directions)) direction = random.choice(final_directions) return direction #go straight if possible prev_directions = get_directions(data['you']['body'][0]['x'], data['you']['body'][0]['y'], data['you']['body'][1]['x'], data['you']['body'][1]['y']) if (prev_directions != None): inverse_directions = [] for direction in prev_directions: if (direction == "left"): inverse_directions.append("right") elif (direction == "right"): inverse_directions.append("left") elif (direction == "down"): inverse_directions.append("up") elif (direction == "up"): inverse_directions.append("down") forward_directions = directions1_in_directions2( inverse_directions, final_directions) if (forward_directions != None and len(forward_directions) > 0): final_directions = forward_directions if (DEBUG_LOGS): print("Final Directions after straight: " + str(final_directions)) direction = random.choice(final_directions) return direction if (DEBUG_LOGS): print("Just choosing random choice: " + str(final_directions)) direction = random.choice(final_directions) return direction