- // Move the piece:
- clear_bit(&(byColorBB[us]), from);
- clear_bit(&(byTypeBB[piece]), from);
- clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
- set_bit(&(byColorBB[us]), to);
- set_bit(&(byTypeBB[piece]), to);
- set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
- board[to] = board[from];
- board[from] = EMPTY;
-
- // Update hash key:
- key ^= zobrist[us][piece][from] ^ zobrist[us][piece][to];
-
- // 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];
- }
+ // 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;
+ pieceList[us][PAWN][pieceCount[us][PAWN]] = SQ_NONE;
+ 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)) & pieces_of_color(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;