STC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 6438 W: 1229 L: 1077 D: 4132
LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 4000 W: 605 L: 473 D: 2922
bench:
7378965
Resolves #636
/// search captures, promotions, and some checks) and how important good move
/// ordering is at the current node.
/// search captures, promotions, and some checks) and how important good move
/// ordering is at the current node.
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
- const CounterMoveStats& cmh, const CounterMoveStats& fmh,
- Move cm, Search::Stack* s)
- : pos(p), history(h), counterMoveHistory(&cmh),
- followupMoveHistory(&fmh), ss(s), countermove(cm), depth(d) {
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Search::Stack* s)
+ : pos(p), ss(s), depth(d) {
+ Square prevSq = to_sq((ss-1)->currentMove);
+ countermove = pos.this_thread()->counterMoves[pos.piece_on(prevSq)][prevSq];
+
stage = pos.checkers() ? EVASION : MAIN_SEARCH;
ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
endMoves += (ttMove != MOVE_NONE);
}
stage = pos.checkers() ? EVASION : MAIN_SEARCH;
ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
endMoves += (ttMove != MOVE_NONE);
}
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d,
- const HistoryStats& h, Square s)
- : pos(p), history(h) {
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Square s)
+ : pos(p) {
endMoves += (ttMove != MOVE_NONE);
}
endMoves += (ttMove != MOVE_NONE);
}
-MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Value th)
- : pos(p), history(h), threshold(th) {
+MovePicker::MovePicker(const Position& p, Move ttm, Value th)
+ : pos(p), threshold(th) {
template<>
void MovePicker::score<QUIETS>() {
template<>
void MovePicker::score<QUIETS>() {
+ const HistoryStats& history = pos.this_thread()->history;
+
+ const CounterMoveStats* cm = (ss-1)->counterMoves;
+ const CounterMoveStats* fm = (ss-2)->counterMoves;
+ const CounterMoveStats* f2 = (ss-4)->counterMoves;
+
- m.value = history[pos.moved_piece(m)][to_sq(m)]
- + (*counterMoveHistory )[pos.moved_piece(m)][to_sq(m)]
- + (*followupMoveHistory)[pos.moved_piece(m)][to_sq(m)];
+ m.value = history[pos.moved_piece(m)][to_sq(m)]
+ + (cm ? (*cm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
+ + (fm ? (*fm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
+ + (f2 ? (*f2)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO);
// Try winning and equal captures ordered by MVV/LVA, then non-captures ordered
// by history value, then bad captures and quiet moves with a negative SEE ordered
// by SEE value.
// Try winning and equal captures ordered by MVV/LVA, then non-captures ordered
// by history value, then bad captures and quiet moves with a negative SEE ordered
// by SEE value.
+ const HistoryStats& history = pos.this_thread()->history;
Value see;
for (auto& m : *this)
Value see;
for (auto& m : *this)
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
- MovePicker(const Position&, Move, const HistoryStats&, Value);
- MovePicker(const Position&, Move, Depth, const HistoryStats&, Square);
- MovePicker(const Position&, Move, Depth, const HistoryStats&,
- const CounterMoveStats&, const CounterMoveStats&, Move, Search::Stack*);
+ MovePicker(const Position&, Move, Value);
+ MovePicker(const Position&, Move, Depth, Square);
+ MovePicker(const Position&, Move, Depth, Search::Stack*);
ExtMove* end() { return endMoves; }
const Position& pos;
ExtMove* end() { return endMoves; }
const Position& pos;
- const HistoryStats& history;
- const CounterMoveStats* counterMoveHistory;
- const CounterMoveStats* followupMoveHistory;
- Search::Stack* ss;
+ const Search::Stack* ss;
Move countermove;
Depth depth;
Move ttMove;
Move countermove;
Depth depth;
Move ttMove;
- Stack stack[MAX_PLY+4], *ss = stack+2; // To allow referencing (ss-2) and (ss+2)
+ Stack stack[MAX_PLY+7], *ss = stack+5; // To allow referencing (ss-5) and (ss+2)
Value bestValue, alpha, beta, delta;
Move easyMove = MOVE_NONE;
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
Value bestValue, alpha, beta, delta;
Move easyMove = MOVE_NONE;
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
- std::memset(ss-2, 0, 5 * sizeof(Stack));
+ std::memset(ss-5, 0, 8 * sizeof(Stack));
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
+ ss->counterMoves = nullptr;
(ss+1)->skipEarlyPruning = false;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
(ss+1)->skipEarlyPruning = false;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
&& pos.non_pawn_material(pos.side_to_move()))
{
ss->currentMove = MOVE_NULL;
&& pos.non_pawn_material(pos.side_to_move()))
{
ss->currentMove = MOVE_NULL;
+ ss->counterMoves = nullptr;
assert(eval - beta >= 0);
assert(eval - beta >= 0);
assert((ss-1)->currentMove != MOVE_NONE);
assert((ss-1)->currentMove != MOVE_NULL);
assert((ss-1)->currentMove != MOVE_NONE);
assert((ss-1)->currentMove != MOVE_NULL);
- MovePicker mp(pos, ttMove, thisThread->history, PieceValue[MG][pos.captured_piece_type()]);
+ MovePicker mp(pos, ttMove, PieceValue[MG][pos.captured_piece_type()]);
CheckInfo ci(pos);
while ((move = mp.next_move()) != MOVE_NONE)
if (pos.legal(move, ci.pinned))
{
ss->currentMove = move;
CheckInfo ci(pos);
while ((move = mp.next_move()) != MOVE_NONE)
if (pos.legal(move, ci.pinned))
{
ss->currentMove = move;
+ ss->counterMoves = &CounterMoveHistory[pos.moved_piece(move)][to_sq(move)];
pos.do_move(move, st, pos.gives_check(move, ci));
value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
pos.undo_move(move);
pos.do_move(move, st, pos.gives_check(move, ci));
value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
pos.undo_move(move);
moves_loop: // When in check search starts from here
Square prevSq = to_sq((ss-1)->currentMove);
moves_loop: // When in check search starts from here
Square prevSq = to_sq((ss-1)->currentMove);
- Square ownPrevSq = to_sq((ss-2)->currentMove);
- Move cm = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
const CounterMoveStats& cmh = CounterMoveHistory[pos.piece_on(prevSq)][prevSq];
const CounterMoveStats& cmh = CounterMoveHistory[pos.piece_on(prevSq)][prevSq];
- const CounterMoveStats& fmh = CounterMoveHistory[pos.piece_on(ownPrevSq)][ownPrevSq];
- MovePicker mp(pos, ttMove, depth, thisThread->history, cmh, fmh, cm, ss);
+ MovePicker mp(pos, ttMove, depth, ss);
CheckInfo ci(pos);
value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
improving = ss->staticEval >= (ss-2)->staticEval
CheckInfo ci(pos);
value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
improving = ss->staticEval >= (ss-2)->staticEval
}
ss->currentMove = move;
}
ss->currentMove = move;
+ ss->counterMoves = &CounterMoveHistory[pos.moved_piece(move)][to_sq(move)];
// Step 14. Make the move
pos.do_move(move, st, givesCheck);
// Step 14. Make the move
pos.do_move(move, st, givesCheck);
&& !bestMove
&& !inCheck
&& !pos.captured_piece_type()
&& !bestMove
&& !inCheck
&& !pos.captured_piece_type()
- && is_ok((ss - 1)->currentMove)
- && is_ok((ss - 2)->currentMove))
+ && is_ok((ss-1)->currentMove))
{
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
{
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
- Square prevPrevSq = to_sq((ss - 2)->currentMove);
- CounterMoveStats& prevCmh = CounterMoveHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
- prevCmh.update(pos.piece_on(prevSq), prevSq, bonus);
+ if ((ss-2)->counterMoves)
+ (ss-2)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
+
+ if ((ss-3)->counterMoves)
+ (ss-3)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
+
+ if ((ss-5)->counterMoves)
+ (ss-5)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
}
tte->save(posKey, value_to_tt(bestValue, ss->ply),
}
tte->save(posKey, value_to_tt(bestValue, ss->ply),
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
- MovePicker mp(pos, ttMove, depth, pos.this_thread()->history, to_sq((ss-1)->currentMove));
+ MovePicker mp(pos, ttMove, depth, to_sq((ss-1)->currentMove));
CheckInfo ci(pos);
// Loop through the moves until no moves remain or a beta cutoff occurs
CheckInfo ci(pos);
// Loop through the moves until no moves remain or a beta cutoff occurs
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
Square prevSq = to_sq((ss-1)->currentMove);
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
Square prevSq = to_sq((ss-1)->currentMove);
- Square ownPrevSq = to_sq((ss-2)->currentMove);
- CounterMoveStats& cmh = CounterMoveHistory[pos.piece_on(prevSq)][prevSq];
- CounterMoveStats& fmh = CounterMoveHistory[pos.piece_on(ownPrevSq)][ownPrevSq];
+ CounterMoveStats* cmh = (ss-1)->counterMoves;
+ CounterMoveStats* fmh = (ss-2)->counterMoves;
+ CounterMoveStats* fmh2 = (ss-4)->counterMoves;
Thread* thisThread = pos.this_thread();
thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus);
Thread* thisThread = pos.this_thread();
thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus);
- if (is_ok((ss-1)->currentMove))
{
thisThread->counterMoves.update(pos.piece_on(prevSq), prevSq, move);
{
thisThread->counterMoves.update(pos.piece_on(prevSq), prevSq, move);
- cmh.update(pos.moved_piece(move), to_sq(move), bonus);
+ cmh->update(pos.moved_piece(move), to_sq(move), bonus);
- if (is_ok((ss-2)->currentMove))
- fmh.update(pos.moved_piece(move), to_sq(move), bonus);
+ if (fmh)
+ fmh->update(pos.moved_piece(move), to_sq(move), bonus);
+
+ if (fmh2)
+ fmh2->update(pos.moved_piece(move), to_sq(move), bonus);
// Decrease all the other played quiet moves
for (int i = 0; i < quietsCnt; ++i)
{
thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
// Decrease all the other played quiet moves
for (int i = 0; i < quietsCnt; ++i)
{
thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
- if (is_ok((ss-1)->currentMove))
- cmh.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
+ if (cmh)
+ cmh->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
- if (is_ok((ss-2)->currentMove))
- fmh.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
+ if (fmh)
+ fmh->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
+
+ if (fmh2)
+ fmh2->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
}
// Extra penalty for a quiet TT move in previous ply when it gets refuted
}
// Extra penalty for a quiet TT move in previous ply when it gets refuted
- if ( (ss-1)->moveCount == 1
- && !pos.captured_piece_type()
- && is_ok((ss-2)->currentMove))
+ if ((ss-1)->moveCount == 1 && !pos.captured_piece_type())
- Square prevPrevSq = to_sq((ss-2)->currentMove);
- CounterMoveStats& prevCmh = CounterMoveHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
- prevCmh.update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
+ if ((ss-2)->counterMoves)
+ (ss-2)->counterMoves->update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
+
+ if ((ss-3)->counterMoves)
+ (ss-3)->counterMoves->update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
+
+ if ((ss-5)->counterMoves)
+ (ss-5)->counterMoves->update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
#include "position.h"
#include "types.h"
#include "position.h"
#include "types.h"
+template<typename T, bool CM> struct Stats;
+typedef Stats<Value, true> CounterMoveStats;
+
namespace Search {
/// Stack struct keeps track of the information we need to remember from nodes
namespace Search {
/// Stack struct keeps track of the information we need to remember from nodes
Value staticEval;
bool skipEarlyPruning;
int moveCount;
Value staticEval;
bool skipEarlyPruning;
int moveCount;
+ CounterMoveStats* counterMoves;
};
/// RootMove struct is used for moves at the root of the tree. For each root move
};
/// RootMove struct is used for moves at the root of the tree. For each root move