Bonanzaの王手になる指し手生成のバグについて

で、その後は香車の移動先が敵陣かどうかを判定せずに、
香車の成りの手を生成しています。
FLAG_PROMOが成りを表しています。

Bonanzaの王手生成(buoyance)
http://d.hatena.ne.jp/hiraoka64/20110923/1316747966


そういや、私もそれBonanza 4.12のときに気づいて、ああ、このまわりのコード、ひどいなーと思いながら、IsDiscoverBKマクロとかを追加する前に書いたコードだからこんなにひどいんですかねぇとか保木さんに雑談(?)してたら、すっかり本題であるその部分のバグ報告をすることを忘れていました。


それで、その部分のバグに関連して、その平岡さんが引用されている部分のコードが何故ひどいのかもう少し具体的に説明します。

      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
      bb_chk.p[1] = bb_chk.p[2] = 0;

      idirec = (int)adirec[sq_wk][from];
      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
        {
          add_behind_attacks( &bb_chk, idirec, sq_wk );
        }

      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
      BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
      BBAnd( bb_chk, bb_chk, bb_move_to );

adirec[sq_wk][from]の部分は、sq_wk(後手玉)とfrom(先手の香)との位置関係を示しています。このテーブルは縦・横・斜 の関係になければ、0 になります。


is_pinned_on_white_kingってのは、fromにある駒をどけたら後手玉に先手からの王手がかかるかという意味です。


要するに、後手玉と先手の香が縦・横・斜めの関係にあるときに、この香をどけて空き王手にならないかを判定しているわけですね。


bb_chkは、香の移動先の候補です。香を成る手のみをここでは生成しますから、成れる場所かつ、後手玉の地点に後手の金を配置して、その金の利きのある場所が第一候補です。引用部のプログラムの先頭2行はそういう意味です。


add_behind_attacksについても説明を要しますね。behindは影(の利き)という意味です。先手の駒Xの影に先手の角や飛車のような遠方に利く駒が配置されているとして、この駒Xをどこに移動させると空き王手になるのかを求めるための関数です。


駒Xを、現在の後手玉と駒Xとの位置関係(縦・横・斜)とは違う位置関係になるところに移動させれば空き王手になりますね。例えば後手玉と駒Xとが同じ筋にいるなら、駒Xをどこか違う筋に移動させれば空き王手になります。


add_behind_attacksの引数としてbb_chkのアドレス , idirec, sq_wkを渡していますが、sq_wk(後手玉の位置)から、idirecの位置関係以外になる場所をbb_chkに追加するという意味です。


そのあと、次のようにしています。

  BBAnd( bb_chk, bb_chk, AttackFile( from ) );
  BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
  BBAnd( bb_chk, bb_chk, bb_move_to );

AttackFileは飛車の利き。abb_minus_raysは盤面の上方向への利き。bb_move_toは自駒(先手の駒)のない場所。要するに、bb_chkに行き先候補が求まったので、そのなかで先手の香の行ける場所を絞っているわけですね。


さて、問題です。このアルゴリズムのどこがそんなに無駄なのでしょう?



正解は明日発表します。