예제 #1
0
class State_Defend():

    def __init__(self):
        self.name = "defend state"
        self.helper = None

    def get_move(self, grid_data, data):
        self.height = data.get("board").get("height")
        self.width = data.get("board").get("width")
        self.head_x = data.get("you").get("body")[0].get("x")
        self.head_y = data.get("you").get("body")[0].get("y")
        self.my_snake_health = data.get("you").get("health")
        self.my_snake_length = len(data.get("you").get("body"))
        self.pathfinder = AStar((self.head_x, self.head_y), grid_data[0], self.width, self.height)
        self.grid_data = grid_data
        self.data = data

        move = self.move_to_food()

        #NOTE FIND TAIL MODE
        if self.my_snake_length > 3 and self.my_snake_health > 65 or move == None:
            move = self.chase_tail(self.my_snake_health == 100)

        if move:
            return move
        else:
            backup_moves = self.helper.get_backup_move((self.head_x, self.head_y), self.grid_data[0], self.height, self.width)
            if backup_moves:
                return self.helper.get_move_letter((self.head_x, self.head_y), backup_moves[0])
            else:
                return 'up'


    def move_to_food(self):
        food_list = self.grid_data[1]
        current_minimum = float('inf')
        current_path = None
        for food in food_list:
            path = self.pathfinder.compute_path(tuple(food))
            if path:
                path = list(path)
                if len(path) < current_minimum:
                    current_minimum = len(path)
                    current_path = path
        if current_path and self.helper.is_good_move(current_path[1], self.grid_data[0], self.my_snake_length):
            return self.helper.get_move_letter((self.head_x, self.head_y), list(current_path)[1])

    def chase_tail(self, snake_growing):
        my_tail = (self.data.get("you").get("body")[-1].get("x"), self.data.get("you").get("body")[-1].get("y"))
        self.grid_data[0][my_tail[1]][my_tail[0]] = 1
        path = self.pathfinder.compute_path(my_tail)
        self.grid_data[0][my_tail[1]][my_tail[0]] = -1

        if path:
            danger_tail_move = (path[1] == (self.data.get("you").get("body")[-1].get("x"), self.data.get("you").get("body")[-1].get("y")) and self.tail_is_in_danger())
            if not danger_tail_move:
                if not snake_growing:
                    return self.helper.get_move_letter((self.head_x, self.head_y), list(path)[1])
                else:
                    neighbours = self.helper.get_neighbors(my_tail, self.grid_data[0], self.height, self.width)
                    for neighbour in neighbours:
                        path = self.pathfinder.compute_path(neighbour)
                        if path:
                            return self.helper.get_move_letter((self.head_x, self.head_y), list(path)[1])

    def tail_is_in_danger(self):
        my_tail = (self.data.get("you").get("body")[-1].get("x"), self.data.get("you").get("body")[-1].get("y"))
        for snake in self.data.get("board").get("snakes"):
            (x, y) = (snake.get("body")[0].get("x"), snake.get("body")[0].get("y"))
            moves = [(nx, ny) for nx, ny in[(x, y - 1), (x, y + 1), (x - 1, y), (x + 1, y)] if 0 <= nx < self.width and 0 <= ny < self.height]
            if my_tail in moves:
                return True
        return False
