Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

Pattern.cpp

Go to the documentation of this file.
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 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3