if (moveIsCheck && pos.see_sign(m) >= 0)
result += CheckExtension[PvNode];
- if (pos.type_of_piece_on(move_from(m)) == PAWN)
+ if (piece_type(pos.piece_on(move_from(m))) == PAWN)
{
Color c = pos.side_to_move();
if (relative_rank(c, move_to(m)) == RANK_7)
}
if ( captureOrPromotion
- && pos.type_of_piece_on(move_to(m)) != PAWN
+ && piece_type(pos.piece_on(move_to(m))) != PAWN
&& ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)
- - pos.midgame_value_of_piece_on(move_to(m)) == VALUE_ZERO)
+ - piece_value_midgame(pos.piece_on(move_to(m))) == VALUE_ZERO)
&& !move_is_special(m))
{
result += PawnEndgameExtension[PvNode];
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;
assert(rdepth >= ONE_PLY);
- MovePicker mp(pos, ttMove, H, Position::see_value(pos.captured_piece_type()));
+ MovePicker mp(pos, ttMove, H, pos.captured_piece_type());
CheckInfo ci(pos);
while ((move = mp.get_next_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(move) || move_is_promotion(move);
+ captureOrPromotion = pos.move_is_capture_or_promotion(move);
// Step 12. Decide the new search depth
ext = extension<PvNode>(pos, move, captureOrPromotion, givesCheck, &dangerous);
}
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);
// Update killers and history only for non capture moves that fails high
if ( bestValue >= beta
- && !pos.move_is_capture(move)
- && !move_is_promotion(move))
+ && !pos.move_is_capture_or_promotion(move))
{
if (move != ss->killers[0])
{
&& !pos.move_is_passed_pawn_push(move))
{
futilityValue = futilityBase
- + pos.endgame_value_of_piece_on(move_to(move))
+ + piece_value_endgame(pos.piece_on(move_to(move)))
+ (move_is_ep(move) ? PawnValueEndgame : VALUE_ZERO);
if (futilityValue < alpha)
&& !inCheck
&& givesCheck
&& move != ttMove
- && !pos.move_is_capture(move)
- && !move_is_promotion(move)
+ && !pos.move_is_capture_or_promotion(move)
&& ss->eval + PawnValueMidgame / 4 < beta
&& !check_is_dangerous(pos, move, futilityBase, beta, &bestValue))
{
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;
// Rule 2. Queen contact check is very dangerous
- if ( type_of_piece(pc) == QUEEN
+ if ( piece_type(pc) == QUEEN
&& bit_is_set(kingAtt, to))
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)
{
victimSq = pop_1st_bit(&b);
- futilityValue = futilityBase + pos.endgame_value_of_piece_on(victimSq);
+ futilityValue = futilityBase + piece_value_endgame(pos.piece_on(victimSq));
// Note that here we generate illegal "double move"!
if ( futilityValue >= beta
assert(move_is_ok(m));
assert(threat && move_is_ok(threat));
- assert(!pos.move_is_capture(m) && !move_is_promotion(m));
+ assert(!pos.move_is_capture_or_promotion(m));
assert(!pos.move_is_passed_pawn_push(m));
Square mfrom, mto, tfrom, tto;
// Case 2: If the threatened piece has value less than or equal to the
// value of the threatening piece, don't prune moves which defend it.
if ( pos.move_is_capture(threat)
- && ( pos.midgame_value_of_piece_on(tfrom) >= pos.midgame_value_of_piece_on(tto)
- || pos.type_of_piece_on(tfrom) == KING)
+ && ( piece_value_midgame(pos.piece_on(tfrom)) >= piece_value_midgame(pos.piece_on(tto))
+ || piece_type(pos.piece_on(tfrom)) == KING)
&& pos.move_attacks_square(m, tto))
return true;
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);