And avoid a redundant one passed as argument in
search calls.
Also renamed gamePly in ply to better clarify this
is used as search ply and is set to zero at the
beginning of the search.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
// pointer to point to the new, ready to be updated, state.
struct ReducedStateInfo {
Key pawnKey, materialKey;
// pointer to point to the new, ready to be updated, state.
struct ReducedStateInfo {
Key pawnKey, materialKey;
- int castleRights, rule50, gamePly, pliesFromNull;
+ int castleRights, rule50, ply, pliesFromNull;
Square epSquare;
Score value;
Value npMaterial[2];
Square epSquare;
Score value;
Value npMaterial[2];
// Save the current key to the history[] array, in order to be able to
// detect repetition draws.
// Save the current key to the history[] array, in order to be able to
// detect repetition draws.
- history[st->gamePly++] = key;
+ history[st->ply++] = key;
// Update side to move
key ^= zobSideToMove;
// Update side to move
key ^= zobSideToMove;
set_bit(&(byTypeBB[promotion]), to);
board[to] = piece_of_color_and_type(us, promotion);
set_bit(&(byTypeBB[promotion]), to);
board[to] = piece_of_color_and_type(us, promotion);
pieceCount[us][promotion]++;
pieceCount[us][PAWN]--;
pieceCount[us][promotion]++;
pieceCount[us][PAWN]--;
// Save the current key to the history[] array, in order to be able to
// detect repetition draws.
// Save the current key to the history[] array, in order to be able to
// detect repetition draws.
- history[st->gamePly++] = st->key;
+ history[st->ply++] = st->key;
// Update the necessary information
if (st->epSquare != SQ_NONE)
// Update the necessary information
if (st->epSquare != SQ_NONE)
// Update the necessary information
sideToMove = opposite_color(sideToMove);
st->rule50--;
// Update the necessary information
sideToMove = opposite_color(sideToMove);
st->rule50--;
-/// Position::reset_game_ply() simply sets gamePly to 0. It is used from the
+/// Position::reset_ply() simply sets ply to 0. It is used from the
/// UCI interface code, whenever a non-reversible move is made in a
/// 'position fen <fen> moves m1 m2 ...' command. This makes it possible
/// for the program to handle games of arbitrary length, as long as the GUI
/// handles draws by the 50 move rule correctly.
/// UCI interface code, whenever a non-reversible move is made in a
/// 'position fen <fen> moves m1 m2 ...' command. This makes it possible
/// for the program to handle games of arbitrary length, as long as the GUI
/// handles draws by the 50 move rule correctly.
-void Position::reset_game_ply() {
+void Position::reset_ply() {
if (st->rule50 > 100 || (st->rule50 == 100 && !is_check()))
return true;
if (st->rule50 > 100 || (st->rule50 == 100 && !is_check()))
return true;
- // Draw by repetition?
- for (int i = 4, e = Min(Min(st->gamePly, st->rule50), st->pliesFromNull); i <= e; i += 2)
- if (history[st->gamePly - i] == st->key)
+ assert(st->ply >= st->rule50);
+
+ // Draw by repetition?
+ for (int i = 4, e = Min(st->rule50, st->pliesFromNull); i <= e; i += 2)
+ if (history[st->ply - i] == st->key)
return true;
return false;
return true;
return false;
struct StateInfo {
Key pawnKey, materialKey;
struct StateInfo {
Key pawnKey, materialKey;
- int castleRights, rule50, gamePly, pliesFromNull;
+ int castleRights, rule50, ply, pliesFromNull;
Square epSquare;
Score value;
Value npMaterial[2];
Square epSquare;
Score value;
Value npMaterial[2];
// Game ply information
int ply() const;
// Game ply information
int ply() const;
// Position consistency check, for debugging
bool is_ok(int* failedStep = NULL) const;
// Position consistency check, for debugging
bool is_ok(int* failedStep = NULL) const;
}
inline int Position::ply() const {
}
inline int Position::ply() const {
}
#endif // !defined(POSITION_H_INCLUDED)
}
#endif // !defined(POSITION_H_INCLUDED)
void idle_loop(int threadID, SplitPoint* sp);
template <bool Fake>
void idle_loop(int threadID, SplitPoint* sp);
template <bool Fake>
- void split(const Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
+ void split(const Position& pos, SearchStack* ss, Value* alpha, const Value beta, Value* bestValue,
Depth depth, bool mateThreat, int* moveCount, MovePicker* mp, int master, bool pvNode);
private:
Depth depth, bool mateThreat, int* moveCount, MovePicker* mp, int master, bool pvNode);
private:
Value root_search(Position& pos, SearchStack* ss, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
template <NodeType PvNode>
Value root_search(Position& pos, SearchStack* ss, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
template <NodeType PvNode>
- Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply, bool allowNullmove, int threadID, Move excludedMove = MOVE_NONE);
+ Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, bool allowNullmove, int threadID, Move excludedMove = MOVE_NONE);
template <NodeType PvNode>
template <NodeType PvNode>
- Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply, int threadID);
+ Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int threadID);
template <NodeType PvNode>
void sp_search(SplitPoint* sp, int threadID);
template <NodeType PvNode>
void sp_search(SplitPoint* sp, int threadID);
H.clear();
init_ss_array(ss);
ValueByIteration[1] = rml.get_move_score(0);
H.clear();
init_ss_array(ss);
ValueByIteration[1] = rml.get_move_score(0);
Iteration = 1;
// Is one move significantly better than others after initial scoring ?
Iteration = 1;
// Is one move significantly better than others after initial scoring ?
alpha = -VALUE_INFINITE;
// Full depth PV search, done on first move or after a fail high
alpha = -VALUE_INFINITE;
// Full depth PV search, done on first move or after a fail high
- value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, 1, false, 0);
+ value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false, 0);
if (ss->reduction)
{
// Reduced depth non-pv search using alpha as upperbound
if (ss->reduction)
{
// Reduced depth non-pv search using alpha as upperbound
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, 1, true, 0);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, true, 0);
doFullDepthSearch = (value > alpha);
}
}
doFullDepthSearch = (value > alpha);
}
}
{
// Full depth non-pv search using alpha as upperbound
ss->reduction = Depth(0);
{
// Full depth non-pv search using alpha as upperbound
ss->reduction = Depth(0);
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, 1, true, 0);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, true, 0);
// If we are above alpha then research at same depth but as PV
// to get a correct score or eventually a fail high above beta.
if (value > alpha)
// If we are above alpha then research at same depth but as PV
// to get a correct score or eventually a fail high above beta.
if (value > alpha)
- value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, 1, false, 0);
+ value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false, 0);
template <NodeType PvNode>
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth,
template <NodeType PvNode>
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth,
- int ply, bool allowNullmove, int threadID, Move excludedMove) {
+ bool allowNullmove, int threadID, Move excludedMove) {
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
assert(beta > alpha && beta <= VALUE_INFINITE);
assert(PvNode || alpha == beta - 1);
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
assert(beta > alpha && beta <= VALUE_INFINITE);
assert(PvNode || alpha == beta - 1);
- assert(ply >= 0 && ply < PLY_MAX);
+ assert(pos.ply() > 0 && pos.ply() < PLY_MAX);
assert(threadID >= 0 && threadID < TM.active_threads());
Move movesSearched[256];
assert(threadID >= 0 && threadID < TM.active_threads());
Move movesSearched[256];
bool isCheck, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
bool mateThreat = false;
int moveCount = 0;
bool isCheck, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
bool mateThreat = false;
int moveCount = 0;
refinedValue = bestValue = value = -VALUE_INFINITE;
oldAlpha = alpha;
if (depth < OnePly)
refinedValue = bestValue = value = -VALUE_INFINITE;
oldAlpha = alpha;
if (depth < OnePly)
- return qsearch<PvNode>(pos, ss, alpha, beta, Depth(0), ply, threadID);
+ return qsearch<PvNode>(pos, ss, alpha, beta, Depth(0), threadID);
// Step 1. Initialize node and poll
// Polling can abort search.
// Step 1. Initialize node and poll
// Polling can abort search.
&& !pos.has_pawn_on_7th(pos.side_to_move()))
{
Value rbeta = beta - razor_margin(depth);
&& !pos.has_pawn_on_7th(pos.side_to_move()))
{
Value rbeta = beta - razor_margin(depth);
- Value v = qsearch<NonPV>(pos, ss, rbeta-1, rbeta, Depth(0), ply, threadID);
+ Value v = qsearch<NonPV>(pos, ss, rbeta-1, rbeta, Depth(0), threadID);
if (v < rbeta)
// Logically we should return (v + razor_margin(depth)), but
// surprisingly this did slightly weaker in tests.
if (v < rbeta)
// Logically we should return (v + razor_margin(depth)), but
// surprisingly this did slightly weaker in tests.
- nullValue = -search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*OnePly, ply+1, false, threadID);
+ nullValue = -search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*OnePly, false, threadID);
return nullValue;
// Do zugzwang verification search
return nullValue;
// Do zugzwang verification search
- Value v = search<NonPV>(pos, ss, alpha, beta, depth-5*OnePly, ply, false, threadID);
+ Value v = search<NonPV>(pos, ss, alpha, beta, depth-5*OnePly, false, threadID);
if (v >= beta)
return nullValue;
} else {
if (v >= beta)
return nullValue;
} else {
&& (PvNode || (!isCheck && ss->eval >= beta - IIDMargin)))
{
Depth d = (PvNode ? depth - 2 * OnePly : depth / 2);
&& (PvNode || (!isCheck && ss->eval >= beta - IIDMargin)))
{
Depth d = (PvNode ? depth - 2 * OnePly : depth / 2);
- search<PvNode>(pos, ss, alpha, beta, d, ply, false, threadID);
+ search<PvNode>(pos, ss, alpha, beta, d, false, threadID);
ttMove = ss->pv[ply];
tte = TT.retrieve(posKey);
}
ttMove = ss->pv[ply];
tte = TT.retrieve(posKey);
}
if (abs(ttValue) < VALUE_KNOWN_WIN)
{
Value b = ttValue - SingularExtensionMargin;
if (abs(ttValue) < VALUE_KNOWN_WIN)
{
Value b = ttValue - SingularExtensionMargin;
- Value v = search<NonPV>(pos, ss, b - 1, b, depth / 2, ply, false, threadID, move);
+ Value v = search<NonPV>(pos, ss, b - 1, b, depth / 2, false, threadID, move);
if (v < ttValue - SingularExtensionMargin)
ext = OnePly;
if (v < ttValue - SingularExtensionMargin)
ext = OnePly;
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (PvNode && moveCount == 1)
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (PvNode && moveCount == 1)
- value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1, false, threadID);
+ value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false, threadID);
else
{
// Step 14. Reduced depth search
else
{
// Step 14. Reduced depth search
ss->reduction = reduction<PvNode>(depth, moveCount);
if (ss->reduction)
{
ss->reduction = reduction<PvNode>(depth, moveCount);
if (ss->reduction)
{
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, ply+1, true, threadID);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, true, threadID);
doFullDepthSearch = (value > alpha);
}
doFullDepthSearch = (value > alpha);
}
if (doFullDepthSearch && ss->reduction > 2 * OnePly)
{
ss->reduction = OnePly;
if (doFullDepthSearch && ss->reduction > 2 * OnePly)
{
ss->reduction = OnePly;
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, ply+1, true, threadID);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, true, threadID);
doFullDepthSearch = (value > alpha);
}
}
doFullDepthSearch = (value > alpha);
}
}
if (doFullDepthSearch)
{
ss->reduction = Depth(0);
if (doFullDepthSearch)
{
ss->reduction = Depth(0);
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, ply+1, true, threadID);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, true, threadID);
// Step extra. pv search (only in PV nodes)
// Search only for possible new PV nodes, if instead value >= beta then
// parent node fails low with value <= alpha and tries another move.
if (PvNode && value > alpha && value < beta)
// Step extra. pv search (only in PV nodes)
// Search only for possible new PV nodes, if instead value >= beta then
// parent node fails low with value <= alpha and tries another move.
if (PvNode && value > alpha && value < beta)
- value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1, false, threadID);
+ value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false, threadID);
&& TM.available_thread_exists(threadID)
&& !AbortSearch
&& !TM.thread_should_stop(threadID))
&& TM.available_thread_exists(threadID)
&& !AbortSearch
&& !TM.thread_should_stop(threadID))
- TM.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
+ TM.split<FakeSplit>(pos, ss, &alpha, beta, &bestValue, depth,
mateThreat, &moveCount, &mp, threadID, PvNode);
}
mateThreat, &moveCount, &mp, threadID, PvNode);
}
// less than OnePly).
template <NodeType PvNode>
// less than OnePly).
template <NodeType PvNode>
- Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta,
- Depth depth, int ply, int threadID) {
+ Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int threadID) {
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
assert(PvNode || alpha == beta - 1);
assert(depth <= 0);
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
assert(PvNode || alpha == beta - 1);
assert(depth <= 0);
- assert(ply >= 0 && ply < PLY_MAX);
+ assert(pos.ply() > 0 && pos.ply() < PLY_MAX);
assert(threadID >= 0 && threadID < TM.active_threads());
EvalInfo ei;
assert(threadID >= 0 && threadID < TM.active_threads());
EvalInfo ei;
bool isCheck, enoughMaterial, moveIsCheck, evasionPrunable;
const TTEntry* tte = NULL;
int moveCount = 0;
bool isCheck, enoughMaterial, moveIsCheck, evasionPrunable;
const TTEntry* tte = NULL;
int moveCount = 0;
Value oldAlpha = alpha;
// Initialize, and make an early exit in case of an aborted search,
Value oldAlpha = alpha;
// Initialize, and make an early exit in case of an aborted search,
// Make and search the move
pos.do_move(move, st, ci, moveIsCheck);
// Make and search the move
pos.do_move(move, st, ci, moveIsCheck);
- value = -qsearch<PvNode>(pos, ss+1, -beta, -alpha, depth-OnePly, ply+1, threadID);
+ value = -qsearch<PvNode>(pos, ss+1, -beta, -alpha, depth-OnePly, threadID);
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
Position pos(*sp->pos);
CheckInfo ci(pos);
Position pos(*sp->pos);
CheckInfo ci(pos);
SearchStack* ss = sp->sstack[threadID] + 1;
isCheck = pos.is_check();
SearchStack* ss = sp->sstack[threadID] + 1;
isCheck = pos.is_check();
if (ss->reduction)
{
Value localAlpha = sp->alpha;
if (ss->reduction)
{
Value localAlpha = sp->alpha;
- value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth-ss->reduction, sp->ply+1, true, threadID);
+ value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth-ss->reduction, true, threadID);
doFullDepthSearch = (value > localAlpha);
}
doFullDepthSearch = (value > localAlpha);
}
{
ss->reduction = OnePly;
Value localAlpha = sp->alpha;
{
ss->reduction = OnePly;
Value localAlpha = sp->alpha;
- value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth-ss->reduction, sp->ply+1, true, threadID);
+ value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth-ss->reduction, true, threadID);
doFullDepthSearch = (value > localAlpha);
}
}
doFullDepthSearch = (value > localAlpha);
}
}
{
ss->reduction = Depth(0);
Value localAlpha = sp->alpha;
{
ss->reduction = Depth(0);
Value localAlpha = sp->alpha;
- value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth, sp->ply+1, true, threadID);
+ value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth, true, threadID);
if (PvNode && value > localAlpha && value < sp->beta)
if (PvNode && value > localAlpha && value < sp->beta)
- value = -search<PV>(pos, ss+1, -sp->beta, -sp->alpha, newDepth, sp->ply+1, false, threadID);
+ value = -search<PV>(pos, ss+1, -sp->beta, -sp->alpha, newDepth, false, threadID);
if (PvNode && value < sp->beta) // This guarantees that always: sp->alpha < sp->beta
sp->alpha = value;
if (PvNode && value < sp->beta) // This guarantees that always: sp->alpha < sp->beta
sp->alpha = value;
- sp_update_pv(sp->parentSstack, ss, sp->ply);
+ sp_update_pv(sp->parentSstack, ss, ply);
// split() returns.
template <bool Fake>
// split() returns.
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, int master, bool pvNode) {
+ void ThreadsManager::split(const Position& p, SearchStack* ss, Value* alpha, const Value beta,
+ Value* bestValue, Depth depth, bool mateThreat, int* moveCount,
+ MovePicker* mp, int master, bool pvNode) {
- assert(ply > 0 && ply < PLY_MAX);
assert(*bestValue >= -VALUE_INFINITE);
assert(*bestValue <= *alpha);
assert(*alpha < beta);
assert(*bestValue >= -VALUE_INFINITE);
assert(*bestValue <= *alpha);
assert(*alpha < beta);
// Initialize the split point object
splitPoint->parent = threads[master].splitPoint;
splitPoint->stopRequest = false;
// Initialize the split point object
splitPoint->parent = threads[master].splitPoint;
splitPoint->stopRequest = false;
splitPoint->depth = depth;
splitPoint->mateThreat = mateThreat;
splitPoint->alpha = *alpha;
splitPoint->depth = depth;
splitPoint->mateThreat = mateThreat;
splitPoint->alpha = *alpha;
init_ss_array(ss);
pos.do_move(cur->move, st);
moves[count].move = cur->move;
init_ss_array(ss);
pos.do_move(cur->move, st);
moves[count].move = cur->move;
- moves[count].score = -qsearch<PV>(pos, ss+1, -VALUE_INFINITE, VALUE_INFINITE, Depth(0), 1, 0);
+ moves[count].score = -qsearch<PV>(pos, ss+1, -VALUE_INFINITE, VALUE_INFINITE, Depth(0), 0);
moves[count].pv[0] = cur->move;
moves[count].pv[1] = MOVE_NONE;
pos.undo_move(cur->move);
moves[count].pv[0] = cur->move;
moves[count].pv[1] = MOVE_NONE;
pos.undo_move(cur->move);
Depth depth;
bool pvNode, mateThreat;
Value beta;
Depth depth;
bool pvNode, mateThreat;
Value beta;
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
move = move_from_string(RootPosition, token);
RootPosition.do_move(move, st);
if (RootPosition.rule_50_counter() == 0)
move = move_from_string(RootPosition, token);
RootPosition.do_move(move, st);
if (RootPosition.rule_50_counter() == 0)
- RootPosition.reset_game_ply();
+ RootPosition.reset_ply();
}
// Our StateInfo st is about going out of scope so copy
// its content inside RootPosition before they disappear.
}
// Our StateInfo st is about going out of scope so copy
// its content inside RootPosition before they disappear.