mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 08:43:09 +00:00
Introduce and use MovePickerExt
A bit of template magic to restore a proper and readable moves 'while' loop that now is again 'similar' to the one that used to be in search(). No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
392c7f2ab6
commit
2e2f1064ba
1 changed files with 68 additions and 32 deletions
100
src/search.cpp
100
src/search.cpp
|
@ -331,7 +331,54 @@ namespace {
|
||||||
DWORD WINAPI init_thread(LPVOID threadID);
|
DWORD WINAPI init_thread(LPVOID threadID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
|
||||||
|
// A dispatcher to choose among different move sources according to the type of node
|
||||||
|
template<bool SpNode, bool Root> struct MovePickerExt;
|
||||||
|
|
||||||
|
// In Root nodes use RootMoveList Rml as source
|
||||||
|
template<> struct MovePickerExt<false, true> {
|
||||||
|
|
||||||
|
MovePickerExt(const Position&, Move, Depth, const History&, SearchStack*, Value)
|
||||||
|
: rm(Rml->begin()), firstCall(true) {}
|
||||||
|
|
||||||
|
Move get_next_move() {
|
||||||
|
|
||||||
|
if (!firstCall)
|
||||||
|
++rm;
|
||||||
|
else
|
||||||
|
firstCall = false;
|
||||||
|
|
||||||
|
return rm != Rml->end() ? rm->pv[0] : MOVE_NONE;
|
||||||
|
}
|
||||||
|
int number_of_evasions() const { return (int)Rml->size(); }
|
||||||
|
|
||||||
|
RootMoveList::iterator rm;
|
||||||
|
bool firstCall;
|
||||||
|
};
|
||||||
|
|
||||||
|
// In SpNodes use split point's shared MovePicker as move source
|
||||||
|
template<> struct MovePickerExt<true, false> {
|
||||||
|
|
||||||
|
MovePickerExt(const Position&, Move, Depth, const History&, SearchStack* ss, Value)
|
||||||
|
: mp(ss->sp->mp) {}
|
||||||
|
|
||||||
|
Move get_next_move() { return mp->get_next_move(); }
|
||||||
|
int number_of_evasions() const { return mp->number_of_evasions(); }
|
||||||
|
|
||||||
|
RootMoveList::iterator rm; // Dummy, never used
|
||||||
|
MovePicker* mp;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Normal case, create and use a MovePicker object as source
|
||||||
|
template<> struct MovePickerExt<false, false> : public MovePicker {
|
||||||
|
|
||||||
|
MovePickerExt(const Position& p, Move ttm, Depth d, const History& h,
|
||||||
|
SearchStack* ss, Value beta) : MovePicker(p, ttm, d, h, ss, beta) {}
|
||||||
|
|
||||||
|
RootMoveList::iterator rm; // Dummy, never used
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
////
|
////
|
||||||
|
@ -743,7 +790,6 @@ namespace {
|
||||||
|
|
||||||
Move movesSearched[MOVES_MAX];
|
Move movesSearched[MOVES_MAX];
|
||||||
int64_t nodes;
|
int64_t nodes;
|
||||||
RootMoveList::iterator rm;
|
|
||||||
StateInfo st;
|
StateInfo st;
|
||||||
const TTEntry *tte;
|
const TTEntry *tte;
|
||||||
Key posKey;
|
Key posKey;
|
||||||
|
@ -958,9 +1004,7 @@ namespace {
|
||||||
split_point_start: // At split points actual search starts from here
|
split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
// Initialize a MovePicker object for the current position
|
// Initialize a MovePicker object for the current position
|
||||||
// FIXME currently MovePicker() c'tor is needless called also in SplitPoint
|
MovePickerExt<SpNode, Root> mp(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));
|
||||||
MovePicker mpBase(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));
|
|
||||||
MovePicker& mp = SpNode ? *sp->mp : mpBase;
|
|
||||||
CheckInfo ci(pos);
|
CheckInfo ci(pos);
|
||||||
ss->bestMove = MOVE_NONE;
|
ss->bestMove = MOVE_NONE;
|
||||||
singleEvasion = !SpNode && isCheck && mp.number_of_evasions() == 1;
|
singleEvasion = !SpNode && isCheck && mp.number_of_evasions() == 1;
|
||||||
|
@ -974,10 +1018,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
&& (tte->type() & VALUE_TYPE_LOWER)
|
&& (tte->type() & VALUE_TYPE_LOWER)
|
||||||
&& tte->depth() >= depth - 3 * ONE_PLY;
|
&& tte->depth() >= depth - 3 * ONE_PLY;
|
||||||
if (Root)
|
if (Root)
|
||||||
{
|
|
||||||
rm = Rml->begin();
|
|
||||||
bestValue = alpha;
|
bestValue = alpha;
|
||||||
}
|
|
||||||
|
|
||||||
if (SpNode)
|
if (SpNode)
|
||||||
{
|
{
|
||||||
|
@ -988,16 +1029,25 @@ split_point_start: // At split points actual search starts from here
|
||||||
// Step 10. Loop through moves
|
// Step 10. Loop through moves
|
||||||
// Loop through all legal moves until no moves remain or a beta cutoff occurs
|
// Loop through all legal moves until no moves remain or a beta cutoff occurs
|
||||||
while ( bestValue < beta
|
while ( bestValue < beta
|
||||||
&& (!Root || rm != Rml->end())
|
&& (move = mp.get_next_move()) != MOVE_NONE
|
||||||
&& ( Root || (move = mp.get_next_move()) != MOVE_NONE)
|
|
||||||
&& !ThreadsMgr.cutoff_at_splitpoint(threadID))
|
&& !ThreadsMgr.cutoff_at_splitpoint(threadID))
|
||||||
{
|
{
|
||||||
|
assert(move_is_ok(move));
|
||||||
|
|
||||||
|
if (SpNode)
|
||||||
|
{
|
||||||
|
moveCount = ++sp->moveCount;
|
||||||
|
lock_release(&(sp->lock));
|
||||||
|
}
|
||||||
|
else if (move == excludedMove)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
movesSearched[moveCount++] = move;
|
||||||
|
|
||||||
if (Root)
|
if (Root)
|
||||||
{
|
{
|
||||||
move = rm->pv[0];
|
|
||||||
|
|
||||||
// This is used by time management
|
// This is used by time management
|
||||||
FirstRootMove = (rm == Rml->begin());
|
FirstRootMove = (moveCount == 1);
|
||||||
|
|
||||||
// Save the current node count before the move is searched
|
// Save the current node count before the move is searched
|
||||||
nodes = pos.nodes_searched();
|
nodes = pos.nodes_searched();
|
||||||
|
@ -1017,18 +1067,6 @@ split_point_start: // At split points actual search starts from here
|
||||||
<< " currmovenumber " << moveCount << endl;
|
<< " currmovenumber " << moveCount << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(move_is_ok(move));
|
|
||||||
|
|
||||||
if (SpNode)
|
|
||||||
{
|
|
||||||
moveCount = ++sp->moveCount;
|
|
||||||
lock_release(&(sp->lock));
|
|
||||||
}
|
|
||||||
else if (move == excludedMove)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
movesSearched[moveCount++] = move;
|
|
||||||
|
|
||||||
isPvMove = (PvNode && moveCount <= (Root ? MultiPV : 1));
|
isPvMove = (PvNode && moveCount <= (Root ? MultiPV : 1));
|
||||||
moveIsCheck = pos.move_is_check(move, ci);
|
moveIsCheck = pos.move_is_check(move, ci);
|
||||||
captureOrPromotion = pos.move_is_capture_or_promotion(move);
|
captureOrPromotion = pos.move_is_capture_or_promotion(move);
|
||||||
|
@ -1222,19 +1260,19 @@ split_point_start: // At split points actual search starts from here
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Remember searched nodes counts for this move
|
// Remember searched nodes counts for this move
|
||||||
rm->nodes += pos.nodes_searched() - nodes;
|
mp.rm->nodes += pos.nodes_searched() - nodes;
|
||||||
|
|
||||||
// Step 17. Check for new best move
|
// Step 17. Check for new best move
|
||||||
if (!isPvMove && value <= alpha)
|
if (!isPvMove && value <= alpha)
|
||||||
rm->pv_score = -VALUE_INFINITE;
|
mp.rm->pv_score = -VALUE_INFINITE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// PV move or new best move!
|
// PV move or new best move!
|
||||||
|
|
||||||
// Update PV
|
// Update PV
|
||||||
ss->bestMove = move;
|
ss->bestMove = move;
|
||||||
rm->pv_score = value;
|
mp.rm->pv_score = value;
|
||||||
rm->extract_pv_from_tt(pos);
|
mp.rm->extract_pv_from_tt(pos);
|
||||||
|
|
||||||
// We record how often the best move has been changed in each
|
// We record how often the best move has been changed in each
|
||||||
// iteration. This information is used for time managment: When
|
// iteration. This information is used for time managment: When
|
||||||
|
@ -1260,8 +1298,6 @@ split_point_start: // At split points actual search starts from here
|
||||||
alpha = bestValue = (*Rml)[Min(moveCount, MultiPV) - 1].pv_score; // FIXME why moveCount?
|
alpha = bestValue = (*Rml)[Min(moveCount, MultiPV) - 1].pv_score; // FIXME why moveCount?
|
||||||
|
|
||||||
} // PV move or new best move
|
} // PV move or new best move
|
||||||
|
|
||||||
++rm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 18. Check for split
|
// Step 18. Check for split
|
||||||
|
@ -1275,7 +1311,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
&& !ThreadsMgr.cutoff_at_splitpoint(threadID)
|
&& !ThreadsMgr.cutoff_at_splitpoint(threadID)
|
||||||
&& Iteration <= 99)
|
&& Iteration <= 99)
|
||||||
ThreadsMgr.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
|
ThreadsMgr.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
|
||||||
threatMove, mateThreat, moveCount, &mp, PvNode);
|
threatMove, mateThreat, moveCount, (MovePicker*)&mp, PvNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 19. Check for mate and stalemate
|
// Step 19. Check for mate and stalemate
|
||||||
|
|
Loading…
Add table
Reference in a new issue