Пример #1
0
    def prepare(self):
        # get best score
        self.main.gameApp.cursor.execute(self.bestQuery)
        rows = self.main.gameApp.cursor.fetchall()

        for row in rows:
            self.data.best = row[0]

        # create foods
        self.data.foods.clear()
        for _ in range(768):
            x = random.randint(0, 31)
            y = random.randint(0, 23)

            newFood = GameTile(x, y)

            self.data.foods.append(newFood)

        if self.data.turn > 1 and self.evolution and self.data.doEvolution:
            self.evolution.generatePopulation(self.data.population)
            self.data.generation += 1
            self.evolution.doMutation()

        # create snake(s)
        self.data.population = self.data.tempPopulation

        self.data.snakes.clear()
        for i in range(self.data.population):

            newWeights = None
            if self.data.turn > 1 and self.evolution and self.data.doEvolution:
                newWeights = self.evolution.newGeneration.weights[i]

            elif self.data.turn > 1:  # if no evolution use old weights
                newWeights = self.weights[i]

            elif self.data.turn == 1 and self.data.isTrained:  # apply trained weights to first turn snakes
                newWeights = self.data.weights

            snake = Snake(self.data.startSize, self.data.foods, self.type,
                          newWeights, self.main.gameApp.db)

            if self.type % 2 == 0:
                snake.aiSensor = AiSensor(snake, 1)
            else:
                snake.aiSensor = AiSensor(snake, 2)

            self.data.snakes.append(snake)

        self.data.displayedSnake = self.data.snakes[0]

        self.data.state = 1
        self.data.dead = 0

        self.map.prepare()

        self.update()
Пример #2
0
    def __init__(self, root, res=20):
        self.root = root
        width, height = self.root.get_size()
        self.cols = int(width / res)
        self.rows = int(height / res)
        self.res = res

        self.gen_food()

        self.player = Snake(self.root, (400, 300), res=self.res)
Пример #3
0
 def __init__(self, weights, apple_position=None):
     self.__snake = Snake()
     self.__apple = Apple(numpy.array([0, 0]))
     self.__score = 0
     self.__clock = pygame.time.Clock()
     self.__weights = weights
     self.__remaining_moves = config.MOVES
     self.__display_manager = DisplayManager(self.__snake, self.__apple)
     self.__time_alive = 0
     self.__apple_position = apple_position
     self.__neural_network = NeuralNetwork(self.__weights)
Пример #4
0
    def __init__(self, width, height):
        self._width = width
        self._height = height
        self.game_state = 'init'
        self.action_list = ['u','d','l','r',None]

        self.snake = Snake(width, height)
        self.candy = Candy(width, height)

        self.world_map = Map(width, height)
        self.world_map.make_lst(self.snake, self.candy)

        self.done = False
Пример #5
0
    def reset(self):
        '''
        Reset state (e.g. Game over)
        and return init state
        '''
        self.game_state = 'init'

        self.snake = Snake(self.width, self.height)
        self.candy = Candy(self.width, self.height)

        self.world_map = Map(self.width, self.height)
        self.world_map.make_lst(self.snake, self.candy)
        self.done = False
        return self.state
Пример #6
0
def on_join(data):
    global thread_lock

    this_user = user.findById(data['user_id'])
    room_id = data['room_id']
    room = game_rooms[room_id]

    join_room(room_id)
    if this_user is not None and len(room.snakes) < 5:
        user_ids[request.sid] = data['user_id']

        user_snakes[request.sid] = Snake(name=this_user[1],
                                         is_ai=False,
                                         sid=request.sid,
                                         uid=data['user_id'])

        room.removeSnake(request.sid)
        room.addSnake(user_snakes[request.sid])
        socketio.emit('status_update', user_snakes[request.sid].colour)
    else:
        socketio.emit('status_update', 'spectating')

    def send_room_state():
        while True:
            time.sleep(0.1)
            for room_id, room in game_rooms.items():
                old_board = []
                # Don't need to send an update if the board's the same
                if not old_board == room.board:
                    socketio.emit('board_changed', {'board': room.board},
                                  room=room_id)
                    old_board = [x[:]
                                 for x in room.board]  # Deep copies the list

    def send_scores():
        while True:
            time.sleep(0.1)
            for room_id, room in game_rooms.items():
                old_snakes = []
                snakes = [{
                    'name': s.name,
                    'colour': s.colour,
                    'score': s.score
                } for s in sorted(room.snakes, reverse=True)]
                # Don't need to send an update if snakes hasn't changed
                if not old_snakes == snakes:
                    socketio.emit('scores_changed', {'snakes': snakes},
                                  room=room_id)
                    old_snakes = snakes.copy()  # Deep copies the list

    if thread_lock == None:
        thread_lock = True
    socketio.start_background_task(target=send_room_state)
    socketio.start_background_task(target=send_scores)
Пример #7
0
    def __init__(self, code_id, log=False, visualization=False, fps=60):
        self.code_id = code_id
        self.snake = Snake(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE,
                           WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2)
        self.food = Food(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE)
        self.food.spawn(self.snake)

        self.log = log
        self.visualization = visualization
        self.window, self.clock = self.init_visualization()
        self.fps = fps

        # basic infos
        self.alive = True
        self.score = 0
        self.step = 0
        # useful infos
        self.s_obstacles = self.get_surrounding_obstacles()
        self.food_angle = self.get_food_angle()
        self.food_distance = self.get_food_distance()
