#include "chess.h"
#include "data.h"
/* last modified 02/22/14 */
/*
*******************************************************************************
* *
* UnmakeMove() is responsible for updating the position database whenever a *
* move is retracted. It is the exact inverse of MakeMove(). The hash *
* signature(s) are not updated, they are just restored to their status that *
* was saved before the move was made, to save time. *
* *
*******************************************************************************
*/
void UnmakeMove(TREE * RESTRICT tree, int ply, int move, int side) {
uint64_t bit_move;
int piece, from, to, captured, promote, enemy = Flip(side);
/*
************************************************************
* *
* First, restore the hash signatures to their state prior *
* to this move being made, and remove the current *
* position from the repetition list. *
* *
************************************************************
*/
HashKey = tree->save_hash_key[ply];
PawnHashKey = tree->save_pawn_hash_key[ply];
/*
************************************************************
* *
* Now do the things that are common to all pieces, such *
* as updating the bitboards and hash signature. *
* *
************************************************************
*/
piece = Piece(move);
from = From(move);
to = To(move);
captured = Captured(move);
promote = Promote(move);
bit_move = SetMask(from) | SetMask(to);
ClearSet(bit_move, Pieces(side, piece));
ClearSet(bit_move, Occupied(side));
PcOnSq(to) = 0;
PcOnSq(from) = pieces[side][piece];
/*
************************************************************
* *
* Now do the piece-specific things by jumping to the *
* appropriate routine. *
* *
************************************************************
*/
switch (piece) {
case pawn:
if (captured == 1) {
if (EnPassant(ply) == to) {
TotalAllPieces++;
Set(to + epsq[side], Pawns(enemy));
Set(to + epsq[side], Occupied(enemy));
PcOnSq(to + epsq[side]) = pieces[enemy][pawn];
Material -= PieceValues(side, pawn);
TotalPieces(enemy, pawn)++;
captured = 0;
}
}
if (promote) {
TotalPieces(side, pawn)++;
Clear(to, Pawns(side));
Clear(to, Occupied(side));
Clear(to, Pieces(side, promote));
Material -= PieceValues(side, promote);
Material += PieceValues(side, pawn);
TotalPieces(side, occupied) -= p_vals[promote];
TotalPieces(side, promote)--;
switch (promote) {
case knight:
case bishop:
TotalMinors(side)--;
break;
case rook:
TotalMajors(side)--;
break;
case queen:
TotalMajors(side) -= 2;
break;
}
}
break;
case knight:
case bishop:
case rook:
case queen:
break;
case king:
KingSQ(side) = from;
if (Abs(to - from) == 2) {
if (to == rook_G[side]) {
from = rook_H[side];
to = rook_F[side];
} else {
from = rook_A[side];
to = rook_D[side];
}
bit_move = SetMask(from) | SetMask(to);
ClearSet(bit_move, Rooks(side));
ClearSet(bit_move, Occupied(side));
PcOnSq(to) = 0;
PcOnSq(from) = pieces[side][rook];
}
break;
}
/*
************************************************************
* *
* Next we restore information related to a piece that was *
* captured and is now being returned to the board. *
* *
************************************************************
*/
if (captured) {
TotalAllPieces++;
Set(to, Pieces(enemy, captured));
Set(to, Occupied(enemy));
Material += PieceValues(enemy, captured);
PcOnSq(to) = pieces[enemy][captured];
TotalPieces(enemy, captured)++;
if (captured != pawn)
TotalPieces(enemy, occupied) += p_vals[captured];
switch (captured) {
case pawn:
break;
case knight:
case bishop:
TotalMinors(enemy)++;
break;
case rook:
TotalMajors(enemy)++;
break;
case queen:
TotalMajors(enemy) += 2;
break;
case king:
break;
}
}
#if defined(DEBUG)
ValidatePosition(tree, ply, move, "UnmakeMove(1)");
#endif
return;
}