int64_t perft(Position& pos, Depth depth) {
- MoveStack mlist[MAX_MOVES];
StateInfo st;
- Move m;
int64_t sum = 0;
// Generate all legal moves
- MoveStack* last = generate<MV_LEGAL>(pos, mlist);
+ MoveList<MV_LEGAL> ml(pos);
// If we are at the last ply we don't need to do and undo
// the moves, just to count them.
if (depth <= ONE_PLY)
- return int(last - mlist);
+ return ml.size();
// Loop through all legal moves
CheckInfo ci(pos);
- for (MoveStack* cur = mlist; cur != last; cur++)
+ for ( ; !ml.end(); ++ml)
{
- m = cur->move;
- pos.do_move(m, st, ci, pos.move_gives_check(m, ci));
+ pos.do_move(ml.move(), st, ci, pos.move_gives_check(ml.move(), ci));
sum += perft(pos, depth - ONE_PLY);
- pos.undo_move(m);
+ pos.undo_move(ml.move());
}
return sum;
}
NodesSincePoll = 0;
current_search_time(get_system_time());
Limits = limits;
- TimeMgr.init(Limits, pos.startpos_ply_counter());
+ TimeMgr.init(Limits, pos.full_moves());
// Set output steram in normal or chess960 mode
cout << set960(pos.is_chess960());
// TT value, so we use a different position key in case of an excluded move.
excludedMove = ss->excludedMove;
posKey = excludedMove ? pos.get_exclusion_key() : pos.get_key();
-
tte = TT.probe(posKey);
ttMove = tte ? tte->move() : MOVE_NONE;
if (move == excludedMove)
continue;
- // At PV and SpNode nodes we want the moves to be legal
+ // At PV and SpNode nodes we want all moves to be legal since the beginning
if ((PvNode || SpNode) && !pos.pl_move_is_legal(move, ci.pinned))
continue;
cout << "info" << speed_to_uci(pos.nodes_searched()) << endl;
}
- // For long searches send to GUI current move
+ // For long searches send current move info to GUI
if (current_search_time() > 2000)
cout << "info" << depth_to_uci(depth)
<< " currmove " << move << " currmovenumber " << moveCount << endl;
}
// At Root and at first iteration do a PV search on all the moves to score root moves
- isPvMove = (PvNode && moveCount <= (RootNode ? depth <= ONE_PLY ? MAX_MOVES : MultiPV : 1));
+ isPvMove = (PvNode && moveCount <= (!RootNode ? 1 : depth <= ONE_PLY ? MAX_MOVES : MultiPV));
givesCheck = pos.move_gives_check(move, ci);
captureOrPromotion = pos.move_is_capture_or_promotion(move);
}
ss->currentMove = move;
+ if (!SpNode && !captureOrPromotion)
+ movesSearched[playedMoveCount++] = move;
// Step 14. Make the move
pos.do_move(move, st, ci, givesCheck);
- if (!SpNode && !captureOrPromotion)
- movesSearched[playedMoveCount++] = move;
-
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (isPvMove)
// Step 15. Reduced depth search
// If the move fails high will be re-searched at full depth.
bool doFullDepthSearch = true;
- alpha = SpNode ? sp->alpha : alpha;
if ( depth > 3 * ONE_PLY
&& !captureOrPromotion
&& !dangerous
&& !move_is_castle(move)
&& ss->killers[0] != move
- && ss->killers[1] != move)
+ && ss->killers[1] != move
+ && (ss->reduction = reduction<PvNode>(depth, moveCount)) != DEPTH_ZERO)
{
- ss->reduction = reduction<PvNode>(depth, moveCount);
- if (ss->reduction)
- {
- Depth d = newDepth - ss->reduction;
- value = d < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
- : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
- doFullDepthSearch = (value > alpha);
- }
- ss->reduction = DEPTH_ZERO; // Restore original reduction
+ Depth d = newDepth - ss->reduction;
+ alpha = SpNode ? sp->alpha : alpha;
+
+ value = d < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
+ : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
+
+ ss->reduction = DEPTH_ZERO;
+ doFullDepthSearch = (value > alpha);
}
// Step 16. Full depth search
alpha = sp->alpha;
}
- if (value > bestValue && !(SpNode && thread.cutoff_occurred()))
+ if (value > bestValue)
{
bestValue = value;
+ ss->bestMove = move;
- if (SpNode)
- sp->bestValue = value;
+ if ( !RootNode
+ && PvNode
+ && value > alpha
+ && value < beta) // We want always alpha < beta
+ alpha = value;
- if (!RootNode && value > alpha)
+ if (SpNode && !thread.cutoff_occurred())
{
- if (PvNode && value < beta) // We want always alpha < beta
- {
- alpha = value;
-
- if (SpNode)
- sp->alpha = value;
- }
- else if (SpNode)
- sp->is_betaCutoff = true;
-
- ss->bestMove = move;
-
- if (SpNode)
- sp->ss->bestMove = move;
+ sp->bestValue = value;
+ sp->ss->bestMove = move;
+ sp->alpha = alpha;
+ sp->is_betaCutoff = (value >= beta);
}
}
if (isPvMove || value > alpha)
{
// Update PV
- ss->bestMove = move;
mp.current().pv_score = value;
mp.current().extract_pv_from_tt(pos);
newAtt = pos.attacks_from(pc, to, occ);
// Rule 1. Checks which give opponent's king at most one escape square are dangerous
- b = kingAtt & ~pos.pieces_of_color(them) & ~newAtt & ~(1ULL << to);
+ b = kingAtt & ~pos.pieces(them) & ~newAtt & ~(1ULL << to);
if (!(b && (b & (b - 1))))
return true;
return true;
// Rule 3. Creating new double threats with checks
- b = pos.pieces_of_color(them) & newAtt & ~oldAtt & ~(1ULL << ksq);
+ b = pos.pieces(them) & newAtt & ~oldAtt & ~(1ULL << ksq);
while (b)
{
void RootMoveList::init(Position& pos, Move searchMoves[]) {
- MoveStack mlist[MAX_MOVES];
Move* sm;
-
- clear();
bestMoveChanges = 0;
+ clear();
// Generate all legal moves and add them to RootMoveList
- MoveStack* last = generate<MV_LEGAL>(pos, mlist);
- for (MoveStack* cur = mlist; cur != last; cur++)
+ for (MoveList<MV_LEGAL> ml(pos); !ml.end(); ++ml)
{
- // If we have a searchMoves[] list then verify cur->move
+ // If we have a searchMoves[] list then verify the move
// is in the list before to add it.
- for (sm = searchMoves; *sm && *sm != cur->move; sm++) {}
+ for (sm = searchMoves; *sm && *sm != ml.move(); sm++) {}
- if (searchMoves[0] && *sm != cur->move)
+ if (sm != searchMoves && *sm != ml.move())
continue;
RootMove rm;
- rm.pv[0] = cur->move;
+ rm.pv[0] = ml.move();
rm.pv[1] = MOVE_NONE;
rm.pv_score = -VALUE_INFINITE;
push_back(rm);