-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMinMaxEngine.cpp
59 lines (57 loc) · 1.66 KB
/
MinMaxEngine.cpp
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
#include "MinMaxEngine.h"
std::vector<EvalMove> MinMaxEngine::eval(Field& field, size_t depth)
{
bool maximizing = (field.getTurn() == Cell::Cross);
std::vector <GlobalCoord> legalMoves = field.getValidMoves();
std::vector <EvalMove> evals;
// This outer cycle's purpose is to save evals of all possible moves in current position.
for (const GlobalCoord& move : legalMoves) {
field.move(move);
evals.push_back(EvalMove(move, minimax(field, depth - 1, -INT_MAX, INT_MAX, !maximizing)));
field.revert();
}
modEvals(evals);
if (maximizing) {
std::sort(evals.begin(), evals.end(), evalMoveCmp);
}
else {
std::sort(evals.rbegin(), evals.rend(), evalMoveCmp);
}
return evals;
}
double MinMaxEngine::minimax(Field& field, size_t depth, double alpha, double beta, bool isMaximizing)
{
if (depth < 1 || field.getWinner() != Cell::Empty) {
return staticEval(field);
}
double eval;
// TODO: this is bad overusing of inefficient method that needs rework.
std::vector <GlobalCoord> legalMoves = field.getValidMoves();
if (isMaximizing) {
eval = -INT_MAX;
for (const GlobalCoord& move : legalMoves) {
field.move(move);
double temp = minimax(field, depth - 1, alpha, beta, false);
field.revert();
eval = std::max(eval, temp);
alpha = std::max(alpha, temp);
if (beta <= alpha) {
break;
}
}
}
else {
eval = INT_MAX;
for (const GlobalCoord& move : legalMoves) {
field.move(move);
double temp = minimax(field, depth - 1, alpha, beta, true);
field.revert();
eval = std::min(eval, temp);
beta = std::min(beta, temp);
if (beta <= alpha) {
break;
}
}
}
return eval;
}