00001 //---------------------------------------------------------------------------- 00002 /** @file 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef PATTERN_H 00007 #define PATTERN_H 00008 00009 #include "Hex.hpp" 00010 #include "RingGodel.hpp" 00011 00012 _BEGIN_BENZENE_NAMESPACE_ 00013 00014 //---------------------------------------------------------------------------- 00015 00016 /** @page patternencoding Pattern Encoding 00017 00018 Each pattern is a type, followed by a colon, followed by six 00019 slices, followed by an optional weight (the weight parameter is 00020 used only for certain types of patterns). 00021 00022 @verbatim 00023 00024 pattern = type : slice; slice; slice; slice; slice; slice; weight 00025 @endverbatim 00026 00027 The six slices form a fan around the center cell. If the pattern 00028 is rotated 60 degrees, the first slice will map onto the second 00029 slice, the second onto the third, etc. This allows the patterns 00030 to be easily rotated on the hex board. 00031 00032 Each slice extends out by MAX_EXTENSION cells. If MAX_EXTENSION=7, 00033 then the slices would be laid out like this: 00034 00035 @verbatim 00036 | 00037 | slice 1 27 00038 slice 2 | 20 26 00039 | 14 19 25 00040 | 9 13 18 24 00041 | 5 8 12 17 23 <-- slice 0 00042 2 4 7 11 16 22 00043 21 15 10 6 3 1 0 * 0 1 3 6 10 15 21 00044 22 16 11 7 4 2 00045 slice 3 --> 23 17 12 8 5 | 00046 24 18 13 9 | 00047 25 19 14 | slice 5 00048 26 20 | 00049 27 slice 4 | 00050 | 00051 @endverbatim 00052 00053 Each slice is composed of five comma separated features. 00054 00055 @verbatim 00056 00057 slice = feature, feature, feature, feature, feature 00058 @endverbatim 00059 00060 Each feature is a 32-bit integer used as a bitmask where the set 00061 bits denote cells int which that feature is "on". 00062 00063 - CELLS the cells used in the slice. 00064 - BLACK the black stones in the slice. 00065 - WHITE the white stones in the slice. 00066 - MARKED1 first set of marked cells in the slice. 00067 - MARKED1 second set of marked cells in the slice. 00068 00069 All features must be a subset of CELLS. BLACK, WHITE, MARKED1 and 00070 MARKED2 must all be pairwise disjoint. 00071 00072 For example, let s be a slice in which CELLS=7, BLACK=4, WHITE=1, 00073 MARKED1=0, and MARKED2=0. Then this slice uses cells 0, 1 and 2; 00074 cell 0 contains a white stone, cell 1 is empty, and cell 2 00075 contains a black stone. 00076 */ 00077 00078 /** Patterns on a Hex board. 00079 00080 Patterns are centered around a cell, and are encoded such that they 00081 can be rotated with minimal computation. 00082 00083 These patterns can only be detected on a PatternBoard. 00084 00085 Used by: 00086 - ICEngine to find inferior cells. 00087 - UCT during the random playout phase. 00088 00089 @see @ref patternencoding 00090 */ 00091 class Pattern 00092 { 00093 public: 00094 00095 /** This sets how far out patterns are allowed to extend. Value 00096 must be >= 1 and <= 7. */ 00097 static const int MAX_EXTENSION = 3; 00098 00099 //----------------------------------------------------------------------- 00100 00101 /** Pattern encodes a move. */ 00102 static const int HAS_MOVES1 = 0x01; 00103 static const int HAS_MOVES2 = 0x02; 00104 00105 /** Pattern has a weight (used by MOHEX patterns). */ 00106 static const int HAS_WEIGHT = 0x04; 00107 00108 //----------------------------------------------------------------------- 00109 00110 /** @name Pattern Types. 00111 The pattern type typically denotes the status of the cell at 00112 the center of the pattern. 00113 */ 00114 00115 // @{ 00116 00117 /** Unknown type. Set in Pattern(), but should not appear in a 00118 defined pattern. */ 00119 static const char UNKNOWN = ' '; 00120 00121 /** Marks that the cell the pattern is centered on is dead. */ 00122 static const char DEAD = 'd'; 00123 00124 /** Marks that the cell the pattern is centered on is 00125 captured. Captured patterns denote a strategy to make this 00126 cell and any cells in MARKED2 as captured. 00127 */ 00128 static const char CAPTURED = 'c'; 00129 00130 /** Marks a permanently inferior cell. MARKED2 holds its 00131 carrier. */ 00132 static const char PERMANENTLY_INFERIOR = 'p'; 00133 00134 /** Mutual fillin. MARKED1 is fillin for one player, MARKED2 is 00135 fillin for other, and cell itself can be assigned to either. */ 00136 static const char MUTUAL_FILLIN = 'u'; 00137 00138 /** Marks a vulnerable cell. MARKED1 holds its killer, and MARKED2 00139 holds its carrier. */ 00140 static const char VULNERABLE = 'v'; 00141 00142 /** Marks a reversible cell. MARKED1 holds its reverser. */ 00143 static const char REVERSIBLE = 'r'; 00144 00145 /** Marks a dominated cell. MARKED1 holds its killer. */ 00146 static const char DOMINATED = '!'; 00147 00148 /** A mohex pattern. These patterns are used during the random 00149 playout phase of an UCT search. */ 00150 static const char MOHEX = 'm'; 00151 00152 /** A mohex pattern. These patterns are used during the random 00153 playout phase of an UCT search. */ 00154 static const char SHIFT = 's'; 00155 00156 // @} // @name 00157 00158 //----------------------------------------------------------------------- 00159 00160 /** Number of triangular slices. Each slice is rooted at a 00161 neighbour of the center cell. Should be 6 (one for each 00162 direction in HexDirection). */ 00163 static const int NUM_SLICES = 6; 00164 00165 /** Info stored in each slice. */ 00166 static const int FEATURE_CELLS = 0; 00167 static const int FEATURE_BLACK = 1; 00168 static const int FEATURE_WHITE = 2; 00169 static const int FEATURE_MARKED1 = 3; 00170 static const int FEATURE_MARKED2 = 4; 00171 static const int NUM_FEATURES = 5; 00172 00173 /** A slice is simply an array of features. */ 00174 typedef int slice_t[NUM_FEATURES]; 00175 00176 //------------------------------------------------------------ 00177 00178 /** Creates an empty pattern. Type is set to UNKNOWN. */ 00179 Pattern(); 00180 00181 /** Returns a string of the pattern in encoded form. 00182 @see @ref patternencoding 00183 */ 00184 std::string serialize() const; 00185 00186 /** Parses a pattern from an encoded string. 00187 @see @ref patternencoding 00188 00189 @return true if pattern was parsed without error. 00190 */ 00191 bool unserialize(std::string code); 00192 00193 /** Returns the pattern's flags. */ 00194 int getFlags() const; 00195 00196 /** Returns the pattern's name. */ 00197 std::string getName() const; 00198 00199 /** Sets the name of this pattern. */ 00200 void setName(const std::string& s); 00201 00202 /** Returns the pattern's type. */ 00203 char getType() const; 00204 00205 /** Returns the list of (slice, bit) pairs for moves defined in the 00206 marked field (f = 0 or 1). */ 00207 const std::vector<std::pair<int, int> >& getMoves1() const; 00208 const std::vector<std::pair<int, int> >& getMoves2() const; 00209 00210 /** Gets the weight for this pattern. */ 00211 int getWeight() const; 00212 00213 /** Gets the extension radius of this pattern. */ 00214 int extension() const; 00215 00216 /** Returns pointer to pattern's slice data. */ 00217 const slice_t* getData() const; 00218 00219 /** Returns the ring godel of this pattern rotated 00220 by angle slices. */ 00221 const PatternRingGodel& RingGodel(int angle) const; 00222 00223 /** Flip the pattern's colors. */ 00224 void flipColors(); 00225 00226 /** Mirrors pattern along x/y diagonal. */ 00227 void mirror(); 00228 00229 /** Parses patterns from a given stream. 00230 00231 Pattern names are assumed to come before the encoding and are 00232 between '[' and '/' characters (this comes from Jack's 00233 pattern file format). 00234 00235 A mirrored copy of a pattern is stored if two names are 00236 encountered before the pattern string. No checking is done 00237 to determine if a mirror is really necessary. 00238 00239 The pattern encoding is detected by any character in the first 00240 column and is assumed to occupy exactly a single line. 00241 00242 So, to create your own pattern file, use something like this: 00243 00244 | ... 00245 | 00246 | [name1/] 00247 | [name2/] 00248 | pattern encoding; 00249 | 00250 | ... 00251 00252 Notice the names are between [ and / symbols and do not start 00253 in the first column. The pattern encoding, however, does 00254 start in the first column (and is the ONLY thing starting in the 00255 first column). 00256 00257 This is temporary. :-) 00258 00259 If you want, you can add a picture of the pattern. Here is 00260 an example pattern from our pattern file: 00261 00262 00263 | 00264 | B B 00265 | B * ! [31/0] 00266 | 00267 | B * ! 00268 | B B [31m/0] 00269 | 00270 |!:1,0,0,1;1,1,0,0;1,1,0,0;1,1,0,0;0,0,0,0;0,0,0,0; 00271 | 00272 00273 00274 This defines a pattern with name "31" and its mirror "31m". 00275 */ 00276 static void LoadPatternsFromStream(std::istream& f, 00277 std::vector<Pattern>& out); 00278 00279 /** Load patterns from a file. */ 00280 static void LoadPatternsFromFile(const char *filename, 00281 std::vector<Pattern>& out); 00282 00283 private: 00284 00285 /** Compute the ring godel codes. */ 00286 void compute_ring_godel(); 00287 00288 /** Pattern type. */ 00289 char m_type; 00290 00291 /** Name of the pattern. */ 00292 std::string m_name; 00293 00294 /** Flags. */ 00295 int m_flags; 00296 00297 /** (slice, bit) pairs of cells in FEATURE_MARKED1. */ 00298 std::vector<std::pair<int, int> > m_moves1; 00299 00300 /** (slice, bit) pairs of cells in FEATURE_MARKED2. */ 00301 std::vector<std::pair<int, int> > m_moves2; 00302 00303 /** MoHex pattern weight. */ 00304 int m_weight; 00305 00306 /** Data for each slice. */ 00307 slice_t m_slice[NUM_SLICES]; 00308 00309 /** How far out the pattern extends. */ 00310 int m_extension; 00311 00312 /** One RingGodel for each rotation of the pattern. */ 00313 PatternRingGodel m_ring_godel[NUM_SLICES]; 00314 }; 00315 00316 /** Sends output of serialize() to the stream. */ 00317 inline std::ostream& operator<<(std::ostream &os, const Pattern& p) 00318 { 00319 os << p.serialize(); 00320 return os; 00321 } 00322 00323 inline std::string Pattern::getName() const 00324 { 00325 return m_name; 00326 } 00327 00328 inline int Pattern::getFlags() const 00329 { 00330 return m_flags; 00331 } 00332 00333 inline char Pattern::getType() const 00334 { 00335 return m_type; 00336 } 00337 00338 inline const Pattern::slice_t* Pattern::getData() const 00339 { 00340 return m_slice; 00341 } 00342 00343 inline void Pattern::setName(const std::string& s) 00344 { 00345 m_name = s; 00346 } 00347 00348 inline const std::vector<std::pair<int, int> >& Pattern::getMoves1() const 00349 { 00350 HexAssert(m_flags & HAS_MOVES1); 00351 return m_moves1; 00352 } 00353 00354 inline const std::vector<std::pair<int, int> >& Pattern::getMoves2() const 00355 { 00356 HexAssert(m_flags & HAS_MOVES2); 00357 return m_moves2; 00358 } 00359 00360 inline int Pattern::getWeight() const 00361 { 00362 HexAssert(m_flags & HAS_WEIGHT); 00363 return m_weight; 00364 } 00365 00366 inline int Pattern::extension() const 00367 { 00368 return m_extension; 00369 } 00370 00371 inline const PatternRingGodel& Pattern::RingGodel(int angle) const 00372 { 00373 return m_ring_godel[angle]; 00374 } 00375 00376 //---------------------------------------------------------------------------- 00377 00378 /** Vector of patterns. */ 00379 typedef std::vector<Pattern> PatternSet; 00380 00381 //---------------------------------------------------------------------------- 00382 00383 /** Utilities on Patterns. */ 00384 namespace PatternUtil 00385 { 00386 /** Computes how far out this godel code extends from the center point 00387 of the pattern. */ 00388 int GetExtensionFromGodel(int godel); 00389 } 00390 00391 //---------------------------------------------------------------------------- 00392 00393 /** A (pattern, angle) pair. */ 00394 class RotatedPattern 00395 { 00396 public: 00397 RotatedPattern(const Pattern* pat, int angle); 00398 const Pattern* pattern() const; 00399 int angle() const; 00400 00401 private: 00402 const Pattern* m_pattern; 00403 int m_angle; 00404 }; 00405 00406 inline RotatedPattern::RotatedPattern(const Pattern* pat, int angle) 00407 : m_pattern(pat), 00408 m_angle(angle) 00409 { 00410 } 00411 00412 inline const Pattern* RotatedPattern::pattern() const 00413 { 00414 return m_pattern; 00415 } 00416 00417 inline int RotatedPattern::angle() const 00418 { 00419 return m_angle; 00420 } 00421 00422 //---------------------------------------------------------------------------- 00423 00424 /** List of RotatedPatterns. */ 00425 typedef std::vector<RotatedPattern> RotatedPatternList; 00426 00427 //---------------------------------------------------------------------------- 00428 00429 _END_BENZENE_NAMESPACE_ 00430 00431 #endif // PATTERN_H