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