Merge commit 'd2d046c2a497b2d70debde07ccc414ca633d550b' into cluster

This commit is contained in:
Steinar H. Gunderson
2025-12-25 20:07:02 +01:00
3 changed files with 65 additions and 2 deletions
+27
View File
@@ -19,6 +19,7 @@
#include "movepick.h"
#include <cassert>
#include <cstddef>
#include <limits>
#include "bitboard.h"
@@ -316,4 +317,30 @@ top:
void MovePicker::skip_quiet_moves() { skipQuiets = true; }
bool MovePicker::otherPieceTypesMobile(PieceType pt, ValueList<Move, 32>& capturesSearched) {
if (stage != GOOD_QUIET && stage != BAD_QUIET)
return true;
// verify good captures
for (std::size_t i = 0; i < capturesSearched.size(); i++)
if (type_of(pos.moved_piece(capturesSearched[i])) != pt)
{
if (type_of(pos.moved_piece(capturesSearched[i])) != KING)
return true;
if (pos.legal(capturesSearched[i]))
return true;
}
// now verify bad captures and quiets
for (ExtMove* c = moves; c < endBadQuiets; ++c)
if (type_of(pos.moved_piece(*c)) != pt)
{
if (type_of(pos.moved_piece(*c)) != KING)
return true;
if (pos.legal(*c))
return true;
}
return false;
}
} // namespace Stockfish
+6
View File
@@ -19,6 +19,8 @@
#ifndef MOVEPICK_H_INCLUDED
#define MOVEPICK_H_INCLUDED
#include <cstddef>
#include "history.h"
#include "movegen.h"
#include "types.h"
@@ -27,6 +29,9 @@ namespace Stockfish {
class Position;
template<typename T, std::size_t MaxSize>
class ValueList;
// The MovePicker class is used to pick one pseudo-legal move at a time from the
// current position. The most important method is next_move(), which emits one
// new pseudo-legal move on every call, until there are no moves left, when
@@ -50,6 +55,7 @@ class MovePicker {
MovePicker(const Position&, Move, int, const CapturePieceToHistory*);
Move next_move();
void skip_quiet_moves();
bool otherPieceTypesMobile(PieceType pt, ValueList<Move, 32>& capturesSearched);
private:
template<typename Pred>
+32 -2
View File
@@ -34,6 +34,7 @@
#include <string>
#include <utility>
#include "bitboard.h"
#include "cluster.h"
#include "evaluate.h"
#include "history.h"
@@ -1121,7 +1122,19 @@ moves_loop: // When in check, search starts here
// SEE based pruning for captures and checks
int seeHist = std::clamp(captHist / 32, -138 * depth, 135 * depth);
if (!pos.see_ge(move, -154 * depth - seeHist))
continue;
{
bool skip = true;
if (depth > 2 && !capture && givesCheck && alpha < 0
&& pos.non_pawn_material(us) == PieceValue[movedPiece]
&& PieceValue[movedPiece] >= RookValue
&& !(PseudoAttacks[KING][pos.square<KING>(us)] & move.from_sq()))
skip = mp.otherPieceTypesMobile(
type_of(movedPiece),
capturesSearched); // if the opponent captures last mobile piece it might be stalemate
if (skip)
continue;
}
}
else
{
@@ -1542,7 +1555,8 @@ moves_loop: // When in check, search starts here
bestValue >= beta ? BOUND_LOWER
: PvNode && bestMove ? BOUND_EXACT
: BOUND_UPPER,
depth, bestMove, unadjustedStaticEval, tt.generation());
moveCount != 0 ? depth : std::min(MAX_PLY - 1, depth + 6), bestMove,
unadjustedStaticEval, tt.generation());
// Adjust correction history
if (!ss->inCheck && !(bestMove && pos.capture(bestMove))
@@ -1797,6 +1811,22 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
if (!is_decisive(bestValue) && bestValue > beta)
bestValue = (bestValue + beta) / 2;
Color us = pos.side_to_move();
if (!ss->inCheck && !moveCount && !pos.non_pawn_material(us)
&& type_of(pos.captured_piece()) >= ROOK)
{
if (!((us == WHITE ? shift<NORTH>(pos.pieces(us, PAWN))
: shift<SOUTH>(pos.pieces(us, PAWN)))
& ~pos.pieces())) // no pawn pushes available
{
pos.state()->checkersBB = Rank1BB; // search for legal king-moves only
if (!MoveList<LEGAL>(pos).size()) // stalemate
bestValue = VALUE_DRAW;
pos.state()->checkersBB = 0;
}
}
// Save gathered info in transposition table. The static evaluation
// is saved as it was before adjustment by correction history.
Distributed::save(tt, threads, thisThread, ttWriter, posKey, value_to_tt(bestValue, ss->ply),