Go to the documentation of this file.00001
00002
00003 #ifndef GAMEPLAYING_SEARCHPLAYER_TCC
00004 #define GAMEPLAYING_SEARCHPLAYER_TCC
00005 #include "osl/game_playing/searchPlayer.h"
00006 #include "osl/game_playing/gameState.h"
00007 #include "osl/game_playing/pvHistory.h"
00008 #include "osl/search/searchState2.h"
00009 #include "osl/eval/evalTraits.h"
00010 #include "osl/container/moveStack.h"
00011
00012 #ifdef USE_NTESUKI
00013 # include "osl/ntesuki/ntesukiSearcher.h"
00014 # include "osl/ntesuki/ntesukiMoveGenerator.h"
00015 #endif
00016
00017 #include <boost/scoped_ptr.hpp>
00018 #include <boost/foreach.hpp>
00019
00020 #ifdef USE_NTESUKI
00021 struct
00022 osl::game_playing::SearchPlayer::NtesukiThread
00023 {
00024 explicit NtesukiThread(Move& next_move,
00025 volatile bool *thread_finished,
00026 volatile bool *stop_flag,
00027 NumEffectState state);
00028
00029 void operator()();
00030
00031 Move& next_move;
00032 volatile bool *thread_finished;
00033 volatile bool *stop_flag;
00034 NumEffectState state;
00035 };
00036 #endif
00037
00038 template <class Searcher>
00039 osl::game_playing::ComputerPlayer* osl::game_playing::
00040 SearchPlayer::cloneIt(const Searcher& copy) const
00041 {
00042 return new Searcher(copy);
00043 }
00044
00045 template <class Searcher>
00046 int osl::game_playing::
00047 SearchPlayer::pawnValue()
00048 {
00049 typedef typename Searcher::eval_t eval_t;
00050 return abs(eval_t::captureValue(newPtypeO(BLACK,PAWN)))/2;
00051 }
00052 template <class Searcher>
00053 int osl::game_playing::
00054 SearchPlayer::pawnValueOfTurn(Player turn)
00055 {
00056 return pawnValue<Searcher>() * eval::delta(turn);
00057 }
00058
00059 template <class Searcher>
00060 const osl::search::MoveWithComment osl::game_playing::
00061 SearchPlayer::search(const GameState& state, const search::TimeAssigned& msec)
00062 {
00063 Searcher& searcher = dynamic_cast<Searcher&>(*this->searcher);
00064 searcher.setRootIgnoreMoves(root_ignore_moves, prediction_for_speculative_search);
00065
00066 typedef typename Searcher::eval_t eval_t;
00067 if (! eval_t::initialized())
00068 throw std::runtime_error("evaluation function not initialized");
00069
00070 const MoveStack& history = state.moveHistory();
00071
00072 #ifdef USE_NTESUKI
00073 volatile bool ntesuki_thread_finished;
00074 volatile bool stop_ntesuki;
00075 Move ntesuki_next_move = Move::INVALID();
00076
00077 NtesukiThread thread(ntesuki_next_move, &ntesuki_thread_finished,
00078 &stop_ntesuki, state.state());
00079 boost::thread ntesuki_thread(thread);
00080 #endif
00081 searcher.setHistory(history);
00082 searcher.enableMultiPV(config.multi_pv_width);
00083 BOOST_FOREACH(const boost::shared_ptr<search::SearchMonitor>& m,
00084 config.monitors)
00085 searcher.addMonitor(m);
00086 int deepening_step_for_this_move = config.deepening_step;
00087 if (! msec.standard.isInfinity())
00088 {
00089 if (msec.standard.toSeconds() < 10.0)
00090 deepening_step_for_this_move = std::min(100, config.deepening_step);
00091 }
00092 searcher.setNextIterationCoefficient(config.next_iteration_coefficient);
00093 searcher.setNodeCountHardLimit(config.node_count_hard_limit);
00094
00095 MoveWithComment best_move;
00096 best_move.root = HashKey(state.state());
00097 if (plan_stop)
00098 return best_move;
00099
00100 searching = true;
00101 best_move.move
00102 = searcher.computeBestMoveIteratively(config.limit,
00103 deepening_step_for_this_move,
00104 config.initial_limit,
00105 config.node_limit,
00106 msec,
00107 &best_move);
00108 searching = false;
00109 #ifdef USE_NTESUKI
00110 if (ntesuki_thread_finished)
00111 {
00112 if (ntesuki_next_move.isNormal())
00113 {
00114 return ntesuki_next_move;
00115 }
00116 else
00117 {
00118
00119 }
00120 }
00121 else
00122 {
00123
00124 stop_ntesuki = true;
00125 ntesuki_thread.join();
00126 }
00127 #endif
00128 saveSearchResult(state, best_move);
00129 static const int resign_value = OslConfig::resignThreshold();
00130 if (! state.state().inCheck() && best_move.move.isNormal()
00131 && best_move.value*playerToMul(state.state().turn()) < -resign_value)
00132 {
00133 ++almost_resign_count;
00134 if (almost_resign_count >= 3)
00135 best_move.move = Move();
00136 }
00137 else
00138 {
00139 almost_resign_count = 0;
00140 }
00141 return best_move;
00142 }
00143
00144 template <class Searcher>
00145 bool osl::game_playing::
00146 SearchPlayer::isReasonableMoveBySearch(Searcher& searcher, Move move, int pawn_sacrifice)
00147 {
00148 return searcher.isReasonableMove(move, pawn_sacrifice);
00149 }
00150
00151 #endif
00152
00153
00154
00155