12
#include <sys/select.h>
13
#include <sys/types.h> // Mac OS X needs this one
27
#include "move_legal.h"
36
static const bool UseDebug = false;
37
static const bool DelayPong = false;
39
static const int StringSize = 4096;
49
bool computer[ColourNb];
61
bool new_hack; // "new" is a C++ keyword
82
enum dummy_state_t { WAIT, THINK, PONDER, ANALYSE };
86
static xboard_t XBoard[1];
88
static state_t State[1];
93
static void adapter_step ();
95
static void xboard_step ();
96
static void engine_step ();
98
static void comp_move (int move);
99
static void move_step (int move);
100
static void board_update ();
103
static void no_mess (int move);
105
static void search_update ();
106
static void search_clear ();
108
static bool active ();
109
static bool ponder_ok (int ponder_move);
111
static void stop_search ();
114
static void send_board (int extra_move);
115
static void send_pv ();
117
static void xboard_get (xboard_t * xboard, char string[], int size);
118
static void xboard_send (xboard_t * xboard, const char format[], ...);
120
static void learn (int result);
126
void adapter_loop() {
136
State->computer[White] = false;
137
State->computer[Black] = true;
139
State->exp_move = MoveNone;
140
State->resign_nb = 0;
141
my_timer_reset(State->timer);
145
XBoard->io->in_fd = STDIN_FILENO;
146
XBoard->io->out_fd = STDOUT_FILENO;
147
XBoard->io->name = "XBOARD";
152
XB->computer = false;
154
my_string_set(&XB->name,"<empty>");
167
XB->time_limit = false;
170
XB->depth_limit = false;
174
XB->opp_time = 300.0;
178
while (true) adapter_step();
183
static void adapter_step() {
189
// process buffered lines
191
while (io_line_ready(XBoard->io)) xboard_step(); // process available xboard lines
192
while (io_line_ready(Engine->io)) engine_step(); // process available engine lines
201
ASSERT(XBoard->io->in_fd>=0);
203
FD_SET(XBoard->io->in_fd,set);
204
if (XBoard->io->in_fd > fd_max) fd_max = XBoard->io->in_fd;
208
ASSERT(Engine->io->in_fd>=0);
210
FD_SET(Engine->io->in_fd,set);
211
if (Engine->io->in_fd > fd_max) fd_max = Engine->io->in_fd;
213
// wait for something to read (no timeout)
217
val = select(fd_max+1,set,NULL,NULL,NULL);
218
if (val == -1 && errno != EINTR) my_fatal("adapter_step(): select(): %s\n",strerror(errno));
221
if (FD_ISSET(XBoard->io->in_fd,set)) io_get_update(XBoard->io); // read some xboard input
222
if (FD_ISSET(Engine->io->in_fd,set)) io_get_update(Engine->io); // read some engine input
228
static void xboard_step() {
230
char string[StringSize];
232
char move_string[256];
235
xboard_get(XBoard,string,StringSize);
239
} else if (match(string,"accepted *")) {
243
} else if (match(string,"analyze")) {
245
State->computer[White] = false;
246
State->computer[Black] = false;
249
XB->new_hack = false;
255
} else if (match(string,"bk")) {
257
if (option_get_bool("Book")) {
258
game_get_board(Game,board);
262
} else if (match(string,"black")) {
264
if (colour_is_black(game_turn(Game))) {
266
State->computer[White] = true;
267
State->computer[Black] = false;
275
} else if (match(string,"computer")) {
279
} else if (match(string,"draw")) {
283
} else if (match(string,"easy")) {
289
} else if (match(string,"edit")) {
293
xboard_send(XBoard,"Error (unknown command): %s",string);
295
} else if (match(string,"exit")) {
297
State->computer[White] = false;
298
State->computer[Black] = false;
304
} else if (match(string,"force")) {
306
State->computer[White] = false;
307
State->computer[Black] = false;
311
} else if (match(string,"go")) {
313
State->computer[game_turn(Game)] = true;
314
State->computer[colour_opp(game_turn(Game))] = false;
316
XB->new_hack = false;
322
} else if (match(string,"hard")) {
328
} else if (match(string,"hint")) {
330
if (option_get_bool("Book")) {
332
game_get_board(Game,board);
333
move = book_move(board,false);
335
if (move != MoveNone && move_is_legal(move,board)) {
336
move_to_san(move,board,move_string,256);
337
xboard_send(XBoard,"Hint: %s",move_string);
341
} else if (match(string,"ics *")) {
345
} else if (match(string,"level * *:* *")) {
347
XB->mps = atoi(Star[0]);
348
XB->base = double(atoi(Star[1])) * 60.0 + double(atoi(Star[2]));
349
XB->inc = double(atoi(Star[3]));
351
} else if (match(string,"level * * *")) {
353
XB->mps = atoi(Star[0]);
354
XB->base = double(atoi(Star[1])) * 60.0;
355
XB->inc = double(atoi(Star[2]));
357
} else if (match(string,"name *")) {
359
my_string_set(&XB->name,Star[0]);
361
} else if (match(string,"new")) {
363
my_log("POLYGLOT NEW GAME\n");
368
State->computer[White] = false;
369
State->computer[Black] = false;
371
State->computer[White] = false;
372
State->computer[Black] = true;
378
XB->depth_limit = false;
380
XB->computer = false;
381
my_string_set(&XB->name,"<empty>");
386
uci_send_ucinewgame(Uci);
388
} else if (match(string,"nopost")) {
392
} else if (match(string,"otim *")) {
394
XB->opp_time = double(atoi(Star[0])) / 100.0;
395
if (XB->opp_time < 0.0) XB->opp_time = 0.0;
397
} else if (match(string,"pause")) {
401
xboard_send(XBoard,"Error (unknown command): %s",string);
403
} else if (match(string,"ping *")) {
405
// HACK; TODO: answer only after an engine move
408
if (XB->ping >= 0) xboard_send(XBoard,"pong %d",XB->ping); // HACK: get rid of old ping
409
XB->ping = atoi(Star[0]);
410
uci_send_isready(Uci);
412
ASSERT(XB->ping==-1);
413
xboard_send(XBoard,"pong %s",Star[0]);
416
} else if (match(string,"playother")) {
418
State->computer[game_turn(Game)] = false;
419
State->computer[colour_opp(game_turn(Game))] = true;
421
XB->new_hack = false;
427
} else if (match(string,"post")) {
431
} else if (match(string,"protover *")) {
433
XB->proto_ver = atoi(Star[0]);
434
ASSERT(XB->proto_ver>=2);
436
xboard_send(XBoard,"feature done=0");
438
xboard_send(XBoard,"feature analyze=1");
439
xboard_send(XBoard,"feature colors=0");
440
xboard_send(XBoard,"feature draw=1");
441
xboard_send(XBoard,"feature ics=1");
442
xboard_send(XBoard,"feature myname=\"%s\"",option_get_string("EngineName"));
443
xboard_send(XBoard,"feature name=1");
444
xboard_send(XBoard,"feature pause=0");
445
xboard_send(XBoard,"feature ping=1");
446
xboard_send(XBoard,"feature playother=1");
447
xboard_send(XBoard,"feature reuse=1");
448
xboard_send(XBoard,"feature san=0");
449
xboard_send(XBoard,"feature setboard=1");
450
xboard_send(XBoard,"feature sigint=0");
451
xboard_send(XBoard,"feature sigterm=0");
452
xboard_send(XBoard,"feature time=1");
453
xboard_send(XBoard,"feature usermove=1");
454
xboard_send(XBoard,"feature variants=\"normal\"");
456
if (Uci->ready) xboard_send(XBoard,"feature done=1");
458
// "feature done=1" will be sent when the engine is ready
460
} else if (match(string,"quit")) {
462
my_log("POLYGLOT *** \"quit\" from XBoard ***\n");
465
} else if (match(string,"random")) {
469
} else if (match(string,"rating * *")) {
473
} else if (match(string,"remove")) {
475
if (game_pos(Game) >= 2) {
477
game_goto(Game,game_pos(Game)-2);
479
ASSERT(!XB->new_hack);
480
XB->new_hack = false; // HACK?
487
} else if (match(string,"rejected *")) {
491
} else if (match(string,"reset")) { // protover 3?
495
xboard_send(XBoard,"Error (unknown command): %s",string);
498
|| match(string,"result * {*}")
499
|| match(string,"result * {* }")
500
|| match(string,"result * { *}")
501
|| match(string,"result * { * }")) {
503
my_log("POLYGLOT GAME END\n");
511
if (option_get_bool("Book") && option_get_bool("BookLearn")) {
514
} else if (my_string_equal(Star[0],"1-0")) {
516
} else if (my_string_equal(Star[0],"0-1")) {
518
} else if (my_string_equal(Star[0],"1/2-1/2")) {
523
} else if (match(string,"resume")) {
527
xboard_send(XBoard,"Error (unknown command): %s",string);
529
} else if (match(string,"sd *")) {
531
XB->depth_limit = true;
532
XB->depth_max = atoi(Star[0]);
534
} else if (match(string,"setboard *")) {
536
my_log("POLYGLOT FEN %s\n",Star[0]);
538
if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]);
540
State->computer[White] = false;
541
State->computer[Black] = false;
543
XB->new_hack = true; // HACK?
549
} else if (match(string,"st *")) {
551
XB->time_limit = true;
552
XB->time_max = double(atoi(Star[0]));
554
} else if (match(string,"time *")) {
556
XB->my_time = double(atoi(Star[0])) / 100.0;
557
if (XB->my_time < 0.0) XB->my_time = 0.0;
559
} else if (match(string,"undo")) {
561
if (game_pos(Game) >= 1) {
563
game_goto(Game,game_pos(Game)-1);
565
ASSERT(!XB->new_hack);
566
XB->new_hack = false; // HACK?
573
} else if (match(string,"usermove *")) {
575
game_get_board(Game,board);
576
move = move_from_san(Star[0],board);
578
if (move != MoveNone && move_is_legal(move,board)) {
580
XB->new_hack = false;
589
xboard_send(XBoard,"Illegal move: %s",Star[0]);
592
} else if (match(string,"variant *")) {
596
xboard_send(XBoard,"Error (unknown command): %s",string);
598
} else if (match(string,"white")) {
600
if (colour_is_white(game_turn(Game))) {
602
State->computer[White] = false;
603
State->computer[Black] = true;
611
} else if (match(string,"xboard")) {
615
} else if (match(string,".")) { // analyse info
617
if (State->state == ANALYSE) {
619
ASSERT(Uci->searching);
620
ASSERT(Uci->pending_nb>=1);
622
if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) {
623
move_to_san(Uci->root_move,Uci->board,move_string,256);
624
xboard_send(XBoard,"stat01: %.0f %lld %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);
626
xboard_send(XBoard,"stat01: %.0f %lld %d %d %d",Uci->time*100.0,Uci->node_nb,Uci->depth,0,0); // HACK
630
} else if (match(string,"?")) { // move now
632
if (State->state == THINK) {
634
ASSERT(Uci->searching);
635
ASSERT(Uci->pending_nb>=1);
640
} else { // unknown command, maybe a move?
642
game_get_board(Game,board);
643
move = move_from_san(string,board);
645
if (move != MoveNone && move_is_legal(move,board)) {
647
XB->new_hack = false;
654
} else if (move != MoveNone) {
656
xboard_send(XBoard,"Illegal move: %s",string);
660
xboard_send(XBoard,"Error (unknown command): %s",string);
667
static void engine_step() {
669
char string[StringSize];
674
engine_get(Engine,string,StringSize);
675
event = uci_parse(Uci,string);
679
if ((event & EVENT_READY) != 0) {
681
// the engine is now ready
685
if (XB->proto_ver >= 2) xboard_send(XBoard,"feature done=1");
688
if (!DelayPong && XB->ping >= 0) {
689
xboard_send(XBoard,"pong %d",XB->ping);
694
if ((event & EVENT_MOVE) != 0 && State->state == THINK) {
696
// the engine is playing a move
698
// MEGA HACK: estimate remaining time because XBoard won't send it!
700
my_timer_stop(State->timer);
702
XB->my_time -= my_timer_elapsed_real(State->timer);
703
XB->my_time += XB->inc;
704
if (XB->mps != 0 && (game_move_nb(Game) + 1) % XB->mps == 0) XB->my_time += XB->base;
706
if (XB->my_time < 0.0) XB->my_time = 0.0;
708
// play the engine move
710
comp_move(Uci->best_move);
713
if ((event & EVENT_PV) != 0) {
715
// the engine has sent a new PV
723
static void comp_move(int move) {
727
ASSERT(move_is_ok(move));
729
ASSERT(State->state==THINK);
730
ASSERT(!XB->analyse);
734
if (!move_to_can(move,string,256)) my_fatal("comp_move(): move_to_can() failed\n");
735
xboard_send(XBoard,"move %s",string);
737
if (option_get_bool("Resign") && Uci->root_move_nb > 1) {
739
if (Uci->best_score <= -abs(option_get_int("ResignScore"))) {
742
my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":"");
744
if (State->resign_nb >= option_get_int("ResignMoves")) {
745
my_log("POLYGLOT *** RESIGN ***\n");
746
xboard_send(XBoard,"resign");
751
if (State->resign_nb > 0) my_log("POLYGLOT resign reset (State->resign_nb=%d)\n",State->resign_nb);
752
State->resign_nb = 0;
762
static void move_step(int move) {
765
char move_string[256];
767
ASSERT(move_is_ok(move));
771
game_get_board(Game,board);
773
if (move != MoveNone && move_is_legal(move,board)) {
775
move_to_san(move,board,move_string,256);
776
my_log("POLYGLOT MOVE %s\n",move_string);
780
move_to_can(move,move_string,256);
781
my_log("POLYGLOT ILLEGAL MOVE \"%s\"\n",move_string);
784
my_fatal("move_step(): illegal move \"%s\"\n",move_string);
789
game_add_move(Game,move);
795
static void board_update() {
801
switch (game_status(Game)) {
805
xboard_send(XBoard,"1-0 {White mates}");
808
xboard_send(XBoard,"0-1 {Black mates}");
811
xboard_send(XBoard,"1/2-1/2 {Stalemate}");
814
xboard_send(XBoard,"1/2-1/2 {Draw by insufficient material}");
817
xboard_send(XBoard,"1/2-1/2 {Draw by fifty-move rule}");
819
case DRAW_REPETITION :
820
xboard_send(XBoard,"1/2-1/2 {Draw by repetition}");
832
// clear state variables
834
State->resign_nb = 0;
835
State->exp_move = MoveNone;
836
my_timer_reset(State->timer);
838
// abort a possible search
842
// calculate the new state
845
} else if (!active()) {
847
my_log("POLYGLOT WAIT\n");
848
} else if (XB->analyse) {
849
State->state = ANALYSE;
850
my_log("POLYGLOT ANALYSE\n");
851
} else if (State->computer[game_turn(Game)]) {
852
State->state = THINK;
853
my_log("POLYGLOT THINK\n");
856
my_log("POLYGLOT WAIT\n");
864
static void no_mess(int move) {
866
ASSERT(move_is_ok(move));
868
// just received a move, calculate the new state
872
} else if (!active()) {
874
stop_search(); // abort a possible search
877
State->exp_move = MoveNone;
879
my_log("POLYGLOT WAIT\n");
881
} else if (State->state == WAIT) {
883
ASSERT(State->computer[game_turn(Game)]);
884
ASSERT(!State->computer[colour_opp(game_turn(Game))]);
885
ASSERT(!XB->analyse);
887
my_log("POLYGLOT WAIT -> THINK\n");
889
State->state = THINK;
890
State->exp_move = MoveNone;
892
} else if (State->state == THINK) {
894
ASSERT(!State->computer[game_turn(Game)]);
895
ASSERT(State->computer[colour_opp(game_turn(Game))]);
896
ASSERT(!XB->analyse);
898
if (XB->ponder && ponder_ok(Uci->ponder_move)) {
900
my_log("POLYGLOT THINK -> PONDER\n");
902
State->state = PONDER;
903
State->exp_move = Uci->ponder_move;
907
my_log("POLYGLOT THINK -> WAIT\n");
910
State->exp_move = MoveNone;
913
} else if (State->state == PONDER) {
915
ASSERT(State->computer[game_turn(Game)]);
916
ASSERT(!State->computer[colour_opp(game_turn(Game))]);
917
ASSERT(!XB->analyse);
919
if (move == State->exp_move && Uci->searching) {
921
ASSERT(Uci->searching);
922
ASSERT(Uci->pending_nb>=1);
924
my_timer_reset(State->timer);
925
my_timer_start(State->timer);
927
my_log("POLYGLOT PONDER -> THINK (*** HIT ***)\n");
928
engine_send(Engine,"ponderhit");
930
State->state = THINK;
931
State->exp_move = MoveNone;
933
send_pv(); // update display
935
return; // do not launch a new search
939
my_log("POLYGLOT PONDER -> THINK (miss)\n");
943
State->state = THINK;
944
State->exp_move = MoveNone;
947
} else if (State->state == ANALYSE) {
951
my_log("POLYGLOT ANALYSE -> ANALYSE\n");
965
static void search_update() {
971
ASSERT(!Uci->searching);
973
// launch a new search if needed
975
if (State->state == THINK || State->state == PONDER || State->state == ANALYSE) {
979
if (State->state == THINK && option_get_bool("Book")) {
981
game_get_board(Game,Uci->board);
983
move = book_move(Uci->board,option_get_bool("BookRandom"));
985
if (move != MoveNone && move_is_legal(move,Uci->board)) {
987
my_log("POLYGLOT *BOOK MOVE*\n");
989
search_clear(); // clears Uci->ponder_move
990
Uci->best_move = move;
992
board_copy(board,Uci->board);
994
Uci->ponder_move = book_move(board,false); // expected move = best book move
996
Uci->best_pv[0] = Uci->best_move;
997
Uci->best_pv[1] = Uci->ponder_move; // can be MoveNone
998
Uci->best_pv[2] = MoveNone;
1000
comp_move(Uci->best_move);
1008
my_log("POLYGLOT START SEARCH\n");
1012
if (option_get_int("UCIVersion") >= 2) {
1013
uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name);
1014
uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false");
1017
uci_send_option(Uci,"Ponder","%s",(XB->ponder)?"true":"false");
1021
move = (State->state == PONDER) ? State->exp_move : MoveNone;
1022
send_board(move); // updates Uci->board global variable
1026
if (State->state == THINK || State->state == PONDER) {
1028
engine_send_queue(Engine,"go");
1030
if (XB->time_limit) {
1032
// fixed time per move
1034
engine_send_queue(Engine," movetime %.0f",XB->time_max*1000.0);
1040
if (colour_is_white(Uci->board->turn)) {
1041
engine_send_queue(Engine," wtime %.0f btime %.0f",XB->my_time*1000.0,XB->opp_time*1000.0);
1043
engine_send_queue(Engine," wtime %.0f btime %.0f",XB->opp_time*1000.0,XB->my_time*1000.0);
1046
if (XB->inc != 0.0) engine_send_queue(Engine," winc %.0f binc %.0f",XB->inc*1000.0,XB->inc*1000.0);
1050
move_nb = XB->mps - (Uci->board->move_nb % XB->mps);
1051
ASSERT(move_nb>=1&&move_nb<=XB->mps);
1053
engine_send_queue(Engine," movestogo %d",move_nb);
1057
if (XB->depth_limit) engine_send_queue(Engine," depth %d",XB->depth_max);
1059
if (State->state == PONDER) engine_send_queue(Engine," ponder");
1061
engine_send(Engine,""); // newline
1063
} else if (State->state == ANALYSE) {
1065
engine_send(Engine,"go infinite");
1074
ASSERT(!Uci->searching);
1078
Uci->searching = true;
1085
static void search_clear() {
1091
my_timer_reset(State->timer);
1092
my_timer_start(State->timer);
1097
static bool active() {
1101
game_get_board(Game,board);
1102
if (!board_can_play(board)) return false; // no legal move => mate or stalemate
1104
// if (game_status(Game) != PLAYING) return false; // draw
1106
if (XB->analyse) return true; // analysing
1108
if (!State->computer[White] && !State->computer[Black]) return false; // force mode
1110
if (XB->new_hack || XB->result) return false; // unstarted or ended game
1112
return true; // playing
1117
static bool ponder_ok(int move) {
1121
ASSERT(move==MoveNone||move_is_ok(move));
1123
if (move == MoveNone) return false;
1125
game_get_board(Game,board);
1127
if (!move_is_legal(move,board)) return false;
1128
move_do(board,move);
1130
if (!board_can_play(board)) return false;
1132
if (option_get_bool("Book") && is_in_book(board)) {
1143
static void stop_search() {
1145
if (Uci->searching) {
1147
ASSERT(Uci->searching);
1148
ASSERT(Uci->pending_nb>=1);
1150
my_log("POLYGLOT STOP SEARCH\n");
1151
engine_send(Engine,"stop");
1153
Uci->searching = false;
1159
static void quit() {
1161
char string[StringSize];
1163
my_log("POLYGLOT *** QUIT ***\n");
1166
engine_send(Engine,"quit");
1168
// wait for the engine to quit
1171
engine_get(Engine,string,StringSize); // HACK: calls exit() on receiving EOF
1180
static void send_board(int extra_move) {
1189
ASSERT(extra_move==MoveNone||move_is_ok(extra_move));
1191
ASSERT(!Uci->searching);
1195
game_get_board(Game,Uci->board);
1196
if (extra_move != MoveNone) move_do(Uci->board,extra_move);
1198
board_to_fen(Uci->board,fen,256);
1199
my_log("POLYGLOT FEN %s\n",fen);
1201
ASSERT(board_can_play(Uci->board));
1206
end = game_pos(Game);
1211
game_get_board(Game,board,start);
1212
board_to_fen(board,string,256);
1214
engine_send_queue(Engine,"position");
1216
if (my_string_equal(string,StartFen)) {
1217
engine_send_queue(Engine," startpos");
1219
engine_send_queue(Engine," fen %s",string);
1224
if (end > start || extra_move != MoveNone) engine_send_queue(Engine," moves");
1226
for (pos = start; pos < end; pos++) { // game moves
1228
move = game_move(Game,pos);
1230
move_to_can(move,string,256);
1231
engine_send_queue(Engine," %s",string);
1234
if (extra_move != MoveNone) { // move to ponder on
1235
move_to_can(extra_move,string,256);
1236
engine_send_queue(Engine," %s",string);
1241
engine_send(Engine,""); // newline
1246
static void send_pv() {
1248
char pv_string[StringSize];
1251
char move_string[StringSize];
1253
ASSERT(State->state!=WAIT);
1255
if (Uci->best_depth == 0) return;
1257
// xboard search information
1261
if (State->state == THINK || State->state == ANALYSE) {
1263
line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);
1264
xboard_send(XBoard,"%d %+d %.0f %lld %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,pv_string);
1266
} else if (State->state == PONDER && option_get_bool("ShowPonder")) {
1268
game_get_board(Game,board);
1269
move = State->exp_move;
1271
if (move != MoveNone && move_is_legal(move,board)) {
1272
move_to_san(move,board,move_string,256);
1273
line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);
1274
xboard_send(XBoard,"%d %+d %.0f %lld (%s) %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,move_string,pv_string);
1281
if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay"))
1282
|| (!Uci->searching && option_get_bool("KibitzMove"))) {
1284
if (State->state == THINK || State->state == ANALYSE) {
1286
line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);
1287
xboard_send(XBoard,"%s depth=%d time=%.2f node=%lld speed=%.0f score=%+.2f pv=\"%s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,double(Uci->best_score)/100.0,pv_string);
1289
} else if (State->state == PONDER) {
1291
game_get_board(Game,board);
1292
move = State->exp_move;
1294
if (move != MoveNone && move_is_legal(move,board)) {
1295
move_to_san(move,board,move_string,256);
1296
line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);
1297
xboard_send(XBoard,"%s depth=%d time=%.2f node=%lld speed=%.0f score=%+.2f pv=\"(%s) %s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,double(Uci->best_score)/100.0,move_string,pv_string);
1305
static void xboard_get(xboard_t * xboard, char string[], int size) {
1307
ASSERT(xboard!=NULL);
1308
ASSERT(string!=NULL);
1311
if (!io_get_line(xboard->io,string,size)) { // EOF
1312
my_log("POLYGLOT *** EOF from XBoard ***\n");
1319
static void xboard_send(xboard_t * xboard, const char format[], ...) {
1322
char string[StringSize];
1324
ASSERT(xboard!=NULL);
1325
ASSERT(format!=NULL);
1329
va_start(arg_list,format);
1330
vsprintf(string,format,arg_list);
1335
io_send(xboard->io,"%s",string);
1340
static void learn(int result) {
1346
ASSERT(result>=-1&&result<=+1);
1349
ASSERT(State->computer[White]||State->computer[Black]);
1356
} else if (State->computer[White]) {
1358
} else if (State->computer[Black]) {
1362
my_fatal("learn(): unknown side\n");
1366
} else if (result > 0) {
1367
my_log("POLYGLOT *LEARN WIN*\n");
1368
} else if (result < 0) {
1369
my_log("POLYGLOT *LEARN LOSS*\n");
1371
my_log("POLYGLOT *LEARN DRAW*\n");
1376
for (; pos < Game->size; pos += 2) {
1378
game_get_board(Game,board,pos);
1379
move = game_move(Game,pos);
1381
book_learn_move(board,move,result);
1387
// end of adapter.cpp