X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=6586144dfabceac40f269567244d192c98702d04;hp=65f5a6add648b73274d2aa9ac7659d50d415a465;hb=b84af67f4c88f3e3f7b61bf2035475f79fb3e62e;hpb=9de4ee6d329b6da4f6bda0387a8ce6918c4e5a99 diff --git a/src/search.cpp b/src/search.cpp index 65f5a6ad..6586144d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -51,11 +51,6 @@ using std::endl; using Eval::evaluate; using namespace Search; -// For some reason argument-dependent lookup (ADL) doesn't work for Android's -// STLPort, so explicitly qualify following functions. -using std::count; -using std::find; - namespace { // Set to true to force running with one thread. Used for debugging @@ -164,7 +159,7 @@ namespace { && type_of(pos.piece_on(to_sq(m))) != PAWN && type_of(m) == NORMAL && ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) - - PieceValueMidgame[pos.piece_on(to_sq(m))] == VALUE_ZERO)) + - PieceValue[Mg][pos.piece_on(to_sq(m))] == VALUE_ZERO)) return true; return false; @@ -203,24 +198,23 @@ void Search::init() { /// Search::perft() is our utility to verify move generation. All the leaf nodes /// up to the given depth are generated and counted and the sum returned. -int64_t Search::perft(Position& pos, Depth depth) { - - StateInfo st; - int64_t cnt = 0; - - MoveList ml(pos); +size_t Search::perft(Position& pos, Depth depth) { - // At the last ply just return the number of moves (leaf nodes) + // At the last ply just return the number of legal moves (leaf nodes) if (depth == ONE_PLY) - return ml.size(); + return MoveList(pos).size(); + StateInfo st; + size_t cnt = 0; CheckInfo ci(pos); - for ( ; !ml.end(); ++ml) + + for (MoveList ml(pos); !ml.end(); ++ml) { pos.do_move(ml.move(), st, ci, pos.move_gives_check(ml.move(), ci)); cnt += perft(pos, depth - ONE_PLY); pos.undo_move(ml.move()); } + return cnt; } @@ -253,9 +247,9 @@ void Search::think() { { Move bookMove = book.probe(pos, Options["Book File"], Options["Best Book Move"]); - if (bookMove && count(RootMoves.begin(), RootMoves.end(), bookMove)) + if (bookMove && std::count(RootMoves.begin(), RootMoves.end(), bookMove)) { - std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), bookMove)); + std::swap(RootMoves[0], *std::find(RootMoves.begin(), RootMoves.end(), bookMove)); goto finalize; } } @@ -496,7 +490,7 @@ namespace { if (skillBest == MOVE_NONE) // Still unassigned ? skillBest = do_skill_level(); - std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), skillBest)); + std::swap(RootMoves[0], *std::find(RootMoves.begin(), RootMoves.end(), skillBest)); } } @@ -694,7 +688,7 @@ namespace { Depth R = 3 * ONE_PLY + depth / 4; // Null move dynamic reduction based on value - if (refinedValue - PawnValueMidgame > beta) + if (refinedValue - PawnValueMg > beta) R += ONE_PLY; pos.do_null_move(st); @@ -815,7 +809,7 @@ split_point_start: // At split points actual search starts from here // At root obey the "searchmoves" option and skip moves not listed in Root // Move List, as a consequence any illegal move is also skipped. In MultiPV // mode we also skip PV moves which have been already searched. - if (RootNode && !count(RootMoves.begin() + PVIdx, RootMoves.end(), move)) + if (RootNode && !std::count(RootMoves.begin() + PVIdx, RootMoves.end(), move)) continue; // At PV and SpNode nodes we want all moves to be legal since the beginning @@ -991,7 +985,7 @@ split_point_start: // At split points actual search starts from here // be trusted, and we don't update the best move and/or PV. if (RootNode && !Signals.stop) { - RootMove& rm = *find(RootMoves.begin(), RootMoves.end(), move); + RootMove& rm = *std::find(RootMoves.begin(), RootMoves.end(), move); // PV move or new best move ? if (isPvMove || value > alpha) @@ -1182,7 +1176,7 @@ split_point_start: // At split points actual search starts from here alpha = bestValue; futilityBase = ss->eval + evalMargin + FutilityMarginQS; - enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame; + enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMg; } // Initialize a MovePicker object for the current position, and prepare @@ -1210,8 +1204,8 @@ split_point_start: // At split points actual search starts from here && !pos.is_passed_pawn_push(move)) { futilityValue = futilityBase - + PieceValueEndgame[pos.piece_on(to_sq(move))] - + (type_of(move) == ENPASSANT ? PawnValueEndgame : VALUE_ZERO); + + PieceValue[Eg][pos.piece_on(to_sq(move))] + + (type_of(move) == ENPASSANT ? PawnValueEg : VALUE_ZERO); if (futilityValue < beta) { @@ -1249,7 +1243,7 @@ split_point_start: // At split points actual search starts from here && givesCheck && move != ttMove && !pos.is_capture_or_promotion(move) - && ss->eval + PawnValueMidgame / 4 < beta + && ss->eval + PawnValueMg / 4 < beta && !check_is_dangerous(pos, move, futilityBase, beta)) continue; @@ -1334,7 +1328,7 @@ split_point_start: // At split points actual search starts from here while (b) { // Note that here we generate illegal "double move"! - if (futilityBase + PieceValueEndgame[pos.piece_on(pop_lsb(&b))] >= beta) + if (futilityBase + PieceValue[Eg][pos.piece_on(pop_lsb(&b))] >= beta) return true; } @@ -1446,7 +1440,7 @@ split_point_start: // At split points actual search starts from here // Case 2: If the threatened piece has value less than or equal to the // value of the threatening piece, don't prune moves which defend it. if ( pos.is_capture(threat) - && ( PieceValueMidgame[pos.piece_on(tfrom)] >= PieceValueMidgame[pos.piece_on(tto)] + && ( PieceValue[Mg][pos.piece_on(tfrom)] >= PieceValue[Mg][pos.piece_on(tto)] || type_of(pos.piece_on(tfrom)) == KING) && pos.move_attacks_square(m, tto)) return true; @@ -1506,7 +1500,7 @@ split_point_start: // At split points actual search starts from here // RootMoves are already sorted by score in descending order size_t size = std::min(MultiPV, RootMoves.size()); - int variance = std::min(RootMoves[0].score - RootMoves[size - 1].score, PawnValueMidgame); + int variance = std::min(RootMoves[0].score - RootMoves[size - 1].score, PawnValueMg); int weakness = 120 - 2 * SkillLevel; int max_s = -VALUE_INFINITE; Move best = MOVE_NONE; @@ -1546,7 +1540,7 @@ split_point_start: // At split points actual search starts from here int t = SearchTime.elapsed(); int selDepth = 0; - for (int i = 0; i < Threads.size(); i++) + for (size_t i = 0; i < Threads.size(); i++) if (Threads[i].maxPly > selDepth) selDepth = Threads[i].maxPly; @@ -1649,11 +1643,15 @@ void RootMove::insert_pv_in_tt(Position& pos) { } -/// Thread::idle_loop() is where the thread is parked when it has no work to do. -/// The parameter 'master_sp', if non-NULL, is a pointer to an active SplitPoint -/// object for which the thread is the master. +/// Thread::idle_loop() is where the thread is parked when it has no work to do + +void Thread::idle_loop() { + + // Pointer 'sp_master', if non-NULL, points to the active SplitPoint + // object for which the thread is the master. + const SplitPoint* sp_master = splitPointsCnt ? curSplitPoint : NULL; -void Thread::idle_loop(SplitPoint* sp_master) { + assert(!sp_master || (sp_master->master == this && is_searching)); // If this thread is the master of a split point and all slaves have // finished their work at this split point, return from the idle loop. @@ -1730,8 +1728,11 @@ void Thread::idle_loop(SplitPoint* sp_master) { // case we are the last slave of the split point. if ( Threads.use_sleeping_threads() && this != sp->master - && !sp->master->is_searching) + && !sp->slavesMask) + { + assert(!sp->master->is_searching); sp->master->wake_up(); + } // After releasing the lock we cannot access anymore any SplitPoint // related data in a safe way becuase it could have been released under