mirror of
https://github.com/sockspls/badfish
synced 2025-05-02 09:39:36 +00:00
Move MovePickerExt specializations away from headings
This unclutters a bit the heading part of search.cpp No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
09d01ee9dc
commit
87f2b52ace
1 changed files with 87 additions and 91 deletions
178
src/search.cpp
178
src/search.cpp
|
@ -43,22 +43,17 @@ using std::endl;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Different node types, used as template parameter
|
// Set to true to force running with one thread. Used for debugging
|
||||||
enum NodeType { NonPV, PV };
|
|
||||||
|
|
||||||
// Set to true to force running with one thread. Used for debugging.
|
|
||||||
const bool FakeSplit = false;
|
const bool FakeSplit = false;
|
||||||
|
|
||||||
// Lookup table to check if a Piece is a slider and its access function
|
// Different node types, used as template parameter
|
||||||
const bool Slidings[18] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 };
|
enum NodeType { NonPV, PV };
|
||||||
inline bool piece_is_slider(Piece p) { return Slidings[p]; }
|
|
||||||
|
|
||||||
// RootMove struct is used for moves at the root of the tree. For each root
|
// RootMove struct is used for moves at the root of the tree. For each root
|
||||||
// move, we store two scores, a node count, and a PV (really a refutation
|
// move, we store two scores, a node count, and a PV (really a refutation
|
||||||
// in the case of moves which fail low). Value pv_score is normally set at
|
// in the case of moves which fail low). Value pv_score is normally set at
|
||||||
// -VALUE_INFINITE for all non-pv moves, while non_pv_score is computed
|
// -VALUE_INFINITE for all non-pv moves, while non_pv_score is computed
|
||||||
// according to the order in which moves are returned by MovePicker.
|
// according to the order in which moves are returned by MovePicker.
|
||||||
|
|
||||||
struct RootMove {
|
struct RootMove {
|
||||||
|
|
||||||
RootMove();
|
RootMove();
|
||||||
|
@ -85,10 +80,8 @@ namespace {
|
||||||
Move pv[PLY_MAX_PLUS_2];
|
Move pv[PLY_MAX_PLUS_2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// RootMoveList struct is just a vector of RootMove objects,
|
// RootMoveList struct is just a vector of RootMove objects,
|
||||||
// with an handful of methods above the standard ones.
|
// with an handful of methods above the standard ones.
|
||||||
|
|
||||||
struct RootMoveList : public std::vector<RootMove> {
|
struct RootMoveList : public std::vector<RootMove> {
|
||||||
|
|
||||||
typedef std::vector<RootMove> Base;
|
typedef std::vector<RootMove> Base;
|
||||||
|
@ -100,32 +93,45 @@ namespace {
|
||||||
int bestMoveChanges;
|
int bestMoveChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// MovePickerExt template class extends MovePicker and allows to choose at compile
|
||||||
|
// time the proper moves source according to the type of node. In the default case
|
||||||
|
// we simply create and use a standard MovePicker object.
|
||||||
|
template<bool SpNode, bool Root> struct MovePickerExt : public MovePicker {
|
||||||
|
|
||||||
// Overload operator<<() to make it easier to print moves in a coordinate
|
MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss, Value b)
|
||||||
// notation compatible with UCI protocol.
|
: MovePicker(p, ttm, d, h, ss, b) {}
|
||||||
std::ostream& operator<<(std::ostream& os, Move m) {
|
|
||||||
|
|
||||||
bool chess960 = (os.iword(0) != 0); // See set960()
|
RootMoveList::iterator rm; // Dummy, needed to compile
|
||||||
return os << move_to_uci(m, chess960);
|
};
|
||||||
}
|
|
||||||
|
// In case of a SpNode we use split point's shared MovePicker object as moves source
|
||||||
|
template<> struct MovePickerExt<true, false> : public MovePicker {
|
||||||
|
|
||||||
|
MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss, Value b)
|
||||||
|
: MovePicker(p, ttm, d, h, ss, b), mp(ss->sp->mp) {}
|
||||||
|
|
||||||
|
Move get_next_move() { return mp->get_next_move(); }
|
||||||
|
|
||||||
|
RootMoveList::iterator rm; // Dummy, needed to compile
|
||||||
|
MovePicker* mp;
|
||||||
|
};
|
||||||
|
|
||||||
|
// In case of a Root node we use RootMoveList as moves source
|
||||||
|
template<> struct MovePickerExt<false, true> : public MovePicker {
|
||||||
|
|
||||||
|
MovePickerExt(const Position&, Move, Depth, const History&, SearchStack*, Value);
|
||||||
|
Move get_next_move();
|
||||||
|
|
||||||
|
RootMoveList::iterator rm;
|
||||||
|
bool firstCall;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// When formatting a move for std::cout we must know if we are in Chess960
|
/// Constants
|
||||||
// or not. To keep using the handy operator<<() on the move the trick is to
|
|
||||||
// embed this flag in the stream itself. Function-like named enum set960 is
|
|
||||||
// used as a custom manipulator and the stream internal general-purpose array,
|
|
||||||
// accessed through ios_base::iword(), is used to pass the flag to the move's
|
|
||||||
// operator<<() that will read it to properly format castling moves.
|
|
||||||
enum set960 {};
|
|
||||||
|
|
||||||
std::ostream& operator<< (std::ostream& os, const set960& f) {
|
// Lookup table to check if a Piece is a slider and its access function
|
||||||
|
const bool Slidings[18] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 };
|
||||||
os.iword(0) = int(f);
|
inline bool piece_is_slider(Piece p) { return Slidings[p]; }
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adjustments
|
|
||||||
|
|
||||||
// Step 6. Razoring
|
// Step 6. Razoring
|
||||||
|
|
||||||
|
@ -264,71 +270,28 @@ namespace {
|
||||||
void poll(const Position& pos);
|
void poll(const Position& pos);
|
||||||
void wait_for_stop_or_ponderhit();
|
void wait_for_stop_or_ponderhit();
|
||||||
|
|
||||||
|
// Overload operator<<() to make it easier to print moves in a coordinate
|
||||||
|
// notation compatible with UCI protocol.
|
||||||
|
std::ostream& operator<<(std::ostream& os, Move m) {
|
||||||
|
|
||||||
// MovePickerExt is an extended MovePicker class used to choose at compile time
|
bool chess960 = (os.iword(0) != 0); // See set960()
|
||||||
// the proper move source according to the type of node.
|
return os << move_to_uci(m, chess960);
|
||||||
template<bool SpNode, bool Root> struct MovePickerExt;
|
|
||||||
|
|
||||||
// In Root nodes use RootMoveList as source. Score and sort the root moves
|
|
||||||
// before to search them.
|
|
||||||
template<> struct MovePickerExt<false, true> : public MovePicker {
|
|
||||||
|
|
||||||
MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss, Value b)
|
|
||||||
: MovePicker(p, ttm, d, h, ss, b), firstCall(true) {
|
|
||||||
Move move;
|
|
||||||
Value score = VALUE_ZERO;
|
|
||||||
|
|
||||||
// Score root moves using standard ordering used in main search, the moves
|
|
||||||
// are scored according to the order in which they are returned by MovePicker.
|
|
||||||
// This is the second order score that is used to compare the moves when
|
|
||||||
// the first orders pv_score of both moves are equal.
|
|
||||||
while ((move = MovePicker::get_next_move()) != MOVE_NONE)
|
|
||||||
for (rm = Rml.begin(); rm != Rml.end(); ++rm)
|
|
||||||
if (rm->pv[0] == move)
|
|
||||||
{
|
|
||||||
rm->non_pv_score = score--;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rml.sort();
|
// When formatting a move for std::cout we must know if we are in Chess960
|
||||||
rm = Rml.begin();
|
// or not. To keep using the handy operator<<() on the move the trick is to
|
||||||
|
// embed this flag in the stream itself. Function-like named enum set960 is
|
||||||
|
// used as a custom manipulator and the stream internal general-purpose array,
|
||||||
|
// accessed through ios_base::iword(), is used to pass the flag to the move's
|
||||||
|
// operator<<() that will read it to properly format castling moves.
|
||||||
|
enum set960 {};
|
||||||
|
|
||||||
|
std::ostream& operator<< (std::ostream& os, const set960& f) {
|
||||||
|
|
||||||
|
os.iword(0) = int(f);
|
||||||
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
Move get_next_move() {
|
|
||||||
|
|
||||||
if (!firstCall)
|
|
||||||
++rm;
|
|
||||||
else
|
|
||||||
firstCall = false;
|
|
||||||
|
|
||||||
return rm != Rml.end() ? rm->pv[0] : MOVE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootMoveList::iterator rm;
|
|
||||||
bool firstCall;
|
|
||||||
};
|
|
||||||
|
|
||||||
// In SpNodes use split point's shared MovePicker object as move source
|
|
||||||
template<> struct MovePickerExt<true, false> : public MovePicker {
|
|
||||||
|
|
||||||
MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss, Value b)
|
|
||||||
: MovePicker(p, ttm, d, h, ss, b), mp(ss->sp->mp) {}
|
|
||||||
|
|
||||||
Move get_next_move() { return mp->get_next_move(); }
|
|
||||||
|
|
||||||
RootMoveList::iterator rm; // Dummy, needed to compile
|
|
||||||
MovePicker* mp;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Default 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 b)
|
|
||||||
: MovePicker(p, ttm, d, h, ss, b) {}
|
|
||||||
|
|
||||||
RootMoveList::iterator rm; // Dummy, needed to compile
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
@ -2090,6 +2053,39 @@ split_point_start: // At split points actual search starts from here
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Specializations for MovePickerExt in case of Root node
|
||||||
|
MovePickerExt<false, true>::MovePickerExt(const Position& p, Move ttm, Depth d,
|
||||||
|
const History& h, SearchStack* ss, Value b)
|
||||||
|
: MovePicker(p, ttm, d, h, ss, b), firstCall(true) {
|
||||||
|
Move move;
|
||||||
|
Value score = VALUE_ZERO;
|
||||||
|
|
||||||
|
// Score root moves using standard ordering used in main search, the moves
|
||||||
|
// are scored according to the order in which they are returned by MovePicker.
|
||||||
|
// This is the second order score that is used to compare the moves when
|
||||||
|
// the first orders pv_score of both moves are equal.
|
||||||
|
while ((move = MovePicker::get_next_move()) != MOVE_NONE)
|
||||||
|
for (rm = Rml.begin(); rm != Rml.end(); ++rm)
|
||||||
|
if (rm->pv[0] == move)
|
||||||
|
{
|
||||||
|
rm->non_pv_score = score--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rml.sort();
|
||||||
|
rm = Rml.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Move MovePickerExt<false, true>::get_next_move() {
|
||||||
|
|
||||||
|
if (!firstCall)
|
||||||
|
++rm;
|
||||||
|
else
|
||||||
|
firstCall = false;
|
||||||
|
|
||||||
|
return rm != Rml.end() ? rm->pv[0] : MOVE_NONE;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue