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 | * 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 | */ |
||
| 14 | void UnmakeMove(TREE * RESTRICT tree, int ply, int move, int side) { |
||
| 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, and remove the current * |
||
| 23 | * position from the repetition list. * |
||
| 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. * |
||
| 52 | * * |
||
| 53 | ************************************************************ |
||
| 54 | */ |
||
| 55 | switch (piece) { |
||
| 56 | case pawn: |
||
| 57 | if (captured == 1) { |
||
| 58 | if (EnPassant(ply) == to) { |
||
| 59 | TotalAllPieces++; |
||
| 60 | Set(to + epsq[side], Pawns(enemy)); |
||
| 61 | Set(to + epsq[side], Occupied(enemy)); |
||
| 62 | PcOnSq(to + epsq[side]) = pieces[enemy][pawn]; |
||
| 63 | Material -= PieceValues(side, pawn); |
||
| 64 | TotalPieces(enemy, pawn)++; |
||
| 65 | captured = 0; |
||
| 66 | } |
||
| 67 | } |
||
| 68 | if (promote) { |
||
| 69 | TotalPieces(side, pawn)++; |
||
| 70 | Clear(to, Pawns(side)); |
||
| 71 | Clear(to, Occupied(side)); |
||
| 72 | Clear(to, Pieces(side, promote)); |
||
| 73 | Material -= PieceValues(side, promote); |
||
| 74 | Material += PieceValues(side, pawn); |
||
| 75 | TotalPieces(side, occupied) -= p_vals[promote]; |
||
| 76 | TotalPieces(side, promote)--; |
||
| 77 | switch (promote) { |
||
| 78 | case knight: |
||
| 79 | case bishop: |
||
| 80 | TotalMinors(side)--; |
||
| 81 | break; |
||
| 82 | case rook: |
||
| 83 | TotalMajors(side)--; |
||
| 84 | break; |
||
| 85 | case queen: |
||
| 86 | TotalMajors(side) -= 2; |
||
| 87 | break; |
||
| 88 | } |
||
| 89 | } |
||
| 90 | break; |
||
| 91 | case knight: |
||
| 92 | case bishop: |
||
| 93 | case rook: |
||
| 94 | case queen: |
||
| 95 | break; |
||
| 96 | case king: |
||
| 97 | KingSQ(side) = from; |
||
| 98 | if (Abs(to - from) == 2) { |
||
| 99 | if (to == rook_G[side]) { |
||
| 100 | from = rook_H[side]; |
||
| 101 | to = rook_F[side]; |
||
| 102 | } else { |
||
| 103 | from = rook_A[side]; |
||
| 104 | to = rook_D[side]; |
||
| 105 | } |
||
| 106 | bit_move = SetMask(from) | SetMask(to); |
||
| 107 | ClearSet(bit_move, Rooks(side)); |
||
| 108 | ClearSet(bit_move, Occupied(side)); |
||
| 109 | PcOnSq(to) = 0; |
||
| 110 | PcOnSq(from) = pieces[side][rook]; |
||
| 111 | } |
||
| 112 | break; |
||
| 113 | } |
||
| 114 | /* |
||
| 115 | ************************************************************ |
||
| 116 | * * |
||
| 117 | * Next we restore information related to a piece that was * |
||
| 118 | * captured and is now being returned to the board. * |
||
| 119 | * * |
||
| 120 | ************************************************************ |
||
| 121 | */ |
||
| 122 | if (captured) { |
||
| 123 | TotalAllPieces++; |
||
| 124 | Set(to, Pieces(enemy, captured)); |
||
| 125 | Set(to, Occupied(enemy)); |
||
| 126 | Material += PieceValues(enemy, captured); |
||
| 127 | PcOnSq(to) = pieces[enemy][captured]; |
||
| 128 | TotalPieces(enemy, captured)++; |
||
| 129 | if (captured != pawn) |
||
| 130 | TotalPieces(enemy, occupied) += p_vals[captured]; |
||
| 131 | switch (captured) { |
||
| 132 | case pawn: |
||
| 133 | break; |
||
| 134 | case knight: |
||
| 135 | case bishop: |
||
| 136 | TotalMinors(enemy)++; |
||
| 137 | break; |
||
| 138 | case rook: |
||
| 139 | TotalMajors(enemy)++; |
||
| 140 | break; |
||
| 141 | case queen: |
||
| 142 | TotalMajors(enemy) += 2; |
||
| 143 | break; |
||
| 144 | case king: |
||
| 145 | break; |
||
| 146 | } |
||
| 147 | } |
||
| 148 | #if defined(DEBUG) |
||
| 149 | ValidatePosition(tree, ply, move, "UnmakeMove(1)"); |
||
| 150 | #endif |
||
| 151 | return; |
||
| 152 | } |