Various tunings.
[rattatechess.git] / commands.cpp
blob3f53aff91fcae27682498f1bcd42181e9312fee7
1 /***************************************************************************
2 commandparse.cpp - description
3 -------------------
4 begin : sab nov 2 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 #include "engine.h"
19 #include "commands.h"
20 #include "utils.h"
21 #include "search_gui.h"
22 #include <stdarg.h>
23 #include <signal.h>
24 #include <string.h>
26 void Engine::Cmd::run(int argc, char *argv[])
28 (Engine::eng()->*m_func)(argc, argv);
31 Engine::Variable::Variable(int (Engine::*ivar), int def_val, const char *d)
32 : m_type(Integer)
33 , m_desc(d)
34 , m_buf(NULL)
35 , m_int_var(ivar)
36 , m_range_min(INT_MIN)
37 , m_range_max(INT_MAX)
39 Engine::eng()->*m_int_var = def_val;
42 Engine::Variable::Variable(int (Engine::*ivar), int def_val, int min, int max, const char *d)
43 : m_type(Integer)
44 , m_desc(d)
45 , m_buf(NULL)
46 , m_int_var(ivar)
47 , m_range_min(min)
48 , m_range_max(max)
50 Engine::eng()->*m_int_var = def_val;
53 Engine::Variable::Variable(char* (Engine::*svar), const char* def_val, const char *d)
54 : m_type(String)
55 , m_desc(d)
56 , m_buf(NULL)
57 , m_string_var(svar)
59 Engine::eng()->*m_string_var = strdup(def_val);
62 Engine::Variable::Variable(VarSetFunc set, VarGetFunc get, const char *d)
63 : m_type(String)
64 , m_desc(d)
65 , m_custom_data(NULL)
66 , m_custom_set(set)
67 , m_custom_get(get)
71 Engine::Variable::Variable(VarSetFunc set, VarGetFunc get, void* data, const char *d)
72 : m_type(String)
73 , m_desc(d)
74 , m_custom_data(data)
75 , m_custom_set(set)
76 , m_custom_get(get)
80 void Engine::Variable::from_string(const char* s)
82 if(m_buf)
84 free(m_buf);
85 m_buf = NULL;
88 switch(m_type)
90 case Integer:
92 int v = atoi(s);
93 if(v < m_range_min || v > m_range_max)
94 printf("Error! value %d out of range (%d-%d)\n", v, m_range_min, m_range_max);
95 else
96 Engine::eng()->*m_int_var = v;
97 break;
100 case String:
101 if(Engine::eng()->*m_string_var)
102 free(Engine::eng()->*m_string_var);
103 Engine::eng()->*m_string_var = strdup(s);
104 break;
106 case Custom:
107 (Engine::eng()->*m_custom_set)(m_custom_data, s);
108 break;
110 default:
111 break;
115 char* str_printf(const char* fmt, ...) {
116 va_list ap;
118 va_start(ap, fmt);
119 int l = vsnprintf(NULL, 0, fmt, ap)+1;
120 va_end(ap);
122 char *str = (char*)malloc(l);
124 va_start(ap, fmt);
125 vsnprintf(str, l, fmt, ap);
126 va_end(ap);
128 return str;
131 const char* Engine::Variable::to_string()
133 if(m_buf)
134 free(m_buf);
136 switch(m_type)
138 case Integer:
139 m_buf = str_printf("%d", Engine::eng()->*m_int_var);
140 break;
142 case String:
143 m_buf = strdup(Engine::eng()->*m_string_var);
144 break;
146 case Custom:
147 m_buf = (Engine::eng()->*m_custom_get)(m_custom_data);
148 break;
150 default:
151 m_buf = NULL;
152 break;
155 return m_buf;
158 static void print_description(int indent, const char* desc)
160 int num;
161 char** tokenized = tokenize(desc ? desc : "<No description>", "\n", &num, false);
163 for(int i=0;i<num;i++)
165 for(int q=0;q<indent;q++)
166 putchar(' ');
167 puts(tokenized[i]);
169 putchar('\n');
170 free(tokenized);
173 void Engine::cmd_quit(int argc, char *argv[])
175 exit(0);
178 void Engine::cmd_ping(int argc, char *argv[])
180 printf("pong %s\n",argv[0]);
183 void Engine::cmd_bench(int argc, char *argv[])
187 void Engine::cmd_perft(int argc, char *argv[])
189 int t = current_time();
190 uint64_t p = perft( atoi(argv[0]) );
191 printf("%lld (time %.02f)\n", (long long)p, (current_time()-t)*0.01 );
194 void Engine::cmd_perftall(int argc, char *argv[])
196 int lev = atoi(argv[0]);
197 Move mv_stack[200];
198 int num;
199 num = board.find_moves(mv_stack);
201 printf("---------\n");
202 for(int i=0;i<num;i++)
204 int p;
205 char buf[32];
206 board.do_move(mv_stack[i]);
207 p = perft(lev);
208 board.undo_move(mv_stack[i]);
209 printf("%s: %d\n", move_to_alg(buf, &mv_stack[i]), p);
211 printf("---------\n");
214 void Engine::cmd_sd(int argc, char *argv[])
216 set_depth( atoi(argv[0]) );
219 void Engine::cmd_st(int argc, char *argv[])
221 set_time_fixed( atoi(argv[0]) );
224 void Engine::cmd_sn(int argc, char *argv[])
226 set_max_nodes( atoi(argv[0]) );
229 void Engine::cmd_otim(int argc, char *argv[])
231 set_other_clock( atoi(argv[0]) );
234 void Engine::cmd_time(int argc, char *argv[])
236 set_my_clock( atoi(argv[0]) );
239 void Engine::cmd_level(int argc, char *argv[])
241 int basem,bases=0;
242 sscanf(argv[1],"%d:%d",&basem,&bases);
244 set_time_control( atoi(argv[0]) ,basem*60+bases, atoi(argv[2]) );
247 void Engine::cmd_help(int argc, char *argv[])
249 for(CmdSet::iterator it = commands.begin(); it != commands.end(); ++it)
251 if(!it->second.max())
252 printf(" %s\n", it->first.c_str() );
253 else if(it->second.min() == it->second.max())
254 printf(" %s (%d %s)\n", it->first.c_str(), it->second.min(), it->second.min()==1?"arg":"args" );
255 else
256 printf(" %s (%d-%d args)\n", it->first.c_str(), it->second.min(), it->second.max() );
258 print_description(4, it->second.desc());
262 void Engine::cmd_force(int argc, char *argv[])
264 force();
267 void Engine::cmd_undo(int argc, char *argv[])
269 undo();
270 if(!io_xboard)
271 print_board();
274 void Engine::cmd_remove(int argc, char *argv[])
276 retract_move();
277 if(!io_xboard)
278 print_board();
281 void Engine::cmd_new(int argc, char *argv[])
283 new_game();
284 if(!io_xboard)
285 print_board();
288 void Engine::cmd_white(int argc, char *argv[])
290 board.color_to_move = WHITE;
291 board.other_color = BLACK;
292 start(BLACK);
295 void Engine::cmd_black(int argc, char *argv[])
297 board.color_to_move = BLACK;
298 board.other_color = WHITE;
299 start(WHITE);
302 void Engine::cmd_go(int argc, char *argv[])
304 start();
307 void Engine::cmd_setboard(int argc, char *argv[])
309 read_board(argv[0], argv[1], argv[2], argv[3], atoi(argv[4]), atoi(argv[5]) );
310 if(!io_xboard)
311 print_board();
314 void Engine::cmd_edit(int argc, char *argv[])
316 //output("Unimplemented!\n");
317 char str[256];
318 while(1)
320 if(!fgets(str, 256, stdin))
321 exit(0);
323 if(str[0]=='.')
324 break;
328 void Engine::cmd_load(int argc, char *argv[])
330 FILE* f = fopen(argv[0],"r");
331 if(f)
333 read_board(f);
334 fclose(f);
335 if(!io_xboard)
336 print_board();
338 else
339 output("Error, could not open \"%s\" for reading.\n", argv[0]);
342 void Engine::cmd_load_pgn(int argc, char *argv[])
344 FILE* f = fopen(argv[0],"r");
345 if(!f)
346 output("Error, could not open \"%s\" for reading.\n", argv[0]);
348 st_computer_color = 0;
349 load_pgn(f);
350 fclose(f);
351 if(!io_xboard)
352 print_board();
355 void Engine::cmd_epdtest(int argc, char *argv[])
357 run_epd_prog(argv[0], atoi(argv[1]), argv[2]);
360 void Engine::cmd_challenge(int argc, char *argv[])
362 challenge(argv[0], atoi(argv[1]), argv[2]);
365 void Engine::cmd_create_book(int argc, char *argv[])
367 create_book(argc, argv);
370 void Engine::cmd_open_book(int argc, char *argv[])
372 open_book(argv[0]);
375 void Engine::cmd_close_book(int argc, char *argv[])
377 close_book();
380 void Engine::cmd_save(int argc, char *argv[])
382 FILE* f = fopen(argv[0],"w");
383 if(f)
385 write_board(f);
386 fclose(f);
388 else
389 output("Error, could not open \"%s\" for writing.\n", argv[0]);
393 void Engine::cmd_test(int argc, char *argv[])
395 printf("test");
396 for(int i=0;i< argc;i++)
397 printf(" \"%s\"", argv[i]);
398 printf("\n");
401 void Engine::cmd_protover(int argc, char *argv[])
403 static const char* features[] = {
404 "san=1",
405 "ping=1",
406 "setboard=1",
407 "sigint=0",
408 "sigterm=0",
409 "analyze=1",
410 "draw=0",
411 "colors=0",
412 "variants=\"normal\"",
413 "myname=\"RattateChess 1.1 Artin\"",
414 "done=1"
416 for(unsigned int i=0; i<sizeof(features)/sizeof(const char*); i++)
417 output("feature %s\n", features[i]);
420 void Engine::cmd_accepted(int argc, char *argv[])
422 if(0 == strcmp("san",argv[0]))
423 io_san = true;
426 void Engine::cmd_rejected(int argc, char *argv[])
431 void Engine::cmd_xboard(int argc, char *argv[])
433 io_xboard = true;
434 signal(SIGINT, SIG_IGN);
437 void Engine::cmd_analyze(int argc, char *argv[])
439 eng_status = ANALYZING;
440 if(thinking)
441 longjmp(back, 1);
444 void Engine::cmd_exit(int argc, char *argv[])
446 eng_status = FORCING;
447 if(thinking)
448 longjmp(back, 1);
451 void Engine::cmd_easy(int argc, char *argv[])
453 ponder = false;
456 void Engine::cmd_hard(int argc, char *argv[])
458 ponder = true;
461 void Engine::cmd_post(int argc, char *argv[])
463 post = true;
466 void Engine::cmd_nopost(int argc, char *argv[])
468 post = false;
471 void Engine::cmd_result(int argc, char *argv[])
473 if(!strcmp(argv[0], "1-0"))
474 status = _10;
475 else if(!strcmp(argv[0], "0-1"))
476 status = _01;
477 else if(!strcmp(argv[0], "1/2-1/2"))
478 status = _12;
479 else
480 output("Unknown result command!\n");
482 if(st_computer_color)
484 FILE *f = fopen("ratta.games", "a");
485 if(f)
487 char all_res[2048];
488 all_res[0] = '\0';
489 for(int i=0;i<argc;i++)
491 strcat(all_res, argv[i]);
492 if(i!=argc-1)
493 strcat(all_res, " " );
495 save_pgn(f, argv[0], all_res);
496 fclose(f);
501 void Engine::cmd_DOT(int argc, char *argv[])
503 print_stat();
506 void Engine::cmd_QUESTION(int argc, char *argv[])
508 move_now();
511 void Engine::cmd_name(int argc, char *argv[])
513 strncpy(opponent, argv[0], 256);
514 opponent[255] = '\0';
517 void Engine::cmd_rating(int argc, char *argv[])
519 w_rating = atoi(argv[0]);
520 b_rating = atoi(argv[1]);
523 void Engine::cmd__gon(int argc, char *argv[])
525 if(search_gui)
526 output("Gui already on!\n");
527 else
528 search_gui = new SearchGui(argc, argv);
531 void Engine::cmd__goff(int argc, char *argv[])
533 if(!search_gui)
534 output("Gui already off!\n");
535 else
537 delete search_gui;
538 search_gui = NULL;
542 void Engine::cmd__check(int argc, char *argv[])
544 Move m;
545 if(parse_move(&m, argv[0])!=1)
547 output("Not a legal move\n");
548 return;
551 board.find_other_pins();
552 if(board.move_is_check(m))
553 output("Yes it is a check\n");
554 else
555 output("Not a check\n");
558 void Engine::cmd__attacks(int argc, char *argv[])
560 uint8_t col = argv[1][0] == 'w' ? WHITE : BLACK;
561 uint8_t pos = POS_XY(argv[0][0]-'a', argv[0][1]-'1' );
562 Board::AttackList al[12];
563 int alnum = board.list_attackers(pos, col, col == board.color_to_move ?
564 board.pins : board.oth_pins, al);
565 for(int i=0;i<alnum;i++)
567 static char nam[] = { 0, 'r', 'b', 'q', 'n', 'p', 'k' };
568 for(int j=0;j<al[i].count;j++)
569 printf("%c ", nam[al[i].piece[j]]);
570 printf("\n");
574 void Engine::cmd__shat(int argc, char *argv[])
576 #if TRACK_ATTACKS
577 board.print_attacks();
578 #else
579 output("Unsupported.\n");
580 #endif
583 void Engine::cmd__see(int argc, char *argv[])
585 Move m;
586 if(parse_move(&m, argv[0])!=1)
588 output("Not a legal move\n");
589 return;
592 output("SEE val: %d\n", board.move_see_val(m));
595 void Engine::cmd__find_moves(int argc, char *argv[])
597 char str[64];
598 Move mv[200];
599 int n = board.find_moves(mv);
601 for(int i=0;i<n;i++)
602 output(" - %s\n", move_to_alg(str, mv+i) );
605 void Engine::cmd__gen_hash(int argc, char *argv[])
607 Board::init_hash_keys( argv[0] );
610 void Engine::cmd_var(int argc, char *argv[])
612 for(VariableSet::iterator it = variables.begin(); it != variables.end(); ++it)
614 printf(" %s = %s\n", it->first.c_str(), it->second.to_string() );
618 void Engine::cmd_varhelp(int argc, char *argv[])
620 for(VariableSet::iterator it = variables.begin(); it != variables.end(); ++it)
622 printf(" %s = %s\n", it->first.c_str(), it->second.to_string() );
623 print_description(4, it->second.desc());
627 void Engine::register_commands()
629 commands["_see"] = Cmd( &Engine::cmd__see, 1,
630 "_see [move]\n"
631 "Calculates the SEE value of a move\n");
632 commands["_shat"] = Cmd( &Engine::cmd__shat,
633 "Shows all attacks\n" );
634 commands["_attacks"] = Cmd( &Engine::cmd__attacks, 2,
635 "_attacks [w|b] [square|a1|a2|...]\n"
636 "Shows all attackers of a square from a color\n" );
637 commands["_check"] = Cmd( &Engine::cmd__check, 1 );
638 commands["_find_moves"] = Cmd( &Engine::cmd__find_moves );
639 commands["_gen_hash"] = Cmd( &Engine::cmd__gen_hash );
640 commands["_gon"] = Cmd( &Engine::cmd__gon );
641 commands["_goff"] = Cmd( &Engine::cmd__goff );
642 //commands["exit"] = Cmd( &Engine::cmd_quit );
643 commands["quit"] = Cmd( &Engine::cmd_quit );
644 commands["ping"] = Cmd( &Engine::cmd_ping, 1 );
645 commands["bench"] = Cmd( &Engine::cmd_bench );
646 commands["perft"] = Cmd( &Engine::cmd_perft, 1 );
647 commands["perftall"] = Cmd( &Engine::cmd_perftall, 1 );
648 commands["sd"] = Cmd( &Engine::cmd_sd, 1 );
649 commands["st"] = Cmd( &Engine::cmd_st, 1 );
650 commands["sn"] = Cmd( &Engine::cmd_sn, 1 );
651 commands["otim"] = Cmd( &Engine::cmd_otim, 1 );
652 commands["time"] = Cmd( &Engine::cmd_time, 1 );
653 commands["level"] = Cmd( &Engine::cmd_level, 3 );
654 commands["help"] = Cmd( &Engine::cmd_help,
655 "Printf this help\n" );
656 commands["force"] = Cmd( &Engine::cmd_force,
657 "Puts the engine in 'force' mode (ie edit game)\n" );
658 commands["undo"] = Cmd( &Engine::cmd_undo );
659 commands["remove"] = Cmd( &Engine::cmd_remove );
660 commands["new"] = Cmd( &Engine::cmd_new );
661 commands["white"] = Cmd( &Engine::cmd_white );
662 commands["black"] = Cmd( &Engine::cmd_black );
663 commands["go"] = Cmd( &Engine::cmd_go );
664 commands["setboard"] = Cmd( &Engine::cmd_setboard, 6,
665 "Sets a FEN string as the current position\n" );
666 commands["edit"] = Cmd( &Engine::cmd_edit,
667 "Puts the engine in (old style) position editing mode\n" );
668 commands["load"] = Cmd( &Engine::cmd_load, 1 );
669 commands["load_pgn"] = Cmd( &Engine::cmd_load_pgn, 1 );
670 commands["epdtest"] = Cmd( &Engine::cmd_epdtest, 3,
671 "Runs an epd test with a chess program and a given time out for each\n"
672 "problem. It requires 3 arguments: the first must be an xboard program\n"
673 "path or 'self', the second the time to think in millseconds, and the\n"
674 "third is the file containing the test positions\n");
675 commands["challenge"] = Cmd( &Engine::cmd_challenge, 3 );
676 commands["create_book"] = Cmd( &Engine::cmd_create_book, 1,
677 "Creates a book file using as argument the path of a PGN file with\n"
678 "a database of games. See also the 'vars' command and the variables\n"
679 "named book_creation_*, that you can use to change many parameters\n" );
680 commands["open_book"] = Cmd( &Engine::cmd_open_book, 1,
681 "Loads a book file\n" );
682 commands["close_book"] = Cmd( &Engine::cmd_close_book,
683 "Closes the book (and make the engine use no book)\n" );
684 commands["save"] = Cmd( &Engine::cmd_save, 1 );
685 commands["test"] = Cmd( &Engine::cmd_test );
686 commands["protover"] = Cmd( &Engine::cmd_protover, 1 );
687 commands["accepted"] = Cmd( &Engine::cmd_accepted, 1 );
688 commands["rejected"] = Cmd( &Engine::cmd_rejected, 1 );
689 commands["xboard"] = Cmd( &Engine::cmd_xboard );
690 commands["winboard"] = Cmd( &Engine::cmd_xboard );
691 commands["analyze"] = Cmd( &Engine::cmd_analyze );
692 commands["exit"] = Cmd( &Engine::cmd_exit );
693 commands["easy"] = Cmd( &Engine::cmd_easy );
694 commands["hard"] = Cmd( &Engine::cmd_hard );
695 commands["post"] = Cmd( &Engine::cmd_post,
696 "Enables printing the thinking\n" );
697 commands["nopost"] = Cmd( &Engine::cmd_nopost,
698 "Disables printing the thinking\n");
699 commands["name"] = Cmd( &Engine::cmd_name, 1 );
700 commands["rating"] = Cmd( &Engine::cmd_rating, 2 );
701 commands["result"] = Cmd( &Engine::cmd_result, 1, 999 );
702 commands["var"] = Cmd( &Engine::cmd_var,
703 "Prints variable values\n" );
704 commands["varhelp"] = Cmd( &Engine::cmd_varhelp,
705 "Prints variable values and with help information\n" );
706 commands["."] = Cmd( &Engine::cmd_DOT,
707 "Print statistics (during analysis)\n" );
708 commands["?"] = Cmd( &Engine::cmd_QUESTION,
709 "Move immediatly\n" );
712 void Engine::register_variables()
714 variables["book_creation_max_depth"] = Variable( &Engine::v_book_creation_max_depth, 28, 1, 50,
715 "Maximum depth (in ply) for selecting positions to include in the book\n");
716 variables["book_creation_max_alternatives"] = Variable( &Engine::v_book_creation_max_alternatives, 7, 1, INT_MAX,
717 "Maximum number of possible moves to store in the book for each position\n");
718 variables["book_creation_min_games"] = Variable( &Engine::v_book_creation_min_games, 6, 1, INT_MAX,
719 "Minimum number of games in which a position must appear to be included\n" );
720 variables["book_creation_min_probability"] = Variable( &Engine::v_book_creation_min_probability, 10, 0, 1000,
721 "Minimum probability that an possible move must have to be put in the book\n");
722 variables["book_creation_weigh_win"] = Variable( &Engine::v_book_creation_weigh_win, 3, 0, INT_MAX,
723 "Weight for a move played in a won game (to make more likely winning moves)\n");
724 variables["book_creation_weigh_draw"] = Variable( &Engine::v_book_creation_weigh_draw, 2, 0, INT_MAX,
725 "Weight for a move played in a drawn game (to make more likely winning moves)\n");
726 variables["book_creation_weigh_lose"] = Variable( &Engine::v_book_creation_weigh_lose, 1, 0, INT_MAX,
727 "Weight for a move played in a lost game (to make more likely winning moves)\n");
729 variables["search_null_reduction"] = Variable( &Engine::v_search_null_reduction, 300, 200, 400,
730 "Reduction for null move (in ply*100)\n");
731 variables["search_threat_extension"] = Variable( &Engine::v_search_threat_extension, 100, 40, 120,
732 "Reduction for null move (in ply*100)\n");
733 variables["search_threat_threshold"] = Variable( &Engine::v_search_threat_threshold, 340, 150, 720,
734 "Reduction for null move (in ply*100)\n");
736 variables["eval_draw"] = Variable( &Engine::v_eval_draw, -20, 0, -100,
737 "Value of a position drawn by repetition, 50 moves rule or insufficient material\n");