template <NodeType PV>
inline Depth reduction(Depth d, int mn) { return (Depth) ReductionMatrix[PV][Min(d / 2, 63)][Min(mn, 63)]; }
- // Common adjustments
-
- // Search depth at iteration 1
- const Depth InitialDepth = ONE_PLY;
-
// Easy move margin. An easy move candidate must be at least this much
// better than the second best move.
const Value EasyMoveMargin = Value(0x200);
void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount);
void update_killers(Move m, Move killers[]);
void update_gains(const Position& pos, Move move, Value before, Value after);
+ void qsearch_scoring(Position& pos, MoveStack* mlist, MoveStack* last);
int current_search_time();
std::string value_to_uci(Value v);
// before to search them.
template<> struct MovePickerExt<false, true> : public MovePicker {
- MovePickerExt(const Position& p, Move, Depth d, const History& h, SearchStack* ss, Value b)
- : MovePicker(p, Rml[0].pv[0], d, h, ss, b), firstCall(true) {
+ MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss, Value b)
+ : MovePicker(p, ttm, d, h, ss, b), firstCall(true) {
Move move;
Value score = VALUE_ZERO;
cout << "info depth " << iteration << endl;
Rml.bestMoveChanges = researchCountFL = researchCountFH = 0;
- depth = (iteration - 2) * ONE_PLY + InitialDepth;
+ depth = (iteration - 1) * ONE_PLY;
// Calculate dynamic aspiration window based on previous iterations
if (MultiPV == 1 && iteration >= 6 && abs(bestValues[iteration - 1]) < VALUE_KNOWN_WIN)
Value refinedValue, nullValue, futilityBase, futilityValueScaled; // Non-PV specific
bool isPvMove, isCheck, singleEvasion, singularExtensionNode, moveIsCheck, captureOrPromotion, dangerous;
bool mateThreat = false;
- int moveCount = 0;
+ int moveCount = 0, playedMoveCount = 0;
int threadID = pos.thread();
SplitPoint* sp = NULL;
else if (move == excludedMove)
continue;
else
- movesSearched[moveCount++] = move;
+ moveCount++;
if (Root)
{
// Step 13. Make the move
pos.do_move(move, st, ci, moveIsCheck);
+ if (!SpNode && !captureOrPromotion)
+ movesSearched[playedMoveCount++] = move;
+
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (isPvMove)
if ( bestValue >= beta
&& !pos.move_is_capture_or_promotion(move))
{
- update_history(pos, move, depth, movesSearched, moveCount);
+ update_history(pos, move, depth, movesSearched, playedMoveCount);
update_killers(move, ss->killers);
}
}
}
+ // qsearch_scoring() scores each move of a list using a qsearch() evaluation,
+ // it is used in RootMoveList to get an initial scoring.
+ void qsearch_scoring(Position& pos, MoveStack* mlist, MoveStack* last) {
+
+ SearchStack ss[PLY_MAX_PLUS_2];
+ StateInfo st;
+
+ memset(ss, 0, 4 * sizeof(SearchStack));
+ ss[0].eval = ss[0].evalMargin = VALUE_NONE;
+
+ for (MoveStack* cur = mlist; cur != last; cur++)
+ {
+ ss[0].currentMove = cur->move;
+ pos.do_move(cur->move, st);
+ cur->score = -qsearch<PV>(pos, ss+1, -VALUE_INFINITE, VALUE_INFINITE, DEPTH_ZERO, 1);
+ pos.undo_move(cur->move);
+ }
+ }
+
+
// check_is_dangerous() tests if a checking move can be pruned in qsearch().
// bestValue is updated only when returning false because in that case move
// will be pruned.
assert(m != move);
- if (!pos.move_is_capture_or_promotion(m))
- H.update(pos.piece_on(move_from(m)), move_to(m), -bonus);
+ H.update(pos.piece_on(move_from(m)), move_to(m), -bonus);
}
}
void update_killers(Move m, Move killers[]) {
- if (m == killers[0])
- return;
-
- killers[1] = killers[0];
- killers[0] = m;
+ if (m != killers[0])
+ {
+ killers[1] = killers[0];
+ killers[0] = m;
+ }
}
void RootMoveList::init(Position& pos, Move searchMoves[]) {
- SearchStack ss[PLY_MAX_PLUS_2];
MoveStack mlist[MOVES_MAX];
- StateInfo st;
Move* sm;
- // Initialize search stack
- memset(ss, 0, PLY_MAX_PLUS_2 * sizeof(SearchStack));
- ss[0].eval = ss[0].evalMargin = VALUE_NONE;
- bestMoveChanges = 0;
clear();
+ bestMoveChanges = 0;
- // Generate all legal moves
+ // Generate all legal moves and score them
MoveStack* last = generate<MV_LEGAL>(pos, mlist);
+ qsearch_scoring(pos, mlist, last);
// Add each move to the RootMoveList's vector
for (MoveStack* cur = mlist; cur != last; cur++)
if (searchMoves[0] && *sm != cur->move)
continue;
- // Find a quick score for the move and add to the list
- pos.do_move(cur->move, st);
-
RootMove rm;
- rm.pv[0] = ss[0].currentMove = cur->move;
+ rm.pv[0] = cur->move;
rm.pv[1] = MOVE_NONE;
- rm.pv_score = -qsearch<PV>(pos, ss+1, -VALUE_INFINITE, VALUE_INFINITE, DEPTH_ZERO, 1);
+ rm.pv_score = Value(cur->score);
push_back(rm);
-
- pos.undo_move(cur->move);
}
sort();
}