mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-12 09:02:41 +01:00
DroidFish: Updated stockfish to version 2.3.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "bitcount.h"
|
||||
#include "movegen.h"
|
||||
#include "notation.h"
|
||||
#include "position.h"
|
||||
#include "psqtab.h"
|
||||
#include "rkiss.h"
|
||||
@@ -35,36 +36,105 @@ using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
Key Position::zobrist[2][8][64];
|
||||
Key Position::zobEp[8];
|
||||
Key Position::zobCastle[16];
|
||||
Key Position::zobSideToMove;
|
||||
Key Position::zobExclusion;
|
||||
|
||||
Score Position::pieceSquareTable[16][64];
|
||||
|
||||
// Material values arrays, indexed by Piece
|
||||
const Value PieceValueMidgame[17] = {
|
||||
VALUE_ZERO,
|
||||
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
|
||||
RookValueMidgame, QueenValueMidgame,
|
||||
VALUE_ZERO, VALUE_ZERO, VALUE_ZERO,
|
||||
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
|
||||
RookValueMidgame, QueenValueMidgame
|
||||
};
|
||||
|
||||
const Value PieceValueEndgame[17] = {
|
||||
VALUE_ZERO,
|
||||
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
|
||||
RookValueEndgame, QueenValueEndgame,
|
||||
VALUE_ZERO, VALUE_ZERO, VALUE_ZERO,
|
||||
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
|
||||
RookValueEndgame, QueenValueEndgame
|
||||
};
|
||||
|
||||
// To convert a Piece to and from a FEN char
|
||||
static const string PieceToChar(" PNBRQK pnbrqk");
|
||||
|
||||
CACHE_LINE_ALIGNMENT
|
||||
|
||||
Score pieceSquareTable[16][64]; // [piece][square]
|
||||
Value PieceValue[2][18] = { // [Mg / Eg][piece / pieceType]
|
||||
{ VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg },
|
||||
{ VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg } };
|
||||
|
||||
namespace Zobrist {
|
||||
|
||||
Key psq[2][8][64]; // [color][pieceType][square / piece count]
|
||||
Key enpassant[8]; // [file]
|
||||
Key castle[16]; // [castleRight]
|
||||
Key side;
|
||||
Key exclusion;
|
||||
|
||||
/// init() initializes at startup the various arrays used to compute hash keys
|
||||
/// and the piece square tables. The latter is a two-step operation: First, the
|
||||
/// white halves of the tables are copied from PSQT[] tables. Second, the black
|
||||
/// halves of the tables are initialized by flipping and changing the sign of
|
||||
/// the white scores.
|
||||
|
||||
void init() {
|
||||
|
||||
RKISS rk;
|
||||
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
for (PieceType pt = PAWN; pt <= KING; pt++)
|
||||
for (Square s = SQ_A1; s <= SQ_H8; s++)
|
||||
psq[c][pt][s] = rk.rand<Key>();
|
||||
|
||||
for (File f = FILE_A; f <= FILE_H; f++)
|
||||
enpassant[f] = rk.rand<Key>();
|
||||
|
||||
for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
|
||||
{
|
||||
Bitboard b = cr;
|
||||
while (b)
|
||||
{
|
||||
Key k = castle[1ULL << pop_lsb(&b)];
|
||||
castle[cr] ^= k ? k : rk.rand<Key>();
|
||||
}
|
||||
}
|
||||
|
||||
side = rk.rand<Key>();
|
||||
exclusion = rk.rand<Key>();
|
||||
|
||||
for (PieceType pt = PAWN; pt <= KING; pt++)
|
||||
{
|
||||
PieceValue[Mg][make_piece(BLACK, pt)] = PieceValue[Mg][pt];
|
||||
PieceValue[Eg][make_piece(BLACK, pt)] = PieceValue[Eg][pt];
|
||||
|
||||
Score v = make_score(PieceValue[Mg][pt], PieceValue[Eg][pt]);
|
||||
|
||||
for (Square s = SQ_A1; s <= SQ_H8; s++)
|
||||
{
|
||||
pieceSquareTable[make_piece(WHITE, pt)][ s] = (v + PSQT[pt][s]);
|
||||
pieceSquareTable[make_piece(BLACK, pt)][~s] = -(v + PSQT[pt][s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Zobrist
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
/// next_attacker() is an helper function used by see() to locate the least
|
||||
/// valuable attacker for the side to move, remove the attacker we just found
|
||||
/// from the 'occupied' bitboard and scan for new X-ray attacks behind it.
|
||||
|
||||
template<int Pt> FORCE_INLINE
|
||||
PieceType next_attacker(const Bitboard* bb, const Square& to, const Bitboard& stmAttackers,
|
||||
Bitboard& occupied, Bitboard& attackers) {
|
||||
|
||||
if (stmAttackers & bb[Pt])
|
||||
{
|
||||
Bitboard b = stmAttackers & bb[Pt];
|
||||
occupied ^= b & ~(b - 1);
|
||||
|
||||
if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
|
||||
attackers |= attacks_bb<BISHOP>(to, occupied) & (bb[BISHOP] | bb[QUEEN]);
|
||||
|
||||
if (Pt == ROOK || Pt == QUEEN)
|
||||
attackers |= attacks_bb<ROOK>(to, occupied) & (bb[ROOK] | bb[QUEEN]);
|
||||
|
||||
return (PieceType)Pt;
|
||||
}
|
||||
return next_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE
|
||||
PieceType next_attacker<KING>(const Bitboard*, const Square&, const Bitboard&, Bitboard&, Bitboard&) {
|
||||
return KING; // No need to update bitboards, it is the last cycle
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
/// CheckInfo c'tor
|
||||
|
||||
@@ -89,7 +159,7 @@ CheckInfo::CheckInfo(const Position& pos) {
|
||||
/// object do not depend on any external data so we detach state pointer from
|
||||
/// the source one.
|
||||
|
||||
void Position::operator=(const Position& pos) {
|
||||
Position& Position::operator=(const Position& pos) {
|
||||
|
||||
memcpy(this, &pos, sizeof(Position));
|
||||
startState = *st;
|
||||
@@ -97,6 +167,8 @@ void Position::operator=(const Position& pos) {
|
||||
nodes = 0;
|
||||
|
||||
assert(pos_is_ok());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +259,7 @@ void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) {
|
||||
for (rsq = relative_square(c, SQ_A1); type_of(piece_on(rsq)) != ROOK; rsq++) {}
|
||||
|
||||
else if (token >= 'A' && token <= 'H')
|
||||
rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1));
|
||||
rsq = File(token - 'A') | relative_rank(c, RANK_1);
|
||||
|
||||
else
|
||||
continue;
|
||||
@@ -199,7 +271,7 @@ void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) {
|
||||
if ( ((fen >> col) && (col >= 'a' && col <= 'h'))
|
||||
&& ((fen >> row) && (row == '3' || row == '6')))
|
||||
{
|
||||
st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
|
||||
st->epSquare = File(col - 'a') | Rank(row - '1');
|
||||
|
||||
if (!(attackers_to(st->epSquare) & pieces(sideToMove, PAWN)))
|
||||
st->epSquare = SQ_NONE;
|
||||
@@ -268,7 +340,7 @@ const string Position::to_fen() const {
|
||||
|
||||
for (File file = FILE_A; file <= FILE_H; file++)
|
||||
{
|
||||
sq = make_square(file, rank);
|
||||
sq = file | rank;
|
||||
|
||||
if (is_empty(sq))
|
||||
emptyCnt++;
|
||||
@@ -325,6 +397,8 @@ void Position::print(Move move) const {
|
||||
|
||||
string brd = twoRows + twoRows + twoRows + twoRows + dottedLine;
|
||||
|
||||
sync_cout;
|
||||
|
||||
if (move)
|
||||
{
|
||||
Position p(*this);
|
||||
@@ -335,7 +409,7 @@ void Position::print(Move move) const {
|
||||
if (piece_on(sq) != NO_PIECE)
|
||||
brd[513 - 68*rank_of(sq) + 4*file_of(sq)] = PieceToChar[piece_on(sq)];
|
||||
|
||||
cout << brd << "\nFen is: " << to_fen() << "\nKey is: " << st->key << endl;
|
||||
cout << brd << "\nFen is: " << to_fen() << "\nKey is: " << st->key << sync_endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -357,7 +431,7 @@ Bitboard Position::hidden_checkers() const {
|
||||
|
||||
while (pinners)
|
||||
{
|
||||
b = between_bb(ksq, pop_1st_bit(&pinners)) & pieces();
|
||||
b = between_bb(ksq, pop_lsb(&pinners)) & pieces();
|
||||
|
||||
if (b && !more_than_one(b) && (b & pieces(sideToMove)))
|
||||
result |= b;
|
||||
@@ -448,7 +522,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
||||
// En passant captures are a tricky special case. Because they are rather
|
||||
// uncommon, we do it simply by testing whether the king is attacked after
|
||||
// the move is made.
|
||||
if (is_enpassant(m))
|
||||
if (type_of(m) == ENPASSANT)
|
||||
{
|
||||
Color them = ~us;
|
||||
Square to = to_sq(m);
|
||||
@@ -469,7 +543,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
||||
// square is attacked by the opponent. Castling moves are checked
|
||||
// for legality during move generation.
|
||||
if (type_of(piece_on(from)) == KING)
|
||||
return is_castle(m) || !(attackers_to(to_sq(m)) & pieces(~us));
|
||||
return type_of(m) == CASTLE || !(attackers_to(to_sq(m)) & pieces(~us));
|
||||
|
||||
// A non-king move is legal if and only if it is not pinned or it
|
||||
// is moving along the ray towards or away from the king.
|
||||
@@ -485,7 +559,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
||||
|
||||
bool Position::move_is_legal(const Move m) const {
|
||||
|
||||
for (MoveList<MV_LEGAL> ml(*this); !ml.end(); ++ml)
|
||||
for (MoveList<LEGAL> ml(*this); !ml.end(); ++ml)
|
||||
if (ml.move() == m)
|
||||
return true;
|
||||
|
||||
@@ -506,7 +580,7 @@ bool Position::is_pseudo_legal(const Move m) const {
|
||||
Piece pc = piece_moved(m);
|
||||
|
||||
// Use a slower but simpler function for uncommon cases
|
||||
if (is_special(m))
|
||||
if (type_of(m) != NORMAL)
|
||||
return move_is_legal(m);
|
||||
|
||||
// Is not a promotion, so promotion piece must be empty
|
||||
@@ -595,7 +669,7 @@ bool Position::is_pseudo_legal(const Move m) const {
|
||||
if (type_of(pc) != KING)
|
||||
{
|
||||
Bitboard b = checkers();
|
||||
Square checksq = pop_1st_bit(&b);
|
||||
Square checksq = pop_lsb(&b);
|
||||
|
||||
if (b) // double check ? In this case a king move is required
|
||||
return false;
|
||||
@@ -640,23 +714,23 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
|
||||
}
|
||||
|
||||
// Can we skip the ugly special cases ?
|
||||
if (!is_special(m))
|
||||
if (type_of(m) == NORMAL)
|
||||
return false;
|
||||
|
||||
Color us = sideToMove;
|
||||
Square ksq = king_square(~us);
|
||||
|
||||
// Promotion with check ?
|
||||
if (is_promotion(m))
|
||||
if (type_of(m) == PROMOTION)
|
||||
return attacks_from(Piece(promotion_type(m)), to, pieces() ^ from) & ksq;
|
||||
|
||||
// En passant capture with check ? We have already handled the case
|
||||
// of direct checks and ordinary discovered check, the only case we
|
||||
// need to handle is the unusual case of a discovered check through
|
||||
// the captured pawn.
|
||||
if (is_enpassant(m))
|
||||
if (type_of(m) == ENPASSANT)
|
||||
{
|
||||
Square capsq = make_square(file_of(to), rank_of(from));
|
||||
Square capsq = file_of(to) | rank_of(from);
|
||||
Bitboard b = (pieces() ^ from ^ capsq) | to;
|
||||
|
||||
return (attacks_bb< ROOK>(ksq, b) & pieces(us, QUEEN, ROOK))
|
||||
@@ -664,7 +738,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
|
||||
}
|
||||
|
||||
// Castling with check ?
|
||||
if (is_castle(m))
|
||||
if (type_of(m) == CASTLE)
|
||||
{
|
||||
Square kfrom = from;
|
||||
Square rfrom = to; // 'King captures the rook' notation
|
||||
@@ -706,14 +780,14 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
st = &newSt;
|
||||
|
||||
// Update side to move
|
||||
k ^= zobSideToMove;
|
||||
k ^= Zobrist::side;
|
||||
|
||||
// Increment the 50 moves rule draw counter. Resetting it to zero in the
|
||||
// case of a capture or a pawn move is taken care of later.
|
||||
st->rule50++;
|
||||
st->pliesFromNull++;
|
||||
|
||||
if (is_castle(m))
|
||||
if (type_of(m) == CASTLE)
|
||||
{
|
||||
st->key = k;
|
||||
do_castle_move<true>(m);
|
||||
@@ -726,7 +800,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
Square to = to_sq(m);
|
||||
Piece piece = piece_on(from);
|
||||
PieceType pt = type_of(piece);
|
||||
PieceType capture = is_enpassant(m) ? PAWN : type_of(piece_on(to));
|
||||
PieceType capture = type_of(m) == ENPASSANT ? PAWN : type_of(piece_on(to));
|
||||
|
||||
assert(color_of(piece) == us);
|
||||
assert(color_of(piece_on(to)) != us);
|
||||
@@ -740,7 +814,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
// update non-pawn material.
|
||||
if (capture == PAWN)
|
||||
{
|
||||
if (is_enpassant(m))
|
||||
if (type_of(m) == ENPASSANT)
|
||||
{
|
||||
capsq += pawn_push(them);
|
||||
|
||||
@@ -753,10 +827,10 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
board[capsq] = NO_PIECE;
|
||||
}
|
||||
|
||||
st->pawnKey ^= zobrist[them][PAWN][capsq];
|
||||
st->pawnKey ^= Zobrist::psq[them][PAWN][capsq];
|
||||
}
|
||||
else
|
||||
st->npMaterial[them] -= PieceValueMidgame[capture];
|
||||
st->npMaterial[them] -= PieceValue[Mg][capture];
|
||||
|
||||
// Remove the captured piece
|
||||
byTypeBB[ALL_PIECES] ^= capsq;
|
||||
@@ -776,8 +850,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
|
||||
|
||||
// Update hash keys
|
||||
k ^= zobrist[them][capture][capsq];
|
||||
st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]];
|
||||
k ^= Zobrist::psq[them][capture][capsq];
|
||||
st->materialKey ^= Zobrist::psq[them][capture][pieceCount[them][capture]];
|
||||
|
||||
// Update incremental scores
|
||||
st->psqScore -= pieceSquareTable[make_piece(them, capture)][capsq];
|
||||
@@ -787,12 +861,12 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
}
|
||||
|
||||
// Update hash key
|
||||
k ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
|
||||
k ^= Zobrist::psq[us][pt][from] ^ Zobrist::psq[us][pt][to];
|
||||
|
||||
// Reset en passant square
|
||||
if (st->epSquare != SQ_NONE)
|
||||
{
|
||||
k ^= zobEp[file_of(st->epSquare)];
|
||||
k ^= Zobrist::enpassant[file_of(st->epSquare)];
|
||||
st->epSquare = SQ_NONE;
|
||||
}
|
||||
|
||||
@@ -800,7 +874,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
if (st->castleRights && (castleRightsMask[from] | castleRightsMask[to]))
|
||||
{
|
||||
int cr = castleRightsMask[from] | castleRightsMask[to];
|
||||
k ^= zobCastle[st->castleRights & cr];
|
||||
k ^= Zobrist::castle[st->castleRights & cr];
|
||||
st->castleRights &= ~cr;
|
||||
}
|
||||
|
||||
@@ -829,10 +903,10 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
&& (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(them, PAWN)))
|
||||
{
|
||||
st->epSquare = Square((from + to) / 2);
|
||||
k ^= zobEp[file_of(st->epSquare)];
|
||||
k ^= Zobrist::enpassant[file_of(st->epSquare)];
|
||||
}
|
||||
|
||||
if (is_promotion(m))
|
||||
if (type_of(m) == PROMOTION)
|
||||
{
|
||||
PieceType promotion = promotion_type(m);
|
||||
|
||||
@@ -854,21 +928,21 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
pieceList[us][promotion][index[to]] = to;
|
||||
|
||||
// Update hash keys
|
||||
k ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
|
||||
st->pawnKey ^= zobrist[us][PAWN][to];
|
||||
st->materialKey ^= zobrist[us][promotion][pieceCount[us][promotion]++]
|
||||
^ zobrist[us][PAWN][pieceCount[us][PAWN]];
|
||||
k ^= Zobrist::psq[us][PAWN][to] ^ Zobrist::psq[us][promotion][to];
|
||||
st->pawnKey ^= Zobrist::psq[us][PAWN][to];
|
||||
st->materialKey ^= Zobrist::psq[us][promotion][pieceCount[us][promotion]++]
|
||||
^ Zobrist::psq[us][PAWN][pieceCount[us][PAWN]];
|
||||
|
||||
// Update incremental score
|
||||
st->psqScore += pieceSquareTable[make_piece(us, promotion)][to]
|
||||
- pieceSquareTable[make_piece(us, PAWN)][to];
|
||||
|
||||
// Update material
|
||||
st->npMaterial[us] += PieceValueMidgame[promotion];
|
||||
st->npMaterial[us] += PieceValue[Mg][promotion];
|
||||
}
|
||||
|
||||
// Update pawn hash key
|
||||
st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
|
||||
st->pawnKey ^= Zobrist::psq[us][PAWN][from] ^ Zobrist::psq[us][PAWN][to];
|
||||
|
||||
// Reset rule 50 draw counter
|
||||
st->rule50 = 0;
|
||||
@@ -892,7 +966,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||
|
||||
if (moveIsCheck)
|
||||
{
|
||||
if (is_special(m))
|
||||
if (type_of(m) != NORMAL)
|
||||
st->checkersBB = attackers_to(king_square(them)) & pieces(us);
|
||||
else
|
||||
{
|
||||
@@ -927,7 +1001,7 @@ void Position::undo_move(Move m) {
|
||||
|
||||
sideToMove = ~sideToMove;
|
||||
|
||||
if (is_castle(m))
|
||||
if (type_of(m) == CASTLE)
|
||||
{
|
||||
do_castle_move<false>(m);
|
||||
return;
|
||||
@@ -945,7 +1019,7 @@ void Position::undo_move(Move m) {
|
||||
assert(color_of(piece) == us);
|
||||
assert(capture != KING);
|
||||
|
||||
if (is_promotion(m))
|
||||
if (type_of(m) == PROMOTION)
|
||||
{
|
||||
PieceType promotion = promotion_type(m);
|
||||
|
||||
@@ -988,7 +1062,7 @@ void Position::undo_move(Move m) {
|
||||
{
|
||||
Square capsq = to;
|
||||
|
||||
if (is_enpassant(m))
|
||||
if (type_of(m) == ENPASSANT)
|
||||
{
|
||||
capsq -= pawn_push(us);
|
||||
|
||||
@@ -1025,7 +1099,7 @@ template<bool Do>
|
||||
void Position::do_castle_move(Move m) {
|
||||
|
||||
assert(is_ok(m));
|
||||
assert(is_castle(m));
|
||||
assert(type_of(m) == CASTLE);
|
||||
|
||||
Square kto, kfrom, rfrom, rto, kAfter, rAfter;
|
||||
|
||||
@@ -1086,18 +1160,18 @@ void Position::do_castle_move(Move m) {
|
||||
st->psqScore += psq_delta(rook, rfrom, rto);
|
||||
|
||||
// Update hash key
|
||||
st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto];
|
||||
st->key ^= zobrist[us][ROOK][rfrom] ^ zobrist[us][ROOK][rto];
|
||||
st->key ^= Zobrist::psq[us][KING][kfrom] ^ Zobrist::psq[us][KING][kto];
|
||||
st->key ^= Zobrist::psq[us][ROOK][rfrom] ^ Zobrist::psq[us][ROOK][rto];
|
||||
|
||||
// Clear en passant square
|
||||
if (st->epSquare != SQ_NONE)
|
||||
{
|
||||
st->key ^= zobEp[file_of(st->epSquare)];
|
||||
st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
|
||||
st->epSquare = SQ_NONE;
|
||||
}
|
||||
|
||||
// Update castling rights
|
||||
st->key ^= zobCastle[st->castleRights & castleRightsMask[kfrom]];
|
||||
st->key ^= Zobrist::castle[st->castleRights & castleRightsMask[kfrom]];
|
||||
st->castleRights &= ~castleRightsMask[kfrom];
|
||||
|
||||
// Update checkers BB
|
||||
@@ -1138,9 +1212,9 @@ void Position::do_null_move(StateInfo& backupSt) {
|
||||
if (Do)
|
||||
{
|
||||
if (st->epSquare != SQ_NONE)
|
||||
st->key ^= zobEp[file_of(st->epSquare)];
|
||||
st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
|
||||
|
||||
st->key ^= zobSideToMove;
|
||||
st->key ^= Zobrist::side;
|
||||
prefetch((char*)TT.first_entry(st->key));
|
||||
|
||||
st->epSquare = SQ_NONE;
|
||||
@@ -1169,7 +1243,7 @@ int Position::see_sign(Move m) const {
|
||||
// Early return if SEE cannot be negative because captured piece value
|
||||
// is not less then capturing one. Note that king moves always return
|
||||
// here because king midgame value is set to 0.
|
||||
if (PieceValueMidgame[piece_on(to_sq(m))] >= PieceValueMidgame[piece_moved(m)])
|
||||
if (PieceValue[Mg][piece_on(to_sq(m))] >= PieceValue[Mg][piece_moved(m)])
|
||||
return 1;
|
||||
|
||||
return see(m);
|
||||
@@ -1178,47 +1252,45 @@ int Position::see_sign(Move m) const {
|
||||
int Position::see(Move m) const {
|
||||
|
||||
Square from, to;
|
||||
Bitboard occ, attackers, stmAttackers, b;
|
||||
Bitboard occupied, attackers, stmAttackers;
|
||||
int swapList[32], slIndex = 1;
|
||||
PieceType capturedType, pt;
|
||||
PieceType captured;
|
||||
Color stm;
|
||||
|
||||
assert(is_ok(m));
|
||||
|
||||
// As castle moves are implemented as capturing the rook, they have
|
||||
// SEE == RookValueMidgame most of the times (unless the rook is under
|
||||
// attack).
|
||||
if (is_castle(m))
|
||||
return 0;
|
||||
|
||||
from = from_sq(m);
|
||||
to = to_sq(m);
|
||||
capturedType = type_of(piece_on(to));
|
||||
occ = pieces();
|
||||
captured = type_of(piece_on(to));
|
||||
occupied = pieces() ^ from;
|
||||
|
||||
// Handle en passant moves
|
||||
if (is_enpassant(m))
|
||||
if (type_of(m) == ENPASSANT)
|
||||
{
|
||||
Square capQq = to - pawn_push(sideToMove);
|
||||
|
||||
assert(!capturedType);
|
||||
assert(!captured);
|
||||
assert(type_of(piece_on(capQq)) == PAWN);
|
||||
|
||||
// Remove the captured pawn
|
||||
occ ^= capQq;
|
||||
capturedType = PAWN;
|
||||
occupied ^= capQq;
|
||||
captured = PAWN;
|
||||
}
|
||||
else if (type_of(m) == CASTLE)
|
||||
// Castle moves are implemented as king capturing the rook so cannot be
|
||||
// handled correctly. Simply return 0 that is always the correct value
|
||||
// unless the rook is ends up under attack.
|
||||
return 0;
|
||||
|
||||
// Find all attackers to the destination square, with the moving piece
|
||||
// removed, but possibly an X-ray attacker added behind it.
|
||||
occ ^= from;
|
||||
attackers = attackers_to(to, occ);
|
||||
attackers = attackers_to(to, occupied);
|
||||
|
||||
// If the opponent has no attackers we are finished
|
||||
stm = ~color_of(piece_on(from));
|
||||
stmAttackers = attackers & pieces(stm);
|
||||
if (!stmAttackers)
|
||||
return PieceValueMidgame[capturedType];
|
||||
return PieceValue[Mg][captured];
|
||||
|
||||
// The destination square is defended, which makes things rather more
|
||||
// difficult to compute. We proceed by building up a "swap list" containing
|
||||
@@ -1226,43 +1298,32 @@ int Position::see(Move m) const {
|
||||
// destination square, where the sides alternately capture, and always
|
||||
// capture with the least valuable piece. After each capture, we look for
|
||||
// new X-ray attacks from behind the capturing piece.
|
||||
swapList[0] = PieceValueMidgame[capturedType];
|
||||
capturedType = type_of(piece_on(from));
|
||||
swapList[0] = PieceValue[Mg][captured];
|
||||
captured = type_of(piece_on(from));
|
||||
|
||||
do {
|
||||
// Locate the least valuable attacker for the side to move. The loop
|
||||
// below looks like it is potentially infinite, but it isn't. We know
|
||||
// that the side to move still has at least one attacker left.
|
||||
for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
|
||||
assert(pt < KING);
|
||||
|
||||
// Remove the attacker we just found from the 'occupied' bitboard,
|
||||
// and scan for new X-ray attacks behind the attacker.
|
||||
b = stmAttackers & pieces(pt);
|
||||
occ ^= (b & (~b + 1));
|
||||
attackers |= (attacks_bb<ROOK>(to, occ) & pieces(ROOK, QUEEN))
|
||||
| (attacks_bb<BISHOP>(to, occ) & pieces(BISHOP, QUEEN));
|
||||
|
||||
attackers &= occ; // Cut out pieces we've already done
|
||||
assert(slIndex < 32);
|
||||
|
||||
// Add the new entry to the swap list
|
||||
assert(slIndex < 32);
|
||||
swapList[slIndex] = -swapList[slIndex - 1] + PieceValueMidgame[capturedType];
|
||||
swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[Mg][captured];
|
||||
slIndex++;
|
||||
|
||||
// Remember the value of the capturing piece, and change the side to
|
||||
// move before beginning the next iteration.
|
||||
capturedType = pt;
|
||||
// Locate and remove from 'occupied' the next least valuable attacker
|
||||
captured = next_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
|
||||
|
||||
attackers &= occupied; // Remove the just found attacker
|
||||
stm = ~stm;
|
||||
stmAttackers = attackers & pieces(stm);
|
||||
|
||||
// Stop before processing a king capture
|
||||
if (capturedType == KING && stmAttackers)
|
||||
if (captured == KING)
|
||||
{
|
||||
assert(slIndex < 32);
|
||||
swapList[slIndex++] = QueenValueMidgame*10;
|
||||
// Stop before processing a king capture
|
||||
if (stmAttackers)
|
||||
swapList[slIndex++] = QueenValueMg * 16;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
} while (stmAttackers);
|
||||
|
||||
// Having built the swap list, we negamax through it to find the best
|
||||
@@ -1317,19 +1378,19 @@ void Position::put_piece(Piece p, Square s) {
|
||||
|
||||
Key Position::compute_key() const {
|
||||
|
||||
Key k = zobCastle[st->castleRights];
|
||||
Key k = Zobrist::castle[st->castleRights];
|
||||
|
||||
for (Bitboard b = pieces(); b; )
|
||||
{
|
||||
Square s = pop_1st_bit(&b);
|
||||
k ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s];
|
||||
Square s = pop_lsb(&b);
|
||||
k ^= Zobrist::psq[color_of(piece_on(s))][type_of(piece_on(s))][s];
|
||||
}
|
||||
|
||||
if (ep_square() != SQ_NONE)
|
||||
k ^= zobEp[file_of(ep_square())];
|
||||
k ^= Zobrist::enpassant[file_of(ep_square())];
|
||||
|
||||
if (sideToMove == BLACK)
|
||||
k ^= zobSideToMove;
|
||||
k ^= Zobrist::side;
|
||||
|
||||
return k;
|
||||
}
|
||||
@@ -1347,8 +1408,8 @@ Key Position::compute_pawn_key() const {
|
||||
|
||||
for (Bitboard b = pieces(PAWN); b; )
|
||||
{
|
||||
Square s = pop_1st_bit(&b);
|
||||
k ^= zobrist[color_of(piece_on(s))][PAWN][s];
|
||||
Square s = pop_lsb(&b);
|
||||
k ^= Zobrist::psq[color_of(piece_on(s))][PAWN][s];
|
||||
}
|
||||
|
||||
return k;
|
||||
@@ -1368,7 +1429,7 @@ Key Position::compute_material_key() const {
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
for (PieceType pt = PAWN; pt <= QUEEN; pt++)
|
||||
for (int cnt = 0; cnt < piece_count(c, pt); cnt++)
|
||||
k ^= zobrist[c][pt][cnt];
|
||||
k ^= Zobrist::psq[c][pt][cnt];
|
||||
|
||||
return k;
|
||||
}
|
||||
@@ -1384,7 +1445,7 @@ Score Position::compute_psq_score() const {
|
||||
|
||||
for (Bitboard b = pieces(); b; )
|
||||
{
|
||||
Square s = pop_1st_bit(&b);
|
||||
Square s = pop_lsb(&b);
|
||||
score += pieceSquareTable[piece_on(s)][s];
|
||||
}
|
||||
|
||||
@@ -1402,7 +1463,7 @@ Value Position::compute_non_pawn_material(Color c) const {
|
||||
Value value = VALUE_ZERO;
|
||||
|
||||
for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
|
||||
value += piece_count(c, pt) * PieceValueMidgame[pt];
|
||||
value += piece_count(c, pt) * PieceValue[Mg][pt];
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -1416,11 +1477,11 @@ bool Position::is_draw() const {
|
||||
|
||||
// Draw by material?
|
||||
if ( !pieces(PAWN)
|
||||
&& (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMidgame))
|
||||
&& (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMg))
|
||||
return true;
|
||||
|
||||
// Draw by the 50 moves rule?
|
||||
if (st->rule50 > 99 && (!in_check() || MoveList<MV_LEGAL>(*this).size()))
|
||||
if (st->rule50 > 99 && (!in_check() || MoveList<LEGAL>(*this).size()))
|
||||
return true;
|
||||
|
||||
// Draw by repetition?
|
||||
@@ -1452,50 +1513,6 @@ template bool Position::is_draw<false>() const;
|
||||
template bool Position::is_draw<true>() const;
|
||||
|
||||
|
||||
/// Position::init() is a static member function which initializes at startup
|
||||
/// the various arrays used to compute hash keys and the piece square tables.
|
||||
/// The latter is a two-step operation: First, the white halves of the tables
|
||||
/// are copied from PSQT[] tables. Second, the black halves of the tables are
|
||||
/// initialized by flipping and changing the sign of the white scores.
|
||||
|
||||
void Position::init() {
|
||||
|
||||
RKISS rk;
|
||||
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
for (PieceType pt = PAWN; pt <= KING; pt++)
|
||||
for (Square s = SQ_A1; s <= SQ_H8; s++)
|
||||
zobrist[c][pt][s] = rk.rand<Key>();
|
||||
|
||||
for (File f = FILE_A; f <= FILE_H; f++)
|
||||
zobEp[f] = rk.rand<Key>();
|
||||
|
||||
for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
|
||||
{
|
||||
Bitboard b = cr;
|
||||
while (b)
|
||||
{
|
||||
Key k = zobCastle[1ULL << pop_1st_bit(&b)];
|
||||
zobCastle[cr] ^= k ? k : rk.rand<Key>();
|
||||
}
|
||||
}
|
||||
|
||||
zobSideToMove = rk.rand<Key>();
|
||||
zobExclusion = rk.rand<Key>();
|
||||
|
||||
for (PieceType pt = PAWN; pt <= KING; pt++)
|
||||
{
|
||||
Score v = make_score(PieceValueMidgame[pt], PieceValueEndgame[pt]);
|
||||
|
||||
for (Square s = SQ_A1; s <= SQ_H8; s++)
|
||||
{
|
||||
pieceSquareTable[make_piece(WHITE, pt)][ s] = (v + PSQT[pt][s]);
|
||||
pieceSquareTable[make_piece(BLACK, pt)][~s] = -(v + PSQT[pt][s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Position::flip() flips position with the white and black sides reversed. This
|
||||
/// is only useful for debugging especially for finding evaluation symmetry bugs.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user