示例#1
0
static void end_protected_command(){
    if(Uci->ready){ // not init faze
        uci_send_isready_sync(Uci); // gobble up spurious "bestmove"
    }
    update_remaining_time();
    search_update();   // relaunch search if necessary
}
示例#2
0
void xboard2uci_gui_step(char string[]) {

	int move;
	char move_string[256];
	board_t board[1];

		if (FALSE) {
         
		} else if (match(string,"accepted *")) {

			// ignore

		} else if (match(string,"analyze")) {

			State->computer[White] = FALSE;
			State->computer[Black] = FALSE;

			XB->analyse = TRUE;
			XB->new_hack = FALSE;
			ASSERT(!XB->result);
			XB->result = FALSE;

			mess();

		} else if (match(string,"bk")) {

			if (option_get_bool(Option,"Book")) {
				game_get_board(Game,board);
				book_disp(board);
			}

		} else if (match(string,"black")) {

			if (colour_is_black(game_turn(Game))) {

				State->computer[White] = TRUE;
				State->computer[Black] = FALSE;

				XB->new_hack = TRUE;
				XB->result = FALSE;

				mess();
			}

		} else if (match(string,"computer")) {

			XB->computer = TRUE;

		} else if (match(string,"draw")) {
			if(option_find(Uci->option,"UCI_DrawOffers")){
			    my_log("POLYGLOT draw from XB received");
				uci_send_option(Uci,"DrawOffer","%s","draw");}
		} else if (match(string,"easy")) {

			XB->ponder = FALSE;

			mess();

		} else if (match(string,"edit")) {

			// refuse

			gui_send(GUI,"Error (unknown command): %s",string);

		} else if (match(string,"exit")) {

			State->computer[White] = FALSE;
			State->computer[Black] = FALSE;

			XB->analyse = FALSE;

			mess();

		} else if (match(string,"force")) {

			State->computer[White] = FALSE;
			State->computer[Black] = FALSE;

			mess();

		} else if (match(string,"go")) {

			State->computer[game_turn(Game)] = TRUE;
			State->computer[colour_opp(game_turn(Game))] = FALSE;

			XB->new_hack = FALSE;
			ASSERT(!XB->result);
			XB->result = FALSE;

			mess();

		} else if (match(string,"hard")) {

			XB->ponder = TRUE;

			mess();

		} else if (match(string,"hint")) {
		    
		        move=MoveNone;
			game_get_board(Game,board);
			if (option_get_bool(Option,"Book")) {

				move = book_move(board,FALSE);
			}
			if(move==MoveNone && State->hint_move!=MoveNone){
			    move=State->hint_move;
			    
			}
			if (move != MoveNone && move_is_legal(move,board)) {
			    move_to_san(move,board,move_string,256);
			    gui_send(GUI,"Hint: %s",move_string);
			}

		} else if (match(string,"ics *")) {

			XB->ics = TRUE;

		} else if (match(string,"level * *:* *")) {

			XB->mps  = atoi(Star[0]);
			XB->base = ((double)atoi(Star[1])) * 60.0 + ((double)atoi(Star[2]));
			XB->inc  = ((double)atoi(Star[3]));

		} else if (match(string,"level * * *")) {

			XB->mps  = atoi(Star[0]);
			XB->base = ((double)atoi(Star[1])) * 60.0;
			XB->inc  = ((double)atoi(Star[2]));

		} else if (match(string,"name *")) {

			my_string_set(&XB->name,Star[0]);

		} else if (match(string,"new")) {

		    uci_send_isready_sync(Uci);
			my_log("POLYGLOT NEW GAME\n");

			option_set(Option,"3Check","false");
			option_set(Option,"Chess960","false");
			option_set(Option,"Atomic","false");
			option_set(Option,"Horde","false");

			game_clear(Game);

			if (XB->analyse) {
				State->computer[White] = FALSE;
				State->computer[Black] = FALSE;
			} else {
				State->computer[White] = FALSE;
				State->computer[Black] = TRUE;
			}

			XB->new_hack = TRUE;
			XB->result = FALSE;

			XB->depth_limit = FALSE;
            XB->node_rate=-1;

			XB->computer = FALSE;
			my_string_set(&XB->name,"<empty>");

			board_update();
			mess();

			uci_send_ucinewgame(Uci);

		} else if (match(string,"nopost")) {

			XB->post = FALSE;

		} else if (match(string,"otim *")) {

			XB->opp_time = ((double)atoi(Star[0])) / 100.0;
			if (XB->opp_time < 0.0) XB->opp_time = 0.0;

		} else if (match(string,"pause")) {

			// refuse

			gui_send(GUI,"Error (unknown command): %s",string);

		} else if (match(string,"ping *")) {

			// HACK; TODO: answer only after an engine move

			if (DelayPong) {
				if (XB->ping >= 0) gui_send(GUI,"pong %d",XB->ping); // HACK: get rid of old ping
				XB->ping = atoi(Star[0]);
				uci_send_isready_sync(Uci);
			} else {
				ASSERT(XB->ping==-1);
				gui_send(GUI,"pong %s",Star[0]);
			}
        } else if (match(string,"nps *")) {
            
                // fake WB play-by-nodes mode
            XB->node_rate = atoi(Star[0]);
		} else if (match(string,"playother")) {

			State->computer[game_turn(Game)] = FALSE;
			State->computer[colour_opp(game_turn(Game))] = TRUE;

			XB->new_hack = FALSE;
			ASSERT(!XB->result);
			XB->result = FALSE;

			mess();

		} else if (match(string,"post")) {

			XB->post = TRUE;

		} else if (match(string,"protover *")) {
            XB->proto_ver = atoi(Star[0]);
            ASSERT(XB->proto_ver>=2);
            send_xboard_options();

		} else if (match(string,"quit")) {
			my_log("POLYGLOT *** \"quit\" from GUI ***\n");
			quit();
		} else if (match(string,"random")) {

			// ignore

		} else if (match(string,"rating * *")) {

			// ignore

		} else if (match(string,"remove")) {

			if (game_pos(Game) >= 2) {

				game_goto(Game,game_pos(Game)-2);

				ASSERT(!XB->new_hack);
				XB->new_hack = FALSE; // HACK?
				XB->result = FALSE;

				board_update();
				mess();
			}

		} else if (match(string,"rejected *")) {

			// ignore

		} else if (match(string,"reset")) { // protover 3?

			// refuse

			gui_send(GUI,"Error (unknown command): %s",string);

		} else if (FALSE
			|| match(string,"result * {*}")
			|| match(string,"result * {* }")
			|| match(string,"result * { *}")
			|| match(string,"result * { * }")) {

				my_log("POLYGLOT GAME END\n");

				XB->result = TRUE;

				mess();

				// book learning

				if (FALSE && option_get_bool(Option,"Book") &&
                    option_get_bool(Option,"BookLearn")) {

					if (FALSE) {
					} else if (my_string_equal(Star[0],"1-0")) {
						learn(+1);
					} else if (my_string_equal(Star[0],"0-1")) {
						learn(-1);
					} else if (my_string_equal(Star[0],"1/2-1/2")) {
						learn(0);
					}
				}
		} else if (match(string,"resume")) {

			// refuse

			gui_send(GUI,"Error (unknown command): %s",string);

        } else if (match(string,"option *=*")   ||
                   match(string,"option * =*") ||
                   match(string,"option *= *") ||
                   match(string,"option * = *")
                   ){
            char *name=Star[0];
            char *value=Star[1];
            if(match(name, "Polyglot *")){
                char *pg_name=Star[0];
                polyglot_set_option(pg_name,value);
            }else{
                option_t *opt=option_find(Uci->option,name);
                if(opt){
                    if(my_string_case_equal(opt->type,"check")){
                       value=my_string_equal(value,"1")?"true":"false";
                    }
                    start_protected_command();
                    uci_send_option(Uci, name, "%s", value);
                    end_protected_command();
                }else{
                    gui_send(GUI,"Error (unknown option): %s",name); 
                }
            }
        } else if (match(string,"option *")){
            char *name=Star[0];
             if(match(name, "Polyglot *")){
                char *pg_name=Star[0];
                polyglot_set_option(pg_name,"<empty>");
	     }else{           
	       start_protected_command();
                // value is ignored
	       if(!uci_send_option(Uci, name, "%s", "<empty>")){
		 gui_send(GUI,"Error (unknown option): %s",name); 
	       }; 
	       end_protected_command();
	     }
        } else if (XB->has_feature_smp && match(string,"cores *")){
                int cores=atoi(Star[0]);
                if(cores>=1){
                    // updating the number of cores
                    my_log("POLYGLOT setting the number of cores to %d\n",cores);
                    start_protected_command();
                    uci_set_threads(Uci,cores); 
                    end_protected_command();
                } else{
                   // refuse
                    gui_send(GUI,"Error (unknown command): %s",string);
                }
        } else if (match(string,"egtpath * *")){
                char *type=Star[0];
                char *path=Star[1];
                if(my_string_empty(path)){
                    // refuse
                    gui_send(GUI,"Error (unknown command): %s",string);
                }else{
		    if(my_string_case_equal(type,"nalimov") && XB->has_feature_egt_nalimov){
			// updating NalimovPath
			my_log("POLYGLOT setting the Nalimov path to %s\n",path);
			start_protected_command();
			uci_send_option(Uci,"NalimovPath","%s",path);
			end_protected_command();
		    }else if(my_string_case_equal(type,"gaviota") && XB->has_feature_egt_gaviota){
			// updating GaviotaPath
			my_log("POLYGLOT setting the Gaviota path to %s\n",path);
			start_protected_command();
			uci_send_option(Uci,"GaviotaTbPath","%s",path);
			end_protected_command();
		    }else{
			// refuse
			gui_send(GUI,"Error (unsupported table base format): %s",string);
		    }
                }
        } else if (XB->has_feature_memory && match(string,"memory *")){
            int memory = atoi(Star[0]);
            int egt_cache;
            int real_memory;
            if(memory>=1){
                // updating the available memory
                option_t *opt;
                my_log("POLYGLOT setting the amount of memory to %dMb\n",memory);
                if(XB->has_feature_egt_nalimov && (opt=option_find(Uci->option,"NalimovCache"))){
                    egt_cache=atoi(opt->value);
                }else if(XB->has_feature_egt_gaviota && 
			 (opt=option_find(Uci->option,"GaviotaTbCache"))){
		    egt_cache=atoi(opt->value);
		}else{
                    egt_cache=0;
                }
                my_log("POLYGLOT EGTB Cache is %dMb\n",egt_cache);
                real_memory=memory-egt_cache;
                if(real_memory>0){
                    start_protected_command();
                    uci_send_option(Uci,"Hash", "%d", real_memory);
                    end_protected_command();
                }
            }else{
                // refuse
                gui_send(GUI,"Error (unknown command): %s",string);
            }

		} else if (match(string,"sd *")) {

			XB->depth_limit = TRUE;
			XB->depth_max = atoi(Star[0]);

		} else if (match(string,"setboard *")) {

			my_log("POLYGLOT FEN %s\n",Star[0]);

			if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]);

			State->computer[White] = FALSE;
			State->computer[Black] = FALSE;

			XB->new_hack = TRUE; // HACK?
			XB->result = FALSE;

			board_update();
			mess();

		} else if (match(string,"st *")) {

			XB->time_limit = TRUE;
			XB->time_max = ((double)atoi(Star[0]));

		} else if (match(string,"time *")) {

			XB->my_time = ((double)atoi(Star[0])) / 100.0;
			if (XB->my_time < 0.0) XB->my_time = 0.0;

		} else if (match(string,"undo")) {

			if (game_pos(Game) >= 1) {

				game_goto(Game,game_pos(Game)-1);

				ASSERT(!XB->new_hack);
				XB->new_hack = FALSE; // HACK?
				XB->result = FALSE;

				board_update();
				mess();
			}

		} else if (match(string,"usermove *")) {

			game_get_board(Game,board);
			move = move_from_san(Star[0],board);

			if (move != MoveNone && move_is_legal(move,board)) {

				XB->new_hack = FALSE;
				ASSERT(!XB->result);
				XB->result = FALSE;

				move_step(move);
				no_mess(move);

			} else {

				gui_send(GUI,"Illegal move: %s",Star[0]);
			}

		} else if (match(string,"variant *")) {

			if (my_string_equal(Star[0],"3check")) {
				option_set(Option,"3Check","true");
			} else {
				option_set(Option,"3Check","false");
			}
			if (my_string_equal(Star[0],"fischerandom")) {
				option_set(Option,"Chess960","true");
			} else {
				option_set(Option,"Chess960","false");
			}
			if (my_string_equal(Star[0],"atomic")) {
				option_set(Option,"Atomic","true");
			} else {
				option_set(Option,"Atomic","false");
			}
			if (my_string_equal(Star[0],"horde")) {
				option_set(Option,"Horde","true");
				game_init(Game,StartFenHorde);
				//gui_send(GUI,"setup %s",StartFenHorde);
			} else {
				option_set(Option,"Horde","false");
			}

		} else if (match(string,"white")) {

			if (colour_is_white(game_turn(Game))) {

				State->computer[White] = FALSE;
				State->computer[Black] = TRUE;

				XB->new_hack = TRUE;
				XB->result = FALSE;

				mess();
			}

		} else if (match(string,"xboard")) {

			// ignore

		} else if (match(string,".")) { // analyse info

			if (State->state == ANALYSE) {
				int depth=Uci->best_depth;//HACK: don't clear engine-output window...

				ASSERT(Uci->searching);
				ASSERT(Uci->pending_nb>=1);

				if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) {
					move_to_san(Uci->root_move,Uci->board,move_string,256);
					gui_send(GUI,"stat01: %.0f "S64_FORMAT" %d %d %d %s",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,Uci->root_move_nb-(Uci->root_move_pos+1),Uci->root_move_nb,move_string);
				} else {
					gui_send(GUI,"stat01: %.0f "S64_FORMAT" %d %d %d",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,0,0); // HACK
				}
			}

		} else if (match(string,"?")) { // move now

			if (State->state == THINK) {

				ASSERT(Uci->searching);
				ASSERT(Uci->pending_nb>=1);

				// HACK: just send "stop" to the engine

				if (Uci->searching) {
					my_log("POLYGLOT STOP SEARCH\n");
					engine_send(Engine,"stop");
				}
			}

		} else { // unknown command, maybe a move?

			game_get_board(Game,board);
			move = move_from_san(string,board);

			if (move != MoveNone && move_is_legal(move,board)) {

				XB->new_hack = FALSE;
				ASSERT(!XB->result);
				XB->result = FALSE;

				move_step(move);
				no_mess(move);

			} else if (move != MoveNone) {

				gui_send(GUI,"Illegal move: %s",string);

			} else {

				gui_send(GUI,"Error (unknown command): %s",string);
			}
		}
	return;
}
示例#3
0
void search(const board_t * board, int depth_max, double time_max) {

   char string[256];

   ASSERT(board_is_ok(board));
   ASSERT(depth_max>=1&&depth_max<DepthMax);
   ASSERT(time_max>=0.0);

   // engine

   Depth = 0;

   BestMove = MoveNone;
   BestValue = 0;
   line_clear(BestPV);

   NodeNb = 0;
   LeafNb = 0;
   Time = 0.0;

   Move = MoveNone;
   MovePos = 0;
   MoveNb = 0;

   // init

   uci_send_ucinewgame(Uci);
   uci_send_isready_sync(Uci);

   // position

   if (!board_to_fen(board,string,256)) ASSERT(false);
   engine_send(Engine,"position fen %s",string);

   // search

   engine_send_queue(Engine,"go");

   engine_send_queue(Engine," movetime %.0f",time_max*1000.0);
   engine_send_queue(Engine," depth %d",depth_max);

   engine_send(Engine,""); // newline

   // wait for feed-back

   while (true) {

      engine_get(Engine,string,256);

      if (false) {

      } else if (match(string,"bestmove * ponder *")) {

         BestMove = move_from_can(Star[0],board);
         ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));

         break;

      } else if (match(string,"bestmove *")) {

         BestMove = move_from_can(Star[0],board);
         ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));

         break;
      }
   }

   printf("\n");
}
示例#4
0
static void epd_test_file(const char file_name[]) {

   FILE * file;
   int hit, tot;
   char epd[StringSize];
   char am[StringSize], bm[StringSize], id[StringSize];
   board_t board[1];
   char string[StringSize];
   int move;
   char pv_string[StringSize];
   bool correct;
   double depth_tot, time_tot, node_tot;

   ASSERT(file_name!=NULL);

   // init

   file = fopen(file_name,"r");
   if (file == NULL) my_fatal("epd_test_file(): can't open file \"%s\": %s\n",file_name,strerror(errno));

   hit = 0;
   tot = 0;

   depth_tot = 0.0;
   time_tot = 0.0;
   node_tot = 0.0;

   // loop

   while (my_file_read_line(file,epd,StringSize)) {

      if (UseTrace) printf("%s\n",epd);

      if (!epd_get_op(epd,"am",am,StringSize)) strcpy(am,"");
      if (!epd_get_op(epd,"bm",bm,StringSize)) strcpy(bm,"");
      if (!epd_get_op(epd,"id",id,StringSize)) strcpy(id,"");

      if (my_string_empty(am) && my_string_empty(bm)) {
         my_fatal("epd_test(): no am or bm field in EPD\n");
      }

      // init

      uci_send_ucinewgame(Uci);
      uci_send_isready_sync(Uci);

      ASSERT(!Uci->searching);

      // position

      if (!board_from_fen(board,epd)) ASSERT(false);
      if (!board_to_fen(board,string,StringSize)) ASSERT(false);

      engine_send(Engine,"position fen %s",string);

      // search

      engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth);
      // engine_send(Engine,"go infinite");

      // engine data

      board_copy(Uci->board,board);

      uci_clear(Uci);
      Uci->searching = true;
      Uci->pending_nb++;

      FirstMove = MoveNone;
      FirstDepth = 0;
      FirstSelDepth = 0;
      FirstScore = 0;
      FirstTime = 0.0;
      FirstNodeNb = 0;
      line_clear(FirstPV);

      LastMove = MoveNone;
      LastDepth = 0;
      LastSelDepth = 0;
      LastScore = 0;
      LastTime = 0.0;
      LastNodeNb = 0;
      line_clear(LastPV);

      // parse engine output

      while (engine_step()) {

         // stop search?

         if (Uci->depth > MaxDepth
          || Uci->time >= MaxTime
          || (Uci->depth - FirstDepth >= DepthDelta
           && Uci->depth > MinDepth
           && Uci->time >= MinTime
           && is_solution(FirstMove,board,bm,am))) {
            engine_send(Engine,"stop");
         }
      }

      move = FirstMove;
      correct = is_solution(move,board,bm,am);

      if (correct) hit++;
      tot++;

      if (correct) {
         depth_tot += double(FirstDepth);
         time_tot += FirstTime;
         node_tot += double(FirstNodeNb);
      }

      printf("%s %d %4d %4d",id,correct,hit,tot);

      if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(false);
      printf(" - %2d %6.2f %9lld %+6.2f %s\n",FirstDepth,FirstTime,FirstNodeNb,double(LastScore)/100.0,pv_string);
   }

   printf("%d/%d",hit,tot);

   if (hit != 0) {

      depth_tot /= double(hit);
      time_tot /= double(hit);
      node_tot /= double(hit);

      printf(" - %.1f %.2f %.0f",depth_tot,time_tot,node_tot);
   }

   printf("\n");

   fclose(file);
}
示例#5
0
void xboard_step() {

	char string[StringSize];
	int move;
#ifdef _WIN32	
int n;
#endif
	char move_string[256];
	board_t board[1];
#ifndef _WIN32
xboard_get(XBoard,string,sizeof(string));
#else
	 while(fgets(string,StringSize-1,stdin)!=NULL){//stops if error or eof
		 //remove \n 
		 n=0;
		 while(string[n]!= '\0' && n < StringSize){
			 if(string[n]=='\n'){ string[n]='\0'; break;}
			 n++;
		 }
		my_log("Xboard->Adapter: %s\n",string);
#endif
		if (false) {

		} else if (match(string,"accepted *")) {

			// ignore

		} else if (match(string,"analyze")) {

			State->computer[White] = false;
			State->computer[Black] = false;

			XB->analyse = true;
			XB->new_hack = false;
			ASSERT(!XB->result);
			XB->result = false;

			mess();

		} else if (match(string,"bk")) {

			if (option_get_bool("Book")) {
				game_get_board(Game,board);
				book_disp(board);
			}

		} else if (match(string,"black")) {

			if (colour_is_black(game_turn(Game))) {

				State->computer[White] = true;
				State->computer[Black] = false;

				XB->new_hack = true;
				XB->result = false;

				mess();
			}

		} else if (match(string,"computer")) {

			XB->computer = true;

		} else if (match(string,"draw")) {
			if(uci_option_exist(Uci,"UCI_DrawOffers")){
			    my_log("POLYGLOT draw from XB received");
				uci_send_option(Uci,"DrawOffer","%s","draw");}
		} else if (match(string,"easy")) {

			XB->ponder = false;

			mess();

		} else if (match(string,"edit")) {

			// refuse

			xboard_send(XBoard,"Error (unknown command): %s",string);

		} else if (match(string,"exit")) {

			State->computer[White] = false;
			State->computer[Black] = false;

			XB->analyse = false;

			mess();

		} else if (match(string,"force")) {

			State->computer[White] = false;
			State->computer[Black] = false;

			mess();

		} else if (match(string,"go")) {

			State->computer[game_turn(Game)] = true;
			State->computer[colour_opp(game_turn(Game))] = false;

			XB->new_hack = false;
			ASSERT(!XB->result);
			XB->result = false;

			mess();

		} else if (match(string,"hard")) {

			XB->ponder = true;

			mess();

		} else if (match(string,"hint")) {

			if (option_get_bool("Book")) {

				game_get_board(Game,board);
				move = book_move(board,false);

				if (move != MoveNone && move_is_legal(move,board)) {
					move_to_san(move,board,move_string,sizeof(move_string));
					xboard_send(XBoard,"Hint: %s",move_string);
				}
			}

		} else if (match(string,"ics *")) {

			XB->ics = true;

		} else if (match(string,"level * *:* *")) {

			XB->mps  = atoi(Star[0]);
			XB->base = double(atoi(Star[1])) * 60.0 + double(atoi(Star[2]));
			XB->inc  = double(atoi(Star[3]));

		} else if (match(string,"level * * *")) {

			XB->mps  = atoi(Star[0]);
			XB->base = double(atoi(Star[1])) * 60.0;
			XB->inc  = double(atoi(Star[2]));

		} else if (match(string,"name *")) {

			my_string_set(&XB->name,Star[0]);

		} else if (match(string,"new")) {

			my_log("POLYGLOT NEW GAME\n");

			option_set("Chess960","false");

			game_clear(Game);

			if (XB->analyse) {
				State->computer[White] = false;
				State->computer[Black] = false;
			} else {
				State->computer[White] = false;
				State->computer[Black] = true;
			}

			XB->new_hack = true;
			XB->result = false;

			XB->depth_limit = false;

			XB->computer = false;
			my_string_set(&XB->name,"<empty>");

			board_update();
			mess();

			uci_send_ucinewgame(Uci);
			uci_send_isready_sync(Uci);

		} else if (match(string,"nopost")) {

			XB->post = false;

		} else if (match(string,"otim *")) {

			XB->opp_time = double(atoi(Star[0])) / 100.0;
			if (XB->opp_time < 0.0) XB->opp_time = 0.0;

		} else if (match(string,"pause")) {

			// refuse

			xboard_send(XBoard,"Error (unknown command): %s",string);

		} else if (match(string,"ping *")) {

			// HACK; TODO: answer only after an engine move

			if (DelayPong) {
				if (XB->ping >= 0) xboard_send(XBoard,"pong %d",XB->ping); // HACK: get rid of old ping
				XB->ping = atoi(Star[0]);
				uci_send_isready(Uci);
			} else {
				ASSERT(XB->ping==-1);
				xboard_send(XBoard,"pong %s",Star[0]);
			}

		} else if (match(string,"playother")) {

			State->computer[game_turn(Game)] = false;
			State->computer[colour_opp(game_turn(Game))] = true;

			XB->new_hack = false;
			ASSERT(!XB->result);
			XB->result = false;

			mess();

		} else if (match(string,"post")) {

			XB->post = true;

		} else if (match(string,"protover *")) {

			XB->proto_ver = atoi(Star[0]);
			ASSERT(XB->proto_ver>=2);

			xboard_send(XBoard,"feature done=0");

			xboard_send(XBoard,"feature analyze=1");
			xboard_send(XBoard,"feature colors=0");
			xboard_send(XBoard,"feature draw=1");
			xboard_send(XBoard,"feature ics=1");
			xboard_send(XBoard,"feature myname=\"%s\"",option_get_string("EngineName"));
			xboard_send(XBoard,"feature name=1");
			xboard_send(XBoard,"feature pause=0");
			xboard_send(XBoard,"feature ping=1");
			xboard_send(XBoard,"feature playother=1");
			xboard_send(XBoard,"feature reuse=1");
			xboard_send(XBoard,"feature san=0");
			xboard_send(XBoard,"feature setboard=1");
			xboard_send(XBoard,"feature sigint=0");
			xboard_send(XBoard,"feature sigterm=0");
			xboard_send(XBoard,"feature time=1");
			xboard_send(XBoard,"feature usermove=1");
			xboard_send(XBoard,"feature debug=1");

			if (uci_option_exist(Uci,"UCI_Chess960")) {
				xboard_send(XBoard,"feature variants=\"normal,fischerandom\"");
			} else {
				xboard_send(XBoard,"feature variants=\"normal\"");
			}

			if (Uci->ready) xboard_send(XBoard,"feature done=1");

			// otherwise "feature done=1" will be sent when the engine is ready

		} else if (match(string,"quit")) {
			my_log("POLYGLOT *** \"quit\" from XBoard ***\n");
			quit();
		} else if (match(string,"random")) {

			// ignore

		} else if (match(string,"rating * *")) {

			// ignore

		} else if (match(string,"remove")) {

			if (game_pos(Game) >= 2) {

				game_goto(Game,game_pos(Game)-2);

				ASSERT(!XB->new_hack);
				XB->new_hack = false; // HACK?
				XB->result = false;

				board_update();
				mess();
			}

		} else if (match(string,"rejected *")) {

			// ignore

		} else if (match(string,"reset")) { // protover 3?

			// refuse

			xboard_send(XBoard,"Error (unknown command): %s",string);

		} else if (false
			|| match(string,"result * {*}")
			|| match(string,"result * {* }")
			|| match(string,"result * { *}")
			|| match(string,"result * { * }")) {

				my_log("POLYGLOT GAME END\n");

				XB->result = true;

				mess();

				// book learning

				if (option_get_bool("Book") && option_get_bool("BookLearn")) {

					if (false) {
					} else if (my_string_equal(Star[0],"1-0")) {
						learn(+1);
					} else if (my_string_equal(Star[0],"0-1")) {
						learn(-1);
					} else if (my_string_equal(Star[0],"1/2-1/2")) {
						learn(0);
					}
				}
		} else if (match(string,"resume")) {

			// refuse

			xboard_send(XBoard,"Error (unknown command): %s",string);

		} else if (match(string,"sd *")) {

			XB->depth_limit = true;
			XB->depth_max = atoi(Star[0]);

		} else if (match(string,"setboard *")) {

			my_log("POLYGLOT FEN %s\n",Star[0]);

			if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]);

			State->computer[White] = false;
			State->computer[Black] = false;

			XB->new_hack = true; // HACK?
			XB->result = false;

			board_update();
			mess();

		} else if (match(string,"st *")) {

			XB->time_limit = true;
			XB->time_max = double(atoi(Star[0]));

		} else if (match(string,"time *")) {

			XB->my_time = double(atoi(Star[0])) / 100.0;
			if (XB->my_time < 0.0) XB->my_time = 0.0;

		} else if (match(string,"undo")) {

			if (game_pos(Game) >= 1) {

				game_goto(Game,game_pos(Game)-1);

				ASSERT(!XB->new_hack);
				XB->new_hack = false; // HACK?
				XB->result = false;

				board_update();
				mess();
			}

		} else if (match(string,"usermove *")) {
			game_get_board(Game,board);
			move = move_from_san(Star[0],board);

			if (move != MoveNone && move_is_legal(move,board)) {

				XB->new_hack = false;
				ASSERT(!XB->result);
				XB->result = false;

				move_step(move);
				board_update();
				no_mess(move);

			} else {

				xboard_send(XBoard,"Illegal move: %s",Star[0]);
			}
		} else if (match(string,"variant *")) {

			if (my_string_equal(Star[0],"fischerandom")) {
				option_set("Chess960","true");
			} else {
				option_set("Chess960","false");
			}

		} else if (match(string,"white")) {

			if (colour_is_white(game_turn(Game))) {

				State->computer[White] = false;
				State->computer[Black] = true;

				XB->new_hack = true;
				XB->result = false;

				mess();
			}

		} else if (match(string,"xboard")) {

			// ignore

		} else if (match(string,".")) { // analyse info

			if (State->state == ANALYSE) {
				int depth=Uci->best_depth;//HACK: don't clear engine-output window...

				ASSERT(Uci->searching);
				ASSERT(Uci->pending_nb>=1);

				if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) {
					move_to_san(Uci->root_move,Uci->board,move_string,sizeof(move_string));
					xboard_send(XBoard,"stat01: %.0f " S64_FORMAT " %d %d %d %s",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,Uci->root_move_nb-(Uci->root_move_pos+1),Uci->root_move_nb,move_string);
				} else {
					xboard_send(XBoard,"stat01: %.0f " S64_FORMAT " %d %d %d",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,0,0); // HACK
				}
			}

		} else if (match(string,"?")) { // move now

			if (State->state == THINK) {

				ASSERT(Uci->searching);
				ASSERT(Uci->pending_nb>=1);

				// HACK: just send "stop" to the engine

				if (Uci->searching) {
					my_log("POLYGLOT STOP SEARCH\n");
					engine_send(Engine,"stop");
				}
			}

		} else { // unknown command, maybe a move?

			game_get_board(Game,board);
			move = move_from_san(string,board);

			if (move != MoveNone && move_is_legal(move,board)) {

				XB->new_hack = false;
				ASSERT(!XB->result);
				XB->result = false;

				move_step(move);
				board_update();
				no_mess(move);

			} else if (move != MoveNone) {

				xboard_send(XBoard,"Illegal move: %s",string);

			} else {

				xboard_send(XBoard,"Error (unknown command): %s",string);
			}
		}
#ifdef _WIN32
		}
#endif
}