// pointer to point to the new, ready to be updated, state.
struct ReducedStateInfo {
Key key, pawnKey, materialKey;
- int castleRights, rule50;
+ int castleRights, rule50, pliesFromNull;
Square epSquare;
Value mgValue, egValue;
Value npMaterial[2];
// Increment the 50 moves rule draw counter. Resetting it to zero in the
// case of non-reversible moves is taken care of later.
st->rule50++;
+ st->pliesFromNull++;
if (move_is_castle(m))
{
// Note that differently from normal case here backupSt is actually used as
// a backup storage not as a new state to be used.
backupSt.key = st->key;
- backupSt.rule50 = st->rule50;
backupSt.epSquare = st->epSquare;
backupSt.mgValue = st->mgValue;
backupSt.egValue = st->egValue;
backupSt.previous = st->previous;
+ backupSt.pliesFromNull = st->pliesFromNull;
st->previous = &backupSt;
// Save the current key to the history[] array, in order to be able to
sideToMove = opposite_color(sideToMove);
st->epSquare = SQ_NONE;
- st->rule50 = 0;
+ st->rule50++;
+ st->pliesFromNull = 0;
gamePly++;
st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
// Restore information from the our backup StateInfo object
StateInfo* backupSt = st->previous;
st->key = backupSt->key;
- st->rule50 = backupSt->rule50;
st->epSquare = backupSt->epSquare;
st->mgValue = backupSt->mgValue;
st->egValue = backupSt->egValue;
st->previous = backupSt->previous;
+ st->pliesFromNull = backupSt->pliesFromNull;
// Update the necessary information
sideToMove = opposite_color(sideToMove);
+ st->rule50--;
gamePly--;
}
int Position::see(Square to) const {
assert(square_is_ok(to));
- return see(SQ_NONE, to);
+ return see(SQ_NONE, to, false);
}
int Position::see(Move m) const {
assert(move_is_ok(m));
- return see(move_from(m), move_to(m));
+ return see(move_from(m), move_to(m), false);
}
int Position::see_sign(Move m) const {
&& type_of_piece_on(from) != KING)
return 1;
- return see(from, to);
+ return see(from, to, true);
}
-int Position::see(Square from, Square to) const {
+int Position::see(Square from, Square to, bool shortcut) const {
// Material values
static const int seeValues[18] = {
};
Bitboard attackers, stmAttackers, b;
+ int pieceDiff = 0;
+ assert(!shortcut || from != SQ_NONE);
assert(square_is_ok(from) || from == SQ_NONE);
assert(square_is_ok(to));
Piece capture = piece_on(to);
Bitboard occ = occupied_squares();
+ // King cannot be recaptured
+ if (type_of_piece(piece) == KING)
+ return seeValues[capture];
+
+ // If captured piece is defended by enemy pawns or knights then SEE is negative
+ // when captured piece value does not compensate the lost of capturing one.
+ if (shortcut)
+ {
+ pieceDiff = seeValues[piece] - seeValues[capture];
+
+ if ( pieceDiff > seeValues[PAWN]
+ &&(attacks_from<PAWN>(to, us) & pieces(PAWN, them)))
+ return -(pieceDiff - seeValues[PAWN] / 2);
+
+ if ( pieceDiff > seeValues[KNIGHT]
+ && pieces(KNIGHT, them)
+ &&(pieces(KNIGHT, them) & attacks_from<KNIGHT>(to)))
+ return -(pieceDiff - seeValues[KNIGHT] / 2);
+ }
+
// Handle en passant moves
if (st->epSquare == to && type_of_piece_on(from) == PAWN)
{
for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
assert(pt < KING);
+ // If captured piece is defended by an enemy piece then SEE is negative
+ // if captured piece value does not compensate the lost of capturing one.
+ if (pieceDiff > seeValues[pt])
+ {
+ assert(shortcut);
+ return -(pieceDiff - seeValues[pt] / 2);
+ } else
+ pieceDiff = 0; // Only first cycle
+
// Remove the attacker we just found from the 'attackers' bitboard,
// and scan for new X-ray attacks behind the attacker.
b = stmAttackers & pieces(pt);
for (int i = 0; i < 64; i++)
board[i] = EMPTY;
- for (int i = 0; i < 7; i++)
- for (int j = 0; j < 8; j++)
+ for (int i = 0; i < 8; i++)
+ for (int j = 0; j < 16; j++)
pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE;
sideToMove = WHITE;
return true;
// Draw by repetition?
- for (int i = 2; i < Min(gamePly, st->rule50); i += 2)
+ for (int i = 2; i < Min(Min(gamePly, st->rule50), st->pliesFromNull); i += 2)
if (history[gamePly - i] == st->key)
return true;