mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 17:19: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 {
|
||||
|
||||
// Different node types, used as template parameter
|
||||
enum NodeType { NonPV, PV };
|
||||
|
||||
// Set to true to force running with one thread. Used for debugging.
|
||||
// Set to true to force running with one thread. Used for debugging
|
||||
const bool FakeSplit = false;
|
||||
|
||||
// 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 };
|
||||
inline bool piece_is_slider(Piece p) { return Slidings[p]; }
|
||||
// Different node types, used as template parameter
|
||||
enum NodeType { NonPV, PV };
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// according to the order in which moves are returned by MovePicker.
|
||||
|
||||
struct RootMove {
|
||||
|
||||
RootMove();
|
||||
|
@ -85,10 +80,8 @@ namespace {
|
|||
Move pv[PLY_MAX_PLUS_2];
|
||||
};
|
||||
|
||||
|
||||
// RootMoveList struct is just a vector of RootMove objects,
|
||||
// with an handful of methods above the standard ones.
|
||||
|
||||
struct RootMoveList : public std::vector<RootMove> {
|
||||
|
||||
typedef std::vector<RootMove> Base;
|
||||
|
@ -100,32 +93,45 @@ namespace {
|
|||
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
|
||||
// notation compatible with UCI protocol.
|
||||
std::ostream& operator<<(std::ostream& os, Move m) {
|
||||
MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss, Value b)
|
||||
: MovePicker(p, ttm, d, h, ss, b) {}
|
||||
|
||||
bool chess960 = (os.iword(0) != 0); // See set960()
|
||||
return os << move_to_uci(m, chess960);
|
||||
}
|
||||
RootMoveList::iterator rm; // Dummy, needed to compile
|
||||
};
|
||||
|
||||
// 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
|
||||
// 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 {};
|
||||
/// Constants
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const set960& f) {
|
||||
|
||||
os.iword(0) = int(f);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
/// Adjustments
|
||||
// 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 };
|
||||
inline bool piece_is_slider(Piece p) { return Slidings[p]; }
|
||||
|
||||
// Step 6. Razoring
|
||||
|
||||
|
@ -264,71 +270,28 @@ namespace {
|
|||
void poll(const Position& pos);
|
||||
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
|
||||
// the proper move source according to the type of node.
|
||||
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;
|
||||
bool chess960 = (os.iword(0) != 0); // See set960()
|
||||
return os << move_to_uci(m, chess960);
|
||||
}
|
||||
|
||||
Rml.sort();
|
||||
rm = Rml.begin();
|
||||
// When formatting a move for std::cout we must know if we are in Chess960
|
||||
// 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
|
||||
|
||||
|
||||
|
@ -2090,6 +2053,39 @@ split_point_start: // At split points actual search starts from here
|
|||
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
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue