Exemplo n.º 1
0
/*
 *******************************************************************************
 *                                                                             *
 *   SetBoard() is used to set up the board in any position desired.  It uses  *
 *   a forsythe-like string of characters to describe the board position.      *
 *                                                                             *
 *   The standard piece codes p,n,b,r,q,k are used to denote the type of piece *
 *   on a square, upper/lower case are used to indicate the side (program/opp.)*
 *   of the piece.                                                             *
 *                                                                             *
 *   The pieces are entered with square a8 first, then b8, ... until the full  *
 *   8th rank is completed.  A "/" terminates that rank.  This is repeated for *
 *   each of the 8 ranks, with the last (1st) rank not needing a terminating   *
 *   "/".  For empty squares, a number between 1 and 8 can be used to indicate *
 *   the number of adjacent empty squares.                                     *
 *                                                                             *
 *   That board description must be followed by a "b" or "w" to indicate which *
 *   side is on move.                                                          *
 *                                                                             *
 *   Next, up to 4 characters are used to indicate which side can castle and   *
 *   to which side.  An uppercase K means white can castle kingside, while a   *
 *   lowercase q means black can castle queenside.                             *
 *                                                                             *
 *   Finally, if there is an enpassant capture possible (the last move was a   *
 *   double pawn move and there was an enemy pawn that could capture it.  The  *
 *   square is the square the capturing pawn ends up on.                       *
 *                                                                             *
 *         K2R/PPP////q/5ppp/7k/ b - -                                         *
 *                                                                             *
 *   this assumes that k represents a white king and -q represents a black     *
 *   queen.                                                                    *
 *                                                                             *
 *                          k  *  *  r  *  *  *  *                             *
 *                          p  p  p  *  *  *  *  *                             *
 *                          *  *  *  *  *  *  *  *                             *
 *                          *  *  *  *  *  *  *  *                             *
 *                          *  *  *  *  *  *  *  *                             *
 *                         -q  *  *  *  *  *  *  *                             *
 *                          *  *  *  *  * -p -p -p                             *
 *                          *  *  *  *  *  *  * -k                             *
 *                                                                             *
 *******************************************************************************
 */
