Rev 33 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 33 | pmbaty | 1 | #include "chess.h" | 
| 2 | #include "data.h" | ||
| 108 | pmbaty | 3 | /* last modified 01/06/16 */ | 
| 33 | pmbaty | 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 |  */ | ||
| 108 | pmbaty | 14 | void UnmakeMove(TREE * RESTRICT tree, int ply, int side, int move) { | 
| 33 | pmbaty | 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 * | ||
| 108 | pmbaty | 22 |  *  to this move being made by simply copying the old       * | 
| 23 |  *  values.                                                 * | ||
| 33 | pmbaty | 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      * | ||
| 108 | pmbaty | 51 |  *  appropriate routine (this only has to deal with pawns   * | 
| 52 |  *  and king moves that are castling moves.                 * | ||
| 33 | pmbaty | 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 | } |