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