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; }
void GoLadderUtil::FindLadderEscapeMoves(const GoBoard& bd, SgPoint prey, SgVector<SgPoint>& escapeMoves) { SG_ASSERT(bd.NumLiberties(prey) == 1); SG_ASSERT(escapeMoves.IsEmpty()); SgPoint p = bd.TheLiberty(prey); SgVector<SgPoint> candidates; candidates.PushBack(p); if (IsLadderEscapeMove(bd, prey, p)) escapeMoves.PushBack(p); for (GoAdjBlockIterator<GoBoard> it(bd, prey, 1); it; ++it) { // check if prey can escape by capturing *it on p. SgPoint p = bd.TheLiberty(*it); if (! candidates.Contains(p)) { candidates.PushBack(p); if (IsLadderEscapeMove(bd, prey, p)) escapeMoves.PushBack(p); } } }
bool GoLadderUtil::IsLadderEscapeMove(const GoBoard& constBd, SgPoint prey, SgPoint firstMove) { SG_ASSERT(constBd.NumLiberties(prey) == 1); GoModBoard mbd(constBd); GoBoard& bd = mbd.Board(); const SgBlackWhite defender = bd.GetStone(prey); const SgBlackWhite attacker = SgOppBW(defender); GoRestoreToPlay r(bd); bd.SetToPlay(defender); if (PlayIfLegal(bd, firstMove, defender)) { GoLadder ladder; bool isCapture = ladder.Ladder(bd, prey, attacker, 0, false/*twoLibIsEscape*/ ) < 0; bd.Undo(); return ! isCapture; } else return false; }
bool GoEyeUtil::NumberOfMoveToEye2(const GoBoard& board, SgBlackWhite color, SgPoint p, int& nummoves) { nummoves = 0; bool capturing = false; SgVector<SgPoint> usedpoints; usedpoints.PushBack(p); SgPointSet counted; // Can never turn own stone into an eye if (board.IsColor(p, color)) return false; // If opponent stone then it must be captured to make eye if (board.IsColor(p, SgOppBW(color))) { capturing = true; // If it is obviously safe then it can never be an eye if (SinglePointSafe2(board, p)) // Quick, naive safety test return false; for (GoBoard::LibertyIterator libit(board, p); libit; ++libit) counted.Include(*libit); } // Count immediate adjacencies for (SgNb4Iterator nb(p); nb; ++nb) { SgPoint adj = *nb; // Empty points must be filled if (board.IsColor(adj, SG_EMPTY)) { counted.Include(adj); } // If adjacent opponent then can never be an eye else if (board.IsColor(adj, SgOppBW(color))) { if (capturing) counted.Include(adj); // must capture and then fill else return false; } } // Up to one diagonal can be ignored: estimate most costly SgPoint toignore = SG_NULLPOINT; int maxcost = 0; int infcost = 1000; if (board.Line(p) > 1) { for (SgNb4DiagIterator nbd(p); nbd; ++nbd) { SgPoint diag = *nbd; int cost = 0; if ( board.IsColor(diag, SG_EMPTY) && ! IsSinglePointEye2(board, diag, color, usedpoints)) { cost = 1; } else if (board.IsColor(diag, SgOppBW(color))) { // quick safety test if (SinglePointSafe2(board, diag)) cost = infcost; else cost = board.NumLiberties(diag); } if (cost > maxcost) { maxcost = cost; toignore = diag; } } } // Now mark points that must be played to secure diagonals for (SgNb4DiagIterator nbd(p); nbd; ++nbd) { SgPoint diag = *nbd; if (diag == toignore) continue; // Empty points must be filled (unless they are eyes) if ( board.IsColor(diag, SG_EMPTY) && ! IsSinglePointEye2(board, diag, color, usedpoints)) { counted.Include(diag); } // Opponent stones on diagonals must be captured and filled else if (board.IsColor(diag, SgOppBW(color))) { if (SinglePointSafe2(board, diag)) return false; else { counted.Include(diag); for (GoBoard::LibertyIterator libit(board, diag); libit; ++libit) counted.Include(*libit); } } } nummoves = counted.Size(); return true; }