Move pv[PLY_MAX_PLUS_2];
};
- // RootMoveList struct is just a vector of RootMove objects,
- // with an handful of methods above the standard ones.
+ // RootMoveList struct is mainly a std::vector of RootMove objects
struct RootMoveList : public std::vector<RootMove> {
-
- typedef std::vector<RootMove> Base;
-
void init(Position& pos, Move searchMoves[]);
- void sort() { insertion_sort<RootMove, Base::iterator>(begin(), end()); }
- void sort_first(int n) { insertion_sort<RootMove, Base::iterator>(begin(), begin() + n); }
-
int bestMoveChanges;
};
NodesSincePoll = 0;
current_search_time(get_system_time());
Limits = limits;
- TimeMgr.init(Limits, pos.full_moves());
+ TimeMgr.init(Limits, pos.startpos_ply_counter());
// Set output steram in normal or chess960 mode
cout << set960(pos.is_chess960());
if (PvNode && thread.maxPly < ss->ply)
thread.maxPly = ss->ply;
- if (SpNode)
+ // Step 1. Initialize node.
+ if (!SpNode)
+ {
+ ss->currentMove = ss->bestMove = threatMove = (ss+1)->excludedMove = MOVE_NONE;
+ (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO;
+ (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
+ }
+ else
{
sp = ss->sp;
tte = NULL;
goto split_point_start;
}
- // Step 1. Initialize node and poll. Polling can abort search
- ss->currentMove = ss->bestMove = threatMove = (ss+1)->excludedMove = MOVE_NONE;
- (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO;
- (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
-
- if (pos.thread() == 0 && ++NodesSincePoll > NodesBetweenPolls)
- {
- NodesSincePoll = 0;
- poll(pos);
- }
-
- // Step 2. Check for aborted search and immediate draw
- if (( StopRequest
- || pos.is_draw<false>()
- || ss->ply > PLY_MAX) && !RootNode)
- return VALUE_DRAW;
-
// Step 3. Mate distance pruning
if (!RootNode)
{
if (pos.pl_move_is_legal(move, ci.pinned))
{
pos.do_move(move, st, ci, pos.move_gives_check(move, ci));
- value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth);
+
+ if (pos.is_draw<false>() || ss->ply + 1 > PLY_MAX)
+ value = VALUE_DRAW;
+ else
+ value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth);
+
pos.undo_move(move);
if (value >= rbeta)
return value;
// Step 14. Make the move
pos.do_move(move, st, ci, givesCheck);
+ // Step XX. Poll. Check if search should be aborted.
+ if (pos.thread() == 0 && ++NodesSincePoll > NodesBetweenPolls)
+ {
+ NodesSincePoll = 0;
+ poll(pos);
+ }
+
+ // Step XX. Check for aborted search and immediate draw
+ if ( StopRequest
+ || pos.is_draw<false>()
+ || ss->ply + 1 > PLY_MAX)
+ {
+ value = VALUE_DRAW;
+ goto undo;
+ }
+
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (isPvMove)
}
// Step 17. Undo move
+undo:
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
// because all the values but the first are usually set to
// -VALUE_INFINITE and we want to keep the same order for all
// the moves but the new PV that goes to head.
- Rml.sort_first(moveCount);
+ sort<RootMove>(Rml.begin(), Rml.begin() + moveCount);
// Update alpha. In multi-pv we don't use aspiration window, so set
// alpha equal to minimum score among the PV lines searched so far.
bool connected_moves(const Position& pos, Move m1, Move m2) {
Square f1, t1, f2, t2;
- Piece p;
+ Piece p1, p2;
+ Square ksq;
assert(m1 && move_is_ok(m1));
assert(m2 && move_is_ok(m2));
return true;
// Case 3: Moving through the vacated square
- if ( piece_is_slider(pos.piece_on(f2))
+ p2 = pos.piece_on(f2);
+ if ( piece_is_slider(p2)
&& bit_is_set(squares_between(f2, t2), f1))
return true;
// Case 4: The destination square for m2 is defended by the moving piece in m1
- p = pos.piece_on(t1);
- if (bit_is_set(pos.attacks_from(p, t1), t2))
+ p1 = pos.piece_on(t1);
+ if (bit_is_set(pos.attacks_from(p1, t1), t2))
return true;
// Case 5: Discovered check, checking piece is the piece moved in m1
- if ( piece_is_slider(p)
- && bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), f2)
- && !bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), t2))
+ ksq = pos.king_square(pos.side_to_move());
+ if ( piece_is_slider(p1)
+ && bit_is_set(squares_between(t1, ksq), f2))
{
- // discovered_check_candidates() works also if the Position's side to
- // move is the opposite of the checking piece.
- Color them = opposite_color(pos.side_to_move());
- Bitboard dcCandidates = pos.discovered_check_candidates(them);
-
- if (bit_is_set(dcCandidates, f2))
+ Bitboard occ = pos.occupied_squares();
+ clear_bit(&occ, f2);
+ if (bit_is_set(pos.attacks_from(p1, t1, occ), ksq))
return true;
}
return false;
while ( (tte = TT.probe(pos.get_key())) != NULL
&& tte->move() != MOVE_NONE
&& pos.move_is_pl(tte->move())
- && pos.pl_move_is_legal(tte->move(), pos.pinned_pieces(pos.side_to_move()))
+ && pos.pl_move_is_legal(tte->move(), pos.pinned_pieces())
&& ply < PLY_MAX
&& (!pos.is_draw<false>() || ply < 2))
{
break;
}
- Rml.sort();
+ sort<RootMove>(Rml.begin(), Rml.end());
}
} // namespace