Beispiel #1
0
    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
Beispiel #2
0
    def best_food_around_body(snake: Snake, board: BoardState) -> Tuple[int, Optional[Position]]:

        length = snake.get_length()
        health = snake.get_health()
        body = snake.get_body()
        foods = [] #Tuple[int, Position]
        position = 0
        any_f = False
        for part in body:
            for direction in Direction:
                if board.is_occupied_by_food(part.advanced(direction)):
                    diff = length - position
                    add = diff, part
                    foods.append(add)
                    any_f = True
            position += 1
        best_dist = 999999
        best_food = None
        if any_f:
            for dist, food in foods:
                if (dist == snake.get_length()) and (health <= 1):
                    return 1, food
                if dist < best_dist and dist <= health:
                    if dist == health:
                        return dist, food
                    best_dist = dist
                    best_food = food
            return best_dist, best_food
        else:
            return 0, None
Beispiel #3
0
    def parse_snake(json):

        snake_id = json['id']
        snake_name = json['name']
        # kilab specific attribute
        snake_color = json['color'] if 'color' in json else None
        health = json['health']
        body_json_list = json['body']
        latency = json['latency'] if 'latency' in json else 0
        # head = json['head']
        # length = json['length']
        shout = json['shout'] if 'shout' in json else ""
        squad = json['squad'] if 'squad' in json else ""

        body = Importer.parse_position_array(body_json_list)

        snake = Snake(
            snake_id=snake_id,
            snake_name=snake_name,
            snake_color=snake_color,
            health=health,
            body=body,
            latency=latency,
            shout=shout,
            squad=squad,
        )

        if "elimination_event" in json:
            e = json["elimination_event"]
            if e is not None:
                event = EliminationEvent(EliminatedCause(e["cause"]),
                                         e["turn"], e["by"])
                snake.elimination_event = event

        return snake
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
    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
Beispiel #8
0
    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)
Beispiel #9
0
    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
Beispiel #10
0
    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
Beispiel #11
0
    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)
Beispiel #12
0
    def create_initial_board_state(self, width: int, height: int, snake_ids: List[str]):

        board: BoardState = BoardState(width=width, height=height)

        for snake_id in snake_ids:
            board.add_snake(Snake(snake_id=snake_id))

        self.place_snakes(board)
        self.place_food(board)

        return board
Beispiel #13
0
    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
Beispiel #14
0
    def test_clone(self):

        snake_a = Snake(snake_id="snake-a", body=[Position(x=3, y=3)])
        snake_b = Snake(snake_id="snake-a", body=[Position(x=9, y=9)])

        food_a = Food(x=1, y=2)

        snakes = [snake_a, snake_b]
        food = [food_a]

        board = BoardState(width=15, height=15, snakes=snakes, food=food)

        board_clone = board.clone()

        self.assertNotEqual(id(board), id(board_clone))
        self.assertNotEqual(id(board.snakes[0]), id(board_clone.snakes[0]))
        self.assertNotEqual(id(board.food[0]), id(board_clone.food[0]))

        board_export = board.to_json()
        board_clone_export = board_clone.to_json()

        self.assertEqual(board_export, board_clone_export)
Beispiel #15
0
    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
Beispiel #16
0
    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
Beispiel #17
0
    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
Beispiel #18
0
    def move(self, game_info: GameInfo, turn: int, board: BoardState, you: Snake) -> MoveResult:

        possible_actions = you.possible_actions()

        if possible_actions is None:
            return None

        grid_map = board.generate_grid_map()

        busy_action = self.feel_busy(board, you, grid_map)
        if busy_action is not None:
            return MoveResult(direction=busy_action)

        random_action = np.random.choice(possible_actions)
        return MoveResult(direction=random_action)
Beispiel #19
0
    def test_to_json(self):

        snake_a = Snake(snake_id="snake-a", body=[Position(x=3, y=3)])
        snake_b = Snake(snake_id="snake-a", body=[Position(x=9, y=9)])

        food_a = Food(x=1, y=2)
        hazard_a = Hazard(x=4, y=1)

        snakes = [snake_a, snake_b]
        food = [food_a]
        hazards = [hazard_a]

        board = BoardState(width=15,
                           height=20,
                           snakes=snakes,
                           food=food,
                           hazards=hazards)

        json_data = board.to_json()

        self.assertEqual(json_data['width'], 15)
        self.assertEqual(json_data['height'], 20)
        self.assertListEqual(json_data['food'], [{'x': 1, 'y': 2}])
        self.assertListEqual(json_data['hazards'], [{'x': 4, 'y': 1}])
Beispiel #20
0
    def food_all_around_body(snake: Snake, board: BoardState) -> bool:

        body = snake.get_body()
        food_next_to_body = 0
        for part in body:
            thispart = False
            for direction in Direction:
                if board.is_occupied_by_food(part.advanced(direction)):
                    thispart = True
            if thispart:
                food_next_to_body += 1
        if food_next_to_body == len(body):
            return True
        else:
            return False
Beispiel #21
0
    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
Beispiel #22
0
    def hunger(snake: Snake, board: BoardState, grid_map: GridMap, food_path: List[Position],
               valid_actions: List[Direction], my_automat: SnakeAutomat) -> Tuple[Direction, List[Position]]:

        possible_actions = snake.possible_actions()
        back_up_actions = ValidActions.get_valid_actions(board, possible_actions, board.snakes, snake, grid_map, False)

        if valid_actions:
            action = np.random.choice(valid_actions)
        else:
            action = np.random.choice(back_up_actions)

        if not food_path:
            print(my_automat.reachable_food)
            food_path = Hungry.follow_food(snake, board, grid_map, my_automat.reachable_food)
        if food_path:
            print("Food_Path: ", food_path)
            if food_path[0][1] in valid_actions:
                action = food_path[0][1]
                food_path.pop(0)
        else:
            food_path = []
        print(action)

        return action, food_path
Beispiel #23
0
    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
Beispiel #24
0
 def feed_snake(self, snake: Snake):
     self.grow_snake(snake)
     snake.health = self.snake_max_health
Beispiel #25
0
 def grow_snake(self, snake: Snake):
     if len(snake.body) > 0:
         tail = snake.get_tail()
         snake.body.append(tail)