56将棋開発ブログ

5×6マスのミニ将棋、「56将棋」で遊べるものをいろいろ開発してます。

Bonanza 56shogi 指し手生成

できました。

f:id:tetsuzuki1115:20140905085641p:plain


指し手生成祭り開催 - 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のどの部分を書き換えたかという記事を、いま書いているのですが、
きちんと書こうとすると、とても長くなりそうで参ってます。

ぼちぼち、ゆっくり書いていこうと思います。

それでは。