Example #1
0
    def test_get_opcode_count(self):
        self.assertIsNone(tracer.get_opcode_count())

        with tracer.limited_opcodes(100):
            self.assertTrue(0 < tracer.get_opcode_count() < 100)

        self.assertIsNone(tracer.get_opcode_count())
Example #2
0
def get_next_move(board, token):
    board_columns_used = get_board_columns_used(board)
    available_moves = game.available_moves(board)
    preferred_locations = [3, 2, 4, 1, 5, 0, 6]
    preferred_locations = [x for x in preferred_locations if x in available_moves]
    priority_locations = get_columns_with_space(board, token, preferred_locations)
    opcode_limit = get_opcode_limit()
    losing_locations = set()
    skip_moves = set()

    # if state is None:
    #     state = {'opening_trap': False}

    moves_played = get_moves_played(board)

    other_token = 'X' if token == 'O' else 'O'

    for move in available_moves:
        board[move][board_columns_used[move]] = token
        if check_winner(board, move, board_columns_used[move]):
            print('MOVE: winning move')
            return move
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        board[move][board_columns_used[move]] = other_token
        if check_winner(board, move, board_columns_used[move]):
            print('MOVE: blocking enemy win')
            return move
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = other_token

        if check_winner(board, move, board_columns_used[move] + 1):
            losing_locations.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    # Opening book
    if moves_played == 1:
        if board[3][0] == other_token:
            losing_locations.add(3)

    if moves_played == 2:
        if board[3][1] == other_token:
            # state['opening_trap'] = True
            return 2
        if board[2][0] == other_token:
            return 2
        if board[4][0] == other_token :
            return 4

    if moves_played == 4:
        if board[3][1] == other_token and board[1][0] == '.' and board[4][0] == '.':
            return 4

    # Take the move if you see a open-ended 3 way opportunity
    for move in available_moves:
        if move in losing_locations:
            continue
        if move_makes_3_horizontal_with_spaces(board, move, board_columns_used[move], token):
            print('MOVE: 3-way opportunity')
            return move

    # Block 2 adjacent tokens for the enemy
    for move in available_moves:
        if move_makes_3_horizontal_with_spaces(board, move, board_columns_used[move], other_token):
            print('MOVE: block 3-way opportunity')
            return move

    for move in available_moves:
        if move in losing_locations or board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = token

        if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True):
            skip_moves.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    print(get_opcode_count())

    # Look for forced wins
    for move in skip_moves:
        if move in losing_locations or board_columns_used[move] > 2:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = other_token
        board[move][board_columns_used[move] + 2] = token

        if check_winner(board, move, board_columns_used[move] + 2):
            print('MOVE: Force WIN')
            return move

        board[move][board_columns_used[move] + 2] = '.'
        board[move][board_columns_used[move] + 1] = '.'
        board[move][board_columns_used[move]] = '.'

    # # Look for a sure win:
    # for move in available_moves:
    #     print(f'sure {move}')
    #     if move in losing_locations or board_columns_used[move] > 2:
    #         continue
    #     copy_board = [x[:] for x in board]
    #     copy_board_columns_used = board_columns_used[:]
    #     copy_board[move][copy_board_columns_used[move]] = token
    #     # copy_board[move][copy_board_columns_used[move] + 1] = token
    #
    #     # if not check_winner(copy_board, move, board_columns_used[move] + 1):
    #     #     continue
    #
    #     # copy_board[move][copy_board_columns_used[move] + 1] = '.'
    #     copy_board_columns_used[move] += 1
    #
    #     result = results_in_a_winner(copy_board, copy_board_columns_used, token, other_token)
    #     print(f'sure result: {result}')
    #
    #     if result == token:
    #         print('MOVE: Sure WIN')
    #         return move
    #     elif result == other_token:
    #         losing_locations.add(move)

    # Look for opening opportunities
    for move in preferred_locations:
        move_score = {}
        if move in skip_moves or move in losing_locations or board_columns_used[move] == 0:
            continue

        score = move_opens_opportunities(board, move, board_columns_used[move], token)
        if score > 0:
            move_score[move] = score

        if move_score:
            sorted_score = sorted(move_score.items(), key=itemgetter(1))
            print('MOVE: making opportunities')
            return sorted_score[0][0]

    # Look for blocking opening opportunities
    for move in available_moves:
        move_score = {}
        if move in losing_locations:
            continue

        score = move_opens_opportunities(board, move, board_columns_used[move], other_token)
        if score > 0:
            move_score[move] = score

        if move_score:
            sorted_score = sorted(move_score.items(), key=itemgetter(1))
            print('MOVE: blocking enemy opportunities')
            return sorted_score[0][0]

    sorted_friendly_neighbours_score = None
    friendly_neighbours_score = {}

    for move in preferred_locations:
        if move in skip_moves or move in losing_locations or board_columns_used[move] == 0 or board_columns_used[move] == 0:
            continue
        friendly_neighbours = get_friendly_neighbours(board, move, board_columns_used[move], token)
        if friendly_neighbours > 1:
            friendly_neighbours_score[move] = friendly_neighbours

    if friendly_neighbours_score:
        sorted_friendly_neighbours_score = sorted(friendly_neighbours_score.items(), key=itemgetter(1))
        if sorted_friendly_neighbours_score[0][1] >= 3:
            print('MOVE: good friendlies')
            return sorted_friendly_neighbours_score[0][0]

    for move in preferred_locations:
        if move in skip_moves or move in losing_locations or board_columns_used[move] == 0 or board_columns_used[move] > 3:
            continue
        if not can_make_4_horizontal(board, move, board_columns_used[move], token):
            continue
        if move > 0:
            if board[move - 1][board_columns_used[move]] == token:
                print('MOVE: pair left')
                return move
        if move < 6:
            if board[move + 1][board_columns_used[move]] == token:
                print('MOVE: pair right')
                return move

    if sorted_friendly_neighbours_score:
        print('MOVE: weak neighbours')
        return sorted_friendly_neighbours_score[0][0]

    print(get_opcode_count())

    for move in priority_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move

    for move in priority_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move

    return random.choice(available_moves)