예제 #2
0
class State_Attack():

    def __init__(self):
        self.name = "attack state"
        self.helper = None

    def get_move(self, grid_data, data):
        self.height = data.get("board").get("height")
        self.width = data.get("board").get("width")
        self.head_x = data.get("you").get("body")[0].get("x")
        self.head_y = data.get("you").get("body")[0].get("y")
        self.my_snake_health = data.get("you").get("health")
        self.my_snake_length = len(data.get("you").get("body"))
        self.pathfinder = AStar((self.head_x, self.head_y), grid_data[0], self.width, self.height)
        self.grid_data = grid_data
        self.data = data

        snakes = data.get("board").get("snakes")
        head = (self.head_x, self.head_y)

        # find closest snake ID
        target_snake_id = self.find_closest_snake_head(snakes)

        # Guard to make sure our snake doesn't just starve
        if self.my_snake_health < 40:
            return self.default_behaviour()

        if target_snake_id:
            return self.attack_snake_head(snakes, target_snake_id)
        else:
            return self.default_behaviour()

    def find_closest_snake_head(self, snakes):
        current_minimum = float('inf')
        current_path = None
        current_id = None
        for snake in snakes:
            if snake.get("id") == self.data.get("you").get("id"):
                continue
            enemy_head_x = snake.get("body")[0].get("x")
            enemy_head_y = snake.get("body")[0].get("y")
            dist = self.helper.get_crows_dist((self.head_x, self.head_y), (enemy_head_x, enemy_head_y))
            if dist < current_minimum:
                current_minimum = dist
                current_id = snake.get("id")
        return current_id

    def attack_snake_head(self, snakes, target_id):
        target_snake = None
        # Find target snake data
        for snake in snakes:
            if snake.get("id") == target_id:
                target_snake = snake.get("body")

                target_position = self.get_danger_squares(target_snake)
                if target_position:
                    #If there is some point in the snakes' danger zone, go to it
                    target_y = target_position[1]
                    target_x = target_position[0]

                    old_val = self.grid_data[0][target_y][target_x]

                    self.grid_data[0][target_y][target_x] = 1;
                    target_move = self.move_to_food([target_position])

                    self.grid_data[0][target_y][target_x] = old_val;

                    return target_move
                else:
                    return self.default_behaviour()

    # Return the first entry of possible danger squares around a snakes' head
    def get_danger_squares(self, target_snake):
        available_moves = []
        head_x = target_snake[0].get("x")
        head_y = target_snake[0].get("y")

        top = head_y - 1
        bottom = head_y + 1
        left = head_x - 1
        right = head_x + 1

        if top >= 0 and self.grid_data[0][top][head_x] != 0:
            available_moves.append((head_x, top))
        if bottom < self.height and self.grid_data[0][bottom][head_x] != 0:
            available_moves.append((head_x, bottom))
        if left >= 0 and self.grid_data[0][head_y][left] != 0:
            available_moves.append((left, head_y))
        if right < self.width and self.grid_data[0][head_y][right] != 0:
            available_moves.append((right, head_y))
        if len(available_moves) > 0:
            return available_moves[0]
        else:
            return None

    # This needs to get changed to a uniquely named method, and altered to do less...
    def move_to_food(self, food_list):
        current_minimum = float('inf')
        current_path = None
        for food in food_list:
            path = self.pathfinder.compute_path(tuple(food))
            if path:
                path = list(path)
                if len(path) < current_minimum:
                    current_minimum = len(path)
                    current_path = path
        if current_path and self.helper.is_good_move(list(current_path)[1], self.grid_data[0], self.my_snake_length):
            #TODO figure out how to stop two competing SNAKES from trying to take the same square
            return self.helper.get_move_letter((self.head_x, self.head_y), list(current_path)[1])
        else:
            backup_moves = self.helper.get_backup_move((self.head_x, self.head_y), self.grid_data[0], self.height, self.width)
            if backup_moves:
                return self.helper.get_move_letter((self.head_x, self.head_y), backup_moves[0])
            else:
                return 'up'

    def default_behaviour(self):
        move = self.move_to_food(self.grid_data[1])
        #NOTE FIND TAIL MODE
        if move:
            return move
            # There should ALWAYS be a move since move_to_food has all the guards
        else:
            backup_moves = self.helper.get_backup_move((self.head_x, self.head_y), self.grid_data[0], self.height, self.width)
            if backup_moves:
                return self.helper.get_move_letter((self.head_x, self.head_y), backup_moves[0])
            else:
                return 'up'