Пример #1
0
    def move(self, direction: Direction) -> (Point, bool, bool):

        # move the snake in a new direction
        snake_head = self.snake.move(direction, self.ate_food)

        self._n_steps += 1

        if self.snake.touches_tail() or self.__is_touching_wall():
            self.game_over()
            return Point.from_numpy(
                snake_head), self.ate_food, self.is_game_over()

        # check if the snake touches food
        if self.__is_touching_food():
            self.ate_food = True
            self._n_food_eaten += 1
            self._n_steps_without_food = 0
            print("Ate food")
            self.__random_food()
        else:
            self.ate_food = False
            self._n_steps_without_food += 1

        if self._n_steps_without_food > 1000:
            self.game_over()
            return Point.from_numpy(
                snake_head), self.ate_food, self.is_game_over()

        self.__draw_snake()
        self.__draw_food()

        return Point.from_numpy(snake_head), self.ate_food, self.is_game_over()
Пример #2
0
    def lidar_west_pulse(self):
        """
        The lidar beam that travels west within the game.
        :return: a point of where the beam either hit a wall or a part of the environment.
        """
        pulse_x, pulse_y = self.snakeEnv.snake.head.pos()
        west_pulse = Point(pulse_x, pulse_y)
        west_wall = Point((-1) * (self.snakeEnv.screen_width / 2), pulse_y)

        hit_obstacle = False
        hit_apple = False

        while True:

            if west_pulse.x <= west_wall.x:
                hit_obstacle = True
                break

            if self.snakeEnv.snake.point_is_in_tail(west_pulse)[0]:
                hit_obstacle = True
                break

            if self.snakeEnv.current_food.point_is_in_food(west_pulse)[0]:
                hit_apple = True
                break

            west_pulse.offset(-1, 0)

        return (west_pulse, hit_obstacle, hit_apple)
        """
Пример #3
0
    def lidar_north_pulse(self):
        """
        The lidar beam that travels north within the game.
        :return: a point of where the beam either hit a wall or a part of the environment.
        """
        pulse_x, pulse_y = self.snakeEnv.snake.head.pos()
        north_pulse = Point(pulse_x, pulse_y)
        north_wall = Point(pulse_x, self.snakeEnv.screen_height / 2)

        hit_obstacle = False
        hit_apple = False

        while True:

            if north_pulse.y >= north_wall.y:
                hit_obstacle = True
                break

            if self.snakeEnv.snake.point_is_in_tail(north_pulse)[0]:
                hit_obstacle = True
                break

            if self.snakeEnv.current_food.point_is_in_food(north_pulse)[0]:
                hit_apple = True
                break

            north_pulse.offset(0, 1)

        return (north_pulse, hit_obstacle, hit_apple)
Пример #4
0
    def __left_lidar(self):
        """
        Gets the Snake's 5 point lidar distances when it is facing left.

        Parameters:
            None

        Returns:
            lidar - A 1D numpy array with 5 entries, one for each lidar distance.
        """
        lidar_pulses = [
            self.lidar_south_pulse(),
            self.lidar_south_west_pulse(),
            self.lidar_west_pulse(),
            self.lidar_north_west_pulse(),
            self.lidar_north_pulse()
        ]
        lidar = np.zeros((len(lidar_pulses) * 3), dtype=np.float32)
        snake_x, snake_y = self.snakeEnv.snake.head.pos(
        )[0], self.snakeEnv.snake.head.pos()[1]
        snake_pos = Point(snake_x, snake_y)

        for i in range(len(lidar_pulses)):
            lidar_pulse = lidar_pulses[i]
            index = i * 3
            lidar[index] = snake_pos.distance(lidar_pulse[0])
            lidar[index + 1] = lidar_pulse[1]
            lidar[index + 2] = lidar_pulse[2]

        self.lidar_end_points = [
            lidar_pulses[0][0], lidar_pulses[1][0], lidar_pulses[2][0],
            lidar_pulses[3][0], lidar_pulses[4][0]
        ]

        return lidar
Пример #5
0
    def __stop_lidar(self):
        """
        Gets the snakes 8 point lidar in it's starting position.
        :return:
        """
        lidar_pulses = [
            self.lidar_north_pulse(),
            self.lidar_north_east_pulse(),
            self.lidar_east_pulse(),
            self.lidar_south_east_pulse(),
            self.lidar_south_pulse(),
            self.lidar_south_west_pulse(),
            self.lidar_west_pulse(),
            self.lidar_north_west_pulse()
        ]
        lidar = np.zeros((len(lidar_pulses) * 3), dtype=np.float32)
        snake_x, snake_y = self.snakeEnv.snake.head.pos(
        )[0], self.snakeEnv.snake.head.pos()[1]
        snake_pos = Point(snake_x, snake_y)

        for i in range(len(lidar_pulses)):
            lidar_pulse = lidar_pulses[i]
            index = i * 3
            lidar[index] = snake_pos.distance(lidar_pulse[0])
            lidar[index + 1] = lidar_pulse[1]
            lidar[index + 2] = lidar_pulse[2]

        self.lidar_end_points = [
            lidar_pulse[0] for lidar_pulse in lidar_pulses
        ]

        return lidar
Пример #6
0
    def __get_food_distance_reward(self, previous_location: Point,
                                   current_location: Point):
        """

        :param previous_location: A type point that specifies previous location of the environment
        :param current_location: A type point that specifies the current location of the environment
        :return: 1 if the environment moved towards the food, 0 if the environment moved away from the food
        """
        """
        food_x = self.current_food.head.xcor()
        food_y = self.current_food.head.ycor()
        food_point = Point(food_x, food_y)
        if (previous_location.distance(food_point) > current_location.distance(food_point)):
            return 1

        return 
        """
        def normalise(x):
            return 1 - (x / self.max_distance)

        food_x = self.current_food.head.xcor()
        food_y = self.current_food.head.ycor()
        food_point = Point(food_x, food_y)
        multiplier = len(
            self.snake.segments) if len(self.snake.segments) > 2 else 1
        return normalise(current_location.distance(food_point)) * multiplier
Пример #7
0
def distance_to_apple_percentage_tail_length_multiplier(env: SnakeEnv):
    def normalise(x):
        return 1 - (x / env.max_distance)

    food_x = env.current_food.head.xcor()
    food_y = env.current_food.head.ycor()
    food_point = Point(food_x, food_y)
    current_location = Point(env.snake.head.xcor(), env.snake.head.ycor())
    multiplier = len(env.snake.segments) if len(env.snake.segments) > 2 else 1
    return normalise(current_location.distance(food_point)) * multiplier
Пример #8
0
    def __wall_distances(self, snake_head: Point,
                         direction: Direction) -> np.array:
        north_wall = Point(snake_head.x, 0)
        west_wall = Point(0, snake_head.y)
        south_wall = Point(snake_head.x, self.game.dimensions()[1])
        east_wall = Point(self.game.dimensions()[0], snake_head.y)

        snake_north_wall_dist = snake_head.distance(north_wall)
        snake_west_wall_dist = snake_head.distance(west_wall)
        snake_south_wall_dist = snake_head.distance(south_wall)
        snake_east_wall_dist = snake_head.distance(east_wall)

        if direction == Direction.UP:
            return np.array([
                snake_west_wall_dist, snake_north_wall_dist,
                snake_east_wall_dist
            ])

        if direction == Direction.RIGHT:
            return np.array([
                snake_north_wall_dist, snake_east_wall_dist,
                snake_south_wall_dist
            ])

        if direction == Direction.DOWN:
            return np.array([
                snake_east_wall_dist, snake_south_wall_dist,
                snake_west_wall_dist
            ])

        if direction == Direction.LEFT:
            return np.array([
                snake_south_wall_dist, snake_west_wall_dist,
                snake_north_wall_dist
            ])
Пример #9
0
    def lidar_south_east_pulse(self):
        """
        The lidar beam that travels south east within the game.
        :return: a point of where the beam either hit a wall or a part of the environment.
        """
        pulse_x, pulse_y = self.snakeEnv.snake.head.pos()
        south_east_pulse = Point(pulse_x, pulse_y)
        south_wall = Point(pulse_x, (-1) * (self.snakeEnv.screen_height / 2))
        east_wall = Point(self.snakeEnv.screen_width / 2, pulse_y)

        hit_obstacle = False
        hit_apple = False

        while True:

            if south_east_pulse.y <= south_wall.y or south_east_pulse.x >= east_wall.x:
                hit_obstacle = True
                break

            if self.snakeEnv.snake.point_is_in_tail(south_east_pulse)[0]:
                hit_obstacle = True
                break

            if self.snakeEnv.current_food.point_is_in_food(
                    south_east_pulse)[0]:
                hit_apple = True
                break

            south_east_pulse.offset(1, -1)

        return (south_east_pulse, hit_obstacle, hit_apple)
        """
