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
)
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
)
50 Engine::eng()->*m_int_var
= def_val
;
53 Engine::Variable::Variable(char* (Engine::*svar
), const char* def_val
, const char *d
)
59 Engine::eng()->*m_string_var
= strdup(def_val
);
62 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, const char *d
)
71 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, void* data
, const char *d
)
80 void Engine::Variable::from_string(const char* 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
);
96 Engine::eng()->*m_int_var
= v
;
101 if(Engine::eng()->*m_string_var
)
102 free(Engine::eng()->*m_string_var
);
103 Engine::eng()->*m_string_var
= strdup(s
);
107 (Engine::eng()->*m_custom_set
)(m_custom_data
, s
);
115 char* str_printf(const char* fmt
, ...) {
119 int l
= vsnprintf(NULL
, 0, fmt
, ap
)+1;
122 char *str
= (char*)malloc(l
);
125 vsnprintf(str
, l
, fmt
, ap
);
131 const char* Engine::Variable::to_string()
139 m_buf
= str_printf("%d", Engine::eng()->*m_int_var
);
143 m_buf
= strdup(Engine::eng()->*m_string_var
);
147 m_buf
= (Engine::eng()->*m_custom_get
)(m_custom_data
);
158 static void print_description(int indent
, const char* desc
)
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
++)
173 void Engine::cmd_quit(int argc
, char *argv
[])
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]);
199 num
= board
.find_moves(mv_stack
);
201 printf("---------\n");
202 for(int i
=0;i
<num
;i
++)
206 board
.do_move(mv_stack
[i
]);
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
[])
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" );
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
[])
267 void Engine::cmd_undo(int argc
, char *argv
[])
274 void Engine::cmd_remove(int argc
, char *argv
[])
281 void Engine::cmd_new(int argc
, char *argv
[])
288 void Engine::cmd_white(int argc
, char *argv
[])
290 board
.color_to_move
= WHITE
;
291 board
.other_color
= BLACK
;
295 void Engine::cmd_black(int argc
, char *argv
[])
297 board
.color_to_move
= BLACK
;
298 board
.other_color
= WHITE
;
302 void Engine::cmd_go(int argc
, char *argv
[])
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]) );
314 void Engine::cmd_edit(int argc
, char *argv
[])
316 //output("Unimplemented!\n");
320 if(!fgets(str
, 256, stdin
))
328 void Engine::cmd_load(int argc
, char *argv
[])
330 FILE* f
= fopen(argv
[0],"r");
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");
346 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
348 st_computer_color
= 0;
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
[])
375 void Engine::cmd_close_book(int argc
, char *argv
[])
380 void Engine::cmd_save(int argc
, char *argv
[])
382 FILE* f
= fopen(argv
[0],"w");
389 output("Error, could not open \"%s\" for writing.\n", argv
[0]);
393 void Engine::cmd_test(int argc
, char *argv
[])
396 for(int i
=0;i
< argc
;i
++)
397 printf(" \"%s\"", argv
[i
]);
401 void Engine::cmd_protover(int argc
, char *argv
[])
403 static const char* features
[] = {
412 "variants=\"normal\"",
413 "myname=\"RattateChess 1.1 Artin\"",
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]))
426 void Engine::cmd_rejected(int argc
, char *argv
[])
431 void Engine::cmd_xboard(int argc
, char *argv
[])
434 signal(SIGINT
, SIG_IGN
);
437 void Engine::cmd_analyze(int argc
, char *argv
[])
439 eng_status
= ANALYZING
;
444 void Engine::cmd_exit(int argc
, char *argv
[])
446 eng_status
= FORCING
;
451 void Engine::cmd_easy(int argc
, char *argv
[])
456 void Engine::cmd_hard(int argc
, char *argv
[])
461 void Engine::cmd_post(int argc
, char *argv
[])
466 void Engine::cmd_nopost(int argc
, char *argv
[])
471 void Engine::cmd_result(int argc
, char *argv
[])
473 if(!strcmp(argv
[0], "1-0"))
475 else if(!strcmp(argv
[0], "0-1"))
477 else if(!strcmp(argv
[0], "1/2-1/2"))
480 output("Unknown result command!\n");
482 if(st_computer_color
)
484 FILE *f
= fopen("ratta.games", "a");
489 for(int i
=0;i
<argc
;i
++)
491 strcat(all_res
, argv
[i
]);
493 strcat(all_res
, " " );
495 save_pgn(f
, argv
[0], all_res
);
501 void Engine::cmd_DOT(int argc
, char *argv
[])
506 void Engine::cmd_QUESTION(int argc
, char *argv
[])
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
[])
526 output("Gui already on!\n");
528 search_gui
= new SearchGui(argc
, argv
);
531 void Engine::cmd__goff(int argc
, char *argv
[])
534 output("Gui already off!\n");
542 void Engine::cmd__check(int argc
, char *argv
[])
545 if(parse_move(&m
, argv
[0])!=1)
547 output("Not a legal move\n");
551 board
.find_other_pins();
552 if(board
.move_is_check(m
))
553 output("Yes it is a check\n");
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
]]);
574 void Engine::cmd__shat(int argc
, char *argv
[])
577 board
.print_attacks();
579 output("Unsupported.\n");
583 void Engine::cmd__see(int argc
, char *argv
[])
586 if(parse_move(&m
, argv
[0])!=1)
588 output("Not a legal move\n");
592 output("SEE val: %d\n", board
.move_see_val(m
));
595 void Engine::cmd__find_moves(int argc
, char *argv
[])
599 int n
= board
.find_moves(mv
);
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,
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");