稲庭戦法対策コードを公開

まず相手が稲庭戦法が判定します。自分でこの戦法を使うことはないと仮定しています。
Bonanza6のコードに近いです。

以下の定数のうちe_pawnは敵(後手)の歩の意味です。

u32 Search::detect_inaniwa_tactics(Tree* RESTRICT tree)
{
  // 初手から数えて20手過ぎている
  if ( 19 < tree->nrep )
  {
    if ( tree->root_turn == black
      // 後手側が稲庭戦法なのか?
	    && ( BOARD[A7]== e_pawn || BOARD[A6]== e_pawn || BOARD[A5]== e_pawn )
	    && BOARD[B7] == e_pawn && BOARD[C7] == e_pawn
	    && BOARD[D7] == e_pawn && BOARD[E7] == e_pawn
	    && BOARD[F7] == e_pawn && BOARD[G7] == e_pawn
	    && BOARD[H7] == e_pawn
	    && ( BOARD[I7]== e_pawn || BOARD[I6]== e_pawn || BOARD[I5]== e_pawn ) )
	  {
      return 2;
	  }

    if ( tree->root_turn == white
      // 先手側が稲庭戦法なのか?
	   && ( BOARD[A3]==pawn || BOARD[A4]==pawn || BOARD[A5] == pawn )
	   && BOARD[B3] == pawn && BOARD[C3] == pawn
	   && BOARD[D3] == pawn && BOARD[E3] == pawn
	   && BOARD[F3] == pawn && BOARD[G3] == pawn
	   && BOARD[H3] == pawn
	   && ( BOARD[I3]==pawn || BOARD[I4]==pawn || BOARD[I5]==pawn ) )
	  {
      return 1;
	  }
  }
  return 0;
}


上の判定で相手が稲庭戦法だと判明した場合は次の評価関数で加点します。

// 稲庭用の評価関数に加点するための関数
Score Eval::evaluate_inaniwa1( const Tree* tree )
{
  // 評価値は先手から見たスコアを返す。

  Score score = 0;

  BoardPosition sq;
  RBB bb;

  if (Search::inaniwa ==1)
  {
    // 先手が稲庭なので後手のなんかに加点。

    // 歩が手駒であることに対する加点
    // ともかく歩は切ろうぜ!!
    score -= (s32)Hands::Pawn(HAND_W)*60;

    // 桂馬が跳んでいることに対する加点
    // これせっかく交換した桂をまた打つんじゃなかろうか…。
    if (BOARD[C7]==e_knight) score-= 10;
    if (BOARD[G7]==e_knight) score-= 10;
    if (BOARD[D5]==e_knight) score-= 20;
    if (BOARD[G5]==e_knight) score-= 20;

    // 全部持ち歩に換えて、あとは桂馬飛んでおけばなんとかなるんでないの?
    // あとは銀か。前に行っている銀ほど価値を高くしよう。
    bb = RBB_WSILVER;
    foreach_RBB(bb,sq,{
      score -= ((s32)Attack::airank[sq])*4;
      score -= (5-abs(file5 - (s32)Attack::aifile[sq]))*2;
    });

    bb = RBB_WPAWN;
    foreach_RBB(bb,sq,{
      score -= (s32)Attack::airank[sq]*5;
    });
    // あとは勝手に飛車・角を利かせて、なんとかしてくれるに違いない…。

  } else {
    score += (s32)Hands::Pawn(HAND_B)*60;

    if (BOARD[C3]==knight) score+= 10;
    if (BOARD[G3]==knight) score+= 10;
    if (BOARD[D5]==knight) score+= 20;
    if (BOARD[G5]==knight) score+= 20;

    bb = RBB_BSILVER;
    foreach_RBB(bb,sq,{
      // 上の段ほど加点
      score += (8-(s32)Attack::airank[sq])*4;
      // 中央に近いほど加点
      score += (5-abs(file5 - (s32)Attack::aifile[sq]))*2;
    });
    // 歩も前進させているほど良いとする。
    // 銀より高い点数にしておかないと銀を前に進めて、歩越し銀になってしまう。
    bb = RBB_BPAWN;
    foreach_RBB(bb,sq,{
      // 上の段ほど加点
      score += (8-(s32)Attack::airank[sq])*5;
    });
  }

  return score;
}

これでなんとなくうまく行っている気がします。

ちなみに、加点を先手と後手と両方に対して対称的に加点しますと、駒得だけの評価関数ではせっかく歩を交換しても相手もその歩を手持ちにしてるからプラマイ0とみなされて、いつまで経っても歩を切ってくれません。

そこで稲庭戦法を使っていない側にのみ加点することにしました。ちょっとしたことですが、このことに気づくのに1時間ぐらい要しました。

上のコードは著作権を主張しませんのでご自由にお使いください。