- // Update incremental scores
- mgValue -= mg_pst(us, piece, from);
- mgValue += mg_pst(us, piece, to);
- egValue -= eg_pst(us, piece, from);
- egValue += eg_pst(us, piece, to);
-
- // If the moving piece was a king, update the king square
- if (piece == KING)
- kingSquare[us] = to;
-
- // If the move was a double pawn push, set the en passant square.
- // This code is a bit ugly right now, and should be cleaned up later.
- // FIXME
- if (epSquare != SQ_NONE)
- {
- key ^= zobEp[epSquare];
- epSquare = SQ_NONE;
- }
- if (piece == PAWN)
- {
- if (abs(int(to) - int(from)) == 16)
- {
- if( ( us == WHITE
- && (pawn_attacks(WHITE, from + DELTA_N) & pawns(BLACK)))
- || ( us == BLACK
- && (pawn_attacks(BLACK, from + DELTA_S) & pawns(WHITE))))
- {
- epSquare = Square((int(from) + int(to)) / 2);
- key ^= zobEp[epSquare];
- }
- }
- // Reset rule 50 draw counter
- rule50 = 0;
-
- // Update pawn hash key
- pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
- }
- // Update piece lists
- pieceList[us][piece][index[from]] = to;
- index[to] = index[from];
-
- // Update castle rights
- key ^= zobCastle[castleRights];
- castleRights &= castleRightsMask[from];
- castleRights &= castleRightsMask[to];
- key ^= zobCastle[castleRights];
-
- // Update checkers bitboard
- checkersBB = EmptyBoardBB;
- Square ksq = king_square(them);
- switch (piece)
- {
- case PAWN:
- if (bit_is_set(pawn_attacks(them, ksq), to))
- set_bit(&checkersBB, to);
-
- if (bit_is_set(dcCandidates, from))
- checkersBB |= ( (piece_attacks<ROOK>(ksq) & rooks_and_queens(us))
- |(piece_attacks<BISHOP>(ksq) & bishops_and_queens(us)));
- break;
-
- case KNIGHT:
- if (bit_is_set(piece_attacks<KNIGHT>(ksq), to))
- set_bit(&checkersBB, to);
-
- if (bit_is_set(dcCandidates, from))
- checkersBB |= ( (piece_attacks<ROOK>(ksq) & rooks_and_queens(us))
- |(piece_attacks<BISHOP>(ksq) & bishops_and_queens(us)));
- break;
-
- case BISHOP:
- if (bit_is_set(piece_attacks<BISHOP>(ksq), to))
- set_bit(&checkersBB, to);
-
- if (bit_is_set(dcCandidates, from))
- checkersBB |= (piece_attacks<ROOK>(ksq) & rooks_and_queens(us));
- break;
-
- case ROOK:
- if (bit_is_set(piece_attacks<ROOK>(ksq), to))
- set_bit(&checkersBB, to);
-
- if (bit_is_set(dcCandidates, from))
- checkersBB |= (piece_attacks<BISHOP>(ksq) & bishops_and_queens(us));
- break;
-
- case QUEEN:
- if (bit_is_set(piece_attacks<QUEEN>(ksq), to))
- set_bit(&checkersBB, to);
- break;
-
- case KING:
- if (bit_is_set(dcCandidates, from))
- checkersBB |= ( (piece_attacks<ROOK>(ksq) & rooks_and_queens(us))
- |(piece_attacks<BISHOP>(ksq) & bishops_and_queens(us)));
- break;
-
- default:
- assert(false);
- break;
- }
+ // If the moving piece was a pawn do some special extra work
+ if (pt == PAWN)
+ {
+ // Reset rule 50 draw counter
+ st->rule50 = 0;
+
+ // Update pawn hash key
+ st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
+
+ // Set en passant square, only if moved pawn can be captured
+ if (abs(int(to) - int(from)) == 16)
+ {
+ if (pawn_attacks_from(from + (us == WHITE ? DELTA_N : DELTA_S), us) & pieces(PAWN, them))
+ {
+ st->epSquare = Square((int(from) + int(to)) / 2);
+ key ^= zobEp[st->epSquare];
+ }
+ }
+ }
+
+ // Update incremental scores
+ st->mgValue += pst_delta<MidGame>(piece, from, to);
+ st->egValue += pst_delta<EndGame>(piece, from, to);
+
+ if (pm) // promotion ?
+ {
+ PieceType promotion = move_promotion_piece(m);
+
+ assert(promotion >= KNIGHT && promotion <= QUEEN);
+
+ // Insert promoted piece instead of pawn
+ clear_bit(&(byTypeBB[PAWN]), to);
+ set_bit(&(byTypeBB[promotion]), to);
+ board[to] = piece_of_color_and_type(us, promotion);
+
+ // Update material key
+ st->materialKey ^= zobMaterial[us][PAWN][pieceCount[us][PAWN]];
+ st->materialKey ^= zobMaterial[us][promotion][pieceCount[us][promotion]+1];
+
+ // Update piece counts
+ pieceCount[us][PAWN]--;
+ pieceCount[us][promotion]++;
+
+ // Update piece lists, move the last pawn at index[to] position
+ // and shrink the list. Add a new promotion piece to the list.
+ Square lastPawnSquare = pieceList[us][PAWN][pieceCount[us][PAWN]];
+ index[lastPawnSquare] = index[to];
+ pieceList[us][PAWN][index[lastPawnSquare]] = lastPawnSquare;
+ index[to] = pieceCount[us][promotion] - 1;
+ pieceList[us][promotion][index[to]] = to;
+
+ // Partially revert hash keys update
+ key ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
+ st->pawnKey ^= zobrist[us][PAWN][to];
+
+ // Partially revert and update incremental scores
+ st->mgValue -= pst<MidGame>(us, PAWN, to);
+ st->mgValue += pst<MidGame>(us, promotion, to);
+ st->egValue -= pst<EndGame>(us, PAWN, to);
+ st->egValue += pst<EndGame>(us, promotion, to);
+
+ // Update material
+ st->npMaterial[us] += piece_value_midgame(promotion);
+ }
+
+ // Update the key with the final value
+ st->key = key;
+
+ // Update checkers bitboard, piece must be already moved
+ if (ep | pm)
+ st->checkersBB = attackers_to(king_square(them), us);
+ else
+ {
+ st->checkersBB = EmptyBoardBB;
+ Square ksq = king_square(them);
+ switch (pt)
+ {
+ case PAWN: update_checkers<PAWN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+ case KNIGHT: update_checkers<KNIGHT>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+ case BISHOP: update_checkers<BISHOP>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+ case ROOK: update_checkers<ROOK>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+ case QUEEN: update_checkers<QUEEN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+ case KING: update_checkers<KING>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+ default: assert(false); break;
+ }