Example #3
0
def get_next_move(board, token):
    board_columns_used = get_board_columns_used(board)
    available_moves = game.available_moves(board)
    preferred_locations = [3, 2, 4, 1, 5, 0, 6]
    preferred_locations = [
        x for x in preferred_locations if x in available_moves
    ]
    priority_locations = get_columns_with_space(board, token,
                                                preferred_locations)
    opcode_limit = get_opcode_limit()
    losing_locations = set()

    # if state is None:
    #     state = {'opening_trap': False}

    moves_played = get_moves_played(board)

    other_token = 'X' if token == 'O' else 'O'

    for move in available_moves:
        board[move][board_columns_used[move]] = token
        if check_winner(board, move, board_columns_used[move]):
            return move
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        board[move][board_columns_used[move]] = other_token
        if check_winner(board, move, board_columns_used[move]):
            return move
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = other_token

        if check_winner(board, move, board_columns_used[move] + 1):
            losing_locations.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    # Opening book
    if moves_played == 1:
        if board[3][0] == other_token:
            losing_locations.add(3)

    if moves_played == 2:
        if board[3][1] == other_token:
            # state['opening_trap'] = True
            return 2
        if board[2][0] == other_token:
            return 2
        if board[4][0] == other_token:
            return 4

    if moves_played == 4:
        if board[3][1] == other_token and board[1][0] == '.' and board[4][
                0] == '.':
            return 4

    skip_moves = set()

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = token

        if check_winner(board,
                        move,
                        board_columns_used[move] + 1,
                        ignore_vertical=True):
            skip_moves.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    print(get_opcode_count())

    for move in preferred_locations:
        if move in skip_moves or move in losing_locations or board_columns_used[
                move] == 0 or board_columns_used[move] > 3:
            continue
        if move > 0:
            if board[move - 1][board_columns_used[move]] == token:
                return move
        if move < 6:
            if board[move + 1][board_columns_used[move]] == token:
                return move

    print(get_opcode_count())

    for move in priority_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move

    for move in priority_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move

    return random.choice(available_moves)
