1 /***************************************************************************
2 commandparse.cpp - description
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
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. *
16 ***************************************************************************/
21 #include "search_gui.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
)
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
)
49 Engine::eng()->*m_int_var
= def_val
;
52 Engine::Variable::Variable(char* (Engine::*svar
), const char* def_val
, const char *d
)
57 Engine::eng()->*m_string_var
= strdup(def_val
);
60 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, const char *d
)
69 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, void* data
, const char *d
)
78 void Engine::Variable::from_string(const char* 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
);
88 Engine::eng()->*m_int_var
= v
;
93 if(Engine::eng()->*m_string_var
)
94 free(Engine::eng()->*m_string_var
);
95 Engine::eng()->*m_string_var
= strdup(s
);
99 (Engine::eng()->*m_custom_set
)(m_custom_data
, s
);
107 const char* Engine::Variable::to_string(char* buf64
)
112 snprintf(buf64
, 64, "%d", Engine::eng()->*m_int_var
);
116 strncpy(buf64
, Engine::eng()->*m_string_var
, 64);
120 (Engine::eng()->*m_custom_get
)(m_custom_data
, buf64
);
131 static void print_description(int indent
, const char* desc
)
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
++)
146 void Engine::cmd_quit(int argc
, char *argv
[])
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]);
172 num
= board
.find_moves(mv_stack
);
174 printf("---------\n");
175 for(int i
=0;i
<num
;i
++)
178 board
.do_move(mv_stack
[i
], save_buf
[save_buf_num
++]);
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
[])
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" );
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
[])
239 void Engine::cmd_undo(int argc
, char *argv
[])
246 void Engine::cmd_remove(int argc
, char *argv
[])
253 void Engine::cmd_new(int argc
, char *argv
[])
260 void Engine::cmd_white(int argc
, char *argv
[])
262 board
.color_to_move
= WHITE
;
263 board
.other_color
= BLACK
;
267 void Engine::cmd_black(int argc
, char *argv
[])
269 board
.color_to_move
= BLACK
;
270 board
.other_color
= WHITE
;
274 void Engine::cmd_go(int argc
, char *argv
[])
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]) );
286 void Engine::cmd_edit(int argc
, char *argv
[])
288 //output("Unimplemented!\n");
292 if(!fgets(str
, 256, stdin
))
300 void Engine::cmd_load(int argc
, char *argv
[])
302 FILE* f
= fopen(argv
[0],"r");
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");
318 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
320 st_computer_color
= 0;
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
[])
347 void Engine::cmd_close_book(int argc
, char *argv
[])
352 void Engine::cmd_open_lines(int argc
, char *argv
[])
357 void Engine::cmd_close_lines(int argc
, char *argv
[])
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
[])
372 void Engine::cmd_save(int argc
, char *argv
[])
374 FILE* f
= fopen(argv
[0],"w");
381 output("Error, could not open \"%s\" for writing.\n", argv
[0]);
385 void Engine::cmd_test(int argc
, char *argv
[])
388 for(int i
=0;i
< argc
;i
++)
389 printf(" \"%s\"", argv
[i
]);
393 void Engine::cmd_protover(int argc
, char *argv
[])
395 static const char* features
[] = {
404 "variants=\"normal\"",
405 "myname=\"RattateChess 1.1 Artin\"",
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]))
418 void Engine::cmd_rejected(int argc
, char *argv
[])
423 void Engine::cmd_xboard(int argc
, char *argv
[])
426 signal(SIGINT
, SIG_IGN
);
429 void Engine::cmd_analyze(int argc
, char *argv
[])
431 eng_status
= ANALYZING
;
436 void Engine::cmd_exit(int argc
, char *argv
[])
438 eng_status
= FORCING
;
443 void Engine::cmd_easy(int argc
, char *argv
[])
448 void Engine::cmd_hard(int argc
, char *argv
[])
453 void Engine::cmd_post(int argc
, char *argv
[])
458 void Engine::cmd_nopost(int argc
, char *argv
[])
463 void Engine::cmd_result(int argc
, char *argv
[])
465 if(!strcmp(argv
[0], "1-0"))
467 else if(!strcmp(argv
[0], "0-1"))
469 else if(!strcmp(argv
[0], "1/2-1/2"))
472 output("Unknown result command!\n");
474 if(st_computer_color
)
476 FILE *f
= fopen("ratta.games", "a");
481 for(int i
=0;i
<argc
;i
++)
483 strcat(all_res
, argv
[i
]);
485 strcat(all_res
, " " );
487 save_pgn(f
, argv
[0], all_res
);
493 void Engine::cmd_DOT(int argc
, char *argv
[])
498 void Engine::cmd_QUESTION(int argc
, char *argv
[])
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
[])
518 output("Gui already on!\n");
520 search_gui
= new SearchGui(argc
, argv
);
523 void Engine::cmd__goff(int argc
, char *argv
[])
526 output("Gui already off!\n");
534 void Engine::cmd__check(int argc
, char *argv
[])
536 Move m
= board
.move_from_string(argv
[0]);
539 output("Not a legal move\n");
543 board
.find_other_pins();
544 if(board
.move_is_check(m
))
545 output("Yes it is a check\n");
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
]]);
566 void Engine::cmd__shat(int argc
, char *argv
[])
569 board
.print_attacks();
571 output("Unsupported.\n");
575 void Engine::cmd__see(int argc
, char *argv
[])
577 Move m
= board
.move_from_string(argv
[0]);
580 output("Not a legal move\n");
584 output("SEE val: %d\n", board
.move_see_val(m
));
587 void Engine::cmd__find_moves(int argc
, char *argv
[])
590 int n
= board
.find_moves(mv
);
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]);
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
[])
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()) );
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
]);
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,
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");