Move ttMove, move, excludedMove, bestMove;
Depth extension, newDepth;
Value bestValue, value, ttValue, eval, maxValue, probCutBeta;
- bool ttHit, ttPv, formerPv, givesCheck, improving, didLMR, priorCapture;
+ bool ttHit, formerPv, givesCheck, improving, didLMR, priorCapture;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
ttCapture, singularQuietLMR;
Piece movedPiece;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
(ss+1)->ply = ss->ply + 1;
+ (ss+1)->ttPv = false;
(ss+1)->excludedMove = bestMove = MOVE_NONE;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
Square prevSq = to_sq((ss-1)->currentMove);
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
: ttHit ? tte->move() : MOVE_NONE;
- ttPv = PvNode || (ttHit && tte->is_pv());
- formerPv = ttPv && !PvNode;
+ if (!excludedMove)
+ ss->ttPv = PvNode || (ttHit && tte->is_pv());
+ formerPv = ss->ttPv && !PvNode;
- if ( ttPv
+ if ( ss->ttPv
&& depth > 12
&& ss->ply - 1 < MAX_LPH
&& !priorCapture
if ( b == BOUND_EXACT
|| (b == BOUND_LOWER ? value >= beta : value <= alpha))
{
- tte->save(posKey, value_to_tt(value, ss->ply), ttPv, b,
+ tte->save(posKey, value_to_tt(value, ss->ply), ss->ttPv, b,
std::min(MAX_PLY - 1, depth + 6),
MOVE_NONE, VALUE_NONE);
else
ss->staticEval = eval = -(ss-1)->staticEval + 2 * Tempo;
- tte->save(posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
+ tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
}
// Step 7. Razoring (~1 Elo)
&& (ss-1)->statScore < 22977
&& eval >= beta
&& eval >= ss->staticEval
- && ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ttPv + 182
+ && ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ss->ttPv + 182
&& !excludedMove
&& pos.non_pawn_material(us)
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
assert(probCutBeta < VALUE_INFINITE);
MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
int probCutCount = 0;
+ bool ttPv = ss->ttPv;
+ ss->ttPv = false;
while ( (move = mp.next_move()) != MOVE_NONE
&& probCutCount < 2 + 2 * cutNode)
return value;
}
}
+ ss->ttPv = ttPv;
}
-
+
// Step 11. If the position is not in TT, decrease depth by 2
if ( PvNode
&& depth >= 6
r++;
// Decrease reduction if position is or has been on the PV (~10 Elo)
- if (ttPv)
+ if (ss->ttPv)
r -= 2;
if (moveCountPruning && !formerPv)
// hence break make_move(). (~2 Elo)
else if ( type_of(move) == NORMAL
&& !pos.see_ge(reverse_move(move)))
- r -= 2 + ttPv - (type_of(movedPiece) == PAWN);
+ r -= 2 + ss->ttPv - (type_of(movedPiece) == PAWN);
ss->statScore = thisThread->mainHistory[us][from_to(move)]
+ (*contHist[0])[movedPiece][to_sq(move)]
if (PvNode)
bestValue = std::min(bestValue, maxValue);
+ // If no good move is found and the previous position was ttPv, then the previous
+ // opponent move is probably good and the new position is added to the search tree.
+ if (bestValue <= alpha)
+ ss->ttPv = ss->ttPv || ((ss-1)->ttPv && depth > 3);
+ // Otherwise, a counter move has been found and if the position is the last leaf
+ // in the search tree, remove the position from the search tree.
+ else if (depth > 3)
+ ss->ttPv = ss->ttPv && (ss+1)->ttPv;
+
if (!excludedMove && !(rootNode && thisThread->pvIdx))
- tte->save(posKey, value_to_tt(bestValue, ss->ply), ttPv,
+ tte->save(posKey, value_to_tt(bestValue, ss->ply), ss->ttPv,
bestValue >= beta ? BOUND_LOWER :
PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
depth, bestMove, ss->staticEval);
assert(type_of(move) != ENPASSANT); // Due to !pos.advanced_pawn_push
// moveCount pruning
- if (moveCount > abs(depth) + 2)
+ if (moveCount > 2)
continue;
futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))];