#include "movegen.h"
#include "movepick.h"
+#include "thread.h"
namespace {
/// move ordering is at the current node.
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h,
- Search::Stack* ss, Value beta) : pos(p), H(h), depth(d) {
+ Search::Stack* s, Value beta) : pos(p), H(h), depth(d) {
assert(d > DEPTH_ZERO);
captureThreshold = 0;
curMove = lastMove = moves;
lastBadCapture = moves + MAX_MOVES - 1;
+ ss = s;
if (p.in_check())
phase = EVASION;
/// It returns a new pseudo legal move every time it is called, until there
/// are no more moves left. It picks the move with the biggest score from a list
/// of generated moves taking care not to return the tt move if has already been
-/// searched previously. Note that this function is not thread safe so should be
-/// lock protected by caller when accessed through a shared MovePicker object.
-
-Move MovePicker::next_move() {
+/// searched previously.
+template<>
+Move MovePicker::next_move<false>() {
Move move;
}
}
}
+
+
+/// Version of next_move() to use at split point nodes where the move is grabbed
+/// from the split point's shared MovePicker object. This function is not thread
+/// safe so should be lock protected by the caller.
+template<>
+Move MovePicker::next_move<true>() { return ss->sp->mp->next_move<false>(); }
MovePicker(const Position&, Move, Depth, const History&, Search::Stack*, Value);
MovePicker(const Position&, Move, Depth, const History&, Square);
MovePicker(const Position&, Move, const History&, PieceType);
- Move next_move();
+ template<bool SpNode> Move next_move();
private:
void score_captures();
const Position& pos;
const History& H;
+ Search::Stack* ss;
Depth depth;
Move ttMove;
MoveStack killers[2];
Move do_skill_level();
string uci_pv(const Position& pos, int depth, Value alpha, Value beta);
- // MovePickerExt class template 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> struct MovePickerExt : public MovePicker {
-
- MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, Stack* ss, Value b)
- : MovePicker(p, ttm, d, h, ss, b) {}
- };
-
- // In case of a SpNode we use split point's shared MovePicker object as moves source
- template<> struct MovePickerExt<true> : public MovePicker {
-
- MovePickerExt(const Position& p, Move ttm, Depth d, const History& h, Stack* ss, Value b)
- : MovePicker(p, ttm, d, h, ss, b), mp(ss->sp->mp) {}
-
- Move next_move() { return mp->next_move(); }
- MovePicker* mp;
- };
-
// is_dangerous() checks whether a move belongs to some classes of known
// 'dangerous' moves so that we avoid to prune it.
FORCE_INLINE bool is_dangerous(const Position& pos, Move m, bool captureOrPromotion) {
MovePicker mp(pos, ttMove, H, pos.captured_piece_type());
CheckInfo ci(pos);
- while ((move = mp.next_move()) != MOVE_NONE)
+ while ((move = mp.next_move<false>()) != MOVE_NONE)
if (pos.pl_move_is_legal(move, ci.pinned))
{
ss->currentMove = move;
split_point_start: // At split points actual search starts from here
- MovePickerExt<SpNode> mp(pos, ttMove, depth, H, ss, PvNode ? -VALUE_INFINITE : beta);
+ MovePicker mp(pos, ttMove, depth, H, ss, PvNode ? -VALUE_INFINITE : beta);
CheckInfo ci(pos);
futilityBase = ss->eval + ss->evalMargin;
singularExtensionNode = !RootNode
// Step 11. Loop through moves
// Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs
while ( bestValue < beta
- && (move = mp.next_move()) != MOVE_NONE
+ && (move = mp.next_move<SpNode>()) != MOVE_NONE
&& !thisThread->cutoff_occurred()
&& !Signals.stop)
{
// Loop through the moves until no moves remain or a beta cutoff occurs
while ( bestValue < beta
- && (move = mp.next_move()) != MOVE_NONE)
+ && (move = mp.next_move<false>()) != MOVE_NONE)
{
assert(is_ok(move));