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__tq(int argc
, char *argv
[])
534 test_quiescence(atoi(argv
[0]), atoi(argv
[1]));
536 test_quiescence(-INF
, INF
);
539 void Engine::cmd__check(int argc
, char *argv
[])
542 if(parse_move(&m
, argv
[0])!=1)
544 output("Not a legal move\n");
548 board
.find_other_pins();
549 if(board
.move_is_check(m
))
550 output("Yes it is a check\n");
552 output("Not a check\n");
555 void Engine::cmd__attacks(int argc
, char *argv
[])
557 uint8_t col
= argv
[1][0] == 'w' ? WHITE
: BLACK
;
558 uint8_t pos
= POS_XY(argv
[0][0]-'a', argv
[0][1]-'1' );
559 Board::AttackList al
[12];
560 int alnum
= board
.list_attackers(pos
, col
, col
== board
.color_to_move
?
561 board
.pins
: board
.oth_pins
, al
);
562 for(int i
=0;i
<alnum
;i
++)
564 static char nam
[] = { 0, 'r', 'b', 'q', 'n', 'p', 'k' };
565 for(int j
=0;j
<al
[i
].count
;j
++)
566 printf("%c ", nam
[al
[i
].piece
[j
]]);
571 void Engine::cmd__shat(int argc
, char *argv
[])
574 board
.print_attacks();
576 output("Unsupported.\n");
580 void Engine::cmd__see(int argc
, char *argv
[])
583 if(parse_move(&m
, argv
[0])!=1)
585 output("Not a legal move\n");
589 output("SEE val: %d\n", board
.move_see_val(m
));
592 void Engine::cmd__find_moves(int argc
, char *argv
[])
596 int n
= board
.find_moves(mv
);
599 output(" - %s\n", move_to_alg(str
, mv
+i
) );
602 void Engine::cmd__gen_hash(int argc
, char *argv
[])
604 Board::init_hash_keys( argv
[0] );
607 void Engine::cmd_var(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() );
615 void Engine::cmd_varhelp(int argc
, char *argv
[])
617 for(VariableSet::iterator it
= variables
.begin(); it
!= variables
.end(); ++it
)
619 printf(" %s = %s\n", it
->first
.c_str(), it
->second
.to_string() );
620 print_description(4, it
->second
.desc());
624 void Engine::register_commands()
626 commands
["_see"] = Cmd( &Engine::cmd__see
, 1,
628 "Calculates the SEE value of a move\n");
629 commands
["_shat"] = Cmd( &Engine::cmd__shat
,
630 "Shows all attacks\n" );
631 commands
["_attacks"] = Cmd( &Engine::cmd__attacks
, 2,
632 "_attacks [w|b] [square|a1|a2|...]\n"
633 "Shows all attackers of a square from a color\n" );
634 commands
["_check"] = Cmd( &Engine::cmd__check
, 1 );
635 commands
["_find_moves"] = Cmd( &Engine::cmd__find_moves
);
636 commands
["_gen_hash"] = Cmd( &Engine::cmd__gen_hash
);
637 commands
["_tq"] = Cmd( &Engine::cmd__tq
, 0, 2, "Test quiescence function\n" );
638 //commands["exit"] = Cmd( &Engine::cmd_quit );
639 commands
["quit"] = Cmd( &Engine::cmd_quit
);
640 commands
["ping"] = Cmd( &Engine::cmd_ping
, 1 );
641 commands
["bench"] = Cmd( &Engine::cmd_bench
);
642 commands
["perft"] = Cmd( &Engine::cmd_perft
, 1 );
643 commands
["perftall"] = Cmd( &Engine::cmd_perftall
, 1 );
644 commands
["sd"] = Cmd( &Engine::cmd_sd
, 1 );
645 commands
["st"] = Cmd( &Engine::cmd_st
, 1 );
646 commands
["sn"] = Cmd( &Engine::cmd_sn
, 1 );
647 commands
["otim"] = Cmd( &Engine::cmd_otim
, 1 );
648 commands
["time"] = Cmd( &Engine::cmd_time
, 1 );
649 commands
["level"] = Cmd( &Engine::cmd_level
, 3 );
650 commands
["help"] = Cmd( &Engine::cmd_help
,
651 "Printf this help\n" );
652 commands
["force"] = Cmd( &Engine::cmd_force
,
653 "Puts the engine in 'force' mode (ie edit game)\n" );
654 commands
["undo"] = Cmd( &Engine::cmd_undo
);
655 commands
["remove"] = Cmd( &Engine::cmd_remove
);
656 commands
["new"] = Cmd( &Engine::cmd_new
);
657 commands
["white"] = Cmd( &Engine::cmd_white
);
658 commands
["black"] = Cmd( &Engine::cmd_black
);
659 commands
["go"] = Cmd( &Engine::cmd_go
);
660 commands
["setboard"] = Cmd( &Engine::cmd_setboard
, 6,
661 "Sets a FEN string as the current position\n" );
662 commands
["edit"] = Cmd( &Engine::cmd_edit
,
663 "Puts the engine in (old style) position editing mode\n" );
664 commands
["load"] = Cmd( &Engine::cmd_load
, 1 );
665 commands
["load_pgn"] = Cmd( &Engine::cmd_load_pgn
, 1 );
666 commands
["epdtest"] = Cmd( &Engine::cmd_epdtest
, 3,
667 "Runs an epd test with a chess program and a given time out for each\n"
668 "problem. It requires 3 arguments: the first must be an xboard program\n"
669 "path or 'self', the second the time to think in millseconds, and the\n"
670 "third is the file containing the test positions\n");
671 commands
["challenge"] = Cmd( &Engine::cmd_challenge
, 3 );
672 commands
["create_book"] = Cmd( &Engine::cmd_create_book
, 1,
673 "Creates a book file using as argument the path of a PGN file with\n"
674 "a database of games. See also the 'vars' command and the variables\n"
675 "named book_creation_*, that you can use to change many parameters\n" );
676 commands
["open_book"] = Cmd( &Engine::cmd_open_book
, 1,
677 "Loads a book file\n" );
678 commands
["close_book"] = Cmd( &Engine::cmd_close_book
,
679 "Closes the book (and make the engine use no book)\n" );
680 commands
["save"] = Cmd( &Engine::cmd_save
, 1 );
681 commands
["test"] = Cmd( &Engine::cmd_test
);
682 commands
["protover"] = Cmd( &Engine::cmd_protover
, 1 );
683 commands
["accepted"] = Cmd( &Engine::cmd_accepted
, 1 );
684 commands
["rejected"] = Cmd( &Engine::cmd_rejected
, 1 );
685 commands
["xboard"] = Cmd( &Engine::cmd_xboard
);
686 commands
["winboard"] = Cmd( &Engine::cmd_xboard
);
687 commands
["analyze"] = Cmd( &Engine::cmd_analyze
);
688 commands
["exit"] = Cmd( &Engine::cmd_exit
);
689 commands
["easy"] = Cmd( &Engine::cmd_easy
);
690 commands
["hard"] = Cmd( &Engine::cmd_hard
);
691 commands
["post"] = Cmd( &Engine::cmd_post
,
692 "Enables printing the thinking\n" );
693 commands
["nopost"] = Cmd( &Engine::cmd_nopost
,
694 "Disables printing the thinking\n");
695 commands
["name"] = Cmd( &Engine::cmd_name
, 1 );
696 commands
["rating"] = Cmd( &Engine::cmd_rating
, 2 );
697 commands
["result"] = Cmd( &Engine::cmd_result
, 1, 999 );
698 commands
["var"] = Cmd( &Engine::cmd_var
,
699 "Prints variable values\n" );
700 commands
["varhelp"] = Cmd( &Engine::cmd_varhelp
,
701 "Prints variable values and with help information\n" );
702 commands
["."] = Cmd( &Engine::cmd_DOT
,
703 "Print statistics (during analysis)\n" );
704 commands
["?"] = Cmd( &Engine::cmd_QUESTION
,
705 "Move immediatly\n" );
708 void Engine::register_variables()
710 variables
["book_creation_max_depth"] = Variable( &Engine::v_book_creation_max_depth
, 28, 1, 50,
711 "Maximum depth (in ply) for selecting positions to include in the book\n");
712 variables
["book_creation_max_alternatives"] = Variable( &Engine::v_book_creation_max_alternatives
, 7, 1, INT_MAX
,
713 "Maximum number of possible moves to store in the book for each position\n");
714 variables
["book_creation_min_games"] = Variable( &Engine::v_book_creation_min_games
, 6, 1, INT_MAX
,
715 "Minimum number of games in which a position must appear to be included\n" );
716 variables
["book_creation_min_probability"] = Variable( &Engine::v_book_creation_min_probability
, 10, 0, 1000,
717 "Minimum probability that an possible move must have to be put in the book\n");
718 variables
["book_creation_weigh_win"] = Variable( &Engine::v_book_creation_weigh_win
, 3, 0, INT_MAX
,
719 "Weight for a move played in a won game (to make more likely winning moves)\n");
720 variables
["book_creation_weigh_draw"] = Variable( &Engine::v_book_creation_weigh_draw
, 2, 0, INT_MAX
,
721 "Weight for a move played in a drawn game (to make more likely winning moves)\n");
722 variables
["book_creation_weigh_lose"] = Variable( &Engine::v_book_creation_weigh_lose
, 1, 0, INT_MAX
,
723 "Weight for a move played in a lost game (to make more likely winning moves)\n");
725 variables
["search_null_reduction"] = Variable( &Engine::v_search_null_reduction
, 300, 200, 400,
726 "Reduction for null move (in ply*100)\n");
727 variables
["search_threat_extension"] = Variable( &Engine::v_search_threat_extension
, 100, 40, 120,
728 "Reduction for null move (in ply*100)\n");
729 variables
["search_threat_threshold"] = Variable( &Engine::v_search_threat_threshold
, 340, 150, 720,
730 "Reduction for null move (in ply*100)\n");
732 variables
["eval_draw"] = Variable( &Engine::v_eval_draw
, -20, 0, -100,
733 "Value of a position drawn by repetition, 50 moves rule or insufficient material\n");