Example #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");
  }
}
void UnMakeMove(int ply, int move, int wtm)
{
  register int piece, from, to, captured, promote;
/*
 ----------------------------------------------------------
|                                                          |
|   first, take care of the hash key if there's a possible |
|   enpassant pawn capture.                                |
|                                                          |
 ----------------------------------------------------------
*/
  HashKey=save_hash_key[ply];
  PawnHashKey=save_pawn_hash_key[ply];
/*
 ----------------------------------------------------------
|                                                          |
|   now do the piece-specific things by calling the        |
|   appropriate routine.                                   |
|                                                          |
 ----------------------------------------------------------
*/
  piece=Piece(move);
  from=From(move);
  to=To(move);
  captured=Captured(move);
  promote=Promote(move);
UnMakePieceMove:
  SetRL90(from,OccupiedRL90);
  SetRL45(from,OccupiedRL45);
  SetRR45(from,OccupiedRR45);
  ClearRL90(to,OccupiedRL90);
  ClearRL45(to,OccupiedRL45);
  ClearRR45(to,OccupiedRR45);
  bit_move=Or(set_mask[from],set_mask[to]);
  PieceOnSquare(to)=0;
  switch (piece) {

/*
********************************************************************************
*                                                                              *
*   unmake pawn moves.                                                         *
*                                                                              *
********************************************************************************
*/
  case pawn:
    if (wtm) {
      ClearSet(bit_move,WhitePawns);
      ClearSet(bit_move,WhitePieces);
      PieceOnSquare(from)=pawn;
      if (captured == 1) {
        if(EnPassant(ply) == to) {
          TotalPieces++;
          SetRL90(to-8,OccupiedRL90);
          SetRL45(to-8,OccupiedRL45);
          SetRR45(to-8,OccupiedRR45);
          Set(to-8,BlackPawns);
          Set(to-8,BlackPieces);
          PieceOnSquare(to-8)=-pawn;
          Material-=PAWN_VALUE;
          TotalBlackPawns++;
          captured=0;
        }
      }
/*
 --------------------------------------------------------------------
|                                                                    |
|  if this is a pawn promotion, remove the pawn from the counts      |
|  then update the correct piece board to reflect the piece just     |
|  created.                                                          |
|                                                                    |
 --------------------------------------------------------------------
*/
      if (promote) {
        TotalWhitePawns++;
        Material+=PAWN_VALUE;
        Clear(to,WhitePawns);
        Clear(to,WhitePieces);
        switch (promote) {
        case knight:
          Clear(to,WhiteKnights);
          TotalWhitePieces-=knight_v;
          Material-=KNIGHT_VALUE;
          break;
        case bishop:
          Clear(to,WhiteBishops);
          Clear(to,BishopsQueens);
          TotalWhitePieces-=bishop_v;
          Material-=BISHOP_VALUE;
          break;
        case rook:
          Clear(to,WhiteRooks);
          Clear(to,RooksQueens);
          TotalWhitePieces-=rook_v;
          Material-=ROOK_VALUE;
          break;
        case queen:
          Clear(to,WhiteQueens);
          Clear(to,BishopsQueens);
          Clear(to,RooksQueens);
          TotalWhitePieces-=queen_v;
          Material-=QUEEN_VALUE;
          break;
        }
      }
    }
    else {
      ClearSet(bit_move,BlackPawns);
      ClearSet(bit_move,BlackPieces);
      PieceOnSquare(from)=-pawn;
      if (captured == 1) {
        if(EnPassant(ply) == to) {
          TotalPieces++;
          SetRL90(to+8,OccupiedRL90);
          SetRL45(to+8,OccupiedRL45);
          SetRR45(to+8,OccupiedRR45);
          Set(to+8,WhitePawns);
          Set(to+8,WhitePieces);
          PieceOnSquare(to+8)=pawn;
          Material+=PAWN_VALUE;
          TotalWhitePawns++;
          captured=0;
        }
      }
/*
 --------------------------------------------------------------------
|                                                                    |
|  if this is a pawn promotion, remove the pawn from the counts      |
|  then update the correct piece board to reflect the piece just     |
|  created.                                                          |
|                                                                    |
 --------------------------------------------------------------------
*/
      if (promote) {
        TotalBlackPawns++;
        Material-=PAWN_VALUE;
        Clear(to,BlackPawns);
        Clear(to,BlackPieces);
        switch (promote) {
        case knight:
          Clear(to,BlackKnights);
          TotalBlackPieces-=knight_v;
          Material+=KNIGHT_VALUE;
          break;
        case bishop:
          Clear(to,BlackBishops);
          Clear(to,BishopsQueens);
          TotalBlackPieces-=bishop_v;
          Material+=BISHOP_VALUE;
          break;
        case rook:
          Clear(to,BlackRooks);
          Clear(to,RooksQueens);
          TotalBlackPieces-=rook_v;
          Material+=ROOK_VALUE;
          break;
        case queen:
          Clear(to,BlackQueens);
          Clear(to,BishopsQueens);
          Clear(to,RooksQueens);
          TotalBlackPieces-=queen_v;
          Material+=QUEEN_VALUE;
          break;
        }
      }
    }
    break;

/*
********************************************************************************
*                                                                              *
*   unmake knight moves.                                                       *
*                                                                              *
********************************************************************************
*/
  case knight:
    if (wtm) {
      ClearSet(bit_move,WhiteKnights);
      ClearSet(bit_move,WhitePieces);
      PieceOnSquare(from)=knight;
    }
    else {
      ClearSet(bit_move,BlackKnights);
      ClearSet(bit_move,BlackPieces);
      PieceOnSquare(from)=-knight;
    }
    break;

/*
********************************************************************************
*                                                                              *
*   unmake bishop moves.                                                       *
*                                                                              *
********************************************************************************
*/
  case bishop:
    ClearSet(bit_move,BishopsQueens);
    if (wtm) {
      ClearSet(bit_move,WhiteBishops);
      ClearSet(bit_move,WhitePieces);
      PieceOnSquare(from)=bishop;
    }
    else {
      ClearSet(bit_move,BlackBishops);
      ClearSet(bit_move,BlackPieces);
      PieceOnSquare(from)=-bishop;
    }
    break;
/*
********************************************************************************
*                                                                              *
*   unmake rook moves.                                                         *
*                                                                              *
********************************************************************************
*/
  case rook:
    ClearSet(bit_move,RooksQueens);
    if (wtm) {
      ClearSet(bit_move,WhiteRooks);
      ClearSet(bit_move,WhitePieces);
      PieceOnSquare(from)=rook;
    }
    else {
      ClearSet(bit_move,BlackRooks);
      ClearSet(bit_move,BlackPieces);
      PieceOnSquare(from)=-rook;
    }
    break;
/*
********************************************************************************
*                                                                              *
*   unmake queen moves.                                                        *
*                                                                              *
********************************************************************************
*/
  case queen:
    ClearSet(bit_move,BishopsQueens);
    ClearSet(bit_move,RooksQueens);
    if (wtm) {
      ClearSet(bit_move,WhiteQueens);
      ClearSet(bit_move,WhitePieces);
      PieceOnSquare(from)=queen;
    }
    else {
      ClearSet(bit_move,BlackQueens);
      ClearSet(bit_move,BlackPieces);
      PieceOnSquare(from)=-queen;
    }
    break;
/*
********************************************************************************
*                                                                              *
*   unmake king moves.                                                         *
*                                                                              *
********************************************************************************
*/
  case king:
    if (wtm) {
      ClearSet(bit_move,WhitePieces);
      PieceOnSquare(from)=king;
      WhiteKingSQ=from;
      if (abs(to-from) == 2) {
        if (to == 6) {
          from=H1;
          to=F1;
          piece=rook;
          goto UnMakePieceMove;
        }
        else {
          from=A1;
          to=D1;
          piece=rook;
          goto UnMakePieceMove;
        }
      }
    }
    else {
      ClearSet(bit_move,BlackPieces);
      PieceOnSquare(from)=-king;
      BlackKingSQ=from;
      if (abs(to-from) == 2) {
        if (to == 62) {
          from=H8;
          to=F8;
          piece=rook;
          goto UnMakePieceMove;
        }
        else {
          from=A8;
          to=D8;
          piece=rook;
          goto UnMakePieceMove;
        }
      }
    }
    break;
  }
/*
********************************************************************************
*                                                                              *
*   now it is time to restore a piece that was captured.                       *
*                                                                              *
********************************************************************************
*/
  if(captured) {
    TotalPieces++;
    SetRL90(to,OccupiedRL90);
    SetRL45(to,OccupiedRL45);
    SetRR45(to,OccupiedRR45);
    switch (captured) {
/*
 ----------------------------------------------------------
|                                                          |
|   restore a captured pawn.                               |
|                                                          |
 ----------------------------------------------------------
*/
    case pawn: 
      if (wtm) {
        Set(to,BlackPawns);
        Set(to,BlackPieces);
        PieceOnSquare(to)=-pawn;
        Material-=PAWN_VALUE;
        TotalBlackPawns++;
      }
      else {
        Set(to,WhitePawns);
        Set(to,WhitePieces);
        PieceOnSquare(to)=pawn;
        Material+=PAWN_VALUE;
        TotalWhitePawns++;
      }
    break;
/*
 ----------------------------------------------------------
|                                                          |
|   restore a captured knight.                             |
|                                                          |
 ----------------------------------------------------------
*/
    case knight: 
      if (wtm) {
        Set(to,BlackKnights);
        Set(to,BlackPieces);
        PieceOnSquare(to)=-knight;
        TotalBlackPieces+=knight_v;
        Material-=KNIGHT_VALUE;
      }
      else {
        Set(to,WhiteKnights);
        Set(to,WhitePieces);
        PieceOnSquare(to)=knight;
        TotalWhitePieces+=knight_v;
        Material+=KNIGHT_VALUE;
      }
    break;
/*
 ----------------------------------------------------------
|                                                          |
|   restore a captured bishop.                             |
|                                                          |
 ----------------------------------------------------------
*/
    case bishop: 
      Set(to,BishopsQueens);
      if (wtm) {
        Set(to,BlackBishops);
        Set(to,BlackPieces);
        PieceOnSquare(to)=-bishop;
        TotalBlackPieces+=bishop_v;
        Material-=BISHOP_VALUE;
      }
      else {
        Set(to,WhiteBishops);
        Set(to,WhitePieces);
        PieceOnSquare(to)=bishop;
        TotalWhitePieces+=bishop_v;
        Material+=BISHOP_VALUE;
      }
    break;
/*
 ----------------------------------------------------------
|                                                          |
|   restore a captured rook.                               |
|                                                          |
 ----------------------------------------------------------
*/
    case rook: 
      Set(to,RooksQueens);
      if (wtm) {
        Set(to,BlackRooks);
        Set(to,BlackPieces);
        PieceOnSquare(to)=-rook;
        TotalBlackPieces+=rook_v;
        Material-=ROOK_VALUE;
      }
      else {
        Set(to,WhiteRooks);
        Set(to,WhitePieces);
        PieceOnSquare(to)=rook;
        TotalWhitePieces+=rook_v;
        Material+=ROOK_VALUE;
      }
    break;
/*
 ----------------------------------------------------------
|                                                          |
|   restore a captured queen.                              |
|                                                          |
 ----------------------------------------------------------
*/
    case queen: 
      Set(to,BishopsQueens);
      Set(to,RooksQueens);
      if (wtm) {
        Set(to,BlackQueens);
        Set(to,BlackPieces);
        PieceOnSquare(to)=-queen;
        TotalBlackPieces+=queen_v;
        Material-=QUEEN_VALUE;
      }
      else {
        Set(to,WhiteQueens);
        Set(to,WhitePieces);
        PieceOnSquare(to)=queen;
        TotalWhitePieces+=queen_v;
        Material+=QUEEN_VALUE;
      }
      break;
/*
 ----------------------------------------------------------
|                                                          |
|   restore a captured king. [this is an error condition]  |
|                                                          |
 ----------------------------------------------------------
*/
    case king: 
      printf("captured a king\n");
      printf("piece=%d,from=%d,to=%d,captured=%d\n",
            piece,from,to,captured);
      printf("ply=%d\n",ply);
      if (log_file) DisplayChessBoard(log_file,search);
    }
  }
#if defined(DEBUG)
  ValidatePosition(ply,move,"UnMakeMove(2)");
#endif
  return;
}
Example #3
0
void ValidatePosition(int ply, int move, char *caller)
{
  BITBOARD temp, temp1, temp_occ, temp_occ_rl90, temp_occ_rl45;
  BITBOARD temp_occ_rr45, temp_occx, cattacks, rattacks;
  int i,square,error;
  int temp_score;
/*
  first, test w_occupied and b_occupied
*/
  error=0;
  temp_occ=Or(Or(Or(Or(Or(WhitePawns,WhiteKnights),WhiteBishops),
                    WhiteRooks),WhiteQueens),WhiteKing);
  if(Xor(WhitePieces,temp_occ)) {
    Print(1,"ERROR white occupied squares is bad!\n");
    Display2BitBoards(temp_occ,WhitePieces);
    error=1;
  }
  temp_occ=Or(Or(Or(Or(Or(BlackPawns,BlackKnights),BlackBishops),
                    BlackRooks),BlackQueens),BlackKing);
  if(Xor(BlackPieces,temp_occ)) {
    Print(1,"ERROR black occupied squares is bad!\n");
    Display2BitBoards(temp_occ,BlackPieces);
    error=1;
  }
/*
  now test rotated occupied bitboards.
*/
  temp_occ_rl90=0;
  temp_occ_rl45=0;
  temp_occ_rr45=0;
  for (i=0;i<64;i++) {
    if (PieceOnSquare(i)) {
      temp_occ_rl90=Or(temp_occ_rl90,set_mask_rl90[i]);
      temp_occ_rl45=Or(temp_occ_rl45,set_mask_rl45[i]);
      temp_occ_rr45=Or(temp_occ_rr45,set_mask_rr45[i]);
    }
  }
  if(Xor(OccupiedRL90,temp_occ_rl90)) {
    Print(1,"ERROR occupied squares (rotated left 90) is bad!\n");
    Display2BitBoards(temp_occ_rl90,OccupiedRL90);
    error=1;
  }
  if(Xor(OccupiedRL45,temp_occ_rl45)) {
    Print(1,"ERROR occupied squares (rotated left 45) is bad!\n");
    Display2BitBoards(temp_occ_rl45,OccupiedRL45);
    error=1;
  }
  if(Xor(OccupiedRR45,temp_occ_rr45)) {
    Print(1,"ERROR occupied squares (rotated right 45) is bad!\n");
    Display2BitBoards(temp_occ_rr45,OccupiedRR45);
    error=1;
  }
/*
  now test bishops_queens and rooks_queens
*/
  temp_occ=Or(Or(Or(WhiteBishops,WhiteQueens),BlackBishops),
              BlackQueens);
  if(Xor(BishopsQueens,temp_occ)) {
    Print(1,"ERROR bishops_queens is bad!\n");
    Display2BitBoards(temp_occ,BishopsQueens);
    error=1;
  }
    temp_occ=Or(Or(Or(WhiteRooks,WhiteQueens),BlackRooks),
                BlackQueens);
  if(Xor(RooksQueens,temp_occ)) {
    Print(1,"ERROR rooks_queens is bad!\n");
    Display2BitBoards(temp_occ,RooksQueens);
    error=1;
  }
/*
  check individual piece bit-boards to make sure two pieces
  don't occupy the same square (bit)
*/
    temp_occ=Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(
       WhitePawns,WhiteKnights),WhiteBishops),WhiteRooks),
       WhiteQueens),BlackPawns),BlackKnights),BlackBishops),
       BlackRooks),BlackQueens),WhiteKing),BlackKing);
    temp_occx=Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(
       WhitePawns,WhiteKnights),WhiteBishops),WhiteRooks),
       WhiteQueens),BlackPawns),BlackKnights),BlackBishops),
       BlackRooks),BlackQueens),WhiteKing),BlackKing);
    if(Xor(temp_occ,temp_occx)) {
      Print(1,"ERROR two pieces on same square\n");
      error=1;
    }
