My Project
edax.c
Go to the documentation of this file.
1
98#include "cassio.h"
99#include "event.h"
100#include "histogram.h"
101#include "options.h"
102#include "opening.h"
103#include "obftest.h"
104#include "perft.h"
105#include "play.h"
106#include "search.h"
107#include "util.h"
108#include "ui.h"
109#ifdef __linux__
110 #include <sys/time.h>
111 #include <sys/resource.h>
112#endif
113
114static Log edax_log[1];
115extern bool book_verbose;
116
117void version(void);
118void bench(void);
119
124static void edax_observer(Result *result)
125{
126 search_observer(result);
127 if (log_is_open(edax_log)) {
128 result_print(result, edax_log->f);
129 putc('\n', edax_log->f);
130 }
131}
132
138{
139 Play *play = ui->play;
140
141 book_verbose = true;
142 play_init(play, ui->book);
143 ui->book->search = play->search;
145 play->search->id = 1;
147 ui->mode = options.mode;
148 play->type = ui->type;
149
151}
152
158{
160 book_free(ui->book);
161 play_free(ui->play);
163 book_verbose = false;
164}
165
169void help_options(void)
170{
171 printf("Options:\n");
172 printf("Options must be entered in the form '[set] <option> [=] <value>', with [set] and\n[=] being optional.\n");
173 printf(" verbose [n] set Edax verbosity (default 1).\n");
174 printf(" noise [n] start displaying Edax search result from this depth\n (default 5).\n");
175 printf(" witdh [n] display edax search results using <width> characters\n (default 80).\n");
176 printf(" hash-table-size [n] set hashtable size (default 18 bits).\n");
177 printf(" n-tasks [n] control the number of parallel threads used in searching\n (default 1).\n");
178 printf(" l|level [n] search using limited depth (default 21).\n");
179 printf(" t|game-time <time> search using limited time per game.\n");
180 printf(" move-time <time> search using limited time per move.\n");
181 printf(" ponder [on/off] set pondering on/off.\n");
182 printf(" book-file [file] use [file] as default book file (default data/book.dat).\n");
183 printf(" book-usage [on/off] use or do not use the opening book.\n");
184 printf(" book-randomness [n] play various but worse moves from the opening book.\n");
185 printf(" auto-start [on/off] automatically start a new game.\n");
186 printf(" auto-swap [on/off] automatically swap players between each game.\n");
187 printf(" auto-store [on/off] automatically store each game into the opening book.\n");
188}
189
193void help_commands(void)
194{
195 printf("\nCommands:\n");
196 printf("Commands must be entered in the form '<command> <parameters>'.\n");
197 printf(" i|nit start a new game from standard initial position.\n");
198 printf(" n|ew start a new game from a personalized position.\n");
199 printf(" setboard <board> set a personalized position to start from.\n");
200 printf(" o|open|load [file] load a played game.\n");
201 printf(" s|save [file] save a played game.\n");
202 printf(" q|quit|exit quit from edax.\n");
203 printf(" u|undo undo the last played move.\n");
204 printf(" r|redo redo the last played move.\n");
205 printf(" play <moves> play a sequence of moves.\n");
206 printf(" force <moves> force to play an opening.\n");
207 printf(" go ask edax to play.\n");
208 printf(" stop stop edax search.\n");
209 printf(" hint [n] ask edax to search the first bestmoves.\n");
210 printf(" m|mode [n] ask edax to automatically play (default = 3).\n");
211 printf(" a|analyze [n] retro-analyze the game.\n");
212 printf(" ?|help show this message.\n");
213 printf(" v|version display the version number.\n");
214}
215
219void help_book(void)
220{
221 printf("\nBook Commands:\n");
222 printf("Book Commands must be entered in the form 'b|book <command> <parameters>'.\n");
223 printf(" new <n1> <n2> create a new empty book with level <n1> and depth <n2>.\n");
224 printf(" load [file] load an opening book from a binary opening file.\n");
225 printf(" merge [file] merge an opening book with the current opening book.\n");
226 printf(" save [file] save an opening book to a binary opening file.\n");
227 printf(" import [file] load an opening book from a portable text file.\n");
228 printf(" export [file] save an opening book to a portable text file.\n");
229 printf(" on use the opening book.\n");
230 printf(" off do not use the opening book.\n");
231 printf(" show display details about the current position.\n");
232 printf(" info display book general information.\n");
233 printf(" a|analyze [n] retro-analyze the game using the opening book.\n");
234 printf(" randomness [n] play more various but worse move from the opening book.\n");
235 printf(" depth [n] change book depth (up to which to add positions).\n");
236 printf(" deepen [n] change book level & reevalute the whole book (very slow!).\n");
237 printf(" fix fix the opening book: add missing links and negamax the\n whole book tree.\n");
238 printf(" store add the last played game to the opening book.\n");
239 printf(" deviate <n1> <n2> add positions by deviating with a relative error <n1> and\n an absolute error <n2>.\n");
240 printf(" enhance <n1> <n2> add positions by improving score accuracy with a midgame\n error <n1> and an endcut error <n2>.\n");
241 printf(" fill [n] add positions between existing positions.\n");
242 printf(" prune remove unreachable positions.\n");
243 printf(" subtree only keep positions from the current position.\n");
244 printf(" add [file] add positions from a game base file (txt, ggf, sgf or\n wthor format).\n");
245}
246
250void help_base(void)
251{
252 printf("\nGame DataBase :\n");
253 printf(" convert [file_in] [file_out] convert between different format.\n");
254 printf(" unique [file_in] [file_out] remove doublons in the base.\n");
255 printf(" check [file_in] [n] check error in the last <n> moves.\n");
256 printf(" correct [file_in] [n] correct error in the last <n> moves.\n");
257 printf(" complete [file_in] complete a database by playing the last\n missing moves.\n");
258 printf(" problem [file_in] [n] [file_out] build a set of <n> problems from a game\n database.\n");
259}
260
264void help_test(void)
265{
266 printf("\nTests:\n");
267 printf(" bench test edax speed.\n");
268 printf(" microbench test CPU cycle speed of some major functions.\n");
269 printf(" obftest [file] Test from an obf file.\n");
270 printf(" script-to-obf [file]Convert a script to an obf file.\n");
271 printf(" wtest [file] check the theoric scores of a wthor base file.\n");
272 printf(" count games [d] compute the number of moves from the current position up\n to depth [d].\n");
273 printf(" perft [d] same as above, but without hash table.\n");
274 printf(" estimate [d] [n] estimate the number of moves from the current position up\n to depth [d].\n");
275 printf(" count positions [d] compute the number of positions from the current position\n up to depth [d].\n");
276 printf(" count shapes [d] compute the number of shapes from the current position up\n to depth [d].\n");
277}
278
279
285{
286 char *cmd = NULL, *param = NULL;
287 Play *play = ui->play;
288 char book_file[FILENAME_MAX];
289 unsigned long long histogram[129][65];
290 int repeat = options.repeat;
291
292 histogram_init(histogram);
293
294 // loop forever
295 for (;;) {
296 errno = 0;
297
298 if (options.verbosity) {
299 putchar('\n');
300 play_print(play, stdout);
301 if (play_is_game_over(play)) printf("\n*** Game Over ***\n");
302 putchar('\n');
303 }
304
305 if (log_is_open(edax_log)) {
306 putc('\n', edax_log->f);
307 play_print(play, edax_log->f);
308 if (play_is_game_over(play)) fputs("\n*** Game Over ***\n", edax_log->f);
309 putc('\n', edax_log->f);
310 }
311
312 // edax turn ? (automatic play mode)
313 if (!ui_event_exist(ui) && !play_is_game_over(play) && (ui->mode == !play->player || ui->mode == 2)) {
314 putchar('\n');
315 play_go(play, true);
316 printf("\nEdax plays "); move_print(play_get_last_move(play)->x, 0, stdout); putchar('\n');
317 if (ui->mode != 2) play_ponder(play);
318
319 // proceed by reading a command
320 } else {
321
322 /* automatic rules after a game over*/
323 if (play_is_game_over(play)) {
324 if (options.auto_store) play_store(play);
325 if (options.auto_swap && ui->mode < 2) ui->mode = !ui->mode;
326 if (options.repeat && repeat > 1) {
327 --repeat;
328 play_new(play);
329 continue;
330 }
331 if (options.auto_quit) {
332 return;
333 }
334 if (options.auto_start) {
335 play_new(play);
336 continue;
337 }
338 }
339
340 putchar('>'); fflush(stdout);
341 ui_event_wait(ui, &cmd, &param);
342 log_print(edax_log, "cmd=\"%s\" ; param=\"%s\"\n", cmd, param);
343 putchar('\n');
344
345 if (cmd == NULL) {
346 warn("unexpected null command?\n");
347 continue;
348 }
349
350 // skip empty lines or commented lines
351 if (*cmd == '\0' || *cmd == '#') {
352
353 // help
354 } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "?") == 0) {
355 if (*param == '\0' || strcmp(param, "options") == 0) help_options();
356 if (*param == '\0' || strcmp(param, "commands") == 0) help_commands();
357 if (*param == '\0' || strcmp(param, "book") == 0) help_book();
358 if (*param == '\0' || strcmp(param, "base") == 0) help_base();
359 if (*param == '\0' || strcmp(param, "test") == 0) help_test();
360
361 // new game from standard position
362 } else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "init") == 0) {
364 play->initial_player = BLACK;
365 play_force_init(play, "F5");
366 play_new(play);
367
368 // new game from personnalized position
369 } else if ((strcmp(cmd, "n") == 0 || strcmp(cmd, "new") == 0) && *param == '\0') {
370 play_new(play);
371
372 // open a saved game
373 } else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "open") == 0 || strcmp(cmd, "load") == 0) {
374 play_load(play, param);
375
376 // save a game
377 } else if (strcmp(cmd, "s") == 0 || strcmp(cmd, "save") == 0) {
378 play_save(play, param);
379
380 // quit
381 } else if (strcmp(cmd, "quit") == 0 || strcmp(cmd, "q") == 0 || strcmp(cmd, "exit") == 0) {
382 free(cmd); free(param);
383 return;
384
385 } else if (!options.auto_quit && (strcmp(cmd, "eof") == 0 && (ui->mode != 2 || play_is_game_over(play)))){
386 free(cmd); free(param);
387 return;
388
389 // undo last move
390 } else if (strcmp(cmd, "u") == 0 || strcmp(cmd, "undo") == 0) {
391 play_undo(play);
392 if (ui->mode == 0 || ui->mode == 1) play_undo(play);
393
394 // redo last move
395 } else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "redo") == 0) {
396 play_redo(play);
397 if (ui->mode == 0 || ui->mode == 1) play_redo(play);
398
399 // mode
400 } else if (strcmp(cmd, "m") == 0 || strcmp(cmd, "mode") == 0) {
401 ui->mode = string_to_int(param, 3);
402
403 // analyze a game
404 } else if (strcmp(cmd, "a") == 0 || strcmp(cmd, "analyze") == 0 || strcmp(cmd, "analyse") == 0) {
405 play_analyze(play, string_to_int(param, play->n_game));
406
407 // set a new initial position
408 } else if (strcmp(cmd, "setboard") == 0) {
409 play_set_board(play, param);
410
411 // vertical mirror
412 } else if (strcmp(cmd, "vmirror") == 0) {
413 play_symetry(play, 2);
414
415 // horizontal mirror
416 } else if (strcmp(cmd, "hmirror") == 0) {
417 play_symetry(play, 1);
418
419 // rotate
420 } else if (strcmp(cmd, "rotate") == 0) {
421 int angle = string_to_int(param, 90) % 360;
422 if (angle < 0) angle += 360;
423 switch (angle) {
424 case 90:
425 play_symetry(play, 5);
426 break;
427 case 180:
428 play_symetry(play, 3);
429 break;
430 case 270:
431 play_symetry(play, 6);
432 break;
433 default:
434 warn("Rotate angle should be 90°, 180° or 270°");
435 break;
436 }
437
438 // direct symetry...
439 } else if (strcmp(cmd, "symetry") == 0) {
440 int sym = string_to_int(param, 1);
441 if (sym < 0 || sym >= 16) warn("symetry parameter should be a number between 0 and 15\n");
442 else {
443 if (sym & 8) play->player ^= 1;
444 play_symetry(play, sym & 7);
445 }
446
447 // play a serie of moves
448 } else if (strcmp(cmd, "play") == 0) {
449 string_to_lowercase(param);
450 play_game(play, param);
451
452 // force edax to play an opening
453 } else if (strcmp(cmd, "force") == 0) {
454 string_to_lowercase(param);
455 play_force_init(play, param);
456
457 // solve a set of problems
458 } else if (strcmp(cmd, "solve") == 0) {
459 char problem_file[FILENAME_MAX + 1], *hard_file;
460 hard_file = parse_word(param, problem_file, FILENAME_MAX);
461 parse_word(hard_file, hard_file, FILENAME_MAX);
462 obf_test(play->search, problem_file, hard_file);
464
465 // convert a set of problems in a .script file to a .obf file
466 } else if (strcmp(cmd, "script-to-obf") == 0) {
467 char script_file[FILENAME_MAX + 1], *obf_file;
468 obf_file = parse_word(param, script_file, FILENAME_MAX);
469 parse_word(obf_file, obf_file, FILENAME_MAX);
470 script_to_obf(play->search, script_file, obf_file);
472
473 } else if (strcmp(cmd, "select-hard") == 0) {
474 char full_file[FILENAME_MAX + 1], *hard_file;
475 hard_file = parse_word(param, full_file, FILENAME_MAX);
476 parse_word(hard_file, hard_file, FILENAME_MAX);
477 obf_filter(full_file, hard_file);
478
479 // game/position enumeration
480 } else if (strcmp(cmd, "count") == 0) {
481 char count_cmd[16], *count_param;
482 int depth = 10, size = 8;
483
484 count_param = parse_word(param, count_cmd, 15);
485 count_param = parse_int(count_param, &depth); BOUND(depth, 1, 90, "max-ply");
486 if (count_param) parse_int(count_param, &size); BOUND(size, 6, 8, "board-size");
487
488 if (strcmp(count_cmd, "games") == 0) { // game enumeration
489 quick_count_games(play->board, depth, size);
490 } else if (strcmp(count_cmd, "positions") == 0) { // position enumeration
491 count_positions(play->board, depth, size);
492 } else if (strcmp(count_cmd, "shapes") == 0) { // shape enumeration
493 count_shapes(play->board, depth, size);
494 } else {
495 warn("Unknown count command: \"%s %s\"\n", cmd, param);
496 }
497
498 } else if (strcmp(cmd, "perft") == 0) {
499 int depth = 14;
500 depth = string_to_int(param, 10); BOUND(depth, 1, 90, "max-ply");
501 count_games(play->board, depth);
502
503 // game/position enumeration
504 } else if (strcmp(cmd, "estimate") == 0) {
505 int n = 1000;
506 n = string_to_int(param, 10); BOUND(n, 1, 2000000000, "max-trials");
507
508 estimate_games(play->board, n);
509
510 // seek highest mobility
511 } else if (strcmp(cmd, "mobility") == 0) {
512 int t = 3600; // 1 hour
513 t = string_to_int(param, 10); BOUND(t, 1, 3600*24*365*10, "max time");
514
516
517 // seek a position
518 } else if (strcmp(cmd, "seek") == 0) {
519 Board target;
520 Line solution;
521
522 board_set(&target, param);
523 line_init(&solution, play->player);
524
525 if (seek_position(&target, play->board, &solution)) {
526 printf("Solution found:\n");
527 line_print(&solution, 200, " ", stdout);
528 putchar('\n');
529 }
530
531 // microbench (a serie of low level tests).
532 } else if (strcmp(cmd, "microbench") == 0) {
533 bench();
534
535 // bench (a serie of low level tests).
536 } else if (strcmp(cmd, "bench") == 0) {
537 int n = string_to_int(param, -1); BOUND(n, -1, 100, "n_problems");
538 obf_speed(play->search, n);
539
540 // wtest test the engine against wthor theoretical scores
541 } else if (strcmp(cmd, "wtest") == 0) {
542 wthor_test(param, play->search);
543
544 // make wthor games played by "Edax (Delorme)" as "Etudes" tournament.
545 } else if (strcmp(cmd, "edaxify") == 0) {
546 wthor_edaxify(param);
547
548 // wtest test the engine against wthor theoretical scores
549 } else if (strcmp(cmd, "weval") == 0) {
550 wthor_eval(param, play->search, histogram);
551 histogram_print(histogram);
552 histogram_stats(histogram);
553 histogram_to_ppm("weval.ppm", histogram);
554
555 // go think!
556 } else if (strcmp(cmd, "go") == 0) {
557 if (play_is_game_over(play)) printf("\n*** Game Over ***\n");
558 else {
559 play_go(play, true);
560 printf("\nEdax plays "); move_print(play_get_last_move(play)->x, 0, stdout); putchar('\n');
561 }
562
563 // hint for [n] moves
564 } else if (strcmp(cmd, "hint") == 0) {
565 int n = string_to_int(param, 1); BOUND(n, 1, 60, "n_moves");
566 play_hint(play, n);
567
568 // stop thinking
569 } else if (strcmp(cmd, "stop") == 0) {
570 ui->mode = 3;
571
572 // stop thinking
573 } else if (strcmp(cmd, "version") == 0 || strcmp(cmd, "v") == 0) {
574 version();
575
576 // user move
577 } else if (play_user_move(play, cmd)) {
578 printf("\nYou play "); move_print(play_get_last_move(play)->x, 0, stdout); putchar('\n');
579
580 // debug pv
581 } else if (strcmp(cmd, "debug-pv") == 0) {
582 Move move[1];
583 if (parse_move(param, play->board, move) != param) {
584 search_set_board(play->search, play->board, play->player);
585 pv_debug(play->search, move, stdout);
586 }
587 } else if (strcmp(cmd, "options") == 0) {
588 options_dump(stdout);
589#ifdef __unix__
590 } else if (strcmp(cmd, "resources") == 0) {
591 struct rusage u;
592 long long t;
593 getrusage(RUSAGE_SELF, &u);
594 t = 1000 * u.ru_utime.tv_sec + u.ru_utime.tv_usec / 1000;
595 printf("user cpu time: "); time_print(t, false, stdout); printf("\n");
596 t = 1000 * u.ru_stime.tv_sec + u.ru_stime.tv_usec / 1000;
597 printf("system cpu time: "); time_print(t, false, stdout); printf("\n");
598 printf("max resident memory: %ld\n", u.ru_maxrss);
599 printf("page fault without I/O: %ld\n", u.ru_minflt);
600 printf("page fault with I/O: %ld\n", u.ru_majflt);
601 printf("number of input: %ld\n", u.ru_inblock);
602 printf("number of output: %ld\n", u.ru_oublock);
603 printf("number of voluntary context switch: %ld\n", u.ru_nvcsw);
604 printf("number of unvoluntary context switch: %ld\n\n", u.ru_nivcsw);
605#endif
606 // opening name
607 } else if (strcmp(cmd, "opening") == 0) {
608 const char *name;
610 if (name == NULL) name = "?";
611 puts(name);
612
613 // opening name in french
614 } else if (strcmp(cmd, "ouverture") == 0) {
615 const char *name;
617 if (name == NULL) name = "?";
618 puts(name);
619
620 // opening book commands
621 } else if (strcmp(cmd, "book") == 0 || strcmp(cmd, "b") == 0) {
622 char book_cmd[FILENAME_MAX + 1], *book_param;
623 int val_1, val_2;
624 Book *book = play->book;
625
626 book->search = play->search;
628 book_param = parse_word(param, book_cmd, FILENAME_MAX);
629
630 // store the last played game
631 if (strcmp(book_cmd, "store") == 0) {
632 play_store(play);
633
634 // turn book usage on
635 } else if (strcmp(book_cmd, "on") == 0) { // learn
636 options.book_allowed = true;
637
638 // turn book usage off
639 } else if (strcmp(book_cmd, "off") == 0) { // learn
640 options.book_allowed = false;
641
642 // set book randomness
643 } else if (strcmp(book_cmd, "randomness") == 0) { // learn
644 val_1 = 0; book_param = parse_int(book_param, &val_1);
645 options.book_randomness = val_1;
646
647 // set book depth (until which to learn)
648 } else if (strcmp(book_cmd, "depth") == 0) { // learn
649 val_1 = 36; book_param = parse_int(book_param, &val_1);
650 book->options.n_empties = 61 - val_1;
651
652 // create a new empty book
653 } else if (strcmp(book_cmd, "new") == 0) {
654 val_1 = 21; book_param = parse_int(book_param, &val_1);
655 val_2 = 36; book_param = parse_int(book_param, &val_2);
656 book_free(book) ;
657 book_new(book, val_1, 61 - val_2);
658
659 // load an opening book (binary format) from the disc
660 } else if (strcmp(book_cmd, "load") == 0 || strcmp(book_cmd, "open") == 0) {
661 book_free(book) ;
662 parse_word(book_param, book_file, FILENAME_MAX);
663 book_load(book, book_file);
664
665 // save an opening book (binary format) to the disc
666 } else if (strcmp(book_cmd, "save") == 0) {
667 parse_word(book_param, book_file, FILENAME_MAX);
668 book_save(book, book_file);
669
670 // import an opening book (text format)
671 } else if (strcmp(book_cmd, "import") == 0) {
672 book_free(book);
673 parse_word(book_param, book_file, FILENAME_MAX);
674 book_import(book, book_file);
675 book_link(book);
676 book_fix(book);
677 book_negamax(book);
678 book_sort(book);
679
680 // export an opening book (text format)
681 } else if (strcmp(book_cmd, "export") == 0) {
682 parse_word(book_param, book_file, FILENAME_MAX);
683 book_export(book, book_file);
684
685 // merge an opening book to the current one
686 } else if (strcmp(book_cmd, "merge") == 0) {
687 Book src[1];
688 parse_word(book_param, book_file, FILENAME_MAX);
689 src->search = play->search;
690 book_load(src, book_file);
691 book_merge(book, src);
692 book_free(src);
693 warn("Book needs to be fixed before usage\n");
694
695 // fix an opening book
696 } else if (strcmp(book_cmd, "fix") == 0) {
697 book_fix(book); // do nothing (or edax is buggy)
698 book_link(book); // links nodes
699 book_negamax(book); // negamax nodes
700 book_sort(book); // sort moves
701
702 // negamax an opening book
703 } else if (strcmp(book_cmd, "negamax") == 0) {
704 book_negamax(book); // negamax nodes
705 book_sort(book); // sort moves
706
707 // check and correct solved positions of the book
708 } else if (strcmp(book_cmd, "correct") == 0) {
709 book_correct_solved(book); // do nothing (or edax is buggy)
710 book_fix(book); // do nothing (or edax is buggy)
711 book_link(book); // links nodes
712 book_negamax(book); // negamax nodes
713 book_sort(book); // sort moves
714
715 // prune an opening book
716 } else if (strcmp(book_cmd, "prune") == 0) {
717 book_prune(book); // remove unreachable lines.
718 book_fix(book); // do nothing (or edax is buggy)
719 book_link(book); // links nodes
720 book_negamax(book); // negamax nodes
721 book_sort(book); // sort moves
722
723 // subtree an opening book
724 } else if (strcmp(book_cmd, "subtree") == 0) {
725 book_subtree(book, play->board); // remove unreachable lines.
726 book_fix(book); // do nothing (or edax is buggy)
727 book_link(book); // links nodes
728 book_negamax(book); // negamax nodes
729 book_sort(book); // sort moves
730
731 // show the current position as stored in the book
732 } else if (strcmp(book_cmd, "show") == 0) {
733 book_show(book, play->board);
734
735 // show book general information
736 } else if (strcmp(book_cmd, "info") == 0) {
737 book_info(book);
738
739 // show book general information
740 } else if (strcmp(book_cmd, "stats") == 0) {
741 book_stats(book);
742
743
744 // set book verbosity
745 } else if (strcmp(book_cmd, "verbose") == 0) {
746 parse_int(book_param, &book->options.verbosity);
748
749 // analyze a game from the opening book point of view
750 } else if (strcmp(book_cmd, "a") == 0 || strcmp(book_cmd, "analyze") == 0 || strcmp(book_cmd, "analyse") == 0) {
751 val_1 = string_to_int(book_param, play->n_game); BOUND(val_1, 1, play->n_game, "depth");
752 play_book_analyze(play, val_1);
753
754 // add positions from a game database
755 } else if (strcmp(book_cmd, "add") == 0) {
756 Base base[1];
757 parse_word(book_param, book_file, FILENAME_MAX);
758 base_init(base);
759 base_load(base, book_file);
760 book_add_base(book, base);
761 base_free(base);
762
763 // check positions from a game database
764 } else if (strcmp(book_cmd, "check") == 0) {
765 Base base[1];
766 parse_word(book_param, book_file, FILENAME_MAX);
767 base_init(base);
768 base_load(base, book_file);
769 book_check_base(book, base);
770 base_free(base);
771
772 // extract positions
773 } else if (strcmp(book_cmd, "problem") == 0) {
774 val_1 = 24; book_param = parse_int(book_param, &val_1); BOUND(val_1, 0, 60, "number of empties");
775 val_2 = 10; book_param = parse_int(book_param, &val_2); BOUND(val_2, 1, 1000000, "number of positions");
776 book_extract_positions(book, val_1, val_2);
777
778 // extract pv to a game database
779 } else if (strcmp(book_cmd, "extract") == 0) {
780 Base base[1];
781 parse_word(book_param, book_file, FILENAME_MAX);
782 base_init(base);
783 book_extract_skeleton(book, base);
784 base_save(base, book_file);
785 base_free(base);
786
787 // add position using the "deviate algorithm"
788 } else if (strcmp(book_cmd, "deviate") == 0) {
789 val_1 = 2; book_param = parse_int(book_param, &val_1); BOUND(val_1, -129, 129, "relative error");
790 val_2 = 4; book_param = parse_int(book_param, &val_2); BOUND(val_2, 0, 65, "absolute error");
791 book_deviate(book, play->board, val_1, val_2);
792
793 // add position using the "enhance algorithm"
794 } else if (strcmp(book_cmd, "enhance") == 0) {
795 val_1 = 2; book_param = parse_int(book_param, &val_1); BOUND(val_1, 0, 129, "midgame error");
796 val_2 = 4; book_param = parse_int(book_param, &val_2); BOUND(val_2, 0, 129, "endcut error");
797 book_enhance(book, play->board, val_1, val_2);
798
799 // add position by filling hole in the book
800 } else if (strcmp(book_cmd, "fill") == 0) {
801 val_1 = 1; book_param = parse_int(book_param, &val_1); BOUND(val_1, 1, 61, "fill depth");
802 book_fill(book, val_1);
803
804 // add positions by expanding positions with no-link
805 } else if (strcmp(book_cmd, "play") == 0) {
806 book_play(book);
807
808 // add positions by expanding positions with no-link
809 } else if (strcmp(book_cmd, "deepen") == 0) {
810 book_deepen(book);
811
812 // add book positions to the hash table
813 } else if (strcmp(book_cmd, "feed-hash") == 0) {
814 book_feed_hash(book, play->board, play->search);
815
816 // wrong command ?
817 } else {
818 warn("Unknown book command: \"%s %s\"\n", cmd, param);
819 }
822
823 /* base TODO: add more actions... */
824 } else if (strcmp(cmd, "base") == 0) {
825 char base_file[FILENAME_MAX + 1];
826 char base_cmd[512], *base_param;
827 Base base[1];
828
829 base_init(base);
830 base_param = parse_word(param, base_cmd, 511);
831 base_param = parse_word(base_param, base_file, FILENAME_MAX);
832
833 // extract problem from a game base
834 if (strcmp(base_cmd, "problem") == 0) {
835 char problem_file[FILENAME_MAX + 1];
836 int n_empties = 24;
837 base_param = parse_int(base_param, &n_empties);
838 base_param = parse_word(base_param, problem_file, FILENAME_MAX);
839
840 base_load(base, base_file);
841 base_to_problem(base, n_empties, problem_file);
842
843 // extract FEN
844 } else if (strcmp(base_cmd, "tofen") == 0) {
845 char problem_file[FILENAME_MAX + 1];
846 int n_empties = 24;
847 base_param = parse_int(base_param, &n_empties);
848 base_param = parse_word(base_param, problem_file, FILENAME_MAX);
849
850 base_load(base, base_file);
851 base_to_FEN(base, n_empties, problem_file);
852
853 // correct erroneous games
854 } else if (strcmp(base_cmd, "correct") == 0) {
855 int n_empties = 24;
856 base_param = parse_int(base_param, &n_empties);
857
858 base_load(base, base_file);
859 base_analyze(base, play->search, n_empties, true);
860 remove(base_file);
861 base_save(base, base_file);
862
863 // check erroneous games
864 } else if (strcmp(base_cmd, "check") == 0) {
865 int n_empties = 24;
866 base_param = parse_int(base_param, &n_empties);
867
868 base_load(base, base_file);
869 base_analyze(base, play->search, n_empties, false);
870
871 // terminate unfinished base
872 } else if (strcmp(base_cmd, "complete") == 0) {
873 base_load(base, base_file);
874 base_complete(base, play->search);
875 remove(base_file);
876 base_save(base, base_file);
877
878 // convert a base to another format
879 } else if (strcmp(base_cmd, "convert") == 0) {
880 base_load(base, base_file);
881 base_param = parse_word(base_param, base_file, FILENAME_MAX);
882 base_save(base, base_file);
883
884 // make a base unique by removing identical games
885 } else if (strcmp(base_cmd, "unique") == 0) {
886 base_load(base, base_file);
887 base_param = parse_word(base_param, base_file, FILENAME_MAX);
888 base_unique(base);
889 base_save(base, base_file);
890
891 // compare two game bases
892 } else if (strcmp(base_cmd, "compare") == 0) {
893 char base_file_2[FILENAME_MAX + 1];
894 base_param = parse_word(base_param, base_file_2, FILENAME_MAX);
895 base_compare(base_file, base_file_2);
896
897 } else {
898 warn("Unknown base command: \"%s %s\"\n", cmd, param);
899 }
900
901 base_free(base);
902
903 /* edax options */
904 } else if (options_read(cmd, param)) {
906 // parallel search changes:
907 if (search_count_tasks(play->search) != options.n_task) {
910 }
911
912 /* switch to another protocol */
913 } else if (strcmp(cmd, "nboard") == 0 && strcmp(param, "1") == 0) {
914 free(cmd); free(param);
916 ui->free(ui);
917 ui_switch(ui, "nboard");
918 ui->init(ui);
919 ui->loop(ui);
920 return;
921
922 } else if (strcmp(cmd, "xboard") == 0) {
923 free(cmd); free(param);
925 ui->free(ui);
926 ui_switch(ui, "xboard");
927 ui->init(ui);
928 ui->loop(ui);
929 return;
930
931 } else if (strcmp(cmd, "engine-protocol") == 0 && strcmp(param, "init") == 0) {
932 free(cmd); free(param);
934 ui->free(ui);
935 ui_switch(ui, "cassio");
936 engine_loop();
937 return;
938
939 } else if (strcmp(cmd, "protocol_version") == 0) {
940 free(cmd); free(param);
942 ui->free(ui);
943 ui_switch(ui, "gtp");
944 ui->init(ui);
945 puts("= 2\n"); fflush(stdout);
946 ui->loop(ui);
947 return;
948
949#ifdef TUNE_EDAX
950 /* edax tuning */
951 } else if (strcmp(cmd, "tune") == 0) {
952 char problem[FILENAME_MAX];
953 char *w_name;
955 w_name = parse_word(param, problem, FILENAME_MAX);
956 tune_move_evaluate(play->search, problem, parse_skip_spaces(w_name));
958#endif
959 /* illegal cmd/move */
960 } else {
961 warn("Unknown command/Illegal move: \"%s %s\"\n", cmd, param);
962 }
963 }
964 }
965}
966
void base_to_problem(Base *base, const int n_empties, const char *problem)
Convert a game database to a set of problems.
Definition base.c:841
void base_analyze(Base *base, Search *search, const int n_empties, const bool apply_correction)
Base analysis.
Definition base.c:893
bool base_load(Base *base, const char *file)
Load a game database.
Definition base.c:740
void base_save(const Base *base, const char *file)
Save a game database.
Definition base.c:788
void base_complete(Base *base, Search *search)
Base analysis.
Definition base.c:919
void wthor_edaxify(const char *file)
Change players to "Edax (delorme)" and tourney to "Etudes" in a wthor base.
Definition base.c:651
void base_to_FEN(Base *base, const int n_empties, const char *problem)
Convert a game database to a set of problems.
Definition base.c:867
void base_unique(Base *base)
Make games unique in the game database.
Definition base.c:720
void wthor_eval(const char *file, Search *search, unsigned long long histogram[129][65])
Test Eval with a wthor base.
Definition base.c:611
void base_init(Base *base)
Initialize a game database.
Definition base.c:672
void wthor_test(const char *file, Search *search)
Test Search with a wthor base.
Definition base.c:516
void base_free(Base *base)
Free resources of a game database.
Definition base.c:684
void base_compare(const char *file_1, const char *file_2)
Base Compare.
Definition base.c:943
void board_init(Board *board)
Set a board to the starting position.
Definition board.c:280
int board_set(Board *board, const char *string)
Set a board from a string description.
Definition board.c:154
void book_extract_positions(Book *book, const int n_empties, const int n_positions)
print a set of position.
Definition book.c:2737
void book_check_base(Book *book, const Base *base)
Check positions from a game database.
Definition book.c:2644
void book_deepen(Book *book)
Deepen a book.
Definition book.c:1746
void book_show(Book *book, Board *board)
Display a position from the book.
Definition book.c:2155
void book_import(Book *book, const char *file)
Import an opening book.
Definition book.c:1547
void book_play(Book *book)
Play.
Definition book.c:1882
void book_subtree(Book *book, const Board *board)
Prune a book.
Definition book.c:2043
void book_enhance(Book *book, Board *board, const int midgame_error, const int endcut_error)
Enhance a book.
Definition book.c:2075
void book_info(Book *book)
display some book's informations.
Definition book.c:2111
void book_correct_solved(Book *book)
Correct wrong solved score in the book.
Definition book.c:1782
void book_negamax(Book *book)
Negamax a book.
Definition book.c:1684
void book_export(Book *book, const char *file)
Export an opening book.
Definition book.c:1589
void book_free(Book *book)
Free resources used by the opening book.
Definition book.c:1422
void book_save(Book *book, const char *file)
Save an opening book.
Definition book.c:1622
void book_fill(Book *book, const int depth)
Fill a book.
Definition book.c:1922
void book_fix(Book *book)
Fix a book.
Definition book.c:1723
void book_sort(Book *book)
Sort a book.
Definition book.c:1862
void book_merge(Book *dest, const Book *src)
Merge two opening books.
Definition book.c:1665
void book_link(Book *book)
Link a book.
Definition book.c:1701
void book_feed_hash(const Book *book, Board *board, Search *search)
feed hash table from the opening book.
Definition book.c:2824
void book_prune(Book *book)
Prune a book.
Definition book.c:2010
void book_stats(Book *book)
print book statistics.
Definition book.c:2773
void book_extract_skeleton(Book *book, Base *base)
Extract book draws to a game base.
Definition book.c:2709
void book_deviate(Book *book, Board *board, const int relative_error, const int absolute_error)
Deviate a book.
Definition book.c:1963
void book_new(Book *book, int level, int n_empties)
Create a new opening book.
Definition book.c:1450
void book_load(Book *book, const char *file)
Load the opening book.
Definition book.c:1471
void book_add_base(Book *book, const Base *base)
Add positions from a game database.
Definition book.c:2556
void engine_loop(void)
Loop event.
Definition cassio.c:683
@ BLACK
Definition const.h:42
void help_book(void)
print book's help.
Definition edax.c:219
bool book_verbose
Definition book.c:36
void bench(void)
perform various performance tests.
Definition bench.c:381
void ui_loop_edax(UI *ui)
Loop event.
Definition edax.c:284
static Log edax_log[1]
Definition edax.c:114
void help_commands(void)
print help commands.
Definition edax.c:193
void ui_init_edax(UI *ui)
initialize edax protocol.
Definition edax.c:137
void ui_free_edax(UI *ui)
free resources used by edax protocol.
Definition edax.c:157
void help_test(void)
print base's help.
Definition edax.c:264
void help_options(void)
print help about options.
Definition edax.c:169
static void edax_observer(Result *result)
default search oberver.
Definition edax.c:124
void help_base(void)
print base's help.
Definition edax.c:250
void version(void)
Print version & copyright.
Definition main.c:27
void histogram_to_ppm(const char *file, unsigned long long histogram[129][65])
Definition histogram.c:156
void histogram_init(unsigned long long h[129][65])
Definition histogram.c:21
void histogram_stats(unsigned long long h[129][65])
Definition histogram.c:103
void histogram_print(unsigned long long h[129][65])
Definition histogram.c:30
void line_print(const Line *line, int width, const char *separator, FILE *f)
Print a move sequence.
Definition move.c:610
void move_print(const int x, const int player, FILE *f)
Print out a move.
Definition move.c:110
void line_init(Line *line, const int player)
Initialize a sequence of moves.
Definition move.c:549
void tune_move_evaluate(struct Search *, const char *, const char *)
void obf_speed(Search *search, const int n)
Definition obftest.c:534
void obf_filter(const char *input_file, const char *output_file)
Select hard position from an OBF file.
Definition obftest.c:437
void script_to_obf(Search *search, const char *script_file, const char *obf_file)
Build an OBF file from a Script file.
Definition obftest.c:378
void obf_test(Search *search, const char *obf_file, const char *wrong_file)
Test an OBF file.
Definition obftest.c:294
Problem solver.
const char * opening_get_french_name(const Board *board)
Check if a board has got a french opening name.
Definition opening.c:1340
const char * opening_get_english_name(const Board *board)
Check if a board has got an engilsh opening name.
Definition opening.c:1321
Options options
Definition options.c:22
int options_read(const char *option, const char *value)
Read an option.
Definition options.c:136
void options_dump(FILE *f)
Print all global options.
Definition options.c:330
void options_bound(void)
Keep options between realistic values.
Definition options.c:288
void quick_count_games(const Board *board, const int depth, const int size)
Count games.
Definition perft.c:521
void estimate_games(const Board *board, const long long n)
Move estimate games.
Definition perft.c:177
bool seek_position(const Board *target, const Board *board, Line *line)
seek a game that reach to a position
Definition perft.c:1115
void seek_highest_mobility(const Board *board, const unsigned long long t)
Move estimate games.
Definition perft.c:290
void count_shapes(const Board *board, const int depth, const int size)
Count shapes.
Definition perft.c:1077
void count_positions(const Board *board, const int depth, const int size)
Count positions.
Definition perft.c:822
void count_games(const Board *board, const int depth)
Move generator performance test.
Definition perft.c:107
Move generator test header file.
void play_store(Play *play)
store the game into the opening book
Definition play.c:1175
void play_set_board(Play *play, const char *board)
Set a new board.
Definition play.c:810
void play_print(Play *play, FILE *f)
Print the game state.
Definition play.c:1225
void play_analyze(Play *play, int n)
Analyze a played game.
Definition play.c:1033
void play_hint(Play *play, int n)
Start thinking.
Definition play.c:365
void play_ponder(Play *play)
Ponder.
Definition play.c:729
void play_stop_pondering(Play *play)
Stop pondering.
Definition play.c:749
void play_book_analyze(Play *play, int n)
Analyze a played game.
Definition play.c:1140
void play_new(Play *play)
Start a new game.
Definition play.c:62
void play_save(Play *play, const char *file)
Save a played game.
Definition play.c:131
void play_init(Play *play, Book *book)
Initialization.
Definition play.c:27
const char * play_show_opening_name(Play *play, const char *(*opening_get_name)(const Board *))
Print the opening name.
Definition play.c:1438
bool play_user_move(Play *play, const char *string)
Play a user move.
Definition play.c:909
Move * play_get_last_move(Play *play)
Get the last played move.
Definition play.c:927
void play_force_init(Play *play, const char *string)
Initialize a forced line.
Definition play.c:1313
void play_game(Play *play, const char *string)
Play a move sequence.
Definition play.c:866
void play_symetry(Play *play, const int sym)
Get the symetry of the actual position.
Definition play.c:1418
bool play_load(Play *play, const char *file)
Load a saved game.
Definition play.c:84
void play_undo(Play *play)
Undo a move.
Definition play.c:779
bool play_is_game_over(Play *play)
Check if game is over.
Definition play.c:190
void play_redo(Play *play)
Redo a move.
Definition play.c:795
void play_go(Play *play, const bool update)
Start thinking.
Definition play.c:214
void play_free(Play *play)
Free resources.
Definition play.c:52
Edax play control - header file.
void pv_debug(Search *search, const Move *bestmove, FILE *f)
Debug PV.
Definition root.c:33
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
void search_set_observer(Search *search, void(*observer)(Result *))
set observer.
Definition search.c:1095
void search_set_board(Search *search, const Board *board, const int player)
Set the board to analyze.
Definition search.c:593
int search_count_tasks(const Search *search)
Count the number of tasks used in parallel search.
Definition search.c:1324
void search_observer(Result *result)
default observer.
Definition search.c:1083
Definition base.h:48
Definition board.h:26
The opening book.
Definition book.h:25
int n_empties
Definition book.h:33
bool need_saving
Definition book.h:47
int verbosity
Definition book.h:36
struct Book::@1 options
Search * search
Definition book.h:49
Definition move.h:35
LogFile.
Definition util.h:423
FILE * f
Definition util.h:424
Definition move.h:20
bool book_allowed
Definition options.h:60
int n_task
Definition options.h:29
char * ui_log_file
Definition options.h:78
bool auto_start
Definition options.h:83
int repeat
Definition options.h:87
int book_randomness
Definition options.h:61
bool auto_quit
Definition options.h:86
int mode
Definition options.h:47
bool auto_swap
Definition options.h:85
char * book_file
Definition options.h:59
bool auto_store
Definition options.h:84
int verbosity
Definition options.h:32
Definition play.h:25
int player
Definition play.h:32
Board board[1]
Definition play.h:26
int initial_player
Definition play.h:33
Board initial_board[1]
Definition play.h:27
int n_game
Definition play.h:36
Search search[1]
Definition play.h:28
int type
Definition play.h:31
Book * book
Definition play.h:30
Definition search.h:41
int id
Definition search.h:101
struct Search::@25 options
int verbosity
Definition search.h:142
Definition ui.h:31
int type
Definition ui.h:36
Play play[2]
Definition ui.h:32
Book book[1]
Definition ui.h:33
void(* init)(struct UI *)
Definition ui.h:40
void(* loop)(struct UI *)
Definition ui.h:41
int mode
Definition ui.h:37
void(* free)(struct UI *)
Definition ui.h:42
bool ui_switch(UI *ui, const char *ui_type)
Switch between different User Interface.
Definition ui.c:25
bool ui_event_exist(UI *ui)
ui_event_exist
Definition ui.c:189
void ui_event_wait(UI *ui, char **cmd, char **param)
Wait input.
Definition ui.c:147
User interface header.
void time_print(long long t, bool justified, FILE *f)
Print time as "D:HH:MM:SS.CC".
Definition util.c:131
char * parse_move(const char *string, const Board *board, Move *move)
Parse a move.
Definition util.c:627
char * parse_int(const char *string, int *result)
Parse an integer.
Definition util.c:761
void string_to_lowercase(char *s)
Change all char of a string to lowercase.
Definition util.c:355
int string_to_int(const char *s, const int default_value)
Convert a string into an integer.
Definition util.c:457
char * parse_skip_spaces(const char *string)
Skip spaces.
Definition util.c:514
char * parse_word(const char *string, char *word, unsigned int n)
Parse a word.
Definition util.c:562
Miscellaneous utilities header.
#define log_close(l)
Close an opened log file.
Definition util.h:435
#define log_print(l,...)
Print into the log file.
Definition util.h:442
#define warn(...)
Display a warning message as "WARNING : ... ".
Definition util.h:373
#define log_open(l, file)
open a log file if allowed.
Definition util.h:429
#define log_is_open(l)
Check if the log stream can be used.
Definition util.h:448
#define BOUND(var, min, max, name)
Definition util.h:104