00001
00002
00003 #include "osl/checkmate/analyzer/treeWriter.h"
00004 #include "osl/checkmate/analyzer/recordSet.h"
00005 #include "osl/checkmate/checkHashRecord.h"
00006 #include "osl/checkmate/checkMove.h"
00007 #include "osl/checkmate/sameBoardList.h"
00008 #include "osl/container/moveVector.h"
00009 #include "osl/record/csa.h"
00010
00011
00012
00013 osl::checkmate::analyzer::
00014 TreeWriter::TreeWriter()
00015 : depth(1)
00016 {
00017 }
00018 osl::checkmate::analyzer::
00019 TreeWriter::~TreeWriter()
00020 {
00021 }
00022
00023
00024 osl::checkmate::analyzer::
00025 DotWriter::DotWriter(std::ostream& o, size_t m, const char *name)
00026 : os(o), visited(new RecordSet()), minimumPdp(m)
00027 {
00028 os << "// minimumPdp " << minimumPdp << "\n";
00029 os << "digraph " << (name ? name : "OSL_DotWriter") << " {\n";
00030 }
00031
00032 osl::checkmate::analyzer::
00033 DotWriter::~DotWriter()
00034 {
00035 os << "}\n";
00036 }
00037
00038 const std::string osl::checkmate::analyzer::
00039 DotWriter::header() const
00040 {
00041 return " ";
00042 }
00043
00044 namespace osl
00045 {
00046 namespace
00047 {
00048 bool focus(const CheckHashRecord& record, size_t threshold)
00049 {
00050 const ProofDisproof& pdp = record.proofDisproof();
00051 return (! record.twins.empty())
00052 || pdp.isFinal()
00053 || ((pdp.proof() > threshold) || (pdp.disproof() > threshold));
00054 }
00055 bool primaryFocus(const CheckHashRecord& record)
00056 {
00057 const size_t threshold = 300;
00058 return focus(record, threshold);
00059 }
00060
00061 void writeEdge(std::ostream& os, const std::string& header,
00062 const CheckHashRecord *from,
00063 const CheckHashRecord *to,
00064 const char *color, const char *style)
00065 {
00066 os << header << 'N' << from << " -> " << 'N' << to
00067 << " [weight=0, color=" << color << ", style=" << style << "]\n";
00068 }
00069 }
00070 }
00071
00072 void osl::checkmate::analyzer::
00073 DotWriter::showRecord(const CheckHashRecord *record)
00074 {
00075 assert(record);
00076 if (! visited->insert(record).second)
00077 return;
00078
00079 os << header() << 'N' << record << ' ';
00080 os << "[label=\"" << record->proofDisproof()
00081 << "\\nd=" << record->distance
00082 << (record->useMaxInsteadOfSum ? "(max)" : "")
00083 << "\"";
00084 if (record->proofDisproof().isFinal())
00085 os << ",fontcolor=blue";
00086 else if (primaryFocus(*record))
00087 os << ",fontcolor=red";
00088 if (getDepth() % 2)
00089 os << ",shape=box";
00090 os << "]\n";
00091
00092
00093
00094 if (record->finalByDominance())
00095 {
00096 writeEdge(os, header(), record->finalByDominance(), record,
00097 "green", "dashed");
00098 }
00099 if (record->sameBoards)
00100 {
00101 for (SameBoardList::const_iterator p=record->sameBoards->begin();
00102 p!=record->sameBoards->end(); ++p)
00103 {
00104 if (p->stand(BLACK) == record->stand(BLACK))
00105 continue;
00106 if (p->stand(BLACK).hasMoreThan<BLACK>(record->stand(BLACK)))
00107 {
00108 writeEdge(os, header(), record, &*p, "blue", "dotted");
00109 showRecord(&*p);
00110 }
00111 #if 0
00112
00113
00114 if (record->blackStand.hasMoreThan<BLACK>(p->blackStand))
00115 {
00116 writeEdge(os, header(), &*p, record, "blue", "dotted");
00117 showRecord(&*p);
00118 }
00119 #endif
00120 }
00121 }
00122 }
00123
00124 void osl::checkmate::analyzer::
00125 DotWriter::showMove(const CheckHashRecord *from, const CheckMove& move)
00126 {
00127 if (! focus(*from, minimumPdp))
00128 {
00129
00130 return;
00131 }
00132 const CheckHashRecord *record = move.record;
00133 if (! record)
00134 {
00135 assert(move.flags.isSet(MoveFlags::ImmediateCheckmate));
00136 return;
00137 }
00138 showRecord(record);
00139 int weight = 1;
00140 if (move.flags.isSet(MoveFlags::Upward))
00141 weight = 0;
00142 if (from->bestMove && (from->bestMove->move == move.move))
00143 weight = 2;
00144 if (primaryFocus(*record))
00145 weight += 1;
00146 const Move m = move.move;
00147 os << header() << 'N' << from << " -> " << 'N' << record
00148 << " [label=\"";
00149 csaShow(os, m);
00150 os << "\", weight=" << weight;
00151 if (move.flags.isSet(MoveFlags::Upward))
00152 os << ", color=magenta";
00153 else if (primaryFocus(*record))
00154 os << ", color=red";
00155 if (from->bestMove
00156 && (from->bestMove->move == move.move))
00157 os << ", style=bold";
00158 os << "]\n";
00159 }
00160
00161 void osl::checkmate::analyzer::
00162 DotWriter::showMoves(const MoveVector& moves)
00163 {
00164 if (moves.size() == 0)
00165 return;
00166 os << "// T";
00167 for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
00168 {
00169 os << ' ';
00170 csaShow(os, *p);
00171 }
00172 os << "\n";
00173 }
00174
00175 void osl::checkmate::analyzer::
00176 DotWriter::writeln(const char *msg)
00177 {
00178 os << "// " << msg << "\n";
00179 }
00180
00181
00182
00183 osl::checkmate::analyzer::
00184 OutlineWriter::OutlineWriter()
00185 {
00186 }
00187
00188 osl::checkmate::analyzer::
00189 OutlineWriter::~OutlineWriter()
00190 {
00191 }
00192
00193 const std::string osl::checkmate::analyzer::
00194 OutlineWriter::header() const
00195 {
00196 return std::string(getDepth(), '*');
00197 }
00198
00199
00200
00201 osl::checkmate::analyzer::
00202 TreeStreamWriter::TreeStreamWriter(std::ostream *o, bool s)
00203 : os(o), simpleMove(s)
00204 {
00205 }
00206 osl::checkmate::analyzer::
00207 TreeStreamWriter::~TreeStreamWriter()
00208 {
00209 }
00210
00211 void osl::checkmate::analyzer::
00212 TreeStreamWriter::showRecord(const CheckHashRecord *record)
00213 {
00214 assert(record);
00215 (*os) << header() << ' ' << record->proofDisproof() << ' ' << record->filter;
00216 if (record->hasBestMove())
00217 {
00218 (*os) << " best move ";
00219 csaShow(*os, record->bestMove->move);
00220 (*os) << "(" << record->bestMove->record << ")";
00221 }
00222 (*os) << "\n";
00223 #if 0
00224 (*os) << "bestResultInSolved " << record->bestResultInSolved << "\n";
00225 #endif
00226 if (! record->twins.empty())
00227 {
00228 for (TwinList::const_iterator p=record->twins.begin();
00229 p!=record->twins.end(); ++p)
00230 {
00231 (*os) << " [" << p->path << " ";
00232 csaShow(*os, p->move.move);
00233 (*os) << " " << p->move.record << "]";
00234 }
00235 (*os) << "\n";
00236 }
00237 }
00238
00239 void osl::checkmate::analyzer::
00240 TreeStreamWriter::showMove(const CheckMove& m)
00241 {
00242 (*os) << header() << ' ';
00243 csaShow(*os, m.move);
00244 (*os) << " " << m.flags;
00245 if (m.record)
00246 {
00247 (*os) << m.record->proofDisproof();
00248 if (! m.record->twins.empty())
00249 {
00250 (*os) << " twins " << m.record->twins.size();
00251 for (TwinList::const_iterator p=m.record->twins.begin();
00252 p!=m.record->twins.end(); ++p)
00253 {
00254 (*os) << " " << p->path << " ";
00255 csaShow(*os, p->move.move);
00256 }
00257 }
00258 }
00259 (*os) << "\n";
00260 }
00261
00262 void osl::checkmate::analyzer::
00263 TreeStreamWriter::showMove(const CheckHashRecord *,
00264 const CheckMove& move)
00265 {
00266 if (simpleMove)
00267 {
00268 showMove(move);
00269 return;
00270 }
00271 const CheckHashRecord *record = move.record;
00272
00273 const Move m = move.move;
00274 (*os) << header() << ' ';
00275 csaShow(*os, m);
00276 (*os) << ' ' << record->distance << ' ' << move.flags << ' '
00277 << record->proofDisproof() << ' ' << record->filter;
00278 if (record->isVisited)
00279 (*os) << " (v)";
00280 if (record->isConfluence)
00281 (*os) << " (c)";
00282 if (record->useMaxInsteadOfSum)
00283 (*os) << " (sum/max)";
00284 (*os) << ' ' << record << " up " << record->parent << " ";
00285 if (! record->twins.empty())
00286 {
00287 (*os) << " twins " << record->twins.size();
00288 for (TwinList::const_iterator p=record->twins.begin();
00289 p!=record->twins.end(); ++p)
00290 {
00291 (*os) << " " << p->path << " ";
00292 csaShow(*os, p->move.move);
00293 }
00294 }
00295 if (record->hasBestMove() && (! record->bestMove->move.isPass()))
00296 {
00297 (*os) << " best move ";
00298 csaShow(*os, record->bestMove->move);
00299 (*os) << "(" << record->bestMove->record << ")";
00300 }
00301 (*os) << "\n";
00302 #if 0
00303 (*os) << "bestResultInSolved " << record->bestResultInSolved << "\n";
00304 #endif
00305 if (! record->twins.empty())
00306 {
00307 for (TwinList::const_iterator p=record->twins.begin();
00308 p!=record->twins.end(); ++p)
00309 {
00310 (*os) << " [" << p->path << " ";
00311 csaShow(*os, p->move.move);
00312 (*os) << " " << p->move.record << "]";
00313 }
00314 (*os) << "\n";
00315 }
00316 }
00317
00318 void osl::checkmate::analyzer::
00319 TreeStreamWriter::showMoves(const MoveVector& moves)
00320 {
00321 if (moves.size() == 0)
00322 return;
00323 (*os) << 'T';
00324 for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
00325 {
00326 (*os) << ' ';
00327 csaShow(*os, *p);
00328 }
00329 (*os) << "\n";
00330 }
00331
00332 void osl::checkmate::analyzer::
00333 TreeStreamWriter::writeln(const char *msg)
00334 {
00335 (*os) << msg << "\n";
00336 }
00337
00338
00339
00340
00341
00342