/*
  test material_evaluation
*/
  temp_score=PopCnt(WhitePawns)*PAWN_VALUE;
  temp_score-=PopCnt(BlackPawns)*PAWN_VALUE;
  temp_score+=PopCnt(WhiteKnights)*KNIGHT_VALUE;
  temp_score-=PopCnt(BlackKnights)*KNIGHT_VALUE;
  temp_score+=PopCnt(WhiteBishops)*BISHOP_VALUE;
  temp_score-=PopCnt(BlackBishops)*BISHOP_VALUE;
  temp_score+=PopCnt(WhiteRooks)*ROOK_VALUE;
  temp_score-=PopCnt(BlackRooks)*ROOK_VALUE;
  temp_score+=PopCnt(WhiteQueens)*QUEEN_VALUE;
  temp_score-=PopCnt(BlackQueens)*QUEEN_VALUE;
  if(temp_score != Material) {
    Print(1,"ERROR  material_evaluation is wrong, good=%d, bad=%d\n",
           temp_score,Material);
    error=1;
  }
  temp_score=PopCnt(WhiteKnights)*knight_v;
  temp_score+=PopCnt(WhiteBishops)*bishop_v;
  temp_score+=PopCnt(WhiteRooks)*rook_v;
  temp_score+=PopCnt(WhiteQueens)*queen_v;
  if(temp_score != TotalWhitePieces) {
    Print(1,"ERROR  white_pieces is wrong, good=%d, bad=%d\n",
           temp_score,TotalWhitePieces);
    error=1;
  }
  temp_score=PopCnt(WhitePawns);
  if(temp_score != TotalWhitePawns) {
    Print(1,"ERROR  white_pawns is wrong, good=%d, bad=%d\n",
           temp_score,TotalWhitePawns);
    error=1;
  }
  temp_score=PopCnt(BlackKnights)*knight_v;
  temp_score+=PopCnt(BlackBishops)*bishop_v;
  temp_score+=PopCnt(BlackRooks)*rook_v;
  temp_score+=PopCnt(BlackQueens)*queen_v;
  if(temp_score != TotalBlackPieces) {
    Print(1,"ERROR  black_pieces is wrong, good=%d, bad=%d\n",
           temp_score,TotalBlackPieces);
    error=1;
  }
  temp_score=PopCnt(BlackPawns);
  if(temp_score != TotalBlackPawns) {
    Print(1,"ERROR  black_pawns is wrong, good=%d, bad=%d\n",
           temp_score,TotalBlackPawns);
    error=1;
  }
