/*
- Glaurung, a UCI chess playing engine.
- Copyright (C) 2004-2008 Tord Romstad
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008 Marco Costalba
- Glaurung is free software: you can redistribute it and/or modify
+ Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
- Glaurung is distributed in the hope that it will be useful,
+ Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Depth RazorDepth = 4*OnePly;
Value RazorMargin = Value(0x300);
+ // Last seconds noise filtering (LSN)
+ bool UseLSNFiltering = false;
+ bool looseOnTime = false;
+ int LSNTime = 4 * 1000; // In milliseconds
+ Value LSNValue = Value(0x200);
+
// Extensions. Array index 0 is used at non-PV nodes, index 1 at PV nodes.
Depth CheckExtension[2] = {OnePly, OnePly};
Depth SingleReplyExtension[2] = {OnePly / 2, OnePly / 2};
/// Functions
- void id_loop(const Position &pos, Move searchMoves[]);
+ Value id_loop(const Position &pos, Move searchMoves[]);
Value root_search(Position &pos, SearchStack ss[], RootMoveList &rml);
Value search_pv(Position &pos, SearchStack ss[], Value alpha, Value beta,
Depth depth, int ply, int threadID);
//// Functions
////
-/// think() is the external interface to Glaurung's search, and is called when
+/// think() is the external interface to Stockfish's search, and is called when
/// the program receives the UCI 'go' command. It initializes various
/// search-related global variables, and calls root_search()
RazorDepth = (get_option_value_int("Maximum Razoring Depth") + 1) * OnePly;
RazorMargin = value_from_centipawns(get_option_value_int("Razoring Margin"));
+ UseLSNFiltering = get_option_value_bool("LSN filtering");
+ LSNTime = get_option_value_int("LSN Time Margin (sec)") * 1000;
+ LSNValue = value_from_centipawns(get_option_value_int("LSN Value Margin"));
+
MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * OnePly;
MaxThreadsPerSplitPoint =
get_option_value_int("Maximum Number of Threads per Split Point");
// We're ready to start thinking. Call the iterative deepening loop
// function:
- id_loop(pos, searchMoves);
+ if (!looseOnTime)
+ {
+ Value v = id_loop(pos, searchMoves);
+ looseOnTime = ( UseLSNFiltering
+ && myTime < LSNTime
+ && myIncrement == 0
+ && v < -LSNValue);
+ }
+ else
+ {
+ looseOnTime = false; // reset for next match
+ while (SearchStartTime + myTime + 1000 > get_system_time())
+ ; // wait here
+ id_loop(pos, searchMoves); // to fail gracefully
+ }
if(UseLogFile)
LogFile.close();
// been consumed, the user stops the search, or the maximum search depth is
// reached.
- void id_loop(const Position &pos, Move searchMoves[]) {
+ Value id_loop(const Position &pos, Move searchMoves[]) {
Position p(pos);
SearchStack ss[PLY_MAX_PLUS_2];
// Stop search if most of MaxSearchTime is consumed at the end of the
// iteration. We probably don't have enough time to search the first
// move at the next iteration anyway.
- if(current_search_time() > ((MaxSearchTime + ExtraSearchTime)*80) / 128)
+ if(current_search_time() > ((MaxSearchTime + ExtraSearchTime)*90) / 128)
stopSearch = true;
if(stopSearch) {
LogFile << "Ponder move: " << move_to_san(p, ss[0].pv[1]) << '\n';
LogFile << std::endl;
}
+ return rml.get_move_score(0);
}
}
}
// Null move search not allowed, try razoring
- else if (depth < RazorDepth && approximateEval < beta - RazorMargin)
+ else if ( (approximateEval < beta - RazorMargin && depth < RazorDepth)
+ ||(approximateEval < beta - PawnValueMidgame && depth <= OnePly))
{
Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
if (v < beta)
Value value, bestValue = -VALUE_INFINITE;
Bitboard dcCandidates = mp.discovered_check_candidates();
Value futilityValue = VALUE_NONE;
- MovePicker::MovegenPhase moveType;
bool isCheck = pos.is_check();
bool useFutilityPruning = UseFutilityPruning
&& depth < SelectiveDepth
// Loop through all legal moves until no moves remain or a beta cutoff
// occurs.
while ( bestValue < beta
- && (move = mp.get_next_move(&moveType)) != MOVE_NONE
+ && (move = mp.get_next_move()) != MOVE_NONE
&& !thread_should_stop(threadID))
{
assert(move_is_ok(move));
bool singleReply = (isCheck && mp.number_of_moves() == 1);
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
- bool moveIsGoodCapture = (moveType == MovePicker::PH_GOOD_CAPTURES);
+ bool moveIsCapture = pos.move_is_capture(move);
bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
movesSearched[moveCount++] = ss[ply].currentMove = move;
// Futility pruning
if ( useFutilityPruning
&& ext == Depth(0)
- && !moveIsGoodCapture
+ && !moveIsCapture
&& !moveIsPassedPawnPush
&& !move_promotion(move))
{
if ( depth >= 2*OnePly
&& ext == Depth(0)
&& moveCount >= LMRNonPVMoves
- && !moveIsGoodCapture
+ && !moveIsCapture
&& !move_promotion(move)
&& !moveIsPassedPawnPush
&& !move_is_castle(move)
Depth extension(const Position &pos, Move m, bool pvNode,
bool check, bool singleReply, bool mateThreat) {
+
Depth result = Depth(0);
- if(check)
- result += CheckExtension[pvNode];
- if(singleReply)
- result += SingleReplyExtension[pvNode];
- if(pos.move_is_pawn_push_to_7th(m))
- result += PawnPushTo7thExtension[pvNode];
- if(pos.move_is_passed_pawn_push(m))
- result += PassedPawnExtension[pvNode];
- if(mateThreat)
- result += MateThreatExtension[pvNode];
- 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))
- result += PawnEndgameExtension[pvNode];
- if(pvNode && pos.move_is_capture(m)
- && pos.type_of_piece_on(move_to(m)) != PAWN && pos.see(m) >= 0)
- result += OnePly/2;
+ if (check)
+ result += CheckExtension[pvNode];
+
+ if (singleReply)
+ result += SingleReplyExtension[pvNode];
+
+ if (pos.move_is_pawn_push_to_7th(m))
+ result += PawnPushTo7thExtension[pvNode];
+
+ if (pos.move_is_passed_pawn_push(m))
+ result += PassedPawnExtension[pvNode];
+
+ if (mateThreat)
+ result += MateThreatExtension[pvNode];
+
+ if ( pos.midgame_value_of_piece_on(move_to(m)) >= RookValueMidgame\r
+ && ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)\r
+ - pos.midgame_value_of_piece_on(move_to(m)) == Value(0))\r
+ && !move_promotion(m))
+ result += PawnEndgameExtension[pvNode];
+
+ if ( pvNode
+ && pos.move_is_capture(m)
+ && pos.type_of_piece_on(move_to(m)) != PAWN
+ && pos.see(m) >= 0)
+ result += OnePly/2;
return Min(result, OnePly);
}
assert(threat == MOVE_NONE || move_is_ok(threat));
assert(!move_promotion(m));
assert(!pos.move_is_check(m));
+ assert(!pos.move_is_capture(m));
assert(!pos.move_is_passed_pawn_push(m));
assert(d >= OnePly);
{
lastInfoTime = t;
lock_grab(&IOLock);
+ if (dbg_show_mean)
+ dbg_print_mean();
+
+ if (dbg_show_hit_rate)
+ dbg_print_hit_rate();
+
std::cout << "info nodes " << nodes_searched() << " nps " << nps()
<< " time " << t << " hashfull " << TT.full() << std::endl;
lock_release(&IOLock);
bool overTime = t > AbsoluteMaxSearchTime
|| (RootMoveNumber == 1 && t > MaxSearchTime + ExtraSearchTime)
|| ( !FailHigh && !fail_high_ply_1() && !Problem
- && t > 6*(MaxSearchTime + ExtraSearchTime));
+ && t > 10*(MaxSearchTime + ExtraSearchTime));
if ( (Iteration >= 2 && (!InfiniteSearch && overTime))
|| (ExactMaxTime && t >= ExactMaxTime)