File: AnalyzeGame.cpp

package info (click to toggle)
pentobi 29.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,892 kB
  • sloc: cpp: 25,719; javascript: 875; xml: 40; makefile: 13; sh: 6
file content (115 lines) | stat: -rw-r--r-- 4,088 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//-----------------------------------------------------------------------------
/** @file libpentobi_mcts/AnalyzeGame.cpp
    @author Markus Enzenberger
    @copyright GNU General Public License version 3 or later */
//-----------------------------------------------------------------------------

#include "AnalyzeGame.h"

#include "Search.h"
#include "libboardgame_base/WallTimeSource.h"

namespace libpentobi_mcts {

using libboardgame_base::SgfError;
using libboardgame_base::WallTimeSource;
using libpentobi_base::BoardUpdater;

//-----------------------------------------------------------------------------

void AnalyzeGame::clear()
{
    m_moves.clear();
    m_values.clear();
}

void AnalyzeGame::run(const Game& game, Search& search, size_t nu_simulations,
                      const function<void()>& progress_callback)
{
    m_variant = game.get_variant();
    m_moves.clear();
    m_values.clear();
    auto& tree = game.get_tree();
    unique_ptr<Board> bd(new Board(m_variant));
    BoardUpdater updater;
    auto& root = game.get_root();
    auto node = &root;
    WallTimeSource time_source;
    auto tie_value = Search::SearchParamConst::tie_value;
    const auto max_count = Float(nu_simulations);
    double max_time = 0;
    // Set min_simulations to a reasonable value because nu_simulations can be
    // reached without having that many value updates if a subtree from a
    // previous search is reused (which re-initializes the value and value
    // count of the new root from the best child)
    size_t min_simulations = min(size_t(100), nu_simulations);
    Move dummy;
    do
    {
        auto mv = tree.get_move(*node);
        if (! mv.is_null())
        {
            if (! node->has_parent())
            {
                // Root shouldn't contain moves in SGF files
                m_moves.push_back(mv);
                m_values.push_back(static_cast<double>(tie_value));
            }
            else
            {
                progress_callback();
                try
                {
                    updater.update(*bd, tree, node->get_parent());
                    LIBBOARDGAME_LOG("Analyzing move ", bd->get_nu_moves());
                    search.search(dummy, *bd, mv.color, max_count,
                                  min_simulations, max_time, time_source);
                    if (search.was_aborted())
                        break;
                    m_moves.push_back(mv);
                    m_values.push_back(static_cast<double>(
                                           search.get_root_val().get_mean()));
                }
                catch (const SgfError&)
                {
                    break;
                }
            }
        }
        if (! node->has_children())
        {
            updater.update(*bd, tree, *node);
            LIBBOARDGAME_LOG("Analyzing last position");
            Color c;
            if (bd->is_game_over() && ! m_moves.empty())
                // If game is over, analyze last position from viewpoint of
                // color that played the last move to avoid using a color that
                // might have run out of moves much earlier.
                c = m_moves.back().color;
            else
                c = bd->get_effective_to_play();
            search.search(dummy, *bd, c, max_count, min_simulations, max_time,
                          time_source);
            if (search.was_aborted())
                break;
            m_moves.emplace_back(c, Move::null());
            m_values.push_back(static_cast<double>(
                                   search.get_root_val().get_mean()));
        }
        node = node->get_first_child_or_null();
    }
    while (node != nullptr);
}

void AnalyzeGame::set(Variant variant, const vector<ColorMove>& moves,
                      const vector<double>& values)
{
    LIBBOARDGAME_ASSERT(moves.size() == values.size());
    m_variant = variant;
    m_moves = moves;
    m_values = values;
}

//-----------------------------------------------------------------------------

} // namespace libpentobi_mcts