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 | } |