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