Example #4
0
def get_next_move(board, token):
    board_columns_used = get_board_columns_used(board)
    available_moves = game.available_moves(board)
    preferred_locations = [3, 2, 4, 1, 5, 0, 6]
    preferred_locations = [
        x for x in preferred_locations if x in available_moves
    ]
    priority_locations = get_columns_with_space(board, token,
                                                preferred_locations)
    opcode_limit = get_opcode_limit()
    losing_locations = set()
    skip_moves = set()

    # if state is None:
    #     state = {'opening_trap': False}

    moves_played = get_moves_played(board)

    other_token = 'X' if token == 'O' else 'O'

    for move in available_moves:
        board[move][board_columns_used[move]] = token
        if check_winner(board, move, board_columns_used[move]):
            return move
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        board[move][board_columns_used[move]] = other_token
        if check_winner(board, move, board_columns_used[move]):
            return move
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = other_token

        if check_winner(board, move, board_columns_used[move] + 1):
            losing_locations.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    # Opening book
    if moves_played == 1:
        if board[3][0] == other_token:
            losing_locations.add(3)

    if moves_played == 2:
        if board[3][1] == other_token:
            # state['opening_trap'] = True
            return 2
        if board[2][0] == other_token:
            return 2
        if board[4][0] == other_token:
            return 4

    if moves_played == 4:
        if board[3][1] == other_token and board[1][0] == '.' and board[4][
                0] == '.':
            return 4

    # Take the move if you see a open-ended 3 way opportunity
    for move in available_moves:
        if move_makes_3_horizontal_with_spaces(board, move,
                                               board_columns_used[move],
                                               token):
            return move

    # Block 2 adjacent tokens for the enemy
    for move in available_moves:
        if move_makes_3_horizontal_with_spaces(board, move,
                                               board_columns_used[move],
                                               other_token):
            return move

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = token

        if check_winner(board,
                        move,
                        board_columns_used[move] + 1,
                        ignore_vertical=True):
            skip_moves.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    print(get_opcode_count())

    for move in preferred_locations:
        if move in skip_moves or move in losing_locations or board_columns_used[
                move] == 0 or board_columns_used[move] > 3:
            continue
        if not can_make_4_horizontal(board, move, board_columns_used[move],
                                     token):
            continue
        if move > 0:
            if board[move - 1][board_columns_used[move]] == token:
                return move
        if move < 6:
            if board[move + 1][board_columns_used[move]] == token:
                return move

    for move in preferred_locations:
        move_score = {}
        if move in skip_moves or move in losing_locations or board_columns_used[
                move] == 0 or board_columns_used[move]:
            continue
        friendly_neighbours = get_friendly_neighbours(board, move,
                                                      board_columns_used[move],
                                                      token)
        if friendly_neighbours > 1:
            move_score[move] = friendly_neighbours
        if move_score:
            sorted_score = sorted(move_score.items(), key=itemgetter(1))
            return sorted_score[0][0]

    print(get_opcode_count())

    for move in priority_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move

    for move in priority_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move

    return random.choice(available_moves)
