-
Notifications
You must be signed in to change notification settings - Fork 0
/
ABPruning.h
174 lines (144 loc) · 4.46 KB
/
ABPruning.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
173
174
#pragma once
#include <vector>
#include <map>
#include <cstdint>
#include <cstring>
#include <iostream>
namespace ABPruning
{
enum class BlockStatus
{
empty = 0,
black,
white,
border
};
typedef struct _Vector2
{
int x;
int y;
bool operator== (const _Vector2 x) const
{
return x.x == this->x && x.y == this->y;
}
}Vec2, * LPVec2;
class ABPruningEngine
{
#define PIECES_PER_ROW 15
#define EMPTY (int)BlockStatus::empty
#define WHITE (int)BlockStatus::white
#define BLACK (int)BlockStatus::black
#define BORDER (int)BlockStatus::border
#define BLOCK_STATUS(i, j) (int)board[i][j]
public:
enum class ScenarioType
{
OTHER = 0,//其他棋型不考虑
WHITE_WIN, //白赢,由于电脑执白子,所以白的状态权重为正,黑的状态权重为负
BLACK_WIN,//
FLEX4,//白活4
flex4,//黑活4
BLOCK4,//白跳4
block4,//黑活4
CHARGE4, //白冲4
charge4, //黑冲4
FLEX3,// 白活3
flex3,// 黑活3
BLOCK3,// 白眠3
block3,// 黑眠3
FLEX2,// 白活2
flex2,// 黑活2
BLOCK2,// 白眠2
block2,// 黑眠2
FLEX1,// 白活1
flex1, // 黑活1
TERMINATOR, //白绝杀,基本无解
terminator //黑绝杀,基本无解
};
using Board = BlockStatus[PIECES_PER_ROW + 2][PIECES_PER_ROW + 2];
enum class WinningStatus
{
NO_WIN = 0,
BLACK_WIN,
WHITE_WIN
};
typedef struct _Node
{
Board board{ {BlockStatus::empty} };
bool isMax{ true };
int value{ NULL };
int depth{ NULL };
_Node* parent{ nullptr };
std::vector<_Node*> children;
int alpha{ INT_MIN };
int beta{ INT_MAX };
WinningStatus status{ WinningStatus::NO_WIN };
_Node(Board board, int depth, int value, int alpha, int beta, bool isMax, _Node* parent, WinningStatus status = WinningStatus::NO_WIN)
{
memcpy_s(this->board, sizeof(Board), board, sizeof(Board));
for (int i = 0; i < PIECES_PER_ROW + 2; i++)
{
board[0][i] = BlockStatus::border;
board[PIECES_PER_ROW + 1][i] = BlockStatus::border;
board[i][0] = BlockStatus::border;
board[i][PIECES_PER_ROW + 1] = BlockStatus::border;
}
this->depth = depth;
this->isMax = isMax;
this->value = value;
this->alpha = alpha;
this->beta = beta;
this->parent = parent;
this->status = status;
}
~_Node()
{
if (!this->children.empty())
for (auto child : this->children) delete child;
this->children.clear();
}
}Node, * LPNode;
typedef struct _EstimateResult
{
int score{ 0 };
WinningStatus status{ WinningStatus::NO_WIN };
}EstimateResult, * LPEstimateResult;
private:
ScenarioType scenarioTypeTuple[4][4][4][4][4][4];
int weight[21]{ NULL };
//transtabel
uint64_t blackPiecesHash[PIECES_PER_ROW][PIECES_PER_ROW]{ {NULL} };
uint64_t whitePiecesHash[PIECES_PER_ROW][PIECES_PER_ROW]{ {NULL} };
std::map<uint64_t, EstimateResult> transTabel;
//best move
Vec2 bestMove{ -1, -1 };
//current pieces' position
std::vector<Vec2> piecesPosition;
private:
uint64_t calculateHash(const Board board);
void initHashValues();
void initScenarioTypeTuple();
void initWeight();
void initPiecesPosition(const Board board);
int dfs(LPNode& node);
public:
Vec2 run(Board board);
EstimateResult estimate(const Board board);
void reset();
private:
ABPruningEngine();
~ABPruningEngine();
private:
static ABPruningEngine* instance;
public:
static ABPruningEngine* getInstance()
{
if (instance == nullptr) instance = new ABPruningEngine();
return instance;
}
static void destroyInstance()
{
if (instance != nullptr) delete instance;
}
};
}