per test
[rattatechess.git] / commands.cpp
blobb3162cdcd0d6ca0ea91227e8bf3ff087930c0cd8
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>
25 #include <limits.h>
27 void Engine::Cmd::run(int argc, char *argv[])
29 (Engine::eng()->*m_func)(argc, argv);
32 Engine::Variable::Variable(int (Engine::*ivar), int def_val, const char *d)
33 : m_type(Integer)
34 , m_desc(d)
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_int_var(ivar)
46 , m_range_min(min)
47 , m_range_max(max)
49 Engine::eng()->*m_int_var = def_val;
52 Engine::Variable::Variable(char* (Engine::*svar), const char* def_val, const char *d)
53 : m_type(String)
54 , m_desc(d)
55 , m_string_var(svar)
57 Engine::eng()->*m_string_var = strdup(def_val);
60 Engine::Variable::Variable(VarSetFunc set, VarGetFunc get, const char *d)
61 : m_type(String)
62 , m_desc(d)
63 , m_custom_data(NULL)
64 , m_custom_set(set)
65 , m_custom_get(get)
69 Engine::Variable::Variable(VarSetFunc set, VarGetFunc get, void* data, const char *d)
70 : m_type(String)
71 , m_desc(d)
72 , m_custom_data(data)
73 , m_custom_set(set)
74 , m_custom_get(get)
78 void Engine::Variable::from_string(const char* s)
80 switch(m_type)
82 case Integer:
84 int v = atoi(s);
85 if(v < m_range_min || v > m_range_max)
86 printf("Error! value %d out of range (%d-%d)\n", v, m_range_min, m_range_max);
87 else
88 Engine::eng()->*m_int_var = v;
89 break;
92 case String:
93 if(Engine::eng()->*m_string_var)
94 free(Engine::eng()->*m_string_var);
95 Engine::eng()->*m_string_var = strdup(s);
96 break;
98 case Custom:
99 (Engine::eng()->*m_custom_set)(m_custom_data, s);
100 break;
102 default:
103 break;
107 const char* Engine::Variable::to_string(char* buf64)
109 switch(m_type)
111 case Integer:
112 snprintf(buf64, 64, "%d", Engine::eng()->*m_int_var);
113 break;
115 case String:
116 strncpy(buf64, Engine::eng()->*m_string_var, 64);
117 break;
119 case Custom:
120 (Engine::eng()->*m_custom_get)(m_custom_data, buf64);
121 break;
123 default:
124 buf64[0] = '\0';
125 break;
128 return buf64;
131 static void print_description(int indent, const char* desc)
133 int num;
134 char** tokenized = tokenize(desc ? desc : "<No description>", "\n", &num, false);
136 for(int i=0;i<num;i++)
138 for(int q=0;q<indent;q++)
139 putchar(' ');
140 puts(tokenized[i]);
142 putchar('\n');
143 free(tokenized);
146 void Engine::cmd_quit(int argc, char *argv[])
148 exit(0);
151 void Engine::cmd_ping(int argc, char *argv[])
153 printf("pong %s\n",argv[0]);
156 void Engine::cmd_bench(int argc, char *argv[])
160 void Engine::cmd_perft(int argc, char *argv[])
162 int t = current_time();
163 uint64_t p = perft( atoi(argv[0]) );
164 printf("%lld (time %.02f)\n", (long long)p, (current_time()-t)*0.01 );
167 void Engine::cmd_perftall(int argc, char *argv[])
169 int lev = atoi(argv[0]);
170 Move mv_stack[200];
171 int num;
172 num = board.find_moves(mv_stack);
174 printf("---------\n");
175 for(int i=0;i<num;i++)
177 int p;
178 board.do_move(mv_stack[i], save_buf[save_buf_num++]);
179 p = perft(lev);
180 board.undo_move(mv_stack[i], save_buf[--save_buf_num]);
181 printf("%s: %d\n", board.move_to_alg(MoveStr().data(), mv_stack[i]), p);
183 printf("---------\n");
186 void Engine::cmd_sd(int argc, char *argv[])
188 set_depth( atoi(argv[0]) );
191 void Engine::cmd_st(int argc, char *argv[])
193 set_time_fixed( atoi(argv[0]) );
196 void Engine::cmd_sn(int argc, char *argv[])
198 set_max_nodes( atoi(argv[0]) );
201 void Engine::cmd_otim(int argc, char *argv[])
203 set_other_clock( atoi(argv[0]) );
206 void Engine::cmd_time(int argc, char *argv[])
208 set_my_clock( atoi(argv[0]) );
211 void Engine::cmd_level(int argc, char *argv[])
213 int basem,bases=0;
214 sscanf(argv[1],"%d:%d",&basem,&bases);
216 set_time_control( atoi(argv[0]) ,basem*60+bases, atoi(argv[2]) );
219 void Engine::cmd_help(int argc, char *argv[])
221 for(CmdSet::iterator it = commands.begin(); it != commands.end(); ++it)
223 if(!it->second.max())
224 printf(" %s\n", it->first.c_str() );
225 else if(it->second.min() == it->second.max())
226 printf(" %s (%d %s)\n", it->first.c_str(), it->second.min(), it->second.min()==1?"arg":"args" );
227 else
228 printf(" %s (%d-%d args)\n", it->first.c_str(), it->second.min(), it->second.max() );
230 print_description(4, it->second.desc());
234 void Engine::cmd_force(int argc, char *argv[])
236 force();
239 void Engine::cmd_undo(int argc, char *argv[])
241 undo();
242 if(!io_xboard)
243 print_board();
246 void Engine::cmd_remove(int argc, char *argv[])
248 retract_move();
249 if(!io_xboard)
250 print_board();
253 void Engine::cmd_new(int argc, char *argv[])
255 new_game();
256 if(!io_xboard)
257 print_board();
260 void Engine::cmd_white(int argc, char *argv[])
262 board.color_to_move = WHITE;
263 board.other_color = BLACK;
264 start(BLACK);
267 void Engine::cmd_black(int argc, char *argv[])
269 board.color_to_move = BLACK;
270 board.other_color = WHITE;
271 start(WHITE);
274 void Engine::cmd_go(int argc, char *argv[])
276 start();
279 void Engine::cmd_setboard(int argc, char *argv[])
281 read_board(argv[0], argv[1], argv[2], argv[3], atoi(argv[4]), atoi(argv[5]) );
282 if(!io_xboard)
283 print_board();
286 void Engine::cmd_edit(int argc, char *argv[])
288 //output("Unimplemented!\n");
289 char str[256];
290 while(1)
292 if(!fgets(str, 256, stdin))
293 exit(0);
295 if(str[0]=='.')
296 break;
300 void Engine::cmd_load(int argc, char *argv[])
302 FILE* f = fopen(argv[0],"r");
303 if(f)
305 read_board(f);
306 fclose(f);
307 if(!io_xboard)
308 print_board();
310 else
311 output("Error, could not open \"%s\" for reading.\n", argv[0]);
314 void Engine::cmd_load_pgn(int argc, char *argv[])
316 FILE* f = fopen(argv[0],"r");
317 if(!f)
318 output("Error, could not open \"%s\" for reading.\n", argv[0]);
320 st_computer_color = 0;
321 load_pgn(f);
322 fclose(f);
323 if(!io_xboard)
324 print_board();
327 void Engine::cmd_epdtest(int argc, char *argv[])
329 run_epd_prog(argv[0], atoi(argv[1]), argv[2], argc==4 && !strncmp(argv[3], "quiet", strlen(argv[3])));
332 void Engine::cmd_challenge(int argc, char *argv[])
334 challenge(argv[0], atoi(argv[1]), argv[2]);
337 void Engine::cmd_create_book(int argc, char *argv[])
339 create_book(argc, argv);
342 void Engine::cmd_open_book(int argc, char *argv[])
344 open_book(argv[0]);
347 void Engine::cmd_close_book(int argc, char *argv[])
349 close_book();
352 void Engine::cmd_open_lines(int argc, char *argv[])
354 open_lines(argv[0]);
357 void Engine::cmd_close_lines(int argc, char *argv[])
359 close_lines();
362 void Engine::cmd_open_eco(int argc, char *argv[])
364 open_openings(argv[0]);
367 void Engine::cmd_close_eco(int argc, char *argv[])
369 close_openings();
372 void Engine::cmd_save(int argc, char *argv[])
374 FILE* f = fopen(argv[0],"w");
375 if(f)
377 write_board(f);
378 fclose(f);
380 else
381 output("Error, could not open \"%s\" for writing.\n", argv[0]);
385 void Engine::cmd_test(int argc, char *argv[])
387 printf("test");
388 for(int i=0;i< argc;i++)
389 printf(" \"%s\"", argv[i]);
390 printf("\n");
393 void Engine::cmd_protover(int argc, char *argv[])
395 static const char* features[] = {
396 "san=1",
397 "ping=1",
398 "setboard=1",
399 "sigint=0",
400 "sigterm=0",
401 "analyze=1",
402 "draw=0",
403 "colors=0",
404 "variants=\"normal\"",
405 "myname=\"RattateChess 1.1 Artin\"",
406 "done=1"
408 for(unsigned int i=0; i<sizeof(features)/sizeof(const char*); i++)
409 output("feature %s\n", features[i]);
412 void Engine::cmd_accepted(int argc, char *argv[])
414 if(0 == strcmp("san",argv[0]))
415 io_san = true;
418 void Engine::cmd_rejected(int argc, char *argv[])
423 void Engine::cmd_xboard(int argc, char *argv[])
425 io_xboard = true;
426 signal(SIGINT, SIG_IGN);
429 void Engine::cmd_analyze(int argc, char *argv[])
431 eng_status = ANALYZING;
432 if(thinking)
433 longjmp(back, 1);
436 void Engine::cmd_exit(int argc, char *argv[])
438 eng_status = FORCING;
439 if(thinking)
440 longjmp(back, 1);
443 void Engine::cmd_easy(int argc, char *argv[])
445 ponder = false;
448 void Engine::cmd_hard(int argc, char *argv[])
450 ponder = true;
453 void Engine::cmd_post(int argc, char *argv[])
455 post = true;
458 void Engine::cmd_nopost(int argc, char *argv[])
460 post = false;
463 void Engine::cmd_result(int argc, char *argv[])
465 if(!strcmp(argv[0], "1-0"))
466 status = _10;
467 else if(!strcmp(argv[0], "0-1"))
468 status = _01;
469 else if(!strcmp(argv[0], "1/2-1/2"))
470 status = _12;
471 else
472 output("Unknown result command!\n");
474 if(st_computer_color)
476 FILE *f = fopen("ratta.games", "a");
477 if(f)
479 char all_res[2048];
480 all_res[0] = '\0';
481 for(int i=0;i<argc;i++)
483 strcat(all_res, argv[i]);
484 if(i!=argc-1)
485 strcat(all_res, " " );
487 save_pgn(f, argv[0], all_res);
488 fclose(f);
493 void Engine::cmd_DOT(int argc, char *argv[])
495 print_stat();
498 void Engine::cmd_QUESTION(int argc, char *argv[])
500 move_now();
503 void Engine::cmd_name(int argc, char *argv[])
505 strncpy(opponent, argv[0], 256);
506 opponent[255] = '\0';
509 void Engine::cmd_rating(int argc, char *argv[])
511 w_rating = atoi(argv[0]);
512 b_rating = atoi(argv[1]);
515 void Engine::cmd__gon(int argc, char *argv[])
517 if(search_gui)
518 output("Gui already on!\n");
519 else
520 search_gui = new SearchGui(argc, argv);
523 void Engine::cmd__goff(int argc, char *argv[])
525 if(!search_gui)
526 output("Gui already off!\n");
527 else
529 delete search_gui;
530 search_gui = NULL;
534 void Engine::cmd__check(int argc, char *argv[])
536 Move m = board.move_from_string(argv[0]);
537 if(!m.valid())
539 output("Not a legal move\n");
540 return;
543 board.find_other_pins();
544 if(board.move_is_check(m))
545 output("Yes it is a check\n");
546 else
547 output("Not a check\n");
550 void Engine::cmd__attacks(int argc, char *argv[])
552 uint8_t col = argv[1][0] == 'w' ? WHITE : BLACK;
553 uint8_t pos = POS_XY(argv[0][0]-'a', argv[0][1]-'1' );
554 Board::AttackList al[12];
555 int alnum = board.list_attackers(pos, col, col == board.color_to_move ?
556 board.pins : board.oth_pins, al);
557 for(int i=0;i<alnum;i++)
559 static char nam[] = { 0, 'r', 'b', 'q', 'n', 'p', 'k' };
560 for(int j=0;j<al[i].count;j++)
561 printf("%c ", nam[al[i].piece[j]]);
562 printf("\n");
566 void Engine::cmd__shat(int argc, char *argv[])
568 #if TRACK_ATTACKS
569 board.print_attacks();
570 #else
571 output("Unsupported.\n");
572 #endif
575 void Engine::cmd__see(int argc, char *argv[])
577 Move m = board.move_from_string(argv[0]);
578 if(!m.valid())
580 output("Not a legal move\n");
581 return;
584 output("SEE val: %d\n", board.move_see_val(m));
587 void Engine::cmd__find_moves(int argc, char *argv[])
589 Move mv[200];
590 int n = board.find_moves(mv);
592 for(int i=0;i<n;i++)
593 output(" - %s\n", board.move_to_alg(MoveStr().data(), mv[i]) );
596 void Engine::cmd__gen_hash(int argc, char *argv[])
598 Board::init_hash_keys( argv[0] );
601 void Engine::cmd_set(int argc, char *argv[])
603 std::map<std::string, Variable>::iterator it = variables.find(argv[0]);
604 if(it == variables.end())
605 printf(" -> unknown variable '%s'!\n", argv[0]);
606 else
608 it->second.from_string(argv[1]);
609 printf(" %s -> %s\n", it->second.to_string(TmpStr().data()), it->first.c_str() );
613 void Engine::cmd_var(int argc, char *argv[])
615 if(argc == 0)
616 for(VariableSet::iterator it = variables.begin(); it != variables.end(); ++it)
617 printf(" %s = %s\n", it->first.c_str(), it->second.to_string(TmpStr().data()) );
618 else
619 for(int i=0;i<argc;i++)
621 std::map<std::string, Variable>::iterator it = variables.find(argv[i]);
622 if(it == variables.end())
623 printf(" -> unknown variable '%s'!\n", argv[i]);
624 else
625 printf(" %s = %s\n", it->first.c_str(), it->second.to_string(TmpStr().data()) );
629 void Engine::cmd_varhelp(int argc, char *argv[])
631 for(VariableSet::iterator it = variables.begin(); it != variables.end(); ++it)
633 printf(" %s = %s\n", it->first.c_str(), it->second.to_string(TmpStr().data()) );
634 print_description(4, it->second.desc());
638 void Engine::register_commands()
640 commands["_see"] = Cmd( &Engine::cmd__see, 1,
641 "_see [move]\n"
642 "Calculates the SEE value of a move\n");
643 commands["_shat"] = Cmd( &Engine::cmd__shat,
644 "Shows all attacks\n" );
645 commands["_attacks"] = Cmd( &Engine::cmd__attacks, 2,
646 "_attacks [w|b] [square|a1|a2|...]\n"
647 "Shows all attackers of a square from a color\n" );
648 commands["_check"] = Cmd( &Engine::cmd__check, 1 );
649 commands["_find_moves"] = Cmd( &Engine::cmd__find_moves );
650 commands["_gen_hash"] = Cmd( &Engine::cmd__gen_hash );
651 commands["_gon"] = Cmd( &Engine::cmd__gon );
652 commands["_goff"] = Cmd( &Engine::cmd__goff );
653 //commands["exit"] = Cmd( &Engine::cmd_quit );
654 commands["quit"] = Cmd( &Engine::cmd_quit );
655 commands["ping"] = Cmd( &Engine::cmd_ping, 1 );
656 commands["bench"] = Cmd( &Engine::cmd_bench );
657 commands["perft"] = Cmd( &Engine::cmd_perft, 1 );
658 commands["perftall"] = Cmd( &Engine::cmd_perftall, 1 );
659 commands["sd"] = Cmd( &Engine::cmd_sd, 1 );
660 commands["st"] = Cmd( &Engine::cmd_st, 1 );
661 commands["sn"] = Cmd( &Engine::cmd_sn, 1 );
662 commands["otim"] = Cmd( &Engine::cmd_otim, 1 );
663 commands["time"] = Cmd( &Engine::cmd_time, 1 );
664 commands["level"] = Cmd( &Engine::cmd_level, 3 );
665 commands["help"] = Cmd( &Engine::cmd_help,
666 "Printf this help\n" );
667 commands["force"] = Cmd( &Engine::cmd_force,
668 "Puts the engine in 'force' mode (ie edit game)\n" );
669 commands["undo"] = Cmd( &Engine::cmd_undo );
670 commands["remove"] = Cmd( &Engine::cmd_remove );
671 commands["new"] = Cmd( &Engine::cmd_new );
672 commands["white"] = Cmd( &Engine::cmd_white );
673 commands["black"] = Cmd( &Engine::cmd_black );
674 commands["go"] = Cmd( &Engine::cmd_go );
675 commands["setboard"] = Cmd( &Engine::cmd_setboard, 6,
676 "Sets a FEN string as the current position\n" );
677 commands["edit"] = Cmd( &Engine::cmd_edit,
678 "Puts the engine in (old style) position editing mode\n" );
679 commands["load"] = Cmd( &Engine::cmd_load, 1 );
680 commands["load_pgn"] = Cmd( &Engine::cmd_load_pgn, 1 );
681 commands["epdtest"] = Cmd( &Engine::cmd_epdtest, 3, 4,
682 "Runs an epd test with a chess program and a given time out for each\n"
683 "problem. It requires 3 arguments: the first must be an xboard program\n"
684 "path or 'self', the second the time to think in millseconds, and the\n"
685 "third is the file containing the test positions\n");
686 commands["challenge"] = Cmd( &Engine::cmd_challenge, 3 );
687 commands["create_book"] = Cmd( &Engine::cmd_create_book, 1, 2,
688 "Creates a book file using as argument the path of a PGN file with\n"
689 "a database of games, and possibly the path of a file with ECO codes.\n"
690 "See also the 'vars' command and the variables named book_creation_*,\n"
691 "that you can use to change many options\n" );
692 commands["open_book"] = Cmd( &Engine::cmd_open_book, 1,
693 "Loads a book file\n" );
694 commands["close_book"] = Cmd( &Engine::cmd_close_book,
695 "Closes the book (and make the engine use no book)\n" );
696 commands["open_lines"] = Cmd( &Engine::cmd_open_lines, 1,
697 "Loads a lines file (where you can select the openings to play)\n" );
698 commands["close_lines"] = Cmd( &Engine::cmd_close_lines,
699 "Closes the lines file (and make the engine use no lines)\n" );
700 commands["open_eco"] = Cmd( &Engine::cmd_open_eco, 1,
701 "Loads a eco file\n" );
702 commands["close_eco"] = Cmd( &Engine::cmd_close_eco,
703 "Closes the eco (and make the engine use no eco)\n" );
704 commands["save"] = Cmd( &Engine::cmd_save, 1 );
705 commands["test"] = Cmd( &Engine::cmd_test );
706 commands["protover"] = Cmd( &Engine::cmd_protover, 1 );
707 commands["accepted"] = Cmd( &Engine::cmd_accepted, 1 );
708 commands["rejected"] = Cmd( &Engine::cmd_rejected, 1 );
709 commands["xboard"] = Cmd( &Engine::cmd_xboard );
710 commands["winboard"] = Cmd( &Engine::cmd_xboard );
711 commands["analyze"] = Cmd( &Engine::cmd_analyze );
712 commands["exit"] = Cmd( &Engine::cmd_exit );
713 commands["easy"] = Cmd( &Engine::cmd_easy );
714 commands["hard"] = Cmd( &Engine::cmd_hard );
715 commands["post"] = Cmd( &Engine::cmd_post,
716 "Enables printing the thinking\n" );
717 commands["nopost"] = Cmd( &Engine::cmd_nopost,
718 "Disables printing the thinking\n");
719 commands["name"] = Cmd( &Engine::cmd_name, 1 );
720 commands["rating"] = Cmd( &Engine::cmd_rating, 2 );
721 commands["result"] = Cmd( &Engine::cmd_result, 1, 999 );
722 commands["var"] = Cmd( &Engine::cmd_var, 0, 999,
723 "Prints variable[s] values\n" );
724 commands["set"] = Cmd( &Engine::cmd_set, 2,
725 "Set variable value\n" );
726 commands["varhelp"] = Cmd( &Engine::cmd_varhelp,
727 "Prints variable values and with help information\n" );
728 commands["."] = Cmd( &Engine::cmd_DOT,
729 "Print statistics (during analysis)\n" );
730 commands["?"] = Cmd( &Engine::cmd_QUESTION,
731 "Move immediatly\n" );
734 void Engine::register_variables()
736 variables["book_creation_max_depth"] = Variable( &Engine::v_book_creation_max_depth, 28, 1, 50,
737 "Maximum depth (in ply) for selecting positions to include in the book\n");
738 variables["book_creation_max_alternatives"] = Variable( &Engine::v_book_creation_max_alternatives, 7, 1, INT_MAX,
739 "Maximum number of possible moves to store in the book for each position\n");
740 variables["book_creation_min_games"] = Variable( &Engine::v_book_creation_min_games, 6, 1, INT_MAX,
741 "Minimum number of games in which a position must appear to be included\n" );
742 variables["book_creation_min_probability"] = Variable( &Engine::v_book_creation_min_probability, 10, 0, 1000,
743 "Minimum probability that an possible move must have to be put in the book\n");
744 variables["book_creation_weigh_win"] = Variable( &Engine::v_book_creation_weigh_win, 3, 0, INT_MAX,
745 "Weight for a move played in a won game (to make more likely winning moves)\n");
746 variables["book_creation_weigh_draw"] = Variable( &Engine::v_book_creation_weigh_draw, 2, 0, INT_MAX,
747 "Weight for a move played in a drawn game (to make more likely winning moves)\n");
748 variables["book_creation_weigh_lose"] = Variable( &Engine::v_book_creation_weigh_lose, 1, 0, INT_MAX,
749 "Weight for a move played in a lost game (to make more likely winning moves)\n");
751 variables["search_null_reduction"] = Variable( &Engine::v_search_null_reduction, 300, 200, 400,
752 "Reduction for null move (in ply*100)\n");
753 variables["search_threat_extension"] = Variable( &Engine::v_search_threat_extension, 100, 40, 120,
754 "Reduction for null move (in ply*100)\n");
755 variables["search_threat_threshold"] = Variable( &Engine::v_search_threat_threshold, 340, 150, 720,
756 "Reduction for null move (in ply*100)\n");
758 variables["eval_draw"] = Variable( &Engine::v_eval_draw, -20, 0, -100,
759 "Value of a position drawn by repetition, 50 moves rule or insufficient material\n");