File: Book.cpp

package info (click to toggle)
pentobi 26.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 4,068 kB
  • sloc: cpp: 25,986; javascript: 897; xml: 57; makefile: 13; sh: 11
file content (121 lines) | stat: -rw-r--r-- 3,833 bytes parent folder | download | duplicates (3)
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
116
117
118
119
120
121
//-----------------------------------------------------------------------------
/** @file libpentobi_base/Book.cpp
    @author Markus Enzenberger
    @copyright GNU General Public License version 3 or later */
//-----------------------------------------------------------------------------

#include "Book.h"

#include "BoardUtil.h"
#include "libboardgame_base/Log.h"
#include "libboardgame_base/TreeReader.h"

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

namespace libpentobi_base {

using libboardgame_base::TreeReader;

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

Book::Book(Variant variant)
    : m_tree(variant)
{
    get_transforms(variant, m_transforms, m_inv_transforms);
}

Move Book::genmove(const Board& bd, Color c)
{
    if (bd.has_setup())
        // Book cannot handle setup positions
        return Move::null();
    Move mv;
    for (unsigned i = 0; i < m_transforms.size(); ++i)
        if (genmove(bd, c, mv, *m_transforms[i], *m_inv_transforms[i]))
            return mv;
    return Move::null();
}

bool Book::genmove(const Board& bd, Color c, Move& mv,
                   const PointTransform& transform,
                   const PointTransform& inv_transform)
{
    LIBBOARDGAME_ASSERT(! bd.has_setup());
    auto node = &m_tree.get_root();
    for (unsigned i = 0; i < bd.get_nu_moves(); ++i)
    {
        ColorMove color_mv = bd.get_move(i);
        color_mv.move = get_transformed(bd, color_mv.move, transform);
        node = m_tree.find_child_with_move(*node, color_mv);
        if (node == nullptr)
            return false;
    }
    node = select_child(bd, c, m_tree, *node, inv_transform);
    if (node == nullptr)
        return false;
    mv = get_transformed(bd, m_tree.get_move(*node).move, inv_transform);
    return true;
}

void Book::load(istream& in)
{
    TreeReader reader;
    try
    {
        reader.read(in);
    }
    catch (const TreeReader::ReadError& e)
    {
        throw runtime_error(string("could not read book: ") + e.what());
    }
    unique_ptr<SgfNode> root = reader.move_tree();
    m_tree.init(root);
    get_transforms(m_tree.get_variant(), m_transforms, m_inv_transforms);
}

const SgfNode* Book::select_child(const Board& bd, Color c,
                                  const PentobiTree& tree, const SgfNode& node,
                                  const PointTransform& inv_transform)
{
    unsigned nu_children = node.get_nu_children();
    if (nu_children == 0)
        return nullptr;
    vector<const SgfNode*> good_moves;
    for (unsigned i = 0; i < nu_children; ++i)
    {
        auto& child = node.get_child(i);
        ColorMove color_mv = tree.get_move(child);
        if (color_mv.is_null())
        {
            LIBBOARDGAME_LOG("WARNING: Book contains nodes without moves");
            continue;
        }
        if (color_mv.color != c)
        {
            LIBBOARDGAME_LOG("WARNING: Book contains non-alternating move sequences");
            continue;
        }
        auto mv = get_transformed(bd, color_mv.move, inv_transform);
        if (! bd.is_legal(color_mv.color, mv))
        {
            LIBBOARDGAME_LOG("WARNING: Book contains illegal move");
            continue;
        }
        if (SgfTree::get_good_move(child) > 0)
        {
            LIBBOARDGAME_LOG(bd.to_string(mv), " !");
            good_moves.push_back(&child);
        }
        else
            LIBBOARDGAME_LOG(bd.to_string(mv));
    }
    if (good_moves.empty())
        return nullptr;
    LIBBOARDGAME_LOG("Book moves: ", good_moves.size());
    auto nu_good_moves = static_cast<unsigned>(good_moves.size());
    return good_moves[m_random.generate() % nu_good_moves];
}

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

} // namespace libpentobi_base