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"
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
)
35 , m_range_min(INT_MIN
)
36 , m_range_max(INT_MAX
)
38 Engine::eng()->*m_int_var
= def_val
;
41 Engine::Variable::Variable(int (Engine::*ivar
), int def_val
, int min
, int max
, const char *d
)
48 Engine::eng()->*m_int_var
= def_val
;
51 Engine::Variable::Variable(char* (Engine::*svar
), const char* def_val
, const char *d
)
56 Engine::eng()->*m_string_var
= strdup(def_val
);
59 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, const char *d
)
68 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, void* data
, const char *d
)
77 void Engine::Variable::from_string(const char* s
)
84 if(v
< m_range_min
|| v
> m_range_max
)
85 printf("Error! value %d out of range (%d-%d)\n", v
, m_range_min
, m_range_max
);
87 Engine::eng()->*m_int_var
= v
;
92 if(Engine::eng()->*m_string_var
)
93 free(Engine::eng()->*m_string_var
);
94 Engine::eng()->*m_string_var
= strdup(s
);
98 (Engine::eng()->*m_custom_set
)(m_custom_data
, s
);
106 const char* Engine::Variable::to_string(char* buf64
)
111 snprintf(buf64
, 64, "%d", Engine::eng()->*m_int_var
);
115 strncpy(buf64
, Engine::eng()->*m_string_var
, 64);
119 (Engine::eng()->*m_custom_get
)(m_custom_data
, buf64
);
130 static void print_description(int indent
, const char* desc
)
133 char** tokenized
= tokenize(desc
? desc
: "<No description>", "\n", &num
, false);
135 for(int i
=0;i
<num
;i
++)
137 for(int q
=0;q
<indent
;q
++)
145 void Engine::cmd_quit(int argc
, char *argv
[])
150 void Engine::cmd_ping(int argc
, char *argv
[])
152 printf("pong %s\n",argv
[0]);
155 void Engine::cmd_bench(int argc
, char *argv
[])
159 void Engine::cmd_perft(int argc
, char *argv
[])
161 int t
= current_time();
162 uint64_t p
= perft( atoi(argv
[0]) );
163 printf("%lld (time %.02f)\n", (long long)p
, (current_time()-t
)*0.01 );
166 void Engine::cmd_perftall(int argc
, char *argv
[])
168 int lev
= atoi(argv
[0]);
171 num
= board
.find_moves(mv_stack
);
173 printf("---------\n");
174 for(int i
=0;i
<num
;i
++)
177 board
.do_move(mv_stack
[i
], save_buf
[save_buf_num
++]);
179 board
.undo_move(mv_stack
[i
], save_buf
[--save_buf_num
]);
180 printf("%s: %d\n", board
.move_to_alg(MoveStr().data(), mv_stack
[i
]), p
);
182 printf("---------\n");
185 void Engine::cmd_sd(int argc
, char *argv
[])
187 set_depth( atoi(argv
[0]) );
190 void Engine::cmd_st(int argc
, char *argv
[])
192 set_time_fixed( atoi(argv
[0]) );
195 void Engine::cmd_sn(int argc
, char *argv
[])
197 set_max_nodes( atoi(argv
[0]) );
200 void Engine::cmd_otim(int argc
, char *argv
[])
202 set_other_clock( atoi(argv
[0]) );
205 void Engine::cmd_time(int argc
, char *argv
[])
207 set_my_clock( atoi(argv
[0]) );
210 void Engine::cmd_level(int argc
, char *argv
[])
213 sscanf(argv
[1],"%d:%d",&basem
,&bases
);
215 set_time_control( atoi(argv
[0]) ,basem
*60+bases
, atoi(argv
[2]) );
218 void Engine::cmd_help(int argc
, char *argv
[])
220 for(CmdSet::iterator it
= commands
.begin(); it
!= commands
.end(); ++it
)
222 if(!it
->second
.max())
223 printf(" %s\n", it
->first
.c_str() );
224 else if(it
->second
.min() == it
->second
.max())
225 printf(" %s (%d %s)\n", it
->first
.c_str(), it
->second
.min(), it
->second
.min()==1?"arg":"args" );
227 printf(" %s (%d-%d args)\n", it
->first
.c_str(), it
->second
.min(), it
->second
.max() );
229 print_description(4, it
->second
.desc());
233 void Engine::cmd_force(int argc
, char *argv
[])
238 void Engine::cmd_undo(int argc
, char *argv
[])
245 void Engine::cmd_remove(int argc
, char *argv
[])
252 void Engine::cmd_new(int argc
, char *argv
[])
259 void Engine::cmd_white(int argc
, char *argv
[])
261 board
.color_to_move
= WHITE
;
262 board
.other_color
= BLACK
;
266 void Engine::cmd_black(int argc
, char *argv
[])
268 board
.color_to_move
= BLACK
;
269 board
.other_color
= WHITE
;
273 void Engine::cmd_go(int argc
, char *argv
[])
278 void Engine::cmd_setboard(int argc
, char *argv
[])
280 read_board(argv
[0], argv
[1], argv
[2], argv
[3], atoi(argv
[4]), atoi(argv
[5]) );
285 void Engine::cmd_edit(int argc
, char *argv
[])
287 //output("Unimplemented!\n");
291 if(!fgets(str
, 256, stdin
))
299 void Engine::cmd_load(int argc
, char *argv
[])
301 FILE* f
= fopen(argv
[0],"r");
310 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
313 void Engine::cmd_load_pgn(int argc
, char *argv
[])
315 FILE* f
= fopen(argv
[0],"r");
317 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
319 st_computer_color
= 0;
326 void Engine::cmd_epdtest(int argc
, char *argv
[])
328 run_epd_prog(argv
[0], atoi(argv
[1]), argv
[2], argc
==4 && !strncmp(argv
[3], "quiet", strlen(argv
[3])));
331 void Engine::cmd_challenge(int argc
, char *argv
[])
333 challenge(argv
[0], atoi(argv
[1]), argv
[2]);
336 void Engine::cmd_create_book(int argc
, char *argv
[])
338 create_book(argc
, argv
);
341 void Engine::cmd_open_book(int argc
, char *argv
[])
346 void Engine::cmd_close_book(int argc
, char *argv
[])
351 void Engine::cmd_open_lines(int argc
, char *argv
[])
356 void Engine::cmd_close_lines(int argc
, char *argv
[])
361 void Engine::cmd_open_eco(int argc
, char *argv
[])
363 open_openings(argv
[0]);
366 void Engine::cmd_close_eco(int argc
, char *argv
[])
371 void Engine::cmd_save(int argc
, char *argv
[])
373 FILE* f
= fopen(argv
[0],"w");
380 output("Error, could not open \"%s\" for writing.\n", argv
[0]);
384 void Engine::cmd_test(int argc
, char *argv
[])
387 for(int i
=0;i
< argc
;i
++)
388 printf(" \"%s\"", argv
[i
]);
392 void Engine::cmd_protover(int argc
, char *argv
[])
394 static const char* features
[] = {
403 "variants=\"normal\"",
404 "myname=\"RattateChess 1.1 Artin\"",
407 for(unsigned int i
=0; i
<sizeof(features
)/sizeof(const char*); i
++)
408 output("feature %s\n", features
[i
]);
411 void Engine::cmd_accepted(int argc
, char *argv
[])
413 if(0 == strcmp("san",argv
[0]))
417 void Engine::cmd_rejected(int argc
, char *argv
[])
422 void Engine::cmd_xboard(int argc
, char *argv
[])
425 signal(SIGINT
, SIG_IGN
);
428 void Engine::cmd_analyze(int argc
, char *argv
[])
430 eng_status
= ANALYZING
;
435 void Engine::cmd_exit(int argc
, char *argv
[])
437 eng_status
= FORCING
;
442 void Engine::cmd_easy(int argc
, char *argv
[])
447 void Engine::cmd_hard(int argc
, char *argv
[])
452 void Engine::cmd_post(int argc
, char *argv
[])
457 void Engine::cmd_nopost(int argc
, char *argv
[])
462 void Engine::cmd_result(int argc
, char *argv
[])
464 if(!strcmp(argv
[0], "1-0"))
466 else if(!strcmp(argv
[0], "0-1"))
468 else if(!strcmp(argv
[0], "1/2-1/2"))
471 output("Unknown result command!\n");
473 if(st_computer_color
)
475 FILE *f
= fopen("ratta.games", "a");
480 for(int i
=0;i
<argc
;i
++)
482 strcat(all_res
, argv
[i
]);
484 strcat(all_res
, " " );
486 save_pgn(f
, argv
[0], all_res
);
492 void Engine::cmd_DOT(int argc
, char *argv
[])
497 void Engine::cmd_QUESTION(int argc
, char *argv
[])
502 void Engine::cmd_name(int argc
, char *argv
[])
504 strncpy(opponent
, argv
[0], 256);
505 opponent
[255] = '\0';
508 void Engine::cmd_rating(int argc
, char *argv
[])
510 w_rating
= atoi(argv
[0]);
511 b_rating
= atoi(argv
[1]);
514 void Engine::cmd__gon(int argc
, char *argv
[])
517 output("Gui already on!\n");
519 search_gui
= new SearchGui(argc
, argv
);
522 void Engine::cmd__goff(int argc
, char *argv
[])
525 output("Gui already off!\n");
533 void Engine::cmd__check(int argc
, char *argv
[])
535 Move m
= board
.move_from_string(argv
[0]);
538 output("Not a legal move\n");
542 board
.find_other_pins();
543 if(board
.move_is_check(m
))
544 output("Yes it is a check\n");
546 output("Not a check\n");
549 void Engine::cmd__attacks(int argc
, char *argv
[])
551 uint8_t col
= argv
[1][0] == 'w' ? WHITE
: BLACK
;
552 uint8_t pos
= POS_XY(argv
[0][0]-'a', argv
[0][1]-'1' );
553 Board::AttackList al
[12];
554 int alnum
= board
.list_attackers(pos
, col
, col
== board
.color_to_move
?
555 board
.pins
: board
.oth_pins
, al
);
556 for(int i
=0;i
<alnum
;i
++)
558 static char nam
[] = { 0, 'r', 'b', 'q', 'n', 'p', 'k' };
559 for(int j
=0;j
<al
[i
].count
;j
++)
560 printf("%c ", nam
[al
[i
].piece
[j
]]);
565 void Engine::cmd__shat(int argc
, char *argv
[])
568 board
.print_attacks();
570 output("Unsupported.\n");
574 void Engine::cmd__see(int argc
, char *argv
[])
576 Move m
= board
.move_from_string(argv
[0]);
579 output("Not a legal move\n");
583 output("SEE val: %d\n", board
.move_see_val(m
));
586 void Engine::cmd__find_moves(int argc
, char *argv
[])
589 int n
= board
.find_moves(mv
);
592 output(" - %s\n", board
.move_to_alg(MoveStr().data(), mv
[i
]) );
595 void Engine::cmd__gen_hash(int argc
, char *argv
[])
597 Board::init_hash_keys( argv
[0] );
600 void Engine::cmd_set(int argc
, char *argv
[])
602 std::map
<std::string
, Variable
>::iterator it
= variables
.find(argv
[0]);
603 if(it
== variables
.end())
604 printf(" -> unknown variable '%s'!\n", argv
[0]);
607 it
->second
.from_string(argv
[1]);
608 printf(" %s -> %s\n", it
->second
.to_string(TmpStr().data()), it
->first
.c_str() );
612 void Engine::cmd_var(int argc
, char *argv
[])
615 for(VariableSet::iterator it
= variables
.begin(); it
!= variables
.end(); ++it
)
616 printf(" %s = %s\n", it
->first
.c_str(), it
->second
.to_string(TmpStr().data()) );
618 for(int i
=0;i
<argc
;i
++)
620 std::map
<std::string
, Variable
>::iterator it
= variables
.find(argv
[i
]);
621 if(it
== variables
.end())
622 printf(" -> unknown variable '%s'!\n", argv
[i
]);
624 printf(" %s = %s\n", it
->first
.c_str(), it
->second
.to_string(TmpStr().data()) );
628 void Engine::cmd_varhelp(int argc
, char *argv
[])
630 for(VariableSet::iterator it
= variables
.begin(); it
!= variables
.end(); ++it
)
632 printf(" %s = %s\n", it
->first
.c_str(), it
->second
.to_string(TmpStr().data()) );
633 print_description(4, it
->second
.desc());
637 void Engine::register_commands()
639 commands
["_see"] = Cmd( &Engine::cmd__see
, 1,
641 "Calculates the SEE value of a move\n");
642 commands
["_shat"] = Cmd( &Engine::cmd__shat
,
643 "Shows all attacks\n" );
644 commands
["_attacks"] = Cmd( &Engine::cmd__attacks
, 2,
645 "_attacks [w|b] [square|a1|a2|...]\n"
646 "Shows all attackers of a square from a color\n" );
647 commands
["_check"] = Cmd( &Engine::cmd__check
, 1 );
648 commands
["_find_moves"] = Cmd( &Engine::cmd__find_moves
);
649 commands
["_gen_hash"] = Cmd( &Engine::cmd__gen_hash
);
650 commands
["_gon"] = Cmd( &Engine::cmd__gon
);
651 commands
["_goff"] = Cmd( &Engine::cmd__goff
);
652 //commands["exit"] = Cmd( &Engine::cmd_quit );
653 commands
["quit"] = Cmd( &Engine::cmd_quit
);
654 commands
["ping"] = Cmd( &Engine::cmd_ping
, 1 );
655 commands
["bench"] = Cmd( &Engine::cmd_bench
);
656 commands
["perft"] = Cmd( &Engine::cmd_perft
, 1 );
657 commands
["perftall"] = Cmd( &Engine::cmd_perftall
, 1 );
658 commands
["sd"] = Cmd( &Engine::cmd_sd
, 1 );
659 commands
["st"] = Cmd( &Engine::cmd_st
, 1 );
660 commands
["sn"] = Cmd( &Engine::cmd_sn
, 1 );
661 commands
["otim"] = Cmd( &Engine::cmd_otim
, 1 );
662 commands
["time"] = Cmd( &Engine::cmd_time
, 1 );
663 commands
["level"] = Cmd( &Engine::cmd_level
, 3 );
664 commands
["help"] = Cmd( &Engine::cmd_help
,
665 "Printf this help\n" );
666 commands
["force"] = Cmd( &Engine::cmd_force
,
667 "Puts the engine in 'force' mode (ie edit game)\n" );
668 commands
["undo"] = Cmd( &Engine::cmd_undo
);
669 commands
["remove"] = Cmd( &Engine::cmd_remove
);
670 commands
["new"] = Cmd( &Engine::cmd_new
);
671 commands
["white"] = Cmd( &Engine::cmd_white
);
672 commands
["black"] = Cmd( &Engine::cmd_black
);
673 commands
["go"] = Cmd( &Engine::cmd_go
);
674 commands
["setboard"] = Cmd( &Engine::cmd_setboard
, 6,
675 "Sets a FEN string as the current position\n" );
676 commands
["edit"] = Cmd( &Engine::cmd_edit
,
677 "Puts the engine in (old style) position editing mode\n" );
678 commands
["load"] = Cmd( &Engine::cmd_load
, 1 );
679 commands
["load_pgn"] = Cmd( &Engine::cmd_load_pgn
, 1 );
680 commands
["epdtest"] = Cmd( &Engine::cmd_epdtest
, 3, 4,
681 "Runs an epd test with a chess program and a given time out for each\n"
682 "problem. It requires 3 arguments: the first must be an xboard program\n"
683 "path or 'self', the second the time to think in millseconds, and the\n"
684 "third is the file containing the test positions\n");
685 commands
["challenge"] = Cmd( &Engine::cmd_challenge
, 3 );
686 commands
["create_book"] = Cmd( &Engine::cmd_create_book
, 1, 2,
687 "Creates a book file using as argument the path of a PGN file with\n"
688 "a database of games, and possibly the path of a file with ECO codes.\n"
689 "See also the 'vars' command and the variables named book_creation_*,\n"
690 "that you can use to change many options\n" );
691 commands
["open_book"] = Cmd( &Engine::cmd_open_book
, 1,
692 "Loads a book file\n" );
693 commands
["close_book"] = Cmd( &Engine::cmd_close_book
,
694 "Closes the book (and make the engine use no book)\n" );
695 commands
["open_lines"] = Cmd( &Engine::cmd_open_lines
, 1,
696 "Loads a lines file (where you can select the openings to play)\n" );
697 commands
["close_lines"] = Cmd( &Engine::cmd_close_lines
,
698 "Closes the lines file (and make the engine use no lines)\n" );
699 commands
["open_eco"] = Cmd( &Engine::cmd_open_eco
, 1,
700 "Loads a eco file\n" );
701 commands
["close_eco"] = Cmd( &Engine::cmd_close_eco
,
702 "Closes the eco (and make the engine use no eco)\n" );
703 commands
["save"] = Cmd( &Engine::cmd_save
, 1 );
704 commands
["test"] = Cmd( &Engine::cmd_test
);
705 commands
["protover"] = Cmd( &Engine::cmd_protover
, 1 );
706 commands
["accepted"] = Cmd( &Engine::cmd_accepted
, 1 );
707 commands
["rejected"] = Cmd( &Engine::cmd_rejected
, 1 );
708 commands
["xboard"] = Cmd( &Engine::cmd_xboard
);
709 commands
["winboard"] = Cmd( &Engine::cmd_xboard
);
710 commands
["analyze"] = Cmd( &Engine::cmd_analyze
);
711 commands
["exit"] = Cmd( &Engine::cmd_exit
);
712 commands
["easy"] = Cmd( &Engine::cmd_easy
);
713 commands
["hard"] = Cmd( &Engine::cmd_hard
);
714 commands
["post"] = Cmd( &Engine::cmd_post
,
715 "Enables printing the thinking\n" );
716 commands
["nopost"] = Cmd( &Engine::cmd_nopost
,
717 "Disables printing the thinking\n");
718 commands
["name"] = Cmd( &Engine::cmd_name
, 1 );
719 commands
["rating"] = Cmd( &Engine::cmd_rating
, 2 );
720 commands
["result"] = Cmd( &Engine::cmd_result
, 1, 999 );
721 commands
["var"] = Cmd( &Engine::cmd_var
, 0, 999,
722 "Prints variable[s] values\n" );
723 commands
["set"] = Cmd( &Engine::cmd_set
, 2,
724 "Set variable value\n" );
725 commands
["varhelp"] = Cmd( &Engine::cmd_varhelp
,
726 "Prints variable values and with help information\n" );
727 commands
["."] = Cmd( &Engine::cmd_DOT
,
728 "Print statistics (during analysis)\n" );
729 commands
["?"] = Cmd( &Engine::cmd_QUESTION
,
730 "Move immediatly\n" );
733 void Engine::register_variables()
735 variables
["book_creation_max_depth"] = Variable( &Engine::v_book_creation_max_depth
, 28, 1, 50,
736 "Maximum depth (in ply) for selecting positions to include in the book\n");
737 variables
["book_creation_max_alternatives"] = Variable( &Engine::v_book_creation_max_alternatives
, 7, 1, INT_MAX
,
738 "Maximum number of possible moves to store in the book for each position\n");
739 variables
["book_creation_min_games"] = Variable( &Engine::v_book_creation_min_games
, 6, 1, INT_MAX
,
740 "Minimum number of games in which a position must appear to be included\n" );
741 variables
["book_creation_min_probability"] = Variable( &Engine::v_book_creation_min_probability
, 10, 0, 1000,
742 "Minimum probability that an possible move must have to be put in the book\n");
743 variables
["book_creation_weigh_win"] = Variable( &Engine::v_book_creation_weigh_win
, 3, 0, INT_MAX
,
744 "Weight for a move played in a won game (to make more likely winning moves)\n");
745 variables
["book_creation_weigh_draw"] = Variable( &Engine::v_book_creation_weigh_draw
, 2, 0, INT_MAX
,
746 "Weight for a move played in a drawn game (to make more likely winning moves)\n");
747 variables
["book_creation_weigh_lose"] = Variable( &Engine::v_book_creation_weigh_lose
, 1, 0, INT_MAX
,
748 "Weight for a move played in a lost game (to make more likely winning moves)\n");
750 variables
["search_null_reduction"] = Variable( &Engine::v_search_null_reduction
, 300, 200, 400,
751 "Reduction for null move (in ply*100)\n");
752 variables
["search_threat_extension"] = Variable( &Engine::v_search_threat_extension
, 100, 40, 120,
753 "Reduction for null move (in ply*100)\n");
754 variables
["search_threat_threshold"] = Variable( &Engine::v_search_threat_threshold
, 340, 150, 720,
755 "Reduction for null move (in ply*100)\n");
757 variables
["eval_draw"] = Variable( &Engine::v_eval_draw
, -20, 0, -100,
758 "Value of a position drawn by repetition, 50 moves rule or insufficient material\n");