Pythonで、人 対 bot、の囲碁対戦ゲームをつくる～できたことと、できなかったこと～ 

囲碁は将棋にくらべてもそれを楽しむ人口が少なく、他のゲームの中で考えれば、既に「化石」のようなゲームともいえよう。
　それでも小さなころから囲碁に親しんできたぼくからすると、囲碁人口が少しでも増えれば、という思いはある（とはいえ、実際、地方在住の自分のまわりで囲碁をうつ人は８０歳前後の人ばかり、というのが現実だが）。 

　既製の囲碁ゲームは誰にもアクセスできる。ダウンロードしてスマホやＰＣで。ネット対戦型。もうこれで充分の気もする豊富なラインアップだ。　
 https://igokuma.com/compare-go-sites-apps/

 　もう少し興味のある人は、個人的に、密かに「思考エンジン」を、既製の囲碁のＧＵＩにとりこみ、そこで対戦させるかもしれない。ただ、これは誰にでも開かれているわけではなく、少しコンピューターの知識がいる。　   　     
  https://www.h-eba.jp/Lizzie/soft.html

　あわよくば、2024年のノーベル物理学賞の対象となった、AlfaZeroのさきがけであるAlfaGoと対戦できるかもしれない、などと夢見て。
 https://book.mynavi.jp/nyushin/
 http://netdays365.com/archives/1818 

今回の報告は、Qiitaで以前書いたものの続きである。
https://qiita.com/tkoji3744/items/bb0b0767089133c7aa5e

　これをやろうと思った理由のひとつが、ぼくが個人的に、「思考エンジン」を、既製の囲碁のＧＵＩにとりこみ、そこで対戦させよとしたとき、Ｃ言語系(.exeファイル)はとりこみやすいが、Python系(.pyファイル)がどうにもとりこめなかったからである（もちろん、知識がある人なら、楽々とりこめるのかもしれないが、ぼくはできなかった）。
　そこで、囲碁ゲームをPythonで書きはじまたのだが、もともとぼくには、pythonで何十行ものプログラムを書く能力はない。どうせ、すぐに挫折する覚悟だったのだが、ChatGPTを使うことで、Python超初心者が自身の期待以上にすすめた、のでそれをここに記録してみた。　
　これを助けたのは、ChatGPTのおかげと、やはり、ぼくが囲碁についてよく知っているということが大きかったことはまちがいない。 

（１）ランダムボット、モンテカルロボットの作成と、６ステージ遷移する囲碁ゲーム設計

　まずは、以前書いた人対人の囲碁ゲームを発展させ、人対ボットを実現させるために、以前の「人対人」のゲームにbot.pyを加えた。ここにランダムボット、モンテカルロボットを記述した。
　ただ、モンテカルロボットが、どうやって勝敗判定をおこなって、次の手を決めているのか？ぼく自身、はっきりしないところがある。今のプレイアウトの回数は10回？何回やるのがいいのか？時間で区切るのか？そもそもそのプレイはランダム勝負か？あるいは各プレイアウトの後、選択の指標は、何か？勝率？それとも、そこまでの累積の勝ち差数？ 

（参考）ぼく、とChatGPTのやりとりより
ぼく：
[MonteCarloBot] シミュレーション 9/10: ランダムプレイアウト開始[MonteCarloBot] ランダムプレイアウト開始
[MonteCarloBot] ランダムプレイアウト: Stone.WHITE が (0, 8) に置く[MonteCarloBot] ランダムプレイアウト終了: 1 手で終了 しました。[MonteCarloBot] 黒: 0, 白: 0
[MonteCarloBot] シミュレーション 9/10: 結果 = 勝利
[MonteCarloBot] シミュレーション 10/10: ランダムプレ イアウト開始[MonteCarloBot] ランダムプレイアウト開始
[MonteCarloBot] ランダムプレイアウト: Stone.WHITE が (2, 2) に置く[MonteCarloBot] ランダムプレイアウト終了: 1 手で終了 しました。[MonteCarloBot] 黒: 0, 白: 1
[MonteCarloBot] シミュレーション 10/10: 結果 = 勝利
[MonteCarloBot] 手 (6, 7) のスコア: 0.9

[MonteCarloBot] 手 (7, 7) を評価中...
[MonteCarloBot] シミュレーションを開始: 手 (7, 7)
[MonteCarloBot] シミュレーション 1/10: ランダムプレイアウト開始　
と続きます。今のコードでよろしいですか？ 

ChatGPT：
　ログを見る限り、現在の MonteCarloBot の動作は期待どおりに進行しているようです。シミュレーションごとにランダムプレイアウトを実行し、終了時点でスコアを計算していることが確認できます。

