00001
00002
00003 #include "osl/search/analyzer/dotWriter.h"
00004 #include "osl/search/analyzer/recordSet_.h"
00005 #include "osl/search/simpleHashRecord.h"
00006 #include "osl/record/csa.h"
00007 #include <boost/format.hpp>
00008 #include <sstream>
00009 #include <iostream>
00010 #include <cassert>
00011
00012 #define BOOST_FORMAT_BUG
00013
00014 osl::search::analyzer::DotWriter::
00015 DotWriter(std::ostream& o)
00016 : written(new RecordSet()), os(o)
00017 {
00018 os << "digraph OSL_DotWriter {\n";
00019 }
00020
00021 osl::search::analyzer::DotWriter::
00022 ~DotWriter()
00023 {
00024 os << "}\n" << std::flush;
00025 }
00026
00027 void osl::search::analyzer::DotWriter::
00028 showComment(const char *line) const
00029 {
00030 os << "// " << line << "\n";
00031 }
00032
00033 void osl::search::analyzer::DotWriter::
00034 showNode(Player turn, const SimpleHashRecord *record,
00035 int limit, NodeType type) const
00036 {
00037 const bool black_turn = turn == BLACK;
00038 if (written->find(record) != written->end())
00039 return;
00040 written->insert(record);
00041 assert(record);
00042 std::stringstream range;
00043 int lower_limit = record->lowerLimit();
00044 int lower_bound = record->lowerBound();
00045 int upper_limit = record->upperLimit();
00046 int upper_bound = record->upperBound();
00047 if (! black_turn)
00048 {
00049 std::swap(lower_limit, upper_limit);
00050 std::swap(lower_bound, upper_bound);
00051 }
00052 int bound = 0;
00053 if (lower_limit >= 0)
00054 {
00055 ++bound;
00056 #ifndef BOOST_FORMAT_BUG
00057 range << (boost::format("%d(%d)") % lower_bound % lower_limit);
00058 #else
00059 range << lower_bound << "(" << lower_limit << ")";
00060 #endif
00061 }
00062 range << '<';
00063 if (upper_limit >= 0)
00064 {
00065 ++bound;
00066 #ifndef BOOST_FORMAT_BUG
00067 range << (boost::format("%d(%d)") % upper_bound % upper_limit);
00068 #else
00069 range << upper_bound << "(" << upper_limit << ")";
00070 #endif
00071 }
00072 const char *color = 0;
00073 switch (type)
00074 {
00075 case IMPORTANT:
00076 color = "blue";
00077 break;
00078 case ABNORMAL:
00079 color = "magenta";
00080 break;
00081 default:
00082 color = (bound == 2) ? "red" : "black";
00083 }
00084 std::stringstream bestMove;
00085 csaShow(bestMove, record->bestMove().getMove());
00086 #ifndef BOOST_FORMAT_BUG
00087 os << (boost::format("N%x [label=\"l=%d\\n%s\\n%s\",color=%s,shape=box]\n")
00088 % record % limit % range.str() % bestMove.str()
00089 % color);
00090 #else
00091 os << "N" << record << " [label=\"l=" << limit << "\\n" << range.str()
00092 << "\\n" << bestMove.str()
00093 << "\",color=" << color << ",shape=box]\n";
00094 #endif
00095 }
00096
00097
00098 void osl::search::analyzer::DotWriter::
00099 showNodeQuiescence(Player turn, const SimpleHashRecord *record,
00100 int limit, NodeType type) const
00101 {
00102 bool black_turn = (turn == BLACK);
00103 if (written->find(record) != written->end())
00104 return;
00105 written->insert(record);
00106 assert(record);
00107 const QuiescenceRecord *qrecord = &record->qrecord;
00108 std::stringstream range;
00109 int lower_limit = qrecord->lowerDepth();
00110 int lower_bound = qrecord->lowerBound();
00111 int upper_limit = qrecord->upperDepth();
00112 int upper_bound = qrecord->upperBound();
00113 if (! black_turn)
00114 {
00115 std::swap(lower_limit, upper_limit);
00116 std::swap(lower_bound, upper_bound);
00117 }
00118 int bound = 0;
00119 if (lower_limit >= 0)
00120 {
00121 ++bound;
00122 #ifndef BOOST_FORMAT_BUG
00123 range << (boost::format("%d(%d)") % lower_bound % lower_limit);
00124 #else
00125 range << lower_bound << "(" << lower_limit << ")";
00126 #endif
00127 }
00128 range << '<';
00129 if (upper_limit >= 0)
00130 {
00131 ++bound;
00132 #ifndef BOOST_FORMAT_BUG
00133 range << (boost::format("%d(%d)") % upper_bound % upper_limit);
00134 #else
00135 range << upper_bound << "(" << upper_limit << ")";
00136 #endif
00137 }
00138 const char *color = 0;
00139 switch (type)
00140 {
00141 case IMPORTANT:
00142 color = "blue";
00143 break;
00144 case ABNORMAL:
00145 color = "magenta";
00146 break;
00147 default:
00148 color = (bound == 2) ? "burlywood" : "cyan";
00149 }
00150 #ifndef BOOST_FORMAT_BUG
00151 os << (boost::format("N%x [label=\"l=%d\\n%s\",color=%s,shape=box]\n")
00152 % record % limit % range.str()
00153 % color);
00154 #else
00155 os << "N" << record << " [label=\"l=" << limit << "\\n" << range.str()
00156 << "\",color=" << color << ",shape=box]\n";
00157 #endif
00158 }
00159
00160 void osl::search::analyzer::DotWriter::
00161 showArc(const SimpleHashRecord *from, const SimpleHashRecord *to,
00162 const MoveLogProb& move, bool important) const
00163 {
00164 if ((written->find(from) != written->end())
00165 && (written->find(to) != written->end()))
00166 return;
00167 assert(from);
00168 assert(to);
00169 std::stringstream move_string;
00170 csaShow(move_string, move.getMove());
00171 const char *color = 0;
00172 if (important)
00173 color = "blue";
00174 else
00175 color = (move.getLogProb() <= 100) ? "red" : "black";
00176 #ifndef BOOST_FORMAT_BUG
00177 os << (boost::format("N%x -> N%x [label=\"%s (%d)\", color=%s, style=bold]\n")
00178 % from % to % move_string.str() % move.getLogProb() % color);
00179 #else
00180 os << "N" << from << " -> N" << to << " [label=\"" << move_string.str()
00181 << " (" << move.getLogProb() << ")\", color=" << color
00182 << ", style=bold]\n";
00183 #endif
00184 }
00185
00186
00187
00188
00189
00190