改造しても・・

今日一日かけてやっていた改造の結果が、自己対戦において全く強くなっていないことがさきほど判明しまして、今日は枕が大量に濡れそうです。(おねしょではありません)

だいたいにして評価関数を改良して棋譜からの学習に1ヶ月程度要して、自己対戦で勝ち越したからと言って嬉々としてfloodgateに投入したらむしろ対Bonanza系のソフトの勝率が下がっていて、以前より低いRがつくだなんてことは珍しくもないはずであり、よく他の開発者の人たちは心が折れないなぁとそのただならぬ忍耐力に頭が下がります。

コンピューター将棋の開発には、天才とか秀才とか呼ばれるようなそういう頭の良さはあるに越したことはないでしょうが、しかしそれとは別次元の、忍耐とか根性とかやる気とかモチベーションとか、そういうもののほうが案外大事なんじゃないかと思わずにはいられません。

Bonanza6からKKPテーブルを抜き出す方法(決定版)

Bonanza6でKKPのみ有効にするのはなかなか簡単ではありません。
何故なら、KPPのほうにもKKPの値が紛れ込んでいるからです。

例えば、KPPの一つ目のPをP1,二つ目のPをP2と表記するとして、P1 = 盤上の駒 , P2 = handの値を加算しておく必要があります。手駒は0枚としてみなして構いません。

KKP1 += KP1P2 (P1 = 盤上の駒 , P2 = それぞれの手駒 , 枚数は0枚。)

ですね。

そのあと、KKPのPがhandのときに、KPPのP1 = hand , P2 = handという場合の値も加算しておく必要があります。

KKP1 += KP1P2 (P1 = 手駒 , P2 = P1以外のそれぞれの手駒 , 枚数は0枚。)

あとKPPは同じ駒同士のPPも計算しています。(おそらく学習を容易にするため。) これらはKKPの値に持ってこなければなりません。

すなわち、
KKP1 += KP1P1 (P1 = 盤上の駒および手駒)
ですね。

私はこれらのことに気づくのに何日もかかりました。

以上のようにKKPのテーブルをKPPのほうの値を参照しながら修正するソースコードおよび、KKPの値を計算するソースコードを以下に貼りつけておきます。皆様のお役に立てれば幸いです。

