00001 //---------------------------------------------------------------------------- 00002 /** @file GoAutoBook.h */ 00003 //---------------------------------------------------------------------------- 00004 00005 #ifndef GOAUTOBOOK_H 00006 #define GOAUTOBOOK_H 00007 00008 #include <cmath> 00009 #include <iostream> 00010 #include <fstream> 00011 #include <set> 00012 #include <map> 00013 #include "SgBookBuilder.h" 00014 #include "SgThreadedWorker.h" 00015 #include "GoBoard.h" 00016 #include "GoBoardSynchronizer.h" 00017 00018 //---------------------------------------------------------------------------- 00019 00020 /** Tracks canonical hash. */ 00021 class GoAutoBookState 00022 { 00023 public: 00024 GoAutoBookState(const GoBoard& brd); 00025 00026 ~GoAutoBookState(); 00027 00028 GoBoard& Board(); 00029 00030 const GoBoard& Board() const; 00031 00032 void Play(SgMove move); 00033 00034 void Undo(); 00035 00036 SgHashCode GetHashCode() const; 00037 00038 void Synchronize(); 00039 00040 private: 00041 GoBoardSynchronizer m_synchronizer; 00042 00043 GoBoard m_brd[8]; 00044 00045 SgHashCode m_hash; 00046 00047 void ComputeHashCode(); 00048 }; 00049 00050 inline GoBoard& GoAutoBookState::Board() 00051 { 00052 return m_brd[0]; 00053 } 00054 00055 inline const GoBoard& GoAutoBookState::Board() const 00056 { 00057 return m_brd[0]; 00058 } 00059 00060 //---------------------------------------------------------------------------- 00061 00062 typedef enum 00063 { 00064 /** Select move with highest count. */ 00065 GO_AUTOBOOK_SELECT_COUNT, 00066 00067 /** Select move with highest value. */ 00068 GO_AUTOBOOK_SELECT_VALUE 00069 00070 } GoAutoBookMoveSelectType; 00071 00072 struct GoAutoBookParam 00073 { 00074 /** Requires 'count' before it can be used by the player when 00075 generating moves. */ 00076 std::size_t m_usageCountThreshold; 00077 00078 /** Move selection type. */ 00079 GoAutoBookMoveSelectType m_selectType; 00080 00081 GoAutoBookParam(); 00082 }; 00083 00084 //---------------------------------------------------------------------------- 00085 00086 /** Simple text-based book format. 00087 Entire book is loaded into memory. */ 00088 class GoAutoBook 00089 { 00090 public: 00091 GoAutoBook(const std::string& filename, 00092 const GoAutoBookParam& param); 00093 00094 ~GoAutoBook(); 00095 00096 /** Read the node at the given state. Returns true if node exists 00097 in the book, and false otherwise. */ 00098 bool Get(const GoAutoBookState& state, SgBookNode& node) const; 00099 00100 /** Store the node in the given state. */ 00101 void Put(const GoAutoBookState& state, const SgBookNode& node); 00102 00103 /** Since there is no cache, same as Save(). */ 00104 void Flush(); 00105 00106 /** Writes book to disk. */ 00107 void Save(const std::string& filename) const; 00108 00109 /** Helper function: calls FindBestChild() on the given board.*/ 00110 SgMove LookupMove(const GoBoard& brd) const; 00111 00112 /** Returns the move leading to the best child state. 00113 The best child state depends on the move selection criteria. 00114 See GoAutoBookParam. */ 00115 SgMove FindBestChild(GoAutoBookState& state) const; 00116 00117 //---------------------------------------------------------------------- 00118 00119 /** Merge this book with given book. 00120 Internal nodes in either book become internal nodes in merged 00121 book, counts are clobbered (max is taken). Leafs in both books 00122 are leafs in merged book, value is the set to be the average. 00123 00124 @todo Handle counts properly? Would need to know the original 00125 book the two books we are merging derived from. */ 00126 void Merge(const GoAutoBook& other); 00127 00128 /** Add states to be disabled. 00129 These states will not be considered for selection in 00130 FindBestChild() from the parent state. */ 00131 void AddDisabledLines(const std::set<SgHashCode>& disabled); 00132 00133 /** Copies a truncated version of the book into other. */ 00134 void TruncateByDepth(int depth, GoAutoBookState& state, 00135 GoAutoBook& other) const; 00136 00137 /** Overwrites values in book by reading stream of (hash, value) 00138 pairs. */ 00139 void ImportHashValuePairs(std::istream& in); 00140 00141 /** Exports book states under the given state in GoBook format to 00142 the given stream. Only the move that would be selected with 00143 FindBestMove() is given as an option in each state. */ 00144 void ExportToOldFormat(GoAutoBookState& state, std::ostream& os) const; 00145 00146 //---------------------------------------------------------------------- 00147 00148 /** Parses a worklist from a stream. */ 00149 static std::vector< std::vector<SgMove> > ParseWorkList(std::istream& in); 00150 00151 private: 00152 typedef std::map<SgHashCode, SgBookNode> Map; 00153 00154 Map m_data; 00155 00156 const GoAutoBookParam& m_param; 00157 00158 std::set<SgHashCode> m_disabled; 00159 00160 std::string m_filename; 00161 00162 void TruncateByDepth(int depth, GoAutoBookState& state, 00163 GoAutoBook& other, 00164 std::set<SgHashCode>& seen) const; 00165 00166 void ExportToOldFormat(GoAutoBookState& state, std::ostream& out, 00167 std::set<SgHashCode>& seen) const; 00168 00169 }; 00170 00171 inline void GoAutoBook::AddDisabledLines(const std::set<SgHashCode>& disabled) 00172 { 00173 m_disabled.insert(disabled.begin(), disabled.end()); 00174 SgDebug() << "Disabled " << disabled.size() << " lines.\n"; 00175 } 00176 00177 //---------------------------------------------------------------------------- 00178 00179 #endif // GOAUTOBOOK_H