/*
  now test the board[...] to make sure piece values are correct.
*/
/*
   test pawn locations
*/
  temp=WhitePawns;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != pawn) {
      Print(1,"ERROR!  board[%d]=%d, should be 1\n",square,
            PieceOnSquare(square));
      error=1;
    }
    Clear(square,temp);
  }
  temp=BlackPawns;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != -pawn) {
      Print(1,"ERROR!  board[%d]=%d, should be -1\n",square,
            PieceOnSquare(square));
      error=1;
    }
    Clear(square,temp);
  }
/*
   test knight locations
*/
  temp=WhiteKnights;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != knight) {
      Print(1,"ERROR!  board[%d]=%d, should be 2\n",square,
            PieceOnSquare(square));
      error=1;
    }
    Clear(square,temp);
  }
  temp=BlackKnights;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != -knight) {
      Print(1,"ERROR!  board[%d]=%d, should be -2\n",square,
            PieceOnSquare(square));
      error=1;
    }
    Clear(square,temp);
  }
/*
   test bishop locations
*/
  temp=WhiteBishops;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != bishop) {
      Print(1,"ERROR!  board[%d]=%d, should be 3\n",square,
            PieceOnSquare(square));
      error=1;
    }
    rattacks=AttacksBishop(square);
    cattacks=ValidateComputeBishopAttacks(square);
    if (rattacks != cattacks) {
      Print(1,"ERROR!  bishop attacks wrong, square=%d\n",square);
      Display2BitBoards(rattacks,cattacks);
      error=1;
    }
    Clear(square,temp);
  }
  temp=BlackBishops;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != -bishop) {
      Print(1,"ERROR!  board[%d]=%d, should be -3\n",square,
            PieceOnSquare(square));
      error=1;
    }
    rattacks=AttacksBishop(square);
    cattacks=ValidateComputeBishopAttacks(square);
    if (rattacks != cattacks) {
      Print(1,"ERROR!  bishop attacks wrong, square=%d\n",square);
      Display2BitBoards(rattacks,cattacks);
      error=1;
    }
    Clear(square,temp);
  }
