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