バックギャモンをブラウザで遊べるページを作りました。
インストールも登録も不要です。PC のブラウザで開けばすぐ始められます。
ルールを知らないまま、最後まで遊べます
バックギャモンは面白いゲームですが、最初の壁が高い。駒の進む向き、止まれない場所、バーからの復帰、あがり方。覚えることが多く、しかも「使える目は可能な限り全部使わなければならない」といった、初心者が知らないうちに違反してしまう規則まであります。
そこで今回は、ルールを一切知らない人が最後まで 1 局を終えられることを最優先に作りました。
仕掛けは「スマートガイド」です。盤の上に、今すべきことだけが印で示されます。
- オレンジのリング … いま動かせる駒
- 点線の丸 … その駒を置ける場所(駒を選ぶと出ます)
- 緑のリング … おすすめの手
オレンジが付いた駒をクリックして、点線の丸をクリックする。これだけです。印が付いた場所を選んでいる限り、ルール違反は原理的に起こりません。「使える目は全部使う」「片方の目しか使えないなら大きいほうを優先する」といった厄介な規則も、ガイドの段階で除外済みです。
盤の下には日本語のナビが常に出ていて、「相手の駒をヒットしました」「1 個あがりました」と、そのつど何が起きたかを説明します。コンピュータの着手も 1 手ずつ間を置いて再生するので、何が起きたのかを目で追えます。
迷ったら緑の印を選んでおけば、まず間違いありません。そうやって何局か遊んでいるうちに、なんとなくルールが分かってくる ― という順番を狙っています。
なお、ダブリングキューブは意図的に載せていません。初心者が最初につまずくところなので、まず対局そのものを楽しんでもらう作りにしました。
コンピュータは 5 段階
初級・初中級・中級・上級・エキスパートの 5 段階です。初級は目に見えて手を緩めますし、上級以上は相手の出目 36 通りをすべて読んで指します。自己対戦で測ると、中級は初級に 78%、エキスパートは初級に 83% 勝ちます。
サイコロはどのレベルでも公正な乱数です。コンピュータが都合のいい目を引くことはありません。
ここから先は、作ってみて分かったことの記録です。遊ぶだけなら読まなくて大丈夫です。
盤面は「手番側を必ず白」にする
バックギャモンは互いに逆向きに進むので、素直に書くと同じ処理を 2 通り書くことになります。そこで、盤面を常に「手番側=正の数」に正規化し、相手の手番では盤を反転してから同じ関数を呼ぶようにしました。
mirror(p)[i] = -p[25 - i]
これだけでルールも評価関数も片側の 1 通りで済みます。コード量とバグの発生源がまるごと半分になりました。副産物として、評価関数が数学的に反対称(evaluate(p) = -evaluate(mirror(p)))であることをテストで保証できます。
合法手は 1 手ずつでは決まらない
「使える目は可能な限りすべて使う」というルールのせいで、ある 1 手が合法かどうかは手番全体を先読みしないと判定できません。先に小さい目を使ったせいで大きい目が使えなくなる、ということが起こるからです。
ここで実際にバグを踏みました。探索のメモ化キーに「残りの出目列」を入れ忘れていて、出目の順列 [6,4] で訪れた局面が [4,6] でも「訪問済み」と判定され、2 番目の順列がまるごと探索されずに終わっていたのです。
症状は「バーから復帰したあと、本来使えるはずの目が消える」。6 では入れないが 4 でなら入れて、入った後なら 6 も使える ― という局面で、4 を使った瞬間に手番が終わってしまいました。
AI は自作の評価関数
GNU Backgammon が使う戦略指標(ブロットの被弾率、プライム、アンカー、ピップ差)を参考にしつつ、評価関数は JavaScript で書き起こしました。gnubg の学習済みニューラルネット重みは移植していません。数百 KB から数 MB になることと、GPLv3 の適用範囲を検討する必要があるためです。
いちばん手こずったのはベアオフ
盤に載せてしばらく遊んで、駒上げ(ベアオフ)がどうにも下手なことに気づきました。上げられる駒を上げずに、盤の中で駒を動かし回っているのです。
原因は評価関数でした。相手と接触がなくなったレース局面を、ピップ数(ゴールまでの残り距離の合計)だけで測っていたのです。
3 ポイントの駒を上げる → ピップ −3
6 ポイントの駒を 3 へ動かす → ピップ −3 ← 同点になってしまう
駒を盤から取り除くこと自体の価値が、評価にまったく入っていませんでした。
正しい尺度は「あと何回振れば全部上げ切れるか」です。そこで検証のために、相手が干渉できないベアオフについて期待ロール数を厳密に動的計画法で解きました。自陣 6 ポイントに 15 個以下を並べる全分布、54,263 局面ぶんです。この正解値に近似式をフィットして評価関数に組み込んだところ、最適手との一致率が 47% から 91% に上がりました。
ついでに分かった、ベアオフのセオリー
せっかく厳密な正解データがあるので、よく言われるセオリーを 1 つずつ検証してみました。
| よく言われるルール | 実際の正解率 |
|---|---|
| 上げられる駒はとにかく上げる | 99.1% |
| 高い位置の駒から動かす | 51.7% |
「とにかく上げる」はほぼ常に正しい。一方「高い駒から動かす」は、ほぼコインフリップでした。
正しいのは「穴を作らない・同じポイントに積み重ねない」です。こちらを優先順位の 2 番目に置くと、最適手との一致率が 81% から 89% に上がります。
理由は単純で、同じポイントに 2 個積むと、その 2 個を上げるにはそのポイント以上の目が 2 つ必要になるからです。散らばっていれば、別々の目で 1 個ずつ処理できます。
配置 5ポイントに2個・6ポイントに1個 出目 1-5
高い駒から : 6/5 5/off → 5ポイントに2個残る 期待 1.915 ロール
最適 : 5/4 5/off → 6と4に散る 期待 1.850 ロール
わずかな差ですが、積み重なると効いてきます。
構成
ゲームのロジックも AI も描画も、すべてブラウザ側の JavaScript で完結しています。サーバー側の実行環境には一切依存しません。
実体は 45KB の HTML ファイル 1 つ(gzip 後 15KB)です。使っているレンタルサーバーの公開ディレクトリに、そのファイルを置いただけで動いています。外部への通信は Google Fonts の読み込みだけなので、一度開いてしまえばオフラインでも遊べます。
遊んでみてください
PC のブラウザ向けです(スマートフォンのレイアウトは未対応)。まずは「中級」あたりから、緑の印を頼りに 1 局どうぞ。
