/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2009 Marco Costalba
+ Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
//// Variables
////
-int Position::castleRightsMask[64];
-
Key Position::zobrist[2][8][64];
Key Position::zobEp[64];
Key Position::zobCastle[16];
-Key Position::zobMaterial[2][8][16];
Key Position::zobSideToMove;
Key Position::zobExclusion;
Position::Position(const Position& pos) {
- fast_copy(pos);
+ memcpy(this, &pos, sizeof(Position));
detach(); // Always detach() in copy c'tor to avoid surprises
}
}
-/// Position::fast_copy() creates a partial copy of the given position,
-/// only data that changes with a do_move() / undo_move() cycle is copied,
-/// in particular for stateInfo are copied only the pointers, so that the
-/// actual data remains stored in the parent Position. This is not a problem
-/// if the parent Position is known not to be destroyed while we are still alive,
-/// as is the common case, see detach() otherwise.
-
-void Position::fast_copy(const Position& pos) {
-
- memcpy(this, &pos, sizeof(Position));
-}
-
-
/// Position::detach() copies the content of the current state and castling
/// masks inside the position itself. This is needed when the st pointee could
/// become stale, as example because the caller is about to going out of scope.
assert(is_ok());
assert(move_is_ok(m));
- Bitboard key = st->key;
+ Key key = st->key;
// Copy some fields of old state to our new StateInfo object except the
// ones which are recalculated from scratch anyway, then switch our state
// pointer to point to the new, ready to be updated, state.
struct ReducedStateInfo {
Key pawnKey, materialKey;
- int castleRights, rule50, pliesFromNull;
+ int castleRights, rule50, ply, pliesFromNull;
Square epSquare;
Score value;
Value npMaterial[2];
// Save the current key to the history[] array, in order to be able to
// detect repetition draws.
- history[gamePly] = key;
- gamePly++;
+ history[st->ply++] = key;
// Update side to move
key ^= zobSideToMove;
key ^= zobEp[st->epSquare];
}
}
+
+ 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 piece counts
+ pieceCount[us][promotion]++;
+ pieceCount[us][PAWN]--;
+
+ // Update material key
+ st->materialKey ^= zobrist[us][PAWN][pieceCount[us][PAWN]];
+ st->materialKey ^= zobrist[us][promotion][pieceCount[us][promotion]-1];
+
+ // 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->value -= pst(us, PAWN, to);
+ st->value += pst(us, promotion, to);
+
+ // Update material
+ st->npMaterial[us] += piece_value_midgame(promotion);
+ }
}
// Update incremental scores
// Set capture piece
st->capture = capture;
- 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->value -= pst(us, PAWN, to);
- st->value += pst(us, promotion, to);
-
- // Update material
- st->npMaterial[us] += piece_value_midgame(promotion);
- }
-
// Update the key with the final value
st->key = key;
/// Position::do_capture_move() is a private method used to update captured
/// piece info. It is called from the main Position::do_move function.
-void Position::do_capture_move(Bitboard& key, PieceType capture, Color them, Square to, bool ep) {
+void Position::do_capture_move(Key& key, PieceType capture, Color them, Square to, bool ep) {
assert(capture != KING);
Square capsq = to;
- if (ep) // en passant ?
+ // If the captured piece was a pawn, update pawn hash key,
+ // otherwise update non-pawn material.
+ if (capture == PAWN)
{
- capsq = (them == BLACK)? (to - DELTA_N) : (to - DELTA_S);
+ if (ep) // en passant ?
+ {
+ capsq = (them == BLACK)? (to - DELTA_N) : (to - DELTA_S);
- assert(to == st->epSquare);
- assert(relative_rank(opposite_color(them), to) == RANK_6);
- assert(piece_on(to) == EMPTY);
- assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN));
+ assert(to == st->epSquare);
+ assert(relative_rank(opposite_color(them), to) == RANK_6);
+ assert(piece_on(to) == EMPTY);
+ assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN));
- board[capsq] = EMPTY;
+ board[capsq] = EMPTY;
+ }
+ st->pawnKey ^= zobrist[them][PAWN][capsq];
}
+ else
+ st->npMaterial[them] -= piece_value_midgame(capture);
// Remove captured piece
clear_bit(&(byColorBB[them]), capsq);
// Update incremental scores
st->value -= pst(them, capture, capsq);
- // If the captured piece was a pawn, update pawn hash key,
- // otherwise update non-pawn material.
- if (capture == PAWN)
- st->pawnKey ^= zobrist[them][PAWN][capsq];
- else
- st->npMaterial[them] -= piece_value_midgame(capture);
-
- // Update material hash key
- st->materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]];
-
// Update piece count
pieceCount[them][capture]--;
+ // Update material hash key
+ st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]];
+
// Update piece list, move the last piece at index[capsq] position
//
// WARNING: This is a not perfectly revresible operation. When we
assert(is_ok());
assert(move_is_ok(m));
- gamePly--;
sideToMove = opposite_color(sideToMove);
if (move_is_castle(m))
pieceList[us][PAWN][index[to]] = to;
}
-
// Put the piece back at the source square
Bitboard move_bb = make_move_bb(to, from);
do_move_bb(&(byColorBB[us]), move_bb);
// Save the current key to the history[] array, in order to be able to
// detect repetition draws.
- history[gamePly] = st->key;
+ history[st->ply++] = st->key;
// Update the necessary information
if (st->epSquare != SQ_NONE)
st->rule50++;
st->pliesFromNull = 0;
st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue;
- gamePly++;
}
// Update the necessary information
sideToMove = opposite_color(sideToMove);
st->rule50--;
- gamePly--;
+ st->ply--;
}
-///
-PieceType Position::captured_piece() const {
- return st->capture;
-}
-
/// Position::see() is a static exchange evaluator: It tries to estimate the
/// material gain or loss resulting from a move. There are three versions of
/// this function: One which takes a destination square as input, one takes a
pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE;
sideToMove = WHITE;
- gamePly = 0;
initialKFile = FILE_E;
initialKRFile = FILE_H;
initialQRFile = FILE_A;
}
-/// Position::reset_game_ply() simply sets gamePly to 0. It is used from the
+/// Position::reset_ply() simply sets ply to 0. It is used from the
/// UCI interface code, whenever a non-reversible move is made in a
/// 'position fen <fen> moves m1 m2 ...' command. This makes it possible
/// for the program to handle games of arbitrary length, as long as the GUI
/// handles draws by the 50 move rule correctly.
-void Position::reset_game_ply() {
+void Position::reset_ply() {
- gamePly = 0;
+ st->ply = 0;
}
for (PieceType pt = PAWN; pt <= QUEEN; pt++)
{
int count = piece_count(c, pt);
- for (int i = 0; i <= count; i++)
- result ^= zobMaterial[c][pt][i];
+ for (int i = 0; i < count; i++)
+ result ^= zobrist[c][pt][i];
}
return result;
}
if (st->rule50 > 100 || (st->rule50 == 100 && !is_check()))
return true;
+ assert(st->ply >= st->rule50);
+
// Draw by repetition?
- for (int i = 4; i <= Min(Min(gamePly, st->rule50), st->pliesFromNull); i += 2)
- if (history[gamePly - i] == st->key)
+ for (int i = 4, e = Min(st->rule50, st->pliesFromNull); i <= e; i += 2)
+ if (history[st->ply - i] == st->key)
return true;
return false;
zobCastle[i] = genrand_int64();
zobSideToMove = genrand_int64();
-
- for (int i = 0; i < 2; i++)
- for (int j = 0; j < 8; j++)
- for (int k = 0; k < 16; k++)
- zobMaterial[i][j][k] = (k > 0)? Key(genrand_int64()) : Key(0LL);
-
- for (int i = 0; i < 16; i++)
- zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = Key(0ULL);
-
zobExclusion = genrand_int64();
}