- // Move the pieces
- Bitboard kmove_bb = make_move_bb(kfrom, kto);
- do_move_bb(&(byColorBB[us]), kmove_bb);
- do_move_bb(&(byTypeBB[KING]), kmove_bb);
- do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares
-
- Bitboard rmove_bb = make_move_bb(rfrom, rto);
- do_move_bb(&(byColorBB[us]), rmove_bb);
- do_move_bb(&(byTypeBB[ROOK]), rmove_bb);
- do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares
-
- // Update board array
- Piece king = piece_of_color_and_type(us, KING);
- Piece rook = piece_of_color_and_type(us, ROOK);
- board[kfrom] = board[rfrom] = EMPTY;
- board[kto] = king;
- board[rto] = rook;
-
- // Update piece lists
- pieceList[us][KING][index[kfrom]] = kto;
- pieceList[us][ROOK][index[rfrom]] = rto;
- int tmp = index[rfrom]; // In Chess960 could be rto == kfrom
- index[kto] = index[kfrom];
- index[rto] = tmp;
+ // If the moving piece is a pawn do some special extra work
+ if (pt == PAWN)
+ {
+ // Set en-passant square, only if moved pawn can be captured
+ if ( (int(to) ^ int(from)) == 16
+ && (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(them, PAWN)))
+ {
+ st->epSquare = Square((from + to) / 2);
+ k ^= Zobrist::enpassant[file_of(st->epSquare)];
+ }
+
+ if (type_of(m) == PROMOTION)
+ {
+ PieceType promotion = promotion_type(m);
+
+ assert(relative_rank(us, to) == RANK_8);
+ assert(promotion >= KNIGHT && promotion <= QUEEN);
+
+ // Replace the pawn with the promoted piece
+ byTypeBB[PAWN] ^= to;
+ byTypeBB[promotion] |= to;
+ board[to] = make_piece(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 lastSquare = pieceList[us][PAWN][--pieceCount[us][PAWN]];
+ index[lastSquare] = index[to];
+ pieceList[us][PAWN][index[lastSquare]] = lastSquare;
+ pieceList[us][PAWN][pieceCount[us][PAWN]] = SQ_NONE;
+ index[to] = pieceCount[us][promotion];
+ pieceList[us][promotion][index[to]] = to;
+
+ // Update hash keys
+ k ^= Zobrist::psq[us][PAWN][to] ^ Zobrist::psq[us][promotion][to];
+ st->pawnKey ^= Zobrist::psq[us][PAWN][to];
+ st->materialKey ^= Zobrist::psq[us][promotion][pieceCount[us][promotion]++]
+ ^ Zobrist::psq[us][PAWN][pieceCount[us][PAWN]];
+
+ // Update incremental score
+ st->psqScore += pieceSquareTable[make_piece(us, promotion)][to]
+ - pieceSquareTable[make_piece(us, PAWN)][to];
+
+ // Update material
+ st->npMaterial[us] += PieceValue[MG][promotion];
+ }
+
+ // Update pawn hash key and prefetch access to pawnsTable
+ st->pawnKey ^= Zobrist::psq[us][PAWN][from] ^ Zobrist::psq[us][PAWN][to];
+ prefetch((char*)thisThread->pawnsTable[st->pawnKey]);
+
+ // Reset rule 50 draw counter
+ st->rule50 = 0;
+ }