Skip to content

Commit d855af1

Browse files
loco-locoIIvec
authored andcommitted
Add a second level of follow-up moves
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
1 parent 79ae466 commit d855af1

File tree

4 files changed

+72
-51
lines changed

4 files changed

+72
-51
lines changed

src/movepick.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,21 @@ namespace {
6767
/// search captures, promotions, and some checks) and how important good move
6868
/// ordering is at the current node.
6969

70-
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
71-
const CounterMoveStats& cmh, const CounterMoveStats& fmh,
72-
Move cm, Search::Stack* s)
73-
: pos(p), history(h), counterMoveHistory(&cmh),
74-
followupMoveHistory(&fmh), ss(s), countermove(cm), depth(d) {
70+
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Search::Stack* s)
71+
: pos(p), ss(s), depth(d) {
7572

7673
assert(d > DEPTH_ZERO);
7774

75+
Square prevSq = to_sq((ss-1)->currentMove);
76+
countermove = pos.this_thread()->counterMoves[pos.piece_on(prevSq)][prevSq];
77+
7878
stage = pos.checkers() ? EVASION : MAIN_SEARCH;
7979
ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
8080
endMoves += (ttMove != MOVE_NONE);
8181
}
8282

83-
MovePicker::MovePicker(const Position& p, Move ttm, Depth d,
84-
const HistoryStats& h, Square s)
85-
: pos(p), history(h) {
83+
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Square s)
84+
: pos(p) {
8685

8786
assert(d <= DEPTH_ZERO);
8887

@@ -106,8 +105,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d,
106105
endMoves += (ttMove != MOVE_NONE);
107106
}
108107

