00001 //---------------------------------------------------------------------------- 00002 /** @file VCBuilder.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef VCBUILDER_HPP 00007 #define VCBUILDER_HPP 00008 00009 #include "Hex.hpp" 00010 #include "VC.hpp" 00011 #include "VCList.hpp" 00012 #include "VCSet.hpp" 00013 #include "Groups.hpp" 00014 #include "PatternState.hpp" 00015 00016 _BEGIN_BENZENE_NAMESPACE_ 00017 00018 //---------------------------------------------------------------------------- 00019 00020 /** Settings for VCBuilder. */ 00021 struct VCBuilderParam 00022 { 00023 /** Maximum number of VCs in the OR combining rule. */ 00024 int max_ors; 00025 00026 /** Whether the and-rule can and over the edge or not. 00027 This results in many more connections. */ 00028 bool and_over_edge; 00029 00030 /** Whether to augment VC set with pre-computed VC patterns. */ 00031 bool use_patterns; 00032 00033 /** Whether to use pre-computed patterns between two non-edge 00034 cells. These can cause an explosion in the number of 00035 connections. */ 00036 bool use_non_edge_patterns; 00037 00038 /** Whether to use the greedy union or not. 00039 @todo DOCUMENT GREEDY UNION! */ 00040 bool use_greedy_union; 00041 00042 /** Stop building VCs once a winning connection is constructed. */ 00043 bool abort_on_winning_connection; 00044 00045 /** Constructor. */ 00046 VCBuilderParam(); 00047 }; 00048 00049 00050 //---------------------------------------------------------------------------- 00051 00052 /** Statistics for the last call to Build(). */ 00053 struct VCBuilderStatistics 00054 { 00055 /** Base connections built. */ 00056 int base_attempts; 00057 00058 /** Base connections successfully added. */ 00059 int base_successes; 00060 00061 /** Pattern connections that match the board. */ 00062 int pattern_attempts; 00063 00064 /** Pattern connections successfully added. */ 00065 int pattern_successes; 00066 00067 /** Full-connections built by and-rule. */ 00068 int and_full_attempts; 00069 00070 /** Full-connections successfully added by and-rule. */ 00071 int and_full_successes; 00072 00073 /** Semi-connections built by and-rule. */ 00074 int and_semi_attempts; 00075 00076 /** Semi-connections successfully added by and-rule. */ 00077 int and_semi_successes; 00078 00079 /** Full-connections built by or-rule. */ 00080 int or_attempts; 00081 00082 /** Full-connections successfully added by or-rule. */ 00083 int or_successes; 00084 00085 /** Calls to or-rule. */ 00086 int doOrs; 00087 00088 /** Successfull or-rule calls -- at least one full-connection 00089 successfully added by this call. */ 00090 int goodOrs; 00091 00092 /** Fulls shrunk in merge phase. */ 00093 int shrunk0; 00094 00095 /** Semis shrunk in merge phase. */ 00096 int shrunk1; 00097 00098 /** Semis upgraded to fulls in merge phase. */ 00099 int upgraded; 00100 00101 /** Fulls killed by opponent stones in merge phase. */ 00102 int killed0; 00103 00104 /** Semis killed by opponent stones in merge phase. */ 00105 int killed1; 00106 00107 /** Dumps statistics to a string. */ 00108 std::string ToString() const; 00109 }; 00110 00111 //---------------------------------------------------------------------------- 00112 00113 /** Builds the Virtual Connections (VCs) between groups of stones a 00114 single color. 00115 00116 VCs can be built from scratch or incrementally from a previous 00117 state. We use Anchelevich's rules for VC computation. This means 00118 that between each pair of cells on the board, we store a VCList of 00119 FULL connections and another VCList of SEMI connections. 00120 00121 IMPORTANT: Take a list of semis between x and y. If any subset of 00122 of these semis has an empty intersection, we require that the list 00123 of full connections between x and y has at least one connection. 00124 00125 See also: 00126 - @ref mergeshrink 00127 - @ref workqueue 00128 */ 00129 class VCBuilder 00130 { 00131 public: 00132 00133 /** Constructor. */ 00134 VCBuilder(VCBuilderParam& param); 00135 00136 /** Destrutor. */ 00137 ~VCBuilder(); 00138 00139 //---------------------------------------------------------------------- 00140 00141 /** Returns parameters used in search. */ 00142 VCBuilderParam& Parameters(); 00143 00144 /** Returns parameters used in search. */ 00145 const VCBuilderParam& Parameters() const; 00146 00147 /** Returns statistics for the last run. */ 00148 VCBuilderStatistics Statistics(HexColor color) const; 00149 00150 /** Clears the statistics for both colors. */ 00151 void ClearStatistics(); 00152 00153 //---------------------------------------------------------------------- 00154 00155 /** Computes connections from scratch. Old connections are removed 00156 prior to starting. */ 00157 void Build(VCSet& con, const Groups& groups, 00158 const PatternState& patterns); 00159 00160 /** Updates connections from oldGroups to newGroups Assumes 00161 existing vc data is valid for oldGroups. Logging is used if 00162 passed log is not 0. Breaks all connections whose carrier 00163 contains a new stone unless a 1-connection of player color and 00164 p is the key; these are upgraded to 0-connections for player 00165 p. */ 00166 void Build(VCSet& cons, const Groups& oldGroups, 00167 const Groups& newGroups, const PatternState& patterns, 00168 bitset_t added[BLACK_AND_WHITE], 00169 ChangeLog<VC>* log); 00170 00171 private: 00172 00173 //---------------------------------------------------------------------- 00174 00175 /** Queue of endpoint pairs that need processing. 00176 @ref workqueue 00177 */ 00178 class WorkQueue 00179 { 00180 public: 00181 WorkQueue(); 00182 bool empty() const; 00183 const HexPointPair& front() const; 00184 std::size_t capacity() const; 00185 00186 void clear(); 00187 void pop(); 00188 void push(const HexPointPair& pair); 00189 00190 private: 00191 std::size_t m_head; 00192 std::vector<HexPointPair> m_array; 00193 bool m_seen[BITSETSIZE][BITSETSIZE]; 00194 }; 00195 00196 //---------------------------------------------------------------------- 00197 00198 /** The types of VC to create when using the AND rule. */ 00199 typedef enum { CREATE_FULL, CREATE_SEMI } AndRule; 00200 00201 void doAnd(HexPoint from, HexPoint over, HexPoint to, 00202 AndRule rule, const VC& vc, const bitset_t& capturedSet, 00203 const VCList* old); 00204 00205 class OrRule 00206 { 00207 public: 00208 OrRule(const VCBuilder& builder) 00209 : m_builder(builder), m_semi(64), m_tail(64) {}; 00210 00211 int operator()(const VC& vc, const VCList* semi_list, 00212 VCList* full_list, std::list<VC>& added, 00213 int max_ors, ChangeLog<VC>* log, 00214 VCBuilderStatistics& stats); 00215 00216 private: 00217 const VCBuilder& m_builder; 00218 /** Vectors used in or rule computation are reused between 00219 calls to avoid unnecessary dynamic memory allocation. */ 00220 std::vector<VC> m_semi; 00221 std::vector<bitset_t> m_tail; 00222 }; 00223 00224 OrRule m_orRule; 00225 00226 void andClosure(const VC& vc); 00227 00228 void DoSearch(); 00229 00230 void ProcessSemis(HexPoint xc, HexPoint yc); 00231 00232 void ProcessFulls(HexPoint p1, HexPoint p2); 00233 00234 bool AddNewFull(const VC& vc); 00235 00236 bool AddNewSemi(const VC& vc); 00237 00238 void LoadCapturedSetPatterns(); 00239 00240 void ComputeCapturedSets(const PatternState& patterns); 00241 00242 void AddBaseVCs(); 00243 00244 void AddPatternVCs(); 00245 00246 void AbsorbMergeShrinkUpgrade(const bitset_t& added_black, 00247 const bitset_t& added_white); 00248 00249 void Merge(const Groups& oldGroups, bitset_t added[BLACK_AND_WHITE]); 00250 00251 void MergeAndShrink(const bitset_t& affected, 00252 const bitset_t& added); 00253 00254 void MergeAndShrink(const bitset_t& added, 00255 HexPoint xin, HexPoint yin, 00256 HexPoint xout, HexPoint yout); 00257 00258 void RemoveAllContaining(const Groups& groups, const bitset_t& bs); 00259 00260 //----------------------------------------------------------------------- 00261 00262 VCBuilderParam& m_param; 00263 00264 WorkQueue m_queue; 00265 00266 VCBuilderStatistics m_statsForColor[BLACK_AND_WHITE]; 00267 00268 VCBuilderStatistics* m_statistics; 00269 00270 const Groups* m_groups; 00271 00272 const StoneBoard* m_brd; 00273 00274 VCSet* m_con; 00275 00276 HexColor m_color; 00277 00278 ChangeLog<VC>* m_log; 00279 00280 bitset_t m_capturedSet[BITSETSIZE]; 00281 00282 PatternSet m_capturedSetPatterns[BLACK_AND_WHITE]; 00283 00284 HashedPatternSet m_hash_capturedSetPatterns[BLACK_AND_WHITE]; 00285 }; 00286 00287 inline VCBuilderParam& VCBuilder::Parameters() 00288 { 00289 return m_param; 00290 } 00291 00292 inline const VCBuilderParam& VCBuilder::Parameters() const 00293 { 00294 return m_param; 00295 } 00296 00297 inline VCBuilderStatistics VCBuilder::Statistics(HexColor color) const 00298 { 00299 return m_statsForColor[color]; 00300 } 00301 00302 inline void VCBuilder::ClearStatistics() 00303 { 00304 m_statsForColor[BLACK] = VCBuilderStatistics(); 00305 m_statsForColor[WHITE] = VCBuilderStatistics(); 00306 } 00307 00308 //---------------------------------------------------------------------------- 00309 00310 _END_BENZENE_NAMESPACE_ 00311 00312 #endif // VCBUILDER_HPP