/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2009 Marco Costalba
+ Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
bool FirstRootMove, AbortSearch, Quit, AspirationFailLow;
- // Show current line?
- bool ShowCurrentLine;
-
// Log file
bool UseLogFile;
std::ofstream LogFile;
MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * OnePly;
MaxThreadsPerSplitPoint = get_option_value_int("Maximum Number of Threads per Split Point");
- ShowCurrentLine = get_option_value_bool("UCI_ShowCurrLine");
MultiPV = get_option_value_int("MultiPV");
Chess960 = get_option_value_bool("UCI_Chess960");
UseLogFile = get_option_value_bool("Use Search Log");
{
TM.set_active_threads(newActiveThreads);
init_eval(TM.active_threads());
- // HACK: init_eval() destroys the static castleRightsMask[] array in the
- // Position class. The below line repairs the damage.
- Position p(pos.to_fen());
- assert(pos.is_ok());
}
// Wake up sleeping threads
EvalInfo ei;
StateInfo st;
+ CheckInfo ci(pos);
int64_t nodes;
Move move;
Depth depth, ext, newDepth;
Value value, alpha, beta;
bool isCheck, moveIsCheck, captureOrPromotion, dangerous;
- int researchCount = 0;
+ int researchCountFH, researchCountFL;
+
+ researchCountFH = researchCountFL = 0;
alpha = *alphaPtr;
beta = *betaPtr;
- CheckInfo ci(pos);
isCheck = pos.is_check();
// Step 1. Initialize node and poll (omitted at root, but I can see no good reason for this, FIXME)
print_pv_info(pos, ss, alpha, beta, value);
// Prepare for a research after a fail high, each time with a wider window
- researchCount++;
- *betaPtr = beta = Min(beta + AspirationDelta * (1 << researchCount), VALUE_INFINITE);
+ *betaPtr = beta = Min(beta + AspirationDelta * (1 << researchCountFH), VALUE_INFINITE);
+ researchCountFH++;
} // End of fail high loop
break;
// Prepare for a research after a fail low, each time with a wider window
- researchCount++;
- *alphaPtr = alpha = Max(alpha - AspirationDelta * (1 << researchCount), -VALUE_INFINITE);
+ *alphaPtr = alpha = Max(alpha - AspirationDelta * (1 << researchCountFL), -VALUE_INFINITE);
+ researchCountFL++;
} // Fail low loop
tte = TT.retrieve(pos.get_key());
}
- // Step 10. Loop through moves
- // Loop through all legal moves until no moves remain or a beta cutoff occurs
-
// Initialize a MovePicker object for the current position
mateThreat = pos.has_mate_threat(opposite_color(pos.side_to_move()));
MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
CheckInfo ci(pos);
+ // Step 10. Loop through moves
+ // Loop through all legal moves until no moves remain or a beta cutoff occurs
while ( alpha < beta
&& (move = mp.get_next_move()) != MOVE_NONE
&& !TM.thread_should_stop(threadID))
}
// Step 6. Razoring
- if ( !value_is_mate(beta)
+ if ( refinedValue < beta - razor_margin(depth)
+ && ttMove == MOVE_NONE
+ && ss[ply - 1].currentMove != MOVE_NULL
+ && depth < RazorDepth
&& !isCheck
- && depth < RazorDepth
- && refinedValue < beta - razor_margin(depth)
- && ss[ply - 1].currentMove != MOVE_NULL
- && ttMove == MOVE_NONE
+ && !value_is_mate(beta)
&& !pos.has_pawn_on_7th(pos.side_to_move()))
{
Value rbeta = beta - razor_margin(depth);
// Step 7. Static null move pruning
// We're betting that the opponent doesn't have a move that will reduce
- // the score by more than fuility_margin(depth) if we do a null move.
- if ( !isCheck
- && allowNullmove
- && depth < RazorDepth
- && refinedValue - futility_margin(depth, 0) >= beta)
+ // the score by more than futility_margin(depth) if we do a null move.
+ if ( allowNullmove
+ && depth < RazorDepth
+ && !isCheck
+ && !value_is_mate(beta)
+ && ok_to_do_nullmove(pos)
+ && refinedValue >= beta + futility_margin(depth, 0))
return refinedValue - futility_margin(depth, 0);
// Step 8. Null move search with verification search
{
ss[ply].currentMove = MOVE_NULL;
- pos.do_null_move(st);
-
// Null move dynamic reduction based on depth
int R = 3 + (depth >= 5 * OnePly ? depth / 8 : 0);
if (refinedValue - beta > PawnValueMidgame)
R++;
+ pos.do_null_move(st);
+
nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
pos.undo_null_move();
if (nullValue >= beta)
{
+ // Do not return unproven mate scores
+ if (nullValue >= value_mate_in(PLY_MAX))
+ nullValue = beta;
+
if (depth < 6 * OnePly)
- return beta;
+ return nullValue;
// Do zugzwang verification search
Value v = search(pos, ss, beta, depth-5*OnePly, ply, false, threadID);
if (v >= beta)
- return beta;
+ return nullValue;
} else {
// The null move failed low, which means that we may be faced with
// some kind of threat. If the previous move was reduced, check if
tte = TT.retrieve(posKey);
}
- // Step 10. Loop through moves
- // Loop through all legal moves until no moves remain or a beta cutoff occurs
-
// Initialize a MovePicker object for the current position
MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply], beta);
CheckInfo ci(pos);
+ // Step 10. Loop through moves
+ // Loop through all legal moves until no moves remain or a beta cutoff occurs
while ( bestValue < beta
&& (move = mp.get_next_move()) != MOVE_NONE
&& !TM.thread_should_stop(threadID))
if ( depth >= SingularExtensionDepthAtNonPVNodes
&& tte
&& move == tte->move()
- && !excludedMove // Do not allow recursive single-reply search
+ && !excludedMove // Do not allow recursive singular extension search
&& ext < OnePly
&& is_lower_bound(tte->type())
&& tte->depth() >= depth - 3 * OnePly)
// Step 13. Make the move
pos.do_move(move, st, ci, moveIsCheck);
- // Step 14. Reduced search
- // if the move fails high will be re-searched at full depth.
+ // Step 14. Reduced search, if the move fails high
+ // will be re-searched at full depth.
bool doFullDepthSearch = true;
if ( depth >= 3*OnePly
}
// Step 19. Check for mate and stalemate
- // All legal moves have been searched and if there were
+ // All legal moves have been searched and if there are
// no legal moves, it must be mate or stalemate.
- // If one move was excluded return fail low.
+ // If one move was excluded return fail low score.
if (!moveCount)
- return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
+ return excludedMove ? beta - 1 : (isCheck ? value_mated_in(ply) : VALUE_DRAW);
// Step 20. Update tables
// If the search is not aborted, update the transposition table,
enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame;
futilityBase = staticValue + FutilityMarginQS + ei.futilityMargin[pos.side_to_move()];
- // Loop through the moves until no moves remain or a beta cutoff
- // occurs.
+ // Loop through the moves until no moves remain or a beta cutoff occurs
while ( alpha < beta
&& (move = mp.get_next_move()) != MOVE_NONE)
{
// All legal moves have been searched. A special case: If we're in check
// and no legal moves were found, it is checkmate.
- if (!moveCount && pos.is_check()) // Mate!
+ if (!moveCount && isCheck) // Mate!
return value_mated_in(ply);
// Update transposition table
cout << "info nodes " << TM.nodes_searched() << " nps " << nps()
<< " time " << t << " hashfull " << TT.full() << endl;
-
- // We only support current line printing in single thread mode
- if (ShowCurrentLine && TM.active_threads() == 1)
- {
- cout << "info currline";
- for (int p = 0; p < ply; p++)
- cout << " " << ss[p].currentMove;
-
- cout << endl;
- }
}
// Should we stop the search?