Exemplo n.º 1
0
def eval_genome(g, config):

    net = neat.nn.FeedForwardNetwork.create(g, config)

    cycles_per_net = 5
    fitnesses = [0] * cycles_per_net

    for cycle in range(cycles_per_net):
        x = random.randrange(SNAKE_WIDTH + SNAKE_WIDTH / 2,
                             WIN_WIDTH - (SNAKE_WIDTH + SNAKE_WIDTH / 2),
                             SNAKE_WIDTH)
        y = random.randrange(SNAKE_WIDTH, WIN_WIDTH - (SNAKE_WIDTH),
                             SNAKE_WIDTH)
        h = Head(WIN_WIDTH, SNAKE_WIDTH, x, y)

        b1 = Body(h.x, h.y + SNAKE_WIDTH, h, SNAKE_WIDTH)
        b2 = Body(b1.x, b1.y + SNAKE_WIDTH, b1, SNAKE_WIDTH)
        bodies = [b1, b2]
        a = Apple(WIN_WIDTH, SNAKE_WIDTH, h, bodies)

        run = True
        score = 0
        time = 200
        while (run):
            time -= 1
            fitnesses[cycle] += 0.01

            if (time <= 0):
                run = False
                break

            # Control Code
            inputs = game.determine_position(h, bodies, a)

            output = net.activate(
                (inputs
                 ))  #distance_up, distance_down, distance_left, distance_right

            i = output.index(max(output))
            if i == 0:
                h.moveForward()
            elif i == 1:
                h.moveLeft()
            elif i == 2:
                h.moveRight()

            game.update_positions(h, bodies)

            if (h.check_collisions(bodies)):
                run = False
                break

            if (h.check_apple(a)):
                score += 1
                fitnesses[cycle] += 10 + time * 0.1
                time = 200
                end = bodies[-1]
                bodies.append(Body(end.p_x, end.p_y, end, SNAKE_WIDTH))
                a.reset(h, bodies)

    return [statistics.median(fitnesses), net]
Exemplo n.º 2
0
def single_game(manual, distances=False, net=None, generation=None):
    win = pygame.display.set_mode((WIN_WIDTH, WIN_WIDTH))
    win.fill((0, 0, 0))

    clock = pygame.time.Clock()

    # generating head of snake
    x = random.randrange(SNAKE_WIDTH + SNAKE_WIDTH / 2,
                         WIN_WIDTH - (SNAKE_WIDTH + SNAKE_WIDTH / 2),
                         SNAKE_WIDTH)
    y = random.randrange(SNAKE_WIDTH, WIN_WIDTH - (SNAKE_WIDTH), SNAKE_WIDTH)
    h = Head(WIN_WIDTH, SNAKE_WIDTH, x, y)

    # generating body of snake
    b1 = Body(h.x, h.y + SNAKE_WIDTH, h, SNAKE_WIDTH)
    b2 = Body(b1.x, b1.y + SNAKE_WIDTH, b1, SNAKE_WIDTH)
    bodies = [b1, b2]

    # generating apple for snake to eat
    a = Apple(WIN_WIDTH, SNAKE_WIDTH, h, bodies)

    run = True
    score = 0
    time = 200
    while (run):

        # setting clock speed. Slower if the game is being manually run
        if manual:
            clock.tick(MANUAL_SNAKE_SPEED)
        else:
            clock.tick(SNAKE_SPEED)

        # Counting down time and cause the game to quit if an apple hasnt been eaten within the time frame
        time -= 1

        if (time <= 0):
            run = False
            print('Time Out!')
            break

        # Automated Control
        # inputs to neural network:
        # distance forward, distance left, distance right, apple right, apple top
        inputs = determine_position(h, bodies, a)

        # Previous attempts
        # head x, head y, boundaries, apple x, apple y # Failed to train after 100 generatations of 100 population -> has no sense of direction
        # distance front, distance down, distance left, distance right, left distance to apple, upwards distance to apple # Failed to train after 100 generatations of 100 population -> has no sense of direction

        # if the user is not playing the game manually, run the game with automated controls
        if not (manual):
            # run inputs into neural network
            output = net.activate((inputs))

            # determing direction indicated by NN
            i = output.index(max(output))
            if i == 0:
                h.moveForward()
            elif i == 1:
                h.moveLeft()
            elif i == 2:
                h.moveRight()

        for event in pygame.event.get():
            # checking if exit button is pushed on game
            if (event.type == pygame.QUIT):
                run = False
                break

            # manual control - checking for key pushes
            if manual:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP:
                        h.KeyMoveUp()
                        break  # breaking prevents multiple keys being processed at the same time
                    elif event.key == pygame.K_DOWN:
                        h.KeyMoveDown()
                        break
                    elif event.key == pygame.K_LEFT:
                        h.KeyMoveLeft()
                        break
                    elif event.key == pygame.K_RIGHT:
                        h.KeyMoveRight()
                        break

        # update the position of the head and bodies
        update_positions(h, bodies)

        # checking for collisions
        if (h.check_collisions(bodies)):
            run = False
            print('Collision!')
            break

        # check if head ate apple
        if (h.check_apple(a)):
            score += 1
            time = 200
            end = bodies[-1]
            bodies.append(Body(end.p_x, end.p_y, end, SNAKE_WIDTH))
            a.reset(h, bodies)
            # if (score >= 200):
            #     run = False
            #     break

        # outputing distances for debugging
        distance_list = []
        if (distances):
            distance_list = [inputs[0], inputs[1], inputs[2]]

        # drawing game state onto screen
        draw_screen(win, h, bodies, a, distance_list, score, time, generation)
