00001 //---------------------------------------------------------------------------- 00002 /** @file VC.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef VC_HPP 00007 #define VC_HPP 00008 00009 #include "Hex.hpp" 00010 00011 _BEGIN_BENZENE_NAMESPACE_ 00012 00013 //---------------------------------------------------------------------------- 00014 00015 /** Rules used to combine VCs. */ 00016 typedef enum 00017 { 00018 /** Empty connection between two adjacent cells. */ 00019 VC_RULE_BASE, 00020 00021 /** Built from two connections with empty intersection sharing 00022 an endpoint. */ 00023 VC_RULE_AND, 00024 00025 /** Built from a set of two or more semi-connections whose 00026 interestion is empty. */ 00027 VC_RULE_OR, 00028 00029 /** Built from an OR using all semi-connections in the 00030 list. */ 00031 VC_RULE_ALL 00032 00033 } VcCombineRule; 00034 00035 /** Utilities on VcCombineRule. */ 00036 namespace VcRuleUtil 00037 { 00038 /** Returns string representation of the rule.*/ 00039 std::string toString(VcCombineRule rule); 00040 00041 } // namespace VcRuleUtil 00042 00043 inline std::string VcRuleUtil::toString(VcCombineRule rule) 00044 { 00045 if (rule == VC_RULE_BASE) 00046 return "base"; 00047 else if (rule == VC_RULE_AND) 00048 return "and"; 00049 else if (rule == VC_RULE_OR) 00050 return "or"; 00051 else if (rule == VC_RULE_ALL) 00052 return "all"; 00053 return "unknown"; 00054 } 00055 00056 /** Extends standout output operator to handle VcCombineRule. */ 00057 inline std::ostream& operator<<(std::ostream& os, VcCombineRule rule) 00058 { 00059 os << VcRuleUtil::toString(rule); 00060 return os; 00061 } 00062 00063 //---------------------------------------------------------------------------- 00064 00065 /** Virtual Connection. */ 00066 class VC 00067 { 00068 public: 00069 00070 /** Two types of Virtual VCSet: FULL and SEMI. 00071 00072 FULL (or "0") connections are second-player strategies 00073 guaranteeing the connection even if the opponent goes first. 00074 FULL must have their key set to NO_KEY. 00075 00076 SEMI (or "1") connections are first-player strategies; ie, the 00077 first player can make the connection if he is given one free 00078 move. This free move is called the "key" of the connection. 00079 */ 00080 typedef enum { FULL, SEMI, NUM_TYPES } Type; 00081 00082 /** Full connections must have their keys set to NO_KEY. */ 00083 static const HexPoint NO_KEY = INVALID_POINT; 00084 00085 //---------------------------------------------------------------------- 00086 00087 /** Constucts and empty VC with endpoints are (INVALID_POINT, 00088 INVALID_POINT). */ 00089 VC(); 00090 00091 /** Creates an empty VC between x and y: no key, empty carrier, 00092 VC_RULE_BASE. */ 00093 VC(HexPoint x, HexPoint y); 00094 00095 /** Creates a 0-connection between x and y with the given 00096 carrier. */ 00097 VC(HexPoint x, HexPoint y, const bitset_t& carrier, VcCombineRule from); 00098 00099 /** Creates a 1-connection between x and y with the given carrier 00100 and key. */ 00101 VC(HexPoint x, HexPoint y, HexPoint key, const bitset_t& carrier, 00102 VcCombineRule from); 00103 00104 //---------------------------------------------------------------------- 00105 00106 /** Returns the smaller of the two endpoints. */ 00107 HexPoint x() const; 00108 00109 /** Returns the larger of the two endpoints. */ 00110 HexPoint y() const; 00111 00112 /** Returns the key of the connection. */ 00113 HexPoint key() const; 00114 00115 /** The set of cells required in order to realize this 00116 connection. */ 00117 bitset_t carrier() const; 00118 00119 /** Returns the type of connection. */ 00120 Type type() const; 00121 00122 /** Returns rule used to construct this connection. */ 00123 VcCombineRule rule() const; 00124 00125 /** Returns the number of set bits in the carrier; this is cached 00126 so only takes constant time. */ 00127 int count() const; 00128 00129 /** Returns true if the carrier is empty, false otherwise. */ 00130 bool IsEmpty() const; 00131 00132 /** Returns string representation of connection. */ 00133 std::string toString() const; 00134 00135 //---------------------------------------------------------------------- 00136 00137 /** Returns true if this vc has been processed; false, otherwise. */ 00138 bool processed() const; 00139 00140 /** Sets the processed flag. 00141 00142 ONLY USE THIS IF YOU KNOW WHAT YOU ARE DOING! 00143 00144 Should only be called inside of VCSet. 00145 */ 00146 void setProcessed(bool flag); 00147 00148 //---------------------------------------------------------------------- 00149 00150 /** Two VCs are equal if their keys and carriers are equal. */ 00151 bool operator==(const VC& o) const; 00152 00153 bool operator!=(const VC& o) const; 00154 00155 /** Comparison is by the number of set bits in the carrier. */ 00156 bool operator<(const VC& o) const; 00157 00158 bool operator>(const VC& o) const; 00159 00160 bool operator<=(const VC& o) const; 00161 00162 /** Is this a subset of o? */ 00163 bool isSubsetOf(const VC& o) const; 00164 00165 //------------------------------------------------------------ 00166 00167 /** @name Static methods */ 00168 // @{ 00169 00170 /** Returns a new full VC by unioning v1 and v2. */ 00171 static VC AndVCs(HexPoint x, HexPoint y, const VC& v1, const VC& v2); 00172 00173 static VC AndVCs(HexPoint x, HexPoint y, const VC& v1, const VC& v2, 00174 const bitset_t& capturedSet); 00175 00176 /** Returns a new semi VC with key key by unioning v1 and v2. */ 00177 static VC AndVCs(HexPoint x, HexPoint y, 00178 const VC& v1, const VC& v2, HexPoint key); 00179 00180 static VC AndVCs(HexPoint x, HexPoint y, const VC& v1, const VC& v2, 00181 const bitset_t& capturedSet, HexPoint key); 00182 00183 static VC UpgradeSemi(const VC& v1, const bitset_t& takeout, 00184 HexPoint outx, HexPoint outy); 00185 00186 static VC ShrinkFull(const VC& v1, const bitset_t& takeout, 00187 HexPoint outx, HexPoint outy); 00188 00189 static VC ShrinkSemi(const VC& v1, const bitset_t& takeout, 00190 HexPoint outx, HexPoint outy); 00191 // @} 00192 00193 private: 00194 00195 /** The smaller of the two endpoints. */ 00196 short m_x; 00197 00198 /** The larger of the two endpoints. */ 00199 short m_y; 00200 00201 /** The connection key; if NO_KEY, then this is a FULL connection, 00202 otherwise this is a SEMI connectin. */ 00203 short m_key; 00204 00205 /** The empty cells that may be required to realize this 00206 connection. */ 00207 bitset_t m_carrier; 00208 00209 /** The rule used to construct this connection. */ 00210 byte m_rule; 00211 00212 /** Flag denoting whether this connection has been used to build 00213 other connections. */ 00214 byte m_processed; 00215 00216 /** Cached number of bits in the carrier. Used for sorting. */ 00217 byte m_count; 00218 }; 00219 00220 inline HexPoint VC::x() const 00221 { 00222 return static_cast<HexPoint>(m_x); 00223 } 00224 00225 inline HexPoint VC::y() const 00226 { 00227 return static_cast<HexPoint>(m_y); 00228 } 00229 00230 inline HexPoint VC::key() const 00231 { 00232 return static_cast<HexPoint>(m_key); 00233 } 00234 00235 inline bitset_t VC::carrier() const 00236 { 00237 return m_carrier; 00238 } 00239 00240 inline VC::Type VC::type() const 00241 { 00242 return (m_key == NO_KEY) ? FULL : SEMI; 00243 } 00244 00245 inline VcCombineRule VC::rule() const 00246 { 00247 return static_cast<VcCombineRule>(m_rule); 00248 } 00249 00250 inline int VC::count() const 00251 { 00252 return m_count; 00253 } 00254 00255 inline bool VC::IsEmpty() const 00256 { 00257 return m_carrier.none(); 00258 } 00259 00260 inline bool VC::processed() const 00261 { 00262 return m_processed; 00263 } 00264 00265 inline void VC::setProcessed(bool flag) 00266 { 00267 m_processed = flag; 00268 } 00269 00270 inline bool VC::operator==(const VC& o) const 00271 { 00272 return (m_key == o.m_key) && (m_carrier == o.m_carrier); 00273 } 00274 00275 inline bool VC::operator!=(const VC& o) const 00276 { 00277 return !(*this == o); 00278 } 00279 00280 inline bool VC::operator<(const VC& o) const 00281 { 00282 if (count() != o.count()) 00283 return (count() < o.count()); 00284 00285 if (m_key != o.m_key) 00286 return (m_key < o.m_key); 00287 00288 return BitsetUtil::IsLessThan(m_carrier, o.m_carrier); 00289 } 00290 00291 inline bool VC::operator>(const VC& o) const 00292 { 00293 return (o < *this); 00294 } 00295 00296 inline bool VC::operator<=(const VC& o) const 00297 { 00298 if (*this == o) 00299 return true; 00300 if (*this < o) 00301 return true; 00302 return false; 00303 } 00304 00305 inline bool VC::isSubsetOf(const VC& o) const 00306 { 00307 return BitsetUtil::IsSubsetOf(m_carrier, o.m_carrier); 00308 } 00309 00310 //---------------------------------------------------------------------------- 00311 00312 /** Misc. utilities on VCs. */ 00313 namespace VCTypeUtil 00314 { 00315 bool IsValidType(VC::Type type); 00316 00317 std::string toString(VC::Type type); 00318 00319 VC::Type fromString(std::string name); 00320 } 00321 00322 //---------------------------------------------------------------------------- 00323 00324 /** Extends standard output operator to print vcs. */ 00325 inline std::ostream& operator<<(std::ostream &os, const VC& vc) 00326 { 00327 os << vc.toString(); 00328 return os; 00329 } 00330 00331 //---------------------------------------------------------------------------- 00332 00333 _END_BENZENE_NAMESPACE_ 00334 00335 #endif // VC_HPP