Subversion Repositories Games.Chess Giants

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "chess.h"
  2. #include "data.h"
  3. /* last modified 02/22/14 */
  4. /*
  5.  *******************************************************************************
  6.  *                                                                             *
  7.  *   MakeMove() is responsible for updating the position database whenever a   *
  8.  *   piece is moved.  It performs the following operations:  (1) update the    *
  9.  *   board structure itself by moving the piece and removing any captured      *
  10.  *   piece.  (2) update the hash keys.  (3) update material counts.  (4) then  *
  11.  *   update castling status.  (5) and finally update number of moves since     *
  12.  *   last reversible move.                                                     *
  13.  *                                                                             *
  14.  *   There are some special-cases handled here, such as en passant captures    *
  15.  *   where the enemy pawn is not on the <target> square, castling which moves  *
  16.  *   both the king and rook, and then rook moves/captures which give up the    *
  17.  *   castling right to that side when the rook is moved.                       *
  18.  *                                                                             *
  19.  *   note:  side = 1 if white is to move, 0 otherwise.  enemy is the opposite  *
  20.  *   and is 1 if it is not white to move, 0 otherwise.                         *
  21.  *                                                                             *
  22.  *******************************************************************************
  23.  */
  24. void MakeMove(TREE * RESTRICT tree, int ply, int move, int side) {
  25.   uint64_t bit_move;
  26.   int piece, from, to, captured, promote, enemy = Flip(side);
  27.   int cpiece;
  28. #if defined(DEBUG)
  29.   int i;
  30. #endif
  31.  
  32. /*
  33.  ************************************************************
  34.  *                                                          *
  35.  *  First, some basic information is updated for all moves  *
  36.  *  before we do the piece-specific stuff.  We need to save *
  37.  *  the current position and both hash signatures, and add  *
  38.  *  the current position to the repetition-list for the     *
  39.  *  side on move, before the move is actually made on the   *
  40.  *  board.  We also update the 50 move rule counter which   *
  41.  *  will be reset if a capture or pawn move is made here.   *
  42.  *                                                          *
  43.  *  If the en passant flag was set the previous ply, we     *
  44.  *  have already used it to generate moves at this ply and  *
  45.  *  we need to clear it before continuing.  If it is set,   *
  46.  *  we also need to update the hash signature since the EP  *
  47.  *  opportunity no longer exists after making any move at   *
  48.  *  this ply (one ply deeper than when a pawn was advanced  *
  49.  *  two squares).                                           *
  50.  *                                                          *
  51.  ************************************************************
  52.  */
  53. #if defined(DEBUG)
  54.   ValidatePosition(tree, ply, move, "MakeMove(1)");
  55. #endif
  56.   tree->status[ply + 1] = tree->status[ply];
  57.   tree->save_hash_key[ply] = HashKey;
  58.   tree->save_pawn_hash_key[ply] = PawnHashKey;
  59.   if (EnPassant(ply + 1)) {
  60.     HashEP(EnPassant(ply + 1));
  61.     EnPassant(ply + 1) = 0;
  62.   }
  63.   Reversible(ply + 1)++;
  64. /*
  65.  ************************************************************
  66.  *                                                          *
  67.  *  Now do the things that are common to all pieces, such   *
  68.  *  as updating the bitboards and hash signature.           *
  69.  *                                                          *
  70.  ************************************************************
  71.  */
  72.   piece = Piece(move);
  73.   from = From(move);
  74.   to = To(move);
  75.   captured = Captured(move);
  76.   promote = Promote(move);
  77.   bit_move = SetMask(from) | SetMask(to);
  78.   cpiece = PcOnSq(to);
  79.   ClearSet(bit_move, Pieces(side, piece));
  80.   ClearSet(bit_move, Occupied(side));
  81.   Hash(side, piece, from);
  82.   Hash(side, piece, to);
  83.   PcOnSq(from) = 0;
  84.   PcOnSq(to) = pieces[side][piece];
  85. /*
  86.  ************************************************************
  87.  *                                                          *
  88.  *  Now do the piece-specific things by jumping to the      *
  89.  *  appropriate routine.                                    *
  90.  *                                                          *
  91.  ************************************************************
  92.  */
  93.   switch (piece) {
  94.     case pawn:
  95.       HashP(side, from);
  96.       HashP(side, to);
  97.       Reversible(ply + 1) = 0;
  98.       if (captured == 1 && !cpiece) {
  99.         Clear(to + epsq[side], Pawns(enemy));
  100.         Clear(to + epsq[side], Occupied(enemy));
  101.         Hash(enemy, pawn, to + epsq[side]);
  102.         HashP(enemy, to + epsq[side]);
  103.         PcOnSq(to + epsq[side]) = 0;
  104.         Material -= PieceValues(enemy, pawn);
  105.         TotalPieces(enemy, pawn)--;
  106.         TotalAllPieces--;
  107.         captured = 0;
  108.       }
  109.       if (promote) {
  110.         TotalPieces(side, pawn)--;
  111.         Material -= PieceValues(side, pawn);
  112.         Clear(to, Pawns(side));
  113.         Hash(side, pawn, to);
  114.         HashP(side, to);
  115.         Hash(side, promote, to);
  116.         PcOnSq(to) = pieces[side][promote];
  117.         TotalPieces(side, occupied) += p_vals[promote];
  118.         TotalPieces(side, promote)++;
  119.         Material += PieceValues(side, promote);
  120.         Set(to, Pieces(side, promote));
  121.         switch (promote) {
  122.           case knight:
  123.           case bishop:
  124.             TotalMinors(side)++;
  125.             break;
  126.           case rook:
  127.             TotalMajors(side)++;
  128.             break;
  129.           case queen:
  130.             TotalMajors(side) += 2;
  131.             break;
  132.         }
  133.       } else if ((Abs(to - from) == 16) && (mask_eptest[to] & Pawns(enemy))) {
  134.         EnPassant(ply + 1) = to + epsq[side];
  135.         HashEP(to + epsq[side]);
  136.       }
  137.       break;
  138.     case knight:
  139.     case bishop:
  140.     case queen:
  141.       break;
  142.     case rook:
  143.       if (Castle(ply + 1, side) > 0) {
  144.         if ((from == rook_A[side]) && (Castle(ply + 1, side) & 2)) {
  145.           Castle(ply + 1, side) &= 1;
  146.           HashCastle(1, side);
  147.         } else if ((from == rook_H[side]) && (Castle(ply + 1, side) & 1)) {
  148.           Castle(ply + 1, side) &= 2;
  149.           HashCastle(0, side);
  150.         }
  151.       }
  152.       break;
  153.     case king:
  154.       KingSQ(side) = to;
  155.       if (Castle(ply + 1, side) > 0) {
  156.         if (Castle(ply + 1, side) & 2)
  157.           HashCastle(1, side);
  158.         if (Castle(ply + 1, side) & 1)
  159.           HashCastle(0, side);
  160.         if (Abs(to - from) == 2) {
  161.           Castle(ply + 1, side) = -1;
  162.           piece = rook;
  163.           if (to == rook_G[side]) {
  164.             from = rook_H[side];
  165.             to = rook_F[side];
  166.           } else {
  167.             from = rook_A[side];
  168.             to = rook_D[side];
  169.           }
  170.           bit_move = SetMask(from) | SetMask(to);
  171.           ClearSet(bit_move, Rooks(side));
  172.           ClearSet(bit_move, Occupied(side));
  173.           Hash(side, rook, from);
  174.           Hash(side, rook, to);
  175.           PcOnSq(from) = 0;
  176.           PcOnSq(to) = pieces[side][rook];
  177.         } else
  178.           Castle(ply + 1, side) = 0;
  179.       }
  180.       break;
  181.   }
  182. /*
  183.  ************************************************************
  184.  *                                                          *
  185.  *  If this is a capture move, we also have to update the   *
  186.  *  information that must change when a piece is removed    *
  187.  *  from the board.                                         *
  188.  *                                                          *
  189.  ************************************************************
  190.  */
  191.   if (captured) {
  192.     Reversible(ply + 1) = 0;
  193.     TotalAllPieces--;
  194.     if (promote)
  195.       piece = promote;
  196.     Hash(enemy, captured, to);
  197.     Clear(to, Pieces(enemy, captured));
  198.     Clear(to, Occupied(enemy));
  199.     Material -= PieceValues(enemy, captured);
  200.     TotalPieces(enemy, captured)--;
  201.     if (captured != pawn)
  202.       TotalPieces(enemy, occupied) -= p_vals[captured];
  203.     switch (captured) {
  204.       case pawn:
  205.         HashP(enemy, to);
  206.         break;
  207.       case knight:
  208.       case bishop:
  209.         TotalMinors(enemy)--;
  210.         break;
  211.       case rook:
  212.         if (Castle(ply + 1, enemy) > 0) {
  213.           if ((to == rook_A[enemy]) && (Castle(ply + 1, enemy) & 2)) {
  214.             Castle(ply + 1, enemy) &= 1;
  215.             HashCastle(1, enemy);
  216.           } else if ((to == rook_H[enemy]) && (Castle(ply + 1, enemy) & 1)) {
  217.             Castle(ply + 1, enemy) &= 2;
  218.             HashCastle(0, enemy);
  219.           }
  220.         }
  221.         TotalMajors(enemy)--;
  222.         break;
  223.       case queen:
  224.         TotalMajors(enemy) -= 2;
  225.         break;
  226.       case king:
  227. #if defined(DEBUG)
  228.         Print(128, "captured a king (Make)\n");
  229.         for (i = 1; i <= ply; i++)
  230.           Print(128, "ply=%2d, piece=%2d,from=%2d,to=%2d,captured=%2d\n", i,
  231.               Piece(tree->curmv[i]), From(tree->curmv[i]), To(tree->curmv[i]),
  232.               Captured(tree->curmv[i]));
  233.         Print(128, "ply=%2d, piece=%2d,from=%2d,to=%2d,captured=%2d\n", i,
  234.             piece, from, to, captured);
  235.         if (log_file)
  236.           DisplayChessBoard(log_file, tree->position);
  237. #endif
  238.         break;
  239.     }
  240.   }
  241. #if defined(DEBUG)
  242.   ValidatePosition(tree, ply + 1, move, "MakeMove(2)");
  243. #endif
  244.   return;
  245. }
  246.  
  247. /* last modified 05/08/14 */
  248. /*
  249.  *******************************************************************************
  250.  *                                                                             *
  251.  *   MakeMoveRoot() is used to make a move at the root of the game tree,       *
  252.  *   before any searching is done.  It uses MakeMove() to execute the move,    *
  253.  *   but then copies the resulting position back to position[0], the actual    *
  254.  *   board position.  It handles the special-case of the draw-by-repetition    *
  255.  *   rule by clearing the repetition list when a non-reversible move is made,  *
  256.  *   since no repetitions are possible once such a move is played.             *
  257.  *                                                                             *
  258.  *******************************************************************************
  259.  */
  260. void MakeMoveRoot(TREE * RESTRICT tree, int move, int side) {
  261.   int player;
  262.  
  263. /*
  264.  ************************************************************
  265.  *                                                          *
  266.  *  First, make the move and then reset the repetition      *
  267.  *  index if the 50 move rule counter was reset to zero.    *
  268.  *                                                          *
  269.  ************************************************************
  270.  */
  271.   MakeMove(tree, 0, move, side);
  272.   if (Reversible(1) == 0)
  273.     tree->rep_index = -1;
  274.   tree->rep_list[++(tree->rep_index)] = HashKey;
  275. /*
  276.  ************************************************************
  277.  *                                                          *
  278.  *  One odd action is to note if the castle status is       *
  279.  *  currently negative, which indicates that that side      *
  280.  *  castled during the previous search.  We simply set the  *
  281.  *  castle status for that side to zero and we are done.    *
  282.  *                                                          *
  283.  *  We then copy this back to ply=0 status (which is the    *
  284.  *  permanent game-board ply).                              *
  285.  *                                                          *
  286.  ************************************************************
  287.  */
  288.   for (player = black; player <= white; player++)
  289.     Castle(1, player) = Max(0, Castle(1, player));
  290.   tree->status[0] = tree->status[1];
  291. }
  292.