Пример #8
0
    def __init__(self, visible=True, waitForEyes=False):

        self.visible= visible
        self.waitForEyes= waitForEyes

        self.iterations_count = 0
        self.score = 0
        #self.main_snake = Snake(4, 4 )
        self.main_snake = Snake(random.randint(4,11), random.randint(3,4) )
        self.apple_eaten = False
        self.apple = self.spawn_apple()
        self.running = True
        # self.last_info = self.get_info()
        self.grow_snake = False

        pygame.init()
        pygame.display.set_caption("Snake")
        pygame.font.init()

        if (not self.visible):
            pygame.display.iconify()
        
        random.seed()
        self.main_screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.HWSURFACE)
        self.score_font = pygame.font.Font(None, 25)
        self.score_area_font = pygame.font.Font(None, 25)
        self.game_over_font = pygame.font.Font(None, 45)
        self.play_again_font = self.score_area_font
        self.score_msg = self.score_font.render("Score:", 1, pygame.Color("white"))
        self.score_msg_size = self.score_font.size("Score")
        self.background_color = pygame.Color(100, 100, 100)

        image_path = os.path.dirname(__file__)

        self.apple_image = pygame.transform.scale(
            pygame.image.load(os.path.join(image_path, "apple.png")).convert_alpha(), (BLOCK_SIZE, BLOCK_SIZE))
        self.snake_image = pygame.transform.scale(
            pygame.image.load(os.path.join(image_path, "snake_box.jpg")).convert_alpha(),
            (BLOCK_SIZE, BLOCK_SIZE))
Пример #9
0
class GameManager():
    game_over = False
    food = None

    def __init__(self, root, res=20):
        self.root = root
        width, height = self.root.get_size()
        self.cols = int(width / res)
        self.rows = int(height / res)
        self.res = res

        self.gen_food()

        self.player = Snake(self.root, (400, 300), res=self.res)

    def reset(self):
        del self.player

        self.player = Snake(self.root, (400, 300), res=self.res)
        self.gen_food()
        self.game_over = False

    def gen_food(self):
        fx = randint(0, self.cols - 1)
        fy = randint(0, self.rows - 1)
        self.food = pygame.Rect(fx * self.res, fy * self.res, self.res,
                                self.res)

    def draw_food(self):
        if self.food:
            food_color = (200, 34, 34)
            pygame.draw.rect(self.root, food_color, self.food)

    def _draw_map(self):
        cell_color = (200, 200, 200, 10)
        for row in range(self.rows):
            for col in range(self.cols):
                cell = pygame.Rect(col * self.res, row * self.res, self.res,
                                   self.res)
                pygame.draw.rect(self.root, cell_color, cell, 1)

    def update(self, dt, events):
        for event in events:
            if event.key == pygame.K_ESCAPE:
                self.reset()
                return

        self.player.update(dt, events)
        head = self.player.body[-1]
        if head and head.colliderect(self.food):
            self.player.grow()
            self.gen_food()

    def draw(self):
        # self._draw_map()
        self.draw_food()
        self.player.draw()
Пример #10
0
def player_init(menu):
    """
    Visszaadja a létrehozott játékosok listáját
    Paraméterek:
        menu: létrehozott menü
    """
    players = []
    colors = [Color.GREEN, Color.ORANGE]
    control = [[pygame.K_LEFT, pygame.K_RIGHT, pygame.K_DOWN, pygame.K_UP],
               [pygame.K_a, pygame.K_d, pygame.K_s, pygame.K_w]]
    for i in range(menu.player_num):
        player = Snake(menu.player_names[i], 0, 0, Image.snake_heads[i],
                       colors[i], control[i])
        players.append(player)
    return players
Пример #11
0
def main():
    # initial direction is right
    direction = Direction.RIGHT
    # init board size, snake and food position
    board = Board(11, 20, Snake(10, 8), Food(5, 10))

    # parse command line arguments
    args = parse_arguments()

    # init LCD and Pillow
    lcd = NokiaLCD()
    pillow = Pillow(lcd.width, lcd.height)

    # output the board
    output_board(board, args.output, lcd, pillow)

    try:
        last_update = time.time()

        with Raw(sys.stdin):
            with NonBlocking(sys.stdin):
                while True:
                    # read input key from stdin
                    key = sys.stdin.read(1)
                    if key in ['w', 's', 'a', 'd']:
                        direction = Direction.from_key(key)
                    elif key == '\x1b':
                        # x1b is ESC - ends the game
                        break

                    time.sleep(0.05)

                    # once in a specified turn_time, move the board and redraw it
                    if time.time() - last_update > (1 / int(args.speed)):
                        board.next_turn(direction)
                        output_board(board, args.output, lcd, pillow)
                        last_update = time.time()

    except CollisionException:
        output_game_over(board, args.output, lcd, pillow)
    except IOError:
        print("I/O not ready.")
    except KeyboardInterrupt:
        pass
