/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
+ Copyright (C) 2008-2015 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
CheckInfo ci(pos);
const bool leaf = (depth == 2 * ONE_PLY);
- for (MoveList<LEGAL> it(pos); *it; ++it)
+ for (const ExtMove& ms : MoveList<LEGAL>(pos))
{
if (Root && depth <= ONE_PLY)
cnt = 1, nodes++;
else
{
- pos.do_move(*it, st, ci, pos.gives_check(*it, ci));
+ pos.do_move(ms.move, st, ci, pos.gives_check(ms.move, ci));
cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
nodes += cnt;
- pos.undo_move(*it);
+ pos.undo_move(ms.move);
}
if (Root)
- sync_cout << UCI::move(*it, pos.is_chess960()) << ": " << cnt << sync_endl;
+ sync_cout << UCI::move(ms.move, pos.is_chess960()) << ": " << cnt << sync_endl;
}
return nodes;
}
}
}
- for (size_t i = 0; i < Threads.size(); ++i)
- Threads[i]->maxPly = 0;
+ for (Thread* th : Threads)
+ th->maxPly = 0;
Threads.timer->run = true;
Threads.timer->notify_one(); // Wake up the recurring timer
// Save the last iteration's scores before first PV line is searched and
// all the move scores except the (new) PV are set to -VALUE_INFINITE.
- for (size_t i = 0; i < RootMoves.size(); ++i)
- RootMoves[i].previousScore = RootMoves[i].score;
+ for (RootMove& rm : RootMoves)
+ rm.previousScore = rm.score;
// MultiPV loop. We perform a full root search for each PV line
for (PVIdx = 0; PVIdx < std::min(multiPV, RootMoves.size()) && !Signals.stop; ++PVIdx)
splitPoint = ss->splitPoint;
bestMove = splitPoint->bestMove;
bestValue = splitPoint->bestValue;
- tte = NULL;
+ tte = nullptr;
ttHit = false;
ttMove = excludedMove = MOVE_NONE;
ttValue = VALUE_NONE;
// If ttMove is quiet, update killers, history, counter move and followup move on TT hit
if (ttValue >= beta && ttMove && !pos.capture_or_promotion(ttMove) && !inCheck)
- update_stats(pos, ss, ttMove, depth, NULL, 0);
+ update_stats(pos, ss, ttMove, depth, nullptr, 0);
return ttValue;
}
else if (ttHit)
{
// Never assume anything on values stored in TT
- if ((ss->staticEval = eval = tte->eval_value()) == VALUE_NONE)
+ if ((ss->staticEval = eval = tte->eval()) == VALUE_NONE)
eval = ss->staticEval = evaluate(pos);
// Can ttValue be used as a better position evaluation?
}
// Step 7. Futility pruning: child node (skipped when in check)
- if ( !PvNode
+ if ( !RootNode
&& depth < 7 * ONE_PLY
&& eval - futility_margin(depth) >= beta
&& eval < VALUE_KNOWN_WIN // Do not return unproven wins
}
if (PvNode)
- (ss+1)->pv = NULL;
+ (ss+1)->pv = nullptr;
extension = DEPTH_ZERO;
captureOrPromotion = pos.capture_or_promotion(move);
// Update the current move (this must be done after singular extension search)
newDepth = depth - ONE_PLY + extension;
- // Step 13. Pruning at shallow depth (exclude PV nodes)
- if ( !PvNode
- && !captureOrPromotion
+ // Step 13. Pruning at shallow depth
+ if ( !captureOrPromotion
&& !inCheck
&& !dangerous
&& bestValue > VALUE_MATED_IN_MAX_PLY)
ss->reduction = reduction<PvNode>(improving, depth, moveCount);
if ( (!PvNode && cutNode)
- || History[pos.piece_on(to_sq(move))][to_sq(move)] < 0)
+ || History[pos.piece_on(to_sq(move))][to_sq(move)] < VALUE_ZERO)
ss->reduction += ONE_PLY;
if (move == countermoves[0] || move == countermoves[1])
if ( ss->reduction
&& type_of(move) == NORMAL
&& type_of(pos.piece_on(to_sq(move))) != PAWN
- && pos.see(make_move(to_sq(move), from_sq(move))) < 0)
+ && pos.see(make_move(to_sq(move), from_sq(move))) < VALUE_ZERO)
ss->reduction = std::max(DEPTH_ZERO, ss->reduction - ONE_PLY);
Depth d = std::max(newDepth - ss->reduction, ONE_PLY);
if (ttHit)
{
// Never assume anything on values stored in TT
- if ((ss->staticEval = bestValue = tte->eval_value()) == VALUE_NONE)
+ if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE)
ss->staticEval = bestValue = evaluate(pos);
// Can ttValue be used as a better position evaluation?
: pos.gives_check(move, ci);
// Futility pruning
- if ( !PvNode
- && !InCheck
+ if ( !InCheck
&& !givesCheck
&& futilityBase > -VALUE_KNOWN_WIN
&& !pos.advanced_pawn_push(move))
futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))];
- if (futilityValue < beta)
+ if (futilityValue <= alpha)
{
bestValue = std::max(bestValue, futilityValue);
continue;
}
- if (futilityBase < beta && pos.see(move) <= VALUE_ZERO)
+ if (futilityBase <= alpha && pos.see(move) <= VALUE_ZERO)
{
bestValue = std::max(bestValue, futilityBase);
continue;
&& !pos.can_castle(pos.side_to_move());
// Don't search moves with negative SEE values
- if ( !PvNode
- && (!InCheck || evasionPrunable)
+ if ( (!InCheck || evasionPrunable)
&& type_of(move) != PROMOTION
&& pos.see_sign(move) < VALUE_ZERO)
continue;
size_t uciPVSize = std::min((size_t)Options["MultiPV"], RootMoves.size());
int selDepth = 0;
- for (size_t i = 0; i < Threads.size(); ++i)
- if (Threads[i]->maxPly > selDepth)
- selDepth = Threads[i]->maxPly;
+ for (Thread* th : Threads)
+ if (th->maxPly > selDepth)
+ selDepth = th->maxPly;
for (size_t i = 0; i < uciPVSize; ++i)
{
// Pointer 'this_sp' is not null only if we are called from split(), and not
// at the thread creation. This means we are the split point's master.
- SplitPoint* this_sp = splitPointsSize ? activeSplitPoint : NULL;
+ SplitPoint* this_sp = splitPointsSize ? activeSplitPoint : nullptr;
assert(!this_sp || (this_sp->masterThread == this && searching));
sp->mutex.lock();
- assert(activePosition == NULL);
+ assert(activePosition == nullptr);
activePosition = &pos;
assert(searching);
searching = false;
- activePosition = NULL;
+ activePosition = nullptr;
sp->slavesMask.reset(idx);
sp->allSlavesSearching = false;
sp->nodes += pos.nodes_searched();
for (size_t i = 0; i < Threads.size(); ++i)
{
const int size = Threads[i]->splitPointsSize; // Local copy
- sp = size ? &Threads[i]->splitPoints[size - 1] : NULL;
+ sp = size ? &Threads[i]->splitPoints[size - 1] : nullptr;
if ( sp
&& sp->allSlavesSearching
}
// Grab the lock to avoid races with Thread::notify_one()
- mutex.lock();
+ std::unique_lock<std::mutex> lk(mutex);
// If we are master and all slaves have finished then exit idle_loop
if (this_sp && this_sp->slavesMask.none())
{
assert(!searching);
- mutex.unlock();
break;
}
// If we are not searching, wait for a condition to be signaled instead of
// wasting CPU time polling for work.
if (!searching && !exit)
- sleepCondition.wait(mutex);
-
- mutex.unlock();
+ sleepCondition.wait(lk);
}
}
// Loop across all split points and sum accumulated SplitPoint nodes plus
// all the currently active positions nodes.
- for (size_t i = 0; i < Threads.size(); ++i)
- for (int j = 0; j < Threads[i]->splitPointsSize; ++j)
+ for (Thread* th : Threads)
+ for (int i = 0; i < th->splitPointsSize; ++i)
{
- SplitPoint& sp = Threads[i]->splitPoints[j];
+ SplitPoint& sp = th->splitPoints[i];
sp.mutex.lock();