Exemplo n.º 3
0
class Game(object):
    def __init__(self, window):
        self.snake = Snake()
        self.apple = Apple()
        self.window = window
        self.grid = []
        self.score = 0

    def move_snake(self, key):
        """Manual move of snake"""
        if key in [KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT]:
            self.snake.move(key)
        else:
            self.snake.move(self.snake.last_direction)

        if self.snake.head == self.apple.position:
            self.snake.eat(self.apple, self.grid)
            self.score += 1

        if self.snake.is_collide():
            self.reset()

    def automove(self):
        """Deplace position of the snake with A* algorithm"""
        path = find_path(tuple(self.snake.head), tuple(self.apple.position), self.grid)
        move = path[0] if path else False

        if not move:
            move = self.any_possible_move()

        if move:
            if not self.snake.is_eating:
                self.snake.position.pop(0)

            self.snake.is_eating = False
            self.snake.position.append(move)
            self.snake.head = self.snake.position[-1]
            self.snake.tail = self.snake.position[0]

        if self.snake.head == self.apple.position:
            self.snake.eat(self.apple, self.grid)
            self.score += 1

        if self.snake.is_collide() or not move:
            self.reset()

    def any_possible_move(self):
        """Return any possible position"""
        neighbors = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        for i, j in neighbors:
            neighbor = self.snake.head[0] + i, self.snake.head[1] + j
            if self.grid[neighbor[0]][neighbor[1]] == 0:
                return [neighbor[0], neighbor[1]]
        return False

    def display(self):
        """display game"""
        self.grid[:] = []
        for line in range(HEIGHT):
            self.grid.append([])
            for column in range(WIDTH):
                if column == 0 or line == 0 or column == WIDTH - 1 or line == HEIGHT - 1:
                    self.grid[line].append(1)
                else:
                    self.grid[line].append(0)

        for line, column in self.snake.position:
            self.grid[line][column] = 1
            self.window.addstr(line, column, 's')

        line, column = self.apple.position
        self.window.addstr(line, column, 'a')

    def reset(self):
        """Reset game"""
        self.apple.reset()
        self.snake.reset()
        self.score = 0
