20183三将棋アプリのソース公開しました3三将棋アプリもそろそろ安定してきたと思うのでソースをgithubに公開しました。Bonanzaを始めとする優秀な将棋ソフトをカスタマイズしようとは思わないけど、CoffeeScript(JavaScript)で将棋ソフトが作れるならやってみようと思う人はいるかも知れないと思ってます。プログラミングには興味ないけど9マス将棋の正解を知りたいと思う人は結構いるかもしれないと思ったので記事を書いてみました。詰みがある場合は別ですが、ここで示す方法で得られた解答が必ず最善手だとは言い切れないことには留意してください1。ちなみに最近9マス将棋オンラインというアプリで遊んでいるのですが、単純な配置でも未だに最善手が何か悩まされることがあります(特に入玉形の場合が難しい)。いう時スクショを取ってこの記事の方法で何が最善手だったか検討したりしています。追記:3三将棋アプリはVersion1.0.5.0からCSA形式(*.csa)の棋譜の入出力に対応しましたので、CUI(コンソール画面)でコマンドを入力しなくてもアプリを使って自由に初期配置を編集出来ます。やり方については3三将棋アプリの記事を参照してください。テスト環境9マス将棋の解答を得るために必要なものはgithubリポジトリ内のファイルとCoffeeScriptのインストールだけです。編集する必要があるのはCUIテスト用スクリプトファイル(game.coffee)だけです。CoffeeScriptのインストールに関しては環境に依りますので省略します。将棋盤に駒を配置するにはBoardクラスのpiecesメンバに駒をpushしていくのですが、コピペして書き換えれば簡単だと思います。[3,3])としてPieceクラスのインスタンスを生成してBoardオブジェクトのpiecesメンバにpushします。上記の初期配置をセットするコードは以下のようになります。Fu先手・後手、駒の状態(不成、成、持ち駒)の区別は以下の定数を使用します。読む深さの指定Playerクラスのdepthプロパティに読む深さを指定します。0になるまで局面を先読みしますので6を指定すると7手読みになります。6を指定しないと解けないかというとそういうわけでもなくて、それ以下でも詰み手順を正確に辿っていくこともあります。2二金、1三玉、2三金)ですが、depth=3(4手読み)の設定でも正確に詰み手順を辿ることができます。読み切れていなくても最善手を指せるかどうかは評価関数の巧拙にかかっています3。後手の駒の重みの合計)という非常に単純なものですが、9マス将棋ならこの程度の評価関数で十分だと言えるでしょう。以下の表のように先手が大文字、後手が小文字のアルファベットで将棋の駒を表現します。T(t)上記の配置はgithubに置いてあるgame.coffeeの初期配置です。game.coffeeと打てば以下のように対局が進行するはずです。Winこれじゃぁ分かりにくいという方も多いと思いますがすぐ慣れます。それか、ある程度結論が得られたら初期配置のコードをgameGui.coffeeに移してトランスパイル(webpackとコマンドを打つだけです)してブラウザで確認するのもいいかもしれません。ブラウザであまり深読みさせると応答しなくなる可能性があります。Const.MAX_VALUE)と呼び出した場合temp[2]に評価値が入っています。temp[2]に最大値(50000)か最小値(-50000)が入っていれば勝ち(あるいは負け)を読み切った(詰みを発見した)ということです。前述の単純な静的評価関数によって指し手を選んだだけなのか、詰みを読み切った上でその手を選んだのかはここで判断出来ます。7で実行すると3一飛と打たれた後の後手番での先読みメソッドの戻り値を見ると、1二玉が最善だと返してきますが、評価値は-18(後手やや有利)になっています。1二玉と指せばやや有利になりますよと言っているだけで、AIは後手の勝ちだとはわかっていません。8にすると1二玉が最善手で評価値も-50000(後手勝ち)と返してきます。8は9手読み)ですので辻褄が合います。このように詰みを発見した上での最善手と、単なる評価関数による最善手は意味合いが全然違うので注意が必要です。詰みがない場合の最善手というのは読みの深さを変えたら変わる可能性があるのに対して、詰み発見後の最善手は絶対不変4の正解手です。この辺の事情は有名な将棋ソフトでも同じことで、読む深さを決めてその手数で詰みが見つからなかった場合は、そのソフトの評価関数を使った最善手というだけの話で客観的に絶対正しい最善手というわけではありません。それでも近年は人間の判断より正確なようですが。8をセットしてAIの評価値が最大値(50000)または最小値(−50000)が返ってこない場合は7手以内の詰みは存在しないという言い方も出来ます。全件探索ということは読む深さを深くする(depthの値を大きくする)と読む局面の数は指数関数的に増加しますので、いくらハイスペックなPCを使っても十数手しか読めないと思います。しても長手数の詰みも確認したいという方は、このソースコードを他のコンパイル言語に移植したりするより、まず将棋盤をビットパターンで表現する手法を取っている他のやり方を探る方がいいと思います。自分はそこまでやろうとは思ってませんけど、このアプリをReactNativeに移植したらどれぐらい速度アップ出来るのか興味を持ってます。有名な将棋ソフトを9マス将棋に対応させるのはそれなりに大変だと思いますが、どうしても9マス将棋の正解を得たいという人は、あの「どうぶつしょうぎ」を完全解析した人のソースコードを改変する方法があるようです。それもまた簡単ではないと思いますが...。前回の記事にも書きましたが玉を取るところまで読まないといけないので、1手詰めの問題を解くには3手読み、3手詰めの問題を解くには5手読みが必要となります。↩これは9×9の本将棋のプログラムでも同じことですが、完全読み切りが出来るのであれば静的評価関数は先手勝ち(+1)か後手勝ち(−1)かそれ以外(0)の3値を返すだけの単純なものでいいのですが、完全読み切りが出来ないので世のプログラマが苦心して評価関数の出来を競っているわけです。詰み手順が複数ある可能性はあります。