00001
00002
00003 #include "osl/search/searchRecorder.h"
00004 #include "osl/search/realizationProbability.h"
00005 #include "osl/eval/evalTraits.h"
00006 #include "osl/state/simpleState.h"
00007 #include "osl/moveLogProb.h"
00008 #include "osl/record/csa.h"
00009 #include <fstream>
00010 #include <iostream>
00011 #include <cassert>
00012 #ifndef _MSC_VER
00013 # include <unistd.h>
00014 #endif
00015
00016 #ifndef MINIMAL
00017 const char *checkmateFileName = "currentCheck.csa";
00018 #endif
00019
00021 #define SELECT_CHECKMATE_LOG
00022
00024
00025
00026
00027
00028 osl::search::CountRecorder::CountRecorder()
00029 : node_count(0), quiescence_count(0), checkmate_count(0)
00030 {
00031 }
00032
00033 osl::search::CountRecorder::~CountRecorder()
00034 {
00035 }
00036
00037 void osl::search::
00038 CountRecorder::recordInvalidMoveInTable(const SimpleState& state,
00039 const MoveLogProb& move, int limit) const
00040 {
00041 std::cerr << "?? invalid move in table " << move.move() << " " << move.logProb()
00042 << " limit " << limit << "\n"
00043 << state;
00044 }
00045
00046 void osl::search::CountRecorder::resetNodeCount()
00047 {
00048 node_count = quiescence_count = checkmate_count = 0;
00049 }
00050
00051 void osl::search::
00052 CountRecorder::finishSearch(Move , double sec, bool verbose) const
00053 {
00054 if (! verbose)
00055 return;
00056 reportCount(std::cerr, sec);
00057 }
00058
00059 void osl::search::
00060 CountRecorder::reportCount(std::ostream& os) const
00061 {
00062 os << "#normal : " << nodeCount() << ", ";
00063 os << "#quiescence: " << quiescenceCount() << ", ";
00064 os << "#checkmate : " << checkmateCount() << "\n";
00065 }
00066
00067 void osl::search::
00068 CountRecorder::reportCount(std::ostream& os, double seconds) const
00069 {
00070 const double total = nodeCount() + quiescenceCount() + checkmateCount();
00071 os << "#total : " << total
00072 << " in " << seconds << " sec., " << total/seconds << " nodes/sec."
00073 << " (quiesce " << 100.0*quiescenceCount()/total << "%,"
00074 << " checkmate " << 100.0*checkmateCount()/total << "%)\n";
00075 }
00076
00077
00078
00079 #ifndef MINIMAL
00080 static bool showAllValues = false;
00081 struct osl::search::SearchRecorder::Recorder
00082 {
00083 std::ofstream os;
00085 int current_depth;
00087 int initial_limit;
00088 int log_margin;
00089
00090 Recorder(const char *filename)
00091 : os(filename),
00092 current_depth(0), initial_limit(0),
00093 log_margin(RealizationProbability::TableMove)
00094 {
00095 }
00096 std::ostream& stream()
00097 {
00098 assert(os);
00099 #if 0
00100 os << current_depth << ':';
00101 #endif
00102 for (int i=0; i<=current_depth; ++i)
00103 os << '*';
00104 os << ' ';
00105 return os;
00106 }
00108 bool notSoDeep(int limit) const
00109 {
00110 return
00111 #ifdef SELECT_CHECKMATE_LOG
00112 (limit <= initial_limit)
00113 &&
00114 #endif
00115 (initial_limit - limit) <= log_margin;
00116 }
00117 void flush()
00118 {
00119 #if 1
00120 os << std::flush;
00121 #endif
00122 }
00123 };
00124
00125 osl::search::
00126 SearchRecorder::SearchRecorder(const char *filename)
00127 : recorder(new Recorder(filename))
00128 {
00129 }
00130
00131 osl::search::
00132 SearchRecorder::~SearchRecorder()
00133 {
00134 }
00135
00136 void osl::search::
00137 SearchRecorder::setLogMargin(int margin)
00138 {
00139 recorder->log_margin = margin;
00140 }
00141
00142 void osl::search::
00143 SearchRecorder::tryMove(const MoveLogProb& m, int last_f, int limit) const
00144 {
00145 ++recorder->current_depth;
00146 if (recorder->notSoDeep(limit-100))
00147 {
00148 std::ostream& os = stream();
00149 os << "==> ";
00150 csaShow(os, m.move());
00151 os << " " << m.logProb() << "\t"
00152 << "last_f: " << last_f << " limit: " << limit << "\n";
00153 recorder->flush();
00154 }
00155 }
00156
00157 void osl::search::
00158 SearchRecorder::retryMove(const MoveLogProb& m, int last_f, int limit,
00159 int retryCount) const
00160 {
00161 ++recorder->current_depth;
00162 if (recorder->notSoDeep(limit))
00163 {
00164 std::ostream& os = stream();
00165 os << "ex" << retryCount << "> ";
00166 csaShow(os, m.move());
00167 os << " " << m.logProb() << "\t"
00168 << "last_f: " << last_f << " limit: " << limit << "\n";
00169 recorder->flush();
00170 }
00171 }
00172
00173 void osl::search::
00174 SearchRecorder::recordValue(const MoveLogProb& m, int val, bool betterMove, int limit) const
00175 {
00176 if (recorder->notSoDeep(limit)
00177 && (showAllValues || betterMove))
00178 {
00179 std::ostream& os = stream();
00180 os << "<== " << val << "\t";
00181 csaShow(os, m.move());
00182 os << "\n";
00183 recorder->flush();
00184 }
00185 CountRecorder::recordValue(m,val,betterMove,limit);
00186 --recorder->current_depth;
00187 }
00188
00189 static const char *lowerChar(osl::Player p)
00190 {
00191 return (p == osl::BLACK) ? "B (lb)>" : "W (lb)<";
00192 }
00193 static const char *higherChar(osl::Player p)
00194 {
00195 return (p == osl::BLACK) ? "B (ub)<" : "W (ub)>";
00196 }
00197
00198 void osl::search::
00199 SearchRecorder::tableHitLowerBound(Player p, int val, int last_f, int limit) const
00200 {
00201 if (recorder->notSoDeep(limit))
00202 {
00203 stream() << "==| table answered " << lowerChar(p) << val
00204 << " for " << p << " last_f " << last_f << "\n";
00205 recorder->flush();
00206 }
00207 }
00208
00209 void osl::search::
00210 SearchRecorder::tableHitUpperBound(Player p, int val, int last_f, int limit) const
00211 {
00212 if (recorder->notSoDeep(limit))
00213 {
00214 stream() << "==| table answered " << higherChar(p) << val
00215 << " for " << p << " last_f " << last_f << "\n";
00216 recorder->flush();
00217 }
00218 }
00219
00220 void osl::search::
00221 SearchRecorder::tableStoreLowerBound(Player p, const MoveLogProb& best_move, int val, int limit) const
00222 {
00223 const Move move = best_move.move();
00224 assert(move.isInvalid() || move.isValidOrPass());
00225
00226 if (recorder->notSoDeep(limit-100))
00227 {
00228 std::ostream& os = stream();
00229 os << "|== table store " << lowerChar(p) << val << " ";
00230 csaShow(os, move);
00231 os << " limit " << limit << "\n";
00232 recorder->flush();
00233 }
00234 }
00235
00236 void osl::search::
00237 SearchRecorder::tableStoreUpperBound(Player p, const MoveLogProb& best_move, int val, int limit) const
00238 {
00239 const Move move = best_move.move();
00240 assert(move.isInvalid() || move.isValidOrPass());
00241 if (recorder->notSoDeep(limit-100))
00242 {
00243 std::ostream& os = stream();
00244 os << "|== table store " << higherChar(p) << val << " ";
00245 csaShow(os, move);
00246 os << " limit " << limit << "\n";
00247 recorder->flush();
00248 }
00249 }
00250
00251 void osl::search::
00252 SearchRecorder::recordTopLevelLowFail(const MoveLogProb& , int last_f) const
00253 {
00254 stream() << "low fail, last_f=" << last_f << "\n";
00255 reportCount(stream());
00256 }
00257 void osl::search::
00258 SearchRecorder::recordTopLevelHighFail(const MoveLogProb& best_move, int last_f) const
00259 {
00260 stream() << "high fail, last_f=" << last_f << " " << best_move << "\n";
00261 reportCount(stream());
00262 }
00263
00264 void osl::search::
00265 SearchRecorder::startSearch(int limit) const
00266 {
00267 stream() << "\nnew search: limit " << limit
00268 << ", log " << recorder->log_margin << "\n";
00269 recorder->initial_limit = limit;
00270 CountRecorder::startSearch(limit);
00271 }
00272 void osl::search::
00273 SearchRecorder::finishSearch(Move best_move, double sec, bool verbose) const
00274 {
00275 stream() << "search finished\t" << best_move << "\n";
00276 CountRecorder::finishSearch(best_move, sec, verbose);
00277 }
00278
00279 void osl::search::
00280 SearchRecorder::gotoCheckmateSearch(const SimpleState&
00281 #ifdef CHECKMATE_SEARCHER_DEBUG
00282 state
00283 #endif
00284 , int
00285 #ifdef CHECKMATE_SEARCHER_DEBUG
00286 nodeLimit
00287 #endif
00288 ) const
00289 {
00290 #ifdef CHECKMATE_SEARCHER_DEBUG
00291 std::ofstream os(checkmateFileName, std::ios::app);
00292 os << state;
00293 os << nodeLimit << "\n";
00294 #endif
00295 }
00296
00297 void osl::search::
00298 SearchRecorder::backFromCheckmateSearch() const
00299 {
00300 #ifdef CHECKMATE_SEARCHER_DEBUG
00301 std::ofstream os(checkmateFileName, std::ios::app);
00302 os << "done\n";
00303 #endif
00304 }
00305
00306 std::ostream& osl::search::
00307 SearchRecorder::stream() const
00308 {
00309 return recorder->stream();
00310 }
00311 #endif
00312
00313
00314
00315
00316
00317