00001
00002
00003
00004
00005
00006 #include "SgSystem.h"
00007 #include "GoUctDefaultPriorKnowledge.h"
00008
00009 using namespace std;
00010
00011
00012
00013 namespace {
00014
00015 bool SetsAtari(const GoBoard& bd, SgPoint p)
00016 {
00017 SG_ASSERT(bd.IsEmpty(p));
00018 SgBlackWhite opp = SgOppBW(bd.ToPlay());
00019 if (bd.NumNeighbors(p, opp) == 0)
00020 return false;
00021 if (! bd.IsBorder(p + SG_NS) && bd.GetColor(p + SG_NS) == opp
00022 && bd.NumLiberties(p + SG_NS) == 2)
00023 return true;
00024 if (! bd.IsBorder(p - SG_NS) && bd.GetColor(p - SG_NS) == opp
00025 && bd.NumLiberties(p - SG_NS) == 2)
00026 return true;
00027 if (! bd.IsBorder(p + SG_WE) && bd.GetColor(p + SG_WE) == opp
00028 && bd.NumLiberties(p + SG_WE) == 2)
00029 return true;
00030 if (! bd.IsBorder(p - SG_WE) && bd.GetColor(p - SG_WE) == opp
00031 && bd.NumLiberties(p - SG_WE) == 2)
00032 return true;
00033 return false;
00034 }
00035
00036 }
00037
00038
00039
00040 GoUctKnowledge::GoUctKnowledge(const GoBoard& bd)
00041 : m_bd(bd)
00042 {
00043 }
00044
00045 GoUctKnowledge::~GoUctKnowledge()
00046 {
00047 }
00048
00049 void GoUctKnowledge::Add(SgPoint p, SgUctValue value, SgUctValue count)
00050 {
00051 m_values[p].Add(value, count);
00052 }
00053
00054 void GoUctKnowledge::Initialize(SgPoint p, SgUctValue value, SgUctValue count)
00055 {
00056 m_values[p].Initialize(value, count);
00057 }
00058
00059 void GoUctKnowledge::ClearValues()
00060 {
00061 for (int i = 0; i < SG_PASS + 1; ++i)
00062 m_values[i].Clear();
00063 }
00064
00065 void GoUctKnowledge::TransferValues(std::vector<SgUctMoveInfo>& outmoves) const
00066 {
00067 for (std::size_t i = 0; i < outmoves.size(); ++i)
00068 {
00069 SgMove p = outmoves[i].m_move;
00070 if (m_values[p].IsDefined())
00071 {
00072 outmoves[i].m_count = m_values[p].Count();
00073 outmoves[i].m_value =
00074 SgUctSearch::InverseEstimate(m_values[p].Mean());
00075 outmoves[i].m_raveCount = m_values[p].Count();
00076 outmoves[i].m_raveValue = m_values[p].Mean();
00077 }
00078 }
00079 }
00080
00081
00082
00083 GoUctDefaultPriorKnowledge::GoUctDefaultPriorKnowledge(const GoBoard& bd,
00084 const GoUctPlayoutPolicyParam& param)
00085 : GoUctKnowledge(bd),
00086 m_policy(bd, param)
00087 {
00088 }
00089
00090 void GoUctDefaultPriorKnowledge::AddLocalityBonus(GoPointList& emptyPoints,
00091 bool isSmallBoard)
00092 {
00093 SgPoint last = m_bd.GetLastMove();
00094 if (last != SG_NULLMOVE && last != SG_PASS)
00095 {
00096 SgPointArray<int> dist = GoBoardUtil::CfgDistance(m_bd, last, 3);
00097 const SgUctValue count = (isSmallBoard ? 4 : 5);
00098 for (GoPointList::Iterator it(emptyPoints); it; ++it)
00099 {
00100 const SgPoint p = *it;
00101 switch (dist[p])
00102 {
00103 case 1:
00104 Add(p, SgUctValue(1.0), count);
00105 break;
00106 case 2:
00107 Add(p, SgUctValue(0.6), count);
00108 break;
00109 case 3:
00110 Add(p, SgUctValue(0.6), count);
00111 break;
00112 default:
00113 Add(p, SgUctValue(0.1), count);
00114 break;
00115 }
00116 }
00117 Add(SG_PASS, SgUctValue(0.1), count);
00118 }
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 bool GoUctDefaultPriorKnowledge::FindGlobalPatternAndAtariMoves(
00128 SgPointSet& pattern,
00129 SgPointSet& atari,
00130 GoPointList& empty) const
00131 {
00132 SG_ASSERT(empty.IsEmpty());
00133 const GoUctPatterns<GoBoard>& patterns = m_policy.Patterns();
00134 bool result = false;
00135 for (GoBoard::Iterator it(m_bd); it; ++it)
00136 if (m_bd.IsEmpty(*it))
00137 {
00138 empty.PushBack(*it);
00139 if (patterns.MatchAny(*it))
00140 {
00141 pattern.Include(*it);
00142 result = true;
00143 }
00144 if (SetsAtari(m_bd, *it))
00145 {
00146 atari.Include(*it);
00147 result = true;
00148 }
00149 }
00150 return result;
00151 }
00152
00153 void
00154 GoUctDefaultPriorKnowledge::ProcessPosition(std::vector<SgUctMoveInfo>& outmoves)
00155 {
00156 m_policy.StartPlayout();
00157 m_policy.GenerateMove();
00158 GoUctPlayoutPolicyType type = m_policy.MoveType();
00159 bool isFullBoardRandom =
00160 (type == GOUCT_RANDOM || type == GOUCT_FILLBOARD);
00161 SgPointSet pattern;
00162 SgPointSet atari;
00163 GoPointList empty;
00164 bool anyHeuristic = FindGlobalPatternAndAtariMoves(pattern, atari, empty);
00165
00166
00167
00168
00169
00170
00171 const bool isSmallBoard = (m_bd.Size() < 15);
00172
00173 Initialize(SG_PASS, 0.1f, isSmallBoard ? 9 : 18);
00174 if (isFullBoardRandom && ! anyHeuristic)
00175 {
00176 for (GoBoard::Iterator it(m_bd); it; ++it)
00177 {
00178 SgPoint p = *it;
00179 if (! m_bd.IsEmpty(p))
00180 continue;
00181 if (GoBoardUtil::SelfAtari(m_bd, *it))
00182 Initialize(*it, 0.1f, isSmallBoard ? 9 : 18);
00183 else
00184 m_values[p].Clear();
00185 }
00186 }
00187 else if (isFullBoardRandom && anyHeuristic)
00188 {
00189 for (GoBoard::Iterator it(m_bd); it; ++it)
00190 {
00191 SgPoint p = *it;
00192 if (! m_bd.IsEmpty(p))
00193 continue;
00194 if (GoBoardUtil::SelfAtari(m_bd, *it))
00195 Initialize(*it, 0.1f, isSmallBoard ? 9 : 18);
00196 else if (atari[*it])
00197 Initialize(*it, 1.0f, 3);
00198 else if (pattern[*it])
00199 Initialize(*it, 0.9f, 3);
00200 else
00201 Initialize(*it, 0.5f, 3);
00202 }
00203 }
00204 else
00205 {
00206 for (GoBoard::Iterator it(m_bd); it; ++it)
00207 {
00208 SgPoint p = *it;
00209 if (! m_bd.IsEmpty(p))
00210 continue;
00211 if (GoBoardUtil::SelfAtari(m_bd, *it))
00212 Initialize(*it, 0.1f, isSmallBoard ? 9 : 18);
00213 else if (atari[*it])
00214 Initialize(*it, 0.8f, isSmallBoard ? 9 : 18);
00215 else if (pattern[*it])
00216 Initialize(*it, 0.6f, isSmallBoard ? 9 : 18);
00217 else
00218 Initialize(*it, 0.4f, isSmallBoard ? 9 : 18);
00219 }
00220 GoPointList moves = m_policy.GetEquivalentBestMoves();
00221 for (GoPointList::Iterator it(moves); it; ++it)
00222 Initialize(*it, 1.0, isSmallBoard ? 9 : 18);
00223 }
00224 AddLocalityBonus(empty, isSmallBoard);
00225 m_policy.EndPlayout();
00226
00227 TransferValues(outmoves);
00228 }
00229
00230