def format_game_board(game_board: str) -> str:
    """Return a string representation of game_board for printing.

    >>> expected = ("\\nThe Connect-N board:\\n\\n   1   2  \\n\\n" +
    ...             "1  B | R\\n  ---+---\\n2  B | -\\n")
    >>> format_game_board('BRB-') == expected
    True
    """

    formatted_board = "\nThe Connect-N board:\n\n"

    board_size = cnf.get_board_size(game_board)

    # Add in the column numbers.
    formatted_board += '  '
    for col in range(1, board_size + 1):
        formatted_board += ' ' + str(col) + '  '
    formatted_board += '\n\n'

    # Add in the row numbers, board contents, and grid markers.
    position = 0
    for row in range(1, board_size + 1):
        formatted_board += str(row) + ' '
        for col in range(1, board_size):
            formatted_board += ' ' + game_board[position] + ' |'
            position += 1
        formatted_board += ' ' + game_board[position] + '\n'
        position += 1
        if row < board_size:
            formatted_board += '  ' + '---+' * (board_size - 1) + '---\n'

    return formatted_board
def vertical_win(game_board: str, winning_string: str) -> bool:
    """Return True if and only if winning_string appears in any column in
    game_board.

    >>> vertical_win('RBBR--R--', 'RRR')
    True
    >>> vertical_win('-R--R--R-', 'RRR')
    True
    >>> vertical_win('RBBR--R--', 'BRB')
    False
    """

    return check_win(game_board, winning_string, range(1, 2),
                     range(cnf.get_board_size(game_board) + 1), cnf.DOWN)
def horizontal_win(game_board: str, winning_string: str) -> bool:
    """Return True if and only if winning_string appears in any row in
    game_board.

    >>> horizontal_win('BBB-R-R--', 'BBB')
    True
    >>> horizontal_win('BRB-BBRRR', 'RRR')
    True
    >>> horizontal_win('BRB-BBRRR', 'BBB')
    False
    """

    return check_win(game_board, winning_string,
                     range(cnf.get_board_size(game_board) + 1), range(1, 2),
                     cnf.ACROSS)
def is_occupied(row_index: int, col_index: int, game_board: str) -> bool:
    """Return True if and only if the cell with indices row_index and
    col_index in game_board does not contain the EMPTY cell character.

    Precondition: row_index and col_index are valid indices for a cell
                  in the game_board.

    >>> is_occupied(1, 1, 'BRB-')
    True
    >>> is_occupied(2, 2, 'BRB-')
    False
    """

    board_size = cnf.get_board_size(game_board)
    position = cnf.get_str_index(row_index, col_index, board_size)
    return game_board[position] != cnf.EMPTY
def retrieve_line(game_board: str, row: int, col: int, direction: str) -> str:
    """Return a line of characters in game_board, starting at position
    (row, col), in the direction direction.

    Precondition: row and col specify a valid location of a cell in
                  game_board.
                  direction is one of DOWN, ACROSS, DOWN_LEFT, DOWN_RIGHT
                  when direction is DOWN_LEFT, location (row, col) is either
                   on the top row or the rightmost column of the game board
                  when direction is DOWN_RIGHT, location (row, col) is either
                   on the top row or the leftmost column of the game board

    >>> retrieve_line('-B--R--B-', 1, 2, 'down')
    'BRB'
    >>> retrieve_line('------BRB', 3, 1, 'across')
    'BRB'
    >>> retrieve_line('B---B---B', 1, 1, 'down_right')
    'BBB'
    >>> retrieve_line('-B---B---', 1, 2, 'down_right')
    'BB'
    >>> retrieve_line('--B------', 1, 3, 'down_right')
    'B'
    >>> retrieve_line('---B---R-', 2, 1, 'down_right')
    'BR'
    >>> retrieve_line('------B--', 3, 1, 'down_right')
    'B'
    >>> retrieve_line('B--------', 1, 1, 'down_left')
    'B'
    >>> retrieve_line('-B-R-----', 1, 2, 'down_left')
    'BR'
    >>> retrieve_line('--B-R-B--', 1, 3, 'down_left')
    'BRB'
    >>> retrieve_line('-----B-R-', 2, 3, 'down_left')
    'BR'
    >>> retrieve_line('--------B', 3, 3, 'down_left')
    'B'
    """

    board_size = cnf.get_board_size(game_board)
    first_index = cnf.get_str_index(row, col, board_size)
    increment = cnf.get_increment(direction, board_size)
    last_index = cnf.get_last_index(row, col, direction, board_size)
    return game_board[first_index:last_index + 1:increment]
def get_empty_row_col(game_board: str) -> (int, int):
    """Return a pair of row and column indices, entered by the user, that
    are valid indices of a non-occupied cell in game_board.
    Repeatedly prompt the user for input, until the user enters valid
    row/col indices of a non-occupied cell. Display an error message
    for each invalid input.

    (No docstring example given since the function either depends on user
    input or randomly generated numbers.)
    """

    board_size = cnf.get_board_size(game_board)

    (row, col) = get_valid_row_col(board_size)
    while is_occupied(row, col, game_board):
        print('That spot is already taken! Try again.')
        (row, col) = get_valid_row_col(board_size)

    return (row, col)
def down_left_win(game_board: str, winning_string: int) -> bool:
    """Return True if and only if winning_string appears in any down_left
    diagonal in game_board.

    >>> down_left_win('--B-BRB-R', 'BBB')
    True
    >>> down_left_win('-----B-B-', 'BB')
    True
    >>> down_left_win('-B-B----B', 'BB')
    True
    >>> down_left_win('-R--R--R-', 'RRR')
    False
    """

    board_size = cnf.get_board_size(game_board)

    return (check_win(game_board, winning_string, range(1, 2),
                      range(board_size + 1), cnf.DOWN_LEFT)
            or check_win(game_board, winning_string, range(board_size + 1),
                         range(board_size, board_size + 1), cnf.DOWN_LEFT))
def get_move(is_human_move: bool, game_board: str) -> (int, int):
    """Return a pair of row and column indices that are valid indices of a
    non-occupied cell in game_board.  If is_human_move is True,
    repeatedly prompt the user for input, until the user enters valid
    row/col indices of a non-occupied cell.  Display an error message
    for each invalid input. Otherwise, randomly generate a valid pair
    of a non-occupied cell's indices.

    (No docstring example given since the function either depends on user
    input or randomly generated numbers.)
    """

    if is_human_move:
        return get_empty_row_col(game_board)

    board_size = cnf.get_board_size(game_board)
    row = random.randint(1, board_size)
    col = random.randint(1, board_size)
    while is_occupied(row, col, game_board):
        row = random.randint(1, board_size)
        col = random.randint(1, board_size)
    return (row, col)