/*
   test rook locations
*/
  temp=WhiteRooks;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != rook) {
      Print(1,"ERROR!  board[%d]=%d, should be 4\n",square,
            PieceOnSquare(square));
      error=1;
    }
    rattacks=AttacksRook(square);
    cattacks=ValidateComputeRookAttacks(square);
    if (rattacks != cattacks) {
      Print(1,"ERROR!  Rook attacks wrong, square=%d\n",square);
      Display2BitBoards(rattacks,cattacks);
      error=1;
    }
    Clear(square,temp);
  }
  temp=BlackRooks;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != -rook) {
      Print(1,"ERROR!  board[%d]=%d, should be -4\n",square,
            PieceOnSquare(square));
      error=1;
    }
    rattacks=AttacksRook(square);
    cattacks=ValidateComputeRookAttacks(square);
    if (rattacks != cattacks) {
      Print(1,"ERROR!  Rook attacks wrong, square=%d\n",square);
      Display2BitBoards(rattacks,cattacks);
      error=1;
    }
    Clear(square,temp);
  }
/*
   test queen locations
*/
  temp=WhiteQueens;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != queen) {
      Print(1,"ERROR!  board[%d]=%d, should be 5\n",square,
            PieceOnSquare(square));
      error=1;
    }
    rattacks=AttacksQueen(square);
    cattacks=Or(ValidateComputeRookAttacks(square),ValidateComputeBishopAttacks(square));
    if (rattacks != cattacks) {
      Print(1,"ERROR!  queen attacks wrong, square=%d\n",square);
      Display2BitBoards(rattacks,cattacks);
      error=1;
    }
    Clear(square,temp);
  }
  temp=BlackQueens;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != -queen) {
      Print(1,"ERROR!  board[%d]=%d, should be -5\n",square,
            PieceOnSquare(square));
      error=1;
    }
    rattacks=AttacksQueen(square);
    cattacks=Or(ValidateComputeRookAttacks(square),ValidateComputeBishopAttacks(square));
    if (rattacks != cattacks) {
      Print(1,"ERROR!  queen attacks wrong, square=%d\n",square);
      Display2BitBoards(rattacks,cattacks);
      error=1;
    }
    Clear(square,temp);
  }
