00001
00002
00003
00004
00005
00006 #ifndef GOUCT_PATTERNS_H
00007 #define GOUCT_PATTERNS_H
00008
00009 #include "GoBoard.h"
00010 #include "GoBoardUtil.h"
00011 #include "SgBoardColor.h"
00012 #include "SgBWArray.h"
00013 #include "SgPoint.h"
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 template<class BOARD>
00062 class GoUctPatterns
00063 {
00064 public:
00065 GoUctPatterns(const BOARD& bd);
00066
00067
00068 bool MatchAny(SgPoint p) const;
00069
00070 private:
00071
00072 static const int GOUCT_POWER3_5 = 3 * 3 * 3 * 3 * 3;
00073
00074
00075 static const int GOUCT_POWER3_8 = 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3;
00076
00077
00078 typedef SgArray<bool, GOUCT_POWER3_5> GoUctEdgePatternTable;
00079
00080
00081 typedef SgArray<bool, GOUCT_POWER3_8> GoUctPatternTable;
00082
00083 const BOARD& m_bd;
00084
00085
00086 SgBWArray<GoUctPatternTable> m_table;
00087
00088
00089 SgBWArray<GoUctEdgePatternTable> m_edgeTable;
00090
00091 static bool CheckCut1(const GoBoard& bd, SgPoint p, SgBlackWhite c,
00092 int cDir, int otherDir);
00093
00094 static bool CheckCut2(const GoBoard& bd, SgPoint p, const SgBlackWhite c,
00095 int cDir, int otherDir);
00096
00097 static bool CheckHane1(const GoBoard& bd, SgPoint p, SgBlackWhite c,
00098 SgBlackWhite opp, int cDir, int otherDir);
00099
00100 static int CodeOf8Neighbors(const BOARD& bd, SgPoint p);
00101
00102 static int CodeOfEdgeNeighbors(const BOARD& bd, SgPoint p);
00103
00104 static int EdgeDirection(GoBoard& bd, SgPoint p, int index);
00105
00106 static int EBWCodeOfPoint(const BOARD& bd, SgPoint p);
00107
00108 static int FindDir(const GoBoard& bd, SgPoint p, SgBlackWhite c);
00109
00110 static void InitCenterPatternTable(SgBWArray<GoUctPatternTable>& table);
00111
00112 static void InitEdgePatternTable(SgBWArray<GoUctEdgePatternTable>&
00113 edgeTable);
00114
00115 static bool MatchCut(const GoBoard& bd, SgPoint p);
00116
00117 static bool MatchEdge(const GoBoard& bd, SgPoint p, const int nuBlack,
00118 const int nuWhite);
00119
00120 static bool MatchHane(const GoBoard& bd, SgPoint p, const int nuBlack,
00121 const int nuWhite);
00122
00123 static bool MatchAnyPattern(const GoBoard& bd, SgPoint p);
00124
00125 static int OtherDir(int dir);
00126
00127 static int SetupCodedEdgePosition(GoBoard& bd, int code);
00128
00129 static int SetupCodedPosition(GoBoard& bd, int code);
00130
00131
00132 bool MatchAnyCenter(SgPoint p) const;
00133
00134
00135 bool MatchAnyEdge(SgPoint p) const;
00136 };
00137
00138 template<class BOARD>
00139 GoUctPatterns<BOARD>::GoUctPatterns(const BOARD& bd)
00140 : m_bd(bd)
00141 {
00142 InitCenterPatternTable(m_table);
00143 InitEdgePatternTable(m_edgeTable);
00144 }
00145
00146 template<class BOARD>
00147 bool GoUctPatterns<BOARD>::CheckHane1(const GoBoard& bd, SgPoint p,
00148 SgBlackWhite c, SgBlackWhite opp,
00149 int cDir, int otherDir)
00150 {
00151 return bd.IsColor(p + cDir, c)
00152 && bd.IsColor(p + cDir + otherDir, opp)
00153 && bd.IsColor(p + cDir - otherDir, opp)
00154 && bd.IsEmpty(p + otherDir)
00155 && bd.IsEmpty(p - otherDir)
00156 ;
00157 }
00158
00159 template<class BOARD>
00160 bool GoUctPatterns<BOARD>::CheckCut1(const GoBoard& bd, SgPoint p,
00161 SgBlackWhite c, int cDir, int otherDir)
00162 {
00163 SG_ASSERT_BW(c);
00164 return bd.IsColor(p + otherDir, c)
00165 && bd.IsColor(p + cDir + otherDir, SgOppBW(c));
00166 }
00167
00168 template<class BOARD>
00169 bool GoUctPatterns<BOARD>::CheckCut2(const GoBoard& bd, SgPoint p,
00170 const SgBlackWhite c, int cDir,
00171 int otherDir)
00172 {
00173 SG_ASSERT_BW(c);
00174 SG_ASSERT(bd.IsColor(p + cDir, c));
00175 const SgBlackWhite opp = SgOppBW(c);
00176 return bd.IsColor(p - cDir, c)
00177 && ( ( bd.IsColor(p + otherDir, opp)
00178 && ! bd.IsColor(p - otherDir + cDir, c)
00179 && ! bd.IsColor(p - otherDir - cDir, c)
00180 )
00181 ||
00182 ( bd.IsColor(p - otherDir, opp)
00183 && ! bd.IsColor(p + otherDir + cDir, c)
00184 && ! bd.IsColor(p + otherDir - cDir, c)
00185 )
00186 );
00187 }
00188
00189 template<class BOARD>
00190 inline int GoUctPatterns<BOARD>::CodeOf8Neighbors(const BOARD& bd, SgPoint p)
00191 {
00192 SG_ASSERT(bd.Line(p) > 1);
00193 int code = (((((( EBWCodeOfPoint(bd, p - SG_NS - SG_WE) * 3
00194 + EBWCodeOfPoint(bd, p - SG_NS)) * 3
00195 + EBWCodeOfPoint(bd, p - SG_NS + SG_WE)) * 3
00196 + EBWCodeOfPoint(bd, p - SG_WE)) * 3
00197 + EBWCodeOfPoint(bd, p + SG_WE)) * 3
00198 + EBWCodeOfPoint(bd, p + SG_NS - SG_WE)) * 3
00199 + EBWCodeOfPoint(bd, p + SG_NS)) * 3
00200 + EBWCodeOfPoint(bd, p + SG_NS + SG_WE);
00201 SG_ASSERT(code >= 0);
00202 SG_ASSERT(code < GOUCT_POWER3_8);
00203 return code;
00204 }
00205
00206 template<class BOARD>
00207 inline int GoUctPatterns<BOARD>::CodeOfEdgeNeighbors(const BOARD& bd,
00208 SgPoint p)
00209 {
00210 SG_ASSERT(bd.Line(p) == 1);
00211 SG_ASSERT(bd.Pos(p) > 1);
00212 const int up = bd.Up(p);
00213 const int other = OtherDir(up);
00214 int code = (((EBWCodeOfPoint(bd, p + other) * 3
00215 + EBWCodeOfPoint(bd, p + up + other)) * 3
00216 + EBWCodeOfPoint(bd, p + up)) * 3
00217 + EBWCodeOfPoint(bd, p + up - other)) * 3
00218 + EBWCodeOfPoint(bd, p - other);
00219 SG_ASSERT(code >= 0);
00220 SG_ASSERT(code < GOUCT_POWER3_5);
00221 return code;
00222 }
00223
00224 template<class BOARD>
00225 inline int GoUctPatterns<BOARD>::EBWCodeOfPoint(const BOARD& bd, SgPoint p)
00226 {
00227 SG_ASSERT(bd.IsValidPoint(p));
00228 BOOST_STATIC_ASSERT(SG_BLACK == 0);
00229 BOOST_STATIC_ASSERT(SG_WHITE == 1);
00230 BOOST_STATIC_ASSERT(SG_EMPTY == 2);
00231 return bd.GetColor(p);
00232 }
00233
00234 template<class BOARD>
00235 int GoUctPatterns<BOARD>::EdgeDirection(GoBoard& bd, SgPoint p, int index)
00236 {
00237 const int up = bd.Up(p);
00238 switch (index)
00239 {
00240 case 0:
00241 return OtherDir(up);
00242 case 1:
00243 return up + OtherDir(up);
00244 case 2:
00245 return up;
00246 case 3:
00247 return up - OtherDir(up);
00248 default:
00249 SG_ASSERT(index == 4);
00250 return - OtherDir(up);
00251 }
00252 }
00253
00254
00255 template<class BOARD>
00256 int GoUctPatterns<BOARD>::FindDir(const GoBoard& bd, SgPoint p,
00257 SgBlackWhite c)
00258 {
00259 if (bd.IsColor(p + SG_NS, c))
00260 return SG_NS;
00261 if (bd.IsColor(p - SG_NS, c))
00262 return -SG_NS;
00263 if (bd.IsColor(p + SG_WE, c))
00264 return SG_WE;
00265 SG_ASSERT(bd.IsColor(p - SG_WE, c));
00266 return -SG_WE;
00267 }
00268
00269 template<class BOARD>
00270 void GoUctPatterns<BOARD>::InitEdgePatternTable(
00271 SgBWArray<GoUctEdgePatternTable>& edgeTable)
00272 {
00273 GoBoard bd(5);
00274 const SgPoint p = SgPointUtil::Pt(1, 3);
00275 for (int i = 0; i < GOUCT_POWER3_5; ++i)
00276 {
00277 int count = SetupCodedEdgePosition(bd, i);
00278 for(SgBWIterator it; it; ++it)
00279 {
00280 bd.SetToPlay(*it);
00281 edgeTable[*it][i] = MatchAnyPattern(bd, p) ? 1 : 0;
00282 }
00283 while (count-- > 0)
00284 bd.Undo();
00285 }
00286 }
00287
00288 template<class BOARD>
00289 void GoUctPatterns<BOARD>::InitCenterPatternTable(
00290 SgBWArray<GoUctPatternTable>& table)
00291 {
00292 GoBoard bd(5);
00293 const SgPoint p = SgPointUtil::Pt(3, 3);
00294 for (int i = 0; i < GOUCT_POWER3_8; ++i)
00295 {
00296 int count = SetupCodedPosition(bd, i);
00297 for(SgBWIterator it; it; ++it)
00298 {
00299 bd.SetToPlay(*it);
00300 table[*it][i] = MatchAnyPattern(bd, p) ? 1 : 0;
00301 }
00302 while (count-- > 0)
00303 bd.Undo();
00304 }
00305 }
00306
00307 template<class BOARD>
00308 bool GoUctPatterns<BOARD>::MatchCut(const GoBoard& bd, SgPoint p)
00309 {
00310 if (bd.Num8EmptyNeighbors(p) > 6)
00311 return false;
00312
00313 const int nuEmpty = bd.NumEmptyNeighbors(p);
00314
00315 const SgEmptyBlackWhite c1 = bd.GetColor(p + SG_NS);
00316 if ( c1 != SG_EMPTY
00317 && bd.NumNeighbors(p, c1) >= 2
00318 && ! (bd.NumNeighbors(p, c1) == 3 && nuEmpty == 1)
00319 && ( CheckCut1(bd, p, c1, SG_NS, SG_WE)
00320 || CheckCut1(bd, p, c1, SG_NS, -SG_WE)
00321 )
00322 )
00323 return true;
00324 const SgEmptyBlackWhite c2 = bd.GetColor(p - SG_NS);
00325 if ( c2 != SG_EMPTY
00326 && bd.NumNeighbors(p, c2) >= 2
00327 && ! (bd.NumNeighbors(p, c2) == 3 && nuEmpty == 1)
00328 && ( CheckCut1(bd, p, c2, -SG_NS, SG_WE)
00329 || CheckCut1(bd, p, c2, -SG_NS, -SG_WE)
00330 )
00331 )
00332 return true;
00333
00334 if ( c1 != SG_EMPTY
00335 && bd.NumNeighbors(p, c1) == 2
00336 && bd.NumNeighbors(p, SgOppBW(c1)) > 0
00337 && bd.NumDiagonals(p, c1) <= 2
00338 && CheckCut2(bd, p, c1, SG_NS, SG_WE)
00339 )
00340 return true;
00341 const SgEmptyBlackWhite c3 = bd.GetColor(p + SG_WE);
00342 if ( c3 != SG_EMPTY
00343 && bd.NumNeighbors(p, c3) == 2
00344 && bd.NumNeighbors(p, SgOppBW(c3)) > 0
00345 && bd.NumDiagonals(p, c3) <= 2
00346 && CheckCut2(bd, p, c3, SG_WE, SG_NS)
00347 )
00348 return true;
00349 return false;
00350 }
00351
00352 template<class BOARD>
00353 bool GoUctPatterns<BOARD>::MatchEdge(const GoBoard& bd, SgPoint p,
00354 const int nuBlack, const int nuWhite)
00355 {
00356 const int up = bd.Up(p);
00357 const int side = OtherDir(up);
00358 const int nuEmpty = bd.NumEmptyNeighbors(p);
00359 const SgEmptyBlackWhite upColor = bd.GetColor(p + up);
00360
00361 if ( nuEmpty > 0
00362 && (nuBlack > 0 || nuWhite > 0)
00363 && upColor == SG_EMPTY
00364 )
00365 {
00366 const SgEmptyBlackWhite c1 = bd.GetColor(p + side);
00367 if (c1 != SG_EMPTY && bd.GetColor(p + side + up) == SgOppBW(c1))
00368 return true;
00369 const SgEmptyBlackWhite c2 = bd.GetColor(p - side);
00370 if (c2 != SG_EMPTY && bd.GetColor(p - side + up) == SgOppBW(c2))
00371 return true;
00372 }
00373
00374
00375 if ( upColor != SG_EMPTY
00376 && ( (upColor == SG_BLACK && nuBlack == 1 && nuWhite > 0)
00377 || (upColor == SG_WHITE && nuWhite == 1 && nuBlack > 0)
00378 )
00379 )
00380 return true;
00381
00382 const SgBlackWhite toPlay = bd.ToPlay();
00383
00384 if ( upColor == toPlay
00385 && bd.NumDiagonals(p, SgOppBW(upColor)) > 0
00386 )
00387 return true;
00388
00389
00390 if ( upColor == SgOppBW(toPlay)
00391 && bd.NumNeighbors(p, upColor) <= 2
00392 && bd.NumDiagonals(p, toPlay) > 0
00393 )
00394 {
00395 if ( bd.GetColor(p + side + up) == toPlay
00396 && bd.GetColor(p + side) != upColor
00397 )
00398 return true;
00399 if ( bd.GetColor(p - side + up) == toPlay
00400 && bd.GetColor(p - side) != upColor
00401 )
00402 return true;
00403 }
00404
00405 if ( upColor == SgOppBW(toPlay)
00406 && bd.NumNeighbors(p, upColor) == 2
00407 && bd.NumNeighbors(p, toPlay) == 1
00408 )
00409 {
00410 if ( bd.GetColor(p + side + up) == toPlay
00411 && bd.GetColor(p + side) == upColor
00412 )
00413 return true;
00414 if ( bd.GetColor(p - side + up) == toPlay
00415 && bd.GetColor(p - side) == upColor
00416 )
00417 return true;
00418 }
00419 return false;
00420 }
00421
00422 template<class BOARD>
00423 bool GoUctPatterns<BOARD>::MatchHane(const GoBoard& bd, SgPoint p,
00424 const int nuBlack, const int nuWhite)
00425 {
00426 const int nuEmpty = bd.NumEmptyNeighbors(p);
00427 if (nuEmpty < 2 || nuEmpty > 3)
00428 return false;
00429 if ( (nuBlack < 1 || nuBlack > 2)
00430 && (nuWhite < 1 || nuWhite > 2)
00431 )
00432 return false;
00433 if (nuEmpty == 2)
00434 {
00435 if (nuBlack == 1 && nuWhite == 1)
00436 {
00437 const int dirB = FindDir(bd, p, SG_BLACK);
00438 const int dirW = FindDir(bd, p, SG_WHITE);
00439 if (! bd.IsEmpty(p + dirB + dirW))
00440 return true;
00441 }
00442 }
00443 else if (nuEmpty == 3)
00444 {
00445 SG_ASSERT(nuBlack + nuWhite == 1);
00446 const SgBlackWhite col = (nuBlack == 1) ? SG_BLACK : SG_WHITE;
00447 const SgBlackWhite opp = SgOppBW(col);
00448 const int dir = FindDir(bd, p, col);
00449 const int otherDir = OtherDir(dir);
00450 if ( bd.IsEmpty(p + dir + otherDir)
00451 && bd.IsColor(p + dir - otherDir, opp)
00452 )
00453 return true;
00454 if ( bd.IsEmpty(p + dir - otherDir)
00455 && bd.IsColor(p + dir + otherDir, opp)
00456 )
00457 return true;
00458 if (bd.ToPlay() == opp)
00459 {
00460 const SgEmptyBlackWhite c1 = bd.GetColor(p + dir + otherDir);
00461 if (c1 != SG_EMPTY)
00462 {
00463 const SgEmptyBlackWhite c2 =
00464 bd.GetColor(p + dir - otherDir);
00465 if (SgOppBW(c1) == c2)
00466 return true;
00467 }
00468 }
00469 }
00470
00471
00472 const int nuBlackDiag = bd.NumDiagonals(p, SG_BLACK);
00473 if ( nuBlackDiag >= 2
00474 && nuWhite > 0
00475 && ( CheckHane1(bd, p, SG_WHITE, SG_BLACK, SG_NS, SG_WE)
00476 || CheckHane1(bd, p, SG_WHITE, SG_BLACK, -SG_NS, SG_WE)
00477 || CheckHane1(bd, p, SG_WHITE, SG_BLACK, SG_WE, SG_NS)
00478 || CheckHane1(bd, p, SG_WHITE, SG_BLACK, -SG_WE, SG_NS)
00479 )
00480 )
00481 return true;
00482 const int nuWhiteDiag = bd.NumDiagonals(p, SG_WHITE);
00483 if ( nuWhiteDiag >= 2
00484 && nuBlack > 0
00485 && ( CheckHane1(bd, p, SG_BLACK, SG_WHITE, SG_NS, SG_WE)
00486 || CheckHane1(bd, p, SG_BLACK, SG_WHITE, -SG_NS, SG_WE)
00487 || CheckHane1(bd, p, SG_BLACK, SG_WHITE, SG_WE, SG_NS)
00488 || CheckHane1(bd, p, SG_BLACK, SG_WHITE, -SG_WE, SG_NS)
00489 )
00490 )
00491 return true;
00492 return false;
00493 }
00494
00495 template<class BOARD>
00496 inline bool GoUctPatterns<BOARD>::MatchAnyCenter(SgPoint p) const
00497 {
00498 return m_table[m_bd.ToPlay()][CodeOf8Neighbors(m_bd, p)];
00499 }
00500
00501 template<class BOARD>
00502 inline bool GoUctPatterns<BOARD>::MatchAnyEdge(SgPoint p) const
00503 {
00504 return m_edgeTable[m_bd.ToPlay()][CodeOfEdgeNeighbors(m_bd, p)];
00505 }
00506
00507 template<class BOARD>
00508 inline bool GoUctPatterns<BOARD>::MatchAny(SgPoint p) const
00509 {
00510
00511
00512 if ( m_bd.NumNeighbors(p, SG_BLACK) == 0
00513 && m_bd.NumNeighbors(p, SG_WHITE) == 0
00514 )
00515 return false;
00516 if (m_bd.Line(p) > 1)
00517 return MatchAnyCenter(p);
00518 else if (m_bd.Pos(p) > 1)
00519 return MatchAnyEdge(p);
00520 else
00521 return false;
00522 }
00523
00524
00525 template<class BOARD>
00526 bool GoUctPatterns<BOARD>::MatchAnyPattern(const GoBoard& bd, SgPoint p)
00527 {
00528 SG_ASSERT(bd.IsEmpty(p));
00529 const int nuBlack = bd.NumNeighbors(p, SG_BLACK);
00530 const int nuWhite = bd.NumNeighbors(p, SG_WHITE);
00531
00532
00533
00534 if (nuBlack == 0 && nuWhite == 0)
00535 return false;
00536
00537
00538 if (bd.Pos(p) == 1)
00539 return false;
00540 if (bd.Line(p) == 1)
00541 return MatchEdge(bd, p, nuBlack, nuWhite);
00542 else
00543 return MatchHane(bd, p, nuBlack, nuWhite)
00544 || MatchCut(bd, p);
00545 }
00546
00547 template<class BOARD>
00548 inline int GoUctPatterns<BOARD>::OtherDir(int dir)
00549 {
00550 if (dir == SG_NS || dir == -SG_NS)
00551 return SG_WE;
00552 return SG_NS;
00553 }
00554
00555 template<class BOARD>
00556 int GoUctPatterns<BOARD>::SetupCodedEdgePosition(GoBoard& bd, int code)
00557 {
00558 const SgPoint p = SgPointUtil::Pt(1, 3);
00559 int count = 0;
00560 for (int i = 4; i >= 0; --i)
00561 {
00562 const SgPoint nb = p + EdgeDirection(bd, p, i);
00563 int c = code % 3;
00564 code /= 3;
00565 if (c != SG_EMPTY)
00566 {
00567 ++count;
00568 bd.Play(nb, c);
00569 }
00570 }
00571 return count;
00572 }
00573
00574 template<class BOARD>
00575 int GoUctPatterns<BOARD>::SetupCodedPosition(GoBoard& bd, int code)
00576 {
00577 const SgPoint p = SgPointUtil::Pt(3, 3);
00578 int count = 0;
00579 for (int i = 7; i >= 0; --i)
00580 {
00581 const SgPoint nb = p + SgNb8Iterator::Direction(i);
00582 int c = code % 3;
00583 code /= 3;
00584 if (c != SG_EMPTY)
00585 {
00586 ++count;
00587 bd.Play(nb, c);
00588 }
00589 }
00590 return count;
00591 }
00592
00593
00594
00595 #endif // GOUCT_PATTERNS_H