#!/usr/bin/env python3
import sys

SIZE = 9
EMPTY = 0
BLACK = 1
WHITE = 2
COLS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J']

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

def in_bounds(y, x):
    return 0 <= y < SIZE and 0 <= x < SIZE

DIRS = [(-1, 0), (1, 0), (0, -1), (0, 1)]

def get_group(board, y, x):
    """Return (set of stones in the group, set of liberties)."""
    color = board[y][x]
    if color == EMPTY:
        return set(), set()
    visited = set()
    stones = set()
    libs = set()
    stack = [(y, x)]
    while stack:
        cy, cx = stack.pop()
        if (cy, cx) in visited:
            continue
        visited.add((cy, cx))
        stones.add((cy, cx))
        for dy, dx in DIRS:
            ny, nx = cy + dy, cx + dx
            if not in_bounds(ny, nx):
                continue
            if board[ny][nx] == EMPTY:
                libs.add((ny, nx))
            elif board[ny][nx] == color and (ny, nx) not in visited:
                stack.append((ny, nx))
    return stones, libs

def remove_group(board, group):
    for y, x in group:
        board[y][x] = EMPTY

def print_board(board):
    header = "   " + " ".join(COLS)
    print(header)
    for row in range(SIZE):
        line = f"{row+1:2d} "
        for col in range(SIZE):
            cell = board[row][col]
            if cell == BLACK:
                line += "X "
            elif cell == WHITE:
                line += "O "
            else:
                line += ". "
        print(line.rstrip())
    print()

def coord_to_index(coord):
    """Return (y, x) indices from a string like 'E5'."""
    coord = coord.strip().upper()
    if len(coord) < 2:
        return None
    col_char = coord[0]
    if col_char not in COLS:
        return None
    try:
        row_num = int(coord[1:])
    except ValueError:
        return None
    if not (1 <= row_num <= SIZE):
        return None
    x = COLS.index(col_char)
    y = row_num - 1
    return y, x

def main():
    board = [[EMPTY for _ in range(SIZE)] for _ in range(SIZE)]
    captures = {BLACK: 0, WHITE: 0}
    player = BLACK
    consecutive_passes = 0

    while True:
        print_board(board)
        prompt = "Black" if player == BLACK else "White"
        move = input(f"{prompt} to move (or pass): ").strip()
        if move.lower() == "pass":
            consecutive_passes += 1
            if consecutive_passes >= 2:
                break
            player = opponent(player)
            continue
        index = coord_to_index(move)
        if index is None:
            print("Invalid coordinate. Try again.")
            continue
        y, x = index
        if board[y][x] != EMPTY:
            print("Point already occupied. Try again.")
            continue

        # Tentatively place the stone
        board[y][x] = player
        captured_this_move = 0
        # Check opponent neighbours for capture
        for dy, dx in DIRS:
            ny, nx = y + dy, x + dx
            if not in_bounds(ny, nx):
                continue
            if board[ny][nx] == opponent(player):
                group, libs = get_group(board, ny, nx)
                if len(libs) == 0:
                    remove_group(board, group)
                    captures[player] += len(group)
                    captured_this_move += len(group)

        # Check for suicide
        own_group, own_libs = get_group(board, y, x)
        if len(own_libs) == 0 and captured_this_move == 0:
            board[y][x] = EMPTY  # revert
            print("Suicide move not allowed. Try again.")
            continue

        # Valid move
        consecutive_passes = 0
        player = opponent(player)

    # Game over, compute score (stones + captures)
    black_stones = sum(row.count(BLACK) for row in board)
    white_stones = sum(row.count(WHITE) for row in board)
    black_score = black_stones + captures[BLACK]
    white_score = white_stones + captures[WHITE]

    print("\nFinal board:")
    print_board(board)
    print(f"Black stones on board: {black_stones}, captures: {captures[BLACK]}, total: {black_score}")
    print(f"White stones on board: {white_stones}, captures: {captures[WHITE]}, total: {white_score}")
    if black_score > white_score:
        print(f"Black wins by {black_score - white_score} points.")
    elif white_score > black_score:
        print(f"White wins by {white_score - black_score} points.")
    else:
        print("The game is a tie.")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        sys.exit("\nGame terminated.")