確認ポイント
以下の点を確認し、現状の挙動が意図に合致しているかを確かめましょう。1. シミュレーション結果
各シミュレーションが正常に終了しています。
黒 (Stone.BLACK) と白 (Stone.WHITE) のスコアが計算されている。
例: [MonteCarloBot] 黒: 0, 白: 1 のようにスコアが出力されている。
2. 手のスコア計算
各合法手に対してシミュレーションが実行され、スコアが計算されています。
例: [MonteCarloBot] 手 (6, 7) のスコア: 0.9 のようにスコアが出力されている。
3. 次の手の評価進行
手ごとにシミュレーションを繰り返し、ログに出力されています。
例: [MonteCarloBot] 手 (7, 7) を評価中... のログが確認できています。

改善ポイント
現在の実装は、正常に動作しているように見えますが、以下の改善を加えることで効率化や精度向上が可能です。
1. シミュレーション回数の調整
デバッグ用にシミュレーション回数を 10 回に設定していますが、実際のゲームではこの値を増やすことで精度が向上します。例: self.simulations = 100 または self.simulations = 500
2. ログの抑制
現在はデバッグ用に詳細なログを出力していますが、ゲーム中のパフォーマンスに影響を与える可能性があります。
必要に応じてログ出力を制限するか、デバッグオプションを切り替えられるようにします。
3. 勝敗判定の条件の確認
スコア計算が妥当かどうかを再確認します。
スコア計算式: 黒の地 + 黒が捕獲した白石数 vs 白の地 + 白が捕獲した黒石数必要であれば、評価関数を改善することでボットの強さを向上させることが可能です。

 　プロジェクトの構成は以下のとおり。シンプルである。
 project/

├── go_board.py (199行)　# 碁盤の初期化、石の配置、ルールチェック（石を囲み取る：連、そしてそれを囲むまで何手あるか「呼吸点」という考え方の導入、自殺手の禁止、その例外のコウ、セキなどの判定）、「ごけ」（取った石をいれる）の設定、「地」のカウント

├── go_typpes.py （30行）＃　Stone（白石/黒石/空点のEnum）、Player（プレイヤー情報）、GameMode（人対人 or 人対ボットの選択）。

├── bot.py （30行）　＃　ランダムボット、モンテカルロボット、（機械学習ボット）。

├── main.py (284行) 　＃　メインエントリポイント、
　画面遷移（Stage1：設定画面、Stage２：対局画面、Stage３：ダメ整理、Stage４：黒石画面、Stage５：白石整理、Stage６：勝敗決定）とそのためのボタンとクリック処理、　「待った」の設置

 実際の画面は。下記のとおりである。

Stage1：設定画面

![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676736/bd8ecc65-fdc9-4bcb-36cf-06e1abbf4f90.jpeg)
    ９路盤、１９路盤の選択 　先手、後手は、人と３種類のbotから選択

Stage２：対局画面

![２.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676736/12c4dfc4-ae8a-3569-9985-de977b05ec59.jpeg)


　待った、をできるようにあえてした（前にうった自分の石の上をクリックすると、 その手の前にもどる）。「待った」は実戦では認められないし、その人の成長を妨 げるかもしれない。しかし、練習では、「待った」により多くを学べると思うか らだ。
　終局は、ボタンをクリックした後、自動計算でなく、人力で決めることにした。 中国ルールのように「自分の地+自分の石の数」を計算すると自動化がしやすい とのことだった。だが、慣れ親しんだ、いわゆる日本ルール（「自分の地 のみ、計算）を採用したかった。するとプログラムが複雑になるので、ここは動 とした。
　既製の囲碁ソフトの中には、終局判定に中国ルールを使っているのか、あきらか に終局なのに、自陣に石をうちまくり碁盤を石で埋め尽くすものもある。だが、 どうもあれは好きになれない。
 
Stage　３：ダメ整理

![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676736/d1011e6e-0236-45f7-e6f5-4d8496b0c741.jpeg)

　前の画面での、「ダメ」が埋まっているのがわかる。 ここからは、手動となっている。
　囲碁を難しく感じる一番の理由は、終局がわかりにくい、ことだと思う。とった 地の大きさ、が大きいほうが勝ち、と聞いても、例えばまだ空白がたくさんある のに、そこは「地」なのか？そうでなくまだ打てるのか？わかりにくい。
　このゲームで、ダメ整理、黒番整理、白番整理をbotにまかせず、人がやること にしたことは、この終局になれることにもつながるかもしれない。
 
Stage４：黒地整理 

![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676736/d4969912-8fb6-58b2-99b8-0402e98ed651.jpeg)

黒地内にある、死んだ白石の上をクリックすると、その石は、ごけ、にはいる。 前の画面にあった、黒地内の白石が消え、ごけ、の数が増えているのがわかる。

Stage５：白地整理 

