After we set ss->threatMove we could go under a IID step that
resets SearchStack ss and so also ss->threatMove.
When later we use that field in futility pruning we have this
set to MOVE_NONE !
The fix is to use a local variable and add threatMove to SplitPoint
to pass this move to slaves.
Spotted by Ralph Stoesser, fix suggested by Richard Vida.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
template <bool Fake>
void split(const Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
template <bool Fake>
void split(const Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
- Depth depth, bool mateThreat, int* moveCount, MovePicker* mp, bool pvNode);
+ Depth depth, Move threatMove, bool mateThreat, int* moveCount, MovePicker* mp, bool pvNode);
private:
friend void poll();
private:
friend void poll();
// Called at the beginning of search() when starting to examine a new node.
void SearchStack::init() {
// Called at the beginning of search() when starting to examine a new node.
void SearchStack::init() {
- currentMove = threatMove = bestMove = MOVE_NONE;
+ currentMove = bestMove = MOVE_NONE;
}
// SearchStack::initKillers() initializes killers for a search stack entry
}
// SearchStack::initKillers() initializes killers for a search stack entry
bool mateThreat = false;
int moveCount = 0;
int threadID = pos.thread();
bool mateThreat = false;
int moveCount = 0;
int threadID = pos.thread();
+ Move threatMove = MOVE_NONE;
refinedValue = bestValue = value = -VALUE_INFINITE;
oldAlpha = alpha;
refinedValue = bestValue = value = -VALUE_INFINITE;
oldAlpha = alpha;
if (nullValue == value_mated_in(ply + 2))
mateThreat = true;
if (nullValue == value_mated_in(ply + 2))
mateThreat = true;
- ss->threatMove = (ss+1)->currentMove;
+ threatMove = (ss+1)->currentMove;
if ( depth < ThreatDepth
&& (ss-1)->reduction
if ( depth < ThreatDepth
&& (ss-1)->reduction
- && connected_moves(pos, (ss-1)->currentMove, ss->threatMove))
+ && connected_moves(pos, (ss-1)->currentMove, threatMove))
{
// Move count based pruning
if ( moveCount >= futility_move_count(depth)
{
// Move count based pruning
if ( moveCount >= futility_move_count(depth)
- && !(ss->threatMove && connected_threat(pos, move, ss->threatMove))
+ && !(threatMove && connected_threat(pos, move, threatMove))
&& bestValue > value_mated_in(PLY_MAX))
continue;
&& bestValue > value_mated_in(PLY_MAX))
continue;
&& !TM.thread_should_stop(threadID)
&& Iteration <= 99)
TM.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
&& !TM.thread_should_stop(threadID)
&& Iteration <= 99)
TM.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
- mateThreat, &moveCount, &mp, PvNode);
+ threatMove, mateThreat, &moveCount, &mp, PvNode);
}
// Step 19. Check for mate and stalemate
}
// Step 19. Check for mate and stalemate
{
// Move count based pruning
if ( moveCount >= futility_move_count(sp->depth)
{
// Move count based pruning
if ( moveCount >= futility_move_count(sp->depth)
- && !(ss->threatMove && connected_threat(pos, move, ss->threatMove))
+ && !(sp->threatMove && connected_threat(pos, move, sp->threatMove))
&& sp->bestValue > value_mated_in(PLY_MAX))
{
lock_grab(&(sp->lock));
&& sp->bestValue > value_mated_in(PLY_MAX))
{
lock_grab(&(sp->lock));
template <bool Fake>
void ThreadsManager::split(const Position& p, SearchStack* ss, int ply, Value* alpha,
template <bool Fake>
void ThreadsManager::split(const Position& p, SearchStack* ss, int ply, Value* alpha,
- const Value beta, Value* bestValue, Depth depth, bool mateThreat,
- int* moveCount, MovePicker* mp, bool pvNode) {
+ const Value beta, Value* bestValue, Depth depth, Move threatMove,
+ bool mateThreat, int* moveCount, MovePicker* mp, bool pvNode) {
assert(p.is_ok());
assert(ply > 0 && ply < PLY_MAX);
assert(*bestValue >= -VALUE_INFINITE);
assert(p.is_ok());
assert(ply > 0 && ply < PLY_MAX);
assert(*bestValue >= -VALUE_INFINITE);
splitPoint.stopRequest = false;
splitPoint.ply = ply;
splitPoint.depth = depth;
splitPoint.stopRequest = false;
splitPoint.ply = ply;
splitPoint.depth = depth;
+ splitPoint.threatMove = threatMove;
splitPoint.mateThreat = mateThreat;
splitPoint.alpha = *alpha;
splitPoint.beta = beta;
splitPoint.mateThreat = mateThreat;
splitPoint.alpha = *alpha;
splitPoint.beta = beta;
struct SearchStack {
Move currentMove;
Move mateKiller;
struct SearchStack {
Move currentMove;
Move mateKiller;
Move excludedMove;
Move bestMove;
Move killers[2];
Move excludedMove;
Move bestMove;
Move killers[2];
bool pvNode, mateThreat;
Value beta;
int ply;
bool pvNode, mateThreat;
Value beta;
int ply;
SearchStack sstack[MAX_THREADS][PLY_MAX_PLUS_2];
// Const pointers to shared data
SearchStack sstack[MAX_THREADS][PLY_MAX_PLUS_2];
// Const pointers to shared data