void Eval::setup_bona6_kkp()
{

  // KKPのPを評価するときに手駒0に対するPになっていないと評価値がおかしいのではなかろうかという疑問

  PieceKPP list0[52], list1[52];
  BoardPosition sq_bk, sq_wk;
  Score sum = 0;
  Score score = 0;

  // tree_macroを使うためのトリック
  Tree tree0;
  Tree* tree = &tree0;
  HAND_B = 0;
  HAND_W = 0;

  list0[ 0] = BonaEval::f_hand_pawn   + Hands::Pawn(HAND_B);
  list0[ 1] = BonaEval::e_hand_pawn   + Hands::Pawn(HAND_W);
  list0[ 2] = BonaEval::f_hand_lance  + Hands::Lance(HAND_B);
  list0[ 3] = BonaEval::e_hand_lance  + Hands::Lance(HAND_W);
  list0[ 4] = BonaEval::f_hand_knight + Hands::Knight(HAND_B);
  list0[ 5] = BonaEval::e_hand_knight + Hands::Knight(HAND_W);
  list0[ 6] = BonaEval::f_hand_silver + Hands::Silver(HAND_B);
  list0[ 7] = BonaEval::e_hand_silver + Hands::Silver(HAND_W);
  list0[ 8] = BonaEval::f_hand_gold   + Hands::Gold(HAND_B);
  list0[ 9] = BonaEval::e_hand_gold   + Hands::Gold(HAND_W);
  list0[10] = BonaEval::f_hand_bishop + Hands::Bishop(HAND_B);
  list0[11] = BonaEval::e_hand_bishop + Hands::Bishop(HAND_W);
  list0[12] = BonaEval::f_hand_rook   + Hands::Rook(HAND_B);
  list0[13] = BonaEval::e_hand_rook   + Hands::Rook(HAND_W);

  list1[ 0] = BonaEval::f_hand_pawn   + Hands::Pawn(HAND_W);
  list1[ 1] = BonaEval::e_hand_pawn   + Hands::Pawn(HAND_B);
  list1[ 2] = BonaEval::f_hand_lance  + Hands::Lance(HAND_W);
  list1[ 3] = BonaEval::e_hand_lance  + Hands::Lance(HAND_B);
  list1[ 4] = BonaEval::f_hand_knight + Hands::Knight(HAND_W);
  list1[ 5] = BonaEval::e_hand_knight + Hands::Knight(HAND_B);
  list1[ 6] = BonaEval::f_hand_silver + Hands::Silver(HAND_W);
  list1[ 7] = BonaEval::e_hand_silver + Hands::Silver(HAND_B);
  list1[ 8] = BonaEval::f_hand_gold   + Hands::Gold(HAND_W);
  list1[ 9] = BonaEval::e_hand_gold   + Hands::Gold(HAND_B);
  list1[10] = BonaEval::f_hand_bishop + Hands::Bishop(HAND_W);
  list1[11] = BonaEval::e_hand_bishop + Hands::Bishop(HAND_B);
  list1[12] = BonaEval::f_hand_rook   + Hands::Rook(HAND_W);
  list1[13] = BonaEval::e_hand_rook   + Hands::Rook(HAND_B);

  // kkp
  for(sq_bk = 0;sq_bk < nsquare ; ++sq_bk)
  {
    for(sq_wk = 0;sq_wk < nsquare ; ++sq_wk)
    {
      for(BoardPosition sq = 0; sq < nsquare; ++sq)
      {
        for(int i=0;i<14;++i)
        {
          // sq > list0[i] , sq > list1[i]
          // kkpとpieceとPcPcOnSqのpieceと違うのか。うわー。
          // PieceKPPとPieceKKPとがいるのか。
          if (sq >= 9)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] += PcPcOnSq( sq_bk , BonaEval::f_pawn + sq , list0[i] );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_pawn + BoardPositions::Inv(sq) , list1[i] );
            if (i==0)
            {
              BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] += PcPcOnSq( sq_bk , BonaEval::f_pawn + sq , BonaEval::f_pawn + sq);
              BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_pawn + BoardPositions::Inv(sq) , BonaEval::e_pawn + BoardPositions::Inv(sq) );
            }

            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] += PcPcOnSq( sq_bk , BonaEval::f_lance + sq , list0[i] );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_lance + BoardPositions::Inv(sq) , list1[i] );
            
            if (i==0)
            {
              BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] += PcPcOnSq( sq_bk , BonaEval::f_lance + sq , BonaEval::f_lance + sq );
              BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_lance + BoardPositions::Inv(sq) , BonaEval::e_lance + BoardPositions::Inv(sq) );
            }
          }
          if (sq >= 18)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] += PcPcOnSq( sq_bk , BonaEval::f_knight + sq , list0[i] );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_knight + BoardPositions::Inv(sq) , list1[i] );

            if (i==0)
            {
              BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] += PcPcOnSq( sq_bk , BonaEval::f_knight + sq , BonaEval::f_knight + sq  );
              BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_knight + BoardPositions::Inv(sq) , BonaEval::e_knight + BoardPositions::Inv(sq) );
            }
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] += PcPcOnSq( sq_bk , BonaEval::f_silver + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_silver + BoardPositions::Inv(sq) , list1[i] );

          if (i==0)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] += PcPcOnSq( sq_bk , BonaEval::f_silver + sq , BonaEval::f_silver + sq );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_silver + BoardPositions::Inv(sq) , BonaEval::e_silver + BoardPositions::Inv(sq) );
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] += PcPcOnSq( sq_bk , BonaEval::f_gold + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_gold + BoardPositions::Inv(sq) , list1[i] );
        
          if (i==0)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] += PcPcOnSq( sq_bk , BonaEval::f_gold + sq , BonaEval::f_gold + sq );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_gold + BoardPositions::Inv(sq) , BonaEval::e_gold + BoardPositions::Inv(sq) );
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] += PcPcOnSq( sq_bk , BonaEval::f_bishop + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_bishop + BoardPositions::Inv(sq) , list1[i] );
          if (i==0)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] += PcPcOnSq( sq_bk , BonaEval::f_bishop + sq , BonaEval::f_bishop + sq );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_bishop + BoardPositions::Inv(sq) , BonaEval::e_bishop + BoardPositions::Inv(sq) );
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] += PcPcOnSq( sq_bk , BonaEval::f_horse + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_horse + BoardPositions::Inv(sq) , list1[i] );
          if (i==0)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] += PcPcOnSq( sq_bk , BonaEval::f_horse + sq , BonaEval::f_horse + sq );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_horse + BoardPositions::Inv(sq) , BonaEval::e_horse + BoardPositions::Inv(sq) );
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] += PcPcOnSq( sq_bk , BonaEval::f_rook + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_rook + BoardPositions::Inv(sq) , list1[i] );
          if (i==0)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] += PcPcOnSq( sq_bk , BonaEval::f_rook + sq , BonaEval::f_rook + sq );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_rook + BoardPositions::Inv(sq) , BonaEval::e_rook + BoardPositions::Inv(sq) );
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] += PcPcOnSq( sq_bk , BonaEval::f_dragon + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_dragon + BoardPositions::Inv(sq) , list1[i] );
          if (i==0)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] += PcPcOnSq( sq_bk , BonaEval::f_dragon + sq , BonaEval::f_dragon + sq );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_dragon + BoardPositions::Inv(sq) , BonaEval::e_dragon + BoardPositions::Inv(sq) );
          }
        }
      }
    }
  }


  // ↓を入れると自己対戦で48-1-38になった。やっぱり有意に強そう。


  // kkp で p= hand
  for(sq_bk = 0;sq_bk < nsquare ; ++sq_bk)
  {
    for(sq_wk = 0;sq_wk < nsquare ; ++sq_wk)
    {
      BoardPosition sq_wk2 = BoardPositions::Inv(sq_wk);

      for(int i = 0 ; i< 14 ; ++i)
      {
        for(int j = 0 ; j<= 18 ; ++j)
        {
          list0[0] += j;
          list1[1] += j;
          BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_pawn + j]
            += 
              + PcPcOnSqAny( sq_bk  , list0[0] , list0[i] )
              - PcPcOnSqAny( sq_wk2 , list1[1] , list1[i] );
          list0[0] -= j;
          list1[1] -= j;
          
          //printf("a) %d \n" , PcPcOnSqAny( sq_wk2 , list1[1] , list1[i] ) );
          //printf("b) %d \n" , PcPcOnSqAny( sq_wk , list1[1] , list1[i] ) );

          if (j>4)
            continue;

          list0[2] += j;
          list1[3] += j;
          BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_lance + j]
            += 
              + PcPcOnSqAny( sq_bk  , list0[2] , list0[i] )
              - PcPcOnSqAny( sq_wk2 , list1[3] , list1[i] );
          list0[2] -= j;
          list1[3] -= j;

          list0[4] += j;
          list1[5] += j;
          BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_knight + j]
          += 
            + PcPcOnSqAny( sq_bk  , list0[4] , list0[i] )
            - PcPcOnSqAny( sq_wk2 , list1[5] , list1[i] );
          list0[4] -= j;
          list1[5] -= j;

          list0[6] += j;
          list1[7] += j;
            BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_silver + j]
              += 
            + PcPcOnSqAny( sq_bk  , list0[6] , list0[i] )
            - PcPcOnSqAny( sq_wk2 , list1[7] , list1[i] );
          list0[6] -= j;
          list1[7] -= j;

          list0[8] += j;
          list1[9] += j;
            BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_gold + j]
              += 
            + PcPcOnSqAny( sq_bk  , list0[8] , list0[i] )
            - PcPcOnSqAny( sq_wk2 , list1[9] , list1[i] );
          list0[8] -= j;
          list1[9] -= j;

          // 飛車・角は2枚まで。
          if (j>2)
            continue;

          list0[10] += j;
          list1[11] += j;
            BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_bishop + j]
              += 
            + PcPcOnSqAny( sq_bk  , list0[10] , list0[i] )
            - PcPcOnSqAny( sq_wk2 , list1[11] , list1[i] );
          list0[10] -= j;
          list1[11] -= j;

          list0[12] += j;
          list1[13] += j;
            BonaEval::kkp[sq_bk][sq_wk][BonaEval::kkp_hand_rook + j]
              += 
            + PcPcOnSqAny( sq_bk  , list0[12] , list0[i] )
            - PcPcOnSqAny( sq_wk2 , list1[13] , list1[i] );
          list0[12] -= j;
          list1[13] -= j;
        }

      }
    }
  }

  // kp1p2でp1==list0,p2==list1のパターンも計算しておかないとおかしくなるのか..
  // まあしかし、それは定数オフセットと考えられるから…
}

