mirror of
https://github.com/sockspls/badfish
synced 2025-05-02 17:49:35 +00:00
Use an enum instead of a table as MovePicker sequencer
No functional change Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
28892666bd
commit
e25de55fac
2 changed files with 52 additions and 60 deletions
111
src/movepick.cpp
111
src/movepick.cpp
|
@ -28,29 +28,16 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum MovegenPhase {
|
enum Sequencer {
|
||||||
PH_TT_MOVE, // Transposition table move
|
MAIN_SEARCH, TT_MOVE_S1, GOOD_CAPTURES_S1, KILLERS_S1, NONCAPTURES_1_S1,
|
||||||
PH_GOOD_CAPTURES, // Queen promotions and captures with SEE values >= captureThreshold (captureThreshold <= 0)
|
NONCAPTURES_2_S1, BAD_CAPTURES_S1, STOP_S1,
|
||||||
PH_GOOD_PROBCUT, // Queen promotions and captures with SEE values > captureThreshold (captureThreshold >= 0)
|
EVASIONS, TT_MOVE_S2, EVASIONS_S2, STOP_S2,
|
||||||
PH_KILLERS, // Killer moves from the current ply
|
CAPTURES_AND_CHECKS, TT_MOVE_S3, QCAPTURES_S3, QCHECKS_S3, STOP_S3,
|
||||||
PH_NONCAPTURES_1, // Non-captures and underpromotions with positive score
|
CAPTURES, TT_MOVE_S4, QCAPTURES_S4, STOP_S4,
|
||||||
PH_NONCAPTURES_2, // Non-captures and underpromotions with non-positive score
|
RECAPTURES, TT_MOVE_S5, RECAPTURES_S5, STOP_S5,
|
||||||
PH_BAD_CAPTURES, // Queen promotions and captures with SEE values < captureThreshold (captureThreshold <= 0)
|
PROBCUT, TT_MOVE_S6, GOOD_CAPTURES_S6, STOP_S6
|
||||||
PH_EVASIONS, // Check evasions
|
|
||||||
PH_QCAPTURES, // Captures in quiescence search
|
|
||||||
PH_QRECAPTURES, // Recaptures in quiescence search
|
|
||||||
PH_QCHECKS, // Non-capture checks in quiescence search
|
|
||||||
PH_STOP
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CACHE_LINE_ALIGNMENT
|
|
||||||
const uint8_t MainSearchTable[] = { PH_TT_MOVE, PH_GOOD_CAPTURES, PH_KILLERS, PH_NONCAPTURES_1, PH_NONCAPTURES_2, PH_BAD_CAPTURES, PH_STOP };
|
|
||||||
const uint8_t EvasionTable[] = { PH_TT_MOVE, PH_EVASIONS, PH_STOP };
|
|
||||||
const uint8_t QsearchWithChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_QCHECKS, PH_STOP };
|
|
||||||
const uint8_t QsearchWithoutChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_STOP };
|
|
||||||
const uint8_t QsearchRecapturesTable[] = { PH_TT_MOVE, PH_QRECAPTURES, PH_STOP };
|
|
||||||
const uint8_t ProbCutTable[] = { PH_TT_MOVE, PH_GOOD_PROBCUT, PH_STOP };
|
|
||||||
|
|
||||||
// Unary predicate used by std::partition to split positive scores from remaining
|
// Unary predicate used by std::partition to split positive scores from remaining
|
||||||
// ones so to sort separately the two sets, and with the second sort delayed.
|
// ones so to sort separately the two sets, and with the second sort delayed.
|
||||||
inline bool has_positive_score(const MoveStack& move) { return move.score > 0; }
|
inline bool has_positive_score(const MoveStack& move) { return move.score > 0; }
|
||||||
|
@ -81,7 +68,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h,
|
||||||
if (p.in_check())
|
if (p.in_check())
|
||||||
{
|
{
|
||||||
killers[0].move = killers[1].move = MOVE_NONE;
|
killers[0].move = killers[1].move = MOVE_NONE;
|
||||||
phasePtr = EvasionTable;
|
phase = EVASIONS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -96,11 +83,11 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h,
|
||||||
else if (ss && ss->eval > beta)
|
else if (ss && ss->eval > beta)
|
||||||
captureThreshold = beta - ss->eval;
|
captureThreshold = beta - ss->eval;
|
||||||
|
|
||||||
phasePtr = MainSearchTable;
|
phase = MAIN_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ttMove = (ttm && pos.is_pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
ttMove = (ttm && pos.is_pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
||||||
phasePtr += int(ttMove == MOVE_NONE) - 1;
|
phase += int(ttMove == MOVE_NONE);
|
||||||
go_next_phase();
|
go_next_phase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,12 +97,14 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h, S
|
||||||
assert(d <= DEPTH_ZERO);
|
assert(d <= DEPTH_ZERO);
|
||||||
|
|
||||||
if (p.in_check())
|
if (p.in_check())
|
||||||
phasePtr = EvasionTable;
|
phase = EVASIONS;
|
||||||
|
|
||||||
else if (d >= DEPTH_QS_CHECKS)
|
else if (d >= DEPTH_QS_CHECKS)
|
||||||
phasePtr = QsearchWithChecksTable;
|
phase = CAPTURES_AND_CHECKS;
|
||||||
|
|
||||||
else if (d >= DEPTH_QS_RECAPTURES)
|
else if (d >= DEPTH_QS_RECAPTURES)
|
||||||
{
|
{
|
||||||
phasePtr = QsearchWithoutChecksTable;
|
phase = CAPTURES;
|
||||||
|
|
||||||
// Skip TT move if is not a capture or a promotion, this avoids
|
// Skip TT move if is not a capture or a promotion, this avoids
|
||||||
// qsearch tree explosion due to a possible perpetual check or
|
// qsearch tree explosion due to a possible perpetual check or
|
||||||
|
@ -125,13 +114,13 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h, S
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
phasePtr = QsearchRecapturesTable;
|
phase = RECAPTURES;
|
||||||
recaptureSquare = recaptureSq;
|
recaptureSquare = recaptureSq;
|
||||||
ttm = MOVE_NONE;
|
ttm = MOVE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ttMove = (ttm && pos.is_pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
ttMove = (ttm && pos.is_pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
||||||
phasePtr += int(ttMove == MOVE_NONE) - 1;
|
phase += int(ttMove == MOVE_NONE);
|
||||||
go_next_phase();
|
go_next_phase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,14 +131,14 @@ MovePicker::MovePicker(const Position& p, Move ttm, const History& h, PieceType
|
||||||
|
|
||||||
// In ProbCut we consider only captures better than parent's move
|
// In ProbCut we consider only captures better than parent's move
|
||||||
captureThreshold = PieceValueMidgame[Piece(parentCapture)];
|
captureThreshold = PieceValueMidgame[Piece(parentCapture)];
|
||||||
phasePtr = ProbCutTable;
|
phase = PROBCUT;
|
||||||
|
|
||||||
if ( ttm != MOVE_NONE
|
if ( ttm != MOVE_NONE
|
||||||
&& (!pos.is_capture(ttm) || pos.see(ttm) <= captureThreshold))
|
&& (!pos.is_capture(ttm) || pos.see(ttm) <= captureThreshold))
|
||||||
ttm = MOVE_NONE;
|
ttm = MOVE_NONE;
|
||||||
|
|
||||||
ttMove = (ttm && pos.is_pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
ttMove = (ttm && pos.is_pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
||||||
phasePtr += int(ttMove == MOVE_NONE) - 1;
|
phase += int(ttMove == MOVE_NONE);
|
||||||
go_next_phase();
|
go_next_phase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,71 +149,73 @@ MovePicker::MovePicker(const Position& p, Move ttm, const History& h, PieceType
|
||||||
void MovePicker::go_next_phase() {
|
void MovePicker::go_next_phase() {
|
||||||
|
|
||||||
curMove = moves;
|
curMove = moves;
|
||||||
phase = *(++phasePtr);
|
|
||||||
switch (phase) {
|
|
||||||
|
|
||||||
case PH_TT_MOVE:
|
switch (++phase) {
|
||||||
|
|
||||||
|
case TT_MOVE_S1: case TT_MOVE_S2: case TT_MOVE_S3:
|
||||||
|
case TT_MOVE_S4: case TT_MOVE_S5: case TT_MOVE_S6:
|
||||||
lastMove = curMove + 1;
|
lastMove = curMove + 1;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_GOOD_CAPTURES:
|
case GOOD_CAPTURES_S1:
|
||||||
case PH_GOOD_PROBCUT:
|
case GOOD_CAPTURES_S6:
|
||||||
lastMove = generate<MV_CAPTURE>(pos, moves);
|
lastMove = generate<MV_CAPTURE>(pos, moves);
|
||||||
score_captures();
|
score_captures();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_KILLERS:
|
case KILLERS_S1:
|
||||||
curMove = killers;
|
curMove = killers;
|
||||||
lastMove = curMove + 2;
|
lastMove = curMove + 2;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_NONCAPTURES_1:
|
case NONCAPTURES_1_S1:
|
||||||
lastNonCapture = lastMove = generate<MV_NON_CAPTURE>(pos, moves);
|
lastNonCapture = lastMove = generate<MV_NON_CAPTURE>(pos, moves);
|
||||||
score_noncaptures();
|
score_noncaptures();
|
||||||
lastMove = std::partition(curMove, lastMove, has_positive_score);
|
lastMove = std::partition(curMove, lastMove, has_positive_score);
|
||||||
sort<MoveStack>(curMove, lastMove);
|
sort<MoveStack>(curMove, lastMove);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_NONCAPTURES_2:
|
case NONCAPTURES_2_S1:
|
||||||
curMove = lastMove;
|
curMove = lastMove;
|
||||||
lastMove = lastNonCapture;
|
lastMove = lastNonCapture;
|
||||||
if (depth >= 3 * ONE_PLY)
|
if (depth >= 3 * ONE_PLY)
|
||||||
sort<MoveStack>(curMove, lastMove);
|
sort<MoveStack>(curMove, lastMove);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_BAD_CAPTURES:
|
case BAD_CAPTURES_S1:
|
||||||
// Bad captures SEE value is already calculated so just pick
|
// Bad captures SEE value is already calculated so just pick
|
||||||
// them in order to get SEE move ordering.
|
// them in order to get SEE move ordering.
|
||||||
curMove = badCaptures;
|
curMove = badCaptures;
|
||||||
lastMove = moves + MAX_MOVES;
|
lastMove = moves + MAX_MOVES;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_EVASIONS:
|
case EVASIONS_S2:
|
||||||
assert(pos.in_check());
|
assert(pos.in_check());
|
||||||
lastMove = generate<MV_EVASION>(pos, moves);
|
lastMove = generate<MV_EVASION>(pos, moves);
|
||||||
score_evasions();
|
score_evasions();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_QCAPTURES:
|
case QCAPTURES_S3:
|
||||||
|
case QCAPTURES_S4:
|
||||||
lastMove = generate<MV_CAPTURE>(pos, moves);
|
lastMove = generate<MV_CAPTURE>(pos, moves);
|
||||||
score_captures();
|
score_captures();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_QRECAPTURES:
|
case RECAPTURES_S5:
|
||||||
lastMove = generate<MV_CAPTURE>(pos, moves);
|
lastMove = generate<MV_CAPTURE>(pos, moves);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_QCHECKS:
|
case QCHECKS_S3:
|
||||||
lastMove = generate<MV_NON_CAPTURE_CHECK>(pos, moves);
|
lastMove = generate<MV_NON_CAPTURE_CHECK>(pos, moves);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PH_STOP:
|
case STOP_S1: case STOP_S2: case STOP_S3:
|
||||||
|
case STOP_S4: case STOP_S5: case STOP_S6:
|
||||||
lastMove = curMove + 1; // Avoid another go_next_phase() call
|
lastMove = curMove + 1; // Avoid another go_next_phase() call
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,12 +309,13 @@ Move MovePicker::next_move() {
|
||||||
|
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
|
|
||||||
case PH_TT_MOVE:
|
case TT_MOVE_S1: case TT_MOVE_S2: case TT_MOVE_S3:
|
||||||
|
case TT_MOVE_S4: case TT_MOVE_S5: case TT_MOVE_S6:
|
||||||
curMove++;
|
curMove++;
|
||||||
return ttMove;
|
return ttMove;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_GOOD_CAPTURES:
|
case GOOD_CAPTURES_S1:
|
||||||
move = pick_best(curMove++, lastMove)->move;
|
move = pick_best(curMove++, lastMove)->move;
|
||||||
if (move != ttMove)
|
if (move != ttMove)
|
||||||
{
|
{
|
||||||
|
@ -340,14 +332,14 @@ Move MovePicker::next_move() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_GOOD_PROBCUT:
|
case GOOD_CAPTURES_S6:
|
||||||
move = pick_best(curMove++, lastMove)->move;
|
move = pick_best(curMove++, lastMove)->move;
|
||||||
if ( move != ttMove
|
if ( move != ttMove
|
||||||
&& pos.see(move) > captureThreshold)
|
&& pos.see(move) > captureThreshold)
|
||||||
return move;
|
return move;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_KILLERS:
|
case KILLERS_S1:
|
||||||
move = (curMove++)->move;
|
move = (curMove++)->move;
|
||||||
if ( move != MOVE_NONE
|
if ( move != MOVE_NONE
|
||||||
&& pos.is_pseudo_legal(move)
|
&& pos.is_pseudo_legal(move)
|
||||||
|
@ -356,8 +348,8 @@ Move MovePicker::next_move() {
|
||||||
return move;
|
return move;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_NONCAPTURES_1:
|
case NONCAPTURES_1_S1:
|
||||||
case PH_NONCAPTURES_2:
|
case NONCAPTURES_2_S1:
|
||||||
move = (curMove++)->move;
|
move = (curMove++)->move;
|
||||||
if ( move != ttMove
|
if ( move != ttMove
|
||||||
&& move != killers[0].move
|
&& move != killers[0].move
|
||||||
|
@ -365,35 +357,36 @@ Move MovePicker::next_move() {
|
||||||
return move;
|
return move;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_BAD_CAPTURES:
|
case BAD_CAPTURES_S1:
|
||||||
move = pick_best(curMove++, lastMove)->move;
|
move = pick_best(curMove++, lastMove)->move;
|
||||||
return move;
|
return move;
|
||||||
|
|
||||||
case PH_EVASIONS:
|
case EVASIONS_S2:
|
||||||
case PH_QCAPTURES:
|
case QCAPTURES_S3:
|
||||||
|
case QCAPTURES_S4:
|
||||||
move = pick_best(curMove++, lastMove)->move;
|
move = pick_best(curMove++, lastMove)->move;
|
||||||
if (move != ttMove)
|
if (move != ttMove)
|
||||||
return move;
|
return move;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_QRECAPTURES:
|
case RECAPTURES_S5:
|
||||||
move = (curMove++)->move;
|
move = (curMove++)->move;
|
||||||
if (to_sq(move) == recaptureSquare)
|
if (to_sq(move) == recaptureSquare)
|
||||||
return move;
|
return move;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_QCHECKS:
|
case QCHECKS_S3:
|
||||||
move = (curMove++)->move;
|
move = (curMove++)->move;
|
||||||
if (move != ttMove)
|
if (move != ttMove)
|
||||||
return move;
|
return move;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PH_STOP:
|
case STOP_S1: case STOP_S2: case STOP_S3:
|
||||||
|
case STOP_S4: case STOP_S5: case STOP_S6:
|
||||||
return MOVE_NONE;
|
return MOVE_NONE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,6 @@ private:
|
||||||
MoveStack killers[2];
|
MoveStack killers[2];
|
||||||
Square recaptureSquare;
|
Square recaptureSquare;
|
||||||
int captureThreshold, phase;
|
int captureThreshold, phase;
|
||||||
const uint8_t* phasePtr;
|
|
||||||
MoveStack *curMove, *lastMove, *lastNonCapture, *badCaptures;
|
MoveStack *curMove, *lastMove, *lastNonCapture, *badCaptures;
|
||||||
MoveStack moves[MAX_MOVES];
|
MoveStack moves[MAX_MOVES];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue