import sys

class GoGame:
    def __init__(self):
        self.size = 9
        self.board = [[None for _ in range(self.size)] for _ in range(self.size)]
        self.turn = 'B'  # 'B' for Black, 'W' for White
        self.captures = {'B': 0, 'W': 0}
        self.cols = "ABCDEFGHJ"  # Skipping 'I'
        self.pass_count = 0

    def print_board(self):
        print("\n  " + " ".join(self.cols))
        for r in range(self.size):
            row_str = f"{r+1} "
            for c in range(self.size):
                cell = self.board[r][c]
                char = '●' if cell == 'B' else '○' if cell == 'W' else '.'
                row_str += char + " "
            print(row_str)
        print(f"\nTurn: {'Black' if self.turn == 'B' else 'White'}")
        print(f"Captures: B:{self.captures['B']} W:{self.captures['W']}")

    def get_neighbors(self, r, c):
        neighbors = []
        for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            nr, nc = r + dr, c + dc
            if 0 <= nr < self.size and 0 <= nc < self.size:
                neighbors.append((nr, nc))
        return neighbors

    def get_group(self, r, c):
        color = self.board[r][c]
        group = set([(r, c)])
        stack = [(r, c)]
        while stack:
            curr_r, curr_c = stack.pop()
            for nr, nc in self.get_neighbors(curr_r, curr_c):
                if self.board[nr][nc] == color and (nr, nc) not in group:
                    group.add((nr, nc))
                    stack.append((nr, nc))
        return group

    def count_liberties(self, group):
        liberties = set()
        for r, c in group:
            for nr, nc in self.get_neighbors(r, c):
                if self.board[nr][nc] is None:
                    liberties.add((nr, nc))
        return len(liberties)

    def handle_captures(self, placed_r, placed_c):
        opponent = 'W' if self.turn == 'B' else 'B'
        captured_any = False
        
        # Check opponent groups around the placed stone
        for nr, nc in self.get_neighbors(placed_r, placed_c):
            if self.board[nr][nc] == opponent:
                group = self.get_group(nr, nc)
                if self.count_liberties(group) == 0:
                    for gr, gc in group:
                        self.board[gr][gc] = None
                        self.captures[self.turn] += 1
                    captured_any = True
        return captured_any

    def is_suicide(self, r, c):
        # Temporarily place stone to check liberties
        original_color = self.board[r][c]
        self.board[r][c] = self.turn
        
        # Check if this move captures anything first
        opponent = 'W' if self.turn == 'B' else 'B'
        can_capture = False
        for nr, nc in self.get_neighbors(r, c):
            if self.board[nr][nc] == opponent:
                if self.count_liberties(self.get_group(nr, nc)) == 0:
                    can_capture = True
                    break
        
        # If it doesn't capture, check if the placed group has liberties
        group = self.get_group(r, c)
        liberties = self.count_liberties(group)
        
        self.board[r][c] = original_color # Restore
        
        if can_capture:
            return False
        return liberties == 0

    def parse_coord(self, coord):
        if not coord or len(coord) < 2:
            return None
        col_char = coord[0].upper()
        if col_char not in self.cols:
            return None
        try:
            row_val = int(coord[1:]) - 1
            col_val = self.cols.index(col_char)
            if 0 <= row_val < self.size and 0 <= col_val < self.size:
                return row_val, col_val
        except ValueError:
            pass
        return None

    def calculate_score(self):
        # Simple Area Scoring: Count stones on board + empty territory
        # Territory is empty space surrounded by one color
        score = {'B': 0, 'W': 0}
        visited = set()
        for r in range(self.size):
            for c in range(self.size):
                if self.board[r][c] is not None:
                    score[self.board[r][c]] += 1
                elif (r, c) not in visited:
                    # Flood fill to find empty area
                    area = set([(r, c)])
                    stack = [(r, c)]
                    border_colors = set()
                    while stack:
                        curr_r, curr_c = stack.pop()
                        for nr, nc in self.get_neighbors(curr_r, curr_c):
                            if 0 <= nr < self.size and 0 <= nc < self.size:
                                if self.board[nr][nc] is None:
                                    if (nr, nc) not in area:
                                        area.add((nr, nc))
                                        stack.append((nr, nc))
                                else:
                                    border_colors.add(self.board[nr][nc])
                    
                    visited.update(area)
                    if len(border_colors) == 1:
                        color = list(border_colors)[0]
                        score[color] += len(area)
        return score

    def play(self):
        print("Welcome to 9x9 Go!")
        print("Enter coordinates like 'E5' or 'pass'.")
        
        while True:
            self.print_board()
            move = input(f"Player {self.turn} move: ").strip().lower()
            
            if move == 'pass':
                self.pass_count += 1
                self.turn = 'W' if self.turn == 'B' else 'B'
                if self.pass_count >= 2:
                    break
                continue
            
            self.pass_count = 0
            coords = self.parse_coord(move)
            if coords is None:
                print("Invalid coordinate format.")
                continue
            
            r, c = coords
            if self.board[r][c] is not None:
                print("Point already occupied.")
                continue
            
            if self.is_suicide(r, c):
                print("Suicide move is forbidden.")
                continue
            
            # Execute move
            self.board[r][c] = self.turn
            self.handle_captures(r, c)
            self.turn = 'W' if self.turn == 'B' else 'B'

        final_scores = self.calculate_score()
        # Add captured stones to the area score
        final_scores['B'] += self.captures['B']
        final_scores['W'] += self.captures['W']
        
        print("\nGame Over!")
        print(f"Final Score (Area + Captures): Black {final_scores['B']}, White {final_scores['W']}")
        if final_scores['B'] > final_scores['W']:
            print("Black wins!")
        elif final_scores['W'] > final_scores['B']:
            print("White wins!")
        else:
            print("It's a tie!")

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