using std::string;
using std::cout;
using std::endl;
+using Eval::evaluate;
using namespace Search;
namespace {
size_t MultiPV, UCIMultiPV, PVIdx;
TimeManager TimeMgr;
+ Time SearchTime;
int BestMoveChanges;
int SkillLevel;
bool SkillLevelEnabled, Chess960;
bool connected_threat(const Position& pos, Move m, Move threat);
Value refine_eval(const TTEntry* tte, Value defaultEval, int ply);
Move do_skill_level();
- int elapsed_time(bool reset = false);
string score_to_uci(Value v, Value alpha = -VALUE_INFINITE, Value beta = VALUE_INFINITE);
void pv_info_to_log(Position& pos, int depth, Value score, int time, Move pv[]);
void pv_info_to_uci(const Position& pos, int depth, Value alpha, Value beta);
Position& pos = RootPosition;
Chess960 = pos.is_chess960();
- elapsed_time(true);
+ Eval::RootColor = pos.side_to_move();
+ SearchTime.restart();
TimeMgr.init(Limits, pos.startpos_ply_counter());
TT.new_search();
H.clear();
}
}
- // Read UCI options: GUI could change UCI parameters during the game
- read_evaluation_uci_options(pos.side_to_move());
- Threads.read_uci_options();
-
- TT.set_size(Options["Hash"]);
- if (Options["Clear Hash"])
- {
- Options["Clear Hash"] = false;
- TT.clear();
- }
-
UCIMultiPV = Options["MultiPV"];
SkillLevel = Options["Skill Level"];
if (Options["Use Search Log"])
{
- int e = elapsed_time();
+ int e = SearchTime.elapsed();
Log log(Options["Search Log Filename"]);
log << "Nodes: " << pos.nodes_searched()
// Send full PV info to GUI if we are going to leave the loop or
// if we have a fail high/low and we are deep in the search.
- if ((bestValue > alpha && bestValue < beta) || elapsed_time() > 2000)
+ if ((bestValue > alpha && bestValue < beta) || SearchTime.elapsed() > 2000)
pv_info_to_uci(pos, depth, alpha, beta);
// In case of failing high/low increase aspiration window and
skillBest = do_skill_level();
if (!Signals.stop && Options["Use Search Log"])
- pv_info_to_log(pos, depth, bestValue, elapsed_time(), &RootMoves[0].pv[0]);
+ pv_info_to_log(pos, depth, bestValue, SearchTime.elapsed(), &RootMoves[0].pv[0]);
// Filter out startup noise when monitoring best move stability
if (depth > 2 && BestMoveChanges)
// Stop search if most of available time is already consumed. We
// probably don't have enough time to search the first move at the
// next iteration anyway.
- if (elapsed_time() > (TimeMgr.available_time() * 62) / 100)
+ if (SearchTime.elapsed() > (TimeMgr.available_time() * 62) / 100)
stop = true;
// Stop search early if one move seems to be much better than others
if ( depth >= 12
&& !stop
&& ( (bestMoveNeverChanged && pos.captured_piece_type())
- || elapsed_time() > (TimeMgr.available_time() * 40) / 100))
+ || SearchTime.elapsed() > (TimeMgr.available_time() * 40) / 100))
{
Value rBeta = bestValue - EasyMoveMargin;
(ss+1)->excludedMove = RootMoves[0].pv[0];
{
Signals.firstRootMove = (moveCount == 1);
- if (pos.thread() == 0 && elapsed_time() > 2000)
+ if (pos.thread() == 0 && SearchTime.elapsed() > 2000)
cout << "info depth " << depth / ONE_PLY
<< " currmove " << move_to_uci(move, Chess960)
<< " currmovenumber " << moveCount + PVIdx << endl;
kingAtt = pos.attacks_from<KING>(ksq);
pc = pos.piece_moved(move);
- occ = pos.occupied_squares() & ~(1ULL << from) & ~(1ULL << ksq);
+ occ = pos.pieces() ^ from ^ ksq;
oldAtt = pos.attacks_from(pc, from, occ);
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(them) & ~newAtt & ~(1ULL << to);
- if (!(b && (b & (b - 1))))
+ if (single_bit(b)) // Catches also !b
return true;
// Rule 2. Queen contact check is very dangerous
// Case 5: Discovered check, checking piece is the piece moved in m1
ksq = pos.king_square(pos.side_to_move());
- if (piece_is_slider(p1) && (squares_between(t1, ksq) & f2))
- {
- Bitboard occ = pos.occupied_squares();
- occ ^= f2;
- if (pos.attacks_from(p1, t1, occ) & ksq)
- return true;
- }
+ if ( piece_is_slider(p1)
+ && (squares_between(t1, ksq) & f2)
+ && (pos.attacks_from(p1, t1, pos.pieces() ^ f2) & ksq))
+ return true;
+
return false;
}
}
- // current_search_time() returns the number of milliseconds which have passed
- // since the beginning of the current search.
-
- int elapsed_time(bool reset) {
-
- static int searchStartTime;
-
- if (reset)
- searchStartTime = system_time();
-
- return system_time() - searchStartTime;
- }
-
-
// score_to_uci() converts a value to a string suitable for use with the UCI
// protocol specifications:
//
void pv_info_to_uci(const Position& pos, int depth, Value alpha, Value beta) {
- int t = elapsed_time();
+ int t = SearchTime.elapsed();
int selDepth = 0;
for (int i = 0; i < Threads.size(); i++)
static RKISS rk;
// PRNG sequence should be not deterministic
- for (int i = abs(system_time() % 50); i > 0; i--)
+ for (int i = Time::current_time().msec() % 50; i > 0; i--)
rk.rand<unsigned>();
// RootMoves are already sorted by score in descending order
void check_time() {
- static int lastInfoTime;
- int e = elapsed_time();
+ static Time lastInfoTime = Time::current_time();
- if (system_time() - lastInfoTime >= 1000 || !lastInfoTime)
+ if (lastInfoTime.elapsed() >= 1000)
{
- lastInfoTime = system_time();
+ lastInfoTime.restart();
dbg_print();
}
if (Limits.ponder)
return;
+ int e = SearchTime.elapsed();
bool stillAtFirstMove = Signals.firstRootMove
&& !Signals.failedLowAtRoot
&& e > TimeMgr.available_time();