オセロAI世界大会で優勝した話

オセロAIを作り続けて早3年半、一通のメールが来ました。オセロAIの大会を2024年12月8日に開催すると言うのです。メールの送信者は世界最強格オセロAIの作者でした。

**オセロAIの大会。面白そうじゃないか…！！**

---

話は3年前に遡ります。

私はふとしたきっかけでオセロAI、つまりオセロにおいて強い手を探すプログラムを書き始めました。それで半年かけて常設のコンテスト[CodinGame Othello](https://www.codingame.com/multiplayer/bot-programming/othello-1)で**世界1位になりました**。

不思議なことで、世界1位になっても飽きることなく、かれこれ**3年半もオセロAIを作っています**。その結果、オセロAIの強さでは世界最強格になれたと思っています。また、オセロAIを作っているうちに「オセロというゲームは楽しいのでは？」と気付き、人力でオセロを打つようにもなり、最近1級を取りました。

現在では自作のオセロAIを**オセロ研究用ソフト"Egaroucid" (えがろーしっど)として公開**していて、累計ダウンロード数14000を突破するなど、(オセロ専用ソフトとしては)かなり多くの方に使っていただいています。
![app_ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/5b82e248-1564-a0c4-afa7-9470fe81a7a2.png)

https://www.egaroucid.nyanyan.dev/ja/

3年もずっと開発を続けているので、私のオセロAIも次第に知名度を増してきました。[GitHubレポジトリ](https://github.com/Nyanyan/Egaroucid)のスター数は110を突破し、世界オセロ連盟のWebサイトに[Egaroucidの紹介記事](https://www.worldothello.org/news/354/egaroucid-an-othello-app-review)を書いていただいたこともありました。

---

そんなわけで、海外のオセロAI開発者の目に留まったのでしょうか。オセロAI大会のお誘いをいただいたわけです。





# 大会会場が生きた化石だった
大会会場は2000年前後に活発に動いていたというサーバ"[Generic Game Server](https://skatgame.net/mburo/ggs/)"、通称GGSです。最近でも動いているようですが、**サーバ本体以外のメンテナンスは滞っている**ようです。

このサーバと接続する公式のGUIアプリが提供されているのですが、**2006年で更新が止まっており、私のPCでは動きませんでした**。まずはこのアプリを動かすところから始めます。大変…
幸いにも、このGUIアプリはJavaのコードが公開されており、手元でいろいろいじることができました。ですので、コンパイルしてみてエラーを確認し、一つずつエラーを修正していきました。**Java書いたことないよ～と言いながら、やけくそでググりながら修正**したら動きました。めでたい！！ ~~最近だとこういうのはChatGPTの力を借りるものなんでしょうが…~~
↓修正して無事動いたGUIアプリ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/c9b94c62-5000-d219-beda-f78e86b29309.png)

また、**オセロAIとサーバをつなぐスクリプトも書かなくてはいけません**。サーバのREADMEを頑張って読みながらコマンドの仕様を理解して、どうにかこうにか**突貫工事でスクリプトをPythonで書きました**。こういう突貫工事にはPythonが便利だと勝手に思っています。




# 時間配分アルゴリズムを考えた
とりあえずサーバと通信できるようになったは良いものの、まだ大会に出るにあたってやるべきことがあります。それが時間配分です。詳しくは後述しますが、大会では**決められた持ち時間を自由に使ってオセロAIを動かします**。人力オセロでも持ち時間を使って対戦するのですが、AIでも人力でも、とにかくこの時間配分が難しいのです。

オセロは60手以内に必ず終局するということが確定しています。また、最後の30手程度は完璧に読み切ってしまいます。ただ、統計をとってみたところ、完璧に読み切る時間は**同じ読み手数でも計算時間に100倍程度のばらつきがある**ようでした。これはしんどい…。というわけで、どのタイミングで完全読みをするかを決めるのがかなり大事になってきます。

完全読みタイミングについては、残り時間の情報を使って何手を完全読みするかの見積もりを立てるアルゴリズムを考えました。考えたとは言っても、**統計から時間と残り手数の関係を雑にモデル化**しただけですが…
↓完全読み深さと訪問ノード数の関係を調べたグラフ(100倍くらいの範囲でバラつく)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/a69ee485-d13c-c27d-d741-348085c628c9.png)


さらに、オセロでは「**こんなのこの手を打つ以外ありえない**」という局面や、「**これはどっちが正解だ…？**」となる局面があります。前者は深く悩まずにとりあえず良さそうな手を打って時間を温存したいですし、後者は時間をかけて考えたいです。
この実装について考えていたとき、ちょうど[ゲームAI関連の学術イベント](https://www.gi-ipsj.org/gpw/2024/)がありました。ここには日本中から将棋AIをはじめとした様々なゲームAI開発者が集います。ちょうど良いタイミングだったので、雑談タイムで**囲碁AI開発者に時間配分について質問してみました**。囲碁AIとオセロAIは根本的にアルゴリズムが全然違うのですが、時間配分の考え方を聞けたのが幸運でした。**囲碁AIのやり方を(原型がないほどに)大胆にアレンジ**してオセロAIに組み込んでみたら、うまく簡単な局面と難しい局面を見分けてくれるようになりました。

このあたりのアップデートを短期間で集中してやったので、GitHubのContribution数が大会直前の1週間だけとんでもないことになりました。最大で1日に75コミットしていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/74844323-e815-985b-70ee-0571356ede3a.png)







