My Project
midgame.c
Go to the documentation of this file.
1
11#include "search.h"
12
13#include "bit.h"
14#include "options.h"
15#include "stats.h"
16#include "ybwc.h"
17#include "settings.h"
18
19#include <assert.h>
20#include <math.h>
21
22#ifndef RCD
24#define RCD 0.5
25#endif
26
33{
34 const short *w = EVAL_WEIGHT[search->eval->player][60 - search->n_empties];
35 int *f = search->eval->feature;
36 int score;
37
40
41 score = w[f[ 0]] + w[f[ 1]] + w[f[ 2]] + w[f[ 3]]
42 + w[f[ 4]] + w[f[ 5]] + w[f[ 6]] + w[f[ 7]]
43 + w[f[ 8]] + w[f[ 9]] + w[f[10]] + w[f[11]]
44 + w[f[12]] + w[f[13]] + w[f[14]] + w[f[15]]
45 + w[f[16]] + w[f[17]] + w[f[18]] + w[f[19]]
46 + w[f[20]] + w[f[21]] + w[f[22]] + w[f[23]]
47 + w[f[24]] + w[f[25]]
48 + w[f[26]] + w[f[27]] + w[f[28]] + w[f[29]]
49 + w[f[30]] + w[f[31]] + w[f[32]] + w[f[33]]
50 + w[f[34]] + w[f[35]] + w[f[36]] + w[f[37]]
51 + w[f[38]] + w[f[39]] + w[f[40]] + w[f[41]]
52 + w[f[42]] + w[f[43]] + w[f[44]] + w[f[45]]
53 + w[f[46]];
54
55 if (score > 0) score += 64; else score -= 64;
56 score /= 128;
57
58 if (score <= SCORE_MIN) score = SCORE_MIN + 1;
59 else if (score >= SCORE_MAX) score = SCORE_MAX - 1;
60
61 return score;
62}
63
74int search_eval_1(Search *search, const int alpha, int beta)
75{
76 const short *w = EVAL_WEIGHT[search->eval->player ^ 1][61 - search->n_empties];
77 Move move[1];
78 SquareList *empty;
79 register int score, bestscore;
80 const Board *board = search->board;
81 Eval *eval = search->eval;
82 unsigned long long moves = get_moves(board->player, board->opponent);
83 int *f;
84
87
88 if (moves) {
89 bestscore = -SCORE_INF;
90 if (beta >= SCORE_MAX) beta = SCORE_MAX - 1;
91 foreach_empty (empty, search->empties) {
92 if (moves & empty->b) {
93 board_get_move(board, empty->x, move);
94 if (move_wipeout(move, board)) return SCORE_MAX;
95 eval_update(eval, move);
96 f = eval->feature;
98 score = -w[f[ 0]] - w[f[ 1]] - w[f[ 2]] - w[f[ 3]]
99 - w[f[ 4]] - w[f[ 5]] - w[f[ 6]] - w[f[ 7]]
100 - w[f[ 8]] - w[f[ 9]] - w[f[10]] - w[f[11]]
101 - w[f[12]] - w[f[13]] - w[f[14]] - w[f[15]]
102 - w[f[16]] - w[f[17]] - w[f[18]] - w[f[19]]
103 - w[f[20]] - w[f[21]] - w[f[22]] - w[f[23]]
104 - w[f[24]] - w[f[25]]
105 - w[f[26]] - w[f[27]] - w[f[28]] - w[f[29]]
106 - w[f[30]] - w[f[31]] - w[f[32]] - w[f[33]]
107 - w[f[34]] - w[f[35]] - w[f[36]] - w[f[37]]
108 - w[f[38]] - w[f[39]] - w[f[40]] - w[f[41]]
109 - w[f[42]] - w[f[43]] - w[f[44]] - w[f[45]]
110 - w[f[46]];
111 eval_restore(eval, move);
112
113 if (score > 0) score += 64; else score -= 64;
114 score /= 128;
115
116 if (score > bestscore) {
117 bestscore = score;
118 if (bestscore >= beta) break;
119 }
120 }
121 }
122 if (bestscore <= SCORE_MIN) bestscore = SCORE_MIN + 1;
123 else if (bestscore >= SCORE_MAX) bestscore = SCORE_MAX - 1;
124 } else {
125 if (can_move(board->opponent, board->player)) {
127 bestscore = -search_eval_1(search, -beta, -alpha);
129 } else { // game over
130 bestscore = search_solve(search);
131 }
132 }
133
134 assert(SCORE_MIN <= bestscore && bestscore <= SCORE_MAX);
135 return bestscore;
136}
137
147int search_eval_2(Search *search, int alpha, const int beta)
148{
149 register int bestscore, score;
150 SquareList *empty;
151 Move move[1];
152 const Board *board = search->board;
153 const unsigned long long moves = get_moves(board->player, board->opponent);
154
157
158 assert(-SCORE_MAX <= alpha && alpha <= SCORE_MAX);
159 assert(-SCORE_MAX <= beta && beta <= SCORE_MAX);
160 assert(alpha <= beta);
161
162 if (moves) {
163 bestscore = -SCORE_INF;
164 foreach_empty(empty, search->empties) {
165 if (moves & empty->b) {
166 board_get_move(board, empty->x, move);
167 search_update_midgame(search, move);
168 score = -search_eval_1(search, -beta, -alpha);
169 search_restore_midgame(search, move);
170 if (score > bestscore) {
171 bestscore = score;
172 if (bestscore >= beta) break;
173 else if (bestscore > alpha) alpha = bestscore;
174 }
175 }
176 }
177 } else {
178 if (can_move(board->opponent, board->player)) {
180 bestscore = -search_eval_2(search, -beta, -alpha);
182 } else {
183 bestscore = search_solve(search);
184 }
185 }
186
187 assert(SCORE_MIN <= bestscore && bestscore <= SCORE_MAX);
188
189 return bestscore;
190}
191
192static inline void search_update_probcut(Search *search, const NodeType node_type)
193{
194 search->node_type[search->height] = node_type;
197}
198
199
200static inline void search_restore_probcut(Search *search, const NodeType node_type, const int selectivity)
201{
202 search->node_type[search->height] = node_type;
203 if (!USE_RECURSIVE_PROBCUT) search->selectivity = selectivity;
205}
206
220static bool search_probcut(Search *search, const int alpha, const int depth, Node *parent, int *value)
221{
222 // assertion
223 assert(search != NULL);
224 assert(parent != NULL);
225 assert(search->node_type[search->height] != PV_NODE);
226 assert(0 <= search->selectivity && search->selectivity <= NO_SELECTIVITY);
227
228 // do probcut ?
229 if (USE_PROBCUT && depth >= options.probcut_d && search->selectivity < NO_SELECTIVITY LIMIT_RECURSIVE_PROBCUT(&& search->probcut_level < 2)) {
230 int probcut_error, eval_error;
231 int probcut_depth, probcut_beta, probcut_alpha;
232 int eval_score, eval_beta, eval_alpha;
233 register int score;
234 const int beta = alpha + 1;
235 double t = selectivity_table[search->selectivity].t;
236 const int saved_selectivity = search->selectivity;
237 const NodeType node_type = search->node_type[search->height];
238
240
241 // compute reduced depth & associated error
242 probcut_depth = 2 * floor(options.probcut_d * depth) + (depth & 1);
243 if (probcut_depth == 0) probcut_depth = depth - 2;
244 assert(probcut_depth > 1 && probcut_depth <= depth - 2 && (probcut_depth & 1) == (depth & 1));
245 probcut_error = t * eval_sigma(search->n_empties, depth, probcut_depth) + RCD;
246
247 // compute evaluation error (i.e. error at depth 0) averaged for both depths
248 eval_score = search_eval_0(search);
249 eval_error = t * 0.5 * (eval_sigma(search->n_empties, depth, 0) + eval_sigma(search->n_empties, depth, probcut_depth)) + RCD;
250
251 // try a probable upper cut first
252 eval_beta = beta - eval_error;
253 probcut_beta = beta + probcut_error;
254 probcut_alpha = probcut_beta - 1;
255 if (eval_score >= eval_beta && probcut_beta < SCORE_MAX) { // check if trying a beta probcut is worth
258 score = NWS_midgame(search, probcut_alpha, probcut_depth, parent);
259 search_restore_probcut(search, node_type, saved_selectivity);
260 if (score >= probcut_beta) {
261 *value = beta;
263 return true;
264 }
265 }
266
267 // try a probable lower cut if upper cut failed
268 eval_alpha = alpha + eval_error;
269 probcut_alpha = alpha - probcut_error;
270 if (eval_score < eval_alpha && probcut_alpha > SCORE_MIN) { // check if trying an alpha probcut is worth
273 score = NWS_midgame(search, probcut_alpha, probcut_depth, parent);
274 search_restore_probcut(search, node_type, saved_selectivity);
275 if (score <= probcut_alpha) {
276 *value = alpha;
278 return true;
279 }
280 }
281 }
282
283 return false;
284}
285
300int NWS_shallow(Search *search, const int alpha, int depth, HashTable *hash_table)
301{
302 int score;
303 unsigned long long hash_code;
304 const int beta = alpha + 1;
305 HashData hash_data[1];
306 Board *board = search->board;
307 MoveList movelist[1];
308 Move *move;
309 int bestscore, bestmove;
310 long long cost = -search->n_nodes;
311
312 if (depth == 2) return search_eval_2(search, alpha, beta);
313
316
317 assert(search->n_empties == bit_count(~(search->board->player|search->board->opponent)));
318 assert(SCORE_MIN <= alpha && alpha <= SCORE_MAX);
319 assert(depth > 2);
320 assert(hash_table != NULL);
321
322 // stability cutoff
323 if (search_SC_NWS(search, alpha, &score)) return score;
324
325 // transposition cutoff
326 hash_code = board_get_hash_code(board);
327 if (hash_get(hash_table, board, hash_code, hash_data) && search_TC_NWS(hash_data, depth, search->selectivity, alpha, &score)) return score;
328 search_get_movelist(search, movelist);
329
330 if (movelist_is_empty(movelist)) { // no moves ?
331 if (can_move(board->opponent, board->player)) { // pass ?
333 bestscore = -NWS_shallow(search, -beta, depth, hash_table);
334 bestmove = PASS;
336 } else { // game-over !
337 bestscore = search_solve(search);
338 bestmove = NOMOVE;
339 }
340 } else {
341 // sort the list of moves
342 movelist_evaluate(movelist, search, hash_data, alpha, depth);
343 movelist_sort(movelist) ;
344
345 // loop over all moves
346 bestscore = -SCORE_INF; bestmove = NOMOVE;
347 foreach_move(move, movelist) {
348 search_update_midgame(search, move);
349 score = -NWS_shallow(search, -beta, depth - 1, hash_table);
350 search_restore_midgame(search, move);
351 if (score > bestscore) {
352 bestscore = score;
353 bestmove = move->x;
354 if (bestscore >= beta) break;
355 }
356 }
357 }
358
359 // save the best result in hash tables
360 cost += search->n_nodes;
361 hash_store(hash_table, board, hash_code, depth, search->selectivity, last_bit(cost), alpha, beta, bestscore, bestmove);
362 assert(SCORE_MIN <= bestscore && bestscore <= SCORE_MAX);
363
364 return bestscore;
365}
366
381int PVS_shallow(Search *search, int alpha, int beta, int depth)
382{
383 int score;
384 HashTable *hash_table = search->shallow_table;
385 unsigned long long hash_code;
386 HashData hash_data[1];
387 Board *board = search->board;
388 MoveList movelist[1];
389 Move *move;
390 int bestscore, bestmove;
391 long long cost = -search->n_nodes;
392 int lower;
393
394 if (depth == 2) return search_eval_2(search, alpha, beta);
395
398
399 assert(search->n_empties == bit_count(~(search->board->player|search->board->opponent)));
400 assert(SCORE_MIN <= alpha && alpha <= SCORE_MAX);
401
402 // stability cutoff
403 if (search_SC_PVS(search, &alpha, &beta, &score)) return score;
404
405 // transposition cutoff
406 hash_code = board_get_hash_code(board);
407// if (hash_get(hash_table, board, hash_code, hash_data) && search_TC_PVS(hash_data, depth, search->selectivity, &alpha, &beta, &score)) return score;
408 hash_get(hash_table, board, hash_code, hash_data);
409
410 search_get_movelist(search, movelist);
411
412 if (movelist_is_empty(movelist)) { // no moves ?
413 if (can_move(board->opponent, board->player)) { // pass ?
415 bestscore = -PVS_shallow(search, -beta, -alpha, depth);
416 bestmove = PASS;
418 } else { // game-over !
419 bestscore = search_solve(search);
420 bestmove = NOMOVE;
421 }
422 } else {
423 // sort the list of moves
424 movelist_evaluate(movelist, search, hash_data, alpha, depth);
425 movelist_sort(movelist) ;
426
427 // loop over all moves
428 bestscore = -SCORE_INF; bestmove = NOMOVE;
429 lower = alpha;
430 foreach_move(move, movelist) {
431 search_update_midgame(search, move);
432 if (bestscore == -SCORE_INF) {
433 score = -PVS_shallow(search, -beta, -lower, depth - 1);
434 } else {
435 score = -NWS_shallow(search, -lower - 1, depth - 1, hash_table);
436 if (alpha < score && score < beta) {
437 score = -PVS_shallow(search, -beta, -lower, depth - 1);
438 }
439 }
440 search_restore_midgame(search, move);
441 if (score > bestscore) {
442 bestscore = score;
443 bestmove = move->x;
444 if (bestscore >= beta) break;
445 else if (bestscore > lower) lower = bestscore;
446 }
447 }
448 }
449
450 // save the best result in hash tables
451 cost += search->n_nodes;
452 hash_store(hash_table, board, hash_code, depth, search->selectivity, last_bit(cost), alpha, beta, bestscore, bestmove);
453 assert(SCORE_MIN <= bestscore && bestscore <= SCORE_MAX);
454
455 return bestscore;
456}
457
458
473int NWS_midgame(Search *search, const int alpha, int depth, Node *parent)
474{
475 int score;
476 HashTable *hash_table = search->hash_table;
477 HashTable *pv_table = search->pv_table;
478 unsigned long long hash_code;
479 const int beta = alpha + 1;
480 HashData hash_data[1];
481 Board *board = search->board;
482 MoveList movelist[1];
483 Move *move;
484 Node node[1];
485 long long cost = -search->n_nodes - search->child_nodes;
486 int hash_selectivity;
487
488 assert(search->n_empties == bit_count(~(search->board->player|search->board->opponent)));
489 assert((2 <= depth && depth < search->n_empties) || depth == search->n_empties);
490 assert(SCORE_MIN <= alpha && alpha <= SCORE_MAX);
491 assert(parent != NULL);
492
493 search_check_timeout(search);
494 if (search->stop) return alpha;
495 else if (search->n_empties == 0) return search_solve_0(search);
496 else if (depth <= 3 && depth < search->n_empties) return NWS_shallow(search, alpha, depth, hash_table);
497 else if (search->n_empties <= depth && depth < DEPTH_MIDGAME_TO_ENDGAME) return NWS_endgame(search, alpha);
498
501
502 // stability cutoff
503 if (search_SC_NWS(search, alpha, &score)) return score;
504
505 // transposition cutoff
506 hash_code = board_get_hash_code(board);
507 if ((hash_get(hash_table, board, hash_code, hash_data) || hash_get(pv_table, board, hash_code, hash_data)) && search_TC_NWS(hash_data, depth, search->selectivity, alpha, &score)) return score;
508
509 search_get_movelist(search, movelist);
510
511 if (movelist_is_empty(movelist)) { // no moves ?
512 node_init(node, search, alpha, beta, depth, movelist->n_moves, parent);
513 if (can_move(board->opponent, board->player)) { // pass ?
515 node->bestscore = -NWS_midgame(search, -node->beta, depth, node);
517 } else { // game-over !
518 node->bestscore = search_solve(search);
519 }
520 } else {
521 // probcut
522 if (search_probcut(search, alpha, depth, parent, &score)) return score;
523
524 // sort the list of moves
525 if (movelist->n_moves > 1) {
526 if (hash_data->move[0] == NOMOVE) hash_get(hash_table, board, hash_code, hash_data);
527 movelist_evaluate(movelist, search, hash_data, alpha, depth + options.inc_sort_depth[search->node_type[search->height]]);
528 movelist_sort(movelist) ;
529 }
530
531 // ETC
532 if (search_ETC_NWS(search, movelist, hash_code, depth, search->selectivity, alpha, &score)) return score;
533
534 node_init(node, search, alpha, beta, depth, movelist->n_moves, parent);
535
536 // loop over all moves
537 for (move = node_first_move(node, movelist); move; move = node_next_move(node)) {
538 if (!node_split(node, move)) {
539 search_update_midgame(search, move);
540 move->score = -NWS_midgame(search, -beta, depth - 1, node);
541 search_restore_midgame(search, move);
542 node_update(node, move);
543 }
544 }
545 node_wait_slaves(node);
546 }
547
548 // save the best result in hash tables
549 if (!search->stop) {
550 cost += search->n_nodes + search->child_nodes;
551 if (search->n_empties < depth && depth <= DEPTH_MIDGAME_TO_ENDGAME) hash_selectivity = NO_SELECTIVITY; // hack
552 else hash_selectivity = search->selectivity;
553 if (search->height <= PV_HASH_HEIGHT) hash_store(pv_table, board, hash_code, depth, hash_selectivity, last_bit(cost), alpha, beta, node->bestscore, node->bestmove);
554 hash_store(hash_table, board, hash_code, depth, hash_selectivity, last_bit(cost), alpha, beta, node->bestscore, node->bestmove);
555 SQUARE_STATS(foreach_move(move, movelist))
557 SQUARE_STATS(if (node->bestscore > alpha) ++statistics.n_good_square[search->n_empties][SQUARE_TYPE[node->bestmove]];)
558
559 assert(SCORE_MIN <= node->bestscore && node->bestscore <= SCORE_MAX);
560 } else {
561 node->bestscore = alpha;
562 }
563
564 node_free(node);
565
566 return node->bestscore;
567}
568
569
585int PVS_midgame(Search *search, const int alpha, const int beta, int depth, Node *parent)
586{
587 // declaration
588 HashTable *hash_table = search->hash_table;
589 HashTable *pv_table = search->pv_table;
590 unsigned long long hash_code;
591 HashData hash_data[1];
592 Board *board = search->board;
593 MoveList movelist[1];
594 Move *move;
595 Node node[1];
596 long long cost;
597 int reduced_depth, depth_pv_extension, saved_selectivity;
598 int hash_selectivity;
599
601
602 assert(search->n_empties == bit_count(~(search->board->player|search->board->opponent)));
603 assert(depth <= search->n_empties);
604 assert((-SCORE_MAX <= alpha && alpha <= SCORE_MAX) || printf("alpha = %d\n", alpha));
605 assert((-SCORE_MAX <= beta && beta <= SCORE_MAX) || printf("beta = %d\n", beta));
606 assert(alpha <= beta);
607
608 // end of search ?
609 search_check_timeout(search);
610 if (search->stop) return alpha;
611 else if (search->n_empties == 0) return search_solve_0(search);
612 else if (USE_PV_EXTENSION && depth < search->n_empties && search->n_empties <= search->depth_pv_extension) return PVS_midgame(search, alpha, beta, search->n_empties, parent);
613 else if (depth == 2 && search->n_empties > 2) return search_eval_2(search, alpha, beta);
614
615 cost = -search_count_nodes(search);
617
618 search_get_movelist(search, movelist);
619 node_init(node, search, alpha, beta, depth, movelist->n_moves, parent);
620 node->pv_node = true;
621 hash_code = board_get_hash_code(board);
622
623 // special cases
624 if (movelist_is_empty(movelist)) {
625 if (can_move(board->opponent, board->player)) {
626 search_update_pass_midgame(search); search->node_type[search->height] = PV_NODE;
627 node->bestscore = -PVS_midgame(search, -beta, -alpha, depth, node);
629 node->bestmove = PASS;
630 } else {
631 node->alpha = -(node->beta = +SCORE_INF);
632 node->bestscore = search_solve(search);
633 node->bestmove = NOMOVE;
634 }
635 } else { // normal PVS
636 if (movelist->n_moves > 1) {
637 //IID
638 if (!hash_get(pv_table, board, hash_code, hash_data)) hash_get(hash_table, board, hash_code, hash_data);
639 if (USE_IID && hash_data->move[0] == NOMOVE) {
640 if (depth == search->n_empties) reduced_depth = depth - ITERATIVE_MIN_EMPTIES;
641 else reduced_depth = depth - 2;
642 if (reduced_depth >= 3) {
643 saved_selectivity = search->selectivity; search->selectivity = 0;
644 depth_pv_extension = search->depth_pv_extension;
645 search->depth_pv_extension = 0;
646 PVS_midgame(search, SCORE_MIN, SCORE_MAX, reduced_depth, parent);
647 hash_get(pv_table, board, hash_code, hash_data);
648 search->depth_pv_extension = depth_pv_extension;
649 search->selectivity = saved_selectivity;
650 }
651 }
652
653 // Evaluate moves for sorting. For a better ordering, the depth is artificially increased
654 movelist_evaluate(movelist, search, hash_data, node->alpha, depth + options.inc_sort_depth[PV_NODE]);
655 movelist_sort(movelist) ;
656 }
657
658 // first move
659 if ((move = node_first_move(node, movelist))) { // why if there ?
660 search_update_midgame(search, move); search->node_type[search->height] = PV_NODE;
661 move->score = -PVS_midgame(search, -beta, -alpha, depth - 1, node);
662 search_restore_midgame(search, move);
663 node_update(node, move);
664
665 // other moves : try to refute the first/best one
666 while ((move = node_next_move(node))) {
667 if (!node_split(node, move)) {
668 const int alpha = node->alpha;
669 search_update_midgame(search, move);
670 move->score = -NWS_midgame(search, -alpha - 1, depth - 1, node);
671 if (!search->stop && alpha < move->score && move->score < beta) {
672 search->node_type[search->height] = PV_NODE;
673 move->score = -PVS_midgame(search, -beta, -alpha, depth - 1, node);
674 }
675 search_restore_midgame(search, move);
676 node_update(node, move);
677 }
678 }
679 node_wait_slaves(node);
680 }
681 }
682
683 // save the best result in hash tables
684 if (!search->stop) {
685 cost += search_count_nodes(search);
686 if (search->n_empties < depth && depth <= DEPTH_MIDGAME_TO_ENDGAME) hash_selectivity = NO_SELECTIVITY;
687 else hash_selectivity = search->selectivity;
688 hash_store(hash_table, board, hash_code, depth, hash_selectivity, last_bit(cost), alpha, beta, node->bestscore, node->bestmove);
689 hash_store(pv_table, board, hash_code, depth, hash_selectivity, last_bit(cost), alpha, beta, node->bestscore, node->bestmove);
690
691 SQUARE_STATS(foreach_move(move, movelist))
693 SQUARE_STATS(if (node->bestscore > alpha) ++statistics.n_good_square[search->n_empties][SQUARE_TYPE[node->bestmove]];)
694
695 assert(SCORE_MIN <= node->bestscore && node->bestscore <= SCORE_MAX);
696
697 } else {
698 node->bestscore = alpha;
699 }
700
701 node_free(node);
702
703 return node->bestscore;
704}
DLL_API int bit_count(unsigned long long b)
Count the number of bits set to one in an unsigned long long.
Definition bit.c:72
DLL_API int last_bit(unsigned long long b)
Search the last bit set (same as log2()).
Definition bit.c:264
unsigned long long board_get_hash_code(const Board *board)
Compute a hash code.
Definition board.c:1134
unsigned long long board_get_move(const Board *board, const int x, Move *move)
Compute a move.
Definition board.c:438
DLL_API unsigned long long get_moves(const unsigned long long P, const unsigned long long O)
Get legal moves.
Definition board.c:621
DLL_API bool can_move(const unsigned long long P, const unsigned long long O)
Check if a player can move.
Definition board.c:797
#define SCORE_MAX
Definition const.h:58
#define SCORE_INF
Definition const.h:52
@ PASS
Definition const.h:37
@ NOMOVE
Definition const.h:37
NodeType
Definition const.h:80
@ CUT_NODE
Definition const.h:82
@ PV_NODE
Definition const.h:81
@ ALL_NODE
Definition const.h:83
#define SCORE_MIN
Definition const.h:55
#define foreach_empty(empty, list)
Definition empty.h:46
int NWS_endgame(Search *search, const int alpha)
Evaluate an endgame position with a Null Window Search algorithm.
Definition endgame.c:449
int search_solve(const Search *search)
Get the final score.
Definition endgame.c:52
int search_solve_0(const Search *search)
Get the final score.
Definition endgame.c:80
void eval_restore(Eval *eval, const Move *move)
Definition eval.c:810
void eval_update(Eval *eval, const Move *move)
Definition eval.c:681
double eval_sigma(const int n_empty, const int depth, const int probcut_depth)
Compute the error-type of the evaluation function according to the depths.
Definition eval.c:843
short *** EVAL_WEIGHT
Definition eval.c:231
bool hash_get(HashTable *hash_table, const unsigned long long hash_code, HashData *data)
Find an hash table entry according to the evaluated board hash codes.
Definition hash-lock-free.c:600
void hash_store(HashTable *hash_table, const unsigned long long hash_code, const int depth, const int selectivity, const int cost, const int alpha, const int beta, const int score, const int move)
Store an hashtable item.
Definition hash-lock-free.c:543
int search_eval_2(Search *search, int alpha, const int beta)
Evaluate a position at depth 2.
Definition midgame.c:147
static void search_update_probcut(Search *search, const NodeType node_type)
Definition midgame.c:192
int NWS_midgame(Search *search, const int alpha, int depth, Node *parent)
Evaluate a midgame position with a Null Window Search algorithm.
Definition midgame.c:473
static bool search_probcut(Search *search, const int alpha, const int depth, Node *parent, int *value)
Probcut.
Definition midgame.c:220
int search_eval_0(Search *search)
evaluate a midgame position with the evaluation function.
Definition midgame.c:32
int PVS_midgame(Search *search, const int alpha, const int beta, int depth, Node *parent)
Evaluate a position with a deep Principal Variation Search algorithm.
Definition midgame.c:585
int PVS_shallow(Search *search, int alpha, int beta, int depth)
Evaluate a midgame position at shallow depth.
Definition midgame.c:381
#define RCD
Definition midgame.c:24
static void search_restore_probcut(Search *search, const NodeType node_type, const int selectivity)
Definition midgame.c:200
int search_eval_1(Search *search, const int alpha, int beta)
Evaluate a position at depth 1.
Definition midgame.c:74
int NWS_shallow(Search *search, const int alpha, int depth, HashTable *hash_table)
Evaluate a midgame position with a Null Window Search algorithm.
Definition midgame.c:300
bool movelist_is_empty(const MoveList *movelist)
Check if the list is empty.
Definition move.c:537
bool move_wipeout(const Move *move, const Board *board)
Check if a move wins 64-0.
Definition move.c:148
void movelist_sort(MoveList *movelist)
Sort all moves.
Definition move.c:505
void movelist_evaluate(MoveList *movelist, Search *search, const HashData *hash_data, const int alpha, const int depth)
Evaluate a list of move in order to sort it.
Definition move.c:436
#define foreach_move(iter, movelist)
Definition move.h:78
Options options
Definition options.c:22
const int NO_SELECTIVITY
Definition search.c:94
bool search_TC_NWS(HashData *data, const int depth, const int selectivity, const int alpha, int *score)
Transposition Cutoff (TC).
Definition search.c:1230
void search_check_timeout(Search *search)
Check if it can iterate more...
Definition search.c:800
bool search_SC_PVS(Search *search, volatile int *alpha, volatile int *beta, int *score)
Stability Cutoff (SC).
Definition search.c:1146
const Selectivity selectivity_table[]
Definition search.c:97
void search_get_movelist(const Search *search, MoveList *movelist)
Get a list of legal moves.
Definition search.c:875
void search_restore_pass_midgame(Search *search)
Update the search state after a passing move.
Definition search.c:998
unsigned long long search_count_nodes(Search *search)
Return the number of nodes searched.
Definition search.c:1073
void search_restore_midgame(Search *search, const Move *move)
Restore the search state as before a move.
Definition search.c:964
const int SQUARE_TYPE[]
Definition search.c:132
void search_update_midgame(Search *search, const Move *move)
Update the search state after a move.
Definition search.c:942
bool search_ETC_NWS(Search *search, MoveList *movelist, unsigned long long hash_code, const int depth, const int selectivity, const int alpha, int *score)
Enhanced Transposition Cutoff (ETC).
Definition search.c:1264
void search_update_pass_midgame(Search *search)
Update the search state after a passing move.
Definition search.c:983
bool search_SC_NWS(Search *search, const int alpha, int *score)
Stability Cutoff (TC).
Definition search.c:1170
#define LIMIT_RECURSIVE_PROBCUT(x)
Definition settings.h:42
#define USE_IID
Definition settings.h:59
#define USE_PV_EXTENSION
Definition settings.h:80
#define ITERATIVE_MIN_EMPTIES
Definition settings.h:89
#define USE_PROBCUT
Definition settings.h:36
#define USE_RECURSIVE_PROBCUT
Definition settings.h:39
#define DEPTH_MIDGAME_TO_ENDGAME
Definition settings.h:86
#define PV_HASH_HEIGHT
Definition settings.h:92
Statistics statistics
Definition stats.c:21
Statistics header.
#define SEARCH_UPDATE_EVAL_NODES()
Definition stats.h:47
#define PROBCUT_STATS(x)
Definition stats.h:33
#define SQUARE_STATS(x)
Definition stats.h:29
#define SEARCH_UPDATE_INTERNAL_NODES()
Definition stats.h:40
#define SEARCH_STATS(x)
Definition stats.h:27
Definition board.h:26
unsigned long long player
Definition board.h:27
unsigned long long opponent
Definition board.h:27
evaluation function
Definition eval.h:18
int player
Definition eval.h:20
int * feature
Definition eval.h:19
Definition hash.h:24
unsigned char move[2]
Definition hash.h:31
Definition hash.h:47
Definition move.h:29
int n_moves
Definition move.h:31
Definition move.h:20
int score
Definition move.h:23
int x
Definition move.h:22
Definition ybwc.h:48
int beta
Definition ybwc.h:52
bool pv_node
Definition ybwc.h:53
volatile int alpha
Definition ybwc.h:51
volatile int bestscore
Definition ybwc.h:50
volatile int bestmove
Definition ybwc.h:49
int inc_sort_depth[3]
Definition options.h:27
double probcut_d
Definition options.h:69
Definition search.h:95
int n_empties
Definition search.h:99
volatile unsigned long long child_nodes
Definition search.h:156
int depth_pv_extension
Definition search.h:121
int height
Definition search.h:133
SquareList empties[BOARD_SIZE+2]
Definition search.h:97
int probcut_level
Definition search.h:119
HashTable pv_table[1]
Definition search.h:104
HashTable hash_table[1]
Definition search.h:103
volatile Stop stop
Definition search.h:122
volatile unsigned long long n_nodes
Definition search.h:155
HashTable shallow_table[1]
Definition search.h:105
int selectivity
Definition search.h:118
Eval eval[1]
Definition search.h:106
NodeType node_type[GAME_SIZE]
Definition search.h:134
Board board[1]
Definition search.h:96
double t
Definition search.h:26
Definition empty.h:15
unsigned long long b
Definition empty.h:16
int x
Definition empty.h:17
unsigned long long n_search_eval_1
Definition stats.h:88
unsigned long long n_probcut_high_try
Definition stats.h:107
unsigned long long n_probcut_high_cutoff
Definition stats.h:107
unsigned long long n_probcut_low_cutoff
Definition stats.h:106
unsigned long long n_PVS_shallow
Definition stats.h:80
unsigned long long n_search_eval_0
Definition stats.h:87
unsigned long long n_search_eval_2
Definition stats.h:89
unsigned long long n_played_square[BOARD_SIZE][10]
Definition stats.h:110
unsigned long long n_NWS_midgame
Definition stats.h:78
unsigned long long n_good_square[BOARD_SIZE][10]
Definition stats.h:111
unsigned long long n_probcut_try
Definition stats.h:105
unsigned long long n_PVS_midgame
Definition stats.h:77
unsigned long long n_probcut_low_try
Definition stats.h:106
Move * node_next_move(Node *node)
Get the next move of the move list.
Definition ybwc.c:345
void node_wait_slaves(Node *node)
Wait for slaves termination.
Definition ybwc.c:212
bool node_split(Node *node, Move *move)
Node split.
Definition ybwc.c:167
void node_free(Node *node)
Free Resources allocated by a node.
Definition ybwc.c:95
Move * node_first_move(Node *node, MoveList *movelist)
Get the first move of the move list.
Definition ybwc.c:297
void node_update(Node *node, Move *move)
Update a node.
Definition ybwc.c:261
void node_init(Node *node, Search *search, const int alpha, const int beta, const int depth, const int n_moves, Node *parent)
Initialize a node.
Definition ybwc.c:59
Parallel search header.