Subversion Repositories Games.Chess Giants

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
33 pmbaty 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
}