def snake_has_lost_head_to_head(self, s: Snake, other: Snake): head = s.get_head() other_head = other.get_head() if head.x == other_head.x and head.y == other_head.y: return len(s.body) <= len(other.body) return False
def get_relevant_food(my_snake: Snake, snakes: List[Snake], all_food: List[Position], height: int, width: int) -> List[Position]: my_head = my_snake.get_head() enemy_heads = [ snake.get_head() for snake in snakes if snake.get_head() is not my_head ] my_close_food = [] for food in all_food: if food.x == 0 or food.y == 0 or food.x == width - 1 or food.y == height - 1: enemy_dist_to_me = min([ Distance.manhattan_dist(head, my_head) for head in enemy_heads ]) enemy_dist_to_food = min([ Distance.manhattan_dist(head, food) for head in enemy_heads ]) if len(all_food) > 5 and my_snake.health > 50: continue if my_snake.health > 25 and enemy_dist_to_food < 2: continue if my_snake.health > 70 and enemy_dist_to_food < 2 and enemy_dist_to_me < 2: continue my_close_food.append(food) if not my_close_food: my_close_food = all_food return my_close_food
def direction_to_food(snake: Snake, food: Position) -> Optional[Direction]: head = snake.get_head() for direction in Direction: if head.advanced(direction) == food: return direction return None
def find_next_food(snake: Snake, board: BoardState) -> Optional[Tuple[int, Position]]: head = snake.get_head() health = snake.get_health() all_food = board.food if len(all_food) == 0: print("KEIN FOOD") return None best_dist = 99999 best_food = None for food in all_food: food_dist = Distance.manhattan_dist(head, food) if food_dist > health: continue #print("food_dist: ",food_dist, "health", health) if food_dist == health: # print("1: ", food_dist, food) return food_dist, food else: diff = (health - food_dist) #print("diff: ",diff) if (best_dist > diff) and diff > 0: best_dist = diff best_food = food #print("2: ", best_dist, best_food) return best_dist, best_food
def feel_busy(self, board: BoardState, snake: Snake, grid_map: GridMap): possible_actions = snake.possible_actions() head = snake.get_head() if possible_actions is None: return None actions_without_obstacle = [] for action in possible_actions: next_field = head.advanced(action) object_at_field = grid_map.get_value_at_position(next_field) if board.is_out_of_bounds(next_field): continue if object_at_field == Occupant.Snake: continue actions_without_obstacle.append(action) if len(actions_without_obstacle) > 0: return np.random.choice(actions_without_obstacle) else: return None
def snake_is_out_of_bounds(self, s: Snake, board_width: int, board_height: int): head = s.get_head() if head.x < 0 or head.x >= board_width: return True elif head.y < 0 or head.y >= board_height: return True return False
def snake_has_body_collided(self, s: Snake, other: Snake): head = s.get_head() for i, body in enumerate(other.body): if i == 0: continue elif body.x == head.x and body.y == head.y: return True return False
def get_valid_actions(board: BoardState, possible_actions: List[Direction], snakes: List[Snake], my_snake: Snake, grid_map: GridMap[Occupant], avoid_food: bool) -> List[Direction]: my_head = my_snake.get_head() snake_tails = [] val_actions = [] forbidden_fields = [] for snake in snakes: if snake.snake_id != my_snake.snake_id: for direc in snake.possible_actions(): enemy_head = snake.get_head() forbidden_fields.append(enemy_head.advanced(direc)) if snake.health == 100: continue snake_tails.append(snake.get_tail()) for direction in possible_actions: next_position = my_head.advanced(direction) # avoid eating if my_snake.health > Params_ValidActions.FOOD_BOUNDARY and avoid_food and my_snake.get_length( ) > 5: if grid_map.get_value_at_position( next_position) is Occupant.Food: continue # outofbounds if board.is_out_of_bounds(next_position): continue # body crash -> ganze Gegner Schlange minus letzten Teil if grid_map.get_value_at_position( next_position ) is Occupant.Snake and next_position not in snake_tails: continue # if next_position in forbidden_fields: # continue val_actions.append(direction) if not val_actions: for direction in possible_actions: next_position = my_head.advanced(direction) # eat if its the only possible valid action if grid_map.get_value_at_position( next_position) is Occupant.Food: val_actions.append(direction) return val_actions
def flood_kill(enemy: Snake, my_snake: Snake, kill_board: np.ndarray, board: BoardState, grid_map: GridMap): # TODO: Parameter snake_dead_in_rounds um mehr valide actions zu erhalten # - breite des PFades auf 1 begrenzen my_head = my_snake.get_head() enemy_head = enemy.get_head() kill_actions = [] search = False for part in enemy.body: kill_board[part.x][part.y] -= 1000 kill_board[my_head.x][my_head.y] -= 1000 x, y = np.unravel_index(kill_board.argmax(), kill_board.shape) print(kill_board) print(Position(x, y)) for (pos_x, pos_y) in get_valid_neigbours(x, y, kill_board): if 0 > kill_board[pos_x][pos_y] > -800: x, y = pos_x, pos_y search = True break enemy_dist = Distance.manhattan_dist(enemy_head, Position(x, y)) my_dist = Distance.manhattan_dist(my_head, Position(x, y)) if enemy_dist > my_dist and search: cost, path = AStar.a_star_search(my_head, Position(x, y), board, grid_map) count = 0 for pos, dir in path: if kill_board[pos.x][pos.y] >= 0: return [] kill_actions.append(dir) count += 1 return kill_actions
def next_step(snake: Snake, board: BoardState, grid_map: GridMap) -> Direction: head = snake.get_head() #tail = snake.get_tail() middle = Position(board.height // 2, board.width // 2) valid = ValidActions.get_valid_actions(board, snake.possible_actions(), [snake], snake, grid_map, False) #for direction in Direction: # if not board.is_out_of_bounds(head.advanced(direction)): # if not (head.advanced(direction) in snake.get_body()): # valid.append(direction) #if snake.get_length() > 10: # for action in valid: # _, path = AStar.a_star_search(head.advanced(action), tail, board, grid_map) # print(len(path)) # end, pat = path[len(path)-1] # if not end == tail: # valid.remove(action) if middle in snake.get_body(): need, next_direction = SoloSurvival.need_food(snake, board, grid_map, valid) if need: if next_direction in valid: return next_direction else: #print("not valid") return np.random.choice(valid) else: next_direction = SoloSurvival.tail_gate(snake, board, grid_map) if next_direction in valid: return next_direction else: return np.random.choice(valid) else: if SoloSurvival.food_around_head(head, board): _, path = AStar.a_star_search(head, middle, board, grid_map) _, next_direction = path[0] else: _, path = AStar.a_star_search(head, middle, board, grid_map) _, next_direction = path[0] if next_direction in valid: return next_direction else: return np.random.choice(valid)
def move(self, game_info: GameInfo, turn: int, board: BoardState, you: Snake) -> MoveResult: if you.latency: print("Latency", you.latency) start_time = time.time() grid_map: GridMap[Occupant] = board.generate_grid_map() self.Decision.set_round(turn) next_action = self.Decision.decide(you, board, grid_map) if not next_action: possible_actions = you.possible_actions() for action in possible_actions: next_position = you.get_head().advanced(action) for snake in board.snakes: if next_position == snake.get_tail() and snake.health != 100: next_action = action if not next_action: next_action = np.random.choice(possible_actions) print("Move-DAUER: ", time.time() - start_time) return MoveResult(direction=next_action)
def tail_gate(snake: Snake, board: BoardState, grid_map : GridMap) -> Direction: head = snake.get_head() tail = snake.get_tail() body = snake.get_body() distance = Distance.manhattan_dist(head, tail) if distance == 1: for direction in Direction: if head.advanced(direction) == tail: return direction else: dist = 9999 next_direction = None for direction in Direction: advanced_head = head.advanced(direction) d = Distance.manhattan_dist(advanced_head, tail) if advanced_head not in body: if d < dist: dist = d next_direction = direction return next_direction
def follow_food(snake: Snake, board: BoardState, grid_map: GridMap, reachable_food: List[Position]) \ -> List[Tuple[Position, Direction]]: my_head = snake.get_head() food = None relevant_foods = RelevantFood.get_relevant_food(snake, board.snakes, reachable_food, board.width, board.height) if not relevant_foods: return [] start_distance = 99 # get food that is nearest to my head for relevant_food in relevant_foods: distance = Distance.manhattan_dist(my_head, relevant_food) if distance < start_distance: food = relevant_food start_distance = distance print("best food:", food) if not food or start_distance > 15: return [] cost, path = AStar.a_star_search(my_head, food, board, grid_map) path_array = path return path_array
def need_food(snake: Snake, board: BoardState, grid_map: GridMap, valid: List[Direction]) -> Tuple[bool, Optional[Direction]]: health = snake.get_health() head = snake.get_head() food_around = SoloSurvival.food_all_around_body(snake, board) if health < 15: if food_around: if health == 1: _, food_pos = SoloSurvival.best_food_around_body(snake, board) food_dir = SoloSurvival.direction_to_food(snake, food_pos) return True, food_dir else: dist, food_pos = SoloSurvival.find_next_food(snake, board) #direction, path = Hungry.hunger(snake, board, grid_map, [], valid, SnakeAutomat(snake, False)) #food_dir = SoloSurvival.direction_to_food(snake, food_pos) #print("head: ", head, " food: ", food_pos) _, path_ = AStar.a_star_search(head, food_pos, board, grid_map) _, path = path_[0] #print("path: ",path) #food_dir = SoloSurvival.direction_to_food(snake, path[0]) return True, path #print("hungry health: ", health) dist, food_pos = SoloSurvival.best_food_around_body(snake, board) if food_pos is None: dist, food_pos = SoloSurvival.find_next_food(snake, board) if (health - dist) <= 1: #print("get the perfect food") food_dir = SoloSurvival.direction_to_food(snake, food_pos) return True, food_dir else: #print("anderes food nehmen") dist, food_pos = SoloSurvival.find_next_food(snake, board) if dist <= health: food_dir = SoloSurvival.direction_to_food(snake, food_pos) return True, food_dir else: return False, None
def avoid_enemy(my_snake: Snake, board: BoardState, grid_map: GridMap, valid_actions: List[Direction], action_plan: ActionPlan, direction_depth: Dict) -> Direction: if not valid_actions: possible_actions = my_snake.possible_actions() valid_actions = ValidActions.get_valid_actions(board, possible_actions, board.snakes, my_snake, grid_map, avoid_food=False) num_snakes = 4 - len(board.snakes) flood_dist = 6 if len(board.snakes) > 2 else 99 my_head = my_snake.get_head() enemy_heads = [ snake.get_head() for snake in board.snakes if snake.snake_id != my_snake.snake_id ] middle = Position(int(board.height / 2), int(board.width / 2)) corners = [ Position(0, 0), Position(0, board.width), Position(board.height, 0), Position(board.height, board.width) ] escape_cost_dict = action_plan.escape_lane(my_head, valid_actions) # TODO: Unterscheidung der Params in Late game und early game abhängig von anzahl der Schlangen p_head = Params_Anxious.ALPHA_DISTANCE_ENEMY_HEAD[num_snakes] * (-1) p_corner = Params_Anxious.BETA_DISTANCE_CORNERS[num_snakes] p_mid = Params_Anxious.THETA_DISTANCE_MID[num_snakes] * (-1) p_border = Params_Anxious.EPSILON_NO_BORDER[num_snakes] p_food = (Params_Anxious.GAMMA_DISTANCE_FOOD[num_snakes] * 20 / my_snake.health) p_flood_min = Params_Anxious.OMEGA_FLOOD_FILL_MIN[num_snakes] * (-1) p_flood_max = Params_Anxious.OMEGA_FLOOD_FILL_MAX[num_snakes] p_flood_dead = Params_Anxious.OMEGA_FLOOD_DEAD[num_snakes] p_corridor = Params_Anxious.RHO_ESCAPE_CORRIDOR[num_snakes] * (-1) p_length = Params_Anxious.TAU_PATH_LENGTH[num_snakes] total_cost = np.array([], dtype=np.float64) direction_cost = np.zeros(10) for action in valid_actions: next_position = my_head.advanced(action) # calculate flood fill flood_fill_value, relevant_food = FloodFill.get_fill_stats( board, next_position, my_snake.snake_id, new_pos=True) enemy_flood = sum([ flood_fill_value[snake.snake_id] for snake in board.snakes if snake.snake_id != my_snake.snake_id and Distance.manhattan_dist(snake.get_head(), my_head) < flood_dist ]) # calculate all costs for heuristics direction_cost[0] = direction_depth[action] * p_length direction_cost[1] = escape_cost_dict[action] * p_corridor direction_cost[2] = ActionPlan.punish_border_fields( next_position, my_head, grid_map.width, grid_map.height) * p_border direction_cost[3] = sum([ Distance.manhattan_dist(next_position, enemy_head) for enemy_head in enemy_heads ]) * p_head direction_cost[4] = sum([ Distance.manhattan_dist(next_position, corner) for corner in corners if Distance.manhattan_dist(next_position, corner) < 9 ]) * p_corner direction_cost[5] = Distance.manhattan_dist(next_position, middle) * p_mid direction_cost[6] = flood_fill_value[ my_snake.snake_id] * p_flood_max direction_cost[7] = enemy_flood * p_flood_min direction_cost[8] = len(relevant_food) * p_food # extra points for killing enemy snake if num_snakes == 1: enemy_id = [ snake.snake_id for snake in board.snakes if snake.snake_id != my_snake.snake_id ][0] if flood_fill_value[enemy_id] < 20: flood_kill_value = (20 - flood_fill_value[enemy_id]) * 1000 direction_cost[9] = flood_kill_value * p_flood_dead total_cost = np.append(total_cost, direction_cost.sum()) direction_cost = np.zeros(10) if valid_actions: best_action = valid_actions[int(np.argmax(total_cost))] print(best_action) else: best_action = None return best_action