/* ******************************************************************************* * * * 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; }
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); } }
/* ******************************************************************************* * * * 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; }