class GoGame:
    def __init__(self):
        self.size = 9
        self.board = [[None for _ in range(self.size)] for _ in range(self.size)]
        self.current_player = 'B'
        self.pass_count = 0
        self.captured = {'B': 0, 'W': 0}
        self.move_history = []

    def print_board(self):
        print("   " + " ".join([chr(65 + i) for i in range(self.size)]))
        for i in range(self.size):
            row = [str(i + 1).rjust(2) + " "]
            for j in range(self.size):
                cell = self.board[i][j]
                row.append('B' if cell == 'B' else 'W' if cell == 'W' else '.')
            print(" ".join(row))

    def is_valid_move(self, move):
        if move.lower() == 'pass':
            return True
        if len(move) < 2:
            return False
        col = move[0].upper()
        row = move[1:]
        if not row.isdigit():
            return False
        row = int(row) - 1
        col = ord(col) - ord('A')
        if col < 0 or col >= self.size or row < 0 or row >= self.size:
            return False
        if self.board[row][col] is not None:
            return False
        return True

    def get_move(self):
        while True:
            move = input(f"Player {self.current_player}'s turn. Enter move (e.g., E5) or 'pass': ").strip()
            if self.is_valid_move(move):
                return move
            print("Invalid move. Try again.")

    def place_stone(self, row, col):
        self.board[row][col] = self.current_player
        self.move_history.append((row, col, self.current_player))

    def get_group(self, row, col):
        color = self.board[row][col]
        if color is None:
            return []
        group = []
        stack = [(row, col)]
        visited = set()
        while stack:
            r, c = stack.pop()
            if (r, c) in visited:
                continue
            visited.add((r, c))
            group.append((r, c))
            for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < self.size and 0 <= nc < self.size:
                    if self.board[nr][nc] == color and (nr, nc) not in visited:
                        stack.append((nr, nc))
        return group

    def count_liberties(self, group):
        liberties = set()
        for r, c in group:
            for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < self.size and 0 <= nc < self.size:
                    if self.board[nr][nc] is None:
                        liberties.add((nr, nc))
        return len(liberties)

    def capture_stones(self, row, col):
        opponent = 'W' if self.current_player == 'B' else 'B'
        captured_groups = []
        for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
            nr, nc = row + dr, col + dc
            if 0 <= nr < self.size and 0 <= nc < self.size:
                if self.board[nr][nc] == opponent:
                    group = self.get_group(nr, nc)
                    if self.count_liberties(group) == 0:
                        captured_groups.append(group)
        for group in captured_groups:
            for r, c in group:
                self.board[r][c] = None
            self.captured[self.current_player] += len(group)

    def is_suicide(self, row, col):
        self.board[row][col] = self.current_player
        group = self.get_group(row, col)
        liberties = self.count_liberties(group)
        self.board[row][col] = None
        return liberties == 0

    def make_move(self, move):
        if move.lower() == 'pass':
            self.pass_count += 1
            return True
        col = move[0].upper()
        row = int(move[1:]) - 1
        col = ord(col) - ord('A')
        if self.is_suicide(row, col):
            print("Suicide move is not allowed.")
            return False
        self.place_stone(row, col)
        self.capture_stones(row, col)
        self.pass_count = 0
        return True

    def switch_player(self):
        self.current_player = 'W' if self.current_player == 'B' else 'B'

    def score_game(self):
        black_score = 0
        white_score = 0
        for i in range(self.size):
            for j in range(self.size):
                if self.board[i][j] == 'B':
                    black_score += 1
                elif self.board[i][j] == 'W':
                    white_score += 1
        black_score += self.captured['B']
        white_score += self.captured['W']
        return black_score, white_score

    def play(self):
        print("Welcome to Go! Enter moves as coordinates (e.g., E5) or 'pass'.")
        while self.pass_count < 2:
            self.print_board()
            move = self.get_move()
            if not self.make_move(move):
                continue
            self.switch_player()
        self.print_board()
        black_score, white_score = self.score_game()
        print(f"Game over. 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!")

if __name__ == "__main__":
    game = GoGame()
    game.play()
