bool GoEyeUtil::IsSinglePointEye2(const GoBoard& board, SgPoint p, SgBlackWhite color, SgVector<SgPoint>& eyes) { // Must be an empty point if (! board.IsColor(p, SG_EMPTY)) return false; // All adjacent neighbours must be friendly SgBoardColor opp = SgOppBW(color); for (SgNb4Iterator adj(p); adj; ++adj) { SgBoardColor adjColor = board.GetColor(*adj); if (adjColor == opp || adjColor == SG_EMPTY) return false; } // All diagonals (with up to one exception) must be friendly or an eye int baddiags = 0; int maxbaddiags = (board.Line(p) == 1 ? 0 : 1); for (SgNb4DiagIterator it(p); it; ++it) { if (board.IsColor(*it, opp)) ++baddiags; if (board.IsColor(*it, SG_EMPTY) && ! eyes.Contains(*it)) { // Assume this point is an eye and recurse eyes.PushBack(p); if (! IsSinglePointEye2(board, *it, color, eyes)) ++baddiags; eyes.PopBack(); } if (baddiags > maxbaddiags) return false; } return true; }
SgPoint GoGtpCommandUtil::StoneArg(const GtpCommand& cmd, std::size_t number, const GoBoard& board) { SgPoint point = PointArg(cmd, number, board); if (board.GetColor(point) == SG_EMPTY) throw GtpFailure() << "point " << SgWritePoint(point) << " must be occupied"; return point; }
void GoGtpCommandUtil::ParseMultiStoneArgument(GtpCommand& cmd, const GoBoard& board, SgBlackWhite& toPlay, SgBlackWhite& defender, SgVector<SgPoint>& crucial) { toPlay = GoGtpCommandUtil::BlackWhiteArg(cmd, 0); SgDebug() << "Set " << SgBW(toPlay) << " to play\n"; SgPoint point = GoGtpCommandUtil::StoneArg(cmd, 1, board); defender = board.GetColor(point); SG_ASSERT(defender == SG_BLACK || defender == SG_WHITE); crucial.PushBack(point); for (size_t i = 2; i < cmd.NuArg(); ++i) { SgPoint p = GoGtpCommandUtil::StoneArg(cmd, i, board); if (board.GetColor(p) != defender) throw GtpFailure("Crucial stones must be same color"); else crucial.PushBack(p); } }
GoSetup GoSetupUtil::CurrentPosSetup(const GoBoard& bd) { GoSetup setup; setup.m_player = bd.ToPlay(); for (GoBoard::Iterator it2(bd); it2; ++it2) { SgPoint p = *it2; if (bd.Occupied(p)) setup.m_stones[bd.GetColor(p)].Include(p); } return setup; }
int GoEyeUtil::CountSinglePointEyes2(const GoBoard& board, SgPoint p) { if (! board.Occupied(p)) return 0; SgBlackWhite color = board.GetColor(p); int numeyes = 0; for (GoBoard::LibertyIterator lib(board, p); lib; ++lib) { if (IsSinglePointEye2(board, *lib, color)) numeyes++; } return numeyes; }
bool GoEyeUtil::CheckInterior(const GoBoard& bd, const SgPointSet& area, SgBlackWhite opp, bool checkBlocks) { bool hasSingleNbPoint = false; int nuPoints = 0; for (SgSetIterator it(area); it; ++it) { const SgPoint p(*it); if (bd.IsEmpty(p)) { int nuNbs = 0; if (area.Contains(p + SG_NS)) ++nuNbs; if (area.Contains(p - SG_NS)) ++nuNbs; if (area.Contains(p + SG_WE)) ++nuNbs; if (area.Contains(p - SG_WE)) ++nuNbs; if (nuNbs == 1) hasSingleNbPoint = true; else if (nuNbs > 2) return false; } else if (p == bd.Anchor(p)) { if (bd.GetColor(p) != opp) // if own stones on inside: not a tree shape. return false; int nuLibs = bd.NumLiberties(p); if (nuLibs == 1) hasSingleNbPoint = true; else if (checkBlocks && nuLibs > 2) return false; } ++nuPoints; } return nuPoints == 1 || hasSingleNbPoint; }
bool GoEyeUtil::IsPossibleEye(const GoBoard& board, SgBlackWhite color, SgPoint p) { bool isPossibleEye = false; SG_ASSERT(board.GetColor(p) != color); const SgBlackWhite opp = SgOppBW(color); if (board.Line(p) == 1) // corner or edge { const int nuOwn = (board.Pos(p) == 1) ? 2 : 4; if ( board.Num8Neighbors(p, color) == nuOwn && board.Num8EmptyNeighbors(p) == 1 ) { isPossibleEye = true; } } else // in center { // have all neighbors, and 2 diagonals, and can get a third if ( board.NumNeighbors(p, color) == 4 && board.NumDiagonals(p, color) == 2 && board.NumEmptyDiagonals(p) > 0 ) { isPossibleEye = true; } // have 3 of 4 neighbors, can get the 4th, and have enough diagonals else if ( board.NumNeighbors(p, color) == 3 && board.NumNeighbors(p, opp) == 0 && board.NumDiagonals(p, color) >= 3 ) { isPossibleEye = true; } } return isPossibleEye; }