Exemple #1
0
def test_next_move():
    cur_ai = AI()
    current_board = BoardState.initial_state()
    answer1_board = BoardState.initial_state()
    answer2_board = BoardState.initial_state()
    current_board.load('board_3_in_a_row.pickle')
    answer1_board.load('board_3_in_a_row_ans1.pickle')
    answer2_board.load('board_3_in_a_row_ans2.pickle')
    assert (cur_ai.next_move(current_board, None)[0].board.all()
            == answer1_board.board.all() or cur_ai.next_move(
                current_board, None)[0].board == answer2_board.board.all())
Exemple #2
0
def ai_1(board: BoardState) -> BoardState:
    """This AI will always choose the winning spot, if there is no winning spot it will place randomly
    """
    cur_piece = board.cpiece
    if cur_piece is not None:
        for (x, y) in board.open_spots:
            move = find_win_spot(cur_piece, board)
            if move:
                return update_board_then_give_random(board, move)
    board.ai_random_move()
    return board
Exemple #3
0
def ai_2(board: BoardState) -> BoardState:
    """This AI will always give a none-winable piece (if there is one) and will place randomly
    """
    cur_piece = board.cpiece
    if cur_piece is None:
        board.cpiece_id = choose_none_winable_piece(board)
    else:
        board[choice(list(board.open_spots))] = board.cpiece_id
        board.cpiece_id = choose_none_winable_piece(board)

    if (board.cpiece_id is None) and not board.is_full:
        board.cpiece_id, _ = choice(list(board.unused_game_pieces))
    return board
Exemple #4
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // 8

    player = 1
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

        start_time = time.time()

        while True:
            new_board = ai.next_move(board if player ==
                                     1 else board.inverted())
            if new_board is None:
                break
            else:
                board = new_board if player == 1 else new_board.inverted()
                if new_board.in_the_process_of_taking == False:
                    player = player % 2 + 1
                    break

        if time.time() - start_time > 30.0:
            print('TL')
            break

        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()
Exemple #5
0
class DraughtsTest(unittest.TestCase):
    MAX_MOVE_TIME = 3

    def setUp(self):
        self.ai = AI(PositionEvaluation(), search_depth=2)
        self.board = BoardState()

    def test_ai_vs_ai(self):
        board = BoardState.initial_state()
        while not board.ended():
            start_time = time()
            board = self.ai.next_move(board)
            finish_time = time()
            self.assertIsNotNone(board)
            elp_time = finish_time - start_time
            self.assertLess(elp_time, DraughtsTest.MAX_MOVE_TIME)

    def test_simple_move_forward(self):
        self.board.board[7, 0] = 1
        result = self.ai.next_move(self.board)
        self.assertEqual(result.board[7, 0], 0)
        self.assertEqual(result.board[6, 1], 1)

    def test_simple_capt(self):
        self.board.board[7, 0] = 1
        self.board.board[6, 1] = -1
        result = self.ai.next_move(self.board)
        self.assertEqual(result.board[7, 0], 0)
        self.assertEqual(result.board[6, 1], 0)
        self.assertEqual(result.board[5, 2], 1)

    def test_king_creation(self):
        self.board.board[1, 0] = 1
        result = self.ai.next_move(self.board)
        self.assertEqual(result.board[1, 0], 0)
        self.assertEqual(result.board[0, 1], 2)

    def test_king_capt(self):
        self.board.board[7, 0] = 2
        self.board.board[1, 6] = -1
        result = self.ai.next_move(self.board)
        self.assertEqual(result.board[7, 0], 0)
        self.assertEqual(result.board[1, 6], 0)
        self.assertEqual(result.board[0, 7], 2)

    def test_multi_move(self):
        self.board.board[7, 0] = 1
        self.board.board[6, 1] = -1
        self.board.board[4, 3] = -1
        self.board.board[4, 5] = -1
        result = self.board.copy()
        for i in range(3):
            result = self.ai.next_move(result)
        self.assertEqual(result.board[7, 0], 0)
        self.assertEqual(result.board[6, 1], 0)
        self.assertEqual(result.board[4, 3], 0)
        self.assertEqual(result.board[4, 5], 0)
        self.assertEqual(result.board[5, 6], 1)
