Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, 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
Position& Position::set(const string& code, Color c, StateInfo* si) {
- assert(code.length() > 0 && code.length() < 8);
assert(code[0] == 'K');
string sides[] = { code.substr(code.find('K', 1)), // Weak
- code.substr(0, code.find('K', 1)) }; // Strong
+ code.substr(0, std::min(code.find('v'), code.find('K', 1))) }; // Strong
+
+ assert(sides[0].length() > 0 && sides[0].length() < 8);
+ assert(sides[1].length() > 0 && sides[1].length() < 8);
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
Square to = to_sq(m);
// Is there a direct check?
- if (st->checkSquares[type_of(piece_on(from))] & to)
+ if (check_squares(type_of(piece_on(from))) & to)
return true;
// Is there a discovered check?
- if ( (st->blockersForKing[~sideToMove] & from)
+ if ( (blockers_for_king(~sideToMove) & from)
&& !aligned(from, to, square<KING>(~sideToMove)))
return true;
assert(relative_rank(us, to) == RANK_6);
assert(piece_on(to) == NO_PIECE);
assert(piece_on(capsq) == make_piece(them, PAWN));
-
- board[capsq] = NO_PIECE; // Not done by remove_piece()
}
st->pawnKey ^= Zobrist::psq[captured][capsq];
st->nonPawnMaterial[them] -= PieceValue[MG][captured];
// Update board and piece lists
- remove_piece(captured, capsq);
+ remove_piece(capsq);
+
+ if (type_of(m) == ENPASSANT)
+ board[capsq] = NO_PIECE;
// Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[captured][capsq];
// Move the piece. The tricky Chess960 castling is handled earlier
if (type_of(m) != CASTLING)
- move_piece(pc, from, to);
+ move_piece(from, to);
// If the moving piece is a pawn do some special extra work
if (type_of(pc) == PAWN)
assert(relative_rank(us, to) == RANK_8);
assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
- remove_piece(pc, to);
+ remove_piece(to);
put_piece(promotion, to);
// Update hash keys
st->nonPawnMaterial[us] += PieceValue[MG][promotion];
}
- // Update pawn hash key and prefetch access to pawnsTable
+ // Update pawn hash key
st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
// Reset rule 50 draw counter
assert(type_of(pc) == promotion_type(m));
assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN);
- remove_piece(pc, to);
+ remove_piece(to);
pc = make_piece(us, PAWN);
put_piece(pc, to);
}
}
else
{
- move_piece(pc, to, from); // Put the piece back at the source square
+ move_piece(to, from); // Put the piece back at the source square
if (st->capturedPiece)
{
to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
// Remove both pieces first since squares could overlap in Chess960
- remove_piece(make_piece(us, KING), Do ? from : to);
- remove_piece(make_piece(us, ROOK), Do ? rfrom : rto);
- board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us
+ remove_piece(Do ? from : to);
+ remove_piece(Do ? rfrom : rto);
+ board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do this for us
put_piece(make_piece(us, KING), Do ? to : from);
put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
}
-/// Position::do(undo)_null_move() is used to do(undo) a "null move": It flips
+/// 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.
void Position::do_null_move(StateInfo& newSt) {
if (swap <= 0)
return true;
- Bitboard occ = pieces() ^ from ^ to;
+ Bitboard occupied = pieces() ^ from ^ to;
Color stm = color_of(piece_on(from));
- Bitboard attackers = attackers_to(to, occ);
+ Bitboard attackers = attackers_to(to, occupied);
Bitboard stmAttackers, bb;
int res = 1;
while (true)
{
stm = ~stm;
- attackers &= occ;
+ attackers &= occupied;
// If stm has no more attackers then give up: stm loses
if (!(stmAttackers = attackers & pieces(stm)))
// Don't allow pinned pieces to attack (except the king) as long as
// there are pinners on their original square.
- if (st->pinners[~stm] & occ)
+ if (st->pinners[~stm] & occupied)
stmAttackers &= ~st->blockersForKing[stm];
if (!stmAttackers)
if ((swap = PawnValueMg - swap) < res)
break;
- occ ^= lsb(bb);
- attackers |= attacks_bb<BISHOP>(to, occ) & pieces(BISHOP, QUEEN);
+ occupied ^= lsb(bb);
+ attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(KNIGHT)))
if ((swap = KnightValueMg - swap) < res)
break;
- occ ^= lsb(bb);
+ occupied ^= lsb(bb);
}
else if ((bb = stmAttackers & pieces(BISHOP)))
if ((swap = BishopValueMg - swap) < res)
break;
- occ ^= lsb(bb);
- attackers |= attacks_bb<BISHOP>(to, occ) & pieces(BISHOP, QUEEN);
+ occupied ^= lsb(bb);
+ attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(ROOK)))
if ((swap = RookValueMg - swap) < res)
break;
- occ ^= lsb(bb);
- attackers |= attacks_bb<ROOK>(to, occ) & pieces(ROOK, QUEEN);
+ occupied ^= lsb(bb);
+ attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
}
else if ((bb = stmAttackers & pieces(QUEEN)))
if ((swap = QueenValueMg - swap) < res)
break;
- occ ^= lsb(bb);
- attackers |= (attacks_bb<BISHOP>(to, occ) & pieces(BISHOP, QUEEN))
- | (attacks_bb<ROOK >(to, occ) & pieces(ROOK , QUEEN));
+ occupied ^= lsb(bb);
+ attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
+ | (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN));
}
else // KING
return (attackers & ~pieces(stm)) ? res ^ 1 : res;
}
- return res;
+ return bool(res);
}
/// Position::is_draw() tests whether the position is drawn by 50-move rule