1 #include "MinimaxEnemy.h"
8 typedef MinimaxEnemy::HeuType HeuType
;
12 , maxhConcentration
= -1
13 , maxhCentralisation
= -1
16 , maxhConnectedness
= -1
24 static Board::MoveListOt g_MoveList
[10];
25 //static Board::Set _think_boards[2] = {Board::Set(board_compare), Board::Set(board_compare)};
27 //static std::map<Board::Comp, int> _board_value[2];
28 static Heu g_Heu
[10][8 * 12];
29 static Board g_Boards
[10][8 * 12];
31 int lessHeu(const void *l
, const void *r
) {
32 return ((Heu
*)l
)->h
- ((Heu
*)r
)->h
;
35 int moreHeu(const void *l
, const void *r
) {
36 return ((Heu
*)r
)->h
- ((Heu
*)l
)->h
;
39 void MinimaxEnemy::move(Board
*board
, int& fromX
, int& fromY
, int& toX
, int& toY
)
41 //_game_boards.insert(board->to_comp());
42 //_think_boards[0].clear();
43 //_think_boards[1].clear();
44 //_board_value[0].clear();
45 //_board_value[1].clear();
48 for(Board::Set::iterator i = _game_boards.begin(); i != _game_boards.end(); ++i) {
49 cout << i->first << ' ' << i->second << endl;
53 Board::MoveListOt moveList
;
54 board
->all_moves(_player
, moveList
);
56 alphabeta(*board
, _minimax_depth
, -HeuTypeMax
, HeuTypeMax
, _player
);
57 //_game_boards.insert(board->move_result(_player, moveList[_choice]).to_comp());
59 //printf("_choice: %i\n", _choice); fflush(stdout);
62 printf("%i: (%i, %i) -> (%i, %i)\n", i, INDEX_X(moveList[i].first), INDEX_Y(moveList[i].first)
63 , INDEX_X(moveList[i].second), INDEX_Y(moveList[i].second));
67 fromX
= INDEX_X(INDEX_FROM(moveList
[_choice
]));
68 fromY
= INDEX_Y(INDEX_FROM(moveList
[_choice
]));
69 toX
= INDEX_X(INDEX_TO(moveList
[_choice
]));
70 toY
= INDEX_Y(INDEX_TO(moveList
[_choice
]));
73 #define SQU(x) ((x) * (x))
74 #define MAX(x, y) ((x) > (y) ? (x) : (y))
75 #define MAX_ALPHABETA HeuTypeMax / 10000
77 // negamax com poda alphabeta
78 HeuType
MinimaxEnemy::alphabeta(Board board
, int depth
, HeuType alpha
, HeuType beta
, int player
)
80 //printf("alphabeta(%i, %i, %i, %i)\n", depth, alpha, beta, player);
83 //printf("board is end %i %i\n", board.win(0), board.win(1));
84 int mul
= 2 * player
- 1; //1 -> 1; 0 -> -1
85 mul
*= 2 * _player
- 1;
86 if(board
.win(_player
)) return mul
* MAX_ALPHABETA
* (1 - 2 * board
.win(!_player
)) * (depth
+ 1); /* considerando vitoria simultanea */
87 return -mul
* MAX_ALPHABETA
* (depth
+ 1); /* dando prioridade para o caminho mais curto */
90 int mul
= 2 * player
- 1; //1 -> 1; 0 -> -1
91 mul
*= 2 * _player
- 1;
92 return mul
* heuristica(board
, _player
);
96 if(_game_boards.count(board.to_comp())) { // empate
97 return 0; // nao funciona, acaba sendo sempre a melhor escolha para ambos
100 //Board::MoveOt *moveList = g_MoveList[depth];
101 int size
= board
.all_moves(player
, g_MoveList
[depth
]);
105 g_Heu
[depth
][i
].h
= heuristica(g_Boards
[depth
][i
] = board
.move_result(player
, g_MoveList
[depth
][i
]), _player
);
106 g_Heu
[depth
][i
].i
= i
;
109 if(player
!= _player
) {
110 qsort(&g_Heu
[depth
], size
, sizeof(Heu
), lessHeu
);
112 qsort(&g_Heu
[depth
], size
, sizeof(Heu
), moreHeu
);
114 //Heu *perm = g_Heu[depth];
115 //Board *boards = g_Boards[depth];
118 if(depth == _minimax_depth) {
120 printf("%i(%i) ", g_Heu[depth][i].i, g_Heu[depth][i].h);
127 if(i / (float) size > 0.75) { // ignora os piores
130 //Board b = board.move_result(player, moveList[perm[i].i]);
131 //if(_game_boards.count(b.to_comp())) { /* empate */
132 //continue; // ignora posições que já foram atingidas antes
135 //if(_think_boards[!player].count(b.to_comp())) { /* transposição */
136 // rec = -_board_value[!player][b.to_comp()];
138 HeuType rec
= -alphabeta(g_Boards
[depth
][g_Heu
[depth
][i
].i
], depth
- 1, -beta
, -alpha
, !player
);
142 if(depth
== _minimax_depth
) {
143 _choice
= g_Heu
[depth
][i
].i
;
147 //_board_value[player][board.to_comp()] = alpha; _think_boards[player].insert(board.to_comp());
151 //_board_value[player][board.to_comp()] = alpha; _think_boards[player].insert(board.to_comp());
156 if(x > MAX(1, max##x)) { \
158 printf(#x ": %f\n", x); \
161 HeuType
MinimaxEnemy::heuristica(Board board
, bool player
)
163 HeuType hNull
= rand() / (double) RAND_MAX
164 , hCentro
= centro(board
, player
)
165 , hConcentration
= concentration(board
, player
)
166 , hCentralisation
= centralisation(board
, player
)
167 , hMasscenter
= masscenter(board
, player
)
168 , hQuads
= quads(board
, player
)
169 , hConnectedness
= connectedness(board
, player
)
170 , hUniformity
= uniformity(board
, player
)
174 //FINDMAX(hConcentration);
175 //FINDMAX(hCentralisation);
176 //FINDMAX(hMasscenter);
178 //FINDMAX(hConnectedness);
179 //FINDMAX(hUniformity);
180 return hNull
* _heu
[0]
182 + hConcentration
* _heu
[2]
183 + hCentralisation
* _heu
[3]
184 + hMasscenter
* _heu
[4]
186 + hConnectedness
* _heu
[6]
187 + hUniformity
* _heu
[7]
188 //+ centro(board, player)
189 //+ concentration(board, player)
190 //+ centralisation(board, player)
191 //+ masscenter(board, player)
192 //+ quads(board, player)
193 //+ connectedness(board, player)
194 //+ uniformity(board, player)
198 // centro: diferença entra as médias das distâncias para o centro
199 HeuType
MinimaxEnemy::centro(Board board
, bool player
)
204 if(board
.get(player
, i
, j
))
205 res
+= SQU(i
- 3.5) + SQU(j
- 3.5); // distância para o centro
206 res
/= (double) board
.t
[player
].count();
210 if(board
.get(!player
, i
, j
))
211 resb
+= SQU(i
- 3.5) + SQU(j
- 3.5); // distância para o centro
212 resb
/= (double) board
.t
[!player
].count();
213 //return MAX_ALPHABETA - res;
214 return (resb
- res
) / 14.8;
217 HeuType
MinimaxEnemy::concentration(Board board
, bool player
)
219 static HeuType minsum
[] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22};
220 HeuType cmx
= 0, cmy
= 0;
221 int n
= board
.t
[player
].count();
224 if(board
.get(player
, i
, j
)) {
231 HeuType sum
= -minsum
[n
];
234 if(board
.get(player
, i
, j
)) {
235 HeuType dx
= abs(cmx
- i
);
236 HeuType dy
= abs(cmy
- j
);
242 n
= board
.t
[!player
].count();
245 if(board
.get(!player
, i
, j
)) {
255 if(board
.get(!player
, i
, j
)) {
256 HeuType dx
= abs(cmx
- i
);
257 HeuType dy
= abs(cmy
- j
);
261 return (resb
- res
) / 24;
264 HeuType
MinimaxEnemy::centralisation(Board board
, bool player
)
267 int squval
[8][8] = {{-80, -25, -20, -20, -20, -20, -25, -80},
268 {-25, 10, 10, 10, 10, 10, 10, -25},
269 {-20, 10, 25, 25, 25, 25, 10, -20},
270 {-20, 10, 25, 50, 50, 25, 10, -20},
271 {-20, 10, 25, 50, 50, 25, 10, -20},
272 {-20, 10, 25, 25, 25, 25, 10, -20},
273 {-25, 10, 10, 10, 10, 10, 10, -25},
274 {-80, -25, -20, -20, -20, -20, -25, -80}};
278 if(board
.get(player
, i
, j
)) {
281 res
/= board
.t
[player
].count();
286 if(board
.get(!player
, i
, j
)) {
287 resb
+= squval
[i
][j
];
289 resb
/= board
.t
[!player
].count();
291 return (res
- resb
) / 63.1;
294 HeuType
MinimaxEnemy::masscenter(Board board
, bool player
)
296 HeuType cmx
= 0, cmy
= 0;
297 int n
= board
.t
[player
].count();
300 if(board
.get(player
, i
, j
)) {
306 HeuType res
= SQU(cmx
) + SQU(cmy
);
309 n
= board
.t
[!player
].count();
312 if(board
.get(!player
, i
, j
)) {
318 HeuType resb
= SQU(cmx
) + SQU(cmy
);
320 return (res
- resb
) / 52.5;
323 HeuType
MinimaxEnemy::quads(Board board
, bool player
)
325 HeuType cmx
= 0, cmy
= 0;
326 int n
= board
.t
[player
].count();
329 if(board
.get(player
, i
, j
)) {
336 repbe(i
, MAX(0, cmx
- 2), MIN(6, cmx
+ 3)) {
337 repbe(j
, MAX(0, cmy
- 2), MIN(6, cmy
+ 3)) {
338 if(board
.get(player
, i
, j
) +
339 board
.get(player
, i
+ 1, j
) +
340 board
.get(player
, i
, j
+ 1) +
341 board
.get(player
, i
+ 1, j
+ 1) >= 3) {
348 n
= board
.t
[!player
].count();
351 if(board
.get(!player
, i
, j
)) {
358 repbe(i
, MAX(0, cmx
- 2), MIN(6, cmx
+ 3)) {
359 repbe(j
, MAX(0, cmy
- 2), MIN(6, cmy
+ 3)) {
360 if(board
.get(!player
, i
, j
) +
361 board
.get(!player
, i
+ 1, j
) +
362 board
.get(!player
, i
, j
+ 1) +
363 board
.get(!player
, i
+ 1, j
+ 1) >= 3) {
369 return (res
- resb
) / 7.0;
372 HeuType
MinimaxEnemy::connectedness(Board board
, bool player
)
374 static int dx
[] = {-1, -1, -1, 0, 0, 1, 1, 1},
375 dy
[] = {-1, 0, 1, -1, 1, -1, 0, 1};
380 if(board
.get(player
, i
, j
)) {
388 if(board
.get(player
, x
, y
)) {
393 res
/= (double) board
.t
[player
].count();
398 if(board
.get(!player
, i
, j
)) {
406 if(board
.get(!player
, x
, y
)) {
411 resb
/= (double) board
.t
[!player
].count();
413 return (res
- resb
) / 4.0;
416 HeuType
MinimaxEnemy::uniformity(Board board
, bool player
)
419 int minx
, miny
, maxx
, maxy
;
424 if(board
.get(player
, i
, j
)) {
425 if(i
< minx
) minx
= i
;
426 if(i
> maxx
) maxx
= i
;
427 if(j
< miny
) miny
= j
;
428 if(j
> maxy
) maxy
= j
;
430 res
= (maxx
- minx
) * (maxy
- miny
);
436 if(board
.get(!player
, i
, j
)) {
437 if(i
< minx
) minx
= i
;
438 if(i
> maxx
) maxx
= i
;
439 if(j
< miny
) miny
= j
;
440 if(j
> maxy
) maxy
= j
;
442 resb
= (maxx
- minx
) * (maxy
- miny
);
443 return (resb
- res
) / 48.84;
446 void MinimaxEnemy::set_weights(HeuType heu
[NUM_HEU
])