mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-23 05:07:14 +00:00
Merge commit 'bc9f08731f10896a306bcc34e30e5606087af79a' into cluster
This is the last commit before there are more conflicts.
This commit is contained in:
@@ -29,9 +29,10 @@ namespace Stockfish::Eval::NNUE::Features {
|
||||
|
||||
// Index of a feature for a given king position and another piece on some square
|
||||
template<Color Perspective>
|
||||
inline IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq) {
|
||||
return IndexType((int(s) ^ OrientTBL[Perspective][ksq]) + PieceSquareIndex[Perspective][pc]
|
||||
+ KingBuckets[Perspective][ksq]);
|
||||
IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq) {
|
||||
const IndexType flip = 56 * Perspective;
|
||||
return (IndexType(s) ^ OrientTBL[ksq] ^ flip) + PieceSquareIndex[Perspective][pc]
|
||||
+ KingBuckets[int(ksq) ^ flip];
|
||||
}
|
||||
|
||||
// Get a list of indices for active features
|
||||
|
||||
@@ -75,45 +75,29 @@ class HalfKAv2_hm {
|
||||
|
||||
#define B(v) (v * PS_NB)
|
||||
// clang-format off
|
||||
static constexpr int KingBuckets[COLOR_NB][SQUARE_NB] = {
|
||||
{ B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28),
|
||||
static constexpr IndexType KingBuckets[SQUARE_NB] = {
|
||||
B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28),
|
||||
B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24),
|
||||
B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20),
|
||||
B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16),
|
||||
B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12),
|
||||
B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8),
|
||||
B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4),
|
||||
B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0) },
|
||||
{ B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0),
|
||||
B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4),
|
||||
B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8),
|
||||
B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12),
|
||||
B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16),
|
||||
B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20),
|
||||
B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24),
|
||||
B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28) }
|
||||
B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0),
|
||||
};
|
||||
// clang-format on
|
||||
#undef B
|
||||
// clang-format off
|
||||
// Orient a square according to perspective (rotates by 180 for black)
|
||||
static constexpr int OrientTBL[COLOR_NB][SQUARE_NB] = {
|
||||
{ SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
static constexpr IndexType OrientTBL[SQUARE_NB] = {
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1 },
|
||||
{ SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
|
||||
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8 }
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
|
||||
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1 ,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -106,8 +106,6 @@ class Network {
|
||||
|
||||
template<IndexType Size>
|
||||
friend struct AccumulatorCaches::Cache;
|
||||
|
||||
friend class AccumulatorStack;
|
||||
};
|
||||
|
||||
// Definitions of the network types
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
#include "nnue_accumulator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../bitboard.h"
|
||||
@@ -75,7 +75,7 @@ void AccumulatorStack::reset() noexcept {
|
||||
}
|
||||
|
||||
void AccumulatorStack::push(const DirtyPiece& dirtyPiece) noexcept {
|
||||
assert(size + 1 < accumulators.size());
|
||||
assert(size < accumulators.size());
|
||||
accumulators[size].reset(dirtyPiece);
|
||||
size++;
|
||||
}
|
||||
@@ -362,6 +362,29 @@ void update_accumulator_incremental(
|
||||
(target_state.acc<TransformedFeatureDimensions>()).computed[Perspective] = true;
|
||||
}
|
||||
|
||||
Bitboard get_changed_pieces(const Piece old[SQUARE_NB], const Piece new_[SQUARE_NB]) {
|
||||
#if defined(USE_AVX512) || defined(USE_AVX2)
|
||||
static_assert(sizeof(Piece) == 1);
|
||||
Bitboard same_bb = 0;
|
||||
for (int i = 0; i < 64; i += 32)
|
||||
{
|
||||
const __m256i old_v = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(old + i));
|
||||
const __m256i new_v = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(new_ + i));
|
||||
const __m256i cmp_equal = _mm256_cmpeq_epi8(old_v, new_v);
|
||||
const std::uint32_t equal_mask = _mm256_movemask_epi8(cmp_equal);
|
||||
same_bb |= static_cast<Bitboard>(equal_mask) << i;
|
||||
}
|
||||
return ~same_bb;
|
||||
#else
|
||||
Bitboard changed = 0;
|
||||
for (Square sq = SQUARE_ZERO; sq < SQUARE_NB; ++sq)
|
||||
{
|
||||
changed |= static_cast<Bitboard>(old[sq] != new_[sq]) << sq;
|
||||
}
|
||||
return changed;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<Color Perspective, IndexType Dimensions>
|
||||
void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& featureTransformer,
|
||||
const Position& pos,
|
||||
@@ -374,28 +397,23 @@ void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& feat
|
||||
auto& entry = cache[ksq][Perspective];
|
||||
FeatureSet::IndexList removed, added;
|
||||
|
||||
for (Color c : {WHITE, BLACK})
|
||||
{
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
{
|
||||
const Piece piece = make_piece(c, pt);
|
||||
const Bitboard oldBB = entry.byColorBB[c] & entry.byTypeBB[pt];
|
||||
const Bitboard newBB = pos.pieces(c, pt);
|
||||
Bitboard toRemove = oldBB & ~newBB;
|
||||
Bitboard toAdd = newBB & ~oldBB;
|
||||
const Bitboard changed_bb = get_changed_pieces(entry.pieces, pos.piece_array());
|
||||
Bitboard removed_bb = changed_bb & entry.pieceBB;
|
||||
Bitboard added_bb = changed_bb & pos.pieces();
|
||||
|
||||
while (toRemove)
|
||||
{
|
||||
Square sq = pop_lsb(toRemove);
|
||||
removed.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
while (toAdd)
|
||||
{
|
||||
Square sq = pop_lsb(toAdd);
|
||||
added.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
}
|
||||
while (removed_bb)
|
||||
{
|
||||
Square sq = pop_lsb(removed_bb);
|
||||
removed.push_back(FeatureSet::make_index<Perspective>(sq, entry.pieces[sq], ksq));
|
||||
}
|
||||
while (added_bb)
|
||||
{
|
||||
Square sq = pop_lsb(added_bb);
|
||||
added.push_back(FeatureSet::make_index<Perspective>(sq, pos.piece_on(sq), ksq));
|
||||
}
|
||||
|
||||
entry.pieceBB = pos.pieces();
|
||||
std::copy_n(pos.piece_array(), SQUARE_NB, entry.pieces);
|
||||
|
||||
auto& accumulator = accumulatorState.acc<Dimensions>();
|
||||
accumulator.computed[Perspective] = true;
|
||||
@@ -518,12 +536,6 @@ void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& feat
|
||||
std::memcpy(accumulator.psqtAccumulation[Perspective], entry.psqtAccumulation,
|
||||
sizeof(int32_t) * PSQTBuckets);
|
||||
#endif
|
||||
|
||||
for (Color c : {WHITE, BLACK})
|
||||
entry.byColorBB[c] = pos.pieces(c);
|
||||
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
entry.byTypeBB[pt] = pos.pieces(pt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "../types.h"
|
||||
#include "nnue_architecture.h"
|
||||
@@ -48,7 +47,7 @@ template<IndexType Size>
|
||||
struct alignas(CacheLineSize) Accumulator {
|
||||
std::int16_t accumulation[COLOR_NB][Size];
|
||||
std::int32_t psqtAccumulation[COLOR_NB][PSQTBuckets];
|
||||
std::array<bool, COLOR_NB> computed;
|
||||
std::array<bool, COLOR_NB> computed = {};
|
||||
};
|
||||
|
||||
|
||||
@@ -71,8 +70,8 @@ struct AccumulatorCaches {
|
||||
struct alignas(CacheLineSize) Entry {
|
||||
BiasType accumulation[Size];
|
||||
PSQTWeightType psqtAccumulation[PSQTBuckets];
|
||||
Bitboard byColorBB[COLOR_NB];
|
||||
Bitboard byTypeBB[PIECE_TYPE_NB];
|
||||
Piece pieces[SQUARE_NB];
|
||||
Bitboard pieceBB;
|
||||
|
||||
// To initialize a refresh entry, we set all its bitboards empty,
|
||||
// so we put the biases in the accumulation, without any weights on top
|
||||
@@ -142,10 +141,6 @@ struct AccumulatorState {
|
||||
|
||||
class AccumulatorStack {
|
||||
public:
|
||||
AccumulatorStack() :
|
||||
accumulators(MAX_PLY + 1),
|
||||
size{1} {}
|
||||
|
||||
[[nodiscard]] const AccumulatorState& latest() const noexcept;
|
||||
|
||||
void reset() noexcept;
|
||||
@@ -178,8 +173,8 @@ class AccumulatorStack {
|
||||
const FeatureTransformer<Dimensions>& featureTransformer,
|
||||
const std::size_t end) noexcept;
|
||||
|
||||
std::vector<AccumulatorState> accumulators;
|
||||
std::size_t size;
|
||||
std::array<AccumulatorState, MAX_PLY + 1> accumulators;
|
||||
std::size_t size = 1;
|
||||
};
|
||||
|
||||
} // namespace Stockfish::Eval::NNUE
|
||||
|
||||
@@ -858,6 +858,10 @@ DirtyPiece Position::do_move(Move m,
|
||||
st->minorPieceKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
|
||||
}
|
||||
|
||||
// If en passant is impossible, then k will not change and we can prefetch earlier
|
||||
if (tt && !checkEP)
|
||||
prefetch(tt->first_entry(adjust_key50(k)));
|
||||
|
||||
// Set capture piece
|
||||
st->capturedPiece = captured;
|
||||
|
||||
|
||||
+7
-4
@@ -91,10 +91,11 @@ class Position {
|
||||
Bitboard pieces(PieceTypes... pts) const;
|
||||
Bitboard pieces(Color c) const;
|
||||
template<typename... PieceTypes>
|
||||
Bitboard pieces(Color c, PieceTypes... pts) const;
|
||||
Piece piece_on(Square s) const;
|
||||
Square ep_square() const;
|
||||
bool empty(Square s) const;
|
||||
Bitboard pieces(Color c, PieceTypes... pts) const;
|
||||
Piece piece_on(Square s) const;
|
||||
const Piece* piece_array() const;
|
||||
Square ep_square() const;
|
||||
bool empty(Square s) const;
|
||||
template<PieceType Pt>
|
||||
int count(Color c) const;
|
||||
template<PieceType Pt>
|
||||
@@ -208,6 +209,8 @@ inline Piece Position::piece_on(Square s) const {
|
||||
return board[s];
|
||||
}
|
||||
|
||||
inline const Piece* Position::piece_array() const { return board; }
|
||||
|
||||
inline bool Position::empty(Square s) const { return piece_on(s) == NO_PIECE; }
|
||||
|
||||
inline Piece Position::moved_piece(Move m) const { return piece_on(m.from_sq()); }
|
||||
|
||||
+29
-33
@@ -138,7 +138,8 @@ void update_all_stats(const Position& pos,
|
||||
SearchedList& quietsSearched,
|
||||
SearchedList& capturesSearched,
|
||||
Depth depth,
|
||||
Move TTMove);
|
||||
Move TTMove,
|
||||
int moveCount);
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -526,9 +527,10 @@ void Search::Worker::iterative_deepening() {
|
||||
double reduction =
|
||||
(1.455 + mainThread->previousTimeReduction) / (2.2375 * timeReduction);
|
||||
double bestMoveInstability = 1.04 + 1.8956 * totBestMoveChanges / threads.size();
|
||||
double highBestMoveEffort = completedDepth >= 10 && nodesEffort >= 92425 ? 0.666 : 1.0;
|
||||
|
||||
double totalTime =
|
||||
mainThread->tm.optimum() * fallingEval * reduction * bestMoveInstability;
|
||||
double totalTime = mainThread->tm.optimum() * fallingEval * reduction
|
||||
* bestMoveInstability * highBestMoveEffort;
|
||||
|
||||
// Cap used time in case of a single legal move for a better viewer experience
|
||||
if (rootMoves.size() == 1)
|
||||
@@ -536,10 +538,6 @@ void Search::Worker::iterative_deepening() {
|
||||
|
||||
auto elapsedTime = elapsed();
|
||||
|
||||
if (completedDepth >= 10 && nodesEffort >= 92425 && elapsedTime > totalTime * 0.666
|
||||
&& !mainThread->ponder)
|
||||
threads.stop = true;
|
||||
|
||||
// Stop the search if we have exceeded the totalTime or maximum
|
||||
if (elapsedTime > std::min(totalTime, double(mainThread->tm.maximum())))
|
||||
{
|
||||
@@ -733,10 +731,7 @@ Value Search::Worker::search(
|
||||
if (!PvNode && !excludedMove && ttData.depth > depth - (ttData.value <= beta)
|
||||
&& is_valid(ttData.value) // Can happen when !ttHit or when access race in probe()
|
||||
&& (ttData.bound & (ttData.value >= beta ? BOUND_LOWER : BOUND_UPPER))
|
||||
&& (cutNode == (ttData.value >= beta) || depth > 5)
|
||||
// avoid a TT cutoff if the rule50 count is high and the TT move is zeroing
|
||||
&& (depth > 8 || ttData.move == Move::none() || pos.rule50_count() < 80
|
||||
|| (!ttCapture && type_of(pos.moved_piece(ttData.move)) != PAWN)))
|
||||
&& (cutNode == (ttData.value >= beta) || depth > 5))
|
||||
{
|
||||
// If ttMove is quiet, update move sorting heuristics on TT hit
|
||||
if (ttData.move && ttData.value >= beta)
|
||||
@@ -866,12 +861,11 @@ Value Search::Worker::search(
|
||||
// Use static evaluation difference to improve quiet move ordering
|
||||
if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture)
|
||||
{
|
||||
int bonus = std::clamp(-10 * int((ss - 1)->staticEval + ss->staticEval), -2023, 1563) + 583;
|
||||
mainHistory[~us][((ss - 1)->currentMove).from_to()] << bonus * 944 / 1024;
|
||||
int evalDiff = std::clamp(-int((ss - 1)->staticEval + ss->staticEval), -200, 156) + 58;
|
||||
mainHistory[~us][((ss - 1)->currentMove).from_to()] << evalDiff * 9;
|
||||
if (!ttHit && type_of(pos.piece_on(prevSq)) != PAWN
|
||||
&& ((ss - 1)->currentMove).type_of() != PROMOTION)
|
||||
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq]
|
||||
<< bonus * 1438 / 1024;
|
||||
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] << evalDiff * 14;
|
||||
}
|
||||
|
||||
// Set up the improving flag, which is true if current static evaluation is
|
||||
@@ -901,7 +895,6 @@ Value Search::Worker::search(
|
||||
return futilityMult * d //
|
||||
- 2094 * improving * futilityMult / 1024 //
|
||||
- 1324 * opponentWorsening * futilityMult / 4096 //
|
||||
+ (ss - 1)->statScore / 331 //
|
||||
+ std::abs(correctionValue) / 158105;
|
||||
};
|
||||
|
||||
@@ -917,7 +910,7 @@ Value Search::Worker::search(
|
||||
assert((ss - 1)->currentMove != Move::null());
|
||||
|
||||
// Null move dynamic reduction based on depth
|
||||
Depth R = 6 + depth / 3;
|
||||
Depth R = 6 + depth / 3 + improving;
|
||||
|
||||
ss->currentMove = Move::null();
|
||||
ss->continuationHistory = &continuationHistory[0][0][NO_PIECE][0];
|
||||
@@ -1308,7 +1301,10 @@ moves_loop: // When in check, search starts here
|
||||
(ss + 1)->pv[0] = Move::none();
|
||||
|
||||
// Extend move from transposition table if we are about to dive into qsearch.
|
||||
if (move == ttData.move && ttData.depth > 1 && rootDepth > 8)
|
||||
// decisive score handling improves mate finding and retrograde analysis.
|
||||
if (move == ttData.move
|
||||
&& ((is_valid(ttData.value) && is_decisive(ttData.value) && ttData.depth > 0)
|
||||
|| (ttData.depth > 1 && rootDepth > 8)))
|
||||
newDepth = std::max(newDepth, 1);
|
||||
|
||||
value = -search<PV>(pos, ss + 1, -beta, -alpha, newDepth, false);
|
||||
@@ -1440,7 +1436,7 @@ moves_loop: // When in check, search starts here
|
||||
else if (bestMove)
|
||||
{
|
||||
update_all_stats(pos, ss, *this, bestMove, prevSq, quietsSearched, capturesSearched, depth,
|
||||
ttData.move);
|
||||
ttData.move, moveCount);
|
||||
if (!PvNode)
|
||||
ttMoveHistory << (bestMove == ttData.move ? 809 : -865);
|
||||
}
|
||||
@@ -1496,16 +1492,15 @@ moves_loop: // When in check, search starts here
|
||||
moveCount != 0 ? depth : std::min(MAX_PLY - 1, depth + 6), bestMove,
|
||||
unadjustedStaticEval, tt.generation());
|
||||
|
||||
// Adjust correction history
|
||||
// Adjust correction history if the best move is not a capture
|
||||
// and the error direction matches whether we are above/below bounds.
|
||||
if (!ss->inCheck && !(bestMove && pos.capture(bestMove))
|
||||
&& ((bestValue < ss->staticEval && bestValue < beta) // negative correction & no fail high
|
||||
|| (bestValue > ss->staticEval && bestMove))) // positive correction & no fail low
|
||||
&& (bestValue < ss->staticEval) == !bestMove)
|
||||
{
|
||||
auto bonus =
|
||||
std::clamp(int(bestValue - ss->staticEval) * depth / (8 + (bestValue > ss->staticEval)),
|
||||
-CORRECTION_HISTORY_LIMIT / 4, CORRECTION_HISTORY_LIMIT / 4);
|
||||
update_correction_history(pos, ss, *this,
|
||||
(1088 - 180 * (bestValue > ss->staticEval)) * bonus / 1024);
|
||||
update_correction_history(pos, ss, *this, bonus);
|
||||
}
|
||||
|
||||
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
|
||||
@@ -1853,41 +1848,42 @@ void update_all_stats(const Position& pos,
|
||||
SearchedList& quietsSearched,
|
||||
SearchedList& capturesSearched,
|
||||
Depth depth,
|
||||
Move ttMove) {
|
||||
Move ttMove,
|
||||
int moveCount) {
|
||||
|
||||
CapturePieceToHistory& captureHistory = workerThread.captureHistory;
|
||||
Piece movedPiece = pos.moved_piece(bestMove);
|
||||
PieceType capturedPiece;
|
||||
|
||||
int bonus = std::min(151 * depth - 91, 1730) + 302 * (bestMove == ttMove);
|
||||
int malus = std::min(951 * depth - 156, 2468) - 30 * quietsSearched.size();
|
||||
int bonus = std::min(121 * depth - 77, 1633) + 375 * (bestMove == ttMove);
|
||||
int malus = std::min(825 * depth - 196, 2159) - 16 * moveCount;
|
||||
|
||||
if (!pos.capture_stage(bestMove))
|
||||
{
|
||||
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 957 / 1024);
|
||||
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 881 / 1024);
|
||||
|
||||
// Decrease stats for all non-best quiet moves
|
||||
for (Move move : quietsSearched)
|
||||
update_quiet_histories(pos, ss, workerThread, move, -malus);
|
||||
update_quiet_histories(pos, ss, workerThread, move, -malus * 1083 / 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increase stats for the best move in case it was a capture move
|
||||
capturedPiece = type_of(pos.piece_on(bestMove.to_sq()));
|
||||
captureHistory[movedPiece][bestMove.to_sq()][capturedPiece] << bonus;
|
||||
captureHistory[movedPiece][bestMove.to_sq()][capturedPiece] << bonus * 1482 / 1024;
|
||||
}
|
||||
|
||||
// Extra penalty for a quiet early move that was not a TT move in
|
||||
// previous ply when it gets refuted.
|
||||
if (prevSq != SQ_NONE && ((ss - 1)->moveCount == 1 + (ss - 1)->ttHit) && !pos.captured_piece())
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 503 / 1024);
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 614 / 1024);
|
||||
|
||||
// Decrease stats for all non-best capture moves
|
||||
for (Move move : capturesSearched)
|
||||
{
|
||||
movedPiece = pos.moved_piece(move);
|
||||
capturedPiece = type_of(pos.piece_on(move.to_sq()));
|
||||
captureHistory[movedPiece][move.to_sq()][capturedPiece] << -malus * 1157 / 1024;
|
||||
captureHistory[movedPiece][move.to_sq()][capturedPiece] << -malus * 1397 / 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1923,7 +1919,7 @@ void update_quiet_histories(
|
||||
|
||||
int pIndex = pawn_history_index(pos);
|
||||
workerThread.pawnHistory[pIndex][pos.moved_piece(move)][move.to_sq()]
|
||||
<< (bonus * (bonus > 0 ? 800 : 500) / 1024) + 70;
|
||||
<< bonus * (bonus > 0 ? 850 : 550) / 1024;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user