Пример #10
0
    def __random_food(self) -> Point:
        available_slots = self.__available_food_positions()

        grid_slot = random.choice(tuple(available_slots))
        n_columns = self.screen_width / self.snake_size
        n_rows = self.screen_height / self.snake_size
        slot_x = grid_slot % n_columns
        slot_y = math.floor(grid_slot / n_rows)

        food_x = slot_x * self.snake_size
        food_y = slot_y * self.snake_size
        # self.food = pygame.Rect(food_x, food_y, self.snake_size, self.snake_size)
        return Point(food_x, food_y)
Пример #11
0
    def move(self, direction: Direction) -> (Point, bool, bool):
        snake_head = self.grid.move_snake(direction, self.ate_food)
        self._n_steps += 1

        if self.grid.snake().touches_tail(
        ) or self.grid.snake_is_touching_wall():
            self.game_over()
            return Point.from_numpy(
                snake_head), self.ate_food, self.is_game_over()

        # check if the snake touches food
        if self.grid.snake_is_touching_food():
            self.ate_food = True
            self._n_food_eaten += 1
            self._n_steps_without_food = 0
            self.grid.random_food()
        else:
            self.ate_food = False
            self._n_steps_without_food += 1

        if self._n_steps_without_food > 1000:
            self.game_over()

        return Point.from_numpy(snake_head), self.ate_food, self.is_game_over()
Пример #12
0
 def start_position(self) -> Point:
     start_x = self.screen_width / 2
     start_y = self.screen_height / 2
     return Point(start_x, start_y)
Пример #13
0
 def food_position(self) -> Point:
     return Point.from_numpy(self.grid.food().position())
Пример #14
0
 def snake_head(self) -> Point:
     return Point.from_numpy(self.grid.snake().head())
Пример #15
0
 def __is_touching_food(self) -> bool:
     return Point.from_numpy(self.snake.head()) == self.food_position()
Пример #16
0
 def get_current_location(self):
     return Point(self.head.xcor(), self.head.ycor())