int perft(Position& pos, Depth depth)
{
- if (depth <= Depth(0)) // Replace with '<' to test also qsearch
- return 1;
-
Move move;
MovePicker mp = MovePicker(pos, MOVE_NONE, depth, H);
- Bitboard dcCandidates = mp.discovered_check_candidates();
+ Bitboard dcCandidates = pos.discovered_check_candidates(pos.side_to_move());
int sum = 0;
+ // If we are at the last ply we don't need to do and undo
+ // the moves, just to count them.
+ if (depth <= OnePly) // Replace with '<' to test also qsearch
+ {
+ while ((move = mp.get_next_move()) != MOVE_NONE) sum++;
+ return sum;
+ }
+
// Loop through all legal moves
while ((move = mp.get_next_move()) != MOVE_NONE)
{
assert(ply >= 0 && ply < PLY_MAX);
assert(threadID >= 0 && threadID < ActiveThreads);
+ Move movesSearched[256];
+ EvalInfo ei;
+ StateInfo st;
+ Bitboard dcCandidates;
+ const TTEntry* tte;
+ Move ttMove, move;
+ Depth ext, newDepth;
+ Value oldAlpha, value;
+ bool isCheck, mateThreat, singleReply, moveIsCheck, captureOrPromotion, dangerous;
+ int moveCount = 0;
+ Value bestValue = -VALUE_INFINITE;
+
if (depth < OnePly)
return qsearch(pos, ss, alpha, beta, Depth(0), ply, threadID);
if (pos.is_draw())
return VALUE_DRAW;
- EvalInfo ei;
-
if (ply >= PLY_MAX - 1)
return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID);
// Mate distance pruning
- Value oldAlpha = alpha;
+ oldAlpha = alpha;
alpha = Max(value_mated_in(ply), alpha);
beta = Min(value_mate_in(ply+1), beta);
if (alpha >= beta)
// Transposition table lookup. At PV nodes, we don't use the TT for
// pruning, but only for move ordering.
- const TTEntry* tte = TT.retrieve(pos.get_key());
- Move ttMove = (tte ? tte->move() : MOVE_NONE);
+ tte = TT.retrieve(pos.get_key());
+ ttMove = (tte ? tte->move() : MOVE_NONE);
// Go with internal iterative deepening if we don't have a TT move
if (UseIIDAtPVNodes && ttMove == MOVE_NONE && depth >= 5*OnePly)
// Initialize a MovePicker object for the current position, and prepare
// to search all moves
- Move move, movesSearched[256];
- int moveCount = 0;
- Value value, bestValue = -VALUE_INFINITE;
- Color us = pos.side_to_move();
- bool isCheck = pos.is_check();
- bool mateThreat = pos.has_mate_threat(opposite_color(us));
-
+ isCheck = pos.is_check();
+ mateThreat = pos.has_mate_threat(opposite_color(pos.side_to_move()));
+ dcCandidates = pos.discovered_check_candidates(pos.side_to_move());
MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
- Bitboard dcCandidates = mp.discovered_check_candidates();
// Loop through all legal moves until no moves remain or a beta cutoff
// occurs.
{
assert(move_is_ok(move));
- bool singleReply = (isCheck && mp.number_of_evasions() == 1);
- bool moveIsCheck = pos.move_is_check(move, dcCandidates);
- bool captureOrPromotion = pos.move_is_capture_or_promotion(move);
+ singleReply = (isCheck && mp.number_of_evasions() == 1);
+ moveIsCheck = pos.move_is_check(move, dcCandidates);
+ captureOrPromotion = pos.move_is_capture_or_promotion(move);
movesSearched[moveCount++] = ss[ply].currentMove = move;
// Decide the new search depth
- bool dangerous;
- Depth ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, singleReply, mateThreat, &dangerous);
- Depth newDepth = depth - OnePly + ext;
+ ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, singleReply, mateThreat, &dangerous);
+ newDepth = depth - OnePly + ext;
// Make and search the move
- StateInfo st;
pos.do_move(move, st, dcCandidates);
if (moveCount == 1) // The first move in list is the PV
else if (bestValue >= beta)
{
BetaCounter.add(pos.side_to_move(), depth, threadID);
- Move m = ss[ply].pv[ply];
- if (!pos.move_is_capture_or_promotion(m))
+ move = ss[ply].pv[ply];
+ if (!pos.move_is_capture_or_promotion(move))
{
- update_history(pos, m, depth, movesSearched, moveCount);
- update_killers(m, ss[ply]);
+ update_history(pos, move, depth, movesSearched, moveCount);
+ update_killers(move, ss[ply]);
}
- TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, m);
+ TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move);
}
else
TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, depth, ss[ply].pv[ply]);
assert(ply >= 0 && ply < PLY_MAX);
assert(threadID >= 0 && threadID < ActiveThreads);
+ Move movesSearched[256];
+ EvalInfo ei;
+ StateInfo st;
+ Bitboard dcCandidates;
+ const TTEntry* tte;
+ Move ttMove, move;
+ Depth ext, newDepth;
+ Value approximateEval, nullValue, value, futilityValue;
+ bool isCheck, useFutilityPruning, singleReply, moveIsCheck, captureOrPromotion, dangerous;
+ bool mateThreat = false;
+ int moveCount = 0;
+ Value bestValue = -VALUE_INFINITE;
+
if (depth < OnePly)
return qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
if (pos.is_draw())
return VALUE_DRAW;
- EvalInfo ei;
-
if (ply >= PLY_MAX - 1)
return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID);
return beta - 1;
// Transposition table lookup
- const TTEntry* tte = TT.retrieve(pos.get_key());
- Move ttMove = (tte ? tte->move() : MOVE_NONE);
+ tte = TT.retrieve(pos.get_key());
+ ttMove = (tte ? tte->move() : MOVE_NONE);
if (tte && ok_to_use_TT(tte, depth, beta, ply))
{
return value_from_tt(tte->value(), ply);
}
- Value approximateEval = quick_evaluate(pos);
- bool mateThreat = false;
- bool isCheck = pos.is_check();
+ approximateEval = quick_evaluate(pos);
+ isCheck = pos.is_check();
// Null move search
if ( allowNullmove
{
ss[ply].currentMove = MOVE_NULL;
- StateInfo st;
pos.do_null_move(st);
int R = (depth >= 5 * OnePly ? 4 : 3); // Null move dynamic reduction
- Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
+ nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
pos.undo_null_move();
// Initialize a MovePicker object for the current position, and prepare
// to search all moves.
MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
-
- Move move, movesSearched[256];
- int moveCount = 0;
- Value value, bestValue = -VALUE_INFINITE;
- Bitboard dcCandidates = mp.discovered_check_candidates();
- Value futilityValue = VALUE_NONE;
- bool useFutilityPruning = depth < SelectiveDepth
- && !isCheck;
+ dcCandidates = pos.discovered_check_candidates(pos.side_to_move());
+ futilityValue = VALUE_NONE;
+ useFutilityPruning = depth < SelectiveDepth && !isCheck;
// Avoid calling evaluate() if we already have the score in TT
if (tte && (tte->type() & VALUE_TYPE_EVAL))
{
assert(move_is_ok(move));
- bool singleReply = (isCheck && mp.number_of_evasions() == 1);
- bool moveIsCheck = pos.move_is_check(move, dcCandidates);
- bool captureOrPromotion = pos.move_is_capture_or_promotion(move);
+ singleReply = (isCheck && mp.number_of_evasions() == 1);
+ moveIsCheck = pos.move_is_check(move, dcCandidates);
+ captureOrPromotion = pos.move_is_capture_or_promotion(move);
movesSearched[moveCount++] = ss[ply].currentMove = move;
// Decide the new search depth
- bool dangerous;
- Depth ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, singleReply, mateThreat, &dangerous);
- Depth newDepth = depth - OnePly + ext;
+ ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, singleReply, mateThreat, &dangerous);
+ newDepth = depth - OnePly + ext;
// Futility pruning
if ( useFutilityPruning
}
// Make and search the move
- StateInfo st;
pos.do_move(move, st, dcCandidates);
// Try to reduce non-pv search depth by one ply if move seems not problematic,
else
{
BetaCounter.add(pos.side_to_move(), depth, threadID);
- Move m = ss[ply].pv[ply];
- if (!pos.move_is_capture_or_promotion(m))
+ move = ss[ply].pv[ply];
+ if (!pos.move_is_capture_or_promotion(move))
{
- update_history(pos, m, depth, movesSearched, moveCount);
- update_killers(m, ss[ply]);
+ update_history(pos, move, depth, movesSearched, moveCount);
+ update_killers(move, ss[ply]);
}
- TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, m);
+ TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move);
}
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
assert(ply >= 0 && ply < PLY_MAX);
assert(threadID >= 0 && threadID < ActiveThreads);
+ EvalInfo ei;
+ StateInfo st;
+ Bitboard dcCandidates;
+ Move ttMove, move;
+ Value staticValue, bestValue, value, futilityValue;
+ bool isCheck, enoughMaterial;
+ const TTEntry* tte = NULL;
+ int moveCount = 0;
+ bool pvNode = (beta - alpha != 1);
+
// Initialize, and make an early exit in case of an aborted search,
// an instant draw, maximum ply reached, etc.
init_node(ss, ply, threadID);
return VALUE_DRAW;
// Transposition table lookup, only when not in PV
- TTEntry* tte = NULL;
- bool pvNode = (beta - alpha != 1);
if (!pvNode)
{
tte = TT.retrieve(pos.get_key());
return value_from_tt(tte->value(), ply);
}
}
- Move ttMove = (tte ? tte->move() : MOVE_NONE);
+ ttMove = (tte ? tte->move() : MOVE_NONE);
// Evaluate the position statically
- EvalInfo ei;
- Value staticValue;
- bool isCheck = pos.is_check();
+ isCheck = pos.is_check();
ei.futilityMargin = Value(0); // Manually initialize futilityMargin
if (isCheck)
// Initialize "stand pat score", and return it immediately if it is
// at least beta.
- Value bestValue = staticValue;
+ bestValue = staticValue;
if (bestValue >= beta)
{
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth == 0) will be generated.
MovePicker mp = MovePicker(pos, ttMove, depth, H);
- Move move;
- int moveCount = 0;
- Bitboard dcCandidates = mp.discovered_check_candidates();
- Color us = pos.side_to_move();
- bool enoughMaterial = pos.non_pawn_material(us) > RookValueMidgame;
+ dcCandidates = pos.discovered_check_candidates(pos.side_to_move());
+ enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame;
// Loop through the moves until no moves remain or a beta cutoff
// occurs.
&& !pos.move_is_check(move, dcCandidates)
&& !pos.move_is_passed_pawn_push(move))
{
- Value futilityValue = staticValue
- + Max(pos.midgame_value_of_piece_on(move_to(move)),
- pos.endgame_value_of_piece_on(move_to(move)))
- + (move_is_ep(move) ? PawnValueEndgame : Value(0))
- + FutilityMarginQS
- + ei.futilityMargin;
+ futilityValue = staticValue
+ + Max(pos.midgame_value_of_piece_on(move_to(move)),
+ pos.endgame_value_of_piece_on(move_to(move)))
+ + (move_is_ep(move) ? PawnValueEndgame : Value(0))
+ + FutilityMarginQS
+ + ei.futilityMargin;
if (futilityValue < alpha)
{
&& pos.see_sign(move) < 0)
continue;
- // Make and search the move.
- StateInfo st;
+ // Make and search the move
pos.do_move(move, st, dcCandidates);
- Value value = -qsearch(pos, ss, -beta, -alpha, depth-OnePly, ply+1, threadID);
+ value = -qsearch(pos, ss, -beta, -alpha, depth-OnePly, ply+1, threadID);
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
// Update transposition table
- Move m = ss[ply].pv[ply];
+ move = ss[ply].pv[ply];
if (!pvNode)
{
// If bestValue isn't changed it means it is still the static evaluation of
if (bestValue < beta)
TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE);
else
- TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, m);
+ TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move);
}
// Update killers only for good check moves
- if (alpha >= beta && !pos.move_is_capture_or_promotion(m))
- update_killers(m, ss[ply]);
+ if (alpha >= beta && !pos.move_is_capture_or_promotion(move))
+ update_killers(move, ss[ply]);
return bestValue;
}