Пример #12
0
def main():
    window = pygame.display.set_mode(
        (WINDOW_WIDTH * PIXEL_SIZE, WINDOW_HEIGHT * PIXEL_SIZE))
    pygame.display.set_caption('SNAKE GAME')
    clock = pygame.time.Clock()

    score = 0
    snake = Snake(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE, WINDOW_WIDTH / 2,
                  WINDOW_HEIGHT / 2)
    food = Food(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE)

    run = True

    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                break
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    snake.change_direction(-1)
                    break
                elif event.key == pygame.K_RIGHT:
                    snake.change_direction(+1)
                    break

        snake.move()

        if snake.collision_food(food.location):
            score += 1
            food.state = False

        food.spawn(snake)

        if snake.collision_obstacles():
            print('over')
            run = False

        if snake.get_length() == WINDOW_WIDTH * WINDOW_HEIGHT:
            print('win')
            run = False

        window.fill((0, 0, 0))
        food.render(window)
        snake.render(window)
        pygame.display.set_caption('SNAKE GAME | Score: ' + str(score))
        pygame.display.update()
        clock.tick(FPS)
Пример #13
0
 def __init__(self):
     for _ in range(GEN_SIZE):
         self.snakes.append(Snake())
         self.NNs.append(NN())
         self.apples.append(Apple())
Пример #14
0
class SnakeEnvironment(object):
    def __init__(self, width, height):
        self._width = width
        self._height = height
        self.game_state = 'init'
        self.action_list = ['u','d','l','r',None]

        self.snake = Snake(width, height)
        self.candy = Candy(width, height)

        self.world_map = Map(width, height)
        self.world_map.make_lst(self.snake, self.candy)

        self.done = False

    @property
    def height(self):
        return self._height

    @property
    def width(self):
        return self._width

    def _replace_item_map(self, x):
        if x in 'v^><':
            return 0
        elif x == '@':
            return 1
        elif x == '*':
            return 2
        else:
            return 3

    @property
    def state(self):
        '''
        Return state from raw map
        wall - 0
        snake - 1
        candy - 2
        '''
        state_map = self.world_map.map.copy()
        for i in range(self.height):
            state_map[i] = list(map(self._replace_item_map, state_map[i]))
        return np.array(state_map)

    def reset(self):
        '''
        Reset state (e.g. Game over)
        and return init state
        '''
        self.game_state = 'init'

        self.snake = Snake(self.width, self.height)
        self.candy = Candy(self.width, self.height)

        self.world_map = Map(self.width, self.height)
        self.world_map.make_lst(self.snake, self.candy)
        self.done = False
        return self.state

    def step(self, action):
        '''
        Input:
        Int - action

        Output:
        Float - reward

        Move an act, return state, reward & done
        '''
        self.snake.move(self.candy, self.action_list[action])
        self.candy.candy_update(self.snake)
        self.world_map.make_lst(self.snake, self.candy)

        if self.candy.candy_eaten:
            return self.state, 5, self.snake.dead, None
        
        if self.snake.dead:
            self.done = True
            # The training process will negative it
            return self.state, 5, self.snake.dead, None

        return self.state, 0, self.snake.dead, None

    
    def render(self):
        '''
        Render game from map
        '''
        clear()
        for stri in self.world_map.map:
            for char in stri:
                print(char, end='')
            print('')
Пример #15
0
 def setup(self) -> NoReturn:
     self.snake: Snake = Snake()
     self.start_key = False
     self.points = 0
     self.apple = Apple(COMPONENT_SIZE, COMPONENT_SIZE)
Пример #16
0
    def reset(self):
        del self.player

        self.player = Snake(self.root, (400, 300), res=self.res)
        self.gen_food()
        self.game_over = False
