My Project
search.c
Go to the documentation of this file.
1
60#include "search.h"
61
62#include "bit.h"
63#include "options.h"
64#include "stats.h"
65#include "util.h"
66#include "ybwc.h"
67#include "settings.h"
68
69#include <assert.h>
70#include <limits.h>
71#include <stdlib.h>
72#include <math.h>
73
75
76#ifdef _MSC_VER
77#define log2(x) (log(x)/log(2.0))
78#endif
79
81const int QUADRANT_ID[] = {
82 1, 1, 1, 1, 2, 2, 2, 2,
83 1, 1, 1, 1, 2, 2, 2, 2,
84 1, 1, 1, 1, 2, 2, 2, 2,
85 1, 1, 1, 1, 2, 2, 2, 2,
86 4, 4, 4, 4, 8, 8, 8, 8,
87 4, 4, 4, 4, 8, 8, 8, 8,
88 4, 4, 4, 4, 8, 8, 8, 8,
89 4, 4, 4, 4, 8, 8, 8, 8,
90 0, 0
91 };
92
94const int NO_SELECTIVITY = 5;
95
98 {1.1, 0, 73}, // strong selectivity
99 {1.5, 1, 87}, // |
100 {2.0, 2, 95}, // |
101 {2.6, 3, 98}, // |
102 {3.3, 4, 99}, // V
103 {999, 5,100}, // no selectivity
104};
105
107// TODO: better values may exist.
108const int NWS_STABILITY_THRESHOLD[] = { // 99 = unused value...
109 99, 99, 99, 99, 6, 8, 10, 12,
110 14, 16, 20, 22, 24, 26, 28, 30,
111 32, 34, 36, 38, 40, 42, 44, 46,
112 48, 48, 50, 50, 52, 52, 54, 54,
113 56, 56, 58, 58, 60, 60, 62, 62,
114 64, 64, 64, 64, 64, 64, 64, 64,
115 99, 99, 99, 99, 99, 99, 99, 99, // no stable square at those depths
116};
117
119// TODO: better values may exist.
120const int PVS_STABILITY_THRESHOLD[] = { // 99 = unused value...
121 99, 99, 99, 99, -2, 0, 2, 4,
122 6, 8, 12, 14, 16, 18, 20, 22,
123 24, 26, 28, 30, 32, 34, 36, 38,
124 40, 40, 42, 42, 44, 44, 46, 46,
125 48, 48, 50, 50, 52, 52, 54, 54,
126 56, 56, 58, 58, 60, 60, 62, 62,
127 99, 99, 99, 99, 99, 99, 99, 99, // no stable square at those depths
128};
129
130
132const int SQUARE_TYPE[] = {
133 0, 1, 2, 3, 3, 2, 1, 0,
134 1, 4, 5, 6, 6, 5, 4, 1,
135 2, 5, 7, 8, 8, 7, 5, 2,
136 3, 6, 8, 9, 9, 8, 6, 3,
137 3, 6, 8, 9, 9, 8, 6, 3,
138 2, 5, 7, 8, 8, 7, 5, 2,
139 1, 4, 5, 6, 6, 5, 4, 1,
140 0, 1, 2, 3, 3, 2, 1, 0,
141 9, 9,
142};
143
144struct Level LEVEL[61][61];
145
152{
153 int level, n_empties;
154
155 for (level = 0; level <= 60; ++level)
156 for (n_empties = 0; n_empties <= 60; ++n_empties) {
157 if (level <= 0) {
158 LEVEL[level][n_empties].depth = 0;
159 LEVEL[level][n_empties].selectivity = 5;
160 } else if (level <= 10) {
161 LEVEL[level][n_empties].selectivity = 5;
162 if (n_empties <= 2 * level) {
163 LEVEL[level][n_empties].depth = n_empties;
164 } else {
165 LEVEL[level][n_empties].depth = level;
166 }
167 } else if (level <= 12) {
168 if (n_empties <= 21) {
169 LEVEL[level][n_empties].depth = n_empties;
170 LEVEL[level][n_empties].selectivity = 5;
171 } else if (n_empties <= 24) {
172 LEVEL[level][n_empties].depth = n_empties;
173 LEVEL[level][n_empties].selectivity = 3;
174 } else {
175 LEVEL[level][n_empties].depth = level;
176 LEVEL[level][n_empties].selectivity = 0;
177 }
178 } else if (level <= 18) {
179 if (n_empties <= 21) {
180 LEVEL[level][n_empties].depth = n_empties;
181 LEVEL[level][n_empties].selectivity = 5;
182 } else if (n_empties <= 24) {
183 LEVEL[level][n_empties].depth = n_empties;
184 LEVEL[level][n_empties].selectivity = 3;
185 } else if (n_empties <= 27) {
186 LEVEL[level][n_empties].depth = n_empties;
187 LEVEL[level][n_empties].selectivity = 1;
188 } else {
189 LEVEL[level][n_empties].depth = level;
190 LEVEL[level][n_empties].selectivity = 0;
191 }
192 } else if (level <= 21) {
193 if (n_empties <= 24) {
194 LEVEL[level][n_empties].depth = n_empties;
195 LEVEL[level][n_empties].selectivity = 5;
196 } else if (n_empties <= 27) {
197 LEVEL[level][n_empties].depth = n_empties;
198 LEVEL[level][n_empties].selectivity = 3;
199 } else if (n_empties <= 30) {
200 LEVEL[level][n_empties].depth = n_empties;
201 LEVEL[level][n_empties].selectivity = 1;
202 } else {
203 LEVEL[level][n_empties].depth = level;
204 LEVEL[level][n_empties].selectivity = 0;
205 }
206 } else if (level <= 24) {
207 if (n_empties <= 24) {
208 LEVEL[level][n_empties].depth = n_empties;
209 LEVEL[level][n_empties].selectivity = 5;
210 } else if (n_empties <= 27) {
211 LEVEL[level][n_empties].depth = n_empties;
212 LEVEL[level][n_empties].selectivity = 4;
213 } else if (n_empties <= 30) {
214 LEVEL[level][n_empties].depth = n_empties;
215 LEVEL[level][n_empties].selectivity = 2;
216 } else if (n_empties <= 33) {
217 LEVEL[level][n_empties].depth = n_empties;
218 LEVEL[level][n_empties].selectivity = 0;
219 } else {
220 LEVEL[level][n_empties].depth = level;
221 LEVEL[level][n_empties].selectivity = 0;
222 }
223 } else if (level <= 27) {
224 if (n_empties <= 27) {
225 LEVEL[level][n_empties].depth = n_empties;
226 LEVEL[level][n_empties].selectivity = 5;
227 } else if (n_empties <= 30) {
228 LEVEL[level][n_empties].depth = n_empties;
229 LEVEL[level][n_empties].selectivity = 3;
230 } else if (n_empties <= 33) {
231 LEVEL[level][n_empties].depth = n_empties;
232 LEVEL[level][n_empties].selectivity = 1;
233 } else {
234 LEVEL[level][n_empties].depth = level;
235 LEVEL[level][n_empties].selectivity = 0;
236 }
237 } else if (level < 30) {
238 if (n_empties <= 27) {
239 LEVEL[level][n_empties].depth = n_empties;
240 LEVEL[level][n_empties].selectivity = 5;
241 } else if (n_empties <= 30) {
242 LEVEL[level][n_empties].depth = n_empties;
243 LEVEL[level][n_empties].selectivity = 4;
244 } else if (n_empties <= 33) {
245 LEVEL[level][n_empties].depth = n_empties;
246 LEVEL[level][n_empties].selectivity = 2;
247 } else if (n_empties <= 36) {
248 LEVEL[level][n_empties].depth = n_empties;
249 LEVEL[level][n_empties].selectivity = 0;
250 } else {
251 LEVEL[level][n_empties].depth = level;
252 LEVEL[level][n_empties].selectivity = 0;
253 }
254 } else if (level <= 31) {
255 if (n_empties <= 30) {
256 LEVEL[level][n_empties].depth = n_empties;
257 LEVEL[level][n_empties].selectivity = 5;
258 } else if (n_empties <= 33) {
259 LEVEL[level][n_empties].depth = n_empties;
260 LEVEL[level][n_empties].selectivity = 3;
261 } else if (n_empties <= 36) {
262 LEVEL[level][n_empties].depth = n_empties;
263 LEVEL[level][n_empties].selectivity = 1;
264 } else {
265 LEVEL[level][n_empties].depth = level;
266 LEVEL[level][n_empties].selectivity = 0;
267 }
268 } else if (level <= 33) {
269 if (n_empties <= 30) {
270 LEVEL[level][n_empties].depth = n_empties;
271 LEVEL[level][n_empties].selectivity = 5;
272 } else if (n_empties <= 33) {
273 LEVEL[level][n_empties].depth = n_empties;
274 LEVEL[level][n_empties].selectivity = 4;
275 } else if (n_empties <= 36) {
276 LEVEL[level][n_empties].depth = n_empties;
277 LEVEL[level][n_empties].selectivity = 2;
278 } else if (n_empties <= 39) {
279 LEVEL[level][n_empties].depth = n_empties;
280 LEVEL[level][n_empties].selectivity = 0;
281 } else {
282 LEVEL[level][n_empties].depth = level;
283 LEVEL[level][n_empties].selectivity = 0;
284 }
285 } else if (level <= 35) {
286 if (n_empties <= 30) {
287 LEVEL[level][n_empties].depth = n_empties;
288 LEVEL[level][n_empties].selectivity = 5;
289 } else if (n_empties <= 33) {
290 LEVEL[level][n_empties].depth = n_empties;
291 LEVEL[level][n_empties].selectivity = 4;
292 } else if (n_empties <= 36) {
293 LEVEL[level][n_empties].depth = n_empties;
294 LEVEL[level][n_empties].selectivity = 3;
295 } else if (n_empties <= 39) {
296 LEVEL[level][n_empties].depth = n_empties;
297 LEVEL[level][n_empties].selectivity = 1;
298 } else {
299 LEVEL[level][n_empties].depth = level;
300 LEVEL[level][n_empties].selectivity = 0;
301 }
302 } else if (level < 60) {
303 if (n_empties <= level - 6) {
304 LEVEL[level][n_empties].depth = n_empties;
305 LEVEL[level][n_empties].selectivity = 5;
306 } else if (n_empties <= level - 3) {
307 LEVEL[level][n_empties].depth = n_empties;
308 LEVEL[level][n_empties].selectivity = 4;
309 } else if (n_empties <= level) {
310 LEVEL[level][n_empties].depth = n_empties;
311 LEVEL[level][n_empties].selectivity = 3;
312 } else if (n_empties <= level + 3) {
313 LEVEL[level][n_empties].depth = n_empties;
314 LEVEL[level][n_empties].selectivity = 2;
315 } else if (n_empties <= level + 6) {
316 LEVEL[level][n_empties].depth = n_empties;
317 LEVEL[level][n_empties].selectivity = 1;
318 } else if (n_empties <= level + 9) {
319 LEVEL[level][n_empties].depth = n_empties;
320 LEVEL[level][n_empties].selectivity = 0;
321 } else {
322 LEVEL[level][n_empties].depth = level;
323 LEVEL[level][n_empties].selectivity = 0;
324 }
325 } else {
326 LEVEL[level][n_empties].depth = n_empties;
327 LEVEL[level][n_empties].selectivity = 5;
328 }
329 }
330 search_log->f = NULL;
331}
332
334 if (search->options.hash_size != options.hash_table_size) {
335 const int hash_size = 1u << options.hash_table_size;
336 const int pv_size = hash_size > 16 ? hash_size >> 4 : 16;
337
339 hash_init(search->pv_table, pv_size);
342 }
343}
344
351void search_init(Search *search)
352{
353 /* id */
354 search->id = 0;
355
356 /* running state */
357 search->stop = STOP_END;
358
359 /* hash_table */
360 search->options.hash_size = 0;
361 search->hash_table->hash = NULL;
362 search->hash_table->hash_mask = 0;
363 search->pv_table->hash = NULL;
364 search->pv_table->hash_mask = 0;
365 search->shallow_table->hash = NULL;
366 search->shallow_table->hash_mask = 0;
368
369 /* board */
370 search->board->player = search->board->opponent = 0;
371 search->player = EMPTY;
372
373 /* evaluation function */
374 eval_init(search->eval);
375
376 // radom generator
377 random_seed(search->random, real_clock());
378
379 /* task stack */
380 search->tasks = (TaskStack*) malloc(sizeof (TaskStack));
381 if (search->tasks == NULL) {
382 fatal_error("Cannot allocate a task stack\n");
383 }
386 search->allow_node_splitting = (search->tasks->n > 1);
387
388 /* task associated with the current search */
389 search->task = search->tasks->task;
390 search->task->loop = false;
391 search->task->run = true;
392 search->task->node = NULL;
393 search->task->move = NULL;
394 search->task->n_calls = 0;
395 search->task->n_nodes = 0;
396 search->task->search = search;
397
398 search->parent = NULL;
399 search->n_child = 0;
400 search->master = search; /* main search */
401
402 /* lock */
403 spin_init(search);
404
405 /* result */
406 search->result = (Result*) malloc(sizeof (Result));
407 if (search->result == NULL) {
408 fatal_error("Cannot allocate a task stack\n");
409 }
410 spin_init(search->result);
411 search->result->move = NOMOVE;
412
413 search->n_nodes = 0;
414 search->child_nodes = 0;
415
416
417 /* observers */
418 search->observer = search_observer;
419
420 /* options */
421 search->options.depth = 60;
423 search->options.time = TIME_MAX;
424 search->options.time_per_move = false;
426 search->options.keep_date = false;
427 search->options.header = NULL;
428 search->options.separator = NULL;
431
433}
434
441void search_free(Search *search)
442{
443
444 hash_free(search->hash_table);
445 hash_free(search->pv_table);
446 hash_free(search->shallow_table);
447 eval_free(search->eval);
448
449 task_stack_free(search->tasks);
450 free(search->tasks);
451 spin_free(search);
452
453 spin_free(search->result);
454 free(search->result);
455
457}
458
466void search_setup(Search *search)
467{
468 int i;
469 SquareList *empty;
470 const int presorted_x[] = {
471 A1, A8, H1, H8, /* Corner */
472 C4, C5, D3, D6, E3, E6, F4, F5, /* E */
473 C3, C6, F3, F6, /* D */
474 A3, A6, C1, C8, F1, F8, H3, H6, /* A */
475 A4, A5, D1, D8, E1, E8, H4, H5, /* B */
476 B4, B5, D2, D7, E2, E7, G4, G5, /* G */
477 B3, B6, C2, C7, F2, F7, G3, G6, /* F */
478 A2, A7, B1, B8, G1, G8, H2, H7, /* C */
479 B2, B7, G2, G7, /* X */
480 D4, E4, D5, E5, /* center */
481 };
482
483 Board *board = search->board;
484 unsigned long long E;
485
486 // init empties
487 search->n_empties = 0;
488
489 empty = search->empties;
490 empty->x = NOMOVE; /* sentinel */
491 empty->previous = NULL;
492 empty->next = empty + 1;
493 empty = empty->next;
494 E = ~(board->player | board->opponent);
495 for (i = 0; i < BOARD_SIZE; ++i) { /* add empty squares */
496 if ((E & x_to_bit(presorted_x[i]))) {
497 empty->x = presorted_x[i];
498 empty->b = x_to_bit(presorted_x[i]);
499 empty->quadrant = QUADRANT_ID[empty->x];
500 empty->previous = empty - 1;
501 empty->next = empty + 1;
502 search->x_to_empties[presorted_x[i]] = empty;
503 empty = empty->next;
504 ++search->n_empties;
505 }
506 }
507 empty->x = NOMOVE; /* sentinel */
508 empty->b = 0;
509 empty->previous = empty - 1;
510 empty->next = NULL;
511
512 empty = search->empties + PASS;
513 empty->x = PASS;
514 empty->b = 0;
515 empty->previous = empty->next = empty;
516 search->x_to_empties[PASS] = empty;
517
518 empty = search->empties + NOMOVE;
519 empty->x = NOMOVE;
520 empty->b = 0;
521 empty->previous = empty->next = empty;
522 search->x_to_empties[NOMOVE] = empty;
523
524 // init parity
525 search->parity = 0;
526 foreach_empty (empty, search->empties) {
527 search->parity ^= empty->quadrant;
528 }
529
530 // init the evaluation function
531 eval_set(search->eval, board);
532}
533
540void search_clone(Search *search, Search *master)
541{
542 search->stop = STOP_END;
543 search->player = master->player;
544 *search->board = *master->board;
545 search_setup(search);
546 *search->hash_table = *master->hash_table; // share the hashtable
547 *search->pv_table = *master->pv_table; // share the pvtable
548 *search->shallow_table = *master->shallow_table; // share the pvtable
549 search->tasks = master->tasks;
550 search->observer = master->observer;
551
552 search->depth = master->depth;
553 search->selectivity = master->selectivity;
554 search->probcut_level = master->probcut_level;
555 search->depth_pv_extension = master->depth_pv_extension;
556 search->time = master->time;
557 search->height = master->height;
559 search->node_type[search->height] = master->node_type[search->height];
560 search->options = master->options;
561 search->result = master->result;
562 search->n_nodes = 0;
563 search->child_nodes = 0;
564 search->stability_bound = master->stability_bound;
565 spin_lock(master);
566 assert(master->n_child < MAX_THREADS);
567 master->child[master->n_child++] = search;
568 spin_unlock(master);
569 search->parent = master;
570 search->master = master->master;
571}
572
579{
580 hash_cleanup(search->hash_table);
581 hash_cleanup(search->pv_table);
583}
584
585
593void search_set_board(Search *search, const Board *board, const int player)
594{
595 search->player = player;
596 *search->board = *board;
597 search_setup(search);
598 search_get_movelist(search, search->movelist);
599}
600
609void search_set_level(Search *search, const int level, const int n_empties)
610{
611 search->options.depth = LEVEL[level][n_empties].depth;
612 search->options.selectivity = LEVEL[level][n_empties].selectivity;
613
614 // post-condition:
615 assert(0 <= search->options.depth && search->options.depth <= 60);
616 assert(0 <= search->options.selectivity && search->options.selectivity <= 5);
617 info("<set level (game level=%d, empties=%d) => position level=%d@%d>\n", level, n_empties, search->options.depth, selectivity_table[search->options.selectivity].percent);
618}
619
629void search_set_ponder_level(Search *search, const int level, const int n_empties)
630{
631 search->options.depth = LEVEL[level][n_empties - 1].depth + 1;
632 if (search->options.depth > n_empties) search->options.depth = n_empties;
633 search->options.selectivity = LEVEL[level][n_empties - 1].selectivity;
634
635 assert(0 <= search->options.depth && search->options.depth <= 60);
636 assert(0 <= search->options.selectivity && search->options.selectivity <= 5);
637}
638
650int solvable_depth(const long long limit, int n_tasks)
651{
652 int d;
653 long long t;
654 double speed = 0.001 * (options.speed * (SMP_W + SMP_C) / (SMP_W / n_tasks + SMP_C));
655
656 for (t = 0.0, d = 15; d <= 60 && t <= limit; ++d) {
657 t += pow(BRANCHING_FACTOR, d) / speed;
658 }
659 return d - 1;
660}
661
671void search_set_game_time(Search *search, const long long t)
672{
673 search->options.time_per_move = false;
674 search->options.time = t;
675}
676
686void search_set_move_time(Search *search, const long long t)
687{
688 search->options.time_per_move = true;
689 search->options.time = t;
690}
691
698{
699 if (search->options.time_per_move) {
700 const long long t = MAX(search->options.time - 10, 100);
701 search->time.extra = t;
702 search->time.maxi = t * 99 / 100;
703 search->time.mini = t * 9 / 10;
704 if (search->options.verbosity >= 2) {
705 info("<Time-alloted: mini = %.2f; maxi = %.2f; extra = %.2f>\n", 0.001 * search->time.mini, 0.001 * search->time.maxi, 0.001 * search->time.extra);
706 }
707 } else {
708 long long t = search->options.time;
709 const int sd = solvable_depth(t / 10, search_count_tasks(search)); // depth solvable with 10% of the time
710 const int d = MAX((search->n_empties - sd) / 2, 2); // unsolvable ply to play
711 t = MAX(t / d - 10, 100); // keep 0.25 s./remaining move, make at least 1s. available
712 search->time.extra = t;
713 search->time.maxi = t * 3 / 4;
714 search->time.mini = t / 4;
715 if (search->options.verbosity >= 2) {
716 info("<Time-init: rt = %.2f; sd = %d; d = %d; t = %.2f>\n", 0.001 * search->options.time, sd, d, 0.001 * t);
717 info("<Time-alloted: mini = %.2f; maxi = %.2f; extra = %.2f>\n", 0.001 * search->time.mini, 0.001 * search->time.maxi, 0.001 * search->time.extra);
718 }
719 }
720 search->time.extended = false;
721 search->time.can_update = true;
722}
723
732void search_time_reset(Search *search, const Board *initial_board)
733{
734 const long long spent = search_time(search);
735 const int n_empties = board_count_empties(initial_board);
736
737 if (search->options.time_per_move) {
738 const long long t = MAX(search->options.time - 10, 100);
739 search->time.extra = spent + t;
740 search->time.maxi = spent + t * 99 / 100;
741 search->time.mini = spent + t * 9 / 10;
742 if (search->options.verbosity >= 2) {
743 info("<Time-alloted: mini = %.2f; maxi = %.2f; extra = %.2f>\n", 0.001 * search->time.mini, 0.001 * search->time.maxi, 0.001 * search->time.extra);
744 }
745 } else {
746 long long t = search->options.time;
747 const int sd = solvable_depth(t / 10, search_count_tasks(search)); // depth solvable with 10% of the time
748 const int d = MAX((n_empties - sd) / 2, 2); // unsolvable ply to play
749 t = MAX(t / d - 10, 100); // keep 0.25 s./remaining move, make at least 0.1 s available
750 search->time.extra = spent + t;
751 search->time.maxi = spent + t * 3 / 4;
752 search->time.mini = spent + t / 4;
753 if (search->options.verbosity >= 2) {
754 info("<Time-reset: spent = %.2f rt = %.2f; sd = %d; d = %d; t = %.2f>\n", 0.001 * spent, 0.001 * search->options.time, sd, d, 0.001 * t);
755 info("<Time-alloted: mini = %.2f; maxi = %.2f; extra = %.2f>\n", 0.001 * search->time.mini, 0.001 * search->time.maxi, 0.001 * search->time.extra);
756 }
757 }
758 search->time.extended = false;
759 search->time.can_update = true;
760}
761
762
763
764
771void search_adjust_time(Search *search, const bool once)
772{
773 if (!search->options.time_per_move) {
774 const long long t = MAX(search->time.extra, MAX(search->options.time - search_time(search) - 10, 100) / 2);
775 search->time.mini = MIN(search->time.maxi, t);
776 search->time.maxi = MIN(search->time.mini * 4 / 3, t);
777 search->time.extra = MIN(search->time.maxi * 4 / 3, t);
778 search->time.extended = once;
779 if (search->options.verbosity >= 2) {
780 info("\n<Time-adjusted: mini = %.2f; maxi = %.2f; extra = %.2f>\n", 0.001 * search->time.mini, 0.001 * search->time.maxi, 0.001 * search->time.extra);
781 }
782 }
783}
784
791{
792 return search->stop == RUNNING && search_time(search) <= search->time.mini;
793}
794
801{
802 long long t;
803 Search *master = search->master;
804
805 assert(master->master == master);
806
807 if (master->stop != STOP_TIMEOUT) {
808
809 t = search_time(master);
810
811 if (t > master->time.extra) {
812
813 if (master->stop != RUNNING) {
814 printf("*** MASTER ALREADY STOPPED FOR ANOTHER REASON (%d) ***\n", master->stop);
815 }
816
817 if (!master->time.extended && master->time.can_update) {
818 Result *result = master->result;
819 spin_lock(result);
820 if ((!master->time.extended && master->time.can_update)
821 && (result->bound[result->move].lower < result->score || result->depth == 0)) {
822 search_adjust_time(master, true);
823 }
824 spin_unlock(result);
825 }
826 if (t > search->time.extra) {
828 }
829 }
830 }
831
832 if (search->stop != STOP_TIMEOUT) {
833 t = search_time(master);
834 if (t > master->time.extra) {
835 printf("*** SEARCH STILL RUNNING ? (%d) ***\n", search->stop);
836 search->stop = STOP_TIMEOUT;
837 }
838 }
839}
840
847void search_set_task_number(Search *search, const int n)
848{
849 assert(n > 0 && n < MAX_THREADS);
850 task_stack_resize(search->tasks, n);
851 search->allow_node_splitting = (n > 1);
852}
853
860void search_swap_parity(Search *search, const int x)
861{
862 search->parity ^= QUADRANT_ID[x];
863}
864
875void search_get_movelist(const Search *search, MoveList *movelist)
876{
877 Move *previous = movelist->move;
878 Move *move = movelist->move + 1;
879 const Board *board = search->board;
880 unsigned long long moves = get_moves(board->player, board->opponent);
881 register int x;
882
883 foreach_bit(x, moves) {
884 board_get_move(board, x, move);
885 move->cost = 0;
886 previous = previous->next = move;
887 ++move;
888 }
889 previous->next = NULL;
890 movelist->n_moves = move - movelist->move - 1;
891 assert(movelist->n_moves == get_mobility(board->player, board->opponent));
892}
893
900void search_update_endgame(Search *search, const Move *move)
901{
902 search_swap_parity(search, move->x);
903 empty_remove(search->x_to_empties[move->x]);
904 board_update(search->board, move);
905 --search->n_empties;
906
907}
908
915void search_restore_endgame(Search *search, const Move *move)
916{
917 search_swap_parity(search, move->x);
918 empty_restore(search->x_to_empties[move->x]);
919 board_restore(search->board, move);
920 ++search->n_empties;
921}
922
929{
930 board_pass(search->board);
931}
932
933
934//static Line debug_line;
935
942void search_update_midgame(Search *search, const Move *move)
943{
944 static const NodeType next_node_type[] = {CUT_NODE, ALL_NODE, CUT_NODE};
945
946// line_push(&debug_line, move->x);
947
948 search_swap_parity(search, move->x);
949 empty_remove(search->x_to_empties[move->x]);
950 board_update(search->board, move);
951 eval_update(search->eval, move);
952 assert(search->n_empties > 0);
953 --search->n_empties;
954 ++search->height;
955 search->node_type[search->height] = next_node_type[search->node_type[search->height- 1]];
956}
957
964void search_restore_midgame(Search *search, const Move *move)
965{
966// line_print(&debug_line, 100, " ", stdout); putchar('\n');
967// line_pop(&debug_line);
968
969 search_swap_parity(search, move->x);
970 empty_restore(search->x_to_empties[move->x]);
971 board_restore(search->board, move);
972 eval_restore(search->eval, move);
973 ++search->n_empties;
974 assert(search->height > 0);
975 --search->height;
976}
977
984{
985 static const NodeType next_node_type[] = {CUT_NODE, ALL_NODE, CUT_NODE};
986
987 board_pass(search->board);
988 eval_pass(search->eval);
989 ++search->height;
990 search->node_type[search->height] = next_node_type[search->node_type[search->height- 1]];
991}
992
999{
1000 board_pass(search->board);
1001 eval_pass(search->eval);
1002 assert(search->height > 0);
1003 --search->height;
1004}
1005
1012int get_pv_extension(const int depth, const int n_empties)
1013{
1014 int depth_pv_extension;
1015
1016 if (depth >= n_empties || depth <= 9) depth_pv_extension = -1;
1017 else if (depth <= 12) depth_pv_extension = 10; // depth + 8
1018 else if (depth <= 18) depth_pv_extension = 12; // depth + 10
1019 else if (depth <= 24) depth_pv_extension = 14; // depth + 12
1020 else depth_pv_extension = 16; // depth + 14
1021
1022 return depth_pv_extension;
1023}
1024
1032bool is_depth_solving(const int depth, const int n_empties)
1033{
1034 return (depth >= n_empties)
1035 || (depth > 9 && depth <= 12 && depth + 8 >= n_empties)
1036 || (depth > 12 && depth <= 18 && depth + 10 >= n_empties)
1037 || (depth > 18 && depth <= 24 && depth + 12 >= n_empties)
1038 || (depth > 24 && depth + 14 >= n_empties);
1039}
1040
1041
1042
1049long long search_clock(Search *search)
1050{
1051 if (options.nps > 0) return search_count_nodes(search) / options.nps;
1052 else return time_clock();
1053}
1054
1061long long search_time(Search *search)
1062{
1063 if (search->stop != STOP_END) return search_clock(search) + search->time.spent;
1064 else return search->time.spent;
1065}
1066
1073unsigned long long search_count_nodes(Search *search)
1074{
1075 return search->n_nodes + search->child_nodes;
1076}
1077
1084{
1085 result_print(result, stdout);
1086 putchar('\n');
1087}
1088
1095void search_set_observer(Search *search, void (*observer)(Result*))
1096{
1097 search->observer = observer;
1098}
1099
1106void result_print(Result *result, FILE *f)
1107{
1108 char bound;
1109#ifdef _WIN32
1110 const int PRINTED_WIDTH = 53;
1111#else
1112 const int PRINTED_WIDTH = 52;
1113#endif
1114
1115 spin_lock(result);
1116
1117 if (result->bound[result->move].lower < result->score && result->score == result->bound[result->move].upper) bound = '<';
1118 else if (result->bound[result->move].lower == result->score && result->score < result->bound[result->move].upper) bound = '>';
1119 else if (result->bound[result->move].lower == result->score && result->score == result->bound[result->move].upper) bound = ' ';
1120 else bound = '?';
1121
1122 if (result->selectivity < 5) fprintf(f, "%2d@%2d%% ", result->depth, selectivity_table[result->selectivity].percent);
1123 else fprintf(f, " %2d ", result->depth);
1124 fprintf(f, "%c%+03d ", bound, result->score);
1125 time_print(result->time, true, f);
1126 if (result->n_nodes) {
1127 fprintf(f, " %13lld ", result->n_nodes);
1128 if (result->time > 0) fprintf(f, "%10.0f ", 1000.0 * result->n_nodes / result->time);
1129 else fprintf(f, " ");
1130 } else fputs(" ", f);
1131 line_print(result->pv, options.width - PRINTED_WIDTH, " ", f);
1132 fflush(f);
1133
1134 spin_unlock(result);
1135}
1136
1146bool search_SC_PVS(Search *search, volatile int *alpha, volatile int *beta, int *score)
1147{
1148 const Board *board = search->board;
1149
1150 if (USE_SC && *beta >= PVS_STABILITY_THRESHOLD[search->n_empties]) {
1152 *score = SCORE_MAX - 2 * get_stability(board->opponent, board->player);
1153 if (*score <= *alpha) {
1155 return true;
1156 }
1157 else if (*score < *beta) *beta = *score;
1158 }
1159 return false;
1160}
1161
1170bool search_SC_NWS(Search *search, const int alpha, int *score)
1171{
1172 const Board *board = search->board;
1173
1174 if (USE_SC && alpha >= NWS_STABILITY_THRESHOLD[search->n_empties]) {
1176 *score = SCORE_MAX - 2 * get_stability(board->opponent, board->player);
1177 if (*score <= alpha) {
1179 return true;
1180 }
1181 }
1182 return false;
1183}
1184
1196bool search_TC_PVS(HashData *data, const int depth, const int selectivity, volatile int *alpha, volatile int *beta, int *score)
1197{
1198 if (USE_TC && (data->selectivity >= selectivity && data->depth >= depth)) {
1200 if (*alpha < data->lower) {
1201 *alpha = data->lower;
1202 if (*alpha >= *beta) {
1204 *score = *alpha;
1205 return true;
1206 }
1207 }
1208 if (*beta > data->upper) {
1209 *beta = data->upper;
1210 if (*beta <= *alpha) {
1212 *score = *beta;
1213 return true;
1214 }
1215 }
1216 }
1217 return false;
1218}
1219
1230bool search_TC_NWS(HashData *data, const int depth, const int selectivity, const int alpha, int *score)
1231{
1232 if (USE_TC && (data->selectivity >= selectivity && data->depth >= depth)) {
1234 if (alpha < data->lower) {
1236 *score = data->lower;
1237 return true;
1238 }
1239 if (alpha >= data->upper) {
1241 *score = data->upper;
1242 return true;
1243 }
1244 }
1245 return false;
1246}
1247
1264bool search_ETC_NWS(Search *search, MoveList *movelist, unsigned long long hash_code, const int depth, const int selectivity, const int alpha, int *score)
1265{
1266 if (USE_ETC && depth > ETC_MIN_DEPTH) {
1267
1268 Move *move;
1269 Board next[1];
1270 HashData etc[1];
1271 unsigned long long etc_hash_code;
1272 HashTable *hash_table = search->hash_table;
1273 const int etc_depth = depth - 1;
1274 const int beta = alpha + 1;
1275
1277 foreach_move (move, movelist) {
1278 next->opponent = search->board->player ^ (move->flipped | x_to_bit(move->x));
1279 next->player = search->board->opponent ^ move->flipped;
1281
1282 if (USE_SC && alpha <= -NWS_STABILITY_THRESHOLD[search->n_empties]) {
1283 *score = 2 * get_stability(next->opponent, next->player) - SCORE_MAX;
1284 if (*score > alpha) {
1285 hash_store(hash_table, search->board, hash_code, depth, selectivity, 0, alpha, beta, *score, move->x);
1287 return true;
1288 }
1289 }
1290
1291 etc_hash_code = board_get_hash_code(next);
1292 if (USE_TC && hash_get(hash_table, next, etc_hash_code, etc) && etc->selectivity >= selectivity && etc->depth >= etc_depth) {
1293 *score = -etc->upper;
1294 if (*score > alpha) {
1295 hash_store(hash_table, search->board, hash_code, depth, selectivity, 0, alpha, beta, *score, move->x);
1297 return true;
1298 }
1299 }
1300 }
1301 }
1302
1303 return false;
1304}
1305
1312void search_share(const Search *src, Search *dest)
1313{
1314 hash_copy(src->pv_table, dest->pv_table);
1315 hash_copy(src->hash_table, dest->hash_table);
1316}
1317
1324int search_count_tasks(const Search *search)
1325{
1326 return search->tasks->n;
1327}
1328
1335void search_stop_all(Search *search, const Stop stop)
1336{
1337 int i;
1338
1339 spin_lock(search);
1340 search->stop = stop;
1341 for (i = 0; i < search->n_child; ++i) {
1342 search_stop_all(search->child[i], stop);
1343 }
1344 spin_unlock(search);
1345}
1346
1353void search_set_state(Search *search, const Stop stop)
1354{
1355 spin_lock(search);
1356 search->stop = stop;
1357 spin_unlock(search);
1358}
1359
1369int search_guess(Search *search, const Board *board)
1370{
1371 HashData hash_data[1];
1372 int move = NOMOVE;
1373
1374 if (hash_get(search->pv_table, board, board_get_hash_code(board), hash_data)) move = hash_data->move[0];
1375 if (move == NOMOVE && hash_get(search->hash_table, board, board_get_hash_code(board), hash_data)) move = hash_data->move[0];
1376
1377 return move;
1378}
1379
#define x_to_bit(x)
Definition bit.h:43
#define foreach_bit(i, b)
Definition bit.h:39
unsigned long long board_get_hash_code(const Board *board)
Compute a hash code.
Definition board.c:1134
void board_restore(Board *board, const Move *move)
Restore a board.
Definition board.c:487
void board_update(Board *board, const Move *move)
Update a board.
Definition board.c:469
int board_count_empties(const Board *board)
Check if the game is over.
Definition board.c:1216
unsigned long long board_get_move(const Board *board, const int x, Move *move)
Compute a move.
Definition board.c:438
int get_stability(const unsigned long long P, const unsigned long long O)
Estimate the stability.
Definition board.c:1067
int get_mobility(const unsigned long long P, const unsigned long long O)
Count legal moves.
Definition board.c:833
DLL_API unsigned long long get_moves(const unsigned long long P, const unsigned long long O)
Get legal moves.
Definition board.c:621
void board_pass(Board *board)
Passing move.
Definition board.c:503
#define SCORE_MAX
Definition const.h:58
#define TIME_MAX
Definition const.h:61
#define BOARD_SIZE
Definition const.h:21
@ B3
Definition const.h:31
@ D7
Definition const.h:35
@ PASS
Definition const.h:37
@ B6
Definition const.h:34
@ F3
Definition const.h:31
@ D4
Definition const.h:32
@ NOMOVE
Definition const.h:37
@ E8
Definition const.h:36
@ E4
Definition const.h:32
@ E6
Definition const.h:34
@ C4
Definition const.h:32
@ A6
Definition const.h:34
@ F5
Definition const.h:33
@ C5
Definition const.h:33
@ D1
Definition const.h:29
@ H4
Definition const.h:32
@ G5
Definition const.h:33
@ B8
Definition const.h:36
@ E7
Definition const.h:35
@ E3
Definition const.h:31
@ A2
Definition const.h:30
@ A3
Definition const.h:31
@ C7
Definition const.h:35
@ H5
Definition const.h:33
@ B7
Definition const.h:35
@ F1
Definition const.h:29
@ C2
Definition const.h:30
@ C8
Definition const.h:36
@ G6
Definition const.h:34
@ E5
Definition const.h:33
@ B4
Definition const.h:32
@ F7
Definition const.h:35
@ A1
Definition const.h:29
@ A7
Definition const.h:35
@ H1
Definition const.h:29
@ D2
Definition const.h:30
@ F4
Definition const.h:32
@ G3
Definition const.h:31
@ B2
Definition const.h:30
@ D5
Definition const.h:33
@ G8
Definition const.h:36
@ F6
Definition const.h:34
@ F2
Definition const.h:30
@ H6
Definition const.h:34
@ A5
Definition const.h:33
@ G1
Definition const.h:29
@ E1
Definition const.h:29
@ H7
Definition const.h:35
@ H3
Definition const.h:31
@ D6
Definition const.h:34
@ H2
Definition const.h:30
@ F8
Definition const.h:36
@ E2
Definition const.h:30
@ B1
Definition const.h:29
@ A4
Definition const.h:32
@ C3
Definition const.h:31
@ H8
Definition const.h:36
@ D3
Definition const.h:31
@ C6
Definition const.h:34
@ G7
Definition const.h:35
@ C1
Definition const.h:29
@ D8
Definition const.h:36
@ G2
Definition const.h:30
@ G4
Definition const.h:32
@ B5
Definition const.h:33
@ A8
Definition const.h:36
@ EMPTY
Definition const.h:44
#define MAX_THREADS
Definition const.h:15
Stop
Definition const.h:70
@ RUNNING
Definition const.h:71
@ STOP_TIMEOUT
Definition const.h:74
@ STOP_END
Definition const.h:76
NodeType
Definition const.h:80
@ CUT_NODE
Definition const.h:82
@ ALL_NODE
Definition const.h:83
#define foreach_empty(empty, list)
Definition empty.h:46
static void empty_remove(SquareList *empty)
remove an empty square from the list.
Definition empty.h:28
static void empty_restore(SquareList *empty)
restore the list of empty squares
Definition empty.h:39
void eval_free(Eval *eval)
Free resources used by the evaluation function.
Definition eval.c:519
void eval_restore(Eval *eval, const Move *move)
Definition eval.c:810
void eval_pass(Eval *eval)
Update/Restore the features after a passing move.
Definition eval.c:824
void eval_update(Eval *eval, const Move *move)
Definition eval.c:681
void eval_init(Eval *eval)
Initialize a new evaluation function.
Definition eval.c:509
void eval_set(Eval *eval, const Board *board)
Set up evaluation features from a board.
Definition eval.c:530
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_init(HashTable *hash_table, const int size)
Initialise the hashtable.
Definition hash-lock-free.c:123
void hash_cleanup(HashTable *hash_table)
Clear the hashtable.
Definition hash-lock-free.c:159
void hash_free(HashTable *hash_table)
Free the hashtable.
Definition hash-lock-free.c:195
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
void hash_copy(const HashTable *src, HashTable *dest)
Copy an hastable to another one.
Definition hash-lock-free.c:652
void line_print(const Line *line, int width, const char *separator, FILE *f)
Print a move sequence.
Definition move.c:610
#define foreach_move(iter, movelist)
Definition move.h:78
Options options
Definition options.c:22
void search_swap_parity(Search *search, const int x)
Change parity.
Definition search.c:860
void search_time_init(Search *search)
Initialize the alloted time.
Definition search.c:697
void search_set_level(Search *search, const int level, const int n_empties)
Set the search level.
Definition search.c:609
void search_init(Search *search)
Init the main search.
Definition search.c:351
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_time_reset(Search *search, const Board *initial_board)
Reset the alloted time.
Definition search.c:732
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
struct Level LEVEL[61][61]
Definition search.c:144
bool search_continue(Search *search)
Check if it can iterate more...
Definition search.c:790
void search_free(Search *search)
Free the search allocated ressource.
Definition search.c:441
const int PVS_STABILITY_THRESHOLD[]
Definition search.c:120
void search_pass_endgame(Search *search)
Update the search state after a passing move.
Definition search.c:928
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
long long search_clock(Search *search)
Return the time spent by the search.
Definition search.c:1049
const int QUADRANT_ID[]
Definition search.c:81
void search_restore_pass_midgame(Search *search)
Update the search state after a passing move.
Definition search.c:998
void search_restore_endgame(Search *search, const Move *move)
Restore the search state as before a move.
Definition search.c:915
unsigned long long search_count_nodes(Search *search)
Return the number of nodes searched.
Definition search.c:1073
void result_print(Result *result, FILE *f)
Print the current search result.
Definition search.c:1106
void search_set_task_number(Search *search, const int n)
Change the number of task.
Definition search.c:847
Log search_log[1]
Definition search.c:74
int get_pv_extension(const int depth, const int n_empties)
Compute the pv_extension.
Definition search.c:1012
void search_clone(Search *search, Search *master)
Clone a search for parallel search.
Definition search.c:540
void search_cleanup(Search *search)
Clean-up some search data.
Definition search.c:578
void search_adjust_time(Search *search, const bool once)
Give more time.
Definition search.c:771
bool is_depth_solving(const int depth, const int n_empties)
Check if final score use pv_extension or is solved.
Definition search.c:1032
void search_restore_midgame(Search *search, const Move *move)
Restore the search state as before a move.
Definition search.c:964
void search_set_observer(Search *search, void(*observer)(Result *))
set observer.
Definition search.c:1095
void search_update_endgame(Search *search, const Move *move)
Update the search state after a move.
Definition search.c:900
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
void search_set_board(Search *search, const Board *board, const int player)
Set the board to analyze.
Definition search.c:593
void search_global_init(void)
Definition search.c:151
int search_guess(Search *search, const Board *board)
Guess the bestmove of a given board.
Definition search.c:1369
int solvable_depth(const long long limit, int n_tasks)
Compute the deepest level that can be solved given a limited time...
Definition search.c:650
int search_count_tasks(const Search *search)
Count the number of tasks used in parallel search.
Definition search.c:1324
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_set_state(Search *search, const Stop stop)
Set the search running/waiting state.
Definition search.c:1353
void search_resize_hashtable(Search *search)
Definition search.c:333
void search_stop_all(Search *search, const Stop stop)
Stop the search.
Definition search.c:1335
void search_set_move_time(Search *search, const long long t)
set time to search.
Definition search.c:686
void search_setup(Search *search)
Set up various structure once the board has been set.
Definition search.c:466
const int NWS_STABILITY_THRESHOLD[]
Definition search.c:108
bool search_TC_PVS(HashData *data, const int depth, const int selectivity, volatile int *alpha, volatile int *beta, int *score)
Transposition Cutoff (TC).
Definition search.c:1196
void search_share(const Search *src, Search *dest)
Share search information.
Definition search.c:1312
void search_set_ponder_level(Search *search, const int level, const int n_empties)
Set the search level while pondering.
Definition search.c:629
void search_update_pass_midgame(Search *search)
Update the search state after a passing move.
Definition search.c:983
void search_observer(Result *result)
default observer.
Definition search.c:1083
bool search_SC_NWS(Search *search, const int alpha, int *score)
Stability Cutoff (TC).
Definition search.c:1170
long long search_time(Search *search)
Return the time spent by the search.
Definition search.c:1061
void search_set_game_time(Search *search, const long long t)
set time to search.
Definition search.c:671
NodeType next_node_type(const NodeType parent, const bool first_move)
#define USE_ETC
Definition settings.h:33
#define BRANCHING_FACTOR
Definition settings.h:110
#define SMP_C
Definition settings.h:116
#define SMP_W
Definition settings.h:113
#define MULTIPV_DEPTH
Definition settings.h:122
#define ETC_MIN_DEPTH
Definition settings.h:95
#define USE_SC
Definition settings.h:30
#define USE_TC
Definition settings.h:27
Statistics statistics
Definition stats.c:21
Statistics header.
#define SEARCH_UPDATE_ALL_NODES()
Definition stats.h:54
#define CUTOFF_STATS(x)
Definition stats.h:31
Definition board.h:26
unsigned long long player
Definition board.h:27
unsigned long long opponent
Definition board.h:27
int lower
Definition search.h:36
int upper
Definition search.h:37
Definition hash.h:24
unsigned char move[2]
Definition hash.h:31
signed char lower
Definition hash.h:29
signed char upper
Definition hash.h:30
unsigned char selectivity
Definition hash.h:26
unsigned char depth
Definition hash.h:25
Definition hash.h:47
Hash * hash
Definition hash.h:49
unsigned long long hash_mask
Definition hash.h:51
Definition search.h:88
int depth
Definition search.h:89
int selectivity
Definition search.h:90
LogFile.
Definition util.h:423
FILE * f
Definition util.h:424
Definition move.h:29
int n_moves
Definition move.h:31
Move move[MAX_MOVE+2]
Definition move.h:30
Definition move.h:20
unsigned int cost
Definition move.h:24
struct Move * next
Definition move.h:25
unsigned long long flipped
Definition move.h:21
int x
Definition move.h:22
bool cpu_affinity
Definition options.h:30
double speed
Definition options.h:49
int n_task
Definition options.h:29
bool pv_guess
Definition options.h:73
int width
Definition options.h:34
char * search_log_file
Definition options.h:77
double nps
Definition options.h:50
int hash_table_size
Definition options.h:25
int verbosity
Definition options.h:32
Definition search.h:41
int move
Definition search.h:44
unsigned long long n_nodes
Definition search.h:49
int score
Definition search.h:45
long long time
Definition search.h:48
int selectivity
Definition search.h:43
Line pv[1]
Definition search.h:47
int depth
Definition search.h:42
Bound bound[BOARD_SIZE+2]
Definition search.h:46
Definition search.h:95
struct Search::@24 time
long long maxi
Definition search.h:130
unsigned int parity
Definition search.h:120
const char * separator
Definition search.h:145
struct Search * parent
Definition search.h:112
volatile long long spent
Definition search.h:126
struct TaskStack * tasks
Definition search.h:109
int n_empties
Definition search.h:99
bool keep_date
Definition search.h:143
void(* observer)(Result *)
Definition search.h:153
long long extra
Definition search.h:125
bool guess_pv
Definition search.h:146
volatile unsigned long long child_nodes
Definition search.h:156
MoveList movelist[1]
Definition search.h:132
bool allow_node_splitting
Definition search.h:123
struct Search * child[MAX_THREADS]
Definition search.h:113
int hash_size
Definition search.h:148
bool can_update
Definition search.h:128
Result * result
Definition search.h:151
const char * header
Definition search.h:144
int depth_pv_extension
Definition search.h:121
int height
Definition search.h:133
bool time_per_move
Definition search.h:141
int id
Definition search.h:101
int player
Definition search.h:100
struct Search::@25 options
Random random[1]
Definition search.h:107
int verbosity
Definition search.h:142
volatile int n_child
Definition search.h:115
SquareList empties[BOARD_SIZE+2]
Definition search.h:97
int depth
Definition search.h:117
int probcut_level
Definition search.h:119
Bound stability_bound
Definition search.h:135
long long mini
Definition search.h:129
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
SquareList * x_to_empties[BOARD_SIZE+2]
Definition search.h:98
Eval eval[1]
Definition search.h:106
NodeType node_type[GAME_SIZE]
Definition search.h:134
struct Task * task
Definition search.h:110
Board board[1]
Definition search.h:96
int multipv_depth
Definition search.h:147
bool extended
Definition search.h:127
struct Search * master
Definition search.h:114
Definition search.h:25
int percent
Definition search.h:28
Definition empty.h:15
struct SquareList * previous
Definition empty.h:19
int quadrant
Definition empty.h:18
unsigned long long b
Definition empty.h:16
struct SquareList * next
Definition empty.h:20
int x
Definition empty.h:17
unsigned long long n_esc_high_cutoff
Definition stats.h:108
unsigned long long n_stability_try
Definition stats.h:104
unsigned long long n_hash_try
Definition stats.h:103
unsigned long long n_etc_try
Definition stats.h:108
unsigned long long n_hash_low_cutoff
Definition stats.h:103
unsigned long long n_hash_high_cutoff
Definition stats.h:103
unsigned long long n_stability_low_cutoff
Definition stats.h:104
unsigned long long n_etc_high_cutoff
Definition stats.h:108
Definition ybwc.h:93
int n
Definition ybwc.h:97
Task * task
Definition ybwc.h:95
struct Node * node
Definition ybwc.h:34
struct Move * move
Definition ybwc.h:35
unsigned long long n_calls
Definition ybwc.h:37
unsigned long long n_nodes
Definition ybwc.h:38
struct Search * search
Definition ybwc.h:33
volatile bool loop
Definition ybwc.h:30
volatile bool run
Definition ybwc.h:31
void time_print(long long t, bool justified, FILE *f)
Print time as "D:HH:MM:SS.CC".
Definition util.c:131
long long(* time_clock)(void)
Time clock.
Definition util.c:122
void thread_set_cpu(Thread thread, int i)
Choose a single core or cpu to run on, under linux systems, to avoid context changes.
Definition util.c:967
void random_seed(Random *random, const unsigned long long seed)
Pseudo-random number seed.
Definition util.c:1062
Thread thread_self(void)
Current thread.
Definition util.c:954
Miscellaneous utilities header.
#define log_close(l)
Close an opened log file.
Definition util.h:435
long long real_clock(void)
#define MIN(a, b)
Definition util.h:101
#define fatal_error(...)
Display an error message as "FATAL_ERROR : file name : function name : line number : ....
Definition util.h:349
#define info(...)
Display a message.
Definition util.h:382
#define log_open(l, file)
open a log file if allowed.
Definition util.h:429
#define MAX(a, b)
Definition util.h:98
static int hash_size(int n)
Definition xboard.c:271
void task_stack_free(TaskStack *stack)
Free resources used by the stack of tasks.
Definition ybwc.c:607
void task_stack_resize(TaskStack *stack, const int n)
Resize the stack of tasks.
Definition ybwc.c:626
void task_stack_init(TaskStack *stack, const int n)
Initialize the stack of tasks.
Definition ybwc.c:560
Parallel search header.