00001
00002
00003
00004
00005 #ifndef GOUCT_PLAYOUTPOLICY_H
00006 #define GOUCT_PLAYOUTPOLICY_H
00007
00008 #include <iostream>
00009 #include <boost/array.hpp>
00010 #include "GoBoardUtil.h"
00011 #include "GoEyeUtil.h"
00012 #include "GoUctPatterns.h"
00013 #include "GoUctPureRandomGenerator.h"
00014
00015
00016
00017
00018 class GoUctPlayoutPolicyParam
00019 {
00020 public:
00021
00022
00023 bool m_statisticsEnabled;
00024
00025
00026
00027
00028
00029
00030 bool m_useNakadeHeuristic;
00031
00032
00033
00034 int m_fillboardTries;
00035
00036 GoUctPlayoutPolicyParam();
00037 };
00038
00039
00040
00041
00042 enum GoUctPlayoutPolicyType
00043 {
00044 GOUCT_FILLBOARD,
00045
00046 GOUCT_NAKADE,
00047
00048 GOUCT_ATARI_CAPTURE,
00049
00050 GOUCT_ATARI_DEFEND,
00051
00052 GOUCT_LOWLIB,
00053
00054 GOUCT_PATTERN,
00055
00056 GOUCT_CAPTURE,
00057
00058 GOUCT_RANDOM,
00059
00060 GOUCT_SELFATARI_CORRECTION,
00061
00062 GOUCT_CLUMP_CORRECTION,
00063
00064 GOUCT_PASS,
00065
00066 _GOUCT_NU_DEFAULT_PLAYOUT_TYPE
00067 };
00068
00069 const char* GoUctPlayoutPolicyTypeStr(GoUctPlayoutPolicyType type);
00070
00071
00072
00073
00074 struct GoUctPlayoutPolicyStat
00075 {
00076
00077 std::size_t m_nuMoves;
00078
00079
00080 SgUctStatistics m_nonRandLen;
00081
00082
00083
00084 SgUctStatistics m_moveListLen;
00085
00086
00087 boost::array<std::size_t,_GOUCT_NU_DEFAULT_PLAYOUT_TYPE> m_nuMoveType;
00088
00089 void Clear();
00090
00091 void Write(std::ostream& out) const;
00092 };
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 template<class BOARD>
00104 class GoUctPlayoutPolicy
00105 {
00106 public:
00107
00108
00109
00110
00111
00112
00113 GoUctPlayoutPolicy(const BOARD& bd, const GoUctPlayoutPolicyParam& param);
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 SgPoint GenerateMove();
00126
00127 void EndPlayout();
00128
00129 void StartPlayout();
00130
00131 void OnPlay();
00132
00133
00134 GoUctPlayoutPolicyType MoveType() const;
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 const GoUctPlayoutPolicyStat& Statistics(SgBlackWhite color) const;
00146
00147 void ClearStatistics();
00148
00149
00150
00151
00152
00153
00154 GoPointList GetEquivalentBestMoves() const;
00155
00156
00157
00158
00159
00160 const GoUctPatterns<BOARD>& Patterns() const;
00161
00162 private:
00163
00164 typedef bool Corrector(const BOARD&, SgPoint&);
00165
00166
00167 class CaptureGenerator
00168 {
00169 public:
00170 CaptureGenerator(const BOARD& bd);
00171
00172 void StartPlayout();
00173
00174 void OnPlay();
00175
00176
00177
00178
00179 void Generate(GoPointList& moves);
00180
00181 private:
00182 const BOARD& m_bd;
00183
00184
00185 std::vector<SgPoint> m_candidates;
00186 };
00187
00188
00189 static const bool SECOND_LAST_MOVE_PATTERNS = true;
00190
00191
00192
00193 static const bool USE_CLUMP_CORRECTION = false;
00194
00195 static const bool DEBUG_CORRECT_MOVE = false;
00196
00197 const BOARD& m_bd;
00198
00199 const GoUctPlayoutPolicyParam& m_param;
00200
00201 GoUctPatterns<BOARD> m_patterns;
00202
00203
00204 bool m_checked;
00205
00206
00207 GoUctPlayoutPolicyType m_moveType;
00208
00209
00210 std::size_t m_nonRandLen;
00211
00212
00213
00214
00215 SgPoint m_lastMove;
00216
00217
00218
00219
00220
00221
00222 GoPointList m_moves;
00223
00224 SgRandom m_random;
00225
00226
00227 mutable SgBalancer m_balancer;
00228
00229 CaptureGenerator m_captureGenerator;
00230
00231 GoUctPureRandomGenerator<BOARD> m_pureRandomGenerator;
00232
00233 SgBWArray<GoUctPlayoutPolicyStat> m_statistics;
00234
00235
00236
00237
00238 bool CorrectMove(typename GoUctPlayoutPolicy<BOARD>::Corrector& corrFunction,
00239 SgPoint& mv, GoUctPlayoutPolicyType moveType);
00240
00241
00242 bool GenerateAtariCaptureMove();
00243
00244
00245 bool GenerateAtariDefenseMove();
00246
00247
00248 bool GenerateLowLibMove(SgPoint lastMove);
00249
00250 bool GenerateNakadeMove();
00251
00252 void GenerateNakadeMove(SgPoint p);
00253
00254
00255 bool GeneratePatternMove();
00256
00257 void GeneratePatternMove(SgPoint p);
00258
00259 void GeneratePatternMove2(SgPoint p, SgPoint lastMove);
00260
00261 void GeneratePureRandom();
00262
00263 bool GeneratePoint(SgPoint p) const;
00264
00265
00266
00267
00268 void PlayGoodLiberties(SgPoint block);
00269
00270
00271 SgPoint SelectRandom();
00272
00273
00274 void UpdateStatistics();
00275 };
00276
00277 template<class BOARD>
00278 GoUctPlayoutPolicy<BOARD>::CaptureGenerator::CaptureGenerator(const BOARD& bd)
00279 : m_bd(bd)
00280 {
00281 m_candidates.reserve(GO_MAX_NUM_MOVES);
00282 }
00283
00284 template<class BOARD>
00285 void GoUctPlayoutPolicy<BOARD>::CaptureGenerator::StartPlayout()
00286 {
00287 m_candidates.clear();
00288 for (typename BOARD::Iterator it(m_bd); it; ++it)
00289 {
00290 const SgPoint p = *it;
00291 if (m_bd.Occupied(p) && m_bd.Anchor(p) == p && m_bd.InAtari(p))
00292 m_candidates.push_back(p);
00293 }
00294 }
00295
00296 template<class BOARD>
00297 void GoUctPlayoutPolicy<BOARD>::CaptureGenerator::OnPlay()
00298 {
00299 SgPoint lastMove = m_bd.GetLastMove();
00300 if (lastMove == SG_NULLMOVE || lastMove == SG_PASS)
00301 return;
00302 if (m_bd.OccupiedInAtari(lastMove))
00303 m_candidates.push_back(m_bd.Anchor(lastMove));
00304 if (m_bd.NumNeighbors(lastMove, m_bd.ToPlay()) == 0)
00305 return;
00306 if (m_bd.OccupiedInAtari(lastMove + SG_NS))
00307 m_candidates.push_back(m_bd.Anchor(lastMove + SG_NS));
00308 if (m_bd.OccupiedInAtari(lastMove - SG_NS))
00309 m_candidates.push_back(m_bd.Anchor(lastMove - SG_NS));
00310 if (m_bd.OccupiedInAtari(lastMove + SG_WE))
00311 m_candidates.push_back(m_bd.Anchor(lastMove + SG_WE));
00312 if (m_bd.OccupiedInAtari(lastMove - SG_WE))
00313 m_candidates.push_back(m_bd.Anchor(lastMove - SG_WE));
00314 }
00315
00316 template<class BOARD>
00317 void GoUctPlayoutPolicy<BOARD>::CaptureGenerator::Generate(GoPointList& moves)
00318 {
00319 SG_ASSERT(moves.IsEmpty());
00320 const SgBlackWhite opp = m_bd.Opponent();
00321
00322
00323
00324
00325
00326 for (size_t i = 0; i < m_candidates.size(); ++i)
00327 {
00328 const SgPoint p = m_candidates[i];
00329 if (! m_bd.OccupiedInAtari(p))
00330 {
00331 m_candidates[i] = m_candidates[m_candidates.size() - 1];
00332 m_candidates.pop_back();
00333 --i;
00334 continue;
00335 }
00336 if (m_bd.GetColor(p) == opp)
00337 moves.PushBack(m_bd.TheLiberty(p));
00338 }
00339 }
00340
00341 template<class BOARD>
00342 GoUctPlayoutPolicy<BOARD>::GoUctPlayoutPolicy(const BOARD& bd,
00343 const GoUctPlayoutPolicyParam& param)
00344 : m_bd(bd),
00345 m_param(param),
00346 m_patterns(bd),
00347 m_checked(false),
00348 m_balancer(100),
00349 m_captureGenerator(bd),
00350 m_pureRandomGenerator(bd, m_random)
00351 {
00352 ClearStatistics();
00353 }
00354
00355 template<class BOARD>
00356 void GoUctPlayoutPolicy<BOARD>::ClearStatistics()
00357 {
00358 m_statistics[SG_BLACK].Clear();
00359 m_statistics[SG_WHITE].Clear();
00360 }
00361
00362 template<class BOARD>
00363 bool GoUctPlayoutPolicy<BOARD>::CorrectMove(
00364 typename GoUctPlayoutPolicy<BOARD>::Corrector& corrFunction,
00365 SgPoint& mv, GoUctPlayoutPolicyType moveType)
00366 {
00367 #if DEBUG
00368 const SgPoint oldMv = mv;
00369 #endif
00370 if (! corrFunction(m_bd, mv))
00371 return false;
00372
00373 m_moves.SetTo(mv);
00374 m_moveType = moveType;
00375
00376 #if DEBUG
00377 if (DEBUG_CORRECT_MOVE)
00378 SgDebug() << m_bd
00379 << "Replace " << SgWriteMove(oldMv, m_bd.ToPlay())
00380 << " by " << SgWriteMove(mv, m_bd.ToPlay()) << '\n';
00381 #endif
00382 return true;
00383 }
00384
00385 template<class BOARD>
00386 void GoUctPlayoutPolicy<BOARD>::EndPlayout()
00387 {
00388 }
00389
00390 template<class BOARD>
00391 bool GoUctPlayoutPolicy<BOARD>::GenerateAtariCaptureMove()
00392 {
00393 SG_ASSERT(! SgIsSpecialMove(m_lastMove));
00394 if (m_bd.InAtari(m_lastMove))
00395 {
00396 SgMove mv = m_bd.TheLiberty(m_lastMove);
00397 m_moves.PushBack(mv);
00398 return true;
00399 }
00400 return false;
00401 }
00402
00403 template<class BOARD>
00404 bool GoUctPlayoutPolicy<BOARD>::GenerateAtariDefenseMove()
00405 {
00406 SG_ASSERT(m_moves.IsEmpty());
00407 SG_ASSERT(! SgIsSpecialMove(m_lastMove));
00408 SgBlackWhite toPlay = m_bd.ToPlay();
00409 if (m_bd.NumNeighbors(m_lastMove, toPlay) == 0)
00410 return false;
00411 SgArrayList<SgPoint,4> anchorList;
00412 for (SgNb4Iterator it(m_lastMove); it; ++it)
00413 {
00414 if (m_bd.GetColor(*it) != toPlay || ! m_bd.InAtari(*it))
00415 continue;
00416 SgPoint anchor = m_bd.Anchor(*it);
00417 if (anchorList.Contains(anchor))
00418 continue;
00419 anchorList.PushBack(anchor);
00420
00421
00422 SgPoint theLiberty = m_bd.TheLiberty(anchor);
00423 if (! GoBoardUtil::SelfAtari(m_bd, theLiberty))
00424 m_moves.PushBack(theLiberty);
00425
00426
00427 for (GoAdjBlockIterator<BOARD> it2(m_bd, anchor, 1); it2; ++it2)
00428 {
00429 SgPoint oppLiberty = m_bd.TheLiberty(*it2);
00430
00431
00432
00433
00434
00435
00436 if (oppLiberty != theLiberty)
00437 m_moves.PushBack(oppLiberty);
00438 }
00439 }
00440 return ! m_moves.IsEmpty();
00441 }
00442
00443 template<class BOARD>
00444 void GoUctPlayoutPolicy<BOARD>::PlayGoodLiberties(SgPoint block)
00445 {
00446 SgPoint ignoreOther;
00447 if (! GoBoardUtil::IsSimpleChain(m_bd, block, ignoreOther))
00448 for (typename BOARD::LibertyIterator it(m_bd, block); it; ++it)
00449 if ( GoUctUtil::GainsLiberties(m_bd, block, *it)
00450 && ! GoBoardUtil::SelfAtari(m_bd, *it)
00451 )
00452 m_moves.PushBack(*it);
00453 }
00454
00455 template<class BOARD>
00456 bool GoUctPlayoutPolicy<BOARD>::GenerateLowLibMove(SgPoint lastMove)
00457 {
00458 SG_ASSERT(! SgIsSpecialMove(lastMove));
00459 SG_ASSERT(! m_bd.IsEmpty(lastMove));
00460 SG_ASSERT(m_moves.IsEmpty());
00461
00462 const SgBlackWhite toPlay = m_bd.ToPlay();
00463
00464
00465 if (m_bd.NumLiberties(lastMove) == 2)
00466 {
00467 const SgPoint anchor = m_bd.Anchor(lastMove);
00468 PlayGoodLiberties(anchor);
00469 }
00470
00471 if (m_bd.NumNeighbors(lastMove, toPlay) != 0)
00472 {
00473
00474 SgArrayList<SgPoint,4> ourLowLibBlocks;
00475 for (SgNb4Iterator it(lastMove); it; ++it)
00476 {
00477 if (m_bd.GetColor(*it) == toPlay
00478 && m_bd.NumLiberties(*it) == 2)
00479 {
00480 const SgPoint anchor = m_bd.Anchor(*it);
00481 if (! ourLowLibBlocks.Contains(anchor))
00482 {
00483 ourLowLibBlocks.PushBack(anchor);
00484 PlayGoodLiberties(anchor);
00485 }
00486 }
00487 }
00488 }
00489
00490 return ! m_moves.IsEmpty();
00491 }
00492
00493 template<class BOARD>
00494 SG_ATTR_FLATTEN SgPoint GoUctPlayoutPolicy<BOARD>::GenerateMove()
00495 {
00496 m_moves.Clear();
00497 m_checked = false;
00498
00499 SgPoint mv = SG_NULLMOVE;
00500
00501 if (m_param.m_fillboardTries > 0)
00502 {
00503 m_moveType = GOUCT_FILLBOARD;
00504 mv = m_pureRandomGenerator.GenerateFillboardMove(
00505 m_param.m_fillboardTries);
00506 }
00507
00508 m_lastMove = m_bd.GetLastMove();
00509 if (mv == SG_NULLMOVE
00510 && ! SgIsSpecialMove(m_lastMove)
00511 && ! m_bd.IsEmpty(m_lastMove)
00512 )
00513 {
00514 if (m_param.m_useNakadeHeuristic && GenerateNakadeMove())
00515 {
00516 m_moveType = GOUCT_NAKADE;
00517 mv = SelectRandom();
00518 }
00519 if (mv == SG_NULLMOVE && GenerateAtariCaptureMove())
00520 {
00521 m_moveType = GOUCT_ATARI_CAPTURE;
00522 mv = SelectRandom();
00523 }
00524 if (mv == SG_NULLMOVE && GenerateAtariDefenseMove())
00525 {
00526 m_moveType = GOUCT_ATARI_DEFEND;
00527 mv = SelectRandom();
00528 }
00529 if (mv == SG_NULLMOVE && GenerateLowLibMove(m_lastMove))
00530 {
00531 m_moveType = GOUCT_LOWLIB;
00532 mv = SelectRandom();
00533 }
00534 if (mv == SG_NULLMOVE && GeneratePatternMove())
00535 {
00536 m_moveType = GOUCT_PATTERN;
00537 mv = SelectRandom();
00538 }
00539 }
00540 if (mv == SG_NULLMOVE)
00541 {
00542 m_moveType = GOUCT_CAPTURE;
00543 m_captureGenerator.Generate(m_moves);
00544 mv = SelectRandom();
00545 }
00546 if (mv == SG_NULLMOVE)
00547 {
00548 m_moveType = GOUCT_RANDOM;
00549 mv = m_pureRandomGenerator.Generate(m_balancer);
00550 }
00551
00552 if (mv == SG_NULLMOVE)
00553 {
00554 m_moveType = GOUCT_PASS;
00555 mv = SG_PASS;
00556 }
00557 else
00558 {
00559 SG_ASSERT(m_bd.IsLegal(mv));
00560 m_checked = CorrectMove(GoUctUtil::DoSelfAtariCorrection, mv,
00561 GOUCT_SELFATARI_CORRECTION);
00562 if (USE_CLUMP_CORRECTION && ! m_checked)
00563 CorrectMove(GoUctUtil::DoClumpCorrection, mv,
00564 GOUCT_CLUMP_CORRECTION);
00565 }
00566 SG_ASSERT(m_bd.IsLegal(mv));
00567 SG_ASSERT(mv == SG_PASS || ! m_bd.IsSuicide(mv));
00568
00569 if (m_param.m_statisticsEnabled)
00570 UpdateStatistics();
00571
00572 return mv;
00573 }
00574
00575
00576
00577
00578 template<class BOARD>
00579 bool GoUctPlayoutPolicy<BOARD>::GenerateNakadeMove()
00580 {
00581 SG_ASSERT(m_moves.IsEmpty());
00582 SG_ASSERT(! SgIsSpecialMove(m_lastMove));
00583 GenerateNakadeMove(m_lastMove + SG_NS);
00584 GenerateNakadeMove(m_lastMove - SG_NS);
00585 GenerateNakadeMove(m_lastMove + SG_WE);
00586 GenerateNakadeMove(m_lastMove - SG_WE);
00587
00588 return ! m_moves.IsEmpty();
00589 }
00590
00591 template<class BOARD>
00592 void GoUctPlayoutPolicy<BOARD>::GenerateNakadeMove(SgPoint p)
00593 {
00594 SgBlackWhite toPlay = m_bd.ToPlay();
00595 if (m_bd.IsEmpty(p) && m_bd.NumNeighbors(p, toPlay) == 0)
00596 {
00597 int numEmptyNeighbors = m_bd.NumEmptyNeighbors(p);
00598 if (numEmptyNeighbors == 2)
00599 {
00600 int n = 0;
00601 for (SgNb4Iterator it(p); it; ++it)
00602 if (m_bd.IsEmpty(*it))
00603 {
00604 if (m_bd.NumEmptyNeighbors(*it) != 1
00605 || m_bd.NumNeighbors(*it, toPlay) > 0)
00606 return;
00607 if (++n > 2)
00608 break;
00609 }
00610 m_moves.PushBack(p);
00611 }
00612 else if (numEmptyNeighbors == 1)
00613 {
00614 for (SgNb4Iterator it(p); it; ++it)
00615 if (m_bd.IsEmpty(*it))
00616 {
00617 if (m_bd.NumEmptyNeighbors(*it) != 2
00618 || m_bd.NumNeighbors(*it, toPlay) > 0)
00619 return;
00620 for (SgNb4Iterator it2(*it); it2; ++it2)
00621 if (m_bd.IsEmpty(*it2) && *it2 != p)
00622 {
00623 if (m_bd.NumEmptyNeighbors(*it2) == 1
00624 && m_bd.NumNeighbors(*it2, toPlay) == 0)
00625 m_moves.PushBack(*it);
00626 break;
00627 }
00628 break;
00629 }
00630
00631 }
00632 }
00633 }
00634
00635
00636
00637
00638 template<class BOARD>
00639 bool GoUctPlayoutPolicy<BOARD>::GeneratePatternMove()
00640 {
00641 SG_ASSERT(m_moves.IsEmpty());
00642 SG_ASSERT(! SgIsSpecialMove(m_lastMove));
00643 GeneratePatternMove(m_lastMove + SG_NS - SG_WE);
00644 GeneratePatternMove(m_lastMove + SG_NS);
00645 GeneratePatternMove(m_lastMove + SG_NS + SG_WE);
00646 GeneratePatternMove(m_lastMove - SG_WE);
00647 GeneratePatternMove(m_lastMove + SG_WE);
00648 GeneratePatternMove(m_lastMove - SG_NS - SG_WE);
00649 GeneratePatternMove(m_lastMove - SG_NS);
00650 GeneratePatternMove(m_lastMove - SG_NS + SG_WE);
00651 if (SECOND_LAST_MOVE_PATTERNS)
00652 {
00653 const SgPoint lastMove2 = m_bd.Get2ndLastMove();
00654 if (! SgIsSpecialMove(lastMove2))
00655 {
00656 GeneratePatternMove2(lastMove2 + SG_NS - SG_WE, m_lastMove);
00657 GeneratePatternMove2(lastMove2 + SG_NS, m_lastMove);
00658 GeneratePatternMove2(lastMove2 + SG_NS + SG_WE, m_lastMove);
00659 GeneratePatternMove2(lastMove2 - SG_WE, m_lastMove);
00660 GeneratePatternMove2(lastMove2 + SG_WE, m_lastMove);
00661 GeneratePatternMove2(lastMove2 - SG_NS - SG_WE, m_lastMove);
00662 GeneratePatternMove2(lastMove2 - SG_NS, m_lastMove);
00663 GeneratePatternMove2(lastMove2 - SG_NS + SG_WE, m_lastMove);
00664 }
00665 }
00666 return ! m_moves.IsEmpty();
00667 }
00668
00669 template<class BOARD>
00670 inline void GoUctPlayoutPolicy<BOARD>::GeneratePatternMove(SgPoint p)
00671 {
00672 if (m_bd.IsEmpty(p)
00673 && m_patterns.MatchAny(p)
00674 && ! GoBoardUtil::SelfAtari(m_bd, p))
00675 m_moves.PushBack(p);
00676 }
00677
00678 template<class BOARD>
00679 inline void GoUctPlayoutPolicy<BOARD>::GeneratePatternMove2(SgPoint p,
00680 SgPoint lastMove)
00681 {
00682 if (m_bd.IsEmpty(p)
00683 && ! SgPointUtil::In8Neighborhood(lastMove, p)
00684 && m_patterns.MatchAny(p)
00685 && ! GoBoardUtil::SelfAtari(m_bd, p))
00686 m_moves.PushBack(p);
00687 }
00688
00689 template<class BOARD>
00690 inline bool GoUctPlayoutPolicy<BOARD>::GeneratePoint(SgPoint p) const
00691 {
00692 return GoUctUtil::GeneratePoint(m_bd, m_balancer, p, m_bd.ToPlay());
00693 }
00694
00695 template<class BOARD>
00696 GoPointList GoUctPlayoutPolicy<BOARD>::GetEquivalentBestMoves() const
00697 {
00698 GoPointList result;
00699 if (m_moveType == GOUCT_RANDOM)
00700 {
00701 for (typename BOARD::Iterator it(m_bd); it; ++it)
00702 if (m_bd.IsEmpty(*it) && GeneratePoint(*it))
00703 result.PushBack(*it);
00704 }
00705
00706 for (GoPointList::Iterator it(m_moves); it; ++it)
00707 if (m_checked || GeneratePoint(*it))
00708 result.PushBack(*it);
00709 return result;
00710 }
00711
00712 template<class BOARD>
00713 GoUctPlayoutPolicyType GoUctPlayoutPolicy<BOARD>::MoveType()
00714 const
00715 {
00716 return m_moveType;
00717 }
00718
00719 template<class BOARD>
00720 void GoUctPlayoutPolicy<BOARD>::OnPlay()
00721 {
00722 m_captureGenerator.OnPlay();
00723 m_pureRandomGenerator.OnPlay();
00724 }
00725
00726
00727 template<class BOARD>
00728 const GoUctPatterns<BOARD>& GoUctPlayoutPolicy<BOARD>::Patterns()
00729 const
00730 {
00731 return m_patterns;
00732 }
00733
00734 template<class BOARD>
00735 inline SgPoint GoUctPlayoutPolicy<BOARD>::SelectRandom()
00736 {
00737 return GoUctUtil::SelectRandom(m_bd, m_bd.ToPlay(), m_moves, m_random,
00738 m_balancer);
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 template<class BOARD>
00750 const GoUctPlayoutPolicyStat&
00751 GoUctPlayoutPolicy<BOARD>::Statistics(SgBlackWhite color) const
00752 {
00753 return m_statistics[color];
00754 }
00755
00756 template<class BOARD>
00757 void GoUctPlayoutPolicy<BOARD>::StartPlayout()
00758 {
00759 m_captureGenerator.StartPlayout();
00760 m_pureRandomGenerator.Start();
00761 m_nonRandLen = 0;
00762 }
00763
00764 template<class BOARD>
00765 void GoUctPlayoutPolicy<BOARD>::UpdateStatistics()
00766 {
00767 GoUctPlayoutPolicyStat& statistics = m_statistics[m_bd.ToPlay()];
00768 ++statistics.m_nuMoves;
00769 ++statistics.m_nuMoveType[m_moveType];
00770 if (m_moveType == GOUCT_RANDOM)
00771 {
00772 if (m_nonRandLen > 0)
00773 {
00774 statistics.m_nonRandLen.Add(float(m_nonRandLen));
00775 m_nonRandLen = 0;
00776 }
00777 }
00778 else
00779 {
00780 ++m_nonRandLen;
00781 statistics.m_moveListLen.Add(float(GetEquivalentBestMoves().Length()));
00782 }
00783 }
00784
00785
00786
00787 template<class BOARD>
00788 class GoUctPlayoutPolicyFactory
00789 {
00790 public:
00791
00792
00793
00794
00795 GoUctPlayoutPolicyFactory(const GoUctPlayoutPolicyParam& param);
00796
00797 GoUctPlayoutPolicy<BOARD>* Create(const BOARD& bd);
00798
00799 private:
00800 const GoUctPlayoutPolicyParam& m_param;
00801 };
00802
00803 template<class BOARD>
00804 GoUctPlayoutPolicyFactory<BOARD>
00805 ::GoUctPlayoutPolicyFactory(const GoUctPlayoutPolicyParam& param)
00806 : m_param(param)
00807 {
00808 }
00809
00810 template<class BOARD>
00811 GoUctPlayoutPolicy<BOARD>*
00812 GoUctPlayoutPolicyFactory<BOARD>::Create(const BOARD& bd)
00813 {
00814 return new GoUctPlayoutPolicy<BOARD>(bd, m_param);
00815 }
00816
00817
00818
00819 #endif // GOUCT_PLAYOUTPOLICY_H