Пример #17
0
class Agent:
    def __init__(self, code_id, log=False, visualization=False, fps=60):
        self.code_id = code_id
        self.snake = Snake(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE,
                           WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2)
        self.food = Food(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE)
        self.food.spawn(self.snake)

        self.log = log
        self.visualization = visualization
        self.window, self.clock = self.init_visualization()
        self.fps = fps

        # basic infos
        self.alive = True
        self.score = 0
        self.step = 0
        # useful infos
        self.s_obstacles = self.get_surrounding_obstacles()
        self.food_angle = self.get_food_angle()
        self.food_distance = self.get_food_distance()

    def init_visualization(self):
        if self.visualization:
            window = pygame.display.set_mode(
                (WINDOW_WIDTH * PIXEL_SIZE, WINDOW_HEIGHT * PIXEL_SIZE))
            fps = pygame.time.Clock()
            return window, fps
        else:
            return None, None

    def get_random_move(self, random_n=10):

        # real random move, 1/random_n
        if random_n is not 0 and random.randint(1, random_n) == 1:
            return random.randint(-1, 1)

        s, a, d = self.get_state()
        # random move depend on state
        ops = []
        # select move based on following the food angle and avoiding the obstacles
        if not s[0] and a < 0:
            ops.insert(-1, -1)
        if not s[1] and a == 0:
            ops.insert(-1, 0)
        if not s[2] and a > 0:
            ops.insert(-1, +1)

        # if no option
        if not ops:
            # select move based on avoiding obstacles
            if not s[0]:
                ops.insert(-1, -1)
            if not s[1]:
                ops.insert(-1, 0)
            if not s[2]:
                ops.insert(-1, +1)

            # again, if no option -> just die
            if not ops:
                return random.randint(-1, 1)
            else:
                return ops[random.randint(0, len(ops) - 1)]
        else:
            return ops[random.randint(0, len(ops) - 1)]

    def next_state(self, move_direction):
        self.step += 1
        info = 'CodeID: {} | Step: {} | Score: {}'.format(
            self.code_id, self.step, self.score)

        self.snake.change_direction(move_direction)
        self.snake.move()

        if self.snake.collision_food(self.food.location):
            self.score += 1
            self.food.state = False

        self.food.spawn(self.snake)

        if self.snake.collision_obstacles():
            info += ' >> Game Over!'
            self.alive = False

        if self.snake.get_length() == WINDOW_WIDTH * WINDOW_HEIGHT:
            info += ' >> Win!'
            self.alive = False

        if self.log:
            print(info)

        if self.visualization:
            self.window.fill((0, 0, 0))
            self.food.render(self.window)
            self.snake.render(self.window)
            pygame.display.set_caption(info)
            pygame.display.update()
            pygame.event.get()
            self.clock.tick(self.fps)

        return self.get_state()

    def get_state(self):
        return self.get_surrounding_obstacles(), self.get_food_angle(
        ), self.get_food_distance()

    def get_surrounding_obstacles(self):
        # check front
        snake_head = self.snake.head
        snake_heading_direction = self.snake.heading_direction
        left = self.snake.moves[(snake_heading_direction - 1) %
                                len(self.snake.moves)]
        front = self.snake.moves[snake_heading_direction]
        right = self.snake.moves[(snake_heading_direction + 1) %
                                 len(self.snake.moves)]
        l_location = [snake_head[0] + left[0], snake_head[1] + left[1]]
        f_location = [snake_head[0] + front[0], snake_head[1] + front[1]]
        r_location = [snake_head[0] + right[0], snake_head[1] + right[1]]

        s_locations = [l_location, f_location, r_location]
        self.s_obstacles = [0, 0, 0]

        # check wall
        for i in range(0, len(s_locations)):
            if s_locations[i][0] < 0 or s_locations[i][0] >= WINDOW_WIDTH \
                    or s_locations[i][1] < 0 or s_locations[i][1] >= WINDOW_HEIGHT:
                self.s_obstacles[i] = 1

        # check body
        for b in self.snake.body:
            if b in s_locations:
                self.s_obstacles[s_locations.index(b)] = 1

        return self.s_obstacles

    def get_food_angle(self):
        # get direction of heading
        heading_direction = numpy.array(
            self.snake.moves[self.snake.heading_direction])
        # get direction of food (distant)
        food_direction = numpy.array(self.food.location) - numpy.array(
            self.snake.head)

        h = heading_direction / numpy.linalg.norm(heading_direction)
        f = food_direction / numpy.linalg.norm(food_direction)

        fa = math.atan2(h[0] * f[1] - h[1] * f[0],
                        h[0] * f[0] + h[1] * f[1]) / math.pi

        if fa == -1 or fa == 1:
            fa = 1

        self.food_angle = fa

        return self.food_angle

    def get_food_distance(self):
        head = numpy.array(self.snake.head)
        food = numpy.array(self.food.location)

        max_dis = numpy.linalg.norm(
            numpy.array([0, 0]) -
            numpy.array([WINDOW_WIDTH - 1, WINDOW_HEIGHT - 1]))
        dis = numpy.linalg.norm(head - food)

        # normalize distance to the range 0 - 1
        self.food_distance = dis / max_dis

        return self.food_distance
Пример #18
0
def main_game(genomes, config):
  gameSpeed = 5
  gameOver = False

  nets = []
  genomes_track = []
  snakes = []

  for _, genome in genomes:
    net = neat.nn.FeedForwardNetwork.create(genome, config)
    nets.append(net)
    snake_initial_coord = unique_coords(snakes)
    snakes.append(Snake(snake_initial_coord, gameSpeed))
    genome.fitness = 0
    genomes_track.append(genome)

  #snake = Snake((int(BOARD_ROWS / 2), int(BOARD_COLS / 2)), gameSpeed)
  tile_coord = unique_coords(snakes)
  tile = Tile(tile_coord)
  board = Board(screen)
  score = Score(screen)
  
  #last_obstacle = pygame.sprite.Group()

  while not gameOver:

    for event in pygame.event.get():
      if event.type == QUIT:
        gameOver = True
        quit() 

      if event.type == KEYDOWN:
        if event.key == K_UP:
          for snake in snakes:
            snake.move_up()
        if event.key == K_DOWN:
          for snake in snakes:
            snake.move_down()
        if event.key == K_RIGHT:
          for snake in snakes:
            snake.move_right()
        if event.key == K_LEFT:
          for snake in snakes:
            snake.move_left()

    for snake in snakes:
      snake.update()

    check_collide(snakes, tile, genomes_track, nets)

    if tile.is_dead():
      score.update()
      #snake.eat_tile()
      tile_coord = unique_coords(snakes)
      tile = Tile(tile_coord)

    if len(snakes) == 0:
      gameOver = True
      quit() 

    board.clean_board()

    for snake in snakes:
      board.display_snake(snake.get_body())

    board.display_tile(tile.get_coord())

    update_fitness(snakes, tile, genomes_track, nets)

    if pygame.display.get_surface() != None:
      screen.fill(BG_COLOR)
      board.draw()
      score.draw()
      pygame.display.update()

    clock.tick(FPS)