Example #5
0
def get_next_move(board, token):

    test_board = test_make_board_from_string()

    print(f'Before check_winner:{get_opcode_count()}')
    game.check_winner(test_board)
    print(f'After check_winner:{get_opcode_count()}')

    board_columns_used = get_board_columns_used(board)

    print(f'Before available moves:{get_opcode_count()}')
    all_available_moves = game.available_moves(board)
    print(f'After available moves:{get_opcode_count()}')

    preferred_locations = [3, 2, 4, 1, 5, 0, 6]

    print(f'Before preferred locations:{get_opcode_count()}')
    priority_locations = get_columns_with_space(board, token, preferred_locations)
    print(f'After preferred locations:{get_opcode_count()}')

    losing_locations = set()
    # if state is None:
    #     state = {'opening_trap': False}

    print(f'Before board walk: {get_opcode_count()}')
    board[3][board_columns_used[3]] = token
    board[3][board_columns_used[3]] = '.'
    print(f'After board walk: {get_opcode_count()}')


    new_board = game.new_board()
    new_board[0][0] = 'X'
    new_board[1][1] = 'X'
    new_board[2][2] = 'X'
    new_board[3][3] = 'X'

    print(f'Before game.check_winner:{get_opcode_count()}')
    game.check_winner(new_board)
    print(f'After game.check_winner:{get_opcode_count()}')

    print(f'Before check_winner:{get_opcode_count()}')
    check_winner(board, 3, 3)
    print(f'After check_winner:{get_opcode_count()}')

    rO = re.compile(r'OOOO|O.{6}O.{6}O.{6}O|O.{7}O.{7}O.{7}O|O.{8}O.{8}O.{8}O')
    rX = re.compile(r'XXXX|X.{6}X.{6}X.{6}X|X.{7}X.{7}X.{7}X|X.{8}X.{8}X.{8}X')
    board_string = make_string_from_board(board)
    print(f'Before check_winner_regex:{get_opcode_count()}')
    board_string = board_string[:2 * 7 + 2] + 'X' + board_string[2 * 7 + 2:]
    check_winner_regex(board_string, 'X', r=rX)
    print(f'After check_winner_regex:{get_opcode_count()}')

    moves_played = get_moves_played(board)

    # best_value = float('-inf')
    # best_move = random.choice(available_moves)

    other_token = 'X' if token == 'O' else 'O'

    for move in all_available_moves:
        board[move][board_columns_used[move]] = token
        if check_winner(board, move, board_columns_used[move]):
            return move
        board[move][board_columns_used[move]] = '.'

    print(get_opcode_count())

    for move in all_available_moves:
        board[move][board_columns_used[move]] = other_token
        if check_winner(board, move, board_columns_used[move]):
            return move
        board[move][board_columns_used[move]] = '.'

    print(get_opcode_count())

    available_moves = set(all_available_moves)

    for move in all_available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = other_token

        if check_winner(board, move, board_columns_used[move] + 1):
            losing_locations.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    print(get_opcode_count())

    skip_moves = set()

    for move in all_available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = token

        if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True):
            skip_moves.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    # for move in all_available_moves:
    #     board[move][board_columns_used[move]] = token
    #     if move_makes_opportunity(board, move, board_columns_used[move], token):
    #         return move


    print(get_opcode_count())

    if moves_played == 1:
        # Don't go on top of the previous player
        losing_locations.add(find_enemy_location(board, other_token))

    if moves_played == 2:
        if board[3][1] == other_token:
            return 2

    if moves_played == 4:
        if board[3][1] == other_token and board[1][0] == '.' and board[4][0] == '.':
            return 4

    priority_locations = [x for x in priority_locations if x not in skip_moves]

    for move in priority_locations:
        if move in losing_locations:
            continue
        return move

    for move in preferred_locations:
        if move in losing_locations:
            continue
        return move

    return random.choice(all_available_moves)
Example #6
0
def get_next_move(board, token, state):
    board_columns_used = get_board_columns_used(board)
    available_moves = game.available_moves(board)
    preferred_locations = [3, 2, 4, 1, 5, 0, 6]
    priority_locations = get_columns_with_space(board, token, preferred_locations)
    losing_locations = set()

    if state is None:
        state = {'opening_trap': False}

    moves_played = get_moves_played(board)

    other_token = 'X' if token == 'O' else 'O'

    for move in available_moves:
        board[move][board_columns_used[move]] = token
        if check_winner(board, move, board_columns_used[move]):
            return move, state
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        board[move][board_columns_used[move]] = other_token
        if check_winner(board, move, board_columns_used[move]):
            return move, state
        board[move][board_columns_used[move]] = '.'

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = other_token

        if check_winner(board, move, board_columns_used[move] + 1):
            losing_locations.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    skip_moves = set()

    for move in available_moves:
        if board_columns_used[move] > 4:
            continue
        board[move][board_columns_used[move]] = token
        board[move][board_columns_used[move] + 1] = token

        if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True):
            skip_moves.add(move)

        board[move][board_columns_used[move]] = '.'
        board[move][board_columns_used[move] + 1] = '.'

    print(get_opcode_count())

    if moves_played == 1:
        # Don't go on top of the previous player
        losing_locations.add(find_enemy_location(board, other_token))

    if moves_played == 2:
        if board[3][1] == other_token:
            state['opening_trap'] = True
            return 2, state

    if moves_played == 4:
        if state['opening_trap']:
            if board[1][0] == '.' and board[4][0] == '.':
                return 4, state

    for move in priority_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move, state

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations or move in skip_moves:
            continue
        return move, state

    for move in priority_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move, state

    for move in preferred_locations:
        if move not in available_moves or move in losing_locations:
            continue
        return move, state

    return random.choice(available_moves), state