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