18 #include <boost/foreach.hpp>
19 #include <boost/thread.hpp>
20 #include <boost/thread/xtime.hpp>
43 data.push_back(std::make_pair(prediction, result));
49 BOOST_FOREACH(
const vector_t::value_type& v, data) {
50 if (v.first == prediction)
62 show(std::ostream& os)
const
65 for (
size_t i=0; i<data.size(); ++i) {
82 : status(*s), mutex(*m), condition(c), in(i),
out(o)
84 boost::mutex::scoped_lock lk(mutex);
86 condition->notify_all();
89 : status(*s), mutex(*m), condition(0), in(i),
out(*s)
91 boost::mutex::scoped_lock lk(mutex);
98 condition->notify_all();
112 : state(s), player(p), status(parent.status), mutex(parent.mutex), index(-1), seconds(sec),
123 player.setRootIgnoreMoves(&tried_moves,
true);
124 player.setVerbose(0);
125 const int sec =
std::max(1, has_byoyomi ? seconds/10 : seconds/7);
126 result = player.selectBestMove(state, 0, 0, sec);
127 player.setRootIgnoreMoves(0,
false);
128 player.setVerbose(1);
131 if (result.move.isNormal()) {
132 std::cerr <<
"search prediction ";
139 catch (std::exception& e)
141 std::cerr <<
"Generator::bestMove " << e.what() <<
"\n";
147 const Move move = pickUpMove();
149 std::cerr <<
"finish\n";
152 tried_moves.push_back(move);
159 : results(r), next_iteration_coefficient(1.0),
160 current_move(
Move::INVALID()), status(INITIAL), seconds(-1),
175 NonBlockDelete::reset(player);
179 player.reset(dynamic_cast<SearchPlayer*>(main_player.
clone()));
180 player->setVerbose(1);
181 player->setNextIterationCoefficient(
std::max(1.0, next_iteration_coefficient/2));
182 state = main_state.
clone();
183 generator.reset(
new Generator(*state, *player, *
this, standard_seconds, has_byoyomi));
184 seconds = standard_seconds;
186 seconds +=
std::min(30, standard_seconds/2);
188 catch (std::exception& e)
191 std::cerr <<
"setUp " << e.what() <<
"\n";
204 boost::thread::yield();
207 while (NonBlockDelete::deleteOne() && !stop_flag)
214 prediction = generator->nextMove();
220 const MoveWithComment
result = testMove(prediction);
221 results.add(prediction, result);
232 Mutex::scoped_lock lk(
mutex);
233 current_move = predicted_move;
236 state->pushMove(predicted_move);
238 player->pushMove(predicted_move);
240 std::cerr <<
"\nprediction (" << seconds <<
") "
242 const time_t now = time(0);
244 std::cerr <<
ctime_r(&now, ctime_buf);
250 const MilliSeconds::Interval msec(seconds*1000);
254 catch (std::exception& e)
257 std::cerr <<
"error in speculative thread " << e.what() <<
"\n";
259 NonBlockDelete::deleteAll();
263 std::cerr <<
"error in speculative thread\n";
269 Mutex::scoped_lock lk(
mutex);
279 if (currentMove() != the_move)
291 player->setNextIterationCoefficient(next_iteration_coefficient);
292 player->setVerbose(2);
301 if (player && status != FINISHED)
303 std::cerr <<
"stopNow " << status <<
"\n";
305 = player->stopSearchNow();
307 std::cerr <<
"stop search failed\n";
314 Mutex::scoped_lock lk(
mutex);
315 while (status == INITIAL)
326 if (player && status != FINISHED)
329 player->setTimeAssign(new_assign);
335 if (player && status != FINISHED)
338 return player->startTime();
340 return MilliSeconds();
346 Mutex::scoped_lock lk(
mutex);
368 parent->searcher->run();
383 selectBestMoveCleanUp();
390 boost::mutex::scoped_lock lk(mutex);
396 search_state = HashKey(state->state());
399 searcher->setUp(*state, main_player, last_search_seconds, has_byoyomi);
400 thread.reset(
new boost::thread(
Runner(
this)));
402 catch (std::exception& e)
404 std::cerr <<
"startSpeculative " << e.what();
412 boost::mutex::scoped_lock lk(mutex);
420 boost::mutex::scoped_lock lk(mutex);
422 searcher->stopOtherThan(the_move);
428 boost::mutex::scoped_lock lk(mutex);
439 boost::mutex::scoped_lock lk(mutex);
440 if (! allowed || ! searcher)
443 last_search_seconds = (int)ceil(wait_for.
standard.toSeconds());
444 has_byoyomi = (byoyomi > 0);
446 const time_t start_time = time(0);
447 const MilliSeconds start_time_msec = MilliSeconds::now();
449 const MoveWithComment *
result = 0;
450 bool stop_now =
false;
451 if (searcher->currentMove() != last_move)
457 const time_t stop_time = start_time +
static_cast<int>(ceil(wait_for.
max.toSeconds()));
459 const MilliSeconds started = searcher->startTime();
460 const bool already_finished = searcher->isFinished();
461 if (! already_finished)
464 std::cerr <<
"wait for (" << wait_for.
standard.toSeconds()
465 <<
"/" << wait_for.
max.toSeconds()
467 <<
ctime_r(&stop_time, ctime_buf);
468 const MilliSeconds::Interval diff = (start_time_msec - started);
470 wait_for.
max = wait_for.
max + diff;
471 searcher->setTimeAssign(wait_for);
477 const bool now_finished = searcher->isFinished();
478 if ((result = results->find(last_move))) {
482 last_move.
player() ==
BLACK ? -result->value : result->value,
483 result->move, &*result->moves.begin(), &*result->moves.end(),
492 if (stop_now && ++wait_count > 60) {
493 std::cerr <<
"error stop now failed for 60 times\n";
499 time_t now = time(0);
500 stop_now = now >= stop_time;
505 boost::mutex::scoped_lock lk(searcher->mutex);
507 #if BOOST_VERSION < 105000
508 boost::xtime_get(&xt, boost::TIME_UTC);
510 boost::xtime_get(&xt, boost::TIME_UTC_);
512 if (wait_count <= 10)
516 searcher->condition.timed_wait(lk, xt);
519 if (! searcher->isFinished())
521 if (result->move.isNormal()) {
536 boost::mutex::scoped_lock lk(mutex);
537 if (searcher && ! searcher->isFinished())
543 NonBlockDelete::reset(searcher);