Bonanza 56shogi 指し手生成
できました。
指し手生成祭り開催 - Bonanzaソース完全解析ブログを参考に、
局面は適当につくりました。
ちなみに、自殺手(1五玉)を生成していますが、
これは本家Bonanzaでも生成します。
詳しいことは指し手生成祭り開催 - Bonanzaソース完全解析ブログに書いてあります。
5M回ループを回して指し手生成関数を呼び出して、実行時間が3076msでした。
指し手生成の回数は、約1.62M/secということになりますが、
生成される手が指し手生成祭り開催 - Bonanzaソース完全解析ブログの局面は199手で、
ごーろく将棋 56shogi のこの局面は60手です。
本将棋の指定局面に換算するために、
1.62M回を単純に0.3倍( 60 ÷ 199 ≒ 0.3 )すると、
約0.486M/secになります。
指し手生成祭り開催 - Bonanzaソース完全解析ブログによると、
『この局面を素のBonanzaで計測してみましたが、
私の普段使っているマシン(Core2Duo2.8GHz)で、1.1M/secぐらいでした。
素のBonanzaからは多少改造してあるソースで測定したので
参考スコアということでお願いします。』
ということで、だいたい速度が半分になってしまっています。
いまつかっているノートPCが、Core2Solo 1.4GHzと、スペックが低いということと、
どの程度かわかりませんが改造してあるソースということなので、
参考スコアが素のBonanzaより少し早くなっているのかもしれません。
(だったらいいな)
それにしても遅い気がしますが。うーむ。
ビットボードが3つから1つに減っているのですが、
(5×6=30マスで、32bit整数型1つにおさまる)
どうしても増えてしまう処理があります。
例えばということで、先手の角が移動する手を生成する関数のソースを引用します。
厳密にいうと、角が移動する手の中で、
1.中段までの移動(成ることができない移動)で駒をとる手
+
2.駒をとる手もとらない手も含む、駒を成る手(敵陣への移動 or 敵陣からの移動)
を生成します
Bonanza (gencap.c)
bb_piece = BB_BBISHOP; while ( BBTest( bb_piece ) ) { ifrom = LastOne( bb_piece ); Xor( ifrom, bb_piece ); AttackBishop( bb_desti, ifrom ); bb_desti.p[0] &= bb_movable.p[0]; if ( ifrom < A6 ) { bb_desti.p[1] &= bb_movable.p[1]; bb_desti.p[2] &= bb_movable.p[2]; } else { bb_desti.p[1] &= bb_capture.p[1]; bb_desti.p[2] &= bb_capture.p[2]; } while ( BBTest( bb_desti ) ) { ito = LastOne( bb_desti ); Xor( ito, bb_desti ); utemp = ( To2Move(ito) | From2Move(ifrom) | Cap2Move(-BOARD[ito]) | Piece2Move(bishop) ); if ( ito < A6 || ifrom < A6 ) { utemp |= FLAG_PROMO; } *pmove++ = utemp; } }
56shogi
bb_piece = BB_BBISHOP; while ( BBTest (bb_piece ) ) { ifrom = LastOne( bb_piece ); Xor( ifrom, bb_piece ); AttackBishop( bb_desti, ifrom ); bb_desti_a = bb_desti & bb_movable & bb_w_position; bb_desti_b = ( ifrom < A4 ) ? bb_desti & bb_movable & ~bb_w_position : bb_desti & bb_capture & ~bb_w_position; bb_desti = bb_desti_a | bb_desti_b; while ( BBTest(bb_desti) ) { ito = LastOne( bb_desti ); Xor( ito, bb_desti ); utemp = ( To2Move(ito) | From2Move(ifrom) | Cap2Move(-BOARD[ito]) | Piece2Move(bishop) ); if ( ito < A4 || ifrom < A4 ) { utemp |= FLAG_PROMO; } *pmove++ = utemp; } }
Bonanzaではp[0]が後手陣、p[2]が先手陣になっていまして、
敵陣/自陣の区別が容易です。
56shogiでは、
bb_w_position(後手陣だけビットが立っているビットボード)を用意して、
それと論理積をとっています。
こういう処理があるので、ビットボードが1つになっても、
それほど高速にならないだろうなと思っていたのですが、
それにしても半分は遅いような気がします。ぐぬぬ。
もしかしてもしかして、unsigned short int( 16bit )3つの構造体を用意して、
下位10bitだけつかって上位6bitは余らせる、
なんてことをしたほうが高速だったんでしょうか。
それならソースをほとんど書き換えなくてよくなるんですが。ぐぬぬぬぬ。
とりあえず、bb_w_positionのビットを反転させたビットボードを
あらかじめ用意しておくようにすれば、
ビット反転の処理が省略できるので、
少し速度がマシになるでしょうか。
とにもかくにも、指し手生成ができるようになったことは、とてもうれしいです。
去年のいまごろ、Windows付属のメモ帳でプログラミングをはじめたころは、
Bonanzaのソースを読んで、書き換えるなんて想像もしていなかったので。
ちなみに、いまは王手を生成する部分(genchk.c)を書き換えてます。
しばらくは、王手生成、王手回避手生成、1手詰ルーチン、3手詰ルーチンを
書き換えることになると思います。
5×6将棋盤でのrotated bitboardの実装方法というか、
Bonanzaのどの部分を書き換えたかという記事を、いま書いているのですが、
きちんと書こうとすると、とても長くなりそうで参ってます。
ぼちぼち、ゆっくり書いていこうと思います。
それでは。