////
#include <cassert>
+#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
};
- /// Constants and variables
+ /// Constants and variables initialized from UCI options
// Minimum number of full depth (i.e. non-reduced) moves at PV and non-PV
- // nodes:
- int LMRPVMoves = 15;
- int LMRNonPVMoves = 4;
+ // nodes
+ int LMRPVMoves, LMRNonPVMoves;
- // Depth limit for use of dynamic threat detection:
- Depth ThreatDepth = 5*OnePly;
+ // Depth limit for use of dynamic threat detection
+ Depth ThreatDepth;
- // Depth limit for selective search:
- Depth SelectiveDepth = 7*OnePly;
+ // Depth limit for selective search
+ const Depth SelectiveDepth = 7*OnePly;
// Use internal iterative deepening?
const bool UseIIDAtPVNodes = true;
const bool PruneBlockingMoves = false;
// Use futility pruning?
- bool UseQSearchFutilityPruning = true;
- bool UseFutilityPruning = true;
+ bool UseQSearchFutilityPruning, UseFutilityPruning;
// Margins for futility pruning in the quiescence search, and at frontier
// and near frontier nodes
- Value FutilityMarginQS = Value(0x80);
+ Value FutilityMarginQS;
Value FutilityMargins[6] = { Value(0x100), Value(0x200), Value(0x250),
Value(0x2A0), Value(0x340), Value(0x3A0) };
// Razoring
const bool RazorAtDepthOne = false;
- Depth RazorDepth = 4*OnePly;
- Value RazorMargin = Value(0x300);
+ Depth RazorDepth;
+ Value RazorMargin;
// Last seconds noise filtering (LSN)
- bool UseLSNFiltering = false;
+ bool UseLSNFiltering;
bool looseOnTime = false;
- int LSNTime = 4 * 1000; // In milliseconds
- Value LSNValue = Value(0x200);
+ int LSNTime; // In milliseconds
+ Value LSNValue;
- // Extensions. Array index 0 is used at non-PV nodes, index 1 at PV nodes.
- Depth CheckExtension[2] = {OnePly, OnePly};
- Depth SingleReplyExtension[2] = {OnePly / 2, OnePly / 2};
- Depth PawnPushTo7thExtension[2] = {OnePly / 2, OnePly / 2};
- Depth PassedPawnExtension[2] = {Depth(0), Depth(0)};
- Depth PawnEndgameExtension[2] = {OnePly, OnePly};
- Depth MateThreatExtension[2] = {Depth(0), Depth(0)};
+ // Extensions. Array index 0 is used at non-PV nodes, index 1 at PV nodes.
+ Depth CheckExtension[2], SingleReplyExtension[2], PawnPushTo7thExtension[2];
+ Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2];
// Search depth at iteration 1
const Depth InitialDepth = OnePly /*+ OnePly/2*/;
int BestMoveChangesByIteration[PLY_MAX_PLUS_2];
// MultiPV mode
- int MultiPV = 1;
+ int MultiPV;
// Time managment variables
int SearchStartTime;
int ExactMaxTime;
// Show current line?
- bool ShowCurrentLine = false;
+ bool ShowCurrentLine;
// Log file
- bool UseLogFile = false;
+ bool UseLogFile;
std::ofstream LogFile;
// MP related variables
- Depth MinimumSplitDepth = 4*OnePly;
- int MaxThreadsPerSplitPoint = 4;
+ Depth MinimumSplitDepth;
+ int MaxThreadsPerSplitPoint;
Thread Threads[THREAD_MAX];
Lock MPLock;
bool AllThreadsShouldExit = false;
////
// The main transposition table
-TranspositionTable TT = TranspositionTable(TTDefaultSize);
+TranspositionTable TT;
// Number of active threads:
LMRPVMoves = get_option_value_int("Full Depth Moves (PV nodes)") + 1;
LMRNonPVMoves = get_option_value_int("Full Depth Moves (non-PV nodes)") + 1;
ThreatDepth = get_option_value_int("Threat Depth") * OnePly;
- SelectiveDepth = get_option_value_int("Selective Plies") * OnePly;
Chess960 = get_option_value_bool("UCI_Chess960");
ShowCurrentLine = get_option_value_bool("UCI_ShowCurrLine");
return bestValue;
if (bestValue <= oldAlpha)
- TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_UPPER);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE);
else if (bestValue >= beta)
{
update_history(pos, m, depth, movesSearched, moveCount);
update_killers(m, ss[ply]);
}
- TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, m);
}
else
- TT.store(pos, value_to_tt(bestValue, ply), depth, ss[ply].pv[ply], VALUE_TYPE_EXACT);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, depth, ss[ply].pv[ply]);
return bestValue;
}
continue;
// Value based pruning
- if (depth < 7 * OnePly && approximateEval < beta)
+ if (approximateEval < beta)
{
if (futilityValue == VALUE_NONE)
futilityValue = evaluate(pos, ei, threadID)
return bestValue;
if (bestValue < beta)
- TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_UPPER);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE);
else
{
BetaCounter.add(pos.side_to_move(), depth, threadID);
update_history(pos, m, depth, movesSearched, moveCount);
update_killers(m, ss[ply]);
}
- TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, m);
}
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
return value_from_tt(tte->value(), ply);
}
}
+ Move ttMove = (tte ? tte->move() : MOVE_NONE);
// Evaluate the position statically
EvalInfo ei;
{
// Store the score to avoid a future costly evaluation() call
if (!isCheck && !tte && ei.futilityMargin == 0)
- TT.store(pos, value_to_tt(bestValue, ply), Depth(-127*OnePly), MOVE_NONE, VALUE_TYPE_EVAL);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_EVAL, Depth(-127*OnePly), MOVE_NONE);
return bestValue;
}
// Initialize a MovePicker object for the current position, and prepare
// 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, pvNode, MOVE_NONE, EmptySearchStack, depth);
+ MovePicker mp = MovePicker(pos, pvNode, ttMove, EmptySearchStack, depth);
Move move;
int moveCount = 0;
Bitboard dcCandidates = mp.discovered_check_candidates();
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
// Update transposition table
+ Move m = ss[ply].pv[ply];
if (!pvNode)
{
Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
if (bestValue < beta)
- TT.store(pos, value_to_tt(bestValue, ply), d, MOVE_NONE, VALUE_TYPE_UPPER);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, d, MOVE_NONE);
else
- TT.store(pos, value_to_tt(bestValue, ply), d, MOVE_NONE, VALUE_TYPE_LOWER);
+ TT.store(pos, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, m);
}
// Update killers only for good check moves
- Move m = ss[ply].currentMove;
if (alpha >= beta && ok_to_history(pos, m)) // Only non capture moves are considered
- {
- // Wrong to update history when depth is <= 0
update_killers(m, ss[ply]);
- }
+
return bestValue;
}