ss << (sideToMove == WHITE ? " w " : " b ");
if (can_castle(WHITE_OO))
- ss << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE, KING_SIDE))))) : 'K');
+ ss << (chess960 ? file_to_char(file_of(castle_rook_square(WHITE, KING_SIDE)), false) : 'K');
if (can_castle(WHITE_OOO))
- ss << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE, QUEEN_SIDE))))) : 'Q');
+ ss << (chess960 ? file_to_char(file_of(castle_rook_square(WHITE, QUEEN_SIDE)), false) : 'Q');
if (can_castle(BLACK_OO))
- ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, KING_SIDE))) : 'k');
+ ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, KING_SIDE)), true) : 'k');
if (can_castle(BLACK_OOO))
- ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, QUEEN_SIDE))) : 'q');
+ ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, QUEEN_SIDE)), true) : 'q');
if (st->castleRights == CASTLES_NONE)
ss << '-';
pieceList[them][capture][index[lastSquare]] = lastSquare;
pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
- // Update hash keys
+ // Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[them][capture][capsq];
st->materialKey ^= Zobrist::psq[them][capture][pieceCount[them][capture]];
+ prefetch((char*)thisThread->materialTable[st->materialKey]);
// Update incremental scores
st->psqScore -= pieceSquareTable[make_piece(them, capture)][capsq];
st->castleRights &= ~cr;
}
- // Prefetch TT access as soon as we know key is updated
+ // Prefetch TT access as soon as we know the new hash key
prefetch((char*)TT.first_entry(k));
// Move the piece
st->npMaterial[us] += PieceValue[MG][promotion];
}
- // Update pawn hash key
+ // 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;
}
- // Prefetch pawn and material hash tables
- prefetch((char*)thisThread->pawnsTable[st->pawnKey]);
- prefetch((char*)thisThread->materialTable[st->materialKey]);
-
// Update incremental scores
st->psqScore += psq_delta(piece, from, to);
sideToMove = ~sideToMove;
if (type_of(m) == CASTLE)
- {
- do_castle_move<false>(m);
- return;
- }
+ return do_castle_move<false>(m);
Color us = sideToMove;
Color them = ~us;
assert(is_ok(m));
assert(type_of(m) == CASTLE);
- Square kto, kfrom, rfrom, rto, kAfter, rAfter;
-
Color us = sideToMove;
- Square kBefore = from_sq(m);
- Square rBefore = to_sq(m);
+ Square kfrom, kto, rfrom, rto;
- // Find after-castle squares for king and rook
- if (rBefore > kBefore) // O-O
+ bool kingSide = to_sq(m) > from_sq(m);
+ kfrom = kto = from_sq(m);
+ rfrom = rto = to_sq(m);
+
+ if (Do)
{
- kAfter = relative_square(us, SQ_G1);
- rAfter = relative_square(us, SQ_F1);
+ kto = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
+ rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
}
- else // O-O-O
+ else
{
- kAfter = relative_square(us, SQ_C1);
- rAfter = relative_square(us, SQ_D1);
+ kfrom = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
+ rfrom = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
}
- kfrom = Do ? kBefore : kAfter;
- rfrom = Do ? rBefore : rAfter;
-
- kto = Do ? kAfter : kBefore;
- rto = Do ? rAfter : rBefore;
-
assert(piece_on(kfrom) == make_piece(us, KING));
assert(piece_on(rfrom) == make_piece(us, ROOK));
byColorBB[us] ^= k_from_to_bb ^ r_from_to_bb;
// Update board
- Piece king = make_piece(us, KING);
- Piece rook = make_piece(us, ROOK);
board[kfrom] = board[rfrom] = NO_PIECE;
- board[kto] = king;
- board[rto] = rook;
+ board[kto] = make_piece(us, KING);
+ board[rto] = make_piece(us, ROOK);
// Update piece lists
pieceList[us][KING][index[kfrom]] = kto;
st->capturedType = NO_PIECE_TYPE;
// Update incremental scores
- st->psqScore += psq_delta(king, kfrom, kto);
- st->psqScore += psq_delta(rook, rfrom, rto);
+ st->psqScore += psq_delta(make_piece(us, KING), kfrom, kto);
+ st->psqScore += psq_delta(make_piece(us, ROOK), rfrom, rto);
// Update hash key
st->key ^= Zobrist::psq[us][KING][kfrom] ^ Zobrist::psq[us][KING][kto];
}
-/// Position::do_null_move() is used to do/undo a "null move": It flips the side
-/// to move and updates the hash key without executing any move on the board.
-template<bool Do>
-void Position::do_null_move(StateInfo& backupSt) {
+/// Position::do(undo)_null_move() is used to do(undo) a "null move": It flips
+/// the side to move without executing any move on the board.
- assert(!checkers());
+void Position::do_null_move(StateInfo& newSt) {
- // Back up the information necessary to undo the null move to the supplied
- // StateInfo object. Note that differently from normal case here backupSt
- // is actually used as a backup storage not as the new state. This reduces
- // the number of fields to be copied.
- StateInfo* src = Do ? st : &backupSt;
- StateInfo* dst = Do ? &backupSt : st;
+ assert(!checkers());
- dst->key = src->key;
- dst->epSquare = src->epSquare;
- dst->psqScore = src->psqScore;
- dst->rule50 = src->rule50;
- dst->pliesFromNull = src->pliesFromNull;
+ memcpy(&newSt, st, sizeof(StateInfo)); // Fully copy here
- sideToMove = ~sideToMove;
+ newSt.previous = st;
+ st = &newSt;
- if (Do)
+ if (st->epSquare != SQ_NONE)
{
- if (st->epSquare != SQ_NONE)
- st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
-
- st->key ^= Zobrist::side;
- prefetch((char*)TT.first_entry(st->key));
-
+ st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
st->epSquare = SQ_NONE;
- st->rule50++;
- st->pliesFromNull = 0;
}
+ st->key ^= Zobrist::side;
+ prefetch((char*)TT.first_entry(st->key));
+
+ st->rule50++;
+ st->pliesFromNull = 0;
+
+ sideToMove = ~sideToMove;
+
assert(pos_is_ok());
}
-// Explicit template instantiations
-template void Position::do_null_move<false>(StateInfo& backupSt);
-template void Position::do_null_move<true>(StateInfo& backupSt);
+void Position::undo_null_move() {
+
+ assert(!checkers());
+
+ st = st->previous;
+ sideToMove = ~sideToMove;
+}
/// Position::see() is a static exchange evaluator: It tries to estimate the