void SetBoard(TREE * tree, int nargs, char *args[], int special) {
  int twtm, i, match, num, pos, square, tboard[64];
  int bcastle, ep, wcastle, error = 0;
  char input[80];
  static const char bdinfo[] =
      { 'k', 'q', 'r', 'b', 'n', 'p', '*', 'P', 'N', 'B',
    'R', 'Q', 'K', '*', '1', '2', '3', '4',
    '5', '6', '7', '8', '/'
  };
  static const char status[13] =
      { 'K', 'Q', 'k', 'q', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
    'h', ' '
  };
  int whichsq;
  static const int firstsq[8] = { 56, 48, 40, 32, 24, 16, 8, 0 };
  if (special)
    strcpy(input, initial_position);
  else
    strcpy(input, args[0]);
  for (i = 0; i < 64; i++)
    tboard[i] = 0;
/*
 ************************************************************
 *                                                          *
 *   Scan the input string searching for pieces, numbers    *
 *   [empty squares], slashes [end-of-rank] and a blank     *
 *   [end of board, start of castle status].                *
 *                                                          *
 ************************************************************
 */
  whichsq = 0;
  square = firstsq[whichsq];
  num = 0;
  for (pos = 0; pos < (int) strlen(args[0]); pos++) {
    for (match = 0; match < 23 && args[0][pos] != bdinfo[match]; match++);
    if (match > 22)
      break;
/*
 "/" -> end of this rank.
 */
    else if (match == 22) {
      num = 0;
      if (whichsq > 6)
        break;
      square = firstsq[++whichsq];
    }
/*
 "1-8" -> empty squares.
 */
    else if (match >= 14) {
      num += match - 13;
      square += match - 13;
      if (num > 8) {
        printf("more than 8 squares on one rank\n");
        error = 1;
        break;
      }
      continue;
    }
/*
 piece codes.
 */
    else {
      if (++num > 8) {
        printf("more than 8 squares on one rank\n");
        error = 1;
        break;
      }
      tboard[square++] = match - 6;
    }
  }
/*
 ************************************************************
 *                                                          *
 *   Now extract (a) side to move [w/b], (b) castle status  *
 *   [KkQq for white/black king-side ok, white/black queen- *
 *   side ok], (c) enpassant target square.                 *
 *                                                          *
 ************************************************************
 */
  twtm = 0;
  ep = 0;
  wcastle = 0;
  bcastle = 0;
/*
 ************************************************************
 *                                                          *
 *   Side to move.                                          *
 *                                                          *
 ************************************************************
 */
  if (args[1][0] == 'w')
    twtm = 1;
  else if (args[1][0] == 'b')
    twtm = 0;
  else {
    printf("side to move is bad\n");
    error = 1;
  }
/*
 ************************************************************
 *                                                          *
 *   Castling/enpassant status.                             *
 *                                                          *
 ************************************************************
 */
  if (nargs > 2 && strlen(args[2])) {
    if (strcmp(args[2], "-")) {
      for (pos = 0; pos < (int) strlen(args[2]); pos++) {
        for (match = 0; (match < 13) && (args[2][pos] != status[match]);
            match++);
        if (match == 0)
          wcastle += 1;
        else if (match == 1)
          wcastle += 2;
        else if (match == 2)
          bcastle += 1;
        else if (match == 3)
          bcastle += 2;
        else if (args[2][0] != '-') {
          printf("castling status is bad.\n");
          error = 1;
        }
      }
    }
  }
  if (nargs > 3 && strlen(args[3])) {
    if (strcmp(args[3], "-")) {
      if (args[3][0] >= 'a' && args[3][0] <= 'h' && args[3][1] > '0' &&
          args[3][1] < '9') {
        ep = (args[3][1] - '1') * 8 + args[3][0] - 'a';
      } else if (args[3][0] != '-') {
        printf("enpassant status is bad.\n");
        error = 1;
      }
    }
  }
  for (i = 0; i < 64; i++)
    PcOnSq(i) = tboard[i];
  Castle(0, white) = wcastle;
  Castle(0, black) = bcastle;
  EnPassant(0) = 0;
  if (ep) {
    if (Rank(ep) == RANK6) {
      if (PcOnSq(ep - 8) != -pawn)
        ep = 0;
    } else if (Rank(ep) == RANK3) {
      if (PcOnSq(ep + 8) != pawn)
        ep = 0;
    } else
      ep = 0;
    if (!ep) {
      printf("enpassant status is bad (must be on 3rd/6th rank only.\n");
      ep = 0;
      error = 1;
    }
    EnPassant(0) = ep;
  }
  Rule50Moves(0) = 0;
/*
 ************************************************************
 *                                                          *
 *   Now check the castling status and enpassant status to  *
 *   make sure that the board is in a state that matches    *
 *   these.                                                 *
 *                                                          *
 ************************************************************
 */
  if (((Castle(0, white) & 2) && (PcOnSq(A1) != rook)) ||
      ((Castle(0, white) & 1) && (PcOnSq(H1) != rook)) ||
      ((Castle(0, black) & 2) && (PcOnSq(A8) != -rook)) ||
      ((Castle(0, black) & 1) && (PcOnSq(H8) != -rook))) {
    printf("ERROR-- castling status does not match board position\n");
    error = 1;
  }
/*
 ************************************************************
 *                                                          *
 *   Now set the bitboards so that error tests can be done. *
 *                                                          *
 ************************************************************
 */
  if ((twtm && EnPassant(0) && (PcOnSq(EnPassant(0) + 8) != -pawn) &&
          (PcOnSq(EnPassant(0) - 7) != pawn) &&
          (PcOnSq(EnPassant(0) - 9) != pawn)) || (Flip(twtm) && EnPassant(0)
          && (PcOnSq(EnPassant(0) - 8) != pawn) &&
          (PcOnSq(EnPassant(0) + 7) != -pawn) &&
          (PcOnSq(EnPassant(0) + 9) != -pawn))) {
    EnPassant(0) = 0;
  }
  SetChessBitBoards(tree);
/*
 ************************************************************
 *                                                          *
 *   Now check the position for a sane position, which      *
 *   means no more than 8 pawns, no more than 10 knights,   *
 *   bishops or rooks, no more than 9 queens, no pawns on   *
 *   1st or 8th rank, etc.                                  *
 *                                                          *
 ************************************************************
 */
  wtm = twtm;
  error += InvalidPosition(tree);
  if (!error) {
    if (log_file)
      DisplayChessBoard(log_file, tree->pos);
    tree->rep_index[white] = 0;
    tree->rep_index[black] = 0;
    Rule50Moves(0) = 0;
    if (!special) {
      last_mate_score = 0;
      InitializeKillers();
      last_pv.pathd = 0;
      last_pv.pathl = 0;
      tree->pv[0].pathd = 0;
      tree->pv[0].pathl = 0;
      moves_out_of_book = 0;
    }
  } else {
    if (special)
      Print(4095, "bad string = \"%s\"\n", initial_position);
    else
      Print(4095, "bad string = \"%s\"\n", args[0]);
    InitializeChessBoard(tree);
    Print(4095, "Illegal position, using normal initial chess position\n");
  }
}
Exemplo n.º 2
0
// 評価関数を38回固定ループにする為に、持ち駒0枚の評価値を他の評価値に足しこみ、持ち駒複数枚の評価値を差分化する。
void convertFV() {
    // K    : 玉
    // B    : 盤上の駒
    // 0    : 持ち駒 0 枚
    // N, M : 持ち駒 0 枚以外

    // K0, K00 を全て足し込んだテーブルを作成
    for (Square ksqb = A9; ksqb < nsquare; ++ksqb) {
        for (Square ksqw = A9; ksqw < nsquare; ++ksqw) {
            int score = 0;
            for (int i = 0; i < 14; ++i) {
                const int k0 = Hand0FVIndex[i];
                for (int j = 0; j <= i; ++j) {
                    const int l0 = Hand0FVIndex[j];
                    score += PcPcOnSqAny(ksqb, k0, l0);
                    // 本当は list0, list1 という風にした方が良いけど、
                    // 全部足すので何でも良い。
                    score -= PcPcOnSqAny(Inv(ksqw), k0, l0);
                }
            }
            mid_kk[ksqb][ksqw] = score;
        }
    }

    // KK0 も全て足し込む
    for (Square ksqB = A9; ksqB < nsquare; ++ksqB) {
        for (Square ksqW = A9; ksqW < nsquare; ++ksqW) {
            for (FVIndex elem : Hand0KKPFVIndex) {
                mid_kk[ksqB][ksqW] += kkp[ksqB     ][ksqW     ][elem];
                mid_kk[ksqB][ksqW] -= kkp[Inv(ksqW)][Inv(ksqB)][elem];
            }
        }
    }

    // K0B を KB に足し込む。
    // 持ち駒 0 枚以外のとき、KB に余分な値が足し込まれているので、KNB で余分を引く。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand = f_hand_pawn; ihand < fe_hand_end; ++ihand) {
            for (FVIndex iboard = fe_hand_end; iboard < fe_end; ++iboard) {
                if (handIs0(ihand)) {
                    MidPcOnSq(ksq, iboard) += PcPcOnSqAny(ksq, ihand, iboard);
                }
                else {
                    const FVIndex ihand0 = hand0Index(ihand);
                    MidPcPcOnSqAny(ksq, ihand, iboard) -= PcPcOnSqAny(ksq, ihand0, iboard);
                }
            }
        }
    }

    // K0N を KN に足し込む。
    // K00 を KN から引く。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand0 : Hand0FVIndex) {
            for (FVIndex jhand = f_hand_pawn; jhand < fe_hand_end; ++jhand) {
                if (handIs0(jhand)  ) {
                    continue;
                }
                const FVIndex jhand0 = hand0Index(jhand);
                if (ihand0 == jhand0) {
                    continue;    // 同じ種類の持ち駒の 0 枚と それ以外の枚数は共存しない。
                }
                MidPcOnSq(ksq, jhand) += PcPcOnSqAny(ksq, ihand0, jhand);
                MidPcOnSq(ksq, jhand) -= PcPcOnSqAny(ksq, ihand0, jhand0);
            }
        }
    }

    // KN に K0N が足し込まれている。
    // KM に K0M が足し込まれている。
    // よって、KNM から K0N, K0M を引く。
    // 更に KN, KM から K00 を 2重に引いたので、K00 を KNM に足す。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand = f_hand_pawn; ihand < fe_hand_end; ++ihand) {
            if (handIs0(ihand)) {
                continue;
            }
            const FVIndex ihand0 = hand0Index(ihand);
            for (FVIndex jhand = f_hand_pawn; jhand < ihand0; ++jhand) {
                if (handIs0(jhand)) {
                    continue;
                }
                const FVIndex jhand0 = hand0Index(jhand);
                MidPcPcOnSqAny(ksq, ihand, jhand) -= PcPcOnSqAny(ksq, ihand, jhand0) + PcPcOnSqAny(ksq, ihand0, jhand);
                MidPcPcOnSqAny(ksq, ihand, jhand) += PcPcOnSqAny(ksq, ihand0, jhand0);
            }
        }
    }

    // K0 を mid_kk テーブルに足しこんでいるので、KN から K0 を引く。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand0 : Hand0FVIndex) {
            for (int i = 18; 0 < i; --i) {
                if (4 < i && f_hand_lance  <= ihand0) continue;
                if (2 < i && f_hand_bishop <= ihand0) continue;
                MidPcOnSq(ksq, ihand0 + i) -= PcOnSq(ksq, ihand0);
            }
        }
    }

    // 味方の同じ種類の駒の枚数違いは、本来無い組み合わせなので、0 にしないといけない。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand = f_hand_pawn; ihand < fe_hand_end; ++ihand) {
            const FVIndex ihand0 = hand0Index(ihand);
            for (FVIndex jhand = f_hand_pawn; jhand < ihand; ++jhand) {
                const FVIndex jhand0 = hand0Index(jhand);
                // 同じ種類の持ち駒のときかつ、駒の枚数が違うとき、0 にする。
                if (ihand0 == jhand0 && ihand != jhand) {
                    MidPcPcOnSq(ksq, ihand, jhand) = 0;
                }
            }
        }
    }

    // KPP 差分値化
    // KBN を KB(N-1) との差分値にする。(1 < N のとき)
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex iboard = fe_hand_end; iboard < fe_end; ++iboard) {
            for (FVIndex jhand0 : Hand0FVIndex) {
                for (int j = 18; 1 < j; --j) {
                    if (4 < j && f_hand_lance  <= jhand0) continue;
                    if (2 < j && f_hand_bishop <= jhand0) continue;
                    const FVIndex jhand = jhand0 + j;
                    MidPcPcOnSq(ksq, iboard, jhand) -= MidPcPcOnSq(ksq, iboard, jhand - 1);
                }
            }
        }
    }

    // KP 差分値化
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand0 : Hand0FVIndex) {
            for (int i = 18; 1 < i; --i) {
                if (4 < i && f_hand_lance  <= ihand0) continue;
                if (2 < i && f_hand_bishop <= ihand0) continue;
                MidPcOnSq(ksq, ihand0 + i) -= MidPcOnSq(ksq, ihand0 + i - 1);
            }
        }
    }

    // KP を KP 用の配列に格納
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex i = f_hand_pawn; i < fe_end; ++i) {
            mid_kp[ksq][i] = MidPcOnSq(ksq, i);
        }
    }

    // KMN を差分化する。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex ihand0 : Hand0FVIndex) {
            for (int i = 18; 0 < i; --i) {
                if (4 < i && f_hand_lance  <= ihand0) continue;
                if (2 < i && f_hand_bishop <= ihand0) continue;
                const FVIndex ihand = ihand0 + i;
                for (FVIndex jhand0 : Hand0FVIndex) {
                    if (ihand0 <= jhand0) continue;
                    for (int j = 18; 0 < j; --j) {
                        if (4 < j && f_hand_lance  <= jhand0) continue;
                        if (2 < j && f_hand_bishop <= jhand0) continue;
                        const FVIndex jhand = jhand0 + j;
                        if      (1 < i && 1 < j)
                            MidPcPcOnSq(ksq, ihand, jhand) += -MidPcPcOnSq(ksq, ihand - 1, jhand) - MidPcPcOnSq(ksq, ihand, jhand - 1) + MidPcPcOnSq(ksq, ihand - 1, jhand - 1);
                        else if (1 < i         )
                            MidPcPcOnSq(ksq, ihand, jhand) += -MidPcPcOnSq(ksq, ihand - 1, jhand);
                        else if (1 < j         )
                            MidPcPcOnSq(ksq, ihand, jhand) += -MidPcPcOnSq(ksq, ihand, jhand - 1);
                    }
                }
            }
        }
    }

    // KP を評価関数で参照しなくて済むように、
    // KP を KKP に足しこむ。
    // 更に、KK に KK0 を押し込んだので、KKN から KK0 を引いておく。
    for (Square ksqB = A9; ksqB < nsquare; ++ksqB) {
        for (Square ksqW = A9; ksqW < nsquare; ++ksqW) {
            auto handcopy = [&](const int handnum, const FVIndex kkp_hand_index) {
                for (int i = 0; i < handnum; ++i) {
                    if (i != 0) {
                        mid_kkp[ksqB][ksqW][kkp_hand_index + i] -= kkp[ksqB][ksqW][kkp_hand_index];
                    }
                }
            };

            handcopy(19, kkp_hand_pawn  );
            handcopy( 5, kkp_hand_lance );
            handcopy( 5, kkp_hand_knight);
            handcopy( 5, kkp_hand_silver);
            handcopy( 5, kkp_hand_gold  );
            handcopy( 3, kkp_hand_bishop);
            handcopy( 3, kkp_hand_rook  );
        }
    }

    // KP = 0
    // 評価値の差分計算時に KP が邪魔にならないように 0 にしておく。
    // 対局時は KP は KKP に足し込んでおけば良いが、
    // 学習に使う際に KP と KKP それぞれの値を知りたい場合もあるので、
    // KP を KKP に足し込まず、別途ファイルに出力しておく。
    for (Square ksq = A9; ksq < nsquare; ++ksq) {
        for (FVIndex i = f_hand_pawn; i < fe_end; ++i) {
            MidPcOnSq(ksq, i) = 0;
        }
    }

    // KK0 = 0
    // 特に必要ではないが、一応やっておく。
    for (Square ksqB = A9; ksqB < nsquare; ++ksqB) {
        for (Square ksqW = A9; ksqW < nsquare; ++ksqW) {
            for (FVIndex elem : Hand0KKPFVIndex) {
                mid_kkp[ksqB][ksqW][elem] = 0;
            }
        }
    }

    // KKP 差分値化
    for (Square ksqB = A9; ksqB < nsquare; ++ksqB) {
        for (Square ksqW = A9; ksqW < nsquare; ++ksqW) {
            for (FVIndex elem : Hand0KKPFVIndex) {
                for (int i = 18; 1 < i; --i) {
                    if (4 < i && kkp_hand_lance  <= elem) continue;
                    if (2 < i && kkp_hand_bishop <= elem) continue;
                    mid_kkp[ksqB][ksqW][elem + i] -= mid_kkp[ksqB][ksqW][elem + i - 1];
                }
            }
        }
    }

    // KKP を KPP と同じインデックスで参照するようにする。
    // 持ち駒について。
    for (Square ksqB = A9; ksqB < nsquare; ++ksqB) {
        for (Square ksqW = A9; ksqW < nsquare; ++ksqW) {
            for (FVIndex elem : Hand0KKPFVIndex) {
                const auto fe_pair = g_kkpToKP[elem];
                for (int i = 0; i < 19; ++i) {
                    if (4 < i && kkp_hand_lance  <= elem) continue;
                    if (2 < i && kkp_hand_bishop <= elem) continue;
                    mid_new_kkp[ksqB][ksqW][fe_pair.first  + i] =  mid_kkp[ksqB     ][ksqW     ][elem + i];
                    mid_new_kkp[ksqB][ksqW][fe_pair.second + i] = -mid_kkp[Inv(ksqW)][Inv(ksqB)][elem + i];
                }
            }
        }
    }
    // 盤上の駒について。
    for (Square ksqB = A9; ksqB < nsquare; ++ksqB) {
        for (Square ksqW = A9; ksqW < nsquare; ++ksqW) {
            for (FVIndex elem : BoardKKPFVIndex) {
                const auto fe_pair = g_kkpToKP[elem];
                for (Square sq = A9; sq < nsquare; ++sq) {
                    if (!(((elem == kkp_pawn || elem == kkp_lance) && sq < A8) || (elem == kkp_knight && sq < A7)))
                        mid_new_kkp[ksqB][ksqW][fe_pair.first  + sq] =  mid_kkp[ksqB     ][ksqW     ][elem + sq     ];
                    if (!(((elem == kkp_pawn || elem == kkp_lance) && Inv(sq) < A8) || (elem == kkp_knight && Inv(sq) < A7)))
                        mid_new_kkp[ksqB][ksqW][fe_pair.second + sq] = -mid_kkp[Inv(ksqW)][Inv(ksqB)][elem + Inv(sq)];
                }
            }
        }
    }
}