1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-30 00:33:09 +00:00

Cleanup MAX_PLY

This area has become obscure and tricky over the course of incremental
changes that did not respect the original's consistency and clarity. Now,
it's not clear why we use MAX_PLY = 120, or why we use MAX_PLY+6, among
other things.

This patch does the following:

* ID loop: depth ranges from 1 to MAX_PLY-1, and due to TT constraint (depth
must fit into an int8_t), MAX_PLY should be 128.

* stack[]: plies now range from 0 to MAX_PLY-1, hence stack[MAX_PLY+4],
because of the extra 2+2 padding elements (for ss-2 and ss+2). Document this
better, while we're at it.

* Enforce 0 <= ply < MAX_PLY:
  - stop condition is now ss->ply >= MAX_PLY and not ss->ply > MAX_PLY.
  - assert(ss->ply < MAX_PLY), before using ss+1 and ss+2.
  - as a result, we don't need the artificial MAX_PLY+6 range. Instead we
  can use MAX_PLY+4 and it's clear why (for ss-2 and ss+2).

* fix: extract_pv_from_tt() and insert_pv_in_tt() had no reason to use
MAX_PLY_PLUS_6, because the array is indexed by plies, so the range of
available plies applies (0..MAX_PLY before, and now 0..MAX_PLY-1).

Tested with debug compile, using MAX_PLY=16, and running bench at depth 17,
using 1 and 7 threads. No assert() fired. Feel free to submit to more severe
crash-tests, if you can think of any.

No functional change.
This commit is contained in:
lucasart 2014-11-03 23:36:24 +08:00 committed by Gary Linscott
parent fc0733087a
commit 8ab9c2511a
2 changed files with 19 additions and 15 deletions

View file

@ -240,7 +240,7 @@ namespace {
void id_loop(Position& pos) {
Stack stack[MAX_PLY_PLUS_6], *ss = stack+2; // To allow referencing (ss-2)
Stack stack[MAX_PLY+4], *ss = stack+2; // To allow referencing (ss-2) and (ss+2)
int depth;
Value bestValue, alpha, beta, delta;
@ -265,7 +265,7 @@ namespace {
multiPV = std::max(multiPV, skill.candidates_size());
// Iterative deepening loop until requested to stop or target depth reached
while (++depth <= MAX_PLY && !Signals.stop && (!Limits.depth || depth <= Limits.depth))
while (++depth < MAX_PLY && !Signals.stop && (!Limits.depth || depth <= Limits.depth))
{
// Age out PV variability metric
BestMoveChanges *= 0.5;
@ -430,10 +430,7 @@ namespace {
moveCount = quietCount = 0;
bestValue = -VALUE_INFINITE;
ss->currentMove = ss->ttMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
ss->ply = (ss-1)->ply + 1;
(ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
// Used to send selDepth info to GUI
if (PvNode && thisThread->maxPly < ss->ply)
@ -442,8 +439,8 @@ namespace {
if (!RootNode)
{
// Step 2. Check for aborted search and immediate draw
if (Signals.stop || pos.is_draw() || ss->ply > MAX_PLY)
return ss->ply > MAX_PLY && !inCheck ? evaluate(pos) : DrawValue[pos.side_to_move()];
if (Signals.stop || pos.is_draw() || ss->ply >= MAX_PLY)
return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos) : DrawValue[pos.side_to_move()];
// Step 3. Mate distance pruning. Even if we mate at the next move our score
// would be at best mate_in(ss->ply+1), but if alpha is already bigger because
@ -457,6 +454,12 @@ namespace {
return alpha;
}
assert(0 <= ss->ply && ss->ply < MAX_PLY);
ss->currentMove = ss->ttMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
(ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
// Step 4. Transposition table lookup
// We don't want the score of a partial search to overwrite a previous full search
// TT value, so we use a different position key in case of an excluded move.
@ -1021,8 +1024,10 @@ moves_loop: // When in check and at SpNode search starts from here
ss->ply = (ss-1)->ply + 1;
// Check for an instant draw or if the maximum ply has been reached
if (pos.is_draw() || ss->ply > MAX_PLY)
return ss->ply > MAX_PLY && !InCheck ? evaluate(pos) : DrawValue[pos.side_to_move()];
if (pos.is_draw() || ss->ply >= MAX_PLY)
return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos) : DrawValue[pos.side_to_move()];
assert(0 <= ss->ply && ss->ply < MAX_PLY);
// Decide whether or not to include checks: this fixes also the type of
// TT entry depth that we are going to use. Note that in qsearch we use
@ -1352,7 +1357,7 @@ moves_loop: // When in check and at SpNode search starts from here
void RootMove::extract_pv_from_tt(Position& pos) {
StateInfo state[MAX_PLY_PLUS_6], *st = state;
StateInfo state[MAX_PLY], *st = state;
const TTEntry* tte;
int ply = 1; // At root ply is 1...
Move m = pv[0]; // ...instead pv[] array starts from 0
@ -1388,7 +1393,7 @@ void RootMove::extract_pv_from_tt(Position& pos) {
void RootMove::insert_pv_in_tt(Position& pos) {
StateInfo state[MAX_PLY_PLUS_6], *st = state;
StateInfo state[MAX_PLY], *st = state;
const TTEntry* tte;
int idx = 0; // Ply starts from 1, we need to start from 0
@ -1430,7 +1435,7 @@ void Thread::idle_loop() {
Threads.mutex.unlock();
Stack stack[MAX_PLY_PLUS_6], *ss = stack+2; // To allow referencing (ss-2)
Stack stack[MAX_PLY+4], *ss = stack+2; // To allow referencing (ss-2) and (ss+2)
Position pos(*sp->pos, this);
std::memcpy(ss-2, sp->ss-2, 5 * sizeof(Stack));

View file

@ -100,9 +100,8 @@ const bool Is64Bit = false;
typedef uint64_t Key;
typedef uint64_t Bitboard;
const int MAX_MOVES = 256;
const int MAX_PLY = 120;
const int MAX_PLY_PLUS_6 = MAX_PLY + 6;
const int MAX_MOVES = 256;
const int MAX_PLY = 128;
/// A move needs 16 bits to be stored
///