1 #include "chess.h"
2 #include "data.h"
3 /* last modified 01/06/16 */
4 /*
5  *******************************************************************************
6  *                                                                             *
7  *   UnmakeMove() is responsible for updating the position database whenever a *
8  *   move is retracted.  It is the exact inverse of MakeMove(). The hash       *
9  *   signature(s) are not updated, they are just restored to their status that *
10  *   was saved before the move was made, to save time.                         *
11  *                                                                             *
12  *******************************************************************************
13  */
UnmakeMove(TREE * RESTRICT tree,int ply,int side,int move)14 void UnmakeMove(TREE * RESTRICT tree, int ply, int side, int move) {
15   uint64_t bit_move;
16   int piece, from, to, captured, promote, enemy = Flip(side);
17 
18 /*
19  ************************************************************
20  *                                                          *
21  *  First, restore the hash signatures to their state prior *
22  *  to this move being made by simply copying the old       *
23  *  values.                                                 *
24  *                                                          *
25  ************************************************************
26  */
27   HashKey = tree->save_hash_key[ply];
28   PawnHashKey = tree->save_pawn_hash_key[ply];
29 /*
30  ************************************************************
31  *                                                          *
32  *  Now do the things that are common to all pieces, such   *
33  *  as updating the bitboards and hash signature.           *
34  *                                                          *
35  ************************************************************
36  */
37   piece = Piece(move);
38   from = From(move);
39   to = To(move);
40   captured = Captured(move);
41   promote = Promote(move);
42   bit_move = SetMask(from) | SetMask(to);
43   ClearSet(bit_move, Pieces(side, piece));
44   ClearSet(bit_move, Occupied(side));
45   PcOnSq(to) = 0;
46   PcOnSq(from) = pieces[side][piece];
47 /*
48  ************************************************************
49  *                                                          *
50  *  Now do the piece-specific things by jumping to the      *
51  *  appropriate routine (this only has to deal with pawns   *
52  *  and king moves that are castling moves.                 *
53  *                                                          *
54  ************************************************************
55  */
56   switch (piece) {
57     case pawn:
58       if (captured == 1) {
59         if (EnPassant(ply) == to) {
60           TotalAllPieces++;
61           Set(to + epsq[side], Pawns(enemy));
62           Set(to + epsq[side], Occupied(enemy));
63           PcOnSq(to + epsq[side]) = pieces[enemy][pawn];
64           Material -= PieceValues(side, pawn);
65           TotalPieces(enemy, pawn)++;
66           captured = 0;
67         }
68       }
69       if (promote) {
70         TotalPieces(side, pawn)++;
71         Clear(to, Pawns(side));
72         Clear(to, Occupied(side));
73         Clear(to, Pieces(side, promote));
74         Material -= PieceValues(side, promote);
75         Material += PieceValues(side, pawn);
76         TotalPieces(side, occupied) -= p_vals[promote];
77         TotalPieces(side, promote)--;
78       }
79       break;
80     case knight:
81     case bishop:
82     case rook:
83     case queen:
84       break;
85     case king:
86       KingSQ(side) = from;
87       if (Abs(to - from) == 2) {
88         if (to == rook_G[side]) {
89           from = rook_H[side];
90           to = rook_F[side];
91         } else {
92           from = rook_A[side];
93           to = rook_D[side];
94         }
95         bit_move = SetMask(from) | SetMask(to);
96         ClearSet(bit_move, Rooks(side));
97         ClearSet(bit_move, Occupied(side));
98         PcOnSq(to) = 0;
99         PcOnSq(from) = pieces[side][rook];
100       }
101       break;
102   }
103 /*
104  ************************************************************
105  *                                                          *
106  *  Next we restore information related to a piece that was *
107  *  captured and is now being returned to the board.        *
108  *                                                          *
109  ************************************************************
110  */
111   if (captured) {
112     TotalAllPieces++;
113     Set(to, Pieces(enemy, captured));
114     Set(to, Occupied(enemy));
115     Material += PieceValues(enemy, captured);
116     PcOnSq(to) = pieces[enemy][captured];
117     TotalPieces(enemy, captured)++;
118     if (captured != pawn)
119       TotalPieces(enemy, occupied) += p_vals[captured];
120   }
121 #if defined(DEBUG)
122   ValidatePosition(tree, ply, move, "UnmakeMove(1)");
123 #endif
124   return;
125 }
126