# ルール
さて、ここでやっと大会のルール説明をします。

8×8の通常のオセロ盤を使い、**ランダムに18石を置いた状態**から打ち始めます。
↓ランダムな初期配置はこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/cf0ab8d4-62df-2f30-0d6f-d756bc88642c.png)

そもそも、オセロは通常の初期配置が**2023年に弱解決された**と報告されています。初期配置から辿れる進行はかなり解析され尽くされていて、局面ごとに(ほぼ確実な)最善手があらかじめ求められている状態です。そのため、通常の初期配置から対戦しても、オセロAIの真の強さを計測することはできません。ですので、ランダム配置から開始するのです。
↓オセロの通常の初期配置
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/3fcf2ea1-2fa9-ea43-476e-86b8d78c04a3.png)

しかし、ランダム配置だと配置によっては形勢が大きく傾いてしまっていることがあります。そのため、対戦する2つのオセロAIがそれぞれ黒番と白番を両方持ち、**2つの対局で得た合計の石数を競います**。
例えば初期配置が少し白番有利に傾いていた場合、2つの対局の結果が以下のようになったとします。
1. 黒(Aさん) 30石 - 白(Bさん) 34石
1. 黒(Bさん) 28石 - 白(Aさん) 36石

もともとのランダム配置が白有利だったので、どちらの対局も白の勝ちでした。ただ、2つの対局で獲得した石の枚数は、Aさんが66石、Bさんは62石です。これによって、Aさんの勝利となります。

対局は**8分持ち**(それぞれのプレイヤが8分の時間をうまく使って打っていく)で、総当たり戦を2回行ってランキングをつけます。また、使用できるリソースは8スレッドが上限とされました。





# 大会本番
これ以上ないほどに緊張していました。**2、3週間くらいかけて突貫工事で必要な機能を作った**のですから、そもそもうまく動くかどうかすらわかりませんでした。大会主催者に「私のAIが打てるコマンドはこれだけだけど大丈夫そうですか？」など連絡をして、大丈夫そうなことを確認しつつ当日を迎えました。

## 参加者
参加者は、以下6つのAIです。
- **[Egaroucid](https://www.egaroucid.nyanyan.dev/ja/)**…私のオセロAI
- [Edax](https://github.com/abulmo/edax-reversi)…私が非常に参考にしているオープンソースオセロAI。世界最強格
- revimhello…私はあまり存じ上げないのですが、とても強いオセロAI
- [Roxane](http://hcyrano.free.fr/index.html)…世界最強格のオセロAI
- [Logistello](https://skatgame.net/mburo/log.html)…1997年に人間の世界チャンピオンを戦って6戦6勝した当時最強のAI
- Logistelloの1手読み版…Logistelloの先読みを1手に制限したもの

つまり、世界最強格が揃っているというわけです。どきどきです。

## いざ対戦
参加者6人で総当たり戦を2回やるので、全部で10回戦あります。
Egaroucidは**総当たり戦が1回終わった段階で暫定1位**となっていて、さらにどきどきでした。
↓尊敬するオセロAI Edaxとの対戦！EgaroucidはegrcdというIDで参加しています。
![GeSI51ZaYAAk6M0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/4398131f-ac3d-9018-c326-c6f9d5362e64.png)

総当たり戦の後半では、**一時Egaroucidが唯一の無敗**になっていました。しかし、最終戦で負けて1敗となりました。**最終戦の相手と優勝争いをしていた**わけですが、ここで負けたことで1位は取れませんでした。
↓最終戦、唯一の敗北…！
![GeSnU_PbEAA0lRg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/dcd73516-b4d1-9acb-3d41-7987b3ef332c.png)



## 対戦結果
1. revimhello 7勝1分2敗
1. **Egaroucid** 5勝4分1敗
1. Roxane 5勝3分2敗
1. Edax 4勝5分1敗
1. Logistello 2勝1分7敗
1. Logistello 1手読み 0勝0分10敗

revimhelloの優勝…！ と、思いきや、なんとrevimhelloが失格になってしまい、繰り上がって**私のEgaroucidが優勝**でした！！！

なんだかびっくりですが、優勝嬉しいです！



# オセロAIの未来
強さを争う大会に出ておいて言うのもどうかという話ですが、これからのオセロAIに求められるのは、強さではなく、「**人力オセロを面白くすること**」だと思っています。

オセロAIが絶対的な正解で、それを外れたら不正解…、オセロはそんな単純な世界ではありません。
人間は当然完璧ではありませんが、だからこそ「実は自分が若干辛いけど、でも相手にとって難しい局面にして相手のミスを待つ」といった戦法が使えます。これが人力オセロの奥深さだと私は考えています。

人間っぽい打ち方をするオセロAI、人間のような考え方をして、それを説明してくれるAI、などなど、やれることはいっぱいありそうです。ただ、なかなかこれが難しくて進まないのです…。だからこそ面白いのですが。

**人力オセロの奥深さを引き出せる**ような、面白いオセロAIを作りたいな…と思いながら、今日もキーボードを叩いています。次回のオセロ研究ソフトでは人力オセロを支援する新機能をまた追加予定です！