/*
   test king locations
*/
  temp=WhiteKing;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != king) {
      Print(1,"ERROR!  board[%d]=%d, should be 6\n",square,
            PieceOnSquare(square));
      error=1;
    }
    if (WhiteKingSQ != square) {
      Print(1,"ERROR!  white_king is %d, should be %d\n",
            WhiteKingSQ,square);
      error=1;
    }
    Clear(square,temp);
  }
  temp=BlackKing;
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square) != -king) {
      Print(1,"ERROR!  board[%d]=%d, should be -6\n",square,
            PieceOnSquare(square));
      error=1;
    }
    if (BlackKingSQ != square) {
      Print(1,"ERROR!  black_king is %d, should be %d\n",
            BlackKingSQ,square);
      error=1;
    }
    Clear(square,temp);
  }
/*
   test board[i] fully now.
*/
  for (i=0;i<64;i++)
  switch (PieceOnSquare(i)) {
    case -king:
      if (!And(BlackKing,set_mask[i])) {
        Print(1,"ERROR!  b_king/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case -queen:
      if (!And(BlackQueens,set_mask[i])) {
        Print(1,"ERROR!  b_queen/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case -rook:
      if (!And(BlackRooks,set_mask[i])) {
        Print(1,"ERROR!  b_rook/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case -bishop:
      if (!And(BlackBishops,set_mask[i])) {
        Print(1,"ERROR!  b_bishop/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case -knight:
      if (!And(BlackKnights,set_mask[i])) {
        Print(1,"ERROR!  b_knight/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case -pawn:
      if (!And(BlackPawns,set_mask[i])) {
        Print(1,"ERROR!  b_pawn/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case king:
      if (!And(WhiteKing,set_mask[i])) {
        Print(1,"ERROR!  w_king/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case queen:
      if (!And(WhiteQueens,set_mask[i])) {
        Print(1,"ERROR!  w_queen/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case rook:
      if (!And(WhiteRooks,set_mask[i])) {
        Print(1,"ERROR!  w_rook/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case bishop:
      if (!And(WhiteBishops,set_mask[i])) {
        Print(1,"ERROR!  w_bishop/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case knight:
      if (!And(WhiteKnights,set_mask[i])) {
        Print(1,"ERROR!  w_knight/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
    case pawn:
      if (!And(WhitePawns,set_mask[i])) {
        Print(1,"ERROR!  w_pawn/board[%d] don't agree!\n",i);
        error=1;
      }
      break;
  }
/*
   test empty squares now
*/
  temp=Compl(Or(temp_occ,temp_occx));
  while(temp) {
    square=FirstOne(temp);
    if (PieceOnSquare(square)) {
      Print(1,"ERROR!  board[%d]=%d, should be 0\n",square,
            PieceOnSquare(square));
      error=1;
    }
    Clear(square,temp);
  }
/*
   test total piece count now
*/
  temp=PopCnt(Occupied);
  if (temp != TotalPieces) {
    Print(1,"ERROR!  TotalPieces is wrong, correct=%d  bad=%d\n",
          temp,TotalPieces);
    error=1;
  }
/*
   test hash key
*/
  temp=0;
  temp1=0;
  for (i=0;i<64;i++) {
    switch (PieceOnSquare(i)) {
      case king:
        temp=Xor(temp,w_king_random[i]);
        break;
      case queen:
        temp=Xor(temp,w_queen_random[i]);
        break;
      case rook:
        temp=Xor(temp,w_rook_random[i]);
        break;
      case bishop:
        temp=Xor(temp,w_bishop_random[i]);
        break;
      case knight:
        temp=Xor(temp,w_knight_random[i]);
        break;
      case pawn:
        temp=Xor(temp,w_pawn_random[i]);
        temp1=Xor(temp1,w_pawn_random[i]);
        break;
      case -pawn:
        temp=Xor(temp,b_pawn_random[i]);
        temp1=Xor(temp1,b_pawn_random[i]);
        break;
      case -knight:
        temp=Xor(temp,b_knight_random[i]);
        break;
      case -bishop:
        temp=Xor(temp,b_bishop_random[i]);
        break;
      case -rook:
        temp=Xor(temp,b_rook_random[i]);
        break;
      case -queen:
        temp=Xor(temp,b_queen_random[i]);
        break;
      case -king:
        temp=Xor(temp,b_king_random[i]);
        break;
      default:
        break;
    }
  }
  if (EnPassant(ply)) HashEP(EnPassant(ply),temp);
  if (!(WhiteCastle(ply)&1)) HashCastleW(0,temp);
  if (!(WhiteCastle(ply)&2)) HashCastleW(1,temp);
  if (!(BlackCastle(ply)&1)) HashCastleB(0,temp);
  if (!(BlackCastle(ply)&2)) HashCastleB(1,temp);
  if(Xor(temp,HashKey)) {
    Print(1,"ERROR!  hash_key is bad.\n");
    error=1;
  }
  if(Xor(temp1,PawnHashKey)) {
    Print(1,"ERROR!  pawn_hash_key is bad.\n");
    error=1;
  }
  if (error) {
/*
    Print(0,"active path:\n");
    for (i=1;i<=ply;i++)
      DisplayChessMove("move=",move);
*/
    Print(0,"current move:\n");
    DisplayChessMove("move=",move);
    DisplayChessBoard(stdout,search);
    Print(0,"called from %s, ply=%d\n",caller,ply);
    Print(0,"node=%d\n",nodes_searched+q_nodes_searched);
    exit(1);
  }
}
Example #4
0
/*
 *******************************************************************************
 *                                                                             *
 *   Analyze() is used to handle the "analyze" command.  This mode basically   *
 *   puts Crafty into a "permanent pondering" state, where it reads a move     *
 *   from the input stream, and then "ponders" for the opposite side.          *
 *   Whenever a move is entered, Crafty reads this move, updates the game      *
 *   board, and then starts "pondering" for the other side.                    *
 *                                                                             *
 *   The purpose of this mode is to force Crafty to follow along in a game,    *
 *   providing analysis continually for the side on move until a move is       *
 *   entered, advancing the game to the next position.                         *
 *                                                                             *
 *******************************************************************************
 */
void Analyze() {
  int i, v, move, back_number, readstat = 1;
  TREE *const tree = block[0];

/*
 ************************************************************
 *                                                          *
 *  Initialize.                                             *
 *                                                          *
 ************************************************************
 */
  int save_swindle_mode = swindle_mode;

  swindle_mode = 0;
  ponder_move = 0;
  analyze_mode = 1;
  if (!xboard)
    display_options |= 1 + 2 + 4;
  printf("Analyze Mode: type \"exit\" to terminate.\n");
/*
 ************************************************************
 *                                                          *
 *  Now loop waiting on input, searching the current        *
 *  position continually until a move comes in.             *
 *                                                          *
 ************************************************************
 */
  do {
    do {
      last_pv.pathd = 0;
      last_pv.pathl = 0;
      input_status = 0;
      pondering = 1;
      tree->status[1] = tree->status[0];
      Iterate(game_wtm, think, 0);
      pondering = 0;
      if (book_move)
        moves_out_of_book = 0;
      if (!xboard) {
        if (game_wtm)
          printf("analyze.White(%d): ", move_number);
        else
          printf("analyze.Black(%d): ", move_number);
        fflush(stdout);
      }
/*
 ************************************************************
 *                                                          *
 *  If we get back to here, something has been typed in and *
 *  is in the command buffer normally, unless the search    *
 *  terminated naturally due to finding a mate or reaching  *
 *  the max depth allowable.                                *
 *                                                          *
 ************************************************************
 */
      if (!input_status)
        do {
          readstat = Read(1, buffer);
          if (readstat < 0)
            break;
          nargs = ReadParse(buffer, args, " \t;");
          Print(32, "%s\n", buffer);
          if (strstr(args[0], "timeleft") && !xboard) {
            if (game_wtm)
              printf("analyze.White(%d): ", move_number);
            else
              printf("analyze.Black(%d): ", move_number);
            fflush(stdout);
          }
        } while (strstr(args[0], "timeleft"));
      else
        nargs = ReadParse(buffer, args, " \t;");
      if (readstat < 0)
        break;
      move = 0;
      if (!strcmp(args[0], "exit"))
        break;
/*
 ************************************************************
 *                                                          *
 *  First, check for the special analyze command "back n"   *
 *  and handle it if present, otherwise try Option() to see *
 *  if it recognizes the input as a command.                *
 *                                                          *
 ************************************************************
 */
      if (OptionMatch("back", args[0])) {
        if (nargs > 1)
          back_number = atoi(args[1]);
        else
          back_number = 1;
        for (i = 0; i < back_number; i++) {
          game_wtm = Flip(game_wtm);
          if (Flip(game_wtm))
            move_number--;
        }
        if (move_number == 0) {
          move_number = 1;
          game_wtm = 1;
        }
        sprintf(buffer, "reset %d", move_number);
        Option(tree);
        display = tree->position;
      } else if (Option(tree)) {
        display = tree->position;
      }
/*
 ************************************************************
 *                                                          *
 *  If InputMove() can recognize this as a move, make it,   *
 *  swap sides, and return to the top of the loop to call   *
 *  search from this new position.                          *
 *                                                          *
 ************************************************************
 */
      else if ((move = InputMove(tree, 0, game_wtm, 1, 0, buffer))) {
        char *outmove = OutputMove(tree, 0, game_wtm, move);

        if (history_file) {
          fseek(history_file, ((move_number - 1) * 2 + 1 - game_wtm) * 10,
              SEEK_SET);
          fprintf(history_file, "%9s\n", outmove);
        }
        if (game_wtm)
          Print(32, "White(%d): ", move_number);
        else
          Print(32, "Black(%d): ", move_number);
        Print(32, "%s\n", outmove);
        if (speech) {
          char announce[64];

          strcpy(announce, "./speak ");
          strcat(announce, outmove);
          strcat(announce, " &");
          v = system(announce);
          if (v != 0)
            perror("Analyze() system() error: ");
        }
        MakeMoveRoot(tree, game_wtm, move);
        display = tree->position;
        last_mate_score = 0;
        if (log_file)
          DisplayChessBoard(log_file, tree->position);
      }
/*
 ************************************************************
 *                                                          *
 *  If Option() didn't handle the input, then it is illegal *
 *  and should be reported to the user.                     *
 *                                                          *
 ************************************************************
 */
      else {
        pondering = 0;
        if (Option(tree) == 0)
          printf("illegal move: %s\n", buffer);
        pondering = 1;
        display = tree->position;
      }
    } while (!move);
    if (readstat < 0 || !strcmp(args[0], "exit"))
      break;
    game_wtm = Flip(game_wtm);
    if (game_wtm)
      move_number++;
  } while (1);
  analyze_mode = 0;
  printf("analyze complete.\n");
  pondering = 0;
  swindle_mode = save_swindle_mode;
}