// kkp評価 by Bonanza
Score Eval::evaluate_bona6_kkp( Tree* tree )
{
#ifdef SAVE_EVAL
  // 値がcacheされているならそれをそのまま返す
  if ( tree->save_eval[tree->ply] != s32_max )
  {
    return tree->save_eval[tree->ply] / FV_SCALE;
  }
#endif

  RBB bb;
  BoardPosition sq;
  Score score;

  // evaluate用の置換表に登録されていればそれをそのまま返す。
  // 置換表に登録されている値は手番による区別はない。
  // 先手から見たスコアなので後手ならマイナスして返す。
  if ( ehash_probe( HASH_KEY, HAND_B, &score ) )
  {
      score                 = TURN ? -score : score;
#ifdef SAVE_EVAL
      tree->save_eval[tree->ply] = score;
#endif
      return score / FV_SCALE;
  }

  // 稲庭対策
  if (Search::inaniwa)
  {
    score =  evaluate_test1(tree);
    tree->save_eval[tree->ply] = score * FV_SCALE;
    return score;
  }

#ifndef MAKE_MOVE_DEBUG
  // デバッグ時は差分計算せずに差分計算した値が正規に計算した値と一致するのかを
  // 検証する。

#ifdef SAVE_EVAL
  // 差分計算に成功した
  if ( calc_difference_kkp( tree, &score ) )
  {
    ehash_store( HASH_KEY, HAND_B, score );
    score                 = TURN ? -score : score;
    tree->save_eval[tree->ply] = score;
    return score / FV_SCALE;
  }
#endif

#endif

  BoardPosition sq_bk0, sq_wk0, sq_bk1, sq_wk1;

  score = 0;

  // 先手と後手の玉の位置。そして、それを180度回転てみたときの位置
  sq_bk0 = SQ_BKING;
  sq_wk0 = SQ_WKING;
  //sq_bk1 = BoardPositions::Inv(SQ_WKING);
  //sq_wk1 = BoardPositions::Inv(SQ_BKING);
  sq_bk1 = BoardPositions::Inv(SQ_BKING);
  sq_wk1 = BoardPositions::Inv(SQ_WKING);
  // ↑これなおしとかんと計算おかしくなる。

  // PcOnSqのテーブルがおかしいとしか思えん..

  bb = RBB_BPAWN;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_pawn + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_pawn + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_pawn + BoardPositions::Inv(sq));
  });

  bb = RBB_WPAWN;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_pawn + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_pawn + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_pawn + BoardPositions::Inv(sq));
  });

  bb = RBB_BLANCE;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_lance + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_lance + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_lance + BoardPositions::Inv(sq));
  });

  bb = RBB_WLANCE;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_lance + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_lance + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_lance + BoardPositions::Inv(sq));
  });

  bb = RBB_BKNIGHT;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_knight + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_knight + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_knight + BoardPositions::Inv(sq));
  });

  bb = RBB_WKNIGHT;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_knight + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_knight + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_knight + BoardPositions::Inv(sq));
  });

  bb = RBB_BSILVER;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_silver + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_silver + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_silver + BoardPositions::Inv(sq));
  });

  bb = RBB_WSILVER;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_silver + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_silver + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_silver + BoardPositions::Inv(sq));
  });

  bb = RBB_BTGOLD;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_gold + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_gold + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_gold + BoardPositions::Inv(sq));
  });

  bb = RBB_WTGOLD;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_gold + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_gold + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_gold + BoardPositions::Inv(sq));
  });

  bb = RBB_BBISHOP;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_bishop + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_bishop + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_bishop + BoardPositions::Inv(sq));
  });

  bb = RBB_WBISHOP;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_bishop + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_bishop + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_bishop + BoardPositions::Inv(sq));
  });

  bb = RBB_BHORSE;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_horse + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_horse + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_horse + BoardPositions::Inv(sq));
  });

  bb = RBB_WHORSE;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_horse + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_horse + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_horse + BoardPositions::Inv(sq));
  });

  bb = RBB_BROOK;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_rook + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_rook + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_rook + BoardPositions::Inv(sq));
  });

  bb = RBB_WROOK;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_rook + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_rook + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_rook + BoardPositions::Inv(sq));
  });

  bb = RBB_BDRAGON;
  foreach_RBB(bb,sq,{
    score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_dragon + sq ];

    //score += PcOnSq(sq_bk0,BonaEval::f_dragon + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::e_dragon + BoardPositions::Inv(sq));
  });

  bb = RBB_WDRAGON;
  foreach_RBB(bb,sq,{
    score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_dragon + BoardPositions::Inv(sq) ];

    //score += PcOnSq(sq_bk0,BonaEval::e_dragon + sq);
    //score -= PcOnSq(sq_wk1,BonaEval::f_dragon + BoardPositions::Inv(sq));
  });

  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_pawn   + Hands::Pawn(HAND_B) ];
  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_lance  + Hands::Lance(HAND_B) ];
  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_knight + Hands::Knight(HAND_B) ];
  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_silver + Hands::Silver(HAND_B) ];
  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_gold   + Hands::Gold(HAND_B) ];
  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_bishop + Hands::Bishop(HAND_B) ];
  score += BonaEval::kkp[sq_bk0][sq_wk0][ BonaEval::kkp_hand_rook   + Hands::Rook(HAND_B) ];

  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_pawn   + Hands::Pawn(HAND_W) ];
  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_lance  + Hands::Lance(HAND_W) ];
  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_knight + Hands::Knight(HAND_W) ];
  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_silver + Hands::Silver(HAND_W) ];
  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_gold   + Hands::Gold(HAND_W) ];
  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_bishop + Hands::Bishop(HAND_W) ];
  score -= BonaEval::kkp[sq_wk1][sq_bk1][ BonaEval::kkp_hand_rook   + Hands::Rook(HAND_W) ];

  score += MATERIAL * FV_SCALE;

  // 置換表上は先後関係ない。
  // 手番によって点数が変わらない。

  ehash_store( HASH_KEY, HAND_B, score );

  // デバッグのために差分計算したときの値を検証
