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]
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)