![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676736/45968f37-ccb6-8f7c-8826-46e0073f3199.jpeg)

白地内にある、死んだ黒石の上をクリックすると、その石は、ごけ、にはいる。 前の画面にあった、白地内の黒石が消え、ごけ、の数が増えているのがわかる。
そして、勝敗決定ボタン、を押すと結果（盤面の「地」－ごけ内の数）が自動計 算される。

 Stage６：勝敗決定 

画像![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676736/8b55dac8-4d11-8c8b-d746-6cb6615ec3a1.jpeg)

　アマチュアの囲碁は、「性格」でうつ。それが正しい。地が好きか？模様が好きか？好戦的か？すっぽかすことが多いか？あきらめが早いか？遅いか？など、対戦していると、その人の囲碁の癖がみえてくる。それが楽しい。もちろん、それは、その人の囲碁の性格であって、その人そのものの性格とは異なる。でも、少しそれも、想像できる。アマチュアはこれでよいと思う。
　だが、botと対戦するとその楽しみは消えてしまう。
　といっても、この時点で、このランダムボット、モンテカルロボットは「おおばかもの」で弱すぎて、ゲームにならないのだが。
　ここで、次の、機械学習をしたbotの導入は、ゲームとして面白くするには必須とおもわれた。

 
（２）機械学習をしたbotの導入
　機械学習をしたbot（思考エンジン）でPythonで書かれたものは（AlfaGoもそう？）主に、MiniGo,DLGo,TamaGo,Pyaqの4つだった。
 
　MiniGo,DLGo,TamaGoに関しては、そのＨＰをみると、思考エンジンを担うファイルはなんとなくわかったが、既に「学習すみのファイル」がどうしてもみつけられなかった。
　　https://github.com/tensorflow/minigo
　　https://github.com/maxpumperla/deep_learning_and_the_game_of_go
　　https://github.com/kobanium/TamaGo

　唯一、Pyaqについては、9ｘ9路盤のために初心者向けの解説のＨＰがあった。そこで、思考エンジン、「学習済ファイル」の入手ができ、なんとかつかえそうだった。
 https://github.com/ymgaq/Pyaq

 (参考)さらに、Pyaqで過去の棋譜（sgfファイル）を新たに学習させることは、わかりやすい解説もあったが残念ながらぼくにはうまくできなかった。
 https://colab.research.google.com/drive/1qTJY_0AfrtwiyGYnmd6PZweWw1zG7n33

 ここで、大きく違ったのは、まずファイル構造である。（１）の単純なものから、下記のように階層下された。
 project/
├── main.py　#エントリーポイント　今回は204行に
├── models/
│ ├── minigo_model/ # （Minigo を使わない場合、整理可能）
│ ├── pyaq_model/
│ │ ├── model.ckpt　# Pyaq のHPのmodelフォルダ内にあった
├── external_engines/
│ ├── minigo/ # Minigo のコード（必要に応じて保持/削除）
│ ├── pyaq/ # Pyaq に関連するコードをHPからここにコピペ
│ │ ├── _init_.py
│ │ ├── pyaq_engine.py # Pyaq 思考エンジンの統合コード
│ │ ├── board.py　
│ │ ├── gtp.py
│ │ ├── pyaq.py
│ │ ├── search.py
├── bots/
│ ├── _init_.py
│ ├── bot.py # ボットの共通インターフェース
│ ├── random_bot.py # ランダム Bot
│ ├── monte_carlo_bot.py # モンテカルロ Bot
│ ├── pyaq_bot.py # Pyaq ボット
├── game/
│ ├── _init_.py
│ ├── go_board.py
│ ├── go_types.py
│ ├── scoring.py
├── config/ # 設定ファイル
│ ├── default_config.json
└── requirements.txt # 必要ライブラリを記　(numpy>=1.18.0 absl-py)

 　修正はくりかえされた。
　 特に、ファイルの相互関係をしめす、コード　from～import～の修正には頭が混乱した。また、_init_.py（ _init_.py は存在するディレクトリをパッケージとして扱う。このファイルがないと、単なるディレクトリとして扱われ、パッケージとしての機能が利用できない）、requirements.txt（pip install -r requirements.txt で記載されたすべてのパッケージをインストールできる）などの、ぼくにとっては新しい知識も得た。 

だが、ずいぶんがんばったが、最終的に、python main.pyでは始動しなかった。でも、python -m main　とWindowsターミナルでうつと動くので、とりあえず完成したといえる。
だが、この差がなぜ起きるのか？ぼくには不明である。　

そして、ここでつくったpyaqボットは、まだまだ全然弱かった。あらたに、pyaqのlearnを使って、あらたな学習をしたファイルがつくれないぼくの現状があるため、いったんここで休止とすることにした。