- int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, TimeAdvantage;
+ int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime;
Depth depth, int ply, int threadID);
void sp_search(SplitPoint *sp, int threadID);
void sp_search_pv(SplitPoint *sp, int threadID);
Depth depth, int ply, int threadID);
void sp_search(SplitPoint *sp, int threadID);
void sp_search_pv(SplitPoint *sp, int threadID);
void init_search_stack(SearchStack ss[]);
void init_node(const Position &pos, SearchStack ss[], int ply, int threadID);
void update_pv(SearchStack ss[], int ply);
void sp_update_pv(SearchStack *pss, SearchStack ss[], int ply);
bool connected_moves(const Position &pos, Move m1, Move m2);
bool move_is_killer(Move m, const SearchStack& ss);
void init_search_stack(SearchStack ss[]);
void init_node(const Position &pos, SearchStack ss[], int ply, int threadID);
void update_pv(SearchStack ss[], int ply);
void sp_update_pv(SearchStack *pss, SearchStack ss[], int ply);
bool connected_moves(const Position &pos, Move m1, Move m2);
bool move_is_killer(Move m, const SearchStack& ss);
- Depth extension(const Position &pos, Move m, bool pvNode, bool check, bool singleReply, bool mateThreat);
+ Depth extension(const Position &pos, Move m, bool pvNode, bool check, bool singleReply, bool mateThreat, bool* dangerous);
bool ok_to_do_nullmove(const Position &pos);
bool ok_to_prune(const Position &pos, Move m, Move threat, Depth d);
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
bool ok_to_history(const Position &pos, Move m);
void update_history(const Position& pos, Move m, Depth depth, Move movesSearched[], int moveCount);
bool ok_to_do_nullmove(const Position &pos);
bool ok_to_prune(const Position &pos, Move m, Move threat, Depth d);
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
bool ok_to_history(const Position &pos, Move m);
void update_history(const Position& pos, Move m, Depth depth, Move movesSearched[], int moveCount);
{
MaxSearchTime = myTime / 30 + myIncrement;
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
} else { // Blitz game without increment
{
MaxSearchTime = myTime / 30 + myIncrement;
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
} else { // Blitz game without increment
ExtraSearchTime = BestMoveChangesByIteration[Iteration] * (MaxSearchTime / 2)
+ BestMoveChangesByIteration[Iteration-1] * (MaxSearchTime / 3);
ExtraSearchTime = BestMoveChangesByIteration[Iteration] * (MaxSearchTime / 2)
+ BestMoveChangesByIteration[Iteration-1] * (MaxSearchTime / 3);
// Try to guess if the current iteration is the last one or the last two
LastIterations = (current_search_time() > ((MaxSearchTime + ExtraSearchTime)*58) / 128);
// Try to guess if the current iteration is the last one or the last two
LastIterations = (current_search_time() > ((MaxSearchTime + ExtraSearchTime)*58) / 128);
- ext = extension(pos, move, true, pos.move_is_check(move), false, false);
+ bool dangerous;
+ ext = extension(pos, move, true, pos.move_is_check(move), false, false, &dangerous);
newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
// Make the move, and search it
newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
// Make the move, and search it
else
{
value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
else
{
value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
Value value, bestValue = -VALUE_INFINITE;
Bitboard dcCandidates = mp.discovered_check_candidates();
bool isCheck = pos.is_check();
Value value, bestValue = -VALUE_INFINITE;
Bitboard dcCandidates = mp.discovered_check_candidates();
bool isCheck = pos.is_check();
bool singleReply = (isCheck && mp.number_of_moves() == 1);
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
bool singleReply = (isCheck && mp.number_of_moves() == 1);
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
- Depth ext = extension(pos, move, true, moveIsCheck, singleReply, mateThreat);
+ bool dangerous;
+ Depth ext = extension(pos, move, true, moveIsCheck, singleReply, mateThreat, &dangerous);
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
if ( depth >= 2*OnePly
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
if ( depth >= 2*OnePly
if (ok_to_history(pos, m)) // Only non capture moves are considered
{
update_history(pos, m, depth, movesSearched, moveCount);
if (ok_to_history(pos, m)) // Only non capture moves are considered
{
update_history(pos, m, depth, movesSearched, moveCount);
- if (m != ss[ply].killers[0])
- {
- ss[ply].killers[1] = ss[ply].killers[0];
- ss[ply].killers[0] = m;
- }
+ update_killers(m, ss[ply]);
}
TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
}
}
TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
}
bool singleReply = (isCheck && mp.number_of_moves() == 1);
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
bool singleReply = (isCheck && mp.number_of_moves() == 1);
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
- Depth ext = extension(pos, move, false, moveIsCheck, singleReply, mateThreat);
+ bool dangerous;
+ Depth ext = extension(pos, move, false, moveIsCheck, singleReply, mateThreat, &dangerous);
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
if (ok_to_history(pos, m)) // Only non capture moves are considered
{
update_history(pos, m, depth, movesSearched, moveCount);
if (ok_to_history(pos, m)) // Only non capture moves are considered
{
update_history(pos, m, depth, movesSearched, moveCount);
- if (m != ss[ply].killers[0])
- {
- ss[ply].killers[1] = ss[ply].killers[0];
- ss[ply].killers[0] = m;
- }
+ update_killers(m, ss[ply]);
}
TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
}
}
TT.store(pos, value_to_tt(bestValue, ply), depth, m, VALUE_TYPE_LOWER);
}
{
Value futilityValue = staticValue
+ Max(pos.midgame_value_of_piece_on(move_to(move)),
{
Value futilityValue = staticValue
+ Max(pos.midgame_value_of_piece_on(move_to(move)),
if (alpha >= beta && ok_to_history(pos, m)) // Only non capture moves are considered
{
// Wrong to update history when depth is <= 0
if (alpha >= beta && ok_to_history(pos, m)) // Only non capture moves are considered
{
// Wrong to update history when depth is <= 0
-
- if (m != ss[ply].killers[0])
- {
- ss[ply].killers[1] = ss[ply].killers[0];
- ss[ply].killers[0] = m;
- }
+ update_killers(m, ss[ply]);
bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
- Depth ext = extension(pos, move, false, moveIsCheck, false, false);
+ bool dangerous;
+ Depth ext = extension(pos, move, false, moveIsCheck, false, false, &dangerous);
&& !move_promotion(move)
&& moveCount >= 2 + int(sp->depth)
&& ok_to_prune(pos, move, ss[sp->ply].threatMove, sp->depth))
&& !move_promotion(move)
&& moveCount >= 2 + int(sp->depth)
&& ok_to_prune(pos, move, ss[sp->ply].threatMove, sp->depth))
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
{
bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
{
bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
bool moveIsCapture = pos.move_is_capture(move);
- Depth ext = extension(pos, move, true, moveIsCheck, false, false);
+ bool dangerous;
+ Depth ext = extension(pos, move, true, moveIsCheck, false, false, &dangerous);
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
// Try to reduce non-pv search depth by one ply if move seems not problematic,
// if the move fails high will be re-searched at full depth.
ss[ply].pv[ply] = ss[ply].pv[ply+1] = ss[ply].currentMove = MOVE_NONE;
ss[ply+2].mateKiller = MOVE_NONE;
ss[ply].pv[ply] = ss[ply].pv[ply+1] = ss[ply].currentMove = MOVE_NONE;
ss[ply+2].mateKiller = MOVE_NONE;
ss[ply].threatMove = MOVE_NONE;
ss[ply].reduction = Depth(0);
ss[ply].currentMoveCaptureValue = Value(0);
ss[ply].threatMove = MOVE_NONE;
ss[ply].reduction = Depth(0);
ss[ply].currentMoveCaptureValue = Value(0);
if(Threads[threadID].printCurrentLine)
print_current_line(ss, ply, threadID);
if(Threads[threadID].printCurrentLine)
print_current_line(ss, ply, threadID);
// killer moves of that ply.
bool move_is_killer(Move m, const SearchStack& ss) {
// killer moves of that ply.
bool move_is_killer(Move m, const SearchStack& ss) {
const Move* k = ss.killers;
for (int i = 0; i < KILLER_MAX; i++, k++)
if (*k == m)
const Move* k = ss.killers;
for (int i = 0; i < KILLER_MAX; i++, k++)
if (*k == m)
// extension() decides whether a move should be searched with normal depth,
// or with extended depth. Certain classes of moves (checking moves, in
// extension() decides whether a move should be searched with normal depth,
// or with extended depth. Certain classes of moves (checking moves, in
- // particular) are searched with bigger depth than ordinary moves.
+ // particular) are searched with bigger depth than ordinary moves and in
+ // any case are marked as 'dangerous'. Note that also if a move is not
+ // extended, as example because the corresponding UCI option is set to zero,
+ // the move is marked as 'dangerous' so, at least, we avoid to prune it.
- Depth extension(const Position &pos, Move m, bool pvNode,
- bool check, bool singleReply, bool mateThreat) {
+ Depth extension(const Position &pos, Move m, bool pvNode, bool check,
+ bool singleReply, bool mateThreat, bool* dangerous) {
if ( pos.midgame_value_of_piece_on(move_to(m)) >= RookValueMidgame
&& ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)
- pos.midgame_value_of_piece_on(move_to(m)) == Value(0))
&& !move_promotion(m))
if ( pos.midgame_value_of_piece_on(move_to(m)) >= RookValueMidgame
&& ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)
- pos.midgame_value_of_piece_on(move_to(m)) == Value(0))
&& !move_promotion(m))
+
+ // update_killers() add a good move that produced a beta-cutoff
+ // among the killer moves of that ply.
+
+ void update_killers(Move m, SearchStack& ss) {
+
+ if (m == ss.killers[0])
+ return;
+
+ for (int i = KILLER_MAX - 1; i > 0; i--)
+ ss.killers[i] = ss.killers[i - 1];
+
+ ss.killers[0] = m;
+ }
+
// fail_high_ply_1() checks if some thread is currently resolving a fail
// high at ply 1 at the node below the first root node. This information
// is used for time managment.
// fail_high_ply_1() checks if some thread is currently resolving a fail
// high at ply 1 at the node below the first root node. This information
// is used for time managment.