Пример #19
0
class GameManager:
    def __init__(self, weights, apple_position=None):
        self.__snake = Snake()
        self.__apple = Apple(numpy.array([0, 0]))
        self.__score = 0
        self.__clock = pygame.time.Clock()
        self.__weights = weights
        self.__remaining_moves = config.MOVES
        self.__display_manager = DisplayManager(self.__snake, self.__apple)
        self.__time_alive = 0
        self.__apple_position = apple_position
        self.__neural_network = NeuralNetwork(self.__weights)

    def directions_distance_objects(self):
        front_direction_vector = self.__snake.position[
            0] - self.__snake.position[1]
        left_direction_vector = numpy.array(
            [front_direction_vector[1], -front_direction_vector[0]])
        right_direction_vector = numpy.array(
            [-front_direction_vector[1], front_direction_vector[0]])

        vision = numpy.zeros((0, 1))
        for vector in [
                left_direction_vector, front_direction_vector,
                right_direction_vector
        ]:
            objects = self.get_objects_by_direction(vector)
            vision = numpy.append(vision, objects[0])
            vision = numpy.append(vision, objects[1])
            vision = numpy.append(vision, objects[2])
        return vision

    def get_objects_by_direction(self, direction):
        end = False
        found_apple = False
        found_self = False
        distance = 0
        objects = numpy.zeros((3, 1))
        while not end:
            distance += 1
            snake_position = self.__snake.position[0] + direction * distance
            if collision_manager.collision_with_wall(snake_position):
                objects[0] = 1 / distance
                end = True
            if not found_apple and collision_manager.collision_with_apple(
                    self.__apple.position, snake_position):
                objects[1] = 1 / distance
                found_apple = True
            if not found_self and collision_manager.collision_with_self(
                    snake_position, self.__snake):
                objects[2] = 1 / distance
                found_self = True
        return objects

    def angle_with_apple(self):
        apple_direction_vector = numpy.array(
            self.__apple.position) - numpy.array(self.__snake.position[0])
        snake_direction_vector = numpy.array(
            self.__snake.position[0]) - numpy.array(self.__snake.position[1])

        norm_of_apple_direction_vector = numpy.linalg.norm(
            apple_direction_vector)
        norm_of_snake_direction_vector = numpy.linalg.norm(
            snake_direction_vector)
        if norm_of_apple_direction_vector == 0:
            norm_of_apple_direction_vector = 10
        if norm_of_snake_direction_vector == 0:
            norm_of_snake_direction_vector = 10

        apple_direction_vector_normalized = apple_direction_vector / norm_of_apple_direction_vector
        snake_direction_vector_normalized = snake_direction_vector / norm_of_snake_direction_vector
        angle = numpy.math.atan2(
            apple_direction_vector_normalized[1] *
            snake_direction_vector_normalized[0] -
            apple_direction_vector_normalized[0] *
            snake_direction_vector_normalized[1],
            apple_direction_vector_normalized[1] *
            snake_direction_vector_normalized[1] +
            apple_direction_vector_normalized[0] *
            snake_direction_vector_normalized[0]) / numpy.math.pi
        return angle

    def check_if_game_ended(self):
        result = False
        next_position = self.__snake.position[0] + numpy.array([0, 0])
        if self.__remaining_moves <= 0:
            result = True

        if collision_manager.collision_with_wall(self.__snake.position[0]):
            result = True

        if collision_manager.collision_with_self(next_position, self.__snake):
            result = True

        return result

    def spawn_apple(self):
        apple_position = numpy.array([
            random.randint(1, config.GRID_SIZE[0] - 1) * config.RECT_SIZE[0],
            random.randint(1, config.GRID_SIZE[1] - 1) * config.RECT_SIZE[1]
        ])
        while collision_manager.collision_with_self(apple_position,
                                                    self.__snake):
            apple_position = numpy.array([
                random.randint(1, config.GRID_SIZE[0] - 1) *
                config.RECT_SIZE[0],
                random.randint(1, config.GRID_SIZE[1] - 1) *
                config.RECT_SIZE[1]
            ])

        return apple_position

    def get_action_from_nn(self):
        vision = self.directions_distance_objects()
        vision = numpy.append(vision, self.angle_with_apple())
        self.__neural_network.update_parameters(vision)
        nn_output = self.__neural_network.get_action()

        new_direction = numpy.array(self.__snake.position[0]) - numpy.array(
            self.__snake.position[1])
        if nn_output == 0:
            new_direction = numpy.array([new_direction[1], -new_direction[0]])
        if nn_output == 2:
            new_direction = numpy.array([-new_direction[1], new_direction[0]])

        if new_direction.tolist() == [config.RECT_SIZE[0], 0]:
            action = Action.RIGHT
        elif new_direction.tolist() == [-config.RECT_SIZE[0], 0]:
            action = Action.LEFT
        elif new_direction.tolist() == [0, config.RECT_SIZE[1]]:
            action = Action.DOWN
        else:
            action = Action.UP
        return action

    def calculate_fitness(self):
        fitness = self.__time_alive + ((2**self.__snake.length) +
                                       (self.__snake.length**2.1) * 500) - (
                                           ((.25 * self.__time_alive)**1.3) *
                                           (self.__snake.length**1.2))
        fitness = max(fitness, .1)
        return fitness

    def collision_with_apple(self):
        self.__score += 1
        self.__remaining_moves += config.APPLE_EXTRA_MOVES
        self.__snake.add_piece()
        if self.__remaining_moves > config.MAX_MOVES:
            self.__remaining_moves = config.MAX_MOVES
        if self.__apple_position is not None:
            self.__apple.position = self.__apple_position[self.__score]
        else:
            self.__apple.position = self.spawn_apple()
        return self.__apple.position

    def play_game(self):
        apple_position = []
        if self.__apple_position is not None:
            self.__apple.position = self.__apple_position[self.__score]
        else:
            self.__apple.position = self.spawn_apple()
        apple_position.append(self.__apple.position)
        ended_game = False
        while ended_game is not True:
            self.__display_manager.draw(self.__score)
            self.__snake.move_snake(self.get_action_from_nn())
            self.__remaining_moves -= 1
            self.__time_alive += 1

            if collision_manager.collision_with_apple(
                    self.__apple.position, self.__snake.position[0]):
                apple_position.append(self.collision_with_apple())

            ended_game = self.check_if_game_ended()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    ended_game = True

            self.__clock.tick(config.FPS)
        return self.calculate_fitness(), apple_position
