forked from tseip/fourinarow
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsearches.h
172 lines (154 loc) · 5.13 KB
/
searches.h
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#ifndef SEARCHES_H_INCLUDED
#define SEARCHES_H_INCLUDED
#include <memory>
#include "bfs_node.h"
#include "game_tree_node.h"
/**
* An abstract search interface, for performing a tree search using a heuristic
* to evaluate each individual position.
*
* @tparam Heuristic The class evaluating each position.
*/
template <class Heuristic>
class AbstractSearch {
public:
/**
* Constructor.
*
* @param heuristic The heuristic that will evaluate each position that
* develops from the board.
* @param board The board containing the initial position to develop.
*/
AbstractSearch(std::shared_ptr<Heuristic> heuristic,
const typename Heuristic::BoardT &board)
: heuristic(heuristic), board(board) {
if (!heuristic)
throw std::invalid_argument("Must pass a non-null heuristic!");
this->heuristic->start_search();
}
/**
* Performs a single step of the search algorithm, typically expanding a
* single node of the search tree (though not necessarily).
*
* @return True if the search is complete.
*/
virtual bool advance_search() = 0;
/**
* Runs the current search to completion.
*/
void complete_search() {
while (!advance_search()) {
}
}
/**
* Destructor.
*/
virtual ~AbstractSearch() {
}
/**
* @return (the root of) The current search tree.
*/
virtual std::shared_ptr<Node<typename Heuristic::BoardT>> get_tree() = 0;
protected:
/**
* The heuristic being used to evaluate positions.
*/
std::shared_ptr<Heuristic> heuristic;
/**
* The starting board position.
*/
const typename Heuristic::BoardT board;
};
/**
* A concrete search interface, for performing a tree search using a heuristic
* to evaluate each individual position, which manages the nodes of the search
* tree.
*
* @tparam Heuristic The class evaluating each position.
* @tparam NodeT The class representing a single node in the search tree.
*/
template <class Heuristic, class NodeT>
class Search : public AbstractSearch<Heuristic> {
public:
/**
* Constructor.
*
* @param heuristic The heuristic that will evaluate each position that
* develops from the board.
* @param board The board containing the initial position to develop.
*/
Search(std::shared_ptr<Heuristic> heuristic,
const typename Heuristic::BoardT &board)
: AbstractSearch<Heuristic>(heuristic, board),
root(NodeT::create(board, heuristic->evaluate(board))) {}
/**
* Performs a single step of the search algorithm, typically expanding a
* single node of the search tree (though not necessarily).
*
* @return True if the search is complete.
*/
virtual bool advance_search() override {
if (stopping_conditions(this->heuristic, this->board)) {
this->heuristic->complete_search();
return true;
} else {
auto current_node = select_next_node();
const auto current_board = current_node->get_board();
const std::vector<typename Heuristic::BoardT::MoveT> candidate_moves =
this->heuristic->get_pruned_moves(current_board,
current_board.active_player());
current_node->expand(candidate_moves);
on_node_expansion(current_node, this->heuristic, this->board);
return false;
}
}
/**
* @return (the root of) The current search tree.
*/
virtual std::shared_ptr<Node<typename Heuristic::BoardT>> get_tree()
override {
return std::dynamic_pointer_cast<Node<typename Heuristic::BoardT>>(root);
}
protected:
/**
* Finds the next node in the tree to be expanded at each step of the search
* process.
*
* @return The next node to be expanded/evaluated.
*/
virtual std::shared_ptr<NodeT> select_next_node() {
return std::dynamic_pointer_cast<NodeT>(root->select());
}
/**
* Evaluates search stopping conditions and returns true if the search should
* end.
*
* @param heuristic The heuristic that will evaluate each position that
* develops from the board.
* @param board The board containing the initial position to develop.
*
* @return True if the search should stop, false otherwise.
*/
virtual bool stopping_conditions(
std::shared_ptr<Heuristic> heuristic,
const typename Heuristic::BoardT &board) const {
return this->root->determined();
}
/**
* Called whenever a node is expanded. Can be overridden to enable tracking of
* search metadata.
*
* @param expanded_node The node that was just expanded.
* @param heuristic The heuristic that will evaluate each position that
* develops from the board.
* @param board The board containing the initial position to develop.
*/
virtual void on_node_expansion(std::shared_ptr<NodeT> expanded_node,
std::shared_ptr<Heuristic> heuristic,
const typename Heuristic::BoardT &board) {}
/**
* The root of the search tree.
*/
std::shared_ptr<NodeT> root;
};
#endif // SEARCHES_H_INCLUDED