forked from skaptox/JuegoDelOso
-
Notifications
You must be signed in to change notification settings - Fork 0
/
agent.cpp
132 lines (108 loc) · 3.19 KB
/
agent.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
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
// Copyright (c) 2017 Richard Games. All rights reserved.
#include <math.h>
#include <iostream>
#include <vector>
#include <QThread>
#include "./agent.h"
#include "./ai.h"
#include "./board.h"
#include "./game.h"
Agent::Agent(QObject *parent) : QObject(parent) { }
size_t Agent::numOfNodes(int empty_squares, int depth) const {
size_t accumulate = 1;
size_t possibilities = 2 * empty_squares;
// 8 * 6 * 4 * .. * n - 2 for n > 2
for (int i = 0; i < depth; ++i) {
accumulate *= possibilities;
possibilities -= 2;
if (possibilities == 0)
break;
}
return accumulate;
}
int Agent::recommendedDepth(const DataGame *data) const {
int depth = data->level;
size_t bound = pow(2, 28); // 268.435.456
size_t num_of_nodes = numOfNodes(data->board->empty_squares(), depth);
// Reduce depth while the future tree has many "nodes".
if (num_of_nodes > bound) {
while (numOfNodes(data->board->empty_squares(), depth) > bound) {
depth--;
}
} else {
if (data->level == 4) {
size_t next;
while ((next = numOfNodes(data->board->empty_squares(), depth + 1)) <
bound) {
size_t current = numOfNodes(data->board->empty_squares(), depth);
// If it reached the tree's background (There is not more nodes)
if (current == next)
break;
depth++;
}
}
}
return depth;
}
void Agent::aiVsAi(DataGame * data) const {
int points;
while (data->status != Status::Over) {
Board copy = *data->board;
data->lastMove = playAI(copy, data->level, data->turn, data->score1,
data->score2);
data->board->setState(data->lastMove);
if (data->board->statusGame() == GAME_STATUS::END) {
data->status = Status::Over;
}
emit(repaint());
points = data->lastMove.dValue;
if (points) {
if (data->turn) {
data->score1 += points;
} else {
data->score2 += points;
}
} else {
data->turn = !data->turn;
}
if (points) {
int row = data->lastMove.row;
int col = data->lastMove.col;
Game::markBoardSquares(data->board->squaresOsoAround(row, col), *data);
}
emit(repaint());
}
emit(gameOver());
}
void Agent::playAgent(DataGame * data) const {
if (data->status == Status::Over)
return;
data->status = Status::PC; // Reserve status
int points = 1;
while (points && data->status != Status::Over) {
/* Use copy because main thread is painting original board and
playAI() receives a reference and is modifying it.
*/
Board copy = *data->board;
data->lastMove = playAI(copy, recommendedDepth(data), data->turn,
data->score1, data->score2);
data->board->setState(data->lastMove);
if (data->board->statusGame() == GAME_STATUS::END) {
data->status = Status::Over;
emit(gameOver());
}
emit(repaint());
points = data->lastMove.dValue;
data->score2 += points;
if (points) {
int row = data->lastMove.row;
int col = data->lastMove.col;
Game::markBoardSquares(data->board->squaresOsoAround(row, col), *data);
QThread::msleep(500);
} else {
data->turn = !data->turn;
}
emit(repaint());
}
data->status = Status::Start;
}