Пример #20
0
class Game:
    def __init__(self, visible=True, waitForEyes=False):

        self.visible= visible
        self.waitForEyes= waitForEyes

        self.iterations_count = 0
        self.score = 0
        #self.main_snake = Snake(4, 4 )
        self.main_snake = Snake(random.randint(4,11), random.randint(3,4) )
        self.apple_eaten = False
        self.apple = self.spawn_apple()
        self.running = True
        # self.last_info = self.get_info()
        self.grow_snake = False

        pygame.init()
        pygame.display.set_caption("Snake")
        pygame.font.init()

        if (not self.visible):
            pygame.display.iconify()
        
        random.seed()
        self.main_screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.HWSURFACE)
        self.score_font = pygame.font.Font(None, 25)
        self.score_area_font = pygame.font.Font(None, 25)
        self.game_over_font = pygame.font.Font(None, 45)
        self.play_again_font = self.score_area_font
        self.score_msg = self.score_font.render("Score:", 1, pygame.Color("white"))
        self.score_msg_size = self.score_font.size("Score")
        self.background_color = pygame.Color(100, 100, 100)

        image_path = os.path.dirname(__file__)

        self.apple_image = pygame.transform.scale(
            pygame.image.load(os.path.join(image_path, "apple.png")).convert_alpha(), (BLOCK_SIZE, BLOCK_SIZE))
        self.snake_image = pygame.transform.scale(
            pygame.image.load(os.path.join(image_path, "snake_box.jpg")).convert_alpha(),
            (BLOCK_SIZE, BLOCK_SIZE))



    def get_info(self):
        closest_right = 1
        closest_left = 1
        closest_up = 1
        closest_down = 1
        head = self.main_snake.elements[0]

        while closest_right <= BOARD_WIDTH - head.x:
            if self.main_snake.collides_with_body(Segment(head.x + closest_right, head.y)):
                break
            closest_right += 1

        while closest_left <= head.x + 1:
            if self.main_snake.collides_with_body(Segment(head.x - closest_left, head.y)):
                break
            closest_left += 1

        while closest_down <= BOARD_HEIGHT - head.y:
            if self.main_snake.collides_with_body(Segment(head.x, head.y + closest_down)):
                break
            closest_down += 1

        while closest_up <= head.y + 1:
            if self.main_snake.collides_with_body(Segment(head.x, head.y - closest_up)):
                break
            closest_up += 1

        closest_right = min(closest_right, BOARD_WIDTH - head.x)
        closest_left = min(closest_left, head.x + 1)
        closest_down = min(closest_down, BOARD_HEIGHT - head.y)
        closest_up = min(closest_up, head.y + 1)

        apple_x_dist = abs(self.main_snake.elements[0].x - self.apple.x)
        apple_y_dist = abs(self.main_snake.elements[0].y - self.apple.y)

        info = {
            "right_crash": closest_right,
            "left_crash": closest_left,
            "down_crash": closest_down,
            "up_crash": closest_up,
            "reward": 0,
            "lost_game": False,
            "apple_x": apple_x_dist,
            "apple_y": apple_y_dist,
            "score": self.score,
            "iterations_count": self.iterations_count
        }

        print("\nRight crash: {0}, left crash: {1}, up crash: {2}, "
              "down crash: {3}. Reward: {4}, lost game: {5}. Apple x: {6}, "
              "apple y: {7}, score: {8}, number of iterations {9}".format(info["right_crash"], info["left_crash"],
                                                                          info["up_crash"],
                                                                          info["down_crash"], info["reward"],
                                                                          info["lost_game"],
                                                                          info["apple_x"], info["apple_y"],
                                                                          info["score"], info["iterations_count"]))

        return info

    def get_action(self, action):
        if action == KEY["UP"]:
            event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_UP)
        elif action == KEY["DOWN"]:
            event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_DOWN)
        elif action == KEY["LEFT"]:
            event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_LEFT)
        elif action == KEY["RIGHT"]:
            event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_RIGHT)
        # make the move
        pygame.event.post(event)

    def wait_for_action(self):
        while True:
            event = pygame.event.wait()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    return KEY["UP"]
                elif event.key == pygame.K_DOWN:
                    return KEY["DOWN"]
                elif event.key == pygame.K_LEFT:
                    return KEY["LEFT"]
                elif event.key == pygame.K_RIGHT:
                    return KEY["RIGHT"]
                elif event.key == pygame.K_ESCAPE:
                    return KEY["EXIT"]
                elif event.key == pygame.K_y:
                    return KEY["YES"]
                elif event.key == pygame.K_n:
                    return KEY["NO"]
            if event.type == pygame.QUIT:
                sys.exit()

    def spawn_apple(self):
        valid_apple = False
        x = 0
        y = 0
        while not valid_apple:
            valid_apple = True
            x = random.randint(0, BOARD_WIDTH - 1)
            y = random.randint(0, BOARD_HEIGHT - 1)
            for segment in self.main_snake.elements:
                if check_collision(segment, Segment(x, y)):
                    valid_apple = False
                    break

        return Apple(x, y, True)

    def rerun(self):
        self.__init__(self.visible, self.waitForEyes)

    def end_game(self):
        # self.get_info()
        self.running = False

    def get_snake_size(self):
        return len(self.main_snake.elements)

    def draw_score(self):
        score_area = self.score_area_font.render(str(self.score), 1, pygame.Color("white"))
        self.main_screen.blit(self.score_msg, (SCREEN_WIDTH - self.score_msg_size[0] - 60, 10))
        self.main_screen.blit(score_area, (SCREEN_WIDTH - 45, 10))

    def redraw_game(self):
        self.main_screen.fill(self.background_color)
        if self.apple.exists:
            self.apple.draw(self.main_screen, self.apple_image)
        self.main_snake.draw(self.main_screen, self.snake_image)
        self.draw_score()
        if DISPLAY:
            pygame.display.flip()
            pygame.display.update()

    def action(self, action_key):
        if action_key == KEY["EXIT"]:
            self.running = False

        # Move snake
        if self.grow_snake:
            self.main_snake.grow()
        if action_key:
            self.main_snake.set_direction(action_key)
        self.main_snake.move()
        return self.last_info

    def run(self, action):
        # Draw game
        self.redraw_game()
        # print(self.send_state(), action)

        # Check apple availability
        self.grow_snake = False
        if self.apple.exists:
            if check_collision(self.main_snake.get_head(), self.apple):
                self.grow_snake = True
                self.apple.exists = False
                self.score += 5
                self.apple_eaten = True

        # Spawn apple
        if self.apple_eaten:
            self.apple_eaten = False
            self.apple = self.spawn_apple()
            print("Wow, you've eaten an apple! Next apple: ({0}, {1})".format(self.apple.x, self.apple.y))
            self.redraw_game()

        # Wait for user input (here goes agent's move)
        # self.main_snake.display_log()
        self.iterations_count += 1
        if self.waitForEyes:
            time.sleep(0.3)
        
        # Here agent is telling what to do
        self.get_action(action)
        key_pressed = self.wait_for_action()
        if key_pressed == "exit":
            self.running = False

        if (key_pressed != action):
            print("error when getting key presed", key_pressed, action)

        # Move snake
        if self.grow_snake:
            self.main_snake.grow()
        if key_pressed in range(0, 4):
            self.main_snake.set_direction(key_pressed)
        self.main_snake.move()

        # Check collisions (walls and self)
        if self.main_snake.check_crash():
            self.end_game()

        reward = self.send_reward()
        return (self.send_state(), reward)

    def send_reward(self):
        # reward = 0
        # apple_part =0
        # apple_distance = abs(self.apple.x - self.main_snake.get_head().x) + abs(self.apple.y - self.main_snake.get_head().y)
        # if apple_distance==1:
        #     apple_part= REWARD["EAT"]
        # if self.running:
        #     reward= REWARD["LIVE"] + apple_part
        # else:
        #     reward = REWARD["DEATH"]+ apple_part
        # return reward
        apple_part =0
        if(self.running == False):
             return REWARD["DEATH"]
        apple_distance = abs(self.apple.x - self.main_snake.get_head().x) + abs(self.apple.y - self.main_snake.get_head().y)

        
        # ------DIFFICULT SCENARIO---------
        if apple_distance == 0:
            apple_part = REWARD["EAT"]
        # ---------------------------------
       
        #if self.apple.x == self.main_snake.get_head().x || self.apple.y == self.main_snake.get_head().y:
        #    apple_part+=REWARD["EAT"]*0.2
       
        # # -------EASIER SCENARIO-----------
        # apple_part = (1-(apple_distance/(BOARD_HEIGHT+BOARD_WIDTH))) * REWARD["EAT"]
        # # ---------------------------------

        return REWARD["LIVE"] + apple_part

    # when snake eats an apple => true
    # that is when the head of the snake is on the apple
    def snake_eating(self):
        return self.apple.x == self.main_snake.get_head().x and self.apple.y == self.main_snake.y

    # Sends state to agent
    # List of collisions (U, R, D L) and apple distances (U, R, D, L)
    def send_state(self):
        collisions = self.check_collisions_all_directions()
        apple_distance = self.check_apple_all_directions()
        if len(collisions) != 4 or len(apple_distance) != 4:
            print(collisions)
            print(apple_distance)
        return collisions + apple_distance

    def check_apple_all_directions(self):
        # distance = [0,0,0,0]
        distance = []

        # snake is eating the apple now  => no reward for that
        if self.snake_eating():
            return [TOOBIG,TOOBIG,TOOBIG,TOOBIG]

        #return self.check_apple()
        
        # UP
        distance.append(self.distance_calc(self.apple.x, self.apple.y,self.main_snake.get_head().x,  self.main_snake.get_head().y-1))
        #distance.append(self.distance_give(self.apple.x, self.apple.y,self.main_snake.get_head().x,  self.main_snake.get_head().y,KEY["UP"]))
        

        # DOWN
        distance.append(self.distance_calc(self.apple.x,self.apple.y, self.main_snake.get_head().x,  self.main_snake.get_head().y+1))
        #distance.append(self.distance_give(self.apple.x,self.apple.y, self.main_snake.get_head().x,  self.main_snake.get_head().y, KEY["DOWN"]))
        
        # LEFT
        distance.append(self.distance_calc(self.apple.x,self.apple.y, self.main_snake.get_head().x-1,  self.main_snake.get_head().y))
        #distance.append(self.distance_give(self.apple.x,self.apple.y, self.main_snake.get_head().x,  self.main_snake.get_head().y, KEY["LEFT"]))

        # RIGHT
        distance.append(self.distance_calc(self.apple.x, self.apple.y,self.main_snake.get_head().x+1,  self.main_snake.get_head().y))
        #distance.append(self.distance_give(self.apple.x, self.apple.y,self.main_snake.get_head().x,  self.main_snake.get_head().y, KEY["RIGHT"]))

       
        colissions= self.check_collisions_all_directions()
        for i in range(len(colissions)):
            if(colissions[i]<=0):
                distance[i]=TOOBIG

        print(distance)
        return distance
        

        

    def distance_calc(self, applex, appley, snakex, snakey):
        return abs(applex - snakex) + abs(appley - snakey)
    
    
    def distance_give(self, applex, appley, snakex,snakey, direction):
        #distances= []
        snake_elements_without_tail = self.main_snake.elements[:-1]
        if direction == KEY["UP"] :
            if applex==snakex and appley <= snakey:
                for segment in snake_elements_without_tail:
                    if segment.x == applex and segment.y < snakey and segment.y > appley:                
                        return 0
                return 1
            return 0
        if direction == KEY["DOWN"]:
            if applex==snakex and appley >= snakey:
                for segment in snake_elements_without_tail:
                    if segment.x == applex and segment.y > snakey and segment.y < appley:                
                        return 0
                return 1
            return 0;
        if direction == KEY["LEFT"]:
            if appley==snakey and applex <= snakex:
                for segment in snake_elements_without_tail:
                    if segment.y == appley and segment.x < snakex and segment.x > applex:                
                        return 0
                return 1
            return 0
        if direction == KEY["RIGHT"]:
            if appley==snakey and applex >= snakex:
                for segment in snake_elements_without_tail:
                    if segment.y == appley and segment.x > snakex and segment.x < applex:                
                        return 0
                return 1
            return 0

    def check_apple(self):

        apple = []

        applex = self.apple.x
        appley = self.apple.y

        # UP
        distance = TOOBIG
        new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y - 1)

        if applex==new_head[0] and appley <= new_head[1]:       
            distance= abs(new_head[1]- appley)
        apple.append(distance)
        
        # DOWN
        distance = TOOBIG
        new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y + 1)
        
        if applex==new_head[0] and appley >= new_head[1]:  
            distance= abs(new_head[1]- appley)
        apple.append(distance)


        # LEFT
        distance = TOOBIG
        new_head = (self.main_snake.get_head().x - 1, self.main_snake.get_head().y)
        if appley==new_head[1] and applex <= new_head[0]:
            distance= abs(new_head[0]- applex)
        apple.append(distance)

        # RIGHT
        distance = TOOBIG
        new_head = (self.main_snake.get_head().x + 1, self.main_snake.get_head().y)
        if appley==new_head[1] and applex >= new_head[0]:
            distance= abs(new_head[0]- applex)
        apple.append(distance)

        return apple



    def check_collisions_all_directions(self):
        collision = []

        # UP
        distance = self.main_snake.get_head().y
        new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y - 1)

        snake_elements_without_tail = self.main_snake.elements[:-1]

        for segment in snake_elements_without_tail:
            if segment.x == new_head[0] and segment.y < self.main_snake.get_head().y:
                distance = min(distance, abs(segment.y - new_head[1]))
        collision.append(distance) 
        
        # DOWN
        distance = BOARD_HEIGHT - self.main_snake.get_head().y - 1
        new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y + 1)
        for segment in snake_elements_without_tail:
            if segment.x == new_head[0] and segment.y > self.main_snake.get_head().y:
                distance = min(distance, abs(segment.y - new_head[1]))
        collision.append(distance)

        # LEFT
        distance = self.main_snake.get_head().x
        new_head = (self.main_snake.get_head().x - 1, self.main_snake.get_head().y)
        for segment in snake_elements_without_tail:
            if segment.y == new_head[1] and segment.x < self.main_snake.get_head().x:
                distance = min(distance, abs(new_head[0] - segment.x))
        collision.append(distance)

        # RIGHT
        distance = BOARD_WIDTH - self.main_snake.get_head().x - 1
        new_head = (self.main_snake.get_head().x + 1, self.main_snake.get_head().y)
        for segment in snake_elements_without_tail:
            if segment.y == new_head[1] and segment.x > self.main_snake.get_head().x:
                distance = min(distance, abs(new_head[0] - segment.x))
        collision.append(distance)

        return collision