Bonanzaの指し手生成ルーチン完全解読(7)

■ Bonanzaの指し手生成ルーチン完全解読(7)


今回は、一通り利きに関するマクロや関数の紹介が終わったのでis_pinned_on_black_kingの実装を読んでみる。


■ is_pinned_on_black_kingの実装


この実装は以下のようになっている。なお、ソース自体は私が少し手を入れている。
説明の代わりにコメントを読んでいただきたい。

// isquareにある先手の駒が、idirec方向にpinされているのか。
// この駒を動かすと先手玉を取られてしまうときtrue。
bool is_pinned_on_black_king( const Tree * restrict ptree, BoardPos isquare,
                        Direction idirec )
{
  u32 ubb_attacks;
  bitboard bb_attacks, bb_attacker;

  switch ( idirec )
  {
	// 横方向にpinされているなら、飛車によってしかpinされている可能性がないので
	// それだけ調べれば良い。
  case direc_rank:
    ubb_attacks = AttackRank( isquare );
    if ( ubb_attacks & (BB_BKING.p[aslide[isquare].ir0]) )
      {
				// RD = 飛と龍(rook & dragon)
        return (ubb_attacks & BB_W_RD.p[aslide[isquare].ir0]) !=0;
      }
    break;

	// 縦方向にpinされているなら飛車か香だろう。
  case direc_file:
    bb_attacks = AttackFile( isquare );
    if ( ( bb_attacks & BB_BKING ).ToU() )
      {
				// 香 + 飛龍
        bb_attacker =  (BB_WLANCE &  abb_minus_rays[isquare] ) | BB_W_RD;
        return ( bb_attacks & bb_attacker ).ToU()!=0;      /* return! */
      }
    break;

	// 斜め方向にpinされているなら角と馬だろう。
  case direc_diag1:
    bb_attacks = AttackDiag1( isquare );
    if ( ( bb_attacks & BB_BKING ).ToU() )
      {
				// BH = Bishop + Horse
        return ( bb_attacks & BB_W_BH ).ToU() != 0;          /* return! */
      }
    break;

		case direc_diag2:
    bb_attacks = AttackDiag2( isquare );
    if ( ( bb_attacks & BB_BKING ).ToU() )
      {
        return ( bb_attacks & BB_W_BH ).ToU() != 0;          /* return! */
      }
    break;

    default:
				// こう書いて心持ち高速化
        __assume(0);
  }
  return false;
}