# -*- coding: utf-8 -*-
"""
対人オセロゲーム（プログラム）
"""
# これは，難易度３を達成するプログラムのソースコードです．


class Othello:
    BOARD_SIZE = 8
    STONE_STR  =  ["[ ]", " X ", " O "]  # 石の文字


    def __init__(self):
        # 盤面を初期化した状態でインスタンス変数として生成
        self.board      = [[0 for j in range(__class__.BOARD_SIZE)] for i in range(__class__.BOARD_SIZE)]
        self.board_rev  = [[False for j in range(__class__.BOARD_SIZE)] for i in range(__class__.BOARD_SIZE)]

        # 最初の石をセット
        self.board[3][4] = 1
        self.board[4][3] = 1
        self.board[3][3] = 2
        self.board[4][4] = 2

        self.num_side = 1


    # 盤面の表示
    def print_board(self):
        print("   1  2  3  4  5  6  7  8")  # 横方向の目盛
        j = 1
        for board_raw in self.board:
            print(f"{j} ", end="")          # 縦方向の目盛
            for board_cel in board_raw:
                # 石を表示
                print(__class__.STONE_STR[board_cel], end="")
            print(f" {j}")                  # 縦方向の目盛
            j += 1
        print("   1  2  3  4  5  6  7  8")  # 横方向の目盛


    # 位置が盤面の外かどうかを判定
    def is_out_of_board(self, num_v, num_h):
        if (0 <= num_v < __class__.BOARD_SIZE) and (0 <= num_h < __class__.BOARD_SIZE):
            return False
        return True


    # board_revの初期化
    def clear_board_rev(self):
        for i in range(__class__.BOARD_SIZE):
            for j in range(__class__.BOARD_SIZE):
                self.board_rev[i][j] = False


    # 縦横斜めのいずれかの方向の石を見て置けるかどうかを判定
    def check_line(self, num_side, num_v, num_h, dv, dh):
        if self.is_out_of_board(num_v, num_h) or (self.board[num_v][num_h] == 0):
            return -1
        elif self.board[num_v][num_h] == num_side:
            return 0
        
        num_d = self.check_line(num_side, num_v+dv, num_h+dh, dv, dh)
        if num_d >= 0:
            self.board_rev[num_v][num_h] = True
            return num_d + 1
        return num_d


    # 石を置けるかどうかを判定
    def check_puttable(self, num_side, num_v, num_h):
        flag_rev = False
        # 位置が盤面の外の場合や既に石が置かれていた場合はやり直し
        if self.is_out_of_board(num_v, num_h) or (self.board[num_v][num_h] != 0):
            return flag_rev

        # ８方向の石を見て置けるかどうかを判断
        self.clear_board_rev()
        for dv in range(-1, 2):
            for dh in range(-1, 2):
                if (dv == 0) and (dh == 0):
                    continue
                if self.check_line(num_side, num_v+dv, num_h+dh, dv, dh) > 0:
                    flag_rev = True
        return flag_rev
    

    # 石を置き，裏返せるところを返す
    def put_stone(self, num_side, num_v, num_h):
        self.board[num_v][num_h] = num_side
        self.rev_stones(num_side)


    # 石の数を数え上げ
    def count_stones(self):
        num_stones = [0, 0, 0]
        for i in range(__class__.BOARD_SIZE):
            for j in range(__class__.BOARD_SIZE):
                num_stones[self.board[i][j]] += 1
        return num_stones

    # 石を裏返す処理
    def rev_stones(self, num_side):
        for i in range(__class__.BOARD_SIZE):
            for j in range(__class__.BOARD_SIZE):
                if self.board_rev[i][j]:
                    self.board[i][j] = num_side



def main():
    board = Othello()
    board.print_board()

    num_side = 1  # どちらの手番か
    num_move = 1  # 何手目か
    flg_pass = False

    while True:
        num_stones = board.count_stones()
        if num_stones[0] == 0:
            print("盤が埋まったため終了します")
            break
        # 手番の出力
        print(f"{Othello.STONE_STR[num_side]}の番です")
        print(f"どこに置きますか？（ {num_move} 手目）")
        # 位置の入力　listのインデックスと対応させるため -1
        num_v = int(input("縦：")) - 1
        num_h = int(input("横：")) - 1
        print()  # 改行のみ

        # 位置が縦横ともに０以下の場合はパス
        if (num_v < 0) and (num_h < 0):
            print("パス")
            if flg_pass:
                print("両者パスのため終了します")
                break
            flg_pass = True
            num_side = (num_side % 2) + 1
            num_move += 1
            continue

        if not(board.check_puttable(num_side, num_v, num_h)):
            print("そこには置けません")
            continue

        board.put_stone(num_side, num_v, num_h)

        # 盤面を表示して攻守交替
        board.print_board()
        flg_pass = False
        num_side = (num_side % 2) + 1
        num_move += 1

    # 勝敗判定と表示
    print(f"{Othello.STONE_STR[1]}の石は {num_stones[1]} 個")
    print(f"{Othello.STONE_STR[2]}の石は {num_stones[2]} 個")
    if num_stones[1] > num_stones[2]:
        print(f"{Othello.STONE_STR[1]}の勝ちです")
    elif num_stones[1] < num_stones[2]:
        print(f"{Othello.STONE_STR[2]}の勝ちです")
    else:
        print("引き分けです")



if __name__ == "__main__":
    main()
