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
[g_Heu
[_minimax_depth
][_choice
].i
]));
68 fromY
= INDEX_Y(INDEX_FROM(moveList
[g_Heu
[_minimax_depth
][_choice
].i
]));
69 toX
= INDEX_X(INDEX_TO(moveList
[g_Heu
[_minimax_depth
][_choice
].i
]));
70 toY
= INDEX_Y(INDEX_TO(moveList
[g_Heu
[_minimax_depth
][_choice
].i
]));
72 *board
= g_Boards
[_minimax_depth
][g_Heu
[_minimax_depth
][_choice
].i
];
74 //b.initial_position();
79 printf(#x ": %.5f %.5f\n", board->x[0], board->x[1]); \
82 //PRINTHEU(concentration);
83 //PRINTHEU(centralisation);
84 //PRINTHEU(masscenter);
86 //PRINTHEU(connectedness);
87 //PRINTHEU(uniformity);
90 #define SQU(x) ((x) * (x))
91 #define ABS(x) ((x) > 0 ? (x) : (-(x)))
92 #define MAX(x, y) ((x) > (y) ? (x) : (y))
93 #define MAX_ALPHABETA HeuTypeMax / 10000
96 // negamax com poda alphabeta
97 HeuType
MinimaxEnemy::alphabeta(const Board
&board
, int depth
, HeuType alpha
, HeuType beta
, int player
)
99 //printf("alphabeta(%i, %i, %i, %i)\n", depth, alpha, beta, player);
102 //printf("board is end %i %i\n", board.win(0), board.win(1));
103 int mul
= 2 * player
- 1; //1 -> 1; 0 -> -1
104 mul
*= 2 * _player
- 1;
105 if(board
.win(_player
)) return mul
* MAX_ALPHABETA
* (1 - 2 * board
.win(!_player
)) * (depth
+ 1); /* considerando vitoria simultanea */
106 return -mul
* MAX_ALPHABETA
* (depth
+ 1); /* dando prioridade para o caminho mais curto */
109 int mul
= 2 * player
- 1; //1 -> 1; 0 -> -1
110 mul
*= 2 * _player
- 1;
112 return mul
* heuristica(b
, _player
, player
);
116 if(_game_boards.count(board.to_comp())) { // empate
117 return 0; // nao funciona, acaba sendo sempre a melhor escolha para ambos
120 //Board::MoveOt *moveList = g_MoveList[depth];
121 int size
= board
.all_moves(player
, g_MoveList
[depth
]);
125 g_Heu
[depth
][i
].h
= heuristica(g_Boards
[depth
][i
] = board
.move_result(player
, g_MoveList
[depth
][i
]), _player
, player
);
126 g_Heu
[depth
][i
].i
= i
;
129 if(player
!= _player
) {
130 qsort(&g_Heu
[depth
], size
, sizeof(Heu
), lessHeu
);
132 qsort(&g_Heu
[depth
], size
, sizeof(Heu
), moreHeu
);
134 //Heu *perm = g_Heu[depth];
135 //Board *boards = g_Boards[depth];
138 if(depth == _minimax_depth) {
140 printf("%i(%i) ", g_Heu[depth][i].i, g_Heu[depth][i].h);
147 if(i / (float) size > 0.75) { // ignora os piores
150 //Board b = board.move_result(player, moveList[perm[i].i]);
151 //if(_game_boards.count(b.to_comp())) { /* empate */
152 //continue; // ignora posições que já foram atingidas antes
155 //if(_think_boards[!player].count(b.to_comp())) { /* transposição */
156 // rec = -_board_value[!player][b.to_comp()];
158 HeuType rec
= -alphabeta(g_Boards
[depth
][g_Heu
[depth
][i
].i
], depth
- 1, -beta
, -alpha
, !player
);
162 if(depth
== _minimax_depth
) {
163 //_choice = g_Heu[depth][i].i;
168 //_board_value[player][board.to_comp()] = alpha; _think_boards[player].insert(board.to_comp());
172 //_board_value[player][board.to_comp()] = alpha; _think_boards[player].insert(board.to_comp());
177 if(x > MAX(1, max##x)) { \
179 printf(#x ": %f\n", x); \
182 HeuType
MinimaxEnemy::heuristica(Board
&board
, bool player
, bool plastmove
)
184 HeuType hNull
= 0 //rand() / (double) RAND_MAX
185 , hCentro
= centro(board
, player
, plastmove
)
186 , hConcentration
= 0 //concentration(board, player, plastmove)
187 , hCentralisation
= centralisation(board
, player
, plastmove
)
188 , hMasscenter
= 0 //masscenter(board, player, plastmove)
189 , hQuads
= quads(board
, player
, plastmove
)
190 , hConnectedness
= connectedness(board
, player
, plastmove
)
191 , hUniformity
= 0 //uniformity(board, player, plastmove)
194 //FINDMAX(hConcentration);
195 //FINDMAX(hCentralisation);
196 //FINDMAX(hMasscenter);
198 //FINDMAX(hConnectedness);
199 //FINDMAX(hUniformity);
200 return (hNull
* _heu
[0]
202 + hConcentration
* _heu
[2]
203 + hCentralisation
* _heu
[3]
204 + hMasscenter
* _heu
[4]
206 + hConnectedness
* _heu
[6]
207 + hUniformity
* _heu
[7]) / _heu_total
208 //+ centro(board, player)
209 //+ concentration(board, player)
210 //+ centralisation(board, player)
211 //+ masscenter(board, player)
212 //+ quads(board, player)
213 //+ connectedness(board, player)
214 //+ uniformity(board, player)
218 // centro: diferença entra as médias das distâncias para o centro
219 HeuType
MinimaxEnemy::centro(Board
&board
, bool player
, bool plastmove
)
223 if(player
== plastmove
) {
226 if(board
.get(player
, i
, j
))
227 res
+= SQU(i
- 3.5) + SQU(j
- 3.5); // distância para o centro
228 res
/= (double) board
.t
[player
].count();
229 board
.centro
[player
] = res
;
230 resb
= board
.centro
[!player
];
234 if(board
.get(!player
, i
, j
))
235 resb
+= SQU(i
- 3.5) + SQU(j
- 3.5); // distância para o centro
236 resb
/= (double) board
.t
[!player
].count();
237 board
.centro
[!player
] = resb
;
238 res
= board
.centro
[player
];
240 //return MAX_ALPHABETA - res;
241 //printf("centro: %i %f %f\n", player, res, resb);
242 return (resb
- res
) / 14.8;
245 HeuType
MinimaxEnemy::concentration(Board
&board
, bool player
, bool plastmove
)
247 static HeuType minsum
[] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22};
248 HeuType cmx
= 0, cmy
= 0;
249 HeuType res
= 0, resb
= 0;
250 int n
= board
.t
[player
].count();
251 if(player
== plastmove
) {
254 if(board
.get(player
, i
, j
)) {
260 board
.cmx
[player
] = cmx
;
261 board
.cmy
[player
] = cmy
;
262 //printf("cm: %f %f\n", cmx, cmy);
264 HeuType sum
= -minsum
[n
];
267 if(board
.get(player
, i
, j
)) {
268 HeuType dx
= ABS(cmx
- i
);
269 HeuType dy
= ABS(cmy
- j
);
273 board
.concentration
[player
] = res
;
274 resb
= board
.concentration
[!player
];
277 n
= board
.t
[!player
].count();
280 if(board
.get(!player
, i
, j
)) {
286 board
.cmx
[!player
] = cmx
;
287 board
.cmy
[!player
] = cmy
;
289 HeuType sum
= -minsum
[n
];
292 if(board
.get(!player
, i
, j
)) {
293 HeuType dx
= ABS(cmx
- i
);
294 HeuType dy
= ABS(cmy
- j
);
298 board
.concentration
[!player
] = resb
;
299 res
= board
.concentration
[player
];
301 //printf(": %f %f\n", res, resb);
302 return (resb
- res
) / 24;
305 HeuType
MinimaxEnemy::centralisation(Board
&board
, bool player
, bool plastmove
)
308 int squval
[8][8] = {{-80, -25, -20, -20, -20, -20, -25, -80},
309 {-25, 10, 10, 10, 10, 10, 10, -25},
310 {-20, 10, 25, 25, 25, 25, 10, -20},
311 {-20, 10, 25, 50, 50, 25, 10, -20},
312 {-20, 10, 25, 50, 50, 25, 10, -20},
313 {-20, 10, 25, 25, 25, 25, 10, -20},
314 {-25, 10, 10, 10, 10, 10, 10, -25},
315 {-80, -25, -20, -20, -20, -20, -25, -80}};
319 if(player
== plastmove
) {
322 if(board
.get(player
, i
, j
)) {
325 res
/= board
.t
[player
].count();
326 board
.centralisation
[player
] = res
;
327 resb
= board
.centralisation
[!player
];
331 if(board
.get(!player
, i
, j
)) {
332 resb
+= squval
[i
][j
];
334 resb
/= board
.t
[!player
].count();
335 board
.centralisation
[!player
] = resb
;
336 res
= board
.centralisation
[player
];
338 //printf(": %f %f\n", res, resb);
339 return (res
- resb
) / 63.1;
342 HeuType
MinimaxEnemy::masscenter(Board
&board
, bool player
, bool plastmove
)
344 HeuType cmx
= 0, cmy
= 0;
345 HeuType res
= 0.0, resb
= 0.0;
346 //int n = board.t[player].count();
349 //if(board.get(player, i, j)) {
355 if(player
== plastmove
) {
356 cmx
= board
.cmx
[player
];
357 cmy
= board
.cmy
[player
];
358 res
= SQU(cmx
- 3.5) + SQU(cmy
- 3.5);
359 board
.masscenter
[player
] = res
;
360 resb
= board
.masscenter
[!player
];
362 cmx
= board
.cmx
[!player
];
363 cmy
= board
.cmy
[!player
];
364 resb
= SQU(cmx
- 3.5) + SQU(cmy
- 3.5);
365 board
.masscenter
[!player
] = resb
;
366 res
= board
.masscenter
[player
];
370 //n = board.t[!player].count();
373 //if(board.get(!player, i, j)) {
379 //HeuType resb = SQU(cmx) + SQU(cmy);
381 //printf(": %f %f\n", res, resb);
382 return (res
- resb
) / 24.5;
385 HeuType
MinimaxEnemy::quads(Board
&board
, bool player
, bool plastmove
)
387 HeuType cmx
= 0, cmy
= 0;
388 //int n = board.t[player].count();
391 //if(board.get(player, i, j)) {
400 if(player
== plastmove
) {
401 cmx
= board
.cmx
[player
];
402 cmy
= board
.cmy
[player
];
403 repbe(i
, MAX(0, cmx
- 2), MIN(6, cmx
+ 3)) {
404 repbe(j
, MAX(0, cmy
- 2), MIN(6, cmy
+ 3)) {
405 if(board
.get(player
, i
, j
) +
406 board
.get(player
, i
+ 1, j
) +
407 board
.get(player
, i
, j
+ 1) +
408 board
.get(player
, i
+ 1, j
+ 1) >= 3) {
413 board
.quads
[player
] = res
;
414 resb
= board
.quads
[!player
];
416 cmx
= board
.cmx
[!player
];
417 cmy
= board
.cmy
[!player
];
418 repbe(i
, MAX(0, cmx
- 2), MIN(6, cmx
+ 3)) {
419 repbe(j
, MAX(0, cmy
- 2), MIN(6, cmy
+ 3)) {
420 if(board
.get(!player
, i
, j
) +
421 board
.get(!player
, i
+ 1, j
) +
422 board
.get(!player
, i
, j
+ 1) +
423 board
.get(!player
, i
+ 1, j
+ 1) >= 3) {
428 board
.quads
[!player
] = resb
;
429 res
= board
.quads
[player
];
432 //n = board.t[!player].count();
435 //if(board.get(!player, i, j)) {
442 //printf(": %f %f\n", res, resb);
443 return (res
- resb
) / 8.0;
446 HeuType
MinimaxEnemy::connectedness(Board
&board
, bool player
, bool plastmove
)
448 static int dx
[] = {-1, -1, -1, 0, 0, 1, 1, 1},
449 dy
[] = {-1, 0, 1, -1, 1, -1, 0, 1};
454 if(player
== plastmove
) {
457 if(board
.get(player
, i
, j
)) {
465 if(board
.get(player
, x
, y
)) {
470 res
/= (double) board
.t
[player
].count();
471 board
.connectedness
[player
] = res
;
472 resb
= board
.connectedness
[!player
];
476 if(board
.get(!player
, i
, j
)) {
484 if(board
.get(!player
, x
, y
)) {
489 resb
/= (double) board
.t
[!player
].count();
490 board
.connectedness
[!player
] = resb
;
491 res
= board
.connectedness
[player
];
493 //printf(": %f %f\n", res, resb);
494 return (res
- resb
) / 4.0;
497 HeuType
MinimaxEnemy::uniformity(Board
&board
, bool player
, bool plastmove
)
501 int minx
, miny
, maxx
, maxy
;
503 if(player
== plastmove
) {
508 if(board
.get(player
, i
, j
)) {
509 if(i
< minx
) minx
= i
;
510 if(i
> maxx
) maxx
= i
;
511 if(j
< miny
) miny
= j
;
512 if(j
> maxy
) maxy
= j
;
514 res
= (maxx
- minx
+ 1) * (maxy
- miny
+ 1);
515 board
.uniformity
[player
] = res
;
516 resb
= board
.uniformity
[!player
];
522 if(board
.get(!player
, i
, j
)) {
523 if(i
< minx
) minx
= i
;
524 if(i
> maxx
) maxx
= i
;
525 if(j
< miny
) miny
= j
;
526 if(j
> maxy
) maxy
= j
;
528 resb
= (maxx
- minx
+ 1) * (maxy
- miny
+ 1);
529 board
.uniformity
[!player
] = resb
;
530 res
= board
.uniformity
[player
];
532 //printf(": %f %f\n", res, resb);
533 return (resb
- res
) / 52;
536 void MinimaxEnemy::set_weights(HeuType heu
[NUM_HEU
])
540 _heu_total
+= _heu
[i
] = heu
[i
];