SgMove GoAutoBook::FindBestChild(GoAutoBookState& state) const { std::size_t bestCount = 0; SgMove bestMove = SG_NULLMOVE; SgMove bestIgnoredMove = SG_NULLMOVE; float bestScore = 100.0f; float bestIgnoredMoveScore = 100.0f; SgBookNode node; // Check for forced moves first // Note this will check for forced moves even if the current // state is not in the book. for (GoBoard::Iterator it(state.Board()); it; ++it) { if (state.Board().IsLegal(*it)) { state.Play(*it); if (m_forced.count(state.GetHashCode()) > 0) { SgDebug() << "Playing forced move " << SgWritePoint(*it) << '\n'; return *it; } state.Undo(); } } if (! Get(state, node)) return SG_NULLMOVE; if (node.IsLeaf()) return SG_NULLMOVE; for (GoBoard::Iterator it(state.Board()); it; ++it) { if (state.Board().IsLegal(*it)) { state.Play(*it); if (m_disabled.count(state.GetHashCode()) > 0) SgDebug() << "Ignoring disabled move " << SgWritePoint(*it) << '\n'; // NOTE: Terminal nodes aren't supported at this time, so // we ignore them here. else if ( Get(state, node) && ! node.IsTerminal() ) { if (node.m_count >= m_param.m_usageCountThreshold) { if (m_param.m_selectType == GO_AUTOBOOK_SELECT_COUNT) { // Select by count, tiebreak by value. if (node.m_count > bestCount) { bestCount = node.m_count; bestMove = *it; bestScore = node.m_value; } // NOTE: do not have access to inverse function, // so we're minimizing here as a temporary solution. else if (node.m_count == bestCount && node.m_value < bestScore) { bestMove = *it; bestScore = node.m_value; } } else if (m_param.m_selectType == GO_AUTOBOOK_SELECT_VALUE) { // NOTE: do not have access to inverse function, // so we're minimizing here as a temporary solution. if (node.m_value < bestScore) { bestMove = *it; bestScore = node.m_value; } } } else // node.m_count < m_param.m_usageCountThreshold if ( m_param.m_selectType == GO_AUTOBOOK_SELECT_VALUE && node.m_value < bestIgnoredMoveScore ) { bestIgnoredMove = *it; bestIgnoredMoveScore = node.m_value; } } state.Undo(); } } if (bestMove != SG_NULLMOVE && bestIgnoredMoveScore < bestScore) { SgDebug() << "Ignoring autobook move " << SgWritePoint(bestMove) << " since best ignored inverse value " << std::setprecision(5) << bestIgnoredMoveScore << " of move " << SgWritePoint(bestIgnoredMove) << " is better than best value above usage threshold " << bestScore << '\n'; return SG_NULLMOVE; } return bestMove; }
std::ostream& operator<<(std::ostream& out, GoPlayerMove mv) { out << (mv.Color() == SG_BLACK ? "B " : "W ") << SgWritePoint(mv.Point()); return out; }
void GoChain::WriteID(std::ostream& stream) const { stream << ' '<< SgBW(Color()) << " GoChain " << SgWritePoint(Anchor()); }
void GoBlock::WriteID(std::ostream& stream) const { stream << ' ' << SgBW(Color()) << " Block " << SgWritePoint(Anchor()); }