Exemple #6
0
 def test_ai_vs_ai(self):
     board = BoardState.initial_state()
     while not board.ended():
         start_time = time()
         board = self.ai.next_move(board)
         finish_time = time()
         self.assertIsNotNone(board)
         elp_time = finish_time - start_time
         self.assertLess(elp_time, DraughtsTest.MAX_MOVE_TIME)
Exemple #7
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // 8

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_s:
                    with open('save', 'wb') as f:
                        f.write(pickle.dumps(board))
                if event.key == pygame.K_l:
                    with open('save', 'rb') as f:
                        board = pickle.loads(f.read())
            if board.ended():
                continue

            if board.current_player == -1:
                pygame.display.set_caption(CAPTION + ' [Computing...]')
                start_time = time.time()
                new_board = ai.next_move(board)
                finish_time = time.time()
                elp_time = finish_time - start_time
                sleep_time = MOVE_TIME - elp_time
                if sleep_time > 0:
                    time.sleep(sleep_time)
                pygame.display.set_caption(CAPTION)
                if new_board is not None:
                    board = new_board

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                mouse_click_position = event.pos

            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                new_x, new_y = [p // grid_size for p in event.pos]
                old_x, old_y = [p // grid_size for p in mouse_click_position]

                new_board = board.do_move(old_x, old_y, new_x, new_y)
                if new_board is not None:
                    board = new_board

        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()
Exemple #8
0
def ai_3(board: BoardState) -> BoardState:
    """This AI will always give a none-winable piece (if there is one) and will only choose winable placements when possible
    """
    cur_piece = board.cpiece
    if cur_piece is not None:
        moved = False
        for (x, y) in board.open_spots:
            move = find_win_spot(cur_piece, board)
            if move:
                board[move] = board.cpiece_id
                moved = True
                break
        if not moved:
            board[choice(list(board.open_spots))] = board.cpiece_id
        board.cpiece_id = choose_none_winable_piece(board)
    else:
        board.cpiece_id = choose_none_winable_piece(board)

    if (board.cpiece_id is None) and not board.is_full:
        board.cpiece_id, _ = choice(list(board.unused_game_pieces))
    return board
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // 8

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                mouse_click_position = event.pos

            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                new_x, new_y = [p // grid_size for p in event.pos]
                old_x, old_y = [p // grid_size for p in mouse_click_position]

                new_board = board.do_move(old_x, old_y, new_x, new_y)
                if new_board is not None:
                    board = new_board

            if event.type == pygame.MOUSEBUTTONUP and event.button == 3:
                x, y = [p // grid_size for p in event.pos]
                board.board[
                    y,
                    x] = (board.board[y, x] + 1 + 2) % 5 - 2  # change figure

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    board = board.inverted()

                if event.key == pygame.K_SPACE:
                    new_board = ai.next_move(board)
                    if new_board is not None:
                        board = new_board

        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()
Exemple #10
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // game_set.board_size

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

            if event.type == pygame.MOUSEBUTTONUP:
                x, y = [p // grid_size for p in event.pos]
                if event.button == 1:  # do move
                    board.notification = None
                    board = board.do_move(y, x)
                elif event.button == 3:  # change figure
                    board.board[y, x] = ((board.board[y, x] + 2) % 3) - 1

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    board = BoardState.initial_state()

                if event.key == pygame.K_s:
                    board.save()

                if event.key == pygame.K_l:
                    board = BoardState.load()

                if event.key == pygame.K_z:
                    pass

                if (game_set.is_ai_enabled and event.key == pygame.K_SPACE and
                        game_set.first_player_is_ai ==
                        board.is_first_player_turn):
                    new_board = ai.next_move(board, None)[0]
                    if new_board is not None:
                        board = new_board

        if board.is_game_finished:
            board.notification = "Second" if board.is_first_player_turn \
                else "First"
            board.notification += " player won! Press R to restart"

        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()
Exemple #11
0
    def __call__(self, board: BoardState) -> float:
        basic_value = [0] * game_set.win_len
        balance: float = 0
        for y, x in product(range(game_set.board_size),
                            range(game_set.board_size)):

            for vector in game_set.basic_vectors:
                max_y = y + vector[0] * (game_set.win_len - 1)
                max_x = x + vector[1] * (game_set.win_len - 1)
                if BoardState.is_coord_correct(max_y, max_x):
                    for diff in range(game_set.win_len):
                        basic_value[diff] = board.board[y + vector[0] * diff,
                                                        x + vector[1] * diff]

                    key_tuple = tuple(basic_value)
                    balance += eval_score[key_tuple]

        return balance
Exemple #12
0
    def next_move(self, board: BoardState, top_res: Optional['int']) -> \
            (Optional[BoardState], float):
        if self.depth == 0:
            return board, self.position_evaluation(board)

        moves = board.get_good_possible_moves()
        best_value = None
        best_board = None
        board_config = board.is_first_player_turn ^ 1
        for move in moves:
            cur_board, cur_score = AI(self.position_evaluation,
                                      self.depth - 1).next_move(
                                          move, best_value)
            if cur_board is None:
                continue

            if top_res is not None and ((top_res > cur_score) == board_config):
                return None, 0

            if best_value is None or (best_value > cur_score) == board_config:
                best_board, best_value = move, cur_score
        return best_board, best_value
Exemple #13
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    max_y, max_x = screen.get_size()[1], screen.get_size()[0]
    elem_size = max_y // 16  # размер одной клетки
    save_box = InputBox('SAVE', max_y + (max_x - max_y) * 625 // 10000,
                        max_y * 4 // 5, 250, 30)
    load_box = InputBox('LOAD', max_y + (max_x - max_y) * 625 // 10000,
                        max_y * 4 // 5 + 50, 250, 30)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
                return
            save_name = save_box.handle_event(event)
            load_name = load_box.handle_event(event)

            if save_name:
                db = shelve.open(save_name)
                db[save_name] = board
                db.close()
            elif load_name:
                if os.path.exists(os.path.join(os.getcwd(),
                                               load_name + '.db')):
                    db = shelve.open(load_name)
                    board = db[load_name]
                    db.close()
                else:
                    print('No such file:(')

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                mouse_click_position = event.pos
                to_x, to_y = [(p - elem_size // 2) // elem_size
                              for p in mouse_click_position]

                try:
                    new_board = board.do_move(to_x, to_y)
                except EndGame as EG:
                    print(EG.winner, 'bruh')
                    board = EG.board
                    board.current_player *= 2
                    new_board = None
                    # draw_board(screen, elem_size, elem_size, elem_size, board)
                    # screen.fill((23, 123, 234))
                    # pygame.display.flip()
                    # print('--------------')
                    # print(new_board)
                    # pygame.time.wait(1000)
                    # return
                    # screen.fill(color)
                    # screen.blit(InputBox.FONT.render(('black' if EG.winner == 1 else 'white') + 'player won!!!', True, (0, 0, 0)), (0.7 * screen.get_size()[0], 0.2 * screen.get_size()[1]))
                    # time.sleep(3)
                    # return
                if new_board is not None:
                    board = new_board

            if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                print('kek')
                # print(ai.next_move(board))
                again = True
                while again:
                    try:
                        position_evalution, *move = ai.next_move(board, (0, 0))
                        again = False
                    except TypeError:
                        pass
                # print(position_evalution)
                # print(move)
                # print((ai.next_move(board)))
                print(
                    '+=+=+=++=++++++++=+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++='
                )
                # break
                move = move[0]
                print(f'my move = {move}')
                try:
                    new_board = board.do_move(move[1], move[0])
                except EndGame as EG:
                    print(EG.winner, 'bruh')
                    board = EG.board
                    board.current_player *= 2
                    new_board = None
                if new_board is not None:
                    board = new_board

        save_box.update()
        load_box.update()
        draw_board(screen, elem_size, elem_size, elem_size, board)
        save_box.draw(screen)
        load_box.draw(screen)
        pygame.display.flip()
Exemple #14
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // 8
    previous_board = board
    visible_board = board
    step = 0
    flag = True
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                mouse_click_position = event.pos

            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                new_x, new_y = [p // grid_size for p in event.pos]
                old_x, old_y = [p // grid_size for p in mouse_click_position]

                new_board = board.do_move(old_x, old_y, new_x, new_y)
                if new_board is not None:
                    previous_board = board
                    board = new_board.inverted()
                    if step % 2 == 0:
                        visible_board = new_board
                    else:
                        visible_board = board
                    step += 1
                if board.get_winner != 0:
                    flag = False

            #if event.type == pygame.MOUSEBUTTONUP and event.button == 3:
            #x, y = [p // grid_size for p in event.pos]
            #board.board[y, x] = (board.board[y, x] + 1 + 2) % 5 - 2  # change figure

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    visible_board = visible_board.inverted()
                elif event.key == pygame.K_n:
                    board = board.initial_state()
                    visible_board = board
                    step = 0
                elif event.key == pygame.K_s:
                    save_board(board, './src/save_board.bin')
                    save_board(visible_board, './src/save_visible.bin')
                elif event.key == pygame.K_l:
                    board = load_board('./src/save_board.bin')
                    visible_board = load_board('./src/save_visible.bin')
                    flag = True
                    if board.current_player == visible_board.current_player:
                        step = 0
                    else:
                        step = 1
                elif event.key == pygame.K_1:
                    board = load_board(
                        './src/test_boards/test_board_1_visible')
                    visible_board = load_board(
                        './src/test_boards/test_board_1_board')
                    flag = True
                    if board.current_player == visible_board.current_player:
                        step = 0
                    else:
                        step = 1
                elif event.key == pygame.K_2:
                    board = load_board(
                        './src/test_boards/test_board_2_visible')
                    visible_board = load_board(
                        './src/test_boards/test_board_2_board')
                    flag = True
                    if board.current_player == visible_board.current_player:
                        step = 0
                    else:
                        step = 1
                elif event.key == pygame.K_z:
                    board = previous_board
                elif event.key == pygame.K_SPACE:
                    new_board = ai.next_move(board)
                    if new_board is not None:
                        previous_board = board
                        board = new_board.inverted()
                        if step % 2 == 0:
                            visible_board = new_board
                        else:
                            visible_board = board
                        step += 1
                    if board.get_winner != 0:
                        flag = False

        draw_board(screen, 0, 0, grid_size, visible_board)
        if not flag:
            draw_final_message(screen, board.get_winner)

        pygame.display.flip()
Exemple #15
0
                            (self.next_move(new_board, move,
                                            current_depth + 1), move))
                    else:
                        evolution_tree.append(
                            self.next_move(new_board, move, current_depth + 1))
            except EndGame as EG:
                if current_depth == 0:
                    return self.position_evaluation(EG.board, move,
                                                    player), move
                else:
                    return self.position_evaluation(EG.board, move, player)

        if maximize:
            board.board[move[0], move[1]] = 0
            return max(evolution_tree)
        elif not maximize:
            board.board[move[0], move[1]] = 0
            return min(evolution_tree)


if __name__ == '__main__':
    import numpy as np
    board = np.zeros(shape=(15, 15), dtype=np.int8)
    board = BoardState(board, 1)

    board.board[5, 5] = 1
    board.board[6, 6] = 1
    board.board[7, 7] = 1
    board.board[8, 8] = 1
    board.board[9, 9] = 1
Exemple #16
0
    def next_move(self, board: BoardState, move, current_depth=0) -> Optional[BoardState]:
        maximize = True if current_depth % 2 == 0 else False
        if maximize:
            player = board.current_player
            limit_score = -100000
        elif not maximize:
            player = board.current_player * (-1)
            limit_score = 100000

        if board == None:
            if maximize:
                return 1000000
            elif not maximize:
                return -1000000

        # new_board = board.copy()

        if current_depth == self.search_depth:
            # print(f'depth = {current_depth}')
            return self.position_evaluation(board, move, player)


        if current_depth == 0:
            highY, leftX, lowY, rightX = Restriction_first(board)
            # # print('rest_arr first = \n', rest_arr)
            # # print(f'delta_y = {delta_y}, delta_x = {delta_x}')
        else:
            highY, leftX, lowY, rightX = Restriction_first(board)
            # delta_y, delta_x, rest_arr = Restriction_first(new_board)
            # # print('rest_ arr = \n', rest_arr)
            # # print(f'delta_y = {delta_y}, delta_x = {delta_x}')




        moves = [(y, x) for y in range(highY, lowY+1) for x in range(leftX, rightX+1) if board.board[y, x] == 0]
        if len(moves) == 0:
            # if maximize:
            #     return 1000000
            # elif not maximize:
            return -1000000
        # print(current_depth)
        # print("moves", moves)

        evolution_tree = []

        for move in moves:
            try:
                # print('move', move)
                # # print(f'current depth = {current_depth}, self.depth = {self.search_depth}')
                new_board = board.do_move(move[1], move[0])
                # if type(new_board) == 'NoneType':
                #     # print(new_board)
                # if new_board == None:
                #     if maximize:
                #         return 10000
                #     elif not maximize:
                #         return -10000
                current_score = self.position_evaluation(new_board, move, player) # player = кто только что сделала ход move
                # print('move = ', move, 'score = ', current_score)
                if (maximize and current_score >= limit_score) or (not maximize and current_score <= limit_score): # todo : may be to fix coeficient
                # if (current_score >= limit_score):  # todo : may be to fix coeficient
                    limit_score = current_score
                    if current_depth == 0:
                        # # print('move = ', move, )
                        evolution_tree.append((self.next_move(new_board, move, current_depth + 1), move))
                    else:
                        # # print(f'type = {type(board.do_move(move[0], move[1]))}')
                        evolution_tree.append(self.next_move(new_board, move, current_depth + 1))
            except EndGame as EG:
                if current_depth == 0:
                    return self.position_evaluation(EG.board, move, player), move
                else:
                    return self.position_evaluation(EG.board, move, player)


        if maximize:
            # print(f'current depth = {current_depth}, evoltion = {max(evolution_tree)}')
            # print(f'max = {max(evolution_tree)}')
            board.board[move[0], move[1]] = 0
            return max(evolution_tree)
        elif not maximize:
            # print(f'current depth = {current_depth}, evoltion = {min(evolution_tree)}')
            # print(f'min = {min(evolution_tree)}')
            board.board[move[0], move[1]] = 0
            return min(evolution_tree)
Exemple #17
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // 8

    for i, j in product(range(8), range(8)):
        board.board[i][j] = 0
    board.board[7][0] = 1
    board.board[7][2] = 1
    board.board[7][4] = 1
    board.board[7][6] = 1
    board.board[5][6] = 1
    board.board[5][4] = -1
    board.board[5][2] = -1
    board.board[3][2] = -1
    board.board[3][6] = -1
    board.board[1][4] = -1
    board.board[1][6] = -1

    player = 1
    while True:        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    while True:
                        new_board = ai.next_move(board if player == 1 else board.inverted())
                        if new_board is None:
                            break
                        else:
                            board = new_board if player == 1 else new_board.inverted()
                            if new_board.in_the_process_of_taking == False:
                                player = player % 2 + 1
                        break
                                           
        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()
Exemple #18
0
 def setUp(self):
     self.ai = AI(PositionEvaluation(), search_depth=2)
     self.board = BoardState()
Exemple #19
0
    def next_move(self,
                  board: BoardState,
                  move,
                  current_depth=0) -> Optional[BoardState]:
        maximize = True if current_depth % 2 == 0 else False
        if maximize:
            player = board.current_player
            limit_score = -100000
        elif not maximize:
            player = board.current_player * (-1)
            limit_score = 100000

        if board == None:
            if maximize:
                return 1000000
            elif not maximize:
                return -1000000

        # new_board = board.copy()

        if current_depth == self.search_depth:
            return self.position_evaluation(board, move, player)

        if current_depth == 0:
            highY, leftX, lowY, rightX = Restriction_first(board)
        else:
            highY, leftX, lowY, rightX = Restriction_first(board)

        moves = [(y, x) for y in range(highY, lowY + 1)
                 for x in range(leftX, rightX + 1) if board.board[y, x] == 0]
        if len(moves) == 0:
            return -1000000

        evolution_tree = []

        for move in moves:
            try:
                new_board = board.do_move(move[1], move[0])
                current_score = self.position_evaluation(
                    new_board, move,
                    player)  # player = кто только что сделала ход move
                if (maximize and current_score >= limit_score) or (
                        not maximize and current_score <= limit_score
                ):  # todo : may be to fix coeficient
                    limit_score = current_score
                    if current_depth == 0:
                        evolution_tree.append(
                            (self.next_move(new_board, move,
                                            current_depth + 1), move))
                    else:
                        evolution_tree.append(
                            self.next_move(new_board, move, current_depth + 1))
            except EndGame as EG:
                if current_depth == 0:
                    return self.position_evaluation(EG.board, move,
                                                    player), move
                else:
                    return self.position_evaluation(EG.board, move, player)

        if maximize:
            board.board[move[0], move[1]] = 0
            return max(evolution_tree)
        elif not maximize:
            board.board[move[0], move[1]] = 0
            return min(evolution_tree)
Exemple #20
0
                if event.key == pygame.K_s:
                    board.save_board("checkers.txt")
                  
                if event.key == pygame.K_l:
                    board.open_saved_board("checkers.txt")

                if event.key == pygame.K_SPACE:
                    new_board = board.inverted()
                    while True:
                        new_board = ai.next_move(new_board)
                        if new_board is None or new_board.in_the_process_of_taking == False:
                            break
                    if new_board is not None:
                        board = new_board.inverted()
        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()

pygame.init()

screen: Surface = pygame.display.set_mode([512, 512])
ai = AI(PositionEvaluation(), search_depth=4)

game_loop(screen, BoardState.initial_state(), ai)

pygame.quit()    



  
Exemple #21
0
def game_loop(screen: Surface, board: BoardState, ai: AI):
    grid_size = screen.get_size()[0] // 8  # размер одной клетки
    count = -1

    while True:
        # print(pygame.event.get())
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                mouse_click_position = event.pos
                # print(f'event.pos = {event.pos}')

            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                new_x, new_y = [p // grid_size for p in event.pos]
                old_x, old_y = [p // grid_size for p in mouse_click_position]

                try:
                    new_board = board.do_move(old_x, old_y, new_x, new_y)
                except EndGame:
                    return

                if new_board is not None:
                    board = new_board

            if event.type == pygame.MOUSEBUTTONUP and event.button == 3:  # ????????????????????????
                x, y = [p // grid_size for p in event.pos]
                board.board[
                    y,
                    x] = (board.board[y, x] + 1 + 2) % 5 - 2  # change figure

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    board = board.inverted()

                elif event.key == pygame.K_SPACE:
                    new_board = ai.next_move(board)
                    if new_board is not None:
                        board = new_board

                elif event.key == pygame.K_s:
                    count += 1
                    count %= 5
                    name = f'game{count}'

                    # name = input_name()
                    db = shelve.open(name)
                    db[name] = board
                    db.close()
                    # todo

                elif event.key == pygame.K_l:
                    load = True

                elif event.key in (pygame.K_0, pygame.K_1, pygame.K_2,
                                   pygame.K_3, pygame.K_4) and load:
                    name = 'game' + (chr(event.key))
                    if os.path.exists(os.path.join(os.getcwd(), name + '.db')):
                        db = shelve.open(name)
                        board = db[name]
                        db.close()
                        load = False
                    else:
                        print('No such file:(')

        draw_board(screen, 0, 0, grid_size, board)
        pygame.display.flip()