109-
MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Value th)
110-
: pos(p), history(h), threshold(th) {
108+
MovePicker::MovePicker(const Position& p, Move ttm, Value th)
109+
: pos(p), threshold(th) {
111110

112111
assert(!pos.checkers());
113112

@@ -142,17 +141,25 @@ void MovePicker::score<CAPTURES>() {
142141
template<>
143142
void MovePicker::score<QUIETS>() {
144143

144+
const HistoryStats& history = pos.this_thread()->history;
145+
146+
const CounterMoveStats* cm = (ss-1)->counterMoves;
147+
const CounterMoveStats* fm = (ss-2)->counterMoves;
148+
const CounterMoveStats* f2 = (ss-4)->counterMoves;
149+
145150
for (auto& m : *this)
146-
m.value = history[pos.moved_piece(m)][to_sq(m)]
147-
+ (*counterMoveHistory )[pos.moved_piece(m)][to_sq(m)]
148-
+ (*followupMoveHistory)[pos.moved_piece(m)][to_sq(m)];
151+
m.value = history[pos.moved_piece(m)][to_sq(m)]
152+
+ (cm ? (*cm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
153+
+ (fm ? (*fm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
154+
+ (f2 ? (*f2)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO);
149155
}
150156

151157
template<>
152158
void MovePicker::score<EVASIONS>() {
153159
// Try winning and equal captures ordered by MVV/LVA, then non-captures ordered
154160
// by history value, then bad captures and quiet moves with a negative SEE ordered
155161
// by SEE value.
162+
const HistoryStats& history = pos.this_thread()->history;
156163
Value see;
157164

158165
for (auto& m : *this)

src/movepick.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,9 @@ class MovePicker {
7979
MovePicker(const MovePicker&) = delete;
8080
MovePicker& operator=(const MovePicker&) = delete;
8181

82-
MovePicker(const Position&, Move, const HistoryStats&, Value);
83-
MovePicker(const Position&, Move, Depth, const HistoryStats&, Square);
84-
MovePicker(const Position&, Move, Depth, const HistoryStats&,
85-
const CounterMoveStats&, const CounterMoveStats&, Move, Search::Stack*);
82+
MovePicker(const Position&, Move, Value);
83+
MovePicker(const Position&, Move, Depth, Square);
84+
MovePicker(const Position&, Move, Depth, Search::Stack*);
8685

8786
Move next_move();
8887

@@ -93,10 +92,7 @@ class MovePicker {
9392
ExtMove* end() { return endMoves; }
9493

9594
const Position& pos;
96-
const HistoryStats& history;
97-
const CounterMoveStats* counterMoveHistory;
98-
const CounterMoveStats* followupMoveHistory;
99-
Search::Stack* ss;
95+
const Search::Stack* ss;
10096
Move countermove;
10197
Depth depth;
10298
Move ttMove;

src/search.cpp

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -380,12 +380,12 @@ void MainThread::search() {
380380

381381
void Thread::search() {
382382

383-
Stack stack[MAX_PLY+4], *ss = stack+2; // To allow referencing (ss-2) and (ss+2)
383+
Stack stack[MAX_PLY+7], *ss = stack+5; // To allow referencing (ss-5) and (ss+2)
384384
Value bestValue, alpha, beta, delta;
385385
Move easyMove = MOVE_NONE;
386386
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
387387

388-
std::memset(ss-2, 0, 5 * sizeof(Stack));
388+
std::memset(ss-5, 0, 8 * sizeof(Stack));
389389

390390
bestValue = delta = alpha = -VALUE_INFINITE;
391391
beta = VALUE_INFINITE;
@@ -657,6 +657,7 @@ namespace {
657657
assert(0 <= ss->ply && ss->ply < MAX_PLY);
658658

659659
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
660+
ss->counterMoves = nullptr;
660661
(ss+1)->skipEarlyPruning = false;
661662
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
662663

@@ -780,6 +781,7 @@ namespace {
780781
&& pos.non_pawn_material(pos.side_to_move()))
781782
{
782783
ss->currentMove = MOVE_NULL;
784+
ss->counterMoves = nullptr;
783785

784786
assert(eval - beta >= 0);
785787

@@ -828,13 +830,14 @@ namespace {
828830
assert((ss-1)->currentMove != MOVE_NONE);
829831
assert((ss-1)->currentMove != MOVE_NULL);
830832

831-
MovePicker mp(pos, ttMove, thisThread->history, PieceValue[MG][pos.captured_piece_type()]);
833+
MovePicker mp(pos, ttMove, PieceValue[MG][pos.captured_piece_type()]);
832834
CheckInfo ci(pos);
833835

834836
while ((move = mp.next_move()) != MOVE_NONE)
835837
if (pos.legal(move, ci.pinned))
836838
{
837839
ss->currentMove = move;
840+
ss->counterMoves = &CounterMoveHistory[pos.moved_piece(move)][to_sq(move)];
838841
pos.do_move(move, st, pos.gives_check(move, ci));
839842
value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
840843
pos.undo_move(move);
@@ -860,12 +863,9 @@ namespace {
860863
moves_loop: // When in check search starts from here
861864

862865
Square prevSq = to_sq((ss-1)->currentMove);
863-
Square ownPrevSq = to_sq((ss-2)->currentMove);
864-
Move cm = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
865866
const CounterMoveStats& cmh = CounterMoveHistory[pos.piece_on(prevSq)][prevSq];
866-
const CounterMoveStats& fmh = CounterMoveHistory[pos.piece_on(ownPrevSq)][ownPrevSq];
867867

868-
MovePicker mp(pos, ttMove, depth, thisThread->history, cmh, fmh, cm, ss);
868+
MovePicker mp(pos, ttMove, depth, ss);
869869
CheckInfo ci(pos);
870870
value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
871871
improving = ss->staticEval >= (ss-2)->staticEval
@@ -992,6 +992,7 @@ namespace {
992992
}
993993

994994
ss->currentMove = move;
995+
ss->counterMoves = &CounterMoveHistory[pos.moved_piece(move)][to_sq(move)];
995996

996997
// Step 14. Make the move
997998
pos.do_move(move, st, givesCheck);
@@ -1153,13 +1154,17 @@ namespace {
11531154
&& !bestMove
11541155
&& !inCheck
11551156
&& !pos.captured_piece_type()
1156-
&& is_ok((ss - 1)->currentMove)
1157-
&& is_ok((ss - 2)->currentMove))
1157+
&& is_ok((ss-1)->currentMove))
11581158
{
11591159
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
1160-
Square prevPrevSq = to_sq((ss - 2)->currentMove);
1161-
CounterMoveStats& prevCmh = CounterMoveHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
1162-
prevCmh.update(pos.piece_on(prevSq), prevSq, bonus);
1160+
if ((ss-2)->counterMoves)
1161+
(ss-2)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
1162+
1163+
if ((ss-3)->counterMoves)
1164+
(ss-3)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
1165+
1166+
if ((ss-5)->counterMoves)
1167+
(ss-5)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
11631168
}
11641169

11651170
tte->save(posKey, value_to_tt(bestValue, ss->ply),
@@ -1280,7 +1285,7 @@ namespace {
12801285
// to search the moves. Because the depth is <= 0 here, only captures,
12811286
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
12821287
// be generated.
1283-
MovePicker mp(pos, ttMove, depth, pos.this_thread()->history, to_sq((ss-1)->currentMove));
1288+
MovePicker mp(pos, ttMove, depth, to_sq((ss-1)->currentMove));
12841289
CheckInfo ci(pos);
12851290

12861291
// Loop through the moves until no moves remain or a beta cutoff occurs
@@ -1434,42 +1439,51 @@ namespace {
14341439
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
14351440

14361441
Square prevSq = to_sq((ss-1)->currentMove);
1437-
Square ownPrevSq = to_sq((ss-2)->currentMove);
1438-
CounterMoveStats& cmh = CounterMoveHistory[pos.piece_on(prevSq)][prevSq];
1439-
CounterMoveStats& fmh = CounterMoveHistory[pos.piece_on(ownPrevSq)][ownPrevSq];
1442+
CounterMoveStats* cmh = (ss-1)->counterMoves;
1443+
CounterMoveStats* fmh = (ss-2)->counterMoves;
1444+
CounterMoveStats* fmh2 = (ss-4)->counterMoves;
14401445
Thread* thisThread = pos.this_thread();
14411446

14421447
thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus);
14431448

1444-
if (is_ok((ss-1)->currentMove))
1449+
if (cmh)
14451450
{
14461451
thisThread->counterMoves.update(pos.piece_on(prevSq), prevSq, move);
1447-
cmh.update(pos.moved_piece(move), to_sq(move), bonus);
1452+
cmh->update(pos.moved_piece(move), to_sq(move), bonus);
14481453
}
14491454

1450-
if (is_ok((ss-2)->currentMove))
1451-
fmh.update(pos.moved_piece(move), to_sq(move), bonus);
1455+
if (fmh)
1456+
fmh->update(pos.moved_piece(move), to_sq(move), bonus);
1457+
1458+
if (fmh2)
1459+
fmh2->update(pos.moved_piece(move), to_sq(move), bonus);
14521460

14531461
// Decrease all the other played quiet moves
14541462
for (int i = 0; i < quietsCnt; ++i)
14551463
{
14561464
thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
14571465

1458-
if (is_ok((ss-1)->currentMove))
1459-
cmh.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
1466+
if (cmh)
1467+
cmh->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
14601468

1461-
if (is_ok((ss-2)->currentMove))
1462-
fmh.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
1469+
if (fmh)
1470+
fmh->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
1471+
1472+
if (fmh2)
1473+
fmh2->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
14631474
}
14641475

14651476
// Extra penalty for a quiet TT move in previous ply when it gets refuted
1466-
if ( (ss-1)->moveCount == 1
1467-
&& !pos.captured_piece_type()
1468-
&& is_ok((ss-2)->currentMove))
1477+
if ((ss-1)->moveCount == 1 && !pos.captured_piece_type())
14691478
{
1470-
Square prevPrevSq = to_sq((ss-2)->currentMove);
1471-
CounterMoveStats& prevCmh = CounterMoveHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
1472-
prevCmh.update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
1479+
if ((ss-2)->counterMoves)
1480+
(ss-2)->counterMoves->update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
1481+
1482+
if ((ss-3)->counterMoves)
1483+
(ss-3)->counterMoves->update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
1484+
1485+
if ((ss-5)->counterMoves)
1486+
(ss-5)->counterMoves->update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
14731487
}
14741488
}
14751489

src/search.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include "position.h"
2929
#include "types.h"
3030

31+
template<typename T, bool CM> struct Stats;
32+
typedef Stats<Value, true> CounterMoveStats;
33+
3134
namespace Search {
3235

3336
/// Stack struct keeps track of the information we need to remember from nodes
@@ -43,6 +46,7 @@ struct Stack {
4346
Value staticEval;
4447
bool skipEarlyPruning;
4548
int moveCount;
49+
CounterMoveStats* counterMoves;
4650
};
4751

4852
/// RootMove struct is used for moves at the root of the tree. For each root move

0 commit comments

Comments
 (0)