#include <fstream>
#include <iostream>
+#include "bitcount.h"
#include "mersenne.h"
#include "movegen.h"
#include "movepick.h"
/// Position::copy() creates a copy of the input position.
-void Position::copy(const Position &pos) {
+void Position::copy(const Position& pos) {
memcpy(this, &pos, sizeof(Position));
+ saveState(); // detach and copy state info
}
&& (direction_between_squares(from, ksq) != direction_between_squares(to, ksq)))
return true;
- if (move_promotion(m)) // Promotion with check?
+ if (move_is_promotion(m)) // Promotion with check?
{
Bitboard b = occupied_squares();
clear_bit(&b, from);
- switch (move_promotion(m))
+ switch (move_promotion_piece(m))
{
case KNIGHT:
return bit_is_set(piece_attacks<KNIGHT>(to), ksq);
if (move_is_castle(m))
do_castle_move(m);
- else if (move_promotion(m))
+ else if (move_is_promotion(m))
do_promotion_move(m);
else if (move_is_ep(m))
do_ep_move(m);
assert(color_of_piece_on(from) == us);
assert(color_of_piece_on(to) == them || piece_on(to) == EMPTY);
- PieceType piece = type_of_piece_on(from);
+ Piece piece = piece_on(from);
+ PieceType pt = type_of_piece(piece);
st->capture = type_of_piece_on(to);
// Move the piece
Bitboard move_bb = make_move_bb(from, to);
do_move_bb(&(byColorBB[us]), move_bb);
- do_move_bb(&(byTypeBB[piece]), move_bb);
+ do_move_bb(&(byTypeBB[pt]), move_bb);
do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
board[to] = board[from];
board[from] = EMPTY;
// Update hash key
- st->key ^= zobrist[us][piece][from] ^ zobrist[us][piece][to];
+ st->key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
// Update incremental scores
- st->mgValue -= pst<MidGame>(us, piece, from);
- st->mgValue += pst<MidGame>(us, piece, to);
- st->egValue -= pst<EndGame>(us, piece, from);
- st->egValue += pst<EndGame>(us, piece, to);
+ st->mgValue += pst_delta<MidGame>(piece, from, to);
+ st->egValue += pst_delta<EndGame>(piece, from, to);
// If the moving piece was a king, update the king square
- if (piece == KING)
+ if (pt == KING)
kingSquare[us] = to;
// Reset en passant square
}
// If the moving piece was a pawn do some special extra work
- if (piece == PAWN)
+ if (pt == PAWN)
{
// Reset rule 50 draw counter
st->rule50 = 0;
}
// Update piece lists
- pieceList[us][piece][index[from]] = to;
+ pieceList[us][pt][index[from]] = to;
index[to] = index[from];
- // Update castle rights
- st->key ^= zobCastle[st->castleRights];
- st->castleRights &= castleRightsMask[from];
- st->castleRights &= castleRightsMask[to];
- st->key ^= zobCastle[st->castleRights];
+ // Update castle rights, try to shortcut a common case
+ if ((castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
+ {
+ st->key ^= zobCastle[st->castleRights];
+ st->castleRights &= castleRightsMask[from];
+ st->castleRights &= castleRightsMask[to];
+ st->key ^= zobCastle[st->castleRights];
+ }
// Update checkers bitboard, piece must be already moved
st->checkersBB = EmptyBoardBB;
Square ksq = king_square(them);
- switch (piece)
+ 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;
set_bit(&(byTypeBB[0]), rto); // 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] = piece_of_color_and_type(us, KING);
- board[rto] = piece_of_color_and_type(us, ROOK);
+ board[kto] = king;
+ board[rto] = rook;
// Update king square
kingSquare[us] = kto;
index[rto] = tmp;
// Update incremental scores
- st->mgValue -= pst<MidGame>(us, KING, kfrom);
- st->mgValue += pst<MidGame>(us, KING, kto);
- st->egValue -= pst<EndGame>(us, KING, kfrom);
- st->egValue += pst<EndGame>(us, KING, kto);
- st->mgValue -= pst<MidGame>(us, ROOK, rfrom);
- st->mgValue += pst<MidGame>(us, ROOK, rto);
- st->egValue -= pst<EndGame>(us, ROOK, rfrom);
- st->egValue += pst<EndGame>(us, ROOK, rto);
+ st->mgValue += pst_delta<MidGame>(king, kfrom, kto);
+ st->egValue += pst_delta<EndGame>(king, kfrom, kto);
+ st->mgValue += pst_delta<MidGame>(rook, rfrom, rto);
+ st->egValue += pst_delta<EndGame>(rook, rfrom, rto);
// Update hash key
st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto];
assert(is_ok());
assert(move_is_ok(m));
- assert(move_promotion(m));
+ assert(move_is_promotion(m));
us = side_to_move();
them = opposite_color(us);
board[from] = EMPTY;
// Insert promoted piece
- promotion = move_promotion(m);
+ promotion = move_promotion_piece(m);
assert(promotion >= KNIGHT && promotion <= QUEEN);
set_bit(&(byColorBB[us]), to);
set_bit(&(byTypeBB[promotion]), to);
st->pawnKey ^= zobrist[them][PAWN][capsq];
// Update incremental scores
+ Piece pawn = piece_of_color_and_type(us, PAWN);
+ st->mgValue += pst_delta<MidGame>(pawn, from, to);
+ st->egValue += pst_delta<EndGame>(pawn, from, to);
st->mgValue -= pst<MidGame>(them, PAWN, capsq);
- st->mgValue -= pst<MidGame>(us, PAWN, from);
- st->mgValue += pst<MidGame>(us, PAWN, to);
st->egValue -= pst<EndGame>(them, PAWN, capsq);
- st->egValue -= pst<EndGame>(us, PAWN, from);
- st->egValue += pst<EndGame>(us, PAWN, to);
// Reset en passant square
st->epSquare = SQ_NONE;
if (move_is_castle(m))
undo_castle_move(m);
- else if (move_promotion(m))
+ else if (move_is_promotion(m))
undo_promotion_move(m);
else if (move_is_ep(m))
undo_ep_move(m);
PieceType promotion;
assert(move_is_ok(m));
- assert(move_promotion(m));
+ assert(move_is_promotion(m));
// When we have arrived here, some work has already been done by
// Position::undo_move. In particular, the side to move has been switched,
assert(piece_on(from) == EMPTY);
// Remove promoted piece
- promotion = move_promotion(m);
+ promotion = move_promotion_piece(m);
assert(piece_on(to)==piece_of_color_and_type(us, promotion));
assert(promotion >= KNIGHT && promotion <= QUEEN);
clear_bit(&(byColorBB[us]), to);
if (pt == KING && stmAttackers)
{
assert(n < 32);
- swapList[n++] = 100;
+ swapList[n++] = QueenValueMidgame*10;
break;
}
} while (stmAttackers);
}
-/// Position::setStartState() copies the content of the argument
+/// Position::saveState() copies the content of the current state
/// inside startState and makes st point to it. This is needed
/// when the st pointee could become stale, as example because
/// the caller is about to going out of scope.
-void Position::setStartState(const StateInfo& s) {
+void Position::saveState() {
- startState = s;
+ startState = *st;
st = &startState;
+ st->previous = NULL; // as a safe guard
}
/// the white and black sides reversed. This is only useful for debugging,
/// especially for finding evaluation symmetry bugs.
-void Position::flipped_copy(const Position &pos) {
+void Position::flipped_copy(const Position& pos) {
assert(pos.is_ok());