import sys

BOARD_SIZE = 9
COLS = [c for c in "ABCDEFGHJ"]  # Skip 'I'
COL_TO_IDX = {c: i for i, c in enumerate(COLS)}
IDX_TO_COL = {i: c for i, c in enumerate(COLS)}

EMPTY = '.'
BLACK = 'B'
WHITE = 'W'

def opponent(player):
    return BLACK if player == WHITE else WHITE

def print_board(board):
    print("  " + " ".join(COLS))
    for r in range(BOARD_SIZE):
        print(f"{r+1:<2}" + " ".join(board[r][c] for c in range(BOARD_SIZE)))

def neighbors(r, c):
    for nr, nc in ((r-1,c),(r+1,c),(r,c-1),(r,c+1)):
        if 0 <= nr < BOARD_SIZE and 0 <= nc < BOARD_SIZE:
            yield nr, nc

def group_and_liberties(board, r, c, visited=None):
    if visited is None:
        visited = set()
    color = board[r][c]
    group = set()
    liberties = set()
    stack = [(r,c)]
    while stack:
        rr, cc = stack.pop()
        if (rr, cc) in visited:
            continue
        visited.add((rr, cc))
        group.add((rr, cc))
        for nr, nc in neighbors(rr, cc):
            if board[nr][nc] == EMPTY:
                liberties.add((nr, nc))
            elif board[nr][nc] == color and (nr, nc) not in visited:
                stack.append((nr, nc))
    return group, liberties

def remove_group(board, group):
    for r, c in group:
        board[r][c] = EMPTY

def parse_move(move):
    move = move.strip().upper()
    if move == "PASS":
        return "PASS", None, None
    if len(move) < 2 or len(move) > 3:
        return None, None, None
    col_c = move[0]
    if col_c not in COL_TO_IDX:
        return None, None, None
    try:
        row_n = int(move[1:])
    except:
        return None, None, None
    if not (1 <= row_n <= BOARD_SIZE):
        return None, None, None
    return "MOVE", row_n-1, COL_TO_IDX[col_c]

def play_move(board, player, r, c):
    if board[r][c] != EMPTY:
        return False, "Point occupied"
    # Place stone tentatively
    board[r][c] = player

    # Capture opponent groups with zero liberties
    captured_any = False
    opp = opponent(player)
    to_capture = []
    for nr, nc in neighbors(r, c):
        if board[nr][nc] == opp:
            group, libs = group_and_liberties(board, nr, nc)
            if len(libs) == 0:
                to_capture.append(group)
    for group in to_capture:
        remove_group(board, group)
        captured_any = True

    # Check suicide: does player's group at (r,c) have liberties?
    group, libs = group_and_liberties(board, r, c)
    if len(libs) == 0 and not captured_any:
        # Undo move
        board[r][c] = EMPTY
        return False, "Suicide move not allowed"
    return True, None

def count_area(board):
    # Area scoring: stones + empty points surrounded by one color
    visited = set()
    black_area = 0
    white_area = 0

    for r in range(BOARD_SIZE):
        for c in range(BOARD_SIZE):
            if board[r][c] == BLACK:
                black_area += 1
            elif board[r][c] == WHITE:
                white_area += 1
            elif board[r][c] == EMPTY and (r,c) not in visited:
                # Flood fill empty area
                queue = [(r,c)]
                territory = set()
                bordering_colors = set()
                while queue:
                    rr, cc = queue.pop()
                    if (rr, cc) in visited:
                        continue
                    visited.add((rr, cc))
                    territory.add((rr, cc))
                    for nr, nc in neighbors(rr, cc):
                        if board[nr][nc] == EMPTY and (nr, nc) not in visited:
                            queue.append((nr, nc))
                        elif board[nr][nc] in (BLACK, WHITE):
                            bordering_colors.add(board[nr][nc])
                if len(bordering_colors) == 1:
                    if BLACK in bordering_colors:
                        black_area += len(territory)
                    else:
                        white_area += len(territory)
                # else neutral, no points
    return black_area, white_area

def main():
    board = [[EMPTY]*BOARD_SIZE for _ in range(BOARD_SIZE)]
    player = BLACK
    passes = 0

    while True:
        print_board(board)
        print(f"{'Black' if player == BLACK else 'White'} to move.")
        while True:
            move_str = input("Enter move (e.g. E5) or pass: ").strip()
            kind, r, c = parse_move(move_str)
            if kind is None:
                print("Invalid move format. Try again.")
                continue
            if kind == "PASS":
                passes += 1
                break
            # Move
            success, err = play_move(board, player, r, c)
            if not success:
                print(err)
                continue
            passes = 0
            break
        if passes >= 2:
            print_board(board)
            print("Both players passed consecutively. Game over.")
            black_score, white_score = count_area(board)
            print(f"Final score (area): Black {black_score}, White {white_score}")
            if black_score > white_score:
                print("Black wins!")
            elif white_score > black_score:
                print("White wins!")
            else:
                print("It's a tie!")
            sys.exit(0)
        player = opponent(player)

if __name__ == "__main__":
    main()
