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