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); } }
/* ******************************************************************************** * * * Swap() is used to analyze capture moves to see whether or not they appear * * to be profitable. the basic algorithm is extremely fast since it uses the * * bitmaps to determine which squares are attacking the [target] square. * * * * the algorithm is quite simple. using the attack bitmaps, we enumerate all * * the pieces that are attacking [target] for either side. then we simply * * use the lowest piece (value) for the correct side to capture on [target]. * * we continually "flip" sides taking the lowest piece each time. * * * * as a piece is used, if it is a sliding piece (pawn, bishop, rook or queen) * * we "peek" behind it to see if it is attacked by a sliding piece in the * * direction away from the piece being captured. if so, and that sliding * * piece moves in this direction, then it is added to the list of attackers * * since its attack has been "uncovered" by moving the capturing piece. * * * ******************************************************************************** */ int Swap(int source, int target, int wtm) { register BITBOARD attacks; register int attacked_piece; register int square, direction; register int sign, color, next_capture=1; int swap_list[32]; /* ---------------------------------------------------------- | | | determine which squares attack <target> for each side. | | | ---------------------------------------------------------- */ attacks=AttacksTo(target); /* ---------------------------------------------------------- | | | initialize by placing the piece on <target> first in | | the list as it is being captured to start things off. | | | ---------------------------------------------------------- */ attacked_piece=p_values[PieceOnSquare(target)+7]; /* ---------------------------------------------------------- | | | the first piece to capture on <target> is the piece | | standing on <source>. | | | ---------------------------------------------------------- */ color=ChangeSide(wtm); swap_list[0]=attacked_piece; sign=-1; attacked_piece=p_values[PieceOnSquare(source)+7]; Clear(source,attacks); direction=directions[target][source]; if (direction) attacks=SwapXray(attacks,source,direction); /* ---------------------------------------------------------- | | | now pick out the least valuable piece for the correct | | side that is bearing on <target>. as we find one, we | | call SwapXray() to add the piece behind this piece | | that is indirectly bearing on <target> (if any). | | | ---------------------------------------------------------- */ while (attacks) { if (color) { if (And(WhitePawns,attacks)) square=FirstOne(And(WhitePawns,attacks)); else if (And(WhiteKnights,attacks)) square=FirstOne(And(WhiteKnights,attacks)); else if (And(WhiteBishops,attacks)) square=FirstOne(And(WhiteBishops,attacks)); else if (And(WhiteRooks,attacks)) square=FirstOne(And(WhiteRooks,attacks)); else if (And(WhiteQueens,attacks)) square=FirstOne(And(WhiteQueens,attacks)); else if (And(WhiteKing,attacks)) square=WhiteKingSQ; else break; } else { if (And(BlackPawns,attacks)) square=FirstOne(And(BlackPawns,attacks)); else if (And(BlackKnights,attacks)) square=FirstOne(And(BlackKnights,attacks)); else if (And(BlackBishops,attacks)) square=FirstOne(And(BlackBishops,attacks)); else if (And(BlackRooks,attacks)) square=FirstOne(And(BlackRooks,attacks)); else if (And(BlackQueens,attacks)) square=FirstOne(And(BlackQueens,attacks)); else if (And(BlackKing,attacks)) square=BlackKingSQ; else break; } /* ------------------------------------------------ | | | located the least valuable piece bearing on | | <target>. remove it from the list and then | | find out if a sliding piece behind it attacks | | through this piece. | | | ------------------------------------------------ */ swap_list[next_capture]=swap_list[next_capture-1]+sign*attacked_piece; attacked_piece=p_values[PieceOnSquare(square)+7]; Clear(square,attacks); direction=directions[target][square]; if (direction) attacks=SwapXray(attacks,square,direction); next_capture++; sign=-sign; color=ChangeSide(color); } /* ---------------------------------------------------------- | | | starting at the end of the sequence of values, use a | | "minimax" like procedure to decide where the captures | | will stop. | | | ---------------------------------------------------------- */ next_capture--; if(next_capture&1) sign=-1; else sign=1; while (next_capture) { if (sign < 0) { if(swap_list[next_capture] <= swap_list[next_capture-1]) swap_list[next_capture-1]=swap_list[next_capture]; } else { if(swap_list[next_capture] >= swap_list[next_capture-1]) swap_list[next_capture-1]=swap_list[next_capture]; } next_capture--; sign=-sign; } return (swap_list[0]); }
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; }