00001
00002
00003
00004
00005
00006 #include "GoAutoBook.h"
00007
00008
00009
00010 GoAutoBookState::GoAutoBookState(const GoBoard& brd)
00011 : m_synchronizer(brd)
00012 {
00013 m_synchronizer.SetSubscriber(m_brd[0]);
00014 }
00015
00016 GoAutoBookState::~GoAutoBookState()
00017 {
00018 }
00019
00020 SgHashCode GoAutoBookState::GetHashCode() const
00021 {
00022 return m_hash;
00023 }
00024
00025 void GoAutoBookState::Synchronize()
00026 {
00027 m_synchronizer.UpdateSubscriber();
00028 int size = m_brd[0].Size();
00029 int numMoves = m_brd[0].MoveNumber();
00030 for (int rot = 1; rot < 8; ++rot)
00031 {
00032 m_brd[rot].Init(size, size);
00033 for (int i = 0; i < numMoves; ++i)
00034 {
00035 SgMove move = m_brd[0].Move(i).Point();
00036 m_brd[rot].Play(SgPointUtil::Rotate(rot, move, size));
00037 }
00038 }
00039 ComputeHashCode();
00040 }
00041
00042 void GoAutoBookState::Play(SgMove move)
00043 {
00044 m_hash = m_brd[0].GetHashCodeInclToPlay();
00045 for (int rot = 0; rot < 8; ++rot)
00046 m_brd[rot].Play(SgPointUtil::Rotate(rot, move, m_brd[0].Size()));
00047 ComputeHashCode();
00048 }
00049
00050 void GoAutoBookState::Undo()
00051 {
00052 for (int rot = 0; rot < 8; ++rot)
00053 m_brd[rot].Undo();
00054 ComputeHashCode();
00055 }
00056
00057 void GoAutoBookState::ComputeHashCode()
00058 {
00059 m_hash = m_brd[0].GetHashCodeInclToPlay();
00060 for (int rot = 1; rot < 8; ++rot)
00061 {
00062 SgHashCode curHash = m_brd[rot].GetHashCodeInclToPlay();
00063 if (curHash < m_hash)
00064 m_hash = curHash;
00065 }
00066 }
00067
00068
00069
00070 GoAutoBook::GoAutoBook(const std::string& filename) throw()
00071 : m_filename(filename)
00072 {
00073 std::ifstream is(filename.c_str());
00074 if (!is)
00075 {
00076 std::ofstream of(filename.c_str());
00077 if (!of)
00078 throw SgException("Invalid file name!");
00079 of.close();
00080 }
00081 else
00082 {
00083 while (is)
00084 {
00085 std::string line;
00086 std::getline(is, line);
00087 if (line.size() < 19)
00088 continue;
00089 std::string str;
00090 std::istringstream iss(line);
00091 iss >> str;
00092 SgHashCode hash;
00093 hash.FromString(str);
00094 SgBookNode node(line.substr(19));
00095 m_data[hash] = node;
00096 }
00097 SgDebug() << "GoAutoBook: Parsed " << m_data.size() << " lines.\n";
00098 }
00099 }
00100
00101 GoAutoBook::~GoAutoBook()
00102 {
00103 }
00104
00105 bool GoAutoBook::Get(const GoAutoBookState& state, SgBookNode& node) const
00106 {
00107 Map::const_iterator it = m_data.find(state.GetHashCode());
00108 if (it != m_data.end())
00109 {
00110 node = it->second;
00111 return true;
00112 }
00113 return false;
00114 }
00115
00116 void GoAutoBook::Put(const GoAutoBookState& state, const SgBookNode& node)
00117 {
00118 m_data[state.GetHashCode()] = node;
00119 }
00120
00121 void GoAutoBook::Flush()
00122 {
00123 Save(m_filename);
00124 }
00125
00126 void GoAutoBook::Save(const std::string& filename) const
00127 {
00128 std::ofstream out(filename.c_str());
00129 for (Map::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
00130 {
00131 out << it->first.ToString() << '\t'
00132 << it->second.ToString() << '\n';
00133 }
00134 out.close();
00135 }
00136
00137 SgMove GoAutoBook::FindBestChild(GoAutoBookState& state) const
00138 {
00139 std::size_t bestCount = 0;
00140 SgMove bestMove = SG_NULLMOVE;
00141 SgBookNode node;
00142 if (!Get(state, node))
00143 return SG_NULLMOVE;
00144 if (node.IsLeaf())
00145 return SG_NULLMOVE;
00146 for (GoBoard::Iterator it(state.Board()); it; ++it)
00147 {
00148 if (state.Board().IsLegal(*it))
00149 {
00150 state.Play(*it);
00151 if (Get(state, node) && !node.IsLeaf() && !node.IsTerminal())
00152 {
00153 if (node.m_count > bestCount)
00154 {
00155 bestCount = node.m_count;
00156 bestMove = *it;
00157 }
00158 }
00159 state.Undo();
00160 }
00161 }
00162 return bestMove;
00163 }
00164
00165 SgMove GoAutoBook::LookupMove(const GoBoard& brd) const
00166 {
00167 GoAutoBookState state(brd);
00168 state.Synchronize();
00169 return FindBestChild(state);
00170 }
00171
00172