Exemplo n.º 4
0
class Field:
    def __init__(self, ga, width, height):
        self.ga = ga
        self.width = width
        self.height = height
        self.sc = pygame.display.set_mode([width + 1, height + 1])
        self.clock = pygame.time.Clock()
        self.snake = Snake(self.sc, self)
        self.apple = Apple(self.sc, self)
        self.death_stats = [0] * 3
        pygame.init()

    def get_fitness(self, individual):
        self.ga.ind_counter += 1
        self.snake.reset()
        self.snake.load_weights(individual)
        self.apple.reset()

        while True:
            self.snake.move()
            self.draw()

            if self.snake.check_apple_collision():
                self.apple.reset()

            if self.snake.check_wall_collision():
                self.death_stats[0] += 1
                break

            if self.snake.check_self_collision():
                self.death_stats[1] += 1
                break

            if self.snake.check_energy():
                self.death_stats[2] += 1
                break

            check_events()

        return self.snake.get_fitness()

    # Проверяем не вышла ли голова змейки на границы поля
    def is_valid_pos(self, pos):
        if pos.x < 0 or pos.x > self.width - self.snake.size or pos.y < 0 or pos.y > self.height - self.snake.size:
            return False
        return True

    # Получаем случайную позицию на поле [доработать]
    def get_random_pos(self):
        while True:
            pos = Vector2(randrange(0, self.width, self.snake.size),
                          randrange(0, self.height, self.snake.size))
            if pos not in self.snake.get_segments():
                return pos

    def get_apple_pos(self):
        return self.apple.get_pos()

    def set_death_stats(self, death_stats):
        self.death_stats = death_stats

    def get_death_stats(self):
        return self.death_stats

    def draw(self):
        if settings['animation']:
            self.sc.fill(pygame.Color('#282A36'))
            if settings['grid']:
                self.draw_grid()
            if settings['info']:
                self.draw_info()
            if settings['snake_footprint']:
                self.snake.draw_footprint()
            if settings['snake_vectors']:
                self.snake.draw_vectors()

            self.snake.draw()
            self.apple.draw()
            pygame.display.flip()

            if settings['slow_mode']:
                self.clock.tick(settings['fps'])

    def draw_grid(self):
        for x in range(0, self.width + self.snake.size, self.snake.size):
            pygame.draw.aaline(self.sc, '#44475a', [x, 0], [x, self.height])
        for y in range(0, self.height + self.snake.size, self.snake.size):
            pygame.draw.aaline(self.sc, '#44475a', [0, y], [self.width, y])

    def draw_info(self):
        self.draw_text(20, 20, f'HIGH SCORE: {self.snake.high_score}')
        self.draw_text(20, 40, f'GENERATION: {self.ga.gen_counter}')
        self.draw_text(20, 60,
                       f'GENOME: {self.ga.ind_counter}/{self.ga.pop_length}')
        self.draw_text(20, 80, f'SCORE: {self.snake.score}')
        self.draw_text(20, 100, f'STEPS: {self.snake.steps}')
        self.draw_text(20, 120, f'ENERGY: {self.snake.get_energy()}')
        if sum(self.death_stats) != 0:
            percent = '{:.2f}'.format(self.death_stats[0] * 100 /
                                      sum(self.death_stats))
            self.draw_text(
                20, 140,
                f'BUMPED INTO A WALL: {self.death_stats[0]} | {percent}%')
            percent = '{:.2f}'.format(self.death_stats[1] * 100 /
                                      sum(self.death_stats))
            self.draw_text(
                20, 160,
                f'HIT ITS OWN TAIL: {self.death_stats[1]} | {percent}%')
            percent = '{:.2f}'.format(self.death_stats[2] * 100 /
                                      sum(self.death_stats))
            self.draw_text(
                20, 180, f'DIED OF HUNGER: {self.death_stats[2]} | {percent}%')

        self.draw_text(20, 220, f'HOTKEYS:')
        self.draw_text(20, 240, f'A - evolution without animation')
        self.draw_text(20, 260, f'S - slow/fast')
        self.draw_text(20, 280, f'M - smart speed')
        self.draw_text(20, 300, f'F - footprint')
        self.draw_text(20, 320, f'V - vectors')
        self.draw_text(20, 340, f'G - grid')
        self.draw_text(20, 360, f'I - info')

        self.draw_text(
            20, 400,
            f'Snake: [ {self.snake.get_head().x}, {self.snake.get_head().y} ]')
        self.draw_text(
            20, 420,
            f'Apple: [ {self.apple.get_pos().x}, {self.apple.get_pos().x} ]')

    def draw_text(self, x, y, text):
        font = pygame.font.Font('./fonts/TerminusTTF.ttf', 14)
        self.sc.blit(font.render(text, True, pygame.Color('#50FA7B')), (x, y))