#ifdef MAKE_MOVE_DEBUG
#ifdef SAVE_EVAL
  {
    Score score2;
    if ( calc_difference_kkp( tree, &score2 ) )
    {
      if (score != score2)
      {
        tree->print();
        Moves::print(MOVE_LAST);
        printf("score = %d , score2 = %d\n",score,score2);
        util_assert(false);
      }
    }
  }
#endif
#endif

  score = TURN ? -score : score;

  // 割る前の値を save_evalに保存しないと駄目
  tree->save_eval[tree->ply] = score;

  score /= FV_SCALE;

  return score;
}

週刊ひよこ将棋がgps_lに3連勝

週刊ひよこ将棋創刊号plusがgps_lに3連勝しました。

これはある意味、事件かも知れません。

私が思うに、どうもGPS将棋はBonanza系の評価関数に弱いのではないでしょうか。floodgateでもGPS将棋はBonanza系には惨敗です。floodgateではBonanza系が上位を独占している状況なのでBonanzaに勝ち越せないようではR2500止まりです。

そしてfloodgateの上位のほうはBonanza系同士の対決となるのでソフト面の改良もそうですが、わずかでもマシン性能が良いほうが圧倒的に勝率が高くなり、高いRがつきすぎるというのはあるのかも知れません。

そう考えるとfloodgateのR2600〜R2900付近は、もしかしたらマシンを2倍速いものにすればR200ぐらい変わってくるのかも知れません。(駒得のみの評価関数のひよこ将棋は並列化で4倍近く速くなってもR100すら変わりませんでしたが…)

しかしfloodgateのR2900が将棋倶楽部24でR3200オーバーということを勘案すると、将棋倶楽部24の2600〜3200付近は、もしかしたらそんなに大きな差はないのではないかと思うのです。考えてみればトップアスリートにしても他の選手の2倍速く走るなんてことは不可能であり、将棋にしてもトップ集団の思考速度は2倍もの差はないと思われます。

プロ棋士のトップとコンピューター将棋が互角ぐらいになった数年後には、もう10回やっても1回ぐらいしか勝てないぐらいに引き離されているのではないかと思うのですが、そうなってもコンピューター将棋の序盤の欠陥はなかなか改善しにくいでしょうから、そこをどう改善していくかということを私はいま考えています。