/** Find global moves that match a playout pattern or set a block into atari. @param[out] pattern @param[out] atari @param[out] empty As a side effect, this function finds all empty points on the board @return @c true if any such moves was found */ bool GoUctDefaultPriorKnowledge::FindGlobalPatternAndAtariMoves( SgPointSet& pattern, SgPointSet& atari, GoPointList& empty) { // Minimum value for pattern gamma to be used. static const float EPSILON = 0.00000000001; const GoBoard& bd = Board(); SG_ASSERT(empty.IsEmpty()); const GoUctPatterns<GoBoard>& patterns = m_policy.GlobalPatterns(); bool result = false; m_maxPatternGamma = -1.f; for (GoBoard::Iterator it(bd); it; ++it) if (bd.IsEmpty(*it)) { empty.PushBack(*it); float gamma = patterns.GetPatternGamma(bd, *it, bd.ToPlay()); if (gamma > EPSILON) { pattern.Include(*it); result = true; m_patternGammas[*it] = gamma; if (gamma > m_maxPatternGamma) m_maxPatternGamma = gamma; } if (SetsAtari(bd, *it)) { atari.Include(*it); result = true; } } return result; }
void GoLadder::ReduceToBlocks(GoPointList& stones) { // Single block is frequent case, don't compute block. if (stones.IsEmpty()) ; // nothing to do else if (stones.Length() <= 1) { if (m_bd->IsEmpty(stones[0])) stones.Clear(); } else { GoPointList visited; // TODO: create SgMarker member in GoLadder and use it for visited // points GoPointList result; for (GoPointList::Iterator it(stones); it; ++it) { SgPoint stone = *it; if (m_bd->Occupied(stone) && ! visited.Contains(stone)) { result.PushBack(stone); for (GoBoard::StoneIterator it(*m_bd, stone); it; ++it) visited.PushBack(*it); } } stones = result; } }
/** Find global moves that match a playout pattern or set a block into atari. @param[out] pattern @param[out] atari @param[out] empty As a side effect, this function finds all empty points on the board @return @c true if any such moves was found */ bool GoUctDefaultPriorKnowledge::FindGlobalPatternAndAtariMoves( SgPointSet& pattern, SgPointSet& atari, GoPointList& empty) const { SG_ASSERT(empty.IsEmpty()); const GoUctPatterns<GoBoard>& patterns = m_policy.Patterns(); bool result = false; for (GoBoard::Iterator it(m_bd); it; ++it) if (m_bd.IsEmpty(*it)) { empty.PushBack(*it); if (patterns.MatchAny(*it)) { pattern.Include(*it); result = true; } if (SetsAtari(m_bd, *it)) { atari.Include(*it); result = true; } } return result; }
int GoLadder::HunterLadder(int depth, SgPoint lib1, SgPoint lib2, const GoPointList& adjBlk, SgVector<SgPoint>* sequence) { if (CheckMoveOverflow()) return GOOD_FOR_PREY; int result = 0; if (m_bd->NumEmptyNeighbors(lib1) < m_bd->NumEmptyNeighbors(lib2)) { swap(lib1, lib2); } if (m_bd->NumEmptyNeighbors(lib1) == 3 && ! SgPointUtil::AreAdjacent(lib1, lib2)) { // If not playing at lib1, then prey will play at lib1 and // get three liberties; little to update in this case. m_bd->Play(lib1, m_hunterColor); result = PreyLadder(depth + 1, lib2, adjBlk, sequence); if (sequence) sequence->PushBack(lib1); m_bd->Undo(); } else { // Two liberties, hunter to play, but not standard case. if (! adjBlk.IsEmpty() && *GoBoard::LibertyIterator(*m_bd, adjBlk[0]) == lib2) { swap(lib1, lib2); // protect hunter blocks in atari } result = PlayHunterMove(depth, lib1, lib1, lib2, adjBlk, sequence); if (0 <= result) // escaped { if (sequence) { SgVector<SgPoint> seq2; int result2 = PlayHunterMove(depth, lib2, lib1, lib2, adjBlk, &seq2); if (result2 < result) { result = result2; sequence->SwapWith(&seq2); } } else { int result2 = PlayHunterMove(depth, lib2, lib1, lib2, adjBlk, 0); if (result2 < result) result = result2; } } } return result; }