#include "move.h"
#include "move_do.h"
#include "move_legal.h"
+#include "move_gen.h"
#include "option.h"
#include "parse.h"
#include "san.h"
typedef struct {
int state;
bool computer[ColourNb];
+ bool playedAllMoves[ColourNb];
int exp_move;
int hint_move;
int resign_nb;
bool has_feature_smp;
bool has_feature_egt_nalimov;
bool has_feature_egt_gaviota;
+ bool has_feature_egt_syzygy;
bool analyse;
bool computer;
const char * name;
// This is a quick hack.
XB->has_feature_egt_nalimov = (option_find(Uci->option,"NalimovPath")!=NULL);
XB->has_feature_egt_gaviota = (option_find(Uci->option,"GaviotaTbPath")!=NULL);
+ XB->has_feature_egt_syzygy = (option_find(Uci->option,"SyzygyPath")!=NULL);
XB->analyse = FALSE;
XB->computer = FALSE;
XB->name = NULL;
XB->node_rate = -1;
}
+
+static list_t move_list[1];
+
// xboard2uci_gui_step()
void xboard2uci_gui_step(char string[]) {
if (option_get_bool(Option,"Book")) {
game_get_board(Game,board);
book_disp(board);
+ } else { // [HGM] without book, print all legal moves
+ int i, gen=!list_size(move_list);
+ game_get_board(Game,board);
+ if(gen) gen_legal_moves(move_list,board);
+ for(i=0; i<list_size(move_list); i++){
+ if(gen) move_list->value[i] = 0;
+ move_to_san(move_list->move[i],board,move_string,256);
+ printf(" %s%6s\n", move_list->value[i]? "* " : "", move_string);
+ }
+ // this is necessary by the xboard protocol
+ printf("\n");
+ }
+
+ } else if (match(string,"exclude *") || match(string,"option Polyglot exclude move=*")) { // [HGM]
+
+ int i, all = !strcmp(Star[0], "all"), change=FALSE, cnt=0;
+ game_get_board(Game,board);
+ if(!list_size(move_list)) {
+ gen_legal_moves(move_list,board);
+ for(i=0; i<list_size(move_list); i++){
+ move_list->value[i] = 0;
+ }
+ }
+ move = move_from_san(Star[0],board);
+
+ for(i=0; i<list_size(move_list); i++){
+ if(all || move_list->move[i] == move)
+ change |= !move_list->value[i], move_list->value[i] = 1;
+ cnt += !move_list->value[i];
+ }
+ if(change && cnt) mess(); // do not relay to engine if no change or no moves left
+
+ } else if (match(string,"include *")) { // [HGM]
+
+ int i, all = !strcmp(Star[0], "all"), change = FALSE;
+ game_get_board(Game,board);
+ move = move_from_san(Star[0],board);
+
+ for(i=0; i<list_size(move_list); i++){
+ if(all || move_list->move[i] == move)
+ change |= move_list->value[i], move_list->value[i] = 0;
}
+ if(change) mess();
} else if (match(string,"black")) {
if(option_find(Uci->option,"UCI_DrawOffers")){
my_log("POLYGLOT draw from XB received");
uci_send_option(Uci,"DrawOffer","%s","draw");}
+ else if (option_get_bool(Option,"HandleDraws") && Uci->root_move_nb > 20) { // [HGM] PG draw handling
+ my_log("POLYGLOT draw from XB received");
+ if (Uci->best_score <= -option_get_int(Option,"ContemptScore"))
+ gui_send(GUI,"offer draw");}
} else if (match(string,"easy")) {
XB->ponder = FALSE;
game_clear(Game);
+ move_list->size = 0; // [HGM] clear all exclude moves
+
if (XB->analyse) {
State->computer[White] = FALSE;
State->computer[Black] = FALSE;
} else {
State->computer[White] = FALSE;
State->computer[Black] = TRUE;
+ State->playedAllMoves[White] = TRUE; // [HGM]
+ State->playedAllMoves[Black] = TRUE;
}
XB->new_hack = TRUE;
start_protected_command();
uci_send_option(Uci,"GaviotaTbPath","%s",path);
end_protected_command();
+ }else if(my_string_case_equal(type,"syzygy") && XB->has_feature_egt_syzygy){
+ // updating SyzygyPath
+ my_log("POLYGLOT setting the Syzygy path to %s\n",path);
+ start_protected_command();
+ uci_send_option(Uci,"SyzygyPath","%s",path);
+ end_protected_command();
}else{
// refuse
gui_send(GUI,"Error (unsupported table base format): %s",string);
if(memory>=1){
// updating the available memory
option_t *opt;
+ int h;
my_log("POLYGLOT setting the amount of memory to %dMb\n",memory);
+ egt_cache=0;
if(XB->has_feature_egt_nalimov && (opt=option_find(Uci->option,"NalimovCache"))){
- egt_cache=atoi(opt->value);
- }else if(XB->has_feature_egt_gaviota &&
+ h=atoi(opt->value);
+ if(h>egt_cache)egt_cache=h;
+ }
+ if(XB->has_feature_egt_gaviota &&
(opt=option_find(Uci->option,"GaviotaTbCache"))){
- egt_cache=atoi(opt->value);
- }else{
- egt_cache=0;
+ h=atoi(opt->value);
+ if(h>egt_cache)egt_cache=h;
}
my_log("POLYGLOT EGTB Cache is %dMb\n",egt_cache);
real_memory=memory-egt_cache;
+ opt=option_find(Uci->option,"Hash");
+ if(opt && real_memory > atoi(opt->max)) real_memory = atoi(opt->max); // [HGM] top off
if(real_memory>0){
start_protected_command();
uci_send_option(Uci,"Hash", "%d", real_memory);
if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]);
+ move_list->size = 0; // [HGM] clear all exclude moves
+
State->computer[White] = FALSE;
State->computer[Black] = FALSE;
} else if (match(string,"undo")) {
+ move_list->size = 0; // [HGM] clear all exclude moves
+
if (game_pos(Game) >= 1) {
game_goto(Game,game_pos(Game)-1);
} else if (match(string,"usermove *")) {
+ move_list->size = 0; // [HGM] clear all exclude moves
+
game_get_board(Game,board);
move = move_from_san(Star[0],board);
ASSERT(!XB->result);
XB->result = FALSE;
+ // [HGM] externally supplied move means we did not fully play the current stm
+ State->playedAllMoves[colour_is_white(game_turn(Game)) ? White : Black] = FALSE;
+
move_step(move);
no_mess(move);
}
}
+// disarm() // [HGM] cleanse a string of offending double-quotes
+
+static char*disarm(const char *s){
+ static char buf[25];
+ char *p = buf, *q;
+ strncpy(buf, s, 24);
+ q = buf + strlen(buf) - 1;
+ while(*q == '"') *q-- = '\0'; // strip trailing quotes
+ while(*p == '"') p++; // strip leading quotes
+ while((q = strchr(p, '"'))) *q = '\''; // replace internal quotes
+ return p;
+}
+
// send_xboard_options()
static void send_xboard_options(){
gui_send(GUI,"feature done=0");
gui_send(GUI,"feature analyze=1");
+ gui_send(GUI,"feature exclude=1");
gui_send(GUI,"feature colors=0");
gui_send(GUI,"feature draw=1");
gui_send(GUI,"feature ics=1");
gui_send(GUI,"feature myname=\"%s\"",
- option_get_string(Option,"EngineName"));
+ disarm(option_get_string(Option,"EngineName")));
gui_send(GUI,"feature name=1");
gui_send(GUI,"feature pause=0");
gui_send(GUI,"feature ping=1");
if(tbs>0){
strncat(egtfeature,",",StringSize-strlen(egtfeature));
}
+ tbs++;
strncat(egtfeature,"gaviota",StringSize-strlen(egtfeature));
}
+ if (XB->has_feature_egt_syzygy){
+ if(tbs>0){
+ strncat(egtfeature,",",StringSize-strlen(egtfeature));
+ }
+ strncat(egtfeature,"syzygy",StringSize-strlen(egtfeature));
+ }
strncat(egtfeature,"\"",StringSize-strlen(egtfeature));
egtfeature[StringSize-1]='\0';
gui_send(GUI,egtfeature);
if(my_string_case_equal(opt->name,"Hash")) continue;
if(my_string_case_equal(opt->name,"NalimovPath")) continue;
if(my_string_case_equal(opt->name,"GaviotaTbPath")) continue;
+ if(my_string_case_equal(opt->name,"SyzygyPath")) continue;
if((name=uci_thread_option(Uci))!=NULL &&
my_string_case_equal(opt->name,name)) continue;
format_xboard_option_line(option_line,opt);
}
+ gui_send(GUI,"feature option=\"Polyglot exclude move -string \"");
+
option_start_iter(Option);
while((opt=option_next(Option))){
if(opt->mode &XBOARD){
my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":"");
if (State->resign_nb >= option_get_int(Option,"ResignMoves")) {
- my_log("POLYGLOT *** RESIGN ***\n");
- gui_send(GUI,"resign");
+ if (!option_get_bool(Option,"QueenNeverResigns") || !board_has_queen(board, board->turn)) { // [HGM] suppress resignig with Queen
+ my_log("POLYGLOT *** RESIGN ***\n");
+ gui_send(GUI,"resign");
+ }
}
} else {
engine_send(Engine,""); // newline
} else if (State->state == ANALYSE) {
-
- engine_send(Engine,"go infinite");
+ int i;
+ char move_string[256];
+
+ engine_send_queue(Engine,"go infinite");
+
+ if(list_size(move_list)) {
+ board_t board[1];
+ game_get_board(Game,board);
+ engine_send_queue(Engine," searchmoves");
+ for(i=0; i<list_size(move_list); i++) {
+ if(!move_list->value[i]) {
+ move_to_can(move_list->move[i],board,move_string,256);
+ engine_send_queue(Engine," %s",move_string);
+ }
+ }
+ }
+ engine_send(Engine,""); // newline
} else {
}else{
min_depth=1;
}
-
+ if(!strncmp(Uci->info, "xboard ", 7)) gui_send(GUI,"%s",Uci->info+7); else // kludge to allow UCI engines to use WB protocol
gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth>min_depth?Uci->best_depth:min_depth,
- 0,0.0,0,Uci->info);
+ 0,0.0,U64(0),Uci->info);
}
// send_pv()
if(Uci->depth==-1) //hack to clear the engine output window
gui_send(GUI,"%d %+d %.0f "S64_FORMAT" ",0,report_best_score(),Uci->time*100.0,Uci->node_nb);
-
+ if(option_get_bool(Option,"ShowTbHits"))
+ gui_send(GUI,"%d %+d %.0f "S64_FORMAT" {"S64_FORMAT"} %s",Uci->best_depth,report_best_score(),Uci->time*100.0,Uci->node_nb,Uci->tbhit_nb,pv_string);
+ else
gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth,report_best_score(),Uci->time*100.0,Uci->node_nb,pv_string);
} else if (State->state == PONDER &&
ASSERT(result>=-1&&result<=+1);
ASSERT(XB->result);
- ASSERT(State->computer[White]||State->computer[Black]);
+// ASSERT(State->computer[White]||State->computer[Black]);
// init
pos = 0;
- if (FALSE) {
- } else if (State->computer[White]) {
+ // [HGM] does not account for the hypothetical possibility we played both sides!
+ if (State->playedAllMoves[White]) {
pos = 0;
- } else if (State->computer[Black]) {
+ } else if (State->playedAllMoves[Black]) {
pos = 1;
result = -result;
} else {
- my_fatal("learn(): unknown side\n");
+ return; // [HGM] if we did not play all moves for some side, do not learn, but don't make a fuss!
}
if (FALSE) {