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 ***************************************************************************/
25 void Engine::Cmd::run(int argc
, char *argv
[])
27 (Engine::eng()->*m_func
)(argc
, argv
);
30 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
)
49 Engine::eng()->*m_int_var
= def_val
;
52 Engine::Variable::Variable(char* (Engine::*svar
), const char* def_val
, const char *d
)
58 Engine::eng()->*m_string_var
= strdup(def_val
);
61 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, const char *d
)
70 Engine::Variable::Variable(VarSetFunc set
, VarGetFunc get
, void* data
, const char *d
)
79 void Engine::Variable::from_string(const char* s
)
92 if(v
< m_range_min
|| v
> m_range_max
)
93 printf("Error! value %d out of range (%d-%d)\n", v
, m_range_min
, m_range_max
);
95 Engine::eng()->*m_int_var
= v
;
100 if(Engine::eng()->*m_string_var
)
101 free(Engine::eng()->*m_string_var
);
102 Engine::eng()->*m_string_var
= strdup(s
);
106 (Engine::eng()->*m_custom_set
)(m_custom_data
, s
);
114 char* str_printf(const char* fmt
, ...) {
118 int l
= vsnprintf(NULL
, 0, fmt
, ap
)+1;
121 char *str
= (char*)malloc(l
);
124 vsnprintf(str
, l
, fmt
, ap
);
130 const char* Engine::Variable::to_string()
138 m_buf
= str_printf("%d", Engine::eng()->*m_int_var
);
142 m_buf
= strdup(Engine::eng()->*m_string_var
);
146 m_buf
= (Engine::eng()->*m_custom_get
)(m_custom_data
);
157 static void print_description(int indent
, const char* desc
)
161 for(int i
=0;i
<indent
;i
++)
162 fwrite(" ", 1, 1, stdout
);
163 printf("<No description>\n\n");
169 int l
= strcspn(desc
, "\n");
170 l
+= strspn(desc
+l
, "\n");
173 for(int i
=0;i
<indent
;i
++)
174 fwrite(" ", 1, 1, stdout
);
175 fwrite(desc
, 1, l
, stdout
);
178 fwrite("\n", 1, 1, stdout
);
181 void Engine::cmd_quit(int argc
, char *argv
[])
186 void Engine::cmd_ping(int argc
, char *argv
[])
188 printf("pong %s\n",argv
[0]);
191 void Engine::cmd_bench(int argc
, char *argv
[])
195 void Engine::cmd_perft(int argc
, char *argv
[])
197 int t
= current_time();
198 uint64_t p
= perft( atoi(argv
[0]) );
199 printf("%lld (time %.02f)\n", (long long)p
, (current_time()-t
)*0.01 );
202 void Engine::cmd_perftall(int argc
, char *argv
[])
204 int lev
= atoi(argv
[0]);
207 num
= board
.find_moves(mv_stack
);
209 printf("---------\n");
210 for(int i
=0;i
<num
;i
++)
214 board
.do_move(mv_stack
[i
]);
216 board
.undo_move(mv_stack
[i
]);
217 printf("%s: %d\n", move_to_alg(buf
, &mv_stack
[i
]), p
);
219 printf("---------\n");
222 void Engine::cmd_sd(int argc
, char *argv
[])
224 set_depth( atoi(argv
[0]) );
227 void Engine::cmd_st(int argc
, char *argv
[])
229 set_time_fixed( atoi(argv
[0]) );
232 void Engine::cmd_sn(int argc
, char *argv
[])
234 set_max_nodes( atoi(argv
[0]) );
237 void Engine::cmd_otim(int argc
, char *argv
[])
239 set_other_clock( atoi(argv
[0]) );
242 void Engine::cmd_time(int argc
, char *argv
[])
244 set_my_clock( atoi(argv
[0]) );
247 void Engine::cmd_level(int argc
, char *argv
[])
250 sscanf(argv
[1],"%d:%d",&basem
,&bases
);
252 set_time_control( atoi(argv
[0]) ,basem
*60+bases
, atoi(argv
[2]) );
255 void Engine::cmd_help(int argc
, char *argv
[])
257 for(CmdSet::iterator it
= commands
.begin(); it
!= commands
.end(); ++it
)
259 if(!it
->second
.max())
260 printf(" %s\n", it
->first
.c_str() );
261 else if(it
->second
.min() == it
->second
.max())
262 printf(" %s (%d %s)\n", it
->first
.c_str(), it
->second
.min(), it
->second
.min()==1?"arg":"args" );
264 printf(" %s (%d-%d args)\n", it
->first
.c_str(), it
->second
.min(), it
->second
.max() );
266 print_description(4, it
->second
.desc());
270 void Engine::cmd_force(int argc
, char *argv
[])
275 void Engine::cmd_undo(int argc
, char *argv
[])
282 void Engine::cmd_remove(int argc
, char *argv
[])
289 void Engine::cmd_new(int argc
, char *argv
[])
296 void Engine::cmd_white(int argc
, char *argv
[])
298 board
.color_to_move
= WHITE
;
299 board
.other_color
= BLACK
;
303 void Engine::cmd_black(int argc
, char *argv
[])
305 board
.color_to_move
= BLACK
;
306 board
.other_color
= WHITE
;
310 void Engine::cmd_go(int argc
, char *argv
[])
315 void Engine::cmd_setboard(int argc
, char *argv
[])
317 read_board(argv
[0], argv
[1], argv
[2], argv
[3], atoi(argv
[4]), atoi(argv
[5]) );
322 void Engine::cmd_edit(int argc
, char *argv
[])
324 //output("Unimplemented!\n");
328 if(!fgets(str
, 256, stdin
))
336 void Engine::cmd_load(int argc
, char *argv
[])
338 FILE* f
= fopen(argv
[0],"r");
347 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
350 void Engine::cmd_load_pgn(int argc
, char *argv
[])
352 FILE* f
= fopen(argv
[0],"r");
354 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
356 st_computer_color
= 0;
363 void Engine::cmd_epdtest(int argc
, char *argv
[])
365 run_epd_prog(argv
[0], atoi(argv
[1]), argv
[2]);
368 void Engine::cmd_challenge(int argc
, char *argv
[])
370 challenge(argv
[0], atoi(argv
[1]), argv
[2]);
373 void Engine::cmd_create_book(int argc
, char *argv
[])
375 create_book(argc
, argv
);
378 void Engine::cmd_open_book(int argc
, char *argv
[])
383 void Engine::cmd_close_book(int argc
, char *argv
[])
388 void Engine::cmd_save(int argc
, char *argv
[])
390 FILE* f
= fopen(argv
[0],"w");
397 output("Error, could not open \"%s\" for writing.\n", argv
[0]);
401 void Engine::cmd_test(int argc
, char *argv
[])
404 for(int i
=0;i
< argc
;i
++)
405 printf(" \"%s\"", argv
[i
]);
409 void Engine::cmd_protover(int argc
, char *argv
[])
411 static const char* features
[] = {
420 "variants=\"normal\"",
421 "myname=\"RattateChess 1.0-rc1 Bologna 2007\"",
424 for(unsigned int i
=0; i
<sizeof(features
)/sizeof(const char*); i
++)
425 output("feature %s\n", features
[i
]);
428 void Engine::cmd_accepted(int argc
, char *argv
[])
430 if(0 == strcmp("san",argv
[0]))
434 void Engine::cmd_rejected(int argc
, char *argv
[])
439 void Engine::cmd_xboard(int argc
, char *argv
[])
442 signal(SIGINT
, SIG_IGN
);
445 void Engine::cmd_analyze(int argc
, char *argv
[])
447 eng_status
= ANALYZING
;
452 void Engine::cmd_exit(int argc
, char *argv
[])
454 eng_status
= FORCING
;
459 void Engine::cmd_easy(int argc
, char *argv
[])
464 void Engine::cmd_hard(int argc
, char *argv
[])
469 void Engine::cmd_post(int argc
, char *argv
[])
474 void Engine::cmd_nopost(int argc
, char *argv
[])
479 void Engine::cmd_result(int argc
, char *argv
[])
481 if(!strcmp(argv
[0], "1-0"))
483 else if(!strcmp(argv
[0], "0-1"))
485 else if(!strcmp(argv
[0], "1/2-1/2"))
488 output("Unknown result command!\n");
490 if(st_computer_color
)
492 FILE *f
= fopen("ratta.games", "a");
497 for(int i
=0;i
<argc
;i
++)
499 strcat(all_res
, argv
[i
]);
501 strcat(all_res
, " " );
503 save_pgn(f
, argv
[0], all_res
);
509 void Engine::cmd_DOT(int argc
, char *argv
[])
514 void Engine::cmd_QUESTION(int argc
, char *argv
[])
519 void Engine::cmd_name(int argc
, char *argv
[])
521 strncpy(opponent
, argv
[0], 256);
522 opponent
[255] = '\0';
525 void Engine::cmd_rating(int argc
, char *argv
[])
527 w_rating
= atoi(argv
[0]);
528 b_rating
= atoi(argv
[1]);
531 void Engine::cmd__check(int argc
, char *argv
[])
534 if(parse_move(&m
, argv
[0])!=1)
536 output("Not a legal move\n");
540 board
.find_other_pins();
541 if(board
.move_is_check(m
))
542 output("Yes it is a check\n");
544 output("Not a check\n");
547 void Engine::cmd__attacks(int argc
, char *argv
[])
549 uint8_t col
= argv
[1][0] == 'w' ? WHITE
: BLACK
;
550 uint8_t pos
= POS_XY(argv
[0][0]-'a', argv
[0][1]-'1' );
551 Board::AttackList al
[12];
552 int alnum
= board
.list_attackers(pos
, col
, col
== board
.color_to_move
?
553 board
.pins
: board
.oth_pins
, al
);
554 for(int i
=0;i
<alnum
;i
++)
556 static char nam
[] = { 0, 'r', 'b', 'q', 'n', 'p', 'k' };
557 for(int j
=0;j
<al
[i
].count
;j
++)
558 printf("%c ", nam
[al
[i
].piece
[j
]]);
563 void Engine::cmd__shat(int argc
, char *argv
[])
566 board
.print_attacks();
568 output("Unsupported.\n");
572 void Engine::cmd__see(int argc
, char *argv
[])
575 if(parse_move(&m
, argv
[0])!=1)
577 output("Not a legal move\n");
581 output("SEE val: %d\n", board
.move_see_val(m
));
584 void Engine::cmd__find_moves(int argc
, char *argv
[])
588 int n
= board
.find_moves(mv
);
591 output(" - %s\n", move_to_alg(str
, mv
+i
) );
594 void Engine::cmd__gen_hash(int argc
, char *argv
[])
596 Board::init_hash_keys( argv
[0] );
599 void Engine::cmd_var(int argc
, char *argv
[])
601 for(VariableSet::iterator it
= variables
.begin(); it
!= variables
.end(); ++it
)
603 printf(" %s = %s\n", it
->first
.c_str(), it
->second
.to_string() );
607 void Engine::cmd_varhelp(int argc
, char *argv
[])
609 for(VariableSet::iterator it
= variables
.begin(); it
!= variables
.end(); ++it
)
611 printf(" %s = %s\n", it
->first
.c_str(), it
->second
.to_string() );
612 print_description(4, it
->second
.desc());
616 void Engine::register_commands()
618 commands
["_see"] = Cmd( &Engine::cmd__see
, 1,
620 "Calculates the SEE value of a move\n");
621 commands
["_shat"] = Cmd( &Engine::cmd__shat
,
622 "Shows all attacks\n" );
623 commands
["_attacks"] = Cmd( &Engine::cmd__attacks
, 2,
624 "_attacks [w|b] [square|a1|a2|...]\n"
625 "Shows all attackers of a square from a color\n" );
626 commands
["_check"] = Cmd( &Engine::cmd__check
, 1 );
627 commands
["_find_moves"] = Cmd( &Engine::cmd__find_moves
);
628 commands
["_gen_hash"] = Cmd( &Engine::cmd__gen_hash
);
629 //commands["exit"] = Cmd( &Engine::cmd_quit );
630 commands
["quit"] = Cmd( &Engine::cmd_quit
);
631 commands
["ping"] = Cmd( &Engine::cmd_ping
, 1 );
632 commands
["bench"] = Cmd( &Engine::cmd_bench
);
633 commands
["perft"] = Cmd( &Engine::cmd_perft
, 1 );
634 commands
["perftall"] = Cmd( &Engine::cmd_perftall
, 1 );
635 commands
["sd"] = Cmd( &Engine::cmd_sd
, 1 );
636 commands
["st"] = Cmd( &Engine::cmd_st
, 1 );
637 commands
["sn"] = Cmd( &Engine::cmd_sn
, 1 );
638 commands
["otim"] = Cmd( &Engine::cmd_otim
, 1 );
639 commands
["time"] = Cmd( &Engine::cmd_time
, 1 );
640 commands
["level"] = Cmd( &Engine::cmd_level
, 3 );
641 commands
["help"] = Cmd( &Engine::cmd_help
,
642 "Printf this help\n" );
643 commands
["force"] = Cmd( &Engine::cmd_force
,
644 "Puts the engine in 'force' mode (ie edit game)\n" );
645 commands
["undo"] = Cmd( &Engine::cmd_undo
);
646 commands
["remove"] = Cmd( &Engine::cmd_remove
);
647 commands
["new"] = Cmd( &Engine::cmd_new
);
648 commands
["white"] = Cmd( &Engine::cmd_white
);
649 commands
["black"] = Cmd( &Engine::cmd_black
);
650 commands
["go"] = Cmd( &Engine::cmd_go
);
651 commands
["setboard"] = Cmd( &Engine::cmd_setboard
, 6,
652 "Sets a FEN string as the current position\n" );
653 commands
["edit"] = Cmd( &Engine::cmd_edit
,
654 "Puts the engine in (old style) position editing mode\n" );
655 commands
["load"] = Cmd( &Engine::cmd_load
, 1 );
656 commands
["load_pgn"] = Cmd( &Engine::cmd_load_pgn
, 1 );
657 commands
["epdtest"] = Cmd( &Engine::cmd_epdtest
, 3,
658 "Runs an epd test with a chess program and a given time out for each\n"
659 "problem. It requires 3 arguments: the first must be an xboard program\n"
660 "path or 'self', the second the time to think in millseconds, and the\n"
661 "third is the file containing the test positions\n");
662 commands
["challenge"] = Cmd( &Engine::cmd_challenge
, 3 );
663 commands
["create_book"] = Cmd( &Engine::cmd_create_book
, 1,
664 "Creates a book file using as argument the path of a PGN file with\n"
665 "a database of games. See also the 'vars' command and the variables\n"
666 "named book_creation_*, that you can use to change many parameters\n" );
667 commands
["open_book"] = Cmd( &Engine::cmd_open_book
, 1,
668 "Loads a book file\n" );
669 commands
["close_book"] = Cmd( &Engine::cmd_close_book
,
670 "Closes the book (and make the engine use no book)\n" );
671 commands
["save"] = Cmd( &Engine::cmd_save
, 1 );
672 commands
["test"] = Cmd( &Engine::cmd_test
);
673 commands
["protover"] = Cmd( &Engine::cmd_protover
, 1 );
674 commands
["accepted"] = Cmd( &Engine::cmd_accepted
, 1 );
675 commands
["rejected"] = Cmd( &Engine::cmd_rejected
, 1 );
676 commands
["xboard"] = Cmd( &Engine::cmd_xboard
);
677 commands
["winboard"] = Cmd( &Engine::cmd_xboard
);
678 commands
["analyze"] = Cmd( &Engine::cmd_analyze
);
679 commands
["exit"] = Cmd( &Engine::cmd_exit
);
680 commands
["easy"] = Cmd( &Engine::cmd_easy
);
681 commands
["hard"] = Cmd( &Engine::cmd_hard
);
682 commands
["post"] = Cmd( &Engine::cmd_post
,
683 "Enables printing the thinking\n" );
684 commands
["nopost"] = Cmd( &Engine::cmd_nopost
,
685 "Disables printing the thinking\n");
686 commands
["name"] = Cmd( &Engine::cmd_name
, 1 );
687 commands
["rating"] = Cmd( &Engine::cmd_rating
, 2 );
688 commands
["result"] = Cmd( &Engine::cmd_result
, 1, 999 );
689 commands
["var"] = Cmd( &Engine::cmd_var
,
690 "Prints variable values\n" );
691 commands
["varhelp"] = Cmd( &Engine::cmd_varhelp
,
692 "Prints variable values and with help information\n" );
693 commands
["."] = Cmd( &Engine::cmd_DOT
,
694 "Print statistics (during analysis)\n" );
695 commands
["?"] = Cmd( &Engine::cmd_QUESTION
,
696 "Move immediatly\n" );
699 void Engine::register_variables()
701 variables
["book_creation_max_depth"] = Variable( &Engine::v_book_creation_max_depth
, 28, 1, 50,
702 "Maximum depth (in ply) for selecting positions to include in the book\n");
703 variables
["book_creation_max_alternatives"] = Variable( &Engine::v_book_creation_max_alternatives
, 7, 1, INT_MAX
,
704 "Maximum number of possible moves to store in the book for each position\n");
705 variables
["book_creation_min_games"] = Variable( &Engine::v_book_creation_min_games
, 6, 1, INT_MAX
,
706 "Minimum number of games in which a position must appear to be included\n" );
707 variables
["book_creation_min_probability"] = Variable( &Engine::v_book_creation_min_probability
, 10, 0, 1000,
708 "Minimum probability that an possible move must have to be put in the book\n");
709 variables
["book_creation_weigh_win"] = Variable( &Engine::v_book_creation_weigh_win
, 3, 0, INT_MAX
,
710 "Weight for a move played in a won game (to make more likely winning moves)\n");
711 variables
["book_creation_weigh_draw"] = Variable( &Engine::v_book_creation_weigh_draw
, 2, 0, INT_MAX
,
712 "Weight for a move played in a drawn game (to make more likely winning moves)\n");
713 variables
["book_creation_weigh_lose"] = Variable( &Engine::v_book_creation_weigh_lose
, 1, 0, INT_MAX
,
714 "Weight for a move played in a lost game (to make more likely winning moves)\n");
716 variables
["search_null_reduction"] = Variable( &Engine::v_search_null_reduction
, 300, 200, 400,
717 "Reduction for null move (in ply*100)\n");
718 variables
["search_threat_extension"] = Variable( &Engine::v_search_threat_extension
, 100, 40, 120,
719 "Reduction for null move (in ply*100)\n");
720 variables
["search_threat_threshold"] = Variable( &Engine::v_search_threat_threshold
, 340, 150, 720,
721 "Reduction for null move (in ply*100)\n");
723 variables
["eval_draw"] = Variable( &Engine::v_eval_draw
, -20, 0, -100,
724 "Value of a position drawn by repetition, 50 moves rule or insufficient material\n");