00001 //---------------------------------------------------------------------------- 00002 /** @file Pattern.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "Pattern.hpp" 00007 00008 using namespace benzene; 00009 00010 //---------------------------------------------------------------------------- 00011 00012 Pattern::Pattern() 00013 : m_type(Pattern::UNKNOWN), 00014 m_name("unknown"), 00015 m_flags(0), 00016 m_weight(0) 00017 { 00018 memset(m_slice, 0, sizeof(m_slice)); 00019 } 00020 00021 //---------------------------------------------------------------------------- 00022 00023 std::string Pattern::serialize() const 00024 { 00025 std::ostringstream os; 00026 os << m_type << ":"; 00027 for (int s=0; s<NUM_SLICES; s++) { 00028 for (int a=0; a<NUM_FEATURES; a++) { 00029 if (a) os << ","; 00030 os << (int)m_slice[s][a]; 00031 } 00032 os << ";"; 00033 } 00034 return os.str(); 00035 } 00036 00037 bool Pattern::unserialize(std::string code) 00038 { 00039 std::istringstream ss(code); 00040 char c; 00041 unsigned int i; 00042 00043 #ifndef NDEBUG 00044 // mask of all valid bits in a slice 00045 const unsigned int check = ~((1<<(MAX_EXTENSION*(MAX_EXTENSION+1)/2))-1); 00046 #endif 00047 00048 ss >> c; 00049 m_type = c; 00050 00051 // set the flags based on the type 00052 m_flags = 0; 00053 switch(m_type) { 00054 case MOHEX: 00055 case SHIFT: 00056 m_flags |= HAS_WEIGHT; 00057 break; 00058 } 00059 00060 // parse encoded pattern data 00061 m_extension = 0; 00062 m_moves1.clear(); 00063 m_moves2.clear(); 00064 for (int s=0; s<Pattern::NUM_SLICES; s++) { 00065 00066 // parse each slice 00067 for (int j = 0; j<Pattern::NUM_FEATURES; j++) { 00068 ss >> c; // skips ':', ';', and ',' 00069 ss >> i; 00070 #ifndef NDEBUG 00071 // ensure no bits outside a slice are set 00072 HexAssert((i & check)==0); 00073 #endif 00074 m_slice[s][j] = i; 00075 m_extension = std::max(m_extension, 00076 PatternUtil::GetExtensionFromGodel(i)); 00077 00078 // handle moves encoded in first marked set 00079 if ((i != 0) && (j == FEATURE_MARKED1)) { 00080 m_flags |= HAS_MOVES1; 00081 for (int b=0; b<31; b++) { 00082 if (i & (1U << b)) { 00083 m_moves1.push_back(std::make_pair(s, b)); 00084 } 00085 } 00086 } 00087 00088 // handle moves encoded in second marked set 00089 if ((i != 0) && (j == FEATURE_MARKED2)) { 00090 m_flags |= HAS_MOVES2; 00091 for (int b=0; b<31; b++) { 00092 if (i & (1U << b)) { 00093 m_moves2.push_back(std::make_pair(s, b)); 00094 } 00095 } 00096 } 00097 } 00098 00099 // ensure each feature is a subset of FEATURE_CELLS 00100 HexAssert(BitsetUtil::IsSubsetOf(m_slice[s][FEATURE_BLACK], 00101 m_slice[s][FEATURE_CELLS])); 00102 HexAssert(BitsetUtil::IsSubsetOf(m_slice[s][FEATURE_WHITE], 00103 m_slice[s][FEATURE_CELLS])); 00104 HexAssert(BitsetUtil::IsSubsetOf(m_slice[s][FEATURE_MARKED1], 00105 m_slice[s][FEATURE_CELLS])); 00106 HexAssert(BitsetUtil::IsSubsetOf(m_slice[s][FEATURE_MARKED2], 00107 m_slice[s][FEATURE_CELLS])); 00108 00109 // ensure BLACK does not intersect with WHITE 00110 HexAssert((m_slice[s][FEATURE_BLACK] & m_slice[s][FEATURE_WHITE])==0); 00111 } 00112 00113 if (m_flags & HAS_WEIGHT) { 00114 ss >> c; // skips ':' 00115 ss >> i; 00116 m_weight = i; 00117 } 00118 00119 compute_ring_godel(); 00120 00121 return true; 00122 } 00123 00124 void Pattern::flipColors() 00125 { 00126 for (int s=0; s<NUM_SLICES; s++) { 00127 std::swap(m_slice[s][Pattern::FEATURE_BLACK], 00128 m_slice[s][Pattern::FEATURE_WHITE]); 00129 } 00130 compute_ring_godel(); 00131 } 00132 00133 //---------------------------------------------------------------------------- 00134 00135 void Pattern::mirror() 00136 { 00137 int data[32][32][Pattern::NUM_FEATURES]; 00138 memset(data, 0, sizeof(data)); 00139 00140 // unpack the pattern into the grid centered at (10,10). 00141 // flip the x,y coords of each piece and store its information 00142 for (int s=0; s<NUM_SLICES; s++) { 00143 int fwd = s; 00144 int lft = (s + 2) % NUM_DIRECTIONS; 00145 int x1 = 10 + HexPointUtil::DeltaX(fwd); 00146 int y1 = 10 + HexPointUtil::DeltaY(fwd); 00147 for (int i=1, g=0; i<=Pattern::MAX_EXTENSION; i++) { 00148 int x2 = x1; 00149 int y2 = y1; 00150 for (int j=0; j<i; j++) { 00151 for (int k=0; k<Pattern::NUM_FEATURES; k++) { 00152 data[x2][y2][k] = ((1 << g) & m_slice[s][k]); 00153 // note flipped (y2,x2) on previous line! 00154 } 00155 x2 += HexPointUtil::DeltaX(lft); 00156 y2 += HexPointUtil::DeltaY(lft); 00157 g++; 00158 } 00159 x1 += HexPointUtil::DeltaX(fwd); 00160 y1 += HexPointUtil::DeltaY(fwd); 00161 } 00162 } 00163 00164 // run over it again and reconstruct the flipped pattern information 00165 m_moves1.clear(); 00166 m_moves2.clear(); 00167 memset(m_slice, 0, sizeof(m_slice)); 00168 for (int s=0; s<NUM_SLICES; s++) { 00169 int fwd = s; 00170 int lft = (s + 2) % NUM_DIRECTIONS; 00171 int x1 = 10 + HexPointUtil::DeltaX(fwd); 00172 int y1 = 10 + HexPointUtil::DeltaY(fwd); 00173 for (int i=1, g=0; i<=Pattern::MAX_EXTENSION; i++) { 00174 int x2 = x1; 00175 int y2 = y1; 00176 for (int j=0; j<i; j++) { 00177 for (int k=0; k<Pattern::NUM_FEATURES; k++) { 00178 if (data[y2][x2][k]) { 00179 m_slice[s][k] ^= (1 << g); 00180 if (k == FEATURE_MARKED1) { 00181 m_moves1.push_back(std::make_pair(s, g)); 00182 } 00183 if (k == FEATURE_MARKED2) { 00184 m_moves2.push_back(std::make_pair(s, g)); 00185 } 00186 } 00187 } 00188 x2 += HexPointUtil::DeltaX(lft); 00189 y2 += HexPointUtil::DeltaY(lft); 00190 g++; 00191 } 00192 x1 += HexPointUtil::DeltaX(fwd); 00193 y1 += HexPointUtil::DeltaY(fwd); 00194 } 00195 } 00196 00197 compute_ring_godel(); 00198 } 00199 00200 //---------------------------------------------------------------------------- 00201 00202 void Pattern::compute_ring_godel() 00203 { 00204 for (int i=0; i<NUM_SLICES; i++) { 00205 m_ring_godel[i].SetEmpty(); 00206 00207 for (int s=0; s<NUM_SLICES; s++) { 00208 int j = (i+s)%NUM_SLICES; 00209 00210 if ((m_slice[j][FEATURE_CELLS] & 1) == 1) { 00211 m_ring_godel[i].AddSliceToMask(s); 00212 00213 HexColor color = EMPTY; 00214 if ((m_slice[j][FEATURE_BLACK] & 1) == 1) 00215 color = BLACK; 00216 else if ((m_slice[j][FEATURE_WHITE] & 1) == 1) 00217 color = WHITE; 00218 00219 m_ring_godel[i].SetSliceToColor(s, color); 00220 } 00221 } 00222 } 00223 } 00224 00225 //---------------------------------------------------------------------------- 00226 00227 void Pattern::LoadPatternsFromStream(std::istream& f, 00228 std::vector<Pattern>& out) 00229 { 00230 std::string name; 00231 bool found_name = false; 00232 bool mirror = false; 00233 while (true) { 00234 std::string line; 00235 if (!getline(f, line)) 00236 break; 00237 00238 size_t a = line.find('['); 00239 if (a != std::string::npos) { 00240 if (!found_name) { 00241 size_t b = line.find('/'); 00242 if (b != std::string::npos && b > a) 00243 name = line.substr(a+1,b-a-1); 00244 found_name = true; 00245 } else { 00246 mirror = true; 00247 } 00248 } 00249 00250 if (line[0] == Pattern::DEAD || 00251 line[0] == Pattern::CAPTURED || 00252 line[0] == Pattern::PERMANENTLY_INFERIOR || 00253 line[0] == Pattern::MUTUAL_FILLIN || 00254 line[0] == Pattern::VULNERABLE || 00255 line[0] == Pattern::REVERSIBLE || 00256 line[0] == Pattern::DOMINATED || 00257 line[0] == Pattern::MOHEX || 00258 line[0] == Pattern::SHIFT) 00259 { 00260 Pattern p; 00261 if (p.unserialize(line)) { 00262 p.setName(name); 00263 out.push_back(p); 00264 00265 if (mirror) { 00266 p.mirror(); 00267 p.setName(name + "m"); 00268 out.push_back(p); 00269 } 00270 } 00271 found_name = false; 00272 mirror = false; 00273 } 00274 } 00275 } 00276 00277 void Pattern::LoadPatternsFromFile(const char* filename, 00278 std::vector<Pattern>& out) 00279 { 00280 std::ifstream f(filename); 00281 if (!f) { 00282 LogWarning() 00283 << "Could not open file for reading: '" << filename << "'" 00284 << '\n'; 00285 } 00286 else { 00287 LoadPatternsFromStream(f, out); 00288 } 00289 } 00290 00291 //---------------------------------------------------------------------------- 00292 00293 int PatternUtil::GetExtensionFromGodel(int godel) 00294 { 00295 for (int r=1; r<=Pattern::MAX_EXTENSION; r++) { 00296 int mask = ~((1<<(r*(r+1)/2))-1); 00297 if ((godel & mask) == 0) { 00298 return r; 00299 } 00300 } 00301 HexAssert(false); 00302 return Pattern::MAX_EXTENSION; 00303 } 00304 00305 //----------------------------------------------------------------------------