-# List of authors for Stockfish, as of August 4, 2020
+# List of authors for Stockfish, as of March 24, 2021
# Founders of the Stockfish project and fishtest infrastructure
Tord Romstad (romstad)
Bitboard b = attacks_bb<KING>(ksq[stm]);
while (b)
- r |= stm == WHITE ? db[index(BLACK, ksq[BLACK] , pop_lsb(b), psq)]
- : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
+ r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)]
+ : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
if (stm == WHITE)
{
using namespace std;
-using namespace Stockfish::Eval::NNUE;
namespace Stockfish {
attackedBy[Us][Pt] = 0;
- while (b1) {
+ while (b1)
+ {
Square s = pop_lsb(b1);
// Find attacked squares, including x-ray attacks for bishops and rooks
return v;
}
- // specifically correct for cornered bishops to fix FRC with NNUE.
+
+ /// Fisher Random Chess: correction for cornered bishops, to fix chess960 play with NNUE
+
Value fix_FRC(const Position& pos) {
- Value bAdjust = Value(0);
+ constexpr Bitboard Corners = 1ULL << SQ_A1 | 1ULL << SQ_H1 | 1ULL << SQ_A8 | 1ULL << SQ_H8;
- constexpr Value p1=Value(209), p2=Value(136), p3=Value(148);
+ if (!(pos.pieces(BISHOP) & Corners))
+ return VALUE_ZERO;
- Color Us = pos.side_to_move();
- if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_A1))
- && (pos.pieces(Us, PAWN) & relative_square(Us, SQ_B2)))
- {
- bAdjust -= !pos.empty(relative_square(Us,SQ_B3)) ? p1
- : pos.piece_on(relative_square(Us,SQ_C3)) == make_piece(Us, PAWN) ? p2
- : p3;
- }
- if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_H1))
- && (pos.pieces(Us, PAWN) & relative_square(Us, SQ_G2)))
- {
- bAdjust -= !pos.empty(relative_square(Us,SQ_G3)) ? p1
- : pos.piece_on(relative_square(Us,SQ_F3)) == make_piece(Us, PAWN) ? p2
- : p3;
- }
- if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_A8))
- && (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_B7)))
- {
- bAdjust += !pos.empty(relative_square(Us,SQ_B6)) ? p1
- : pos.piece_on(relative_square(Us,SQ_C6)) == make_piece(~Us, PAWN) ? p2
- : p3;
- }
- if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_H8))
- && (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_G7)))
- {
- bAdjust += !pos.empty(relative_square(Us,SQ_G6)) ? p1
- : pos.piece_on(relative_square(Us,SQ_F6)) == make_piece(~Us, PAWN) ? p2
- : p3;
- }
- return bAdjust;
+ constexpr int penalty1 = -209;
+ constexpr int penalty2 = -136;
+ constexpr int penalty3 = -148;
+
+ int correction = 0;
+
+ if ( pos.piece_on(SQ_A1) == W_BISHOP
+ && pos.piece_on(SQ_B2) == W_PAWN)
+ correction += !pos.empty(SQ_B3) ? penalty1
+ : pos.piece_on(SQ_C3) == W_PAWN ? penalty2
+ : penalty3;
+
+ if ( pos.piece_on(SQ_H1) == W_BISHOP
+ && pos.piece_on(SQ_G2) == W_PAWN)
+ correction += !pos.empty(SQ_G3) ? penalty1
+ : pos.piece_on(SQ_F3) == W_PAWN ? penalty2
+ : penalty3;
+
+ if ( pos.piece_on(SQ_A8) == B_BISHOP
+ && pos.piece_on(SQ_B7) == B_PAWN)
+ correction += !pos.empty(SQ_B6) ? -penalty1
+ : pos.piece_on(SQ_C6) == B_PAWN ? -penalty2
+ : -penalty3;
+
+ if ( pos.piece_on(SQ_H8) == B_BISHOP
+ && pos.piece_on(SQ_G7) == B_PAWN)
+ correction += !pos.empty(SQ_G6) ? -penalty1
+ : pos.piece_on(SQ_F6) == B_PAWN ? -penalty2
+ : -penalty3;
+
+ return pos.side_to_move() == WHITE ? Value(correction)
+ : -Value(correction);
}
-} // namespace
+} // namespace Eval
/// evaluate() is the evaluator for the outer world. It returns a static
else
{
// Scale and shift NNUE for compatibility with search and classical evaluation
- auto adjusted_NNUE = [&](){
- int mat = pos.non_pawn_material() + 2 * PawnValueMg * pos.count<PAWN>();
- Value nnueValue = NNUE::evaluate(pos) * (641 + mat / 32 - 4 * pos.rule50_count()) / 1024 + Tempo;
+ auto adjusted_NNUE = [&]()
+ {
+ int material = pos.non_pawn_material() + 2 * PawnValueMg * pos.count<PAWN>();
+ int scale = 641
+ + material / 32
+ - 4 * pos.rule50_count();
+
+ Value nnue = NNUE::evaluate(pos) * scale / 1024 + Tempo;
if (pos.is_chess960())
- nnueValue += fix_FRC(pos);
+ nnue += fix_FRC(pos);
- return nnueValue;
+ return nnue;
};
// If there is PSQ imbalance use classical eval, with small probability if it is small
bool is_KBPsK(const Position& pos, Color us) {
return pos.non_pawn_material(us) == BishopValueMg
- && pos.count<PAWN >(us) >= 1;
+ && pos.count<PAWN>(us) >= 1;
}
bool is_KQKRPs(const Position& pos, Color us) {
/// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages.
#if defined(_WIN32)
-#if defined(_WIN64)
-static void* aligned_large_pages_alloc_win(size_t allocSize) {
+
+static void* aligned_large_pages_alloc_windows(size_t allocSize) {
+
+ #if !defined(_WIN64)
+ return nullptr;
+ #else
HANDLE hProcessToken { };
LUID luid { };
CloseHandle(hProcessToken);
return mem;
+
+ #endif
}
-#endif
void* aligned_large_pages_alloc(size_t allocSize) {
-#if defined(_WIN64)
// Try to allocate large pages
- void* mem = aligned_large_pages_alloc_win(allocSize);
+ void* mem = aligned_large_pages_alloc_windows(allocSize);
// Fall back to regular, page aligned, allocation if necessary
if (!mem)
mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
-#else
- void* mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
-#endif
return mem;
}
if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{
DWORD err = GetLastError();
- std::cerr << "Failed to free transposition table. Error code: 0x" <<
- std::hex << err << std::dec << std::endl;
+ std::cerr << "Failed to free large page memory. Error code: 0x"
+ << std::hex << err
+ << std::dec << std::endl;
exit(EXIT_FAILURE);
}
}
Bitboard bb = piecesToMove & pos.pieces(Pt);
- while (bb) {
+ while (bb)
+ {
Square from = pop_lsb(bb);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
Square ksq = orient(perspective, pos.square<KING>(perspective));
Bitboard bb = pos.pieces() & ~pos.pieces(KING);
- while (bb) {
+ while (bb)
+ {
Square s = pop_lsb(bb);
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
}
IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
sum[w[idx] < 0] += w[idx];
}
- for (int sign : {-1, 1})
+ for (int sign : { -1, 1 })
while (sign * sum[sign == -1] > 258)
{
int maxK = 0, maxW = 0;
__m128i product1 = _mm_maddubs_epi16(a1, b1);
__m128i product2 = _mm_maddubs_epi16(a2, b2);
__m128i product3 = _mm_maddubs_epi16(a3, b3);
- product0 = _mm_adds_epi16(product0, product1);
- product2 = _mm_adds_epi16(product2, product3);
- product0 = _mm_adds_epi16(product0, product2);
+ product0 = _mm_add_epi16(product0, product1);
+ product2 = _mm_add_epi16(product2, product3);
+ product0 = _mm_add_epi16(product0, product2);
product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0);
};
e->blockedCount += popcount(shift<Up>(ourPawns) & (theirPawns | doubleAttackThem));
// Loop through all pawns of the current color and score each pawn
- while (b) {
+ while (b)
+ {
s = pop_lsb(b);
assert(pos.piece_on(s) == make_piece(Us, PAWN));
// Step 1. Initialize node
Thread* thisThread = pos.this_thread();
- ss->inCheck = pos.checkers();
- priorCapture = pos.captured_piece();
- Color us = pos.side_to_move();
- moveCount = captureCount = quietCount = ss->moveCount = 0;
- bestValue = -VALUE_INFINITE;
- maxValue = VALUE_INFINITE;
+ ss->inCheck = pos.checkers();
+ priorCapture = pos.captured_piece();
+ Color us = pos.side_to_move();
+ moveCount = captureCount = quietCount = ss->moveCount = 0;
+ bestValue = -VALUE_INFINITE;
+ maxValue = VALUE_INFINITE;
ss->distanceFromPv = (PvNode ? 0 : ss->distanceFromPv);
// Check for the available remaining time
return probCutBeta;
assert(probCutBeta < VALUE_INFINITE);
+
MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
int probCutCount = 0;
bool ttPv = ss->ttPv;
{
Value singularBeta = ttValue - ((formerPv + 4) * depth) / 2;
Depth singularDepth = (depth - 1 + 3 * formerPv) / 2;
+
ss->excludedMove = move;
value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode);
ss->excludedMove = MOVE_NONE;
// Decrease reduction if position is or has been on the PV
// and node is not likely to fail low. (~10 Elo)
- if (ss->ttPv && !likelyFailLow)
+ if ( ss->ttPv
+ && !likelyFailLow)
r -= 2;
// Increase reduction at root and non-PV nodes when the best move does not change frequently
- if ((rootNode || !PvNode) && thisThread->rootDepth > 10 && thisThread->bestMoveChanges <= 2)
+ if ( (rootNode || !PvNode)
+ && thisThread->rootDepth > 10
+ && thisThread->bestMoveChanges <= 2)
r++;
// More reductions for late moves if position was not in previous PV
- if (moveCountPruning && !formerPv)
+ if ( moveCountPruning
+ && !formerPv)
r++;
// Decrease reduction if opponent's move count is high (~5 Elo)
if (captureOrPromotion)
{
- // Unless giving check, this capture is likely bad
+ // Increase reduction for non-checking captures likely to be bad
if ( !givesCheck
&& ss->staticEval + PieceValue[EG][pos.captured_piece()] + 210 * depth <= alpha)
r++;
// Decrease reduction for moves that escape a capture. Filter out
// castling moves, because they are coded as "king captures rook" and
- // hence break make_move(). (~2 Elo)
+ // hence break reverse_move() (~2 Elo)
else if ( type_of(move) == NORMAL
&& !pos.see_ge(reverse_move(move)))
r -= 2 + ss->ttPv - (type_of(movedPiece) == PAWN);
assert(moveCount || !ss->inCheck || excludedMove || !MoveList<LEGAL>(pos).size());
if (!moveCount)
- bestValue = excludedMove ? alpha
- : ss->inCheck ? mated_in(ss->ply) : VALUE_DRAW;
+ bestValue = excludedMove ? alpha :
+ ss->inCheck ? mated_in(ss->ply)
+ : VALUE_DRAW;
// If there is a move which produces search value greater than alpha we update stats of searched moves
else if (bestMove)
std::stringstream ss(Paths);
std::string path;
- while (std::getline(ss, path, SepChar)) {
+ while (std::getline(ss, path, SepChar))
+ {
fname = path + "/" + f;
std::ifstream::open(fname);
if (is_open())
int buf64Size = 64;
Sym sym;
- while (true) {
+ while (true)
+ {
int len = 0; // This is the symbol length - d->min_sym_len
// Now get the symbol length. For any symbol s64 of length l right-padded
// We binary-search for our value recursively expanding into the left and
// right child symbols until we reach a leaf node where symlen[sym] + 1 == 1
// that will store the value we need.
- while (d->symlen[sym]) {
-
+ while (d->symlen[sym])
+ {
Sym left = d->btree[sym].get<LR::Left>();
// If a symbol contains 36 sub-symbols (d->symlen[sym] + 1 = 36) and
void ThreadPool::set(size_t requested) {
- if (size() > 0) { // destroy any existing thread(s)
+ if (size() > 0) // destroy any existing thread(s)
+ {
main()->wait_for_search_finished();
while (size() > 0)
delete back(), pop_back();
}
- if (requested > 0) { // create new thread(s)
+ if (requested > 0) // create new thread(s)
+ {
push_back(new MainThread(0));
while (size() < requested)