euphonictechnologies’s diary

Haskell超初心者の日記です。OCamlが好きです。

follow us in feedly

Haskellで将棋 - プログラムの外観をみてみる

将棋ぶらうざQで対局をしてみた

Gyazoというサービスがあるのでそれを使って対局の模様をGIFアニメにしてみた。

http://i.gyazo.com/8e623aa8ffb4c4e743bff50c8ff3750e.gif

(このサービスすぐアップロードしてくれて便利。)

将棋ぶらうざQはGUIの完成度は高いし、Haskellの将棋プログラムも動かすことができたので、これで開発に専念できそうだ。

Haskell将棋の外観

ysnrkdm/hamilcar · GitHub

第21回世界コンピュータ将棋選手権のアピール文書用のプログラム - ながとダイアリーをベースに書かれたHaskell将棋は今のところこのリンク先に掲載されているコードを整形してモジュールに分離して少々のリントエラーを修正した程度なので、ほぼロジックはいじっていない。 ロジックのコーディングに入る前に外観を捉えておこうと思う。

エントリポイントから順にたどる

プログラムのエントリポイントは当然Main.hsだ。Main.hsはすぐに制御をUsi.hsに渡す。ここがmain loopになっている。

usiLoopという関数がmain loop関数で、positionコマンドでボードを作りgoコマンドで手の探索と評価を始める。 Search.hsminmax関数が探索と評価のエントリポイントになっていて、探索結果とPVを返す。

PVはprincipal variation、主な変化のこと。日本語に直すと「読み筋」といったところか。感覚的には、あらゆる合法手が次の手としては考えられるけど、普通だったらそうはしないよね、というものを除いていった残りというか、普通だったらこう指すよね、というのは主な次の展開、principal variationになる。多分コンピュータチェス用語。

Search.hsminmaxがやっているのは引数depが0になるまですべての合法手を生成して、その手に対して次の合法手をすべて生成していって、最後にその合法手の末端局面(一番あとの局面の集合)のすべてをeval関数で評価する。

Eval.hsは局面の評価戦略を実装したモジュール。呼ばれる関数はevalのみ。 evalは

eval :: Board.Bd -> Va
eval bd = matVa bd + bonaVa bd

とあるように、小回りの評価とボナンザ評価の足し算になっている。ボナンザ型の評価をするためにfv.binを読み込むことができるようになっている。

小回りの評価関数は

matVa (Board.Bd _ hs co _ pcl) = co == Piece.B |-> negate $
    sum [pcVa pc * hs ! pc | pc <- Board.bothHsRa] + sum[pcVa pc * length(pcl ! pc) | pc <- Piece.pcRa]

pcVa :: Piece.Pc -> Va
pcVa = (!) $ listArray Piece.pcBnd (a ++ negate `fmap` a)
    where
        a = [100, 430, 450, 640, 690, 890, 1040, 15000, 420, 530, 540, 670, -1, 1150, 1300, -1]

であり、Piece.hsには

pcBnd = (Pc B Unp FU, Pc W Pro OU)

とある。ここを読み解くのを次回までの宿題としたい。