Subversion Repositories Games.Chess Giants

Rev

Rev 33 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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